diff --git a/Dockerfile.dev b/Dockerfile.dev
new file mode 100644
index 0000000..27e6325
--- /dev/null
+++ b/Dockerfile.dev
@@ -0,0 +1,26 @@
+FROM node:22-alpine AS builder
+RUN apk add --no-cache git
+RUN corepack enable pnpm
+
+# Copy local @kleffio/ui so the build uses the workspace source instead of the published tag
+WORKDIR /workspace/packages/ui
+COPY packages/ui/package.json ./
+COPY packages/ui/src ./src
+
+WORKDIR /workspace/plugins/components-plugin
+COPY plugins/components-plugin/package.json ./
+# Point @kleffio/ui at the local copy
+RUN node -e "\
+ const fs = require('fs');\
+ const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));\
+ pkg.devDependencies['@kleffio/ui'] = 'file:../../packages/ui';\
+ fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2));\
+"
+RUN pnpm install
+COPY plugins/components-plugin .
+RUN pnpm build
+
+FROM nginx:alpine
+COPY --from=builder /workspace/plugins/components-plugin/dist /usr/share/nginx/html
+COPY --from=builder /workspace/plugins/components-plugin/nginx.conf /etc/nginx/conf.d/default.conf
+EXPOSE 3001
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..9d6e438
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 Kleff
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/package.json b/package.json
index b8792b0..71d7cb3 100644
--- a/package.json
+++ b/package.json
@@ -27,7 +27,7 @@
},
"devDependencies": {
"@kleffio/sdk": "github:kleffio/plugin-sdk-js#v0.1.0",
- "@kleffio/ui": "github:kleffio/ui#v0.1.0",
+ "@kleffio/ui": "github:kleffio/ui#v0.1.2",
"@types/react": "^19.0.0",
"lucide-react": "^0.577.0",
"next": "^15.0.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5ed8227..7af14c0 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -12,8 +12,8 @@ importers:
specifier: github:kleffio/plugin-sdk-js#v0.1.0
version: https://codeload.github.com/kleffio/plugin-sdk-js/tar.gz/53dc62a3aa928ade5315f7105de72c455d617417(react@19.2.4)
'@kleffio/ui':
- specifier: github:kleffio/ui#v0.1.0
- version: https://codeload.github.com/kleffio/ui/tar.gz/ac5ab3ffe82630bafe7f8965f1510bbb9d629b01(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ specifier: github:kleffio/ui#v0.1.2
+ version: https://codeload.github.com/kleffio/ui/tar.gz/43590e0e08ca0fd9f1d15c0497d9b6e5ed2ab82b(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@types/react':
specifier: ^19.0.0
version: 19.2.14
@@ -412,8 +412,8 @@ packages:
peerDependencies:
react: ^18.0.0 || ^19.0.0
- '@kleffio/ui@https://codeload.github.com/kleffio/ui/tar.gz/ac5ab3ffe82630bafe7f8965f1510bbb9d629b01':
- resolution: {tarball: https://codeload.github.com/kleffio/ui/tar.gz/ac5ab3ffe82630bafe7f8965f1510bbb9d629b01}
+ '@kleffio/ui@https://codeload.github.com/kleffio/ui/tar.gz/43590e0e08ca0fd9f1d15c0497d9b6e5ed2ab82b':
+ resolution: {tarball: https://codeload.github.com/kleffio/ui/tar.gz/43590e0e08ca0fd9f1d15c0497d9b6e5ed2ab82b}
version: 0.1.0
peerDependencies:
react: ^19.0.0
@@ -2098,7 +2098,7 @@ snapshots:
dependencies:
react: 19.2.4
- '@kleffio/ui@https://codeload.github.com/kleffio/ui/tar.gz/ac5ab3ffe82630bafe7f8965f1510bbb9d629b01(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
+ '@kleffio/ui@https://codeload.github.com/kleffio/ui/tar.gz/43590e0e08ca0fd9f1d15c0497d9b6e5ed2ab82b(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies:
'@base-ui/react': 1.3.0(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
class-variance-authority: 0.7.1
diff --git a/src/ComponentsPage.tsx b/src/ComponentsPage.tsx
index 86a0e47..8e44f16 100644
--- a/src/ComponentsPage.tsx
+++ b/src/ComponentsPage.tsx
@@ -1,7 +1,6 @@
"use client";
import { useState, type ReactNode } from "react";
-import { toast } from "sonner";
import {
Area,
AreaChart,
@@ -18,7 +17,6 @@ import {
Bell,
Check,
CheckCircle2,
- ChevronRight,
Info,
OctagonX,
Server,
@@ -47,7 +45,15 @@ import { Button } from "@kleffio/ui";
import { ButtonGroup } from "@kleffio/ui";
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@kleffio/ui";
import { Checkbox } from "@kleffio/ui";
-import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@kleffio/ui";
+import {
+ Collapsible,
+ CollapsibleContent,
+ CollapsibleTrigger,
+ CollapsibleTriggerIcon,
+ FolderCollapsible,
+ FolderCollapsibleContent,
+ FolderCollapsibleTrigger,
+} from "@kleffio/ui";
import {
DropdownMenu,
DropdownMenuContent,
@@ -84,6 +90,7 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@kleffio/ui";
import { Textarea } from "@kleffio/ui";
import { Toggle } from "@kleffio/ui";
+import { toast } from "@kleffio/ui";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@kleffio/ui";
import {
ChartContainer,
@@ -180,10 +187,23 @@ const TABLE_ROWS = [
// ─── Section wrapper ──────────────────────────────────────────────────────────
-function Section({ title, children }: { title: string; children: ReactNode }) {
+function Section({
+ title,
+ description,
+ children,
+}: {
+ title: string
+ description?: ReactNode
+ children: ReactNode
+}) {
return (
- {title}
+
+
{title}
+ {description ? (
+
{description}
+ ) : null}
+
{children}
);
@@ -261,7 +281,10 @@ export function ComponentsPage() {
{/* ── Alerts ── */}
-
+
Scheduled maintenance
@@ -301,7 +324,10 @@ export function ComponentsPage() {
{/* ── Toasts ── */}
-
+
diff --git a/src/index.ts b/src/index.ts
index 509272b..748f512 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -13,7 +13,7 @@ export const componentsPlugin = definePlugin({
{
slot: "page",
component: ComponentsPage,
- props: { path: "/components" },
+ props: { path: "/p/components" },
},
{
slot: "navbar.item",