let p = import "purpose-defaults.ncl" in p.make_purpose { declaration = { id = "website-htmx-rustelo-purpose", name = "Website (HTMX/Rustelo) Purpose", pole = 'Yin, statement = "This site exists to publish bilingual EN/ES technical content through a Rustelo HTMX implementation, giving both language audiences the same depth of material with crawlable, server-rendered pages.", elaboration = "The bilingual constraint is not cosmetic — it commits the site to closing the quality-technical-content gap for Spanish-speaking developers. The HTMX rendering profile is chosen for simplicity and crawlability; Leptos hydration remains available per-route. The purpose is fulfilled when both audiences (EN and ES) reach parity in content and in rendered quality, and the implementation never forks the Rustelo framework to get there.", primary_audience = ['Developer, 'EndUser], anti_purpose = "This site is not a marketing funnel, not a general-opinion blog, and not a lead-capture portfolio. It is not intended to maximize traffic at the cost of content depth, and it must never ship a route in one language only.", horizon = 'Ongoing, }, publication_intent = { id = "website-htmx-rustelo-publication-intent", name = "Publication Intent", description = "Publishing means deploying to production where both EN and ES audiences can reach every launched content section. Publication requires bilingual completeness on launched sections, hydration parity for any hydration-opted route, and verified purpose-aligned SEO criteria.", channels = ['PublishedSite, 'RSSFeed], readiness_gate = "purpose-gate", trigger_condition = "content-coverage is at full-parity, rendering-mode hydration-opted routes pass validate-hydration, and publication-readiness has reached production-ready. validate-purpose-alignment passes all Hard criteria.", anti_patterns = [ "Launching a content section with only one language populated", "Publishing while publication-readiness is still pre-production", "Publishing with known hydration mismatches on hydration-opted routes", "Publishing content that serves no declared audience (Developer or EndUser)", ], }, content_objectives = [ { id = "bilingual-content", name = "Bilingual Technical Content", description = "Technical articles and pages published in both English and Spanish covering Rust, web architecture, and infrastructure. Bilingual parity is non-negotiable — every EN item has its ES equivalent and vice versa.", target_audience = ['Developer, 'EndUser], content_kinds = ["blog", "pages"], purpose_alignment_note = "Primary vehicle of the purpose: closes the quality-technical-content gap for Spanish-speaking developers on the same stack.", seo_intent = 'Organic, horizon = 'Ongoing, active = true, }, { id = "project-showcase", name = "Project Showcase", description = "Bilingual presentation of technical projects with architecture, real status, and goals. Published status must reflect reality, not the desired state.", target_audience = ['Developer, 'EndUser], content_kinds = ["projects"], purpose_alignment_note = "Demonstrates technical work with depth and honesty — reinforces the site as a knowledge platform, not marketing.", seo_intent = 'Reference, horizon = 'Months, active = true, }, ], validation_criteria = [ { id = "bilingual-completeness", name = "Bilingual Content Completeness Before Publication", description = "No menu-visible section may publish if EN and ES counts diverge. Every menu-enabled route must have corresponding content in both language directories.", check_hint = "Run the validate-content mode. The diff-routes and count-content steps must report zero asymmetries for menu-enabled routes.", severity = 'Hard, applies_to = ["bilingual-content", "project-showcase"], }, { id = "purpose-audience-relevance", name = "Content Serves Declared Audience", description = "Every published content item must classify as serving the 'Developer or 'EndUser audience. Content serving no declared audience is a purpose-alignment violation.", check_hint = "Review each content item's front-matter for audience markers; flag items with no audience classification. Run validate-purpose-alignment.", severity = 'Hard, applies_to = ["bilingual-content", "project-showcase"], }, { id = "no-publish-during-hydration-instability", name = "No Publication During Hydration Instability", description = "The site must not deploy to production while any hydration-opted route fails hydration parity — rendering-mode must not regress below its current htmx-ssr baseline for served routes.", check_hint = "Run validate-hydration: no empty HashMap in *Client components, SsrTranslator used, FTL registry populated for hydration-opted routes.", severity = 'Hard, applies_to = ["bilingual-content", "project-showcase"], }, ], seo_criteria = [ { id = "bilingual-canonical-urls", name = "Bilingual Canonical URLs with hreflang", description = "Every EN URL must carry to its ES equivalent and vice versa. The XML sitemap must include both variants for each page.", rationale = "Serves the purpose directly: EN and ES audiences must find the same content in their language via organic search. Without hreflang, search engines may index only one variant.", check_hint = "Audit a rendered blog route's HTML: confirm in
, and that sitemap.xml includes both URLs.", severity = 'Hard, applies_to = ["bilingual-content", "project-showcase"], }, { id = "structured-data-articles", name = "Article Structured Data (JSON-LD)", description = "Technical blog articles must include JSON-LD typed Article or TechArticle: author, datePublished, headline, inLanguage.", rationale = "Improves prominence for developers searching technical guides — serves the purpose by connecting content to technical audiences through rich results.", check_hint = "Inspect a rendered article's HTML for