A daily programming puzzle app. https://dailyprog.club
  • TypeScript 59.9%
  • JavaScript 39.5%
  • CSS 0.4%
  • Dockerfile 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Ata Kuyumcu dfb596e52c
Some checks failed
CI / ci (push) Has been cancelled
chore: bump ops submodule for the visual-renderer sprint
Moves the pinned ops pointer to include puzzles 40 and 41 and the
add-an-output-renderer runbook update; all three are on the ops remote.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 05:34:28 +02:00
.forgejo feat: schedule daily difficulty and visual days by weekday 2026-07-29 04:02:06 +02:00
brand/stickers chore: add print-ready sticker artwork 2026-07-27 03:31:00 +02:00
ops@489c249110 chore: bump ops submodule for the visual-renderer sprint 2026-07-29 05:34:28 +02:00
scripts fix: only sync puzzle-examples.json from ops, never self-copy 2026-07-18 16:12:32 +02:00
workspaces feat: add intervals output renderer 2026-07-29 05:28:53 +02:00
.dockerignore build: exclude infra/ from the Docker build context 2026-06-24 22:45:01 +02:00
.env.example chore: tidy open-sourcing loose ends 2026-07-18 16:12:32 +02:00
.gitignore feat: add APL language support (ngn/apl runtime, editor, 26 puzzle starters) 2026-07-26 14:39:26 +02:00
.gitmodules feat: open-source the codebase under AGPL-3.0, move private content to ops submodule 2026-07-18 12:00:03 +02:00
AGENTS.md feat: sync practice completions for puzzles solved after their day 2026-07-23 16:10:47 +02:00
biome.json feat: add APL language support (ngn/apl runtime, editor, 26 puzzle starters) 2026-07-26 14:39:26 +02:00
CLAUDE.md docs: add agent guide 2026-06-17 11:30:14 +02:00
docker-compose.yml chore: tidy open-sourcing loose ends 2026-07-18 16:12:32 +02:00
LICENSE feat: open-source the codebase under AGPL-3.0, move private content to ops submodule 2026-07-18 12:00:03 +02:00
package.json chore: tidy open-sourcing loose ends 2026-07-18 16:12:32 +02:00
pnpm-lock.yaml feat: add Clojure as a puzzle language via SCI/Scittle 2026-07-06 04:12:30 +02:00
pnpm-workspace.yaml feat: add embedded SQLite gameplay store 2026-06-23 16:36:01 +02:00
README.md chore: tidy open-sourcing loose ends 2026-07-18 16:12:32 +02:00

dailyprog

A daily coding-challenge app. This is a pnpm monorepo housing the web app and its shared UI component library.

Stack

  • pnpm workspaces (run via corepack)
  • Next.js 16 (App Router, Turbopack) — the app
  • Storybook 10 (Vite builder) — UI library development
  • React 19 + Tailwind CSS v4
  • next-intl for app internationalization (locale routing + message catalogs)
  • Biome for linting and formatting

Layout

dailyprog/
├── workspaces/
│   ├── ui/    → @dailyprog/ui   shared React component library (Storybook)
│   └── app/   → @dailyprog/app  Next.js app, consumes @dailyprog/ui
├── biome.json            # lint + format config
├── pnpm-workspace.yaml   # workspaces, pinned Node, build allowlist
└── AGENTS.md             # contributor/agent guide (conventions, commit rules)

@dailyprog/app depends on @dailyprog/ui via workspace:* and compiles its TypeScript source directly (transpilePackages).

Prerequisites

  • Node (the exact version is pinned in pnpm-workspace.yaml via useNodeVersion; pnpm manages it for you).
  • pnpm through corepack — no global install needed. Either prefix commands with corepack pnpm …, or run corepack enable once to get a bare pnpm on your PATH.

Getting started

corepack pnpm install

Common commands

Run from the repo root:

Task Command
Install dependencies corepack pnpm install
Lint + format (write) corepack pnpm check
Run all tests corepack pnpm test
Build all workspaces corepack pnpm build
Run the app (dev) corepack pnpm --filter @dailyprog/app dev
Build the app corepack pnpm --filter @dailyprog/app build
Develop UI in Storybook corepack pnpm --filter @dailyprog/ui storybook
Build Storybook corepack pnpm --filter @dailyprog/ui build-storybook

