Getting Started with Accent

This walkthrough takes you from a fresh checkout to your first published edit through the admin UI. The full reference docs live next to it; this page is the canonical 1.0 onboarding.

Install

Accent CMS ships as one binary per platform: every download contains the full feature set, and a license key decides which tier is unlocked at runtime. Building a site and running the development server are free and need no key.

On Linux and macOS:

curl -fsSL https://raw.githubusercontent.com/AccentCMS/accent/main/install.sh | sh

On Windows (PowerShell):

irm https://raw.githubusercontent.com/AccentCMS/accent/main/install.ps1 | iex

Or download the archive for your platform manually from the latest release (accent-<version>-<target>.tar.gz, or .zip on Windows) and place the accent binary on your PATH.

Every release is checksummed and GPG-signed. The install script verifies both automatically; to verify a manual download, see Verifying downloads.

Reinstalling or pinning a version

Re-running the installer when Accent CMS is already current reports “Already up to date” and changes nothing. To reinstall or update in place, pass force. In the piped form, flags belong to sh, not curl – a flag placed after the URL is consumed by curl and never reaches the installer:

curl -fsSL https://raw.githubusercontent.com/AccentCMS/accent/main/install.sh | sh -s -- --force
# or, using the environment-variable form:
curl -fsSL https://raw.githubusercontent.com/AccentCMS/accent/main/install.sh | ACCENT_FORCE=1 sh

To install a specific version, pass --version v0.23.1 the same way, or set ACCENT_VERSION=v0.23.1 (the v prefix is optional). Explicit flags win when both a flag and its environment variable are set.

On Windows the same environment variables steer the PowerShell installer. They are the only way to pass options to the piped irm ... | iex form, which cannot receive parameters at all:

# Reinstall or update in place
$env:ACCENT_FORCE = "1"; irm https://raw.githubusercontent.com/AccentCMS/accent/main/install.ps1 | iex

# Install a specific version (the v prefix is optional)
$env:ACCENT_VERSION = "v0.23.1"; irm https://raw.githubusercontent.com/AccentCMS/accent/main/install.ps1 | iex

An explicit -Force / -Version parameter (via the [scriptblock]::Create invocation shown in the download repository’s README) wins over its environment variable, matching the Linux/macOS behavior. $env:ACCENT_FORCE stays set for the rest of the PowerShell session; clear it with Remove-Item Env:ACCENT_FORCE.

Instant preview

Already have a markdown file? You do not need a project at all – point serve straight at it:

accent serve README.md

The file renders at https://localhost:4400/ with a built-in viewer theme. No config.yaml, theme, or content directory has to exist on disk – nothing is written or extracted anywhere. The title comes from the file’s frontmatter title, falling back to the first # heading, then the filename. Images and other files sitting next to it resolve as you would expect, and editing the file refreshes the browser automatically.

Point it at a directory to browse a whole folder of notes with the same viewer theme:

accent serve ./notes/

Each markdown file becomes a page; a default.md, README.md, or index.md in the directory root is the home page. To preview a folder with your own theme instead of the built-in viewer, add --theme-dir ./themes --theme my-theme.

Preview a remote markdown file

The markdown does not even have to be on your machine. Point serve at an http(s) URL and it fetches the document once and renders it the same way:

accent serve https://raw.githubusercontent.com/rust-lang/book/main/README.md

Use the raw file URL (the one that returns plain markdown), not the rendered web page – a code host’s HTML page is rejected with a hint to switch to the raw URL. Because the document is third-party content, two safety rules apply automatically: inline raw HTML is shown as text rather than executed, and relative links and images are rewritten to load from the source origin. The fetch is hardened with a request timeout, a 10 MB size limit, and a redirect cap, and never sends credentials.

By default the document is fetched once at startup. To keep a long-lived preview in sync with a changing source, add --refresh with a polling interval in seconds:

accent serve https://example.com/docs/runbook.md --refresh 60

Each poll only re-downloads when the origin reports a change; when it does, the page cache is refreshed and the browser reloads. A failed poll keeps the last good copy. --refresh is valid only with a URL target.

When you are ready to turn a preview into a real project, accent init scaffolds one.

Initialise a site

accent init my-site
cd my-site

init lays out the starter template: a config.yaml, a content/ directory with a homepage, and the default theme under themes/.

Start the dev server

accent serve

