markdr-hue/open-fabrica

A tribute to the best software in the world.

1

stars

45

commits

Go

primary language

Sep 8, 2026

updated

openfabrica.org
ai-coding
application
database
llm-agent
vibe-coding
webserver
your-mom

README

Latest release Single binary Windows macOS Linux

Setup provider

Open Fabrica is a single binary that builds and serves your ideas to the world. AI-powered apps, (real-time) multiplayer games, websites, secure end-2-end encrypted communication apps, collaboration tools, headless APIs...anything that runs in a browser. Everything is stored and served from your machine. It's a portable ecosystem in which there's no need for a dedicated webserver, database engine or third party plugins to have as little friction as possible.

Great Ideas are Everywhere

Unfortunately not everyone has the tools, time, technical know-how or finances to put them into fruition. We want to enable anyone from all walks of life to build, own and publish their ideas for free, regardless of skill-level and background. Ideally one day Open Fabrica will be pre-installed on computers all over the world instead of a link to AliExpress and a trial version of Fruit Ninja.

If your company wants to support Open Fabrica and its goals please do reach out on X @antifoundering. We are in desperate need of model-access and powerful local hardware so finetuning can be done faster and in parallel.

In similar fashion...we do eventually want to ship with a default coding model, accessible for anyone for free. We understand it needs a paid upgrade path on your side for higher usage but it allows for a zero friction experience.

What Can it Create?

Anything, promised. As long as it runs in a browser. You can even fork it to modify the build loop for other platforms such as Android or iOS.

Winamp

Kanban

Pong

Website

Multiplayer 3D game

But my favorite [name app builder/cloud app builder] can do this too?

Well yes and no. They will create a site for you, a tool, a game but then what? You have to go figure out how to get it online, how does hosting work, where do I host it, where do I store my databases? Then the headache starts. You're bound to buy into whatever cloud provider and go to the painful process of making the parts work together. Open Fabrica gives you everything right outside the box. No need for ANY configuration, we will even protect your domain name so your apps run HTTPS. Free of course. We promise you that you'll be amazed on how easy this is, it might even feel like magic to some.

Free, Private and Portable

  • Forever Free. No sign-up, no subscription, no per-project fee. Download the binary and run it.
  • No phone-home. No usage or error reporting, no analytics SDK, no "check for updates" call. The admin panel is fully self-contained (every script, style, and font is served from the binary), so it works fully offline.
  • Local First. One binary, your data, your machine. The only time anything leaves your computer is when you trigger it.
  • Bring your own key. Use your own Anthropic, OpenAI, Google, or any OpenAI-compatible key, or run fully offline models.
  • Portable. Copy the binary and your data/ folder to any Windows, macOS, or Linux box and it picks up where it left off.

Build start

Quick Start

Important: This is an early release which focuses on getting the core build loop as stable as possible: things will break and tokens will be wasted. Ideally you're on a cheap coding plan or run a local model when your hardware allows for that. Many architectural decisions are not finalized.

  1. Download latest binary from Releases.
  2. Run it. Double-click the file, or run ./openfabrica in your terminal.
  3. Open http://localhost:5734 in your browser.
  4. Pick an AI provider. The setup wizard asks for an API key (Anthropic, OpenAI, Google, or any OpenAI-compatible provider). A local Ollama is auto-detected, no key needed.
  5. Describe your idea. Open Fabrica takes it from there.

Features

  • Fully self-contained binary which runs everywhere.
  • Instantly live by eliminating the concept of hosting.
  • Unlimited projects from a single instance.
  • Accounts and logins with optional Google/GitHub social login (any OAuth2 provider works), TOTP 2FA, and passwordless magic links.
  • Payments via Stripe, PayPal, or Mollie; one-off, or recurring on Stripe and PayPal. Stripe reconciles itself from signed webhooks; PayPal and Mollie payments are reconciled manually.
  • Email (SendGrid, Mailgun, Resend, or any JSON endpoint) and SMS (Twilio, MessageBird, or any JSON endpoint).
  • Notifications in-app, plus Web Push with auto-managed VAPID keys.
  • Real-time chat rooms, live feeds, P2P calling, and file uploads, with optional end-to-end encryption.
  • Image generation via OpenAI or a local Stable Diffusion (Automatic1111) instance.
  • Stock photos from Pexels, Pixabay, and Unsplash, picked automatically.
  • PDF generation for invoices, receipts, tickets, and reports (needs a local Chromium based browser).
  • CSV import/export, RSS/Atom feeds served straight from a table.
  • Keyword and semantic search out of the box.
  • Analytics (visits, unique visitors, top pages, referrers, AI usage/cost), all stored locally.
  • SEO (Open Graph, Twitter cards, JSON-LD, sitemaps, robots.txt) handled automatically.
  • Native PWA support for offline and installable apps.
  • Auto-generated APIs with rate limiting and docs.
  • Per-project AI assistants with configurable personality and memory.
  • AI agents that plan and act over multiple steps: a hosted endpoint that reasons, calls your app's own functions and reads its data in a loop, and can spawn and manage sub-agents to break down bigger jobs. Stream progress live or run in the background, each bounded by a per-endpoint daily token budget.
  • Server-side AI hooks to auto-summarize, classify, or embed new rows on insert.
  • Telegram bot so you can plan/build projects and get push notifications from your phone.
  • Scheduled jobs (cron or intervals) that run SQL, send emails, hit HTTP endpoints, or invoke the AI.
  • Event-driven actions reacting to signups, logins, payments, and data changes.
  • Roles and permissions with wildcard-based access control.
  • Project templates: save any project as a template and spin up new ones in seconds.
  • Free HTTPS automatically, no manual actions needed.

