Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions docs/06-development/01-overview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
sidebar_position: 1
title: Developer Documentation
description: Technical reference for developers building on or contributing to StudyU
---

# Developer Documentation

StudyU is an open-source platform for designing and running N-of-1 clinical trials on participants' smartphones. It consists of two Flutter applications sharing a common core library, backed by Supabase (PostgreSQL + Auth + Storage).

## System Architecture

```mermaid
graph TB
subgraph "Client Layer"
APP["<b>StudyU App</b><br/>Flutter (iOS, Android, Web)<br/>For participants"]
DESIGNER["<b>StudyU Designer</b><br/>Flutter Web<br/>For researchers"]
end

subgraph "Shared Code"
CORE["<b>studyu_core</b><br/>Domain models, serialization,<br/>Supabase ORM utilities"]
COMMON["<b>studyu_flutter_common</b><br/>Shared Flutter widgets,<br/>localization, secure storage"]
end

subgraph "Backend (Supabase)"
AUTH["Auth (GoTrue)<br/>Email/password"]
DB["PostgreSQL<br/>RLS-protected tables"]
STORAGE["Storage<br/>Blob bucket: observations"]
EDGE["Edge Functions<br/>(minimal usage)"]
end

APP --> COMMON
APP --> CORE
DESIGNER --> COMMON
DESIGNER --> CORE
COMMON --> CORE

APP -->|"supabase_flutter SDK"| AUTH
APP -->|"REST API (PostgREST)"| DB
APP -->|"File uploads"| STORAGE

DESIGNER -->|"supabase_flutter SDK"| AUTH
DESIGNER -->|"REST API (PostgREST)"| DB

style APP fill:#4FC3F7,color:#000
style DESIGNER fill:#81C784,color:#000
style CORE fill:#FFB74D,color:#000
style COMMON fill:#FFB74D,color:#000
style AUTH fill:#CE93D8,color:#000
style DB fill:#CE93D8,color:#000
style STORAGE fill:#CE93D8,color:#000
style EDGE fill:#CE93D8,color:#000
```

## Tech Stack

| Layer | Technology | Notes |
|---|---|---|
| **Mobile / Web apps** | Flutter / Dart 3.8+ | Two apps from one codebase |
| **App state (participants)** | Provider + ChangeNotifier | Lightweight, mobile-first |
| **App state (researchers)** | Riverpod + code gen | Complex async form workflows |
| **Routing (participants)** | Navigator 1.0 | Named routes, imperative |
| **Routing (researchers)** | GoRouter v17 | URL-driven, auth guards |
| **Form handling (researchers)** | reactive_forms | Debounced auto-save |
| **Serialization** | json_serializable | Compile-time safety, code-generated |
| **Monorepo tooling** | Melos | Script runner, package linking |
| **Backend** | Supabase | PostgreSQL + Auth + Storage + PostgREST |
| **Database** | PostgreSQL 15 | RLS on all tables |
| **Authentication** | GoTrue (Supabase) | Email/password only |
| **Error tracking** | Sentry | Analytics opt-in |

## Key Architectural Decisions

| Decision | Choice | Rationale |
|---|---|---|
| Monorepo | Melos-managed workspace | Shared models and utilities across two apps |
| Backend | Supabase (hosted PostgreSQL) | Auth, RLS, real-time, and storage out of the box |
| State management (App) | Provider | Lightweight, sufficient for mobile-first participant flows |
| State management (Designer) | Riverpod | Complex form workflows and async data management |
| Serialization | json_serializable (code gen) | Compile-time safety for 30+ model classes |
| Offline strategy | Exception-based fallback + cache sync | Pragmatic for clinical data entry in low-connectivity scenarios |

## Reading Order for New Developers

If you are new to StudyU, follow this sequence:

