Made by ⚡Sieutoc
Important
Work in progress, breaking changes are expected!
- Next.js 16
- TypeScript
- ESLint
- Prettier
- Shadcn UI with Tailwind CSS
- Postgresql with Prisma
- Email OTP authentication with Better-Auth
For easy deployment with Docker, we recommend using Dokploy - a self-hosted platform that simplifies application deployment. Follow the Docker deployment instructions below and use Dokploy's interface to manage your deployment.
You need at least one Postgresql instance up and running.
Then you can deploy like a simple Next.js app, there are lot of tutorial on Vercel, Netlify etc.
The environment variables you need:
BETTER_AUTH_SECRET=topsecret
BETTER_AUTH_URL=https://yourdomain.com
NEXT_PUBLIC_BASE_URL=https://yourdomain.com
DATABASE_URL=postgres://....
SMTP_USER=yoursmtpuser
SMTP_PASSWORD=yoursmtppass
SMTP_HOST=yoursmtpserver
SMTP_PORT=587- We use
pnpmpackage manager. Get it here. - Make sure Docker up and running.
- If your Docker account has 2FA enabled, you have to create a Personal Access Token and login before:
- Follow this guide.
- Login with
docker login --username <your-username>
cd your-project
pnpm installFor the first time, you need some default environment variables:
cp .env.example .envThen, run the development server:
pnpm devNOTE: The dev server need to be running, because we need Postgres instance.
Sometimes, for example in fresh database situation when you have just started:
pnpm prisma migrate devWe use shadcn-ui, and create 2 helper scripts for you:
# for adding new component
pnpm ui:add <compnent-name>
# for checking diffs
pnpm ui:diff <component-name>Open http://localhost:3000 with your browser and start developing.
- This project uses
App Routerfeature. - We try to take adventage of Next.js's ecosystem, thus most of the features here are built on top of Next.js best practices.
This project uses automated releases powered by semantic-release and follows Conventional Commits specification.
Every push to the master branch triggers an automated release process that:
- Analyzes commit messages to determine the version bump
- Generates/updates the
CHANGELOG.mdfile - Creates a GitHub release with release notes
- Updates the version in
package.json
Follow the Conventional Commits format for your commit messages:
<type>(<scope>): <subject>
<body>
<footer>
feat: A new feature (triggers minor version bump: 0.1.0 → 0.2.0)fix: A bug fix (triggers patch version bump: 0.1.0 → 0.1.1)perf: Performance improvements (triggers patch version bump)refactor: Code refactoring (triggers patch version bump)docs: Documentation changes (no release)style: Code style changes (no release)test: Adding or updating tests (no release)chore: Maintenance tasks (no release)ci: CI/CD changes (no release)build: Build system changes (no release)revert: Reverting previous changes (triggers patch version bump)
For breaking changes, add ! after the type or include BREAKING CHANGE: in the footer to trigger a major version bump:
# Example 1: Using !
git commit -m "feat!: redesign authentication API"
# Example 2: Using footer
git commit -m "feat: redesign authentication API
BREAKING CHANGE: The authentication API endpoints have been completely redesigned."# Feature (minor bump: 0.1.0 → 0.2.0)
git commit -m "feat: add dark mode toggle"
git commit -m "feat(auth): add social login with Google"
# Bug fix (patch bump: 0.1.0 → 0.1.1)
git commit -m "fix: resolve navigation menu overflow on mobile"
git commit -m "fix(api): handle null values in user profile"
# Performance improvement (patch bump)
git commit -m "perf: optimize image loading with lazy loading"
# No release
git commit -m "docs: update installation instructions"
git commit -m "chore: upgrade dependencies"
git commit -m "style: format code with prettier"Husky and commitlint are configured to validate your commit messages. If your commit message doesn't follow the Conventional Commits format, the commit will be rejected with a helpful error message.
In most cases, you don't need to manually update the version. However, if you need to force a specific version, you can do so using semantic-release's environment variables in the GitHub Actions workflow.
Docker images are automatically built and published to GitHub Container Registry on every release.
You can use specific versions in your docker-compose.yml:
# Use latest version
image: ghcr.io/getsieutoc/voi:latest
# Use specific version
image: ghcr.io/getsieutoc/voi:v1.0.0- Docker
- Docker Compose
- PostgreSQL 16+
- SMTP Credentials
Create a voi folder and copy the minimal content of this template below:
version: "3.8"
name: voi
services:
postgres:
container_name: voi-postgres
image: postgres:16-alpine
restart: always
ports:
- "5432:5432"
volumes:
- data:/var/lib/postgresql/data
environment:
POSTGRES_DB: postgresdb
POSTGRES_USER: postgresuser
POSTGRES_PASSWORD: yourpostgrespassword
app:
container_name: voi-app
image: ghcr.io/getsieutoc/voi:latest
restart: always
ports:
- "80:3000"
environment:
# Needed for authentication
BETTER_AUTH_SECRET: topsecret
BETTER_AUTH_URL: http://localhost
# Connection string to the PostgreSQL database
DATABASE_URL: postgres://postgresuser:yourpostgrespassword@db:5432/postgresdb
# From which account e-mails will be sent
EMAIL_FROM: [email protected]
SMTP_USER: username
SMTP_PASSWORD: password
SMTP_HOST: smtp.yourdomain.com
SMTP_PORT: 587
# Extra
PROJECT_NAME: Voi
volumes:
data:The Docker Compose file above defines two services: postgres and app. In case you're using an external Postgres database, remove the db service and replace DATABASE_URL environment variable with your connection string.
Open your favorite terminal, navigate to voi folder and run
docker compose pull
docker compose up -dYou can find the logs by using docker-compose logs app. The message http server started on :3000 means everything is ok and you're ready to go.
Just open your favorite browser and navigate to http://localhost. You should see a voi app.
Congratulation! 🎉 🎉

