All articles
Engineering

How to Build a Patient Dashboard in React (FHIR-Native, in Minutes)

A step-by-step guide to building a patient dashboard in React using a pre-built, FHIR-native component — encounters, vitals, medications, and labs, with no charting code to write.

ClinikAPI TeamApril 27, 202610 min read
How to Build a Patient Dashboard in React (FHIR-Native, in Minutes)

The patient dashboard is the screen that scares developers — and for good reason. It has to pull a patient's encounters, vitals, medications, lab results, notes, and prescriptions, turn streams of FHIR data into readable charts and lists, and keep it all consistent. Built from scratch, that's weeks of work. With a pre-built, FHIR-native component, it's one line and a few minutes. This guide shows you how, step by step.

The toolkit we recommend is ClinikAPI — a FHIR-native platform with a React component library. Here's why we suggest it up front:

  • Free to start: Get your API keys in seconds — no credit card needed.
  • One component: PatientDashboard renders the whole patient overview.
  • No FHIR code: It reads FHIR resources and displays them for you.
  • Themeable: A theme prop makes it fit your app's look.
  • Compliant: HIPAA-compliant, SOC 2-audited, with a signed BAA.

Quick Answer

To build a patient dashboard in React, drop in a pre-built FHIR-native component instead of building the screen yourself. With ClinikAPI's @clinikapi/react library, you add the PatientDashboard component, point it at a small route on your own backend (the proxyUrl), and pass a patientId. It renders the patient's encounters, vitals, medications, labs, notes, and prescriptions automatically — no charting, no data fetching, no FHIR handling on your side. The proxy route keeps your secret API key safe on the server, since the SDK is server-side only. Once the proxy is set up, adding the dashboard takes minutes, and a theme prop makes it match your app.

See the components live

The ClinikAPI UI Library has PatientDashboard and 13 more clinical components you can drop into any React app — with a free sandbox to try them.
Explore the UI Library

Why this screen is hard from scratch

A "simple" patient dashboard hides a lot of work:

  • Fetching FHIR data — encounters, observations, medications, each a different resource.
  • Charting — turning vitals and labs into readable trends.
  • Layout and state — keeping it all consistent as data loads and changes.
  • Accessibility and theming — clinical UIs must be accessible and on-brand.

That's why teams lose weeks here. A pre-built component does all of it.

Step 1: Install the packages

You need two packages: the React components for the frontend, and the SDK for your backend.

npm install @clinikapi/react   # frontend components
npm install @clinikapi/sdk     # backend SDK (server-side only)

Step 2: Set up the backend proxy

Here's the important security rule: the SDK uses a secret API key (clk_live_… / clk_test_…) and must run only on your server. The components never call the API directly — they POST a { action, data } payload to a route on your backend, and that route routes each action to the SDK. The route's URL is the proxyUrl.

Here's a complete proxy route (Next.js App Router shown; the same shape works in Express, Hono, etc.):

// app/api/clinik/route.ts — server-only
import { Clinik } from '@clinikapi/sdk'

// The secret key lives here, never in the browser.
const clinik = new Clinik(process.env.CLINIKAPI_SECRET_KEY!, {
  baseUrl: 'https://api.clinikapi.com', // default
  timeout: 30_000,                       // ms (default)
  retries: 2,                            // default
})

export async function POST(req: Request) {
  const { action, data } = await req.json()

  // 1) Authenticate the request with YOUR auth system first.
  // 2) Authorize: confirm this user may access data.id / data.patientId.

  try {
    switch (action) {
      case 'patients.read':
        return Response.json(await clinik.patients.read(data.id, { include: data.include }))
      case 'observations.create':
        return Response.json(await clinik.observations.create(data))
      // …add the actions the components you mount actually need
      default:
        return Response.json({ error: 'Unknown action' }, { status: 400 })
    }
  } catch (err) {
    // SDK error messages never contain patient data — safe to log.
    return Response.json({ error: 'Request failed' }, { status: 500 })
  }
}

