Deploying

CarvePress writes static files to outDir. This repo builds to .site and publishes that directory to GitHub Pages.

GitHub Pages

The workflow in this repository runs on pushes to main, never deploys pull requests, and still builds pull requests so broken docs fail checks.

.github/workflows/pages.yml
name: Pages
on:
  push:
    branches: [main]
  pull_request:
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: pages
  cancel-in-progress: false

The job uses Node 22, runs npm ci, npm run build, npm test, and npm run docs:build, then uploads .site with actions/upload-pages-artifact and deploys with actions/deploy-pages.

Base Path

Project pages need base: '/carve-press/' because the site is served below https://markup-carve.github.io/carve-press/. Keep authored internal links rooted at the site route, such as /guide/getting-started; CarvePress rewrites rendered URLs with the configured base.

Route Manifest

CarvePress writes a route manifest at routes.json by default. The file is a sorted JSON array of content routes and should be committed. On later builds, any route in the manifest that is no longer present must be covered by a redirect source from redirects or page redirectFrom, or the build fails.

Fix a missing route by restoring the page, adding redirectFrom to the page that replaced it, or adding a redirects entry in config. Redirect stubs are not written into the manifest, so removing a redirect later does not look like a removed content page. Set routeManifest: false to disable this check.

Netlify And Cloudflare Pages

Set the build command to:

static host build
npm ci
npm run docs:build

Publish .site. CarvePress can also write a Netlify-style redirects file from the redirects config and page redirectFrom frontmatter; this dogfood site maps /old-guide/ to /guide/getting-started.

On GitHub Pages, redirect stubs are static HTML files. They return 200 and use a meta refresh, not an HTTP 301, because Pages serves static files.

If you use clean URLs with a host that needs explicit fallback routing, add redirects in publicDir:

_redirects
/* /404.html 404

Any Static Host

Upload the contents of .site to the configured base path. If you disable cleanUrls, links include concrete .html files.

Redirecting A Whole Section

A prefix pattern moves a renamed section in one entry:

carve-press.config.ts
redirects: { '/docs/*': '/guide/*' }

The pattern is expanded against the pages that actually exist, so each one gets its own stub - a static host cannot match a pattern at request time. The _redirects file keeps the single splat line for hosts that do understand one. A pattern whose target matches no page fails the build rather than emitting nothing.

robots.txt

Every build writes robots.txt, advertising the sitemap when the site knows its own hostname:

robots.txt
User-agent: *
Allow: /

Sitemap: https://example.com/docs/sitemap.xml

Without a hostname the Sitemap: line is omitted rather than written relative, which is a line crawlers ignore. robots: false writes nothing, and a robots.txt of your own in publicDir is never replaced - a file you shipped is your answer to this question, and silently overriding it is the kind of thing discovered weeks later by a crawler doing the wrong thing.

Edit this page

Last updated