skip to content
Mohammad Rebati

Free Angular App with Cloudflare Workers and Supabase

/ 9 min read

Christmas at Königsee

My Journey to a Fully Serverless Angular App with Cloudflare and Supabase

About last year the same time

Last year, during our company’s Christmas party, I spent two wonderful nights at Königsee in Germany. The Alps provided a breathtaking backdrop as we enjoyed a fun-filled celebration by the lake. Here’s a photo I took of the serene lake surrounded by trees and a charming house in the background. It was a perfect blend of festive joy and natural beauty.

Hello, tech enthusiasts! Today, I want to share an exciting adventure I embarked on to build a fully serverless Angular application using Cloudflare Workers as my API, Cloudflare Pages for deployment, and Supabase for the database. The best part? I did it all on free tiers, and it worked like a charm. So, grab a snack, sit back, and let’s dive into this story of seamless integration, cost-effective solutions, and a few unexpected twists.

The Challenge: Building a Scalable Angular App Without Breaking the Bank

A few months ago, I decided to create a feature-rich Angular application that required a robust backend and scalable infrastructure. Traditional setups often involve juggling multiple services, dealing with hefty pricing as the user base grows, and managing server maintenance. I wanted something different—something modern, serverless, and preferably free to get started.

Issues I Faced:

  • High Initial Costs: Traditional backend services were expensive, especially when scaling.
  • Complex Integrations: Coordinating between different services was cumbersome.
  • Maintenance Overhead: Managing servers and ensuring uptime added to the workload.
  • Performance Bottlenecks: Ensuring low latency and high availability was a constant struggle.

Determined to find a better way, I stumbled upon Cloudflare Workers, Cloudflare Pages, and Supabase. Little did I know, this trio would revolutionize my project.

Introducing the Dream Team: Cloudflare Workers, Pages, and Supabase

Cloudflare Workers: A serverless platform that allows you to run JavaScript, Rust, C, and C++ code at the edge, providing low latency and high performance.

Cloudflare Pages: A JAMstack platform for deploying frontend applications, offering seamless integration with Git and automatic deployments.

Supabase: An open-source Firebase alternative that provides a Postgres database, authentication, and real-time capabilities.

Together, these tools promised a scalable, cost-effective, and maintainable architecture for my Angular app.

Key Features:

  • Serverless APIs: Build and deploy APIs without managing servers.
  • Edge Computing: Run code closer to users for faster responses.
  • Real-Time Database: Supabase offers real-time updates and a robust Postgres database.
  • Cost-Effective: Start for free and scale without exorbitant costs.

Setting Up the Project: From Zero to Hero

Let me walk you through the steps I took to set up this architecture, integrating Cloudflare Workers, Pages, and Supabase with R2 storage.

Step 1: Creating the Angular Application

First, I set up a new Angular project.

Terminal window
ng new cloudflare-supabase-app
cd cloudflare-supabase-app
ng serve

This initializes a fresh Angular app, which I could start developing locally.

Step 2: Setting Up Supabase for the Database

Supabase provides an easy-to-use interface for managing a Postgres database. Here’s how I set it up:

  1. Sign Up: I created a free account on Supabase.

  2. Create a New Project: Once logged in, I initiated a new project, which gave me access to a Postgres database and authentication features.

  3. Database Schema: I designed a simple schema for my application. For example, a todos table:

    -- supabase.sql
    CREATE TABLE todos (
    id SERIAL PRIMARY KEY,
    title TEXT NOT NULL,
    completed BOOLEAN DEFAULT FALSE
    );
  4. Supabase Client: I installed the Supabase client in my Angular project.

    Terminal window
    npm install @supabase/supabase-js
  5. Configuration: I configured the Supabase client with my project’s URL and anon key.

    src/app/services/supabase.service.ts
    import { Injectable } from '@angular/core';
    import { createClient, SupabaseClient } from '@supabase/supabase-js';
    @Injectable({
    providedIn: 'root',
    })
    export class SupabaseService {
    private supabase: SupabaseClient;
    constructor() {
    this.supabase = createClient('https://your-supabase-url.supabase.co', 'public-anon-key');
    }
    getTodos() {
    return this.supabase.from('todos').select('*');
    }
    addTodo(title: string) {
    return this.supabase.from('todos').insert([{ title }]);
    }
    toggleTodo(id: number, completed: boolean) {
    return this.supabase.from('todos').update({ completed }).eq('id', id);
    }
    removeTodo(id: number) {
    return this.supabase.from('todos').delete().eq('id', id);
    }
    }

