308 lines
6.5 KiB
Text
308 lines
6.5 KiB
Text
# Unified Site Configuration Contracts
|
||
#
|
||
# Type contracts for site.ncl — validates the complete site configuration
|
||
# including site metadata, paths, themes, content types, and routes with
|
||
# embedded multilingual menu data.
|
||
#
|
||
# JSON output of site.ncl is deserialized by build_config::site_config::UnifiedSiteConfig.
|
||
|
||
{
|
||
SiteMetadata = {
|
||
name
|
||
| String
|
||
| doc "Site display name",
|
||
|
||
languages
|
||
| Array String
|
||
| doc "Supported language codes (ISO 639-1, e.g. ['en', 'es'])",
|
||
|
||
default_language
|
||
| String
|
||
| doc "Default language code when none is specified in URL",
|
||
},
|
||
|
||
SitePaths = {
|
||
i18n
|
||
| String
|
||
| doc "Path to i18n/FTL locales directory",
|
||
|
||
content
|
||
| String
|
||
| doc "Path to content directory",
|
||
|
||
themes
|
||
| String
|
||
| doc "Path to themes configuration directory",
|
||
|
||
assets
|
||
| String
|
||
| doc "Path to public assets directory",
|
||
|
||
migrations
|
||
| String
|
||
| doc "Path to SQL migration files directory (server-only)"
|
||
| optional,
|
||
|
||
email_templates
|
||
| String
|
||
| doc "Path to email template files directory (server-only)"
|
||
| optional,
|
||
|
||
work
|
||
| String
|
||
| doc "Path to work-in-progress / staging assets directory (implementation-specific)"
|
||
| optional,
|
||
},
|
||
|
||
ThemeConfig = {
|
||
default
|
||
| String
|
||
| doc "Default theme name",
|
||
|
||
available
|
||
| Array String
|
||
| doc "List of available theme names",
|
||
},
|
||
|
||
ContentTypeFeatures = {
|
||
style_mode
|
||
| String
|
||
| doc "Display style: 'row' or 'grid'",
|
||
|
||
use_feature
|
||
| Bool
|
||
| doc "Enable featured content at top of index",
|
||
|
||
use_categories
|
||
| Bool
|
||
| default = true,
|
||
|
||
use_tags
|
||
| Bool
|
||
| default = true,
|
||
|
||
use_emojis
|
||
| Bool
|
||
| default = false,
|
||
|
||
cta_view
|
||
| String
|
||
| doc "CTA component name (e.g. 'BlogCTAView')",
|
||
|
||
default_page_size
|
||
| Number
|
||
| default = 10,
|
||
|
||
# Allow additional feature fields without breaking the contract
|
||
..
|
||
},
|
||
|
||
ContentType = {
|
||
name
|
||
| String
|
||
| doc "Content type identifier (e.g. 'blog', 'recipes')",
|
||
|
||
directory
|
||
| String
|
||
| doc "Directory name under content path",
|
||
|
||
enabled
|
||
| Bool
|
||
| default = true,
|
||
|
||
features
|
||
| ContentTypeFeatures
|
||
| doc "Content display and pagination settings",
|
||
},
|
||
|
||
# Database connection configuration.
|
||
# Structural settings (type, path, pool sizing) belong here.
|
||
# Credentials and full overrides go in .env via DATABASE_URL.
|
||
DatabaseConfig = {
|
||
url
|
||
| String
|
||
| doc "Database connection URL (e.g. 'sqlite:data/dev.db' or 'postgres://...')",
|
||
|
||
create_if_missing
|
||
| Bool
|
||
| doc "Create the SQLite database file if it does not exist"
|
||
| default = true,
|
||
|
||
max_connections
|
||
| Number
|
||
| doc "Maximum number of connections in the pool"
|
||
| default = 5,
|
||
|
||
min_connections
|
||
| Number
|
||
| doc "Minimum number of idle connections in the pool"
|
||
| default = 1,
|
||
|
||
connect_timeout
|
||
| Number
|
||
| doc "Connection acquisition timeout in seconds"
|
||
| default = 30,
|
||
|
||
idle_timeout
|
||
| Number
|
||
| doc "Maximum idle connection duration in seconds"
|
||
| default = 600,
|
||
|
||
max_lifetime
|
||
| Number
|
||
| doc "Maximum connection lifetime in seconds"
|
||
| default = 1800,
|
||
},
|
||
|
||
# Footer metadata — absorbed inline into SiteConfig.
|
||
FooterMetadata = {
|
||
title
|
||
| String
|
||
| doc "Footer title (language-neutral, e.g. author name)",
|
||
|
||
company_desc
|
||
| { _ : String }
|
||
| doc "Company description keyed by language code",
|
||
|
||
copyright_text
|
||
| { _ : String }
|
||
| doc "Copyright notice keyed by language code",
|
||
|
||
social_links
|
||
| Array {
|
||
name | String,
|
||
url | String,
|
||
icon | String,
|
||
}
|
||
| default = [],
|
||
},
|
||
|
||
# Menu configuration embedded directly in Route.
|
||
# At least one of label_key or labels must be present (validated by Nickel contracts
|
||
# plus runtime assertion in Rust loader).
|
||
MenuEntry = {
|
||
enabled
|
||
| Bool
|
||
| doc "Whether this route appears in navigation"
|
||
| default = false,
|
||
|
||
order
|
||
| Number
|
||
| doc "Display order (lower = first)"
|
||
| optional,
|
||
|
||
icon
|
||
| String
|
||
| doc "Icon identifier (e.g. 'home', 'fas fa-user')"
|
||
| optional,
|
||
|
||
label_key
|
||
| String
|
||
| doc "Primary: FTL i18n key for label (e.g. 'nav-home')"
|
||
| optional,
|
||
|
||
labels
|
||
| { _ : String }
|
||
| doc "Fallback inline labels keyed by language code"
|
||
| optional,
|
||
|
||
visible_in
|
||
| Array String
|
||
| doc "Language codes this item is visible in. Empty = all languages."
|
||
| default = [],
|
||
|
||
use_in
|
||
| Array String
|
||
| doc "Navigation zones: ['header'], ['footer'], or ['header','footer']"
|
||
| default = ["header"],
|
||
},
|
||
|
||
# A unified route entry covering all languages in a single record.
|
||
# paths maps language code → URL path (e.g. { en = '/', es = '/inicio' }).
|
||
Route = {
|
||
component
|
||
| String
|
||
| doc "Page component name (e.g. 'HomePage', 'ContentIndex')",
|
||
|
||
paths
|
||
| { _ : String }
|
||
| doc "URL paths keyed by language code",
|
||
|
||
priority
|
||
| Number
|
||
| doc "SEO/sitemap priority (0.0–1.0)"
|
||
| default = 0.8,
|
||
|
||
content_type
|
||
| String
|
||
| doc "Content type for dynamic routes (e.g. 'blog')"
|
||
| optional,
|
||
|
||
menu
|
||
| MenuEntry
|
||
| doc "Navigation menu configuration for this route",
|
||
|
||
props
|
||
| { _ : Dyn }
|
||
| doc "Additional route-specific properties passed to component"
|
||
| optional,
|
||
|
||
},
|
||
|
||
LogoConfig = {
|
||
light_src
|
||
| String
|
||
| doc "Path to light-mode logo image",
|
||
|
||
dark_src
|
||
| String
|
||
| doc "Path to dark-mode logo image (empty string disables dark variant)",
|
||
|
||
alt
|
||
| String
|
||
| doc "Alt text for the logo image",
|
||
|
||
show_in_nav
|
||
| Bool
|
||
| doc "Whether to show the logo in the navigation bar",
|
||
|
||
show_in_footer
|
||
| Bool
|
||
| doc "Whether to show the logo in the footer",
|
||
|
||
width
|
||
| optional
|
||
| doc "Optional logo width (CSS value or null)",
|
||
|
||
height
|
||
| optional
|
||
| doc "Optional logo height (CSS value or null)",
|
||
},
|
||
|
||
SiteConfig = {
|
||
site
|
||
| SiteMetadata,
|
||
|
||
paths
|
||
| SitePaths,
|
||
|
||
themes
|
||
| ThemeConfig,
|
||
|
||
logo
|
||
| LogoConfig,
|
||
|
||
content_types
|
||
| Array ContentType,
|
||
|
||
database
|
||
| DatabaseConfig
|
||
| doc "Database connection and pool configuration",
|
||
|
||
footer
|
||
| FooterMetadata,
|
||
|
||
routes
|
||
| Array Route,
|
||
},
|
||
}
|