{"id":25875956,"url":"https://github.com/andrewarrow/rusty-feedback","last_synced_at":"2026-02-13T17:03:29.928Z","repository":{"id":249734814,"uuid":"832387523","full_name":"andrewarrow/rusty-feedback","owner":"andrewarrow","description":null,"archived":false,"fork":false,"pushed_at":"2024-07-23T00:49:40.000Z","size":24,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-28T02:14:16.410Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"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/andrewarrow.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":"2024-07-22T23:36:18.000Z","updated_at":"2024-07-23T00:49:43.000Z","dependencies_parsed_at":"2024-07-23T03:12:44.087Z","dependency_job_id":null,"html_url":"https://github.com/andrewarrow/rusty-feedback","commit_stats":null,"previous_names":["andrewarrow/rusty_feedback"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/andrewarrow/rusty-feedback","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewarrow%2Frusty-feedback","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewarrow%2Frusty-feedback/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewarrow%2Frusty-feedback/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewarrow%2Frusty-feedback/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andrewarrow","download_url":"https://codeload.github.com/andrewarrow/rusty-feedback/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewarrow%2Frusty-feedback/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29412670,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-13T06:24:03.484Z","status":"ssl_error","status_checked_at":"2026-02-13T06:23:12.830Z","response_time":78,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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":"2025-03-02T10:20:13.660Z","updated_at":"2026-02-13T17:03:29.907Z","avatar_url":"https://github.com/andrewarrow.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# rusty-feedback\n\nThis is the web framework you use when it's your choice. This is a\nweb framework that makes it fun and easy to throw together anything\nweb related.\n\nIt's an opinionated framework.\n\nWe use full page refreshes by default. When frontend work is required we do that on a per page basis and it becomes an SPA.\n\nWe use \n\n```\ncargo install wasm-pack\n```\n\nto write all frontend logic still in rust. The frontend and the backend are rust.\n\nWe use .mu templates which look like:\n\n```\ndiv p-0 \n  {{ template \"navbar\" . }}\n  div flex justify-between\n    ul menu bg-base-200 menu-horizontal rounded-box\n      li\n        a href=./{{$guid}}\n          Services\n  div flex justify-center mt-3 p-3\n    div text-4xl\n      {{ .name }}\n```\n\nIt's just HTML but without having to close any tags (two spaces indent to show which tag is under another.) all the words after the tag are made classes. No need to type class=\"\".\nNo need to use quotes but you can't have spaces.\n\nUsing .mu files I can make tailwind and daisy designs fast. Its very easy to just add\na new parent div and indent children over. In normal HTML I'm 50% slower.\n\nThis all gets rendered to normal .html files with rust templates.\n\n```\n[dependencies]\ntera = \"1.13\"\nserde = { version = \"1.0\", features = [\"derive\"] }\n```\n\ntera is the way. We use the same template in the backend and frontend. wasm-pack will use tera and render what might be called server-side templates client side.\n\n\n[https://tailwindcss.com/](https://tailwindcss.com/) and [https://daisyui.com/](https://daisyui.com/) is how we make everything look polished and professional.\n\n[https://www.postgresql.org/](https://www.postgresql.org/) and [https://www.sqlite.org/](https://www.sqlite.org/) are the database we support.\n\n\n```\n    use std::collections::HashMap;\n\n    let rows = client.query(\"SELECT * FROM users\", \u0026[]).await?;\n\n    // Iterate over the rows and create dictionaries\n    let mut results = Vec::new();\n    for row in rows {\n        let mut row_dict = HashMap::new();\n        for (i, column) in row.columns().iter().enumerate() {\n            let column_name = column.name();\n            let value: Option\u003cString\u003e = row.try_get(i).unwrap_or(None);\n            row_dict.insert(column_name.to_string(), value);\n        }\n        results.push(row_dict);\n    }\n```\n\nThis is all you get in terms of an ORM. Ha. Well not really. But don't expect\nActive::Record. You can do a few basic things but can always drop down to \nFreeFormSelect and FreeFormUpdate when needed.\n\nWe don't strongly type things. We just use these HashMap everywhere for dealing\nwith data. When needed we make a \"model\" and start giving ourselves methods needed on something like a User database record. But for many database table records when they first enter our codebase, they are just HashMaps and nothing more. Only when I write the same logic a few times because there is no model do I stop interacting with HashMap directly and add an abstraction layer. NOT BEFORE. Before that happens its important to just\ninteract with the HashMap. Pre mature abstraction layer. PMAL. Bad.\n\nThere are root level routes:\n\n/foo\n\n/bar\n\n/other\n\nand then you have three controllers for foo, bar and other.\n\nInside these controllers a handle method is called with two strings, `second` and `third`.\n\n/foo/test1\n\n/foot/test1/test2\n\nFoo is first, then test1 is second and third is \"\" in the first example.\nIn the next example third is \"test2\".\n\nWhen just /foo is called you get both second == \"\" and third == \"\".\n\nYou check the method for POST or GET etc inside this method and route where you want.\n\nIf you need /foo/bar/something/a-forth break this into /new-top-level-route/better\n\nMigrations. They are additive. We run \n\n```\nalter table users add column foo\n```\n\nover and over every time the program starts and 99% of the time they are errors. But the errors are harmless. We never run drop table or drop column. You have to do those by hand but they are rare. \n\nBecause it's effortless to add a new column, you don't have to make a new file and have everyone run a migration. You just edit one json file (or yaml we might move this file to yaml to be more human editable) and everyone on the team is already running all migrations every single time they start the app.\n\n# origins\n\nThis repo is based off the golang version called just:\n\n[https://github.com/andrewarrow/feedback/](https://github.com/andrewarrow/feedback/)\n\nit has all these features above but in go vs rust.\n\nI'm slowly moving everything from go to rust and want to market this framework as rusty-feedback.\n\nThe name feedback comes from the coding style. Everything is very messy and in flux think saw-dust-on-the-floor construction site. As in, look at this function, see what it's doing? What do you think? Any feedback?\n\nAnd because you are shown the code with that frame of mind, here's a start of what I'm thinking, do you see the vision? I know it's not perfect, by all means, give me feedback. \n# show and tell\n\n[https://andrewarrow.dev/](https://andrewarrow.dev/)\n\n[https://script.fly.dev/](https://script.fly.dev/)\n\n[https://g-n-r.fly.dev/](https://g-n-r.fly.dev/)\n\n[https://foneproblem.com/](https://foneproblem.com/)\n\n[https://homeducky.com/](https://homeducky.com/)\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrewarrow%2Frusty-feedback","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandrewarrow%2Frusty-feedback","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrewarrow%2Frusty-feedback/lists"}