Skip to content

Repository files navigation

Devdle

A developer-themed semantic guessing game — guess languages, frameworks, and tools from attribute clues, not letters.

Play: devdle.co.uk · Repo: github.com/jayc595/devdle

Next.js React TypeScript Prisma Vitest

What is Devdle?

Devdle is like Wordle for developers, but instead of matching letters you decode semantic attributes. Pick a category, search for a name, submit your guess, and each column reveals how close you are — typing model, execution model, paradigm, year, and more.

  • 6 guesses per puzzle
  • Two modes:
    • Unlimited — a new random target each session
    • Daily — one shared puzzle per category each UTC day
  • Feedback types: correct, partial (multi-value overlap), wrong, and higher/lower for numeric attributes

Categories

Category Words Example clues
Languages 45+ typing, execution model, memory model, primary domain, concurrency model, paradigm, year
Frameworks 65+ framework type, host language, rendering strategy, opinionated, component based, runtime
Tools 75+ tool type, primary purpose, execution environment, statefulness, complexity

Highlights

  • Server-authoritative game state — the target word is never sent to the client until you win or lose; progress lives in an AES-256-GCM encrypted httpOnly cookie.
  • Deterministic daily puzzles — a server-only secret selects the same word for every player each day without exposing it client-side.
  • Security-first edge layer — centralized request proxy with nonce-based CSP, HSTS, API lockdown CSP, same-origin guards, and IP rate limits.
  • Typed, extensible content model — categories, attribute schemas (text / enum / multi_enum / number / boolean), and word data validated at seed time.
  • Share results — Wordle-style emoji grid after each game; copy or native-share via lib/game/share.ts.
  • Local player stats — streaks and score cards stored in browser localStorage.
  • AI/crawler docs/llms.txt, /llms-full.txt, and /ai.txt for LLM and crawler discovery.
  • Privacy-first analytics — optional PostHog via first-party /ingest proxy; game events also logged in Postgres. Accept/Reject consent banner; PostHog is opt-out by default until accepted. No accounts. Policy at /privacy.
  • Test coverage where it matters — ~30 test files covering game logic, session crypto, API routes, security headers, rate limits, consent, share, and site docs.
  • CI quality gate — GitHub Actions runs tests and ESLint on every push and pull request.
  • Polished UX — staggered clue reveals, a navigation guard when leaving mid-game, and an interactive 404 terminal.

Architecture

No user accounts. The game API is stateless aside from an encrypted cookie; the word catalog lives in Postgres.

flowchart LR
  Browser --> NextApp[Next.js App Router]
  NextApp --> Proxy[proxy.ts]
  Proxy --> Pages[Pages and RSC]
  Proxy --> API[Game API routes]
  Proxy --> Ingest["/ingest PostHog proxy"]
  API --> Session[Encrypted cookie session]
  API --> Prisma[Prisma plus Neon Postgres]
  API --> Analytics[lib/analytics dual-write]
  Analytics --> Prisma
  Analytics --> Ingest
  Browser --> LocalStats[localStorage stats]
Loading

Tech stack

  • Framework: Next.js 16 (App Router), React 19, TypeScript
  • UI: Tailwind CSS 4, shadcn/ui, Base UI, next-themes
  • Data: Prisma 7 + Neon Postgres (pooled + direct URLs)
  • Analytics: PostHog (@posthog/next) with first-party /ingest proxy; events also stored in Postgres analytics_events
  • Validation: Zod 4
  • Testing: Vitest, Testing Library, jsdom
  • Tooling: ESLint 9, GitHub Actions CI

Local setup

Prerequisites

  • Node.js 22 (matches CI)
  • npm
  • A Neon Postgres database (or any Postgres instance)

1. Clone and install

git clone https://github.com/jayc595/devdle.git
cd devdle
npm install

2. Configure environment

Copy the example env file and fill in your values:

cp .env.example .env.local
Variable Purpose
DATABASE_URL Pooled connection for app runtime (Neon -pooler suffix)
DIRECT_URL Direct connection for Prisma CLI and migrations
GAME_SESSION_SECRET 32+ character random string for cookie encryption
DAILY_PUZZLE_SECRET Different 32+ character random string for daily word selection
NEXT_PUBLIC_SITE_URL Public canonical URL for OG metadata, share links, sitemap (default https://devdle.co.uk)
ALLOWED_API_ORIGINS Optional comma-separated extra origins for API same-origin checks (preview deploys)
ENABLE_DEV_TOOLS Optional. Set to true to enable the dev-only answer reveal API
DEV_TOOLS_ACCESS_KEY Required with dev tools enabled. Must match the devToolsKey URL query param
NEXT_PUBLIC_POSTHOG_KEY Optional. PostHog project API key for anonymous analytics
NEXT_PUBLIC_POSTHOG_HOST Optional. PostHog ingest host (default EU: https://eu.i.posthog.com)

.env.local is gitignored — never commit secrets. Only .env.example is tracked as a template.

When PostHog is enabled, analytics only runs after the user accepts the consent banner.

Dev answer reveal: Set both ENABLE_DEV_TOOLS=true and DEV_TOOLS_ACCESS_KEY, then visit a game page with the key in the URL, e.g. /game/languages?devToolsKey=your-key. The reveal control only appears while that param is present.

3. Set up the database

npm run db:migrate   # apply migrations
npm run db:seed      # seed categories, attributes, and words

4. Start the dev server

npm run dev

Open http://localhost:3000.

5. Verify locally

npm run test:run
npm run lint

Production deploy

  1. Set production env vars (unique GAME_SESSION_SECRET and DAILY_PUZZLE_SECRET — never use .env.example placeholders).
  2. Do not set ENABLE_DEV_TOOLS in production.
  3. Set NEXT_PUBLIC_SITE_URL=https://devdle.co.uk.
  4. Optionally set NEXT_PUBLIC_POSTHOG_KEY (+ NEXT_PUBLIC_POSTHOG_HOST for EU).
  5. Build and migrate:
npm run build
npm run db:deploy   # includes analytics_events migration
npm run start       # or deploy to Vercel
  1. Re-seed only when adding/updating word catalog: npm run db:seed.

Production site: devdle.co.uk.

Scripts

Script Purpose
dev Start dev server
build / start Production build and serve
test / test:run Vitest watch / CI mode
lint ESLint
postinstall Runs prisma generate after npm install
db:migrate Run migrations (development)
db:deploy Apply migrations (production)
db:seed Seed word catalog

Project layout

app/                # pages, API routes, privacy, llms/ai.txt routes
components/         # game UI, layout, analytics, consent providers
lib/
  analytics/        # PostHog capture, Postgres event store, distinct-id
  consent/          # analytics consent localStorage helpers
  game/             # session, compare, daily puzzle, share
  ...
instrumentation.ts  # server env validation on Node boot
proxy.ts            # CSP, rate limits, PostHog /ingest proxy
prisma/             # schema, migrations, seed

To add content, extend the seed data in lib/categories/words/ and ensure attributes match the schema in lib/categories/attributes/, then re-run npm run db:seed.

Contributing

Issues and pull requests are welcome.

Before submitting, run:

npm run test:run
npm run lint

To add words: update the seed files in lib/categories/words/, match the category attribute schema, and re-seed the database.

License

Licensed under the MIT License.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages