pb_public

Static files served at / by the same instance that serves the API. A single-page app, a landing page, a documentation build: anything that is files. It is optional, and an instance without it is simply an API.

What goes in it

Inside pb_public/:

  • index.html
  • 404.html: optional; a copy of index.html is used when there is none
  • assets/
  • favicon.ico
  • _redirects: optional

An index.html here is the site. Requests that match a file get that file; requests that match nothing get 404.html, or a copy of index.html when the build did not make one, which is what a single-page app wants so its own router can handle the path. /api and /_/ are never affected.

One difference between the two runtimes: voidbase serve answers a deep link with the shell and status 200, as PocketBase does. On Cloudflare everything outside /api is served by the asset layer without invoking the Worker, which answers a miss with the nearest 404.html, so a deep link gets the same shell with status 404. The body is identical and the client router boots as usual.

Getting a build in there

There is no bundler here on purpose: build your frontend with whatever it already uses, and copy the output in. A line in your deploy script is usually the whole integration.

# build your frontend wherever it lives, then put the output here
cd ../web && bun run build
rm -rf ../blog-api/pb_public && cp -r dist ../blog-api/pb_public

A frontend served this way is same-origin with its API, which means the SDK needs no address at all: new PocketBase("/") and no CORS to think about.

The files crawlers ask for

/robots.txt, /sitemap.xml and /llms.txt are answered by the seo plugin when this directory has no such file: robots keeps crawlers out of the panel and the API and names the sitemap, the sitemap lists the site root and one entry per record of each collection VOIDBASE_SITEMAP declares (only a publicly listable collection is read), and llms.txt describes the instance and its machine-readable endpoints for the crawlers that are not search engines. A real file here wins over the generated answer.

Redirects

A _redirects file in the directory is read on deploy, in the syntax Netlify and Cloudflare Pages use: source, destination, optional status.

/old-post/:slug   /posts/:slug        301
/download         https://example.com/dl  302
https://api.example.com/  /_/  302

Path-only rules are uploaded with the assets as Cloudflare's own _redirects, evaluated before the Worker runs. A rule whose source names a host becomes a redirect rule on the zone instead, tagged with the Worker's name so a redeploy replaces exactly its own rules, which is how one instance behind several domains can answer differently per hostname. That second kind needs the deploy token to carry the zone's Single Redirect permission, and without it the deploy prints the rules to create by hand and carries on.

Somewhere else, if you prefer

Point at another directory, so a frontend build can stay where it is built rather than being copied. The directory has to contain an index.html, and the deploy refuses before touching anything if it does not. VOIDBASE_DEPLOY_PUBLIC_DIR does the same for a deploy from the environment.

voidbase serve --publicDir ../web/dist
voidbase deploy --public-dir ../web/dist
Found something wrong on this page?

Fix it yourself. The link below opens this file in GitHub's editor and forks the repository for you if you need one, and your change becomes a pull request without leaving the browser.