AnyBio
Guides

Bolt Integration

Add health widgets to your Bolt app in three steps. This guide walks through setting up the BioUI Web SDK inside a Bolt (bolt.new) project using a Next.js API route for secure token-based authentication.

Prerequisites

  • An AnyBio account with a project key (proj_*) and a Write-scoped API key (org_*)
  • A Bolt project using the Next.js template (recommended) or any framework that supports server-side routes

Architecture

Bolt App (Next.js in StackBlitz WebContainer)

  │ 1. User interacts with your app

  │ 2. App calls Next.js API route
  │    POST /api/anybio-auth

  │ 3. API route calls AnyBio (server-side, secret key)
  │    POST https://api.anybio.io/api/v1/sdk/token
  │    Authorization: Bearer org_your_write_key

  │ 4. AnyBio returns short-lived JWT (1 hour)
  │    { xuser_token: "eyJ...", xuser_id: "...", expires_in: 3600 }

  │ 5. App passes token to <bio-provider>
  │    <bio-provider sdk-key="sdk_..." xuser-token="eyJ...">

  │ 6. Widgets make API calls using the JWT
  │    Authorization: Bearer eyJ...

Your Write-scoped API key never leaves the server. The browser only sees a short-lived, user-scoped JWT.

Step 1: Create the API Route

In your Bolt project, create a Next.js API route that mints AnyBio xuser tokens.

Create the file app/api/anybio-auth/route.ts:

import { NextRequest, NextResponse } from "next/server";

const ANYBIO_API_KEY = process.env.ANYBIO_API_KEY!;
const ANYBIO_PROJECT_KEY = process.env.ANYBIO_PROJECT_KEY!;

export async function POST(request: NextRequest) {
  // In production, verify the caller is authenticated with your app's auth.
  // For prototyping in Bolt, you can use a simple user ID.
  const { userId } = await request.json();

  if (!userId) {
    return NextResponse.json({ error: "Missing userId" }, { status: 400 });
  }

  const res = await fetch("https://api.anybio.io/api/v1/sdk/token", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${ANYBIO_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      external_id: userId,
      project_key: ANYBIO_PROJECT_KEY,
    }),
  });

  if (!res.ok) {
    const body = await res.text();
    return NextResponse.json(
      { error: `AnyBio error: ${body}` },
      { status: 502 }
    );
  }

  const data = await res.json();
  return NextResponse.json(data);
}

Then add your secrets to the Bolt project's .env.local:

ANYBIO_API_KEY=org_your_write_key_here
ANYBIO_PROJECT_KEY=proj_your_project_key_here

Bolt tip: In Bolt's StackBlitz environment, create .env.local via the file explorer. Environment variables prefixed with NEXT_PUBLIC_ are exposed to the browser — your API key does NOT have that prefix, so it stays server-side.

Step 2: Add the SDK to Your App

In your Bolt project's root layout or app/layout.tsx, add the BioUI Web SDK:

import Script from "next/script";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <link rel="stylesheet" href="https://cdn.anybio.io/biosdk-web/v1/bioui-base.css" />
      </head>
      <body>
        {children}
        <Script src="https://cdn.anybio.io/biosdk-web/v1/bioui.js" strategy="afterInteractive" />
      </body>
    </html>
  );
}

Then add the provider and widgets to a page component:

"use client";

export default function Dashboard() {
  return (
    <bio-provider
      id="bio"
      sdk-key="sdk_your_key"
      base-url="https://api.anybio.io"
    >
      <bio-health-metrics></bio-health-metrics>
      <bio-mood></bio-mood>
      <bio-checkin question-types='["readiness","confidence","worry"]'></bio-checkin>
    </bio-provider>
  );
}

Note: BioUI Web uses custom elements (Web Components). In Next.js, you need the "use client" directive on any page that renders them — custom elements require browser APIs.

The widgets won't render data until a valid xuser-token is set on the provider.

Step 3: Initialize After Login

After your user authenticates (or on page load for prototyping), call the API route to get a token and pass it to the provider:

"use client";

import { useEffect } from "react";

