@jens4m/unbase-pages
v0.2.0
Published
Keeps draft pages out of a site's production build: an Astro integration and a Vite plugin, for Unbase.
Maintainers
Readme
@jens4m/unbase-pages
Keeps draft pages out of a site's production build. A page marked as a draft stays off the live site however often the rest is published, while previews and the dev server show it as it is.
It is a build step only: an Astro integration and a Vite plugin for React Router apps. Nothing it does reaches a visitor's browser, and it never calls a hosted service. Made for Unbase, which writes the list of drafts; it works the same without it.
npm install --save-exact @jens4m/unbase-pagesAstro
// astro.config.mjs
import { defineConfig } from "astro/config";
import sitemap from "@astrojs/sitemap";
import unbasePages from "@jens4m/unbase-pages/astro";
export default defineConfig({
// Last, or at least after sitemap() and comment-modus: it cleans the page lists they write.
integrations: [sitemap(), unbasePages()],
});Vite + React Router
// vite.config.ts
import react from "@vitejs/plugin-react";
import { unbasePages } from "@jens4m/unbase-pages/vite";
export default { plugins: [react(), unbasePages()] };Which pages are drafts
unbase.pages.json at the app's root lists them. Without the file, or without a draft in it, the
build is untouched.
{ "pages": { "/pricing-2027": { "draft": true } } }What a production build does with a draft
- Its page is not built. Astro: the page file compiles to an empty page, so nothing it imports
is bundled, and its HTML is removed. React Router: its
<Route />leaves the router and its module becomes empty, so the address falls to the app's own Not Found. - Its address leaves every page list: sitemaps, comment-modus's
pages.jsonand content map, and the entries the page owns in Astro's content store. - The output is checked for its text. If a sentence only the draft has is still in a served file, the build stops.
Which builds are production
UNBASE_DEPLOY_CONTEXT (production, preview, development) when it is set; otherwise a dev
server is development, and the host decides (VERCEL_ENV, Netlify's CONTEXT). Anything else
counts as production, so a draft only shows where a host says it is a preview. NODE_ENV is never
read: previews are production-optimised builds too.
Fails closed
A production build stops, with the page and the reason, when a draft cannot be kept out: a
dynamic route, a page another file imports, content it cannot attribute to the page, an invalid
unbase.pages.json, or a draft's text still in the output. Mark the page as ready, or fix the
reason, and build again.
Removing it
Publish or delete the drafts first: without the package, a draft in unbase.pages.json is
simply built. Then remove the package, its line in the config, and unbase.pages.json.
Exports
| | |
|---|---|
| @jens4m/unbase-pages/astro | The Astro integration (default export, and unbasePages) |
| @jens4m/unbase-pages/vite | The Vite plugin (unbasePages) |
| @jens4m/unbase-pages | The core: discovering a site's pages and checking a draft, as pure functions on the app's files |
Node 18.17 or newer. MIT licence.
Developing
The source lives in the Unbase repository, kit/pages/. core.mjs is the one implementation of
page discovery and the draft check; Unbase's backend runs an exact copy
(supabase/functions/_shared/pages-core.mjs, and a test fails when they differ). After changing
it: cp kit/pages/core.mjs supabase/functions/_shared/pages-core.mjs.
node --test kit/pages/test/core.test.mjs(also in the repository'snpm test).- A11, the acceptance test, on lab sites only:
npm run test:a11 -- vibe(the Lovable-shaped fixture intest/fixtures/lab-vibe) andnpm run test:a11 -- astro --dir <lab copy>(a git repository without a remote). It needsplaywright-core(PLAYWRIGHT_CORE=<path>) and Chrome (CHROME_PATH).
