{"id":18761302,"url":"https://github.com/patte/axum-solid-playground","last_synced_at":"2025-09-01T17:30:39.020Z","repository":{"id":220692944,"uuid":"751934208","full_name":"patte/axum-solid-playground","owner":"patte","description":"playground for: axum (rust), solidJS, passkeys, sqlite, rusqlite, sessions, graphql, fly.io","archived":false,"fork":false,"pushed_at":"2024-02-20T18:52:00.000Z","size":393,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-12-20T12:59:48.956Z","etag":null,"topics":["axum","hmr","litefs","passkeys","proxy","rust","solidjs","sqlite","web-development"],"latest_commit_sha":null,"homepage":"https://axum-solid-playground.fly.dev","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/patte.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}},"created_at":"2024-02-02T16:41:07.000Z","updated_at":"2024-11-16T13:20:04.000Z","dependencies_parsed_at":"2024-02-15T21:48:03.247Z","dependency_job_id":null,"html_url":"https://github.com/patte/axum-solid-playground","commit_stats":null,"previous_names":["patte/axum-solid-playground"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patte%2Faxum-solid-playground","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patte%2Faxum-solid-playground/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patte%2Faxum-solid-playground/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patte%2Faxum-solid-playground/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/patte","download_url":"https://codeload.github.com/patte/axum-solid-playground/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231701585,"owners_count":18413419,"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":["axum","hmr","litefs","passkeys","proxy","rust","solidjs","sqlite","web-development"],"created_at":"2024-11-07T18:15:37.540Z","updated_at":"2024-12-29T04:53:50.037Z","avatar_url":"https://github.com/patte.png","language":"TypeScript","readme":"# axum-solid-playground\n\nTest your passkeys at: https://axum-solid-playground.fly.dev\n\nFeatures:\n- [x] Rust backend with [axum](https://github.com/tokio-rs/axum)\n- [x] Database integration: rusqlite\n- [x] [SolidJS](https://www.solidjs.com) frontend with [vite](https://vitejs.dev/)\n- [x] [solid-ui](https://www.solid-ui.com/) for UI components\n- [x] [Dev proxy](./server/src/proxy.rs) for frontend in backend\n- [x] Prod: embed client js dist in rust binary \n- [x] Discoverable [passkeys](https://www.passkeys.io/technical-details) for authentication with [webauthn-rs](https://github.com/kanidm/webauthn-rs/blob/d278c56adfa39a0723c79bdcd461644194bc5138/webauthn-rs/src/lib.rs#L1270)\n- [x] be: session management: [tower-sessions-rusqlite-store](https://github.com/patte/tower-sessions-rusqlite-store)\n- [x] be: roll expire of session on request (max every minute)\n- [x] be: session management: write informative cookie for fe\n- [x] fe: session management: [AuthContext](./client/src/components/auth/AuthContext.tsx)\n- [x] fe: session: detect expire and refresh ui\n- [x] Deployment (fly.io)\n- [x] ~~[litefs](https://fly.io/docs/litefs/) for distributed SQLite~~ removed, [no websockets](https://github.com/superfly/litefs/issues/427)\n- [x] PR [maxcountryman/tower-sessions-stores#6](https://github.com/maxcountryman/tower-sessions-stores/pull/6)\n- [x] publish crate [tower-sessions-rusqlite-store](https://github.com/patte/tower-sessions-rusqlite-store)\n- [x] [rspc](https://github.com/oscartbeaumont/rspc)? cool idea but 🚫 [no support for axum 0.7](https://github.com/oscartbeaumont/httpz/blob/main/Cargo.toml#L50) and generally a big mess\n- [x] GraphQL with [async-graphql](https://github.com/async-graphql/async-graphql) for typed api between server and client\n- [x] allow users to register additional passkeys\n- [x] ui: passkey details \n- [ ] security headers\n- [ ] signout all my sessions\n- [ ] ui: server info, debug network\n- [ ] github action\n- [ ] websockets?\n- [ ] distributed kv?\n- [ ] ssr?\n- [ ] ... the possibilities are endless, the time so short\n\nPlayground to learn:\n- how to combine a rust axum backend with a solidJS frontend?\n- how to authenticate users with discoverable passkeys? and what's the user experience in different browsers?\n- how to manage a session on the server with persistence and sync to the js client (on first render) (MVP)? - async sqlite in rust, yes please #no_orm?\n- how cool is litefs and how to (ab)use it?\n- how to have fun, go light and fast, with a small (\u003c10MB) single standalone binary, that uses \u003c100MB RAM idle.\n- ... all PRs welcome 💓\n- ... and all issues too 🤗\n\n\u003e \u003cimg width=\"475\" alt=\"Screenshot 2024-02-07 at 23 10 20\" src=\"https://github.com/patte/axum-solid-playground/assets/3500621/86e3834a-45e0-4bb4-a4fc-28d0cd7a4682\"\u003e\u003c/br\u003e\n\u003e -GitHub Copilot\n\u003e \u003cdetails\u003e\u003csummary\u003eactually...\u003c/summary\u003e\n\u003e \u003cimg width=\"882\" alt=\"Screenshot 2024-02-07 at 23 11 58\" src=\"https://github.com/patte/axum-solid-playground/assets/3500621/76fd47aa-2059-42a9-bfb0-6b3c9f79715a\"\u003e\n\u003e \u003c/details\u003e\n\n\n## Development\n\nCopy `.env.example` to `.env`:\n```bash\ncd server\ncp .env.example .env\ncd ..\n```\n\nThe rust backend includes a [dev proxy](./server/src/proxy.rs) for the frontend, so that the host and port of the fe and be is the same, no CORS issues arise, increased dev prod parity, good dev-ex with hot reloading.\n\nIn one terminal, run vite:\n```bash\ncd client\nnpm install\nnpm run dev\n```\n\nIn another terminal, run the backend server:\n```bash\ncd server\ncargo watch -x \"run --features dev_proxy\"\n```\n\nOpen [http://localhost:3000](http://localhost:3000) to view it in your browser.\n\n## Prod\n\n### Local\n[axum-embed](https://github.com/informationsea/axum-embed) is used to embed the frontend into the backend. For single binary niceness.\n\n```bash\ncd client\nnpm run build\ncd ..\ncargo build --release\n./target/release/axum-solid-playground\n```\nThe resulting binary is ~8MB.\n\n### fly.io\n\n#### volume\nCreate volume initially:\n```bash\nfly launch --no-deploy\n\n# if no volume created during initial launch:\nfly volumes create playground --region ams --size 3\n```\n\n#### envs\nSet before the first deploy:\n```bash\nfly secrets set \\\nRP_ID=axum-solid-playground.fly.dev \\\nRP_ORIGIN=https://axum-solid-playground.fly.dev \\\nRP_NAME=axum-solid-playground \\\nDATABASE_URL=sqlite:///data/playground.db\n```\n\n#### deploy\n\n```bash\nfly deploy\n```\n*image size: 104 MB* (but as our binary is only ~8MB, this is what needs to be pushed in most cases)\n\n#### add clones in other regions\nCurrently there is only one database on one volume (in ams). Litefs, which would enable distributed SQLite, was removed again, mainly to keep things simple and [the limitations with websockets](https://github.com/superfly/litefs/issues/427) . Only one instance can be run at a time.\n\nremove:\n```bash\nfly machine ls\nfly m destroy \u003cid\u003e\nfly volumes ls\nfly volumes destroy \u003cid\u003e\n```\n\n## Docs\n\n### Auth\nSignUp and SignIn are implemented with passkeys with [webauthn-rs](https://github.com/kanidm/webauthn-rs).\n\n[tower-sessions](https://github.com/maxcountryman/tower-sessions/tree/52983f026f0c805598e68f82647a0865b29a60bd) with a custom [RusqliteStore](./server/src/rusqlite_session_store.rs) is used for session management.\n\nThe session is used for the passkey dance as well as to remember the authenticated user.\nA cookie `authenticated_user_js` (http_only=false) is set on successful signin so that the [js frontend knows](./client/src/components/auth/AuthContext.tsx) the user is authenticated and can render appropriatly on first load.\nThis cookie is only informative for the client and not used to determine if the user is authenticated on the server. No auth decision on the server is based on the cookie.\n\nThe session are rolled every minute (see: roll_expiry_mw). This also keeps the informative cookie fresh.\n\n\n### Browsers\n\nChrome (local) passkeys can be managed at [chrome://settings/passkeys](chrome://settings/passkeys).\n\nFirefox and Safari on MacOS save them in the system keychain, which can be managed in Settings -\u003e Passwords.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatte%2Faxum-solid-playground","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpatte%2Faxum-solid-playground","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatte%2Faxum-solid-playground/lists"}