# templ: an HTML templating language for Go that compiles ahead of time

> A Go library that adds typed HTML components, a formatter, a language server and a live reload proxy, with a README that documents the maintainers' tasks rather than the language itself.

**a-h/templ** — A language for writing HTML user interfaces in Go.

- Repository: https://github.com/a-h/templ
- Website: https://templ.guide/
- Stars: 10,548 · Forks: 366
- Language: Go
- License: MIT
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/a-h-templ

## A README that documents maintainer tasks instead of the language

The README on a-h/templ does something unusual for a language project: it lists the maintainers' task runner rather than the language itself. There is no install command on the page, no hello world, no tour of the syntax. What you get is a list of named tasks, each paired with the shell commands it runs. That makes the README a maintenance document rather than a tutorial, and it means a reader looking for how to start has to leave the repository entirely.

The task worth understanding first is `generate`, because it is the code generation step that turns `.templ` files into Go source:

```bash
go run ./cmd/templ generate -include-version=false
```

The `-include-version=false` flag is itself interesting. By default the generated code stamps the templ version into the output, which makes generated files change on every version bump. Passing the flag during development keeps those diffs out of the working tree, which is why the same invocation shows up in the `generate`, `test`, `test-short` and `benchmark` tasks.

Formatting is two tools in one command, and both halves are needed:

```bash
gofmt -s -w .
go run ./cmd/templ fmt .
```

Go files get gofmt, `.templ` files get the built in formatter. The separate `.templignore_fmt` file in the repository tree is where paths are excluded from that second pass.

## Where the generated code lives once it is written

The repository tree shows a project split along a clean line between the compiler and the runtime. `parser/`, `generator/`, `cmd/` and `internal/` belong to the side that reads `.templ` files and writes Go. `runtime/`, `safehtml/` and the flat top level files belong to the side that runs after compilation: `handler.go` for HTTP handling, `fragment.go` for fragments, `join.go` for joining element groups, `js.go` and `scripttemplate.go` for script elements, `jsonscript.go` and `jsonstring.go` for safe JSON embedding, `url.go` for URL handling, `once.go` for one time execution, `flush.go` for streaming flushes and `runtime.go` for the renderer itself.

Each of those top level files has a matching test file next to it, which is a small signal about how the project is maintained. So is `go.mod`, which declares Go 1.25.0 and pulls in a short, purposeful dependency list: brotli for compression, cors for the proxy, fsnotify for file watching, testify and go-cmp for assertions, `golang.org/x/tools` for the tooling side, and `github.com/a-h/parse`, a parser written by the same author.

That last dependency is worth noting. templ is not standing on a general purpose parser framework pulled in from elsewhere; the parsing library is part of the same author's work, and `parser/v2/` plus `parser/v2/goexpression/` are where its fuzzer scripts live.

## The language server is a first class part of the repository

templ advertises developer tooling as its headline feature, and `lsp/` is a top level directory rather than something tucked into a subproject. The topics on the repository agree: `language-server`, `lsp` and `ide-support` all appear there, alongside `server-side-rendering` and `htmx`.

The README's task list includes `docs-run` and `docs-build`, both scoped to the `docs` directory:

```bash
npm run start
npm run build
```

So the documentation site is a Docusaurus project living inside the same repository, which means the language documentation and the compiler can move in the same commit. Several release entries point the same way. v0.3.977 added prettier to the `templ info` command, and v0.3.1001 bumped the Docusaurus version. Getting an external formatter into the `info` output is a small feature, but it is aimed squarely at editor setup rather than runtime behaviour.

For a project whose pitch is a new syntax for Go, this is the part that decides whether it is pleasant to use day to day. The README does not document editor configuration, so the setup instructions live on templ.guide rather than in the repository.

## Concurrency, streaming and gzip fixes in v0.3.1020

Three releases are published in the repository: v0.3.977 on 2025-12-31, v0.3.1001 on 2026-02-28 and v0.3.1020 on 2026-05-10. Their notes are commit lists rather than written explanations, so the useful signal is which packages appear.

v0.3.1020 is the one with real behavioural changes: concurrent rendering of templ components, a fix for corrupted output in watch mode when gzip is in the pipeline, a `-check` flag added for the generate command to close issue 1007, and a fix that clears children context in `Fragment.Render`. It also adds `Range` tracking to ExpressionAttribute, GoCode and StringExpression nodes, which is what lets an editor highlight the exact span of a component in the source file rather than the whole template.

