{"id":29208926,"url":"https://github.com/tikinang/sheeet","last_synced_at":"2026-04-28T13:32:34.372Z","repository":{"id":296066227,"uuid":"992219215","full_name":"tikinang/sheeet","owner":"tikinang","description":"Rust and WebAssembly powered spreadsheet.","archived":false,"fork":false,"pushed_at":"2025-07-01T09:06:34.000Z","size":224,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-01T10:24:30.643Z","etag":null,"topics":["rust","spreadsheet","wasm"],"latest_commit_sha":null,"homepage":"","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/tikinang.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,"zenodo":null}},"created_at":"2025-05-28T20:03:36.000Z","updated_at":"2025-07-01T09:06:38.000Z","dependencies_parsed_at":"2025-05-28T21:21:13.813Z","dependency_job_id":"434e106e-cc12-4277-a9ce-c4cdfbdcd705","html_url":"https://github.com/tikinang/sheeet","commit_stats":null,"previous_names":["tikinang/sheeet"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tikinang/sheeet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tikinang%2Fsheeet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tikinang%2Fsheeet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tikinang%2Fsheeet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tikinang%2Fsheeet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tikinang","download_url":"https://codeload.github.com/tikinang/sheeet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tikinang%2Fsheeet/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263212390,"owners_count":23431501,"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":["rust","spreadsheet","wasm"],"created_at":"2025-07-02T20:37:21.649Z","updated_at":"2026-04-28T13:32:34.366Z","avatar_url":"https://github.com/tikinang.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sheeet!\n\nRust and WebAssembly powered spreadsheet. **Sheeet!** is just a classic, in-browser spreadsheet, but with a twist: Users can define their own functions - in Rust - and use them to create and transform data in any way imaginable. Both _sync_ (sum range of numbers) and _async_ (fetch data over HTTP) functions are supported. \n\n![Sheeet logo.](/assets/sheeet-baner.png)\n\n## Public Demo\n\n\u003e [!WARNING]\n\u003e Don't share any sensitive information in the code to be compiled.\n\nLive at: [https://sheeet.matejpavlicek.cz](https://sheeet.matejpavlicek.cz?demo=true)\n\nSheet data lives in your browser, it is not sent to the public demo backend.\n\n## Disclaimer\nThis is my first project written in Rust, and it currently primarily serves as a learning opportunity.\nThe project is still v0. Be cautious using it in production - **you may lose your data**.\n\n[Security/Isolation Brainstorm](assets/security-isolation-brainstorm.md)\n\n## The Future\nThe current code editing in the browser is close to unusable. It would be great to sync the user's local code in the user's favorite code editor with the Sheeet! app, either via git or some form of ssh (scp).\n\nAdding SQL interface and some database-like functionalities would also be great.\n\n### WASM's (In)Efficiency\nThe initial idea of this project was: _\"Let's build a spreadsheet powered by Rust. It shall be fast and efficient (because Rust) and easy to use by Rust users.\"_ - Well, this idea dissolved rather quickly.\nThe current implementation relies heavily on the JS and WASM (wasm-bindgen) interface and the interpretability of JS to resolve user-defined functions. Majority of memory allocations is done in the JS runtime.\nThe communication between Rust WASM and JS is definitely not for free. One could make the argument that this hybrid is slower than vanilla JS.\n\n\u003e TODO: Benchmarks?\n\nWASM Rust platform has many limitations, many features (e.g. `thread::sleep()`, common HTTP client libs, ...) - that typical Rustacean is used to - are not available in `wasm32-unknown-unknown` target.\n\n### The Potential\nHaving said that, there are plans for WASM to eventually be able to manage the DOM directly without the need to jump to JS.\nAnd with some (a lot of) UI tweaks and enterprise-grade support for storing data, I believe this tool could make sense. The goal is still the same:\n\n\u003e Create browser enabled, fast and efficient, highly customizable spreadsheet for Rust power users.\n\nThis tool may eventually be useful for data analysts in their day job. Spreadsheet + SQL interface + Rust. What's not to like? :)\n\n## How to Deploy?\n\nThis quick tutorial will deploy your own **private** instance of Sheeet!, that is secured against public usage via `SHEEET_SECRET_API_KEY`.\nIf you wish to deploy public instance, just remove the `SHEEET_SECRET_API_KEY` secret environment variable from the import yaml file.\n\n1. Sign Up to [Zerops.io](https://app.zerops.io) (as of 2025 you'll receive free credits upon Sign Up)\n2. In the GUI navigate to \"Dashboard \u003e Import a project\"\n\n\u003cimg src=\"assets/import-project-zerops-gui.png\" alt=\"import-project-zerops-gui\" width=\"768\"/\u003e\n\nAnd paste there the following contents of `zerops-import.yml`:\n```yaml\n#yamlPreprocessor=on\nproject: \n  name: recipe-sheeet\n  tags:\n    - zerops-recipe\nservices:\n  - hostname: api\n    type: rust@stable\n    priority: 10\n    envSecrets:\n      SHEEET_SECRET_API_KEY: \u003c@generateRandomString(\u003c32\u003e)\u003e\n    maxContainers: 1\n    verticalAutoscaling:\n      minRam: 0.25\n    buildFromGit: https://github.com/tikinang/sheeet@main\n    enableSubdomainAccess: true\n  - hostname: app\n    type: static@latest\n    buildFromGit: https://github.com/tikinang/sheeet@main\n    enableSubdomainAccess: true\n```\n\n3. Wait for deployment process to finish\n4. Go to \"Dashboard \u003e `recipe-sheeet` \u003e `api` \u003e Environment Variables \u003e Secret Variables\" and copy the `SHEEET_SECRET_API_KEY` value\n\n\u003cimg src=\"assets/copy-secret-zerops-gui.png\" alt=\"copy-secret-zerops-gui\" width=\"768\"/\u003e\n\n5. Visit deployed site via \"Subdomain Access\" and set your API Key\n\n\u003cimg src=\"assets/set-api-key-sheeet-gui.png\" alt=\"set-api-key-sheeet-gui\" width=\"768\"/\u003e\n\n6. Enjoy!\n\n## TODOs and Contributing\n\nAny feedback, ideas or bug reports are warmly welcomed! Just open an issue.\n\n### Necessary\n- [x] implement spreadsheet functionality\n  - copy, cut, paste cell\n  - select and manipulate multiple cells\n  - deselect cell out when clicking in the editor\n- [x] support for range references\n- [x] create public lib crate with basic functions in prelude\n  - `add`, `sub`, `mul`, `div`, `pow` (match the operators below)\n  - `avg`, `sum`, `med`, `concat_with`\n  - `http_get` (enabled by a feature, keep the first compile nice and fast)\n- [x] enhance workspace isolation\n  - allow making API access private (`SHEEET_SECRET_API_KEY`)\n- [x] workspace management\n  - reset workspace (both ID and sheet data)\n  - set secret API key\n  - workspace status bar (ID, API key, compile status, save status)\n- [x] prepare Zerops Recipe for simple deployment\n- [x] better onboarding (default data and code with comments)\n- [x] extensive UI and error handling testing\n\n### Nice to Have\n- [ ] add operators support (`+`,`-`,`*`,`/`,`^`,`%`) in expression parsing\n- [ ] add and remove columns and rows\n- [ ] allow resizing columns and rows\n- [ ] cut should not change the expressions - should be 1:1\n- [ ] extender on range end\n- [ ] use `async` instead of spawning threads in `PUT /compile`\n- [ ] browser stored environment secrets\n- [ ] pre-heat workspaces for demo newcomers\n- [ ] on-save formatting support\n- [ ] code highlighting ([`highlight.js`](https://highlightjs.org))\n- [ ] allow more robust crate structure\n- [ ] shareable workspaces (both data and code)\n- [ ] add note to `README.md` where which data lives\n- [ ] support Vim motions\n- [ ] How does it work? section in `README.md`\n- [ ] export/import data as JSON\n- [ ] cheat-sheet tooltip\n- [ ] allow logging to the build log console from user defined functions (better debug)\n- [ ] autosave and versioning (ctrl+z)\n\n### Known Errors\n- [x] self reference should error\n- [x] update unbounded range dependents\n- [x] `=add(A1,,)` panics\n\n## Development\n\nPrerequisites:\n- Rust and Cargo installed (https://doc.rust-lang.org/cargo/getting-started/installation.html)\n- Trunk (WASM and JS packer) installed (`cargo install --locked trunk`)\n\nRunning locally:\n\n- start the API, API will listen on port `:8080` by default\n```shell\nmkdir $HOME/workspaces\nRUST_LOG=debug cargo run --package sheeet-api\n\n# changing the workspaces artifacts path, default is $HOME/workspaces\nexport SHEEET_WORKSPACES_PATH=/some/other/path \nRUST_LOG=debug cargo run --package sheeet-api\n``` \n- serve the GUI, GUI will be served on port `:7878`\n```shell\ncd ./wasm\ntrunk serve\n\n# with console debug logging enabled\ntrunk serve --features debug-log\n```\n- visit http://localhost:7878\n- `trunk serve` will auto-reload on changes in the `./wasm/...` code\n\nAdding base functions to the [sheeet_funcs::prelude](https://crates.io/crates/sheeet-funcs):\n- change `sheeet-funcs` dependency to local path in the user defined `Cargo.toml` (in the Sheeet! app) and hit CTRL-Enter\n```toml\n[dependencies]\nsheeet-funcs = { path=\"/path/to/the/cloned/sheeet/repo/funcs\", features=[\"fetch\"] }\n```\n- test the functionality in the app\n- write tests\n- and maybe publish your own crate to use it via `cargo publish`, or wait for maintainers to publish a new version","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftikinang%2Fsheeet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftikinang%2Fsheeet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftikinang%2Fsheeet/lists"}