{"id":20838751,"url":"https://github.com/royalicing/dovetail","last_synced_at":"2025-05-08T21:29:13.054Z","repository":{"id":48569667,"uuid":"203948748","full_name":"RoyalIcing/dovetail","owner":"RoyalIcing","description":"Fast server rendered components in Go. Inspired by SwiftUI, React, Elm.","archived":false,"fork":false,"pushed_at":"2022-06-26T09:58:03.000Z","size":44,"stargazers_count":16,"open_issues_count":6,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-06-20T15:01:56.765Z","etag":null,"topics":["components","go","golang","html-components","tailwind","ui"],"latest_commit_sha":null,"homepage":"","language":"Go","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/RoyalIcing.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}},"created_at":"2019-08-23T07:37:24.000Z","updated_at":"2024-03-26T13:10:26.000Z","dependencies_parsed_at":"2022-09-26T20:00:56.810Z","dependency_job_id":null,"html_url":"https://github.com/RoyalIcing/dovetail","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoyalIcing%2Fdovetail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoyalIcing%2Fdovetail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoyalIcing%2Fdovetail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RoyalIcing%2Fdovetail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RoyalIcing","download_url":"https://codeload.github.com/RoyalIcing/dovetail/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225110549,"owners_count":17422411,"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":["components","go","golang","html-components","tailwind","ui"],"created_at":"2024-11-18T01:11:27.132Z","updated_at":"2024-11-18T01:11:27.738Z","avatar_url":"https://github.com/RoyalIcing.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dovetail\n\n_CURRENTLY IN ALPHA, API WILL CHANGE_\n\n[Documentation](https://godoc.org/github.com/RoyalIcing/dovetail)\n\nUser- and developer-friendly HTML Components for Go, inspired by SwiftUI/React/Elm.\n\n- Produce accessible HTML markup easily.\n- Make components with functions.\n- Supports ARIA and data attributes.\n- Conveniences for forms and lists.\n\n```go\nRender(\n  w,\n  Div(\n    Header(\n      Nav(\n        AriaLabel(\"Primary\"),\n        List(\n          Link(\"/\", Text(\"Home\")),\n          Link(\"/about\", Text(\"About\")),\n          Link(\"/pricing\", Text(\"Pricing\"), AriaCurrentPage),\n          Link(\"/sign-in\", Text(\"Sign In\")),\n          Link(\"/join\", Text(\"Join\")),\n        ),\n      ),\n    ),\n    Main(\n      Article(\n        H(1, Text(\"Welcome\")),\n        P(\"Render HTML using components with Go\"),\n      ),\n      FormTo(\"/newsletter\").With(\n        FieldLabelled(\"Email\", Textbox(\"email\")),\n        SubmitButton(Text(\"Sign up for the newsletter\")),\n      ),\n    ),\n  )\n)\n```\n\n## Provided components\n\nType: `HTMLElementView`\n\n### Landmarks\n\n- `Main(children ...HTMLView)` — [`\u003cmain\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main)\n- `Nav(children ...HTMLView)` — [`\u003cnav\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav)\n- `Header(children ...HTMLView)` — [`\u003cheader\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header)\n- `Footer(children ...HTMLView)` — [`\u003cfooter\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer)\n- `Section(children ...HTMLView)` — [`\u003csection\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section)\n- `Article(children ...HTMLView)` — [`\u003carticle\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article)\n- `Aside(children ...HTMLView)` — [`\u003caside\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside)\n\n### Structure\n\n- `Div(children ...HTMLView)` — [`\u003cdiv\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div)\n- `List(children ...HTMLView)` — `\u003cul\u003e\u003cli\u003e{ children[0] }\u003c/li\u003e…\u003cli\u003e{ children[n] }\u003c/li\u003e\u003c/ul\u003e`\n- `Ul(children ...HTMLView)` — [`\u003cul\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul)\n- `Li(children ...HTMLView)` — [`\u003cli\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li)\n- Coming soon: `\u003col\u003e`, `\u003cdl\u003e`\n\n### Elements\n\n- `Link(url string, children ...HTMLView)` — [`\u003ca href=\"{ url }\"\u003e{ children }\u003c/a\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)\n- `Button(children ...HTMLView)` — [`\u003cbutton type=\"button\"\u003e{ children }\u003c/button\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button)\n- `Img(srcUrl string, alt string, enhancers ...HTMLEnhancer)` — `\u003cimg src=\"{ srcUrl }\" alt=\"{ alt }\" {...enhancers}\u003e`\n- `P(children ...HTMLView)` — `\u003cp\u003e`\n- `TextWith(text string, enhancers ...HTMLEnhancer)` — `\u003cspan {...enhancers}\u003e{ text }\u003c/span\u003e`\n- `Noscript(children ...HTMLView)` — `\u003cnoscript\u003e{ children }\u003c/noscript\u003e`\n\n### Forms\n\n- `FormTo(action string, options ...func(form FormHTMLView) FormHTMLView)` — [`\u003cform\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form)\n  - `Multipart(form FormHTMLView) FormHTMLView` — [`\u003cform enctype=\"multipart/form-data\"\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attr-enctype)\n- `Textbox(inputName string, options ...FieldTextInputOption)` — [`\u003cinput type=\"text\"\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/text)\n- `SubmitButton(children ...HTMLView)` — [`\u003cbutton type=\"submit\"\u003e{ children }\u003c/button\u003e`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type)\n\n### Text nodes\n\n- `Text(text string)` — [HTML text node](https://developer.mozilla.org/en-US/docs/Web/API/Text)\n\n### Logic\n\n- `When(when bool, view HTMLView)` — renders the provided `view` only if `when` is `true`\n\n### Custom\n\n- `HTMLElementViewOf(tagName string, tagAtom atom.Atom, children []HTMLView)` — custom html element\n\n## Attributes\n\n- `AriaAttr` — [`aria-*`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques#States_and_properties)\n- `AriaLabel` — [`aria-label`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute)\n- `CustomAttr` — custom HTML attributes\n- `DataAttr` — [`data-*` attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-*)\n\n## Define components\n\nComponents are defined using functions. These functions can take any number of arguments, and return a composite of other components.\n\n```go\nfunc PrimaryButton(text string) View {\n\treturn Button(Text(text)).Class(\"btn btn-primary\")\n}\n```\n\n## Performance\n\nWhile not trying to be the fastest HTML producer possible, Dovetail aims to be faster than `html/template` to parse and execute.\n\nRun `make test_bench` to see how Dovetail performs to produce a variety of HTML components. Here are results on a 2016 15″ MacBook Pro:\n\n```\ngo test -p 1 -timeout 30s -bench=\"Bench\" -benchmem -v -run \"Bench\" ./...\ngoos: darwin\ngoarch: amd64\npkg: github.com/RoyalIcing/dovetail\nBenchmarkTailwindJustDiv-8                  \t 4758601\t       247 ns/op\t     272 B/op\t       2 allocs/op\nBenchmarkTailwind0Classes-8                 \t 4620313\t       249 ns/op\t     272 B/op\t       2 allocs/op\nBenchmarkTailwind2Classes-8                 \t 2074034\t       580 ns/op\t     400 B/op\t       6 allocs/op\nBenchmarkTailwind4Classes-8                 \t 1713938\t       694 ns/op\t     464 B/op\t       7 allocs/op\nBenchmarkTailwind8Classes-8                 \t 1349778\t       887 ns/op\t     640 B/op\t       8 allocs/op\nBenchmarkTailwindAddClasses2Classes-8       \t 1990402\t       601 ns/op\t     416 B/op\t       6 allocs/op\nBenchmarkTailwindAddClasses4Classes-8       \t 1771840\t       677 ns/op\t     480 B/op\t       6 allocs/op\nBenchmarkTailwindAddClasses8Classes-8       \t 1504893\t       783 ns/op\t     656 B/op\t       6 allocs/op\nBenchmarkTailwindDivWithClasses8Classes-8   \t 1757682\t       729 ns/op\t     528 B/op\t       5 allocs/op\nBenchmarkTailwindChangeClasses2Classes-8    \t 1797513\t       643 ns/op\t     464 B/op\t       8 allocs/op\nBenchmarkTailwindChangeClasses4Classes-8    \t 1533936\t       790 ns/op\t     560 B/op\t       9 allocs/op\nBenchmarkTailwindChangeClasses8Classes-8    \t 1234028\t       970 ns/op\t     800 B/op\t      10 allocs/op\nBenchmarkText-8                             \t 7639869\t       154 ns/op\t     128 B/op\t       2 allocs/op\nBenchmarkHeader-8                           \t 4320638\t       251 ns/op\t     272 B/op\t       2 allocs/op\nBenchmarkDiv-8                              \t 4858587\t       242 ns/op\t     272 B/op\t       2 allocs/op\nBenchmarkDivWithClasses1-8                  \t 2697412\t       445 ns/op\t     336 B/op\t       4 allocs/op\nBenchmarkDivWithClasses2Together-8          \t 2296304\t       519 ns/op\t     368 B/op\t       5 allocs/op\nBenchmarkDivWithClasses2-8                  \t 2066386\t       576 ns/op\t     384 B/op\t       6 allocs/op\nBenchmarkDivWithChildClassNames-8           \t 1734169\t       672 ns/op\t     448 B/op\t       9 allocs/op\nBenchmarkButton-8                           \t 2446404\t       478 ns/op\t     352 B/op\t       5 allocs/op\nBenchmarkButtonSubmit-8                     \t 2451301\t       480 ns/op\t     352 B/op\t       5 allocs/op\nBenchmarkH1-8                               \t 2267946\t       521 ns/op\t     448 B/op\t       6 allocs/op\nPASS\nok  \tgithub.com/RoyalIcing/dovetail\t39.216s\n```\n\n## Why?\n\nBecause I want to create server-rendered web apps that I can host cheaply on GCP App Engine Standard.\n\nI want something that is both user friendly (quick to load, accessible) while also being developer friendly.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froyalicing%2Fdovetail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froyalicing%2Fdovetail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froyalicing%2Fdovetail/lists"}