A production-style Go backend for a Telegram-first tire and wheel commerce platform.
This service powers three operational surfaces:
- a buyer-facing Telegram Mini App for catalog browsing and checkout,
- a staff-facing warehouse and order management panel,
- an admin layer for reporting, exports, user management, and operational auditability.
The codebase is structured around clear application boundaries: HTTP transport, services, repositories, infrastructure integrations, and domain models. It is intentionally practical rather than over-engineered, with a focus on shipping warehouse workflows, Telegram automation, and e-commerce operations end to end.
- Telegram authentication for Mini Apps
- Public catalog API for client storefronts
- Order creation and order history for buyers
- Staff inventory management with lots, photos, QR codes, and printable price tags
- Warehouse CRUD and inter-warehouse transfers
- Order status workflow and buyer messaging via Telegram bot
- Admin-only reports, exports, notifications, audit logs, and user management
- MinIO-backed media storage
- Google Sheets export support
- PostgreSQL persistence with automatic schema migration on startup
The backend is designed for a tire retail operation, but the data model is broader than tires only.
Supported product groups include:
- Tires
- Rims
- Accessories
Accessory support includes categories such as:
- Fasteners
- Hub rings
- Spacers
- Tire bags
This makes the service suitable for a compact but realistic automotive commerce and warehouse management project.
The project follows a layered structure:
internal/domaincontains business entities, DTOs, filters, and repository/service contracts.internal/servicecontains business workflows and orchestration.internal/repository/pgcontains PostgreSQL persistence logic.internal/repository/modelscontains database models used by GORM.internal/transport/http/v1contains HTTP handlers and request parsing.internal/infrastructurecontains external integrations such as Telegram, MinIO, QR generation, and Google Sheets export.pkgcontains lower-level technical packages such as database and JWT setup.cmd/apicontains the application entrypoint and dependency wiring.
This is a pragmatic clean-architecture variant: domain and use-case logic stay separated from transport and infrastructure, but the project remains compact enough for a commercial pet project.
- Browse lots through a public API
- Create buyer orders
- Retrieve buyer order history
- Preserve order item snapshots for reliable post-purchase order details
- Manage lots with prices, stock, status, photos, and warehouse assignment
- Generate QR codes for lots
- Upload and remove lot photos
- Filter inventory across tire, rim, and accessory-specific attributes
- Manage warehouses
- Create transfers between warehouses
- Accept or cancel transfers
- Track transfer items and stock flow
- List staff orders
- Update order status
- Send messages to buyers through the client Telegram bot
- Persist order message threads
- Receive buyer replies through a webhook
- Profit and loss reports
- Inventory and P&L export to Google Sheets
- User management and role changes
- Audit log browsing with filters
- Internal notification center for admins
The backend supports two Telegram bots with distinct responsibilities.
Configured through:
TELEGRAM_BOT_TOKEN
Used for:
- internal admin notifications,
- staff-facing communication flows,
- operational alerts.
Configured through:
CLIENT_TELEGRAM_BOT_TOKEN
Used for:
- buyer-facing Telegram Mini App authentication,
- buyer message delivery related to orders,
- receiving buyer replies through a webhook.
This separation matters. Buyer communication should go through the bot the buyer already interacted with, while internal alerts should stay inside the staff/admin bot channel.
High-level route groups:
POST /api/v1/auth/telegramGET /api/v1/lotsPOST /api/v1/telegram/client/webhook
POST /api/v1/ordersGET /api/v1/orders
GET /api/v1/staff/lotsPOST /api/v1/staff/lotsPUT /api/v1/staff/lots/:idDELETE /api/v1/staff/lots/:idGET /api/v1/staff/lots/:id/qrPOST /api/v1/staff/lots/uploadDELETE /api/v1/staff/lots/:id/photosGET /api/v1/staff/ordersPATCH /api/v1/staff/orders/:id/statusPOST /api/v1/staff/orders/:id/messageGET /api/v1/staff/orders/:id/messagesGET /api/v1/staff/transfersGET /api/v1/staff/transfers/:idPOST /api/v1/staff/transfersPOST /api/v1/staff/transfers/:id/acceptPOST /api/v1/staff/transfers/:id/cancelGET /api/v1/staff/warehouses
GET /api/v1/admin/reports/pnlGET /api/v1/admin/exports/inventoryGET /api/v1/admin/exports/pnlGET /api/v1/admin/usersPOST /api/v1/admin/usersPUT /api/v1/admin/users/:id/roleDELETE /api/v1/admin/users/:idPOST /api/v1/admin/warehousesPUT /api/v1/admin/warehouses/:idDELETE /api/v1/admin/warehouses/:idGET /api/v1/admin/audit-logsGET /api/v1/admin/notificationsPOST /api/v1/admin/notifications/:id/read
For the exact request and response contracts, use the generated Swagger docs.
- Go
- Gin
- GORM
- PostgreSQL
- JWT
- Telegram Bot API
- MinIO (S3-compatible object storage)
- Google Sheets API
- Swaggo / Swagger
- Docker / Docker Compose
Primary transactional database for users, warehouses, lots, orders, transfers, audit logs, and notifications.
Used for storing lot photos and serving them through public URLs.
Used for:
- Mini App authentication,
- buyer order messaging,
- internal admin notifications.
Used for admin export flows, including inventory and P&L exports.
Used for warehouse operations and printable lot labels.
Create a .env file in the repository root. A working example is provided in .env.example.
| Variable | Required | Description |
|---|---|---|
HTTP_PORT |
No | API port. Default: 8083 |
ENV |
No | Runtime environment name, e.g. local |
POSTGRES_HOST |
Yes | PostgreSQL host |
POSTGRES_PORT |
Yes | PostgreSQL port |
POSTGRES_USER |
Yes | PostgreSQL username |
POSTGRES_PASSWORD |
Yes | PostgreSQL password |
POSTGRES_DB |
Yes | PostgreSQL database name |
POSTGRES_SSLMODE |
No | PostgreSQL SSL mode |
JWT_SECRET |
Yes | JWT signing secret |
JWT_TTL |
No | JWT lifetime. Default: 72h |
TELEGRAM_BOT_TOKEN |
Yes | Staff/internal Telegram bot token |
CLIENT_TELEGRAM_BOT_TOKEN |
Yes | Buyer/client Telegram bot token |
CLIENT_BOT_WEBHOOK_URL |
Recommended | Public webhook URL for buyer replies |
MINIO_ENDPOINT |
Yes | MinIO endpoint |
MINIO_ACCESS_KEY |
Yes | MinIO access key |
MINIO_SECRET_KEY |
Yes | MinIO secret key |
MINIO_BUCKET_NAME |
Yes | MinIO bucket name |
MINIO_PUBLIC_URL |
Yes | Public base URL for stored files |
MINIO_USE_SSL |
No | Whether MinIO uses SSL |
GOOGLE_SPREADSHEET_ID |
Optional | Spreadsheet used for export workflows |
- Go toolchain compatible with the project
- Docker and Docker Compose, or local PostgreSQL + MinIO
- Telegram bot tokens for both staff and client flows
- Optional: Google service credentials if you plan to use Sheets export
cp .env.example .envThen update secrets and environment-specific values.
docker compose up -d db minio pgadminAvailable local services from docker-compose.yml:
- API:
http://localhost:8083 - MinIO API:
http://localhost:9000 - MinIO Console:
http://localhost:9001 - PgAdmin:
http://localhost:5050
go run ./cmd/api/main.goOn startup the application:
- loads configuration,
- connects to PostgreSQL,
- auto-migrates database tables,
- ensures the MinIO bucket exists,
- wires Telegram senders and webhook support,
- seeds a default warehouse if none exists.
If you want to run the API in Docker as well:
docker compose up --buildThe API exposes Swagger UI at:
http://localhost:8083/swagger/index.html
If you update handler annotations and want to regenerate Swagger docs:
swag init -g cmd/api/main.goA simple health route is available at:
GET /health
Buyer replies to order messages are received through the client bot webhook:
POST /api/v1/telegram/client/webhook
For this to work reliably, CLIENT_BOT_WEBHOOK_URL must point to a public HTTPS endpoint that Telegram can reach.
Example:
CLIENT_BOT_WEBHOOK_URL=https://api.example.com/api/v1/telegram/client/webhookThe application can ensure the webhook automatically on startup when this value is configured.
Important constraints:
- Telegram cannot deliver webhooks to plain
localhost. - For local development, use a tunnel or a public dev URL.
- Buyer replies can be associated with an order thread only when the message context allows it.
cmd/
api/ Application entrypoint and wiring
internal/
config/ Environment config loading
domain/ Business entities, DTOs, contracts
infrastructure/ Telegram, storage, QR, Sheets integrations
repository/
models/ GORM models
pg/ PostgreSQL repositories
service/ Business logic and orchestration
transport/
http/
middleware/ Auth middleware
v1/ HTTP handlers
pkg/
database/ PostgreSQL bootstrapping
jwt/ JWT utilities
docs/ Generated Swagger assets
tma-test/ Local HTML test page for Mini App experiments
Order communication is modeled as a thread attached to order_id, not as a generic free-form chat.
That decision keeps conversations operationally clean:
- one buyer can have multiple orders,
- each order keeps its own message history,
- staff communication does not get mixed across unrelated orders.
Operational changes are designed to be inspectable via audit logs and admin notifications. This is useful for warehouse environments where state changes should remain traceable.
Order items preserve product snapshots so historical orders remain readable even if the source lot later changes or disappears from the active catalog.
Run the full test suite:
go test ./...This backend is a strong fit for:
- a commercial pet project that should look and behave like a real internal platform,
- a portfolio project demonstrating end-to-end product thinking,
- a Telegram-native commerce workflow with warehouse operations,
- a compact back office with practical admin tooling.
It is not positioned as a generic marketplace framework. It is intentionally specialized around automotive retail and operations.
This repository currently includes a LICENSE file. Use that file as the source of truth for licensing terms.