Pablan, as it stands

Self-hosted knowledge management for SMEs: a split-screen Markdown editor
whose sections an LLM refines while you write, and RAG question answering
over the documents that result. FastAPI + Postgres/pgvector on the back,
SvelteKit on the front, everything OpenAI-compatible and self-hostable.

Squashed into a single commit; the development history stays local.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CA43ZJda8Rbp2hKXNy8f6b
This commit is contained in:
ProfessorNova
2026-09-04 09:21:37 +02:00
co-authored by Claude Opus 5
parent 68d3a43191
commit 784b76baf7
346 changed files with 43430 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
<script lang="ts">
import { Tabs } from 'bits-ui';
import type { Snippet } from 'svelte';
type Tab = { value: string; label: string };
type Props = {
tabs: Tab[];
value?: string;
/** Rendered once per tab; receives that tab's value. */
panel: Snippet<[string]>;
class?: string;
};
let {
tabs,
value = $bindable(tabs[0]?.value ?? ''),
panel,
class: className = ''
}: Props = $props();
</script>
<Tabs.Root bind:value class="flex min-h-0 flex-col {className}">
<Tabs.List class="flex gap-1 rounded-md bg-surface-sunken p-1">
{#each tabs as tab (tab.value)}
<Tabs.Trigger
value={tab.value}
data-testid="tab-{tab.value}"
class="flex-1 cursor-pointer rounded-md px-3 py-1.5 text-sm font-medium text-ink-muted transition-colors data-[state=active]:bg-surface-raised data-[state=active]:text-ink"
>
{tab.label}
</Tabs.Trigger>
{/each}
</Tabs.List>
{#each tabs as tab (tab.value)}
<Tabs.Content value={tab.value} class="mt-2 min-h-0 flex-1">
<!-- Only the open tab is rendered. Bits keeps inactive panels mounted
(just hidden), which for a page of independent panels means every
one of them fetches its data on arrival and hidden controls sit in
the DOM where a click can never reach them. -->
{#if tab.value === value}{@render panel(tab.value)}{/if}
</Tabs.Content>
{/each}
</Tabs.Root>