This template comes configured with the bare minimum to get started on anything you need.
Your task is to build a minimal but functional quiz app using:
- Next.js (latest version. Use either SSR or SSG) + typescript
- Payload CMS (connected to Postgres)
- Tailwind CSS for styling
The quiz is based on a cosmic personality test (see sample JSON below). The app must meet the outlined user journeys and backend criteria. Bonus points for modularity, maintainability, clarity, and simplicity.
To spin up this template locally, follow these steps:
- First clone the repo if you have not done so already
- Connect with your local postgres instance and input credentials in
.env npm install && npm devto install dependencies and start the dev server- open
http://localhost:3000to open the app in your browser
Youβll use this data (store in Payload CMS) to build the quiz:
π¦ Sample Quiz Data:
{
"title": "What Kind of Cosmic Animal Are You?",
"questions": [
{
"id": 1,
"question": "What's your ideal weekend vibe?",
"options": [
{ "label": "Stargazing in silence π", "score": 0 },
{ "label": "A road trip with no map π", "score": 1 },
{ "label": "Organizing your sock drawer π§¦", "score": 2 },
{ "label": "Hosting a secret underground rave π", "score": 3 }
]
},
{
"id": 2,
"question": "How do you respond to conflict?",
"options": [
{ "label": "Meditate and wait for the storm to pass π§", "score": 0 },
{ "label": "Speak up, but keep it chill π", "score": 1 },
{ "label": "Write a pros-and-cons list π", "score": 2 },
{ "label": "Throw a pie (or a metaphorical one) π₯§", "score": 3 }
]
},
{
"id": 3,
"question": "Which color calls to your soul?",
"options": [
{ "label": "Deep violet π", "score": 0 },
{ "label": "Electric blue β‘", "score": 1 },
{ "label": "Earthy brown π±", "score": 2 },
{ "label": "Neon green π’", "score": 3 }
]
},
{
"id": 4,
"question": "Your dream mode of transport?",
"options": [
{ "label": "Flying carpet πͺ", "score": 0 },
{ "label": "Teleportation π«", "score": 1 },
{ "label": "Tank π‘οΈ", "score": 2 },
{ "label": "Unicycle on fire π₯", "score": 3 }
]
},
{
"id": 5,
"question": "Pick a snack:",
"options": [
{ "label": "Moon cheese π§", "score": 0 },
{ "label": "Spicy chips πΆοΈ", "score": 1 },
{ "label": "Wasabi popcorn πΏ", "score": 2 },
{ "label": "Cosmic brownies π«", "score": 3 }
]
},
{
"id": 6,
"question": "What's your greatest strength?",
"options": [
{ "label": "Patience", "score": 0 },
{ "label": "Curiosity", "score": 1 },
{ "label": "Planning", "score": 2 },
{ "label": "Chaos energy", "score": 3 }
]
},
{
"id": 7,
"question": "Choose a celestial body:",
"options": [
{ "label": "The Moon π", "score": 0 },
{ "label": "A comet βοΈ", "score": 1 },
{ "label": "A black hole π³οΈ", "score": 2 },
{ "label": "A rogue planet π", "score": 3 }
]
},
{
"id": 8,
"question": "What's your social energy?",
"options": [
{ "label": "Low-key lurker", "score": 0 },
{ "label": "One-on-one convos", "score": 1 },
{ "label": "Team brainstormer", "score": 2 },
{ "label": "Life of the party", "score": 3 }
]
},
{
"id": 9,
"question": "Whatβs your spirit time of day?",
"options": [
{ "label": "3am under the stars π", "score": 0 },
{ "label": "Sunrise hustle π
", "score": 1 },
{ "label": "Midday focus βοΈ", "score": 2 },
{ "label": "Midnight rebellion π", "score": 3 }
]
},
{
"id": 10,
"question": "What animal resonates with you most?",
"options": [
{ "label": "Owl π¦", "score": 0 },
{ "label": "Fox π¦", "score": 1 },
{ "label": "Bear π»", "score": 2 },
{ "label": "Dragon π", "score": 3 }
]
}
],
"results": [
{ "range": [0, 6], "label": "π Mooncat β Mysterious, calm, and observant." },
{ "range": [7, 14], "label": "π¦ Solar Fox β Clever, curious, and adaptable." },
{ "range": [15, 22], "label": "π» Cosmic Bear β Grounded, strong, and thoughtful." },
{ "range": [23, 30], "label": "π Galactic Dragon β Wild, bold, and unstoppable." }
]
}Your implementation must support the following flow, if possible in one or 2 pages maximum to save time:
-
Take the quiz
- Display each question and options(shuffled)
- Allow user to answer all 10 questions
- On submit, calculate total score and show matching result label
-
Score page
- Show total score and matching cosmic animal
- Show how the score was calculated (score breakdown or logic)
- Include an optional free-text "Notes" field
- Add a playful easter egg: If the user scores exactly 13, replace the label with βYou lucky fucker! You scored 13 exactly.β
-
Email saving
- Ask user for email (optional)
- If user enters it, store quiz results + score + notes in the DB
-
Retrieve old results
- User enters email
- App shows previous quiz score, notes, breakdown, just like the score page
-
Data encryption
- Encrypt/decrypt ONLY one field("Notes" if any) field in Payload using Hooks. See code snippet below.
- Acceptable methods:
- Store hashed data in DB, decrypt it for display
- See
Payload Encryption (Notes Field)section for exact code snippet
- Use only:
- Next.js
- Payload CMS + Postgres
- TailwindCSS
- Minimal client-side JavaScript
- No 3rd party quiz libraries or AI-generated code
- Modular, readable, production-quality code
- Follow clean architecture: reusable components, services, and schema definitions
- Document logic where needed (README inline or in code)
- Focus on clarity, naming conventions, maintainability
- β
Questions & options editable from Payload CMS UI
- Support question order, option scores, etc.
- β Mobile responsive
- β SSG with fallback or SSR for score screen
- β
CI/CD setup or
.env.examplefor local testing - β No client-side state management lib required
| Score Range | Result | --| | 0β6 | π Mooncat | | 7β14 | π¦ Solar Fox | | 15β22 | π» Cosmic Bear | | 23β30 | π Galactic Dragon |
Each question has 4 options scored 0β3. Sum all selected option scores. Match total score with result range.
Use Payload Hooks to:
- Before save: Encrypt the
notesfield - After read: Decrypt it for admin and API use
- Just donβt store notes in plain text
Use the following code snippet to save time.
export function encrypt(str, shift = 3) {
return str
.split('')
.map(char => String.fromCharCode(char.charCodeAt(0) + shift))
.join('');
}
export function decrypt(str, shift = 3) {
return str
.split('')
.map(char => String.fromCharCode(char.charCodeAt(0) - shift))
.join('');
}- Upload to GitHub and share a public repo
- Include instructions to run CMS (
yarn,.env, Docker if needed) - Link to deployed app (if hosted)
- Be prepared to walk through the structure
What to do if test takes longer than 2 hours? Before exceeding 2 hours, Write a brief note in your README explaining:
- Which parts you prioritized and why
- Which parts you skipped or simplified and why
- What you would do to complete or improve the test if given more time
- Any assumptions or architectural choices you made