Landing Pages — Meta Portal (meta.koder.dev)

v0.1.0 — pre-normative (draft 2026-05-24) mandatory

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.

Landing Pages — Meta Portal (meta.koder.dev)

1. Visão Geral

meta.koder.dev é o *ortal 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 *ndexador de documentos* Tem nav hierárquico por tipo (RFC, spec, policy, registry, module, runbook, compendium), uma página por arquivo fonte, search clientside e crosslinks resolvidos.

*istinto de:*

  • specs/landing-pages/products.kmd — landings de *m*produto
  • specs/landing-pages/specs.kmd — landing de *ma*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 (20260524):

  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 20260524 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 (RFCsspecspolicies/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 METADOCS131. 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. *rivado 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

*xemplos:*

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/

*egra 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 *erados*pelo renderer (#131.2); nenhum HTML é escrito à mão exceto os _layouts/. O diretório _layouts/ e _assets/ (exceto o que for gerado) *ão commitados*no monorepo; o resto (<category>/, search/, sitemap.xml, 404.html, index.html, search-index.json) é *uild artifact*— gitignored, regenerado em CI a cada push (per policies/hyperscale-first.kmd).

5. Information Architecture

5.1 Homepage (/)

Estrutura (top→bottom):

  1. *av*(sticky, idêntica a outras landings — ver §8)
  2. *ero*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. *ategory 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. *ecently updated*— lista das 10 últimas modificações

    (extraídas de git log no build)

  5. *eatured*— opcional, curado: links pra 3-5 docs de entrada

    (RFC001, headlessfirst.kmd, multi-tenancy/contract.kmd, …)

  6. *ooter 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. *iltros*
    • 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. *ista de docs*— tabela ou cards:
    • Nome + subpath + 1line 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. *eft sidebar*(sticky, scroll-independente):
    • Navegação da categoria atual (árvore expandida no doc atual)
  3. *ain 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 date · commit sha"

  4. *ight 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 METADOCS131.2. Esta seção é o *ontrato*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
  • Crosslinks: resolver `[texto](relativepath.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 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: date"
facets tags clicáveis

6.6 Hyperscale gate

Per policies/hyperscale-first.kmd: renderer *EVE*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 areasbrandcompany). 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

*heme* lightdark per `specsthemes/light-dark.kmd`. Toggle JS idêntico ao das outras landings.

*okens visuais* per specs/themes/verge.kmd — usar Verge default.

*ontes* per specs/fonts/typography.kmd:

  • Sans: Inter (self-hosted woff2 via /_assets/fonts/inter.woff2)
  • Mono: JetBrains Mono (self-hosted)
  • *roibido*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=…

  • Copytoclipboard em code blocks (button hover)
  • Anchor links em H2/H3 (hover icon → copy URL com fragment)

lunr.min.js carregado *ó na rota*/search/ (lazy) — não penaliza páginas de leitura.

A spec *andata*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 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) *Ã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
  • Skiptocontent 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 stgdev (per `policiesenvironments.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:

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:

  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é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

  • *wner* Koder Stack (Rodrigo)
  • *pec maturity gate* v1.0 normative quando #131.2.3.4.5.6/.7

    do umbrella METADOCS131 estiverem done + lighthouse scores atingidos + dead-link audit limpa em 2 builds consecutivos

  • *ersioning* a spec do portal segue semver per

    specs/landing-pages/specs.kmd §6

  • *udit* koder-spec-audit landing-pages --slug docs (a ser

    implementado pelo audit harness em dev/koder-tools/)

18. Decisões Em Aberto

  1. *earch backend longterm* lunr.js (v0) → kdbsearch quando

    rfcs/stack-RFC-001-kdb-as-unified-data-plane.kmd entregar layer de busca. Decisão revisitada no kickoff de #131.2.

  2. *ersionamento 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. *G 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. *omments / feedback* deixar fora do v0. Avaliar Giscus

    (GitHubbacked) vs solução selfhosted em v2.

  5. *ersioned 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 docaspage
  • 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)

  • METADOCS131 — umbrella ticket do programa
  • JET-161 — vhost ticket

20. Estado Atual (20260524)

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

Source: ../home/koder/dev/koder/meta/docs/stack/specs/landing-pages/meta.kmd