Algolia Integration ExampleCloudflareSupabase

Algolia Search

Instant, typo-tolerant search over your Postgres data.

algolia-search

Vercel's Algolia Integration Example (Algolia's Algolia × Supabase × Vercel starter) — instant, typo-tolerant search over a Postgres products table, with InstantSearch's facets and a product page that shows what only the database holds — running on Cloudflare Workers + Static Assets through @opennextjs/cloudflare, with the database a Supabase Postgres project reached through Cloudflare Hyperdrive, both provisioned by Terraform through Orun and the schema and the template's demo products applied by Orun's db-migrate (the way the Lumen baseline does it), and packaged as an Orun baseline: one command takes a new product from nothing to live on stage and prod, in its own repository, under its own name — in ONE landing.

The template's code is the code. What the port changes is what the Workers runtime, a fresh unattended deployment and Orun's rule that no SaaS key is ever in a build force: upstream's lazy module-level pg.Pool becomes one pg client per request over the Hyperdrive binding (lib/db.ts, its query() unchanged at every call site); the Algolia application id and search-only key are the Worker's secrets, read when the page renders and handed to InstantSearch as props, instead of NEXT_PUBLIC_ variables inlined at build; and demo/seed.sql, which upstream had you paste into Supabase's SQL Editor, is two migrations (the table, then its twenty demo products) applied before the app serves. Until the owner connects Algolia, the home page keeps the template's "search activates once…" notice and lists the catalogue straight from Postgres under it. Every table in public has row-level security, so Supabase's Data API serves none of it — the internal-only cost prices, suppliers and notes above all. What the baseline adds is everything needed to make a copy of it somebody else's, built the way cirrus-baseline is. See specs/epics/algolia-search for the design, the milestones and the as-built status, including every departure.

Instantiating a product

git clone --depth 1 --branch <baseline-tag> https://github.com/sourceplane/algolia-search
cd algolia-search
orun new --blueprint repo-blueprint.yaml --out ~/products/acme-search --run-hooks --resume \
  --set reponame=acme-search --set productname="Acme Cloud" \
  --set githuborg=acme-inc --set subdomain=<workers-dev-subdomain>

Or, once the platform's registry lists it, from the Orun console (Baselines → algolia-search → Build). Two phases: 01-product creates the repository, mints the five brokered credentials (Cloudflare and Supabase) and lands the whole product as one pull request, whose convergence on main provisions and deploys it per environment in a fixed order —

supabase ──▶ cloudflare-hyperdrive ──▶ db-migrate ──▶ web

— each edge mode: enforced on a push to main and advisory on a pull request; then 02-docs records the live deployment from probed facts. BOOTSTRAP.md is the operator guide; docs/phases/ has a page per phase. The Supabase organization needs room for two projects (stage and prod) — the free plan's limit.

The new repository receives the product only — the app, the Terraform roots, the migrations, the tests, its CI, its tooling, a README of its own and its operating contract — renamed throughout to the product's name, repository, Worker, Supabase project and Hyperdrive config. None of this repository's machinery ships. The card asks for no Algolia key: the product goes live with search not connected, and its owner connects Algolia after the bootstrap — two optional secrets (ALGOLIA_APP_ID, ALGOLIA_SEARCH_API_KEY) and the Algolia connector in Algolia's dashboard (the product's README, "Connect Algolia").

What makes it a baselineWhere
The console card (inputs, secrets, programme)blueprint.yaml
The build document (modules, phases, hooks)repo-blueprint.yaml
This tree's identity, the product's README and the bootstrap's task contracts.baseline/
The rename engine (product-name seam: apps/web/lib/site.ts)tooling/rebrand/rebrand.mjs
The bootstrap's helpers (deferrals, redeploy marker, work-tree strip)tooling/bootstrap/
The deployment-record rendererhooks/render-deployment-docs.sh
The product's context packai/context/
The baseline's tests: contract, leak, offline bootstrap and plans, end to end (a headless Chrome running the search against an Algolia stand-in included)testing/, .github/workflows/baseline.yml
Cutting a baseline-vN tag.github/workflows/tag.yml

What is here (the product)

