{"id":26398486,"url":"https://github.com/sglmr/go-web-starter","last_synced_at":"2025-03-17T12:32:06.967Z","repository":{"id":282571639,"uuid":"948749116","full_name":"sglmr/go-web-starter","owner":"sglmr","description":"A starter template for a Go web app.","archived":false,"fork":false,"pushed_at":"2025-03-15T13:48:25.000Z","size":40,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-15T14:33:20.432Z","etag":null,"topics":["go","template","web","webapp"],"latest_commit_sha":null,"homepage":"https://github.com/sglmr/go-web-starter","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/sglmr.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}},"created_at":"2025-03-14T22:22:22.000Z","updated_at":"2025-03-15T13:48:28.000Z","dependencies_parsed_at":"2025-03-15T14:43:25.221Z","dependency_job_id":null,"html_url":"https://github.com/sglmr/go-web-starter","commit_stats":null,"previous_names":["sglmr/go-web-starter"],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sglmr%2Fgo-web-starter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sglmr%2Fgo-web-starter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sglmr%2Fgo-web-starter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sglmr%2Fgo-web-starter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sglmr","download_url":"https://codeload.github.com/sglmr/go-web-starter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244033601,"owners_count":20386955,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["go","template","web","webapp"],"created_at":"2025-03-17T12:30:57.022Z","updated_at":"2025-03-17T12:32:06.958Z","avatar_url":"https://github.com/sglmr.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Go Start\n\nA lightweight, feature-rich Go web application template with built-in security features, session management, email functionality, and more.\n\nThis project template aims to reduce third party dependencies wherever possible. Most of the \"code\" for the project is in a single `cmd/web/main.go` file. Because (A) it's easier to give AI project context when most of the project is in a single file and (B) it's a simple starter template with minimal assumptions about how a project might evovle over time.\n\nThis project does not currently include any configuration for a database.\n\nThis project aims to avoid using receiver methods on handlers and other project functions. An application struct hanging off of every method is convenient and makes for pretty code, but there are also some negatives:\n\n- Surprise dependency issues during testing\n- Non-implicit dependencies\n- More restrictive coupling of project components and structure\n\nThis project assumes you will be running it behind a reverse proxy service that handles HTTPS and certificates for you.\n\n## Features\n\n- **Complete Web Server**: HTTP server with graceful shutdown\n- **Middleware Stack**:\n  - Panic recovery\n  - Secure headers\n  - Request logging\n  - CSRF protection\n  - Basic authentication\n  - Static asset caching\n  - Session management\n- **Email Support**: Send emails with configurable SMTP\n- **Form Validation**: Comprehensive validation helpers\n- **Flash Messages**: Session-based notifications system\n- **Templating**: HTML template rendering with data context\n- **Static File Serving**: Embedded static file handling\n- **Development Mode**: Enhanced debugging with stack traces and additional logging.\n\n## Getting Started\n\n### Prerequisites\n\n- Go 1.22 or higher\n- [Task](https://taskfile.dev/) for project management commands.\n\n### Installation\n\n1. Clone the repository:\n\n```bash\ngit clone https://github.com/sglmr/gowebstart.git\ncd gowebstart\n```\n\n2. Replace \"gowebstart\" with your new project name.\n\n3. Build the project:\n\n```bash\ntask build\n```\n\n### Running the Server\n\nBasic usage:\n\n```bash\n# Run the app\ntask run\n\n# Run the app with live reload\ntask run:live\n```\n\nThis will start the server on the default address `0.0.0.0:8000`.\n\n### Command-Line Options\n\n| Flag | Description | Default |\n|------|-------------|---------|\n| `-host` | Server host | `0.0.0.0` |\n| `-port` | Server port | `8000` or `PORT` env variable |\n| `-dev` | Development mode | `false` |\n| `-username` | Basic auth admin username | `admin` |\n| `-password` | Basic auth admin password | `password` (hashed) |\n| `-smtp-host` | SMTP server host | `` |\n| `-smtp-port` | SMTP server port | `25` |\n| `-smtp-username` | SMTP username | `` |\n| `-smtp-password` | SMTP password | `` |\n| `-smtp-from` | Email sender | `Example Name \u003cno-reply@example.com\u003e` |\n\nExample with custom options:\n\n```bash\n./gowebstart -port=3000 -dev -smtp-host=smtp.example.com -smtp-port=587 -smtp-username=user -smtp-password=pass\n```\n\n## SMTP Emails\n\nThe application includes methods for sending SMTP Emails. Email templates are configuratble in the `assets/emails` directory.\n\n```go\nerr = mailer.Send(recipient string, replyTo string, data any, templates ...string)\n```\n\n## Background Tasks\n\nThe application includes a system for running asynchornous tasks using the `BackgroundTask` function.\n\n```go\nBackgroundTask(wg *sync.WaitGroup, logger *slog.Logger, fn func() error)\n```\n\nBackground task system features:\n\n- **Panic Recovery**: Tasks are isolated so panics don't crash the server\n- **Logging**: Automatic error logging with the function name\n- **WaitGroup Integration**: Proper shutdown handling with sync.WaitGroup\n- **Graceful Shutdown**: Tasks tracked during server shutdown\n\nExample usage:\n\n```go\n// Send an email in the background\nBackgroundTask(\n    wg, logger, \n    func() error {\n        return mailer.Send(\"recipient@example.com\", \"reply-to@example.com\", emailData, \"email-template.tmpl\")\n    })\n\n// Continue processing the request without waiting\n```\n\nThis pattern is useful for operations like:\n\n- Sending emails\n- Processing uploaded files\n- Running reports\n- Performing database maintenance\n- Any long-running task that shouldn't block the request handler\n\n## Architecture\n\n### Application Structure\n\n- `assets/`: Folder for all project embedded files\n  - `emails/`: Email templates\n  - `static/`: Static files like CSS, Javascript, etc\n  - `templates/`: Templates to render to HTML pages for the application\n    - `pages/`: Main web page content to load, like \"home.tmpl\" or \"about.tmpl\"\n    - `partials/`: Page partials, like a nav bar, footer, etc\n    - `base.tmpl`: Base template for all pages and partials\n- `cmd/`\n  - `web/`\n    - `main.go`: Entry point and server configuration\n- `internal/`:\n  - `asserts/`: Testing assert functions\n  - `email/`: SMTP email functionality\n  - `funcs/`: Template functions\n  - `render/`: Template rendering helpers\n  - `vcs/`: Version information\n\n### Middleware\n\nThe application uses a composable middleware pattern:\n\n```go\nhandler = RecoverPanicMW(mux, logger, devMode)\nhandler = SecureHeadersMW(handler)\nhandler = LogRequestMW(logger)(handler)\nhandler = sessionManager.LoadAndSave(handler)\n```\n\n### Using Basic Authentication\n\nThe project contains a `BasicAuthMW` middleware that you can use to protect the application, or specific routes with HTTP basic authentication.\n\nYou can try this out by visiting the [https://localhost:8000/protected/](https://localhost:8000/protected/) endpoint in any web browser and entering the default user name and password:\n\n```\nUser name: admin\nPassword:  password\n```\n\nYou can change the user name and password by setting the `--username` command-line flag and `--password` command-line flag. For example:\n\n```sh\ngo run ./cmd/web -username='alice' --password='$2a$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'\n```\n\nNote: You will probably need to wrap the username and password in `'` quotes to prevent your shell interpreting dollar and slash symbols as special characters.\n\nThe value for the `-password` command-line flag should be a bcrypt hash of the password, not the plaintext password itself. An easy way to generate the bcrypt hash for a password is to use the `gophers.dev/cmds/bcrypt-tool` package like so:\n\n```sh\ngo run gophers.dev/cmds/bcrypt-tool@latest hash 'your_pa55word'\n```\n\nThere is also a helper \"app\" you can run in `cmd/hash/main.go` that prompts for and generates a password.\n\n```sh\ngo run ./cmd/hash\n\n   Enter password: \nRe-enter password:\n    Password hash: $2a$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n```\n\nIf you want to change the default values for username and password you can do so by editing the default command-line flag values in the `cmd/web/main.go` file.\n\n## Request Handlers\n\nRequest handlers follow a standardized pattern:\n\n```go\nfunc handlerName(dependencies...) http.HandlerFunc {\n    // Handler specific type, constant, or variable definitions\n    return func(w http.ResponseWriter, r *http.Request) {\n        // Handler logic\n    }\n}\n```\n\n### Background Tasks\n\nTasks like sending emails are handled in the background:\n\n```go\nBackgroundTask(wg, logger, func() error {\n    return mailer.Send(...)\n})\n```\n\n## Form Validation\n\nThe application includes a comprehensive validation system with the `Validator` struct.\n\n```go\ntype Validator struct {\n    Errors map[string]string\n}\n```\n\n`Validator` includes methods for managing errors and validation. For Example:\n\n\n```go\n// Example ContactForm validation with Validator\n\ntype contactForm struct {\n    Name    string\n    Message string\n    Validator\n}\n\nform := contactForm{}\nform.Check(IsEmail(form.Email), \"Email\", \"Email must be a valid email address.\")\nform.Check(NotBlank(form.Message), \"Message\", \"Message is required.\")\n\nif form.HasErrors() { \n    // Do something with errors\n}\n// Do something with no errors\n```\n\nAvailable validators:\n- `NotBlank`: Ensures string is not empty\n- `MinRunes`/`MaxRunes`: Length validation\n- `Between`: Range validation\n- `Matches`: Regex validation\n- `In`/`NotIn`: Value presence validation\n- `NoDuplicates`: Uniqueness validation\n- `IsEmail`: Email validation\n- `IsURL`: URL validation\n\n## Flash Messages\n\nThe application supports various flash message types. Flash messages are formatted and rendered in the `assets/templates/partials/flashMessages.tmpl` template.\n\n```go\nputFlashMessage(r, LevelSuccess, \"Welcome!\", sessionManager)\n```\n\nMessage levels:\n- `LevelSuccess`\n- `LevelError`\n- `LevelWarning`\n- `LevelInfo`\n\n## Customization\n\n### Adding New Routes and Middleware\n\nAdd new routes and middleware in the `AddRoutes` function. This project takes advantage of the [Go 1.22 Routing Enhancements](https://go.dev/blog/routing-enhancements).\n\n```go\nfunc AddRoutes(mux *http.ServeMux, ...) http.Handler {\n    // Existing routes...\n    \n    // Add your new route\n    mux.Handle(\"GET /your-path\", yourHandler(dependencies...))\n    \n    // Middleware...\n    handler := middleware1(mux)\n    handler = middleware2(handler)\n\n    return handler\n}\n```\n\n### Rendering pages from templates\n\nTemplates are rendered using the `render.Page` function. Template pages live in the `assets/templates/pages` directory.\n\nA `newTemplateData` function prefills a map with commony used template data\n\n```go\ndata := newTemplateData(r, sessionManager)\nerr := render.Page(w, http.StatusOK, data, \"your-template.tmpl\")\n```\n\nTemplate functions are managed in the `internal/funcs` package.\n\n## License\n\n[MIT License](LICENSE)\n\n## External Dependencies\n\n- github.com/alexedwards/scs/v2\n- github.com/justinas/nosurf\n- github.com/wneessen/go-mail","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsglmr%2Fgo-web-starter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsglmr%2Fgo-web-starter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsglmr%2Fgo-web-starter/lists"}