Data import and export
Download a JSON copy of your content, users, audience, settings and email data, and a ZIP of your media files, then load them back into the same install or a new one.
What it is
The Data admin menu has four screens:
| Screen | Address | Does |
|---|---|---|
| Export Data | /admin/data/export-data | Downloads chosen Firestore collections as one JSON file |
| Import Data | /admin/data/import-data | Writes the collections of such a file back into Firestore |
| Export Files | /admin/data/export-files | Downloads media library images and files as a ZIP with a manifest |
| Import Files | /admin/data/import-files | Uploads files to Storage and adds them to the media library; documents go to its Files |
Everything runs in the admin's browser, with the admin's own permissions. There are no Cloud Functions involved.
For creating content entries from a spreadsheet, use the content type's Bulk Import instead (Content). For contacts from a CSV, see Audience.
Turn it on or off
Data import and export is a switchable feature with the id data. It is on by default and needs no other feature. To turn it off, list it in src/custom/features.ts:
export const CUSTOM_FEATURES: FeatureChoice = {
off: ['data'],
};
When it is off, the Data menu goes and its addresses show the not-found page. Nothing is stored by this feature, so nothing is left behind. See Feature ids.
Set it up
Nothing to set up. The screens need an admin account and the deployed security rules.
Use it
Export data
Open Data > Export Data.
Pick a preset (Everything, All Content, All Settings) or tick collections by group. Picking a content type takes its drafts, its published entries and its tags together.
Export. The browser downloads
arccms-export-{date}.json.
| Group | Collections |
|---|---|
| Content | ContentTypes, and per type arc_{slug}_drafts, arc_{slug}, Tags_{slug} |
| Users and waitlists | users, Waitlists with each form's users, WaitlistedUsers |
| Audience | Contacts, Lists, ContactTags, Suppression |
| Settings and media | Settings, media (the records, not the files) |
EmailTemplate, BroadcastEmails, EmailLogs |
Collections of a feature that is off are not offered. Nothing else is exported: not Authors, not content translations or version history, not payments, feedback or notification data.
An export holds personal data (users, contacts with their consent state) and secrets (the Settings documents carry email provider passwords and API keys). Store the file as you would a database backup.
The file format
{
"version": "1.0",
"exportedAt": "2026-09-30T10:00:00.000Z",
"collections": {
"ContentTypes": { "articles": { "name": "Articles", "slug": "articles" } },
"Waitlists/waitlist/users": { "abc123": { "email": "a@example.com" } }
},
"metadata": { "totalDocuments": 2, "collectionSummary": [ { "name": "ContentTypes", "count": 1 } ] }
}
Keys under collections are collection paths, then document ids. Firestore timestamps, document references and geo points are written as objects with a __type of timestamp, ref or geopoint, and turned back into those types on import.
Import data
Open Data > Import Data and choose an export file. It is checked for a
versionand acollectionsobject; unknown collections are flagged but can still be imported.Tick the collections to import.
Choose what happens to a document that already exists:
Mode Existing document Skip existing (default) Left as it is Overwrite Replaced by the file's version Merge The file's fields are written over it; other fields stay Import. Document ids are kept. Collections go in a fixed order so that what others refer to comes first: content types and settings, then tags, users, drafts and published entries, media records and email templates, then signup forms, audience, broadcasts and email logs. Writes go in batches of 500. A content type whose slug another type on the site (or earlier in the file) already uses is not imported, and the result lists it as an error: the same type, with the same document id, is imported as usual. A type already on the site, by document id, whose slug in the file differs (or is missing, when existing documents are overwritten) is not imported either while entries, drafts or tags are stored under its current slug, since they would be left behind; the edit form locks the slug for the same reason. To restore a type over one the setup wizard created, such as Articles, delete the wizard's type first, then import.
Importing published entries restores the data, not the pages. Rebuild the pages on Hosting after an import with npm run seed:dev (or npm run seed:prod); see How publishing works.
Contacts and Suppression can only be written by Cloud Functions, so importing them fails with a permission error even for an admin. Rebuild an audience with the contact CSV import on the Audience page.
Importing users into another Firebase project creates the records but not the sign-in accounts, so those people cannot sign in until their accounts exist again. See Users and roles.
Export files
Data > Export Files lists the media library: its images, then its files (PDFs and other documents, shown with their first page or an icon). Select items and download arccms-media-{date}.zip: one file per item (the largest stored size of an image) and media-manifest.json with each item's name, URL, Storage path and upload time, its title, alt text and notes when it has them, and "collection": "mediaFiles" for a file.
Import files
Data > Import Files has two modes:
| Mode | Does |
|---|---|
| Upload new files (recommended) | Choose files and a Storage path prefix (default mediaImages/). Each file is uploaded under it. A document the library takes (PDF, Word, Excel, PowerPoint, CSV, text) goes to the library's Files instead, whatever the prefix, stored the way the Files tab stores it, with a fresh first-page picture for a PDF. |
| Restore from manifest | Choose a media-manifest.json and the files. Files are matched by the name in the manifest and uploaded to the path it records, with the title, alt text and notes it carries. A library file goes back to Files with its title and notes. |
With Update media collection metadata ticked (the default), each uploaded file also gets a new media record (a mediaFiles record for a document), with a new id. Unzip the export first: the screen takes files, not the ZIP. Imported files are stored as they are, at one size.
Content stores full image URLs. After moving to another project, entries still point at the old project's Storage, so images keep working only while the old files exist. Re-pick the images in the editor if the old project goes away.
Extend it
The exported collections are listed in KNOWN_COLLECTIONS in src/app/pages/admin/(data)/data-constants.ts, a core file. An app's own collections are not exported; back them up with your own tooling, or say so as a core feature request (Keep core generic).
What it stores
Nothing of its own. Export reads the collections above; import writes them, plus Storage files and media records (downloadURL, name, storagePath, uploadTime) for imported files. There are no Cloud Functions. Collection details are in Data model.
Who can do what
The Data screens are admin only. Every read and write is the admin's own, so each collection's security rules apply as usual: an admin can read and write everything offered except Contacts and Suppression, which admins can read but only Cloud Functions write. Storage uploads need an admin (or the reserved editor role). See Security rules.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
Invalid JSON file or Missing "version" field | The file is not an Arc CMS export. Use a file from Export Data, unedited. |
| Some documents report "Missing or insufficient permissions" | The collection is written only by Cloud Functions (Contacts, Suppression), or the rules are not deployed. A failure fails its whole batch of up to 500 documents. |
| Imported entries are not on the site | Run the seed to rebuild the pages. |
| Nothing is skipped although documents exist | Merge or Overwrite was chosen. Skip existing is the only mode that leaves them alone. |
| Restore from manifest uploads nothing | No chosen file has the exact name the manifest records; files in the export ZIP can carry an extra extension (photo-xl.webp.webp). Use Upload mode instead. |
| A large export stalls | The whole file is built in the browser's memory. Export one group at a time. |