Static HTMX frontend for unified dashboard access to sequencing metadata and technician-facing project sample tracking. Supabase Edge Functions return HTML fragments for HTMX swaps.
Samplesheet metadata (container):
- pi_name
- date
- submitter_name
- submitter_email
- project_id
- project_title
- experiment_type
- project_description
- filename
Samplesheet entry fields:
- run_id
- samplesheet_id (required link to
samplesheets.id) - smart_id
- data_type
- species
- sample_type
- source_id
- is_paired_end
- read_end
- replicate_num
- test_or_control
- location_id
- disease_id
- treatment_id
- genetic_factors
- sequencing_instrument
- batch_date
- description
Project sample tracking fields:
- Projects (
public.projects): code, title, description - Project samples (
public.project_samples): name, tissue_type, library_type, source - Sample status updates (
public.sample_status_updates): status values arenot started,in progress,data generated,failed - User profile access gate (
public.user_profiles): booleanis_internalcontrols who can add status updates
frontend/static site (index.html,styles.css,app.js)supabase/migrations/DB schema and RLS policy migrationssupabase/migrations_legacy/archived pre-baseline migration chain (kept for history)supabase/seed.sqldev-only sample/demo data loaded bysupabase db resetsupabase/functions/HTML fragment edge endpoints
public.samplesheetstable stores top-level samplesheet metadata.public.samplesheet_entriesremains in place and now includes requiredsamplesheet_id.public.projectsstores sequencing cohorts for technician tracking.public.project_samplesstores sample-level constants for each project.public.sample_status_updatesstores append-only status history for samples.public.project_samples_latest_statusview returns one row per sample with latest status.
- Install Supabase CLI.
- Start local Supabase services:
supabase start
- Apply migrations:
supabase db reset- This applies
supabase/migrations/001_baseline.sqland then loadssupabase/seed.sql.
- Set edge function secrets:
supabase secrets set SUPABASE_URL=http://127.0.0.1:54321 SUPABASE_ANON_KEY=<anon_key>
- Serve static site from
frontend/(example):cd frontend && python3 -m http.server 8080
- Open:
http://127.0.0.1:8080/index.htmlfor the dashboard
Deploy locally after editing:
supabase functions serve
These functions use the caller's bearer token plus the anon key to create a scoped Supabase client. They do not use the service role key.
Endpoints:
list-samplesheetsget-samplesheetlist-projectslist-project-samplesget-dashboardget-sample-status-modaladd-sample-status-update
-
Production schema is managed by the baseline migration only.
-
Demo/sample data is intentionally not stored in migration files, so
supabase db pushdoes not insert seed data. -
Keep
supabase/seed.sqlfor local/dev reset workflows only. -
Before first production cutover, deploy to a separate dry-run Supabase project and validate auth + RLS behavior.
-
Auth model is invite-only using Supabase Auth. Self-signup is disabled.
-
Internal users can read all projects, samples, and samplesheets.
-
External users are read-only and can see only granted projects and their samples.
-
Samplesheets are internal-only. External samplesheet list requests return empty results and samplesheet detail requests return 404.
-
Status updates remain internal-only for writes.
-
Keep function responses as
text/htmlfor HTMX compatibility.
Frontend hosting is automated by .github/workflows/deploy-pages.yml.
Required repository variables:
SUPABASE_URL: your cloud project URL, e.g.https://<project-ref>.supabase.coSUPABASE_PUBLISHABLE_KEY: cloud anon/publishable keyFUNCTIONS_BASE(optional): override edge base URL. If omitted, workflow uses${SUPABASE_URL}/functions/v1.
Workflow behavior:
- On push to
main, build runtimefrontend/config.jsfrom repo variables. - Publish the
frontend/directory to GitHub Pages.
Necessary server configurations:
- Enable GitHub Pages source as GitHub Actions in repository settings.
- Add
https://prensner-lab.github.ioto allowed origins/CORS in Supabase.
To run a gated rollout: create a backup, run supabase db push --dry-run, then apply supabase db push.
For a full first-deploy checklist (dry-run and production), see DEPLOYMENT.md.
- Successful auth auto-loads dashboard cards.
- Dashboard cards include projects for all signed-in users (subject to access policy) and samplesheets for internal users.
- Left nav is in-session recent history and can contain both projects and samplesheets.
- Selecting a project shows that cohort's samples; selecting
Allshows accessible samples across projects. - Each sample row displays sample name and latest status.
public.user_profilesstores per-user fields:display_name,is_internal.- Only users with
is_internal = truecan insert rows intosample_status_updates. - Status timeline modal is visible to users with access to the sample's project; only internal users can submit updates.
- For local testing, each user should create/update their own profile row after sign-in.
Example SQL (run as admin):
insert into public.user_profiles (id, display_name, is_internal)
values ('<auth_user_uuid>', 'Lab Tech', true)
on conflict (id) do update
set display_name = excluded.display_name,
is_internal = excluded.is_internal,
updated_at = now();- Run edge functions with JWT verification enabled:
supabase functions serve
- The browser still sends the publishable key in the
apikeyheader because the local gateway requires it, but row-level access is enforced by the signed-in user's JWT. - To create new users, use Supabase invite flow from dashboard or admin APIs.
- Existing seed rows with null ownership are read-only to normal users by design.