Screenshots

Play a game while you wait

Build end

Projects page

Setup welcome

Setup provider

Before You Go Live

If you only run locally, the Quick Start is all you need. If you expose generated apps to the internet or enable payments, do these first:

  • Back up your encryption key with your data. data/.security/encryption.key decrypts every stored secret (API keys, OAuth tokens, payment credentials, TOTP seeds). Lose it and those are unrecoverable. Back it up together with the data/ folder, kept somewhere the data backup alone can't leak it.
  • Set a spend ceiling. Unattended AI, the build/self-repair loop plus event triggers, scheduled jobs, and server functions, calls the LLM on your key. A safe ~1M-token-per-project-per-day ceiling ships on by default and is a single shared pool across all of those paths (change it in the wizard or Settings → Daily AI spend limit, or set OPENFABRICA_ENGINE_DAILY_TOKEN_BUDGET=0 for unlimited). When a project hits the ceiling those calls pause instead of billing all night.
  • Isolate untrusted/multi-user apps. The public CSP is permissive by design. Serve each project on its own domain/subdomain so one app can't reach another's same-origin storage, and tighten the CSP instance-wide via OPENFABRICA_PUBLIC_CSP or per project in Project → Settings → Advanced.
  • Cap memory for untrusted apps. Model-authored server functions run in a JS sandbox that limits CPU and output but not heap, so a runaway handler can exhaust memory and crash the whole instance. Set a soft ceiling with OPENFABRICA_MEMORY_LIMIT (e.g. 1GiB) so GC pushes back before the process climbs into the OS OOM-killer, and for a hard backstop run under an OS/container memory limit with auto-restart. The shipped Dockerfile wires --memory + GOMEMLIMIT for you; on bare metal use systemd MemoryMax=/Restart= or a cgroup. This is a floor, not tenant isolation. See Security.
  • Keep the admin panel on localhost (the default). See Security below.

Health probes on either port (both bypass auth and routing): GET /health (alias /healthz) is a liveness check that always returns {"status":"ok"} while the process can answer requests. GET /ready (alias /readyz) is a readiness check that pings the database and returns {"status":"ready"} (200) when it can serve, or {"status":"unavailable"} (503) when the database is unreachable, point your load balancer or orchestrator at /ready.

Self-Hosting and HTTPS

Point your domain's DNS at your server, open ports 80 and 443, then add the domain to a project (Project → Settings → General → Domain). HTTPS goes live on demand: Open Fabrica binds :80/:443 and Let's Encrypt issues the certificate within ~30 seconds, no restart. If another web server already owns those ports, set "tls_disabled": true in config.json (or OPENFABRICA_TLS_DISABLED=1) to skip the bind.

When you set a public domain, the admin UI offers a one-click Allow through firewall button (Project → Settings → General) if the local OS firewall is blocking inbound. It adds the allow-rule after a single system prompt (UAC on Windows, polkit on Linux), scoped to your active network profile. This opens the local firewall only; reaching the machine from the internet still needs your router to forward ports 80 and 443.

Security

The admin panel runs on port 5734 and binds to localhost only (127.0.0.1) by default. It can read every project's data and decrypt stored secrets, so it is treated as a local control plane, not a public surface. To reach it on a remote server, use an SSH tunnel:

ssh -L 5734:localhost:5734 user@yourserver

If you genuinely need it reachable over the network (behind your own firewall or authenticating reverse proxy), set both OPENFABRICA_ADMIN_BIND to the interface (e.g. 0.0.0.0) and OPENFABRICA_ADMIN_EXPOSE=1 to acknowledge the exposure, or the server refuses to start. The public project server on port 5733 is always network-reachable.

