Repository navigation
v0.1.9
Added
- Plugin-owned admin apps. A plugin can declare
adminAppin its manifest and
ship a self-contained HTML build; the host serves it at
/ext/<pluginId>/admin/**and mounts each declared route in a same-origin
<iframe>inside the admin shell (PluginHostPage). The two sides talk only
overpostMessagevia the new@justflows/admin-bridgepackage — no shared
React runtime, no core page, no core route. See
PLUGINS.md → Ship your own admin app.
(#24)
Changed
-
Forms is now a fully standalone plugin. The host no longer implements it:
lib/forms-public.ts,routes/forms.ts(/api/forms), the
/justflows-forms/submitendpoint, thejustflows.forms.formrender
special-case and/js/jf-forms.jsinjection inpublic-site.ts, the
plugin-runtimeactivation skip, theadmin-menu/plugins-dbfallbacks,
and the admin-UIFormsPage+BlockInspectorpicker were all removed. The
plugin (plugin-registry-service/plugins/formsv0.2.0) ships its own block,
submit route, admin app, and public enhancement script. The additive,
permission-gatedctx.mail.send()SDK API lets Forms send submission
notifications through the host-configured transport without exposing mail
credentials; a multi-form site loses the block's form picker until a generic
plugin-block inspector lands.
(#24) -
Static / edge export. A new exporter
(apps/server/src/lib/static-export/) crawls the site's own running server
over loopback and writes every published page, its assets, locale variants,
sitemap.xml,robots.txt,favicon.ico, the themed404, and the
/theme.cssbuild toSTATIC_EXPORT_DIR(default./static-export), plus a
_static-export.jsonmanifest with per-filesha256andCache-Control
advice, plus a Cloudflare Pages / Netlify_headersfile derived from the
active Performance suite browser-cache settings. Run it from Admin → System →
Tools → “Static site export”,pnpm export:static, or
justflows export static. A master
STATIC_EXPORT_ENABLEDswitch, output directory, public base URL,
dynamic-endpoint origin, crawl limits, and auto-rebuild are editable from the
Tools page and written to.env(STATIC_EXPORT_*), applied without a
restart. Clear export (Tools card /pnpm export:static -- --clear)
deletes the whole output folder; disabling the feature or auto-rebuild leaves
files on disk.STATIC_EXPORT_AUTO=1re-runs a targeted incremental export (and
prunes removed pages) after publish, unpublish, delete, menu, theme, or
settings changes, debounced via the existingcache.revalidatedaction.
Every same-origin sub-resource a page references is downloaded —/theme.css,
/js/*, uploads, and plugin / custom-theme scripts and assets on their own
paths (/ext/<plugin>/…,/themes/<theme>/…); only/admin,/apiand the
auth/submit endpoints are skipped. A targeted incremental run also fetches any
asset a rebuilt page newly references (an image or gallery block added to a
page) even though it skips re-downloading unchanged ones — previously those
files 404'd on the static host until the next full export. The
staticExport.assetsfilter adds URLs the scanner cannot see. Plugins can now ship client-side assets first-class: a
manifest.assetsblock ({ dir?, scripts?, styles? }) makes the host serve
<dir>/**at/ext/<id>/**— noctx.httproute orhtml.headfilter —
and concatenate every active plugin's scripts/styles into one
content-hashed/jf-plugins.<hash>.{js,css}bundle added to each public
page (PLUGIN_ASSETS_BUNDLE=0for one tag per file). A marketplace plugin's
front-end lands in the export automatically as that single bundle
(plugins/hello-worlddemonstrates it). Pageview analytics keep counting: the
Analytics plugin ships ajf-analytics.jsbeacon viamanifest.assets, so it
rides the/jf-plugins.<hash>.jsbundle into the export with no
analytics-specific code in the exporter. The exporter only stamps every page
with a genericwindow.__JF_ORIGIN__hint; the beacon acts on that stamp
(absent on the live server render, where views are counted server-side) and
POSTs to the/justflows-analytics/collectingest endpoint (rate-limited,
CORS). The Cookie Consent runtime ships the same way, and its two calls (the
record beacon and the cookie-disclosure fetch) resolve against
window.__JF_ORIGIN__too, so a split-origin export still reaches them. Two
additivePluginHttpResponsefields back this:revalidate: trueruns the
site-wide cache revalidation thatPUT /api/plugins/<id>/settingsdoes (so
saving Consent settings regenerates the export under auto-rebuild, not only
after a manual full export), andcors: trueadds
Access-Control-Allow-Originfor a vouched-for export origin on a public read
the runtime fetches cross-origin (the Consent cookie-disclosure route). The
Forms enhancement script ships the same way. Form blocks now
submit in place:jf-forms.js
posts byfetch()and shows the confirmation without leaving the page
(native<form>POST is the no-JS / CAPTCHA fallback);/justflows-forms/submit
gained a JSON response mode and CORS for allowed origins
(APP_URL/STATIC_EXPORT_BASE_URL/STATIC_EXPORT_ALLOWED_ORIGINS, plus
localhostoff production). Keep the submit endpoint reachable via a hybrid
proxy orSTATIC_EXPORT_ORIGIN_URL(which also rewrites<form action>to an
absolute URL). Object-storage/CDN deployment is documented (aws s3 sync/
rclone/rsync+ manifest-driven invalidation) with additive
staticExport.routes/staticExport.assets/staticExport.formAction/
staticExport.completed/staticExport.deploySDK hooks. See
docs/STATIC-EXPORT.md.
(#24) -
The page builder now has a categorized block-pattern library with theme-width
previews, editable insertion, six accessible token-driven section starters,
local and optionally synced site patterns, locale variants and RTL-aware UI,
validated JSON import/export, additive theme SDK registration, required-block
checking,ctx.patterns.register()contributions with automatic plugin
lifecycle cleanup, and a bounded, sanitized opt-in marketplace directory.
(#110) -
Admin → System → Diagnostics completes the developer-tooling workflow with
plugin scheduler status and safe failed-job retries, non-destructive database,
cache, and scheduler test actions, copyable CLI reproduction guidance, and an
additivectx.diagnostics.register()SDK for permission-gated, namespaced,
sanitized plugin health checks. This builds on the debug toolbar, request
traces, support bundles, and core diagnostics shipped in 0.1.8.
(#57)
Fixed
- Static export on a proxied host (Passenger, Plesk) no longer fails with
"The site at http://127.0.0.1:3000 is not installed yet — nothing to
export." The crawl origin now resolves toSTATIC_EXPORT_CRAWL_URL(new,
editable on the Tools page) or, on production,APP_URL— the site's real
domain — falling back to loopback only in development or when neither is set.
The production bootstrap wrapper (server.js) answered/api/healthzwithout
theinstalledflag the full app includes, so over the public URL the export
read the site as uninstalled; the wrapper now mirrors the full app's healthz
shape. As a belt-and-braces measure the readiness check no longer trusts a
bare/api/healthz: an unclear health result is cross-checked against/,
which only redirects to/installwhen the site genuinely is not set up, so
an installed site behind any intercepting layer still exports. The exporter
also retries once againstAPP_URL, and the failure message now names every
origin it tried.
(#24)