Dad Joke Generator (djg)

A minimal React + TypeScript single-page app for generating and sharing dad jokes. Built with Vite using the rolldown bundler and Tailwind CSS 4.1. Google Analytics 4 integration via react-ga4 tracks user feedback on generated jokes. No external joke API is currently integrated — core joke generation is pending implementation.

  • GitHub: irishrocker1125/djg
  • Port: 3090 (registered in ops-core ports.yaml)
  • Status: Early-stage active development (v0.1)

Overview

djg was graduated from lab/Playground experiments into apps/ as a production candidate. The app scaffolding, governance structure, and test infrastructure are in place. The core joke generation feature is the primary outstanding item.

Key characteristics:

  • Single-page React app with minimal component structure (App.tsx, Feedback.tsx, main.tsx)
  • GA4 event tracking via react-ga4 for user feedback — events follow { category, action, label } pattern
  • Tailwind-first styling — zero custom CSS files beyond Tailwind directives
  • TypeScript strict mode with no any types
  • Local component state only (useState/useEffect) — no Redux or Zustand

Tech Stack

TechnologyVersionPurpose
React19.2.0UI framework
TypeScript5.9.3Type safety (strict mode)
Vite (rolldown-vite)7.2.5Build tool / dev server (Rust-based bundler)
TailwindCSS4.1.18Utility CSS
PostCSS8.5.6CSS processing
react-ga42.1.0Google Analytics 4
Vitest4.0.18Unit testing
ESLint9.39.2 (pinned)Linting

ESLint is pinned to 9.39.2 because ESLint 10.0.0 is incompatible with the typescript-eslint@8.x ecosystem — an org-wide constraint.

Architecture

src/
├── main.tsx        # App entry point, ReactGA initialization, root render
├── App.tsx         # Main UI: title, joke display, Feedback form
├── Feedback.tsx    # Feedback submission with GA event tracking
└── index.css       # Tailwind directives (@tailwind base/components/utilities)

Data flow: User views joke in App.tsx → submits feedback via Feedback.tsx → GA event fires with structured payload → tracked in GA4 dashboard.

Key Decisions

DecisionRationale
React 19 + TypeScript strict modeModern type safety; strict typing prevents common bugs
rolldown-vite 7.2Rust-based bundler — faster builds vs traditional Vite
Tailwind CSS 4.1, no custom CSSRapid UI iteration without CSS maintenance overhead
No external joke API initiallyDefer API complexity until core UI/UX validated
Local state onlyApp is simple enough; no Redux/Zustand overhead warranted
Vitest 4.0 with jsdomVite-native test runner; test infrastructure built before features

See also: Vitest setup with react-ga4 mocking — the pattern established in this project for mocking analytics SDKs during tests.

Patterns Established

  • GA event tracking via functional component — Feedback.tsx sends structured events; cleanly separates analytics from UI logic. Reusable across any React app with GA4.
  • Vitest + react-ga4 mocking — test/setup.ts mocks entire react-ga4 module. Applicable to any React app with analytics SDKs.
  • localStorage mock in tests — Vitest setup provides localStorage shim for jsdom. Standard browser API testing pattern.
  • TypeScript project references — root tsconfig delegates to tsconfig.app.json + tsconfig.node.json. Vite standard for faster type checking.
  • Self-hosted GitHub Actions runners — security.yml targets [self-hosted, linux, general]. Org-wide pattern from Actions minutes crisis.

Current Status

Phase: Active Development — scaffolding complete, core feature pending.

MetricStatusNotes
CI/CDPending review
DependenciesCurrentReact + Vite + Tailwind
DocumentationStaleREADME is default Vite template
Test CoverageN/AVitest configured, no tests yet

Technical Debt

ItemPriority
No actual joke generation functionalityHigh
Replace placeholder GA tracking ID (G-XXXXXXXXXX)High — must resolve before production
Update README.md from Vite boilerplateMedium
Sync USER_TESTING.md with actual features (references removed counter feature)Medium
Add React-specific ESLint rules (react-hooks, react-refresh)Medium
Feedback UI labeled “Report a Bug” but tracks as “Feedback” categoryLow

Lessons Learned

  • Test infrastructure before features — full Vitest setup exists despite minimal features; enables TDD and avoids the “add tests later” trap.
  • Placeholder tracking IDs ship silently — use env vars for GA tracking IDs (VITE_GA_TRACKING_ID) to prevent dummy IDs reaching production.
  • Scaffold READMEs are noise — replace boilerplate READMEs early; default Vite content misleads contributors.

See Also

  • AP Ecosystem — djg is an active production app within the Aloysius Productions ecosystem
  • DevOps — CI/CD patterns, self-hosted runners, and security scanning used in this project