{"id":43790941,"url":"https://github.com/gerbenjacobs/svc","last_synced_at":"2026-02-05T20:17:54.518Z","repository":{"id":39663306,"uuid":"228677967","full_name":"gerbenjacobs/svc","owner":"gerbenjacobs","description":"An opinionated Go service and folder structure setup.","archived":false,"fork":false,"pushed_at":"2025-11-25T13:40:58.000Z","size":110,"stargazers_count":4,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-11-28T19:30:25.607Z","etag":null,"topics":["folder-structure","golang","microservice"],"latest_commit_sha":null,"homepage":"https://gerben.dev/posts/svc-an-opinionated-go-service-framework","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gerbenjacobs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":null,"dco":null,"cla":null}},"created_at":"2019-12-17T18:29:22.000Z","updated_at":"2025-11-25T13:40:55.000Z","dependencies_parsed_at":"2024-06-20T01:43:59.141Z","dependency_job_id":"1d4c6338-62a1-4311-9f4e-d4d6fc355581","html_url":"https://github.com/gerbenjacobs/svc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gerbenjacobs/svc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gerbenjacobs%2Fsvc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gerbenjacobs%2Fsvc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gerbenjacobs%2Fsvc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gerbenjacobs%2Fsvc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gerbenjacobs","download_url":"https://codeload.github.com/gerbenjacobs/svc/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gerbenjacobs%2Fsvc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29133378,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T19:36:52.185Z","status":"ssl_error","status_checked_at":"2026-02-05T19:35:40.941Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["folder-structure","golang","microservice"],"created_at":"2026-02-05T20:17:54.055Z","updated_at":"2026-02-05T20:17:54.513Z","avatar_url":"https://github.com/gerbenjacobs.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# svc\n\nAn opinionated Go service and folder structure setup, inspired by @prep.\n\nNote: This is **not** an actual framework; however you are free to use, adapt and learn (parts of) it.\n\n## Rationale\n\nThere are 4 main directories of which 3 are synonymous to a layer:\n\n- `cmd`: contains executables, most likely just an application (http, grpc), but also CLI tools\n- `handler`: contains all files related to handling incoming requests or triggers\n- `services`: contains your business logic\n- `storage`: contains all repository and storage related operations\n\nDomain models live in the root of the project, although people have created a `models` folder\nbefore.\n\nThe last 3 folders each contain a self-titled go file that is the entry point of their layer.\nFor example `handler/handler.go` has the actual endpoints and the mux router,\n`services/services.go` and `storage/storage.go` contain the interfaces that are being used\nthroughout the application.\n\nIdeally *handlers* only know about *services* and services only know about *storage*.\nUse the interfaces instead of actual implementations.\n\nEvery layers knows about the *Domain Models* and you should have these be the types that are\ntransferred between the Service and Storage layer. It's perfectly ok to then create custom\nstorage DAOs and custom input or output models for dealing with HTTP (i.e. an almost exact\ncopy of app.User but without the Password field). Just make sure that the service and storage\nmethods do the transformation back and forth.\n\nSeparation of concern and an explicit clarity is what this structure gives you.\n\n*Throughout the code I've written comments prefixed with `Rationale:` to explain a bit about the code.*\n\n## Running this example\n\n- Copy the config.yml.example to config.yml\n  - `cp config.yml.example config.yml`\n- Create a secret token\n  - `echo -n \"my secret, make sure it's not too short\" | openssl dgst -sha256`\n- Set up the database with Docker Compose\n  - `docker-compose up -d`\n- Run the application (make sure the database container is up and running)\n  - `go run cmd/app/main.go`\n\n## Examples\n\nYou can use the User service to test some endpoints out.\nChange the token when retrieving your user to the one you received when creating a user.\n\n### Creating a user\n\n```shell script\ncurl -i -X POST -d '{\"name\": \"Gerben\"}' http://127.0.0.1:8000/v1/user\n```\n\n```json\n{\n \"id\": \"93d5baed-3f2d-44a6-b3e0-02841fcf30b9\",\n \"name\": \"Gerben\",\n \"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySUQiOiI5M2Q1YmFlZC0zZjJkLTQ0YTYtYjNlMC0wMjg0MWZjZjMwYjkiLCJuYmYiOjE1NzY2NjU5ODd9.UtIQNBpLBCRVH65LriP9uqKds-jrKJzmIcILQv082yc\",\n \"created_at\": \"2019-12-18T10:46:27.002421Z\",\n \"updated_at\": \"2019-12-18T10:46:27.002421Z\"\n}\n```\n\n### Retrieving your user\n\n```shell script\ncurl -i -X GET -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySUQiOiI5M2Q1YmFlZC0zZjJkLTQ0YTYtYjNlMC0wMjg0MWZjZjMwYjkiLCJuYmYiOjE1NzY2NjU5ODd9.UtIQNBpLBCRVH65LriP9uqKds-jrKJzmIcILQv082yc\" http://127.0.0.1:8000/v1/user\n```\n\n```json\n{\n \"id\": \"93d5baed-3f2d-44a6-b3e0-02841fcf30b9\",\n \"name\": \"Gerben\",\n \"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySUQiOiI5M2Q1YmFlZC0zZjJkLTQ0YTYtYjNlMC0wMjg0MWZjZjMwYjkiLCJuYmYiOjE1NzY2NjU5ODd9.UtIQNBpLBCRVH65LriP9uqKds-jrKJzmIcILQv082yc\",\n \"created_at\": \"2019-12-18T10:46:27Z\",\n \"updated_at\": \"2019-12-18T10:46:27Z\"\n}\n```\n\n### Converting our users to a JSON output file using the CLI\n\n```shell\ngo run cmd/cli/main.go\n```\n\n```shell\n2019/12/18 12:58:23 Found 1 users\n2019/12/18 12:58:23 [93d5baed-3f2d-44a6-b3e0-02841fcf30b9] Gerben - 2019-12-18T10:46:27Z\n2019/12/18 12:58:23 Finished writing to output.json\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgerbenjacobs%2Fsvc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgerbenjacobs%2Fsvc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgerbenjacobs%2Fsvc/lists"}