Docs
GitHub

Quickstart

Before you start

  • Node 20+ and a package manager (pnpm, npm, or yarn).
  • A React app that can run server code (a Next.js App Router project is ideal).
  • You do not need an AI agent or an LLM key.

Install

pnpm add @sina-design-system/theme @sina-design-system/core \
  @sina-design-system/fintech @sina-design-system/fintech-react \
  @sina-design-system/governance

Installing only theme + core is enough for the primitives; the other three packages are the governance layer.

Wire the stylesheets

Import the token and component styles once, in this order. The reset is layered, so your app's own styles always win over it.

// app/layout.tsx
import "@sina-design-system/theme/reset.css";
import "@sina-design-system/theme/css";
import "@sina-design-system/core/styles.css";
import "@sina-design-system/fintech-react/styles.css";

Render a primitive

// app/page.tsx
import { Button } from "@sina-design-system/core";

export default function Page() {
  return <Button variant="primary">It works</Button>;
}

If the button renders unstyled, a stylesheet import above is missing or out of order. The primitives gallery shows everything else core ships.

Run the gate once

The governance check is a plain server-side function call: an intent envelope in, a decision out. Try it in a route handler (any server-only module works):

// app/api/gate/route.ts
import { evaluateFintechIntent } from "@sina-design-system/fintech";

export async function POST(request: Request) {
  const envelope = await request.json(); // { intent, props } from your agent
  const decision = evaluateFintechIntent(envelope);
  return Response.json(decision);
}

POST a small wire to it:

{
  "intent": "wire_transfer",
  "props": {
    "amount": 50000,
    "currency": "USD",
    "debtor": { "name": "Acme Corp", "account": { "scheme": "sepa", "iban": "DE89370400440532013000" } },
    "creditor": { "name": "Beta LLC", "account": { "scheme": "sepa", "iban": "DE89370400440532013000" } }
  }
}

amount is in minor units, so this is a $500.00 transfer. It clears every policy band and the decision reports a clean pass (intent and props are echoed back alongside these fields):

{
  "result": { "valid": true, "violations": [], "requiredComponent": null },
  "mount": null
}

Change amount to 6000000 ($60,000) and the same call escalates: result.requiredComponent becomes "SecureWireDialog", the second-approver dialog from @sina-design-system/fintech-react, and mount names it as the only component allowed to continue. That decision-to-component step is your app's job; How SINA works shows where it sits.

Keep the call server-side. The same function runs in the browser, but there it is advisory: only the server copy is out of reach of the page and the model.

Next steps