This monorepo contains the frontend applications and shared packages for the CELINE project.
├── packages/
│ ├── ui/ # @celine-eu/ui - Shared UI components
│ │ ├── src/
│ │ │ ├── theme.css # Design tokens & CSS variables
│ │ │ ├── Icon.svelte # Lucide-based icon component
│ │ │ ├── Button.svelte # Button variants
│ │ │ ├── Skeleton.svelte # Loading skeletons
│ │ │ ├── Panel.svelte # Slide-over panel
│ │ │ ├── Modal.svelte # Modal dialog
│ │ │ └── ThemeToggle.svelte
│ │ └── package.json
│ │
│ └── assistant-ui/ # @celine-eu/assistant-ui - AI chat components
│ ├── src/
│ │ ├── ChatCore.svelte # Main chat component
│ │ ├── AssistantWidget.svelte # Floating chat button + modal
│ │ ├── AssistantProvider.svelte # Context provider
│ │ ├── AskAssistantButton.svelte# Contextual trigger button
│ │ ├── api.ts # Configurable API client
│ │ ├── types.ts
│ │ └── internal/ # Internal components
│ │ ├── MessageList.svelte
│ │ ├── Composer.svelte
│ │ ├── ChatHeader.svelte
│ │ ├── HistoryPanel.svelte
│ │ ├── AttachmentsPanel.svelte
│ │ ├── DropOverlay.svelte
│ │ └── Markdown.svelte
│ └── package.json
│
├── apps/
│ ├── assistant/ # Standalone AI Assistant app
│ │ ├── src/routes/
│ │ │ ├── +layout.svelte
│ │ │ └── +page.svelte # Full-page chat
│ │ └── package.json
│ │
│ └── webapp/ # REC Participant Webapp
│ ├── src/
│ │ ├── lib/
│ │ │ ├── api.ts # Webapp-specific API
│ │ │ ├── stores.ts
│ │ │ └── components/
│ │ │ ├── EnergyChart.svelte
│ │ │ └── StatCard.svelte
│ │ └── routes/
│ │ ├── +layout.svelte # App shell with AssistantProvider
│ │ ├── +page.svelte # Overview with AskAssistantButtons
│ │ ├── assistant/+page.svelte # Embedded ChatCore
│ │ ├── notifications/
│ │ └── settings/
│ └── package.json
│
├── pnpm-workspace.yaml
└── package.json
# Install pnpm if needed
npm install -g pnpm
# Install all dependencies
pnpm install
# Run the assistant standalone
pnpm dev:assistant
# Run the webapp
pnpm dev:webapp
# Build all
pnpm buildShared design system with theme variables and base components.
<script>
import { Icon, Button, Skeleton, Panel, Modal, ThemeToggle } from '@celine-eu/ui';
import '@celine-eu/ui/theme.css';
</script>
<Button variant="primary" onclick={handleClick}>
<Icon name="zap" size={16} />
Click me
</Button>AI assistant chat interface that can be embedded anywhere.
<script>
import {
ChatCore,
AssistantProvider,
AssistantWidget,
AskAssistantButton
} from '@celine-eu/assistant-ui';
</script>
<!-- Option 1: Full page chat -->
<ChatCore apiBaseUrl="/api" mode="full" />
<!-- Option 2: Floating widget with provider -->
<AssistantProvider apiBaseUrl="/api">
<YourApp />
<!-- Widget auto-included by provider -->
</AssistantProvider>
<!-- Option 3: Contextual trigger buttons -->
<AskAssistantButton
context={{ page: 'dashboard', section: 'stats' }}
prompt="Explain these statistics"
/>| Mode | Description |
|---|---|
full |
Full viewport, used in standalone app |
modal |
Centered modal dialog |
floating |
Floating window (for widget) |
interface ChatCoreProps {
apiBaseUrl?: string; // API base URL, default "/api"
mode?: 'full' | 'modal' | 'floating';
embedded?: boolean; // Embedded in another app
showHeader?: boolean; // Show header bar
enableHistory?: boolean; // Enable history panel
enableAttachments?: boolean; // Enable attachments panel
enableUpload?: boolean; // Allow file uploads
enableCitations?: boolean; // Show source citations
conversationId?: string; // Load existing conversation
initialContext?: AssistantContext;
initialPrompt?: string;
onConversationChange?: (id: string | null) => void;
onError?: (error: Error) => void;
onClose?: () => void;
}When using AskAssistantButton or the widget, you can provide context:
interface AssistantContext {
page?: string; // Current page identifier
section?: string; // Specific section/component
data?: object; // Structured data to include
hint?: string; // Natural language hint for the AI
}The assistant components expect these endpoints at apiBaseUrl:
POST /chat - Chat stream (SSE)
POST /upload - File upload
GET /user - Current user info
GET /conversations - List conversations
GET /conversations/:id/messages - Get messages
DELETE /conversations/:id - Delete conversation
GET /attachments - List attachments
GET /attachments/:id/raw - Get attachment file
DELETE /attachments/:id - Delete attachment
POST /admin/ingest - Reindex (admin only)
POST /admin/reload - Reload (admin only)
The theme uses CSS custom properties. Override in your app:
:root {
--celine-primary: #0d9488;
--celine-primary-hover: #0f766e;
/* ... see theme.css for full list */
}Edit packages/ui/src/Icon.svelte and add the path to the icons object.
Use Lucide icon paths.
- Create in appropriate package (
uifor generic,assistant-uifor chat-specific) - Export from
src/index.js - Add TypeScript types if needed
The webapp proxies assistant requests through its BFF:
# webapp BFF: /api/assistant/* -> assistant backend
@router.api_route("/assistant/{path:path}", methods=["GET", "POST", "DELETE"])
async def proxy_assistant(path: str, request: Request):
return await proxy_to(f"{ASSISTANT_URL}/api/{path}", request)This allows the assistant to receive user context from the webapp.