A simple starter template for building web applications using Gleam.
- Development / testing database using docker and pog
- Logging setup
- Background jobs setup using bg_jobs
- (WIP) Production docker image and fly.toml
- (WIP) Frontend configuration using vite for css and ts
- (TODO) Session management using kv_sessions
- (TODO) Email provider
- (TODO) Auth
To start developing
$ just dev
This starts:
- Database - (dockerized postgres)
- Dev server - (wisp server)
- Query generation - (squirrel)
- tests - (gleeunit)
Dev server, Query generation and tests are all started in watch mode,
see
justfile
for more info.
This is all started in a mproc instance so it's easy to switch between them.
- Development: Configure in .env.
- Production: Set in fly.toml.
├── db
│ ├── dev
│ │ └── mnt_data
│ └── migrations
├── src
│ ├── controllers
│ ├── jobs
│ ├── lib
│ ├── models
│ │ └── guestbook_model
│ │ └── sql
│ ├── providers
│ │ ├── cache
│ │ ├── db
│ │ ├── jobs
│ │ ├── logging
│ │ └── web_server
│ ├── resources
│ │ ├── css
│ │ ├── js
│ │ └── views
│ │ └── view_guestbook_view
│ └── routes
│ └── middlewares
└── test
└── integration
Contains database migrations and development database configurations.
The main entry point of the application. This is where everything is wired up.
Defines two context types:
- For routing and controllers.
- For background jobs.
Controllers handle incoming requests and define application logic. Each route points to a controller.
Background jobs are managed here. For example, to send emails, create
/src/jobs/send_email_job.gleam
. This project uses bg_jobs.
The interface for database operations. Models encapsulate resource-specific logic and data interaction.
Providers offer specific functionalities like database access, email sending, or logging.
Contains rendering-related code such as CSS, JavaScript, and views.
Note: Static files should be placed in /static
.
Defines application routes and their associated controllers.
Middleware configuration is also located here under /src/routes/middlewares
.
Write integration tests here to simulate user workflows.
JobContext and WebContext is passed to the web_server and jobs, it contains the db connection and other useful values that should not be constructed in place. This makes testing easier since you can construct separate testing dependencies.
Sets up the erlang default logger using wisp, also provides a context-builder
and logging functions for context aware logging.
Separate log contexts are passed to jobs and web_server using the
context.JobContext
and context.WebContext
respectivly.
There is also a log_request_middleware
that logs requests and adds a
request_id to the logging context, the logging context is passed to
the controllers using context.WebContext.
Create a new logging context
import providers/logging/logging_provider as log
// Create a new log_context
let example_logger = log.new("example_logger")
|> with_context("thing", "value")
// Log message to info level
example_logger |> log.log_info("some log value")
// -> INFO example_logger: some log value |thing="value"
Provides setup function that configures bg_jos. This is also where you register your jobs.
Provides setup function for starting mist - wisp
This starter uses PostgreSQL as the database. The starter provides:
- Development/testing database setup using docker, read more below
- Database migrations using DbMate
- Integration testing setup with postgres
- Development database configuration is managed via Docker. See the
justfile
for available commands. - Environment variables for database settings are found in the
.env
file. - If you modify
.env
, a database reset may be required. Use:
$ just db_delete
$ just db_start
Provides setup and helper functions related to setting up and connecting to the database.
The Docker container includes a separate test database. Examples of
its usage can be found in test/integration/create_guestbook_entry_test.gleam
.
Tests interacting with the database can run using one of two strategies:
- Transaction-based tests (test_db_provider.transaction_test): Code runs inside a transaction that is rolled back afterward. Faster but not always feasible.
- Truncate-based tests (test_db_provider.truncate_test): Cleans up tables after running. Use this as a fallback.
Prefer transaction tests unless specific scenarios require truncation.
Migrations are handled using DbMate. Always use the alias just db [...]
to
ensure the correct environment variables are set.
Some migrations, like bg_jobs, are executed automatically at startup.
Check /src/providers/db/db_provider
for the setup process.