A full-stack form builder application inspired by Google Forms, built with React, TypeScript, Flask, and SQLite.
- Docker & Docker Compose (recommended)
- OR Node.js 20+, Python 3.11+
# 1. Copy environment template
cp config/.env.example config/.env.local
# 2. Generate a Flask secret key (paste into .env.local)
python3 -c "import secrets; print(secrets.token_hex(32))"
# 3. Start the application
docker compose upAccess the app at: http://localhost
Backend Setup:
cd backend
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# Generate secret key and add to ../config/.env.local
python3 -c "import secrets; print(secrets.token_hex(32))"
python server.pyFrontend Setup:
cd frontend
npm install
npm run devAccess at: http://localhost:5173
Shape/
├── frontend/ # React + Vite frontend
│ ├── src/
│ │ ├── components/ # Reusable components & form builder
│ │ ├── features/ # Feature-specific pages
│ │ ├── context/ # Auth context
│ │ ├── types/ # TypeScript definitions
│ │ ├── constants/ # API endpoints, defaults
│ │ ├── hooks/ # Custom React hooks
│ │ ├── lib/ # Utilities
│ │ └── main.tsx # Entry point
│ ├── package.json
│ ├── vite.config.ts
│ ├── tsconfig.json
│ ├── Dockerfile # Multi-stage build
│ └── nginx.conf # Production nginx config
├── backend/ # Flask API server
│ ├── server.py # Flask app & routes
│ ├── requirements.txt
│ ├── instance/ # SQLite database
│ ├── Dockerfile
│ └── .dockerignore
├── config/ # Configuration
│ ├── .env.example # Template (committed)
│ └── .env.local # Secrets (gitignored)
├── docs/ # Documentation
│ └── DEPLOYMENT.md # Deployment guide
├── docker-compose.yml # Local dev & production config
├── .gitignore
└── README.md
- Drag-and-drop field editor
- Multiple field types (text, email, select, checkbox, date, etc.)
- Form preview while editing
- Rich form settings (presentation, restrictions, quiz options)
- Presentation: Progress bar, shuffle questions, confirmation message
- Restrictions: Accept responses, email collection, allow editing
- Quiz Mode: Show correct answers, points, missed questions
- Defaults: Account-level default settings for new forms
- Dashboard with form cards
- Group responses by form with counts
- View individual responses
- Export data (planned)
- User authentication with password hashing
- Single-session login enforcement (token-based)
- CORS protection
- Session-based form access control
- Form owner preview mode (doesn't save responses)
- Dark mode toggle
- Responsive design
- Form cards redesigned (image removed, title/description swapped)
- Account settings page with defaults
See docs/DEPLOYMENT.md for complete configuration.
Critical for Development:
FLASK_SECRET_KEY=your_generated_key_here
FLASK_ENV=development
CORS_ORIGINS=http://localhost:5173Users
- id, email, username, password, dark_mode, default_form_settings, session_token
Forms
- id, name, description, fields (JSON), settings (JSON), user_id, created_at
FormResponses
- id, form_id, user_id, answers (JSON), created_at
POST /signup- Create new accountPOST /login- Authenticate user (generates session token)POST /logout- Logout (clears session token)GET /me- Get current user profile
GET /user/preferences- Get dark_mode and defaultFormSettingsPUT /user/preferences- Update preferences
GET /forms- List user's formsPOST /forms- Create new formGET /forms/<id>- Get form detailsPUT /forms/<id>- Update formDELETE /forms/<id>- Delete form
GET /share/<form_id>- Get form for public submission
GET /responses- Get all responses for user's forms (grouped)GET /forms/<id>/responses- Get responses for specific formPOST /forms/<id>/responses- Submit form response (with validation)
Each user has a unique session_token stored in the database. Logging in on a new device invalidates the previous session automatically.
- Development: Secrets in
config/.env.local(gitignored) - Production: Use platform secrets (Heroku, AWS, Docker, etc.)
See docs/DEPLOYMENT.md for deployment options.
When a form owner submits through the public share link, responses are not persisted, allowing owners to test without polluting data.
# Development
docker compose up
# Production
docker compose -f docker-compose.prod.yml up -dHeroku:
heroku config:set FLASK_SECRET_KEY=your_key
git push heroku mainAWS/Google Cloud/Azure: See docs/DEPLOYMENT.md
cd frontend
npm install
npm run dev # Start dev server
npm run build # Production build
npm run lint # ESLintcd backend
source venv/bin/activate
python server.py # Start servercd frontend
npx tsc --noEmitPort already in use:
docker compose -p my_app up
# OR kill process on port 80/5000Database locked:
# Restart backend container
docker compose restart backendCORS errors:
- Check
CORS_ORIGINSinconfig/.env.local - Ensure frontend URL matches
Secret key error in production:
- Set
FLASK_SECRET_KEYvia your platform's secret manager - See docs/DEPLOYMENT.md
MIT - See LICENSE file
Contributions welcome! Please follow the existing code style and create a pull request.
Built with ❤️ using React, Flask, and TypeScript