Skip to main content

Troubleshooting

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:

  1. Hard-refresh (Cmd+Shift+R)
  2. If still failing, open https://<your-site>/admin/config.js in a browser tab — should contain window.__FLEXWEG_CONFIG__ = { /* values */ };. If it shows null, 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:

  • .env is filled at build time AND the bundle was rebuilt (npm run build), OR
  • config.js on Flexweg has the populated window.__FLEXWEG_CONFIG__

Login form rejects valid credentials​

Cause: usually Firebase Auth's password hashing or 2FA. Or the user record is missing.

Fix:

  1. Check Firebase Console → Authentication → Users — does the user exist with the right email?
  2. Try password reset via the Firebase Console (sends an email)
  3. 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:

  1. 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.
  2. 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:

  1. Check the browser devtools console for the actual error stack
  2. Disable plugins one at a time to isolate the culprit
  3. 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:

  1. Check the browser devtools console — the boot loader logs every external load attempt
  2. For apiVersion mismatch: the bundle was built against a different admin version. Re-build the external against your admin's FLEXWEG_API_VERSION or upgrade the admin
  3. 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-cache on /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:

  1. Run Themes → Sync theme assets to push the latest theme CSS to Flexweg
  2. 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:

  1. Check browser console for blocked third-party scripts
  2. Check that flexweg-embeds is registered (it's MU — should always be)
  3. 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:

  1. Open https://<your-site>/<path> directly to confirm 404
  2. Check Flexweg's file manager — is the file at the expected path? If not, re-publish.
  3. 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:

  1. Note the old URL
  2. Delete the file via Flexweg's file manager
  3. 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.

Cause: /menu.json didn't re-upload, or the page is using the static cache.

Fix:

  1. Save the menu in the admin again (forces a new upload)
  2. Hard-refresh the public site
  3. Verify /menu.json has the right content (open in browser)

Data + permissions​

"Missing or insufficient permissions" reading Firestore​

Cause: the rules block the user.

Fix:

  1. Check the user is signed in
  2. Check the user has a users/{uid} doc with role: "admin" or "editor"
  3. 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)

Continue​