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

LaagWaarWijzigt per klant?
@xiwebdesign/xicms-core (engine)packages/coreNee — gedeeld, versioned
Klantsite (content + styling)eigen repo (kopie van template/)Ja — alleen hier
Firebase (data)één gedeeld projectGescheiden 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-core

Wikkel 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

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 versionnpm 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.

Naar de live demo →