Pouta Forms, open-source alternative to TypeForm

mohanjith1 pts0 comments

GitHub - pouta-cms/form · GitHub

/" data-turbo-transient="true" />

Skip to content

Search or jump to...

Search code, repositories, users, issues, pull requests...

-->

Search

Clear

Search syntax tips

Provide feedback

--><br>We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Cancel

Submit feedback

Saved searches

Use saved searches to filter your results more quickly

-->

Name

Query

To see all available qualifiers, see our documentation.

Cancel

Create saved search

Sign in

/;ref_cta:Sign up;ref_loc:header logged out"}"<br>Sign up

Appearance settings

Resetting focus

You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.

Dismiss alert

{{ message }}

pouta-cms

form

Public

Notifications<br>You must be signed in to change notification settings

Fork

Star

main

BranchesTags

Go to file

CodeOpen more actions menu

Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit

History<br>8 Commits<br>8 Commits

src

src

.gitignore

.gitignore

ARCHITECTURE.md

ARCHITECTURE.md

README.md

README.md

package-lock.json

package-lock.json

package.json

package.json

schema.sql

schema.sql

tsconfig.json

tsconfig.json

vitest.config.ts

vitest.config.ts

worker-configuration.d.ts

worker-configuration.d.ts

wrangler.json

wrangler.json

View all files

Repository files navigation

Pouta Forms

A dynamic, high-performance, open-source Typeform alternative running entirely on the Cloudflare Edge network. Built with pure Cloudflare Workers (ES modules syntax), KV, D1, and the Workers Analytics Engine.

Features

Dynamic Form Schemas : Fetched instantly from Cloudflare KV (FORM_SCHEMAS) on public GET requests with zero cold starts.

Single-Table Submission Upserts : Partial saves (checkpoints) and completed submissions reside in the exact same D1 SQL table (submissions), indexed on (form_id, status) to preserve query performance.

Submission Locking : Completed submissions are locked and cannot be overwritten or altered.

High-Volume Telemetry : Tracks form views (viewed) and initial engagements (started) via non-blocking, fire-and-forget Workers Analytics Engine data points.

Google OAuth Login : Secure admin auth flow issuing stateless, cryptographically signed JWT sessions via Web Crypto APIs (stored as HTTP-only cookies).

Spam Protection : Optional, configuration-backed verification hooks against Cloudflare Turnstile endpoints.

Getting Started

1. Installation

Install dependencies:

npm install

2. Database Migrations

Initialize the local D1 database schema:

npx wrangler d1 execute DB --local --file=schema.sql

3. Generate TypeScript Bindings

Generate TypeScript types for all KV, D1, and Analytics bindings:

npx wrangler types

4. Running Locally

Create a .dev.vars file in the root directory with the following variables:

GOOGLE_CLIENT_ID="your-google-client-id"<br>GOOGLE_CLIENT_SECRET="your-google-client-secret"<br>JWT_SECRET="your-jwt-signing-secret"<br>ALLOWED_ADMIN_EMAILS="admin@example.com,another@example.com"<br># Optional Turnstile site verification secret<br>TURNSTILE_SECRET_KEY="your-turnstile-secret-key"

Start the local Wrangler development server:

npm run dev

Google OAuth Client Configuration

To enable admin authentication, you must configure a Google OAuth 2.0 Client:

Go to the Google Cloud Console Credentials Page.

Create or select your Google Cloud project.

Click Create Credentials and select OAuth client ID .

Set the Application type to Web application .

Configure the OAuth origins and redirect URIs:

Authorized JavaScript origins :

http://localhost:8787 (for local development)

https://your-worker-name.your-subdomain.workers.dev (for production)

Authorized redirect URIs :

http://localhost:8787/admin/oauth/callback (for local development)

https://your-worker-name.your-subdomain.workers.dev/admin/oauth/callback (for production)

Click Create to obtain your Client ID and Client Secret.

Configure these secrets in your environments:

Locally : Place them in your .dev.vars file.

Production : Set them as encrypted secrets on Cloudflare using Wrangler:<br>npx wrangler secret put GOOGLE_CLIENT_ID<br>npx wrangler secret put GOOGLE_CLIENT_SECRET<br>npx wrangler secret put JWT_SECRET<br># For live Analytics Engine statistics:<br>npx wrangler secret put CLOUDFLARE_ACCOUNT_ID<br>npx wrangler secret put CLOUDFLARE_API_TOKEN

Note<br>To transition from mocked analytics to live analytics in the admin dashboard, you must define CLOUDFLARE_ACCOUNT_ID (your Cloudflare account identifier) and CLOUDFLARE_API_TOKEN (an API token with Account Analytics: Read permission) in your production secrets. Without these, the dashboard falls back to mocked view counts.

Directory Layout

src/index.ts: Application router, OAuth flow, telemetry, Turnstile validation, and D1 upsert...

wrangler secret json oauth analytics google

Related Articles