Subtext Reading Coach
Lovable AI analyzes hidden meanings in dialogue so playwrights can deepen subtext; the Adamo bridge relays each cue to a humanoid on stage.
The move.
Writers open a browser 'humanoid controller' tuned for dramatic subtext: every slider, pad, or gesture publishes a control topic through the local Adamo bridge, and the robot on the Writing, Poetry & Narrative stage responds in the same beat.
Why this kernelA browser humanoid controller fits dramatic subtext because Writing, Poetry & Narrative is a live art — the operator wants a control surface they can perform with, not a config screen. Every gesture in the UI publishes a control topic the robot obeys in the same beat.
Run the bridge first.
Start the bridge on your laptop before pasting the prompt below. The Lovable app never holds the Adamo key.
The build prompt.
Paste into a fresh Lovable project. Make sure the bridge above is running first. read the bridge protocol →
Build "Subtext Reading Coach" as a ONE-SHOT Lovable build **from a phone**. The participant
has only 5 credits and only a mobile browser — this single message must ship a
working demo with zero follow-ups and zero laptop steps. Physical AI on Adamo.
CONCEPT
Lovable AI analyzes hidden meanings in dialogue so playwrights can deepen subtext; the Adamo bridge relays each cue to a humanoid on stage.
Discipline: writing (dramatic subtext).
Kernel: Author (mobile authoring).
Why this kernel: A browser humanoid controller fits dramatic subtext because Writing, Poetry & Narrative is a live art — the operator wants a control surface they can perform with, not a config screen. Every gesture in the UI publishes a control topic the robot obeys in the same beat.
MOBILE-ONLY, SANDBOX-BACKED — READ THIS FIRST
Adamo's SDK is Python-only. Cloudflare Workers cannot import it. The
participant is on a phone; there is no laptop bridge. The ONLY place inside
this Lovable session where the SDK runs is the Linux build sandbox. So:
- Every Adamo call happens in a Python script the agent runs ONCE at
build time in the sandbox.
- The script writes a JSON proof artifact into `public/` that the
deployed mobile web app fetches at runtime.
- The deployed app itself never imports adamo, never holds
ADAMO_API_KEY, never opens a QUIC/Zenoh socket, never calls a
server function that tries to.
- The runtime robot performance happens later at the physical showcase,
off-device. The mobile app AUTHORS, the sandbox VERIFIES, the operator
PLAYS BACK.
SECRETS
Request `ADAMO_API_KEY` via the add-secret tool (format hint `ak_...`).
Never reference it in .ts/.tsx code, never in `import.meta.env`, never in
a `createServerFn` handler. It lives only in the sandbox process env.
BUDGET (5 CREDITS, ONE-SHOT)
- ONE TanStack Start app, one primary route (`src/routes/index.tsx`).
- ONE mobile-first surface (touch targets >=44px, thumb-reachable primary
action, no hover-only affordances, no drag-only interactions).
- Lovable AI Gateway allowed for text (default `google/gemini-3-flash-preview`),
called from a server fn.
- NO database, NO auth, NO Lovable Cloud, NO extra pages, NO tests.
- Libraries: template defaults + `ai` + `@ai-sdk/openai-compatible` + `zod`.
VERIFIED ADAMO SDK SURFACE (adamo >= 0.4.42)
import adamo
session = adamo.connect(api_key=os.environ["ADAMO_API_KEY"])
session.put(key, payload_bytes)
sub = session.subscribe(key, callback=fn) # kwarg-only, NOT positional
session.get(key, timeout_ms=5000) # returns list[Sample]
session.live_tokens("**/alive") # discovery (returns live tokens)
session.alive(token_key) # DECLARES a token; not discovery
session.close()
Footguns: subscribe callback is kwarg-only; `alive()` declares, `live_tokens`
discovers; `connect` requires `api_key=` (keyword).
STEP 1 — SMOKE TEST (mandatory, every build)
Write this to `scripts/adamo_smoke.py` verbatim:
```python
"""Verify ADAMO_API_KEY from the Lovable sandbox and write proof to
public/adamo-smoke.json. Run once during the build."""
from __future__ import annotations
import json, os, sys, time, threading
from datetime import datetime, timezone
from pathlib import Path
OUT = Path(__file__).resolve().parent.parent / "public" / "adamo-smoke.json"
OUT.parent.mkdir(parents=True, exist_ok=True)
def write(p): OUT.write_text(json.dumps(p, indent=2) + "\n"); print(json.dumps(p))
def main() -> int:
key = os.environ.get("ADAMO_API_KEY")
if not key:
write({"ok": False, "error": "ADAMO_API_KEY missing"}); return 2
try:
import adamo
except Exception as e:
write({"ok": False, "error": f"adamo import failed: {e!r}"}); return 2
out = {"ok": False, "at": datetime.now(timezone.utc).isoformat(),
"sdk_version": getattr(adamo, "__version__", "unknown"),
"roundtrip_ms": None, "alive": [], "error": None}
s = None
try:
t0 = time.time()
s = adamo.connect(api_key=key)
out["connect_ms"] = int((time.time() - t0) * 1000)
k = f"lovable/smoke/{int(time.time()*1000)}"
got = threading.Event(); seen = {}
def on(sample):
try: seen["v"] = json.loads(bytes(sample.payload).decode())
except Exception: seen["v"] = None
got.set()
sub = s.subscribe(k, callback=on)
time.sleep(0.2)
sent = time.time()
s.put(k, json.dumps({"ping": sent}).encode())
if got.wait(3.0):
out["roundtrip_ms"] = int((time.time() - sent) * 1000)
out["ok"] = True; out["echo"] = seen.get("v")
else:
out["error"] = "roundtrip timeout"
try: sub.undeclare()
except Exception: pass
try: out["alive"] = sorted({str(t) for t in (s.live_tokens("**/alive") or [])})
except Exception as e: out["alive_error"] = repr(e)
except Exception as e:
out["error"] = f"{type(e).__name__}: {e}"
finally:
try:
if s is not None: s.close()
except Exception: pass
write(out)
return 0 if out["ok"] else 1
if __name__ == "__main__":
sys.exit(main())
```
Then in the sandbox run:
python -m pip install --no-cache-dir adamo
python scripts/adamo_smoke.py
Commit the resulting `public/adamo-smoke.json`.
STEP 2 — KERNEL JOB (Author)
SANDBOX JOB — smoke test only
The Author kernel does not need a second sandbox job. Ship the mobile
authoring UI. The `<AdamoProof />` card reading `/adamo-smoke.json` is the
only Adamo surface required.
STEP 3 — MOBILE APP
- `src/routes/index.tsx` renders the Author surface for "Subtext Reading Coach".
- Include an `<AdamoProof />` card that `fetch("/adamo-smoke.json")` on
mount and shows: "Sandbox verified at HH:MM · Xms roundtrip · N tokens
live". Empty state: "No proof yet — re-run scripts/adamo_smoke.py".
- Mobile-first layout: single column, 16-24px padding, primary CTA fixed
or bottom-anchored within thumb reach. NO desktop-only grids as the
main surface.
- Empty state copy when no robot is connected: "Your key is verified in
the sandbox. The operator will replay this on the robot at the
showcase." — never "start the bridge" or "install Python".
- Tailwind + shadcn. Editorial industrial look: gold accent, dark
background, one strong headline, one primary action.
- Footer: "Built during the Physical AI & Creative Robotics Hackathon
organised by StreetKode Fam during Indian Krump Festival 14".
BRAIN — Lovable AI Gateway (already provisioned, no key prompt)
```ts
// src/lib/ai-gateway.server.ts
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
export function gateway() {
return createOpenAICompatible({
name: "lovable",
baseURL: "https://ai.gateway.lovable.dev/v1",
headers: {
"Lovable-API-Key": process.env.LOVABLE_API_KEY!,
"X-Lovable-AIG-SDK": "vercel-ai-sdk",
},
});
}
```
Call `generateText` inside `createServerFn` handlers only.
DO / DON'T
| Do | Don't |
| ----------------------------------------------- | ---------------------------------------------- |
| Run adamo only in scripts/ (sandbox) | `import adamo` from a server fn or route |
| Read `/adamo-smoke.json` from the browser | Read ADAMO_API_KEY from `import.meta.env` |
| `session.subscribe(k, callback=fn)` | `session.subscribe(k, fn)` (positional fails) |
| `session.live_tokens("**/alive")` for discovery | `session.alive()` for discovery |
| Design for a phone in portrait first | Ship a desktop dashboard as the primary UI |
SUCCESS
On first load on a phone, the participant sees the Author surface for
"Subtext Reading Coach", the AdamoProof card shows a green "sandbox verified" line with
a real roundtrip number, and the primary action is reachable with the
thumb. That is the demo.
Market sizing.
Indicative figures for hackathon pitches — refine with your own research before raising.