Admin login is protected by a per-IP rate limit and a per-account lockout (five wrong passwords locks the account with escalating backoff). Changing or resetting a password immediately invalidates every existing session for that user.

Configuration

Zero-config by default. To tweak, use config.json or environment variables.

VariableDefaultWhat it does
OPENFABRICA_ADMIN_PORT5734Port for the admin panel
OPENFABRICA_ADMIN_BIND127.0.0.1Interface the admin panel binds to (loopback by default)
OPENFABRICA_ADMIN_EXPOSESet to 1 to allow binding admin to a non-loopback address (required alongside a routable bind)
OPENFABRICA_PUBLIC_PORT5733Port where your project is served
OPENFABRICA_DATA_DIR./dataWhere project data is stored
OPENFABRICA_DB_PATH<data_dir>/openfabrica.dbPath to the core SQLite database
OPENFABRICA_SEED_PATH./seed.jsonSeed data loaded on first run
OPENFABRICA_JWT_SECRETauto-generatedJWT signing key (min 32 chars)
OPENFABRICA_ENCRYPTION_KEYauto-generatedAt-rest encryption key (64 hex chars)
OPENFABRICA_ALLOW_KEY_REGENSet to 1 to permit generating a new jwt.key/encryption.key when the file is missing but a database already exists. Off by default: a missing key on a populated data dir makes the server refuse to start rather than silently mint a new one. Regenerating invalidates every session (JWT key) and makes previously-encrypted secrets - provider keys, OAuth/payment tokens, TOTP seeds - permanently unreadable (encryption key). Set it only if you have no key backup and accept that loss.
OPENFABRICA_TLS_DISABLEDfalseSkip binding :80/:443 (use when another web server owns those ports)
OPENFABRICA_TLS_STAGINGfalseUse Let's Encrypt's staging CA (avoids the production rate limit while iterating)
OPENFABRICA_LOG_LEVELinfodebug, info, warn, error
OPENFABRICA_MEMORY_LIMITSoft heap ceiling (e.g. 1GiB, 512MiB, or raw bytes; 0 disables). Applied via Go's soft memory limit so GC pushes back before the process is OOM-killed. When unset, a GOMEMLIMIT in the environment is still honored. Not tenant isolation: pair it with a container/OS hard limit + auto-restart for untrusted apps.
OPENFABRICA_RATE_LIMIT_RATE100Requests per second per IP
OPENFABRICA_RATE_LIMIT_BURST200Burst allowance above the rate
OPENFABRICA_LLM_TIMEOUT900Per-LLM-call deadline in seconds
OPENFABRICA_ENGINE_DAILY_TOKEN_BUDGET1000000Max cost-weighted engine tokens per project per UTC day. The build/self-repair loop pauses when reached. Set 0 for unlimited. Resolution order: env var > admin/setup setting > config.json > default (applies live).
OPENFABRICA_ENGINE_STAGE_EXPAND_TIMEOUT_MIN2Wall-clock timeout (minutes) for the EXPAND stage. Overrides the built-in default; raise it when a slow provider makes a legitimate build exceed it, instead of rebuilding the binary.
OPENFABRICA_ENGINE_STAGE_PLAN_TIMEOUT_MIN30Wall-clock timeout (minutes) for the PLAN stage.
OPENFABRICA_ENGINE_STAGE_BUILD_TIMEOUT_MIN90Wall-clock timeout (minutes) for the BUILD stage.
OPENFABRICA_PUBLIC_CSP(permissive)Override the CSP on public project pages. The permissive default carries 'wasm-unsafe-eval' so WebAssembly modules (TensorFlow.js, MediaPipe, ffmpeg.wasm, game engines) compile - the browser gates WASM behind CSP, and this keyword permits only WASM compilation, not JavaScript eval(). Put the literal {nonce} token in a script-src and the server mints a per-request nonce so inline scripts work without 'unsafe-inline'. Or set it to the keyword hardened for a built-in strict preset (scripts locked to 'self' + nonce + 'wasm-unsafe-eval'; external images, fonts, and styles still load). Also settable per project. Empty string removes the header.
OPENFABRICA_NO_BROWSERSet to any value to suppress auto-opening the admin URL on startup.
OPENFABRICA_OLLAMA_KEEP_ALIVE30mHow long Ollama keeps a model (and its prefix cache) resident between calls. -1 keeps it resident, 0 unloads after each call.
OPENFABRICA_OLLAMA_NUM_CTXOllama context window for build calls. Set it at least as large as the build prompt (~16k+ tokens) so the cached prefix isn't evicted.

A few knobs are set only in config.json (no env-var override). cors_origins is a JSON array of origins allowed to call the public project APIs cross-origin; when omitted it defaults to permissive (*, credentials withheld) - set it to your app's origins if you serve untrusted or multi-user apps.

