146 lines
9 KiB
Text
146 lines
9 KiB
Text
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 <link rel=\"alternate\" hreflang=\"es\"> 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 <link rel=\"alternate\" hreflang=\"es|en\"> in <head>, 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 <script type=\"application/ld+json\"> with @type Article or TechArticle.",
|
|
severity = 'Hard,
|
|
applies_to = ["bilingual-content"],
|
|
},
|
|
{
|
|
id = "meta-description-purpose-aligned",
|
|
name = "Meta Descriptions Are Accurate and Purpose-Aligned",
|
|
description = "Every published page must have a <meta name=\"description\"> describing the real content. No clickbait, no keyword stuffing.",
|
|
rationale = "The purpose demands editorial honesty. A misleading meta description contradicts the anti_purpose ('not a marketing funnel').",
|
|
check_hint = "Audit meta descriptions of the most-visited pages; verify each matches the real article content, not artificial keywords.",
|
|
severity = 'Hard,
|
|
applies_to = ["bilingual-content", "project-showcase"],
|
|
},
|
|
{
|
|
id = "core-web-vitals-threshold",
|
|
name = "Core Web Vitals Meet Threshold",
|
|
description = "Lighthouse performance score >= 90 on mobile for main content pages. LCP < 2.5s, CLS < 0.1.",
|
|
rationale = "A technical audience judges quality by performance; the HTMX SSR profile should make this readily achievable. Core Web Vitals are also a ranking factor.",
|
|
check_hint = "Run Lighthouse (mobile) for /, and main content routes; verify score >= 90 and LCP/CLS within thresholds.",
|
|
severity = 'Soft,
|
|
applies_to = ["bilingual-content", "project-showcase"],
|
|
},
|
|
],
|
|
|
|
propagation_channels = [
|
|
{
|
|
id = "published-site",
|
|
name = "Production Site",
|
|
channel = 'PublishedSite,
|
|
description = "Primary distribution channel: HTMX server-rendered pages serving all content kinds in EN and ES, with optional per-route Leptos hydration.",
|
|
status = 'Active,
|
|
target_audience = ['EndUser, 'Developer],
|
|
content_kinds = ["blog", "pages", "projects"],
|
|
seo_role = 'Organic,
|
|
gate_id = "purpose-gate",
|
|
},
|
|
{
|
|
id = "rss-feed",
|
|
name = "RSS Feed",
|
|
channel = 'RSSFeed,
|
|
description = "RSS feed for blog articles, enabling syndication and subscription-based consumption.",
|
|
status = 'Planned,
|
|
target_audience = ['Developer, 'EndUser],
|
|
content_kinds = ["blog"],
|
|
seo_role = 'None,
|
|
frequency = "on every new blog post",
|
|
},
|
|
],
|
|
}
|