application tier

application-public-ui

Forge public-site UI kit — themeable Askama templates + typed render contexts (chrome/brand/i18n/jsonld/hero) over forge-cms PageView. Consumers shadow templates via askama.toml dirs precedence and rebrand via CSS custom-property tokens.

Forge public-site UI kit — themeable Askama templates + typed render contexts (chrome/brand/i18n/jsonld/hero) over forge-cms PageView. Consumers shadow templates via askama.toml dirs precedence and rebrand via CSS custom-property tokens.

Tierapplication
Roleunclassified (baselined)
Pathcrates/application/public-ui
Edition2021
Targetsapplication_public_ui
Public items15 across 3 modules
Tests60

What it is for

# application-public-ui

A reusable, themeable public-site UI kit: Askama base layout + page templates + the typed render contexts they consume, over the application-cms PageView render contract.

What the kit ships

forge/_layout.html with override blocks (head_extra/header/hero/hero_cta/content/cta/footer/ decoration/body_class) and page templates forge/pages/{home,services,service,sectors,projects,about,contact, default}.html. The contact template exposes a contact_form block so a consumer supplies its own bespoke form.

ChromeBuilder), HeroContext, the I18n helper, and the jsonld builders.

on CSS custom properties — a consumer rebrands by overriding tokens.

(ServiceCard, Sector, Project, Faq, ContactMethod, TeamMember), re-exported so consumers depend on one crate.

owns compiled #derive(Template) structs over its bundled forge/pages/*.html, so a new consumer mounts a working public site over a PublicPageReader with no template wiring. Registry-safe.

Two consumption paths (A vs B)

