ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
The Oregon State University EECS Capstone application: browse and propose capstone
projects, run them through a review workflow, and manage shared inventory.
This README covers how to run and develop the app. Known issues and the roadmap
live in GitHub Issues. For
the full, exhaustive feature list, see PRD.md. For implementation
quirks and gotchas, see docs/QUIRKS.md. For how work moves
through the repo and the gates it passes, see CONTRIBUTING.md;
for the rules that bind an agent on every turn, AGENTS.md.查看完整 README ↗The Oregon State University EECS Capstone application: browse and propose capstone projects, run them through a review workflow, and manage shared inventory.
This README covers how to run and develop the app. Known issues and the roadmap
live in GitHub Issues. For
the full, exhaustive feature list, see PRD.md. For implementation
quirks and gotchas, see docs/QUIRKS.md. For how work moves
through the repo and the gates it passes, see CONTRIBUTING.md;
for the rules that bind an agent on every turn, AGENTS.md.
Both live in GitHub Issues rather than in this file, so that what is outstanding has one home that can be assigned, closed and linked from a PR.
For the exhaustive list of what is already built, see PRD.md.
New to the repo? docs/ONBOARDING.md is day one: the
accounts to ask for, a wizard that runs the steps below and every test suite
once (bash scripts/onboard.sh), what Claude Code does here, and a first week.
npm install
docker compose up -d
npm run db:migrate # nothing applies migrations on boot
npm run dev
To stop the database and storage:
docker compose down
The stack publishes Postgres on 5432 and RustFS on 9000/9001. If another
project already holds those host ports, the containers still start but silently
publish nothing, and the app talks to the other project's services instead:
Postgres fails with password authentication failed, while S3 may quietly
accept writes, because the default rustfsadmin credentials are the same.
Give this stack its own host ports in .env (docker compose reads .env, and
not .env.local), then mirror them in .env.local:
# .env, read by docker compose
POSTGRES_PORT=5433
STORAGE_PORT=9100
STORAGE_CONSOLE_PORT=9101
# .env.local, read by the app and the scripts
DATABASE_URL="postgresql://postgres:postgres@localhost:5433/eecs_capstone"
S3_ENDPOINT=http://localhost:9100
VITE_STORAGE_PUBLIC_BASE=http://localhost:9100/cs-capstone
Then docker compose up -d --force-recreate. Confirm the ports actually bound
with docker compose ps and check the publishers column is not empty.
To build for production:
npm run build
This is a TanStack Start app (React SSR) with TanStack Router (file-based routes
in src/routes), TanStack Query, Drizzle ORM on PostgreSQL, Better Auth, and
S3-compatible object storage (RustFS locally). UI is shadcn/ui + Radix.
A few conventions worth knowing before you contribute:
src/lib/project-workflow.ts) and
visibility rules (src/lib/project-visibility.ts) are pure modules. Keep
business logic there, not in routes.proposer_id when an account exists and
proposer_email otherwise. Staff cannot retype a linked address directly;
the edit form routes that through a re-assign modal (see
docs/QUIRKS.md).src/server/, each enforcing its own gate and wrapping writes in a
transaction. The companion *As(viewer, ...) helpers next to each
createServerFn let integration tests exercise business logic directly,
without the HTTP layer.ZodError is mapped
back to field-level errors via src/lib/apply-server-errors.ts.tsvector column with a GIN index.
To change field weights, drop and re-add the column in a new migration (see
docs/QUIRKS.md).src/server/_internal/project-embeddings.ts, the single writer of every
vector. npm run embeddings:backfill is the safety net.This project uses Better Auth backed by Drizzle + Postgres. Identity lives in the
user, session, account, and verification tables (generated by Better
Auth's CLI into src/db/auth-schema.ts and re-exported from src/db/schema.ts).
Copy .env.example to .env.local and fill in values.
Generate a Better Auth secret if you don't have one:
npx -y @better-auth/cli secret
Register a GitHub OAuth App at https://github.com/settings/developers with
callback http://localhost:3000/api/auth/callback/github, then put the
credentials into .env.local.
Start Postgres and run the dev server:
docker compose up -d
npm run dev
Seed your dev database (safe to re-run):
npm run db:seed:dev
In production, seed an admin user (configured via environment variables).
Keep at least two
adminusers in production. The self-action guard prevents a sole admin from accidentally demoting or banning themselves into a one-way trap. Usenpm run db:seed:adminor a directdb:studioedit to bootstrap the second admin.
src/db/auth-schema.ts is hand-maintained. Do not run @better-auth/cli generate against it: that package lags the library (the CLI is stuck on 1.4.x
while we run better-auth 1.7.x), and its output silently drops the
timezone-aware timestamps, the session/account/verification indexes, and the
role NOT NULL default that this file carries. Running it would produce a
destructive migration.
To add or change a Better Auth additionalField:
Add the field to user.additionalFields in src/lib/auth.ts (this is what
Better Auth reads at runtime).
Add the matching column to the user table in src/db/auth-schema.ts by
hand, with the correct type and a DB default (so existing rows backfill).
Generate and apply the migration, reviewing the SQL to confirm it only adds your column:
npm run db:generate
npm run db:migrate
If the @better-auth/cli package ever catches up to the installed better-auth
version, this file could return to CLI generation; until then, edit it directly.
EMAIL_TRANSPORT selects the sender behind the EmailSender interface in
src/lib/email/sender.ts:
console (the default, and what local development uses): every email below is
written to the server's stderr instead of being sent, review notices included.ses: real outbound mail through AWS SES v2 (src/lib/email/ses-sender.ts),
which additionally requires EMAIL_FROM to be a verified sender identity.
EMAIL_REPLY_TO is optional: set it and every message carries that
Reply-To, leave it blank and the header is omitted.Every email renders through src/lib/email/templates.ts. Every one is mandatory
for its recipient; there are no notification preferences (ADR-0019).
| Trigger | Recipient | |
|---|---|---|
| Your sign-in code | Somebody asks for a code at /sign-in | The address typed |
| New project submitted | A project moves to submitted | EMAIL_STAFF_INBOX |
| Approved / Changes requested / Returned to draft | Staff review a project | The proposer |
| New comment on your project | Staff comment, not internal | The proposer |
| Comment from the proposer | The proposer comments | EMAIL_STAFF_INBOX |
| A project was assigned to you | Staff reassign the proposer | The new proposer |
| You were named as a mentor | Staff set a mentor address | The mentor |
| Your draft was deleted | Staff hard-delete a draft | The proposer |
| Borrow list / Custom request submitted | A student submits | EMAIL_STAFF_INBOX |
| Reserved / Request denied / Checked out | Staff decide a request line | The requester or holder, an address-only walk-in included |
| Fulfilled / Request denied (custom line) | Staff close a custom line | The requester |
| Your role is now ... / Your account was suspended | An admin changes a role or bans | The account |
The full channel table, in-app beside email, is PRD section 13. Everything not in it is in-app only or silent. Staff can skip the proposer email per action from the transition dialog; the server ignores that flag from anyone else.
Production runs ses and has done since task definition revision 22: the domain
identity verifies with DKIM SUCCESS, the account has production access (so the
sandbox recipient restriction no longer applies), and mail sends From
[email protected].
EMAIL_FROM must align with the verified identity or DKIM fails, which is why
both it and var.domain_name derive from the same variable in infra/ecs.tf.
It is also not optional under ses: getEmailSender() runs at module scope in
src/lib/auth.ts, so a missing EMAIL_FROM throws during import and stops the
app booting rather than merely stopping its email. Terraform always writes the
two into the same task definition revision, which is why the transport must
never be flipped by hand in the ECS console. EMAIL_REPLY_TO is not
DKIM-aligned and so carries an ordinary OSU mailbox,
[email protected].
Images live in an S3-compatible bucket (RustFS locally, AWS S3 in production).
docker compose up -d rustfs
npm run storage:init # idempotent
npm run storage:init is the local RustFS path only. In production the bucket
blocks all public access and grants s3:GetObject to the assets CloudFront
distribution alone, through Origin Access Control; Terraform provisions both
(infra/s3.tf, infra/cloudfront.tf), so there is no bucket policy to apply by
hand and no Block Public Access setting to turn off. Set
VITE_STORAGE_PUBLIC_BASE to the customer-facing URL prefix; in production the
deploy workflow reads the assets distribution's domain from SSM and bakes it in
as a build arg, so that one is nobody's to set by hand either.
The project form can request per-field improvement suggestions, backed by AWS
Bedrock. Set BEDROCK_MODEL_ID (and the relevant AWS credentials) to configure
the model; the default is OpenAI GPT-6 Luna.
The call goes to the OpenAI-compatible Responses API on the bedrock-mantle
endpoint, signed with SigV4 from the ambient AWS credentials, so no separate
Bedrock API key is needed. BEDROCK_REASONING_EFFORT tunes how much the model
thinks before answering. Embeddings still use bedrock-runtime.
This project uses Vitest.
npm run test
The auth and server surfaces have integration tests that hit the docker-compose Postgres:
npm run test:integration
Each test starts from a TRUNCATEd database, so they share a single fork and run
serially. They read the schema as it exists, so run npm run db:migrate after
pulling a migration or every one of them fails on the missing column.
Accessibility is checked separately, with Playwright and axe against the running
app (the config starts npm run dev itself, or reuses one already listening on
port 3000):
npm run test:accessibility
Pull requests run only the scans tagged @smoke (npm run test:accessibility:smoke);
the whole suite runs from the dispatch-only Full Accessibility workflow.
TODO (future): integration tests currently run against the same database as dev and TRUNCATE every table before each test, which wipes dev data. Point them at a dedicated
eecs_capstone_testdatabase via a separateTEST_DATABASE_URL. See the Drizzle section ofdocs/QUIRKS.mdfor details.
This project uses Ultracite (Biome under the hood).
npm run lint
npm run format
npm run check
Always run npm run check after finishing work and fix any issues before
committing.
Add components using the latest version of shadcn:
npx shadcn@latest add button
Production runs on AWS, provisioned with Terraform (infra/) and deployed via a
one-click GitHub Actions workflow (.github/workflows/deploy.yml):
capstone.eecs.oregonstate.edu (var.domain_name). Two DNS records live in
the OSU-managed eecs.oregonstate.edu zone rather than in this Terraform
configuration: one validating the ACM certificate, and one pointing the
hostname at the CloudFront distribution. That is why the certificate is a
read-only data lookup in infra/cloudfront.tf instead of a managed
resource. CloudFront reaches an internal Application Load Balancer through a
VPC origin, so the ALB itself has no public IP.See DEPLOYMENT.md for the full operational runbook
(first-time setup through teardown) and infra/README.md
for the Terraform specifics.