ডকুমেন্টেশন আপাতত শুধুমাত্র ইংরেজি। সাইট বাকি আপনার ভাষা অনুসরণ করে.
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.htmland<slug>/index.htmlfor every published page and post, in the default locale, plus<locale>/…/index.htmlfor each active non-default locale.sitemap.xml,robots.txt,favicon.ico, and the themed404.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 withbytes,sha256, and a suggestedcacheControl._headersfor Cloudflare Pages / Netlify, plus generated.htaccessand_nginx.confwith 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
| How | Notes |
|---|---|
| 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
| Variable | Default | Purpose |
|---|---|---|
STATIC_EXPORT_ENABLED | 1 | Master switch. 0 refuses the Run actions and auto-rebuild; existing files stay on disk. |
STATIC_EXPORT_DIR | ./static-export | Output directory, relative to the install root. |
STATIC_EXPORT_BASE_URL | APP_URL | Public origin recorded in the manifest and used to recognise same-origin links while crawling. |
STATIC_EXPORT_CRAWL_URL | loopback / APP_URL | Origin 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_URL | — | Origin that still serves form/comment POST. When set, <form action> in the output is rewritten to absolute URLs against it. |
STATIC_EXPORT_ALLOWED_ORIGINS | — | Extra origins allowed to cross-origin fetch() the submit endpoints (CORS), comma-separated. |
STATIC_EXPORT_AUTO | 0 | Rebuild incrementally after content, menu, theme, or settings changes (needs CACHE_REVALIDATE_ENABLED=1). |
STATIC_EXPORT_DEBOUNCE_MS | 5000 | Quiet period that coalesces a burst of changes. |
STATIC_EXPORT_MAX_PAGES / STATIC_EXPORT_CONCURRENCY | 2000 / 4 | Crawl 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), andsitemap.xml. - Delete or unpublish so a URL now 404s → that page's files are removed and
sitemap.xmlis rewritten. - Menu, theme, Customizer, CSS provider, or settings change → every route, plus
theme.cssand 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.
# 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.
| Feature | On a static host |
|---|---|
| Forms submission | In 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 submission | Native POST to /justflows-comments/submit; existing threads render at export time and are read-only otherwise. |
| Pageview analytics | Beacon to /justflows-analytics/collect — the Analytics plugin's jf-analytics.js rides the plugin bundle; needs the endpoint reachable. |
| Cookie consent | Banner, 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 / search | Origin 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.