Improve soleprint docs: bilingual EN/ES, system pages, architecture cleanup

This commit is contained in:
buenosairesam
2026-01-27 09:15:59 -03:00
parent ed1c8f6c96
commit fa7bbe3953
6 changed files with 1366 additions and 51 deletions

View File

@@ -0,0 +1,191 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sidebar Injection - Soleprint</title>
<link rel="stylesheet" href="styles.css" />
<style>
pre {
background: #1a1a1a;
padding: 1rem;
border-radius: 8px;
overflow-x: auto;
font-size: 0.85rem;
line-height: 1.5;
}
code {
font-family: monospace;
background: #2a2a2a;
padding: 0.15rem 0.4rem;
border-radius: 4px;
}
pre code {
background: none;
padding: 0;
}
table {
width: 100%;
border-collapse: collapse;
margin: 1rem 0;
}
th, td {
border: 1px solid #3f3f3f;
padding: 0.5rem;
text-align: left;
}
th {
background: #1a1a1a;
}
</style>
<script src="../lang-toggle.js"></script>
</head>
<body>
<header>
<div id="lang-toggle"></div>
<h1>Sidebar Injection</h1>
<p class="subtitle">
<span class="lang-en">How managed room sidebar works</span>
<span class="lang-es">Como funciona el sidebar del managed room</span>
</p>
</header>
<main>
<section class="findings-section">
<h2>Overview</h2>
<p class="lang-en">The soleprint sidebar is injected into managed app pages using a hybrid nginx + JavaScript approach. This allows any frontend framework (React, Next.js, static HTML) to receive the sidebar without code modifications.</p>
<p class="lang-es">El sidebar de soleprint se inyecta en las paginas de apps manejadas usando un enfoque hibrido nginx + JavaScript. Esto permite que cualquier framework frontend (React, Next.js, HTML estatico) reciba el sidebar sin modificaciones de codigo.</p>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">How It Works</span>
<span class="lang-es">Como Funciona</span>
</h2>
<pre>
┌─────────────────────────────────────────────────────────────────┐
│ Browser Request │
│ http://room.spr.local.ar/ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Nginx │
│ │
│ 1. Routes /spr/* → soleprint:PORT (sidebar assets + API) │
│ 2. Routes /* → frontend:PORT (app pages) │
│ 3. Injects CSS+JS into HTML responses via sub_filter │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Browser Renders │
│ │
│ 1. Page loads with injected CSS (sidebar styles ready) │
│ 2. sidebar.js executes (deferred, after DOM ready) │
│ 3. JS fetches /spr/api/sidebar/config │
│ 4. JS creates sidebar DOM elements and injects into page │
│ 5. Sidebar appears on left side, pushes content with margin │
└─────────────────────────────────────────────────────────────────┘</pre>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Key Design Decisions</span>
<span class="lang-es">Decisiones de Diseno Clave</span>
</h2>
<div class="findings-grid">
<article class="finding-card">
<h3><span class="lang-en">Why nginx sub_filter?</span><span class="lang-es">Por que nginx sub_filter?</span></h3>
<p class="lang-en"><strong>Framework agnostic</strong>: Works with any frontend. No app changes needed. Easy to disable.</p>
<p class="lang-es"><strong>Agnostico de framework</strong>: Funciona con cualquier frontend. Sin cambios en la app. Facil de deshabilitar.</p>
</article>
<article class="finding-card">
<h3><span class="lang-en">Why inject into &lt;/head&gt;?</span><span class="lang-es">Por que inyectar en &lt;/head&gt;?</span></h3>
<p class="lang-en">Next.js and streaming SSR may not include &lt;/body&gt; in initial response. &lt;/head&gt; is always present.</p>
<p class="lang-es">Next.js y SSR streaming pueden no incluir &lt;/body&gt; en la respuesta inicial. &lt;/head&gt; siempre esta presente.</p>
</article>
<article class="finding-card">
<h3><span class="lang-en">Why JS instead of iframe?</span><span class="lang-es">Por que JS en vez de iframe?</span></h3>
<p class="lang-en">No isolation issues, better UX (no double scrollbars), simpler CSS with margin-left.</p>
<p class="lang-es">Sin problemas de aislamiento, mejor UX (sin doble scrollbar), CSS mas simple con margin-left.</p>
</article>
</div>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Nginx Configuration</span>
<span class="lang-es">Configuracion de Nginx</span>
</h2>
<p class="lang-en">The nginx config injects CSS+JS into HTML responses:</p>
<p class="lang-es">La config de nginx inyecta CSS+JS en las respuestas HTML:</p>
<pre><code>location / {
proxy_pass http://frontend:PORT;
proxy_set_header Accept-Encoding ""; # Required for sub_filter
# Inject sidebar
sub_filter '&lt;/head&gt;'
'&lt;link rel="stylesheet" href="/spr/sidebar.css"&gt;
&lt;script src="/spr/sidebar.js" defer&gt;&lt;/script&gt;&lt;/head&gt;';
sub_filter_once off;
sub_filter_types text/html;
}</code></pre>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Port Allocation</span>
<span class="lang-es">Asignacion de Puertos</span>
</h2>
<p class="lang-en">Each room uses unique ports for concurrent operation:</p>
<p class="lang-es">Cada room usa puertos unicos para operacion concurrente:</p>
<table>
<tr><th>Room</th><th>Soleprint</th><th>Frontend</th><th>Backend</th></tr>
<tr><td>amar</td><td>12000</td><td>3000</td><td>8001</td></tr>
<tr><td>dlt</td><td>12010</td><td>3010</td><td>-</td></tr>
<tr><td>sample</td><td>12020</td><td>3020</td><td>8020</td></tr>
</table>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Sidebar Config API</span>
<span class="lang-es">API de Config del Sidebar</span>
</h2>
<p class="lang-en">The sidebar JS fetches configuration from <code>/spr/api/sidebar/config</code>:</p>
<p class="lang-es">El JS del sidebar obtiene configuracion de <code>/spr/api/sidebar/config</code>:</p>
<pre><code>{
"room": "amar",
"soleprint_base": "/spr",
"auth_enabled": true,
"tools": {
"artery": "/spr/artery",
"atlas": "/spr/atlas",
"station": "/spr/station"
}
}</code></pre>
</section>
<section class="findings-section">
<h2>Troubleshooting</h2>
<div class="findings-grid">
<article class="finding-card">
<h3><span class="lang-en">Sidebar not appearing</span><span class="lang-es">Sidebar no aparece</span></h3>
<p class="lang-en">Check if soleprint is running. Verify nginx has <code>Accept-Encoding ""</code>. Hard refresh (Ctrl+Shift+R).</p>
<p class="lang-es">Verificar que soleprint esta corriendo. Verificar que nginx tiene <code>Accept-Encoding ""</code>. Refresco forzado (Ctrl+Shift+R).</p>
</article>
<article class="finding-card">
<h3><span class="lang-en">sub_filter not working</span><span class="lang-es">sub_filter no funciona</span></h3>
<p class="lang-en">Ensure <code>proxy_set_header Accept-Encoding ""</code> is set. Check response is <code>text/html</code>.</p>
<p class="lang-es">Asegurar que <code>proxy_set_header Accept-Encoding ""</code> esta seteado. Verificar que la respuesta es <code>text/html</code>.</p>
</article>
</div>
</section>
</main>
<footer>
<p><a href="../"><span class="lang-en">← Back to index</span><span class="lang-es">← Volver al indice</span></a></p>
</footer>
</body>
</html>

314
docs/artery/index.html Normal file
View File

@@ -0,0 +1,314 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Artery - Soleprint</title>
<link rel="stylesheet" href="../architecture/styles.css" />
<style>
.composition {
background: #1a1a1a;
border: 2px solid #b91c1c;
padding: 1rem;
border-radius: 12px;
margin-bottom: 1rem;
}
.composition h3 {
margin: 0 0 0.75rem 0;
font-size: 1.1rem;
color: #fca5a5;
}
.composition > p {
margin: 0 0 1rem 0;
font-size: 0.9rem;
color: #a3a3a3;
}
.components {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 0.75rem;
}
.component {
background: #0a0a0a;
border: 1px solid #3f3f3f;
padding: 0.75rem;
border-radius: 8px;
}
.component h4 {
margin: 0 0 0.25rem 0;
font-size: 0.95rem;
color: #fca5a5;
}
.component p {
margin: 0;
font-size: 0.85rem;
color: #a3a3a3;
}
.model-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1rem;
}
</style>
<script src="../lang-toggle.js"></script>
</head>
<body>
<header>
<div id="lang-toggle"></div>
<h1>Artery</h1>
<p class="subtitle">Todo lo vital</p>
</header>
<main>
<section class="findings-section">
<h2>
<span class="lang-en">Model</span
><span class="lang-es">Modelo</span>
</h2>
<div class="model-grid">
<div class="composition">
<h3>Pulse</h3>
<p class="lang-en">
Composed data flow: a vein configured for a room
with storage
</p>
<p class="lang-es">
Flujo de datos compuesto: vein configurado para un
room con almacenamiento
</p>
<div class="components">
<div class="component">
<h4>Vein</h4>
<p class="lang-en">API connector</p>
<p class="lang-es">Conector API</p>
</div>
<div class="component">
<h4>Room</h4>
<p class="lang-en">Config/env</p>
<p class="lang-es">Config/entorno</p>
</div>
<div class="component">
<h4>Depot</h4>
<p class="lang-en">Data storage</p>
<p class="lang-es">Almacenamiento</p>
</div>
</div>
</div>
<div class="composition">
<h3>Shunt</h3>
<p class="lang-en">
Mock connector for testing - same interface, fake
data
</p>
<p class="lang-es">
Conector mock para testing - misma interfaz, datos
falsos
</p>
<div class="components">
<div class="component">
<h4>Vein Interface</h4>
<p class="lang-en">Same API shape</p>
<p class="lang-es">Misma forma de API</p>
</div>
<div class="component">
<h4>Mock Data</h4>
<p class="lang-en">Fake responses</p>
<p class="lang-es">Respuestas falsas</p>
</div>
</div>
</div>
<div class="composition">
<h3>Plexus</h3>
<p class="lang-en">
Full application when you need more than data flow
</p>
<p class="lang-es">
Aplicacion completa cuando necesitas mas que flujo
de datos
</p>
<div class="components">
<div class="component">
<h4>Backend</h4>
<p>FastAPI server</p>
</div>
<div class="component">
<h4>Frontend</h4>
<p>Web UI</p>
</div>
<div class="component">
<h4>Infra</h4>
<p class="lang-en">DB, queues, etc</p>
<p class="lang-es">DB, colas, etc</p>
</div>
</div>
</div>
</div>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Architecture</span
><span class="lang-es">Arquitectura</span>
</h2>
<img
src="../architecture/02-artery-hierarchy.svg"
alt="Artery Hierarchy"
style="
max-width: 100%;
background: white;
border-radius: 8px;
padding: 1rem;
"
/>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Components</span
><span class="lang-es">Componentes</span>
</h2>
<div class="findings-grid">
<article class="finding-card">
<h3>Vein</h3>
<p class="lang-en">
Stateless API connector. Connects to external
services like Google Sheets, Jira, Slack. Pure data
flow - no state, no storage.
</p>
<p class="lang-es">
Conector API sin estado. Conecta a servicios
externos como Google Sheets, Jira, Slack. Flujo de
datos puro.
</p>
</article>
<article class="finding-card">
<h3>Shunt</h3>
<p class="lang-en">
Mock connector for testing. Same interface as a vein
but returns fake data.
</p>
<p class="lang-es">
Conector mock para testing. Misma interfaz que un
vein pero devuelve datos falsos.
</p>
</article>
<article class="finding-card">
<h3>Pulse</h3>
<p class="lang-en">
Composed data flow. Formula:
<strong>Vein + Room + Depot</strong>.
</p>
<p class="lang-es">
Flujo de datos compuesto. Formula:
<strong>Vein + Room + Depot</strong>.
</p>
</article>
<article class="finding-card">
<h3>Plexus</h3>
<p class="lang-en">
Full application with backend, frontend, and
infrastructure.
</p>
<p class="lang-es">
Aplicacion completa con backend, frontend e
infraestructura.
</p>
</article>
</div>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Shared Components</span
><span class="lang-es">Componentes Compartidos</span>
</h2>
<div class="findings-grid">
<article class="finding-card">
<h3>Room</h3>
<p class="lang-en">
Runtime environment configuration. Each room is an
isolated instance with its own config and
credentials.
</p>
<p class="lang-es">
Configuracion del entorno. Cada room es una
instancia aislada con su propia config y
credenciales.
</p>
</article>
<article class="finding-card">
<h3>Depot</h3>
<p class="lang-en">
Data storage / provisions. JSON files, configs,
cached responses.
</p>
<p class="lang-es">
Almacenamiento de datos. Archivos JSON, configs,
respuestas cacheadas.
</p>
</article>
</div>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Available Veins</span
><span class="lang-es">Veins Disponibles</span>
</h2>
<div class="findings-grid">
<a
href="../veins/index.html"
class="finding-card"
style="text-decoration: none"
>
<h3>Google</h3>
<p class="lang-en">
Google Sheets API. OAuth authentication, read/write
spreadsheets.
</p>
<p class="lang-es">
Google Sheets API. Autenticacion OAuth,
leer/escribir hojas de calculo.
</p>
</a>
<a
href="../veins/index.html"
class="finding-card"
style="text-decoration: none"
>
<h3>Jira</h3>
<p class="lang-en">
Jira Cloud API. Query issues, projects, sprints.
</p>
<p class="lang-es">
Jira Cloud API. Consultar issues, proyectos,
sprints.
</p>
</a>
<a
href="../veins/index.html"
class="finding-card"
style="text-decoration: none"
>
<h3>Slack</h3>
<p class="lang-en">
Slack API. Channels, messages, users.
</p>
<p class="lang-es">
Slack API. Canales, mensajes, usuarios.
</p>
</a>
</div>
</section>
</main>
<footer>
<p>
<a href="../"
><span class="lang-en">← Back to index</span
><span class="lang-es">← Volver al indice</span></a
>
</p>
</footer>
</body>
</html>

258
docs/atlas/index.html Normal file
View File

@@ -0,0 +1,258 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Atlas - Soleprint</title>
<link rel="stylesheet" href="../architecture/styles.css" />
<style>
.composition {
background: #1a1a1a;
border: 2px solid #15803d;
padding: 1rem;
border-radius: 12px;
margin-bottom: 1rem;
}
.composition h3 {
margin: 0 0 0.75rem 0;
font-size: 1.1rem;
color: #86efac;
}
.composition > p {
margin: 0 0 1rem 0;
font-size: 0.9rem;
color: #a3a3a3;
}
.components {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 0.75rem;
}
.component {
background: #0a0a0a;
border: 1px solid #3f3f3f;
padding: 0.75rem;
border-radius: 8px;
}
.component h4 {
margin: 0 0 0.25rem 0;
font-size: 0.95rem;
color: #86efac;
}
.component p {
margin: 0;
font-size: 0.85rem;
color: #a3a3a3;
}
.model-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1rem;
}
</style>
<script src="../lang-toggle.js"></script>
</head>
<body>
<header>
<div id="lang-toggle"></div>
<h1>Atlas</h1>
<p class="subtitle">Todo lo escrito</p>
</header>
<main>
<section class="findings-section">
<h2>
<span class="lang-en">Model</span
><span class="lang-es">Modelo</span>
</h2>
<div class="model-grid">
<div class="composition">
<h3>Plain Book</h3>
<p class="lang-en">
Static documentation with an index page
</p>
<p class="lang-es">
Documentacion estatica con una pagina indice
</p>
<div class="components">
<div class="component">
<h4>index.html</h4>
<p class="lang-en">Entry point</p>
<p class="lang-es">Punto de entrada</p>
</div>
<div class="component">
<h4>Depot</h4>
<p class="lang-en">Static content</p>
<p class="lang-es">Contenido estatico</p>
</div>
</div>
</div>
<div class="composition">
<h3>Templated Book</h3>
<p class="lang-en">
Dynamic docs from template + data elements
</p>
<p class="lang-es">
Docs dinamicos desde template + elementos de datos
</p>
<div class="components">
<div class="component">
<h4>Template</h4>
<p class="lang-en">Jinja2 pattern</p>
<p class="lang-es">Patron Jinja2</p>
</div>
<div class="component">
<h4>Depot</h4>
<p class="lang-en">Data elements</p>
<p class="lang-es">Elementos de datos</p>
</div>
</div>
</div>
</div>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Architecture</span
><span class="lang-es">Arquitectura</span>
</h2>
<img
src="../architecture/01-system-overview.svg"
alt="System Overview"
style="
max-width: 100%;
background: white;
border-radius: 8px;
padding: 1rem;
"
/>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Components</span
><span class="lang-es">Componentes</span>
</h2>
<div class="findings-grid">
<article class="finding-card">
<h3>Book</h3>
<p class="lang-en">
Collection of related documentation. Can be plain
(static HTML) or templated (template + depot
elements).
</p>
<p class="lang-es">
Coleccion de documentacion relacionada. Puede ser
plain (HTML estatico) o templated (template +
elementos de depot).
</p>
</article>
<article class="finding-card">
<h3>Template</h3>
<p class="lang-en">
Jinja2 templates that generate documentation. Define
the structure once, fill with data from depot.
</p>
<p class="lang-es">
Templates Jinja2 que generan documentacion. Definen
la estructura una vez, llenan con datos del depot.
</p>
</article>
</div>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Shared Components</span
><span class="lang-es">Componentes Compartidos</span>
</h2>
<div class="findings-grid">
<article class="finding-card">
<h3>Room</h3>
<p class="lang-en">
Runtime environment configuration. Each room can
have its own atlas with project-specific books.
</p>
<p class="lang-es">
Configuracion del entorno. Cada room puede tener su
propio atlas con books especificos del proyecto.
</p>
</article>
<article class="finding-card">
<h3>Depot</h3>
<p class="lang-en">
Data storage. For plain books: static files. For
templated books: elements that fill the template.
</p>
<p class="lang-es">
Almacenamiento de datos. Para plain books: archivos
estaticos. Para templated books: elementos que
llenan el template.
</p>
</article>
</div>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Examples</span
><span class="lang-es">Ejemplos</span>
</h2>
<div class="findings-grid">
<article class="finding-card">
<h3>Feature Flow</h3>
<p class="lang-en">
Plain book - HTML presentation explaining the
standardization pipeline.
</p>
<p class="lang-es">
Plain book - Presentacion HTML explicando el
pipeline de estandarizacion.
</p>
</article>
<article class="finding-card">
<h3>Feature Form Samples</h3>
<p class="lang-en">
Templated book - Form template + depot of actual
feature forms.
</p>
<p class="lang-es">
Templated book - Template de formulario + depot de
feature forms reales.
</p>
</article>
<article class="finding-card">
<h3>Gherkin Samples</h3>
<p class="lang-en">
Templated book - Gherkin viewer + depot of .feature
files.
</p>
<p class="lang-es">
Templated book - Visor Gherkin + depot de archivos
.feature.
</p>
</article>
<article class="finding-card">
<h3>Arch Model</h3>
<p class="lang-en">
Plain book - Static site with architecture diagrams.
</p>
<p class="lang-es">
Plain book - Sitio estatico con diagramas de
arquitectura.
</p>
</article>
</div>
</section>
</main>
<footer>
<p>
<a href="../"
><span class="lang-en">← Back to index</span
><span class="lang-es">← Volver al indice</span></a
>
</p>
</footer>
</body>
</html>

View File

@@ -5,39 +5,151 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Soleprint - Documentation</title> <title>Soleprint - Documentation</title>
<link rel="stylesheet" href="architecture/styles.css" /> <link rel="stylesheet" href="architecture/styles.css" />
<style>
.one-liner {
font-size: 1.2rem;
color: var(--text-secondary);
margin-top: 0.5rem;
}
.demo-link {
display: inline-block;
margin-top: 1rem;
padding: 0.5rem 1rem;
background: var(--accent);
color: var(--bg-primary);
text-decoration: none;
border-radius: 4px;
font-weight: 500;
}
.demo-link:hover {
opacity: 0.9;
}
.systems-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin: 1rem 0;
}
.system-card {
background: var(--bg-secondary);
padding: 1rem;
border-radius: 8px;
border-left: 3px solid var(--accent);
}
.system-card h3 {
margin: 0 0 0.5rem 0;
color: var(--text-primary);
}
.system-card p {
margin: 0;
color: var(--text-secondary);
font-size: 0.9rem;
}
.arch-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1rem;
margin: 1rem 0;
}
.arch-card {
display: block;
background: var(--bg-secondary);
padding: 1rem;
border-radius: 8px;
text-decoration: none;
transition: transform 0.15s;
}
.arch-card:hover {
transform: translateY(-2px);
}
.arch-card h4 {
margin: 0 0 0.5rem 0;
color: var(--text-primary);
}
.arch-card p {
margin: 0;
color: var(--text-secondary);
font-size: 0.85rem;
}
pre {
background: var(--bg-primary);
padding: 1rem;
border-radius: 4px;
overflow-x: auto;
margin-top: 0.5rem;
}
</style>
<script src="lang-toggle.js"></script>
</head> </head>
<body> <body>
<header> <header>
<div id="lang-toggle"></div>
<h1>Soleprint</h1> <h1>Soleprint</h1>
<p class="subtitle"> <p class="subtitle">Cada paso deja huella</p>
Cada paso deja huella / Each step leaves a mark <p class="one-liner">
<span class="lang-en"
>Pluggable stuff to tackle any challenge</span
>
<span class="lang-es"
>Piezas enchufables para cualquier desafio</span
>
</p> </p>
<a href="https://sample.spr.mcrn.ar" class="demo-link">
<span class="lang-en">Try the Demo</span>
<span class="lang-es">Ver Demo</span>
</a>
</header> </header>
<main> <main>
<section class="findings-section"> <section class="findings-section">
<h2>Documentation</h2> <h2>
<div class="findings-grid"> <span class="lang-en">The Three Systems</span>
<span class="lang-es">Los Tres Sistemas</span>
</h2>
<div class="systems-grid">
<a <a
href="architecture/index.html" href="artery/"
class="finding-card" class="system-card"
style="text-decoration: none" style="text-decoration: none"
> >
<h3>Architecture</h3> <h3>Artery</h3>
<p> <p class="lang-en">
System overview, connector hierarchy, build flow, API connectors and data flow. Veins for real APIs,
and room configuration diagrams. shunts for mocks.
</p>
<p class="lang-es">
Conectores y flujo de datos. Veins para APIs reales,
shunts para mocks.
</p> </p>
</a> </a>
<a <a
href="veins/index.html" href="atlas/"
class="finding-card" class="system-card"
style="text-decoration: none" style="text-decoration: none"
> >
<h3>Veins & Shunts</h3> <h3>Atlas</h3>
<p> <p class="lang-en">
API connectors (Jira, Slack, Google) and mock Actionable documentation. Templates that generate
connectors for testing. living docs.
</p>
<p class="lang-es">
Documentacion accionable. Templates que generan docs
vivos.
</p>
</a>
<a
href="station/"
class="system-card"
style="text-decoration: none"
>
<h3>Station</h3>
<p class="lang-en">
Tools and monitors. Everything to run, test, and
observe.
</p>
<p class="lang-es">
Herramientas y monitores. Todo para correr, testear,
y observar.
</p> </p>
</a> </a>
</div> </div>
@@ -45,53 +157,106 @@
<section class="findings-section"> <section class="findings-section">
<h2>Quick Start</h2> <h2>Quick Start</h2>
<div class="finding-card"> <pre>
<h3>Build & Run</h3> # Clone
<pre git clone https://git.mcrn.ar/soleprint
style=" cd soleprint
background: var(--bg-primary);
padding: 1rem;
border-radius: 4px;
overflow-x: auto;
margin-top: 0.5rem;
"
>
# Build standalone
python build.py
cd gen/standalone && .venv/bin/python run.py
# Build with room config # Setup (once)
python build.py --cfg amar python -m venv .venv && source .venv/bin/activate
cd gen/amar && .venv/bin/python run.py pip install -r requirements.txt
# Visit http://localhost:12000</pre # Option 1: Build standalone (soleprint only)
> python build.py --cfg standalone
</div> cd gen/standalone && ./ctrl/start.sh
# Visit http://localhost:12000
# Option 2: Build managed room (soleprint + your app)
python build.py --cfg myroom
cd gen/myroom && ./ctrl/start.sh
# Visit http://myroom.spr.local.ar
# Option 3: Use the installer (coming soon)</pre
>
<p style="margin-top: 1rem">
<span class="lang-en">Minimal config example:</span>
<span class="lang-es">Ejemplo de config minima:</span>
</p>
<pre>
// cfg/myroom/config.json
{
"room": "myroom",
"artery": {
"veins": ["google", "jira", "slack"],
"shunts": ["mercadopago"]
},
"atlas": {
"books": ["gherkin", "feature-flow"]
},
"station": {
"tools": ["tester", "modelgen"],
"monitors": ["databrowse"]
}
}</pre
>
</section> </section>
<section class="findings-section"> <section class="findings-section">
<h2>What Soleprint Solves</h2> <h2>
<span class="lang-en">Architecture</span>
<span class="lang-es">Arquitectura</span>
</h2>
<p class="lang-en">Deep dive into how soleprint works.</p>
<p class="lang-es">Profundizando en como funciona soleprint.</p>
<div class="findings-grid"> <div class="findings-grid">
<article class="finding-card"> <a
<h3>Freelance Standardization</h3> href="architecture/"
<p>Consistent framework across projects.</p> class="finding-card"
</article> style="text-decoration: none"
<article class="finding-card"> >
<h3>Missing Infrastructure</h3> <h3>
<p> <span class="lang-en">Architecture Diagrams →</span
Mock systems not ready yet - DBs, APIs, Kubernetes. ><span class="lang-es"
>Diagramas de Arquitectura →</span
>
</h3>
<p class="lang-en">
System overview, artery hierarchy, build flow, room
configuration.
</p> </p>
</article> <p class="lang-es">
<article class="finding-card"> Vista general, jerarquia de artery, flujo de build,
<h3>Reliable Testing</h3> configuracion de rooms.
<p>BDD -> Gherkin -> Tests.</p> </p>
</article> </a>
<a
href="architecture/sidebar-injection.html"
class="finding-card"
style="text-decoration: none"
>
<h3>
<span class="lang-en">Sidebar Injection →</span
><span class="lang-es">Inyeccion de Sidebar →</span>
</h3>
<p class="lang-en">
How the managed room sidebar works with nginx +
JavaScript.
</p>
<p class="lang-es">
Como funciona el sidebar del managed room con nginx
+ JavaScript.
</p>
</a>
</div> </div>
</section> </section>
</main> </main>
<footer> <footer>
<p>Soleprint - Development Workflow Platform</p> <p>
<a href="https://soleprint.mcrn.ar">soleprint.mcrn.ar</a> ·
<a href="https://sample.spr.mcrn.ar">Live Demo</a>
</p>
</footer> </footer>
</body> </body>
</html> </html>

54
docs/lang-toggle.js Normal file
View File

@@ -0,0 +1,54 @@
// Language toggle for soleprint docs
// Include this script and add: <div id="lang-toggle"></div> in header
(function () {
function setLang(lang) {
localStorage.setItem("spr-docs-lang", lang);
document.documentElement.lang = lang;
document.querySelectorAll(".lang-toggle button").forEach((btn) => {
btn.classList.toggle("active", btn.dataset.lang === lang);
});
}
document.addEventListener("DOMContentLoaded", () => {
const currentLang = localStorage.getItem("spr-docs-lang") || "en";
// Inject toggle HTML
const container = document.getElementById("lang-toggle");
if (container) {
container.className = "lang-toggle";
const btnEn = document.createElement("button");
btnEn.textContent = "EN";
btnEn.dataset.lang = "en";
btnEn.addEventListener("click", () => setLang("en"));
const btnEs = document.createElement("button");
btnEs.textContent = "ES";
btnEs.dataset.lang = "es";
btnEs.addEventListener("click", () => setLang("es"));
container.appendChild(btnEn);
container.appendChild(btnEs);
}
setLang(currentLang);
});
// Inject styles
const style = document.createElement("style");
style.textContent = `
.lang-toggle { position: absolute; top: 1.5rem; right: 2rem; display: flex; border: 1px solid #888; border-radius: 4px; overflow: hidden; }
.lang-toggle button { background: #1a1a1a; border: none; color: #888; padding: 0.4rem 0.8rem; font-family: inherit; font-size: 0.75rem; cursor: pointer; }
.lang-toggle button:first-child { border-right: 1px solid #888; }
.lang-toggle button:hover { background: #0a0a0a; color: #fff; }
.lang-toggle button.active { background: var(--accent, #b91c1c); color: #fff; }
header { position: relative; }
.lang-en, .lang-es { display: none; }
html[lang="en"] .lang-en { display: block; }
html[lang="es"] .lang-es { display: block; }
html[lang="en"] span.lang-en { display: inline; }
html[lang="es"] span.lang-es { display: inline; }
`;
document.head.appendChild(style);
})();

333
docs/station/index.html Normal file
View File

@@ -0,0 +1,333 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Station - Soleprint</title>
<link rel="stylesheet" href="../architecture/styles.css" />
<style>
.composition {
background: #1a1a1a;
border: 2px solid #7c3aed;
padding: 1rem;
border-radius: 12px;
margin-bottom: 1rem;
}
.composition h3 {
margin: 0 0 0.75rem 0;
font-size: 1.1rem;
color: #c4b5fd;
}
.composition > p {
margin: 0 0 1rem 0;
font-size: 0.9rem;
color: #a3a3a3;
}
.components {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 0.75rem;
}
.component {
background: #0a0a0a;
border: 1px solid #3f3f3f;
padding: 0.75rem;
border-radius: 8px;
}
.component h4 {
margin: 0 0 0.25rem 0;
font-size: 0.95rem;
color: #c4b5fd;
}
.component p {
margin: 0;
font-size: 0.85rem;
color: #a3a3a3;
}
.model-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1rem;
}
</style>
<script src="../lang-toggle.js"></script>
</head>
<body>
<header>
<div id="lang-toggle"></div>
<h1>Station</h1>
<p class="subtitle">Todo lo construido</p>
</header>
<main>
<section class="findings-section">
<h2>
<span class="lang-en">Model</span
><span class="lang-es">Modelo</span>
</h2>
<div class="model-grid">
<div class="composition">
<h3>Desk</h3>
<p class="lang-en">
Control center - collection of monitors
</p>
<p class="lang-es">
Centro de control - coleccion de monitores
</p>
<div class="components">
<div class="component">
<h4>Monitor</h4>
<p>Web UI</p>
</div>
<div class="component">
<h4>Monitor</h4>
<p>Web UI</p>
</div>
<div class="component">
<h4>...</h4>
<p></p>
</div>
</div>
</div>
<div class="composition">
<h3>Monitor</h3>
<p class="lang-en">
Web interface - always running, always watching
</p>
<p class="lang-es">
Interfaz web - siempre corriendo, siempre observando
</p>
<div class="components">
<div class="component">
<h4>Web UI</h4>
<p>Dashboard</p>
</div>
<div class="component">
<h4>Room</h4>
<p class="lang-en">Config/env</p>
<p class="lang-es">Config/entorno</p>
</div>
<div class="component">
<h4>Depot</h4>
<p class="lang-en">Data source</p>
<p class="lang-es">Fuente de datos</p>
</div>
</div>
</div>
<div class="composition">
<h3>Tool</h3>
<p class="lang-en">
CLI utility - run once, get results
</p>
<p class="lang-es">
Utilidad CLI - ejecutar una vez, obtener resultados
</p>
<div class="components">
<div class="component">
<h4>CLI</h4>
<p class="lang-en">Command interface</p>
<p class="lang-es">Interfaz de comandos</p>
</div>
<div class="component">
<h4>Room</h4>
<p class="lang-en">Config/env</p>
<p class="lang-es">Config/entorno</p>
</div>
<div class="component">
<h4>Depot</h4>
<p class="lang-en">Output storage</p>
<p class="lang-es">Almacenamiento de salida</p>
</div>
</div>
</div>
</div>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Architecture</span
><span class="lang-es">Arquitectura</span>
</h2>
<img
src="../architecture/01-system-overview.svg"
alt="System Overview"
style="
max-width: 100%;
background: white;
border-radius: 8px;
padding: 1rem;
"
/>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Components</span
><span class="lang-es">Componentes</span>
</h2>
<div class="findings-grid">
<article class="finding-card">
<h3>Desk</h3>
<p class="lang-en">
Collection of monitors. Your control center with all
the views you need.
</p>
<p class="lang-es">
Coleccion de monitores. Tu centro de control con
todas las vistas que necesitas.
</p>
</article>
<article class="finding-card">
<h3>Monitor</h3>
<p class="lang-en">
Web interfaces for observation. Data browsers,
dashboards, log viewers. Always running.
</p>
<p class="lang-es">
Interfaces web para observacion. Navegadores de
datos, dashboards, visores de logs. Siempre
corriendo.
</p>
</article>
<article class="finding-card">
<h3>Tool</h3>
<p class="lang-en">
CLI utilities and scripts. Code generators, test
runners, infra provisioners. Run once, get results.
</p>
<p class="lang-es">
Utilidades CLI y scripts. Generadores de codigo,
test runners, provisioners de infra. Ejecutar una
vez, obtener resultados.
</p>
</article>
</div>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Shared Components</span
><span class="lang-es">Componentes Compartidos</span>
</h2>
<div class="findings-grid">
<article class="finding-card">
<h3>Room</h3>
<p class="lang-en">
Runtime environment configuration. Tools and
monitors are configured per-room for isolation.
</p>
<p class="lang-es">
Configuracion del entorno. Tools y monitors se
configuran por room para aislamiento.
</p>
</article>
<article class="finding-card">
<h3>Depot</h3>
<p class="lang-en">
Data storage. For tools: output files, results. For
monitors: data to display.
</p>
<p class="lang-es">
Almacenamiento de datos. Para tools: archivos de
salida, resultados. Para monitors: datos a mostrar.
</p>
</article>
</div>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Available Tools</span
><span class="lang-es">Tools Disponibles</span>
</h2>
<div class="findings-grid">
<article class="finding-card">
<h3>Tester</h3>
<p class="lang-en">
API and Playwright test runner. Discover tests, run
them, collect artifacts.
</p>
<p class="lang-es">
Test runner de API y Playwright. Descubrir tests,
ejecutarlos, recolectar artefactos.
</p>
</article>
<article class="finding-card">
<h3>ModelGen</h3>
<p class="lang-en">
Generate model diagrams from code. Introspect
soleprint structure, output SVG.
</p>
<p class="lang-es">
Generar diagramas de modelo desde codigo.
Introspeccionar estructura de soleprint, generar
SVG.
</p>
</article>
<article class="finding-card">
<h3>Infra</h3>
<p class="lang-en">
Infrastructure provisioners. AWS, GCP, DigitalOcean
deployment helpers.
</p>
<p class="lang-es">
Provisioners de infraestructura. Helpers de deploy
para AWS, GCP, DigitalOcean.
</p>
</article>
<article class="finding-card">
<h3>DataGen</h3>
<p class="lang-en">
Test data generation. Create realistic fake data for
development.
</p>
<p class="lang-es">
Generacion de datos de test. Crear datos falsos
realistas para desarrollo.
</p>
</article>
<article class="finding-card">
<h3>DataBrowse</h3>
<p class="lang-en">
Navigable data model graphs generated from existing
models.
</p>
<p class="lang-es">
Grafos de modelo de datos navegables generados desde
modelos existentes.
</p>
</article>
</div>
</section>
<section class="findings-section">
<h2>
<span class="lang-en">Available Monitors</span
><span class="lang-es">Monitors Disponibles</span>
</h2>
<div class="findings-grid">
<article class="finding-card">
<h3>DataBrowse</h3>
<p class="lang-en">
Navigable data model graphs generated from existing
models.
</p>
<p class="lang-es">
Grafos de modelo de datos navegables generados desde
modelos existentes.
</p>
</article>
</div>
</section>
</main>
<footer>
<p>
<a href="../"
><span class="lang-en">← Back to index</span
><span class="lang-es">← Volver al indice</span></a
>
</p>
</footer>
</body>
</html>