Document where the desktop app lives

So both the docs and agents know `desktop/` is its own project, with
commands run from there.
This commit is contained in:
Rūdolfs Ošiņš
2026-10-13 17:23:20 +02:00
parent e5e79605d6
commit 357f4311f6
5 changed files with 132 additions and 55 deletions
+113 -50
View File
@@ -1,20 +1,109 @@
# radicle-explorer # radicle-gui
Svelte web app for browsing Radicle repositories with a TypeScript HTTP Monorepo for Radicle's graphical interfaces. It holds two independent
client (`http-client/`) and a Rust backend (`radicle-httpd/`). projects, each with its own npm package, Cargo workspace, toolchain files,
checks and conventions:
## Plan mode - **Explorer** (repository root): the Svelte web app for browsing Radicle
repositories, its TypeScript HTTP client, and the `radicle-httpd` and
`radicle-search` backends it talks to.
- **Desktop** (`desktop/`): the Tauri desktop app. Its own `desktop/CLAUDE.md`
is the source of truth for anything under `desktop/`.
## Layout
| Path | Project | What it is |
|---|---|---|
| `src/`, `public/`, `tests/` | explorer | Svelte web app and its unit, e2e and visual tests |
| `http-client/` | explorer | TypeScript client for the httpd API |
| `crates/radicle-httpd/` | explorer | HTTP daemon serving the API (Rust), with its own `CLAUDE.md` for code conventions |
| `crates/radicle-search/` | explorer | Search service, released together with httpd (Rust) |
| `workers/` | explorer | Cloudflare workers (open-graph images) |
| `scripts/` | explorer | Check, CI and e2e helper scripts |
| `desktop/` | desktop | Tauri app: Svelte frontend in `desktop/src/`, Rust in `desktop/crates/` |
| `.github/workflows/` | both | GitHub CI: `check*.yml` for explorer, `desktop-*.yml` for desktop |
| `.buildkite/` | explorer | Radicle CI pipelines |
| `.ryph/` | both | Dev machine image and setup for agents, see `.ryph/environment.md` |
## Working in this repo
- Work out which project a change belongs to first, and run every command
from that project's root: the repository root for explorer, `desktop/`
for desktop. Root `npm` and `cargo` commands never cover `desktop/`, and
the root lint and format checks skip it on purpose.
- The two projects don't share code. A change that touches both is two
changes: check each project with its own commands.
- The rules under "Explorer" below don't apply in `desktop/`. In particular,
explorer uses legacy Svelte syntax while desktop uses Svelte 5 runes.
### Plan mode
- Propose the minimal MVP first — no tests, no docs, no speculative extras - Propose the minimal MVP first — no tests, no docs, no speculative extras
- Tests are added only when explicitly requested after MVP review - Tests are added only when explicitly requested after MVP review
- Keep plans concise: short bullet points listing what changes and where - Keep plans concise: short bullet points listing what changes and where
- Skip obvious details and boilerplate explanations - Skip obvious details and boilerplate explanations
## Tech stack ### Shared conventions
- Svelte 5 with legacy syntax (`$:`, stores, `export let`) - Prefer `undefined` over `null`
- Do not add comments unless explicitly asked. When writing comments,
use proper English sentences
- Ask before adding new dependencies
- Use npm, never `yarn` or `pnpm`
- Do not use `npm test` — neither project has a default test script
- Do not use `npx vitest` or `npx playwright test` — use the `npm run` scripts
## Commands ### Commit messages
- Imperative mood: "Add feature" not "Added feature"
- Capitalize subject, no trailing period, max 50 chars
- Prefix backend-only commits with `httpd:`
### Releases and tags
Each project is released on its own. Release tags are
`releases/<component>/<version>`; the `refs/tags/releases/*` rule in the
repository's identity decides when they become canonical.
| Component | How it's released | Tag |
|---|---|---|
| Explorer web app | Deployed continuously, no releases or tags | — |
| `radicle-httpd` + `radicle-search` | Together, one version, see `RELEASE.md` | `releases/httpd/<version>` |
| Desktop app | `desktop/scripts/release`, see `desktop/README.md` | `releases/desktop/<version>` |
The older `releases/<version>` tags (httpd 0.22.0–0.29.0, desktop
0.9.0–0.16.0) are left over from before the two repositories were merged.
Never create, match or describe against them; scripts must always match a
component's own prefix.
### 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
## Explorer (repository root)
Everything in this section applies to the repository root only. Run all
commands from there.
### Tech stack
- Svelte 5 with legacy syntax (`$:`, stores, `export let`). Do not use
Svelte 5 runes (`$state`, `$derived`, `$props`) here
- TypeScript, Vite, Vitest, Playwright, Zod
- Rust for `crates/radicle-httpd` and `crates/radicle-search`
### Checks and linting (tsc, svelte-check, eslint, prettier) ### Checks and linting (tsc, svelte-check, eslint, prettier)
@@ -46,17 +135,21 @@ or test fixtures requires a full run.
SKIP_SETUP=true npm run test:e2e -- --project chromium SKIP_SETUP=true npm run test:e2e -- --project chromium
``` ```
### Rust backend (radicle-httpd) ### Rust backend (`crates/`)
The same commands CI runs:
```sh ```sh
cd radicle-httpd && cargo clippy --all --tests RUSTFLAGS="-D warnings" cargo clippy --workspace --all-features --tests
cd radicle-httpd && cargo fmt --all --check RUSTFLAGS="-D warnings" cargo clippy -p radicle-httpd --no-default-features --tests
cd radicle-httpd && cargo test --all-features cargo fmt --all -- --check
cargo test --workspace --all-features
cargo test -p radicle-httpd
``` ```
E2E and http-client tests run against a stable pre-built httpd by E2E and http-client tests run against a stable pre-built httpd by
default. When changing `radicle-httpd/`, also test against the local default. When changing `crates/radicle-httpd/`, also test against the
build and run both to verify backwards compatibility: local build and run both to verify backwards compatibility:
```sh ```sh
npm run test:e2e:local -- --project chromium npm run test:e2e:local -- --project chromium
@@ -66,7 +159,7 @@ npm run test:http-client:unit:local
### API changes across layers ### API changes across layers
Adding or changing an API endpoint typically touches three layers: Adding or changing an API endpoint typically touches three layers:
1. `radicle-httpd/` — Rust handler (add route, types, logic) 1. `crates/radicle-httpd/` — Rust handler (add route, types, logic)
2. `http-client/` — TypeScript client (add fetch function, types) 2. `http-client/` — TypeScript client (add fetch function, types)
3. `src/` — Svelte UI (consume the new data) 3. `src/` — Svelte UI (consume the new data)
@@ -84,30 +177,6 @@ and fall back when they're absent.
5. If Rust code changed: clippy, fmt, cargo test (see above), 5. If Rust code changed: clippy, fmt, cargo test (see above),
plus `:local` variants of e2e and http-client tests plus `:local` variants 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 `undefined` over `null`
- Do not add comments unless explicitly asked. When writing comments,
use proper English sentences
- Ask before adding new dependencies
### Svelte components ### Svelte components
- Script order (enforced by prettier): `<script context="module">`, - Script order (enforced by prettier): `<script context="module">`,
@@ -123,8 +192,8 @@ crates and files in each.
- Avoid `{@html}` with backend-derived data (branch/ref names, aliases, - Avoid `{@html}` with backend-derived data (branch/ref names, aliases,
descriptions); when unavoidable, its argument must be DOMPurify-sanitized descriptions); when unavoidable, its argument must be DOMPurify-sanitized
(`sanitizeConfig` in `lib/markdown.ts`) or built from `escape()`'d parts, in (`sanitizeConfig` in `src/lib/markdown.ts`) or built from `escape()`'d
the component that renders it. parts, in the component that renders it.
### TypeScript / HTTP client ### TypeScript / HTTP client
@@ -135,14 +204,8 @@ crates and files in each.
- API timestamps are in seconds; multiply by 1000 for JS `Date` - API timestamps are in seconds; multiply by 1000 for JS `Date`
- Relative imports inside `http-client/` use `.js` extension (ESM) - Relative imports inside `http-client/` use `.js` extension (ESM)
## Commit messages ## Desktop (`desktop/`)
- Imperative mood: "Add feature" not "Added feature" See `desktop/CLAUDE.md`. In short: Tauri with a Svelte 5 frontend that uses
- Capitalize subject, no trailing period, max 50 chars runes, a hexagonal Rust backend in `desktop/crates/`, and its own checks
(`npm run check:ci` from `desktop/`).
## Do NOT
- Do not use `npm test` — no default test script exists
- Do not use `yarn` or `pnpm` — use npm
- Do not use `npx vitest` or `npx playwright test` — use the `npm run` scripts
- Do not use Svelte 5 runes (`$state`, `$derived`, `$props`) — codebase uses legacy Svelte syntax
+3
View File
@@ -3,6 +3,9 @@
This user interface lets you interact with [Radicle][rad], a peer-to-peer code This user interface lets you interact with [Radicle][rad], a peer-to-peer code
collaboration and publishing stack, directly from your web browser. collaboration and publishing stack, directly from your web browser.
The [Radicle desktop app](desktop/README.md) lives in the `desktop/` folder of
this repository.
**Deployment Options:** **Deployment Options:**
* **Public Server:** The Radicle team maintains a public instance at [radicle.network][app] * **Public Server:** The Radicle team maintains a public instance at [radicle.network][app]
+2 -1
View File
@@ -1,6 +1,7 @@
# radicle-httpd # radicle-httpd
Rust backend for radicle-explorer. Rust backend for the Radicle web explorer, released together with
`radicle-search` (see `RELEASE.md` at the repository root).
## Code conventions ## Code conventions
+6
View File
@@ -4,6 +4,12 @@ Tauri desktop app for Radicle. Svelte 5 frontend communicates with a Rust
backend via Tauri IPC commands. TypeScript types are generated from Rust backend via Tauri IPC commands. TypeScript types are generated from Rust
structs using ts-rs (`crates/radicle-types/`). structs using ts-rs (`crates/radicle-types/`).
The app lives in `desktop/` of the radicle-gui monorepo. It is its own npm
package and Cargo workspace: run every command here from `desktop/`, and all
paths in this file are relative to it. The repository root holds the Radicle
web explorer, which has its own `CLAUDE.md`. Release tags are
`releases/desktop/<version>`.
## Tech stack ## Tech stack
- Svelte 5 with runes syntax (`$state`, `$derived`, `$props`, `$effect`) - Svelte 5 with runes syntax (`$state`, `$derived`, `$props`, `$effect`)
+8 -4
View File
@@ -2,6 +2,9 @@
This desktop application lets you interact with [Radicle][rad], a peer-to-peer code collaboration and publishing stack. This desktop application lets you interact with [Radicle][rad], a peer-to-peer code collaboration and publishing stack.
It lives in the `desktop/` folder of the radicle-gui repository, next to the
Radicle web explorer. Run all commands below from `desktop/`.
## Installation ## Installation
See [radicle.dev/desktop#install](https://radicle.dev/desktop#install). See [radicle.dev/desktop#install](https://radicle.dev/desktop#install).
@@ -24,8 +27,8 @@ npm config set script-shell "C:\\Program Files\\git\\bin\\bash.exe"
Run the following commands to build the desktop app locally: Run the following commands to build the desktop app locally:
``` ```
git clone https://seed.radicle.dev/z4D5UCArafTzTQpDZNQRuqswh3ury.git radicle-desktop git clone https://seed.radicle.dev/z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git radicle-gui
cd radicle-desktop cd radicle-gui/desktop
npm install npm install
npm run tauri build npm run tauri build
``` ```
@@ -54,7 +57,7 @@ Windows, open a link in it by starting the dev binary a second time with the
link as its argument, while `npm run dev` is running: link as its argument, while `npm run dev` is running:
``` ```
target/dev-without-assertions/radicle-desktop rad:z4D5UCArafTzTQpDZNQRuqswh3ury target/dev-without-assertions/radicle-desktop rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5
``` ```
On macOS links only reach app bundles. Quit the installed app, then build and On macOS links only reach app bundles. Quit the installed app, then build and
@@ -74,7 +77,8 @@ scripts/release --phase prep --version X.Y.Z
Each phase does its mechanical work, then prints the manual tasks for its gate Each phase does its mechanical work, then prints the manual tasks for its gate
and the exact flag to resume with. List the phases and see the configuration and the exact flag to resume with. List the phases and see the configuration
with `scripts/release --list` and `scripts/release --help`. with `scripts/release --list` and `scripts/release --help`. Releases are tagged
`releases/desktop/<version>`.
## Getting in touch ## Getting in touch