ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
A free, open-source study platform for the US amateur radio license exams. Practice against the real FCC question pools, with plain-English lessons for Technician. No paywall, ever.
EducationTypeScript · PLpgSQLGitHub @sonyccdOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
A modern web application for studying and preparing for US Amateur Radio license exams
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
A modern web application for studying US Amateur Radio license exams. Open source, community-driven, born in North Carolina.Read the full README ↗A modern web application for studying US Amateur Radio license exams. Open source, community-driven, born in North Carolina.
Live App: app.openhamprep.com
Supports all three license classes: Technician, General, and Extra.
Prerequisites: Node.js 20+, Docker Desktop
git clone https://github.com/sonyccd/openhamprep.git
cd openhamprep
npm install
npm run dev:full
See LOCAL_DEVELOPMENT.md for details.
Frontend: React 18, TypeScript, Vite, MUI (Material UI) with Emotion, MUI X Charts & Data Grid (Community), TanStack Query, React Router, Framer Motion, lucide icons, next-themes
Backend: Supabase (PostgreSQL, Auth, Edge Functions)
Tooling: Vitest + Testing Library (happy-dom), Playwright (e2e), ESLint, Amplitude & Pendo (product analytics), Sentry (error tracking), Vercel Analytics & Speed Insights
useAppNavigationuseAuth contextsrc/hooks/The app wraps components in this provider order, outermost → innermost (see App.tsx):
light/dark class on <html>colorSchemeNode={null} so it follows next-themes instead of competing with itsrc/
├── components/ # React components
│ ├── ohp/ # Shared presentational primitives (PageContainer, Icon, ScoreRing, …)
│ ├── admin/ # Admin-only components
│ ├── <feature>/ # Sub-components grouped by feature (dashboard/, question/, …)
│ └── *.tsx # Feature components
├── hooks/ # Custom React hooks
├── pages/ # Route page components
├── services/ # Service layer + centralized query keys
├── theme/ # MUI theme (palette, typography, component overrides)
├── lib/ # Utilities
├── integrations/ # Supabase client (auto-generated)
├── assets/ # Static assets
├── test/ # Test setup and helpers
└── types/ # TypeScript types
Outside src/: supabase/ (migrations, seed data, Edge Functions), e2e/ (Playwright tests), website/ (static marketing site), docs/ (guides and design specs).
The UI is built entirely with MUI, styled through the sx prop. Use the library's components rather than hand-rolling your own, and never use direct colors — always use the theme's palette tokens so light and dark mode both work:
// Correct - palette tokens follow light/dark
<Box sx={{ bgcolor: "background.default", color: "text.primary" }}>
// Wrong - a literal color breaks theme switching
<Box sx={{ bgcolor: "#fff", color: "#000" }}>
| what you want | sx path |
|---|---|
| page background | background.default |
| card / surface | background.paper |
| body text | text.primary / text.secondary |
| hairlines, borders | divider |
| subtle surface / green accent | muted / accent (flat keys, no .main) |
| brand | primary.main, secondary.main |
| states | error.main, warning.main, info.main, success.main |
Colors live in src/theme/muiTheme.ts, which is the source of truth. Icons come from lucide and are rendered through ohp/Icon, which hides decorative icons from screen readers.
npm run dev # Start dev server
npm run dev:full # Start Supabase + dev server
npm run supabase:stop # Stop Supabase
npm run supabase:reset # Reset database
npm run lint # Run ESLint
npm test # Run unit tests (watch mode)
npm run test:run # Run unit tests once (CI mode)
npm run e2e # Run Playwright end-to-end tests
npm run build # Production build
Uses local Supabase via Docker - no hosted account needed:
npm run dev:full # Start Supabase + dev server
For production or if you have Supabase project access:
cp .env.example .env.local
# Edit .env.local with your credentials
npm run dev
npm install && npm run dev:fullSee CONTRIBUTING.md for guidelines.
Licensed under the GNU General Public License v3.0. © Brad Bazemore