diff --git a/docs/blog/posts/2026-08-17-one-command-self-hosting.md b/docs/blog/posts/2026-08-17-one-command-self-hosting.md new file mode 100644 index 00000000..909dbef8 --- /dev/null +++ b/docs/blog/posts/2026-08-17-one-command-self-hosting.md @@ -0,0 +1,53 @@ +--- +title: Fluxify now starts from a single docker run +date: 2026-08-17 +author: Prajwal Aradhya +tags: + - release + - self-hosting + - engineering +--- + +# Fluxify now starts from a single docker run + +Trying Fluxify used to mean copying an environment file, filling in a database URL, a cache host, and an event bus token, then bringing up four containers with `docker compose` before you'd seen a single screen of the product. That's a reasonable price to pay for a production deployment, but it's the wrong first five minutes for someone who just wants to see what Fluxify does. + +The trial image now ships everything it needs. One command: + +```bash +docker run -d --name fluxify \ + -p 8080:8080 \ + -v fluxify_data:/data \ + -e SEED_USER_EMAIL=admin@example.com \ + -e SEED_USER_PASSWORD=ChangeThisPassword123! \ + fluxify-kit +``` + +and you have a complete stack: the dashboard, the API, the database, the cache, and the event bus, all up and healthy behind port `8080`. + +## Still the same image, still your choice + +Nothing was removed. Bringing your own database, cache, and event bus with `docker compose` is still fully supported, for anyone who wants their data in infrastructure they already manage. The image just decides for itself which mode to run in: if you hand it a database connection string, it uses yours, and if you don't, it starts its own inside the container. Same image, same compose file, no separate build to maintain. + +## What actually changed underneath + +Getting a single container to boot a full stack reliably surfaced a handful of problems that only show up once everything genuinely has to start together and stay up: + +- **A dead service used to leave the container "running."** If one internal piece crashed, the container kept reporting healthy while quietly serving nothing. Now the whole container exits the moment anything inside it dies, so your restart policy actually gets a chance to fix it, instead of a demo that looks fine and answers nothing. +- **The health check was pointed at a URL that didn't exist**, so a perfectly healthy instance could never report itself as ready. +- **A missing admin email or password used to fail late and vaguely.** A fresh instance now refuses to start at all without both, rather than coming up with no way to log in. +- **The dashboard is a static bundle now**, served directly rather than run as its own Node process. One less moving part inside the container, and the whole thing comes in under 340MB. + +None of this changes how you run Fluxify in production, that path is untouched and still the recommended one for anything beyond a trial. It changes how long it takes to find out whether Fluxify is worth running in production at all. + +## A UI to actually test what you build + +The other big piece this week: `apps/portal`, the current dashboard, had no way to create or run test suites at all. The backend for sandboxed test execution had been built out over a run of earlier issues, but every screen for it lived only in the legacy dashboard, so once that gets retired a user could build routes and blocks but never write a single test for them. [Issue #227](https://github.com/Fluxify-rest/Fluxify/issues/227) tracked closing that gap, and [PR #253](https://github.com/Fluxify-rest/Fluxify/pull/253) shipped it. + +The new UI covers the full loop: create and edit a suite for a route, define assertions against the status code, body, headers, timing, or a custom JS check, override app config and integrations so a test run doesn't touch production data, then run one suite or every suite for a route and watch results fill in as they finish rather than waiting on a single spinner. A run that times out or errors says so plainly instead of showing an empty result. + +![Test suite UI showing run results for a route](/test-suites/demo-blog.png) + +## Try it + +Full walkthrough, including how to point it at your own database instead of the bundled one, is in the [Kit deployment guide](/deployments/kit). diff --git a/docs/public/assets/favicon.ico b/docs/public/assets/favicon.ico index 20d83368..75c53833 100644 Binary files a/docs/public/assets/favicon.ico and b/docs/public/assets/favicon.ico differ diff --git a/docs/public/assets/logo.png b/docs/public/assets/logo.png index ddfcaf20..2951ae9a 100644 Binary files a/docs/public/assets/logo.png and b/docs/public/assets/logo.png differ diff --git a/docs/public/assets/logo.svg b/docs/public/assets/logo.svg index 9bce6552..43b71ff8 100644 --- a/docs/public/assets/logo.svg +++ b/docs/public/assets/logo.svg @@ -1 +1,29 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/public/assets/logo.webp b/docs/public/assets/logo.webp index 956d80cc..3629fd5e 100644 Binary files a/docs/public/assets/logo.webp and b/docs/public/assets/logo.webp differ diff --git a/docs/public/assets/logo_source.json b/docs/public/assets/logo_source.json new file mode 100644 index 00000000..5a122c46 --- /dev/null +++ b/docs/public/assets/logo_source.json @@ -0,0 +1 @@ +[["Layer",{"applyMatrix":true,"children":[["Group",{"applyMatrix":true,"children":[["Group",{"applyMatrix":true,"children":[["Group",{"applyMatrix":true,"children":[["Path",{"applyMatrix":true,"segments":[[-160.29422,500.39835],[-308.95755,414.79918],[-308.95755,585.99753],[-160.29422,671.5967]],"closed":true,"fillColor":[0.70196,0.90196,0],"strokeColor":[0.70196,0.90196,0],"strokeWidth":2,"strokeJoin":"round","miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"applyMatrix":true,"segments":[[-160.29422,500.39835],[-11.63088,414.79918],[-11.63088,585.99753],[-160.29422,671.5967]],"closed":true,"fillColor":[0.54902,0.74902,0],"strokeColor":[0.54902,0.74902,0],"strokeWidth":2,"strokeJoin":"round","miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"applyMatrix":true,"segments":[[-160.29422,500.39835],[-308.95755,414.79918],[-160.29422,329.20001],[-11.63088,414.79918]],"closed":true,"fillColor":[0.83137,1,0],"strokeColor":[0.83137,1,0],"strokeWidth":2,"strokeJoin":"round","miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"applyMatrix":true,"segments":[[434.35912,500.39835],[285.69578,414.79918],[285.69578,585.99753],[434.35912,671.5967]],"closed":true,"fillColor":[0.70196,0.90196,0],"strokeColor":[0.70196,0.90196,0],"strokeWidth":2,"strokeJoin":"round","miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"applyMatrix":true,"segments":[[434.35912,500.39835],[583.02245,414.79918],[583.02245,585.99753],[434.35912,671.5967]],"closed":true,"fillColor":[0.54902,0.74902,0],"strokeColor":[0.54902,0.74902,0],"strokeWidth":2,"strokeJoin":"round","miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"applyMatrix":true,"segments":[[434.35912,500.39835],[285.69578,414.79918],[434.35912,329.20001],[583.02245,414.79918]],"closed":true,"fillColor":[0.83137,1,0],"strokeColor":[0.83137,1,0],"strokeWidth":2,"strokeJoin":"round","miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"applyMatrix":true,"segments":[[137.03245,158.00167],[-11.63088,72.4025],[-11.63088,243.60084],[137.03245,329.20001]],"closed":true,"fillColor":[0.70196,0.90196,0],"strokeColor":[0.70196,0.90196,0],"strokeWidth":2,"strokeJoin":"round","miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"applyMatrix":true,"segments":[[137.03245,158.00167],[285.69578,72.4025],[285.69578,243.60084],[137.03245,329.20001]],"closed":true,"fillColor":[0.54902,0.74902,0],"strokeColor":[0.54902,0.74902,0],"strokeWidth":2,"strokeJoin":"round","miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"applyMatrix":true,"segments":[[137.03245,158.00167],[-11.63088,72.4025],[137.03245,-13.19667],[285.69578,72.4025]],"closed":true,"fillColor":[0.83137,1,0],"strokeColor":[0.83137,1,0],"strokeWidth":2,"strokeJoin":"round","miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}]]}],["Path",{"applyMatrix":true,"segments":[[[62.70078,200.80126],[0,0],[-148.66333,0]],[[-160.29422,414.79918],[0,-142.66528],[0,0]]],"strokeColor":[0.50196,0.50196,0.50196],"strokeWidth":18,"strokeCap":"round","miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"applyMatrix":true,"segments":[[[211.36412,200.80126],[0,0],[148.66333,0]],[[434.35912,414.79918],[0,-142.66528],[0,0]]],"strokeColor":[0.50196,0.50196,0.50196],"strokeWidth":18,"strokeCap":"round","miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}]]}],["PointText",{"applyMatrix":false,"matrix":[1,0,0,1,656.09036,404.37172],"data":{"textContent":"FLUXIFY","textWidth":845.94914,"textHeight":235.65658},"content":"FLUXIFY","fillColor":[0.54902,0.74902,0,1],"miterLimit":4,"selectedColor":[0,0,0,0],"fontFamily":"Inter Tight","fontWeight":"900","fontSize":200,"leading":240}]]}]]}]] \ No newline at end of file diff --git a/docs/public/assets/logo_title.png b/docs/public/assets/logo_title.png index 89e739f7..3a510077 100644 Binary files a/docs/public/assets/logo_title.png and b/docs/public/assets/logo_title.png differ diff --git a/docs/public/assets/logo_title.webp b/docs/public/assets/logo_title.webp index 9c79d256..5eac249e 100644 Binary files a/docs/public/assets/logo_title.webp and b/docs/public/assets/logo_title.webp differ diff --git a/docs/public/assets/provector-logo.json b/docs/public/assets/provector-logo.json deleted file mode 100644 index 7c97d79c..00000000 --- a/docs/public/assets/provector-logo.json +++ /dev/null @@ -1 +0,0 @@ -[["Layer",{"name":"Frame - 1","applyMatrix":true,"children":[["Path",{"applyMatrix":true,"locked":true,"clipMask":true,"data":{},"segments":[[0,500],[0,0],[500,0],[500,500]],"closed":true,"miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"applyMatrix":true,"locked":true,"data":{},"segments":[[0,500],[0,0],[500,0],[500,500]],"closed":true,"miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Group",{"name":"left","applyMatrix":true,"children":[["Path",{"applyMatrix":true,"data":{},"segments":[[121.48317,250],[192.96634,291.27083],[192.96634,373.81248],[121.48317,415.0833],[50,373.81248],[50,291.27083]],"closed":true,"fillColor":["hsb",262.83186,0.65,0.95,1],"strokeColor":[0,0,0],"strokeWidth":0,"miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"name":"left","applyMatrix":true,"data":{},"segments":[[50,373.81248],[50,291.27083],[121.48317,326.06914],[121.48317,415.0833]],"closed":true,"fillColor":["hsb",262.7451,0.72,0.66,1],"strokeColor":["hsb",0,0.79,0.74,1],"strokeWidth":0,"miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"name":"right","applyMatrix":true,"data":{},"segments":[[192.96634,373.69973],[192.96634,291.27083],[121.48317,326.06914],[121.48317,415.0833]],"closed":true,"fillColor":["hsb",262.80992,0.81,0.62,1],"strokeColor":["hsb",0,0.79,0.74,1],"strokeWidth":0,"miterLimit":4,"shadowColor":["hsb",262.96875,0.62,0.54,1],"selectedColor":[0.18431,0.6902,0.62745,1]}]]}],["Group",{"name":"right","applyMatrix":true,"children":[["Path",{"name":"top","applyMatrix":true,"segments":[[378.51683,250],[450,291.27083],[450,373.81248],[378.51683,415.0833],[307.03366,373.81248],[307.03366,291.27083]],"closed":true,"fillColor":["hsb",262.83186,0.65,0.95,1],"strokeColor":[0,0,0],"strokeWidth":0,"miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"name":"left","applyMatrix":true,"segments":[[307.03366,373.81248],[307.03366,291.27083],[378.51683,326.06914],[378.51683,415.0833]],"closed":true,"fillColor":["hsb",262.7451,0.72,0.66,1],"strokeColor":["hsb",0,0.79,0.74,1],"strokeWidth":0,"miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"name":"right","applyMatrix":true,"segments":[[450,373.69973],[450,291.27083],[378.51683,326.06914],[378.51683,415.0833]],"closed":true,"fillColor":["hsb",262.80992,0.81,0.62,1],"strokeColor":["hsb",0,0.79,0.74,1],"strokeWidth":0,"miterLimit":4,"shadowColor":["hsb",262.96875,0.62,0.54,1],"selectedColor":[0.18431,0.6902,0.62745,1]}]]}],["Group",{"name":"top","applyMatrix":true,"children":[["Path",{"name":"main","applyMatrix":true,"data":{},"segments":[[249.19358,100],[320.67675,141.27083],[320.67675,223.81248],[249.19358,265.0833],[177.71041,223.81248],[177.71041,141.27083]],"closed":true,"fillColor":[0.56863,0.33333,0.94902,1],"strokeColor":[0,0,0],"strokeWidth":0,"miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"name":"left","applyMatrix":true,"data":{},"segments":[[177.71041,223.81248],[177.71041,141.27083],[249.19358,176.06914],[249.19358,265.0833]],"closed":true,"fillColor":[0.36471,0.18431,0.65882,1],"strokeColor":["hsb",0,0.79,0.74,1],"strokeWidth":0,"miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"name":"right","applyMatrix":true,"data":{},"segments":[[320.67675,223.69973],[320.67675,141.27083],[249.19358,176.06914],[249.19358,265.0833]],"closed":true,"fillColor":["hsb",262.80992,0.71,0.7,1],"strokeColor":["hsb",0,0.79,0.74,1],"strokeWidth":0,"miterLimit":4,"shadowColor":["hsb",262.96875,0.62,0.54,1],"selectedColor":[0.18431,0.6902,0.62745,1]}]]}],["Path",{"applyMatrix":true,"fillColor":[1,1,1],"strokeColor":[0,0,0],"miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"applyMatrix":true,"fillColor":["hsb",262.96875,0.91,0.6,1],"strokeColor":[0,0,0],"miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"applyMatrix":true,"data":{},"segments":[[[213.452,200],[49.89785,-3.1944],[-49.89785,3.1944]],[[121.48317,289.73302],[0.22539,-56.9365],[0,0]]],"strokeColor":["hsb",262.96875,0.9,0.63,1],"strokeWidth":11,"strokeCap":"round","strokeJoin":"round","miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"applyMatrix":true,"segments":[[[285.94684,200],[-49.89785,-3.1944],[49.89785,3.1944]],[[377.91567,289.73302],[-0.22539,-56.9365],[0,0]]],"strokeColor":["hsb",262.96875,0.9,0.63,1],"strokeWidth":11,"strokeCap":"round","strokeJoin":"round","miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}]]}],["Layer",{"applyMatrix":true,"selected":true,"children":[["Path",{"applyMatrix":true,"segments":[[-207.68981,240.50835],[-207.68981,240.50835],[-207.68981,240.50835],[-207.68981,240.50835],[-207.68981,240.50835],[-207.68981,240.50835]],"closed":true,"fillColor":[1,1,1],"strokeColor":[0,0,0],"miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}],["Path",{"applyMatrix":true,"selected":true,"fillColor":[1,1,1],"strokeColor":[0,0,0],"miterLimit":4,"selectedColor":[0.18431,0.6902,0.62745,1]}]]}]] \ No newline at end of file diff --git a/docs/public/test-suites/demo-blog.png b/docs/public/test-suites/demo-blog.png new file mode 100644 index 00000000..7e4a94a7 Binary files /dev/null and b/docs/public/test-suites/demo-blog.png differ