When using Ollama, run the daemon with OLLAMA_NUM_PARALLEL=1 for best prefix-cache reuse. Stock-photo providers (Pexels, Unsplash, Pixabay) are optional: configure them from the admin UI or seed a key via PEXELS_KEY, UNSPLASH_KEY, and PIXABAY_KEY.

Build from Source

Requires Go 1.26+. No C compiler needed, the SQLite driver is pure Go.

git clone https://github.com/markdr-hue/open-fabrica.git
cd open-fabrica
make dev        # run directly, or: go run ./cmd/openfabrica
make build      # stripped, version-stamped binary in ./bin

Before opening a pull request, run the local quality gates with make check (gofmt + vet + build + tests). See CONTRIBUTING.md for the full developer guide and CONVENTIONS.md for house rules.

To see what a build actually did, and what it cost, read TRIAGE.md.

Architecture

Open Fabrica runs a per-project background worker, the engine (engine/), which walks each project through a stage pipeline:

EXPAND → PLAN → BUILD → LIVE
                  |
                  +--- (validators; any failure feeds a bounded fix-pass)

EXPAND sharpens a sparse brief; PLAN seeds a build checklist; BUILD works through it in one continuous, prompt-cached session, then runs the validators (a headless-Chrome runtime probe plus websockets smoke tests). Failures feed back as a bounded fix-pass until clean (or they ship as known issues), then the project goes LIVE. Chat changes re-enter at PLAN and BUILD rebuilds only what actually changed.

Every stage runs through one unified session loop (engine/session.go): an append-only, byte-stable transcript so provider prompt caches hit across iterations, plus a content-addressed replay cache (of_llm_cache) that makes crash resume and retries nearly free. Context overflow ends the segment and reseeds deterministically from database state, the same mechanism that powers crash recovery.

All LLM-facing guidance lives in one knowledge tree (knowledge/): an always-on mental-model.md, recall-on-demand capability guides, canonical contracts, and per-stage frames + fragments. The pack package selects and renders them into each stage's byte-stable system prompt. Load-bearing facts (REST envelope, auth_token key, E2EE wire envelope, realtime frames, trigger events, payment flow) are defined once in contracts/ and transcluded via {{contract:<id>}}, so a copy can't silently drift; a consistency test fails the build if it does. Tools live under tools/, each registering a declarative tools.Tool. Guard tests (TestNoCrossPackDuplication, TestGovernedDocsMatchContracts, the *_drift tests) fail the build on a drifted copy.

License

See LICENSE (MIT) for details.

Acknowledgements

Open Fabrica stands on a lot of excellent open-source work. Special thanks to Let's Encrypt for free HTTPS, and to the libraries it's built on:

  • modernc.org/sqlite: a pure-Go SQLite, and the reason the whole app ships as one binary with no cgo and cross-compiles anywhere.
  • goja: the embedded JavaScript engine that runs model-authored server functions and multiplayer game logic in a sandbox.
  • esbuild: parses and statically analyses the JavaScript the model writes.
  • chromedp + cdproto: headless-Chrome automation for the runtime validator and PDF generation.
  • certmagic: automatic Let's Encrypt issuance and on-demand TLS.
  • chi: HTTP routing.
  • coder/websocket: WebSockets for realtime rooms, feeds, and calls.
  • golang-jwt: JSON Web Tokens for end-user auth.
  • ledongthuc/pdf: PDF text extraction.

Plus google/uuid, zap, and the Go team's golang.org/x crypto, net, and text packages.

Meet the 'Team'

Hi I'm Mark.

Be nice to others. It makes the world a much nicer place to live in!

If you need me I'm on X (@antifoundering)

Meet my team

A personal Note

I don't do hype, and I believe real talent is hard to find. A significant portion of workplace activity is self-justifying: processes and tasks that exist to preserve roles rather than produce outcomes.

The workplace fascinates me precisely because I've never figured it out. Sandboxes governed by their own rules and power dynamics, none of which ever made sense to me. But people want to belong to something. A group, a mindset, a reassurance that they're doing great things while wearing a hoodie with the company logo on it. Until a higher paying job comes along.

I think there's comfort in that, in running on autopilot. Honestly, I wish I could. It would have spared me the mental toll, and everything that followed from it: the physical, the relational, the financial. That's the cost of trying to act like a machine when you aren't one.

So if you want to take anything from this: you'd better hope you're a robot. Otherwise life will bring you to your knees while the world keeps moving. I've used the workplace as an example, but this applies to everything.

Or maybe, just maybe, it's all just me.

Contributors

markdr-hue

45 commits

markdr-hue/open-fabrica

