ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
첫 투자 준비를 무료로 제공, 예산·부채·목표·투자 원리·위기 모델에서 시험하는 개인 계획, 교육 목적이며 투자 조언이 아님
Bezplatná příprava na první investici v češtině: rozpočet, dluhy, cíle, jak investice fungují a vlastní investiční plán, který si vyzkoušíš v modelové krizi. Vzdělávání, ne investiční doporučení.
교육TypeScript · JavaScriptGitHub @Johnyyy1온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Interactive investing education platform with hands-on lessons, portfolio simulations, and real market data.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Investník (formerly investi) is a free, Czech-first investing-education platform at investnik.cz. docs/brand.md covers the name, the brand assets, the domain setup and the remaining external rollout steps.
Learn investing by doing. The authenticated product is organized around three destinations: Learn, Lab, and Progress. Guided lessons are organized into modules (Investing Foundations, Returns & Compounding, …), with persisted lesson position, transactional first-completion rewards, and focused interactive exercises. The lesson catalog in src/features/learning/catalog.ts lists what is published.
features/lessons is the typed authored lesson engine shared by Foundations and Returns.features/progress validates step transitions and completes lessons with rewards in one transaction.features/gamification derives XP, local learning days, streak, and daily lesson progress from persisted award receipts.features/rewards owns the server-side Practice Capital policy and exact receipt-derived entitlement read model.features/portfolio owns persistent paper trading, exact accounting, generations, and transaction authority.features/market-data normalizes deterministic/FMP security data, Frankfurter FX, equity fundamentals, and ETF analytics behind server-only services.features/personalization owns diagnostic evidence, preference validation, and deterministic recommendations.features/lab contains pure allocation/backtest math and an explicitly synthetic educational fixture.Use Node.js 24 (nvm use reads .nvmrc). .nvmrc is the single version source: CI reads it through setup-node, Vercel follows the matching engines.node in package.json, and src/lib/node-version.test.ts keeps the Dockerfile, engines and @types/node on the same major.
Run npm ci, copy .env.example to an ignored .env, and set a real BETTER_AUTH_SECRET. See environment settings for required, optional, infrastructure, and test variables.
Start PostgreSQL and update DATABASE_URL.
Apply committed migrations before starting the new application code, then seed the curriculum:
npm run db:migrate
npm run db:seed
On Vercel, production deploys run vercel-build (scripts/vercel-build.mjs), which applies pending migrations and then the curriculum seed before next build, so a lesson added to the catalog is completable without a manual step. The seed fails the deploy if any catalog lesson is still missing from the lesson table afterwards. Preview deploys skip both so unmerged branches never change the shared database.
Start the app:
npm run dev
db:seed is idempotent and safe to run on every deploy. npm run db:check-curriculum is a read-only check that exits non-zero when a published catalog module or lesson has no row in the database. Apply every committed migration in drizzle/ (npm run db:migrate applies the pending ones in order); the application code assumes the full chain. Historical migrations and their metadata must remain intact.
Google and Facebook can be enabled independently with server-only credential pairs. See authentication setup for callback URLs, provider-console setup, safe account-linking behavior and verification. Email/password and demo continue to work without OAuth credentials.
The Dockerfile and compose.yaml are a local development stack only: the image runs npm run dev (Next.js development mode) as root with the source tree bind-mounted. Never use it as a production image; production deploys go through Vercel (vercel-build).
Prerequisites: Docker Desktop (or Docker Engine with the Compose plugin). On first use, create an ignored Compose environment file and replace both placeholder secrets with locally generated values:
cp .env.example .env
BETTER_AUTH_SECRET must be at least 32 characters. POSTGRES_PASSWORD is used only by the Docker PostgreSQL instance. BETTER_AUTH_URL should remain http://localhost:3000 unless the app is exposed on another host or port. DATABASE_URL remains the non-Docker development connection string; Compose supplies its own internal value using the db service hostname.
Start the complete development stack:
docker compose up --build
The app is available at http://localhost:3000. Compose waits for PostgreSQL to pass its healthcheck, then the app automatically runs the committed Drizzle migrations and idempotent curriculum seed before launching Next.js development mode. To run them manually instead, use:
docker compose run --rm app npm run db:migrate
docker compose run --rm app npm run db:seed
Stop the stack with docker compose down. PostgreSQL data remains in the named postgres_data volume across stops and rebuilds. To remove containers and the persisted development database deliberately, run docker compose down --volumes.
GitHub Actions runs the gates automatically. .github/workflows/ci.yml runs on every pull request and every push to main: one job generates Next.js route types (next typegen, which a clean checkout needs before tsc) and runs lint, typecheck, unit tests and build; a second job migrates and seeds a disposable PostgreSQL service container and runs the persistence, migration and concurrency suites. .github/workflows/browser.yml runs every Playwright browser suite nightly, on demand, and on pull requests that change a suite or the workflow. Four parallel jobs each migrate and seed their own disposable databases: core suites against next start, sign-in/onboarding/personalization/settings, Progress/IPS/lesson outputs on their dedicated databases, and development-only routes against next dev. .github/workflows/lesson-exercises.yml runs the lesson-exercise suites on pull requests that touch lessons. All of them use deterministic sample data. main requires both CI jobs to pass before merging.
Locally, run npx next typegen once on a fresh checkout before npm run typecheck (next dev and next build also generate the types).
Static gates run independently. Database and browser suites require a local disposable QA database and a fresh app runtime; see Scripts and test suites for the full list.
Run migrations and seed on a disposable local QA database, with DATABASE_URL and local auth/provider settings explicitly exported. Re-run db:seed followed by test:curriculum-seed to verify idempotence. Personalization upgrade QA additionally requires a fresh database and explicit opt-in; see onboarding. Browser suites create and remove only their own local disposable identities. Screenshots are written under /tmp, never the repository.
Every suite below is an npm script in package.json unless it is written as node scripts/…. "CI" says where GitHub Actions runs a suite: ✓ is ci.yml on every pull request; a browser suite names its nightly browser.yml job in parentheses, or lesson-exercises.yml, which runs on lesson changes.
App and database
| Script | Purpose |
|---|---|
dev, build, start | Next.js development server, production build, production server |
vercel-build | Production deploys on Vercel: applies pending migrations, seeds the curriculum, then next build |
db:migrate, db:seed | Apply committed migrations; seed the curriculum (idempotent, fails if a catalog lesson is still missing) |
db:check-curriculum | Read-only: fail when a published catalog module or lesson is missing from the database |
db:generate, db:studio | Generate a new migration from the Drizzle schema; open Drizzle Studio |
Static gates (no database, all in CI)
| Script | Purpose |
|---|---|
lint, typecheck | ESLint; tsc --noEmit (run npx next typegen first on a fresh checkout) |
knip | Unused files, exports and dependencies (config and reasoned exceptions in knip.jsonc) |
test, test:watch | Vitest unit tests: domain, accounting, lesson content, components |
Database suites (need DATABASE_URL pointing at a disposable local database that is migrated and seeded)
| Script | Covers | CI |
|---|---|---|
test:curriculum-seed | Seed idempotence and lesson publication/order | ✓ |
test:migration | Practice Capital receipt migrations | ✓ |
test:portfolio-migration | Portfolio schema migrations | ✓ |
test:persistence | Progress, completion and reward receipts | ✓ |
test:portfolio-persistence | Trades, generations, reset, exact accounting, concurrency | ✓ |
test:portfolio-allocation | Target-mix execution and rebalancing | ✓ |
test:portfolio-closed-market | Orders and valuations while the market is closed | ✓ |
test:progression-persistence | Portfolio Lab unlock, demo access grant and row-lock concurrency | ✓ |
test:log-returns-persistence | Returns module answers, completion and rewards | ✓ |
test:guest-claim | Guest → account claim | ✓ |
test:market-data-cache | Shared Postgres market-data cache | ✓ |
test:rate-limit | Shared rate limits | ✓ |
test:account-deletion | Account deletion, data export, session retention (needs ACCOUNT_DATA_QA_DISPOSABLE=1) | ✓ |
test:anonymous-cleanup | Anonymous identity cleanup (needs ANONYMOUS_CLEANUP_QA_DISPOSABLE=1) | ✓ |
test:product-analytics | Product funnel migration, early returns and landing views (needs FUNNEL_QA_DISPOSABLE=1 and a database named investi_funnel_qa, see product analytics) | ✓ |
test:personalization-persistence | Onboarding profile and recommendations (needs PERSONALIZATION_QA_DISPOSABLE=1, see ) |
Browser suites (Playwright; need a fresh running server on a disposable database. Each suite reads its base URL from a *_TEST_URL variable listed in environment settings; BROWSER_CHANNEL=chrome uses installed Chrome)
| Script | Covers | CI |
|---|---|---|
test:product | Product shell and Backtesting | browser (core) |
test:studovna | Learn page: inline question, saved continuation, reflow | browser (core) |
test:foundations-browser | Foundations lessons | browser (core) |
test:returns-browser, test:log-returns-browser | Returns module | browser (core) |
test:volatility-browser | Volatility module | browser (core) |
test:correlation-browser | Returns checkpoint, Correlation and Diversification modules | browser (core) |
test:portfolio-browser | Portfolio Lab | browser (core) |
test:portfolio-browser-closed | Closed/stale market states (server started with DETERMINISTIC_MARKET_NOW=2026-01-17T12:00:00.000Z) | browser (core) |
test:instrument-browser-unavailable | Unavailable instrument history/quotes (server started with DETERMINISTIC_MARKET_NOW=2026-03-20T15:00:00.000Z) | browser (core) |
test:compare-browser | Instrument comparison | browser (core) |
test:progression-browser | Unlock progression | browser (core) |
test:backtesting-browser | Backtesting Lab | browser (core) |
test:marketing-browser | Landing page | browser (core) |
test:not-found-browser | 404 pages: unmatched URL, lesson, instrument | browser (core) |
test:legal-browser | Privacy and terms pages | browser (core) |
test:account-recovery-browser | Password reset and e-mail verification through the local outbox | browser (core) |
test:demo-session | Demo and guest session lifetimes | browser (core) |
Operator and diagnostics
| Script | Purpose |
|---|---|
demo:cleanup | Dry run of the anonymous identity cleanup; -- --apply applies it |
analytics:funnel | Read-only funnel to milestone A: last 7 and 30 days, weekly cohorts, lesson drop-off; -- --json for JSON (see product analytics) |
smoke:fmp | Manual smoke test of the live FMP market-data adapter |
smoke:fmp-fundamentals | Manual smoke test of live FMP equity fundamentals and their cache |
bench:navigation | Client navigation benchmark (see performance baseline) |
Demos and guests are anonymous Better Auth identities without a password or provider account. A demo is one-time: its session lasts a fixed 24 hours from the start and using it never extends that. A guest session lasts seven days and, like an account's, extends while it is used. Once every session of an anonymous identity has expired, nobody can sign in to it again.
A daily Vercel Cron job (vercel.json) calls /api/cron/cleanup-anonymous, which removes anonymous identities that have had no valid session for over a day (and were created over a day ago). Deleting the user cascades its sessions, profile, progress, receipts, unlocks, portfolios and trades; saved accounts and shared curriculum/market data are never touched. Rows locked by a guest claim or lesson completion are skipped and retried by the next run. The endpoint requires Authorization: Bearer $CRON_SECRET and refuses every request when CRON_SECRET is not set, so set it in the Vercel project for production. The same job then deletes session rows (with their IP address and user agent) for every identity once they expired more than 30 days ago (deleteExpiredSessions).
A saved account downloads its data from Settings → Moje data (GET /api/account/export, session owner only, rate limited per user): profile, sign-in methods without secrets, sessions, learning profile, progress, reward receipts, unlocks, the funnel's early-return record, portfolio generations with trades and target mixes, with money in minor units and decimals as exact strings. The same screen deletes the account through Better Auth's /delete-user; a guard in src/lib/auth.ts requires the password for password accounts, a sign-in from the last 10 minutes for Google/Facebook-only accounts, refuses guests and demos (the cleanup above removes those), and limits attempts per user. The user row cascades everything the user owns; shared curriculum, market data and rate-limit counters stay. /privacy and /terms are linked from every footer and the sign-up step; the operator's identity and contact in src/components/legal/legal-page.tsx must be filled in and the texts reviewed before they are relied on.
The operator command applies the same rule and needs only DATABASE_URL:
npm run demo:cleanup
npm run demo:cleanup -- --apply
See current product contracts for reward, streak, daily-goal, synthetic-data, migration, compatibility, and validation semantics. Current policy v3: Foundations lessons earn XP only, finishing Foundations unlocks Portfolio Lab with a one-time 5,000 Kč, and every lesson outside Foundations adds 2,000 Kč; stored receipts keep their original amounts.
Investník is proprietary: all rights reserved, no licence granted. See LICENSE and ownership, licence and trademark.
test:prepared-statements | Prepared-statement compatibility of a pooler endpoint (see performance baseline) |
test:request-isolation | Request-scoped memoization across users | browser (core) |
test:navigation-feedback | Client navigation feedback | browser (core) |
test:auth-browser | Sign-in/sign-up and social sign-in with fake providers; two servers and an investi_6a4_qa database (see authentication) | browser (accounts) |
test:personalization-browser, test:personalization-compatibility | Personalization and legacy accounts (investi_6a3a_qa, PERSONALIZATION_QA_DISPOSABLE=1) | browser (accounts) |
test:onboarding-redesign | Guest onboarding (same database and opt-in) | browser (accounts) |
test:settings | Settings, linked accounts, account deletion and data export (same database and opt-in) | browser (accounts) |
test:progress-browser | Progress page (needs PROGRESS_QA_DISPOSABLE=1 and an investi_progress_qa database) | browser (dedicated databases) |
test:ips-browser | Investment policy statement (investi_artifacts_qa, IPS_QA_DISPOSABLE=1) | browser (dedicated databases) |
test:artifacts-browser | Lesson outputs: with ARTIFACTS_TEST_URL the shipped Settings UI, without it an editor harness on its own next dev (investi_artifacts_qa, ARTIFACTS_QA_DISPOSABLE=1) | browser (both) |
test:design-system-browser | Design system (development-only route, needs next dev) | browser (development runtime) |
test:facts-browser | Facts registry (development-only route); FACTS_EXPECT_PRODUCTION=1 checks its production 404 instead | browser (development runtime, core) |
test:lesson-exercises-browser | Server-validated lesson exercises | lesson-exercises |
test:lesson-walkthrough | Every published lesson: wrong answer and retry, then the authored answer for each question, resume after reload, completion with one receipt; no overflow at 1440/390/320 px and no serious axe (WCAG 2.1 AA) finding on any step. LESSON_IDS=a,b walks only those lessons | browser (core), lesson-exercises |