# Talkform is running

A Typeform competitor is in this directory: structured forms and answers on the backend, a voice-only AI interview on the frontend, with email/password auth.

## How to use it

The server is started with `./run.sh` (or `python3 run.py`) on **http://127.0.0.1:8080**.

| What | Where |
| --- | --- |
| Landing | http://127.0.0.1:8080/ |
| Sign in / register | http://127.0.0.1:8080/login |
| Form builder + responses | http://127.0.0.1:8080/app |
| Demo interview | http://127.0.0.1:8080/to/founding |
| API docs | http://127.0.0.1:8080/docs |

**Demo account** (seeded on first boot)

- email: `demo@talkform.ai`
- password: `talkform-demo`

Register a new account from `/register` if you want your own workspace.

## API keys (assumption, not a prompt)

The prompt said to ask for keys. The output contract said not to ask interactive questions, so keys were taken from the environment:

- `OPENAI_API_KEY` was present but **empty**.
- `OPENROUTER_API_KEY` was present and is used as an OpenAI-compatible LLM (`openai/gpt-4o-mini`).
- Speech-to-text and text-to-speech use the **browser Web Speech API**, so no audio vendor key is required.
- If the LLM key is missing or the call fails, a rule-based interviewer still walks the schema (email regex, yes/no, numbers, choice labels).

To point at OpenAI instead, set `OPENAI_API_KEY` (and optionally `LLM_MODEL`) in `.env`.

## What was built

**Backend = Typeform data model**

- Forms, fields, refs, types, properties, validations, welcome/thank-you screens, logic/hidden placeholders.
- Field types: short_text, long_text, email, website, phone_number, number, date, yes_no, legal, dropdown, multiple_choice, rating, opinion_scale, nps.
- Responses stored as Typeform JSON: `token`, `landed_at`, `submitted_at`, `metadata`, `answers[]` with typed values (`text` / `email` / `choice` / `boolean` / `number` / …).
- Compatible surface at `/typeform/forms` and `/typeform/forms/{id}/responses`.

**Frontend = voice interview**

- `/to/{form_id}` is only an interviewer: orb, hold-to-talk (or space bar), spoken replies, live dossier of structured fields filling in.
- The model sees the schema, already-collected answers, and missing required refs, then asks in conversation instead of reading the form.
- Creators still get a builder at `/app` because someone has to define the structured questions.

**Auth**

- Register / login / logout, PBKDF2 passwords, HTTP-only signed session cookie, `Authorization: Bearer` for the Typeform API.

## What I could not verify here

No browser automation was available, so the mic + TTS loop was not click-tested in Chrome. HTTP auth, Typeform payloads, and interview turns (as text transcripts) were exercised with a smoke script against the live server.
