Visit parroquia.app for a working example.
This repository is a site factory: a single template used to build many parish websites. There are no site-specific files committed here — each site's content is stored remotely and fetched at build time.
The aim is to provide a simple template for non-technical users to be able to create a modern parish website. Site content is edited with an online editor, fetched at build time, processed into something a modern tool like Vitepress can render, and published to Cloudflare — one site per parish.
The pipeline has three stages:
- User input — site content lives in a remote R2 bucket (behind the config-api)
and is edited with the online editor (
editor.parroquia.app), not on git. - Adapter —
npm run before-builddownloads the site's remoteconfig.json(viafetch.js) and processes the pages/events it contains into the files Vitepress needs. - Render — VitePress + Tailwind CSS v4 turn the processed content into a static website.
npm install
node docs/.vitepress/fetch.js <site-slug>
npm run before-build
npm run build # or npm run devSite content (site configuration, pages, events, media) is stored in a remote R2
bucket and managed through a schema-driven online editor (editor.parroquia.app), as
described in catholicweb/config-api. It is
not stored in this repository.
At build time we materialize that content for a given site. The site lives in a single
remote JSON document, and the fetch step also pulls the previously published per-site
data files, so every local file is ready before the adapter runs — no .md files and
no images are downloaded:
node docs/.vitepress/fetch.js <site-slug>fetch.js downloads https://data.parroquia.app/<site-slug>/config.json (pages under
pages.list, events under calendar.events), normalizes it, and writes
docs/public/config.json for the adapter. It also best-effort materializes
dictionary.json + buildtimecache.json from the site's public URL and videos.json
from the data host, all into docs/public/. Media is served remotely — it is
never downloaded or transformed locally. See
CLAUDE.md for the env overrides and the cross-repo data contract.
This is the key stage: it takes the materialized content and processes it, creating the
files stage 3 (Vitepress) needs to render. It reads the site's pages, translates and
enriches them (transform/fetch resources/...) and saves them per language under
docs/*.md.
npm run before-buildKey bits are:
- Translate - Autotranslates key fields
- Rewrites media to remote URLs, generates PWA icons...
- Fetch Youtube videos
- Fetch Google calendar events, merging them with the site's own events
- Fetch gospel
- Fetch internal/external pages preview (oembed), eg: fetches youtube video thumbnail from its url
- ...
Takes the processed content at docs/*.md and creates a magnificent website.
npm run build
# or
npm run devKey elements are:
docs/.vitepress/theme/Layout.vue- We follow a modular approach, this component takes each section defined in the processed.mdand renders itdocs/.vitepress/theme/components/*- Each section is rendered using a custom.vuecomponent
This single repository builds and deploys one Cloudflare Pages project per site. A
GitHub Actions workflow (.github/workflows/deploy.yml) is triggered with a
site_slug; the prepare job validates the slug, the build job runs
fetch.js <slug> → before-build → build and uploads the
artifact with a zero-scoped token, and the deploy job pushes that artifact to the
Cloudflare Pages project named after the slug. A fleet workflow
(.github/workflows/dispatch-fleet.yml) fans out a build per known site on content
changes and nightly.