Lovable Integration
Add HIPAA-ready health widgets to your Lovable app in three steps. This guide walks through setting up the BioUI Web SDK with Lovable's Supabase backend for secure token-based authentication.
Prerequisites
- An AnyBio account with a project key (
proj_*) and a Write-scoped API key (org_*) - A Lovable project with Supabase connected
Architecture
Lovable App (browser)
│
│ 1. User logs in via your app's auth
│
│ 2. App calls Supabase Edge Function
│ POST /functions/v1/anybio-auth
│
│ 3. Edge Function 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 Supabase Edge Function
In your Lovable project, create a Supabase Edge Function that mints AnyBio xuser tokens.
Create the file supabase/functions/anybio-auth/index.ts:
import { serve } from 'https://deno.land/std/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
serve(async (req) => {
// Verify the caller is authenticated with your Supabase project
const authHeader = req.headers.get('Authorization')
if (!authHeader) {
return new Response(JSON.stringify({ error: 'Missing auth' }), { status: 401 })
}
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_ANON_KEY')!,
{ global: { headers: { Authorization: authHeader } } }
)
const { data: { user }, error: authError } = await supabase.auth.getUser()
if (authError || !user) {
return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 })
}
// Mint an AnyBio xuser token for this user
const res = await fetch('https://api.anybio.io/api/v1/sdk/token', {
method: 'POST',
headers: {
'Authorization': `Bearer ${Deno.env.get('ANYBIO_PROJECT_KEY')}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
external_id: user.id,
project_key: Deno.env.get('ANYBIO_PROJECT_KEY_ID'),
}),
})
if (!res.ok) {
const body = await res.text()
return new Response(JSON.stringify({ error: `AnyBio error: ${body}` }), { status: 502 })
}
const data = await res.json()
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
})
})Then store your secrets:
supabase secrets set ANYBIO_PROJECT_KEY=org_your_write_key_here
supabase secrets set ANYBIO_PROJECT_KEY_ID=proj_your_project_key_hereDeploy the function:
supabase functions deploy anybio-authStep 2: Add the SDK to Your App
In your Lovable app's index.html, add the BioUI Web SDK:
<script type="module" src="https://cdn.anybio.io/biosdk-web/v1/bioui.js"></script>
<link rel="stylesheet" href="https://cdn.anybio.io/biosdk-web/v1/bioui-base.css" />Then add the provider and widgets to your page:
<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-journal></bio-journal>
</bio-provider>The widgets won't render until a valid xuser-token is set on the provider.
Step 3: Initialize After Login
After your user authenticates, call the Edge Function to get a token and pass it to the provider:
import { supabase } from './supabaseClient'
async function initBioWidgets() {
const { data: { session } } = await supabase.auth.getSession()
if (!session) return
const { data, error } = await supabase.functions.invoke('anybio-auth', {
headers: { Authorization: `Bearer ${session.access_token}` },
})
if (error) {
console.error('Failed to get AnyBio token:', error)
return
}
const provider = document.getElementById('bio')
provider?.setAttribute('xuser-token', data.xuser_token)
}
// Call after login or on app load if session exists
initBioWidgets()Token Refresh
Tokens expire after 1 hour. Listen for the expiry warning and refresh automatically:
document.addEventListener('anybio:token:expiring', async () => {
const { data: { session } } = await supabase.auth.getSession()
if (!session) return
const { data } = await supabase.functions.invoke('anybio-auth', {
headers: { Authorization: `Bearer ${session.access_token}` },
})
if (data?.xuser_token) {
document.getElementById('bio')?.setAttribute('xuser-token', data.xuser_token)
}
})Working with Lovable's AI Agent
When using Lovable's AI coding agent, you can point it to this documentation. Here's a prompt template:
Add AnyBio BioUI Web health widgets to my app. Follow the integration guide at https://docs.anybio.io/bioui-web/guides/lovable-integration. The SDK CDN URL is https://cdn.anybio.io/biosdk-web/v1/bioui.js. My project key ID is
proj_XXX. Create a Supabase Edge Function calledanybio-auththat mints xuser tokens, then add<bio-health-metrics>and<bio-mood>widgets to the dashboard page.
Available Widgets
| Widget | Tag | Purpose |
|---|---|---|
| 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 |
Security Notes
- Your AnyBio Write-scoped API key (
org_*) stays in the Supabase Edge Function — never exposed to the browser - The
xuser-tokenis a short-lived JWT (1-hour expiry, RS256-signed) - Each token is scoped to a single user — cross-user access is impossible
- The Edge Function verifies Supabase auth before minting a token, so only your authenticated users can get AnyBio access
Troubleshooting
| Issue | Solution |
|---|---|
| Widgets show "Loading..." indefinitely | Check that xuser-token is set on the provider. Open DevTools and verify the Edge Function returns a token. |
| Edge Function returns 401 | Verify ANYBIO_PROJECT_KEY is set correctly in Supabase secrets. The key must have Write scope. |
| CORS errors | The AnyBio API allows cross-origin requests when using JWT tokens. Make sure you're using xuser-token mode, not api-key mode. |
| Token expired | Listen for the anybio:token:expiring event and refresh. See Token Refresh above. |