kogral/assets/web/src/index.html
2026-01-23 16:11:07 +00:00

957 lines
31 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title
data-en="KOGRAL - Git-Native Knowledge Graphs"
data-es="KOGRAL - Grafos de Conocimiento Git-Native"
>
KOGRAL
</title>
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&display=swap"
rel="stylesheet"
/>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
background: #0a0a14;
color: #ffffff;
overflow-x: hidden;
}
.gradient-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
background:
radial-gradient(
circle at 20% 50%,
rgba(74, 158, 255, 0.15) 0%,
transparent 50%
),
radial-gradient(
circle at 80% 80%,
rgba(61, 214, 141, 0.15) 0%,
transparent 50%
),
radial-gradient(
circle at 40% 90%,
rgba(251, 191, 36, 0.1) 0%,
transparent 50%
);
}
.language-toggle {
position: fixed;
top: 2rem;
right: 2rem;
z-index: 100;
display: flex;
gap: 0.5rem;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(74, 158, 255, 0.3);
border-radius: 20px;
padding: 0.3rem 0.3rem;
}
.lang-btn {
background: transparent;
border: none;
color: #94a3b8;
padding: 0.5rem 1rem;
border-radius: 18px;
cursor: pointer;
font-weight: 700;
font-size: 0.85rem;
text-transform: uppercase;
transition: all 0.3s ease;
font-family: "Inter", sans-serif;
}
.lang-btn.active {
background: linear-gradient(135deg, #4a9eff 0%, #3dd68d 100%);
color: #fff;
}
.lang-btn:hover {
color: #3dd68d;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
position: relative;
}
header {
text-align: center;
padding: 5rem 0 4rem;
animation: fadeInUp 0.8s ease-out;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.status-badge {
display: inline-block;
background: rgba(61, 214, 141, 0.2);
border: 1px solid #3dd68d;
color: #3dd68d;
padding: 0.5rem 1.5rem;
border-radius: 50px;
font-size: 0.85rem;
font-weight: 700;
margin-bottom: 1.5rem;
}
.logo-container {
margin-bottom: 2rem;
}
.logo-container img {
max-width: 500px;
width: 100%;
height: auto;
filter: drop-shadow(0 0 30px rgba(74, 158, 255, 0.4));
}
.tagline {
font-size: 0.95rem;
color: #3dd68d;
font-weight: 600;
letter-spacing: 0.1em;
text-transform: uppercase;
margin-bottom: 1rem;
}
h1 {
font-size: 2.8rem;
font-weight: 800;
line-height: 1.2;
margin-bottom: 1.5rem;
background: linear-gradient(
135deg,
#4a9eff 0%,
#3dd68d 50%,
#fbbf24 100%
);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-subtitle {
font-size: 1.15rem;
color: #cbd5e1;
max-width: 800px;
margin: 0 auto 2rem;
line-height: 1.8;
}
.highlight {
color: #3dd68d;
font-weight: 700;
}
.section {
margin: 4rem 0;
animation: fadeInUp 0.8s ease-out;
}
.section-title {
font-size: 2rem;
font-weight: 800;
margin-bottom: 2rem;
color: #3dd68d;
text-align: center;
}
.section-title span {
background: linear-gradient(135deg, #4a9eff 0%, #3dd68d 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.problems-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
margin-top: 2rem;
}
.problem-card {
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(74, 158, 255, 0.3);
border-radius: 12px;
padding: 2rem;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.problem-card:hover {
transform: translateY(-5px);
background: rgba(255, 255, 255, 0.05);
border-color: rgba(61, 214, 141, 0.5);
}
.problem-number {
font-size: 2rem;
font-weight: 800;
background: linear-gradient(135deg, #4a9eff 0%, #3dd68d 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
line-height: 1;
margin-bottom: 0.5rem;
}
.problem-card h3 {
color: #4a9eff;
font-size: 1.05rem;
margin-bottom: 0.7rem;
font-weight: 700;
}
.problem-card p {
color: #cbd5e1;
font-size: 0.9rem;
line-height: 1.6;
}
.problem-card ul {
color: #cbd5e1;
font-size: 0.9rem;
line-height: 1.6;
list-style: none;
padding: 0;
margin: 0;
}
.problem-card ul li {
padding-left: 1.2rem;
margin-bottom: 0.5rem;
position: relative;
}
.problem-card ul li:before {
content: "•";
color: #4a9eff;
font-weight: bold;
position: absolute;
left: 0;
}
.tech-stack {
display: flex;
flex-wrap: wrap;
gap: 1rem;
margin-top: 2rem;
justify-content: center;
}
.tech-badge {
background: rgba(61, 214, 141, 0.15);
border: 1px solid #3dd68d;
padding: 0.5rem 1rem;
border-radius: 20px;
font-size: 0.8rem;
color: #3dd68d;
font-weight: 700;
}
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-top: 2rem;
}
.feature-box {
background: linear-gradient(
135deg,
rgba(74, 158, 255, 0.1) 0%,
rgba(61, 214, 141, 0.1) 100%
);
border-radius: 12px;
padding: 2rem;
border-left: 4px solid #4a9eff;
transition: all 0.3s ease;
}
.feature-box:hover {
background: linear-gradient(
135deg,
rgba(74, 158, 255, 0.15) 0%,
rgba(61, 214, 141, 0.15) 100%
);
transform: translateY(-3px);
}
.feature-icon {
font-size: 2.5rem;
margin-bottom: 1rem;
}
.feature-title {
font-size: 1.15rem;
font-weight: 700;
color: #4a9eff;
margin-bottom: 0.7rem;
}
.feature-text {
color: #cbd5e1;
font-size: 0.95rem;
line-height: 1.7;
}
.feature-text.feature-text {
list-style: none;
padding: 0;
margin: 0;
}
.feature-text li {
padding-left: 1.2rem;
margin-bottom: 0.6rem;
position: relative;
}
.feature-text li:before {
content: "▸";
color: #3dd68d;
font-weight: bold;
position: absolute;
left: 0;
}
.components-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 1rem;
margin-top: 2rem;
}
.component-item {
background: rgba(74, 158, 255, 0.1);
padding: 1.2rem;
border-radius: 8px;
font-size: 0.9rem;
border: 1px solid rgba(74, 158, 255, 0.3);
transition: all 0.2s ease;
text-align: center;
}
.component-item:hover {
background: rgba(74, 158, 255, 0.15);
transform: translateY(-2px);
}
.component-name {
color: #4a9eff;
font-weight: 700;
display: block;
margin-bottom: 0.3rem;
}
.component-role {
color: #94a3b8;
font-size: 0.85rem;
}
.cta-section {
text-align: center;
margin: 5rem 0 3rem;
padding: 4rem 2rem;
background: linear-gradient(
135deg,
rgba(74, 158, 255, 0.1) 0%,
rgba(61, 214, 141, 0.1) 100%
);
border-radius: 20px;
border: 1px solid rgba(74, 158, 255, 0.3);
}
.cta-title {
font-size: 2rem;
font-weight: 800;
margin-bottom: 1rem;
background: linear-gradient(135deg, #4a9eff 0%, #3dd68d 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.cta-button {
display: inline-block;
background: linear-gradient(
135deg,
#4a9eff 0%,
#3dd68d 50%,
#fbbf24 100%
);
color: #fff;
padding: 1.1rem 2.8rem;
border-radius: 50px;
text-decoration: none;
font-weight: 800;
font-size: 1rem;
transition: all 0.3s ease;
box-shadow: 0 10px 30px rgba(74, 158, 255, 0.3);
text-transform: uppercase;
letter-spacing: 0.05em;
border: none;
cursor: pointer;
}
.cta-button:hover {
transform: translateY(-3px) scale(1.05);
box-shadow: 0 20px 50px rgba(74, 158, 255, 0.5);
}
footer {
text-align: center;
padding: 3rem 0 2rem;
color: #64748b;
border-top: 1px solid rgba(255, 255, 255, 0.1);
margin-top: 4rem;
font-size: 0.9rem;
}
footer p:first-child {
font-weight: 700;
color: #94a3b8;
}
footer p:last-child {
margin-top: 0.5rem;
font-size: 0.85rem;
}
.hidden {
display: none;
}
@media (max-width: 768px) {
h1 {
font-size: 2rem;
}
.hero-subtitle {
font-size: 1rem;
}
.logo-container img {
max-width: 320px;
}
.section-title {
font-size: 1.6rem;
}
.cta-title {
font-size: 1.6rem;
}
.language-toggle {
top: 1rem;
right: 1rem;
}
}
</style>
</head>
<body>
<div class="gradient-bg"></div>
<div class="language-toggle">
<button
class="lang-btn active"
data-lang="en"
onclick="switchLanguage('en')"
>
EN
</button>
<button class="lang-btn" data-lang="es" onclick="switchLanguage('es')">
ES
</button>
</div>
<div class="container">
<header>
<span class="status-badge" data-en="✅ v0.1.0" data-es="✅ v0.1.0"
>✅ v0.1.0</span
>
<div class="logo-container">
<img src="/kogral.svg" alt="KOGRAL - Git-Native Knowledge Graphs" />
</div>
<p class="tagline">Git-Native Knowledge Management</p>
<h1
data-en="Knowledge Graphs<br>That Live in Git"
data-es="Grafos de Conocimiento<br>Que Viven en Git"
>
Knowledge Graphs
</h1>
<p class="hero-subtitle">
<span
class="highlight"
data-en="Structured knowledge management"
data-es="Gestión estructurada de conocimiento"
>Structured knowledge management</span
><span
data-en=" that scales from solo projects to organizations. Config-driven architecture for capturing architectural decisions, coding guidelines, and reusable patterns in version-controlled markdown."
data-es=" que escala desde proyectos individuales a organizaciones. Arquitectura basada en configuración para capturar decisiones arquitectónicas, guías de código y patrones reutilizables en markdown versionado."
> that scales from solo projects to organizations. Config-driven architecture for capturing architectural decisions, coding guidelines, and reusable patterns in version-controlled markdown.
</span>
<br><span><strong data-en="100% Rust. Zero compromises." data-es="100% Rust. Sin compromisos."
>100% Rust. Zero compromises.</strong
>
</span>
</p>
</header>
<section class="section">
<h2 class="section-title">
<span
data-en="The 4 Problems It Solves"
data-es="Los 4 Problemas que Resuelve"
>The 4 Problems It Solves</span
>
</h2>
<div class="problems-grid">
<div class="problem-card">
<div class="problem-number">01</div>
<h3 data-en="Scattered Documentation" data-es="Documentación Dispersa">
Scattered Documentation
</h3>
<ul
data-en="<li>Notes in Notion</li><li>Decisions in Slack</li><li>Guidelines in wikis—all disconnected</li><li>KOGRAL unifies with git-native markdown + MCP</li>"
data-es="<li>Notas en Notion</li><li>Decisiones en Slack</li><li>Guías en wikis—todo desconectado</li><li>KOGRAL unifica con markdown git-native + MCP</li>"
>
<li>Notes in Notion</li>
<li>Decisions in Slack</li>
<li>Guidelines in wikis—all disconnected</li>
<li>KOGRAL unifies with git-native markdown + MCP</li>
</ul>
</div>
<div class="problem-card">
<div class="problem-number">02</div>
<h3
data-en="No Version Control for Decisions"
data-es="Sin Control de Versiones para Decisiones"
>
No Version Control for Decisions
</h3>
<ul
data-en="<li>Architectural decisions lost in chat history</li><li>No traceability for why code exists</li><li>KOGRAL: Git-tracked ADRs with full history</li><li>Link decisions directly to code with @file:line</li>"
data-es="<li>Decisiones arquitectónicas perdidas en chat</li><li>Sin trazabilidad de por qué existe el código</li><li>KOGRAL: ADRs rastreados en Git con historial completo</li><li>Vincula decisiones al código con @file:line</li>"
>
<li>Architectural decisions lost in chat history</li>
<li>No traceability for why code exists</li>
<li>KOGRAL: Git-tracked ADRs with full history</li>
<li>Link decisions directly to code with @file:line</li>
</ul>
</div>
<div class="problem-card">
<div class="problem-number">03</div>
<h3 data-en="Lost Context Over Time" data-es="Contexto Perdido con el Tiempo">
Lost Context Over Time
</h3>
<ul
data-en="<li>Team members join and can't find past decisions</li><li>Outdated documentation causes repeated mistakes</li><li>KOGRAL: Semantic search across your knowledge base</li><li>Relationship tracking shows why patterns exist</li>"
data-es="<li>Nuevos miembros no encuentran decisiones pasadas</li><li>Documentación desactualizada causa errores repetidos</li><li>KOGRAL: Búsqueda semántica en tu base de conocimiento</li><li>Rastreo de relaciones muestra por qué existen patrones</li>"
>
<li>Team members join and can't find past decisions</li>
<li>Outdated documentation causes repeated mistakes</li>
<li>KOGRAL: Semantic search across your knowledge base</li>
<li>Relationship tracking shows why patterns exist</li>
</ul>
</div>
<div class="problem-card">
<div class="problem-number">04</div>
<h3 data-en="Isolated Team Knowledge" data-es="Conocimiento Aislado del Equipo">
Isolated Team Knowledge
</h3>
<ul
data-en="<li>Every project reinvents the wheel</li><li>Patterns can't be shared across teams</li><li>KOGRAL: Multi-graph architecture</li><li>Shared organizational knowledge + project-specific overrides</li><li>Inheritance system for guidelines</li>"
data-es="<li>Cada proyecto reinventa la rueda</li><li>Los patrones no se comparten entre equipos</li><li>KOGRAL: Arquitectura multi-grafo</li><li>Conocimiento organizacional compartido + sobrescrituras por proyecto</li><li>Sistema de herencia para guías</li>"
>
<li>Every project reinvents the wheel</li>
<li>Patterns can't be shared across teams</li>
<li>KOGRAL: Multi-graph architecture</li>
<li>Shared organizational knowledge + project-specific overrides</li>
<li>Inheritance system for guidelines</li>
</ul>
</div>
</div>
</section>
<section class="section">
<h2 class="section-title">
<span data-en="How It Works" data-es="Cómo Funciona"
>How It Works</span
>
</h2>
<div class="features-grid">
<div class="feature-box">
<div class="feature-icon">📝</div>
<h3
class="feature-title"
data-en="Markdown-Native"
data-es="Markdown Nativo"
>
Markdown-Native
</h3>
<ul
class="feature-text"
data-en="<li>YAML frontmatter for metadata</li><li>Wikilinks [[like-this]] for relationships</li><li>Code references @file.rs:42</li><li>Logseq-compatible format</li><li>Human-readable, Git-friendly</li>"
data-es="<li>YAML frontmatter para metadatos</li><li>Wikilinks [[así]] para relaciones</li><li>Referencias de código @file.rs:42</li><li>Formato compatible con Logseq</li><li>Legible por humanos, amigable con Git</li>"
>
<li>YAML frontmatter for metadata</li>
<li>Wikilinks [[like-this]] for relationships</li>
<li>Code references @file.rs:42</li>
<li>Logseq-compatible format</li>
<li>Human-readable, Git-friendly</li>
</ul>
</div>
<div class="feature-box" style="border-left-color: #3dd68d">
<div class="feature-icon">🔍</div>
<h3
class="feature-title"
style="color: #3dd68d"
data-en="Semantic Search"
data-es="Búsqueda Semántica"
>
Semantic Search
</h3>
<ul
class="feature-text"
data-en="<li>Text search across all nodes</li><li>Vector embeddings for semantic queries</li><li>Local embeddings (fastembed, no API costs)</li><li>Cloud APIs supported (OpenAI, Claude, Ollama)</li><li>Find related knowledge automatically</li>"
data-es="<li>Búsqueda de texto en todos los nodos</li><li>Embeddings vectoriales para consultas semánticas</li><li>Embeddings locales (fastembed, sin costos API)</li><li>APIs en la nube soportadas (OpenAI, Claude, Ollama)</li><li>Encuentra conocimiento relacionado automáticamente</li>"
>
<li>Text search across all nodes</li>
<li>Vector embeddings for semantic queries</li>
<li>Local embeddings (fastembed, no API costs)</li>
<li>Cloud APIs supported (OpenAI, Claude, Ollama)</li>
<li>Find related knowledge automatically</li>
</ul>
</div>
<div class="feature-box" style="border-left-color: #fbbf24">
<div class="feature-icon">⚙️</div>
<h3
class="feature-title"
style="color: #fbbf24"
data-en="Config-Driven"
data-es="Basado en Configuración"
>
Config-Driven
</h3>
<ul
class="feature-text"
data-en="<li>Nickel schemas with validation</li><li>3 modes: dev, prod, test</li><li>Storage backend selection (filesystem, SurrealDB, in-memory)</li><li>Embedding provider configuration</li><li>No hardcoded paths or settings</li>"
data-es="<li>Esquemas Nickel con validación</li><li>3 modos: dev, prod, test</li><li>Selección de backend de almacenamiento (filesystem, SurrealDB, memoria)</li><li>Configuración de proveedor de embeddings</li><li>Sin rutas o configuraciones hardcodeadas</li>"
>
<li>Nickel schemas with validation</li>
<li>3 modes: dev, prod, test</li>
<li>Storage backend selection (filesystem, SurrealDB, in-memory)</li>
<li>Embedding provider configuration</li>
<li>No hardcoded paths or settings</li>
</ul>
</div>
<div class="feature-box" style="border-left-color: #64748b">
<div class="feature-icon">🤖</div>
<h3
class="feature-title"
style="color: #64748b"
data-en="Claude Code Integration"
data-es="Integración Claude Code"
>
Claude Code Integration
</h3>
<ul
class="feature-text"
data-en="<li>MCP server (Model Context Protocol)</li><li>7 tools: search, add notes/decisions, link, export</li><li>6 resources: project/shared graphs</li><li>2 prompts: summarize project, find related</li><li>JSON-RPC 2.0 over stdio</li>"
data-es="<li>Servidor MCP (Model Context Protocol)</li><li>7 herramientas: buscar, añadir notas/decisiones, vincular, exportar</li><li>6 recursos: grafos proyecto/compartidos</li><li>2 prompts: resumir proyecto, encontrar relacionados</li><li>JSON-RPC 2.0 sobre stdio</li>"
>
<li>MCP server (Model Context Protocol)</li>
<li>7 tools: search, add notes/decisions, link, export</li>
<li>6 resources: project/shared graphs</li>
<li>2 prompts: summarize project, find related</li>
<li>JSON-RPC 2.0 over stdio</li>
</ul>
</div>
</div>
</section>
<section class="section">
<h2 class="section-title">
<span data-en="Technology Stack" data-es="Stack Tecnológico"
>Technology Stack</span
>
</h2>
<div class="tech-stack">
<span class="tech-badge">Rust Edition 2021</span>
<span class="tech-badge">Nickel Config</span>
<span class="tech-badge">SurrealDB</span>
<span class="tech-badge">fastembed</span>
<span class="tech-badge">rig-core</span>
<span class="tech-badge">MCP Protocol</span>
<span class="tech-badge">Logseq Compatible</span>
<span class="tech-badge">Tera Templates</span>
<span class="tech-badge">Clap CLI</span>
<span class="tech-badge">DashMap</span>
<span class="tech-badge">Nushell Scripts</span>
<span class="tech-badge">mdBook Docs</span>
</div>
</section>
<section class="section">
<h2 class="section-title">
<span data-en="Core Components" data-es="Componentes Principales"
>Core Components</span
>
</h2>
<div class="components-grid">
<div class="component-item">
<span class="component-name" data-en="kogral-core" data-es="kogral-core"
>kogral-core</span
><span
class="component-role"
data-en="Core library"
data-es="Biblioteca núcleo"
>Core library</span
>
</div>
<div class="component-item">
<span class="component-name" data-en="kogral-cli" data-es="kogral-cli"
>kogral-cli</span
><span
class="component-role"
data-en="13 commands"
data-es="13 comandos"
>13 commands</span
>
</div>
<div class="component-item">
<span
class="component-name"
data-en="kogral-mcp"
data-es="kogral-mcp"
>kogral-mcp</span
><span
class="component-role"
data-en="MCP server"
data-es="Servidor MCP"
>MCP server</span
>
</div>
<div class="component-item">
<span class="component-name" data-en="Config System" data-es="Sistema Config"
>Config System</span
><span
class="component-role"
data-en="Nickel schemas"
data-es="Esquemas Nickel"
>Nickel schemas</span
>
</div>
<div class="component-item">
<span class="component-name" data-en="3 Storage Backends" data-es="3 Backends Storage"
>3 Storage Backends</span
><span
class="component-role"
data-en="Filesystem, SurrealDB, Memory"
data-es="Filesystem, SurrealDB, Memoria"
>Filesystem, SurrealDB, Memory</span
>
</div>
<div class="component-item">
<span class="component-name" data-en="2 Embedding Providers" data-es="2 Proveedores Embeddings"
>2 Embedding Providers</span
><span
class="component-role"
data-en="FastEmbed, rig-core"
data-es="FastEmbed, rig-core"
>FastEmbed, rig-core</span
>
</div>
<div class="component-item">
<span
class="component-name"
data-en="6 Node Types"
data-es="6 Tipos de Nodos"
>6 Node Types</span
><span
class="component-role"
data-en="Note, Decision, Guideline, Pattern, Journal, Execution"
data-es="Nota, Decisión, Guía, Patrón, Diario, Ejecución"
>Note, Decision, Guideline, Pattern, Journal, Execution</span
>
</div>
<div class="component-item">
<span
class="component-name"
data-en="6 Relationships"
data-es="6 Relaciones"
>6 Relationships</span
><span
class="component-role"
data-en="relates_to, depends_on, implements, extends, supersedes, explains"
data-es="relates_to, depends_on, implements, extends, supersedes, explains"
>relates_to, depends_on, implements, extends, supersedes, explains</span
>
</div>
<div class="component-item">
<span
class="component-name"
data-en="Multi-Graph"
data-es="Multi-Grafo"
>Multi-Graph</span
><span
class="component-role"
data-en="Project + Shared"
data-es="Proyecto + Compartido"
>Project + Shared</span
>
</div>
<div class="component-item">
<span class="component-name" data-en="56 Tests Passing" data-es="56 Tests Pasando"
>56 Tests Passing</span
><span
class="component-role"
data-en="Quality assurance"
data-es="Aseguramiento calidad"
>Quality assurance</span
>
</div>
<div class="component-item">
<span class="component-name" data-en="0 Unsafe Code" data-es="0 Código Unsafe"
>0 Unsafe Code</span
><span
class="component-role"
data-en="Memory safety"
data-es="Seguridad memoria"
>Memory safety</span
>
</div>
<div class="component-item">
<span
class="component-name"
data-en="100% Doc Coverage"
data-es="100% Cobertura Doc"
>100% Doc Coverage</span
><span
class="component-role"
data-en="Public APIs documented"
data-es="APIs públicas documentadas"
>Public APIs documented</span
>
</div>
</div>
</section>
<div class="cta-section">
<h2
class="cta-title"
data-en="Ready to organize your knowledge?"
data-es="¿Listo para organizar tu conocimiento?"
>
Ready to organize your knowledge?
</h2>
<p
style="color: #94a3b8; margin-bottom: 2rem; font-size: 1.05rem"
data-en="3 Crates | 56 Tests | 15K LOC | 100% Rust 🦀"
data-es="3 Crates | 56 Tests | 15K LOC | 100% Rust 🦀"
>
3 Crates | 56 Tests | 15K LOC | 100% Rust 🦀
</p>
<a
href="https://github.com/jesusperezlorenzo/kogral"
class="cta-button"
data-en="Get Started →"
data-es="Comenzar →"
>Get Started →</a
>
</div>
<footer>
<p data-en="KOGRAL v0.1.0" data-es="KOGRAL v0.1.0">KOGRAL v0.1.0</p>
<p
data-en="Built with Rust • Configuration with Nickel"
data-es="Construido con Rust • Configuración con Nickel"
>
Built with Rust • Configuration with Nickel
</p>
<p
style="margin-top: 1rem; font-size: 0.8rem"
data-en="Git-Native Knowledge Graphs for Developer Teams"
data-es="Grafos de Conocimiento Git-Native para Equipos de Desarrollo"
>
Git-Native Knowledge Graphs for Developer Teams
</p>
</footer>
</div>
<script>
// Language management
const LANG_KEY = "kogral-lang";
function getCurrentLanguage() {
return localStorage.getItem(LANG_KEY) || "en";
}
function switchLanguage(lang) {
localStorage.setItem(LANG_KEY, lang);
// Update language buttons
document.querySelectorAll(".lang-btn").forEach((btn) => {
btn.classList.remove("active");
if (btn.dataset.lang === lang) {
btn.classList.add("active");
}
});
// Update all translatable elements
document.querySelectorAll("[data-en][data-es]").forEach((el) => {
const content = el.dataset[lang];
// Use innerHTML for headings (might contain <br>) and lists (contain <li>)
if (
el.tagName === "H1" ||
el.tagName === "H2" ||
el.tagName === "H3" ||
el.tagName === "UL"
) {
el.innerHTML = content;
} else {
el.textContent = content;
}
});
document.documentElement.lang = lang;
}
// Initialize language on page load
document.addEventListener("DOMContentLoaded", () => {
const currentLang = getCurrentLanguage();
switchLanguage(currentLang);
});
</script>
</body>
</html>