SurfaceWhere
The product's name (the page's title)apps/web/lib/site.ts
The home page: the hero, InstantSearch, the catalogue while search is not connectedapps/web/app/page.tsx, apps/web/components/search/, apps/web/components/catalogue.tsx
The product page, with the database-only fieldsapps/web/app/products/[id]/page.tsx, apps/web/lib/products.ts
The per-request pg client (Hyperdrive first, POSTGRES_URL fallback)apps/web/lib/db.ts
The Algolia config the page hands the browser, read from the Workerapps/web/lib/algolia.ts
The connector's transformation (pasted into Algolia's dashboard)apps/web/demo/transform.js
The database check the deploy smoke-testsapps/web/app/api/health/route.ts
Workers build, bindings and deploy contractapps/web/next.config.ts, open-next.config.ts, wrangler.template.jsonc → wrangler.jsonc (committed), component.yaml; the Algolia secrets pushed after the build by tooling/wire/worker-secrets.mjs
The schema and the demo products as migrations, and Lumen's runnerpackages/db (@saas/db — the name the db-migrate composition builds); apps/web/scripts/migrate.mjs applies the same files to a local database
The Supabase project, the Hyperdrive config, the migration stepinfra/terraform/supabase, infra/terraform/cloudflare-hyperdrive, infra/db-migrate
Teststests/web (vitest; InstantSearch rendered in jsdom against an in-process Algolia stand-in), tests/db (vitest; the migrations in PGlite)

Getting started

pnpm install
pnpm run wire:fixture   # re-render apps/web/wrangler.jsonc from its template (committed; this changes nothing)
pnpm typecheck
pnpm lint
pnpm test
pnpm build              # next build + opennextjs-cloudflare build → apps/web/.open-next

The build needs no database and no Algolia account. Running it locally — a Postgres on localhost:54322 (supabase start), pnpm --filter @app/web db:migrate, then next dev or wrangler dev, with Algolia's keys in apps/web/.dev.vars if you have them — is in the product's README (.baseline/product/README.md), which is what a product built from here carries.

How it maps to Vercel

VercelHere
Next.js hostingOne Cloudflare Worker (.open-next/worker.js) + Static Assets
The Supabase integration's POSTGRES_URL, a lazy module-level pg.Pool (with an ssl override for Supabase's pooler)The Supabase project's Postgres through Hyperdrive: query() is still upstream's, run on one pg client per request from env.HYPERDRIVE.connectionString (no ssl override: the Worker talks to Hyperdrive); POSTGRES_URL is for local work without wrangler, through upstream's own pool
The Algolia integration's NEXT_PUBLIC_ALGOLIA_APP_ID / NEXT_PUBLIC_ALGOLIA_SEARCH_API_KEY, inlined into the browser bundle at build (next.config env)Orun secrets ALGOLIA_APP_ID / ALGOLIA_SEARCH_API_KEY, pushed to the Worker as secrets after the build (tooling/wire/worker-secrets.mjs) and read per request (lib/algolia.ts); the page hands them to InstantSearch as props. The write key, never read upstream either, is not used at all
Paste demo/seed.sql into the Supabase SQL Editorinfra/db-migrate applies packages/db/src/migrations per environment — the table (010), row-level security (020), the twenty demo products (030, upstream's rows byte for byte) — after the project and the Hyperdrive config exist, before the Worker deploys
The Algolia connector, set up in Algolia's dashboardThe same, as the owner's one-time step (the product's README, "Connect Algolia"), with the same demo/transform.js
Until the integration's env vars are pulled, the page shows a noticeThe same notice (naming the Orun secrets), and the catalogue listed from Postgres under it
next/font/google (Geist)The geist package (next/font/local): Google's font download fails on GitHub's runners
The Supabase and Algolia integrations "Deploy with Vercel" installsinfra/terraform/supabase (one project per environment) + infra/terraform/cloudflare-hyperdrive (one config per environment), ids and credentials as orun secrets; Algolia connected by the owner
"Deploy with Vercel" (clone the template)orun new --blueprint repo-blueprint.yaml — a new repository, branded, provisioned, migrated, deployed

CI

WorkflowWhat it runsShips to a product
ci.ymlthe Orun pipeline, and the only workflow a product carries: orun plan --changed, then one job per lane. A pull request runs the verify lanes (the app built and dry-deployed per environment, both Terraform roots checked and planned, the migrations planned), except the bootstrap's own landings (orun/BASE-*), where plan alone runs and nothing waits for it — the landing was checked in the build box; a merge applies, migrates and deploys stage → prod. The lanes do not typecheck, lint or run the tests: baseline.yml's e2e tier does, on the landing, before each tag. It plans nothing while intent.yaml names the placeholder workspace ws_CHANGE_ME, as this repository does. A manual run (Orunbase's Deploy button, or Run workflow on main) plans the environment and components it names under the push-to-main trigger, so they deploy as a merge deploys themyes
baseline.ymlthe baseline's own tiers: contract tests; the blueprint read by the pinned orun, the leak gate, the offline bootstrap and the product's own plans; the product built (the Algolia secrets kept out of it), migrated into a local Postgres, dry-deployed and served without Algolia and with it — its search run in a headless Chrome against an Algolia stand-in — and its table shut to the Data API's rolesno
tag.ymlcuts a baseline-vN tag (manual)no