A full-stack MERN application for building dynamic forms with a drag-and-drop interface, and for tracking and viewing the responses they receive.
π Live demo: easy-quick-form.vercel.app Β Β·Β API: easy-quick-form-api.vercel.app/api/docs
- π Sign in with Google (Google-only auth; no passwords to manage), backed by JWT access tokens and refresh tokens with reuse detection and rotation.
- πͺ Logout and delete account.
- πΌοΈ Profile-picture upload with drag-and-drop and cropping.
- π§± Drag-and-drop form builder with many element types.
- π Full CRUD and search over forms.
- π Form submission and response viewing.
- π§° Rich form elements β WYSIWYG editor, calendar, date-range picker, and more.
- πͺ΅ Centralized error logging and consistent error handling / user feedback.
Note: profile pictures are uploaded to ImgBB when
IMGBB_API_KEYis set, otherwise to Cloudinary when theCLOUDINARY_*env vars are set, and otherwise to the server's local disk (fine for local development). On Vercel, avatar uploads return503unless ImgBB or Cloudinary is configured.
| Layer | Technologies |
|---|---|
| Frontend | React, TypeScript, Tailwind, ShadcnUI, React Hook Form, Zod, React Router, DND Kit, TanStack Query/Table, Tiptap, React Dropzone, React Easy Crop, Zustand |
| Backend | Node, Express, TypeScript, Mongoose, Google OAuth, Multer, Sharp, JWT |
| Database | MongoDB |
| Shared | Zod validation schemas reused across client and server |
This is a pnpm workspace monorepo:
easy-quick-form/
βββ client/ # React + Vite frontend
βββ server/ # Express + TypeScript API
βββ packages/
βββ validation/ # Shared Zod schemas (used by client and server)
-
Node.js 18+
-
pnpm β enable via Corepack (ships with Node 16.13+):
corepack enableβ¦or install globally:
npm install -g pnpm -
A MongoDB database β e.g. a free MongoDB Atlas cluster.
-
A Google OAuth client (Google Cloud Console β APIs & Services β Credentials β OAuth client ID, type "Web application"). Add
http://localhost:4400(andhttp://localhost:8080for Docker) as Authorized JavaScript origins; no redirect URIs are needed. Sign-in is Google-only, so this is required.
-
Clone and install
git clone https://github.com/SahinurDEV/easy-quick-form.git cd easy-quick-form pnpm install -
Build the shared validation package (required before the first run β both apps depend on it)
pnpm -F @form-builder/validation build
-
Configure environment variables. Copy each example file and fill it in:
cp server/.env.example server/.env cp client/.env.example client/.env
-
Run everything (client + server together)
pnpm dev
The client runs on
http://localhost:4400and the API onhttp://localhost:8000.
Bring up the whole stack (MongoDB + API + client) with one command:
docker compose up --buildThe client is served on http://localhost:8080, the API on http://localhost:8000.
Override secrets (JWT, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET) via a root .env file or your shell.
pnpm -F @form-builder/server test # API/auth integration tests (Vitest + Supertest)
pnpm -F @form-builder/client test # component tests (Vitest + Testing Library)Interactive Swagger UI is served by the API at /api/docs (e.g.
http://localhost:8000/api/docs).
Run from the repo root:
| Command | Description |
|---|---|
pnpm dev |
Start the client and server in watch mode |
pnpm build |
Build all workspace packages |
pnpm preview |
Preview the production builds |
The live demo runs as two Vercel projects built from this monorepo (both are connected
to the GitHub repo, so every push to main redeploys them):
| Project | Root directory | What it is |
|---|---|---|
easy-quick-form |
client |
Vite static build; client/vercel.json adds the SPA fallback rewrite to index.html |
easy-quick-form-api |
server |
Express app as a single serverless function (server/api/index.js); server/vercel.json rewrites every path to it |
Both projects use Node.js 24.x, keep "Include files outside the root directory"
enabled (the shared packages/validation lives outside them), and install from the
workspace root with pnpm. The build commands compile @form-builder/validation first.
How the API runs serverless:
server/api/index.jsreuses the compiled Express app (dist/app.js) without callingapp.listen, and caches the MongoDB connection across warm invocations (server/src/utils/db.ts).pnpm dev/ Docker still startsrc/server.tsas before.trust proxyis enabled on Vercel so rate limiting sees the real client IP.- The refresh-token cookie is
SameSite=None; Secure, so it works across the two domains. - Swagger UI's static assets are copied into the static output at build time
(
server/scripts/copy-swagger-assets.js).
Environment variables:
- API:
DATABASE,ACCESS_TOKEN_SECRET,REFRESH_TOKEN_SECRET,NODE_ENV=production,CLIENT_URL(the client origin, for CORS),GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET(required: sign-in is Google-only). Optional:IMGBB_API_KEYorCLOUDINARY_*(avatar uploads; without them uploads answer503). TheSMTP_*variables are no longer used. - Client:
VITE_BACKEND_BASE_URL(e.g.https://<api-domain>/api/v1),VITE_SECRET_KEY, andVITE_GOOGLE_CLIENT_ID(same value asGOOGLE_CLIENT_ID).VITE_*values are baked into the public JS bundle, so never put real secrets in them.
To deploy your own copy: create the two projects with the root directories above, set the
env vars, then run vercel deploy --prod from the repo root (or push to the connected repo).
Base path: /api/v1
Auth
| Method | Endpoint |
|---|---|
| POST | /auth/google |
| GET | /auth/refresh |
| GET | /auth/logout |
Sign-in is Google-only: the former email/password endpoints (/auth/signup, /auth/login,
/auth/forgot-password, /auth/reset-password/:token, /user/change-password) return
410 Gone.
User
| Method | Endpoint |
|---|---|
| GET | /user/profile |
| PATCH | /user/profile |
| DELETE | /user/delete-account |
Forms
| Method | Endpoint |
|---|---|
| GET | /forms?page=0&pageSize=10&sort=-name&search=form |
| GET | /forms/:id |
| POST | /forms |
| PATCH | /forms/:id |
| PATCH | /forms/bulk-delete |
| DELETE | /forms/:id |
Form responses
| Method | Endpoint |
|---|---|
| GET | /forms/:id/responses |
| POST | /forms/:id/responses |
Contributions are welcome! Please read CONTRIBUTING.md for the development workflow and guidelines, and our Code of Conduct.
Found a vulnerability? Please see SECURITY.md for how to report it responsibly.
Distributed under the MIT License.