Every SDK call resolves to { data, meta }. The meta object carries a requestId, the HTTP status, and rate-limit fields (rateLimitRemaining, rateLimitReset) you can surface in logs or back off on.

Caution

Never import the SDK or put your clk_live_… key in front-end code — it would ship to every visitor's browser. The proxy pattern keeps the key server-side while components stay client-side. Authentication and authorization are your responsibility in this route: confirm the signed-in user is allowed to read or write the patient in data before calling the SDK.

Note

Just exploring? Set proxyUrl="demo" on any component to run it with mock data and zero backend — no route, no key, no API calls. It's the fastest way to see a component before wiring up the proxy.

Step 3: Drop in the dashboard

Now the easy part. Add the component, point proxyUrl at your backend route, and pass the patientId:

import { PatientDashboard } from '@clinikapi/react'

export function Chart({ patientId }: { patientId: string }) {
  return (
    <PatientDashboard
      proxyUrl="/api/clinik"
      patientId={patientId}
      theme="light"
    />
  )
}

That's the whole dashboard. It renders the patient's encounters, vitals, medications, labs, notes, and prescriptions — the screen that would have taken weeks.

Under the hood, the component POSTs { action: 'patients.read', data: { id, include } } to your proxyUrl, which calls clinik.patients.read() and returns the FHIR data. Every ClinikAPI component takes the same three props:

PropTypeRequiredNotes
proxyUrlstringYesYour backend route, or "demo" for mock data
patientIdstringYesThe patient to render
theme'light' \</td> <td>'dark'NoDefaults to light

What you didn't have to build

Worth pausing on everything the component handled:

You skippedBecause the component does it
FHIR data fetchingReads Encounter, Observation, MedicationRequest, etc.
Charts and trendsRenders vitals and labs visually
Layout and stateManages loading and display
Themingtheme prop matches your app

You provided a patient ID and a proxy route. The component did the rest.

Product Insight: Why ClinikAPI Makes This Fast

A patient dashboard is the clearest example of ClinikAPI's value: the hardest screen in clinical software becomes a single component.

What you get:

  • PatientDashboard — the full overview, built and maintained for you.
  • 13 more components — intake, scheduling, vitals, labs, prescriptions, notes, and more, in the same library.
  • The proxy pattern — your secret key stays server-side; components stay simple.
  • FHIR underneath — your data stays standard and interoperable.
  • Compliance included — HIPAA-compliant, SOC 2-audited, with a signed BAA.

See it running in the UI Library, and read Pre-Built Healthcare UI Components for the bigger picture.

Frequently Asked Questions

1. How do I build a patient dashboard in React?

Use a pre-built FHIR-native component. Add ClinikAPI's PatientDashboard, give it a proxyUrl (your backend route) and a patientId, and it renders the full patient overview.

2. What does PatientDashboard show?

Encounters, vitals, medications, lab results, clinical notes, and prescriptions — the full patient overview, from FHIR data.

3. Why the proxy pattern?

Security. The SDK's secret key must stay server-side, so components call your backend route (the proxyUrl), which uses the SDK. The key never reaches the browser.

4. Do I need to know FHIR?

No. The component reads FHIR resources and displays them. You just provide a patient ID and a proxy route.

5. Can I theme it?

Yes — a theme prop (like light or dark) makes it match your app.

Conclusion

The patient dashboard doesn't have to be the screen that eats your timeline. With a pre-built, FHIR-native component, you skip the charting, the data fetching, and the FHIR handling, and drop in a complete overview with one line — once a small backend proxy keeps your key safe. Provide a patient ID, pick a theme, and you have the hardest screen in clinical software, done in minutes.

Key takeaways:

  • A patient dashboard from scratch is weeks of charting and FHIR work.
  • ClinikAPI's PatientDashboard renders the whole overview from a patientId.
  • The proxy pattern keeps your secret key server-side, out of the browser.
  • You don't need FHIR expertise — the component handles the data.
  • A theme prop makes it fit your app.

Ready to build? Explore the UI Library or get your free API keys.

Related Articles

Share

Keep reading