Skip to content

23f3001304/FormDash

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Formdash

A form-making and sharing application. Project-organized, conditionally-routed, properly analyzed.

Built by Hemang · developer.coehemang.dev

For a tour of the code itself, jump to DEVELOPMENT.md.

What's in the box

  • Editor: drag-and-drop form builder with live preview, branching rules, multi-page flows, themed presentation, density and typography presets.
  • Public form runtime: anonymous and signed-in submissions, file uploads, password gating, response caps, close dates, geolocation with consent.
  • Owner surfaces: per-form responses list with filters, per-question analytics, response export, webhook subscriptions, personal access tokens.
  • Anti-abuse: per-IP, per-(form, IP), per-token rate limits, honeypot, timing checks, payload size and nesting caps, file MIME and magic-byte validation, SSRF guard on webhook delivery.

Stack

React + JSX on Vite, Express + JSX on Node ESM, Tailwind CSS v4, shadcn/ui, Framer Motion, Prisma (SQLite in dev, Postgres in prod), pnpm workspaces. No TypeScript.

Quick start

pnpm install
cp packages/db/.env.example  packages/db/.env
cp apps/web/.env.example     apps/web/.env
pnpm db:migrate              # applies dev migrations to SQLite
pnpm dev                     # web on :5173, API on :4000

The API process reads packages/db/.env via Node's --env-file flag, so a single file drives both the Prisma CLI and the API runtime. See apps/api/.env.example for the full list of variables the API supports.

Repo layout

apps/
  web/         React frontend (Vite). Marketing, dashboard, editor, runtime.
  api/         Express backend. JSON API at /api/v1/*.
packages/
  db/          Prisma schema + migrations + singleton client.
  forms/       Shared validators + the conditional-rule evaluator.
  ui/          shadcn-style primitives (Button, Card, Accordion).
  config/      Shared ESLint config.
scripts/       Helper scripts not shipped to prod.
Ideology/      Product, design, and code-organization source-of-truth docs.

For a per-file walkthrough see DEVELOPMENT.md.

Scripts

Dev

Command What it does
pnpm dev Web + API in parallel.
pnpm dev:web Web only.
pnpm dev:api API only.
pnpm test:api Run the API vitest suite (44 tests).
pnpm lint Lint every workspace.

Web (Cloudflare Pages build)

Command What it does
pnpm build:web Builds the web bundle to apps/web/dist.
pnpm preview:web Serves the built bundle locally (sanity check).

API (Heroku build + run)

Command What it does
pnpm build:api prisma generate against the prod schema. Runs in heroku-postbuild.
pnpm release:api prisma migrate deploy against the prod schema. Runs in the Heroku release phase.
pnpm start:api Boots the API server. What Heroku runs to start the web dyno.
pnpm heroku-postbuild Alias for build:api. Heroku auto-detects this.

Database

Command What it does
pnpm db:migrate Apply migrations to the local SQLite DB.
pnpm db:migrate:prod Apply migrations to the prod (Postgres) DB. Same script the release phase uses.
pnpm db:studio Open Prisma Studio against the dev DB.
pnpm db:generate Regenerate the Prisma client (dev schema).

Deploying

Frontend on Cloudflare Pages

  1. Connect the repo in the Cloudflare Pages dashboard.
  2. Build configuration:
    • Build command: pnpm install --frozen-lockfile && pnpm build:web
    • Build output directory: apps/web/dist
    • Root directory (advanced): leave blank
    • Node version: 20 or later (set NODE_VERSION=20 or use .nvmrc)
  3. Environment variables (Settings -> Environment variables):
    • VITE_API_BASE_URL -> https://<your-api>.herokuapp.com/api/v1
    • VITE_GOOGLE_CLIENT_ID -> your Google OAuth client ID, optional

The web bundle hits the API via cross-origin XHR with credentials: 'include'. That requires SameSite=None cookies on the API side, see below.

Backend on Heroku

  1. Create the app and add the Heroku Postgres add-on:
    heroku create your-formdash-api
    heroku addons:create heroku-postgresql:essential-0
    
  2. Set env vars (everything the API reads is documented in apps/api/.env.example):
    heroku config:set NODE_ENV=production
    heroku config:set WEB_ORIGIN=https://your-web.pages.dev
    heroku config:set FORMDASH_COOKIE_SAMESITE=none
    heroku config:set FORMDASH_STORAGE_DRIVER=s3
    heroku config:set S3_BUCKET=... S3_REGION=... S3_ENDPOINT=...
    heroku config:set AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=...
    heroku config:set RESEND_API_KEY=... MAIL_FROM='Formdash <auth@your.tld>'
    heroku config:set GOOGLE_CLIENT_ID=...
    
    DATABASE_URL is set automatically by the Heroku Postgres add-on.
  3. Push:
    git push heroku main
    
    Heroku runs pnpm install, then heroku-postbuild (prisma generate), then the release phase from the Procfile (prisma migrate deploy), then boots the web process (pnpm run start:api).

The Procfile at the repo root drives the dyno:

release: pnpm run release:api
web:     pnpm run start:api

Cookies + CORS for split deploys

When the web and API live on different origins (the Cloudflare Pages + Heroku setup above), three things have to line up:

  1. API allowlist: WEB_ORIGIN matches the Pages origin (with https://).
  2. Cookie policy: FORMDASH_COOKIE_SAMESITE=none on the API. The session cookie is then SameSite=None; Secure, which is what cross-origin XHR with credentials: 'include' requires.
  3. Web env: VITE_API_BASE_URL points at the API origin including the /api/v1 suffix.

If the web and API share a domain (behind the same reverse proxy, for example), all three can be left at defaults.

Tests

pnpm test:api          # vitest, single pass, ~450ms

Coverage focuses on the critical paths: SSRF guard, webhook HMAC roundtrip, rate-limit math, submit honeypot tolerance, file magic-byte sniffing, and the health endpoints.

For a tour of the actual files you'll edit, see DEVELOPMENT.md.

Author

Hemang · developer.coehemang.dev

Open to feedback, bug reports, and feature ideas. Reach out via the portfolio site.

License

Private project. Not open source at this point.

About

Multi-page form builder with conditional branching, themed publishing that updates the public URL on every save, signed webhooks, REST API, and a .fd file format for portable forms. React/Vite + Express/Prisma monorepo

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages