Pular para o conteúdo

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.

Quando esta spec se aplica

Triggers primários

Todos os triggers

Corpo da especificação

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 produto
  • specs/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):

  1. ~10 landings de Área (meta/sites/areas/*/), meta/sites/brand/ e meta/sites/_ecosystem_gen.py referenciaram docs.koder.dev desde 2026-Q2 como "Public documentation" (sempre dead link).
  2. Sessão de 2026-05-24 turn 3: owner pediu site pro conteúdo de meta/. Pragmaticamente decidido construir docs.koder.dev reusando o nome já referenciado. Implementação concluída em 5 turns (spec, renderer, vhost, audit, deploy paralelo) — portal shipped com 652 docs.
  3. 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 domain meta/ do monorepo.
  4. Cutover atomic agendado (Phase B) quando infra/net/jet liberar o lock atual (jet#160 Phase 1) — ver jet#NNN follow-up ticket no 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)

FonteTipoSub-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 em brand.koder.dev)
  • meta/sites/ — landings (cada uma tem seu próprio domínio)
  • Qualquer arquivo com frontmatter visibility: internal ou audit: 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údo
  • meta/docs/trust/ — possivelmente público; auditar conteúdo
  • meta/docs/flow-releases/ — público se substituir flow.koder.dev/releases; senão, manter privado
  • meta/docs/docs/ — meta-docs sobre o sistema de docs; provavelmente público
  • meta/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/.md removidos e nomes preservados
  • Trailing slash sempre presente (URLs com slash final → index.html do 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

Exemplos:

FonteURL
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):

  1. Nav (sticky, idêntica a outras landings — ver §8)
  2. 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"
  3. 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
  4. Recently updated — lista das 10 últimas modificações (extraídas de git log no build)
  5. Featured — opcional, curado: links pra 3-5 docs de entrada (RFC-001, headless-first.kmd, multi-tenancy/contract.kmd, …)
  6. Footer dark (idêntico a institutional.kmd §2.8)

5.2 Category listing (/<category>/)

Estrutura:

  1. Nav
  2. Breadcrumb: Home / <Category>
  3. Header: nome da categoria + descrição de 1 linha + total
  4. 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)
  5. 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
  6. Footer

5.3 Document page (/<category>/<slug>/)

Estrutura (layout 3 colunas em desktop, stacked em mobile):

  1. Nav
  2. Left sidebar (sticky, scroll-independente):
    • Navegação da categoria atual (árvore expandida no doc atual)
  3. Main content:
    • Breadcrumb
    • Frontmatter rendered como badge bar (status, version, mandatory, audit date)
    • H1: name: ou title: 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 "
  4. Right sidebar (TOC):
    • Lista de headings H2/H3 do doc
    • Scroll-spy: destaca seção atual
  5. 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 .kmd e .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); fallback goldmark se kmd parser indisponível
  • Frontmatter: yaml.v3
  • Cross-links: resolver [texto](relative-path.kmd) → URL canônica do portal (ver §3); [[wiki-link]] → busca por name: 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.html per doc
  • meta/sites/docs/<category>/index.html per categoria
  • meta/sites/docs/index.html homepage
  • meta/sites/docs/search/index.html + _assets/search-index.json
  • meta/sites/docs/sitemap.xml (Google + IndexNow)
  • meta/sites/docs/404.html
  • meta/sites/docs/redirects.toml (Jet-consumível, se houver renames detectados)

6.5 Metadata extraída do frontmatter

Frontmatter keyOnde aparece no HTML
name / title<title>, <h1>, og:title
summary<meta description>, og:description, listing card
statusbadge bar + filter em listing
typecategory routing
mandatory: true"Mandatory" badge no header
triggerssection "When this applies" (collapsible)
referencesrendered como linked list no rodapé do doc
auditbadge "Audit: "
facetstags 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 listings
  • og:image per 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.

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 em redirects.toml necessá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/PT no nav (mesmo padrão das outras landings)
  • Default por geo / browser language; persiste em localStorage
  • T1-T6 da spec specs/i18n/contract.kmd aplicam

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" e aria-label="Code sample"
  • Tabela de conformance per page em audit periódico (#131 followup)

14. SEO

  • sitemap.xml gerado no build, submetido ao Google Search Console
  • Per-page meta tags (§7)
  • robots.txt em /_assets/robots.txtAllow: / em prd, Disallow: / em stg/dev (per policies/environments.kmd)
  • IndexNow ping no deploy de produção (lista de URLs alteradas)
  • Schema.org TechArticle JSON-LD em doc pages

15. Deploy

Per policies/web-server.kmd (Jet only) + policies/environments.kmd:

AmbienteHostBranch sourcenoindex
dev.meta.koder.devs.forgedevtrue
stg.meta.koder.devs.forgestagingtrue
meta.koder.dev (prd)s.forgemainfalse

DNS A record provisionado via ClouDNS (meta/context/infrastructure/dns.md). TLS via Jet autocert (LE/ACME).

Pipeline de deploy:

  1. CI roda koder-docs-render --env <env> no monorepo
  2. Output em meta/sites/docs/ (sub-paths gitignored)
  3. rsync pro /var/www/meta.koder.dev/ no s.forge
  4. Jet reload (zero-downtime)
  5. Smoke: curl -I https://meta.koder.dev/ → 200 + TTFB <500ms
  6. Lighthouse: a11y ≥ 95, perf ≥ 90, SEO = 100

16. Performance Targets

MétricaTarget
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 em dev/koder-tools/)

18. Decisões Em Aberto

  1. Search backend long-term: lunr.js (v0) → kdb-search quando rfcs/stack-RFC-001-kdb-as-unified-data-plane.kmd entregar layer de busca. Decisão revisitada no kickoff de #131.2.
  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.
  3. OG image generation per page: usar kicon generate --targets og per doc, ou template estático compartilhado por categoria? Default v0: estático por categoria (8 imagens curadas).
  4. Comments / feedback: deixar fora do v0. Avaliar Giscus (GitHub-backed) vs solução self-hosted em v2.
  5. 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 + nav
  • specs/landing-pages/specs.kmd — padrão de doc-as-page
  • specs/kmd/ — parser canônico
  • policies/hyperscale-first.kmd — gate de build incremental
  • policies/reuse-first.kmd — reuso de ecosystem.css
  • meta/sites/_ecosystem_gen.py — gerador atual de landings de Área (referencia o dead link meta.koder.dev/ecosystem)
  • META-DOCS-131 — umbrella ticket do programa
  • JET-161 — vhost ticket

20. Estado Atual (2026-05-24)

Sub-streamTicketStatus
Landing spec#131.1✅ esta spec (v0.1.0 pre-normative)
Renderer pipeline#131.2pending
Templates + nav#131.3pending
Vhost + TLSJET-161pending (blocked on #131.1+#131.2)
Dead-link audit + fix#131.5pending
OG image + brand assets#131.6pending
i18n chrome#131.7pending

Referências