450 lines
19 KiB
Text
450 lines
19 KiB
Text
|
|
# 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"],
|
||
|
|
},
|
||
|
|
},
|
||
|
|
],
|
||
|
|
}
|