feat: improve landing page (#33)

This commit is contained in:
Carlos Florêncio
2026-01-17 23:48:23 +00:00
committed by GitHub
parent 2c5c9072ed
commit 58cd7425ed
29 changed files with 1307 additions and 270 deletions
+2 -47
View File
@@ -1,50 +1,5 @@
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@kandev/ui/card';
import Link from 'next/link';
const blogPosts = [
{
title: 'Introducing kandev.ai: AI-Powered Kanban for Developers',
description: 'Learn how kandev.ai combines Kanban boards with AI agents, isolated worktrees, and Docker containers to accelerate your development workflow.',
date: 'January 10, 2026',
slug: 'introducing-kandev',
author: 'Kandev Team',
},
{
title: 'Running Multiple AI Agents in Parallel: Best Practices',
description: 'Discover how to effectively manage multiple AI coding agents working simultaneously on different tasks using isolated environments and approval workflows.',
date: 'January 5, 2026',
slug: 'parallel-ai-agents',
author: 'Kandev Team',
},
];
import { redirect } from 'next/navigation';
export default function BlogPage() {
return (
<div className="container mx-auto max-w-6xl py-24 px-4">
<h1 className="text-4xl font-bold mb-4">Blog</h1>
<p className="text-lg text-muted-foreground mb-12">
Insights and updates from the kandev.ai team.
</p>
<div className="grid gap-6 md:grid-cols-2">
{blogPosts.map((post) => (
<Link key={post.slug} href={`/blog/${post.slug}`}>
<Card className="h-full transition-transform hover:scale-[1.02] cursor-pointer">
<CardHeader>
<div className="flex items-center gap-2 text-sm text-muted-foreground mb-2">
<span>{post.date}</span>
<span>•</span>
<span>{post.author}</span>
</div>
<CardTitle className="text-2xl">{post.title}</CardTitle>
</CardHeader>
<CardContent>
<CardDescription className="text-base">{post.description}</CardDescription>
</CardContent>
</Card>
</Link>
))}
</div>
</div>
);
redirect('/changelog');
}
@@ -0,0 +1,61 @@
import { notFound } from 'next/navigation';
import { MDXRemote } from 'next-mdx-remote/rsc';
import { getChangelogEntry, getChangelogSlugs } from '@/lib/changelog';
import { mdxComponents } from '@/components/mdx-components';
function formatDate(date: string) {
if (!date) return '';
return new Intl.DateTimeFormat('en-US', {
month: 'long',
day: 'numeric',
year: 'numeric',
}).format(new Date(date));
}
export async function generateStaticParams() {
const slugs = await getChangelogSlugs();
return slugs.map((slug) => ({ slug }));
}
export default async function ChangelogEntryPage({
params,
}: {
params: { slug?: string } | Promise<{ slug?: string }>;
}) {
const resolvedParams = await Promise.resolve(params);
const slug = resolvedParams.slug;
if (!slug) {
notFound();
}
const entry = await getChangelogEntry(slug);
if (!entry) {
notFound();
}
return (
<div className="relative overflow-hidden">
<div className="absolute inset-0 -z-10 bg-[radial-gradient(circle_at_top,_rgba(109,40,217,0.12),_transparent_55%)]" />
<div className="container mx-auto max-w-4xl px-4 pb-24 pt-24">
<div className="mb-10">
<p className="text-sm uppercase tracking-[0.3em] text-muted-foreground">{entry.surface}</p>
<h1 className="mt-4 text-4xl font-semibold text-foreground md:text-5xl">{entry.title}</h1>
<p className="mt-4 text-sm text-muted-foreground">{formatDate(entry.date)}</p>
</div>
<div className="space-y-6">
{entry.summary.map((line) => (
<p key={line} className="text-lg text-muted-foreground">
{line}
</p>
))}
</div>
<div className="mt-10 border-t border-border/60 pt-8">
<MDXRemote source={entry.content} components={mdxComponents} />
</div>
</div>
</div>
);
}
+70
View File
@@ -0,0 +1,70 @@
import Link from 'next/link';
import { getChangelogEntries } from '@/lib/changelog';
function formatDate(date: string) {
if (!date) return '';
return new Intl.DateTimeFormat('en-US', {
month: 'long',
day: 'numeric',
year: 'numeric',
}).format(new Date(date));
}
export default async function ChangelogPage() {
const entries = await getChangelogEntries();
return (
<div className="relative overflow-hidden">
<div className="absolute inset-0 -z-10 bg-[radial-gradient(circle_at_top,_rgba(109,40,217,0.12),_transparent_55%)]" />
<div className="container mx-auto max-w-6xl px-4 pb-24 pt-24">
<div className="mb-12">
<p className="text-sm uppercase tracking-[0.3em] text-muted-foreground">Changelog</p>
<h1 className="mt-4 text-4xl font-semibold text-foreground md:text-5xl">Product updates</h1>
<p className="mt-4 max-w-2xl text-lg text-muted-foreground">
A running log of kandev.ai releases, shipped features, and operational improvements.
</p>
</div>
<div className="space-y-12">
{entries.map((entry, index) => (
<article
key={entry.slug}
className="grid gap-6 border-b border-border/60 pb-12 md:grid-cols-[180px_1fr]"
>
<div className="text-sm text-muted-foreground">
<p className="font-medium text-foreground">{entry.surface}</p>
<p>{formatDate(entry.date)}</p>
{index === 0 ? (
<span className="mt-3 inline-flex items-center rounded-full border border-border bg-background px-2 py-1 text-[11px] font-semibold uppercase tracking-[0.2em] text-foreground">
Latest
</span>
) : null}
</div>
<div>
<h2 className="text-2xl font-semibold text-foreground">
<Link href={`/changelog/${entry.slug}`} className="hover:text-primary">
{entry.title}
</Link>
</h2>
<div className="mt-4 space-y-3 text-muted-foreground">
{entry.summary.map((line) => (
<p key={line}>{line}</p>
))}
</div>
<div className="mt-6">
<Link
href={`/changelog/${entry.slug}`}
className="text-sm font-semibold text-primary hover:text-primary/80"
>
Read full update →
</Link>
</div>
</div>
</article>
))}
</div>
</div>
</div>
);
}
+35
View File
@@ -0,0 +1,35 @@
import { DocsShell } from '@/components/docs-shell';
import { DocsCard } from '@/components/docs-card';
import { DocsCode } from '@/components/docs-code';
export default function AgentsDocsPage() {
return (
<DocsShell
eyebrow="Features"
title="AI Agents"
description="Agents are containerized workers that execute tasks. They communicate with the backend using ACP, a JSON-RPC protocol over stdin/stdout."
>
<section className="grid gap-4 md:grid-cols-2">
<DocsCard title="Agent lifecycle">
<ol className="space-y-2 list-decimal list-inside">
<li>Container starts with agentctl on port 9999.</li>
<li>Backend calls <code>initialize</code> and <code>session/new</code>.</li>
<li>Tasks are sent via <code>session/prompt</code>.</li>
<li>Agent streams <code>session/update</code> notifications.</li>
</ol>
</DocsCard>
<DocsCard title="What agents can do" variant="accent">
<ul className="space-y-2">
<li>Read and edit files inside the worktree</li>
<li>Run shell commands with approval gates</li>
<li>Stream progress updates to the UI</li>
</ul>
</DocsCard>
</section>
<DocsCard title="ACP example" variant="muted">
<DocsCode>{`{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"1.0"}}`}</DocsCode>
</DocsCard>
</DocsShell>
);
}
+51
View File
@@ -0,0 +1,51 @@
import { DocsShell } from '@/components/docs-shell';
import { DocsCard } from '@/components/docs-card';
import { DocsCode } from '@/components/docs-code';
const stages = [
{ title: 'Backlog', desc: 'Collect ideas and future work.' },
{ title: 'In Progress', desc: 'Active tasks owned by agents.' },
{ title: 'Review', desc: 'Approvals and QA before merge.' },
{ title: 'Done', desc: 'Completed and shipped items.' },
];
export default function BoardsDocsPage() {
return (
<DocsShell
eyebrow="Core Concepts"
title="Boards"
description="Boards are the Kanban surface for your workspace. Each board defines columns that represent the lifecycle of a task, from backlog to review to done."
>
<section className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
{stages.map((stage) => (
<DocsCard key={stage.title} title={stage.title}>
<p>{stage.desc}</p>
</DocsCard>
))}
</section>
<DocsCard title="Example board config" variant="muted">
<p>Keep columns minimal and apply WIP limits where review capacity is tight.</p>
<DocsCode>{`board:
name: "Product Roadmap"
columns:
- name: "Backlog"
wipLimit: null
- name: "In Progress"
wipLimit: 4
- name: "Review"
wipLimit: 2
- name: "Done"
wipLimit: null`}</DocsCode>
</DocsCard>
<DocsCard title="Tips" variant="accent">
<ul className="space-y-2">
<li>Use a single “Review” column so approvals are centralized.</li>
<li>Keep WIP limits low to prevent agent overload.</li>
<li>Archive finished tasks weekly to keep focus on active work.</li>
</ul>
</DocsCard>
</DocsShell>
);
}
+36
View File
@@ -0,0 +1,36 @@
import { DocsShell } from '@/components/docs-shell';
import { DocsCard } from '@/components/docs-card';
import { DocsCode } from '@/components/docs-code';
export default function DockerDocsPage() {
return (
<DocsShell
eyebrow="Features"
title="Docker Execution"
description="Every agent runs inside a Docker container to keep execution isolated from your host machine. Containers are created per task and destroyed after completion."
>
<section className="grid gap-4 md:grid-cols-2">
<DocsCard title="What is mounted">
<ul className="space-y-2">
<li><code>/workspace</code> — your repository worktree</li>
<li><code>/root/.augment/sessions</code> — agent session storage (when enabled)</li>
</ul>
</DocsCard>
<DocsCard title="Why containers" variant="accent">
<ol className="space-y-2 list-decimal list-inside">
<li>Consistent, reproducible environments</li>
<li>Security boundaries for file and network access</li>
<li>Easy cleanup after task completion</li>
</ol>
</DocsCard>
</section>
<DocsCard title="Sample run (conceptual)" variant="muted">
<DocsCode>{`docker run -it --rm \
-v /path/to/repo:/workspace \
-e TASK_DESCRIPTION="Fix the login bug" \
kandev/augment-agent:latest`}</DocsCode>
</DocsCard>
</DocsShell>
);
}
@@ -0,0 +1,42 @@
import { DocsShell } from '@/components/docs-shell';
import { DocsCard } from '@/components/docs-card';
import { DocsCode } from '@/components/docs-code';
export default function InstallationDocsPage() {
return (
<DocsShell
eyebrow="Getting Started"
title="Installation"
description="These steps outline a typical local installation. Exact commands may change as we finalize the installer, but the flow remains the same."
>
<section className="grid gap-4 md:grid-cols-2">
<DocsCard title="Prerequisites" variant="accent">
<ul className="space-y-2">
<li>Docker Desktop (or Docker Engine)</li>
<li>Git 2.30+</li>
<li>Node.js 20+</li>
</ul>
</DocsCard>
<DocsCard title="Install the repo">
<DocsCode>{`git clone https://github.com/kdlbs/kandev.git
cd kandev
pnpm install`}</DocsCode>
</DocsCard>
</section>
<DocsCard title="Run the services" variant="muted">
<p>Start the backend, app, and landing site in separate terminals.</p>
<DocsCode>{`pnpm --filter @kandev/backend dev
pnpm --filter @kandev/web dev
pnpm --filter @kandev/landing dev`}</DocsCode>
</DocsCard>
<DocsCard title="Verify">
<p>
Open the UI and create a test workspace. The system should start an agent container on demand and stream
progress back over WebSocket.
</p>
</DocsCard>
</DocsShell>
);
}
+5 -3
View File
@@ -2,9 +2,11 @@ import { DocsSidebar } from '@/components/docs-sidebar';
export default function DocsLayout({ children }: { children: React.ReactNode }) {
return (
<div className="flex min-h-screen pt-16 justify-center">
<DocsSidebar />
<main className="flex-1 max-w-4xl py-8 px-6">{children}</main>
<div className="min-h-screen bg-[radial-gradient(circle_at_top,_rgba(109,40,217,0.12),_transparent_55%)]">
<div className="mx-auto flex w-full max-w-6xl gap-8 px-6">
<DocsSidebar />
<main className="flex-1 py-16">{children}</main>
</div>
</div>
);
}
+45 -143
View File
@@ -1,149 +1,51 @@
import { DocsShell } from '@/components/docs-shell';
import { DocsCard } from '@/components/docs-card';
import { DocsCode } from '@/components/docs-code';
export default function DocsPage() {
return (
<div className="prose prose-slate dark:prose-invert max-w-none">
<div className="not-prose mb-8">
<h1 className="text-4xl font-bold mb-4">Getting Started with kandev.ai</h1>
<p className="text-xl text-muted-foreground">
kandev.ai combines Kanban task management with AI-powered development workflows. Manage tasks visually,
execute them with AI agents in isolated environments, and ship faster with confidence.
</p>
</div>
<DocsShell
eyebrow="Getting Started"
title="Documentation"
description="Learn how kandev.ai orchestrates AI agents across isolated worktrees, Docker containers, and a WebSocket-first control plane."
>
<section className="grid gap-4 md:grid-cols-2">
<DocsCard title="What is kandev.ai?" variant="accent">
<p>
kandev.ai is a WebSocket-first platform that pairs Kanban task management with AI-assisted execution.
Every task runs inside a dedicated git worktree and a Docker container, with approvals for sensitive
operations.
</p>
</DocsCard>
<DocsCard title="Why teams use it">
<ul className="space-y-2">
<li>Ship in parallel without branch conflicts.</li>
<li>Keep execution auditable and reviewable.</li>
<li>Stream progress updates in real time.</li>
</ul>
</DocsCard>
</section>
<div className="not-prose mb-8 p-6 bg-muted/50 rounded-lg border border-border">
<h2 className="text-2xl font-bold mb-3">What is kandev.ai?</h2>
<p className="text-muted-foreground">
kandev.ai is a development tool that bridges project management and AI-assisted coding. Each task on your
Kanban board can be executed by AI agents working in isolated git worktrees and Docker containers.
</p>
</div>
<DocsCard title="Core workflow" variant="muted">
<p>From task creation to approval, kandev.ai follows a consistent loop.</p>
<DocsCode>{`1. Create task on the board
2. Start agent container via agentctl
3. Initialize ACP session
4. Stream progress over WebSocket
5. Review and approve output`}</DocsCode>
</DocsCard>
<h2 className="text-2xl font-bold mt-8 mb-4">Key Features</h2>
<div className="grid gap-4 not-prose mb-8">
<div className="p-4 border border-border rounded-lg">
<h3 className="font-semibold mb-2">Visual Task Management</h3>
<p className="text-sm text-muted-foreground">Organize development work with Kanban boards</p>
</div>
<div className="p-4 border border-border rounded-lg">
<h3 className="font-semibold mb-2">Isolated Worktrees</h3>
<p className="text-sm text-muted-foreground">Each task gets its own git worktree for parallel development</p>
</div>
<div className="p-4 border border-border rounded-lg">
<h3 className="font-semibold mb-2">Local Docker Execution</h3>
<p className="text-sm text-muted-foreground">AI agents run in secure Docker containers on your machine</p>
</div>
<div className="p-4 border border-border rounded-lg">
<h3 className="font-semibold mb-2">Multiple AI Agents</h3>
<p className="text-sm text-muted-foreground">Support for Claude Code, OpenAI Codex, Augment, and more</p>
</div>
<div className="p-4 border border-border rounded-lg">
<h3 className="font-semibold mb-2">Approval Workflows</h3>
<p className="text-sm text-muted-foreground">Review and approve agent changes before merging</p>
</div>
<div className="p-4 border border-border rounded-lg">
<h3 className="font-semibold mb-2">Multiple Workspaces</h3>
<p className="text-sm text-muted-foreground">Organize projects by client, team, or product</p>
</div>
</div>
<h2 className="text-2xl font-bold mt-8 mb-4">How It Works</h2>
<div className="not-prose space-y-4 mb-8">
<div className="flex gap-4">
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center font-bold">1</div>
<div>
<h3 className="font-semibold mb-1">Create a Task</h3>
<p className="text-sm text-muted-foreground">Add a task to your Kanban board with a description of what needs to be done</p>
</div>
</div>
<div className="flex gap-4">
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center font-bold">2</div>
<div>
<h3 className="font-semibold mb-1">Configure Repository</h3>
<p className="text-sm text-muted-foreground">Select a repository and base branch for the task</p>
</div>
</div>
<div className="flex gap-4">
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center font-bold">3</div>
<div>
<h3 className="font-semibold mb-1">Choose AI Agent</h3>
<p className="text-sm text-muted-foreground">Select which AI agent should work on the task</p>
</div>
</div>
<div className="flex gap-4">
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center font-bold">4</div>
<div>
<h3 className="font-semibold mb-1">Isolated Environment</h3>
<p className="text-sm text-muted-foreground">kandev creates an isolated git worktree and Docker container</p>
</div>
</div>
<div className="flex gap-4">
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center font-bold">5</div>
<div>
<h3 className="font-semibold mb-1">AI Execution</h3>
<p className="text-sm text-muted-foreground">The AI agent executes the task in the secure environment</p>
</div>
</div>
<div className="flex gap-4">
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center font-bold">6</div>
<div>
<h3 className="font-semibold mb-1">Review & Approve</h3>
<p className="text-sm text-muted-foreground">Review the changes and approve them for merging</p>
</div>
</div>
</div>
<div className="not-prose mb-8 p-6 bg-primary/10 rounded-lg border border-primary/20">
<h2 className="text-2xl font-bold mb-3">Why kandev.ai?</h2>
<p className="text-muted-foreground mb-4">
Traditional development workflows require constant context switching. kandev.ai eliminates this by:
</p>
<ul className="space-y-2">
<li className="flex items-start gap-2">
<span className="text-primary">✓</span>
<span className="text-sm">Visualizing all work in progress on a single board</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary">✓</span>
<span className="text-sm">Enabling parallel development without branch conflicts</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary">✓</span>
<span className="text-sm">Automating routine tasks with AI agents</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary">✓</span>
<span className="text-sm">Maintaining security through isolated execution environments</span>
</li>
</ul>
</div>
<div className="not-prose mb-8 p-6 bg-accent/10 rounded-lg border border-accent/20">
<h2 className="text-2xl font-bold mb-3">Security & Control</h2>
<p className="text-muted-foreground">
Every operation performed by AI agents is logged and requires approval. Agents run in isolated Docker
containers with restricted permissions, ensuring your codebase and system remain secure.
</p>
</div>
<div className="not-prose mt-12 p-8 bg-gradient-to-br from-primary/10 to-accent/10 rounded-lg border border-border text-center">
<h2 className="text-2xl font-bold mb-4">Ready to Get Started?</h2>
<p className="text-muted-foreground mb-6">
Check out our guides to install and configure kandev.ai
</p>
<div className="flex gap-4 justify-center">
<a
href="/docs/installation"
className="inline-flex items-center justify-center px-6 py-3 rounded-md bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors"
>
Installation Guide
</a>
<a
href="/docs/quick-start"
className="inline-flex items-center justify-center px-6 py-3 rounded-md border border-border bg-background hover:bg-muted font-medium transition-colors"
>
Quick Start Tutorial
</a>
</div>
</div>
</div>
<section className="grid gap-4 md:grid-cols-3">
<DocsCard title="Workspaces">
<p>Group repositories, boards, and team settings.</p>
</DocsCard>
<DocsCard title="Boards" variant="accent">
<p>Model your workflow with Kanban columns.</p>
</DocsCard>
<DocsCard title="Tasks">
<p>Define the scope, constraints, and agent requirements.</p>
</DocsCard>
</section>
</DocsShell>
);
}
@@ -0,0 +1,46 @@
import { DocsShell } from '@/components/docs-shell';
import { DocsCard } from '@/components/docs-card';
import { DocsCode } from '@/components/docs-code';
const steps = [
{
step: '1. Create a workspace',
body: 'Create a workspace for the repository you want to manage.',
},
{
step: '2. Add a board and task',
body: 'Add a board with columns, then create a task that describes the desired change.',
},
{
step: '3. Run an agent',
body: 'Start an agent from the task. The UI should stream progress updates as the agent works.',
},
{
step: '4. Review and merge',
body: 'Review the diff, approve any gated actions, and merge the worktree.',
},
];
export default function QuickStartDocsPage() {
return (
<DocsShell
eyebrow="Getting Started"
title="Quick Start"
description="This guide walks through a minimal workflow so you can see the agent loop end-to-end."
>
<section className="grid gap-4 md:grid-cols-2">
{steps.map((item) => (
<DocsCard key={item.step} title={item.step}>
<p>{item.body}</p>
</DocsCard>
))}
</section>
<DocsCard title="Example task prompt" variant="muted">
<DocsCode>{`Task: Update onboarding copy
Constraints: Touch only apps/landing
Acceptance: Copy updated and passes lint`}</DocsCode>
</DocsCard>
</DocsShell>
);
}
+42
View File
@@ -0,0 +1,42 @@
import { DocsShell } from '@/components/docs-shell';
import { DocsCard } from '@/components/docs-card';
import { DocsCode } from '@/components/docs-code';
export default function TasksDocsPage() {
return (
<DocsShell
eyebrow="Core Concepts"
title="Tasks"
description="Tasks capture the work that agents will execute. A good task includes a goal, constraints, and the desired output so the agent can plan accurately."
>
<section className="grid gap-4 md:grid-cols-2">
<DocsCard title="Recommended fields">
<ul className="space-y-2">
<li>Title and description</li>
<li>Priority and due date</li>
<li>Repository and base branch</li>
<li>Agent type and environment</li>
<li>Approval requirements</li>
</ul>
</DocsCard>
<DocsCard title="Writing effective tasks" variant="accent">
<ol className="space-y-2 list-decimal list-inside">
<li>State the outcome, not the steps.</li>
<li>Call out sensitive files or commands.</li>
<li>Include acceptance criteria.</li>
</ol>
</DocsCard>
</section>
<DocsCard title="Example task" variant="muted">
<DocsCode>{`Title: Add changelog page
Repo: github.com/kdlbs/kandev
Branch: main
Agent: augment-agent
Goal: Replace blog with changelog
Constraints: Keep existing navbar/footer
Output: New route + MDX entries`}</DocsCode>
</DocsCard>
</DocsShell>
);
}
+42
View File
@@ -0,0 +1,42 @@
import { DocsShell } from '@/components/docs-shell';
import { DocsCard } from '@/components/docs-card';
import { DocsCode } from '@/components/docs-code';
export default function WorkspacesDocsPage() {
return (
<DocsShell
eyebrow="Core Concepts"
title="Workspaces"
description="Workspaces are the top-level container in kandev.ai. They group repositories, boards, agent settings, and members so teams can ship without stepping on each other."
>
<section className="grid gap-4 md:grid-cols-2">
<DocsCard title="What a workspace includes">
<ul className="space-y-2">
<li>Boards that define workflow stages</li>
<li>Repositories connected to those boards</li>
<li>Default agent settings and approvals</li>
<li>Member roles and permissions</li>
</ul>
</DocsCard>
<DocsCard title="Best practices" variant="accent">
<ol className="space-y-2 list-decimal list-inside">
<li>Use one workspace per product or client.</li>
<li>Keep board naming consistent across teams.</li>
<li>Set approvals at the workspace level.</li>
</ol>
</DocsCard>
</section>
<DocsCard title="Example structure" variant="muted">
<p>A workspace keeps everything organized in one place.</p>
<DocsCode>{`Workspace: "Core Platform"
Boards:
- Product Roadmap
- Incident Response
Repositories:
- github.com/kdlbs/kandev
- github.com/kdlbs/kandev-docs`}</DocsCode>
</DocsCard>
</DocsShell>
);
}
+40
View File
@@ -0,0 +1,40 @@
import { DocsShell } from '@/components/docs-shell';
import { DocsCard } from '@/components/docs-card';
import { DocsCode } from '@/components/docs-code';
const benefits = [
{ title: 'Parallel tasks', desc: 'Multiple agents can work without branch collisions.' },
{ title: 'Clean diffs', desc: 'Each task produces an isolated patch.' },
{ title: 'Fast setup', desc: 'No extra clones required.' },
];
export default function WorktreesDocsPage() {
return (
<DocsShell
eyebrow="Features"
title="Git Worktrees"
description="kandev.ai uses git worktrees to isolate each agent run. Every task gets its own directory that shares the same repository history while keeping file changes separate."
>
<section className="grid gap-4 md:grid-cols-3">
{benefits.map((item) => (
<DocsCard key={item.title} title={item.title}>
<p>{item.desc}</p>
</DocsCard>
))}
</section>
<DocsCard title="How it looks on disk" variant="muted">
<DocsCode>{`/repos/kandev
/main (primary checkout)
/.worktrees/task-123
/.worktrees/task-124`}</DocsCode>
</DocsCard>
<DocsCard title="Cleanup" variant="accent">
<p>
When a task is completed and merged, the worktree can be safely removed without affecting the main checkout.
</p>
</DocsCard>
</DocsShell>
);
}
@@ -0,0 +1,28 @@
import type { HTMLAttributes } from 'react';
type ChangelogVideoProps = {
src: string;
poster?: string;
caption?: string;
} & HTMLAttributes<HTMLVideoElement>;
export function ChangelogVideo({ src, poster, caption, className, ...props }: ChangelogVideoProps) {
return (
<figure className="mt-6">
<video
className={`w-full rounded-2xl border border-border bg-muted/40 ${className ?? ''}`}
src={src}
poster={poster}
autoPlay
loop
muted
playsInline
preload="metadata"
{...props}
/>
{caption ? (
<figcaption className="mt-2 text-sm text-muted-foreground">{caption}</figcaption>
) : null}
</figure>
);
}
+26
View File
@@ -0,0 +1,26 @@
import type { ReactNode } from 'react';
export function DocsCard({
title,
children,
variant = 'default',
}: {
title: string;
children: ReactNode;
variant?: 'default' | 'accent' | 'muted';
}) {
const base =
'rounded-2xl border border-border/60 bg-card/50 p-6 shadow-[0_12px_40px_-28px_rgba(37,99,235,0.5)] backdrop-blur';
const variants: Record<typeof variant, string> = {
default: 'bg-card/50',
accent: 'border-primary/30 bg-primary/10',
muted: 'bg-muted/30',
};
return (
<div className={`${base} ${variants[variant]}`}>
<h2 className="text-lg font-semibold text-foreground">{title}</h2>
<div className="mt-3 text-sm text-muted-foreground">{children}</div>
</div>
);
}
+9
View File
@@ -0,0 +1,9 @@
import type { ReactNode } from 'react';
export function DocsCode({ children }: { children: ReactNode }) {
return (
<pre className="mt-4 rounded-xl border border-primary/30 bg-background/80 p-4 text-sm text-foreground shadow-[0_16px_30px_-24px_rgba(59,130,246,0.6)]">
<code>{children}</code>
</pre>
);
}
+25
View File
@@ -0,0 +1,25 @@
export function DocsShell({
eyebrow,
title,
description,
children,
}: {
eyebrow: string;
title: string;
description: string;
children: React.ReactNode;
}) {
return (
<div className="relative overflow-hidden">
<div className="absolute inset-0 -z-10 " />
<div className="space-y-10">
<header className="space-y-3">
<p className="text-sm uppercase tracking-[0.3em] text-muted-foreground">{eyebrow}</p>
<h1 className="text-4xl font-semibold text-foreground">{title}</h1>
<p className="text-lg text-muted-foreground">{description}</p>
</header>
{children}
</div>
</div>
);
}
+1 -22
View File
@@ -29,34 +29,13 @@ const sections = [
{ title: 'Docker Execution', href: '/docs/docker' },
],
},
{
title: 'Integrations',
items: [
{ title: 'MCP Servers', href: '/docs/mcp' },
{ title: 'GitHub', href: '/docs/github' },
],
},
{
title: 'Security',
items: [
{ title: 'Approval Workflows', href: '/docs/approvals' },
{ title: 'Audit Logs', href: '/docs/audit-logs' },
],
},
{
title: 'Advanced',
items: [
{ title: 'Configuration', href: '/docs/configuration' },
{ title: 'CLI Reference', href: '/docs/cli' },
],
},
];
export function DocsSidebar() {
const pathname = usePathname();
return (
<aside className="sticky top-14 h-[calc(100vh-3.5rem)] w-64 shrink-0 overflow-y-auto border-r border-border py-8 pr-6">
<aside className="sticky top-22 h-[calc(100vh-3.5rem)] w-64 shrink-0 overflow-y-auto border-r border-border py-8 pr-6">
<nav className="space-y-6">
{sections.map((section) => (
<div key={section.title}>
+2 -2
View File
@@ -36,8 +36,8 @@ export function Footer() {
</Link>
</li>
<li>
<Link href="/blog" className="text-muted-foreground hover:text-foreground">
Blog
<Link href="/changelog" className="text-muted-foreground hover:text-foreground">
Changelog
</Link>
</li>
</ul>
+39 -47
View File
@@ -16,56 +16,48 @@ export function HeroSection() {
return (
<section className="relative overflow-hidden">
{/* Animated gradient cloud */}
<div className="absolute inset-0 -z-10 flex items-center justify-center">
<div
className="absolute w-[800px] h-[800px] rounded-full filter blur-3xl opacity-60 animate-pulse-slow"
style={{
background: 'radial-gradient(circle, rgba(133, 110, 232, 0.3) 0%, rgba(177, 140, 254, 0.15) 40%, transparent 70%)'
}}
/>
</div>
<div className="container mx-auto max-w-6xl flex flex-col items-center gap-8 px-4 pt-32 pb-16 md:pt-40 md:pb-24">
<Badge variant="secondary" className="cursor-pointer border border-border px-6 py-3">
<span className="text-sm">kandev.ai – AI-powered Kanban for developers</span>
</Badge>
<h1 className="max-w-4xl text-center text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl lg:text-7xl">
Kanban meets <span className="text-primary">AI development</span>
</h1>
<p className="max-w-2xl text-center text-lg text-muted-foreground md:text-xl">
Manage development tasks with isolated git worktrees, secure Docker execution, and AI agents.
Ship faster without breaking your workflow.
</p>
<div className="flex flex-col items-center gap-4 sm:flex-row">
<Button size="lg" asChild className="cursor-pointer">
<a href="#features">Get Started</a>
</Button>
<Button size="lg" variant="outline" asChild className="cursor-pointer">
<a href="#demo">Watch Demo</a>
</Button>
</div>
<div className="mt-8 w-full max-w-2xl">
<div className="flex items-center justify-center gap-2 rounded-lg border border-border bg-card p-4">
<code className="flex-1 text-sm font-mono text-foreground">npx kandev</code>
<Button
size="icon"
variant="ghost"
onClick={copyCommand}
className="cursor-pointer"
>
{copied ? (
<IconCheck className="h-4 w-4 text-green-500" />
) : (
<IconCopy className="h-4 w-4" />
)}
<div className="absolute inset-0 -z-10 bg-[radial-gradient(circle_at_top,_rgba(109,40,217,0.12),_transparent_55%)]" />
<div className="container mx-auto max-w-6xl flex flex-col items-center gap-8 px-4 pt-16 pb-16 md:pb-24">
<Badge variant="secondary" className="cursor-pointer border border-border px-6 py-3">
<span className="text-sm">kandev.ai – AI-powered Kanban for developers</span>
</Badge>
<h1 className="max-w-4xl text-center text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl lg:text-7xl">
Kanban meets <span className="text-primary">AI development</span>
</h1>
<p className="max-w-2xl text-center text-lg text-muted-foreground md:text-xl">
Manage development tasks with isolated git worktrees, secure Docker execution, and AI agents.
Ship faster without breaking your workflow.
</p>
<div className="flex flex-col items-center gap-4 sm:flex-row">
<Button size="lg" asChild className="cursor-pointer">
<a href="#features">Get Started</a>
</Button>
<Button size="lg" variant="outline" asChild className="cursor-pointer">
<a href="#demo">Watch Demo</a>
</Button>
</div>
</div>
<div className="mt-8 w-full max-w-5xl">
<div className="aspect-video rounded-lg border border-border bg-muted flex items-center justify-center">
<p className="text-muted-foreground">Video placeholder</p>
<div className="mt-8 w-full max-w-2xl">
<div className="flex items-center justify-center gap-2 rounded-lg border border-border bg-card p-4">
<code className="flex-1 text-sm font-mono text-foreground">npx kandev</code>
<Button
size="icon"
variant="ghost"
onClick={copyCommand}
className="cursor-pointer"
>
{copied ? (
<IconCheck className="h-4 w-4 text-green-500" />
) : (
<IconCopy className="h-4 w-4" />
)}
</Button>
</div>
</div>
<div className="mt-8 w-full max-w-5xl">
<div className="aspect-video rounded-lg border border-border bg-muted flex items-center justify-center">
<p className="text-muted-foreground">Video placeholder</p>
</div>
</div>
</div>
</div>
</section>
);
@@ -0,0 +1,44 @@
import type { ComponentProps, ReactElement } from 'react';
import { ChangelogVideo } from '@/components/changelog-video';
function MdxHeading({ className, ...props }: ComponentProps<'h2'>) {
return <h2 className={`mt-10 text-2xl font-semibold text-foreground ${className ?? ''}`} {...props} />;
}
function MdxSubheading({ className, ...props }: ComponentProps<'h3'>) {
return <h3 className={`mt-8 text-xl font-semibold text-foreground ${className ?? ''}`} {...props} />;
}
function MdxParagraph({ className, ...props }: ComponentProps<'p'>) {
return <p className={`mt-4 text-base leading-relaxed text-muted-foreground ${className ?? ''}`} {...props} />;
}
function MdxList({ className, ...props }: ComponentProps<'ul'>) {
return <ul className={`mt-4 space-y-2 pl-6 text-muted-foreground ${className ?? ''}`} {...props} />;
}
function MdxListItem({ className, ...props }: ComponentProps<'li'>) {
return <li className={`list-disc text-base ${className ?? ''}`} {...props} />;
}
function MdxImage({ className, alt, ...props }: ComponentProps<'img'>): ReactElement {
return (
<img
className={`mt-6 w-full rounded-2xl border border-border bg-muted/40 ${className ?? ''}`}
alt={alt ?? ''}
loading="lazy"
decoding="async"
{...props}
/>
);
}
export const mdxComponents = {
h2: MdxHeading,
h3: MdxSubheading,
p: MdxParagraph,
ul: MdxList,
li: MdxListItem,
img: MdxImage,
ChangelogVideo,
};
+3 -3
View File
@@ -37,13 +37,13 @@ export function Navbar() {
Documentation
</Link>
<Link
href="/blog"
href="/changelog"
className={cn(
'text-sm font-medium transition-colors hover:text-foreground cursor-pointer',
pathname?.startsWith('/blog') ? 'text-foreground' : 'text-muted-foreground'
pathname?.startsWith('/changelog') ? 'text-foreground' : 'text-muted-foreground'
)}
>
Blog
Changelog
</Link>
</nav>
@@ -0,0 +1,37 @@
---
title: "kandev.ai Launch"
date: "2026-01-17"
surface: "Platform"
summary:
- "kandev.ai ships a WebSocket-first Kanban + AI agent workflow for developer teams."
- "Tasks run inside isolated git worktrees and Docker containers with approval gates."
---
## What is kandev.ai?
kandev.ai is a Kanban-native development platform that pairs task management with AI agents. Every task can be executed by an agent in a clean, isolated environment, while you keep control over approvals and merge decisions.
![kandev launch overview](/changelog/2026-01-17-launch/launch-hero.svg)
## Initial launch features
- **Kanban boards for engineering work** with task metadata, priorities, and agent selection.
- **Isolated git worktrees** so parallel tasks never collide.
- **Docker-based execution** for secure, repeatable runs.
- **Agent control plane** via `agentctl` with start/stop/status and ACP relays.
- **WebSocket-only client API** for real-time orchestration and updates.
- **Approval gates** for sensitive paths and commands.
## How it works (high level)
1. The client opens a single WebSocket connection to the backend.
2. The backend spins up an agent container with `agentctl` as a sidecar.
3. The backend initializes ACP over stdin/stdout and creates a session.
4. The task prompt is streamed to the agent and progress events flow back in real time.
5. Results are reviewed, approved, and merged back into the main branch.
![High-level flow](/changelog/2026-01-17-launch/high-level-flow.svg)
### What’s next
Expect expanded agent types, richer approvals, and deeper task analytics in upcoming releases.
+71
View File
@@ -0,0 +1,71 @@
import fs from 'node:fs/promises';
import path from 'node:path';
import matter from 'gray-matter';
export type ChangelogEntry = {
slug: string;
title: string;
date: string;
surface: string;
summary: string[];
content: string;
};
const changelogRoot = path.join(process.cwd(), 'content', 'changelog');
function normalizeSummary(summary: unknown): string[] {
if (Array.isArray(summary)) {
return summary.filter((item): item is string => typeof item === 'string');
}
if (typeof summary === 'string') {
return [summary];
}
return [];
}
function parseEntry(slug: string, fileContent: string): ChangelogEntry {
const { data, content } = matter(fileContent);
return {
slug,
title: String(data.title ?? slug),
date: String(data.date ?? ''),
surface: String(data.surface ?? 'Product'),
summary: normalizeSummary(data.summary),
content,
};
}
export async function getChangelogEntries(): Promise<ChangelogEntry[]> {
const entries = await fs.readdir(changelogRoot, { withFileTypes: true });
const slugs = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
const items = await Promise.all(
slugs.map(async (slug) => {
const entryPath = path.join(changelogRoot, slug, 'index.mdx');
const fileContent = await fs.readFile(entryPath, 'utf8');
return parseEntry(slug, fileContent);
})
);
return items.sort((a, b) => {
const aTime = new Date(a.date).getTime();
const bTime = new Date(b.date).getTime();
return bTime - aTime;
});
}
export async function getChangelogEntry(slug: string): Promise<ChangelogEntry | null> {
const entryPath = path.join(changelogRoot, slug, 'index.mdx');
try {
const fileContent = await fs.readFile(entryPath, 'utf8');
return parseEntry(slug, fileContent);
} catch {
return null;
}
}
export async function getChangelogSlugs(): Promise<string[]> {
const entries = await fs.readdir(changelogRoot, { withFileTypes: true });
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
}
+1 -1
View File
@@ -1,6 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts";
import "./.next/dev/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
+2
View File
@@ -15,8 +15,10 @@
"clsx": "^2.1.1",
"next": "16.1.1",
"next-themes": "^0.4.6",
"next-mdx-remote": "^5.0.0",
"react": "19.2.3",
"react-dom": "19.2.3",
"gray-matter": "^4.0.3",
"shadcn": "^3.6.3",
"tailwind-merge": "^2.6.0",
"tw-animate-css": "^1.4.0"
@@ -0,0 +1,18 @@
<svg width="1200" height="640" viewBox="0 0 1200 640" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="1200" height="640" rx="32" fill="#0B1220"/>
<rect x="80" y="120" width="240" height="120" rx="20" fill="#111827" stroke="#1F2937" stroke-width="2"/>
<rect x="360" y="120" width="240" height="120" rx="20" fill="#111827" stroke="#1F2937" stroke-width="2"/>
<rect x="640" y="120" width="240" height="120" rx="20" fill="#111827" stroke="#1F2937" stroke-width="2"/>
<rect x="920" y="120" width="200" height="120" rx="20" fill="#111827" stroke="#1F2937" stroke-width="2"/>
<path d="M320 180H360" stroke="#38BDF8" stroke-width="6" stroke-linecap="round"/>
<path d="M600 180H640" stroke="#38BDF8" stroke-width="6" stroke-linecap="round"/>
<path d="M880 180H920" stroke="#38BDF8" stroke-width="6" stroke-linecap="round"/>
<text x="110" y="190" fill="#E2E8F0" font-family="Figtree, sans-serif" font-size="16">Client WS</text>
<text x="390" y="190" fill="#E2E8F0" font-family="Figtree, sans-serif" font-size="16">Backend</text>
<text x="670" y="190" fill="#E2E8F0" font-family="Figtree, sans-serif" font-size="16">agentctl</text>
<text x="950" y="190" fill="#E2E8F0" font-family="Figtree, sans-serif" font-size="16">Agent</text>
<rect x="80" y="300" width="1040" height="200" rx="24" fill="#0F172A" stroke="#1E293B" stroke-width="2"/>
<text x="120" y="360" fill="#94A3B8" font-family="Figtree, sans-serif" font-size="16">orchestrator.start → /api/v1/start → ACP initialize/session/prompt → session/update</text>
<text x="120" y="400" fill="#94A3B8" font-family="Figtree, sans-serif" font-size="16">Real-time progress streamed back over WebSocket</text>
<text x="96" y="96" fill="#E2E8F0" font-family="Figtree, sans-serif" font-size="24" font-weight="600">High-level execution flow</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,14 @@
<svg width="1200" height="640" viewBox="0 0 1200 640" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="1200" height="640" rx="32" fill="#0B1120"/>
<rect x="64" y="72" width="1072" height="496" rx="28" fill="#111827" stroke="#1F2937" stroke-width="2"/>
<rect x="104" y="120" width="320" height="120" rx="20" fill="#0F172A" stroke="#1F2937" stroke-width="2"/>
<rect x="448" y="120" width="320" height="120" rx="20" fill="#0F172A" stroke="#1F2937" stroke-width="2"/>
<rect x="792" y="120" width="320" height="120" rx="20" fill="#0F172A" stroke="#1F2937" stroke-width="2"/>
<rect x="104" y="272" width="640" height="44" rx="14" fill="#1E293B"/>
<rect x="104" y="332" width="560" height="44" rx="14" fill="#1E293B"/>
<rect x="104" y="392" width="480" height="44" rx="14" fill="#1E293B"/>
<circle cx="980" cy="364" r="82" fill="#0F172A" stroke="#38BDF8" stroke-width="3"/>
<path d="M940 364L968 392L1024 336" stroke="#38BDF8" stroke-width="10" stroke-linecap="round" stroke-linejoin="round"/>
<text x="104" y="112" fill="#E2E8F0" font-family="Figtree, sans-serif" font-size="24" font-weight="600">kandev.ai Launch</text>
<text x="104" y="500" fill="#94A3B8" font-family="Figtree, sans-serif" font-size="16">Kanban + AI agents with secure execution</text>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+470 -2
View File
@@ -29,9 +29,15 @@ importers:
clsx:
specifier: ^2.1.1
version: 2.1.1
gray-matter:
specifier: ^4.0.3
version: 4.0.3
next:
specifier: 16.1.1
version: 16.1.1(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
next-mdx-remote:
specifier: ^5.0.0
version: 5.0.0(@types/react@19.2.8)(react@19.2.3)
next-themes:
specifier: ^0.4.6
version: 0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -68,7 +74,7 @@ importers:
version: 9.39.2(jiti@2.6.1)
eslint-config-next:
specifier: 16.1.1
version: 16.1.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
version: 16.1.1(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
tailwindcss:
specifier: ^4.0.0
version: 4.1.18
@@ -373,7 +379,7 @@ importers:
version: 9.39.2(jiti@2.6.1)
eslint-config-next:
specifier: 16.1.1
version: 16.1.1(@typescript-eslint/parser@8.53.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
version: 16.1.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
happy-dom:
specifier: ^20.1.0
version: 20.1.0
@@ -1122,6 +1128,15 @@ packages:
'@marijn/find-cluster-break@1.0.2':
resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==}
'@mdx-js/mdx@3.1.1':
resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==}
'@mdx-js/react@3.1.1':
resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==}
peerDependencies:
'@types/react': '>=16'
react: '>=16'
'@modelcontextprotocol/sdk@1.25.2':
resolution: {integrity: sha512-LZFeo4F9M5qOhC/Uc1aQSrBHxMrvxett+9KLHt7OhcExtoiRN9DKgbZffMP/nxjutWDQpfMDfP3nkHI4X9ijww==}
engines: {node: '>=18'}
@@ -2268,6 +2283,9 @@ packages:
'@types/mdast@4.0.4':
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
'@types/mdx@2.0.13':
resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==}
'@types/ms@2.1.0':
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
@@ -2572,6 +2590,9 @@ packages:
resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==}
engines: {node: '>=14'}
argparse@1.0.10:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
@@ -2625,6 +2646,10 @@ packages:
resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==}
engines: {node: '>=4'}
astring@1.9.0:
resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
hasBin: true
async-function@1.0.0:
resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
engines: {node: '>= 0.4'}
@@ -2769,6 +2794,9 @@ packages:
codemirror@6.0.2:
resolution: {integrity: sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==}
collapse-white-space@2.1.0:
resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==}
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
@@ -3095,6 +3123,12 @@ packages:
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
engines: {node: '>= 0.4'}
esast-util-from-estree@2.0.0:
resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==}
esast-util-from-js@2.0.1:
resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==}
esbuild@0.21.5:
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
engines: {node: '>=12'}
@@ -3232,9 +3266,24 @@ packages:
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
engines: {node: '>=4.0'}
estree-util-attach-comments@3.0.0:
resolution: {integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==}
estree-util-build-jsx@3.0.1:
resolution: {integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==}
estree-util-is-identifier-name@3.0.0:
resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
estree-util-scope@1.0.0:
resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==}
estree-util-to-js@2.0.0:
resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==}
estree-util-visit@2.0.0:
resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==}
estree-walker@3.0.3:
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
@@ -3279,6 +3328,10 @@ packages:
resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==}
engines: {node: '>= 18'}
extend-shallow@2.0.1:
resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==}
engines: {node: '>=0.10.0'}
extend@3.0.2:
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
@@ -3478,6 +3531,10 @@ packages:
resolution: {integrity: sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==}
engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0}
gray-matter@4.0.3:
resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
engines: {node: '>=6.0'}
happy-dom@20.1.0:
resolution: {integrity: sha512-ebvqjBqzenBk2LjzNEAzoj7yhw7rW/R2/wVevMu6Mrq3MXtcI/RUz4+ozpcOcqVLEWPqLfg2v9EAU7fFXZUUJw==}
engines: {node: '>=20.0.0'}
@@ -3509,6 +3566,9 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
hast-util-to-estree@3.1.3:
resolution: {integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==}
hast-util-to-jsx-runtime@2.3.6:
resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==}
@@ -3654,6 +3714,10 @@ packages:
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
hasBin: true
is-extendable@0.1.1:
resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
engines: {node: '>=0.10.0'}
is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
@@ -3811,6 +3875,10 @@ packages:
js-tokens@9.0.1:
resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
js-yaml@3.14.2:
resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==}
hasBin: true
js-yaml@4.1.1:
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
hasBin: true
@@ -3857,6 +3925,10 @@ packages:
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
kind-of@6.0.3:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
kleur@3.0.3:
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
engines: {node: '>=6'}
@@ -3986,6 +4058,10 @@ packages:
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
markdown-extensions@2.0.0:
resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==}
engines: {node: '>=16'}
markdown-table@3.0.4:
resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
@@ -4023,6 +4099,9 @@ packages:
mdast-util-mdx-jsx@3.2.0:
resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==}
mdast-util-mdx@3.0.0:
resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==}
mdast-util-mdxjs-esm@2.0.1:
resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
@@ -4080,12 +4159,30 @@ packages:
micromark-extension-gfm@3.0.0:
resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
micromark-extension-mdx-expression@3.0.1:
resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==}
micromark-extension-mdx-jsx@3.0.2:
resolution: {integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==}
micromark-extension-mdx-md@2.0.0:
resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==}
micromark-extension-mdxjs-esm@3.0.0:
resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==}
micromark-extension-mdxjs@3.0.0:
resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==}
micromark-factory-destination@2.0.1:
resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}
micromark-factory-label@2.0.1:
resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}
micromark-factory-mdx-expression@2.0.3:
resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==}
micromark-factory-space@2.0.1:
resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}
@@ -4116,6 +4213,9 @@ packages:
micromark-util-encode@2.0.1:
resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
micromark-util-events-to-acorn@2.0.3:
resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==}
micromark-util-html-tag-name@2.0.1:
resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}
@@ -4215,6 +4315,12 @@ packages:
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
engines: {node: '>= 0.6'}
next-mdx-remote@5.0.0:
resolution: {integrity: sha512-RNNbqRpK9/dcIFZs/esQhuLA8jANqlH694yqoDBK8hkVdJUndzzGmnPHa2nyi90N4Z9VmzuSWNRpr5ItT3M7xQ==}
engines: {node: '>=14', npm: '>=7'}
peerDependencies:
react: '>=16'
next-themes@0.4.6:
resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==}
peerDependencies:
@@ -4597,6 +4703,20 @@ packages:
react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
recma-build-jsx@1.0.0:
resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==}
recma-jsx@1.0.1:
resolution: {integrity: sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==}
peerDependencies:
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
recma-parse@1.0.0:
resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==}
recma-stringify@1.0.0:
resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==}
reflect.getprototypeof@1.0.10:
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
engines: {node: '>= 0.4'}
@@ -4605,12 +4725,18 @@ packages:
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
engines: {node: '>= 0.4'}
rehype-recma@1.0.0:
resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==}
remark-breaks@4.0.0:
resolution: {integrity: sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ==}
remark-gfm@4.0.1:
resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
remark-mdx@3.1.1:
resolution: {integrity: sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==}
remark-parse@11.0.0:
resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
@@ -4692,6 +4818,10 @@ packages:
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
section-matter@1.0.0:
resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
engines: {node: '>=4'}
semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
@@ -4783,9 +4913,16 @@ packages:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
source-map@0.7.6:
resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
engines: {node: '>= 12'}
space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
stable-hash@0.0.5:
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
@@ -4856,6 +4993,10 @@ packages:
resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==}
engines: {node: '>=12'}
strip-bom-string@1.0.0:
resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==}
engines: {node: '>=0.10.0'}
strip-bom@3.0.0:
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
engines: {node: '>=4'}
@@ -5059,15 +5200,27 @@ packages:
unified@11.0.5:
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
unist-util-is@5.2.1:
resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==}
unist-util-is@6.0.1:
resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
unist-util-position-from-estree@2.0.0:
resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==}
unist-util-position@5.0.0:
resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
unist-util-remove@3.1.1:
resolution: {integrity: sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw==}
unist-util-stringify-position@4.0.0:
resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
unist-util-visit-parents@5.1.3:
resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==}
unist-util-visit-parents@6.0.2:
resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
@@ -5139,6 +5292,9 @@ packages:
react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc
vfile-matter@5.0.1:
resolution: {integrity: sha512-o6roP82AiX0XfkyTHyRCMXgHfltUNlXSEqCIS80f+mbAyiQBE2fxtDVMtseyytGx75sihiJFo/zR6r/4LTs2Cw==}
vfile-message@4.0.3:
resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
@@ -5289,6 +5445,11 @@ packages:
yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
yaml@2.8.2:
resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==}
engines: {node: '>= 14.6'}
hasBin: true
yargs-parser@21.1.1:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'}
@@ -6176,6 +6337,42 @@ snapshots:
'@marijn/find-cluster-break@1.0.2': {}
'@mdx-js/mdx@3.1.1':
dependencies:
'@types/estree': 1.0.8
'@types/estree-jsx': 1.0.5
'@types/hast': 3.0.4
'@types/mdx': 2.0.13
acorn: 8.15.0
collapse-white-space: 2.1.0
devlop: 1.1.0
estree-util-is-identifier-name: 3.0.0
estree-util-scope: 1.0.0
estree-walker: 3.0.3
hast-util-to-jsx-runtime: 2.3.6
markdown-extensions: 2.0.0
recma-build-jsx: 1.0.0
recma-jsx: 1.0.1(acorn@8.15.0)
recma-stringify: 1.0.0
rehype-recma: 1.0.0
remark-mdx: 3.1.1
remark-parse: 11.0.0
remark-rehype: 11.1.2
source-map: 0.7.6
unified: 11.0.5
unist-util-position-from-estree: 2.0.0
unist-util-stringify-position: 4.0.0
unist-util-visit: 5.0.0
vfile: 6.0.3
transitivePeerDependencies:
- supports-color
'@mdx-js/react@3.1.1(@types/react@19.2.8)(react@19.2.3)':
dependencies:
'@types/mdx': 2.0.13
'@types/react': 19.2.8
react: 19.2.3
'@modelcontextprotocol/sdk@1.25.2(hono@4.11.3)(zod@3.25.76)':
dependencies:
'@hono/node-server': 1.19.8(hono@4.11.3)
@@ -7284,6 +7481,8 @@ snapshots:
dependencies:
'@types/unist': 3.0.3
'@types/mdx@2.0.13': {}
'@types/ms@2.1.0': {}
'@types/node@20.19.28':
@@ -7591,6 +7790,10 @@ snapshots:
ansis@4.2.0: {}
argparse@1.0.10:
dependencies:
sprintf-js: 1.0.3
argparse@2.0.1: {}
aria-hidden@1.2.6:
@@ -7674,6 +7877,8 @@ snapshots:
dependencies:
tslib: 2.8.1
astring@1.9.0: {}
async-function@1.0.0: {}
available-typed-arrays@1.0.7:
@@ -7831,6 +8036,8 @@ snapshots:
'@codemirror/state': 6.5.3
'@codemirror/view': 6.39.10
collapse-white-space@2.1.0: {}
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
@@ -8170,6 +8377,20 @@ snapshots:
is-date-object: 1.1.0
is-symbol: 1.1.1
esast-util-from-estree@2.0.0:
dependencies:
'@types/estree-jsx': 1.0.5
devlop: 1.1.0
estree-util-visit: 2.0.0
unist-util-position-from-estree: 2.0.0
esast-util-from-js@2.0.1:
dependencies:
'@types/estree-jsx': 1.0.5
acorn: 8.15.0
esast-util-from-estree: 2.0.0
vfile-message: 4.0.3
esbuild@0.21.5:
optionalDependencies:
'@esbuild/aix-ppc64': 0.21.5
@@ -8454,8 +8675,35 @@ snapshots:
estraverse@5.3.0: {}
estree-util-attach-comments@3.0.0:
dependencies:
'@types/estree': 1.0.8
estree-util-build-jsx@3.0.1:
dependencies:
'@types/estree-jsx': 1.0.5
devlop: 1.1.0
estree-util-is-identifier-name: 3.0.0
estree-walker: 3.0.3
estree-util-is-identifier-name@3.0.0: {}
estree-util-scope@1.0.0:
dependencies:
'@types/estree': 1.0.8
devlop: 1.1.0
estree-util-to-js@2.0.0:
dependencies:
'@types/estree-jsx': 1.0.5
astring: 1.9.0
source-map: 0.7.6
estree-util-visit@2.0.0:
dependencies:
'@types/estree-jsx': 1.0.5
'@types/unist': 3.0.3
estree-walker@3.0.3:
dependencies:
'@types/estree': 1.0.8
@@ -8548,6 +8796,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
extend-shallow@2.0.1:
dependencies:
is-extendable: 0.1.1
extend@3.0.2: {}
fast-deep-equal@3.1.3: {}
@@ -8738,6 +8990,13 @@ snapshots:
graphql@16.12.0: {}
gray-matter@4.0.3:
dependencies:
js-yaml: 3.14.2
kind-of: 6.0.3
section-matter: 1.0.0
strip-bom-string: 1.0.0
happy-dom@20.1.0:
dependencies:
'@types/node': 20.19.28
@@ -8771,6 +9030,27 @@ snapshots:
dependencies:
function-bind: 1.1.2
hast-util-to-estree@3.1.3:
dependencies:
'@types/estree': 1.0.8
'@types/estree-jsx': 1.0.5
'@types/hast': 3.0.4
comma-separated-tokens: 2.0.3
devlop: 1.1.0
estree-util-attach-comments: 3.0.0
estree-util-is-identifier-name: 3.0.0
hast-util-whitespace: 3.0.0
mdast-util-mdx-expression: 2.0.1
mdast-util-mdx-jsx: 3.2.0
mdast-util-mdxjs-esm: 2.0.1
property-information: 7.1.0
space-separated-tokens: 2.0.2
style-to-js: 1.1.21
unist-util-position: 5.0.0
zwitch: 2.0.4
transitivePeerDependencies:
- supports-color
hast-util-to-jsx-runtime@2.3.6:
dependencies:
'@types/estree': 1.0.8
@@ -8923,6 +9203,8 @@ snapshots:
is-docker@3.0.0: {}
is-extendable@0.1.1: {}
is-extglob@2.1.1: {}
is-finalizationregistry@1.1.1:
@@ -9050,6 +9332,11 @@ snapshots:
js-tokens@9.0.1: {}
js-yaml@3.14.2:
dependencies:
argparse: 1.0.10
esprima: 4.0.1
js-yaml@4.1.1:
dependencies:
argparse: 2.0.1
@@ -9091,6 +9378,8 @@ snapshots:
dependencies:
json-buffer: 3.0.1
kind-of@6.0.3: {}
kleur@3.0.3: {}
kleur@4.1.5: {}
@@ -9199,6 +9488,8 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
markdown-extensions@2.0.0: {}
markdown-table@3.0.4: {}
math-intrinsics@1.1.0: {}
@@ -9312,6 +9603,16 @@ snapshots:
transitivePeerDependencies:
- supports-color
mdast-util-mdx@3.0.0:
dependencies:
mdast-util-from-markdown: 2.0.2
mdast-util-mdx-expression: 2.0.1
mdast-util-mdx-jsx: 3.2.0
mdast-util-mdxjs-esm: 2.0.1
mdast-util-to-markdown: 2.1.2
transitivePeerDependencies:
- supports-color
mdast-util-mdxjs-esm@2.0.1:
dependencies:
'@types/estree-jsx': 1.0.5
@@ -9446,6 +9747,57 @@ snapshots:
micromark-util-combine-extensions: 2.0.1
micromark-util-types: 2.0.2
micromark-extension-mdx-expression@3.0.1:
dependencies:
'@types/estree': 1.0.8
devlop: 1.1.0
micromark-factory-mdx-expression: 2.0.3
micromark-factory-space: 2.0.1
micromark-util-character: 2.1.1
micromark-util-events-to-acorn: 2.0.3
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
micromark-extension-mdx-jsx@3.0.2:
dependencies:
'@types/estree': 1.0.8
devlop: 1.1.0
estree-util-is-identifier-name: 3.0.0
micromark-factory-mdx-expression: 2.0.3
micromark-factory-space: 2.0.1
micromark-util-character: 2.1.1
micromark-util-events-to-acorn: 2.0.3
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
vfile-message: 4.0.3
micromark-extension-mdx-md@2.0.0:
dependencies:
micromark-util-types: 2.0.2
micromark-extension-mdxjs-esm@3.0.0:
dependencies:
'@types/estree': 1.0.8
devlop: 1.1.0
micromark-core-commonmark: 2.0.3
micromark-util-character: 2.1.1
micromark-util-events-to-acorn: 2.0.3
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
unist-util-position-from-estree: 2.0.0
vfile-message: 4.0.3
micromark-extension-mdxjs@3.0.0:
dependencies:
acorn: 8.15.0
acorn-jsx: 5.3.2(acorn@8.15.0)
micromark-extension-mdx-expression: 3.0.1
micromark-extension-mdx-jsx: 3.0.2
micromark-extension-mdx-md: 2.0.0
micromark-extension-mdxjs-esm: 3.0.0
micromark-util-combine-extensions: 2.0.1
micromark-util-types: 2.0.2
micromark-factory-destination@2.0.1:
dependencies:
micromark-util-character: 2.1.1
@@ -9459,6 +9811,18 @@ snapshots:
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
micromark-factory-mdx-expression@2.0.3:
dependencies:
'@types/estree': 1.0.8
devlop: 1.1.0
micromark-factory-space: 2.0.1
micromark-util-character: 2.1.1
micromark-util-events-to-acorn: 2.0.3
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
unist-util-position-from-estree: 2.0.0
vfile-message: 4.0.3
micromark-factory-space@2.0.1:
dependencies:
micromark-util-character: 2.1.1
@@ -9511,6 +9875,16 @@ snapshots:
micromark-util-encode@2.0.1: {}
micromark-util-events-to-acorn@2.0.3:
dependencies:
'@types/estree': 1.0.8
'@types/unist': 3.0.3
devlop: 1.1.0
estree-util-visit: 2.0.0
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
vfile-message: 4.0.3
micromark-util-html-tag-name@2.0.1: {}
micromark-util-normalize-identifier@2.0.1:
@@ -9635,6 +10009,19 @@ snapshots:
negotiator@1.0.0: {}
next-mdx-remote@5.0.0(@types/react@19.2.8)(react@19.2.3):
dependencies:
'@babel/code-frame': 7.28.6
'@mdx-js/mdx': 3.1.1
'@mdx-js/react': 3.1.1(@types/react@19.2.8)(react@19.2.3)
react: 19.2.3
unist-util-remove: 3.1.1
vfile: 6.0.3
vfile-matter: 5.0.1
transitivePeerDependencies:
- '@types/react'
- supports-color
next-themes@0.4.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
react: 19.2.3
@@ -10110,6 +10497,35 @@ snapshots:
tiny-invariant: 1.3.3
victory-vendor: 36.9.2
recma-build-jsx@1.0.0:
dependencies:
'@types/estree': 1.0.8
estree-util-build-jsx: 3.0.1
vfile: 6.0.3
recma-jsx@1.0.1(acorn@8.15.0):
dependencies:
acorn: 8.15.0
acorn-jsx: 5.3.2(acorn@8.15.0)
estree-util-to-js: 2.0.0
recma-parse: 1.0.0
recma-stringify: 1.0.0
unified: 11.0.5
recma-parse@1.0.0:
dependencies:
'@types/estree': 1.0.8
esast-util-from-js: 2.0.1
unified: 11.0.5
vfile: 6.0.3
recma-stringify@1.0.0:
dependencies:
'@types/estree': 1.0.8
estree-util-to-js: 2.0.0
unified: 11.0.5
vfile: 6.0.3
reflect.getprototypeof@1.0.10:
dependencies:
call-bind: 1.0.8
@@ -10130,6 +10546,14 @@ snapshots:
gopd: 1.2.0
set-function-name: 2.0.2
rehype-recma@1.0.0:
dependencies:
'@types/estree': 1.0.8
'@types/hast': 3.0.4
hast-util-to-estree: 3.1.3
transitivePeerDependencies:
- supports-color
remark-breaks@4.0.0:
dependencies:
'@types/mdast': 4.0.4
@@ -10147,6 +10571,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
remark-mdx@3.1.1:
dependencies:
mdast-util-mdx: 3.0.0
micromark-extension-mdxjs: 3.0.0
transitivePeerDependencies:
- supports-color
remark-parse@11.0.0:
dependencies:
'@types/mdast': 4.0.4
@@ -10271,6 +10702,11 @@ snapshots:
scheduler@0.27.0: {}
section-matter@1.0.0:
dependencies:
extend-shallow: 2.0.1
kind-of: 6.0.3
semver@6.3.1: {}
semver@7.7.3: {}
@@ -10451,8 +10887,12 @@ snapshots:
source-map@0.6.1: {}
source-map@0.7.6: {}
space-separated-tokens@2.0.2: {}
sprintf-js@1.0.3: {}
stable-hash@0.0.5: {}
stackback@0.0.2: {}
@@ -10551,6 +10991,8 @@ snapshots:
dependencies:
ansi-regex: 6.2.2
strip-bom-string@1.0.0: {}
strip-bom@3.0.0: {}
strip-final-newline@2.0.0: {}
@@ -10746,18 +11188,37 @@ snapshots:
trough: 2.2.0
vfile: 6.0.3
unist-util-is@5.2.1:
dependencies:
'@types/unist': 2.0.11
unist-util-is@6.0.1:
dependencies:
'@types/unist': 3.0.3
unist-util-position-from-estree@2.0.0:
dependencies:
'@types/unist': 3.0.3
unist-util-position@5.0.0:
dependencies:
'@types/unist': 3.0.3
unist-util-remove@3.1.1:
dependencies:
'@types/unist': 2.0.11
unist-util-is: 5.2.1
unist-util-visit-parents: 5.1.3
unist-util-stringify-position@4.0.0:
dependencies:
'@types/unist': 3.0.3
unist-util-visit-parents@5.1.3:
dependencies:
'@types/unist': 2.0.11
unist-util-is: 5.2.1
unist-util-visit-parents@6.0.2:
dependencies:
'@types/unist': 3.0.3
@@ -10843,6 +11304,11 @@ snapshots:
- '@types/react'
- '@types/react-dom'
vfile-matter@5.0.1:
dependencies:
vfile: 6.0.3
yaml: 2.8.2
vfile-message@4.0.3:
dependencies:
'@types/unist': 3.0.3
@@ -11020,6 +11486,8 @@ snapshots:
yallist@3.1.1: {}
yaml@2.8.2: {}
yargs-parser@21.1.1: {}
yargs@17.7.2: