Showing posts with label Backend as a Service. Show all posts
Showing posts with label Backend as a Service. Show all posts

Tuesday, 10 March 2026

Building Modern Web Applications with Angular and PocketBase: A Complete Guide

 


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:

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

bash
# 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

bash
./pocketbase serve

Your 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

bash
ng new angular-pocketbase-app --style=css --routing
cd angular-pocketbase-app

2. Install PocketBase SDK

bash
npm install pocketbase

3. Create PocketBase Service
Generate a service to handle all PocketBase interactions:

bash
ng generate service services/pocketbase

4. Configure Environment Variables
Update src/environments/environment.ts:

typescript
export const environment = {
  production: false,
  pocketBaseUrl: 'http://127.0.0.1:8090'
};

Step 3: Building the PocketBase Service

src/app/services/pocketbase.service.ts

typescript
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

bash
ng generate component posts-list

src/app/posts-list/posts-list.component.ts

typescript
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

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

bash
ng generate component login

src/app/login/login.component.ts

typescript
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:

typescript
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:

typescript
this.pb.watchPosts().subscribe(update => {
  console.log('Real-time update:', update);
  // Update your local data accordingly
});

Step 7: Deployment Considerations

Building Angular for Production

bash
ng build --prod

Deploying PocketBase

  1. Upload PocketBase binary to your VPS or cloud server

  2. Set up as a systemd service for auto-restart

  3. Configure environment variables

  4. Use Nginx as reverse proxy for SSL

Sample systemd service file:

ini
[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

  1. Environment Variables: Never hardcode credentials

  2. CORS Configuration: Configure PocketBase CORS properly

  3. Validation Rules: Set collection validation rules in PocketBase admin

  4. API Rules: Implement proper collection permissions

  5. 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