v0.3.1001 adds TLS support to the live reload proxy and strips whitespace from rendered CSS class names, closing issue 1074. v0.3.977 flushes streamed HTML from the proxy, adds `fallthrough` support in case statements, and fixes LSP diagnostics on Windows.

The pattern across all three is that the proxy, the language server and the generator are where the work lands. New language features are rare in these notes; correctness fixes are not.

## What the examples directory says about intended use

`examples/` holds twenty one directories, and the list is more informative than any documentation about them. Four are framework integrations: `integration-chi/`, `integration-echo/`, `integration-gin/` and `integration-gofiber/`. Two are static output: `hello-world-static/` and `static-generator/`. Two are streaming and partial updates: `streaming/` and `htmx-fragments/`. One is `suspense/`, which the v0.3.1020 notes reference directly in a fix about rendering the header inside a dedicated shadow host.

The remainder cover narrower cases: `content-security-policy/`, `internationalization/`, `typescript/`, `integration-react/`, `integration-go-echarts/`, `external-libraries/`, `blog/`, `crud/`, plus the `counter/`, `counter-basic/` and `hello-world-ssr/` starting points. A `storybook/` directory at the repository root suggests the component catalogue is developed outside the site generator.

Read together, the examples place templ in the server rendered world with an htmx lean, not in the component library world. That is a narrower claim than many templating languages make, and the directory names back it up.

The benchmarks live in their own `benchmarks/` directory and are driven by the same generate step as the tests:

```bash
go run ./cmd/templ generate -include-version=false && go test ./... -bench=. -benchmem
```

## Where the repository stops and templ.guide begins

The boundary is sharp enough to state plainly. The repository answers questions about how the project is built, released and linted. It answers nothing about how the language works. There is no syntax reference in the tree beyond `docs/`, and the README points readers at templ.guide rather than summarising anything.

For an evaluation, that split decides what you can learn where. Choosing between templ and html/template, or between templ and a JavaScript framework, is a question about syntax and escaping semantics, and templ.guide is where you answer it. Knowing what the project does about gzipped output during watch mode, what `-check` does, or where the Windows LSP diagnostics bug was fixed is a question the repository and the release notes answer well.

Two more details are worth carrying into any adoption decision. The license is MIT, and the release tags follow a `0.3.x` line with a four digit build component, which signals pre-1.0 stability rather than a settled API. Fuzzing is wired in as its own task for both the parser and the Go expression subparser:

```sh
./parser/v2/fuzz.sh
./parser/v2/goexpression/fuzz.sh
```

A parser project that keeps two fuzz harnesses is taking input handling seriously, even if the README never says so.

## Conclusion

templ is at its best when you want server rendered HTML in a Go service and you would rather not hand-write the plumbing around it: escaping is handled by the compiler, formatting is a task you can wire into a pre-commit hook, and the language server is part of the same repository rather than a separate community project. The README gives you almost none of the language itself, so templ.guide is the place to start learning, and the `examples/` directory is where you can see how the pieces fit into chi, echo, gin and gofiber services. Last push was on 2026-09-04, with v0.3.1020 published on 2026-05-10, and the changelogs in those releases are dominated by correctness fixes in the language server and the live reload proxy rather than new syntax.

## FAQ

### How do I install templ and start a project?

The repository README does not contain an install command, so templ.guide is the starting point. What the README does document is the code generation step that runs inside an existing Go module: `go run ./cmd/templ generate -include-version=false`. The `examples/hello-world-ssr/` and `examples/counter/` directories are the quickest way to see a working project layout.

### Does templ replace html/template in Go?

It is an alternative to it rather than a drop in replacement, because templ adds its own syntax, a compile step and a runtime package. The repository ships its own escaping and rendering code in `runtime/` and `safehtml/`, and the `examples/external-libraries/` directory suggests running templ output alongside existing libraries. The syntax comparison itself is documented on templ.guide.

### What is the templ language server and how do I use it with templ files?

The language server lives in the `lsp/` directory and is the reason the repository lists `language-server`, `lsp` and `ide-support` among its topics. Several releases have targeted it directly, including LSP diagnostics fixes on Windows in v0.3.977 and a `$GOROOT` workaround removal in v0.3.1020. Editor setup instructions are not in the README and live on templ.guide.

## Sources

- [a-h/templ on GitHub](https://github.com/a-h/templ)
- [License: MIT](https://github.com/a-h/templ/blob/main/LICENSE)
- [Project website](https://templ.guide/)
- [README](https://github.com/a-h/templ/blob/main/README.md)
- [Releases](https://github.com/a-h/templ/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/a-h-templ