1. **[Domain Model: N-of-1 Trials](./02-domain-model/01-n-of-1-trials.mdx)** — understand the clinical research concepts before touching code
2. **[Domain Model: Core Entities](./02-domain-model/02-core-entities.mdx)** — learn what Study, Intervention, Observation, and Subject mean in the codebase
3. **[Domain Model: Entity Relationships](./02-domain-model/03-entity-relationships.mdx)** — see how entities connect via diagrams
4. **[Domain Model: Concrete Example](./02-domain-model/04-concrete-example.mdx)** — walk through the Vitamin D trial end-to-end
5. **[Architecture: System Overview](./03-architecture/01-system-overview.mdx)** — high-level architecture and tech stack
6. **[Architecture: Monorepo Structure](./03-architecture/02-monorepo-structure.mdx)** — packages, dependencies, Melos scripts
7. **[Local Setup: Prerequisites](./06-local-setup/01-prerequisites.mdx)** — tools to install
8. **[Local Setup: Clone and Bootstrap](./06-local-setup/02-clone-and-bootstrap.mdx)** — get the repo running
9. **[Local Setup: Running Apps](./06-local-setup/04-running-apps.mdx)** — start the apps locally

## Documentation Sections

| Section | What it covers |
|---|---|
| [Domain Model](./02-domain-model/01-n-of-1-trials.mdx) | N-of-1 trial concepts, entity glossary, ERD diagrams, concrete walkthrough |
| [Architecture](./03-architecture/01-system-overview.mdx) | System design, monorepo, frontend patterns, Supabase backend, offline sync |
| [App Reference](./04-app-reference/01-screen-map.mdx) | Participant app screen flow, task system, widget reference |
| [Designer Reference](./05-designer-reference/01-screen-map.mdx) | Researcher app navigation, design tabs, management screens, form patterns |
| [Local Setup](./06-local-setup/01-prerequisites.mdx) | Prerequisites, clone, Supabase, running apps, environment config, code generation |
| [Development Workflow](./07-development-workflow/01-edit-build-test.mdx) | Daily workflow, coding conventions, IDE setup, troubleshooting |
| [Database Reference](./08-database-reference/01-schema.mdx) | Tables, columns, computed functions, RLS policies, migrations |
| [JSON Schema Reference](./09-json-schema-reference/01-overview.mdx) | Complete JSON structure of every model class with examples |
144 changes: 144 additions & 0 deletions docs/06-development/02-domain-model/01-n-of-1-trials.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
---
sidebar_position: 1
title: What is an N-of-1 Trial?
description: The clinical research concept at the heart of StudyU, explained for developers
---

# What is an N-of-1 Trial?

This document is the entry point for developers joining the StudyU project who know Flutter but have no background in clinical research. Understanding the research concept behind the product is the key to understanding why the data model looks the way it does.

## The problem with traditional clinical trials

A standard Randomized Controlled Trial (RCT) enrolls hundreds or thousands of participants, randomly assigns them to a treatment or a placebo group, and then measures the *average* treatment effect across the group. This answers the question "does this drug work for people *on average*?" — but it says nothing about whether the drug will work for *you specifically*.

## What an N-of-1 trial is

An N-of-1 trial studies a **single participant** across time. Instead of comparing two groups of different people, it compares the *same person* across different treatment phases. The participant alternates between an active treatment (Intervention A) and a control or alternative treatment (Intervention B), repeating the cycle multiple times. Because the same person experiences both conditions, many sources of individual variability are controlled automatically.

This answers a different question: **"Does this treatment work for this individual?"**

## Why this matters for StudyU

StudyU is a platform that lets researchers design and run N-of-1 trials digitally, using participants' smartphones. The clinical insight translates directly into product requirements:

- A study must have **at least two intervention arms** to alternate between.
- A study has a **schedule** that dictates which arm is active on which days.
- Data is collected through **tasks** that participants complete on each study day.
- Results are meaningful *per participant*, not only in aggregate.

## How a typical N-of-1 trial runs

