A focused web app for post-meeting notes, shared follow-up items, and per-student supervision history.
- Astro v6 - Modern web framework with server-first rendering
- React v19 - UI library for interactive components
- TypeScript v5 - Type-safe JavaScript
- Tailwind CSS v4 - Utility-first CSS framework
- Supabase - Authentication and backend-as-a-service
- Cloudflare Workers - Edge deployment runtime
- Node.js v22.14.0 (as specified in
.nvmrc) - npm (comes with Node.js)
- Clone the repository:
git clone https://github.com/ounold/10xdev.git
cd 10xdev- Install dependencies:
npm install-
Set up Supabase and configure environment variables — see Supabase Configuration below.
-
Create a
.dev.varsfile for local Cloudflare dev secrets:
cp .env.example .dev.vars- Run the development server:
npm run devIf npm run dev fails inside Codex on Windows with Access is denied or Cannot read directory "../../..", rerun the same command from a normal PowerShell session outside Codex. In this repository, that error pattern points to Codex sandbox filesystem limits rather than broken app dependencies.
npm run dev- Start development server (Cloudflare workerd runtime)npm run build- Build for productionnpm run preview- Preview production buildnpm run lint- Run ESLint with type-checked rulesnpm run lint:fix- Auto-fix ESLint issuesnpm run format- Run Prettier
.
├── src/
│ ├── layouts/ # Astro layouts
│ ├── pages/ # Astro pages
│ │ └── api/ # API endpoints
│ ├── components/ # UI components (Astro & React)
│ └── assets/ # Static assets
├── public/ # Public assets
├── wrangler.jsonc # Cloudflare Workers configThis project uses Supabase for authentication. Environment variables are declared via Astro's astro:env schema and are treated as server-only secrets — they are never exposed to the client.
Requires Docker and ~7 GB RAM.
- Create your
.envfile:
cp .env.example .env- Initialize the local Supabase project (creates a
supabase/config folder):
npx supabase init- Start the local stack (downloads Docker images on first run):
npx supabase start- Copy the credentials printed by the CLI into your
.envand.dev.vars:
SUPABASE_URL=http://127.0.0.1:54321
SUPABASE_KEY=<anon key from CLI output>
- To stop the stack when done:
npx supabase stopThe local Studio UI is available at http://localhost:54323.
This repository now includes supervision-domain migrations under supabase/migrations/. After the local stack starts, apply the repository schema with the usual Supabase migration workflow so local development includes the app's profiles, students, notes, and note_items tables in addition to auth.users.
Recommended local reset/apply flow after schema changes:
npx supabase db resetThat applies the checked-in migrations and the minimal development seed from supabase/seed.sql.
If you prefer to use a hosted Supabase project, add these variables to your .env and .dev.vars files:
| Variable | Description |
|---|---|
SUPABASE_URL |
Project URL from Supabase dashboard → Settings → API |
SUPABASE_KEY |
anon public key from Supabase dashboard → Settings → API |
SUPABASE_URL=https://<project-ref>.supabase.co
SUPABASE_KEY=<anon-key>
If your change adds or modifies database schema, RLS, or SQL helpers, deploy the hosted Supabase changes explicitly before treating the Cloudflare release as complete:
# one-time auth if needed
& '.\node_modules\supabase\bin\supabase.exe' login
# one-time link to the hosted project
& '.\node_modules\supabase\bin\supabase.exe' link --project-ref <project-ref>
# apply checked-in migrations to the linked remote project
& '.\node_modules\supabase\bin\supabase.exe' db push --linkedOnly after the remote database is updated should you proceed with the Cloudflare release flow.
If you run the professor-bootstrap change against a hosted Supabase project, also configure:
SUPABASE_SERVICE_ROLE_KEY=<service-role-key>
BOOTSTRAP_PROFESSOR_EMAIL=<professor-email>
SUPABASE_SERVICE_ROLE_KEY is required because the first-professor claim is performed by a dedicated server-side bootstrap endpoint with an admin client. This is intentional: current RLS blocks self-service role escalation for normal authenticated clients.
BOOTSTRAP_PROFESSOR_EMAIL is the single allowlisted account that may claim the first professor role when no professor exists yet.
By default Supabase requires email confirmation before a user can sign in. To skip this during local development:
- Open the Supabase dashboard for your project
- Go to Authentication → Email → Confirm email
- Toggle it off
Users can then sign in immediately after sign-up without clicking a confirmation link.
| Route | Description |
|---|---|
/auth/signin |
Email/password sign-in form |
/auth/signup |
Email/password sign-up form |
/auth/confirm-email |
Post-signup "check your inbox" page |
/dashboard |
Example protected page (redirects to /auth/signin if unauthenticated) |
Route protection is handled in src/middleware.ts. Add paths to the PROTECTED_ROUTES array there to require authentication.
To verify the MVP professor bootstrap locally with a hosted Supabase project:
- Set
BOOTSTRAP_PROFESSOR_EMAILto the account that should become the first professor. - Sign in with that allowlisted account and open
/dashboard. - Confirm the app lands on the professor shell and shows
Current app role: professor. - Sign out, then sign in with a different non-allowlisted account.
- Confirm that second account lands on
/pending-accessrather than seeing professor content.
This two-account flow is the expected manual verification path for professor-bootstrap.
To verify the current professor-note-history slice against a hosted Supabase project:
- Sign in as the bootstrap professor and open
/dashboard. - Confirm at least one student thread is visible. If the hosted project has no students yet, create one manually in Supabase Studio under
public.studentswithprofessor_profile_idset to the professor profile id. - Open a student thread and confirm existing notes render in chronological order when present.
- Create a fresh dated note with multiple
info/taskrows and confirm it appears on the same thread after submit.
Current hosted-project note:
- the shipped write path verifies professor access with the session client, then persists note writes with the server-side admin client because the hosted Supabase project currently rejects session-client note inserts under RLS. Treat that as a temporary hardening adaptation until the hosted RLS/session-write path is reconciled.
The MVP now includes a first-pass supervision data model in Supabase:
profiles— app-level identity and role overauth.usersstudents— professor-owned student records, optionally linked to a student profilenotes— dated post-meeting notes for a single studentnote_items— ordered bullet items for a note, with explicit item type
Row-level security for these tables is planned as a follow-up foundation step; this repository change introduces the schema first so later slices can build on a stable model.
The app-facing TypeScript contract for the supervision domain lives in src/lib/database.ts. Follow-up slices should import these types through the @/* alias instead of recreating the row shapes ad hoc.
This project deploys to Cloudflare Workers.
- Build the project:
npm run buildIf Wrangler or astro build fails on Windows with EPERM while writing under %APPDATA%, run the build with workspace-local XDG directories instead:
$env:XDG_CONFIG_HOME="$PWD\\.tmp-xdg"
$env:XDG_CACHE_HOME="$PWD\\.tmp-xdg-cache"
& 'C:\Program Files\nodejs\node.exe' '.\node_modules\astro\bin\astro.mjs' build- Deploy with Wrangler:
npx wrangler deployRecommended release order for production:
- Push remote Supabase migrations with
supabase db push --linkedif the change touches schema or RLS. - Verify the hosted Supabase project is at the expected schema level.
- Deploy the Worker with
npx wrangler deploy.
Set SUPABASE_URL and SUPABASE_KEY as secrets in your Cloudflare dashboard or via npx wrangler secret put. If you deploy professor bootstrap, also set SUPABASE_SERVICE_ROLE_KEY and BOOTSTRAP_PROFESSOR_EMAIL in the target environment.
GitHub Actions runs lint + build on every push and PR to master. Configure SUPABASE_URL and SUPABASE_KEY as repository secrets in GitHub for the build step.
MIT
