Architecture

Arc CMS is an Angular app on Firebase. The browser talks to Firestore, Auth and Storage directly, under security rules; Cloud Functions do everything the browser must not, and publish the public pages as plain files on Firebase Hosting.

The pieces

PieceWhat it doesWhere it lives
The appAnalogJS (full-stack Angular), built with Vite. It is the admin area, the member area, the sign-in pages and the fallback for every public address.src/app/, src/shared/, src/custom/
FirestoreAll data: content, settings, people, lists, logs. One database per install, (default) unless the install names another.Rules in firestore.rules
Firebase AuthSign-in. A person's role travels as a custom claim on their ID token (see Roles and claims).functions/src/auth/, functions/src/users/
Cloud StorageMedia, imports and exports, and each person's own folder.Rules in storage.rules
Cloud FunctionsTriggers on database writes, callables the browser calls, scheduled jobs and a few public HTTP endpoints (webhooks, unsubscribe, email tracking). Node.js 22.functions/src/
Firebase HostingServes the built app and the pages the functions publish.firebase.json

How pages are served

No server runs when someone opens a page. Firebase Hosting serves files:

During development, npm run dev also renders pages on the server. Pages that need a signed-in person are always rendered in the browser.

The three areas

AreaAddressesWho gets in
Public site/, content and static pages, /search, signup formsEveryone
Member area/user/dashboard, /user/profile, and your app's own pagesAnyone signed in (route guard in src/app/pages/user/user.guards.ts); premium pages need an entitlement
Admin area/admin/...Admins (route guard in src/app/guards/role.guard.ts)

The sign-in pages (/signup) and the first-run setup (/onboarding) sit between them. The route guards only decide what the browser shows: the security rules and the function checks are what protect the data. See What members see and Use the admin area.

How the functions are grouped

The full list is in Cloud Functions.

Install settings

Which database, bucket, upload folder and hosting site an install uses comes from arccms.config.json. npm run arc:configure and the guided deploy turn it into one file per consumer:

Read byFile
The app (browser and build)src/environments/arc-install.ts, read only by src/app/core/config/arc-config.ts
The functionsfunctions/.env.{projectId}, read only by functions/src/arc-config.ts
The Firebase CLIfirebase.{projectId}.json, used by npm run deploy

With no settings, an install uses the (default) database, the project's default bucket and its main hosting site. See Configure a project and Sharing a Firebase project.

The main data flows

WhenWhat happens
An editor publishes contentThe draft lives in arc_{slug}_drafts. Publishing adds an item to _publish_queue; the processPublishQueue function copies the draft to arc_{slug}, renders its page, the list pages, the sitemap and the feeds, publishes them to Hosting as one release, and updates the search index.
Someone signs upA callable creates the users record on the server. onUserRoleChange puts the role and the record id on the account as claims, which the rules read.
An admin changes a roleThe admin writes role on the users record; onUserRoleChange copies it to the arccms_role claim.
Something happens to a personCore writes an event to AppEvents (such as user.signed_up, user.deleted or user.signInDeleted). Automations, and your app's own triggers, react to it.
A person is deletedDeleting the users record starts onUserDeleted, which ends their access, removes their sign-in (unless another app shares it), their data under the record and their storage folder, then writes user.deleted. See Follow the account contract.