opsinjs
IntroductionStart hereInstallation

React Router

The framework-mode install. Server rendering, route modules, and where the stylesheet goes.

Overview

React Router in framework mode gives you server rendering with a route-module data story, which suits health interfaces well: the value, its range and its status are all loader data, and the component that renders them is display-only.

Shipped, and no published host yet

The sixty implemented components are real code and their registry items carry the source shadcn add copies. What is missing is the host: opsinjs.pensievelabs.org is not serving, so the commands below resolve only against a registry you point @opsinjs at yourself, and there is no npm package to fall back to. Troubleshooting.

If you are on Remix, upgrade to React Router 7 framework mode first. There is no separate Remix path and there will not be one.

Set it up

Start from a framework-mode app with Tailwind v4

React Router framework mode builds on Vite, so Tailwind is installed the Vite way. Everything in Vite about source scanning applies here too.

Confirm @/ resolves in both places

vite.config.ts and tsconfig.json must agree, exactly as in a plain Vite app.

Add the registry entry and a component

npx shadcn@latest add @opsinjs/result-card

Place the stylesheet

Framework mode exposes stylesheets through the root route's links export, which means the ordering rule is expressed as import order in one file rather than as a sequence of @import statements. The rule is unchanged: Tailwind, then the opsinjs token layer, then your overrides.

app/app.css
@import "tailwindcss";
@import "./opsinjs.css";

@source "./components/opsinjs/**/*.{ts,tsx}";

Export it from the root route so it is present on every document, not only on the routes that happen to use a component.

Keep display components on the server

The natural shape here is the one opsinjs is designed for:

  • The loader fetches the value, resolves the reference range and applies your clinical mapping to produce a status. All three are server-side, in one place, where they can be tested and reviewed.
  • The component receives value, range and status as props and renders them. No computation, no thresholds, no client JavaScript.

That split is not a React Router idiom being imposed on opsinjs; it is what the system's central rule looks like when a framework happens to make it easy. See Safety, scope and limitations.

Verify it worked

  1. The stylesheet is on every document, including error and 404 routes. A missing stylesheet on the error route is a classic and only shows up on a bad day.
  2. A copied component renders styled. If not, check the @source line.
  3. Colours resolve through custom properties.
  4. The status in your rendered markup came from the loader, not from anything inside the component.

Troubleshooting

Styles missing on error boundaries. The links export on the root route did not apply, or the error boundary renders outside it. This affects every stylesheet in your app, not just opsinjs.

Hydration mismatch on a formatted time. Server and browser time zones differ. Use the components' documented hydration-safe formatting rather than formatting in a render function.

Unstyled components. As always, @source. See Vite.

Coming from Remix v2. Upgrade first; the alias and stylesheet mechanics changed and following this page on Remix v2 will mislead you.

Next

  • Next.js has the CSS order rule stated in full.
  • Quick start covers the loader-plus-display-component shape, end to end.
  • components.json covers the aliases that must agree.

On this page