A tribute to the best software in the world.

1

stars

45

commits

Go

primary language

Sep 8, 2026

updated

openfabrica.org
ai-coding
application
database
llm-agent
vibe-coding
webserver
your-mom

README

Latest release Single binary Windows macOS Linux

Setup provider

Open Fabrica is a single binary that builds and serves your ideas to the world. AI-powered apps, (real-time) multiplayer games, websites, secure end-2-end encrypted communication apps, collaboration tools, headless APIs...anything that runs in a browser. Everything is stored and served from your machine. It's a portable ecosystem in which there's no need for a dedicated webserver, database engine or third party plugins to have as little friction as possible.

Great Ideas are Everywhere

Unfortunately not everyone has the tools, time, technical know-how or finances to put them into fruition. We want to enable anyone from all walks of life to build, own and publish their ideas for free, regardless of skill-level and background. Ideally one day Open Fabrica will be pre-installed on computers all over the world instead of a link to AliExpress and a trial version of Fruit Ninja.

If your company wants to support Open Fabrica and its goals please do reach out on X @antifoundering. We are in desperate need of model-access and powerful local hardware so finetuning can be done faster and in parallel.

In similar fashion...we do eventually want to ship with a default coding model, accessible for anyone for free. We understand it needs a paid upgrade path on your side for higher usage but it allows for a zero friction experience.

What Can it Create?

Anything, promised. As long as it runs in a browser. You can even fork it to modify the build loop for other platforms such as Android or iOS.

Winamp

Kanban

Pong

Website

Multiplayer 3D game

But my favorite [name app builder/cloud app builder] can do this too?

Well yes and no. They will create a site for you, a tool, a game but then what? You have to go figure out how to get it online, how does hosting work, where do I host it, where do I store my databases? Then the headache starts. You're bound to buy into whatever cloud provider and go to the painful process of making the parts work together. Open Fabrica gives you everything right outside the box. No need for ANY configuration, we will even protect your domain name so your apps run HTTPS. Free of course. We promise you that you'll be amazed on how easy this is, it might even feel like magic to some.

Free, Private and Portable

  • Forever Free. No sign-up, no subscription, no per-project fee. Download the binary and run it.
  • No phone-home. No usage or error reporting, no analytics SDK, no "check for updates" call. The admin panel is fully self-contained (every script, style, and font is served from the binary), so it works fully offline.
  • Local First. One binary, your data, your machine. The only time anything leaves your computer is when you trigger it.
  • Bring your own key. Use your own Anthropic, OpenAI, Google, or any OpenAI-compatible key, or run fully offline models.
  • Portable. Copy the binary and your data/ folder to any Windows, macOS, or Linux box and it picks up where it left off.

Build start

Quick Start

Important: This is an early release which focuses on getting the core build loop as stable as possible: things will break and tokens will be wasted. Ideally you're on a cheap coding plan or run a local model when your hardware allows for that. Many architectural decisions are not finalized.

  1. Download latest binary from Releases.
  2. Run it. Double-click the file, or run ./openfabrica in your terminal.
  3. Open http://localhost:5734 in your browser.
  4. Pick an AI provider. The setup wizard asks for an API key (Anthropic, OpenAI, Google, or any OpenAI-compatible provider). A local Ollama is auto-detected, no key needed.
  5. Describe your idea. Open Fabrica takes it from there.

Features

  • Fully self-contained binary which runs everywhere.
  • Instantly live by eliminating the concept of hosting.
  • Unlimited projects from a single instance.
  • Accounts and logins with optional Google/GitHub social login (any OAuth2 provider works), TOTP 2FA, and passwordless magic links.
  • Payments via Stripe, PayPal, or Mollie; one-off, or recurring on Stripe and PayPal. Stripe reconciles itself from signed webhooks; PayPal and Mollie payments are reconciled manually.
  • Email (SendGrid, Mailgun, Resend, or any JSON endpoint) and SMS (Twilio, MessageBird, or any JSON endpoint).
  • Notifications in-app, plus Web Push with auto-managed VAPID keys.
  • Real-time chat rooms, live feeds, P2P calling, and file uploads, with optional end-to-end encryption.
  • Image generation via OpenAI or a local Stable Diffusion (Automatic1111) instance.
  • Stock photos from Pexels, Pixabay, and Unsplash, picked automatically.
  • PDF generation for invoices, receipts, tickets, and reports (needs a local Chromium based browser).
  • CSV import/export, RSS/Atom feeds served straight from a table.
  • Keyword and semantic search out of the box.
  • Analytics (visits, unique visitors, top pages, referrers, AI usage/cost), all stored locally.
  • SEO (Open Graph, Twitter cards, JSON-LD, sitemaps, robots.txt) handled automatically.
  • Native PWA support for offline and installable apps.
  • Auto-generated APIs with rate limiting and docs.
  • Per-project AI assistants with configurable personality and memory.
  • AI agents that plan and act over multiple steps: a hosted endpoint that reasons, calls your app's own functions and reads its data in a loop, and can spawn and manage sub-agents to break down bigger jobs. Stream progress live or run in the background, each bounded by a per-endpoint daily token budget.
  • Server-side AI hooks to auto-summarize, classify, or embed new rows on insert.
  • Telegram bot so you can plan/build projects and get push notifications from your phone.
  • Scheduled jobs (cron or intervals) that run SQL, send emails, hit HTTP endpoints, or invoke the AI.
  • Event-driven actions reacting to signups, logins, payments, and data changes.
  • Roles and permissions with wildcard-based access control.
  • Project templates: save any project as a template and spin up new ones in seconds.
  • Free HTTPS automatically, no manual actions needed.

