forms-free.openapps.xyz

Source

This app’s code and revision history are public. Download a copy or explore the files below.

Public
The app’s code and revision history are public.
Owned app · rev ce303909347f
Run it yourself
Take the whole tree and run it on your own machine. The download needs no account. Cloning needs a sign-in.
Download .zip
bounded clone cf614aedcf4cdabfa9c45095
A copy you download is not bounded. The guarantees this app runs under - declared egress, proven invariants, writes that fail closed - live in the runtime serving this page, not in the files. What you get is auditable source you can read and run, with no runtime guarantees attached.
← All files
AGENTS.md
# Forms

Forms is a free form and survey builder with unlimited responses, and a free alternative to Typeform, Google Forms, Jotform, SurveyMonkey, Formspree and Microsoft Forms. It is an OpenApp in the OpenApps free apps store (https://free-apps.openapps.xyz/), owned by the OpenApps team.

## What it promises

- Free, with no limit on forms, questions or responses, no ads and no paid tier. Never add a cap, an upsell or tracking.
- No sign-up for the person building a form or for the people filling it in. Every visitor is a guest account created in the browser.
- Only a form's owners can read its responses or change it. Owners are the browser that made the form and anyone who opens its admin link. People filling in a form never see other responses.
- Every form doubles as a website form endpoint: a plain HTML form can post to it with no script.
- AI assistants can do everything a person can through the public API (`functions/api.ts`), documented in `public/llms.txt`. Keep that file true whenever the API changes.

## How it is built

- `index.html` is the static landing page that search engines and AI crawlers read. Keep its copy, comparison table, FAQ and JSON-LD in sync with what the app does, and `public/index.md` (the same page as plain markdown) in sync with it. Competitor figures link to each company's own pricing page with the month they were checked; check them again before changing the date.
- `src/` is the React app. `/` keeps the landing (and lists "Your forms" from localStorage); `/new` is the builder; `/f/<id>` is the public form; `/f/<id>/results` (summary), `/f/<id>/responses`, `/f/<id>/edit` and `/f/<id>/share` are the owner pages.
- The public form reads the form from the public API (`GET /forms/<id>`) and sends the response there, so respondents never sign in and the page does not load the account library. The builder and owner pages load it on demand (`React.lazy` in `src/main.tsx`). Answers in the link (`?<label or id>=<answer>`) are filled in ahead, and a half-filled form is kept in sessionStorage.
- `functions/lib/forms.ts` is shared by the app and the API: question types, form and answer checks, conditions (`showIf`: show a question only when an earlier choice, checkboxes, dropdown or yes or no answer matches; hidden questions are skipped), summaries (including the Net Promoter Score for the 0 to 10 `scale`) and CSV. Change validation there so both sides stay identical.
- `functions/lib/config.ts` holds the app id, the site URL and the API base used in links.
- `public/llms.txt` and `public/openapi.json` describe the API for assistants. Keep both true whenever the API changes.
- `policy.json` holds the data rules:
  - `forms/<id>` is readable by anyone who joined it (`forms/<id>/joins/<userId>`, which needs only the id), and writable by owners.
  - `forms/<id>/owners/<userId>` is created by the creator in the same batch as the form, or by anyone who writes the matching admin key into `formclaims/<id>/c/<userId>` in the same batch.
  - `formkeys/<id>` holds the 24-character admin key. Only the API's public principal can read it, to check keys callers present.
  - `forms/<id>/responses/<responseId>` can be created by anyone who joined while the form is not closed, with `by` set to themselves; only owners can read or delete them; nobody can edit them.
- The admin link carries the key in the URL fragment (`#k=`), which never reaches a server. The app moves it into localStorage and removes it from the address bar.
- Live reads return at most 1,000 rows, so the results page reloads every page of responses when a form has more (`useResponses` in `src/Owner.tsx`); the API pages through them the same way.
- The hosted pages cannot be framed by other websites (the platform's `frame-ancestors` header), so "put it on your website" means the HTML form snippet that posts to the endpoint, not an iframe.

## Working on it

```bash
npm install
npm run build                     # typecheck + build to dist/
```

Forms is an OpenApp, so nobody deploys it directly: changes ship through previews and releases as your runtime instructions describe.

Check a change by building a form with every question type and a condition, answering it on a phone from a second browser while the summary is open in a first, reading the results and CSV, posting an HTML form to the endpoint, and calling every API route with curl, including a wrong owner key.

## Voice

Plain words, short sentences, no jargon, no em dashes. Say what happens, not how clever it is.

Change history

Quality pass: conditional questions, 0 to 10 scale, QR code, prefill links, results tabs, API docs
ce30390934 · 5 hours ago
Bounded source sync
7d82add8ae · 1 day ago
Bounded source sync
8230fd7d59 · 1 day ago
Bounded source sync
d92a6e3b44 · 1 day ago
Bounded source sync
b548641922 · 1 day ago
Bounded source sync
b89074ffd2 · 1 day ago