Skip to content

Deckle

Deckle is a site for independent magazines and journals (print quarterlies with a website, literary and food journals, studio publications, newsletters that come out in issues, long-form blogs that want to feel like print), set like a printed magazine you could pick up: uncoated paper with grain, photos with torn deckled edges, letterpressed serif headlines and covers that catch a raking light. It has your stories (each with its own page), your issues with their covers, contents and editor’s letters, subscriptions and single issues, and an about page for pitches and advertisers.

Deckle comes in two variants, chosen when you create the site: files/Sanity (static pages, any host) and EmDash (--cms emdash, rendered on request on Cloudflare). The pages are the same in both.

Page Edit it in
Home Pages → Home page (a list of sections)
Stories, issues, subscribe, about, 404 Pages → the page’s own entry
Stories Content → Stories
Issues (covers, contents, editor’s letters) Content → Issues
Magazine name, tagline, email, where it’s made, navigation, header button, profiles, colophon Pages → Site settings
Buttons, labels, chat, search, emails, game texts Content → Interface texts
Privacy, terms Pages → Legal

In headlines, words wrapped in *stars* are set in italic in the accent, as in “Brine, *slowly*”.

Each issue has a number, a theme (“Salt”), a season, a 4:5 cover photo, up to four cover lines, the cover stock (the second or third color as paper, the accent as book cloth), its pages and price, and the editor’s letter as its text. An issue can be sold out: its page then says so instead of offering it.

Each story has a standfirst, a department (the stories page filters by it, so keep them short and consistent: “Essays”, “Food”, “Places”), the author and an optional photo credit, a 3:2 lead photo with its caption, a color for its swatch, and the issue it was printed in (the issue’s address, e.g. salt) with its page in print: together they build the issue’s contents page. A story without an issue is web-only. Reading time is counted from the text.

Stories are written in Markdown: > makes a pull quote, --- a section break (* * *), ## a small-capitals subhead, and footnotes ([^1]) are listed at the end. The first paragraph gets a drop cap and the last an end mark.

Covers are drawn by the site from the issue’s fields: the masthead (your magazine’s name) is letterpressed across the stock, the photo is set in as a plate with a deckled edge, the cover lines are printed under it. On the home page and the issue page, the cover catches a soft light once as the page opens. Back issues stand on a shelf; hovering one draws it out.

On a story, a silk ribbon in the accent hangs from the top of the page on wide screens and lengthens as you read. Visitors who prefer reduced motion see the light at rest and the ribbon simply hanging.

Pages → Subscribe page → Plans holds up to four plans, each a yearly subscription or a one payment (a gift), with what’s included and a Stripe Price id. The plan marked Featured is bound in cloth. Issues have their own one-time Stripe Price id: the issue page then shows a buy button. Without Price ids the buttons say how to set them up. The subscribe page also lists your stockists and questions.

Everything works without keys; each feature switches on with its variables in .env.example.

Feature Where Service
Subscriptions, gifts, single issues Subscribe page, home page, issue pages Stripe
Pitch form About page; pitches go to the email in Site settings Resend
Book a call (advertising, stockists) About page, loads on click Cal.com
The Sunday Letter (newsletter) Home and stories pages, under every story, with a welcome email Supabase
Ask the archive Chat on every page, answers from your stories, issues, plans and questions Claude
Search ⌘K or the search button: stories, issues, subscribe, about built in, or Algolia
Analytics Every page; Google Analytics only after consent Plausible, Umami, Google Analytics

After a payment, the Stripe webhook (/api/stripe/webhook) emails the reader; add your own steps there, such as adding a subscriber to the mailing list for the print run.

The home page is built from these sections, in any order: Cover (the current issue, or one you pick, with its first stories), Lead story (a spread), In this issue (the contents page), Latest stories, Pull quote, Back issues (the shelf), Subscribe (the plans) and Newsletter sign-up. Sections that show an issue or a story take its address; leave it empty for the newest issue and the newest featured story.

src/content/singletons/brand.json (Pages → Brand in Keystatic) holds three colors: the accent is the ink (buttons, italics in headlines, rules, the bookmark ribbon, book cloth), the second and third are paper stocks (covers, the newsletter, selected states). Buttons and cloth are darkened until their paper-white text is readable, the stocks lightened until ink on them is; a color that can’t get there stops the build with a message. The paper, links and the night theme (black card stock under a lamp) are derived from them. Brand also sets the fonts (a serif display face for headlines, a serif for reading, and the labels in the text font or a grotesk) and the corners (square, or softly rounded).

Deckle is ready for more languages: see Languages.

A small game, Stop the press: the proofs are back, one line at a time, and every line hides one misprint. Tap the wrong word (or move along the words with the arrow keys and press Enter) before the press runs in 60 seconds; a word that was right costs three seconds. The lines are content (Interface texts → 404 game), with each misprint written {right|wrong}. The best score is kept in the visitor’s browser.

Stories print as plain text: no navigation, forms or chat, ink on white, with link addresses written out.

  • AGENTS.md describes the project for coding assistants (Claude Code reads it through CLAUDE.md, Cursor through .cursor/rules/), including what makes the look.
  • /llms.txt lists your pages, stories and issues for AI assistants, in every language.
  • Pages carry JSON-LD: the magazine as a periodical, each issue, each story as an article, the plans and the questions.
Terminal window
pnpm dev # local site, editor at /keystatic
pnpm build # production build
pnpm cms sanity schema|seed # move content to Sanity (see Content → Sanity)

In the EmDash variant: npm run dev, npm run deploy (Cloudflare) and npm run emdash:schema (after changing the content model).