{"id":13478240,"url":"https://github.com/ekzhang/rustpad","last_synced_at":"2025-05-14T00:05:53.274Z","repository":{"id":37310238,"uuid":"372695773","full_name":"ekzhang/rustpad","owner":"ekzhang","description":"Efficient and minimal collaborative code editor, self-hosted, no database required","archived":false,"fork":false,"pushed_at":"2025-02-02T01:44:29.000Z","size":335,"stargazers_count":3677,"open_issues_count":9,"forks_count":162,"subscribers_count":30,"default_branch":"main","last_synced_at":"2025-04-10T15:57:20.487Z","etag":null,"topics":["async","code-editor","collaborative-editing","distributed-systems","operational-transformation","react","rust","self-hosted","tokio","typescript"],"latest_commit_sha":null,"homepage":"https://rustpad.io","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ekzhang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2021-06-01T03:58:36.000Z","updated_at":"2025-04-09T13:46:09.000Z","dependencies_parsed_at":"2024-01-08T07:57:30.445Z","dependency_job_id":"cbef9f98-88d6-4cc1-8a1e-93c7dbaff70e","html_url":"https://github.com/ekzhang/rustpad","commit_stats":{"total_commits":87,"total_committers":5,"mean_commits":17.4,"dds":0.09195402298850575,"last_synced_commit":"aa4ee8560a59178cd249c18bd6a21caa502ff73e"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekzhang%2Frustpad","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekzhang%2Frustpad/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekzhang%2Frustpad/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekzhang%2Frustpad/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ekzhang","download_url":"https://codeload.github.com/ekzhang/rustpad/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254043421,"owners_count":22004950,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["async","code-editor","collaborative-editing","distributed-systems","operational-transformation","react","rust","self-hosted","tokio","typescript"],"created_at":"2024-07-31T16:01:54.482Z","updated_at":"2025-05-14T00:05:53.240Z","avatar_url":"https://github.com/ekzhang.png","language":"Rust","funding_links":[],"categories":["Rust","typescript"],"sub_categories":[],"readme":"# Rustpad\n\n[![Docker Pulls](https://img.shields.io/docker/pulls/ekzhang/rustpad)](https://hub.docker.com/r/ekzhang/rustpad/)\n[![Docker Image Size](https://img.shields.io/docker/image-size/ekzhang/rustpad/latest)](https://hub.docker.com/r/ekzhang/rustpad/)\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/ekzhang/rustpad/ci.yml)](https://github.com/ekzhang/rustpad/actions/workflows/ci.yml)\n\n**Rustpad** is an _efficient_ and _minimal_ open-source collaborative text\neditor based on the operational transformation algorithm. It lets users\ncollaborate in real time while writing code in their browser. Rustpad is\ncompletely self-hosted and fits in a tiny Docker image, no database required.\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://rustpad.io/\"\u003e\n\u003cimg src=\"https://i.imgur.com/WjU5UrP.png\" width=\"800\"\u003e\u003cbr\u003e\n\u003cstrong\u003erustpad.io\u003c/strong\u003e\n\u003c/a\u003e\n\u003c/p\u003e\n\nThe server is written in Rust using the\n[warp](https://github.com/seanmonstar/warp) web server framework and the\n[operational-transform](https://github.com/spebern/operational-transform-rs)\nlibrary. We use [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) to\ncompile text operation logic to WebAssembly code, which runs in the browser. The\nfrontend is written in TypeScript using [React](https://reactjs.org/) and\ninterfaces with [Monaco](https://github.com/microsoft/monaco-editor), the text\neditor that powers VS Code.\n\nArchitecturally, client-side code communicates via WebSocket with a central\nserver that stores in-memory data structures. This makes the editor very fast,\nallows us to avoid provisioning a database, and makes testing much easier. The\ntradeoff is that documents are transient and lost between server restarts, or\nafter 24 hours of inactivity.\n\n## Development setup\n\nTo run this application, you need to install Rust, `wasm-pack`, and Node.js.\nThen, build the WebAssembly portion of the app:\n\n```\nwasm-pack build rustpad-wasm\n```\n\nWhen that is complete, you can install dependencies for the frontend React\napplication:\n\n```\nnpm install\n```\n\nNext, compile and run the backend web server:\n\n```\ncargo run\n```\n\nWhile the backend is running, open another shell and run the following command\nto start the frontend portion.\n\n```\nnpm run dev\n```\n\nThis command will open a browser window to `http://localhost:5173`, with hot\nreloading on changes.\n\n## Testing\n\nTo run integration tests for the server, use the standard `cargo test` command.\nFor the WebAssembly component, you can run tests in a headless browser with\n\n```\nwasm-pack test --chrome --headless rustpad-wasm\n```\n\n## Configuration\n\nAlthough the default behavior of Rustpad is to store documents solely in memory\nand collect garbage after 24 hours of inactivity, this can be configured by\nsetting the appropriate variables. The application server looks for the\nfollowing environment variables on startup:\n\n- `EXPIRY_DAYS`: An integer corresponding to the number of days that inactive\n  documents are kept in memory before being garbage collected by the server\n  (default 1 day).\n- `SQLITE_URI`: A SQLite connection string used for persistence. If provided,\n  Rustpad will snapshot document contents to a local file, which enables them to\n  be retained between server restarts and after their in-memory data structures\n  expire. (When deploying a Docker container, this should point to the path of a\n  mounted volume.)\n- `PORT`: Which local port to listen for HTTP connections on (defaults to 3030).\n- `RUST_LOG`: Directives that control application logging, see the\n  [env_logger](https://docs.rs/env_logger/#enabling-logging) docs for more\n  information.\n\n## Deployment\n\nRustpad is distributed as a single 6 MB Docker image, which is built\nautomatically from the `Dockerfile` in this repository. You can pull the latest\nversion of this image from Docker Hub. It has multi-platform support for\n`linux/amd64` and `linux/arm64`.\n\n```\ndocker pull ekzhang/rustpad\n```\n\n(You can also manually build this image with `docker build -t rustpad .` in the\nproject root directory.) To run locally, execute the following command, then\nopen `http://localhost:3030` in your browser.\n\n```\ndocker run --rm -dp 3030:3030 ekzhang/rustpad\n```\n\nWe deploy a public instance of this image using [Fly.io](https://fly.io/).\n\n## In the media\n\n- **July 11, 2021:** Featured in\n  [Console 61 - The open-source newsletter](https://console.substack.com/p/console-61).\n- **June 5, 2021:** Front-page\n  [Hacker News post](https://news.ycombinator.com/item?id=27408326). Reddit\n  discussions in [r/rust](https://www.reddit.com/r/rust/comments/nt4p9f/) and\n  [r/programming](https://www.reddit.com/r/programming/comments/nt4ws7/).\n\n\u003cbr\u003e\n\n\u003csup\u003e\nAll code is licensed under the \u003ca href=\"LICENSE\"\u003eMIT license\u003c/a\u003e.\n\u003c/sup\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekzhang%2Frustpad","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fekzhang%2Frustpad","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekzhang%2Frustpad/lists"}