# ISCC Theme A [Zensical](https://zensical.org/) theme that gives all ISCC documentation sites the same brand, the same page tools and the same privacy rules. { .iscc-lead } The `zensical-iscc` Python package has three parts: - The theme. - The `zensical-iscc` command. It builds a site and checks it. - Two agent skills. One sets up the theme in a project. The other writes the page for coding agents. This site uses the theme. Its [`zensical.toml`](https://github.com/iscc/zensical-iscc/blob/main/zensical.toml) is the reference configuration for all ISCC sites. [Get started](get-started.md){ .iscc-btn .iscc-btn--primary } [Repository](https://github.com/iscc/zensical-iscc){ .iscc-btn } ## Features
### Brand The ISCC fonts, colors and logos on the modern Zensical design. The header shows the project name next to the ISCC logo. [Design →](design.md)
### Shared tools A "Copy page" button, a "Projects" menu that links the ISCC sites, the iscc.ai chat and Plausible analytics. One table in `zensical.toml` sets them all. [Configuration →](configuration.md)
### Checks `zensical-iscc check` makes sure that a site uses the theme, loads nothing from third parties and has a page for coding agents. [Command line →](command-line.md)
## Where to go next | To | Read | | ------------------------------------------------ | ----------------------------------------- | | Put the documentation of a project on the theme | [Get started](get-started.md) | | Find a setting | [Configuration](configuration.md) | | Write pages: front matter, icons, images, agents | [Writing pages](writing.md) | | See all styled elements | [Components](components.md) | | Fix a `zensical-iscc check` finding | [Command line](command-line.md) | | Learn about the colors, type and header | [Design](design.md) | | Change the theme | [Development](development.md) | | Work on a site or on the theme as an agent | [For Coding Agents](for-coding-agents.md) | # Get started A site on the theme has three parts: - A `zensical.toml` file. - A `docs/` directory with the Markdown pages. - The `zensical-iscc` package in the docs dependencies of the project. You need Python 3.11 or newer. ## With a coding agent The repository is also a Claude Code plugin marketplace. Its plugin has two skills: | Skill | Does | | -------------------------------- | ----------------------------------------------------------------------------------------- | | `zensical-iscc:iscc-docs-theme` | Sets up, migrates, upgrades or checks the theme in a project, also from MkDocs Material | | `zensical-iscc:docs-for-agents` | Writes and updates the [For Coding Agents](writing.md#for-coding-agents) page of the site | Install the plugin: ``` /plugin marketplace add iscc/zensical-iscc /plugin install zensical-iscc@zensical-iscc ``` Then, in the project, tell the agent: "Put the docs on the ISCC theme". The skill examines the project. It asks you for the information that only you have, for example the tagline and whether the site uses the chat widget. When it is done, the site passes `zensical-iscc check --strict`. Other agents can follow the steps in [`skills/iscc-docs-theme/SKILL.md`](https://github.com/iscc/zensical-iscc/blob/main/skills/iscc-docs-theme/SKILL.md). ## By hand ### 1. Add the dependency Get the latest release tag: ```bash git ls-remote --tags --refs --sort=-v:refname https://github.com/iscc/zensical-iscc | head -1 ``` Add the theme to the dependency group of your docs tools: ```toml [dependency-groups] docs = ["zensical-iscc"] [tool.uv.sources] zensical-iscc = { git = "https://github.com/iscc/zensical-iscc", tag = "vX.Y.Z" } ``` The theme pins the Zensical version that it is tested with. Remove all direct requirements on `zensical`, `mkdocs` and `mkdocs-material`. Then run `uv lock` and `uv sync`. If you do not use uv, install the theme with pip: ```bash pip install "zensical-iscc @ git+https://github.com/iscc/zensical-iscc@vX.Y.Z" ``` ### 2. Configure the site 1. Copy [`zensical.toml`](https://github.com/iscc/zensical-iscc/blob/main/zensical.toml) from the theme repository. 1. Replace each value that has the comment `# site`. 1. Add the `nav`, the Markdown extensions and the plugins of your project. [Configuration](configuration.md) explains each setting. Read its [TOML traps](configuration.md#toml-traps) first. ### 3. Write the pages Give each page a navigation icon in its front matter. Put the "For Coding Agents" page last in the navigation. [Writing pages](writing.md) has all conventions. [Components](components.md) shows the elements that the theme styles. ### 4. Build, check and preview | Task | Command | | ------- | --------------------------------------------------------------------------- | | Build | `uv run zensical-iscc build` | | Check | `uv run zensical-iscc check --strict` | | Preview | `python -m http.server --directory site` after a build | | Draft | `uv run zensical serve --dev-addr 127.0.0.1:` for live reload | `zensical serve` does not run the build steps of the theme. Its preview has no project logo, no "Copy page" content and no `llms.txt`. To see the real site, serve the built `site/` directory. ### 5. Deploy 1. Copy [`docs-workflow.yml`](https://github.com/iscc/zensical-iscc/blob/main/skills/iscc-docs-theme/docs-workflow.yml) to `.github/workflows/docs.yml`. The workflow builds and checks the site for each pull request. It deploys `main` to GitHub Pages. 1. For a custom domain, put the domain in `docs/CNAME`. 1. Add the host name of the site at stats.iscc.codes. Plausible does not count visits to a host that is not registered. ## Upgrade 1. Change the `tag` in `[tool.uv.sources]`. 1. Run `uv lock --upgrade-package zensical-iscc`. 1. Build and check the site. The [changelog](changelog.md) tells what changed in each release and which Zensical version the release pins. # Configuration A site sets up the theme in `zensical.toml`. The [`zensical.toml`](https://github.com/iscc/zensical-iscc/blob/main/zensical.toml) of the theme repository builds this site. It is also the full reference: - Values with the comment `# site` are different for each site. - All other values are the shared ISCC setup. ## TOML traps - Put `nav = [...]` directly below `[project]`, before all subtables such as `[project.extra.iscc]`. In TOML, a key after a table header goes into that table. - Write related projects with double brackets: `[[project.extra.iscc.related]]`. Single brackets make one table, not a list. `zensical-iscc check` reports this error. ## Site settings | Setting | Rule | | ----------------------------- | ---------------------------------------------------------------------------------------- | | `site_name` | The name of the project. It is the first part of the home page title and link previews | | `site_description` | One sentence. Pages without a description of their own use it | | `site_url` | The published URL, with a trailing slash. Link previews, canonical URLs and analytics need it | | `repo_url`, `repo_name` | The GitHub repository. `repo_name` also gives the name in the project logo | | `edit_uri` | `"edit/main//"`. The Zensical default points to a `master` branch | | `copyright` | Plain text with the years, such as `"Copyright © 2026 The Authors"`. The theme adds the ISCC links | | `nav` | All pages. The last entry is `{ "For Coding Agents" = "for-coding-agents.md" }` | ## `[project.extra.iscc]` The theme reads these options: | Option | Default | Use | | ----------- | ----------------------------------- | ---------------------------------------------------------------------- | | `tagline` | International Standard Content Code | The second part of the home page title: "ISCC Theme - Zensical theme for ISCC documentation" | | `copy_page` | `true` | Shows the "Copy page" button. Its content needs `zensical-iscc build` | | `chat` | `false` | Shows the iscc.ai chat widget. Set it only for domains that iscc.ai serves | | `og_image` | `assets/iscc/social-share.png` | The path of the link preview image, relative to the site root | | `project` | `repo_name` without `iscc-` | The name in the project logo of the header | | `related` | none | The entries of the "Projects" menu, as `[[project.extra.iscc.related]]` tables | ```toml [project.extra.iscc] tagline = "Zensical theme for ISCC documentation" copy_page = true chat = false project = "theme" ``` The chat widget starts only on domains that the iscc.ai token endpoint allows. It does not work on localhost. ## Project logo The header starts with the ISCC project logo: the ISCC logo, a thin vertical line and the project name with a coral period. On this site, it reads "ISCC | theme.". - The name comes from `project`. If `project` is not set, the theme uses `repo_name` without the owner and without the prefix `iscc-`. For example, `iscc/iscc-monitor` gives `monitor`. - Set `project` if this rule gives the wrong name. This site sets it, because `iscc/zensical-iscc` gives `zensical-iscc`, which is not a valid name. - A valid name has lowercase words with hyphens between them. It does not contain `iscc`. - `zensical-iscc build` writes the project logo to `assets/iscc/project-logo.svg`. - The header shows the plain ISCC logo and the site name instead of the project logo: - under `zensical serve` - on screens narrower than 720px - on sites without a project name ## Related projects menu ISCC has many sites that work together, for example the specification, the hub, search, the web generator and the monitor. Readers go from one site to the next, so each site lists its related sites in the "Projects" menu of the header: - the sites that it connects to - the specification at iscc.codes - the site itself ```toml [[project.extra.iscc.related]] name = "ISCC Monitor" # this site; marked as the current one link = "https://monitor.iscc.codes/" description = "Verifies and mirrors the transparency logs of ISCC hubs" [[project.extra.iscc.related]] name = "ISCC Specification" link = "https://iscc.codes/" description = "The International Standard Content Code, ISO 24138" ``` - Each table adds one menu entry, in the order of the file. An entry has a `name`, an https `link` and a one-line `description`. - Write the description for the readers of this site. Tell them what the other site does for them, in less than 60 characters. - The entry that links to the `site_url` of the site gets the coral marker for the current site. When all sites of a group list themselves, the menu is the same on each site and readers see where they are. - A site without entries has no menu. - The menu opens on hover, focus or tap, without JavaScript. ## Analytics All ISCC sites count visits with Plausible at stats.iscc.codes, under the host name of `site_url`. Register that host name at stats.iscc.codes. A site without `site_url` has no analytics. You need the `[project.extra.analytics]` table only to change the defaults: ```toml [project.extra.analytics] domain = "iscc.codes" # default: the host name of site_url src = "https://stats.iscc.codes/js/plausible.js" # default ``` ## `[project.theme]` ```toml [project.theme] name = "zensical_iscc" # custom_dir = "docs/overrides" # templates for this site only, on top of the theme # features = [...] # replaces the default features of the theme ``` | Setting | Rule | | ------------------------------------ | ------------------------------------------------------------------------------- | | `name` | `"zensical_iscc"` | | `font`, `logo`, `favicon`, `palette` | Do not set. The theme supplies the fonts and the ISCC logos and colors | | `features` | Do not set, to get the theme defaults. Never add `navigation.instant` | | `custom_dir` | Only for templates of this site. Never put a copy of the theme or a `main.html` there | The default features are `content.code.annotate`, `content.code.copy`, `content.tooltips`, `navigation.expand`, `navigation.footer`, `navigation.indexes`, `navigation.sections`, `navigation.top`, `navigation.tracking`, `search.highlight` and `toc.follow`. A `features` list replaces all of them. Copy the defaults that the site needs into the list. A page template in `custom_dir` can extend the theme with `{% extends "main.html" %}`. Do not put a `main.html` in `custom_dir`. It replaces the `main.html` of the theme and removes its styles, metadata and widgets. ## Markdown extensions A list of Markdown extensions replaces the Zensical default set, so the list must be complete. Start from the list in the reference configuration: `abbr`, `admonition`, `attr_list`, `def_list`, `footnotes`, `md_in_html`, `toc` with permalinks, and the pymdownx extensions `details`, `highlight`, `superfences` and `tabbed`. Add the extensions of your project to it. # Writing pages Pages are Markdown files in `docs/`. Use these conventions, so that all ISCC sites work the same for readers and for agents. ## Front matter | Key | Use | | ------------- | ------------------------------------------------------------------------------------------ | | `icon` | The navigation icon, `lucide/`. Each page must have one | | `description` | One sentence for link previews and the `llms.txt` index. Without it, the page uses `site_description` | | `title` | The page title in the browser and in link previews, if it is different from the navigation label | | `location` | Makes the page a redirect to another URL. Use it for pages that moved | ```markdown --- icon: lucide/rocket description: Set up the theme for the documentation of an ISCC project --- ``` ## Navigation icons Each page shows an icon before its entry in the navigation. Select a name from the [Lucide](https://lucide.dev/icons/) set. Zensical puts the icon into the page as SVG, so the icon adds no request. Section labels in `nav` have no icon. Only pages have icons. ## For Coding Agents The last page in the navigation of each ISCC site is "For Coding Agents". It is a short reference for AI agents that work on the project or use it. It contains an architecture map, decision tables, constraints, side effects, task recipes, change playbooks and common mistakes. It uses tables and code, not long text. | Convention | Value | | ----------- | -------------------------------------------------------- | | File | `docs/for-coding-agents.md` | | Nav entry | `{ "For Coding Agents" = "for-coding-agents.md" }`, last | | Icon | `lucide/bot` | - Write the page with the `zensical-iscc:docs-for-agents` skill: `/zensical-iscc:docs-for-agents create`. - Run the skill with `update` each time the public API, the command line or the configuration changes. Agents follow this page closely. If it is out of date, they make errors. - Add this line to the `CLAUDE.md` or `AGENTS.md` of the project, so that coding sessions keep the page up to date: "After changing the public API, CLI or configuration, run the docs-for-agents skill with `update`." - `zensical-iscc check` gives a warning if the page is missing or not in `nav`. With `--strict`, as in CI, the warning makes the build fail. - `llms.txt` lists the page first, so agents that read the index start there. The [For Coding Agents](for-coding-agents.md) page of this site is an example. ## Markdown for agents and people `zensical-iscc build` writes the Markdown source of each page next to its HTML, without the front matter: | File | Contents | | --------------------- | --------------------------------------------------------------------------- | | `/index.md` | One page. "Copy page" and "View as Markdown" read it | | `llms-full.txt` | All pages, in navigation order | | `llms.txt` | An index in the [llmstxt.org](https://llmstxt.org/) format: the agent page first, then all pages with their descriptions | The head of each page links to its Markdown copy with ``, so an agent that gets the HTML can also find the source. ## Page components The theme styles a lead paragraph, buttons for calls to action, audience cards and ISCC-UNIT labels. [Components](components.md) shows each of them with its markup. Cards need the `md_in_html` extension. ## Images, badges and media Pages load nothing from other domains, except Plausible and, if chat is on, iscc.ai. - Keep images and badges in `docs/`. Do not link to images on other sites. Download shields.io badges one time and link to the copies. - To show an image in a lightbox, put it in ``. The theme loads its own copy of GLightbox, and only on pages with a lightbox. - Do not use Mermaid diagrams. The Zensical bundle loads Mermaid from unpkg.com, and `zensical-iscc check` rejects pages with a Mermaid diagram. Use an SVG file. [Command line](command-line.md#third-party-requests) lists the requests that the check cannot see. # Components The theme styles each element on this page. After a change to the theme or to Zensical, look at this page in both color schemes. The theme also styles these ISCC components. Do not style them again in the stylesheets of a site. | Class | Use | | --------------------------------------------------------------------- | ---------------------------------------------------------------------------- | | `.iscc-lead` | The first paragraph of a page, in a larger size. Add `{ .iscc-lead }` on the line after it | | `.iscc-btn`, `.iscc-btn--primary` | Call-to-action buttons on links, with space between them in a row: `[Start](start.md){ .iscc-btn .iscc-btn--primary }` | | `.iscc-cards`, `.iscc-card` | Audience cards, three in a row on wide screens. Each card has an `h3`, text and a last paragraph with one link | | `.iscc-unit--meta`, `--semantic`, `--content`, `--data`, `--instance` | ISCC-UNIT labels in the colors of their units | Cards need the `md_in_html` extension and blank lines around each block: ```html
### Developers Generate ISCC codes from your own code. [Get started →](start.md)
``` ## Lead paragraph The first paragraph of a page, in a larger size. Add `{ .iscc-lead }` on the line after the paragraph. { .iscc-lead } ## Calls to action [Primary action](index.md){ .iscc-btn .iscc-btn--primary } [Second action](index.md){ .iscc-btn } ## Cards
### Developers Generate ISCC codes from your own code with the libraries. [Get started →](index.md)
### Registries Declare content and make it discoverable on the network. [Declare →](index.md)
### Operators Run a service for mainnet or testnet. [Deploy →](index.md)
## Text Body copy with **strong**, *emphasis*, `inline code`, a [link](index.md) and an abbreviation: ISCC. *[ISCC]: International Standard Content Code > A block quote with a single sentence. Content-Code : A definition list entry, here for an ISCC-UNIT. Footnotes render at the end of the page.[^1] [^1]: The footnote text. ## ISCC-UNIT labels Meta-Code, Semantic-Code, Content-Code, Data-Code and Instance-Code. ## Admonitions !!! note Note and info are Sky Blue. !!! tip Tip and success are Lime. !!! warning Warning is Yellow. !!! danger Danger is Coral. ??? info "Collapsible" Details collapse with `???`. ## Code ```python import iscc_core as ic code = ic.gen_meta_code("Title", "Description") print(code["iscc"]) ``` === "Python" ```python print("tabbed code") ``` === "Shell" ```bash echo "tabbed code" ``` ## Tables | Unit | Header | Bits | | -------- | --------- | ---- | | Meta | `0000...` | 64 | | Content | `0010...` | 64 | | Instance | `0100...` | 64 | ## Buttons [Primary](index.md){ .md-button .md-button--primary } [Secondary](index.md){ .md-button } # Command line The `zensical-iscc` command comes with the theme package. Each subcommand reads `zensical.toml` in the working directory. To use a different file, add `--config-file` (`-f`). | Command | Does | | ------------------------------- | ------------------------------------------------------------------------------------ | | `zensical-iscc build` | Runs `zensical build --clean`, then writes the Markdown copies, `llms.txt` and the project logo | | `zensical-iscc markdown` | Writes the Markdown copies and `llms.txt` into a site that is already built | | `zensical-iscc check` | Checks the configuration and the built site. Exits with 1 on errors | | `zensical-iscc check --strict` | Also exits with 1 on warnings. Use this mode in CI | Zensical has no plugins for steps after the build, so use `zensical-iscc build` instead of `zensical build`. ## What the build writes | Output | From | Read by | | ------------------------------ | ---------------------------------------------------------- | --------------------------------------- | | `site/**/index.html` | Zensical | Browsers | | `site//index.md` | The Markdown of each page, without front matter | "Copy page", "View as Markdown", agents | | `site/llms-full.txt` | All pages, in navigation order | Language models that read a full site | | `site/llms.txt` | The title, link and description of each page, agent page first | Agents that look for a start page | | `site/assets/iscc/project-logo.svg` | The project name and the ISCC project logo construction rules | The header | ## Findings The check reads `zensical.toml` and the docs directory. Then it examines each HTML page and stylesheet of the built site. It cannot see the requests that the Zensical bundle makes in the browser. [Third-party requests](#third-party-requests) lists them. ### Errors | Finding | Fix | | ---------------------------------------------------------- | -------------------------------------------------------------------- | | `set name = "zensical_iscc" in [project.theme]` | Set the theme | | `remove font from [project.theme]` | Remove it. The theme supplies its fonts | | `remove the navigation.instant feature` | Remove it. It makes lightbox pages load GLightbox from unpkg.com | | `custom_dir … holds a copy of the ISCC theme` | Delete the copy. Add the package as a dependency | | `main.html replaces the theme's main.html` | Delete it. Page templates can extend `main.html` | | `project … use lowercase words and hyphens, without iscc-` | Correct `project` in `[project.extra.iscc]` | | `related project … lacks …` or `… use an https:// URL` | Add the missing field. Use an https link | | `write related projects as [[project.extra.iscc.related]] tables` | Use double brackets | | `extra_css / extra_javascript loads …` | Put a copy in the docs directory | | ` loads ` | Put the image, script or stylesheet in `docs/` | | ` has a Mermaid diagram` | Replace the diagram with an SVG file | | `Markdown pages are missing from the site` | Build with `zensical-iscc build`, not with `zensical build` | | `the project logo is missing from the site` | Build with `zensical-iscc build` | ### Warnings | Finding | Fix | | ---------------------------------------------------------- | -------------------------------------------------------------------- | | `[project.theme] sets logo / favicon / palette` | Remove it, unless the site needs a different logo | | `set site_url` | Link previews, canonical URLs and analytics need it | | `set edit_uri` | The Zensical default edit links point to a `master` branch | | `set tagline in [project.extra.iscc]` | It is the second part of the home page title | | `set project in [project.extra.iscc] or repo_name` | Without a name, the header has no project logo | | `set copyright to plain text` | The footer already links the ISCC Foundation, privacy policy, imprint and license | | `add docs/for-coding-agents.md` | Write it with the `docs-for-agents` skill. See [Writing pages](writing.md#for-coding-agents) | | `list for-coding-agents.md in nav` | Add `{ "For Coding Agents" = "for-coding-agents.md" }` as the last entry | | `[project.extra.analytics] replaces Plausible` | All ISCC sites use Plausible | | `analytics domain … differs from the site_url host` | Remove `domain`, unless the site must count visits under a different host | | `the site is not built` | Build the site. Until then, the check examines only the configuration | ## Third-party requests Pages request nothing from third parties, except Plausible analytics and, if chat is on, iscc.ai. The theme supplies the fonts and GLightbox. Without the theme copy, the Zensical bundle loads GLightbox from unpkg.com, and privacy tools such as Privacy Badger flag unpkg.com as a tracker. The check cannot see these requests: - For a page with a Mermaid diagram, the bundle loads Mermaid from unpkg.com, so the check rejects these pages. To allow them, the theme must supply its own copy of Mermaid, as it does for GLightbox. - The bundle loads GLightbox on each page that has lightbox links in its content. With `navigation.instant`, the bundle can open a lightbox page without a full page load. Then it loads GLightbox from unpkg.com, so the check rejects this feature. - The chat widget loads the fonts that iscc.ai declares in its `public/theme.json`. - If `repo_url` is set, the bundle gets the stars, forks and latest release of the repository from `api.github.com`. ISCC sites are on GitHub Pages, so GitHub is not a third party for them. This request stays. # Design The theme applies the ISCC brand to the modern Material design of Zensical. The colors, fonts and logos come from the ISCC brand assets. ## Schemes | Scheme | Canvas | Text | Fields and code | Links | | ------ | ---------- | ---------- | ------------------------------ | -------- | | Light | Paper | Near-black | White, with thin rules | Blue | | Dark | Near-black | Paper | Graphite, with thin rules | Sky Blue | Readers change the scheme with the sun and moon button. On the first visit, the site uses the scheme of the operating system. ## Header The header is the same in both schemes: Deep Navy with a grain texture, 72px high, with controls in 78% white. - The header starts with the project logo in white and coral, at a symbol height of 24px. - The page title, which replaces the site name when the page scrolls, sits on the baseline of the logo letters. - The header content aligns with the columns below. The logo starts at the coral marker of the navigation. The search field ends at the right edge of the content column. The repository icon is above the text of the table of contents. - Without a project logo, the header shows the plain ISCC logo and the site name in spaced Light capitals. On phones, it shows only the logo. ## Footer The footer bar is one row, Deep Navy with a grain texture like the header, and 52px high. Its ends align with the ends of the header. - On the left: the white ISCC logo, the `copyright` text of the site and "Made with Zensical". - On the right: the links that all ISCC sites share (ISCC Foundation, Privacy Policy, Imprint, CC BY 4.0), then the social links of the site from `[[project.extra.social]]` and the LinkedIn and X pages of the ISCC Foundation. - Links and icons are 78% white. On hover and focus, they are white. - On narrow screens, the row wraps. ## Color roles - Blue is the link color. - Coral marks the chevron of the primary button, the current page in the navigation, the current site in the "Projects" menu, selected text and the circle in the logo. - Text is never on a coral background. The only exception is the iscc.ai chat button. - Each admonition type has a color: note and info are Sky Blue, tip and success are Lime, warning is Yellow, danger is Coral. In the dark scheme, admonitions have a colored left line and title, not a colored background. - An ISCC-UNIT label always shows the unit name with its color. ## Type - Body text is Readex Pro Light at 16px on all screen widths. - The lead paragraph has the same weight and a larger size, 1.2em. - Lines of running text stop at about 75 characters. Tables, code and cards use the full width of the column. - Table headers, section labels and the previous and next labels in the footer use small JetBrains Mono capitals. ## Buttons The buttons follow the ISCC button design: JetBrains Mono capitals, 46px high. - **Primary:** a near-black block with a pointed end, a white label and a coral chevron. The chevron moves on hover. In the dark scheme, the block is white with a near-black label. - **Secondary:** an outline of 1.5px in the text color. [Components](components.md#calls-to-action) shows both. ## Motion Transitions take 160 ms, with ease-out. They are off when the reader sets `prefers-reduced-motion`. # Development The theme is in [iscc/zensical-iscc](https://github.com/iscc/zensical-iscc). This site comes from the same repository, so each theme change shows here first. ## Commands ```bash uv sync # install the dev dependencies uv run prek install # install the git hooks, one time for each clone uv run poe all # format, type check, test uv run poe ci # run all gates without changes to files, with the check of this site uv run poe docs # build this site and serve it on 127.0.0.1:45472 ``` The tests build copies of this site with Zensical. They need 100% branch coverage. After each change to the theme or to the Zensical version, look at this site in both color schemes. ## Layout | Path | Contents | | -------------------------------------------------------- | -------------------------------------------------------------------------------- | | `zensical_iscc/theme/mkdocs_theme.yml` | Theme defaults: fonts off, favicon, features, palette | | `zensical_iscc/theme/main.html` | Brand stylesheets, social metadata, Markdown link, redirects, widget settings | | `zensical_iscc/theme/partials/logo.html` | The project logo and the ISCC logo in both color versions | | `zensical_iscc/theme/partials/header.html` | The Zensical header plus the "Projects" menu. A test compares it with the Zensical header | | `zensical_iscc/theme/partials/projects.html` | The "Projects" menu, from `[[project.extra.iscc.related]]` | | `zensical_iscc/theme/partials/copyright.html` | The footer content: ISCC logo, `copyright` text, shared ISCC links, social links | | `zensical_iscc/theme/partials/social.html` | Empty. `copyright.html` shows the social links, also without `extra.social` | | `zensical_iscc/theme/partials/integrations/analytics*` | Plausible as the default analytics provider | | `zensical_iscc/theme/assets/iscc/theme.css` | Maps the tokens to the Zensical variables and styles the components | | `zensical_iscc/theme/assets/iscc/tokens/`, `fonts/`, `logos/` | Copies of the ISCC brand assets: tokens, Readex Pro and JetBrains Mono, logos | | `zensical_iscc/theme/assets/iscc/vendor/glightbox/` | GLightbox 3.3.1, not changed | | `zensical_iscc/theme/assets/iscc/copypage.js` | "Copy page", "View as Markdown", "Edit on GitHub" | | `zensical_iscc/theme/assets/iscc/copilot.js`, `copilot.css` | The loader and styles of the iscc.ai chat widget | | `zensical_iscc/cli.py`, `markdown.py`, `check.py`, `project.py` | The `zensical-iscc` command | | `zensical_iscc/project_logo.py` | Draws the project logo | | `zensical.toml`, `docs/` | This site and the reference configuration | | `CHANGELOG.md` | Release notes. A git hook copies them to `docs/changelog.md` | | `skills/iscc-docs-theme/` | The setup skill and the docs workflow template for sites | | `skills/docs-for-agents/` | The skill for the "For Coding Agents" page | | `.claude-plugin/marketplace.json` | The plugin marketplace. Its one entry points to `skills/` | | `skills/.claude-plugin/` | The plugin manifest and its icon. The plugin version is the package version | | `tests/fixtures/project-logos/` | Reference project logos. `project_logo.py` must make the same files, byte for byte | Zensical copies all files of the theme directory that are not templates into the built site, so `theme/` contains no Python code. The `mkdocs.themes` entry point names an object whose `__file__` is in `theme/`. ## Copied files Some files are copies. Update them from their source. Do not edit them here. | Files | Source | | --------------------------------------------- | ------------------------------------------------------------------------- | | Tokens, fonts, logos, favicons, `grain.png`, the app tile, the plugin icon | ISCC sources that are not public | | `tests/fixtures/project-logos/` | The ISCC brand assets. Port changes of the project logo construction to `project_logo.py` | | `skills/docs-for-agents/SKILL.md` | `plugins/docs-for-agents/` in [titusz/skills](https://github.com/titusz/skills) | | `docs/changelog.md` | `CHANGELOG.md`, written by the `changelog` git hook | ## Upgrade Zensical `pyproject.toml` pins one Zensical version, because the theme overrides Zensical templates. To upgrade: 1. Change the pin. 1. Build this site. Compare both color schemes with the previous version in a browser. 1. Run the tests. 1. Release. A test compares `partials/header.html` with the Zensical header. If Zensical changes its header, the test fails. ## Release 1. In `CHANGELOG.md`, change "Unreleased" to the version and the date. Commit the copy that the hook writes. 1. Set `version` in `pyproject.toml` and in `skills/.claude-plugin/plugin.json`. A test makes sure that both versions are equal. Users get skill changes only when the plugin version changes, which is at each release. 1. Merge to `main`. 1. Tag and publish the release. In the release notes, give the Zensical version that the release pins: ```bash git tag vX.Y.Z && git push origin vX.Y.Z gh release create vX.Y.Z --title vX.Y.Z --notes "..." ``` Sites change to the release with the `tag` in their `[tool.uv.sources]`. This site deploys from `main` to GitHub Pages on each push that changes it. ## License The code, templates and stylesheets are licensed under the Apache License 2.0. The bundled fonts are licensed under the SIL Open Font License and GLightbox under the MIT License. The ISCC logos and symbols are brand assets of the ISCC Foundation for use on ISCC sites. # Changelog To upgrade a site, change the `tag` in its `[tool.uv.sources]` and run `uv lock --upgrade-package zensical-iscc`. ## 0.3.0 - 2026-11-08 Pins **Zensical 0.1.0**. - **Project logo.** The header shows the ISCC project logo, for example "ISCC | monitor.". `zensical-iscc build` draws it from `project` in `[project.extra.iscc]`, or from `repo_name` without `iscc-`. - **Header and footer.** Both are Deep Navy with grain and align with the page columns. A "Projects" menu links the related ISCC sites in `[[project.extra.iscc.related]]`. The footer shows the ISCC links and the social links of the site and of the ISCC Foundation. - **For Coding Agents.** Each site ends its navigation with `for-coding-agents.md`. The `docs-for-agents` skill of the plugin writes it. The build writes an `llms.txt` index with this page first. - **Type.** Body text is Readex Pro Light at 16px. Pages set a navigation icon with `icon: lucide/`. - The theme documentation is at . Upgrade: `zensical-iscc check --strict` fails until the site has a For Coding Agents page and a plain-text `copyright`. ## 0.2.0 - 2026-10-09 Pins **Zensical 0.0.69**. - **Plausible analytics by default.** Each site counts visits under the host name of its `site_url`. `[project.extra.analytics] domain` sets a different host. Register new hosts at stats.iscc.codes. - **Page components:** lead paragraph (`.iscc-lead`), calls to action (`.iscc-btn`, `.iscc-btn--primary`) and audience cards (`.iscc-cards`, `.iscc-card`). Remove these rules from site stylesheets. - `zensical-iscc check` does not ask for an analytics table anymore. It reports a different analytics provider and a domain that is not the `site_url` host. ## 0.1.0 - 2026-10-09 First release of the ISCC theme for Zensical as a package. Pins **Zensical 0.0.69**. - The theme files are the same as the copy that ISCC sites used before. - `zensical-iscc build` builds a site and writes the Markdown copies of its pages and `llms-full.txt`. - `zensical-iscc check` reports errors in the theme configuration and resources from other domains. - The agent skill `iscc-docs-theme` sets up the theme in ISCC projects. # For Coding Agents Prescriptive reference for agents. Two audiences: agents that **build a site** on the theme (sections marked *site*) and agents that **change the theme** in `iscc/zensical-iscc` (marked *theme*). Everything else applies to both. Full Markdown of this site: [`llms-full.txt`](https://theme.iscc.codes/llms-full.txt). ## Architecture map ### Package layout (*theme*) | Path | Contains | | -------------------------------------------- | ------------------------------------------------------------------------------------------ | | `zensical_iscc/__init__.py` | `THEME_DIR`; `THEME`, a `SimpleNamespace` whose `__file__` lies in `theme/` | | `zensical_iscc/cli.py` | `main(argv)`, `run_build`, `run_markdown`, `run_project_logo`, `run_check` | | `zensical_iscc/project.py` | `load_project`, `docs_dir`, `site_dir`, `custom_dir`, `resolve_dir` | | `zensical_iscc/markdown.py` | Markdown copies, `llms-full.txt`, `llms.txt`; `AGENT_PAGE`, `agent_page`, `flatten_nav` | | `zensical_iscc/check.py` | `check(config_path)` and one `*_findings` function per rule | | `zensical_iscc/project_logo.py` | `compose`, `write`, `project_name`, `is_valid`; port of the ISCC project logo construction | | `zensical_iscc/theme/` | The theme directory Zensical loads; templates, partials, `assets/iscc/`; no Python | | `zensical.toml`, `docs/` | theme.iscc.codes and the reference configuration for sites | | `skills/iscc-docs-theme/SKILL.md` | Setup, migration and upgrade procedure for sites; `docs-workflow.yml` template | | `skills/docs-for-agents/SKILL.md` | Vendored copy from `titusz/skills`; writes this kind of page | | `skills/.claude-plugin/plugin.json` | Plugin manifest; plugin root is `skills/`, `version` equals the package version | | `scripts/sync_changelog.py` | Git hook: `CHANGELOG.md` → `docs/changelog.md` with front matter | | `tests/` | pytest; `docs_config` fixture copies `zensical.toml` + `docs/` and builds for real | ### Import flow ``` cli → check → markdown, project, project_logo cli → markdown, project, project_logo project_logo → zensical_iscc.THEME_DIR, fontTools ``` ### Public surface | Surface | Name | Consumers | | --------------------------- | -------------------------------------------------------- | ------------------------------- | | Console script | `zensical-iscc` → `zensical_iscc.cli:main` | Sites, CI | | Theme entry point | `mkdocs.themes: zensical_iscc = zensical_iscc:THEME` | Zensical, `name = "zensical_iscc"` | | Config table | `[project.extra.iscc]`, `[project.extra.analytics]` | `main.html`, partials, `check` | | CSS classes | `.iscc-lead`, `.iscc-btn`, `.iscc-btn--primary`, `.iscc-cards`, `.iscc-card`, `.iscc-unit--*` | Site pages | | Plugin marketplace | `zensical-iscc@zensical-iscc`: `iscc-docs-theme`, `docs-for-agents` | Claude Code | ## Decision dispatch ### Which command (*site*) | Goal | Command | | -------------------------------------------- | ----------------------------------------- | | Build for deployment or real preview | `zensical-iscc build` | | Live-reload drafting (no project logo, no `.md`) | `zensical serve --dev-addr 127.0.0.1:` | | Add Markdown copies to an existing build | `zensical-iscc markdown` | | Gate CI | `zensical-iscc check --strict` | | Config elsewhere | add `-f path/to/zensical.toml` | ### Which setting (*site*) | Need | Setting | | ------------------------------------ | --------------------------------------------------------------- | | Home page title suffix | `[project.extra.iscc] tagline` | | Project logo name differs from `repo_name` minus `iscc-` | `[project.extra.iscc] project` | | Header "Projects" menu | `[[project.extra.iscc.related]]` with `name`, `link`, `description` | | Hide "Copy page" | `copy_page = false` | | Chat widget | `chat = true`, only after iscc.ai serves the domain | | Link preview image | `og_image = "assets/..."` | | Count analytics under another host | `[project.extra.analytics] domain` | | Site-specific template | `[project.theme] custom_dir`, file extends `main.html` | ### Where a theme change goes (*theme*) | Change | File | | ---------------------------------------- | ------------------------------------------------------------ | | Colours, spacing, component styles | `theme/assets/iscc/theme.css` (map tokens; never edit `tokens/`) | | Head metadata, page-level widgets | `theme/main.html` | | Header markup | `theme/partials/header.html` (Zensical copy + one include) | | Footer content, shared ISCC links, social links | `theme/partials/copyright.html` | | Default features, palette | `theme/mkdocs_theme.yml` | | New configuration rule | `check.py` new `*_findings` + call in `check()` | | New build output | `cli.run_build` chain + `check` presence finding | ## Constraints and invariants | Constraint | Why | | -------------------------------------------------------------------------- | ----------------------------------------------------------- | | No Python file under `zensical_iscc/theme/` | Zensical copies every non-template file into the site | | One pinned Zensical version in `pyproject.toml` | Templates override Zensical's | | Pages load nothing from other origins except `stats.iscc.codes`, `iscc.ai` | Privacy promise; `check.ALLOWED_HOSTS` | | Project name matches `[a-z0-9]+(-[a-z0-9]+)*`, does not start with `iscc` | `project_logo.is_valid`; invalid explicit `project` is an error | | `project_logo.compose` output equals `tests/fixtures/project-logos/*.svg` | Byte fidelity with the reference SVGs; keep arithmetic order | | Coordinates formatted by `project_logo.fmt`, two decimals | Fidelity | | `nav` is directly under `[project]`, before any subtable | TOML scopes keys into the last table header | | Listing Markdown extensions replaces Zensical's defaults | The list must be complete | | `for-coding-agents.md` exists and is in `nav`, last | `check.agent_page_findings` warns; fails under `--strict` | | Directory URLs: page `a/b.md` → `site/a/b/index.md` | `markdown.output_path`; the `` relies on it | | `theme.css` overrides match Zensical's selector specificity | Lower specificity loses silently (see mistakes) | | Content width capped at 1385px; root font size held at 125% | Layout and type scale | | Templates run on MiniJinja | Attribute access on undefined raises; guard with `or {}` | ## Side effects catalog | Call | Writes | Exit / return | | --------------------------------- | ------------------------------------------------------------------------------- | --------------------------- | | `cli.run_build` | Zensical build (clean), then everything below | First non-zero step code | | `cli.run_markdown` | `site/**/index.md`, `site/llms-full.txt`, `site/llms.txt` | 1 if `site/` is missing | | `cli.run_project_logo` | `site/assets/iscc/project-logo.svg` (white-coral, 1 h = 24px) | 1 for an invalid name; 0 and a note without a name | | `cli.run_check` | Nothing; prints findings and a count | 1 on errors, or on warnings with `--strict` | | `markdown.write_pages` | One `index.md` per page, front matter stripped; both llms files | None | | `project_logo.write` | Creates `assets/iscc/` if needed | Path written | | `scripts/sync_changelog.py` | `docs/changelog.md` | 1 when it changed the file | | `project_logo.signature_geometry`, `face` | Cached (`functools.cache`) per process | - | ## Task recipes ### Put a site on the theme (*site*) 1. Follow `skills/iscc-docs-theme/SKILL.md`; it covers survey, questions for the human, dependency, config, cleanup, CI and verification. 1. Dependency: `docs = ["zensical-iscc"]` and `zensical-iscc = { git = "https://github.com/iscc/zensical-iscc", tag = "vX.Y.Z" }` in `[tool.uv.sources]`. 1. Copy this repository's `zensical.toml`; replace values marked `# site`. 1. Every page: `icon: lucide/` and `description:` in front matter. 1. Write `docs/for-coding-agents.md` with `/zensical-iscc:docs-for-agents create`; add `{ "For Coding Agents" = "for-coding-agents.md" }` as the last `nav` entry. 1. `uv run zensical-iscc build && uv run zensical-iscc check --strict` → `0 errors, 0 warnings`. ### Add a check (*theme*) ```python def thing_findings(config): # type: (dict) -> list[tuple[str, str]] """Check ...""" if problem: return [warning("set `x` in [project.extra.iscc]: why it matters")] return [] ``` Then call it in `check.check()`, add tests in `tests/test_check.py`, list the finding in `docs/command-line.md`, and the setting in `docs/configuration.md` and `skills/iscc-docs-theme/SKILL.md`. ### Upgrade Zensical (*theme*) 1. Bump `zensical==` in `pyproject.toml`; `uv lock`. 1. `uv run poe docs`; compare both schemes at phone, desktop and wide widths with the previous version. 1. `uv run poe ci`; `test_header_is_zensicals_plus_the_projects_menu` fails if Zensical's header changed. 1. Add a `CHANGELOG.md` entry naming the pinned version. ### Release (*theme*) Only when the human asks: rename "Unreleased" in `CHANGELOG.md`, set `version` in `pyproject.toml` and `skills/.claude-plugin/plugin.json` (`tests/test_plugin.py` keeps them equal), commit, then `git tag vX.Y.Z && git push origin vX.Y.Z` and `gh release create vX.Y.Z --notes "..."`. ## Change playbook | If you change | Also update | | ------------------------------------- | -------------------------------------------------------------------------------------- | | A skill or the plugin manifest | Users get it with the next release, when the plugin `version` changes | | A `[project.extra.iscc]` option | `main.html` comment, `docs/configuration.md`, `zensical.toml`, `SKILL.md`, tests | | A check finding | `docs/command-line.md` tables, `tests/test_check.py`, `SKILL.md` if it guides a fix | | A command or build output | `cli.py` docstring, `docs/command-line.md`, `markdown_findings`/presence checks | | `theme.css` or templates | Look at theme.iscc.codes in both schemes; `docs/design.md` if a design rule changes | | `project_logo.py` | Fixtures must still match; refresh them from the ISCC brand assets if the project logo design changed | | Brand assets | Copy from the ISCC brand assets; never edit | | `CHANGELOG.md` | Commit the `docs/changelog.md` the hook writes | | Agent page convention | `markdown.AGENT_PAGE`, `check.agent_page_findings`, `docs/writing.md`, `SKILL.md` | | Public API, CLI or configuration | This page: run `/zensical-iscc:docs-for-agents update` | ## Common mistakes NEVER build a deployable site with `zensical build`. ALWAYS use `zensical-iscc build`; otherwise "Copy page", `llms.txt` and the project logo are missing and `check` reports errors. --- NEVER set `font`, `logo`, `favicon` or `palette` in `[project.theme]`, and NEVER add `navigation.instant` to `features`. The theme serves its own fonts and marks; instant navigation makes lightbox pages fetch GLightbox from unpkg.com. --- NEVER put `main.html` or a copy of the theme in a site's `custom_dir`. ```html {% extends "base.html" %} {% extends "main.html" %} ``` --- NEVER hot-link images or badges (`https://img.shields.io/...`). ALWAYS store a copy under `docs/`. --- NEVER use fenced `mermaid` blocks. The bundle would load Mermaid from unpkg.com; `check` rejects the page. --- NEVER write `[project.extra.iscc.related]` with single brackets, and NEVER put `nav = [...]` after a table header. ```toml # WRONG [project.extra.iscc] nav = [{ "Home" = "index.md" }] # now project.extra.iscc.nav # RIGHT [project] nav = [{ "Home" = "index.md" }] ``` --- NEVER override a Zensical rule in `theme.css` with a less specific selector. ALWAYS match the original, including `:not()` arguments, which add their own weight. ```css /* WRONG: loses to Zensical's `html .md-footer-meta.md-typeset a:not(:focus, :hover)` */ .md-footer-meta a { color: var(--md-footer-fg-color); } /* RIGHT */ html .md-footer-meta.md-typeset a:not(:focus, :hover) { color: var(--md-footer-fg-color--light); } ``` --- NEVER read `page.meta.x` in a template without a guard. ALWAYS `{% set meta = page.meta or {} %}` first; MiniJinja raises on attribute access of an undefined value. `page.is_homepage` is unreliable: also test `page.url == ""`. --- NEVER edit `docs/changelog.md`, `tokens/`, `fonts/`, `logos/`, `vendor/` or `skills/docs-for-agents/SKILL.md` in this repository. They are copies; change the source. --- NEVER let this page drift. ALWAYS run `/zensical-iscc:docs-for-agents update` after changing the public API, the command line or the configuration.