Screenshots

Play a game while you wait

Build end

Projects page

Setup welcome

Setup provider

Before You Go Live

If you only run locally, the Quick Start is all you need. If you expose generated apps to the internet or enable payments, do these first:

  • Back up your encryption key with your data. data/.security/encryption.key decrypts every stored secret (API keys, OAuth tokens, payment credentials, TOTP seeds). Lose it and those are unrecoverable. Back it up together with the data/ folder, kept somewhere the data backup alone can't leak it.
  • Set a spend ceiling. Unattended AI, the build/self-repair loop plus event triggers, scheduled jobs, and server functions, calls the LLM on your key. A safe ~1M-token-per-project-per-day ceiling ships on by default and is a single shared pool across all of those paths (change it in the wizard or Settings → Daily AI spend limit, or set OPENFABRICA_ENGINE_DAILY_TOKEN_BUDGET=0 for unlimited). When a project hits the ceiling those calls pause instead of billing all night.
  • Isolate untrusted/multi-user apps. The public CSP is permissive by design. Serve each project on its own domain/subdomain so one app can't reach another's same-origin storage, and tighten the CSP instance-wide via OPENFABRICA_PUBLIC_CSP or per project in Project → Settings → Advanced.
  • Cap memory for untrusted apps. Model-authored server functions run in a JS sandbox that limits CPU and output but not heap, so a runaway handler can exhaust memory and crash the whole instance. Set a soft ceiling with OPENFABRICA_MEMORY_LIMIT (e.g. 1GiB) so GC pushes back before the process climbs into the OS OOM-killer, and for a hard backstop run under an OS/container memory limit with auto-restart. The shipped Dockerfile wires --memory + GOMEMLIMIT for you; on bare metal use systemd MemoryMax=/Restart= or a cgroup. This is a floor, not tenant isolation. See Security.
  • Keep the admin panel on localhost (the default). See Security below.

Health probes on either port (both bypass auth and routing): GET /health (alias /healthz) is a liveness check that always returns {"status":"ok"} while the process can answer requests. GET /ready (alias /readyz) is a readiness check that pings the database and returns {"status":"ready"} (200) when it can serve, or {"status":"unavailable"} (503) when the database is unreachable, point your load balancer or orchestrator at /ready.

Self-Hosting and HTTPS

Point your domain's DNS at your server, open ports 80 and 443, then add the domain to a project (Project → Settings → General → Domain). HTTPS goes live on demand: Open Fabrica binds :80/:443 and Let's Encrypt issues the certificate within ~30 seconds, no restart. If another web server already owns those ports, set "tls_disabled": true in config.json (or OPENFABRICA_TLS_DISABLED=1) to skip the bind.

When you set a public domain, the admin UI offers a one-click Allow through firewall button (Project → Settings → General) if the local OS firewall is blocking inbound. It adds the allow-rule after a single system prompt (UAC on Windows, polkit on Linux), scoped to your active network profile. This opens the local firewall only; reaching the machine from the internet still needs your router to forward ports 80 and 443.

Security

The admin panel runs on port 5734 and binds to localhost only (127.0.0.1) by default. It can read every project's data and decrypt stored secrets, so it is treated as a local control plane, not a public surface. To reach it on a remote server, use an SSH tunnel:

ssh -L 5734:localhost:5734 user@yourserver

If you genuinely need it reachable over the network (behind your own firewall or authenticating reverse proxy), set both OPENFABRICA_ADMIN_BIND to the interface (e.g. 0.0.0.0) and OPENFABRICA_ADMIN_EXPOSE=1 to acknowledge the exposure, or the server refuses to start. The public project server on port 5733 is always network-reachable.

