| features |
|
|||||||
|---|---|---|---|---|---|---|---|---|
| languages |
|
Building healthcare dashboards on top of FHIR data typically requires significant boilerplate: mapping FHIR resources to SQL, setting up charting libraries, and wiring everything together.
This project demonstrates how Claude Code can build a complete patient dashboard from a single prompt, using Aidbox FHIR Server's SQL on FHIR ViewDefinitions to flatten FHIR resources into queryable SQL tables, and Chart.js to visualize the data.
The dashboard shows a list of patients with drill-down detail pages, including a body weight trend chart powered by materialized ViewDefinitions.
- SQL on FHIR ViewDefinitions: Declarative mapping from FHIR resources to queryable SQL tables
- Chart.js Visualizations: Interactive line charts showing body weight trends over time
- FHIR API Integration: Patient and Observation data fetched via
@health-samurai/aidbox-client - AI-Assisted Development: Dashboard features built entirely through Claude Code prompts using the
/aidbox-dashboardskill
- Bun - JavaScript runtime and toolkit
- Docker and Docker Compose - Container orchestration
- AI coding agent with agents.md and skills support (e.g., Claude Code) - this tutorial was tested with Claude Code but should work with any compatible agent
- Aidbox - Local FHIR server
-
Clone the repository:
git clone git@github.com:Aidbox/examples.git cd examples/developer-experience/agentic-coding-dashboard -
Install dependencies:
bun install
-
Start the FHIR server:
docker compose up
-
Initialize Aidbox:
- Open http://localhost:8080 in your browser
- Log in and initialize the instance with your Aidbox account
- The init bundle automatically configures:
- Client with Basic authentication (
basic:secret) - Access policies for the client
- Body weight ViewDefinition (with automatic materialization)
- Client with Basic authentication (
-
Seed sample data:
bun run seed
-
Start the dashboard App:
bun run dev
-
Open the dashboard App at http://localhost:3000
agentic-coding-dashboard/
├── .claude/ # Claude Code configuration
│ └── skills/
│ └── aidbox-dashboard/ # Dashboard development skill
│ └── SKILL.md
├── CLAUDE.md # Claude Code main configuration
├── README.md # Project documentation
├── docker-compose.yaml # Aidbox + PostgreSQL
├── package.json
├── tsconfig.json
├── init-bundle.json # Generated bundle (do not edit)
├── fhir/
│ └── definitions/ # FHIR resource definitions
│ ├── access-control/
│ │ ├── 01-client.json # Basic auth client
│ │ └── 02-access-policy.json # Access policy
│ └── view-definitions/
│ └── 01-body-weight.json # Body weight ViewDefinition
├── scripts/
│ ├── build-init-bundle.ts # Build, upload & materialize
│ ├── generate-types.ts # FHIR type generation config
│ └── seed.ts # Seed sample patient data
└── src/
├── index.ts # Web server, routes & charts
├── aidbox.ts # AidboxClient instance
└── fhir-types/ # Auto-generated FHIR types
A ViewDefinition declaratively maps FHIR Observation resources (filtered by LOINC code 29463-7 for body weight) into a flat SQL table:
| Column | Source |
|---|---|
id |
Observation ID |
patient_id |
Referenced Patient ID |
effective_date |
Observation date |
weight_kg |
Quantity value |
unit |
Quantity unit |
status |
Observation status |
Running bun run build:init-bundle --upload uploads the ViewDefinition to Aidbox and calls $materialize, which creates a SQL table populated with data from matching FHIR resources.
The dashboard queries the materialized table directly, bypassing the FHIR API for efficient tabular access:
const rows = await db.unsafe(
`SELECT effective_date, weight_kg, unit
FROM sof.body_weight
WHERE patient_id = $1
ORDER BY effective_date`,
[patientId],
);Body weight data is passed to a Chart.js line chart, showing each patient's weight trend over time with interactive tooltips.
| Command | Description |
|---|---|
bun run dev |
Start dev server with hot reload (port 3000) |
bun run build:init-bundle |
Rebuild init-bundle.json from definitions |
bun run build:init-bundle --upload |
Rebuild, upload to Aidbox & materialize views |
bun run seed |
Seed sample data (2 patients, 20 observations) |
bun run generate-types |
Regenerate FHIR TypeScript types |
This project includes a custom /aidbox-dashboard skill that teaches Claude Code how to add new dashboard features. To add a new chart or view:
claude
> /aidbox-dashboard Add a blood pressure chart to the patient detail pageClaude Code will:
- Create a new ViewDefinition in
fhir/definitions/view-definitions/ - Run
bun run build:init-bundle --uploadto materialize it - Add the SQL query and Chart.js visualization to
src/index.ts - Verify the result end-to-end
The CLAUDE.md file provides Claude Code with full context about the project structure, Aidbox client usage, FHIR type generation, and available commands. The skill definition provides step-by-step instructions for the SQL on FHIR dashboard workflow.
