Skip to content
Guides

Guides

How to do one thing, step by step.

  • Add accounts with make:auth: Give your app user accounts in one command: registration, login with “remember me” and throttling, sign-in with Google and GitHub, logout, email verification, password reset and API tokens, with their pages, emails, routes, migration and tests. The code is written into your app, where you change it as you like; the parts that must be right (password hashing, tokens, sessions, throttling, the OAuth flow) stay in the auth and social packages, so fixes reach you with go get -u.
  • Add AI to your app: Use a language model in your app: summarize text into a typed struct, answer questions with tools that look up the user’s own data, and stream the answer as it’s written. Package ai does the work around the model: schemas, validation, the tool loop, logging and tests that never call a model. The complete example is examples/ai, a small support desk API.
  • Add full-text search: Give users a search box that finds what they mean: every word they type, in any of the columns you choose, best matches first. Search runs on your database’s own full-text engine (PostgreSQL, MySQL/MariaDB or SQLite), with an index built by a migration; there’s no search server to run. The complete example is examples/forms, a notes app with a search box.
  • Authentication: Let people register, log in (with “remember me”), log out, verify their email address and reset a forgotten password, and give API clients tokens. The complete app is examples/auth. In an anetos new project, go tool anetos make:auth writes all of this into your app: see Add accounts with make:auth. This guide is the auth package underneath, step by step.
  • Authorization: Decide what a signed-in user may do, with policies the compiler checks.
  • Build an AI assistant: Give your users a chat with an agent that answers from your app’s data: conversations stored in the database, answers streamed to the page as they’re written, slow questions answered in the background, and a usage budget per user.
  • Cache values: Keep the results of slow work for a while, count events for rate limits, and use locks so only one instance of the app does a job at a time.
  • Commands: Your application builds to one binary. Its first argument picks what it does: run the app (the default), run only some roles, migrate the database, list the routes, or run commands of your own.
  • Configure your application: Read settings from .env files and the environment into typed Go structs, with defaults, required keys and validation.
  • Connect to a database: Open your app’s database from configuration and use it from handlers, jobs and background tasks.
  • Define models and save data: Map structs to tables, and create, update and delete rows with timestamps, soft deletes and hooks.
  • Events: Emit an event when something happens, and let listeners react: write an audit log, email a receipt, update a dashboard. The code that places an order then doesn’t need to know about all of them. Events are typed Go values, and listeners are functions of their type. The complete app is examples/queue.
  • Find N+1 queries: An N+1 is a query in a loop: one query for a list of posts, then one per post for its author. It works, and it’s fast with three posts in development; with three hundred in production, it isn’t. Anetos warns when a request (or a job, a listener, a scheduled task) runs the same query many times, and says where, so you can load the rows in one query instead. The complete example is examples/database.
  • Generate typed columns: Let anetos gen declare a typed column for every field of your models, and a handle for every relation, so queries say PostCols.Title.Like("%go%") and With(PostRels.Author), and the compiler checks the column name, the value’s type and the relation’s model.
  • Handle HTML forms: Protect forms against cross-site request forgery, send PUT and DELETE from plain HTML, and show validation errors next to the fields with the submitted values kept.
  • Handlers and requests: Write handlers that receive typed input, return typed output, and turn errors into proper HTTP responses.
  • Migrations: Create and change your database tables with versioned migrations that are compiled into your app and run with one command.
  • Numbers, dates and languages: Show numbers, prices, dates and times the way each user reads them, in their language and time zone, and add the framework’s translations for a language with one command.
  • Pub/sub listeners: Listen to message streams other services publish, such as orders.created, and publish your own, from the same binary as your web app. Where the queue runs an app’s own jobs, pub/sub connects services: each subscription gets every message of a topic. The complete app is examples/pubsub, a billing service.
  • Query data: Find rows with typed conditions, sort and paginate them, aggregate, and update or delete in bulk.
  • Queues: Run slow or failure-prone work in the background: charge a card, send an email, build a report. A request dispatches a job, a typed struct, and responds at once. Workers run the job later, retry it when it fails, and keep a record of the jobs that failed for good. The complete app is examples/queue.
  • Rate limiting: Limit how often clients can call your routes, and how often they can attempt actions such as logging in.
  • Raw SQL: Write SQL yourself and scan the results into structs, when the query builder is in the way.
  • Relations and eager loading: Declare how models relate (a post belongs to an author, an author has many posts, posts have many tags), load related rows in one query per relation, and filter rows by what they relate to.
  • Render HTML with templ: Write pages as templ components (typed, compiled, escaped by default), share a layout, link to routes by name, serve static files with cache-busting URLs, and add interactivity with the bundled htmx.
  • Roles and permissions: Give users roles, globally or in a team, and check what they may do, with package auth/rbac.
  • Routing: Map URLs to handlers, group routes under shared prefixes and middleware, name them, and generate URLs from names.
  • Run background tasks: Run long-lived work, such as a poller, a cache warmer or a heartbeat, as a supervised goroutine that restarts on failure and stops cleanly on deploy.
  • Scheduling: Run tasks on a schedule: prune old rows every night, send a report every hour, sync with another service every five minutes. The scheduler runs in your app’s binary, as a supervised component, so there is no crontab to install and nothing to run every minute. The complete app is examples/queue.
  • Search by meaning: Find records by what they mean, not only by the words they share: “how much is the team plan” finds the article on plans and billing, which never says “how much”. Each record’s text is split into chunks, turned into vectors (embeddings) by an embedding model, and stored next to the record; a search embeds the question and returns the nearest records, with the passage that matched. With a full-text index too, the search is hybrid: records that its words find rank high as well, so names, codes and rare words aren’t missed. An agent can use the search as a tool, to answer from your data (retrieval-augmented generation).
  • Seed the database: Fill a database with sample data for development, or with the reference data every environment needs.
  • Send email: Send email from your app: a receipt, a welcome message, a password reset link. An email is a mailable, a type that builds its message from its fields, with an HTML body from a templ component. Send it now, or queue it so a worker sends it with retries. The complete app is examples/queue, which emails a receipt for each order.
  • Sessions and flash messages: Remember things about a visitor between requests, and show a message once after a redirect.
  • Social login: Let users sign in with Google, GitHub, or any OpenID Connect provider (Okta, Auth0, Microsoft Entra ID, Keycloak, GitLab…). The complete app is examples/auth.
  • Store files: Store files your app receives or makes: uploads, avatars, exports, invoices. Files go on disks: a local directory by default, or an S3-compatible bucket (Amazon S3, Cloudflare R2, MinIO, …) or a Google Cloud Storage bucket, with the same code. Private files are read through temporary signed URLs. The complete app is examples/files.
  • Test your app: Boot the app in a test, send it requests like a browser or an API client, and check the responses, the session, the database, the jobs, events and email the app sent, and its files, with anetostest; freeze or move the app’s clock.
  • Times and dates: Store times without thinking about time zones, keep calendar dates on their day, and choose the zone your app works in.
  • Transactions: Make several writes succeed or fail together, and run follow-up work only after they are saved.
  • Translations: Show your app, its validation messages and error pages, and its emails in each user’s language. Adding a language is adding a file.
  • Use plugins: Add features to your app with plugins: packages that bring their own routes, database tables, settings, commands, queue jobs, scheduled tasks or event listeners. anetos add installs one with one command. The complete app is examples/queue, which uses the Postmark plugin to stop emailing addresses that bounced.
  • Validation: Declare rules on an input struct, get one clear message per field, and add checks of your own.
  • Write a plugin: Package a feature so any Anetos app can add it with anetos add: its routes, tables, settings, commands, queue jobs, scheduled tasks and event listeners. A plugin uses only the framework’s public packages, as an app does. The complete plugin is plugins/postmark, which receives Postmark’s webhooks and keeps a list of the addresses Postmark stopped sending to.