Landing Pages — Meta Portal (meta.koder.dev)
landing-pages specs/landing-pages/meta.kmd
Estrutura, IA, pipeline de render, deploy e governança do portal público de documentação da Koder Stack em `meta.koder.dev`. Renderiza o conteúdo de `meta/docs/{stack,ia,cryptography,blockchain}/` como HTML estático navegável, com nav hierárquico por tipo de documento (RFC, spec, policy, registry, module, runbook, compendium), search client-side, theme light/dark, i18n EN/PT. Distinto de landings de produto, área, sector, institucional, catálogo, packages e specs — é um **portal-indexador de documentos**, não uma landing-vendedor.
When this spec applies
Primary triggers
- Criar ou editar a landing/portal meta.koder.dev
All triggers
- Criar ou editar a landing/portal meta.koder.dev
- Decidir o que de meta/docs/ é público vs interno
- Definir IA, nav, search ou render pipeline do portal de docs
- Resolver dead-link a meta.koder.dev/* em landings existentes
Specification body
Landing Pages — Meta Portal (meta.koder.dev)
1. Visão Geral
meta.koder.dev é o portal público de documentação da Koder Stack.
Renderiza o conteúdo de meta/docs/ do monorepo como site estático
navegável.
Não é uma landing de produto, marca, área ou spec individual — é um indexador de documentos. Tem nav hierárquico por tipo (RFC, spec, policy, registry, module, runbook, compendium), uma página por arquivo fonte, search client-side e cross-links resolvidos.
Distinto de:
specs/landing-pages/products.kmd— landings de um produtospecs/landing-pages/specs.kmd— landing de uma spec/formato (KVG, KPKG)specs/landing-pages/areas.kmd— landing de Área L2 (foundation, ai, …)specs/landing-pages/institutional.kmd— landings sobre a Koder (www, company)specs/landing-pages/catalog.kmd— Hub catalog (hub.koder.dev)specs/landing-pages/packages.kmd— página individual de pacote no Hub
Histórico canônico (2026-05-24):
- ~10 landings de Área (
meta/sites/areas/*/),meta/sites/brand/emeta/sites/_ecosystem_gen.pyreferenciaramdocs.koder.devdesde 2026-Q2 como "Public documentation" (sempre dead link). - Sessão de 2026-05-24 turn 3: owner pediu site pro conteúdo de
meta/. Pragmaticamente decidido construirdocs.koder.devreusando o nome já referenciado. Implementação concluída em 5 turns (spec, renderer, vhost, audit, deploy paralelo) — portal shipped com 652 docs. - Mesma sessão turn 12: owner observou que o nome
docs.está semanticamente errado pro conteúdo (RFCs/specs/policies/registries = "meta", não "docs do usuário"). Decisão revertida: canonical émeta.koder.dev, mirror direto do L1 domainmeta/do monorepo. - Cutover atomic agendado (Phase B) quando
infra/net/jetliberar o lock atual (jet#160 Phase 1) — verjet#NNN follow-up ticketno umbrella META-DOCS-131.docs.koder.dev→ 301 →meta.koder.dev, landings editorialmente atualizadas, per-product docs ficam em<product>.koder.dev/docs/quando os produtos shipam.
2. Escopo de Conteúdo
2.1 Em escopo (público, vai pro portal)
| Fonte | Tipo | Sub-path no portal |
|---|---|---|
meta/docs/stack/rfcs/ | RFCs | /rfcs/ |
meta/docs/stack/specs/ | Specs normativas | /specs/ |
meta/docs/stack/policies/ | Policies comportamentais | /policies/ |
meta/docs/stack/registries/ | Registries (fontes de verdade) | /registries/ |
meta/docs/stack/modules/ | Module catalog | /modules/ |
meta/docs/stack/runbooks/ | Runbooks operacionais públicos | /runbooks/ |
meta/docs/stack/releases/ | Release notes consolidadas | /releases/ |
meta/docs/ia/compendium/ | Compendium de IA | /compendiums/ia/ |
meta/docs/cryptography/compendium/ | Compendium de criptografia | /compendiums/cryptography/ |
meta/docs/blockchain/compendium/ | Compendium de blockchain | /compendiums/blockchain/ |
2.2 Fora de escopo (NUNCA publicar)
meta/context/— runbooks internos, hooks de IA, credenciais, notices, recaps. Privado por contrato.meta/brand/— assets de marca (vivem embrand.koder.dev)meta/sites/— landings (cada uma tem seu próprio domínio)- Qualquer arquivo com frontmatter
visibility: internalouaudit: private(ver §6.3) meta/docs/stack/backlog/— tickets de trabalho interno
2.3 Avaliação per-diretório (decidir caso a caso)
meta/docs/platform/— possivelmente público; auditar conteúdometa/docs/trust/— possivelmente público; auditar conteúdometa/docs/flow-releases/— público se substituirflow.koder.dev/releases; senão, manter privadometa/docs/docs/— meta-docs sobre o sistema de docs; provavelmente públicometa/docs/stack/diagrams/,presentation/,build/— públicos como assets/anexos, não páginas próprias
3. URL Canônica
Padrão: https://meta.koder.dev/<category>/<path>/
<category>∈ {rfcs,specs,policies,registries,modules,runbooks,releases,compendiums}<path>espelha 1:1 a estrutura de subdir na fonte, com.kmd/.mdremovidos e nomes preservados- Trailing slash sempre presente (URLs com slash final →
index.htmldo diretório virtual) - Casos especiais:
- Homepage:
https://meta.koder.dev/(não/index.html) - Search:
https://meta.koder.dev/search/?q=<query>(client-side) - Sitemap:
https://meta.koder.dev/sitemap.xml - 404:
https://meta.koder.dev/404.html
- Homepage:
Exemplos:
| Fonte | URL |
|---|---|
meta/docs/stack/rfcs/stack-RFC-001-kdb-as-unified-data-plane.kmd | /rfcs/stack-RFC-001-kdb-as-unified-data-plane/ |
meta/docs/stack/specs/auth/oauth-flow.kmd | /specs/auth/oauth-flow/ |
meta/docs/stack/policies/hyperscale-first.kmd | /policies/hyperscale-first/ |
meta/docs/stack/registries/component-names.md | /registries/component-names/ |
meta/docs/ia/compendium/01-models.md | /compendiums/ia/01-models/ |
Regra de imutabilidade: URLs uma vez publicadas não mudam. Renomes
em meta/docs/ precisam de redirect 301 em
/redirects.toml consumido pelo Jet (#131.5 audit).
4. Estrutura do Arquivo de Site
meta/sites/docs/
├── _layouts/ ← Templates HTML (não servidos)
│ ├── home.html
│ ├── category.html ← Listing de uma categoria
│ ├── doc.html ← Página de um documento
│ ├── 404.html
│ └── search.html
├── _assets/
│ ├── ecosystem.css ← Symlink pra meta/sites/ecosystem.css
│ ├── docs.css ← Estilos específicos (sidebar, TOC, code blocks)
│ ├── docs.js ← Search + theme + i18n
│ ├── lunr.min.js ← Search engine (vendored ~100KB)
│ ├── search-index.json ← Gerado pelo renderer
│ ├── icon.svg
│ └── og-image-default.png
├── index.html ← Gerado: homepage
├── <category>/ ← Gerado per category
│ ├── index.html
│ └── <doc-slug>/
│ └── index.html
├── search/index.html
├── sitemap.xml
└── 404.html
Todos os HTMLs servidos são gerados pelo renderer (#131.2);
nenhum HTML é escrito à mão exceto os _layouts/. O diretório
_layouts/ e _assets/ (exceto o que for gerado) são commitados
no monorepo; o resto (<category>/, search/, sitemap.xml,
404.html, index.html, search-index.json) é build artifact —
gitignored, regenerado em CI a cada push (per policies/hyperscale-first.kmd).
5. Information Architecture
5.1 Homepage (/)
Estrutura (top→bottom):
- Nav (sticky, idêntica a outras landings — ver §8)
- Hero centralizado:
- Eyebrow: "The Koder Stack"
- H1 grande: "Documentation" (com palavra em accent gradient)
- Lead 2 frases: "RFCs, specifications, policies and registries that define how every Koder component is built and operated. Browse, search, link."
- Search bar full-width (foco automático em desktop)
- 2 CTAs: "Browse RFCs" + "Browse Specs"
- Category grid — 8 cards (uma por categoria de §2.1):
- Ícone + título + contagem ("47 RFCs", "180 specs", "32 policies", …)
- Card inteiro clicável →
/<category>/ - Counts injetados pelo renderer no build
- Recently updated — lista das 10 últimas modificações
(extraídas de
git logno build) - Featured — opcional, curado: links pra 3-5 docs de entrada (RFC-001, headless-first.kmd, multi-tenancy/contract.kmd, …)
- Footer dark (idêntico a
institutional.kmd§2.8)
5.2 Category listing (/<category>/)
Estrutura:
- Nav
- Breadcrumb:
Home / <Category> - Header: nome da categoria + descrição de 1 linha + total
- Filtros:
- Por sub-area (specs:
auth/,i18n/,themes/, …) - Por status (RFCs: draft / accepted / superseded; specs: pre-normative / normative / draft)
- Por data (modified last 7d / 30d / 90d / all)
- Por sub-area (specs:
- Lista de docs — tabela ou cards:
- Nome + sub-path + 1-line summary (do frontmatter
summary:) - Status badge
- Last-modified date
- Audit status se aplicável
- Nome + sub-path + 1-line summary (do frontmatter
- Footer
5.3 Document page (/<category>/<slug>/)
Estrutura (layout 3 colunas em desktop, stacked em mobile):
- Nav
- Left sidebar (sticky, scroll-independente):
- Navegação da categoria atual (árvore expandida no doc atual)
- Main content:
- Breadcrumb
- Frontmatter rendered como badge bar (status, version, mandatory, audit date)
- H1:
name:outitle:do frontmatter - Render do body markdown/kmd (ver §6)
- Footer da página: "Edit this page" (link pro Flow se público) +
prev/next (mesma categoria) + "Last updated
· commit "
- Right sidebar (TOC):
- Lista de headings H2/H3 do doc
- Scroll-spy: destaca seção atual
- Footer global
5.4 Search (/search/?q=…)
- Client-side, lunr.js indexa título + frontmatter + headings (não full text — keeps index <500KB)
- Resultados agrupados por categoria
- Highlight do termo nos snippets
6. Render Pipeline
Implementação: dev/koder-tools/cmd/koder-docs-render/ (Go) — ticket
META-DOCS-131.2. Esta seção é o contrato do renderer.
6.1 Input
- Walk de
meta/docs/{stack,ia,cryptography,blockchain}/(e diretórios promovidos por §2.3) - Aceita
.kmde.md. Frontmatter YAML obrigatório (sem frontmatter → log warning + skip ou render como "untyped doc") - Respeita
.docsignore(lista de globs) em cada diretório raiz
6.2 Parser
- Markdown: reutilizar parser canônico da Stack (mesmo de
kmd render); fallbackgoldmarkse kmd parser indisponível - Frontmatter:
yaml.v3 - Cross-links: resolver
[texto](relative-path.kmd)→ URL canônica do portal (ver §3);[[wiki-link]]→ busca porname:no frontmatter de todos os docs indexados, falha emite warning
6.3 Visibility filter
Skip arquivo se:
- Frontmatter contém
visibility: internal - Frontmatter contém
audit: private - Path bate com qualquer entrada de
meta/sites/docs/_excluded.toml(escape hatch curado)
6.4 Output
meta/sites/docs/<category>/<slug>/index.htmlper docmeta/sites/docs/<category>/index.htmlper categoriameta/sites/docs/index.htmlhomepagemeta/sites/docs/search/index.html+_assets/search-index.jsonmeta/sites/docs/sitemap.xml(Google + IndexNow)meta/sites/docs/404.htmlmeta/sites/docs/redirects.toml(Jet-consumível, se houver renames detectados)
6.5 Metadata extraída do frontmatter
| Frontmatter key | Onde aparece no HTML |
|---|---|
name / title | <title>, <h1>, og:title |
summary | <meta description>, og:description, listing card |
status | badge bar + filter em listing |
type | category routing |
mandatory: true | "Mandatory" badge no header |
triggers | section "When this applies" (collapsible) |
references | rendered como linked list no rodapé do doc |
audit | badge "Audit: |
facets | tags clicáveis |
6.6 Hyperscale gate
Per policies/hyperscale-first.kmd: renderer DEVE escalar a 10×
o volume atual sem mudança arquitetural (~5k docs). Decisões:
- HTML estático puro, sem SSR/CSR runtime
- Build incremental: hash do arquivo fonte + frontmatter; só re-renderiza o que mudou
- Search index gerado em pass único, paralelizado por worker
- Sem JS bundlers —
docs.jsé vanilla JS direto
7. Head — Meta Tags
Template aplicado a TODA página:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{page.title}} — Koder Docs</title>
<meta name="description" content="{{page.summary}}">
<meta name="theme-color" content="#0b1120">
<link rel="canonical" href="https://meta.koder.dev{{page.url}}">
<!-- Open Graph -->
<meta property="og:title" content="{{page.title}} — Koder Docs">
<meta property="og:description" content="{{page.summary}}">
<meta property="og:type" content="article">
<meta property="og:url" content="https://meta.koder.dev{{page.url}}">
<meta property="og:image" content="https://meta.koder.dev{{page.og_image | default('/_assets/og-image-default.png')}}">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{page.title}} — Koder Docs">
<meta name="twitter:description" content="{{page.summary}}">
<meta name="twitter:image" content="https://meta.koder.dev{{page.og_image | default('/_assets/og-image-default.png')}}">
<link rel="icon" type="image/svg+xml" href="/_assets/icon.svg">
<script>
(function(){
const s = localStorage.getItem('theme');
const dark = s ? s === 'dark' : matchMedia('(prefers-color-scheme:dark)').matches;
if (dark) document.documentElement.setAttribute('data-theme','dark');
})();
</script>
<link rel="stylesheet" href="/_assets/ecosystem.css">
<link rel="stylesheet" href="/_assets/docs.css">
</head>
<title>max 60 chars; trunca{{page.title}}se preciso (renderer warn)og:type = "article"em doc pages,"website"em homepage/category listingsog:imageper page é opcional; default =og-image-default.png(Koder Docs branded)
8. Nav
Idêntica ao padrão de outras landings (ecosystem.css):
<nav>
<div class="nav-inner">
<a class="nav-brand" href="/"><img src="/_assets/icon.svg" alt="">Koder Docs</a>
<button aria-label="Menu" class="nav-toggle" onclick="...">☰</button>
<div class="nav-links">
<a href="/rfcs/">RFCs</a>
<a href="/specs/">Specs</a>
<a href="/policies/">Policies</a>
<a href="/registries/">Registries</a>
<a href="/compendiums/">Compendiums</a>
<button id="lang-btn" onclick="toggleLang()">EN</button>
<button class="theme-toggle" onclick="toggleTheme()">…</button>
</div>
</div>
</nav>
Versão sticky com backdrop-filter: blur(16px). Ordem dos links é
canônica (RFCs antes de Specs antes de Policies, por densidade de
referência).
9. CSS — Tokens
Reusar meta/sites/ecosystem.css (mesma base de areas/brand/company).
Estilos específicos do portal em meta/sites/docs/_assets/docs.css:
- Sidebar tree (left + right TOC)
- Code blocks com syntax highlighting (Prism vendored ou highlight.js)
- Tables responsivas (scroll-x em mobile)
- Badge bar (status, mandatory, audit)
- Search results
Theme: light/dark per specs/themes/light-dark.kmd. Toggle JS
idêntico ao das outras landings.
Tokens visuais: per specs/themes/verge.kmd — usar Verge default.
Fontes: per specs/fonts/typography.kmd:
- Sans: Inter (self-hosted woff2 via
/_assets/fonts/inter.woff2) - Mono: JetBrains Mono (self-hosted)
- Proibido Google Fonts / jsDelivr / unpkg
10. JavaScript — Comportamentos
_assets/docs.js (vanilla, ~10KB minified):
- Theme toggle (idêntico a outras landings)
- Language toggle EN ↔ PT-BR (i18n; conteúdo é EN por
policies/language.kmd, mas chrome traduzível) - Mobile nav hamburger
- TOC scroll-spy
- Sidebar tree expand/collapse + persistência em
localStorage - Search input (homepage + página search): query lunr index,
renderiza resultados ou redireciona pra
/search/?q=… - Copy-to-clipboard em code blocks (button hover)
- Anchor links em H2/H3 (hover icon → copy URL com fragment)
lunr.min.js carregado só na rota /search/ (lazy) — não
penaliza páginas de leitura.
11. Dead-Link Audit
A spec mandata que ao primeiro deploy em produção, o renderer
gere um relatório audit/dead-links-<date>.json listando todas as
refs a meta.koder.dev/* no monorepo (especialmente em
meta/sites/areas/*/index.html, meta/sites/brand/index.html,
meta/sites/_ecosystem_gen.py) e marque cada uma como:
- ✅
resolves— path canônico existe - 🔁
redirects-to: <new-path>— entrada emredirects.tomlnecessária - ❌
broken— bloqueia release até #131.5 decidir destino
CI gate: build do portal falha se houver broken sem resolução.
12. i18n
- Conteúdo (doc body) NÃO é traduzido — é EN por
policies/language.kmd - Chrome (nav, footer, breadcrumbs, status badges, "Recently updated") É traduzido EN ↔ PT-BR
- Toggle
EN/PTno nav (mesmo padrão das outras landings) - Default por geo / browser language; persiste em
localStorage - T1-T6 da spec
specs/i18n/contract.kmdaplicam
13. Acessibilidade
- WCAG 2.1 AA
- Skip-to-content link no topo
- Sidebar tree navegável por teclado (arrow keys)
- Theme toggle com
aria-label+aria-pressed - TOC com
aria-current="location"no item ativo - Code blocks com
role="region"earia-label="Code sample" - Tabela de conformance per page em audit periódico (#131 followup)
14. SEO
sitemap.xmlgerado no build, submetido ao Google Search Console- Per-page meta tags (§7)
robots.txtem/_assets/robots.txt—Allow: /em prd,Disallow: /em stg/dev (perpolicies/environments.kmd)- IndexNow ping no deploy de produção (lista de URLs alteradas)
- Schema.org
TechArticleJSON-LD em doc pages
15. Deploy
Per policies/web-server.kmd (Jet only) + policies/environments.kmd:
| Ambiente | Host | Branch source | noindex |
|---|---|---|---|
dev.meta.koder.dev | s.forge | dev | true |
stg.meta.koder.dev | s.forge | staging | true |
meta.koder.dev (prd) | s.forge | main | false |
DNS A record provisionado via ClouDNS (meta/context/infrastructure/dns.md).
TLS via Jet autocert (LE/ACME).
Pipeline de deploy:
- CI roda
koder-docs-render --env <env>no monorepo - Output em
meta/sites/docs/(sub-paths gitignored) rsyncpro/var/www/meta.koder.dev/no s.forge- Jet reload (zero-downtime)
- Smoke:
curl -I https://meta.koder.dev/→ 200 + TTFB <500ms - Lighthouse: a11y ≥ 95, perf ≥ 90, SEO = 100
16. Performance Targets
| Métrica | Target |
|---|---|
| TTFB | <200ms (CDN/edge se necessário, futuro) |
| LCP | <1.5s |
| CLS | <0.05 |
| Page weight (homepage) | <100KB (sem search index) |
| Page weight (doc page) | <150KB (sem code samples grandes) |
| Search index | <500KB |
| Build time (full) | <60s pra ~500 docs |
| Build time (incremental) | <5s |
17. Governança
- Owner: Koder Stack (Rodrigo)
- Spec maturity gate: v1.0 normative quando #131.2/.3/.4/.5/.6/.7 do umbrella META-DOCS-131 estiverem done + lighthouse scores atingidos + dead-link audit limpa em 2 builds consecutivos
- Versioning: a spec do portal segue semver per
specs/landing-pages/specs.kmd §6 - Audit:
koder-spec-audit landing-pages --slug docs(a ser implementado pelo audit harness emdev/koder-tools/)
18. Decisões Em Aberto
- Search backend long-term: lunr.js (v0) → kdb-search quando
rfcs/stack-RFC-001-kdb-as-unified-data-plane.kmdentregar layer de busca. Decisão revisitada no kickoff de #131.2. - Versionamento de docs: always-latest (HEAD) vs por tag (v1.0, v1.1). Default v0: always-latest; versões anteriores acessíveis via Flow se requestado. Revisitar quando portal tiver ≥1 ano de tráfego.
- OG image generation per page: usar
kicon generate --targets ogper doc, ou template estático compartilhado por categoria? Default v0: estático por categoria (8 imagens curadas). - Comments / feedback: deixar fora do v0. Avaliar Giscus (GitHub-backed) vs solução self-hosted em v2.
- Versioned dark mode: usar Verge default ou expor preset switcher como no KDS? Default v0: Verge default, sem switcher.
19. Referência Cruzada
specs/landing-pages/institutional.kmd— padrão de footer dark + navspecs/landing-pages/specs.kmd— padrão de doc-as-pagespecs/kmd/— parser canônicopolicies/hyperscale-first.kmd— gate de build incrementalpolicies/reuse-first.kmd— reuso deecosystem.cssmeta/sites/_ecosystem_gen.py— gerador atual de landings de Área (referencia o dead linkmeta.koder.dev/ecosystem)- META-DOCS-131 — umbrella ticket do programa
- JET-161 — vhost ticket
20. Estado Atual (2026-05-24)
| Sub-stream | Ticket | Status |
|---|---|---|
| Landing spec | #131.1 | ✅ esta spec (v0.1.0 pre-normative) |
| Renderer pipeline | #131.2 | pending |
| Templates + nav | #131.3 | pending |
| Vhost + TLS | JET-161 | pending (blocked on #131.1+#131.2) |
| Dead-link audit + fix | #131.5 | pending |
| OG image + brand assets | #131.6 | pending |
| i18n chrome | #131.7 | pending |
References
specs/landing-pages/institutional.kmdspecs/landing-pages/specs.kmdspecs/landing-pages/areas.kmdspecs/kmd/specs/themes/light-dark.kmdspecs/themes/verge.kmdspecs/fonts/typography.kmdpolicies/language.kmdpolicies/web-server.kmdpolicies/security.kmdpolicies/environments.kmdpolicies/hyperscale-first.kmdpolicies/reuse-first.kmd