A Go Templ web frontend development environment that automatically rebuilds the server and reloads the tab.
Go
120
203 commits
updated Sep 21, 2026
Templiér is a Go web frontend development environment for
Templ
that works similarly to templ's native
--watch mode but provides
more functionality and reports errors directly to all open browser tabs ✨.
Templiér allows arbitrary CLI commands to be defined as custom watchers ✨.
Templiér is an integral part of github.com/romshark/datapages.
Install Templiér:
go install github.com/romshark/templier@latest
Then copy example-config.yml to your project source folder as templier.yml, adjust it to your needs, and run:
templier --config ./templier.yml
ℹ️ Templiér automatically detects templier.yml and templier.yaml in the current directory without requiring the explicit --config flag.
Templiér runs on Linux, macOS and Windows. Behavior is identical on all three except for the following Windows specifics:
cmd runs through cmd /C instead of sh -c.
Even where a POSIX shell is on PATH (Git Bash for example), it isn't used.Access is denied. Windows refuses to rename a directory while its
sub-directories are held open for watching.Glob expressions in app.exclude and in custom watcher include and exclude
always use forward slashes (/) as path separators, on all platforms,
regardless of the path separator the operating system itself uses.
As you may already know, templ supports live reload
out of the box using templ generate --watch --proxy="http://localhost:8080" --cmd="go run .",
which is great, but Templiér provides an even better developer experience:
app.exclude or is handled by a custom watcher).
Editing an embedded .json file in your app?
Updating go.mod? Templiér will notice, rebuild, restart, and reload the browser
tab for you automatically!Custom watchers let you change how Templiér behaves for files that match any of
the include globs, and they can be used for the use cases shown below.
cmd runs through a shell (sh -c, cmd /C on
Windows). include and exclude globs always use
forward slashes as path separators.
The requires option lets you override the default behavior:
cmd.reload: Only reload all open browser tabs.restart: Restarts the server without rebuilding.rebuild: Requires the server to be rebuilt and restarted (standard behavior).If custom watcher A requires reload but custom watcher B requires rebuild,
rebuild will be chosen once all custom watchers have finished executing.
The following custom watcher watches for .js file updates and automatically runs
the CLI command npm run js:bundle, after which all browser tabs will be reloaded
using requires: reload. fail-on-error: true means that if eslint or esbuild
fails, their error output will be shown directly in the browser.
custom-watchers:
- name: Bundle JS
cmd: npm run bundle:js
include: ["**/*.js", "**/*.jsx"]
exclude: ["path/to/your/dist.js"]
fail-on-error: true
debounce:
# reload browser after successful bundling
requires: reload
The cmd above refers to a script defined in package.json scripts:
"scripts": {
"bundle:js": "eslint . && esbuild --bundle --minify --outfile=./dist.js server/js/bundle.js",
"lint:js": "eslint ."
},
TailwindCSS and PostCSS are often used to simplify CSS styling, and a custom watcher enables Templiér to hot-reload the styles on changes. This example uses the Tailwind CSS v4 PostCSS setup:
First, configure postcss.config.mjs:
export default {
plugins: {
"@tailwindcss/postcss": {},
},
};
Add Tailwind to your input.css:
@import "tailwindcss";
Create a package.json file and install all necessary dev dependencies:
npm install tailwindcss @tailwindcss/postcss postcss postcss-cli --save-dev
Add the scripts to package.json (where input.css is your main CSS
file containing your global custom styles and public/dist.css is the built CSS
output file that's linked to in your HTML):
"scripts": {
"build:css": "postcss ./input.css -o ./public/dist.css",
"watch:css": "postcss ./input.css -o ./public/dist.css --watch"
},
Finally, define a Templiér custom watcher to watch all Templ and CSS files and reload the browser:
- name: Build CSS
cmd: npm run build:css
include: ["**/*.templ", "input.css"]
exclude: ["public/**/*.css"]
fail-on-error: true
debounce:
requires: reload
NOTE: if your dist.css is embedded, you may need to use requires: rebuild.
Normally, Templiér rebuilds and restarts the server when any file changes except
for .templ files. However, when a config file changes, you usually don't need
to rebuild the server. Restarting it may be sufficient:
- name: Restart server on config change
cmd: # No command, just restart
include: ["*.toml"] # Any TOML file
exclude:
fail-on-error:
debounce:
requires: restart
Templiér acts as a file watcher, proxy server and process manager.
Once Templiér is started, it runs templ generate --watch in the background and begins
watching files in the app.dir-src-root directory.
On start, it runs all configured custom watchers and then builds your application server
executable in the OS temp directory (cleaned up on exit at the latest), assuming that
the main package is specified by the app.dir-cmd directory.
Custom Go compiler arguments can be specified with compiler. Once built, the application server
executable is launched with app.flags CLI parameters and the working directory
set to app.dir-work. On file changes, Templiér runs matching custom watchers and
then reloads, restarts, or rebuilds the app server depending on the configured action.
For .templ changes, templ generate --watch handles code generation and tells
Templiér whether the browser should reload or the app server should rebuild.
Templiér hosts your application under the URL specified by templier-host and proxies
all requests to the application server process it launches, injecting Templiér
JavaScript that opens a websocket connection back to Templiér from the browser tab
to listen for events and reload or display status information when needed.
In the CLI console logs, all Templiér logs are prefixed with 🤖,
while application server logs are displayed without the prefix.
Run the tests using go test -race ./... and use the latest version of
golangci-lint to ensure code integrity.
Install Templiér using the following command in the repository root directory:
go install .
This installs the templier binary into your Go bin directory.
If templier isn't found afterwards, make sure your Go bin directory is on
your PATH: https://go.dev/wiki/GOPATH
app.host in your templier.yml configuration.GET /__templier/events HTTP endpoint for
its websocket connection. Make sure it doesn't collide with your application's paths.Go
96.8%
templ
3.2%
A Go Templ web frontend development environment that automatically rebuilds the server and reloads the tab.
Go
120
203 commits
updated Sep 21, 2026
Templiér is a Go web frontend development environment for
Templ
that works similarly to templ's native
--watch mode but provides
more functionality and reports errors directly to all open browser tabs ✨.
Templiér allows arbitrary CLI commands to be defined as custom watchers ✨.
Templiér is an integral part of github.com/romshark/datapages.
Install Templiér:
go install github.com/romshark/templier@latest
Then copy example-config.yml to your project source folder as templier.yml, adjust it to your needs, and run:
templier --config ./templier.yml
ℹ️ Templiér automatically detects templier.yml and templier.yaml in the current directory without requiring the explicit --config flag.
Templiér runs on Linux, macOS and Windows. Behavior is identical on all three except for the following Windows specifics:
cmd runs through cmd /C instead of sh -c.
Even where a POSIX shell is on PATH (Git Bash for example), it isn't used.Access is denied. Windows refuses to rename a directory while its
sub-directories are held open for watching.Glob expressions in app.exclude and in custom watcher include and exclude
always use forward slashes (/) as path separators, on all platforms,
regardless of the path separator the operating system itself uses.
As you may already know, templ supports live reload
out of the box using templ generate --watch --proxy="http://localhost:8080" --cmd="go run .",
which is great, but Templiér provides an even better developer experience:
app.exclude or is handled by a custom watcher).
Editing an embedded .json file in your app?
Updating go.mod? Templiér will notice, rebuild, restart, and reload the browser
tab for you automatically!Custom watchers let you change how Templiér behaves for files that match any of
the include globs, and they can be used for the use cases shown below.
cmd runs through a shell (sh -c, cmd /C on
Windows). include and exclude globs always use
forward slashes as path separators.
The requires option lets you override the default behavior:
cmd.reload: Only reload all open browser tabs.restart: Restarts the server without rebuilding.rebuild: Requires the server to be rebuilt and restarted (standard behavior).If custom watcher A requires reload but custom watcher B requires rebuild,
rebuild will be chosen once all custom watchers have finished executing.
The following custom watcher watches for .js file updates and automatically runs
the CLI command npm run js:bundle, after which all browser tabs will be reloaded
using requires: reload. fail-on-error: true means that if eslint or esbuild
fails, their error output will be shown directly in the browser.
custom-watchers:
- name: Bundle JS
cmd: npm run bundle:js
include: ["**/*.js", "**/*.jsx"]
exclude: ["path/to/your/dist.js"]
fail-on-error: true
debounce:
# reload browser after successful bundling
requires: reload
The cmd above refers to a script defined in package.json scripts:
"scripts": {
"bundle:js": "eslint . && esbuild --bundle --minify --outfile=./dist.js server/js/bundle.js",
"lint:js": "eslint ."
},
TailwindCSS and PostCSS are often used to simplify CSS styling, and a custom watcher enables Templiér to hot-reload the styles on changes. This example uses the Tailwind CSS v4 PostCSS setup:
First, configure postcss.config.mjs:
export default {
plugins: {
"@tailwindcss/postcss": {},
},
};
Add Tailwind to your input.css:
@import "tailwindcss";
Create a package.json file and install all necessary dev dependencies:
npm install tailwindcss @tailwindcss/postcss postcss postcss-cli --save-dev
Add the scripts to package.json (where input.css is your main CSS
file containing your global custom styles and public/dist.css is the built CSS
output file that's linked to in your HTML):
"scripts": {
"build:css": "postcss ./input.css -o ./public/dist.css",
"watch:css": "postcss ./input.css -o ./public/dist.css --watch"
},
Finally, define a Templiér custom watcher to watch all Templ and CSS files and reload the browser:
- name: Build CSS
cmd: npm run build:css
include: ["**/*.templ", "input.css"]
exclude: ["public/**/*.css"]
fail-on-error: true
debounce:
requires: reload
NOTE: if your dist.css is embedded, you may need to use requires: rebuild.
Normally, Templiér rebuilds and restarts the server when any file changes except
for .templ files. However, when a config file changes, you usually don't need
to rebuild the server. Restarting it may be sufficient:
- name: Restart server on config change
cmd: # No command, just restart
include: ["*.toml"] # Any TOML file
exclude:
fail-on-error:
debounce:
requires: restart
Templiér acts as a file watcher, proxy server and process manager.
Once Templiér is started, it runs templ generate --watch in the background and begins
watching files in the app.dir-src-root directory.
On start, it runs all configured custom watchers and then builds your application server
executable in the OS temp directory (cleaned up on exit at the latest), assuming that
the main package is specified by the app.dir-cmd directory.
Custom Go compiler arguments can be specified with compiler. Once built, the application server
executable is launched with app.flags CLI parameters and the working directory
set to app.dir-work. On file changes, Templiér runs matching custom watchers and
then reloads, restarts, or rebuilds the app server depending on the configured action.
For .templ changes, templ generate --watch handles code generation and tells
Templiér whether the browser should reload or the app server should rebuild.
Templiér hosts your application under the URL specified by templier-host and proxies
all requests to the application server process it launches, injecting Templiér
JavaScript that opens a websocket connection back to Templiér from the browser tab
to listen for events and reload or display status information when needed.
In the CLI console logs, all Templiér logs are prefixed with 🤖,
while application server logs are displayed without the prefix.
Run the tests using go test -race ./... and use the latest version of
golangci-lint to ensure code integrity.
Install Templiér using the following command in the repository root directory:
go install .
This installs the templier binary into your Go bin directory.
If templier isn't found afterwards, make sure your Go bin directory is on
your PATH: https://go.dev/wiki/GOPATH
app.host in your templier.yml configuration.GET /__templier/events HTTP endpoint for
its websocket connection. Make sure it doesn't collide with your application's paths.Go
96.8%
templ
3.2%