{"id":13502929,"url":"https://github.com/ivanceras/sauron","last_synced_at":"2025-05-14T05:00:27.068Z","repository":{"id":34641565,"uuid":"181514298","full_name":"ivanceras/sauron","owner":"ivanceras","description":"A versatile web framework and library for building client-side and server-side web applications","archived":false,"fork":false,"pushed_at":"2025-01-27T11:51:25.000Z","size":5282,"stargazers_count":2023,"open_issues_count":6,"forks_count":59,"subscribers_count":29,"default_branch":"master","last_synced_at":"2025-05-07T00:04:54.205Z","etag":null,"topics":["dom","elm","html","react","ssr","vdom","web"],"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/ivanceras.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.md","contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"ivanceras","patreon":"ivanceras","open_collective":"sauron","ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2019-04-15T15:21:54.000Z","updated_at":"2025-04-28T16:05:48.000Z","dependencies_parsed_at":"2023-01-15T08:15:51.651Z","dependency_job_id":"24c4736e-05f7-44e6-9d7c-41d2bc9355da","html_url":"https://github.com/ivanceras/sauron","commit_stats":{"total_commits":2231,"total_committers":12,"mean_commits":"185.91666666666666","dds":0.009412819363514124,"last_synced_commit":"6a374abda479fed19ef10c324b9a91e3015a53a3"},"previous_names":[],"tags_count":113,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivanceras%2Fsauron","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivanceras%2Fsauron/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivanceras%2Fsauron/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivanceras%2Fsauron/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ivanceras","download_url":"https://codeload.github.com/ivanceras/sauron/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253641205,"owners_count":21940690,"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":["dom","elm","html","react","ssr","vdom","web"],"created_at":"2024-07-31T22:02:30.701Z","updated_at":"2025-05-14T05:00:26.691Z","avatar_url":"https://github.com/ivanceras.png","language":"Rust","funding_links":["https://github.com/sponsors/ivanceras","https://patreon.com/ivanceras","https://opencollective.com/sauron"],"categories":["Rust","Libraries","库 Libraries","Inspired by Elm","Alternatives"],"sub_categories":["Web programming","网络编程 Web programming","Games","Frameworks"],"readme":"![Maintenance](https://img.shields.io/badge/maintenance-activly--developed-brightgreen.svg)\n\n# sauron\n\n\n[![Latest Version](https://img.shields.io/crates/v/sauron.svg)](https://crates.io/crates/sauron)\n[![Build Status](https://img.shields.io/github/workflow/status/ivanceras/sauron/Rust)](https://github.com/ivanceras/sauron/actions/workflows/rust.yml)\n[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)\n\n![sauron](https://raw.githubusercontent.com/ivanceras/sauron/master/assets/sauron.png)\n\n**Sauron** is a versatile web framework and library for building client-side and/or server-side web applications\nwith strong focus on ergonomics, simplicity and elegance.\nThis allows you to write least amount of code possible, and focus more on the business logic rather than the inner details of the framework.\n\nSauron is inspired by elm-lang and is following The Elm Architecture.\n\n#### Features\n- server-side rendering\n- static site generation\n- progressive rendering\n- web components / custom-element\n- html syntax for writing views\n- elegant macro to write styles\n- batteries included\n- standalone DOM/VirtualDOM patcher\n  (see [`examples/patch_dom_node`](https://github.com/ivanceras/sauron/tree/master/examples/patch_dom_node))\n\n### Devoid of unnecessary framework complexities\n- **no** framework specific cli needed\n- **no** template specific language as everything is in rust.\n    - Model and update function is all in rust.\n    - view? in rust\n    - events handling? rust\n    - styling? believe it or not: rust\n\nIn a sauron application, there is only the model, view and update.\nThe model is your application state.\nThe view describes how to present the model to the user.\nThe update function describes how to update the model, this uses message which contains the data needed for updating the model.\n\n\n#### Counter example\nIn your `src/lib.rs`\n```rust\nuse sauron::{\n    html::text, html::units::px, jss, node, wasm_bindgen, Application, Cmd, Node, Program,\n};\n\nenum Msg {\n    Increment,\n    Decrement,\n    Reset,\n}\n\nstruct App {\n    count: i32,\n}\n\nimpl App {\n    fn new() -\u003e Self {\n        App { count: 0 }\n    }\n}\n\nimpl Application for App {\n\n    type MSG = Msg;\n\n    fn view(\u0026self) -\u003e Node\u003cMsg\u003e {\n        node! {\n            \u003cmain\u003e\n                \u003cinput type=\"button\"\n                    value=\"+\"\n                    on_click=|_| {\n                        Msg::Increment\n                    }\n                /\u003e\n                \u003cbutton class=\"count\" on_click=|_|{Msg::Reset} \u003e{text(self.count)}\u003c/button\u003e\n                \u003cinput type=\"button\"\n                    value=\"-\"\n                    on_click=|_| {\n                        Msg::Decrement\n                    }\n                /\u003e\n            \u003c/main\u003e\n        }\n    }\n\n    fn update(\u0026mut self, msg: Msg) -\u003e Cmd\u003cMsg\u003e {\n        match msg {\n            Msg::Increment =\u003e self.count += 1,\n            Msg::Decrement =\u003e self.count -= 1,\n            Msg::Reset =\u003e self.count = 0,\n        }\n        Cmd::none()\n    }\n\n    fn stylesheet() -\u003e Vec\u003cString\u003e {\n        vec![jss! {\n            \"body\":{\n                font_family: \"verdana, arial, monospace\",\n            },\n\n            \"main\":{\n                width: px(30),\n                height: px(100),\n                margin: \"auto\",\n                text_align: \"center\",\n            },\n\n            \"input, .count\":{\n                font_size: px(40),\n                padding: px(30),\n                margin: px(30),\n            }\n        }]\n    }\n}\n\n#[wasm_bindgen(start)]\npub fn start() {\n    Program::mount_to_body(App::new());\n}\n```\n\n`index.html`\n\n```html\n\u003c!doctype html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003cmeta content=\"text/html;charset=utf-8\" http-equiv=\"Content-Type\"/\u003e\n    \u003ctitle\u003eCounter\u003c/title\u003e\n    \u003cscript type=module\u003e\n        import init from './pkg/counter.js';\n        await init().catch(console.error);\n    \u003c/script\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\nIn `Cargo.toml`, specify the crate-type to be `cdylib`\n\n```toml\n[package]\nname = \"counter\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\nsauron = \"0.61.0\"\n```\n\n#### Prerequisite:\n\n```sh\ncargo install wasm-pack\ncargo install basic-http-server\n```\n\n\nBuild using\n```sh\nwasm-pack build --target web --release\n```\nServe using\n```sh\nbasic-http-server -a 0.0.0.0:4000\n```\nThen navigate to http://localhost:4000\n\nHead over to the [`getting-started.md`](docs/getting-started.md) for the full tutorial.\n\nFor more details on the commands to build and serve, look on [examples](https://github.com/ivanceras/sauron/tree/master/examples) on this repo, each\nhas scripts on how to build and run them.\n\n\n#### Demo examples\n- [todomvc](https://ivanceras.github.io/todomvc/) The todomvc example\n- [data-viewer](https://ivanceras.github.io/data-viewer/) - A resizable spreadsheet CSV data viewer\n- [svg-clock](https://ivanceras.github.io/svg-clock/) - A clock drawn using SVG and window tick event.\n- [ultron code-editor](https://ivanceras.github.io/ultron/) - A web-base text-editor with syntax highlighting\n- [hackernews-sauron](https://github.com/ivanceras/hackernews-sauron) - A hackernews clone showcasing the feature of sauron to write web applications that can work with or without javascript.\n\n\n\nLicense: MIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivanceras%2Fsauron","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivanceras%2Fsauron","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivanceras%2Fsauron/lists"}