GoTodo is a small, self-hosted task manager built with Go and PostgreSQL. It focuses on simplicity and a pleasant developer experience: user accounts, per-user tasks, invite flow, role-based permissions, a responsive UI, and a lightweight AJAX/HTMX interaction model.
- User signup / login / logout
- Editable profile with a single
user_namefield and timezone preference - Per-user tasks: add, list, update status, delete
- Invite creation and confirmation (permission gated)
- Role-based permissions and a default role
- Responsive UI with Bootstrap and a dark/light theme toggle
- HTMX for in-place interactions and partial updates
- Asset cache-busting via
AssetVersion
Requirements:
- Go (1.20+)
- PostgreSQL
- Node.js + npm (for frontend assets)
- Copy the example env file to
.envand edit values:
DB_HOST=localhost
DB_PORT=5432
DB_USER=youruser
DB_PASSWORD=yourpassword
DB_NAME=gotodo
BASE_PATH=/ # optional
ASSET_VERSION=20251130 # optional; bump to force client cache refresh
- Install frontend dependencies and builds assets:
npm ci
npm run build:assets- Build and run:
go build -o app.exe main.go
.\app.exeOr run directly:
go run main.goOpen the app in your browser (default from code: http://localhost:8080).
The repository includes pre-built minified CSS/JS files (internal/server/public/css/site.min.css, internal/server/public/js/site.min.js) so a fresh clone works immediately.
If you modify frontend source files (CSS/JS in internal/server/public/src/):
npm ci
npm run build:assets
# update .asset_version if needed
Get-Date -UFormat %Y%m%d%H%M%S | Out-File -FilePath "internal/server/public/.asset_version" -Encoding utf8
git add internal/server/public/css/site.min.css internal/server/public/js/site.min.js internal/server/public/.asset_version
git commit -m "Update frontend assets"
The app uses github.com/jackc/pgx/v5/pgxpool. There are helper/migration functions in internal/storage/database.go you can run or inspect.
- Templates are rendered via
utils.RenderTemplate. The renderer injectsAssetVersioninto your templates automatically (fromASSET_VERSIONenv or fallback). - Use
?v={{.AssetVersion}}on CSS/JS includes to bust caches when you update assets.
- Sessions are managed through
sessionstore. GetSessionUserWithTimezonereturns the logged-in user's email, role, permissions, timezone, a logged-in flag, anduser_name.- Profile updates are handled by
/api/update-profile(AJAX). On success the session is updated so UI reflects the change immediately.
- The dark/light theme is implemented with CSS custom properties in
site.cssand a smallsite.jsscript that stores the choice inlocalStorage. - Make sure
site.jsis included on pages so the toggle initialization works correctly.
- HTMX is used for in-place swaps and short server-client flows. Some handlers set
HX-Redirectfor client-side redirects after an XHR-style submit.
- Blank name after login: ensure
session.Values["user_name"]is set during login (login handler loads it from DB). - 500 on profile save: confirm DB has
user_nameandtimezonecolumns and check server logs for the error. - Theme toggle not persisting: ensure
site.jsis loaded andlocalStorage.themeis set. - Asset caching: bump
ASSET_VERSIONor setASSET_VERSIONenv var to force clients to fetch updated assets.
- Code is organized under
internal/with clear separation for handlers, templates, storage, and utils. - If you want automated asset versioning, set
ASSET_VERSIONin your CI/CD pipeline (build timestamp or git SHA).
- Routes and server setup:
internal/server/server.go - Handlers:
internal/server/handlers - Templates:
internal/server/templates(+ partials) - Static assets:
internal/server/public - DB helpers and migrations:
internal/storage/database.go - Template helper and session utils:
internal/server/utils
README file generated with AI Assistance