Admin login is protected by a per-IP rate limit and a per-account lockout (five wrong passwords locks the account with escalating backoff). Changing or resetting a password immediately invalidates every existing session for that user.

Configuration

Zero-config by default. To tweak, use config.json or environment variables.

VariableDefaultWhat it does
OPENFABRICA_ADMIN_PORT5734Port for the admin panel
OPENFABRICA_ADMIN_BIND127.0.0.1Interface the admin panel binds to (loopback by default)
OPENFABRICA_ADMIN_EXPOSESet to 1 to allow binding admin to a non-loopback address (required alongside a routable bind)
OPENFABRICA_PUBLIC_PORT5733Port where your project is served
OPENFABRICA_DATA_DIR./dataWhere project data is stored
OPENFABRICA_DB_PATH<data_dir>/openfabrica.dbPath to the core SQLite database
OPENFABRICA_SEED_PATH./seed.jsonSeed data loaded on first run
OPENFABRICA_JWT_SECRETauto-generatedJWT signing key (min 32 chars)
OPENFABRICA_ENCRYPTION_KEYauto-generatedAt-rest encryption key (64 hex chars)
OPENFABRICA_ALLOW_KEY_REGENSet to 1 to permit generating a new jwt.key/encryption.key when the file is missing but a database already exists. Off by default: a missing key on a populated data dir makes the server refuse to start rather than silently mint a new one. Regenerating invalidates every session (JWT key) and makes previously-encrypted secrets - provider keys, OAuth/payment tokens, TOTP seeds - permanently unreadable (encryption key). Set it only if you have no key backup and accept that loss.
OPENFABRICA_TLS_DISABLEDfalseSkip binding :80/:443 (use when another web server owns those ports)
OPENFABRICA_TLS_STAGINGfalseUse Let's Encrypt's staging CA (avoids the production rate limit while iterating)
OPENFABRICA_LOG_LEVELinfodebug, info, warn, error
OPENFABRICA_MEMORY_LIMITSoft heap ceiling (e.g. 1GiB, 512MiB, or raw bytes; 0 disables). Applied via Go's soft memory limit so GC pushes back before the process is OOM-killed. When unset, a GOMEMLIMIT in the environment is still honored. Not tenant isolation: pair it with a container/OS hard limit + auto-restart for untrusted apps.
OPENFABRICA_RATE_LIMIT_RATE100Requests per second per IP
OPENFABRICA_RATE_LIMIT_BURST200Burst allowance above the rate
OPENFABRICA_LLM_TIMEOUT900Per-LLM-call deadline in seconds
OPENFABRICA_ENGINE_DAILY_TOKEN_BUDGET1000000Max cost-weighted engine tokens per project per UTC day. The build/self-repair loop pauses when reached. Set 0 for unlimited. Resolution order: env var > admin/setup setting > config.json > default (applies live).
OPENFABRICA_ENGINE_STAGE_EXPAND_TIMEOUT_MIN2Wall-clock timeout (minutes) for the EXPAND stage. Overrides the built-in default; raise it when a slow provider makes a legitimate build exceed it, instead of rebuilding the binary.
OPENFABRICA_ENGINE_STAGE_PLAN_TIMEOUT_MIN30Wall-clock timeout (minutes) for the PLAN stage.
OPENFABRICA_ENGINE_STAGE_BUILD_TIMEOUT_MIN90Wall-clock timeout (minutes) for the BUILD stage.
OPENFABRICA_PUBLIC_CSP(permissive)Override the CSP on public project pages. The permissive default carries 'wasm-unsafe-eval' so WebAssembly modules (TensorFlow.js, MediaPipe, ffmpeg.wasm, game engines) compile - the browser gates WASM behind CSP, and this keyword permits only WASM compilation, not JavaScript eval(). Put the literal {nonce} token in a script-src and the server mints a per-request nonce so inline scripts work without 'unsafe-inline'. Or set it to the keyword hardened for a built-in strict preset (scripts locked to 'self' + nonce + 'wasm-unsafe-eval'; external images, fonts, and styles still load). Also settable per project. Empty string removes the header.
OPENFABRICA_NO_BROWSERSet to any value to suppress auto-opening the admin URL on startup.
OPENFABRICA_OLLAMA_KEEP_ALIVE30mHow long Ollama keeps a model (and its prefix cache) resident between calls. -1 keeps it resident, 0 unloads after each call.
OPENFABRICA_OLLAMA_NUM_CTXOllama context window for build calls. Set it at least as large as the build prompt (~16k+ tokens) so the cached prefix isn't evicted.

A few knobs are set only in config.json (no env-var override). cors_origins is a JSON array of origins allowed to call the public project APIs cross-origin; when omitted it defaults to permissive (*, credentials withheld) - set it to your app's origins if you serve untrusted or multi-user apps.

