Since I primarily use Neovim for all my development, configuring my environment for comfortable development of my new web project wasn't a quick task. I've decided to share my experience in hopes that it helps others get started as quickly as possible.
The main topics I want to cover are:
- Neovim LSP and Treesitter updates
- Templ formatting configuration
- TailwindCSS configuration
- Enabling HTMX in the project
- Setting up file watchers
As for the structure of my project, I simply follow conventions.
Neovim LSP and Treesitter updates
To make the LSP aware of Templ files, I had to introduce a few changes to the "lspconfig." However, before doing that, I needed to ensure that all the necessary components would be installed automatically. For this, we use Mason:
ensure_installed = {
"templ",
"html",
"htmx",
"tailwindcss",
"html",
"cssls",
"efm",
"gopls",
},
Now, we are ready to update the 'lspconfig' configuration:
-- templ
lspconfig.templ.setup({
capabilities = capabilities,
on_attach = on_attach,
})
-- html
lspconfig.html.setup({
on_attach = on_attach,
capabilities = capabilities,
filetypes = { "html", "templ" },
})
-- htmx
lspconfig.htmx.setup({
on_attach = on_attach,
capabilities = capabilities,
filetypes = { "html", "templ" },
})
-- tailwindcss
lspconfig.tailwindcss.setup({
on_attach = on_attach,
capabilities = capabilities,
filetypes = { "templ", "astro", "javascript", "typescript", "react" },
init_options = { userLanguages = { templ = "html" } },
settings = {
tailwindCSS = {
includeLanguages = {
templ = "html",
},
},
},
For proper semantic highlighting provided by Treesitter, I installed the following TS plugins:
ensure_installed = {
"javascript",
"go",
"html",
"templ",
"css",
},
Templ formatting
This was possibly the most complicated part to automate. Through EFM, I was unable to get the LSP to trigger formatting specifically for Templ files (format on save). I suspect this might be because multiple LSP servers are running for Templ files, which may confuse the LSP.
After some struggle, I decided to offload this operation to another plugin called 'conform.'
I installed the 'conform' plugin in my editor.
Below is my 'conform' configuration:
return {
"stevearc/conform.nvim",
opts = {
formatters_by_ft = {
templ = { "templ" },
},
},
config = function()
require("conform").setup({
format_on_save = {
timeout_ms = 500,
lsp_format = "fallback",
},
})
end,
}
Once set up, it's time to make 'format on save' for Templ files semi-automatic using 'autocmd.'
Insert the following snippet somewhere in your Lua config:
-- conform format
vim.api.nvim_create_autocmd("BufWritePre", {
pattern = "*.templ",
callback = function(args)
require("conform").format({ bufnr = args.buf })
end,
})
Originally the pattern part looked like this:
pattern = "*."
However, I experienced some formatting issues in my Go files, so I tried to be more specific. While I'm not convinced that these problems were solely caused by this change, I no longer experience such issues (perhaps it was just a coincidence).
TailwindCSS configuration
As for TailwindCSS, the setup has been quite straightforward. I simply followed the installation manual. Just make sure that 'lspconfig' is aware of 'tailwindcss,' as described in the LSP setup section.
Enabling htmx inside the project
This part is also quite straightforward. To enable HTMX in your project, import the HTMX library from a CDN. In my case, I included it in my base.templ
file:
<head>
<title>MyProject</title>
<link rel="icon" type="image/x-icon" href="/public/favicon.ico" />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/public/styles.css" />
<script src="https://unpkg.com/htmx.org@1.9.9" defer></script>
</head>
Setting up file watchers
Here’s a refined version of that section:
An important part of the workflow is ensuring that all my edited files are being watched for changes, so that my web project gets updated 'on-the-fly.'
We need to watch for:
- TailwindCSS changes
- Go file changes
- Templ changes
Optionally, you can include all file-watching commands in your Makefile.
.PHONY: build
build: tailwind-build templ-gen
@go build -o bin/app .
.PHONY: tailwind-watch
tailwind-watch:
npx tailwindcss -i views/css/app.css -o public/styles.css --watch
.PHONY: tailwind-build
tailwind-build:
npx tailwindcss -i views/css/app.css -o public/styles.min.css --minify
.PHONY: templ-watch
templ-watch:
templ generate --watch
.PHONY: templ-gen
templ-gen:
templ generate
For each part, there is a specific way to set up the watcher.
tailwind watcher
npx tailwindcss -i views/css/app.css -o public/styles.css --watch
For production you might want to run with --minify
flag, not --watch
Go watcher
To detect changes in standard Go files, we can use the 'AIR' tool. Follow the fairly simple AIR manual. Essentially, all I had to do was execute air init inside the project to create the config file, and I updated it if needed. Finally, executing the air command should suffice.
My configuration for reference:
root = "."
tmp_dir = "tmp"
[build]
bin = "./tmp/main"
cmd = "go build -tags dev -o ./tmp/main ."
delay = 20
exclude_dir = ["assets", "tmp", "vendor"]
exclude_file = []
exclude_regex = [".*_templ.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "templ", "html"]
kill_delay = "0s"
log = "build-errors.log"
send_interrupt = false
stop_on_error = true
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
time = false
[misc]
clean_on_exit = false
Templ changes
'Templ' tooling provides a convenient way for .templ files monitoring inside your project
templ generate --watch
For production, you may want to run just templ generate
without the --watch
flag; otherwise, after running your binary, you might encounter some errors about missing files.
Conclusion
Thank you for reading! If you come across any inaccuracies or if you would like to delve deeper into any topic, please feel free to contact me. I welcome your feedback and insights.
Let me know if you'd like any adjustments!
Top comments (0)