Step 3: Deploying the Angular App with Cloudflare Pages

Cloudflare Pages offers seamless deployment for frontend applications.

  1. Connect Repository: I connected my GitHub repository containing the Angular project to Cloudflare Pages.
  2. Configuration: Configured the build settings, specifying ng build --prod as the build command and dist/cloudflare-supabase-app as the output directory.
  3. Deployment: Cloudflare Pages automatically built and deployed the application, providing a live URL.

Step 4: Building the API with Cloudflare Workers

Cloudflare Workers serve as my serverless API, handling requests from the Angular frontend.

  1. Install Wrangler: Wrangler is Cloudflare’s CLI tool for managing Workers.

    Terminal window
    npm install -g wrangler
  2. Initialize Worker: I created a new Worker project.

    Terminal window
    wrangler init api-worker
    cd api-worker
  3. Writing the API: Here’s a simple API to interact with Supabase.

    api-worker/src/index.js
    import { handleRequest } from './handler';
    addEventListener('fetch', event => {
    event.respondWith(handleRequest(event.request));
    });
    api-worker/src/handler.js
    import { createClient } from '@supabase/supabase-js';
    const supabase = createClient('https://your-supabase-url.supabase.co', 'public-anon-key');
    export async function handleRequest(request) {
    const url = new URL(request.url);
    const { pathname } = url;
    if (pathname === '/api/todos' && request.method === 'GET') {
    const { data, error } = await supabase.from('todos').select('*');
    if (error) return new Response(JSON.stringify({ error: error.message }), { status: 400 });
    return new Response(JSON.stringify(data), { headers: { 'Content-Type': 'application/json' } });
    }
    if (pathname === '/api/todos' && request.method === 'POST') {
    const { title } = await request.json();
    const { data, error } = await supabase.from('todos').insert([{ title }]);
    if (error) return new Response(JSON.stringify({ error: error.message }), { status: 400 });
    return new Response(JSON.stringify(data), { headers: { 'Content-Type': 'application/json' } });
    }
    // Add more routes as needed
    return new Response('Not Found', { status: 404 });
    }
  4. Deploying the Worker: I deployed the Worker to Cloudflare.

    Terminal window
    wrangler publish

Now, the API was live and accessible via the provided Worker URL.

Step 5: Integrating R2 Storage for File Streaming

For real-time file streaming, I utilized Cloudflare’s R2 Storage.

  1. Set Up R2 Bucket: In the Cloudflare dashboard, I created an R2 bucket.

  2. Configuration: Configured access keys and integrated R2 with my Worker.

    api-worker/src/handler.js
    import { R2Bucket } from '@cloudflare/workers-types';
    const r2 = R2Bucket('YOUR_R2_BUCKET');
    export async function handleRequest(request) {
    // Existing routes...
    if (pathname.startsWith('/api/stream') && request.method === 'GET') {
    const fileKey = pathname.split('/').pop();
    const file = await r2.get(fileKey);
    if (!file) return new Response('File not found', { status: 404 });
    return new Response(file.body, {
    headers: { 'Content-Type': 'application/octet-stream' },
    });
    }
    return new Response('Not Found', { status: 404 });
    }
  3. Testing Streaming: I uploaded a test file to R2 and accessed it via the /api/stream endpoint, ensuring smooth real-time streaming without incurring any costs during testing.

The Free Tier Advantage: Getting Started Without Spending a Dime

One of the standout aspects of this setup was the generous free tiers offered by Cloudflare and Supabase.

  • Cloudflare Workers: The free tier provides up to 100,000 requests per day, which was more than sufficient for testing and small-scale applications.
  • Cloudflare Pages: Free tier includes unlimited sites with generous build limits, perfect for deploying multiple projects without extra costs.
  • Supabase: Offers a free tier with ample database storage, authentication, and real-time capabilities.
  • R2 Storage: Generous free storage and bandwidth for testing purposes, allowing me to stream files without worrying about costs.

