XiCMS — documentatie
XiCMS is de herbruikbare CMS-basis waarop alle Xi Webdesign klantsites draaien. De motor is het npm-package @xiwebdesign/xicms-core; elke klantsite is een dunne laag met alleen eigen content en styling erbovenop. Deze pagina vat samen hoe het werkt — de volledige docs (README, ARCHITECTURE, RECREATE, HANDOFF) staan in de repository.
Motor vs. carrosserie
| Laag | Waar | Wijzigt per klant? |
|---|---|---|
@xiwebdesign/xicms-core (engine) | packages/core | Nee — gedeeld, versioned |
| Klantsite (content + styling) | eigen repo (kopie van template/) | Ja — alleen hier |
| Firebase (data) | één gedeeld project | Gescheiden per siteId |
Gulden regel: de engine bevat nooit site-specifieke code. Alles wat per klant verschilt leeft in content/site.config.ts en de pagina-compositie van de klantrepo. En de content (teksten, foto's, nieuws) hoort in Firebase — niet in Git.
Het package gebruiken
Consumers installeren de engine vanaf GitHub Packages. Voeg een .npmrc toe:
@xiwebdesign:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}npm i @xiwebdesign/xicms-coreWikkel de site in de provider; content bestaat uit pagina's met blokken:
// app/layout.tsx
import "@xiwebdesign/xicms-core/styles.css";
import { XiCMSProvider } from "@xiwebdesign/xicms-core";
import { siteConfig } from "@/content/site.config";
export default function RootLayout({ children }) {
return <XiCMSProvider config={siteConfig}>{children}</XiCMSProvider>;
}// app/[[...slug]]/page.tsx
import { PublishedPage } from "@xiwebdesign/xicms-core";
import { getPublishedPageByPathExpanded, pathFromSlugs } from "@xiwebdesign/xicms-core/server";
import { siteConfig } from "@/content/site.config";
export default async function CatchAllPage({ params }) {
const { slug } = await params;
const page = await getPublishedPageByPathExpanded(siteConfig.siteId, pathFromSlugs(slug));
return <PublishedPage page={page} siteId={siteConfig.siteId} />;
}Datamodel (multi-tenant, één project)
sites/{siteId} metadata: naam, domein, mode (demo|live)
sites/{siteId}/pages/{pageId} gepubliceerde pagina: { title, path, seo, blocks[] }
sites/{siteId}/drafts/{pageId} werkversie (autosave vanuit de visuele editor)
sites/{siteId}/symbols/{id} gedeelde secties (propageren naar elke pagina)
sites/{siteId}/customBlocks/{t} eigen bloktypes (Field-IR + veilige template)
sites/{siteId}/news/{articleId} { title, slug, excerpt, body, coverUrl, date, published }
sites/{siteId}/media/{mediaId} { url, path, name, contentType, size }
users/{uid} { email, displayName }Rollen
- superadmin — maakt sites en accounts aan, mag alles.
- siteadmin — beheert één site volledig.
- editor — bewerkt content/media/nieuws van één site.
Rechten lopen via Firebase Auth custom claims; claims worden alleen door Cloud Functions gezet die controleren dat de aanroeper superadmin is.
De demo-workflow
Demo bouwen
Kopie van template/, alleen site.config.ts aanpassen, mode: "demo".
Content seeden
Gescrapte content per siteId naar Firebase met scripts/seed.ts.
Live zetten
mode: "live", beheeraccount aanmaken, domein koppelen.
Updaten zonder klantsites te breken
Verbeter de engine → npm version → npm publish. Klantsites bumpen hun versie en deployen opnieuw. Semver: minor/patch is veilig; major komt met migratienotes. Omdat klantsites nooit in de core schrijven en alle data per siteId gescheiden is, raakt een update nooit hun content of styling.