```mermaid
flowchart TD
A([Participant opens StudyU app]) --> B[Browse study registry\nor enter invite code]
B --> C[View study details]
C --> D{Has eligibility check?}
D -- No --> F
D -- Yes --> E[Complete eligibility questionnaire]
E --> EE{All criteria\nsatisfied?}
EE -- No --> Z1([Not eligible — exit])
EE -- Yes --> F
F{Has consent items?}
F -- No --> H
F -- Yes --> G[Review and agree to\neach consent item]
G --> GG{All items\nagreed?}
GG -- No --> Z2([Cannot enroll — exit])
GG -- Yes --> H
H[Enrolled as StudySubject\nstartedAt recorded] --> I
I{includeBaseline?}
I -- Yes --> J[Baseline phase\nObservations only — no intervention tasks]
I -- No --> K
J --> K[Intervention phase A\nIntervention tasks + Observations]
K --> L[Intervention phase B\nIntervention tasks + Observations]
L --> M{More cycles?}
M -- Yes --> K
M -- No --> N[Study complete]
N --> O[View personal results report]
```

## Phase sequences

The order of intervention phases within each cycle is configurable by the researcher:

```mermaid
gantt
title Study Phase Sequences (phaseDuration = 7 days, numberOfCycles = 2, includeBaseline = true)
dateFormat YYYY-MM-DD
axisFormat Day %j

section Alternating (ABAB)
Baseline :baseline1, 2024-01-01, 7d
Intervention A :a1, after baseline1, 7d
Intervention B :b1, after a1, 7d
Intervention A :a2, after b1, 7d
Intervention B :b2, after a2, 7d

section Counter-Balanced (ABBA)
Baseline :baseline2, 2024-01-01, 7d
Intervention A :c1, after baseline2, 7d
Intervention B :c2, after c1, 7d
Intervention B :c3, after c2, 7d
Intervention A :c4, after c3, 7d

section Randomized
Baseline :baseline3, 2024-01-01, 7d
Intervention A :d1, after baseline3, 7d
Intervention B :d2, after d1, 7d
Intervention B :d3, after d2, 7d
Intervention A :d4, after d3, 7d

section Customized (ABBA string)
Baseline :baseline4, 2024-01-01, 7d
Intervention A :e1, after baseline4, 7d
Intervention B :e2, after e1, 7d
Intervention B :e3, after e2, 7d
Intervention A :e4, after e3, 7d
```

> **Note:** Each bar is one phase lasting `phaseDuration` days. The counter-balanced and customized sequences shown above happen to produce the same output (ABBA) — the difference is that `customized` takes a researcher-provided string, while `counterBalanced` is computed by the `_generateCounterBalancedCycle` algorithm.

## The study lifecycle

```mermaid
flowchart LR
A([Start]) --> B[Draft]
B --> |"Researcher designs study\nin Designer app"| B
B --> |"Researcher publishes"| C[Running]
C --> |"Participants enroll\nand complete tasks"| C
C --> |"Researcher closes\nor study period ends"| D[Closed]
D --> E([Analyze results])

subgraph "Draft phase — what the researcher configures"
F[Define interventions]
G[Add observations and questionnaires]
H[Set eligibility criteria and consent]
I[Configure schedule]
J[Set up report specification]
end

subgraph "Running phase — what participants do"
K[Enroll via app]
L[Complete daily tasks]
M[SubjectProgress records accumulate]
end

B -.-> F
C -.-> K
```

## What this means in code

The N-of-1 structure maps directly to the domain model:

| Clinical concept | Code entity | Where to find it |
|---|---|---|
| The trial protocol | `Study` | `core/lib/src/models/tables/study.dart` |
| A treatment arm | `Intervention` | `core/lib/src/models/interventions/intervention.dart` |
| A task the participant does per phase | `CheckmarkTask` | `core/lib/src/models/interventions/tasks/checkmark_task.dart` |
| A measurement taken every phase | `QuestionnaireTask` | `core/lib/src/models/observations/tasks/questionnaire_task.dart` |
| The trial schedule | `StudySchedule` | `core/lib/src/models/study_schedule/study_schedule.dart` |
| An enrolled participant | `StudySubject` | `core/lib/src/models/tables/study_subject.dart` |
| A single task completion | `SubjectProgress` | `core/lib/src/models/tables/subject_progress.dart` |

Continue to [Core Entities](./02-core-entities.mdx) for the full glossary of each domain object.
Loading