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