papyrus

Back

Install and configure Papyrus

Use papyrus-template as the recommended starting point, then configure the site with TOML, Markdown, and asset overrides.

The recommended way to start a Papyrus site is to use papyrus-template. The template keeps site-owned files small: one site config, one profile config, one example post, and a few asset overrides. Papyrus provides the layouts, standard pages, content collection, RSS route, robots route, post UI, profile components, and theme CSS through the published astro-theme-papyrus package.

Start from the template

Create a new repository from papyrus-template, then install dependencies:

pnpm install
pnpm dev
sh

The package repo uses pnpm’s mature-release guard: minimumReleaseAge: 10080 and minimumReleaseAgeStrict: true. That seven-day gate makes installs fail instead of silently falling back when a dependency was published too recently.

The template depends on the npm package:

package.json
{
  "dependencies": {
    "astro-theme-papyrus": "^0.2.0"
  }
}
json

The template enables Papyrus in Astro:

astro.config.mjs
import sitemap from "@astrojs/sitemap";
import { defineConfig } from "astro/config";
import { loadPapyrusConfig } from "astro-theme-papyrus/config";
import papyrus from "astro-theme-papyrus/integration";

const papyrus = await loadPapyrusConfig();

export default defineConfig({
  site: papyrus.site,
  integrations: [papyrus(), sitemap()],
});
js

It also reuses the Papyrus content collection:

src/content.config.ts
export { collections } from "astro-theme-papyrus/content";
ts

Papyrus injects these standard routes from the package:

RouteSource
/Home page with latest posts and project cards
/posts/Public post list
/posts/[...slug]/Post detail page
/projects/Project cards from papyrus.config.toml
/profile/Profile page from src/data/profile.toml
/tag/ and /tag/[tag]/Tag index and tag detail pages
/404.htmlHelpful not-found page
/rss.xmlMain RSS feed
/robots.txtRobots file with sitemap URL

Because the pages are injected by the package, the template does not need a src/pages tree.

Know src vs public

Papyrus follows the same Astro convention used by Papyrus-style starter repos: src/ is source, public/ is static output input.

Use src/ for files Astro should read, transform, type-check, or route during the build:

  • src/content/posts/*.md for posts
  • src/content.config.ts for the Papyrus content collection export
  • src/data/profile.toml for the profile and CV source
  • src/pages/*.astro only when a consuming site needs custom routes that the package does not already provide

Use public/ for files that should be copied to the deployed site as-is:

  • public/logo.svg, public/favicon.svg, and public/site.webmanifest
  • public/images/* for covers, avatars, and project images referenced by frontmatter or papyrus.config.toml
  • generated artifacts such as public/cv/profile.json, public/cv/profile.md, public/ai/*, public/rss/tags/*, and public/pagefind/*

Do not hand-edit generated files in public/. Edit the source in src/, papyrus.config.toml, or src/data/profile.toml, then regenerate the artifacts.

Edit the right file

For normal site work, start with these files:

GoalEdit
Site title, description, nav, social links, projects, theme, feature flags, and post-card defaultspapyrus.config.toml
Add or edit postssrc/content/posts/*.md
Add a page that Papyrus does not already injectsrc/pages/*.astro
Change the profile, CV, links, skills, dates, and print colorsrc/data/profile.toml
Change logos, favicons, covers, avatars, and project imagespublic/ assets

The package repo has many files because it owns reusable components, injected routes, scripts, and demo fixtures. A consuming site should stay closer to the template shape: config, content, profile data, and assets.

Long-lived site copy should live in Markdown, TOML, JSON, or other site-owned data. Components may keep generic fallback labels such as Back, Share, Source, or On this page, but site-specific text should not be hidden inside package code. Demo routes in this repository can contain route-local prose when they are examples; if that prose becomes user documentation, move it into a post or docs content source.

Edit the site config

Most site behavior starts in papyrus.config.toml. The template keeps the system color preference as the default and uses the Everforest theme profile.

Use exactly the project cards you want to publish. The starter keeps two projects to demonstrate local and upstream links without turning the template into a demo catalog.

Add posts

Posts live in src/content/posts. A minimal post needs a title, description, date, and optional tags.

src/content/posts/publishing-with-papyrus.md
---
title: Publishing with Papyrus
description: A short implementation note published from a Papyrus-powered site.
pubDatetime: 2026-07-10T09:00:00.000Z
tags: [astro, papyrus]
cover: /images/cover.svg
---

Write the post body in Markdown.
md

Papyrus handles list pages, detail pages, adjacent post links, tags, reading time, cover images, RSS entries, and the generated route paths.

Edit the profile

The profile page reads src/data/profile.toml.

src/data/profile.toml
[user]
name = "Site Author"
title = "Software Engineer"
bio = "Writer and software engineer"
location = "Lisbon, Portugal"
print_color = "#37474F"
email_user = "hello"
email_domain = "site.test"
sections = ["about", "experience", "education", "skills"]
toml

The same profile data can be exported to JSON and Markdown with:

pnpm run cv:export
sh

Override assets

Keep visual identity in public/:

  • public/logo.svg
  • public/favicon.svg
  • public/site.webmanifest
  • public/images/cover.svg
  • public/images/avatar.svg
  • project images referenced by papyrus.config.toml

These are normal site assets. Papyrus supplies the components and theme CSS, while the consuming site supplies its own images and metadata.

Advanced composition

The template is the recommended path. For a custom site that needs different routes, import Papyrus components directly:

---
import { PapyrusBaseLayout, PapyrusPostList } from "astro-theme-papyrus/components";
import { publishedPosts, routablePosts } from "astro-theme-papyrus/utils";

const allPosts = await getCollection("posts");
const posts = publishedPosts(allPosts);
const routePosts = routablePosts(allPosts);
const adjacentPosts = publishedPosts(allPosts);
---

<PapyrusBaseLayout title="My site" description="Custom page.">
  <PapyrusPostList posts={posts} />
</PapyrusBaseLayout>
astro

Use routePosts when creating static post detail paths. Use adjacentPosts when computing previous/next links so hidden archive pages can still exist as routes without showing up in public navigation.

In a post-detail route, pass folder-aware tags into the post layout:

<PapyrusPostLayout post={post} tags={postTags(post)}>
  <Content />
</PapyrusPostLayout>
astro

Keep the boundary clear: Papyrus owns reusable pages, components, styles, and helpers. The consuming site owns content, TOML config, asset overrides, private data, analytics, and deployment settings.