# Docs URL: /docs --- # Accent CMS URL: / Accent CMS renders your markdown as a fast, clean website -- served live with hot reload while you write, or built to plain static files you can host anywhere. One binary, no database, no Node toolchain. --- # Spec-driven development with AI agents URL: /blog/spec-driven-development-with-ai-agents Date: 2026-08-01 Tags: ai-workflows, spec-driven-development The interesting problem with AI-assisted development is not getting code written. Models are good at that now. The problems are that an agent starts every session knowing nothing about the decisions you made last week, and that when it does not know something it will frequently produce a confident, well-formed, entirely wrong answer instead of stopping. Both problems have the same shape: there is no durable, checkable record of what is true about the project. ## Where this sits That diagnosis is no longer contrarian. Through 2026 it became the mainstream reaction to vibe coding, under the name **spec-driven development**. GitHub's [Spec Kit](https://github.com/github/spec-kit) is an open-source toolkit that runs an agent through four phases -- Specify, Plan, Tasks, Implement -- and its [announcement](https://github.blog/ai-and-ml/generative-ai/spec-driven-development-with-ai-get-started-with-a-new-open-source-toolkit/) puts the thesis plainly: "We're moving from 'code is the source of truth' to 'intent is the source of truth.'" AWS shipped [Kiro](https://kiro.dev/), an agentic IDE built on the same premise, where the spec is the source of truth and code is a build artifact. [Tessl](https://tessl.io/blog/tessl-launches-spec-driven-framework-and-registry/) ships a framework plus a registry of more than ten thousand pre-built library specs, explicitly aimed at stopping agents from hallucinating APIs. So the general idea is settled. What is still open is how *rigorous* the artifact has to be, and the honest answer in most write-ups is "a requirements document and some acceptance criteria." This post is about a project that goes considerably further, because the difference turns out to matter. ## The project `yqr` is a small Rust CLI we develop alongside Accent -- a jq-style query and edit tool for YAML, [open source](https://github.com/zoosky/yqr) and [on crates.io](https://crates.io/crates/yqr) at 0.5.0, so `cargo install yqr` works. It is not a large program. It carries **27 specification documents**, and those are not a side artifact: they are the issue tracker, the design record, and the standard the work is held to. The whole set is [published as part of the project's own website](https://zoosky.github.io/yqr/specs/), which is itself built with Accent. ## Five kinds of document, each with one job There is no issue tracker. No Jira, no scratch to-do files, no in-chat task lists. Every unit of work is a markdown file in one of five directories, each carrying a `Status:` field -- Draft, In Progress, Done, Resolved, Superseded, Historical. - **Research** asks a question and answers it with evidence. One evaluation of a candidate YAML library opens with a `Question` section and then a `Method` section beginning: "Three independent, cross-checked lines of evidence." - **Architecture** records a decision, what it forecloses, and what it explicitly is not. - **Features** run Problem, Prior art, Design, Acceptance criteria. - **Bugs** run Summary, Impact, Reproduction, Observed behavior, Root cause, Remediation options, Acceptance criteria. - **Implementation** holds cross-cutting conventions and is the declared source of truth for them. The separation matters more than the exact taxonomy. A research note that concludes nothing is fine; an architecture document that concludes nothing is a failure. Giving each kind of thinking its own container prevents the fuzzy document that is half investigation, half decision, and binding as neither. ## The part that does the real work: a falsifiable invariant The architecture document makes one product promise -- the tool never rewrites bytes it did not change, so comments, key order, quoting, and blank lines survive an edit. On its own that sentence would be worth very little. What makes it useful is the next section, which reduces the promise to a single property you can run: ``` yqr '.' input.yaml == cat input.yaml # byte-for-byte identical ``` and then the line that gives it teeth: > If `yqr .` does not reproduce its input byte-for-byte, the build is broken. That is the methodology in miniature. The prose promise is not the contract; the executable property is the contract, and the prose exists to explain it. Everything downstream inherits it. The bug that opened the work measured the tool against that property across a 14-file corpus and found **13 of 14 failed**. The features that followed existed to move that number. The `validate` subcommand shipped later re-asserts the same invariant at runtime. One invariant, stated once, doing work in four documents and in CI. This is where the project departs from most of the tooling. Spec Kit, Kiro, and Tessl all give an agent structured requirements and acceptance criteria; what they do not generally produce is a *single load-bearing property that fails the build*. The distinction is between criteria an agent can argue it satisfied, and a command whose output either matches or does not. That difference is the whole reason to prefer the harder version. A model asked to "preserve formatting" produces something plausible and you end up reviewing prose. A model asked to satisfy `yqr '.' f` equals `cat f` over a corpus has a test it cannot talk its way past, and so do you. ## Claims carry citations The bug report that started the fidelity work is the most instructive document in the set. It argues that the library then in use could not possibly meet the guarantee -- not that it did not, but that it *could not*, because the information is destroyed before the emitter ever runs. An argument like that is exactly where a fluent model confabulates. This one closes with a 24-row citation index mapping every claim to a specific `file:line` in the dependency's source, and a note on method: > Method: root cause was produced by reading the source across the > load/compose/emit layers; every claim above was independently re-verified > against the source (0 of 64 claims refuted). Sixty-four claims, each re-checked, with the refutation count reported -- including the number that would have been embarrassing had it been non-zero. This turns out to be more than good manners. A cross-model study published in June 2026, [*Citation Discipline in Spec-Driven Development*](https://arxiv.org/abs/2606.30689) (Subham Panda), tested a framework requiring per-line requirement citations against an uncited control. Because a cited requirement that does not exist in the specification is mechanically detectable, the cited condition caught hallucinated requirements at an 86.4 percent true-detection rate on Claude Sonnet 4.6 and 88.0 percent on GLM-5-turbo, with no false positives. The uncited condition detected **zero**. The paper also reports the trade-off honestly: uncited generation was more deterministic; citations bought verifiability, not consistency. Which is the point. A claim without a reference is not checkable by anything, human or machine. A claim with one is a hypothesis you can refute in seconds. The habit shows up inline too. Assertions are annotated where they were verified -- that a position index is a byte offset rather than a character offset, for instance, is marked as verified against the function that advances it. And when a later investigation contradicted the architecture document, it did not quietly diverge: it added a corrections section listing four specifics the source review had disproved, flagged to be folded back. Specs correcting other specs, in writing, is a property worth engineering for. It is the mechanism by which a body of documents converges on being true rather than drifting into being decorative. ## The false pass One detail is worth the whole corpus. The test set included a file with a UTF-8 byte-order mark, and it was the only one of the fourteen whose output was byte-identical to its input. By the headline metric, it passed. It was corrupt. There was no BOM handling in the library at all, so the mark was being absorbed into the first key -- the key became something other than `a`, and `.a` returned null. The bytes round-tripped because the file had been misparsed in a way that happened to be stable for the identity filter. The spec records this under a heading that says so plainly: the case is corruption, not preservation. An agent optimising for a green metric ships that. So does a tired human. It was caught because the document format demanded an explanation of each result rather than a tally, and "this one passes for a reason I cannot state" does not survive that format. If you take one habit from this post: **make the artifact require a mechanism, not just an outcome.** A count of passing checks is not evidence. It is a number that happens to be green. ## Superseded, never deleted Of twelve feature specs, three are marked Superseded. Two were made obsolete by consolidating on a single YAML engine; one was replaced when an opt-in flag became default behavior. None were deleted. They sit in the tracker with their status and a pointer to what replaced them, and the epic summary narrates the sequence -- byte fidelity first shipped behind a flag, then became the default while the old pipeline moved behind a different flag, then the engine-selection flag was removed entirely. That narration is the part an agent cannot reconstruct and will otherwise guess at. A fresh session reading only current code sees one engine and no flags, with no way to tell whether that is a considered endpoint or an accident. Reading the tracker, it knows the shape of the road. The same instinct appears in the architecture document, about a deliberate breaking change: > Breaking the v0.1.1 contract is intended. Current `yqr .` reformats; under > this decision it must round-trip. This is a deliberate, pre-1.0 correction, > captured here so the change is a decision and not a regression. "Captured here so the change is a decision and not a regression" is the entire argument for writing specs, in one clause. ## Prior art as a required section Feature specs carry a `Prior art` section before the design. The one for the validation subcommand surveys how jq handles it (no such command; the idiom is `jq empty`), that one YAML tool shipped a validate command and later dropped it, what the dedicated linter in the space catches that parsers do not, and the long-standing precedent of `xmllint --noout`. Only then does it decide, and the decision explicitly names what it replaces. Models are excellent at this section and reliably skip it unless asked. They have read the ecosystem. Requiring the survey converts latent knowledge into a written comparison you can disagree with, and heads off the characteristic failure of agent-designed features: a locally sensible interface that ignores the convention every neighbouring tool already established. ## Why this shape suits agents in particular Most of the above is good engineering discipline that would pay off with an all-human team. Four parts pay off specifically because of how models fail. **Specs are memory.** An agent's context does not survive the session; a file does. This is not a hypothetical weakness -- [*Spec Kit Agents*](https://arxiv.org/abs/2604.05278) (Taghavi and Bhavani, April 2026) identifies agents going "context blind" in large, evolving repositories, producing hallucinated APIs and architectural violations, and proposes hooks that ground each phase in actual repository evidence. Written specs are the low-tech version of the same idea: grounding that persists. The rule that a spec's status must be updated in the same change that advances it is what keeps that memory honest, and it is enforced before a pull request rather than during review. **Falsifiability beats fluency.** The characteristic model failure is not bad code, it is a convincing account of code. Byte-equality over a corpus does not care how convincing anything is. **Navigability is a design constraint.** The project caps source files at around 500 lines, splitting them into directory modules past that, with the stated reason that it "keeps files agent-navigable." Whatever you make of the number, treating "can a reader with a limited window find its way" as an architectural requirement is genuinely new, and it is downstream of the tooling. **Admitting is a rule.** Two standing rules say, in effect: if a URL or a file cannot be fetched or read, stop and say so, and never reconstruct its contents from inference -- never fabricate a version number, an API shape, or a changelog entry. This is written down because it is the most damaging thing a capable model does, and because it does it while sounding completely reliable. A visible blocker is worth more than a plausible guess. ## What it costs The honest accounting: this is heavy. Twenty-seven documents for a pre-1.0 CLI is a lot of prose, and a real fraction of the effort goes into writing and maintaining it rather than shipping features. The bug report discussed above is longer than the module it indicts. It earns that on work with three properties. The problem must be subtle enough that the wrong solution looks right -- byte fidelity qualifies, because a semantic round-trip looks fine until you diff it. The work must span more sessions than fit in one context. And correctness must be checkable by machine, because a spec whose acceptance criteria cannot be run is just a longer opinion. Where those do not hold -- exploratory work, a spike, anything you intend to throw away -- this apparatus is friction with no return. The failure mode of spec-driven development is spec-driven procrastination, and it is real. ## The smallest version worth trying If you want the benefit without adopting the whole structure, three habits carry most of it: 1. **Write the falsifiable property first.** Before the design, before the code: what command, run against what input, proves this works? If you cannot answer, you do not yet understand the feature, and neither will an agent. 2. **Make claims cite their evidence.** A `file:line`, a command with its output, a fetched URL. Anything asserted without one is a hypothesis and should be labelled as such -- and, per the research above, it is the only version a machine can check for you. 3. **Never delete a decision.** Mark it superseded and point at what replaced it. The cost is a stale file; the benefit is that nobody re-litigates a settled question at 2am, including the agent. None of this requires particular tooling. It is markdown in a directory, next to the code, in the same commits. If you would rather read a working example than a description of one, the specs are [public](https://zoosky.github.io/yqr/specs/). ## Next: the specs as a site There is a second half to this, and it is the reason those specs are readable in a browser at all rather than being 27 files you have to clone a repository to see. A spec corpus is only durable memory if it can be *found*. Twenty-seven documents that cross-reference each other, supersede each other, and carry status fields are a small hypertext, and a directory listing is a poor way to navigate one. What that corpus wants is what any documentation wants: an index, working cross-links, full-text search, and a build that fails when a reference goes stale -- which is exactly the check that keeps a superseded pointer from rotting into a dead end. The `yqr` site is built with Accent for that reason. The specs on it are not a copy or an export: they are the same markdown files the repository holds, mounted as a section of the site and published on every push, so the record an agent reads and the record a human browses cannot drift apart. The next post in this series works through how that is set up -- content mounted from a directory the project already maintains, cross-references that break the build when they dangle, search over the corpus, and deployment from CI -- using `yqr` as the worked example throughout. ## Sources - GitHub, [*Spec-driven development with AI: Get started with a new open source toolkit*](https://github.blog/ai-and-ml/generative-ai/spec-driven-development-with-ai-get-started-with-a-new-open-source-toolkit/), and the [Spec Kit toolkit](https://github.com/github/spec-kit). - AWS, [Kiro](https://kiro.dev/) -- agentic IDE built on spec-driven development. - Tessl, [*Tessl launches spec-driven development tools for reliable AI coding agents*](https://tessl.io/blog/tessl-launches-spec-driven-framework-and-registry/). - Subham Panda, [*Citation Discipline in Spec-Driven Development: A Cross-Model Empirical Study of Output Determinism and Automated Hallucination Detection in LLM-Generated Code*](https://arxiv.org/abs/2606.30689), June 2026. - Pardis Taghavi and Santosh Bhavani, [*Spec Kit Agents: Context-Grounded Agentic Workflows*](https://arxiv.org/abs/2604.05278), April 2026. - The [`yqr` specification corpus](https://zoosky.github.io/yqr/specs/), [repository](https://github.com/zoosky/yqr), and [crate](https://crates.io/crates/yqr). --- # Accent as a static site generator URL: /blog/accent-static-site-generator Date: 2026-07-31 Tags: static-site-generator, getting-started Most of what you read about Accent CMS talks about *serving* -- the live server, hot reload, the admin UI. But the same binary is also a static site generator, and for a lot of sites that is all you need. This post is an introduction to that side of Accent: what it does, why it exists, and how to go from a directory of Markdown to a deployable site with a single command. ## What "static" means here A static site generator takes your content -- Markdown files, some templates, a few images -- and renders it *ahead of time* into plain HTML, CSS, and assets. There is no application running when a visitor arrives; their browser just downloads files. That is why static sites are fast, cheap to host, and hard to break: there is no server to crash, no database to migrate, and no runtime to patch. Accent produces exactly this kind of output. You run: ```bash accent build --output ./public ``` and Accent walks your content directory, renders every page through your theme, processes your images, generates a sitemap and RSS feed, builds a client-side search index, and writes the whole thing to `./public`. Upload that folder to any static host -- object storage, a CDN, GitHub Pages, Netlify, your own nginx -- and you are live. ## One binary, no toolchain The thing that sets Accent apart from most generators is that it is a **single binary written in Rust**. There is no Node install, no Ruby, no Python virtualenv, no plugin ecosystem to `npm install` before your first build. You download one executable and you have the whole system: the Markdown renderer, the Jinja template engine, image processing, syntax highlighting, diagram rendering, and search are all compiled in. That means a build is reproducible and self-contained. The binary you run locally is the binary your CI runs, and it has no hidden dependencies that drift between machines. ## The same content, served or built Accent's build and serve modes render through the **same code path**, so what you preview locally with `accent serve` is what `accent build` writes to disk. You develop against a live server with hot reload: ```bash accent serve --config config.yaml ``` Save a Markdown file or edit a template, and the browser refreshes itself. When the site looks right, you build it. There is no separate "production renderer" to surprise you -- serve-vs-build parity is a first-class concern in Accent, tested explicitly. ## What you get in the output A build is more than raw HTML. From the same content, `accent build` emits: - **Rendered pages** with your Jinja theme applied, breadcrumbs and navigation resolved from the content hierarchy. - **Processed, resized images** in modern formats, generated once at build time and cached. - **A sitemap and RSS feed** so search engines and readers can follow along. - **A client-side search index** -- search works on a purely static host, with no search server behind it. - **Diagrams and syntax-highlighted code**, rendered at build time so no JavaScript is required to display them. This very website is built with `accent build` and deployed as static files. ## Deploying under a path prefix If your site does not live at the root of a domain -- a GitHub Pages project site at `user.github.io/repo`, say, or a reverse-proxy mount -- Accent can rewrite every internal URL to sit under a prefix: ```bash accent build --base-path /repo --output ./public ``` Page links, theme assets, media, pagination, search, and feeds all move under the prefix together, so nothing 404s once deployed. ## Catching broken links before you ship Static sites fail silently: a mistyped link becomes a 404 that no one sees until a visitor does. Accent can fail the build instead: ```bash accent build --strict-links --output ./public ``` With `--strict-links`, Accent resolves every internal link in the build output and stops the build if one is broken. A bad link becomes a red CI check, not a shipped 404. ## Getting the binary There is one download per platform, and it contains the full feature set. Your license key decides which tier is unlocked at runtime, and neither building a site nor running the development server needs a key at all -- so everything in this post works with an unlicensed binary. On Linux and macOS the install script picks the right archive for your platform, checks the SHA-256 checksum (and the GPG signature when `gpg` is present), and installs `accent` into `~/.local/bin` -- no root, no package manager: ```bash curl -fsSL https://raw.githubusercontent.com/AccentCMS/accent/main/install.sh | sh ``` On Windows, the PowerShell equivalent: ```powershell irm https://raw.githubusercontent.com/AccentCMS/accent/main/install.ps1 | iex ``` To pin a version rather than take the latest, pass it through to the script. Note the `-s --`: a flag placed after the URL is eaten by `curl`, which does not understand it, and never reaches `sh`. ```bash curl -fsSL https://raw.githubusercontent.com/AccentCMS/accent/main/install.sh | sh -s -- --version v0.23.1 ``` ### Downloading from the releases page If you would rather not pipe a script into a shell -- a reasonable instinct, and often the policy on a build server -- take the archive yourself from the [releases page](https://github.com/AccentCMS/accent/releases/latest): | Platform | Archive | |---|---| | Linux x86_64 | `accent--x86_64-unknown-linux-gnu.tar.gz` | | Linux ARM64 | `accent--aarch64-unknown-linux-gnu.tar.gz` | | macOS Intel | `accent--x86_64-apple-darwin.tar.gz` | | macOS Apple Silicon | `accent--aarch64-apple-darwin.tar.gz` | | Windows x86_64 | `accent--x86_64-pc-windows-msvc.zip` | | Windows ARM64 | `accent--aarch64-pc-windows-msvc.zip` | Unpack it and put `accent` somewhere on your `PATH`: ```bash VERSION=v0.23.1 BASE=https://github.com/AccentCMS/accent/releases/download/$VERSION curl -fsSLO $BASE/accent-$VERSION-x86_64-unknown-linux-gnu.tar.gz tar xzf accent-$VERSION-x86_64-unknown-linux-gnu.tar.gz install -m755 accent ~/.local/bin/accent accent --version ``` Every release also ships `checksums-.txt` and a detached signature `checksums-.txt.asc` made with the Accent CMS release key, so you can verify the archive before you run it: ```bash curl -fsSLO https://raw.githubusercontent.com/AccentCMS/accent/main/release-signing-key.asc gpg --import release-signing-key.asc curl -fsSLO $BASE/checksums-$VERSION.txt curl -fsSLO $BASE/checksums-$VERSION.txt.asc gpg --verify checksums-$VERSION.txt.asc checksums-$VERSION.txt sha256sum -c --ignore-missing checksums-$VERSION.txt ``` ## Starting from scratch with `accent init` You do not need to assemble a project by hand. `accent init` scaffolds a complete, buildable site -- content, theme, and `config.yaml` -- so your first `accent build` produces real output: ```bash # Scaffold a starter site into ./my-site accent init my-site cd my-site # Preview it live, with hot reload accent serve # Build the static output accent build --output ./public ``` `accent init` ships more than one starting point. List what is available, then pick one: ```bash # See the bundled templates accent init --list # Scaffold the full documentation site instead of the simple starter accent init my-docs --docs ``` The simple starter is a good base for a blog or a small marketing site; the `--docs` template gives you the full documentation layout with navigation and search wired up. Either way you get a directory that builds on the first try -- no missing theme, no empty `config.yaml` to fill in before anything renders. ## Deploying to GitHub Pages GitHub Pages is the shortest path from a repository to a live static site, and Accent is built to deploy there cleanly -- including the awkward case that trips up most generators. GitHub Pages serves in one of two shapes, and the difference decides how you build: - **User or organization sites** (`username.github.io`) serve at the domain root. Nothing special is needed -- build as you would for any domain. - **Project sites** (`username.github.io/repo`) serve under a `/repo` sub-path. Every page link, theme asset, media file, and search fetch has to carry that prefix, or the deployed site 404s on its own assets. Accent handles the project-site case for you. The path component of `--base-url` sets the site's base path, so every internal URL Accent emits is prefixed to match -- no post-build rewriting step: ```bash accent build --output ./public --base-url https://username.github.io/repo ``` Before you push, preview the prefixed build exactly as it will be served. `accent serve-static` reads the resolved base path from the build, so no extra flags are needed: ```bash accent serve-static --dir ./public # Visit http://127.0.0.1:4403/repo ``` To automate the deploy, commit a GitHub Actions workflow that installs Accent, builds, and publishes the output: ```yaml # .github/workflows/pages.yml name: Deploy to GitHub Pages on: push: branches: [main] permissions: contents: read pages: write id-token: write # Let a running deploy finish rather than cancelling it half-published. concurrency: group: pages cancel-in-progress: false jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - name: Install Accent CMS run: | curl -fsSL https://raw.githubusercontent.com/AccentCMS/accent/main/install.sh | sh -s -- --version v0.23.1 echo "$HOME/.local/bin" >> "$GITHUB_PATH" - name: Build site run: accent build --output ./public --base-url https://username.github.io/repo --strict-links - name: Upload artifact uses: actions/upload-pages-artifact@v5 with: path: ./public deploy: needs: build runs-on: ubuntu-latest environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v5 ``` Pinning the Accent version with `--version` is deliberate: a CI job that silently follows the latest release is a build that can change under you without a commit. Bump it when you choose to. Then enable Pages in the repository under **Settings > Pages** and select **GitHub Actions** as the source. On the next push to `main`, the workflow builds the site and publishes it. Two Accent touches make this pipeline safe. The `--strict-links` flag above fails the build if any internal link is broken, so a bad link stops the deploy instead of shipping a 404. And whenever a base path is in effect -- as it is for a project site -- the build finishes with a conformance check over its own output: if any emitted page, the search index, or `llms.txt` still carries an unprefixed root-absolute URL, the build fails and names the offending files. You find out at build time, not when a visitor hits a broken asset on the sub-path. (Both guards are no-ops for a root deployment, where there is no prefix to get wrong.) One limitation worth knowing: GitHub Pages cannot set custom response headers, so the security headers Accent's server would send (CSP, frame options) are absent on Pages. For a content site that is usually fine; if you need those headers, host somewhere that supports them. ## Where to go next The whole loop -- scaffold, preview, build, deploy -- is **free, with no license key**. You pay to serve in production, not to build, so you can take a project from an empty directory all the way to a live GitHub Pages site without one: ```bash accent init my-site cd my-site accent build --output ./public --base-url https://username.github.io/repo --strict-links ``` We will go deeper on templates, content modeling, and other deployment targets in future posts. For now, the [documentation](https://accentcms.dev/docs) covers the full command set, and the [news page](https://accentcms.dev/news) tracks every release. --- # Blog URL: /blog Everything we write, in one place: how-to guides and deep dives alongside every release announcement. Subscribe via the [RSS feed](https://accentcms.dev/feed.xml), or follow the [GitHub releases](https://github.com/AccentCMS/accent/releases) for version news only. --- # Pricing URL: /pricing ## How licensing works **Free to build, pay to serve.** The full feature set -- plugins, media processing, client-side search, styling, every diagram language -- is free in `accent build` and the development server. You pay only to serve in production, to mount the admin UI, and for the Pro integrations. **One binary for everyone.** Every download contains everything. A license key -- an offline-verified, Ed25519-signed token -- unlocks your tier at runtime. No phone-home, no telemetry, no network calls for licensing. **Yearly means ownership.** A yearly license covers every release up to its version line, forever. When it lapses, everything you licensed keeps running -- you only renew to get newer releases. Monthly is a rental: full capability while active, falling back to the free tier if not renewed. **Evaluate for free.** Building sites and local development never need a license -- download and try everything. To evaluate production serving, a monthly license is the low-commitment path: full capability while active, no obligation beyond the month. Questions, team licenses, or anything else: [hello@accentcms.dev](mailto:hello@accentcms.dev). --- # About URL: /about Accent CMS is a high-performance markdown CMS built in Rust. It exists for people who want their content to be plain files under version control -- and still want a fast site, a comfortable authoring UI, and a modern publishing pipeline without assembling one from a dozen services. ## What it is One binary that does the whole job: a live server with hot reload for writing, a static site generator for publishing, an admin authoring UI, a WASM plugin runtime, on-demand image processing, client-side search, text-diagram rendering, and Jinja-style theming. Your content is markdown with YAML frontmatter; your site is a folder you can `git clone`. This website and the [documentation site](https://docs.accentcms.dev) are built and published with Accent CMS itself. ## Principles 1. **Files first.** Content is plain text you own, diff, and back up. No database, no export lock-in. 2. **One binary.** No runtime dependencies, no Node toolchain, no containers required. Download, run. 3. **Free to build, pay to serve.** The full feature set is free for building sites and local development. Licenses -- verified offline, never phoning home -- unlock production serving and the paid tiers. 4. **Sovereign by default.** Developed and operated from Switzerland, with infrastructure choices that keep the control plane under Swiss law. No telemetry, no tracking, no third-party calls from your site unless you add them. ## Technology Rust end to end: Tokio and Axum for the server, MiniJinja for templating, pulldown-cmark for markdown, wasmtime for the Component-Model plugin runtime. Static builds are byte-for-byte parity-tested against the live server's rendering. ## Company Accent CMS is made by AccentX GmbH, Switzerland. - Product and licensing: [hello@accentcms.dev](mailto:hello@accentcms.dev) - Security reports: [security@accentcms.dev](mailto:security@accentcms.dev) - Community: [GitHub Discussions](https://github.com/AccentCMS/accent/discussions) - Plugins, themes, and starter templates: [the Hub](https://hub.accentcms.dev) --- # Download URL: /download One binary per platform. Every download contains the full feature set; your [license key](/pricing) decides which tier is unlocked at runtime. Building a site and running the development server are free and need no key at all. ## Install **Linux and macOS** ```bash curl -fsSL https://accentcms.dev/install.sh | sh ``` **Windows (PowerShell)** ```powershell irm https://raw.githubusercontent.com/AccentCMS/accent/main/install.ps1 | iex ``` The script detects your platform, downloads the [latest release](https://github.com/AccentCMS/accent/releases/latest), verifies the checksum (and the GPG signature when `gpg` is available), and installs `accent` to your user directory -- no root required. ### System requirements The Linux glibc binaries are built against glibc 2.28 and run on any distribution that ships it or newer: Debian 10, Ubuntu 20.04, RHEL 8 (and AlmaLinux and Rocky Linux 8), Amazon Linux 2023, and everything after them. Alpine and other musl-based distributions are served by fully static musl binaries with no runtime requirements at all (v0.26.0 and later); the installer detects your libc and picks the right build. It runs the binary once before installing it and stops, naming the versions involved, if your system cannot run it. The macOS and Windows binaries have no additional runtime requirements. ## Manual download Grab the archive for your platform from the [releases page](https://github.com/AccentCMS/accent/releases/latest): | Platform | Archive | |---|---| | Linux x86_64 (glibc) | `accent--x86_64-unknown-linux-gnu.tar.gz` | | Linux ARM64 (glibc) | `accent--aarch64-unknown-linux-gnu.tar.gz` | | Linux x86_64 (musl, static -- Alpine) | `accent--x86_64-unknown-linux-musl.tar.gz` | | Linux ARM64 (musl, static -- Alpine) | `accent--aarch64-unknown-linux-musl.tar.gz` | | macOS Intel | `accent--x86_64-apple-darwin.tar.gz` | | macOS Apple Silicon | `accent--aarch64-apple-darwin.tar.gz` | | Windows x86_64 | `accent--x86_64-pc-windows-msvc.zip` | | Windows ARM64 | `accent--aarch64-pc-windows-msvc.zip` | ## Verify your download Every release ships a SHA-256 checksums file signed with the Accent CMS release key. Verification is three commands: ```bash # One-time: import the release signing key curl -fsSLO https://raw.githubusercontent.com/AccentCMS/accent/main/release-signing-key.asc gpg --import release-signing-key.asc # Verify the signature, then the archive gpg --verify checksums-.txt.asc checksums-.txt sha256sum -c --ignore-missing checksums-.txt ``` The full guide, including the embedded SBOM audit and publication attestation, is in the [documentation](https://docs.accentcms.dev/docs/v0.21/deployment/verifying-downloads). ## First steps ```bash accent init my-site cd my-site accent serve # http://127.0.0.1:4400, hot reload included accent build # static output in ./output ``` From here, the [Getting Started guide](https://docs.accentcms.dev) walks you through themes, templates, and publishing. --- # Accent CMS 0.26.1 — security fixes for the plugin runtime URL: /news/2026/10/accent-cms-0-26-1 Date: 2026-10-04 Accent CMS 0.26.1 is out: a security release for the 0.26 line, cut from the `v0.26.0` tag with none of the 0.27 development work. Any licence with a 0.26 ceiling covers it. **Plugins run on a patched runtime.** Accent runs plugins in wasmtime, a WebAssembly sandbox. RustSec published ten advisories against the wasmtime 48.0.2 that 0.26.0 ships, and 0.26.1 moves to wasmtime 48.0.5, which fixes all of them. The most severe, RUSTSEC-2026-0327, is rated critical: a native stack buffer overflow from a value the runtime did not validate. The others would have let a plugin: - make the server panic with an out-of-range file timestamp, - corrupt the runtime's garbage-collected memory, - run past the CPU budget Accent gives each plugin call, - make the server allocate excessive memory, or - read leftover bytes from a directory listing. **Who should upgrade.** Only plugins run through wasmtime, so a site that runs no plugins never reaches the affected code. If your site runs plugins, and especially plugins you did not write, upgrade now. **Nothing else changes.** Configuration, templates, and content need no changes. Installed plugins keep working without a rebuild, because the plugin interface is the same. Install or upgrade: ```bash curl -fsSL https://accentcms.dev/install.sh | sh ``` Binaries for all platforms, checksums, and signatures are on the [GitHub release page](https://github.com/AccentCMS/accent/releases/tag/v0.26.1). --- # Accent CMS 0.26: script policy, portable components, directory previews URL: /news/2026/09/accent-cms-0-26 Date: 2026-09-24 Accent CMS 0.26.0 is out. Four changes need action when you upgrade, so they come first. ## Before you upgrade **Scripts need a nonce.** Served pages now send a `Content-Security-Policy` with `script-src 'self' 'nonce-...'` and no `'unsafe-inline'`. A script runs only if it loads from your own site or carries `nonce="{{ nonce }}"`. All bundled themes already do this. If your theme has inline scripts, add the attribute to each `