{"id":30615627,"url":"https://github.com/alexfalkowski/web","last_synced_at":"2026-06-08T20:01:06.757Z","repository":{"id":247582955,"uuid":"826246685","full_name":"alexfalkowski/web","owner":"alexfalkowski","description":"A website lean-thoughts.com.","archived":false,"fork":false,"pushed_at":"2026-06-08T11:33:13.000Z","size":2064,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-06-08T13:22:14.029Z","etag":null,"topics":["cucumber","golang","htmx","make","ruby"],"latest_commit_sha":null,"homepage":"https://alexfalkowski.github.io/web","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexfalkowski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2024-07-09T10:42:51.000Z","updated_at":"2026-06-08T11:30:31.000Z","dependencies_parsed_at":"2026-02-26T11:06:16.766Z","dependency_job_id":null,"html_url":"https://github.com/alexfalkowski/web","commit_stats":null,"previous_names":["alexfalkowski/web"],"tags_count":765,"template":false,"template_full_name":"alexfalkowski/go-service-template","purl":"pkg:github/alexfalkowski/web","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexfalkowski%2Fweb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexfalkowski%2Fweb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexfalkowski%2Fweb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexfalkowski%2Fweb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexfalkowski","download_url":"https://codeload.github.com/alexfalkowski/web/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexfalkowski%2Fweb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34078019,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cucumber","golang","htmx","make","ruby"],"created_at":"2025-08-30T08:06:07.212Z","updated_at":"2026-06-08T20:01:06.720Z","avatar_url":"https://github.com/alexfalkowski.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![CircleCI](https://circleci.com/gh/alexfalkowski/web.svg?style=svg)](https://circleci.com/gh/alexfalkowski/web)\n[![codecov](https://codecov.io/gh/alexfalkowski/web/graph/badge.svg?token=S9SPVVYQAY)](https://codecov.io/gh/alexfalkowski/web)\n[![Go Report Card](https://goreportcard.com/badge/github.com/alexfalkowski/web)](https://goreportcard.com/report/github.com/alexfalkowski/web)\n[![Go Reference](https://pkg.go.dev/badge/github.com/alexfalkowski/web.svg)](https://pkg.go.dev/github.com/alexfalkowski/web)\n[![Stability: Active](https://masterminds.github.io/stability/active.svg)](https://masterminds.github.io/stability/active.html)\n\n# Web\n\nA small Go service that serves the website at:\n\n- \u003chttps://web.lean-thoughts.com/\u003e\n\nThe service is built on top of the [`mvc`](https://github.com/alexfalkowski/go-service/tree/master/net/http/mvc) package from `go-service` and ships as a single binary with templates and content embedded.\n\n## Background\n\nThis project is an implementation playground for the ideas outlined in:\n\n- \u003chttps://alejandrofalkowski.substack.com/p/hyperprogress\u003e\n\n## What it does\n\nAt a high level the service:\n\n- serves the home page (`/`)\n- serves a books page (`/books`)\n- serves `robots.txt` (`/robots.txt`)\n- exposes health and liveness/readiness endpoints (see below)\n\nThe HTML templates and the books YAML data are embedded into the binary using `go:embed`.\n\n## Architecture overview\n\n### Project layout\n\nThis repo follows the structure described in:\n\n- \u003chttps://github.com/golang-standards/project-layout\u003e\n\nKey directories:\n\n- `main.go`: entrypoint for the `web` binary\n- `internal/`: application code (not importable from other modules)\n- `test/`: acceptance/system tests and supporting Ruby test client\n- `bin/` + `Makefile`: build/dev/test automation\n\n### Dependency injection and modules\n\nThe service is wired with dependency injection using `go-service/v2/di`. The top-level module that assembles the server is:\n\n- `internal/cmd.Module`\n\nIt pulls in configuration, health, and site modules.\n\n### MVC routing and rendering\n\nRouting and rendering are handled using:\n\n- `go-service/v2/net/http/mvc`\n\nFeature modules (e.g. books/root/robots) register their routes during DI wiring.\n\n### Embedded assets\n\nThe site package embeds:\n\n- templates for layout and pages\n- the books YAML file used to render the books page\n\nSee:\n\n- `internal/site/site.go`\n\n## Endpoints\n\n### Pages\n\n- `GET /` renders the home page\n- `PUT /` renders a partial/fragment version of the home page (used for incremental updates)\n- `GET /books` renders the books page\n- `PUT /books` renders a partial/fragment version of the books page\n- `GET /robots.txt` serves the robots file as a static asset\n\n\u003e Note: the `PUT` endpoints exist to support partial rendering patterns (for example HTMX-style incremental updates). The exact response shape depends on the templates/layout configured in the MVC layer.\n\n### Health\n\nThe service registers health checks and exposes standard probe endpoints:\n\n- `/healthz` (overall health / online)\n- `/livez` (liveness)\n- `/readyz` (readiness)\n\nHealth timings are configured via the service config under the `health` section.\n\n## Development\n\n### Prerequisites\n\nInstall:\n\n- [Go](https://go.dev/)\n- [Ruby](https://www.ruby-lang.org/en/)\n\n### Useful Make targets\n\nThis repo relies on `make` for a consistent developer experience.\n\nList all available commands:\n\n```sh\nmake help\n```\n\nCommon workflows:\n\n```sh\n# Install dependencies (Go + Ruby)\nmake dep\n\n# Run linters\nmake lint\n\n# Auto-fix lint where possible\nmake fix-lint\n\n# Format code\nmake format\n\n# Run Go tests\ngo test ./...\n\n# Run the repo-defined Go specs wrapper\nmake specs\n\n# Run Cucumber acceptance tests\nmake features\n```\n\n### Running locally\n\nThere are two common ways to run the service:\n\n#### 1) Dev mode\n\nUse the dev target (recommended while iterating):\n\n```sh\nmake dev\n```\n\nThis typically runs the service with a development configuration (see the `Makefile` includes and CI configuration for how it is invoked).\n\n#### 2) Build and run the binary\n\nBuild a local binary:\n\n```sh\nmake build\n```\n\nThen run it:\n\n```sh\n./web server -i file:test/.config/server.yml\n```\n\n\u003e The CLI command is `server`. It is registered in `internal/cmd` and starts the HTTP server using the DI module graph.\n\n### Example: verifying endpoints\n\nOnce the server is running, you can verify key endpoints.\n\nIf you started the service with `make dev` (or with `-i file:test/.config/server.yml`),\nthe HTTP server listens on `localhost:11000`.\n\nPages:\n\n```sh\ncurl -i http://localhost:11000/\ncurl -i http://localhost:11000/books\ncurl -i http://localhost:11000/robots.txt\n```\n\nPartial renders (PUT):\n\n```sh\ncurl -i -X PUT http://localhost:11000/\ncurl -i -X PUT http://localhost:11000/books\n```\n\nHealth:\n\n```sh\ncurl -i http://localhost:11000/healthz\ncurl -i http://localhost:11000/livez\ncurl -i http://localhost:11000/readyz\n```\n\n\u003e Ports, TLS, and other server settings are controlled by configuration. If your local environment differs, inspect the config used by `make dev` / CI.\n\n## Configuration\n\nThe service config model lives in:\n\n- `internal/config.Config`\n\nIt embeds the shared base config from `go-service` and adds a `health` section.\n\nThe health section looks conceptually like:\n\n```yaml\nhealth:\n  duration: 5s\n  timeout: 2s\n```\n\n\u003e The exact full configuration file shape depends on the embedded `go-service` base config and the environment in which you run the binary. For canonical examples, check the CI configuration and any config files used by `make dev`.\n\n## Testing\n\n### Go\n\nRun all Go tests:\n\n```sh\ngo test ./...\n```\n\n### Ruby acceptance test client\n\nThe Ruby test helper client is in:\n\n- `test/lib/web.rb`\n- `test/lib/web/v1/http.rb`\n\nIt provides a small wrapper around HTTP calls used by the acceptance tests.\n\n## Style\n\nGo code generally follows:\n\n- \u003chttps://github.com/uber-go/guide/blob/master/style.md\u003e\n\n## Changes / releases\n\nSee:\n\n- `CHANGELOG.md`\n\n## License\n\nSee:\n\n- `LICENSE`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexfalkowski%2Fweb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexfalkowski%2Fweb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexfalkowski%2Fweb/lists"}