its own templates (driven by this crate's askama.toml) and mounts them behind a PublicPageReader fetch seam + PublicSiteConfig. No markup override — config + CSS tokens only. Use this from a registry dependency.

The consumer adds the kit's template dir to its own askama.toml dirs and writes its own page structs, overriding any template by a same-named file. Askama joins dirs to the compiling crate's CARGO_MANIFEST_DIR with no OUT_DIR/env support, so B only works when the kit is a path/Git dep at a stable relative path. See CONTRACT.md §5 for the full distribution matrix and the "vendor the templates" escape hatch for registry consumers who need override.

The override mechanism (Mechanism B — dirs precedence)

Askama compiles templates at build from askama.toml dirs, each resolved relative to the compiling crate's CARGO_MANIFEST_DIR. A consumer adds the kit's template dir to its own dirs AFTER its own templates:

# consumer askama.toml
general
dirs = 
"templates",
"../rust-primitives-main/crates/platform/public-ui/templates",

Then a consumer page-template struct does #template(path = "forge/pages/home.html") (or {% extends "forge/_layout.html" %} from its own template). Because dirs is searched first-match-wins, the consumer overrides any kit template by placing a same-named file under its own templates/forge/….

The render contract

The kit's templates and the consumer's Rust struct are coupled by: 1. Context fields — the page struct must expose page: ChromeContext plus the per-page fields documented in CONTRACT.md. 2. CSS class names — the kit markup emits a fixed set of classes the theme stylesheet (kit default or consumer override) styles. They are listed in CONTRACT.md. A shadowed template that drops a class silently breaks styling, so the contract is the checklist for any override.

Capabilities

I18n

Path-prefix i18n helper — the mechanism lifted from the consumer's

Item
pub struct I18n
I18n :: fn new(secondary_prefix : impl Into <String>, slug_map : & 'static SlugMap) -> Self
I18n :: fn to_canonical(& self, secondary_path : & str) -> String
I18n :: fn to_secondary(& self, primary_path : & str) -> String
I18n :: fn localized_path(& self, canonical_path : & str, is_secondary : bool) -> String

SlugMap

Path-prefix i18n helper — the mechanism lifted from the consumer's

Item
pub type SlugMap: (& 'static str, & 'static str)

jsonld (other)

schema.org JSON-LD builders over BrandContext.

Item
fn organization(brand : & BrandContext, site_origin : & str, area_served : Option <& str>) -> Value
fn website_entity(brand : & BrandContext, site_origin : & str, languages : & & str) -> Value
fn home_page(brand : & BrandContext, site_origin : & str, area_served : Option <& str>, languages : & & str,) -> Vec <Value>
fn generic_page(brand : & BrandContext, site_origin : & str, area_served : Option <& str>, canonical_url : & str, name : & str,) -> Vec <Value>
fn serialize(graph : Vec <Value>) -> String

preview (other)

Sprint 0.75 — gated template preview render (the live half of the New-Page

Item
fn render_preview(cfg : & PublicSiteConfig, template_key : & str, metadata : & serde_json::Value,) -> Option <Result <String, askama::Error>>
fn render_block_sample(cfg : & PublicSiteConfig, block_key : & str) -> Option <String>
fn render_widget_sample(_cfg : & PublicSiteConfig, widget_key : & str) -> Option <String>
fn preview_router <S>(cfg : PublicSiteConfig) -> Router <S> where S : Clone + Send + Sync + 'static,

How to use it

No examples/ target and no doctest in this crate's rustdoc. The tests listed under Verification are the closest executable usage.

Module structure

application_public_ui

flowchart TD
  n_application_public_ui["application_public_ui"]
  n_application_public_ui --> n_i18n["i18n"]
  n_application_public_ui --> n_jsonld["jsonld"]
  n_application_public_ui --> n_preview["preview"]

Public surface

`i18n`

ItemWhat it is
pub type SlugMap: (& 'static str, & 'static str)ES↔EN (primary↔secondary) slug pairs
pub struct I18nPath-prefix i18n configuration + helpers.
I18n :: fn new(secondary_prefix : impl Into <String>, slug_map : & 'static SlugMap) -> SelfConstruct from a secondary-locale prefix + the consumer's slug map.
I18n :: fn to_canonical(& self, secondary_path : & str) -> StringTranslate a secondary-locale path (already stripped of the prefix) to its canonical primary form
I18n :: fn to_secondary(& self, primary_path : & str) -> StringTranslate a canonical primary path to its secondary-locale form (without the prefix)
I18n :: fn localized_path(& self, canonical_path : & str, is_secondary : bool) -> StringBuild the public URL path for canonical_path in the requested locale

`jsonld`

ItemWhat it is
fn organization(brand : & BrandContext, site_origin : & str, area_served : Option <& str>) -> Value
fn website_entity(brand : & BrandContext, site_origin : & str, languages : & & str) -> ValueWebSite entity — home page only
fn home_page(brand : & BrandContext, site_origin : & str, area_served : Option <& str>, languages : & & str,) -> Vec <Value>Home-page graph: org + website.
fn generic_page(brand : & BrandContext, site_origin : & str, area_served : Option <& str>, canonical_url : & str, name : & str,) -> Vec <Value>A generic page graph: org + a WebPage referencing it by @id.
fn serialize(graph : Vec <Value>) -> StringSerialize a graph as a <script>-ready string wrapped in @context + @graph.

`preview`

ItemWhat it is
fn render_preview(cfg : & PublicSiteConfig, template_key : & str, metadata : & serde_json::Value,) -> Option <Result <String, askama::Error>>Public render-from-(key, metadata) entry (Sprint 0.75, T4)
fn render_block_sample(cfg : & PublicSiteConfig, block_key : & str) -> Option <String>Render one block from its registry sample, through the public-tier resolver (Sprint 0.76 T4) — the live half of the block palette, the block analogue of render_preview
fn render_widget_sample(_cfg : & PublicSiteConfig, widget_key : & str) -> Option <String>Render one widget from its registry sample, through the public-tier resolver (Sprint 0.76 T7) — the live half of the widget palette, the widget analogue of render_block_sample
fn preview_router <S>(cfg : PublicSiteConfig) -> Router <S> where S : Clone + Send + Sync + 'static,The gated preview router (Sprint 0.75, T3)

Re-exports. Exported here, defined elsewhere.

ExportDefined in
{AltLink,ChromeBuilder,ChromeContext,NavItem,SwitcherLink}chrome::{AltLink,ChromeBuilder,ChromeContext,NavItem,SwitcherLink}
{BrandContext,ContactInfo,SocialLinks}brand::{BrandContext,ContactInfo,SocialLinks}
{ContactMethod,Faq,PageView,Project,Sector,ServiceCard,TeamMember}application_cms::{ContactMethod,Faq,PageView,Project,Sector,ServiceCard,TeamMember}
{I18n,SlugMap}i18n::{I18n,SlugMap}
{PostgresPublicPageReader,PublicPageContent,PublicPageReader}application_cms::{PostgresPublicPageReader,PublicPageContent,PublicPageReader}
{preview_router,render_block_sample,render_preview}preview::{preview_router,render_block_sample,render_preview}
{public_router,NavSpec,PublicSiteConfig}router::{public_router,NavSpec,PublicSiteConfig}
{render_block_preview,render_blocks_html,GalleryImage}blocks::{render_block_preview,render_blocks_html,GalleryImage}
{render_slot_html,render_widget_preview,SocialLink}widgets::{render_slot_html,render_widget_preview,SocialLink}
{render_style_block,HeroContext}hero::{render_style_block,HeroContext}

Boundary

Depends on no other workspace tier.

Shares tier application with 120 other crates: application-agreements, application-ai, application-analytics, application-approvals, application-assessments, application-audit-log, application-auth, application-billing, … (120 total).

_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._

Where it sits

Tier (ontology)application
Architectural role (taxonomy)unclassified (baselined)
Locationcrates/application/public-ui
Vocabulary in force (lexicon)current

Dependencies

Runtime, in this workspace.

CrateTierOptionalOnly on
`application-cms`applicationnoalways

Runtime, from outside the workspace.

CrateRequirementFeaturesOptionalOnly on
askama^0.12noalways
askama_axum^0.4noalways
async-trait^0.1noalways
axum^0.7multipartnoalways
serde^1derivenoalways
serde_json^1noalways

Development, from outside the workspace.

CrateRequirementFeaturesOptionalOnly on
tokio^1fullnoalways
tower^0.5noalways

Build. None.

Depended on by. Nothing in this workspace.

Signal flow — what reaches this crate, and what it reaches.

flowchart LR
  SELF["application-public-ui"]
  SELF -->|runtime| n_application_cms["application-cms"]
  classDef self fill:#1f883d,stroke:#1f883d,color:#fff;
  class SELF self;

Feature flags

No Cargo features are defined: every capability is unconditional, so no consumer can receive a half-wired crate.

Targets

KindNameSource
libapplication_public_ui`src/lib.rs`

Error model

No public error type was detected: no public item declares a type named *Error, and no public signature returns one.

Operational characteristics

PropertyEvidence
async public surfacenone detected
async runtimenone detected
database accessnone detected
network I/Oyes
unsafe codenone detected
environment variablesnone detected

No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.

Configuration

No environment variable is read with a literal name anywhere in this crate. A variable whose key is computed at run time cannot be listed here, and is not claimed to be absent.

No workspace crate depends on this one.

Verification

KindCount
Unit tests60
Integration tests0
Examples0
Doctests0

Evidence by module. How often each public module is named by something executable.

ModuleTestsExamplesConsumers
i18n200
jsonld500
preview400

What the tests establish, by name:

Documentation coverage

MeasureDocumentedTotal
Public items with rustdoc1415
Public modules with a //! block33
pie showData
    title Public items with rustdoc
    "Documented" : 14
    "No rustdoc detected" : 1

Metrics

MetricValue
Rust source files10
Source lines3473
Code lines2551
Public API items15
Public modules3
Tests60
Examples0
Cargo features0
Direct runtime dependencies7
Workspace reverse dependencies0
pie showData
    title Public API by kind
    "function" : 9
    "method" : 4
    "struct" : 1
    "type alias" : 1
pie showData
    title Rust source composition
    "Code" : 2551
    "Blank or comment" : 922

Generation

Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.

All application · Manual