325 lines
12 KiB
Text
325 lines
12 KiB
Text
|
|
# Unified Site Configuration — Single Source of Truth
|
||
|
|
#
|
||
|
|
# Replaces:
|
||
|
|
# site/config/routes/en.ncl + es.ncl (per-language routes)
|
||
|
|
# site/ui/menus/menu.ncl (multilingual menus)
|
||
|
|
# site/content/content-kinds.toml (content type definitions)
|
||
|
|
# site/ui/footer/footer.ncl (footer metadata)
|
||
|
|
#
|
||
|
|
# Consumed by build_config::site_config::load_unified_site_config() in all
|
||
|
|
# build.rs scripts (shared, client, server).
|
||
|
|
#
|
||
|
|
# NICKEL_IMPORT_PATH must point to rustelo/nickel/ (auto-detected by nickel.rs).
|
||
|
|
#
|
||
|
|
# Adding a new language: add the lang code to site.languages, add a paths
|
||
|
|
# entry to every route record, and create the corresponding FTL file.
|
||
|
|
# 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
|
||
|
|
|
||
|
|
{
|
||
|
|
site = {
|
||
|
|
name = "Website",
|
||
|
|
languages = ["en", "es"],
|
||
|
|
default_language = "en",
|
||
|
|
},
|
||
|
|
|
||
|
|
paths = {
|
||
|
|
i18n = "site/i18n/locales",
|
||
|
|
content = "site/content",
|
||
|
|
themes = "site/config/themes",
|
||
|
|
assets = "site/public",
|
||
|
|
migrations = "rustelo/migrations",
|
||
|
|
email_templates = "site/templates/email",
|
||
|
|
work = "works-pv",
|
||
|
|
},
|
||
|
|
|
||
|
|
themes = {
|
||
|
|
default = "default",
|
||
|
|
available = ["default", "dark", "corporate"],
|
||
|
|
},
|
||
|
|
|
||
|
|
logo = {
|
||
|
|
light_src = "/logos/site-logo-b.png",
|
||
|
|
dark_src = "/logos/site-logo-w.png",
|
||
|
|
alt = "Site logo",
|
||
|
|
show_in_nav = true,
|
||
|
|
show_in_footer = true,
|
||
|
|
width = null,
|
||
|
|
height = null,
|
||
|
|
},
|
||
|
|
|
||
|
|
content_types = [
|
||
|
|
{
|
||
|
|
name = "blog",
|
||
|
|
directory = "blog",
|
||
|
|
enabled = true,
|
||
|
|
features = {
|
||
|
|
style_mode = "row",
|
||
|
|
style_css = "blog-content",
|
||
|
|
use_feature = true,
|
||
|
|
use_categories = true,
|
||
|
|
use_tags = true,
|
||
|
|
use_emojis = true,
|
||
|
|
cta_view = "BlogCTAView",
|
||
|
|
default_page_size = 8,
|
||
|
|
page_size_options = [5, 8, 12, 20],
|
||
|
|
show_page_info = true,
|
||
|
|
pagination_style = "numbered",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name = "recipes",
|
||
|
|
directory = "recipes",
|
||
|
|
enabled = true,
|
||
|
|
features = {
|
||
|
|
style_mode = "grid",
|
||
|
|
style_css = "recipe-content",
|
||
|
|
use_feature = false,
|
||
|
|
use_categories = true,
|
||
|
|
use_tags = true,
|
||
|
|
use_emojis = true,
|
||
|
|
cta_view = "RecipesCTAView",
|
||
|
|
default_page_size = 12,
|
||
|
|
page_size_options = [6, 12, 18, 24],
|
||
|
|
show_page_info = true,
|
||
|
|
pagination_style = "numbered",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
],
|
||
|
|
|
||
|
|
database = {
|
||
|
|
url = "sqlite:works-pv/data/dev_database.db",
|
||
|
|
create_if_missing = true,
|
||
|
|
max_connections = 5,
|
||
|
|
min_connections = 1,
|
||
|
|
connect_timeout = 30,
|
||
|
|
idle_timeout = 600,
|
||
|
|
max_lifetime = 1800,
|
||
|
|
},
|
||
|
|
|
||
|
|
footer = {
|
||
|
|
title = "Jesús Pérez",
|
||
|
|
company_desc = {
|
||
|
|
en = "Rust Developer & Infrastructure Consultant",
|
||
|
|
es = "Desarrollador Rust y Consultor de Infraestructura",
|
||
|
|
},
|
||
|
|
copyright_text = {
|
||
|
|
en = "© 2024 Jesús Pérez. All rights reserved.",
|
||
|
|
es = "© 2024 Jesús Pérez. Todos los derechos reservados.",
|
||
|
|
},
|
||
|
|
social_links = [
|
||
|
|
{ name = "LinkedIn", url = "https://linkedin.com/in/example-org", icon = "fab fa-linkedin" },
|
||
|
|
{ name = "GitHub", url = "https://github.com/example-org", icon = "fab fa-github" },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
|
||
|
|
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,
|
||
|
|
},
|
||
|
|
|
||
|
|
# ── 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"],
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
# ── 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,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
# ── 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,
|
||
|
|
},
|
||
|
|
|
||
|
|
# ── 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"],
|
||
|
|
},
|
||
|
|
},
|
||
|
|
],
|
||
|
|
} | site_c.SiteConfig
|