This combination allowed me to develop, test, and deploy a fully functional application without any financial commitment, making it ideal for startups, hobby projects, or anyone looking to minimize expenses.

Scaling Up: Handling High Loads Without Breaking the Bank

As my application grew, I needed to ensure that it could handle increased traffic without incurring prohibitive costs.

Cloudflare D1 Database

I transitioned to Cloudflare D1 for even more scalable and efficient database management. D1 integrates seamlessly with Workers, providing a serverless SQL database that’s highly performant.

R2 Storage for High Traffic

Cloudflare’s R2 Storage proved to be incredibly cost-effective even under high loads. Its integration with Workers allowed for efficient file streaming, and the pricing remained competitive as usage scaled.

Pricing Insights:

  • Free Tier Sufficiency: During development and initial launch, the free tiers covered all my needs.
  • Post-Free Pricing: After surpassing free limits, the pay-as-you-go model ensured that costs remained predictable and affordable, with no surprise bills.
  • High Load Efficiency: Even under high traffic, the pricing scales linearly, ensuring that you only pay for what you use without massive jumps in cost.

The Ups and Downs: Navigating the Serverless Landscape

High Points

  1. Seamless Integration: Cloudflare Workers, Pages, and Supabase worked together flawlessly, reducing the complexity of the stack.
  2. Cost Efficiency: Building and scaling the application without incurring significant costs was a game-changer.
  3. Performance: Leveraging edge computing ensured low latency and fast response times for users globally.
  4. Scalability: The serverless architecture effortlessly handled traffic spikes without manual intervention.

Challenges Faced

  1. Initial Learning Curve: Understanding serverless paradigms and integrating multiple services took time and effort.
  2. Debugging: Troubleshooting issues across different platforms (Cloudflare and Supabase) required familiarity with their respective tools.
  3. Limitations of Free Tiers: While generous, free tiers have limits that necessitate careful monitoring as the application grows.
  4. R2 Storage Configurations: Setting up R2 storage with Workers required precise configurations to ensure smooth streaming.

Avoiding Pitfalls: Best Practices for a Smooth Serverless Experience

While the serverless approach offers numerous benefits, it’s essential to follow best practices to avoid common pitfalls.

Preventing Memory Leaks

  • Efficient Coding: Ensure that Workers do not hold onto resources longer than necessary.
  • Proper Cleanup: Implement cleanup logic in Workers to free up memory after handling requests.

Optimizing Performance

  • Caching: Utilize Cloudflare’s caching capabilities to reduce load on Workers and speed up responses.
  • Minimize Cold Starts: Keep Workers lightweight to reduce latency caused by cold starts.
  • Efficient Database Queries: Optimize Supabase queries to minimize response times and reduce database load.

Cost Management

  • Monitor Usage: Regularly monitor usage statistics to stay within free tier limits or manage costs effectively.
  • Optimize Resources: Scale resources based on actual needs, avoiding over-provisioning.

Wrapping Up: A Seamless Serverless Success

Embarking on this serverless journey with Cloudflare Workers, Pages, and Supabase was transformative. What started as a quest to build a scalable, cost-effective Angular application turned into a testament of modern web development’s capabilities.

With this setup:

  • Deployment became effortless with Cloudflare Pages’ seamless integrations.
  • API management was simplified using Cloudflare Workers’ serverless functions.
  • Database operations were robust and real-time with Supabase’s powerful features.
  • File streaming was efficient and cost-effective using R2 Storage.

Final Thoughts and Recommendations

If you’re looking to build a modern, scalable Angular application without the overhead of managing servers or breaking the bank, this combination of Cloudflare and Supabase is worth exploring. Embrace the serverless revolution, leverage the generous free tiers to kickstart your projects, and enjoy the seamless integrations that make development smoother and more efficient.

Happy coding, and may your applications be as scalable and efficient as your dreams!