Skip to content
Leader

Documentation

Deploy

pnpm build writes a static site to dist/. There is no server, no adapter and no runtime: any static host will serve it.

Two things to do before the first deploy.

  1. Set site.url in src/config.ts to the address the site will actually have. Canonical links, the sitemap, the feeds and the share cards are absolute, and they are all wrong until you do. SITE_URL in the build environment overrides it, which is useful for preview deployments:

    SITE_URL=https://staging.example.com pnpm build
  2. Run the gate: pnpm check && pnpm build. A build that fails on a host usually fails locally first.

Your own repository

The Pro repository is private and cannot be forked. Start your site as a repository of your own:

git clone https://github.com/ondelva/astro-theme-leader-pro.git my-workshop
cd my-workshop
rm -rf .git
git init && git add -A && git commit -m "Leader Pro"
git remote add origin [email protected]:you/my-workshop.git
git push -u origin main

From the zip, unpack it and start at git init.

Taking an update. Releases within 1.x are yours for the life of the licence. Keep the theme as a second remote and merge the release tag:

git remote add theme https://github.com/ondelva/astro-theme-leader-pro.git
git fetch theme --tags
git merge v1.1.0 --allow-unrelated-histories   # first time only

Your content lives in src/content/ and your changes in src/config.ts and src/styles/theme.css, so the conflicts are usually few and always in files you have edited. Read CHANGELOG.md first.

Cloudflare Pages

Create a project, connect the repository, and set:

  • Framework preset: Astro
  • Build command: pnpm build
  • Output directory: dist
  • Environment variable: NODE_VERSION = 22

Cloudflare reads packageManager in package.json and uses the right pnpm.

Vercel

Import the repository; Vercel detects Astro and fills in pnpm build and dist. Nothing else is needed. Set SITE_URL as an environment variable if you want preview deployments to have correct canonical URLs.

Netlify

Import the repository and set:

  • Build command: pnpm build
  • Publish directory: dist
  • Environment variable: NODE_VERSION = 22

Anywhere else

Upload dist/. It is plain files. A 404.html is generated, so point the host’s not-found handler at it if that is not automatic.

Continuous integration

.github/workflows/ci.yml runs on push and pull request: pnpm check, pnpm lint, pnpm check:contrast, pnpm build, Lighthouse CI against the thresholds in lighthouserc.cjs, and an internal link check over dist/. It needs no secrets. Delete the file if you would rather not run it.

The integrations, once you are live

Each of these is off until you fill in src/config.ts, and each is a plain form post or a single script — nothing is loaded while the settings are empty.

What What to fill in
Analytics analytics.provider and analytics.id. host only for self-hosted Plausible or Umami
Contact form contact.endpoint from Formspree, Web3Forms or Basin. Web3Forms also wants contact.accessKey, and contact.redirect if you would rather land on your own page than the provider’s
Newsletter newsletter.provider: 'buttondown' and newsletter.id (your buttondown.com username), then the two return addresses in Buttondown — step by step in customization.md
Comments features.comments: true plus the four ids from giscus.app, after installing the giscus app on a repository with Discussions enabled

Submit the contact form and the newsletter form once on the deployed site. Both post to somebody else’s server, and the only way to know the key is right is to watch a message arrive.

After deploying

  • Search is indexed at build time, so check it on the deployed site — or on pnpm preview — rather than in pnpm dev.
  • Share cards are generated per product and note when seo.ogImages is on. Paste a couple of URLs into a card validator once; after that they take care of themselves.
  • /robots.txt is generated from site.url and points at the sitemap. It allows everything; edit src/pages/robots.txt.ts to narrow it.
  • The legal pages (src/pages/privacy.astro, terms.astro) are placeholders. Replace them.

Next: Content