Skip to content

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

Live coding interview — Greeting Settings

A small Next.js task to talk through architecture together. Plan for about an hour of coding plus discussion.

Setup

Requires Node.js 20+.

npm install
npm run dev

Open http://localhost:3000 — you'll land on /settings/greeting.

What you're building

We're building a SaaS for call centers. Each organization has an auto-greeting — a short message played automatically when a customer calls in.

You build the page at /settings/greeting:

  • Everyone in the org sees the current greeting text.
  • Admins also see a form that lets them edit and save the greeting.

The form itself is your call — a text input or textarea, a save button, whatever loading state and feedback you think the user needs. Make sane UX choices; you don't need to overengineer it.

Acceptance criteria

A Mock auth bar sits at the top of every page with three buttons: Login as Admin / Login as Member / Logout. Use it to switch roles and verify each scenario.

# Acting as Expected behaviour
1 admin Sees the current greeting and the edit form. Saving updates the text; refreshing the page shows the saved value.
2 member Sees the current greeting. The form is not rendered.
3 logged out Visiting /settings/greeting redirects to /sign-in.
4 member, but malicious Calls the update endpoint directly (DevTools fetch / curl) bypassing the UI. The request must be rejected on the server.

Scenario #4 is the one we'll actively try to break — build it knowing we'll poke.

What you have to work with

Backend (lib/backend.ts)

Two async functions. They persist to data/state.json, so changes survive page refreshes.

backend.getGreeting(orgId: string): Promise<{ text: string }>
backend.updateGreeting(orgId: string, text: string): Promise<void>

Auth (lib/auth.ts)

One async function. Reads the cookie set by the mock auth bar.

auth.getCurrentUser(): Promise<{
  id: string;
  orgId: string;
  role: 'admin' | 'member';
} | null>

Project tour

app/
├── layout.tsx                   Root layout, mounts the mock auth bar
├── page.tsx                     Redirects "/" → "/settings/greeting"
├── sign-in/page.tsx             Placeholder for the redirect target
├── settings/greeting/page.tsx   ← your work goes here
├── _components/RoleSwitcher     The mock auth bar (server component)
└── _actions/setRole             Server action behind the bar's buttons
lib/
├── backend.ts                   Persisted state, fs-backed
└── auth.ts                      getCurrentUser, cookie-backed
data/state.json                  The persisted "database"

Everything here is modifiable. Refactor, rename, replace, restructure — just be ready to explain why. The scaffolding is here to save you setup time, not to constrain your design.

Ground rules

  • Any libraries are fair game — zod, react-hook-form, react-query, tRPC, NextAuth, anything else. Install with npm i <name>.
  • Any AI assistant is fair game — Cursor, Claude, ChatGPT. Be ready to explain each meaningful decision and defend it if challenged.
  • Think out loud. Saying "not sure, let me check the docs" is a strong answer; confidently guessing is a weak one.
  • Ask if anything's ambiguous. Don't guess your way around requirements.

What we'll be paying attention to

We're not grading "did your solution match our codebase". We're listening for how you reason about:

  • Trust boundaries — who decides what, and who is allowed to lie?
  • Validation — when and where do you check the shape of data?
  • Types — single source of truth, or duplicated by hand?
  • Composition — how do you avoid copy-pasting similar checks?
  • Server vs client — what runs where, and why does it matter?

The size of the diff is irrelevant. The quality of the decisions behind it is everything. Good luck — and have fun.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages