Component framework that renders one YAML content file into a self-contained HTML report page
Project description
skaldr
A component framework for AI-authored report pages. An AI (or a person) doing real work — an investigation, a review, a proposal, an ingestion report — writes one YAML content file; skaldr validates it and renders one polished, self-contained HTML page. No time is spent on design, styling, or layout: those decisions are made once, here, by the component library.
# from a checkout
uv run skaldr data/example.yaml
open out/example.html
# or installed (from PyPI, once published)
uv tool install skaldr
skaldr data/example.yaml
The CLI is deliberately tiny: skaldr <content.yaml> [-o out.html], plus
skaldr --write-schema schema/page.schema.json. There are no styling flags — everything is
in the content file.
The content file
version: 1
meta:
title: "Q3 Data Import — Issues & Proposed Fixes"
subtitle: ["Reconciled review of the 10,000-record batch."]
source: "Salesforce export" # optional; feeds the provenance footer
date: "Q3 2026" # optional; never auto-now (builds are reproducible)
toc: true # optional; auto table-of-contents from level-2 headings
width: default # optional; page width cap: default (1600) | wide (1920) | full
badges: # author-declared vocabulary (see below)
OUR_SIDE: { label: "Our side", tone: amber, legend: "We can fix it before import." }
BUG: { label: "Bug", tone: blue, legend: "Defect in our pipeline code." }
blocks:
- { type: heading, text: "Overview" }
- { type: text, body: "Prose with **bold**, *italic*, `code`, ~~strike~~ and [links](https://x)." }
- { type: cards, items: [{ label: "Imported cleanly", value: 8500, of: 10000, tone: success }] }
# … more blocks
Top level is version · meta · optional badges · blocks — nothing else. Every block
carries a type discriminator; the model is a pydantic discriminated union, so an unknown
type, a field from the wrong block, or an unknown key each fails with a precise
blocks.3.items.2.value-style error. See data/example.yaml for a
complete file exercising every block, docs/authoring.md for the full
authoring guide, and schema/page.schema.json for the JSON Schema
(point your editor's YAML language server at it).
Blocks
heading · text · list · fact_strip · key_value · cards · badge_row · callout ·
status_list · meter · table · code (plain or diff) · quote · image (data-URI) ·
timeline · section (collapsible) · grid (bounded 6-column side-by-side layout).
section and grid are the two containers: section holds leaf blocks (no nested section);
grid places cells side by side over 6 columns and may nest one level (see
docs/design/grid-layout.md).
The table is the workhorse: typed columns (text/number/badge/rich), optional
groups with derived subtotals, sub-rows, an optional totals footer, and an optional
reconcile block — declare a total and skaldr hard-fails the build if the column sum plus an
optional handled bucket doesn't equal it, naming the delta.
Badges are author-declared
Every tag/status a report uses is declared in the top-level badges map
(key → { label, tone, legend }) and referenced by key from table badge columns and
badge_row. A key that isn't declared is a hard error. skaldr ships no built-in
vocabulary — the only fixed, referenced-by-name vocabularies are the design-system
primitives: the tone palette used by cards/callouts/meters
(neutral · info · success · warning · danger · accent), the badge-chip colours
(slate · blue · green · amber · red · violet · teal · sky), and the state glyphs for
status_list / timeline.
Rich text
Prose fields accept a small markdown subset — **bold**, *italic*, `code`,
~~strike~~, [text](url) (http/https/mailto only). Everything else is escaped; raw HTML is
never interpreted.
Guarantees
- One self-contained file — inline CSS, system fonts, no external resources; the page
carries its own
<!doctype>+<meta charset>so it renders correctly fromfile://, any static host, or a claude.ai Artifact. - Validation is the product — structural mistakes fail the build with a field path, never reach the reader's eyes.
- Derived, not authored — number formatting, percentages, subtotals, the legend, the TOC, and the provenance footer are all computed, so they can't drift from the data.
Layout
src/skaldr/models.py— the content-file contract (pydantic).src/skaldr/compute.py— derived values (legend, TOC, subtotals, footer).src/skaldr/render.py+components/— Jinja rendering.src/skaldr/styles.css— the single tokenised stylesheet.docs/design/component-spec.md— the normative spec;docs/design/reference.html— the rendered golden.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file skaldr-0.3.1.tar.gz.
File metadata
- Download URL: skaldr-0.3.1.tar.gz
- Upload date:
- Size: 24.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7bd44852a10fef976067743cbda39935ad2aed4eca17054eebd02f17d8735ac0
|
|
| MD5 |
2b0724d0f61b6547d0f7bb271bc688ba
|
|
| BLAKE2b-256 |
aa8618ab9f05feac98b58a6f3703c38f60df8b8a7bdd1bc4c3c76021c0a578d9
|
Provenance
The following attestation bundles were made for skaldr-0.3.1.tar.gz:
Publisher:
publish.yml on alex-yanchenko/skaldr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
skaldr-0.3.1.tar.gz -
Subject digest:
7bd44852a10fef976067743cbda39935ad2aed4eca17054eebd02f17d8735ac0 - Sigstore transparency entry: 2139276847
- Sigstore integration time:
-
Permalink:
alex-yanchenko/skaldr@9657f9ad9cc77a1a9d956a89ccdeff99a19d9899 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/alex-yanchenko
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9657f9ad9cc77a1a9d956a89ccdeff99a19d9899 -
Trigger Event:
release
-
Statement type:
File details
Details for the file skaldr-0.3.1-py3-none-any.whl.
File metadata
- Download URL: skaldr-0.3.1-py3-none-any.whl
- Upload date:
- Size: 27.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
841de6d5e2a02c29b33f89e485290e9e284a6eb5999b5ed0b0c22c9676efd9fe
|
|
| MD5 |
b62f16d3fad677c0830f790322d297fb
|
|
| BLAKE2b-256 |
e24ae0efa81c72ef53d955a7a9f59c3970fa21c7b76208075daf35c29b56571a
|
Provenance
The following attestation bundles were made for skaldr-0.3.1-py3-none-any.whl:
Publisher:
publish.yml on alex-yanchenko/skaldr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
skaldr-0.3.1-py3-none-any.whl -
Subject digest:
841de6d5e2a02c29b33f89e485290e9e284a6eb5999b5ed0b0c22c9676efd9fe - Sigstore transparency entry: 2139276872
- Sigstore integration time:
-
Permalink:
alex-yanchenko/skaldr@9657f9ad9cc77a1a9d956a89ccdeff99a19d9899 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/alex-yanchenko
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9657f9ad9cc77a1a9d956a89ccdeff99a19d9899 -
Trigger Event:
release
-
Statement type: