ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Greta – the English tutor
The app was migrated from a single-file vanilla-JS index.html to a React + TypeScript + Vite app. app/ is the whole frontend now — there's no legacy version left.
cd app
npm install
npm run dev # local dev server
npm run lint # oxlint
npm run format:check # prettier
npm run build # tsc -b && vite build
npm test # playwright, against the built app
React + TypeScript + Vite, with Base UI for unstyled accessible components. All state lives in a single useAppState() hook (app/src/state/useAppState.ts), passed down as props — no Context or Redux. Screens are components in app/src/screens/, switched by a plain if/else chain in App.tsx keyed on the current screen. Pure data and logic with no dependency on runtime state (icons, i18n strings, avatar/list constants, paste-parsing, shuffling, etc.) live in app/src/data/ and app/src/lib/.
Sign-in is real — a magic-link email through Supabase, the same project's public auth endpoints the app always used (app/src/lib/auth.ts) — but nothing re-syncs a signed-in user's lists to the server yet. Every screen still reads/writes local state only, exactly as a guest would; wiring up server sync for lists is separate follow-up work.
The app tracks the visual viewport (app/src/lib/viewportHeight.ts) so the on-screen keyboard shrinks #frame to fit above it instead of covering it, and corrects mobile browsers' own "scroll the focused input into view" behavior where it fights with that shrink — without this, content above a focused input (like the coin pouch during the write-5x remediation) can end up scrolled out of view exactly when it matters. index.html's meta viewport also declares interactive-widget=resizes-content, which gets browsers that honor it (Chrome for Android 108+) the same result natively, but that's Chromium-only — Safari has never implemented it, so this JS is what actually makes it work on iOS. #screen is a CSS size container so the word card can size its own padding/font off cqh (its real, shrunk height) rather than vh (the viewport as a whole) — otherwise the frame shrinks but its content doesn't, and overflows it.
A multi-step plan: coins (earning, persistence, balance display — shipped) → a dressing room shell proving the equip/render loop end to end with one free accessory (shipped) → a real priced shop with several accessories across categories, using the same overlay technique → full-body avatars and clothing, if the earlier steps land well.
The dressing room (app/src/screens/DressingRoom.tsx) lets you equip/unequip accessories, which then render as an overlay (app/src/components/AccessoryOverlay.tsx) on top of the avatar image wherever it appears (Home header, Settings profile card). Accessories are defined in app/src/data/accessories.ts; there's currently one free starter item (a hand-drawn party hat, since no sourced accessory art exists yet) with no purchase flow — that's the next step, once real art is available.
End-to-end tests (Playwright) drive the real UI against the built app (app/tests/, run via npm test from app/).
.github/workflows/deploy.yml publishes app/'s build output to the gh-pages branch:
main build the app (npm ci && npm run build in app/) and deploy it to the site rootapp/** gets its own preview build at pr-preview/pr-<number>/, deployed on open/update and removed on close (via rossjrw/pr-preview-action)The build's asset paths are relative (base: './' in app/vite.config.ts), so the exact same app/dist output works unmodified whether it's deployed at the site root or nested under a PR's own pr-preview/pr-<n>/ subpath — no per-deployment rebuild needed.
.github/workflows/app-ci.yml lints, format-checks, builds, and runs the Playwright tests on every PR that touches app/**, as a quality gate independent of deployment.
One-time repo settings this workflow needs (Settings → …):
gh-pages / (root).contents: write permission is capped by whatever this is set to, so it must allow write for the deploy step to push.supabase/functions/greta/ is a Supabase Edge Function backing account sync and word-list translation — see SETUP.md for deploying it. It's independent of the frontend rewrite above.