The app dev server runs at http://localhost:3000; Storybook at http://localhost:6006.

Docker

A docker-compose.yml runs the production app (web) on its own — it's stateless. The app image is a multi-stage build of Next's standalone output, on a Debian base so the native isolated-vm addon compiles.

cp .env.example .env   # the app has no secrets of its own
docker compose up -d --build

The app serves on http://localhost:3000 (liveness at /api/health). To enable analytics, bring up Umami (a separate stack — see the ops submodule's infra/umami/), create a website in its UI, put its script URL + id in NEXT_PUBLIC_UMAMI_SRC / NEXT_PUBLIC_UMAMI_WEBSITE_ID, then rebuild the app (docker compose build web) — these are inlined at build time. With them empty, the tracker is disabled.

The web image targets linux/arm64 by default — the deploy VPS is arm64 (netcup; see the ops submodule) and the isolated-vm prebuild is arch-specific. Set WEB_PLATFORM=linux/amd64 for an x86 target. The web container is hardened (read-only rootfs + tmpfs, all caps dropped, no-new-privileges, memory/CPU/pid limits — tunable via WEB_* in .env).

The full deploy runbook and live VPS documentation live in the ops submodule (ops/DEPLOY.md, ops/infra/README.md) — private operational content, available to maintainers only.

Running with Podman

The stack is Podman-compatible (image names are fully qualified, e.g. docker.io/library/postgres). A few differences from Docker:

  • Use podman compose (Podman 4.1+, which drives Docker Compose v2 over the Podman socket), not the older Python podman-compose — the latter is unreliable with depends_on: condition: service_healthy gates (e.g. the Umami → Postgres ordering in the ops submodule's infra/umami/).
  • Resource limits need cgroups v2. mem_limit / cpus / pids_limit are silently ignored under rootless Podman unless controller delegation is configured; run rootful or set up delegation if you need them enforced. The other hardening (read_only, cap_drop, no-new-privileges, tmpfs) works rootless.
  • Build cache mounts (--mount=type=cache in the Dockerfile) need a recent Podman/Buildah; on older versions, drop that flag.
  • Autostart: prefer Quadlet (.container units) or podman generate systemd over the compose restart: policy for a real server.

Testing

Tests run on Vitest for unit and component layers, and Playwright for end-to-end browser flows. Three layers are set up:

  • Unit tests for pure logic in @dailyprog/app (lib/), in a Node environment.
  • Component tests for @dailyprog/ui and @dailyprog/app using React Testing Library in jsdom.
  • E2E tests in @dailyprog/app (e2e/) — real Chromium + WebKit against a production build, exercising the isolated-vm verify path, the CodeMirror editor, and the Web Worker runner.

Run everything with corepack pnpm test, E2E with corepack pnpm --filter @dailyprog/app test:e2e. See AGENTS.md for conventions.

Conventions

Code style is enforced by Biome (corepack pnpm check before every change). Styling uses Tailwind utilities — avoid inline CSS. Icons come from Heroicons (@heroicons/react), not hand-written SVG. Versions shared across workspaces are centralized in the pnpm catalog: (pnpm-workspace.yaml) and referenced as "catalog:" in each package. Commits follow Conventional Commits without a scope. User-facing strings in @dailyprog/ui are passed in as props with English defaults so the app — which owns i18n via next-intl — can localize them, and the monospace font (IBM Plex Mono) is reserved for numbers, tags, and identifiers. See AGENTS.md for the full contributor guide.

Ops submodule

The puzzle catalogue, architecture decision records, infrastructure documentation, and the deploy runbook live in a private ops repo set up as a git submodule at ops/. The app's predev/prebuild/pretest scripts run scripts/sync-ops.mjs to copy them into place.

  • Maintainers — run git submodule update --init to pull the ops repo, then build as usual.
  • Contributors — the sync script falls back to sample puzzles under workspaces/app/content/sample-puzzles/. The app boots and tests pass without ops access.

License

GNU Affero General Public License v3.0

Copyright (C) 2026 lvmbdv