{"id":49803357,"url":"https://github.com/freenet/raven","last_synced_at":"2026-05-12T16:11:07.340Z","repository":{"id":352436876,"uuid":"1214977697","full_name":"freenet/raven","owner":"freenet","description":null,"archived":false,"fork":false,"pushed_at":"2026-04-27T11:21:50.000Z","size":465,"stargazers_count":4,"open_issues_count":2,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-27T12:23:25.702Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/freenet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-19T10:07:20.000Z","updated_at":"2026-04-27T10:30:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/freenet/raven","commit_stats":null,"previous_names":["freenet/freenet-microblogging","freenet/raven"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/freenet/raven","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freenet%2Fraven","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freenet%2Fraven/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freenet%2Fraven/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freenet%2Fraven/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/freenet","download_url":"https://codeload.github.com/freenet/raven/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freenet%2Fraven/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32946640,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-12T09:19:52.626Z","status":"ssl_error","status_checked_at":"2026-05-12T09:17:33.438Z","response_time":102,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-12T16:11:06.429Z","updated_at":"2026-05-12T16:11:07.333Z","avatar_url":"https://github.com/freenet.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Freenet Microblogging - Decentralized Social on Freenet\n\nFreenet Microblogging is a decentralized Twitter/X-like application built on\n[Freenet](https://freenet.org), designed to provide censorship-resistant social networking where\nusers own their data. It features a web-based interface built with TypeScript and Vite, Rust/WASM\ncontracts for post storage and social graph, and an Ed25519 identity delegate for cryptographic\nsigning.\n\n![Screenshot of microblogging interface](docs/screenshot.png)\n\n## Roadmap\n\n- [x] Posts contract with 280-character limit and content-hash deduplication\n- [x] Follows contract for social graph (follow/unfollow)\n- [x] Likes contract for post reactions\n- [x] Ed25519 identity delegate with keypair generation and signing\n- [x] Web UI with feed, compose box, profile, sidebar, dark/light mode\n- [x] Onboarding flow with identity creation and import\n- [x] Real-time post updates via contract subscription\n- [ ] Wire likes to contract (currently local-only)\n- [ ] Wire follows to contract (Following tab exists but empty)\n- [ ] Post search and filtering\n- [ ] Media attachments\n- [ ] GhostKey support for anonymous posting\n\n## Getting Started\n\n### Building and Running\n\n1. Install dependencies:\n\n   ```bash\n   # Install Rust with wasm target\n   curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n   rustup target add wasm32-unknown-unknown\n\n   # Install Node.js (v18+)\n   # See https://nodejs.org/en/download\n\n   # Install Freenet tools\n   cargo install freenet\n   cargo install fdev\n\n   # Install BLAKE3 hash tool (used for delegate key computation)\n   cargo install b3sum\n   ```\n\n2. Clone and set up:\n\n   ```bash\n   # Clone the repository\n   git clone git@github.com:freenet/freenet-microblogging.git\n   cd freenet-microblogging\n\n   # Clone freenet-stdlib as a sibling directory (required for TypeScript SDK)\n   cd .. \u0026\u0026 git clone git@github.com:nicobao/freenet-stdlib.git \u0026\u0026 cd freenet-microblogging\n\n   # Install web dependencies\n   cd web \u0026\u0026 npm install \u0026\u0026 cd ..\n   ```\n\n3. Build and publish:\n\n   ```bash\n   # Set target directory (required by Makefile.toml)\n   export CARGO_TARGET_DIR=$(pwd)/target\n\n   # Full build: contracts + delegate + web app + publish all\n   cargo make build\n   ```\n\n4. Run the node:\n\n   ```bash\n   cargo make run-node\n   ```\n\n5. Open the web app URL printed during publish\n   (e.g. `http://127.0.0.1:7509/contract/web/\u003chash\u003e/`)\n\n### Key Development Commands\n\n```bash\n# Rebuild just the web app\ncargo make build-ui publish-webapp-test\n\n# Rebuild a single contract\ncargo make publish-posts\ncargo make publish-follows\ncargo make publish-likes\n\n# Rebuild identity delegate\ncargo make publish-identity\n\n# Run all tests (Rust + web)\ncargo make test\n\n# Type check everything\ncargo make check\n\n# Reset node data (required when republishing contracts)\ncargo make clean-node\n\n# Vite dev server (without Freenet)\ncd web \u0026\u0026 npm run dev\n```\n\n## Technical Details\n\n### Project Structure\n\n- [contracts/posts](contracts/posts/): Posts feed contract (store, validate, merge)\n- [contracts/follows](contracts/follows/): Follow graph contract\n- [contracts/likes](contracts/likes/): Like graph contract\n- [delegates/identity](delegates/identity/): Ed25519 identity delegate\n- [web](web/): TypeScript + Vite web application\n\n### Architecture\n\nThe system is built using:\n\n- **Freenet Contracts**: Rust/WASM contracts with commutative merge for conflict-free replication\n- **Freenet Delegates**: Client-side WASM modules for identity and cryptographic operations\n- **freenet-stdlib**: TypeScript SDK for WebSocket communication with the Freenet node\n- **Vite**: Fast build toolchain for the web app, served as a webapp contract\n- **Ed25519**: Elliptic curve cryptography for identity and post signing\n- **BLAKE3**: Content-addressable hashing for post deduplication and delegate key computation\n\n### Contract Architecture\n\nPosts are stored in a commutative contract that merges updates from multiple users deterministically.\nThe core state structure is defined in [contracts/posts/src/lib.rs](contracts/posts/src/lib.rs):\n\n```rust\n#[derive(Serialize, Deserialize)]\nstruct PostsFeed {\n    posts: Vec\u003cPost\u003e,\n}\n\n#[derive(Serialize, Deserialize, Clone)]\npub struct Post {\n    pub id: String,                    // \"{author_pubkey}-{timestamp_ms}\"\n    pub author_pubkey: String,         // hex-encoded public key\n    pub author_name: String,           // display name\n    pub author_handle: String,         // @handle\n    pub content: String,               // post text (max 280 chars)\n    pub timestamp: u64,                // unix timestamp milliseconds\n    pub signature: Option\u003cBox\u003c[u8]\u003e\u003e,  // Ed25519 signature over content\n}\n```\n\nEach contract handles its own state merging:\n\n- [Posts](contracts/posts/src/lib.rs): Append-only feed, deduplication by BLAKE3 content hash\n- [Follows](contracts/follows/src/lib.rs): Set-based merge (union of follow relationships)\n- [Likes](contracts/likes/src/lib.rs): Set-based merge (union of likes per post)\n\n### Identity Delegate\n\nThe identity delegate runs client-side in the Freenet node and manages Ed25519 keypairs. It supports:\n\n- **CreateIdentity**: Generate a new keypair with display name\n- **GetIdentity**: Retrieve the current identity\n- **SignPost**: Sign post content for authenticity\n- **ExportIdentity / ImportIdentity**: Transfer identity between devices\n\nThe delegate key is computed as `BLAKE3(BLAKE3(wasm_bytes))` with empty parameters, and the code\nhash as `BLAKE3(wasm_bytes)`. Both are required for the node to locate the delegate in its store.\n\n### Privacy Model\n\n- Posts are currently public and readable by anyone with the contract address\n- Identity keys are stored locally in the node's delegate store\n- Post signatures provide authenticity but not confidentiality\n- Future versions may support encrypted posts and private feeds\n\n## License\n\nFreenet Microblogging is open-source software. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffreenet%2Fraven","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffreenet%2Fraven","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffreenet%2Fraven/lists"}