ewan's projects — docs

projects

@ewanc26/pkgs

March 24, 2026

# monorepo# pnpm# typescript# rust# python# atproto# library# tools

@ewanc26/pkgs is a language-agnostic monorepo containing all of Ewan's publishable packages across multiple programming languages. It was created by extracting the packages/ subdirectories from their original host repositories (malachite and website) and migrating the entire svelte-standard-site repository — all with full git history preserved via git subtree. The standalone malachite repository has since been fully consolidated here too, with the CLI and web frontend split into separate packages.

The monorepo has since expanded to include Rust CLI tools and Python utilities, making it a unified workspace for all reusable code.

Packages

TypeScript

Package Version Description
@ewanc26/tid 1.x Zero-dependency AT Protocol TID generation
@ewanc26/atproto 0.x AT Protocol service layer (profiles, posts, Standard.site, music status)
@ewanc26/ui 0.x Svelte 5 UI component library (cards, layout, stores, themes)
@ewanc26/utils 0.x Shared utilities (dates, numbers, URLs, validators, RSS)
@ewanc26/noise 0.x Generic deterministic value-noise generation — arbitrary dimensions, multi-octave FBM, multiple colour modes
@ewanc26/noise-avatar 0.x Deterministic value-noise avatar generation from a string seed — thin wrapper around @ewanc26/noise
@ewanc26/bismuth 0.x Convert pub.leaflet RTF-block documents (site.standard.document records) to Markdown — CLI and library
@ewanc26/svelte-standard-site 0.x SvelteKit library for site.standard.* AT Protocol records — design system, federated comments, publishing tools, and content verification
@ewanc26/pds-landing 2.x Composable Svelte components for an ATProto PDS landing page — terminal-aesthetic UI with live status fetching
@ewanc26/supporters 0.x SvelteKit component library for displaying Ko-fi supporters, backed by an ATProto PDS
@ewanc26/wafrn-theme 1.x WAFRN CSS theme using the pds-landing Catppuccin terminal aesthetic — dark forest-green palette, JetBrains Mono
@ewanc26/tangled-sync 1.x CLI tool for syncing GitHub repos to Tangled with ATProto records
@ewanc26/malachite 0.x CLI tool for importing Last.fm & Spotify history to AT Protocol as fm.teal.alpha.feed.play records
malachite-web 0.x SvelteKit web frontend for Malachite — browser-based import with ATProto OAuth (private, not published to npm)

Rust

Package Version Description
nix-config-tools 0.x Management tools for nixos/nix-darwin configuration (flake-bump, health-check, gen-diff, server-config)

Python

Package Version Description
llm-analyser 0.x Document analysis tool using Ollama LLM

Why a monorepo?

The packages share overlapping concerns — @ewanc26/ui depends on @ewanc26/noise-avatar and optionally @ewanc26/atproto for its card components, and both consume types from @ewanc26/utils. @ewanc26/svelte-standard-site pulls in @ewanc26/atproto, @ewanc26/tid, and @ewanc26/utils. @ewanc26/bismuth converts the same site.standard.document records that @ewanc26/svelte-standard-site renders. Having them colocated means:

  • Cross-package changes can land in a single PR
  • workspace:* references keep internal deps in sync without publishing intermediary versions
  • One place to update shared tooling (TypeScript config, build scripts, licence)
  • Unified development experience across languages

Installation

TypeScript packages

pnpm add @ewanc26/tid
pnpm add @ewanc26/atproto
pnpm add @ewanc26/ui
pnpm add @ewanc26/utils
pnpm add @ewanc26/noise
pnpm add @ewanc26/noise-avatar
pnpm add @ewanc26/bismuth
pnpm add @ewanc26/svelte-standard-site
pnpm add @ewanc26/pds-landing
pnpm add @ewanc26/supporters
pnpm add @ewanc26/wafrn-theme
pnpm add @ewanc26/tangled-sync

Rust tools

nix run https://github.com/ewanc26/pkgs#health-check

Python tools

# Install dependencies
pip install -r packages/llm-analyser/requirements.txt

# Run the tool
python3 packages/llm-analyser/main.py

Development

git clone https://github.com/ewanc26/pkgs.git
cd pkgs
pnpm install

# Build all TypeScript packages
pnpm build

# Type-check all TypeScript packages
pnpm check

# Test all TypeScript packages
pnpm test

# Build all Rust packages
cargo build --release

# Work on a single package
pnpm --filter @ewanc26/tid build
pnpm --filter @ewanc26/bismuth dev
pnpm --filter @ewanc26/svelte-standard-site dev
cargo build -p nix-config-tools --bin health-check

How history was migrated

Each package was extracted from its source repository using one of two approaches:

Subdirectory packages (tid, atproto, ui, utils) — git subtree split was run inside the source repo to isolate that subdirectory's commit history into a standalone branch, which was then merged into pkgs via git subtree add. git log packages/tid in this repo shows the real history going back to when the package was first created in malachite.

Whole-repo package (svelte-standard-site) — the repo root was already the package, so no split step was needed. The full history was merged directly into packages/svelte-standard-site via git subtree add.

Consolidated packages (nix-config-tools, tangled-sync, llm-analyser) — these were copied from their original locations and integrated into the monorepo structure.

Archived repo consolidation (malachite, malachite-web) — the standalone malachite repository was fully migrated using git filter-repo, rewriting its commit history under packages/malachite/ (CLI) and packages/malachite-web/ (web frontend) separately. The original repo is now archived.

The source repos retain their original files for reference, but the canonical source of truth for all packages is this monorepo.

Publishing

TypeScript packages are published to npm automatically via GitHub Actions. Pushing a tag in the format <package-name>/v<semver> triggers the workflow, which resolves the package from the tag, builds it, and publishes to npm with provenance via OIDC.

# Publish a specific package
git tag bismuth/v0.1.0
git push origin bismuth/v0.1.0

The NPM_TOKEN secret must be set in the repository's GitHub Actions secrets. malachite-web is private and not published. Rust and Python packages are not published automatically.

Licence

AGPL-3.0-only.


← all docs