Describe an app. Get a real one — running on your own machine.
The open-source, self-hosted alternative to Lovable, Replit Agent and Base44.
Get started · What you can build · Setting it up · Put it on a server · Install guide
Describe what you want, in your own language. An AI agent plans it, builds the interface, designs the database, sets up logins, and puts it online — all inside one container on a machine you control.
It writes the app in whatever language you wrote to it in. No cloud account, no subscription, no lock-in — and your apps and their data never leave your machine.
First run to working app — no code, no configuration files.
One command. It downloads Exepad and starts it — and it sorts out Docker for you: installing it on Linux if it's missing, starting Docker Desktop on Windows if it's installed but not running, and pointing you at the download page when there's nothing to start.
macOS and Linux
curl -fsSL https://get.exepad.com | bashWindows — paste into PowerShell
irm https://get.exepad.com/install.ps1 | iexAny system with Node 18 or newer — the same command manages the install afterwards
npx exepad-app-builder upTip
Prefer downloading to typing? Every release
ships a Windows installer (.msi), a macOS package, and a Linux archive —
download, double-click, done. Steps in INSTALL.md.
1. Open http://localhost:8080 and create your account.
If you gave the installer an email and password, it already made this account — just log in. That is the recommended path: until an account exists the studio offers to create one to anyone who can reach it, and answering two questions at install time closes that window before it opens.
Skipped it? Create the account now, on the spot — same two fields, no token to
look up. Servers and shared networks should prefer the install-time prompt, or
--admin-email / --admin-password for unattended installs.
2. Open Settings and add your AI key.
Exepad does not include AI credits — you bring your own key, so you pay the provider directly and nobody sits in between. Pick your provider from the list, paste the key, save. More on setup
3. Describe your app, and watch it get built.
Each step happens in front of you. Preview the result, ask for changes the same way you asked for the app, then publish it.
Working software with a real database and user accounts — not mockups or static pages. The kind of thing it is built for:
- "A client tracker where I can add companies, log calls against them, and see which deals are stuck."
- "An inventory list for my shop, with low-stock warnings and a photo for each item."
- "A booking page where customers pick a time slot, and a dashboard showing my week."
- "An internal wiki with sign-in, so only my team can read it."
Each of those produces a multi-page application with a database behind it, logins, file uploads, and a link you can share.
Built from the single sentence in the animation above — its own theme, database, seeded data and sign-in, in one run.
| A complete application | A multi-agent builder plans the app, writes the interface, models the data, and connects it — in a single run you can watch. |
| A genuine React front end | Real components with proper styling and theming, not filled-in templates. |
| A database, automatically | Describe your data and get a full create, read, update and delete API over SQLite — plus custom logic where you need something specific. |
| Accounts built in | Per-app user sign-in, multiple pages, saved state and file uploads, out of the box. |
| Changes by conversation | Follow-up prompts edit the running app. No starting over. |
| Works in your language | Write to it in any language. It detects which one and writes the app's entire interface to match — or you can pick a different language for the app than the one you're writing in. |
| A single container | Interface, backend, database and AI agent in one image. Nothing else to install or wire together. |
| Any AI provider | Gemini, Anthropic, OpenAI, OpenRouter, or a model running on your own hardware. |
| Genuinely yours | AGPL-3.0 — and the apps you build are entirely your own. See LICENSING.md. |
Your prompts go to the AI provider you chose. Everything else — the applications, their databases, uploaded files, and the accounts that sign into them — stays in a folder on your own computer or server.
Three things reach the internet by default, none of them carrying your data: a
public-IP lookup at startup so HTTPS can name your machine, a Let's Encrypt
certificate request, and a version check when you open Settings. Set
EXEPAD_NO_OUTBOUND=1 to switch all three off.
Everything is configured in the studio, not in config files. After you sign in, open Settings:
| In Settings | What you set there |
|---|---|
| AI engine | Your provider and API key — Google Gemini, OpenAI, Anthropic, OpenRouter, or any OpenAI-compatible endpoint (Ollama, vLLM, LM Studio) — plus the model. On OpenRouter the model field searches the live catalogue. |
| Access & Domains | Your own domain and HTTPS, without touching a server config. |
| Stock images | Pexels, Unsplash, Pixabay or Openverse for photos in generated apps. |
Changes apply to your next build. No restart, no file editing, no redeploy.
Each app also gets its own Admin panel — users, database contents, uploaded files, and sign-in rules — all from the same interface.
Important
On any provider other than Gemini, fill in the Model field too. Left empty it falls back to a Gemini model name, which other providers do not recognise — so builds fail without a useful message. On OpenRouter the field searches the live catalogue as you type; on the others you type the model id yourself, and the greyed hint in the box shows the expected shape.
Setting up without the interface (unattended installs)
If you are scripting a deployment and want the instance configured before anyone logs in, these environment variables seed the same settings on first boot. Anything later saved in Settings overrides them.
| Provider | Variables |
|---|---|
| Google Gemini (default) | EXEPAD_LLM_API_KEY (or GEMINI_API_KEY) |
| Anthropic | EXEPAD_LLM_PROVIDER=anthropic · EXEPAD_LLM_API_KEY=sk-ant-… |
| OpenAI | EXEPAD_LLM_PROVIDER=openai · EXEPAD_LLM_API_KEY=sk-… |
| OpenRouter | EXEPAD_LLM_PROVIDER=openrouter · EXEPAD_LLM_API_KEY=… |
| Ollama, vLLM, LM Studio | EXEPAD_LLM_PROVIDER=custom · EXEPAD_LLM_BASE_URL=http://host:11434/v1 |
On any non-Gemini provider also set EXEPAD_LLM_MODEL_DEFAULT, for the reason
above. EXEPAD_ADMIN_EMAIL and EXEPAD_ADMIN_PASSWORD create the operator
account so there is no browser setup step at all.
Already running? Add your domain under Settings → Access & Domains and the certificate is handled for you.
Setting a server up from scratch, one command does the whole thing:
npx exepad-app-builder up --domain app.example.com --acme-email you@example.comPrefer a hosting provider? One-click templates for Render and Coolify, Portainer and Dokploy live in deploy/.
A server needs 2 GB of RAM or more and an ordinary disk — not network storage, because the database needs real file locking. Run one instance per data folder.
HTTPS, in more detail
The installers and npx exepad-app-builder up serve plain HTTP on port 8080
unless you pass --domain, which is the right shape if you already run your own
HTTPS proxy. Pass a domain and they add automatic Let's Encrypt certificates.
From a checkout, docker compose up runs Caddy inside the image with no
extra sidecar, and issues certificates itself: an internal certificate for
localhost and LAN addresses (one browser warning the first time), and a fully
trusted Let's Encrypt certificate for your machine's own
https://<your-public-ip-dashed>.sslip.io if it is reachable from the internet —
with no domain to buy.
./run.sh local (from source, without Docker) serves a self-signed certificate
on https://localhost — port 443, or 8443 without the privileged-port
capability — with plain HTTP also on 8090. Turn all of it off with
EXEPAD_HTTPS_DISABLE=1.
Behind your own reverse proxy, forward X-Forwarded-Proto and
X-Forwarded-Host. A minimal Caddy configuration is
app.example.com { reverse_proxy localhost:8080 }.
Everything lives in one place: a Docker volume named exepad-data. Updating or
reinstalling never touches it.
npx exepad-app-builder backupWarning
Use the command above rather than copying the folder while Exepad is running.
The databases are written to continuously, so copying a live instance can
produce an archive that looks fine and fails to restore — which you would
discover at exactly the wrong moment. backup stops the container for you
first.
The equivalent without the command-line tool
# Chained with && on purpose: if the stop fails, the archive must NOT be taken
# against a running database.
docker stop exepad && \
docker run --rm -v exepad-data:/data:ro -v "$PWD":/backup alpine \
tar czf /backup/exepad-backup.tgz -C /data . && \
docker start exepadCheck the archive actually contains something —
tar tzf exepad-backup.tgz | head should list meta.sqlite, apps/,
storage/ and secrets/.
Note
You should not need any of this. Everything in normal use is in Settings. The variables below are for unattended installs and unusual network setups — anything saved in Settings overrides them.
Core settings
| Variable | Purpose |
|---|---|
EXEPAD_LLM_API_KEY |
AI key — required to build apps |
EXEPAD_LLM_PROVIDER · EXEPAD_LLM_BASE_URL · EXEPAD_LLM_MODEL_DEFAULT |
Provider selection (see above) |
EXEPAD_ADMIN_EMAIL · EXEPAD_ADMIN_PASSWORD |
Create the operator account on first boot instead of using the browser setup |
PEXELS_API_KEY |
Optional stock-image search for generated apps |
EXEPAD_FETCH_ALLOWLIST |
Hosts that deployed app logic may call out to (default: none) |
PORT |
The runtime's internal listener (default 8080). Only meaningful with EXEPAD_HTTPS_DISABLE=1 — the in-image Caddy proxies to 127.0.0.1:8080 and ignores this, so changing it on the default HTTPS path takes the studio offline. Move the public port in Settings → Server & network instead. |
Secrets (EXEPAD_SESSION_SECRET, DEPLOY_SECRET, and others) are generated on
first run and kept in the data volume. They are never regenerated, so logins and
preview links survive restarts.
Networking and custom domains
Reaching the studio on a LAN address or a custom domain needs no extra configuration on its own — the browser talks to a single origin. These cover the edge cases:
| Variable | Purpose |
|---|---|
EXEPAD_ALLOWED_ORIGINS |
Extra browser origins allowed to make signed-in /api calls. An exact origin (https://app.company.com), a host:port, or a *.suffix wildcard. localhost and 127.0.0.1 are allowed by default. Optional — browsing straight to the machine is same-origin and needs nothing. Set this only for a different origin, such as a separate front end. |
EXEPAD_COOKIE_SECURE |
1 forces Secure cookies. Also automatic behind a proxy that forwards X-Forwarded-Proto: https. |
RESEND_API_KEY |
Gates all account email in your generated apps — address verification and password reset — through a Resend relay. Unset by default, so those flows cannot send. Sign-up and sign-in work regardless. |
EXEPAD_EMAIL_FROM · EXEPAD_EMAIL_FROM_NAME |
The From address for that email. Needed alongside the key: the built-in default is an @exepad.com address you cannot verify with your own Resend account, so sends using it are rejected. |
EXEPAD_EMAIL_SENDER_DOMAINS |
From-address domains allowed for that email (default exepad.com,exepad.app). |
EXEPAD_CDN_DOMAIN · EXEPAD_APP_DOMAIN |
Advanced content-security-policy overrides, only needed when serving assets from a custom CDN. |
What the agent is allowed to generate (advanced)
| Variable | Purpose |
|---|---|
ALLOWED_FETCH_DOMAINS |
Extra hosts the agent may call from generated code; anything else is rewritten to a placeholder |
ALLOWED_IMAGE_DOMAINS |
Extra image hosts allowed in generated components |
These are a different layer from EXEPAD_FETCH_ALLOWLIST: that one governs what
a deployed app may call at runtime, while these govern what the agent will
write at build time.
Architecture
One image runs two processes behind a single public port:
:8080 Node runtime (Hono on @hono/node-server)
├─ / builder UI (login / studio / apps)
├─ /a/{id} · /a/preview-… rendered generated apps
├─ /api/{id}/… gateway → in-process app-backend (auto-CRUD + handlers)
├─ /api/orchestrate/… prompt → build → compile → deploy
├─ /api/deploy · /auth/… deploy pipeline + local auth
└─ /agent/* reverse-proxy ▼
:8081 Python agent (ADK / FastAPI) — the multi-agent app builder (loopback only)
/data meta.sqlite · per-app *.sqlite · storage/ · uploads/ · agent sessions · secrets/
Cloudflare bindings are replaced by local adapters: R2 becomes the filesystem, D1
becomes better-sqlite3, Workers-for-Platforms dispatch becomes an in-process
fetch() call, and KV and Cache become in-memory shims. The agent compiles
component and handler TSX to JavaScript with esbuild at deploy time.
Build it from source
No registry and no accounts — only Docker and a checkout. This produces the same image the installers download:
git clone https://github.com/Exepad/exepad-app-builder.git && cd exepad-app-builder
docker build -t exepad-app-builder:local .
docker run -d --name exepad --restart unless-stopped \
-p 8080:8080 -e EXEPAD_HTTPS_DISABLE=1 \
-v exepad-data:/data exepad-app-builder:localBuilding costs considerably more than running: a full workspace install, a serial
compile, a Python layer and a bundled Chromium. It takes a while and wants far
more memory, CPU and disk than the roughly 2 GB the running container needs — a
small machine is better used to run an image built elsewhere.
--build-arg EXEPAD_LITE=1 skips Chromium for a smaller image (~1.7 GB
rather than ~3.1 GB); the only loss is dashboard thumbnails, which then
switch themselves off.
To have the container handle HTTPS itself, drop EXEPAD_HTTPS_DISABLE=1 and use
the bundled compose file, which uses host networking so it can bind :80 and
:443:
docker compose up --build # then open https://localhostWorking on Exepad itself
./run.sh is the development wrapper — it rebuilds from your working tree on
every start, so it is for working on Exepad rather than running a real instance.
git clone https://github.com/Exepad/exepad-app-builder.git && cd exepad-app-builder
./run.sh # build and run the single container (docker compose)
# ./run.sh local # …or from source, without Docker (runtime :8090, agent :8081;
# needs `pnpm install` and the agent venv)
# ./run.sh stop # stop the containerOpen https://localhost and accept the one-time local-certificate warning. Set
the AI key in Settings after the first login, or seed it beforehand with
echo "EXEPAD_LLM_API_KEY=your-key" > .env.
The first login asks for a setup token: ./run.sh local prints it at startup,
and ./run.sh prints it in the compose logs. EXEPAD_ALLOW_OPEN_SETUP=1 skips
the prompt on a purely local machine.
Layout and commands: CLAUDE.md, the apps/*/CLAUDE.md files, and
the development guide.
Exepad is single-tenant and trusting by design: you run your own instance and
you trust the applications you generate on it. Generated logic runs in a
restricted scope — its own database only, no filesystem or process access, and
outbound calls gated by EXEPAD_FETCH_ALLOWLIST — but that boundary enforces the
build-time validators rather than defending against deliberately hostile code.
In practice: do not hand a shared instance to people you do not trust, and do not run generated applications you have not reviewed.
Found a vulnerability? Please report it privately — see
SECURITY.md — rather than opening a public issue.
Exepad is licensed under the GNU Affero General Public License v3.0 — see
LICENSE. You are free to run, study, modify and share it. If you run
a modified version as a service for other people, the AGPL asks you to offer
those users your modifications.
The applications you build with Exepad are entirely your own. Exepad LLC
claims no ownership of and no copyright interest in them, and an explicit AGPL
section 7 permission lets you license them however you like, including closed and
commercial. The details in plain English: LICENSING.md.
Forks are welcome. They simply ship under their own name — see
TRADEMARK.md.
Install guide · Full reference · Contributing · Changelog · Issues
Built by Exepad LLC and contributors.


