// build-strategy / free-tier
Real quantum, 5 credits, one build message.
Every mega-prompt in this repo uses the same pattern, because it's the only pattern that lets a free-tier Lovable account ship a real Quantinuum demo in one shot.
Why not run Guppy at runtime?
Lovable apps deploy to Cloudflare Workers (edge JavaScript). Workers cannot run Python — so calling Selene from a server function at runtime will fail. Don't burn credits trying. Instead, run the quantum circuit at build time in the Lovable Linux sandbox, commit the real output as JSON, and let the frontend read it.
The 5-step pattern
recipe
# 1. In the Lovable Linux sandbox during the build: pip install guppylang selene-sim # 2. Author the kernel as a REAL .py file: # quantum/kernel.py (see snippet) # 3. Author a driver that runs the kernel over a small grid and writes JSON: # quantum/run.py (see snippet) # 4. Execute the driver ONCE during the build: python quantum/run.py # 5. The React app statically imports src/data/quantum-results.json. # No Python runs at runtime. No backend. No Cloud. No auth.
1. The kernel — a real .py file
Guppy reads source via inspect.getsource, so it must be on disk. REPL strings, exec(), and Jupyter cells all fail.
quantum/kernel.py
# quantum/kernel.py — a real .py file on disk (Guppy reads source via inspect)
from guppylang import guppy
from guppylang.std.builtins import result
from guppylang.std.quantum import qubit, h, cx, measure, discard
@guppy
def swap_test() -> None:
a = qubit()
b = qubit()
anc = qubit()
h(anc)
# ... prepare |a>, |b> however your problem encodes them ...
cx(anc, a)
cx(anc, b)
h(anc)
result("anc", measure(anc))
discard(a); discard(b)
2. The driver — runs once at build time
Keep the grid small (5–20 inputs, ≤8 qubits, ~256 shots). The driver writes one JSON file the frontend reads.
quantum/run.py
# quantum/run.py — runs once at build time, writes real Selene output as JSON
import json, pathlib
from selene_sim import build, Quest
from kernel import swap_test
OUT = pathlib.Path("src/data/quantum-results.json")
OUT.parent.mkdir(parents=True, exist_ok=True)
runner = build(swap_test)
records = []
for i in range(10): # candidate axis
for j in range(10): # reference axis
# bind your problem inputs here (state prep, parameters, etc.)
shots = list(runner.run_shots(Quest(), n_shots=256))
ones = sum(1 for s in shots if s.get_results().get("anc", [0])[0] == 1)
fidelity = max(0.0, 1.0 - 2.0 * ones / 256)
records.append({"input": {"i": i, "j": j}, "output": {"fidelity": fidelity}})
OUT.write_text(json.dumps(records, indent=2))
print(f"wrote {len(records)} records to {OUT}")
3. The frontend — pure static read
src/routes/index.tsx
// src/routes/index.tsx — frontend just reads the JSON, no runtime Python import results from "@/data/quantum-results.json"; // every number on screen traces back to a real Selene shot const top = [...results].sort((a, b) => b.output.fidelity - a.output.fidelity)[0];
Credit budget rules
- · One mega-prompt = one build message. No iterative refinement loop.
- · Hard scope cap: 1 page (the workspace) + an "About the quantum" strip.
- · No accounts. No Lovable Cloud. No database. No auth.
- · Add a "Quantum trace" disclosure that prints kernel.py inline so judges see it's real.
- · Keep ~1 credit in reserve for a single fix-it pass after the first build.