This app runs as an iframe embedded within the Assembly.com dashboard (for internal users) and client portal (for clients). It communicates with the parent frame via the app-bridge for UI controls like breadcrumbs and header actions.
When your app loads, Assembly passes a token query parameter that identifies the current user, workspace, and context. This token is used with the Node SDK to fetch data and make API calls.
yarn install- Log into your Assembly workspace
- Navigate to Settings > App Setup
- Click Add App and select Custom App
- Leave the URLs blank for now (dev-mode handles local development)
- Save and note your API Key
Create a .env.local file:
ASSEMBLY_API_KEY=your_api_key_hereThe API key must stay server-side only. Never expose it to the client.
yarn devThis starts the app on port 8080 and opens the Assembly dev-mode page.
The SDK requires your API key and the session token from query params:
import { assemblyApi } from '@assembly-js/node-sdk';
const assembly = assemblyApi({
apiKey: process.env.ASSEMBLY_API_KEY,
token: searchParams.token, // From the iframe URL
});// Get workspace info
const workspace = await assembly.retrieveWorkspace();
// Get token payload to identify the current user
const tokenPayload = await assembly.getTokenPayload();
// Fetch user data based on token
if (tokenPayload?.clientId) {
const client = await assembly.retrieveClient({ id: tokenPayload.clientId });
}
if (tokenPayload?.internalUserId) {
const user = await assembly.retrieveInternalUser({
id: tokenPayload.internalUserId,
});
}See src/utils/session.ts for a complete example.
Use Next.js server components or API routes to make SDK calls:
src/
├── app/
│ ├── page.tsx # Server component - can use SDK
│ └── api/
│ └── data/
│ └── route.ts # API route - can use SDK
├── components/
│ └── MyClient.tsx # Client component - fetch from API routes
└── utils/
└── session.ts # SDK helper (server-only)
// src/app/api/clients/route.ts
import { assemblyApi } from '@assembly-js/node-sdk';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const token = searchParams.get('token');
const assembly = assemblyApi({
apiKey: process.env.ASSEMBLY_API_KEY!,
token: token ?? undefined,
});
const clients = await assembly.listClients();
return Response.json(clients);
}Fetch data from your API routes, not directly from the SDK:
'use client';
export function ClientList({ token }: { token: string }) {
const [clients, setClients] = useState([]);
useEffect(() => {
fetch(`/api/clients?token=${token}`)
.then(res => res.json())
.then(setClients);
}, [token]);
return <ul>{clients.map(c => <li key={c.id}>{c.givenName}</li>)}</ul>;
}Import components from @assembly-js/design-system:
import { Button, Heading, Body, Icon } from '@assembly-js/design-system';See the Design System section in the app for examples, or explore the full Storybook.