Fullstack is a comprehensive full stack project template with React frontend, Node.js/Express backend, and PocketBase database.
# Clone the repository
git clone https://github.com/dastron/project.git
cd project
# Rename the project from template (interactive)
yarn rename
# Install dependencies
yarn install
# Complete setup (runs scripts, builds everything)
yarn setup
# Start development environment
yarn dev# Install dependencies
yarn install
# Complete setup (runs scripts, installs dependencies, builds)
yarn setup
# Start development environment (frontend, backend, shared, PocketBase)
yarn dev
# Build all workspaces
yarn build
# Run PocketBase server only
yarn pb
# Generate migrations from Zod schemas
yarn migrate:generate
# Check migration status
yarn migrate:status
# Sync dev database migrations to/from project
yarn pb:sync
# Creates a migration snapshot of the current pb
yarn pb:snapshot
# Create/regenerate base snapshot from PocketBase
yarn pb:base-snapshotyarn test # Run tests across all workspaces
yarn check # Run all checks (format, lint, typecheck)
yarn lint # Run linting across all workspaces
yarn format # Format code across all workspaces
yarn typecheck # Run type checking across all workspaces
yarn clean # Clean all workspacesyarn outdated # Check for outdated packages
yarn update-deps # Update all dependencies
yarn focus # Focus on a specific workspace
yarn why # Check why a package is installedproject/
├── app/ # Vite React frontend
│ └── package.json
├── functions/ # Node.js/Express backend
│ └── package.json
├── shared/ # Shared code between workspaces
│ ├── src/
│ │ └── schema/ # Zod schemas (source of truth for DB)
│ └── package.json
├── pocketbase/ # PocketBase configuration
│ └── pb_migrations/ # Generated migration files
├── package.json # Root configuration
└── README.md
This project uses a schema-driven approach where Zod schemas in shared/src/schema/ serve as the single source of truth for the database structure. Migrations are automatically generated from these schemas.
The migration system uses a base snapshot (pocketbase/pb_migrations/000000000_collections_snapshot.js) that represents PocketBase's initial state with system collections. This file:
- Contains PocketBase's default system collections (
_mfas,_otps,_externalAuths,_authOrigins,_superusers) - Includes the default
userscollection - Serves as the starting point for schema comparisons
- Is automatically created during
yarn setupif it doesn't exist
When to regenerate the base snapshot:
- After upgrading PocketBase versions (system collections may change)
- When setting up a new development environment
- If the base snapshot is missing or corrupted
yarn pb:base-snapshot- Define schema in
shared/src/schema/entity.ts:
import { z } from "zod";
import { baseSchema } from "./base";
export const EntityInputSchema = z.object({
name: z.string().min(2),
status: z.enum(["active", "inactive"]),
});
export const EntitySchema = EntityInputSchema.extend(baseSchema);- Generate migration:
yarn migrate:generate- Apply migration (automatic on PocketBase startup):
yarn pbFor complete documentation, see shared/MIGRATION_GUIDE.md.
-
Create a
.envfile in the root directory by copying the example:cp .envExample .env
-
Configure the environment variables in
.env:# Functions Service (Node) FUNCTIONS_PORT=8081 API_URL='http://localhost:8080' # PocketBase URL for backend OPENAI_API_KEY='sk-proj-...' PB_SUPERUSER_EMAIL='admin@example.com' PB_SUPERUSER_PASSWORD='password' # App Service (Vite) VITE_FUNCTIONS_URL='http://localhost:8081' # Functions URL for frontend VITE_POCKETBASE_URL='http://localhost:8080' # PocketBase URL for frontend # PocketBase (used in docker/staging) PB_VERSION=0.34.2 # Specify desired PocketBase version -
Adjust the configuration as needed for your environment.
-
Install dependencies:
yarn install
-
Complete setup (runs scripts, installs dependencies, builds):
yarn setup
-
Start the development environment:
yarn dev
This will concurrently run:
- Shared workspace watcher
- React frontend (Vite)
- Express backend
- PocketBase server
This project uses Yarn Workspaces to manage dependencies across multiple packages:
# To work on a specific workspace
yarn workspace @project/app <command>
# To run commands across all workspaces
yarn workspaces foreach <command>
# To focus on a specific workspace
yarn focus @project/appYou can run the application in a production-like environment using Docker:
# Build and run the Docker container locally
yarn stagingTo manually build and run the Docker container:
# Build the Docker image
docker build -t fullstack-pb-template:local .
# Create a .dockerEnv file from .env
cp .dockerEnvExample .dockerEnv
# Run the container
docker run --rm -it \
--env-file .dockerEnv \
-p 8081:8081 \
-p 8000:80 \
-p 8080:8080 \
fullstack-pb-template:localThis exposes:
- Frontend on http://localhost:8000
- PocketBase on http://localhost:8080
- API functions on http://localhost:8081
The Docker image includes:
- Compiled frontend (served via Nginx)
- Backend API server
- PocketBase database
- Process management with Supervisor
This project uses GitHub Actions for continuous integration and deployment:
-
Automated Testing: On every push and pull request, tests are run to ensure code quality.
-
Docker Image Building: When a release is created or on pushes to the main branch:
- A Docker image is built using the multi-stage Dockerfile
- The image is tagged and pushed to the Docker registry
- Both versioned tags and latest/nightly tags are created
-
Release Management: Release Please handles versioning based on conventional commits.
The following Docker image tags are available:
dastro/project:latest- Latest stable releasedastro/project:x.y.z- Specific version (e.g., 1.0.0)dastro/project:nightly- Latest nightly builddastro/project:nightly-YYYYMMDD- Specific nightly build date
This project uses Release Please to automate versioning and changelog generation.
-
Commit messages follow the Conventional Commits format:
feat: add new feature- Minor version bumpfix: resolve bug- Patch version bumpdocs: update README- No version bumpchore: update dependencies- No version bumpBREAKING CHANGE: redesign API- Major version bump
-
When commits are pushed to the main branch, Release Please automatically creates or updates a release PR.
-
When the release PR is merged, Release Please:
- Creates a new GitHub release with a generated changelog
- Tags the release with the new version
- Triggers the release Docker build workflow
This project uses semantic versioning managed by Release Please. When a new release is created:
- The version number is automatically incremented based on commit types
- The version is passed to the Docker build process as a build argument
- The Docker image is tagged with both the specific version and "latest"
- Inside the Docker container:
- The version is available as an environment variable
- Frontend apps can access it via
VITE_APP_VERSION - Backend services can access it via
APP_VERSION - The version is displayed in logs during container startup