ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A Next.js 16 (App Router) + TypeScript + Tailwind port of the original single-file
index.html lab-record builder. Behavior, layout, and UX are preserved 1:1; the
codebase has been split into typed components and modules.
npm install
npm run dev # http://localhost:3000
npm run build # production build
npm run start # serve the production build
See docs/deploy.md for the environment variables, Firebase and Google setup, and a post-deploy checklist. The admin area is described in docs/admin.md and mail in docs/admin-mail.md.
app/page.tsx — top-level client component holding all app state (record,
watermark options, mobile panel, AI modal) and wiring the editor, preview,
print, and PDF-save flows together.app/layout.tsx — loads Material Symbols and html2pdf.js (via
next/script, strategy="lazyOnload" — it touches document/canvas and
isn't SSR-safe).components/ — RecordEditorPanel, WatermarkOptionsSection,
AccordionSection, PreviewPanel, A4Page, MobileNav, and
AiAssistantModal (with ai/CopyPromptTab, ai/PasteImportTab,
ai/DirectLlmTab).lib/paginate.ts — the smart pagination engine, ported line-for-line from
the original. It still measures real rendered heights in a hidden offscreen
DOM node (lib/usePaginatedPages.ts wraps it in a debounced
useEffect/useState hook) because text wrapping depends on actual font
rendering and can't be predicted analytically — this keeps it accurate but
means it isn't a pure function in the strict sense; it's as close to
testable/pure as the original algorithm allows.lib/buildPrintHtml.ts / lib/printCss.ts — build the exact print-document
HTML string reused by both the hidden print <iframe> and html2pdf.js.lib/aiAssistant.ts — the AI prompt template, DOMParser-based section
parser with regex extractTag fallback, and validator.lib/puter.ts — client-side AI text generation via Puter.js
(window.puter.ai.chat), no API key required.lib/types.ts — RecordState, OutputImage, WatermarkOptions,
PageObject.The app chrome (editor, preview toolbar, modal, nav) uses a "lab notebook"
visual identity — a warm paper background, a serif/mono title-block treatment
(Source Serif 4 + Inter + JetBrains Mono, loaded via next/font/google),
a copper accent color, and numbered section eyebrows (01 AIM, 02 ALGORITHM, …)
that mirror the record's actual printed order. Icons are from lucide-react.
This only touches the app UI. The generated record itself (.a4-page and
everything inside it, in A4Page.tsx / globals.css / printCss.ts /
buildPrintHtml.ts) intentionally keeps its own hard-coded Arial stack so
preview, print, and PDF stay pixel-identical — never point the chrome's
--font-* variables at those selectors.
lib/paginate.ts output, rendered via
dangerouslySetInnerHTML in A4Page): the pagination engine has to work in
raw HTML strings because it measures and splits content by rendered pixel
height across page boundaries, and re-deriving that from JSX per fragment
isn't safely feasible without changing the algorithm. All user text within
those fragments is still run through escapeHTML before being placed in the
HTML string, matching the original's XSS-safety guarantee.usePaginatedPages so rapid typing doesn't trigger a synchronous
DOM-measurement pass on every keystroke. This is a minor smoothness
improvement over the original (which re-paginated on every input event
synchronously); it does not change output.useState), matching the
original — nothing is written to localStorage/sessionStorage.puter.ai.chat (loaded via the https://js.puter.com/v2/ script tag in
app/layout.tsx) instead of a keyed provider API. lib/puter.ts tries
gpt-4o first and falls back once to claude-3-5-sonnet if the first
model call fails. Errors surface as a toast ("Generation failed, please try
again") rather than an inline API error message.lib/rateLimiter.ts is a small in-memory
sliding-window limiter (5 requests / 60s) used by DirectLlmTab to block
rapid repeat clicks and show a countdown before the next request is
allowed. It's a UX guard, not a security control..a4-page node and measures scrollHeight), so it only produces
accurate output in a browser environment, not during SSR — this matches the
original's DOM-measurement approach.