Packages your full-stack tool/app/product in a single Docker image (~33 MB
) and stores it in a centralized location (GitHub Container Registry by default), making it easily accessible for distribution across different environments.
- Refine provides business logic for your UI elements, supporting CRUD functions, security, state management, and live updates.
- PocketBase is a powerful combination of a database, real-time API, authentication with a dynamic authorization system, file storage, backup management, and an admin dashboard with robust user management.
- This template combines these two open-source tools, saving you days of setting up dependencies, build-scripts, pipelines, and distribution, allowing you to start shipping features right away.
-
Frontend
- Refine (React meta-framework for CRUD-heavy web applications)
- Refine providers for PocketBase using the refine-pocketbase library and PocketBase JS SDK
- Headless, use any UI framework you like
- Real-time updates enabled
- E2E tests with Playwright (optional)
- Typesafe routes using the typesafe-routes library (optional)
- Pre-configured TypeScript type generation from database schema with pocketbase-typegen (optional)
- Vite, TypeScript, ESLint
-
Backend (Pocketbase)
- SQLite database and CRUD API
- Admin dashboard
- Authentication with passwords, OTP, OAuth2, MFA, and users impersonation
- Authorization with custom roles and rules
- File storage (local file system or S3 storage)
- Pre-configured email testing with Inbucket webmail server
- Custom routes, middlewares and event hooks with JavaScript
-
Distribution
- Preconfigured GitHub Actions pipeline (build, test, container registry push)
- Frontend & backend in a single Docker image
- Stores Docker images in GitHub Container Registry by default
- Easy self-hosting on VPS (Hetzner, Linode, Fly.io, etc.) or using your own hardware (e.g., Raspberry Pi)
- Ready for cloud deployment via Google Cloud Run
To begin developing your features, you need to start PocketBase, Inbucket, and the frontend. Below are the commands to start the necessary services, along with their URLs and default credentials.
PocketBase serves as the backend and can be started using the following Docker Compose command:
cd pocketbase
docker compose up
The admin dashboard is part of PocketBase and can be accessed through a web browser using the following credentials:
- URL: http://localhost:8090/_
- User: [email protected]
- Password: 1234567890
Important
The default credentials can be changed in the admin dashboard to maintain security.
Inbucket is a local email service that can be used for testing purposes. For example, you can send password recovery emails or OTP codes from PocketBase to Inbucket. PocketBase is preconfigured to use Inbucket, so no additional setup is required. It starts automatically with PocketBase.
This setup allows you to easily test email functionalities without needing an external email service.
The frontend is a React application with basic dependencies such as Refine, ESLint, and Vite. You can start the development server with the following command:
cd app
npm run dev # starts dev server on port 8080
This will launch the application, making it accessible in your browser at the specified URL. Ensure that all necessary dependencies are installed before running the development server.
Now you are all set up to add more frontend dependencies and start turning your app ideas into code. If you're interested in learning how to deploy your application and make your features available to users, continue reading the distribution section.
cd app
npm run codegen # updates generated database schema types
npx playwright test --ui # runs playwright tests with gui
Database migrations are a way to manage versions of your database schema. They allow you to update your database schema in production while preserving existing data. Migrations are generated automatically whenever the database schema is modified using the PocketBase dashboard. However, you also have the option to create migrations manually. Since migrations are part of the distribution process, they must be included in your git commits to ensure they are part of the final Docker image.
Tip
Remember to regularly commit and test migration changes to prevent issues during deployment.
The default distribution method is via GitHub Container Registry. Other container registries (Dockerhub, gcr.io, etc.) can also be used, but they require minor adjustments to the GitHub Action workflow file.
A GitHub workflow will build a single Docker image that can be deployed with a single command (docker compose up -d
) on your server or using tools like Portainer and Docker, etc.
Note:
If you prefer not to manage your own server, you can opt-out of the GitHub Actions workflow by deleting the.github/workflows/build.yml
file and switching to Google Cloud Run or similar cloud hosting services.You can find deployment instructions for Google Cloud Run here, and here is the corresponding discussion thread.
This approach allows for flexible distribution options depending on your infrastructure preferences and requirements.
You can build and push a new Docker image of a new version by creating a git tag following semver-like syntax:
git tag 1.0.0 # creates a tag for the latest commit
git push --tags # pushes the created tag to github
Only tags that match the [0-9]+.[0-9]+.[0-9]+
format will trigger the build workflow. However, if you want to support more complex version patterns, you can modify the format by editing the .github/workflows/build.yml
file.
This flexibility allows you to adjust the versioning scheme to fit your project's needs.
Note
All Docker images will be pushed to the GitHub Container Registry associated with your Git repository.
This ensures that your images are stored in a centralized location, making them easily accessible for deployment across different environments.
Pushing a new tag will trigger a workflow that builds a Docker image, which is then pushed to the GitHub Container Registry by default.
The default architecture is linux/amd64
. Modify the .github/workflows/build.yml
file if you want to self-host the Docker image on a Raspberry Pi or deploy to a server with an ARM architecture.
Building multiple architectures (e.g., linux/amd64,linux/arm64,linux/arm/v7
) simultaneously is also possible. Considerations for architecture and infrastructure are important for ensuring compatibility with your environment.
For deploying PocketBase on a Synology NAS, refer to this guide: How to Install PocketBase on Your Synology NAS.
Deploying a Docker image on your server is straightforward. The fastest method is to create a docker-compose.yaml
file on your server with the following content, describing your service:
name: refine-pocketbase-starter
services:
refine-pocketbase-starter:
image: ghcr.io/kruschid/refine-pocketbase-starter:latest # replace with your image
restart: always
ports:
- 8090:8090
volumes:
- ./volumes/pb_data:/pb/pb_data
After that, simply navigate to that file in your terminal and enter:
docker compose up -d
This will start all services defined in the docker-compose.yaml
file and keep them running in the background, even after you disconnect from your server. In this example there is only one service refine-pocketbase-starter
.
Your GitHub repository might be private. In that case, you might see an unauthorized error in your terminal. Read the next section to learn how to generate a GitHub token to download from your private container registry.
The following steps are required to pull Docker images from a private GitHub container registry.
- Go to GitHub and log in to your account.
- Navigate to
Settings
>Developer settings
>Personal access tokens
. - Click on
Generate new token
. - Set a note for the token, like
GitHub Container Registry
. - Set the expiration for the token as per your requirement.
- Under Select scopes, ensure you check
read:packages
. - Click Generate token and copy the token somewhere safe, as you won't be able to view it again.
After completing these steps, connect to your server and type the following command in the terminal. You will be asked for a Username
and Password
. The Username
is your GitHub username, and for the Password
, you need to use the GitHub token you just created.
docker login ghcr.io/kruschid # replace with your namespace
Username: kruschid # replace with your github username
Password: ***** # replace with your github token
After the initial deployment, you will need to perform a few manual steps to improve security and prevent data loss.
- Change the default admin credentials to a secure email/password combination.
- Update the SMTP settings to use our production email server/service (AWS SES, etc.).
- Enable scheduled backups in the admin dashboard by using a remote bucket (S3, Backblaze, etc.).
More details can be found on the pocketbase "Going to production" page
You can extend your Docker Compose file with caddy-docker-proxy to serve your app over HTTPS with a certificate for your domain.
Caddy is a web server that supports automatic provisioning of TLS certificates. By using caddy-docker-proxy, Caddy can be configured using labels. The docker-compose.yaml
file below serves the app via the fictional domain refine-pocketbase-starter.com
.
Make sure to replace the example domain with your actual domain and configure the necessary DNS settings to enable HTTPS for your application.
name: refine-pocketbase-starter
services:
refine-pocketbase-starter:
image: ghcr.io/kruschid/refine-pocketbase-starter:latest # replace with your image
restart: always
networks:
- caddy
volumes:
- ./volumes/pb_data:/pb/pb_data
labels:
caddy: refine-pocketbase-starter.com # replace with your domain
caddy.reverse_proxy: "{{upstreams 8090}}"
healthcheck: # optional but recommended
test: wget --no-verbose --tries=1 --spider http://localhost:8090/api/health || exit 1
interval: 5s
timeout: 5s
retries: 5
caddy:
image: lucaslorentz/caddy-docker-proxy:2.8-alpine
ports:
- 80:80
- 443:443
networks:
- caddy
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./volumes/caddy:/data
restart: unless-stopped
environment:
- CADDY_INGRESS_NETWORKS=caddy
- leave a star ⭐
- report a bug 🐞
- open a pull request 🏗️
- help others ❤️
- buy me a coffee ☕