{"id":13693654,"url":"https://github.com/maragudk/gomponents","last_synced_at":"2025-05-14T06:12:13.202Z","repository":{"id":37995111,"uuid":"294889564","full_name":"maragudk/gomponents","owner":"maragudk","description":"HTML components in pure Go.","archived":false,"fork":false,"pushed_at":"2025-05-06T13:31:04.000Z","size":473,"stargazers_count":1546,"open_issues_count":1,"forks_count":46,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-05-08T09:04:53.306Z","etag":null,"topics":["go","golang","gomponents","html"],"latest_commit_sha":null,"homepage":"https://www.gomponents.com","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/maragudk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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":{"custom":["https://maragu.gumroad.com/l/gomponents"]}},"created_at":"2020-09-12T07:01:22.000Z","updated_at":"2025-05-08T02:17:36.000Z","dependencies_parsed_at":"2024-03-12T17:52:18.793Z","dependency_job_id":"58748f3d-a146-45dd-9715-9c88c8b1c70c","html_url":"https://github.com/maragudk/gomponents","commit_stats":null,"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maragudk%2Fgomponents","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maragudk%2Fgomponents/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maragudk%2Fgomponents/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maragudk%2Fgomponents/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maragudk","download_url":"https://codeload.github.com/maragudk/gomponents/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254080305,"owners_count":22011371,"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":["go","golang","gomponents","html"],"created_at":"2024-08-02T17:01:14.821Z","updated_at":"2025-05-14T06:12:13.194Z","avatar_url":"https://github.com/maragudk.png","language":"Go","funding_links":["https://maragu.gumroad.com/l/gomponents"],"categories":["开源类库","Open source library","Go","Repositories","\u003ca name=\"Go\"\u003e\u003c/a\u003eGo"],"sub_categories":["文本处理","Word Processing"],"readme":"# Tired of complex template languages?\n\n\u003cimg src=\"logo.png\" alt=\"Logo\" width=\"300\" align=\"right\"\u003e\n\n[![GoDoc](https://pkg.go.dev/badge/maragu.dev/gomponents)](https://pkg.go.dev/maragu.dev/gomponents)\n[![CI](https://github.com/maragudk/gomponents/actions/workflows/ci.yml/badge.svg)](https://github.com/maragudk/gomponents/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/maragudk/gomponents/branch/main/graph/badge.svg)](https://codecov.io/gh/maragudk/gomponents)\n[![Go Report Card](https://goreportcard.com/badge/maragu.dev/gomponents)](https://goreportcard.com/report/maragu.dev/gomponents)\n\nTry HTML components in pure Go.\n\n_gomponents_ are HTML components written in pure Go.\nThey render to HTML 5, and make it easy for you to build reusable components.\nSo you can focus on building your app instead of learning yet another templating language.\n\n```shell\ngo get maragu.dev/gomponents\n```\n\nMade with ✨sparkles✨ by [maragu](https://www.maragu.dev/): independent software consulting for cloud-native Go apps \u0026 AI engineering.\n\n[Contact me at markus@maragu.dk](mailto:markus@maragu.dk) for consulting work, or perhaps an invoice to support this project?\n\n## Features\n\nCheck out [www.gomponents.com](https://www.gomponents.com) for an introduction.\n\n- Build reusable HTML components\n- Write declarative HTML 5 in Go without all the strings, so you get\n  - Type safety from the compiler\n  - Auto-completion from the IDE\n  - Easy debugging with the standard Go debugger\n  - Automatic formatting with `gofmt`/`goimports`\n- Simple API that's easy to learn and use (you know most already if you know HTML)\n- Useful helpers like\n  - `Text` and `Textf` that insert HTML-escaped text,\n  - `Raw` and `Rawf` for inserting raw strings,\n  - `Map` for mapping data to components and `Group` for grouping components,\n  - and `If`/`Iff` for conditional rendering.\n- No external dependencies\n- Mature and stable, no breaking changes\n\n## Usage\n\n```shell\ngo get maragu.dev/gomponents\n```\n\n```go\npackage main\n\nimport (\n\t. \"maragu.dev/gomponents\"\n\t. \"maragu.dev/gomponents/components\"\n\t. \"maragu.dev/gomponents/html\"\n)\n\nfunc Navbar(authenticated bool, currentPath string) Node {\n\treturn Nav(\n\t\tNavbarLink(\"/\", \"Home\", currentPath),\n\t\tNavbarLink(\"/about\", \"About\", currentPath),\n\t\tIf(authenticated, NavbarLink(\"/profile\", \"Profile\", currentPath)),\n\t)\n}\n\nfunc NavbarLink(href, name, currentPath string) Node {\n\treturn A(Href(href), Classes{\"is-active\": currentPath == href}, g.Text(name))\n}\n```\n\n(Some people don't like dot-imports, and luckily it's completely optional.)\n\nFor a more complete example, see [the examples directory](internal/examples/).\nThere's also the [gomponents-starter-kit](https://github.com/maragudk/gomponents-starter-kit) for a full application template.\n\n## Architecture\n\ngomponents is organized into several packages:\n\n- `gomponents`: Core interfaces and functions like `Node`, `El`, `Attr`, and helpers like `Map`, `Group`, `If`, `Text`, `Raw`.\n- `gomponents/html`: HTML elements and attributes.\n- `gomponents/components`: Higher-level components and utilities.\n- `gomponents/http`: HTTP-related utilities for web servers.\n\n### Void Elements\n\nVoid elements in HTML (like `\u003cbr\u003e`, `\u003cimg\u003e`, `\u003cinput\u003e`) don't have closing tags.\ngomponents handles these correctly by checking against an internal list of void elements during rendering.\nWhen you create a void element, any child nodes that are not attributes will be ignored automatically to ensure valid HTML output.\n\n## Performance Considerations\n\ngomponents renders directly to an `io.Writer`, making it efficient for server-side rendering.\nThe library avoids unnecessary allocations where possible.\n\n## FAQ\n\n### Is gomponents production-ready?\n\nYes! gomponents is mature, stable, fully tested with 100% coverage, and has been used in production by myself and many others.\n\n### Should I choose `html/template`, Templ, or gomponents?\n\nThese are all good choices, and it largely comes down to preference.\nI wrote gomponents because I didn't like how I think it's hard to pass data around between templates in `html/template`.\ngomponents is pure Go, with no extra build step like Templ, so it works with all tools that already support Go.\n\nThat said, both `html/template` and Templ will do the same thing as gomponents in the end. Try them all and choose what you like!\n\n### I don't like how HTML looks in Go.\n\nFirst of all, that's not a question. 😉\n\nMore seriously, think of gomponents like a DSL for HTML. You're building UI components. Give it a day, and it'll feel natural.\n\n### I'd like to add feature X, can I do that?\n\nFirst of all, thank you for wanting to contribute! 😊 See [CONTRIBUTING.md](CONTRIBUTING.md) for a guide.\n\nI accept code contributions, especially with new HTML elements and attributes.\nI always welcome issues discussing interesting aspects of gomponents, and obviously bug reports and the like.\nBut otherwise, I consider gomponents pretty much feature complete.\n\nNew features to the core library are unlikely to be merged, since I like keeping it simple and the API small.\nIn particular, new functions around collections (similar to `Map`) or flow control (`IfElse`/`Else`) will not be added.\n`Map` was introduced before generics where a thing, and I think it's better to start using generic functions\nfrom the stdlib or other libraries, instead of adding gomponents-specific variations of them to this library.\n\nIf there's something missing that you need, I would recommend to keep small helper functions around in your own projects.\nAnd if all else fails, you can always use an [IIFE](https://developer.mozilla.org/en-US/docs/Glossary/IIFE):\n\n```go\nfunc list(ordered bool) Node {\n\treturn func() Node {\n\t\t// Do whatever you need to do, imperatively\n\t\tif ordered {\n\t\t\treturn Ol()\n\t\t} else {\n\t\t\treturn Ul()\n\t\t}\n\t}()\n}\n```\n\n### What's up with the specially named elements and attributes?\n\nUnfortunately, there are some name clashes in HTML elements and attributes, so they need an `El` or `Attr` suffix,\nto be able to co-exist in the same package in Go.\n\nI've chosen one or the other based on what I think is the common usage.\nIn either case, the less-used variant also exists in the codebase:\n\n- `cite` (`Cite`/`CiteAttr`, `CiteEl` also exists)\n- `data` (`DataEl`/`Data`, `DataAttr` also exists)\n- `form` (`Form`/`FormAttr`, `FormEl` also exists)\n- `label` (`Label`/`LabelAttr`, `LabelEl` also exists)\n- `style` (`StyleEl`/`Style`, `StyleAttr` also exists)\n- `title` (`TitleEl`/`Title`, `TitleAttr` also exists)\n\n\u003cdetails\u003e\n\t\u003csummary\u003eExample with `Style` and `StyleEl`\u003c/summary\u003e\n\n```go\npackage html\n\nimport (\n\t. \"maragu.dev/gomponents\"\n\t. \"maragu.dev/gomponents/components\"\n\t. \"maragu.dev/gomponents/html\"\n)\n\nfunc MyPage() Node {\n\treturn HTML5(HTML5Props{\n\t\tTitle: \"My Page\",\n\t\tHead: []Node{\n\t\t\tStyleEl(g.Raw(\"body {background-color: #fff; }\")),\n\t\t},\n\t\tBody: []Node{\n\t\t\tH1(Style(\"color: #000\"), Text(\"My Page\")),\n\t\t},\n\t})\n}\n```\n\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaragudk%2Fgomponents","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaragudk%2Fgomponents","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaragudk%2Fgomponents/lists"}