This is a template for creating Telegram bots using the aiogram library.
- SQLAlchemy + Alembic
- PostgreSQL
- Redis
- Caddy Server
- Docker
- i18n (Project Fluent)
- uv
git clone https://github.com/andrew000/aiogram-template.git
cd aiogram-template
I recommend using UV to manage your project.
# Create virtual environment using UV
uv venv --python=3.12.8
# Activate virtual environment
source .venv/bin/activate
# Install dependencies
make sync
Create a .env
file in the root of the project and fill it with the necessary data.
cp .env.example .env
make up
The project structure is as follows:
AIOGRAM-TEMPLATE
├───app (main application)
│ ├───bot (bot)
│ ├───migrations (alembic migrations)
│ ├───requirements.txt (auto-generated requirements file. Use `make freeze` to update)
│ └───Dockerfile (Dockerfile for the bot)
├───caddy (Caddy web server)
├───psql (PostgreSQL database)
│ ├───data (database data)
│ └───db-init-script (database initialization script)
├───redis (Redis database)
│ └───data (redis data)
├───pyproject.toml (project configuration)
├───.env.example (example environment file)
├───docker-compose.yml (docker-compose configuration)
├───.pre-commit-config.yaml (pre-commit configuration)
└───Makefile (make commands)
The bot is located in the app/bot
directory. The bot is divided into modules, each of which is responsible for a
specific functionality. handlers
are responsible for processing events, middlewares
for preprocessing events,
storages
for declaring models and working with the database, locales
for localization, filters
for own filters,
errors
for error handling.
Migration files are located in the app/migrations
directory.
I hate when app makes migrations automatically. It often causes problems. So I prefer to create and upgrade migrations
manually. Additionally, I always add function, to compare in-code migration_rev_id
with database migration_rev_id
(function is not included in template). If they are different, the app will raise an error and exit.
To create initial migration, check if your models imported in the app/bot/storages/psql/__init__.py
file and run the
following command (Don't forget to run database container):
Command will create initial migration file in the app/migrations/versions
directory and create an empty table
alembic_version
in the database.
make create-init-revision
To apply the migration, run the following command:
make upgrade-revision revision=<revision_id>
revision_id
- id of the migration in the app/migrations/versions
directory. Initial migration id is
000000000000
.
To check current migration revision_id
in the database, run the following command:
make current-revision
The bot supports localization. Localization files are located in the app/bot/locales
directory. The bot uses the
aiogram-i18n
library for localization and FTL-Extract
for extracting FTL-keys from the code.
To extract FTL-keys from the code, run the following command:
make extract-locales
After extracting FTL-keys, you can find new directories and files in the app/bot/locales
directory. To add or remove
locales for extraction, edit Makefile
I recommend to make a submodule from app/bot/locales
directory. It will allow you to control locales versions and
publish them (without code exposing) for translations help by other people.
The project uses pre-commit hooks. To install pre-commit hooks, run the following command:
uv run pre-commit install
Now, before each commit, pre-commit hooks will be executed. If any of the hooks fail, the commit will be canceled. Also,
pre-commit generates requirements file app/requirements.txt
and updates it on each commit. To update requirements file
manually, run the following command:
make freeze
requirements.txt
file is used in the Dockerfile to install dependencies.
Make sure to commit the requirements.txt
file.
The project uses Docker for deployment. To build and run the bot in Docker, run the following command:
make up
Yes, little command to run large project. It will build and run the bot, PostgreSQL, Redis, and Caddy containers.
To gracefully stop the bot and remove containers, run the following command:
make down
The project uses Caddy as a web server. Caddy can automatically get and renew SSL certificates. To configure Caddy, edit
the Caddyfile
file in the caddy
directory. public
directory is used to store static files.
By default, Caddy is disabled in the docker-compose.yml
file. To enable Caddy, uncomment the caddy
service in the
docker-compose.yml
file.
Bot may use webhooks. To enable webhooks, set WEBHOOKS
environment variable to True
in the .env
file. Also, set
WEBHOOK_URL
and WEBHOOK_SECRET_TOKEN
environment variables.
Don't forget to uncomment the caddy
service in the docker-compose.yml
file.
Q: Why PyCharm marks import with red color?
A: I use "unique" project structure, where app
directory contains code, but root directory contains configuration
files.
In PyCharm, right-click on the app
directory and select Mark Directory as
-> Sources Root
. Also,
unmark project root directory Unmark as Sources Root
. This will fix the problem.
Q: Why You import sys
or os
libs
like this?
A: My inclinations make me do this to avoid some attack vector invented by my paranoia
Q: Why not use aiogram-cli
?
A: It's a good library, but I prefer to use my own code 🤷♂️
First, run make outdated
to check for outdated dependencies. Then, edit pyproject.toml
file and run the
following command to update dependencies:
make outdated
# Edit pyproject.toml
make sync
make outdated
make lint
make mypy
make format