Building Dashboard Components#
Warning
Project Neo is currently in Technical Preview. Features described in this section may change before general availability.
Every dashboard in your bundle is a standard React component. This page covers the component contract, available libraries, navigation, and TypeScript usage.
Component Signature#
Every dashboard component must accept a projectId prop. The host injects it automatically when rendering your dashboard.
interface Props {
projectId: string;
}
export default function Analytics({ projectId }: Props) {
return (
<div className="p-6">
<h1 className="text-xl font-semibold">Analytics</h1>
<p className="text-sm text-muted-foreground">
Showing data for project: {projectId}
</p>
</div>
);
}
projectId is the identifier of the active Squirro project. Use it to scope API calls, display project-specific data, and construct URLs.
Project and User Context#
projectId is the only prop injected by the host. Project metadata such as the title, the workspace, or your role in the project is not passed directly. Fetch it from the Squirro API using the shared @tanstack/react-query library. The identity of the signed-in user is available from a hook, described further below.
Fetching Project Metadata#
A single API call to GET /v0/projects/{projectId} returns the most commonly needed project fields:
Field |
Description |
|---|---|
|
Human-readable project name. |
|
Project description, if set. |
|
Workspace domain (used to construct API URLs). |
|
Human-readable workspace name. |
|
Role of the current user in this project (for example, |
|
List of permission strings granted to the current user for this project. |
Example using useQuery:
import { useQuery } from '@tanstack/react-query';
interface Project {
id: string;
title: string;
description?: string;
workspace?: string;
workspace_title?: string;
project_role?: string;
permissions?: string[];
}
function Analytics({ projectId }: { projectId: string }) {
const { data: project, isPending, isError } = useQuery<Project>({
queryKey: ['project', projectId],
queryFn: async () => {
const response = await fetch(`/v0/projects/${projectId}`);
if (!response.ok) throw new Error('Failed to fetch project');
return response.json();
},
});
if (isPending) return <p>Loading...</p>;
if (isError) return <p>Failed to load project.</p>;
return (
<div>
<h1>{project.title}</h1>
<p>Workspace: {project.workspace_title}</p>
<p>Your role: {project.project_role}</p>
</div>
);
}
Reading the Current User#
Call the useCurrentUser() hook from @squirro/nextgen-core/api to read the signed-in user. The hook returns null until authentication resolves, and it re-renders the component when the user changes:
import { useCurrentUser } from '@squirro/nextgen-core/api';
export default function Analytics() {
const user = useCurrentUser();
if (!user) return <p>Loading...</p>;
return (
<p>
Signed in as {user.full_name ?? user.email} ({user.role})
</p>
);
}
The hook returns the following fields:
Field |
Description |
|---|---|
|
Identifier of the user. |
|
Tenant the user belongs to. |
|
Email address of the user. |
|
Role of the user, for example |
|
List of permission strings granted by that role. |
|
Display name. Optional, because the backend omits it when it is not set. |
|
Groups the user belongs to, each with an |
The groups field is undefined when the membership is unknown, which is not the same as an empty array. An empty array means the user is known to belong to no group. Treat the unknown case as undecided rather than as an absence of membership.
Those fields are a deliberately narrow view of the user profile. For anything outside them, call the endpoint directly with the fetch escape hatch of useSquirroApi(), described on the Squirro API page. For the available user fields, see the Microservices APIs page.
Note
The hook needs a host that reports the user identity. On an older host, it raises an error naming the missing support instead of returning a user.
Restricting a Dashboard to Specific Groups#
A user group is defined once for the whole Squirro instance, not per project. An administrator creates groups in the Server space under Groups, then gives a group a role in a project under Setup → Settings → Project Members. Where single sign-on is used, membership can be mapped from the groups of the identity provider. For more information about groups, roles, and permissions, see the Squirro Roles & Permissions page.
Project roles are a separate concept. allowedGroups matches the name or the ID of a group, so a role such as Administrator, Member, or Reader in that list matches nothing and leaves the dashboard hidden from everyone.
Add the allowedGroups field to the manifest entry of a dashboard to show it only to members of specific user groups:
{
id: 'exec-summary',
title: 'Executive Summary',
icon: 'chart-line',
route: 'exec-summary',
component: () => import('./dashboards/ExecSummary'),
allowedGroups: ['Executives'],
}
Each entry matches either the name or the ID of a group. To list the groups of your instance with both values, run
neo-ui groups.The dashboard is shown to viewers who belong to at least one of the listed groups.
Omit the field, or leave the array empty, to show the dashboard to everyone.
If the group membership of the viewer cannot be determined, because the identity has not resolved yet or the host does not report it, the dashboard stays hidden.
neo-ui create dashboard offers a group picker when it creates the dashboard, and --groups sets the same field without prompting. Both are described on the CLI Reference page. The restriction can be changed at any time by editing the manifest entry.
To remove an item from the sidebar for every viewer, including a core item of the host application, use the nav field of the manifest instead. The two fields compose, so an item appears only when it passes both. For more information, see the The Bundle Manifest page.
A restricted dashboard is left out of the sidebar, and it cannot be opened by URL either. A viewer who tries is redirected to the first dashboard available to them, or to the project home page when no dashboard is available.
Warning
allowedGroups tailors the interface to the viewer. It is not a security boundary. The field removes an entry point from the sidebar and blocks a route in the browser, but it does not restrict the underlying data. Data access is enforced by the Squirro platform, so a dashboard that presents sensitive content still requires the matching project and item permissions.
TypeScript#
TypeScript is fully configured in the generated project. TypeScript type-checks dashboard components against the shared library types automatically.
To check types manually:
npx tsc --noEmit
Avoid as for type casting. Use type guards or proper type narrowing instead:
// Avoid
const item = data as SearchResult;
// Prefer
function isSearchResult(value: unknown): value is SearchResult {
return typeof value === 'object' && value !== null && 'id' in value;
}
Browser Support#
Project Neo targets the same browsers as the classic Squirro interface: the latest versions of Chrome, Edge, Firefox, and Safari. When choosing JavaScript or Web APIs for your dashboard components, you can rely on anything supported across those four browsers at their current release.
For the full client requirements, see the System Requirements page.
Runtime Environment#
Bundles run directly inside the host application’s JavaScript context via Module Federation. There is no iframe or Worker-based sandbox between bundle code and the host: dashboards share the host’s React instance, router, query cache, and origin. Plan for the implications below before writing code that crosses a trust boundary.
Browser Storage#
Bundles share the same origin as the host and have full read and write access to localStorage and sessionStorage. Use a namespaced key prefix to avoid collisions with host data or other bundles:
localStorage.setItem('my-bundle:user-preference', value);
const pref = localStorage.getItem('my-bundle:user-preference');
Warning
Because all bundles share the same origin, any code running on the page can read any key in localStorage and sessionStorage. Do not store tokens, credentials, or other sensitive data there.
External APIs#
The Squirro instance is the only origin a dashboard can reach without additional setup. To call a third-party service, route the request through a server-side proxy you control rather than calling the external API directly from the browser. There is no built-in pass-through proxy for bundle use.
Browser Permissions#
The host denies access to geolocation, microphone, and camera via the Permissions-Policy header. Bundles cannot request those browser APIs regardless of user consent.