When using Ollama, run the daemon with OLLAMA_NUM_PARALLEL=1 for best prefix-cache reuse. Stock-photo providers (Pexels, Unsplash, Pixabay) are optional: configure them from the admin UI or seed a key via PEXELS_KEY, UNSPLASH_KEY, and PIXABAY_KEY.

Build from Source

Requires Go 1.26+. No C compiler needed, the SQLite driver is pure Go.

git clone https://github.com/markdr-hue/open-fabrica.git
cd open-fabrica
make dev        # run directly, or: go run ./cmd/openfabrica
make build      # stripped, version-stamped binary in ./bin

Before opening a pull request, run the local quality gates with make check (gofmt + vet + build + tests). See CONTRIBUTING.md for the full developer guide and CONVENTIONS.md for house rules.

To see what a build actually did, and what it cost, read TRIAGE.md.

Architecture

Open Fabrica runs a per-project background worker, the engine (engine/), which walks each project through a stage pipeline:

EXPAND → PLAN → BUILD → LIVE
                  |
                  +--- (validators; any failure feeds a bounded fix-pass)

EXPAND sharpens a sparse brief; PLAN seeds a build checklist; BUILD works through it in one continuous, prompt-cached session, then runs the validators (a headless-Chrome runtime probe plus websockets smoke tests). Failures feed back as a bounded fix-pass until clean (or they ship as known issues), then the project goes LIVE. Chat changes re-enter at PLAN and BUILD rebuilds only what actually changed.

Every stage runs through one unified session loop (engine/session.go): an append-only, byte-stable transcript so provider prompt caches hit across iterations, plus a content-addressed replay cache (of_llm_cache) that makes crash resume and retries nearly free. Context overflow ends the segment and reseeds deterministically from database state, the same mechanism that powers crash recovery.

All LLM-facing guidance lives in one knowledge tree (knowledge/): an always-on mental-model.md, recall-on-demand capability guides, canonical contracts, and per-stage frames + fragments. The pack package selects and renders them into each stage's byte-stable system prompt. Load-bearing facts (REST envelope, auth_token key, E2EE wire envelope, realtime frames, trigger events, payment flow) are defined once in contracts/ and transcluded via {{contract:<id>}}, so a copy can't silently drift; a consistency test fails the build if it does. Tools live under tools/, each registering a declarative tools.Tool. Guard tests (TestNoCrossPackDuplication, TestGovernedDocsMatchContracts, the *_drift tests) fail the build on a drifted copy.

License

See LICENSE (MIT) for details.

Acknowledgements

Open Fabrica stands on a lot of excellent open-source work. Special thanks to Let's Encrypt for free HTTPS, and to the libraries it's built on:

  • modernc.org/sqlite: a pure-Go SQLite, and the reason the whole app ships as one binary with no cgo and cross-compiles anywhere.
  • goja: the embedded JavaScript engine that runs model-authored server functions and multiplayer game logic in a sandbox.
  • esbuild: parses and statically analyses the JavaScript the model writes.
  • chromedp + cdproto: headless-Chrome automation for the runtime validator and PDF generation.
  • certmagic: automatic Let's Encrypt issuance and on-demand TLS.
  • chi: HTTP routing.
  • coder/websocket: WebSockets for realtime rooms, feeds, and calls.
  • golang-jwt: JSON Web Tokens for end-user auth.
  • ledongthuc/pdf: PDF text extraction.

Plus google/uuid, zap, and the Go team's golang.org/x crypto, net, and text packages.

Meet the 'Team'

Hi I'm Mark.

Be nice to others. It makes the world a much nicer place to live in!

If you need me I'm on X (@antifoundering)

Meet my team

A personal Note

I don't do hype, and I believe real talent is hard to find. A significant portion of workplace activity is self-justifying: processes and tasks that exist to preserve roles rather than produce outcomes.

The workplace fascinates me precisely because I've never figured it out. Sandboxes governed by their own rules and power dynamics, none of which ever made sense to me. But people want to belong to something. A group, a mindset, a reassurance that they're doing great things while wearing a hoodie with the company logo on it. Until a higher paying job comes along.

I think there's comfort in that, in running on autopilot. Honestly, I wish I could. It would have spared me the mental toll, and everything that followed from it: the physical, the relational, the financial. That's the cost of trying to act like a machine when you aren't one.

So if you want to take anything from this: you'd better hope you're a robot. Otherwise life will bring you to your knees while the world keeps moving. I've used the workplace as an example, but this applies to everything.

Or maybe, just maybe, it's all just me.

Contributors

markdr-hue

45 commits

Languages

Go

88.2%

JavaScript

9.9%

CSS

1.7%