4.6 KiB
radicle-explorer
Svelte web app for browsing Radicle repositories with a TypeScript HTTP
client (http-client/) and a Rust backend (radicle-httpd/).
Plan mode
- Propose the minimal MVP first — no tests, no docs, no speculative extras
- Tests are added only when explicitly requested after MVP review
- Keep plans concise: short bullet points listing what changes and where
- Skip obvious details and boilerplate explanations
Tech stack
- Svelte 5 with legacy syntax (
$:, stores,export let)
Commands
Checks and linting (tsc, svelte-check, eslint, prettier)
npm run check
npm run format # auto-fix prettier issues
Unit tests
npm run test:unit
npm run test:http-client:unit
E2E tests
npm run test:e2e -- --project chromium
npm run test:e2e -- tests/e2e/<file>.spec.ts --project chromium
SKIP_SETUP=true skips fixture creation for faster iteration.
Only use it when you are solely editing .spec.ts files and fixtures
already exist from a previous full run. Any change to app code, httpd,
or test fixtures requires a full run.
SKIP_SETUP=true npm run test:e2e -- --project chromium
Rust backend (radicle-httpd)
cd radicle-httpd && cargo clippy --all --tests
cd radicle-httpd && cargo fmt --all --check
cd radicle-httpd && cargo test --all-features
E2E and http-client tests run against a stable pre-built httpd by
default. When changing radicle-httpd/, also test against the local
build and run both to verify backwards compatibility:
npm run test:e2e:local -- --project chromium
npm run test:http-client:unit:local
API changes across layers
Adding or changing an API endpoint typically touches three layers:
radicle-httpd/— Rust handler (add route, types, logic)http-client/— TypeScript client (add fetch function, types)src/— Svelte UI (consume the new data)
Backwards compatibility: Only add to the backend API — never rename or remove fields/endpoints unless explicitly deprecating. The frontend must handle older nodes gracefully: treat new API fields as optional and fall back when they're absent.
Pre-push checklist
npm run checknpm run test:unitnpm run test:http-client:unitnpm run test:e2e -- --project chromium- If Rust code changed: clippy, fmt, cargo test (see above),
plus
:localvariants of e2e and http-client tests
Radicle ecosystem (sibling repos)
See the radicle-ecosystem skill for the map of sibling repositories
(heartwood, radicle-git, radicle-job, rips, radicle.dev) and the key
crates and files in each.
Domain glossary
- RID — Repository ID (
rad:z3gqc...) - DID — Decentralized Identifier, user identity (
did:key:z6Mk...) - NID — Node ID, public key suffix of a DID
- COB — Collaborative Object (issue, patch, or identity as a Git DAG)
- Delegate — authorized repo maintainer; signatures determine canonical state
- Patch — pull-request equivalent with immutable revisions and reviews
- Seed — hosting/replicating a repo; seed nodes are always-on servers
- Canonical refs — branches/tags resolved by delegate quorum
Code conventions
- Prefer
undefinedovernull - Do not add comments unless explicitly asked. When writing comments, use proper English sentences
- Ask before adding new dependencies
Svelte components
- Script order (enforced by prettier):
<script context="module">,<script lang="ts">,<style>, markup - Optional props use
export let foo: T = undefined, not?: - CSS: scoped styles with design tokens (
var(--color-text-primary),var(--txt-body-m-regular),var(--border-radius-sm)); use:global()for styling slotted or{@html}content - Loading states:
{#await promise}blocks for inline async; localloadingboolean withtry/catchfor imperative fetches
TypeScript / HTTP client
- Derive types from Zod schemas (
z.infer<typeof fooSchema>), never hand-write interfaces that duplicate a schema - Schema naming:
fooSchema(camelCase + Schema suffix) → typeFoo - Use ES private fields (
#field), not the TypeScriptprivatekeyword - API timestamps are in seconds; multiply by 1000 for JS
Date - Relative imports inside
http-client/use.jsextension (ESM)
Commit messages
- Imperative mood: "Add feature" not "Added feature"
- Capitalize subject, no trailing period, max 50 chars
Do NOT
- Do not use
npm test— no default test script exists - Do not use
yarnorpnpm— use npm - Do not use
npx vitestornpx playwright test— use thenpm runscripts - Do not use Svelte 5 runes (
$state,$derived,$props) — codebase uses legacy Svelte syntax