Visit https://localhost:4400. The home page is live. Editing any markdown file under content/ triggers a browser refresh in under a second.

The certificate warning on your first visit

The dev server uses HTTPS, so your browser shows a certificate warning the first time you open the site. Choose the option to proceed anyway.

The certificate is self-signed but cached, so the warning appears once and not on every restart. On the first start Accent prints where it stored the certificate along with the command that installs it into your platform’s trust store, which removes the warning entirely.

HTTPS is the default because it negotiates HTTP/2. The live-reload connection stays open for as long as the page does, and over HTTP/1.1 that consumes one of the six connections a browser allows per origin – enough, on a page with many assets, to make a request occasionally hang. HTTP/2 multiplexes everything over one connection instead.

To serve plain HTTP – for a test harness, or a client that cannot accept a self-signed certificate:

accent serve --no-tls

Production mode is unaffected: accent serve --production still binds plain HTTP, because deployments normally terminate TLS at a reverse proxy.

Editing your first page in the admin

The admin UI runs alongside the public site at /_admin/. Three gates must be true for the shell to mount: the binary must be built with the admin cargo feature (the default for Standard and Pro editions), a Core+, Standard, or Pro license must be loaded (the admin is a licensed feature in dev and production alike – a Core+ key is the cheapest tier that unlocks it), and admin.enabled in config.yaml must be true.

  1. Enable the admin and set a token. Add an admin section to config.yaml:

    admin:
      enabled: true
      token: "your-secret-admin-token-min-32-bytes"
    

    The token can also be supplied through the ACCENT_ADMIN_TOKEN environment variable, which takes precedence over the value in config.yaml. In production, use at least 32 bytes of entropy; a startup warning is logged for tokens shorter than 16 characters.

  2. Start the server:

    accent serve
    
  3. Open https://localhost:4400/_admin/login and enter your token. It is compared in constant time against the configured token; on success you land on the dashboard. Failed attempts re-render the form with an inline error; only failed attempts count toward the rate limit of 10 per minute, so a burst of legitimate logins never locks you out.

  4. Browse the dashboard. It lists the five most recently modified pages and a validation summary bucketed by severity, so you can see at a glance what changed and whether anything needs attention.

  5. Open a page from the pages list. Click Pages to reach /_admin/pages – a paginated, filterable list of every page – and open the page you want to edit. The editor opens in edit mode with one input per frontmatter field.

  6. Edit a field and watch the live preview. As you change a field, the editor re-renders a live preview from your current form values, giving immediate visual feedback before you commit the change.

  7. Save the page. The save path validates your input, checks for concurrent edits, writes the file, and appends an entry to the admin audit log. The cache layer invalidates automatically, so the public site reflects your change on the next request.

  8. Move the page through the workflow. The editor shows only the transitions legal from the page’s current state, so the available buttons depend on where the page is. New pages start as Published, so to send one into the editorial flow you choose Unpublish (back to Draft) or Archive. From Draft the flow runs Submit for review to Review, then Approve to Published. Published pages are publicly visible (subject to any date constraints); drafts and pages in review stay hidden from the public site.

Shareable by default

Every page the default theme renders ships complete Open Graph and Twitter Card tags, a build-safe canonical link, and a page-specific description, so links unfurl as rich cards on Slack, LinkedIn, X, Mastodon, and friends with no extra work. To make those cards as good as possible, set a few site-wide values in config.yaml:

site:
  name: My Site
  url: https://example.com        # required for absolute canonical / og:url
  description: A short site-wide description used when a page has none.
  meta:
    twitter:site: "@mysite"        # any platform tag is just a key

structured_data:
  default_image: /assets/social-card.png   # branded fallback card image
  default_image_width: 1200                # its size, so a client can reserve
  default_image_height: 630                #   the card box before fetching it
  default_image_alt: "My Site -- notes on things."

Per page, set description:, image:, or a meta: block in frontmatter to override the defaults. See Social Sharing and SEO Metadata for the full system.

Printable by default

Any page can be saved as a PDF straight from the browser’s print dialog (Ctrl-P / Cmd-P, then “Save as PDF”). The default theme ships a print stylesheet, so what you get is the article on its own – no navigation, sidebar, search box, or footer – laid out black-on-white across A4 pages. The Templating Guide covers what the sheet strips and how to change the page size or margins in your own theme.

What’s next