Svelte 5 component library with TailwindCSS for rendering Git and Nostr UI elements in modern web applications.
Provides a comprehensive set of reusable Svelte components for building Git-aware applications on the Nostr protocol, with a focus on accessibility, performance, and developer experience.
# Using pnpm (recommended)
pnpm add @nostr-git/ui
# Using npm
npm install @nostr-git/ui
# Using yarn
yarn add @nostr-git/ui
# Required peer dependencies
pnpm add svelte@^5.28.2
<script lang="ts">
import { RepoCard, PatchViewer } from "@nostr-git/ui";
import type { NostrEvent } from "@nostr-git/shared-types";
let repoEvent: NostrEvent;
let patchEvent: NostrEvent;
</script>
<RepoCard event={repoEvent} />
<PatchViewer event={patchEvent} />
Add the UI preset to your tailwind.config.js:
// tailwind.config.js
import { preset } from "@nostr-git/ui/tailwind.preset.js";
export default {
presets: [preset],
content: ["./src/**/*.{html,js,svelte,ts}", "./node_modules/@nostr-git/ui/**/*.{js,svelte,ts}"],
};
/* app.css */
@import "@nostr-git/ui/index.css";
<script lang="ts">
import { EventPublisher, RepoSelector } from "@nostr-git/ui";
import type { GitRepository } from "@nostr-git/shared-types";
// Svelte 5 runes for reactive state
let selectedRepo = $state<GitRepository | null>(null);
let isPublishing = $state(false);
// Derived state
const canPublish = $derived(selectedRepo && !isPublishing);
function handleRepoSelect(repo: GitRepository) {
selectedRepo = repo;
}
async function handlePublish() {
if (!selectedRepo) return;
isPublishing = true;
try {
await publishRepoEvent(selectedRepo);
} finally {
isPublishing = false;
}
}
</script>
<RepoSelector onselect={handleRepoSelect} />
{#if selectedRepo}
<EventPublisher repo={selectedRepo} disabled={!canPublish} onpublish={handlePublish} />
{/if}
For detailed component documentation, see:
RepoCard - Repository information displayRepoSelector - Repository picker with searchCloneRepository - Repository cloning interfaceForkRepository - Repository forking workflowCommitViewer - Commit details and diff displayPatchViewer - Git patch visualizationBranchSelector - Branch switching interfaceMergeConflictResolver - Conflict resolution UIEventCard - Generic Nostr event displayPublishButton - Event publishing interfaceRelayStatus - Relay connection indicatorKeyManager - Private key management/* Custom CSS properties */
:root {
--color-primary: #8b5cf6;
--color-primary-foreground: #ffffff;
--color-secondary: #6b7280;
--color-accent: #10b981;
--color-destructive: #ef4444;
}
<script>
import { ThemeProvider } from "@nostr-git/ui";
</script>
<ThemeProvider theme="dark">
<!-- Your app content -->
</ThemeProvider>
The UI package follows these design principles:
src/lib/
โโโ components/
โ โโโ git/ # Git-specific components
โ โโโ nostr/ # Nostr-specific components
โ โโโ ui/ # Generic UI primitives
โ โโโ forms/ # Form components
โโโ stores/ # Svelte stores for state management
โโโ utils/ # Utility functions
โโโ styles/ # TailwindCSS configurations
# Install dependencies
pnpm install
# Start development mode
pnpm watch
# Build components
pnpm build
# Run component tests
pnpm test
# Test with coverage
pnpm test --coverage
# Visual regression testing
pnpm test:visual
This UI package includes a testable core for Git/Nostr repo features, decoupled from Svelte runes, plus a reactive Repo class for UI consumption.
Core module: @nostr-git/core RepoCore class
trustedMaintainers(ctx)mergeRepoStateByMaintainers(ctx, events) โ merges trusted 30618 refs; includes legacy r tag pair fallbackgetPatchGraph(ctx) returns:nodes: Map<string, PatchEvent>roots: string[], rootRevisions: string[]edgesCount: number, topParents: string[]parentOutDegree: Record<string, number>, parentChildren: Record<string, string[]>resolveStatusFor(ctx, rootId) โ trust/author precedence; maps NIP-163x kinds to UI statesgetIssueThread(ctx, rootId) โ NIP-22 commentsgetEffectiveLabelsFor, getIssueLabels, getPatchLabels, getRepoLabelsgetMaintainerBadge(ctx, pubkey) โ 'owner' | 'maintainer' | nullReactive Repo class: src/lib/components/git/Repo.svelte.ts
getPatchGraph() fields for UImergeRepoStateByMaintainers(), getPatchGraph(), resolveStatusFor()getIssueThread(), getEffectiveLabelsFor() and label helpersgetMaintainerBadge(), getRecommendedFilters()RepoContext snapshot and passes it to RepoCore functionsRun the focused Repo tests from the workspace root:
pnpm -w test:repo
This uses a dedicated Vitest config to run packages/nostr-git/packages/ui/tests/Repo.spec.ts with:
vitest.repo.config.ts, vitest.setup.ts)$lib/stores/context|tokens|toastfake-indexeddb, self)src/lib/components/StatusChip.svelte โ resolved/raw status with reason tooltipsrc/lib/components/MaintainerBadge.svelte โ displays owner/maintainer rolesrc/lib/components/PatchDagSummary.svelte โ DAG summary: nodes, edges, roots, top parents; hover shows up to 3 child IDs (truncated)The package uses @sveltejs/package for building:
// svelte.config.js
import { sveltekit } from "@sveltejs/kit/vite";
export default {
kit: {
package: {
exports: (filepath) => {
return filepath.endsWith(".svelte") || filepath.endsWith(".js");
},
},
},
};
See the main project's DEVELOPMENT.md for development setup and CODING_STANDARDS.md for code style guidelines.
MIT License - see LICENSE for details.