FAQ and troubleshooting
Two parts. First the questions we get before anyone connects a first site. Then troubleshooting: every cause described here matches a real behaviour of the loader, the CLI or the admin, with the exact messages.
Product FAQ
Section titled “Product FAQ”What if Menestrel shuts down?
Section titled “What if Menestrel shuts down?”Your site keeps running. Graceful failure is not a marketing promise, it is structural:
- The production site does not depend on us. It is a set of static files at your host: nothing in the serving path of a page goes through Menestrel.
- Builds still pass.
MENESTREL_CONTENT_URLreads the published snapshot from the CDN, not from the application. A redeploy during an outage, or after one, succeeds. - The full export is available on every plan, free included.
npx menestrel exportwritescontent/as Markdown,data/as verbatim JSON andmedia/with the originals. No proprietary format, no support ticket.
After cancellation, content is kept for 30 days, with an export offered before deletion. The full mechanism is described in How Menestrel works.
Why Astro only?
Section titled “Why Astro only?”Because depth of integration cannot be shared. The loader is a native Content Layer loader: entries come out typed, with ids designed for getStaticPaths, and the locale and translations exposed for your i18n routing. menestrel import reads your content collections directly. The components (RichText, CmsImage, CmsSeo) are Astro components.
A “works with every framework” CMS would have had to give all of that up. The two latest Astro majors are supported, see Astro compatibility. If your site is not on Astro, Menestrel is not for you, and we would rather say so.
Where is my data?
Section titled “Where is my data?”In France. The database, the media and the snapshots are hosted at Scaleway, Paris region. Public distribution goes through a European CDN (Bunny). A DPA can be signed online, the sub-processor list is public, and the admin runs no third-party trackers. The details, retention periods included, are in API tokens and security.
Does my site really stay 100% static?
Section titled “Does my site really stay 100% static?”Yes. Content is only needed at build time: the loader reads a published snapshot, astro build produces static files, and in production the site sends no request to Menestrel, neither on page load nor in the background. A traffic spike on your site is your static host’s business, never the CMS’s.
How much does it cost?
Section titled “How much does it cost?”Free for one site (1 site, 2 editors, 200 entries, 2 locales). After that, €3/month per site billed yearly, or €5/month with no commitment. The price you sign up at is locked for life. The full plans are on menestrel.dev.
Troubleshooting
Section titled “Troubleshooting”The build returns an empty collection
Section titled “The build returns an empty collection”getCollection() returns [] while the admin shows content. Three real causes, in the order to check them:
MENESTREL_OFFLINE=1is still in the.env. It is the loader’s highest priority: even withMENESTREL_CONTENT_URLorMENESTREL_TOKENset, it reads.menestrel/snapshot/, that is the starter’s demo fixture or an oldpull. The starter sets this variable by default;menestrel initcomments it out when it installs your token. Comment it out, or refresh the cache withnpx menestrel pull.- Nothing is published in that collection. A snapshot only contains published entries: a draft never appears in it. An entry not published in a locale is served with its fallback locale, then with the default locale; it only disappears from a locale when no locale in its fallback chain is published. Check the per-language status in the admin, then publish.
- The snapshot being read is not the latest. A pinned
MENESTREL_SNAPSHOT_IDor apullolder than the publication serves you content that is exact, but stale.
If no source is configured (no URL, no token, no offline mode), there is no silent empty collection: the build fails with this message, escape hatch included.
[menestrel] No content source configured. Set MENESTREL_CONTENT_URL, or MENESTREL_TOKEN, or run `npx menestrel pull` and set MENESTREL_OFFLINE=1.The loader fails with HTTP 401 or 403
Section titled “The loader fails with HTTP 401 or 403”The message looks like [menestrel] GET https://... failed with HTTP 401. The two codes do not mean the same thing:
- 401: the token is unknown, revoked or expired. The response never says which, on purpose: a stolen secret teaches nothing to whoever tests it. Create a new token in “Site settings”, “API tokens” tab, and replace the old one in the
.envor at your host. - 403: the token exists but its scope is not enough.
sync,importandexportrequire anadmintoken (prefixcmt_adm_); for the loader at build time,read_published(cmt_pub_) is enough.
In production, the best move is still to set no token at all: with MENESTREL_CONTENT_URL, the build reads the CDN and can no longer hit a 401. See Environment variables.
The deployment does not trigger
Section titled “The deployment does not trigger”Publishing does create a snapshot, but nothing rebuilds. Everything can be checked in “Site settings”, “Deployment” tab:
- No host connected. Publishing materializes the snapshot, but nothing rebuilds until a host is wired up.
- The target is “Paused”. After three consecutive trigger failures, Menestrel stops hammering the host and pauses the target. Fix the configuration (hook deleted on the host side, revoked token…), then click “Resume”: the failure counter starts over from zero.
- The target is “Disabled”. It was switched off on purpose: “Enable” button.
- It is not broken, it is batched. Each project has a build batching window (90 seconds by default, adjustable), plus an hourly trigger quota depending on the plan. Bursts of publications are grouped, never rejected.
The full cycle, deployment state machine included, is in Publishing and versions.
The import was interrupted
Section titled “The import was interrupted”Run the same command again. menestrel import keeps local state in .menestrel/import-state.json, written atomically after each entry, and resuming never duplicates:
- entries already created are skipped (counted as “skipped”), never recreated;
- media files are deduplicated by SHA-256 checksum: nothing is re-uploaded;
- a kill in the middle of a request is covered: if the server had already created the entry (slug already taken, singleton already present), the resume flags it (
already_existswarning) instead of duplicating it.
A source file modified after the import is flagged (source_changed warning) but never re-imported: once the migration is done, the admin is the only source of truth. The full walkthrough is in Import an existing site.