Shared data & publishing
The business database becomes the website’s source, too.
It started with…
Operations needs to maintain programmes, campuses and intakes in a consistent model that other products can reuse. The first responsibility is the quality and meaning of the source data.
So we built…
A shared Airtable reference, with linked entities and explicit field mappings for downstream use. This example focuses on preserving source relationships as the catalogue evolves; the linked web example covers publication.
- Airtable
Maintain
Business model and relationships
- Supabase
Prepare for publishing
Selected fields, statuses and media
- Vercel
Serve the website
Next.js reads the publishable catalogue
This documented flow uses a dedicated synchronisation engine. Zapier can coordinate other events; it does not replace that engine in this case.
Take a look inside
Screen 1 of 61. Maintain the offer
The internal catalogue uses linked programmes and campuses.
What we set out to change
Give operations one maintainable reference whose relationships remain reliable when other systems read it.
How it is builtData model, code, controls and team ownership
The user journey
- 01
Maintain programmes and their linked campuses.
- 02
Read the selected source fields and distinguish missing data from read errors.
- 03
Preserve valid relationships for downstream consumers.
Base structure
| Entity / table | Key fields | Relationships |
|---|---|---|
| Programmes | Title · pathway · description | Linked campuses and intakes |
| Intakes | Period · programme · campus | Connect the offer to locations |
Technical implementation
- Source entities and relationships have stable identifiers.
- Mappings make the fields shared with downstream products explicit.
- A failed relationship read must not become an instruction to clear existing links.
Engineering decision
A failed read must not erase catalogue relationships
Adapted from the synchronisation guard for programme/category links. A failed source read omits the relationship column; a trusted empty link may clear it. If all links disappear while the publishing database still has relationships, the run preserves them and reports a warning. Renamed entities and an injected database probe keep this excerpt independent of private schema identifiers.
type LinkRead = | { ok: false; reason: "unconfigured" | "read-error" } | { ok: true; links: Map<string, string | null> };export async function catalogueLinkPolicy( source: LinkRead, destinationIds: Map<string, string>, hasPublishedRelationships: () => Promise<boolean>,) { let trusted = source.ok; if (source.ok && destinationIds.size > 0 && ![...source.links.values()].some(Boolean)) { try { trusted = !(await hasPublishedRelationships()); } catch { trusted = false; // unable to verify: preserve the previous links } } return { warning: trusted ? null : "Relationships preserved; inspect source mapping", fieldsFor(sourceId: string): { category_id?: string | null } { if (!trusted || !source.ok) return {}; // omit, do not write null const linkedId = source.links.get(sourceId) ?? null; return { category_id: linkedId ? destinationIds.get(linkedId) ?? null : null, }; }, };}// Merge fieldsFor(id) into an allowlisted upsert row keyed by airtable_id.// Source reading and category synchronisation must complete beforehand.Adapted implementation excerpt
Controls and boundaries
- The browser receives no Airtable token or privileged Supabase key.
- Internal fields and staff data are outside the public catalogue.
- Synchronisation is not publication: permissions, statuses and publishing filters have distinct roles.
Who can contribute
- Operations: maintain programmes, campuses and Airtable links.
- Communications: enrich and approve publication in the web back office.
- Developers: evolve mappings, checks and versioned components.
What supports this case
Source model and synchronisation guard reviewed. This capture shows the internal catalogue; the web journey is presented in the linked Vercel / Supabase implementation.