Skip to content

Packages Overview

Cosella’s monorepo contains 13 shared packages that provide common functionality across all applications.

PackageDescriptionDependencies
@cosella/uiReact component library (25+ components)tokens
@cosella/tokensDesign tokens (CSS + JS)-
@cosella/domainZod schemas + TypeScript types-
@cosella/api-clientGenerated OpenAPI types + TanStack Query hooksdomain
@cosella/realtimeTyped WebSocket client with reconnectdomain
@cosella/authAuth provider, session storedomain
@cosella/permissionsCapability-based permission helpersdomain, auth
@cosella/testingMSW server + handlers + fixturesdomain
@cosella/observabilityError boundaries, Sentry, redactionui, domain
@cosella/app-shellAppShell layout, Sidebar, TopBarauth, tokens, ui
@cosella/formsReact Hook Form + Zod integrationui
@cosella/audio-captureAudio capture (Web + Electron)domain
@cosella/audio-engineAudio pipeline, VAD, Opus encodingdomain
import { Button, Card, Input, Alert, Modal, DataTable } from '@cosella/ui';
function MyForm() {
return (
<Card>
<Alert variant="info" title="Welcome" />
<Input placeholder="Enter email" />
<Button variant="primary">Submit</Button>
</Card>
);
}
/* In your CSS file */
@import "tailwindcss";
@import "@cosella/tokens/theme.css";
@import "@cosella/tokens/components.css";
/* Use tokens in Tailwind */
.my-component {
background-color: var(--color-brand-500);
color: var(--color-text-primary);
border-radius: var(--radius-lg);
padding: 1rem;
}
import { UserSchema, type User } from '@cosella/domain';
// Validate API responses
const user = UserSchema.parse(apiResponse);
// Use in TypeScript
function greet(user: User) {
return `Hello, ${user.name}!`;
}
import { useQuery, useMutation } from '@tanstack/react-query';
import { api } from '@cosella/api-client';
import { callKeys } from '@cosella/api-client';
// Fetch data with centralized query keys
const { data: calls } = useQuery({
queryKey: callKeys.list(filters),
queryFn: () => api.calls.list(filters),
});
// Mutate data
const createCall = useMutation({
mutationFn: (data) => api.calls.create(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: callKeys.lists() });
},
});
import { useCapability } from '@cosella/permissions';
function AdminPanel() {
const canManage = useCapability('admin:manage');
if (!canManage) return null;
return <div>Admin content</div>;
}
import { AppShell, Sidebar, TopBar } from '@cosella/app-shell';
function App() {
return (
<AppShell>
<Sidebar />
<TopBar />
<main>{/* Page content */}</main>
</AppShell>
);
}

Use the Plop generator:

Terminal window
pnpm gen package

This creates:

  • packages/<name>/package.json
  • packages/<name>/tsconfig.json
  • packages/<name>/src/index.ts
Terminal window
pnpm gen component

This creates:

  • packages/ui/src/<kebab-name>/<Name>.tsx
  • packages/ui/src/<kebab-name>/<Name>.test.tsx
  • Export added to packages/ui/src/index.ts

Hard constraints (enforced by ESLint):

  1. Apps may depend on packages — never the reverse
  2. Packages may not depend on sibling apps
  3. packages/uipackages/tokens only

Packages are published to npm as @cosella/* scoped packages:

Terminal window
# Build all packages
pnpm build
# Publish (requires npm auth)
pnpm publish --access public