Troubleshooting
The most common problems and how to fix them. Skim the section that matches your symptom.
The most common problems and how to fix them. Skim the section that matches your symptom.
Login + setup
"Permission denied" on first login
Cause: the bootstrap admin email pinned in VITE_ADMIN_EMAIL doesn't match the email pinned in your Firestore rules' bootstrapAdminEmail() function.
Fix: update the rules to match — exact string equality. Firestore Console → Rules → edit → Publish.
SetupForm appears every time I refresh
Cause: the form uploaded config.js successfully but the next request is hitting a cached version (without the populated values) or the upload silently failed.
Fix:
- Hard-refresh (Cmd+Shift+R)
- If still failing, open
https://<your-site>/admin/config.jsin a browser tab — should containwindow.__FLEXWEG_CONFIG__ = { /* values */ };. If it showsnull, the upload didn't take. Check Flexweg's file manager; manually upload a populated file if needed.
"Cannot find Firebase config"
Cause: neither .env nor config.js is providing values.
Fix: ensure either:
.envis filled at build time AND the bundle was rebuilt (npm run build), ORconfig.json Flexweg has the populatedwindow.__FLEXWEG_CONFIG__
Login form rejects valid credentials
Cause: usually Firebase Auth's password hashing or 2FA. Or the user record is missing.
Fix:
- Check Firebase Console → Authentication → Users — does the user exist with the right email?
- Try password reset via the Firebase Console (sends an email)
- Try in an incognito window (rules out browser extensions)
Publishing
"Failed to upload to Flexweg" mid-publish
Cause: typically a transient API hiccup, expired API key, or hitting a plan limit.
Fix:
Check the toast message for the HTTP status code:
- 401 / 403: API key is invalid. Update via Settings → General.
- 413: file too large or storage quota exceeded. Check the Flexweg storage card on the dashboard.
- 429: rate-limited. Wait a few minutes; Flexweg's rate limit resets quickly.
- 5xx: Flexweg server issue. Retry; if persistent, check Flexweg status page.
Click Publish again. The publisher's stale-path-cleanup retries failed deletions automatically.
Page renders but doesn't reach Flexweg
Cause: hash optimisation skipped the upload because the rendered HTML matched lastPublishedHash exactly — but the file isn't actually on Flexweg (you deleted it manually, or Flexweg lost it).
Fix: edit the post and re-save (touches updatedAt), then publish. Or change something that affects rendering (e.g. a setting).
For mass recovery: change settings.title (forces a hash mismatch on every page), regenerate, change it back, regenerate again.
"Failed to render" in publish log
Cause: a plugin's filter or a theme template threw during render.
Fix:
- Check the browser devtools console for the actual error stack
- Disable plugins one at a time to isolate the culprit
- If a theme template, check that BaseLayout includes the required sentinels (
<meta name="x-cms-head-extra" />,<script type="application/x-cms-body-end" />)
Cascade regeneration fails
Cause: the post itself uploaded fine but a category archive or sitemap failed.
Fix: post is online but listings are stale. Run Themes → Regenerate site → All HTML pages to recover.
Plugins / themes don't appear after install
Cause: external bundle failed to load (network error, parse error, apiVersion mismatch).
Fix:
- Check the browser devtools console — the boot loader logs every external load attempt
- For apiVersion mismatch: the bundle was built against a different admin version. Re-build the external against your admin's
FLEXWEG_API_VERSIONor upgrade the admin - For parse errors: the bundle is malformed (CommonJS instead of ESM, missing externalised imports). Re-build with the correct Vite config
Theme / CSS
Public site CSS is stale after editing theme settings
Cause: browsers / CDN caching the old CSS file at theme-assets/<id>.css.
Fix:
- Hard-refresh on a browser (Cmd+Shift+R)
- Or wait for the cache TTL (~few minutes for most browsers + CDNs)
- For instant updates: configure your CDN to set
Cache-Control: no-cacheon/theme-assets/*— but you'll lose the cache benefits for everyone
Theme preview doesn't match published page
Cause: usually a SCSS / Tailwind config divergence between admin (where the preview renders) and Flexweg (where the published page loads CSS).
Fix:
- Run Themes → Sync theme assets to push the latest theme CSS to Flexweg
- Then Themes → Regenerate site → All HTML pages to re-render every page against the latest CSS
Tailwind classes missing from a theme's runtime-injected DOM
Cause: the theme's tailwind.config.cjs has a content glob that doesn't include .js files. The Tailwind CLI's purge step strips classes that aren't referenced from scanned files.
Fix: add .js to the content glob:
content: ["./src/themes/<id>/**/*.{ts,tsx,html,js}"]
Theme settings aren't taking effect
Cause: the theme has a compileCss hook that needs to run; just saving doesn't auto-upload the CSS.
Fix: most theme settings pages run compileCss(savedConfig) + upload automatically on save. If yours doesn't (custom theme), add an applyAndUploadCustomCss({ themeId, baseCssText, config: next }) call after save(next).
For built-in themes: this should always work. If it doesn't, run Themes → Sync theme assets manually.
Editor
Block toolbar doesn't appear
Cause: the cursor isn't on a top-level block, or the block is too tall to render the floating toolbar above it.
Fix:
- Click directly inside the block content
- Scroll so the block's top edge is visible
Custom HTML block content doesn't render in editor preview
Cause: the rendered HTML is broken (unclosed tag, syntax error).
Fix: check your HTML for syntax errors. The block uses dangerouslySetInnerHTML — what you see in the published page is what you see in the editor. If it doesn't render in editor, it won't render in publish.
Embed shows "Loading..." forever
Cause: the embed provider's runtime script isn't loading (Twitter widgets.js, etc.).
Fix:
- Check browser console for blocked third-party scripts
- Check that
flexweg-embedsis registered (it's MU — should always be) - For corporate networks blocking Twitter: nothing to do — the visitor's network is the issue
Public site
404 on a published page
Cause: file isn't actually on Flexweg, or you're hitting a wrong URL.
Fix:
- Open
https://<your-site>/<path>directly to confirm 404 - Check Flexweg's file manager — is the file at the expected path? If not, re-publish.
- If file exists but URL is 404, check for case mismatch — Flexweg is case-sensitive on file paths.
Stale URL still serves old content
Cause: the post's URL changed (slug edit) but the cleanup didn't run (e.g. publisher crashed mid-cycle).
Fix:
- Note the old URL
- Delete the file via Flexweg's file manager
- The post is online at the new URL; old URL now 404s as expected
Wrong language in <html lang>
Cause: site language wasn't updated, or pages weren't regenerated after the change.
Fix: Settings → General → Language → set correct → Save → Themes → Regenerate site → All HTML pages.
Menu changes don't appear
Cause: /menu.json didn't re-upload, or the page is using the static cache.
Fix:
- Save the menu in the admin again (forces a new upload)
- Hard-refresh the public site
- Verify
/menu.jsonhas the right content (open in browser)
Data + permissions
"Missing or insufficient permissions" reading Firestore
Cause: the rules block the user.
Fix:
- Check the user is signed in
- Check the user has a
users/{uid}doc withrole: "admin"or"editor" - Check the rules match — see Firestore rules
Editor can't publish
Cause: config/flexweg has stricter rules than posts / pages. Editors can save drafts but can't publish (publishing reads the API key).
This is intentional — see Users and roles. Promote the user to admin if they should be able to publish.
Composite index missing in paginated mode
Cause: you switched to paginated mode without creating the required composite indexes.
Fix: the in-app FirestoreSetupGate should appear on first paginated query and offer one-click create links. If it doesn't, see Settings → Performance for manual creation paths.
Performance
Admin is slow on a large site
Cause: global pagination mode keeps every post in memory.
Fix: switch to paginated mode (Settings → Performance). Create the required composite indexes. See Settings → Performance.
Regenerate site → Everything takes forever
Expected for large sites. The throttle is 75 ms/upload by design. A 5 000-post site is ~7 minutes.
Workarounds:
- Run Everything overnight (kick it off, walk away)
- Run subset targets (e.g. just All HTML pages — skip the plugin regenerations)
- Edit
regenerateAll's throttle in the publisher source to be faster (risk: hitting Flexweg rate limits)