Skip to content

Repository files navigation

unlovable

A self-hostable replacement for Lovable ($25/mo). Describe a website, watch it get built page by page, refine it by chatting, export it. Runs on a free hosted model, or fully offline on your own machine.

Drop #001 of Slopsource. Not affiliated with Lovable.

unlovable building a coffee roaster site: chat and version history on the left, live preview on the right

A real site built by gemma-4-26b-a4b:free — chat and history on the left, live preview on the right, export and deploy top-right.


Quickstart

cp ../.env.example ../.env
cd unlovable && docker compose up

Open http://localhost:4321. The app asks you to connect a model on first run — pick a provider, paste a free key, done. No file editing.

Without Docker:

npm install && npm run dev

Read this before you rely on it

Free tiers have a daily request cap. A 5-page site costs 6 requests (one plan, one per page). On OpenRouter's free tier that works out to roughly 8 sites a day before you get:

429 Rate limit exceeded: free-models-per-day

That is the provider's limit, not a bug, and the app shows you the message. If you hit it: switch provider in Settings, run locally, or add credits with whoever you're using.

Running locally needs one non-obvious flag:

OLLAMA_CONTEXT_LENGTH=16384 ollama serve

Ollama defaults to 4096 tokens. Every chat edit sends the whole site, which overflows that and is truncated silently — editing looks completely broken while generation looks fine. This cost an hour to diagnose.


unlovable landing screen with prompt box and model picker

What it does

  • Describe a site in a sentence → a complete multi-page static website
  • Watch each page get written, one at a time
  • Chat to refine: "make the headline punchier", "add a pricing section"
  • Pick your model from the free ones your provider offers
  • Full version history, one-click rollback
  • Reopen anything you've built before
  • Export a .zip of dependency-free HTML and CSS
  • Deploy to Netlify in one click, if you add a token

What it doesn't do

Up front, because finding out later is worse.

  • Static sites only. Marketing pages, portfolios, landing pages. No React apps, no backend, no database, no forms that submit anywhere.
  • No images. Pages are built from type, colour and layout. There is no image generation and no stock library.
  • Single user, no auth. It's your machine. Don't expose it to the internet.
  • The model writes structure, not CSS. Design comes from tokens rendered by code, which is why separately-generated pages look like one site. You get a coherent site, not an arbitrary one.
  • A page containing a literal ======= line can break editing. That's the delimiter of the SEARCH/REPLACE format the edit loop uses; aider has the same limitation.
  • Max 5 pages per site. More pages means more sequential model calls, and that gets slow fast.
  • Free models vary a lot. Some advertised as free return nothing at all. The picker only lists ones your provider actually offers, but it can't tell you which are good — see the table below.

Models

Measured, not estimated.

Hosted — one full page, same prompt, via OpenRouter:

Model Time Finished cleanly
google/gemma-4-26b-a4b-it:free ← default 62s
poolside/laguna-s-2.1:free 112s
openai/gpt-oss-20b:free 135s
inclusionai/ling-3.0-flash:free 15s ❌ truncated
nvidia/nemotron-3-ultra-550b-a55b:free 219s ❌ truncated

Of the 17 models OpenRouter lists as free, 8 actually answer. cohere/north-mini-code:free sounds ideal and returns empty. Reasoning models are the usual failure: they spend the token budget thinking and get cut off before the answer. The app rejects truncated output rather than handing you half a page — raise LLM_MAX_TOKENS or pick another model.

Localqwen2.5-coder:7b on an Apple Silicon laptop, fully offline:

Step Time
Site plan 22s
Each page 23–39s
One chat edit 10–19s
Export 0 remote references

A 7B model is the floor and it clears it: valid plan JSON, no <style> tags, no markdown fences leaking through, working nav links.


How it works

The interesting part is what the model isn't asked to do.

  1. Plan — one small call returns JSON: the page list plus seven design tokens. The response is scanned for every balanced JSON value and the last one that parses wins, so a model that shows an example before its real answer doesn't poison the result.
  2. Stylesheet — rendered by TypeScript from those tokens. The model never writes CSS. This is why separately-generated pages look like one site, and why exports have no CDN dependency. Tokens that would inject CSS or fetch something remote are rejected.
  3. Pages — one bounded call per page, writing semantic HTML against a fixed class vocabulary the stylesheet is guaranteed to define. Nothing depends on a single long generation succeeding.
  4. EditsSEARCH/REPLACE blocks, not file rewrites. Short, and a miss is detectable, so it retries with the exact error fed back. Model-authored paths are flattened to bare filenames before they can reach the exported zip.
  5. Versions — every generation and edit appends an immutable snapshot. Current state is just the newest one, so what you see and the history can't disagree.

Configuration

Settings saved in the app win over the repo root .env, which wins over defaults. You never need to edit a file.

Variable Default
LLM_BASE_URL https://openrouter.ai/api/v1 Any OpenAI-compatible endpoint
LLM_MODEL google/gemma-4-26b-a4b-it:free
LLM_API_KEY (empty) Free key, no card
LLM_TIMEOUT_MS 240000 One hosted call has taken 219s
LLM_MAX_TOKENS (unset) Raise if a verbose model truncates
NETLIFY_TOKEN (unset) Enables the Deploy button
DB_PATH ./data/unlovable.db

Free keys, none needing a card: OpenRouter · Groq · Google AI Studio · Cerebras · NVIDIA

There is no keyless free model. Every hosted provider rejects unauthenticated completions — checked, not assumed. "Free" means free of charge, not free of signup. Local is the no-signup option.


Development

npm test          # 144 tests, no network required
npm run typecheck
npm run build:check   # builds to .next-verify so it can't disturb a running dev server

Everything in src/lib/ is pure and tested. API routes are thin wiring. That boundary is deliberate — it's where the confidence comes from.


Verified, and not

Verified by running it, not by reading the code:

  • Plan → pages → preview, on a hosted model and on a local one with no network
  • Chat edit landing on the right file, with the change present in the exported zip
  • Version history and rollback
  • Reopening a previously built project with its files, versions and model
  • Export — and grep across the extracted zip finds no http:// or https:// anywhere
  • docker compose up --build from a cold daemon, reaching a model on the host
  • Saving a provider you have no key for is refused rather than silently accepted

Not verified:

  • The Deploy button. The code path is written but has never run — there was no Netlify token to test with.
  • Models other than the ones in the table above.

MIT.

About

A self-hostable replacement for Lovable. Describe a website, watch it get built page by page, refine it by chatting, export it.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages