JustFlows

दस्तऐवजीकरण आतासाठी फक्त इंग्रजी आहे. उर्वरित साइट तुमच्या भाषेचे अनुसरण करते.

Static / edge export

Crawl your own running site and write every published page, asset, locale, sitemap, and the built stylesheet to a folder you can serve from object storage or a CDN — no Node origin required for those pages.

9 मिनिटे वाचले

The exporter crawls the site's own running server — over loopback, or its real domain on a proxied host — so the output is byte-for-byte what a visitor receives: the active theme, the template hierarchy, blocks, localized routes, the SEO <head>, favicon, and the /theme.css build all come out unchanged. Use it for marketing sites, documentation, and campaign pages that get far more reads than writes.

What a run produces

  • index.html and <slug>/index.html for every published page and post, in the default locale, plus <locale>/…/index.html for each active non-default locale.
  • sitemap.xml, robots.txt, favicon.ico, and the themed 404.html.
  • theme.css, /js/*, /uploads/*, plugin and custom-theme assets on their own paths (/ext/<plugin>/…, /themes/<theme>/…) — every same-origin sub-resource an exported page references.
  • _static-export.json — a manifest listing every file with bytes, sha256, and a suggested cacheControl.
  • _headers for Cloudflare Pages / Netlify, plus generated .htaccess and _nginx.conf with serving rules, hardening, security headers, and a commented hand-off for the dynamic surface.

Link discovery is breadth-first from the sitemap and published entries, so menu targets and /slug/page/N pagination are picked up automatically. STATIC_EXPORT_MAX_PAGES (default 2000) caps a runaway crawl.

Running an export

HowNotes
Admin → System → Tools → “Static site export”Run full export / Run incremental, with a live log. Administrator only.
pnpm export:static [-- --incremental] [-- --base-url URL]For CI / cron. Needs a compiled server and a running site.
justflows export static [--incremental]Posts to the admin API using the same auth rules as justflows cache clear.

A full export always prunes: any file under the output directory that the run did not produce is deleted, so a full run is the way to recover from a divergent tree. Clear export (Tools card, or pnpm export:static -- --clear) deletes the whole output folder.

Configuration

VariableDefaultPurpose
STATIC_EXPORT_ENABLED1Master switch. 0 refuses the Run actions and auto-rebuild; existing files stay on disk.
STATIC_EXPORT_DIR./static-exportOutput directory, relative to the install root.
STATIC_EXPORT_BASE_URLAPP_URLPublic origin recorded in the manifest and used to recognise same-origin links while crawling.
STATIC_EXPORT_CRAWL_URLloopback / APP_URLOrigin the crawler fetches from. Set it to your public domain when the app runs behind Passenger / Plesk, where a loopback port is unreachable.
STATIC_EXPORT_ORIGIN_URLOrigin that still serves form/comment POST. When set, <form action> in the output is rewritten to absolute URLs against it.
STATIC_EXPORT_ALLOWED_ORIGINSExtra origins allowed to cross-origin fetch() the submit endpoints (CORS), comma-separated.
STATIC_EXPORT_AUTO0Rebuild incrementally after content, menu, theme, or settings changes (needs CACHE_REVALIDATE_ENABLED=1).
STATIC_EXPORT_DEBOUNCE_MS5000Quiet period that coalesces a burst of changes.
STATIC_EXPORT_MAX_PAGES / STATIC_EXPORT_CONCURRENCY2000 / 4Crawl ceiling and parallel fetches.

All of these are editable from Admin → System → Tools → “Static site export” → Configuration — the admin writes them to .env and applies them in place, no restart. Absolute URLs *inside* the exported HTML/XML (<link rel="canonical">, og:url, every <loc> in sitemap.xml) are rendered by the origin from APP_URL and are not rewritten, so set APP_URL to the public origin the files will be served from.

Rebuild and invalidation

  • Publish / unpublish / update a page → that page's routes (per the manifest deps), its translation siblings, every route with a dynamic list (blog / archive / home), and sitemap.xml.
  • Delete or unpublish so a URL now 404s → that page's files are removed and sitemap.xml is rewritten.
  • Menu, theme, Customizer, CSS provider, or settings change → every route, plus theme.css and other assets.
  • Newly published page → picked up by the incremental run that publish triggers; discovery re-reads the live sitemap and published list.

Deploying the output

Point a static web server (nginx, Caddy, Apache) at the output directory with directory-index resolution, or use the generated .htaccess / _nginx.conf. The exporter uploads nothing itself — sync the folder with a tool you already run and drive CDN invalidation from the manifest.

shell
# S3 + CloudFront
aws s3 sync ./static-export s3://my-bucket --delete
aws cloudfront create-invalidation --distribution-id XXXX --paths '/*'

# rclone (S3, GCS, R2, B2, …)
rclone sync ./static-export remote:my-bucket --checksum

# plain rsync to an edge box
rsync -a --delete ./static-export/ deploy@edge:/var/www/site/

Register a staticExport.deploy action in a plugin to automate the push — it receives { outDir, publicUrl, manifest, summary } after every successful run. staticExport.routes, staticExport.assets, and staticExport.formAction filters and the staticExport.completed action are also available.

Dynamic features off-origin

The exported pages are complete server-rendered HTML plus the site's client-side JavaScript. Menus, animations, the language switcher, and block / plugin / theme client code all run with no origin. A plugin's front-end needs no export-specific work: declare assets in its manifest and its script rides the /jf-plugins.<hash>.js bundle the exporter downloads.

FeatureOn a static host
Forms submissionIn place via fetch() to /justflows-forms/submit — needs the endpoint reachable (hybrid proxy or STATIC_EXPORT_ORIGIN_URL); native POST is the no-JS fallback.
Comment submissionNative POST to /justflows-comments/submit; existing threads render at export time and are read-only otherwise.
Pageview analyticsBeacon to /justflows-analytics/collect — the Analytics plugin's jf-analytics.js rides the plugin bundle; needs the endpoint reachable.
Cookie consentBanner, preference center, and script / embed gating work offline; the record beacon and cookie-disclosure fetch resolve against window.__JF_ORIGIN__ and need the endpoint reachable.
Login / register / password reset / searchOrigin only — never route these to the static host.

Tip

A same-origin hybrid deployment — the web server serves the static folder and the dynamic prefixes (/api, /admin, /justflows-forms/, …) fall through to the app — needs no CORS and no allow-list. Prefer it unless the host genuinely cannot proxy. See docs/STATIC-EXPORT.md in the CE repository for full nginx / Apache / Passenger examples.