# Route table — the FRAMEWORK SHARED SUPERSET (ADR-001, single-image deploy). # # This is NOT one site's personal routes — it is the superset any htmx-ssr consumer # may need, baked once into the shared binary. A consumer decides at runtime which # routes carry content and which appear in its menu (menus/footer load from the # consumer's routes.ncl at startup). MUST declare a ContentIndex + PostViewer for # every standard content kind {blog, projects, adr, catalog} so a consumer link # never 404s — guarded by `just validate-route-superset`. Routing stays compiled # (ADR-001 forbids runtime-routing); add a kind here + rebuild. # # Adding a new route: add a make_route/make_content_route record here. # Adding a new language: add the lang code to site.ncl and add a `paths` entry # to every route record — no other files need changing. let site_d = import "site/defaults.ncl" in let site_c = import "site/contracts.ncl" in let { make_route, make_content_route, make_external, priorities, orders, no_menu } = site_d in { routes = [ # ── Home ──────────────────────────────────────────────────────────────── make_route "HomePage" { en = "/", es = "/inicio" } & { priority = priorities.critical, menu = { enabled = true, order = orders.home, icon = "home", label_key = "nav-home", labels = { en = "Home", es = "Inicio" }, use_in = ["header"], }, }, # Alternate Spanish home path (/es) — no menu entry make_route "HomePage" { es = "/es" } & { priority = priorities.critical, menu = no_menu, }, # Alternate English home path (/en) — no menu entry make_route "HomePage" { en = "/en" } & { priority = priorities.critical, menu = no_menu, }, # ── About ──────────────────────────────────────────────────────────────── make_route "AboutPage" { en = "/about", es = "/acerca-de" } & { priority = priorities.high, menu = { enabled = true, order = orders.about, icon = "fas fa-user", label_key = "nav-about", labels = { en = "About", es = "Acerca de" }, use_in = ["header"], }, }, # ── Services ───────────────────────────────────────────────────────────── make_route "ServicesPage" { en = "/services", es = "/servicios" } & { priority = priorities.high, menu = { enabled = true, order = orders.services, icon = "briefcase", label_key = "nav-services", labels = { en = "Services", es = "Servicios" }, use_in = ["header"], }, }, # ── Projects article viewer ─────────────────────────────────────────────── make_content_route "PostViewer" "projects" { en = "/projects/{slug}", es = "/proyectos/{slug}" } & { priority = priorities.low, menu = no_menu, }, # ── ADR viewer (kind `adr`, projected from .ontoref/adrs) ───────────────── make_content_route "PostViewer" "adr" { en = "/adr/{slug}", es = "/adr/{slug}" } & { priority = priorities.low, menu = no_menu, }, make_content_route "ContentIndex" "adr" { en = "/adr", es = "/adr" } & { priority = priorities.normal, menu = no_menu, }, # ── Catalog viewer (kind `catalog`, projected from .ontoref/catalog) ────── # Part of the shared superset (ADR-001); a consumer's About/links to /catalog # resolve against the baked binary instead of 404-ing. make_content_route "PostViewer" "catalog" { en = "/catalog/{slug}", es = "/catalog/{slug}" } & { priority = priorities.low, menu = no_menu, }, make_content_route "ContentIndex" "catalog" { en = "/catalog", es = "/catalog" } & { priority = priorities.normal, menu = no_menu, }, # ── Domains viewer (kind `domains`, ontoref's four-door domain surface) ──── # Shared superset (ADR-001/065): baked so /domains (EN) · /dominios (ES) resolve. # Consumer (outreach/site) supplies content at runtime via spine projection. make_content_route "PostViewer" "domains" { en = "/domains/{slug}", es = "/dominios/{slug}" } & { priority = priorities.low, menu = no_menu, }, make_content_route "ContentIndex" "domains" { en = "/domains", es = "/dominios" } & { priority = priorities.high, menu = { enabled = true, order = orders.projects, icon = "folder", label_key = "nav-domains", labels = { en = "Domains", es = "Dominios" }, use_in = ["header"], }, props = { content_type = "domains", cta_view = "ProjectsCTAView", style_css = "projects-content", style_mode = "grid", use_categories = true, use_feature = true, use_tags = true, }, }, # ── Projects (content index) — nav moved to /dominios (ADR-065) ──────────── make_content_route "ContentIndex" "projects" { en = "/projects", es = "/proyectos" } & { priority = priorities.high, menu = no_menu, props = { content_type = "projects", cta_view = "ProjectsCTAView", style_css = "projects-content", style_mode = "grid", use_categories = true, use_feature = true, use_tags = true, }, }, # ── Activities article viewer ───────────────────────────────────────────── make_content_route "PostViewer" "activities" { en = "/activities/{category}/{slug}", es = "/actividades/{category}/{slug}" } & { priority = priorities.minimal, menu = no_menu, }, # ── Activities category filter ──────────────────────────────────────────── make_content_route "ContentIndex" "activities" { en = "/activities/{category}", es = "/actividades/{category}" } & { priority = priorities.low, menu = no_menu, }, # ── Activities (content index) ──────────────────────────────────────────── make_content_route "ContentIndex" "activities" { en = "/activities", es = "/actividades" } & { priority = priorities.normal, menu = { enabled = true, order = 7, icon = "presentation", label_key = "nav-activities", labels = { en = "Activities", es = "Actividades" }, use_in = ["header"], }, props = { content_type = "activities", cta_view = "ActivitiesCTAView", style_css = "activities-content", style_mode = "grid", use_categories = true, use_feature = true, use_tags = true, }, }, # ── Blog article viewer ─────────────────────────────────────────────────── make_content_route "PostViewer" "blog" { en = "/blog/{category}/{slug}", es = "/blog/{category}/{slug}" } & { priority = priorities.minimal, menu = no_menu, }, # ── Recipes article viewer ──────────────────────────────────────────────── make_content_route "PostViewer" "recipes" { en = "/recipes/{category}/{slug}", es = "/recetas/{category}/{slug}" } & { priority = priorities.minimal, menu = no_menu, }, # ── Blog category filter ────────────────────────────────────────────────── make_content_route "ContentIndex" "blog" { en = "/blog/{category}", es = "/blog/{category}" } & { priority = priorities.low, menu = no_menu, }, # ── Recipes category filter ─────────────────────────────────────────────── make_content_route "ContentIndex" "recipes" { en = "/recipes/{category}", es = "/recetas/{category}" } & { priority = priorities.low, menu = no_menu, }, # ── Blog (content index) ────────────────────────────────────────────────── make_content_route "ContentIndex" "blog" { en = "/blog", es = "/blog" } & { priority = priorities.normal, menu = { enabled = true, order = orders.blog, icon = "book", label_key = "nav-blog", labels = { en = "Blog", es = "Blog" }, use_in = ["header"], }, props = { content_type = "blog", cta_view = "BlogCTAView", style_css = "blog-content", style_mode = "row", use_categories = true, use_emojis = true, use_feature = true, use_links = [ ["archive", "/blog/archive"], ["rss", "/blog/rss.xml"], ["categories", "/blog/categories"], ], use_tags = true, }, }, # ── Recipes (content index) ─────────────────────────────────────────────── make_content_route "ContentIndex" "recipes" { en = "/recipes", es = "/recetas" } & { priority = priorities.normal, menu = { enabled = true, order = orders.recipes, icon = "lightbulb", label_key = "nav-recipes", labels = { en = "Recipes", es = "Recetas" }, use_in = ["header"], }, props = { content_type = "recipes", cta_view = "RecipesCTAView", style_css = "recipes-content", style_mode = "row", use_categories = true, use_feature = true, }, }, # ── Content Graph ───────────────────────────────────────────────────────── make_route "ContentGraphPage" { en = "/graph", es = "/grafo" } & { priority = priorities.low, menu = no_menu, }, # ── Ontoref ─────────────────────────────────────────────────────────────── make_route "OntorefPage" { en = "/ontoref", es = "/ontoref" } & { priority = priorities.normal, menu = no_menu, }, # ── Rustelo ─────────────────────────────────────────────────────────────── make_route "RusteloPage" { en = "/rustelo", es = "/rustelo" } & { priority = priorities.normal, menu = no_menu, }, # ── Vapora ──────────────────────────────────────────────────────────────── make_route "VaporaPage" { en = "/vapora", es = "/vapora" } & { priority = priorities.normal, menu = no_menu, }, # ── Provisioning ───────────────────────────────────────────────────────── make_route "ProvisioningPage" { en = "/provisioning-systems", es = "/provisioning-systems" } & { priority = priorities.normal, menu = no_menu, }, # ── StratumIOps ───────────────────────────────────────────────────────── make_route "StratumiopsPage" { en = "/stratumiops", es = "/stratumiops" } & { priority = priorities.normal, menu = no_menu, }, # ── SecretumVault ─────────────────────────────────────────────────────── make_route "SecretumvaultPage" { en = "/secretumvault", es = "/secretumvault" } & { priority = priorities.normal, menu = no_menu, }, # ── Kogral ─────────────────────────────────────────────────────────────── make_route "KogralPage" { en = "/kogral", es = "/kogral" } & { priority = priorities.normal, menu = no_menu, }, # ── TypeDialog ─────────────────────────────────────────────────────────── make_route "TypedialogPage" { en = "/typedialog", es = "/typedialog" } & { priority = priorities.normal, menu = no_menu, }, # ── Syntaxis ───────────────────────────────────────────────────────────── make_route "SyntaxisPage" { en = "/syntaxis", es = "/syntaxis" } & { priority = priorities.normal, menu = no_menu, }, # ── lian-build ─────────────────────────────────────────────────────────── make_route "LianBuildPage" { en = "/lian-build", es = "/lian-build" } & { priority = priorities.normal, menu = no_menu, }, # ── lamina ──────────────────────────────────────────────────────────────── make_route "LaminaPage" { en = "/lamina", es = "/lamina" } & { priority = priorities.normal, menu = no_menu, }, # ── solera ──────────────────────────────────────────────────────────────── make_route "SoleraPage" { en = "/solera", es = "/solera" } & { priority = priorities.normal, menu = no_menu, }, # ── Work Request ────────────────────────────────────────────────────────── make_route "WorkRequestPage" { en = "/work-request", es = "/solicitud-trabajo" } & { priority = priorities.normal, menu = no_menu, }, # ── Contact ─────────────────────────────────────────────────────────────── make_route "ContactPage" { en = "/contact", es = "/contacto" } & { priority = priorities.normal, menu = { enabled = true, order = orders.contact, icon = "fas fa-envelope", label_key = "nav-contact", labels = { en = "Contact", es = "Contacto" }, use_in = ["header"], }, }, # ── Legal / footer routes ───────────────────────────────────────────────── make_route "LegalPage" { en = "/legal", es = "/legal" } & { priority = priorities.low, menu = { enabled = true, order = 2, icon = "fas fa-gavel", label_key = "nav-legal", labels = { en = "Legal Notice", es = "Aviso Legal" }, use_in = ["footer"], }, }, make_route "PrivacyPage" { en = "/privacy", es = "/privacidad" } & { priority = priorities.low, menu = { enabled = true, order = 1, icon = "fas fa-shield-alt", label_key = "nav-privacy", labels = { en = "Privacy Policy", es = "Política de Privacidad" }, use_in = ["footer"], }, }, # ── User (not in sitemap) ───────────────────────────────────────────────── make_route "UserPage" { en = "/user", es = "/usuario" } & { priority = priorities.minimal, menu = no_menu, }, # ── Sign-out goodbye page ───────────────────────────────────────────────── make_route "SignoutPage" { en = "/signout", es = "/hasta-pronto" } & { priority = priorities.minimal, menu = no_menu, }, # ── Login (passwordless OTP) ────────────────────────────────────────────── make_route "LoginPage" { en = "/login", es = "/iniciar-sesion" } & { priority = priorities.minimal, menu = no_menu, }, # ── External links ──────────────────────────────────────────────────────── make_external "Kit-Digital" "/kitdigital.html" & { menu = { enabled = true, order = orders.external, label_key = "nav-kit-digital", labels = { en = "Kit-Digital", es = "Kit-Digital" }, visible_in = ["es"], use_in = ["header"], }, }, ], }