This is my (embiem's) favorite Go web stack at the time of making.
I use this to start new web projects quickly and will likely change this template over time.
The simple password auth in this template is just to get going and should be replaced with a more secure approach or additional best practices, before going to production. Always reference the OWASP Top 10 list to ensure you're building a secure app.
curl -L https://github.com/golang-migrate/migrate/releases/download/v4.18.1/migrate.linux-amd64.tar.gz | tar xvz
go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest
go install github.com/air-verse/air@latest
go install github.com/a-h/templ/cmd/templ@latest
curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-linux-x64 && chmod +x tailwindcss-linux-x64 && mv tailwindcss-linux-x64 tailwindcss
cp .env.example .env
& fill-in any missing env varsdocker compose up -d
air
go test ./...
Using golang-migrate for migrations (Tutorial) and sqlc for queries, mutations & codegen (Tutorial).
sqlc doc about handling SQL migrations.
For local dev, setup env var like so: export POSTGRESQL_URL='postgres://postgres:password@localhost:5432/postgres?sslmode=disable'
.
Optionally, test migrations up & down on a separate local db instance e.g. by spinning up a stack with different name: docker compose -p dbmigrations-testing up -d
.
migrate create -ext sql -dir db/migrations -seq your_migration_description
migrate -database ${POSTGRESQL_URL} -path db/migrations up
migrate -database ${POSTGRESQL_URL} -path db/migrations down
& check db as wellWhen dirty, force db to a version reflecting it's real state: migrate -database ${POSTGRESQL_URL} -path db/migrations force VERSION
Important: Write migration SQL in transactions. In Postgres, when we want our queries to be done in a transaction, we need to wrap it with BEGIN
and COMMIT
commands. Example:
-- up migration
BEGIN;
CREATE TYPE enum_mood AS ENUM (
'happy',
'sad',
'neutral'
);
ALTER TABLE users ADD COLUMN mood enum_mood;
COMMIT;
-- down migration
BEGIN;
ALTER TABLE users DROP COLUMN mood;
DROP TYPE enum_mood;
COMMIT;
Write the SQL queries & mutations in db/query.sql
and then run sqlc generate
.
Using Templ: https://templ.guide/quick-start/creating-a-simple-templ-component
templ generate
to generate go files after adding or editing .templ filesHere is a list of tips to optimize the loading times.
defer
attribute.rel="preload"
attribute to the head.rel="dns-prefetch"
attribute to the head.