Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion hugo-site/content/apps/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ still at the RFC stage.

Decentralized live social feed (posts, profiles, follows, likes), designed as
a high-churn live surface that complements [Atlas](#atlas) for durable
discovery and archival.
discovery and archival. Built with TypeScript and Vite, Raven is also the
reference frontend for the [TypeScript SDK](/build/manual/typescript-sdk/).

{{< app-screenshot light="/images/apps/raven.png" alt="Raven microblogging interface" >}}

Expand Down
9 changes: 6 additions & 3 deletions hugo-site/content/build/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@ peer-to-peer network with no servers to maintain.

- [Tutorial](/build/manual/tutorial/) - Build your first Freenet app
- [Manual](/build/manual/) - Architecture, components, and reference
- [TypeScript SDK](/build/manual/typescript-sdk/) - Connect a browser or Node.js UI to a node with `@freenetorg/freenet-stdlib`

## AI-Assisted Development

Install the [freenet-dapp-builder](https://github.com/freenet/freenet-agent-skills/tree/main/skills/dapp-builder) skill for Claude Code:
Install the [dapp-builder](https://github.com/freenet/freenet-agent-skills/tree/main/skills/dapp-builder) skill for Claude Code:

```bash
/plugin marketplace add freenet/freenet-agent-skills
/plugin install freenet-dapp-builder
/plugin install freenet@freenet-agent-skills
```

This skill guides you through building contracts, delegates, and UI for Freenet apps.
This installs the `freenet` plugin, whose `dapp-builder` skill guides you through building
contracts, delegates, and UI for Freenet apps. The plugin also bundles `local-dev` and other
development skills.

## Developer Tools

Expand Down
36 changes: 26 additions & 10 deletions hugo-site/content/build/manual/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ usage. Use the table of contents below to navigate through the manual.
2. [Components](#components)
3. [Architecture](#architecture)
4. [Developer Guide](#developer-guide)
5. [Examples](#examples)
6. [Community and Support](#community-and-support)
7. [Reference](#reference)
8. [Further reading](#further-reading)
5. [Client SDKs](#client-sdks)
6. [Examples](#examples)
7. [Community and Support](#community-and-support)
8. [Reference](#reference)
9. [Further reading](#further-reading)

---

Expand All @@ -34,7 +35,7 @@ Learn the basics of Freenet and its purpose.

---

## Components
## Components {#components}

Explore the key components of Freenet:

Expand All @@ -60,15 +61,31 @@ Understand Freenet's architecture and how it works:
Resources for building on Freenet:

- [Publish a Website](publish-a-website): Host a static website on Freenet -- no coding required.
- [Remote Access to a Node](remote-access): Safely reach your local node's API from another device (SSH tunnel, Tailscale).
- [Remote Access to a Node](remote-access): Safely reach your local node's API from another device
(SSH tunnel, Tailscale).
- [Tutorial: Create an App](tutorial): Step-by-step guide to creating a decentralized app.
- [Contract Interfaces](contract-interface): Reference for contract interfaces.
- [Contract Interfaces](contract-interface): The Rust contract-authoring API (`ContractInterface`).
Full API on [docs.rs](https://docs.rs/freenet-stdlib).
- [Manifest Format](manifest): Details about the `freenet.toml` configuration format.

---

## Client SDKs {#client-sdks}

Libraries for connecting a user interface to a Freenet node over WebSocket:

- [TypeScript SDK](typescript-sdk): The browser/Node.js client -- `@freenetorg/freenet-stdlib`.
Recommended for most UIs.
- Rust client (Dioxus): use `freenet-stdlib` with the `net` feature; see
[docs.rs](https://docs.rs/freenet-stdlib) and [River](https://github.com/freenet/river) for the
reference implementation.

---

## Examples {#examples}

- [Example Apps](example-app): Canonical apps to learn from -- freenet-ping (minimal Rust), Raven
(TypeScript + Vite), and River (Dioxus).
- [Antiflood Tokens](examples/antiflood-tokens)
- [Blind Trust Tokens](examples/blind-trust-tokens)

Expand Down Expand Up @@ -97,8 +114,7 @@ Deep-dive articles on the design principles behind Freenet's architecture:
- [Understanding Small World Networks](/build/manual/further-reading/small-world-networks/): the
routing intuition behind the P2P network. How Freenet finds destinations in just a few hops
without a central index.
- [Understanding Freenet's Delta-Sync](/build/manual/further-reading/delta-sync/): how shared
state stays consistent across the network using mergeable, additive updates rather than full
snapshots.
- [Understanding Freenet's Delta-Sync](/build/manual/further-reading/delta-sync/): how shared state
stays consistent across the network using mergeable, additive updates rather than full snapshots.

See [Further reading](/build/manual/further-reading/) for the full collection.
2 changes: 1 addition & 1 deletion hugo-site/content/build/manual/components/delegates.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Beyond handling messages, delegates can create, read, and modify contracts; crea

A **key manager delegate** stores private keys and signs data on request, possibly prompting the user for permission. An **inbox delegate** monitors an inbox contract, downloads new messages, decrypts them, and stores them privately for UIs to display. A **contacts delegate** stores and retrieves contact information. An **alerts delegate** watches for events (like mentions in a discussion) and notifies the user.

Delegates store their state encrypted on the local device. Recent prior values are kept as snapshots so accidental overwrites can be recovered. Cross-device synchronization is not yet implemented see [issue #3050](https://github.com/freenet/freenet-core/issues/3050) for the planned vault-delegate primitive.
Delegates store their state encrypted on the local device. Recent prior values are kept as snapshots so accidental overwrites can be recovered. Cross-device synchronization is not yet implemented; see [issue #3050](https://github.com/freenet/freenet-core/issues/3050) for the planned vault-delegate primitive.

For a real-world example, River's [chat delegate](https://github.com/freenet/river/tree/main/delegates/chat-delegate) stores per-room signing keys and signs messages, invitations, and room configurations on behalf of the UI, without ever exposing the keys.

Expand Down
11 changes: 7 additions & 4 deletions hugo-site/content/build/manual/components/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ aliases:

Delegates, contracts, and user interfaces (UIs) each serve distinct roles in the Freenet ecosystem.
[Contracts](/build/manual/components/contracts) control public data, or "shared state".
[Delegates](/build/manual/components/delegates) act as the user's agent and can store private data on the
user's behalf, while [User Interfaces](/build/manual/components/ui) provide an interface between these and
the user through a web browser. UIs are distributed through the P2P network via contracts.
[Delegates](/build/manual/components/delegates) act as the user's agent and can store private data
on the user's behalf, while [User Interfaces](/build/manual/components/ui) provide an interface
between these and the user through a web browser. UIs are distributed through the P2P network via
contracts and connect to the node through a client SDK; see
[Client SDKs](/build/manual/#client-sdks).

![Architectural Primitives Diagram](/components.svg)

Expand All @@ -24,7 +26,8 @@ Its primary functions are:

- Providing a user-friendly interface to access Freenet via a web browser
- Host the user's [delegates](/build/manual/components/delegates) and the private data they store
- Host [contracts](/build/manual/components/contracts) and their associated data on behalf of the network
- Host [contracts](/build/manual/components/contracts) and their associated data on behalf of the
network
- Manage communication between contracts, delegates, and UI components

Built with Rust, the core is designed to be compact (ideally under 5 MB), efficient, and capable of
Expand Down
107 changes: 104 additions & 3 deletions hugo-site/content/build/manual/components/ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ On the normal web, a user might visit `https://gmail.com/`, their browser will d
user interface which then runs in their browser and connects back to the Gmail servers.

On Freenet the user interface is downloaded from a Freenet contract, and it
[interacts](/build/manual/components/overview) with contracts and delegates by sending messages through
the Freenet core.
[interacts](/build/manual/components/overview) with contracts and delegates by sending messages
through the Freenet core.

![Delegate, Contract, and UI Diagram](/ui_delegate_contract.svg)

Expand All @@ -20,4 +20,105 @@ over Freenet and run in a web browser. UIs can create, retrieve, and update cont
WebSocket connection to the local Freenet peer, as well as communicate with delegates.

Because UIs run in a web browser, they can be built using any web framework, such as React, Angular,
Vue.js, Bootstrap, and so on.
Vue.js, Bootstrap, and so on. There are two first-class paths:

- **TypeScript + Vite**: a standard web frontend that talks to the node over WebSocket using the
published TypeScript SDK (below). This is the recommended path for most apps.
- **Dioxus (Rust to WebAssembly)**: a Rust UI framework that lets you share types and logic with
your contracts. See [River](https://github.com/freenet/river) for a complete example.

## The TypeScript SDK

The SDK is published to npm as
[`@freenetorg/freenet-stdlib`](https://www.npmjs.com/package/@freenetorg/freenet-stdlib). Install
the latest release (no version pin needed, npm fetches the current one):

```bash
npm install @freenetorg/freenet-stdlib
```

The essentials are below; for the complete API (every request/response class, update types,
streaming, and delegates) see the [TypeScript SDK reference](/build/manual/typescript-sdk/).

### Connecting to the node

The SDK's `FreenetWsApi` opens a WebSocket to the local node. Derive the URL from the page location
rather than hardcoding a host or port, because the host is not known ahead of time when your app is
served from a Freenet container:

```typescript
import {
FreenetWsApi,
ContractKey,
GetRequest,
SubscribeRequest,
UpdateRequest,
UpdateData,
UpdateDataType,
DeltaUpdate,
} from "@freenetorg/freenet-stdlib";

// The third argument is the auth token. When your app runs inside the
// Freenet web-container shell, leave it empty; the shell injects auth.
const wsUrl = new URL(`ws://${location.host}/v1/contract/command`);
const api = new FreenetWsApi(wsUrl, handler, "");
```

`handler` is a `ResponseHandler` object: the node pushes results and live updates to its callbacks
(`onContractGet`, `onContractUpdateNotification`, `onErr`, `onOpen`, and more). A minimal handler:

```typescript
const handler = {
onOpen: () => console.log("[freenet] connected"),
onContractGet: (r) => {
/* initial state */
},
onContractUpdateNotification: (n) => {
/* live delta from a subscription */
},
onContractPut: () => {},
onContractUpdate: () => {},
onContractNotFound: () => {},
onDelegateResponse: () => {},
onErr: (e) => console.error("[freenet]", e.cause),
};
```

### Reading, subscribing, and updating

The request methods are promise-based (`await`); each also fires the matching handler callback. The
default request timeout is 30 seconds.

```typescript
const contractKey = ContractKey.fromInstanceId("<base58-instance-id>");

// GET: fetch current state (pass true to also fetch the contract code)
const response = await api.get(new GetRequest(contractKey, true));
const state = JSON.parse(new TextDecoder().decode(Uint8Array.from(response.state)));

// SUBSCRIBE: receive real-time updates via onContractUpdateNotification
await api.subscribe(new SubscribeRequest(contractKey, []));

// UPDATE: send a delta
const deltaBytes = new TextEncoder().encode(JSON.stringify(myDelta));
const delta = new DeltaUpdate(Array.from(deltaBytes));
const update = new UpdateData(UpdateDataType.DeltaUpdate, delta);
await api.update(new UpdateRequest(contractKey, update));
```

Reads are not correlated to their responses: the SDK settles `get()` promises in FIFO order, so do
not run multiple `get()` calls concurrently; serialize them. See
[Request ordering](/build/manual/typescript-sdk/#request-ordering) in the SDK reference.

### Packaging notes

When your UI is served from a Freenet web container it runs inside a sandboxed iframe with a strict
Content Security Policy:

- Set `base: "./"` in your Vite config so assets resolve relative to the container URL.
- Prefer vendoring third-party CSS/JS locally (copy into `public/`); the gateway applies a Content
Security Policy, so verify any remote origins (such as a font CDN) against a real gateway.

See the [tutorial](/build/manual/tutorial/) for an end-to-end walkthrough and
[Raven](https://github.com/freenet/raven) (a decentralized microblogging app) for a complete
TypeScript + Vite reference.
3 changes: 3 additions & 0 deletions hugo-site/content/build/manual/contract-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ aliases:
- /resources/manual/contract-interface/
---

This page documents the Rust contract-authoring API. To connect a user interface to a node, see
[Client SDKs](/build/manual/#client-sdks).

## Terms

- [Contract State](/build/manual/glossary#contract-state) - data associated with a contract that can be
Expand Down
2 changes: 1 addition & 1 deletion hugo-site/content/build/manual/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,5 @@ CONTRACT_SRC_DIR=./web /location/of/freenet/docker/fdev.sh build
From the base directory of the contract project.

```sh
/location/of/freenet/docker/fdev.sh publish --code target/wasm32-unknown-unknown/release/freenet_microblogging_web.wasm --state web/build/freenet/contract-state
/location/of/freenet/docker/fdev.sh publish --code target/wasm32-unknown-unknown/release/my_contract.wasm contract --state web/build/freenet/contract-state
```
Loading
Loading