export default function Dashboard() {
  useEffect(() => {
    async function initBio() {
      const res = await fetch("/api/anybio-auth", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ userId: "demo-user-1" }),
      });

      if (!res.ok) {
        console.error("Failed to get AnyBio token");
        return;
      }

      const { xuser_token } = await res.json();
      const provider = document.getElementById("bio");
      provider?.setAttribute("xuser-token", xuser_token);
    }

    initBio();
  }, []);

  return (
    <bio-provider
      id="bio"
      sdk-key="sdk_your_key"
      base-url="https://api.anybio.io"
    >
      <bio-health-metrics></bio-health-metrics>
      <bio-mood></bio-mood>
    </bio-provider>
  );
}

Token Refresh

Tokens expire after 1 hour. Listen for the expiry warning and refresh automatically:

useEffect(() => {
  function handleExpiring() {
    fetch("/api/anybio-auth", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ userId: "demo-user-1" }),
    })
      .then((res) => res.json())
      .then(({ xuser_token }) => {
        document.getElementById("bio")?.setAttribute("xuser-token", xuser_token);
      });
  }

  document.addEventListener("anybio:token:expiring", handleExpiring);
  return () => document.removeEventListener("anybio:token:expiring", handleExpiring);
}, []);

Working with Bolt's AI Agent

When prompting Bolt's AI to build a health app, include the integration details. Here's a prompt template:

Add AnyBio BioUI Web health widgets to my Next.js app. The SDK CDN URL is https://cdn.anybio.io/biosdk-web/v1/bioui.js and the CSS is https://cdn.anybio.io/biosdk-web/v1/bioui-base.css. Create a Next.js API route at /api/anybio-auth that calls POST https://api.anybio.io/api/v1/sdk/token with Authorization: Bearer ${process.env.ANYBIO_API_KEY} and body { external_id: userId, project_key: process.env.ANYBIO_PROJECT_KEY }. Then add <bio-health-metrics> and <bio-mood> widgets inside a <bio-provider> on the dashboard page. Use "use client" for the page with widgets. Follow the guide at https://docs.anybio.io/bioui-web/guides/bolt-integration.

Available Widgets

WidgetTagPurpose
Health Metrics<bio-health-metrics>Wearable data (steps, sleep, heart rate, stress)
Journal<bio-journal>Daily journaling with prompts
Mood<bio-mood>Mood tracking with configurable scales
Check-in<bio-checkin>PRO questionnaires
Task List<bio-task-list>Daily task tracking
Progress Ring<bio-progress-ring>Circular progress visualization
Trend Card<bio-trend-card>Single biosignal trend summary
Trend Chart<bio-trend-chart>Multi-biosignal trend charts

Non-Next.js Templates

If your Bolt project uses React + Vite or plain HTML instead of Next.js, you won't have API routes for server-side token minting. In that case:

  1. Use an external serverless function (e.g., Cloudflare Workers, Vercel Edge Functions, or any backend you control) to host the token endpoint.
  2. Call that endpoint from your Bolt app instead of /api/anybio-auth.
  3. The rest of the guide (SDK setup, widgets, token refresh) is the same.

See the Authentication guide for the full server-side token flow.

Security Notes

  • Your AnyBio Write-scoped API key (org_*) stays in the API route — never exposed to the browser
  • The xuser-token is a short-lived JWT (1-hour expiry, RS256-signed)
  • Each token is scoped to a single user — cross-user access is impossible
  • In production, add proper auth verification to the API route before minting tokens

Troubleshooting

IssueSolution
Widgets show "Loading..." indefinitelyCheck that xuser-token is set on the provider. Open DevTools and verify the API route returns a token.
API route returns 502Verify ANYBIO_API_KEY is set in .env.local. The key must have Write scope.
Custom elements not renderingMake sure the page has "use client" directive. Custom elements require browser APIs.
ReferenceError: document is not definedYou're rendering <bio-provider> in a Server Component. Add "use client" to the file.
Token expiredListen for the anybio:token:expiring event and refresh. See Token Refresh above.

On this page