A lightweight Next.js 14 survey engine designed for client onboarding and project completion workflows. It runs without a database, parsing declarative JSON files into dynamic validation schemas and delivering responses over email.
flowchart TD
subgraph Client["Client Browser (WebGL & Motion)"]
UI["User Interface"]
Shader["OGL WebGL Silk Canvas"]
Inputs["Framer Motion Caret Inputs"]
TurnstileWidget["Cloudflare Turnstile Widget"]
end
subgraph SecurityLayer["Security & Gateway Pipeline"]
TurnstileCheck{"1. Turnstile Verified?"}
HoneypotCheck{"2. Honeypot Clean?"}
RateLimitCheck{"3. Cookie HMAC Valid?"}
end
subgraph CoreEngine["Server Execution Engine"]
JSONParser["JSON Config Loader"]
ZodCompiler["Dynamic Zod Schema Compiler"]
FormValidator["Runtime Payload Validator"]
Mailer["Resend Mail Dispatcher"]
end
UI --> TurnstileWidget
TurnstileWidget -- Token Generated --> UI
UI -- "POST /api/survey/submit" --> TurnstileCheck
TurnstileCheck -- No --> Reject403["403 Forbidden"]
TurnstileCheck -- Yes --> HoneypotCheck
HoneypotCheck -- Bot Detected --> SilentSuccess["200 Fake Success"]
HoneypotCheck -- Clean --> RateLimitCheck
RateLimitCheck -- Exceeded --> Reject429["429 Rate Limited"]
RateLimitCheck -- Pass --> JSONParser
JSONParser --> ZodCompiler
ZodCompiler --> FormValidator
FormValidator -- Invalid --> Reject400["400 Field Errors"]
FormValidator -- Valid --> Mailer
Mailer --> AdminEmail["Admin Inbox (HTML + JSON attachment)"]
Mailer --> ParticipantEmail["Participant Inbox (Confirmation)"]
sequenceDiagram
autonumber
actor Client as Visitor Browser
participant API as /api/survey/submit
participant Config as survey/data/surveys/*.json
participant Schema as survey/lib/survey-schema.ts
participant Resend as Resend Mailer API
Client->>API: Submit JSON Payload (Answers + Respondent + Tokens)
API->>Config: Fetch Survey Config by Token
Config-->>API: Return Raw Survey Schema Definition
API->>Schema: buildSurveySchema(config)
Note over Schema: Compiles Zod Object dynamically<br/>matching Question Types & Required Rules
Schema-->>API: Executable Zod Schema
API->>API: schema.safeParse(payload)
alt Validation Failed
API-->>Client: 400 Bad Request + Field Error Map
else Validation Succeeded
par Admin notification
API->>Resend: Send HTML notification + JSON export
Resend-->>API: Admin message accepted
and Participant confirmation
API->>Resend: Send localized confirmation
Resend-->>API: Participant message accepted
end
API-->>Client: 200 Success + Redirect URL
end
Note
All visual assets, shaders, and micro-interactions run on the client's GPU via WebGL, keeping server-side CPU consumption near zero.
Surveys are written as plain JSON definitions. The server reads the file on demand and compiles a Zod validation schema matching question types and requirements.
- Cloudflare Turnstile: Submission buttons are disabled until the client challenge resolves.
- Honeypot Traps: Silent failure routing traps malicious automated submitters.
- Signed Cookie Rate Limiting: HMAC-signed cookies prevent rapid repeated POST requests.
Background rendering uses custom satin silk shaders via OGL. A MutationObserver detects document root class changes, switching shader color palettes dynamically between light mode (#ECEAE4) and dark mode (#36323B).
Responses compile into styled HTML emails delivered via Resend. The administrator notification also includes one downloadable UTF-8 JSON attachment (survey-response/v1) with localized question labels, raw answer values, and readable display values. The participant receives a separate localized receipt without answers, IP information, or an attachment. The submission is considered successful only after Resend accepts both messages.
The application does not persist survey responses or email attachments. In development mode without API keys, both messages are simulated with generic logs and no participant address or response payload is printed.
| Layer | Library / Engine | Technical Role |
|---|---|---|
| Core | Next.js 15.5 (App Router) | React Server Components, Server Actions |
| Language | TypeScript 5.8 | Strict type assertions across JSON & runtime APIs |
| Styling | Tailwind CSS v4 | CSS variable design tokens and utility rules |
| Graphics | OGL 1.0 | Low-overhead WebGL shader pipeline |
| Motion | Framer Motion 12 | Caret position spring physics |
| Validation | Zod 3.23 | Dynamic runtime schema synthesis |
| Resend 4.0 | Direct HTML mail dispatch | |
| Bot Gate | React Turnstile | Cloudflare Turnstile token validation |
Memory Allocation (RAM):
[==================== ] 70 MB (Idle)
[============================ ] 110 MB (Active Submit)
CPU Load (1 vCPU Core):
[= ] <1% (Idle)
[=== ] <5% (Spike during POST parsing)
.
├── app/ # Next.js App Router entry points
│ ├── layout.tsx # Root layout, Google fonts, theme init script
│ ├── globals.css # Tailwind imports and CSS token definitions
│ ├── (survey)/ # Route group sharing the survey shell
│ │ ├── layout.tsx # Shell wrapper with floating controls
│ │ ├── [slug]/page.tsx # Dynamic survey page loader
│ │ └── thank-you/page.tsx # Submission confirmation page
│ ├── not-found.tsx # Clean 404 page
│ └── api/
│ └── survey/submit/route.ts # Verification and mail submission route
├── survey/ # Core domain logic
│ ├── data/surveys/ # JSON survey configs (onboarding, completion)
│ ├── components/ # UI components, question types, WebGL canvas
│ ├── i18n/ # Turkish / English translation dictionaries
│ ├── lib/ # Zod schema builder, rate limiter, mailer, JSON export
│ └── styles/ # Tokens and color definitions
└── README.md
- Node.js
18.17.0or higher - pnpm
9.0.0or higher
Create .env.local in the project root:
# Mail Delivery
RESEND_API_KEY=re_your_resend_api_key
RESEND_FROM_EMAIL=surveys@yourdomain.com
NOTIFICATION_TO_EMAIL=admin@yourdomain.com
# Cloudflare Turnstile
NEXT_PUBLIC_TURNSTILE_SITE_KEY=1x00000000000000000000AA
TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA# Install dependencies
pnpm install
# Start development server
pnpm dev
# Build for production
pnpm build
pnpm startDefault local routes:
- Onboarding Survey:
http://localhost:3000/client-onboarding - Completion Survey:
http://localhost:3000/project-completion
This project is licensed under the MIT License.