In today's fast-paced development world, choosing the right tech stack can make or break your project timeline. While Angular remains one of the most powerful frontend frameworks, developers often struggle with backend setup complexity. Enter PocketBase – an open-source backend that gives you authentication, database, and file storage in a single file.
In this guide, I'll show you how to build a complete web application using Angular + PocketBase, combining the best of both worlds.
Why Angular + PocketBase?
Angular Benefits:
Full-featured MVC framework with TypeScript support
Built-in dependency injection
Powerful CLI for scaffolding
RxJS for reactive programming
Enterprise-ready architecture
PocketBase Benefits:
Single binary deployment (no complex setup)
Embedded SQLite database
Built-in authentication (email, OAuth2)
Real-time subscriptions via Server-Sent Events (SSE)
Automatic REST API generation
Admin dashboard UI included
File storage capabilities
Perfect For:
MVPs and startups needing rapid development
Internal tools and dashboards
E-commerce applications
Content management systems
Real-time collaborative apps
Prerequisites
Before we begin, ensure you have:
Node.js (v18 or later)
Angular CLI (
npm install -g @angular/cli)PocketBase executable (download from pocketbase.io)
Basic knowledge of TypeScript and Angular
Step 1: Setting Up PocketBase
1. Download and Install
# For Linux/Mac wget https://github.com/pocketbase/pocketbase/releases/download/v0.22.0/pocketbase_0.22.0_linux_amd64.zip unzip pocketbase_0.22.0_linux_amd64.zip # For Windows # Download the .exe file from GitHub releases
2. Start PocketBase
./pocketbase serveYour PocketBase server will run at http://127.0.0.1:8090. Visit the admin UI at http://127.0.0.1:8090/_/ and create your admin account.
3. Create Your First Collection
In the admin UI, create a new collection called posts with fields:
title(text, required)content(text, required)published(boolean, default false)created(date, auto)
Step 2: Creating Angular Application
1. Generate New Angular Project
ng new angular-pocketbase-app --style=css --routing cd angular-pocketbase-app
2. Install PocketBase SDK
npm install pocketbase3. Create PocketBase Service
Generate a service to handle all PocketBase interactions:
ng generate service services/pocketbase4. Configure Environment Variables
Update src/environments/environment.ts:
export const environment = { production: false, pocketBaseUrl: 'http://127.0.0.1:8090' };
Step 3: Building the PocketBase Service
src/app/services/pocketbase.service.ts
import { Injectable } from '@angular/core'; import PocketBase from 'pocketbase'; import { environment } from '../../environments/environment'; @Injectable({ providedIn: 'root' }) export class PocketbaseService { private pb: PocketBase; constructor() { this.pb = new PocketBase(environment.pocketBaseUrl); } // Authentication methods async login(email: string, password: string) { return await this.pb.collection('users').authWithPassword(email, password); } async register(email: string, password: string, passwordConfirm: string) { return await this.pb.collection('users').create({ email, password, passwordConfirm }); } logout() { this.pb.authStore.clear(); } get currentUser() { return this.pb.authStore.model; } // Posts CRUD operations async getPosts() { return await this.pb.collection('posts').getFullList({ sort: '-created', filter: 'published = true' }); } async createPost(data: any) { return await this.pb.collection('posts').create(data); } async updatePost(id: string, data: any) { return await this.pb.collection('posts').update(id, data); } async deletePost(id: string) { return await this.pb.collection('posts').delete(id); } // Real-time subscriptions subscribeToPosts(callback: (data: any) => void) { return this.pb.collection('posts').subscribe('*', (e) => { callback(e); }); } }
Step 4: Creating Components
1. Posts List Component
ng generate component posts-listsrc/app/posts-list/posts-list.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core'; import { PocketbaseService } from '../services/pocketbase.service'; @Component({ selector: 'app-posts-list', templateUrl: './posts-list.component.html', styleUrls: ['./posts-list.component.css'] }) export class PostsListComponent implements OnInit, OnDestroy { posts: any[] = []; private unsubscribe: any; constructor(private pb: PocketbaseService) {} async ngOnInit() { await this.loadPosts(); this.setupRealtime(); } async loadPosts() { this.posts = await this.pb.getPosts(); } setupRealtime() { this.unsubscribe = this.pb.subscribeToPosts((data) => { console.log('Realtime update:', data); this.loadPosts(); // Reload posts on any change }); } ngOnDestroy() { if (this.unsubscribe) { this.unsubscribe(); } } }
src/app/posts-list/posts-list.component.html
<div class="posts-container"> <h2>Latest Posts</h2> <div class="posts-grid"> <div *ngFor="let post of posts" class="post-card"> <h3>{{ post.title }}</h3> <p>{{ post.content }}</p> <small>Published: {{ post.created | date }}</small> </div> </div> </div>
Step 5: Adding Authentication UI
1. Login Component
ng generate component loginsrc/app/login/login.component.ts
import { Component } from '@angular/core'; import { Router } from '@angular/router'; import { PocketbaseService } from '../services/pocketbase.service'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'] }) export class LoginComponent { email = ''; password = ''; error = ''; constructor( private pb: PocketbaseService, private router: Router ) {} async onSubmit() { try { await this.pb.login(this.email, this.password); this.router.navigate(['/posts']); } catch (err: any) { this.error = err.message || 'Login failed'; } } }
Step 6: Real-time Features with RxJS
PocketBase's real-time capabilities work beautifully with Angular's RxJS. Here's an enhanced service using Observables:
import { Observable } from 'rxjs'; // In pocketbase.service.ts watchPosts(): Observable<any> { return new Observable((observer) => { const unsubscribe = this.pb.collection('posts').subscribe('*', (data) => { observer.next(data); }); return () => unsubscribe(); }); }
Now you can use this in components:
this.pb.watchPosts().subscribe(update => { console.log('Real-time update:', update); // Update your local data accordingly });
Step 7: Deployment Considerations
Building Angular for Production
ng build --prodDeploying PocketBase
Upload PocketBase binary to your VPS or cloud server
Set up as a systemd service for auto-restart
Configure environment variables
Use Nginx as reverse proxy for SSL
Sample systemd service file:
[Unit] Description=PocketBase service [Service] Type=simple User=youruser WorkingDirectory=/opt/pocketbase ExecStart=/opt/pocketbase/pocketbase serve --http=0.0.0.0:8090 Restart=on-failure [Install] WantedBy=multi-user.target
Step 8: Security Best Practices
Environment Variables: Never hardcode credentials
CORS Configuration: Configure PocketBase CORS properly
Validation Rules: Set collection validation rules in PocketBase admin
API Rules: Implement proper collection permissions
HTTPS: Always use SSL in production
Conclusion
Angular + PocketBase creates a powerful, modern stack that significantly reduces development time while maintaining scalability and performance. PocketBase handles all backend complexity, letting you focus on building amazing Angular applications.
Key Takeaways:
PocketBase provides instant backend with zero configuration
Angular offers robust structure for large applications
Real-time features are simple to implement
Perfect for startups and MVPs
Open-source and self-hosted (no vendor lock-in)
Next Steps
Explore PocketBase's file upload capabilities
Implement OAuth authentication (Google, GitHub)
Add search functionality
Build an admin dashboard
Deploy to production with Docker