DEV Community

Cover image for Bootstrapping a Serverless CRM: Surviving a Forensic P0 Audit & Hardening Supabase
Miloš Kulpinski
Miloš Kulpinski

Posted on • Originally published at lukulatelier.com

Bootstrapping a Serverless CRM: Surviving a Forensic P0 Audit & Hardening Supabase

Supabase Data Schema

Note: I am launching the LuKul Bio-Sync CRM architecture on Product Hunt this Wednesday. If you are a systems architect handling complex biometric telemetry or migrating monoliths to Next.js, I’d love your technical teardown on the launch here.

After 16 years running elite coaching operations in the GCC, I got tired of standard fitness SaaS dropping high-value biometric data. I transitioned to software engineering and built LuKul Bio-Sync—a serverless B2B CRM and PWA ecosystem—entirely from scratch as a solo developer.

To ship the MVP fast, I built it in Vanilla JS, HTML, and CSS, backed by Supabase (PostgreSQL + Edge Functions). The product-market fit was immediate. It retained clients, acquired new ones, and generated revenue.

Then, I ran a full Production-Grade Forensic Systems Audit. The results were terrifying.

The Fragility of the Vanilla Monolith
The audit uncovered a massive gap between the conceptual brilliance of the product (which featured an Ephemeral State Engine and time-decaying somatic heatmaps) and its operational security. I had built a prototype that was operating at a SaaS scale, and the architectural seams were cracking.

My "ship-it-fast" approach had introduced critical vulnerabilities:

Global API Exposure (P1): window.supabaseClient was initialized globally, creating a trivial target for XSS amplification where any injected payload could hijack the authenticated user's RLS permissions.

Orphaned Closures & Memory Leaks: During "Nuclear Wipes" (clearing the DOM via .innerHTML = ""), global event listeners stacked infinitely on the document object, severely degrading performance.

Unauthenticated Edge Webhooks (P1): Mission-critical data pipelines (like somatic_sync) were accepting raw payloads without JWT validation.

The "Hydra" Anomaly: The client was fetching infinite historical logs to deduplicate arrays in the main UI thread, choking the browser's memory.

The Defensive Engineering Sprint (Zero-Downtime)
Transitioning from a founder-led project to an enterprise platform required an immediate pivot to defensive engineering. Before migrating the frontend to Next.js, I had to harden the infrastructure.

Here are the specific architectural remediations deployed to production:

  1. Cryptographic Validation & Threat Mitigation
    I purged all hardcoded legacy checks and implemented a timing-safe, constant-time bitwise XOR comparison at the Edge to handle administrative overrides. To neutralize open relay spam vectors, I engineered a pg_cron garbage-collected atomic rate limiter using Postgres RPCs (check_rate_limit), mapping request windows strictly to x-forwarded-for IPs.

  2. RLS Hardening & Singleton Isolation
    The global supabaseClient was destroyed. I isolated the SDK payload dynamically via a unified ES6 singleton module, ensuring state could not be read or mutated from the global window scope. Row Level Security (RLS) policies were tightened to strictly enforce is_coach_of() boundaries, preventing vertical privilege bleeding.

  3. Eradicating the "Hydra" (RPC Telemetry)
    Client-side array slicing for biometric telemetry was deleted. I pushed the compute burden entirely to the database, invoking strict PostgreSQL RPCs (get_daily_telemetry_batch) with explicit limits to stabilize the render pipeline.

The Next.js 14 & Zustand Architecture
With the backend fortified, the UI is currently undergoing a massive zero-downtime migration to Next.js 14 (App Router) and Zustand.

To maintain 100% visual parity across 5 distinct B2B and consumer locales without rewriting 10,000 lines of legacy CSS, I am leveraging Next.js Route Groups (marketing), (b2b), and (blog-hub). Each layout.tsx imports only its specific legacy CSS dependencies, achieving perfect cascade isolation.

Imperative DOM reads and module-scope variables have been replaced by declarative Zustand stores (e.g., useBotStore for the AI Concierge, useCalculatorStore for in-memory B2B revenue simulations).

The Multimodal Flex: Zero-Dependency Audio Injection
While migrating the heavy infrastructure, I wanted to deploy ElevenLabs AI voice clones across our static editorial pages. Avoiding bloated React audio players, I wrote a lightweight, decoupled Vanilla JS injector. It securely fetches the assets from a public Supabase storage bucket without coupling the .mp3 target to fragile URL paths.

JavaScript

const AUDIO_CONFIG = {
    projectId: 'nwugkqkesolynuzlhqum', 
    bucketName: 'voiceovers',
    containerClass: '.voiceover-container' 
};

class VoiceoverPlayer {
    constructor(container) {
        this.container = container;
        this.slug = this.container.getAttribute('data-slug'); 
        this.audioUrl = `https://${AUDIO_CONFIG.projectId}.supabase.co/storage/v1/object/public/${AUDIO_CONFIG.bucketName}/${this.slug}.mp3`;
        this.audioElement = null;
        this.isPlaying = false;
    }

    async init() {
        if (!this.slug) return;
        if (await this.verifyAudioExists()) {
            this.injectUI();
            this.setupAudio();
        }
    }

    async verifyAudioExists() {
        try {
            return (await fetch(this.audioUrl, { method: 'HEAD' })).ok;
        } catch (error) {
            console.warn(`[LuKul Audio] Fetch failed: ${this.slug}`);
            return false;
        }
    }

    injectUI() {
        const playerHTML = `
            <style>
                .lukul-audio-wrapper {
                    display: inline-flex; align-items: center; background-color: #0a0a0a;
                    border: 1px solid #1a1a1a; padding: 8px 16px; font-family: monospace;
                    cursor: pointer; transition: all 0.3s ease; margin: 20px 0;
                }
                .lukul-audio-wrapper:hover { border-color: #cda434; }
                .lukul-play-icon {
                    width: 0; height: 0; border-top: 6px solid transparent;
                    border-bottom: 6px solid transparent; border-left: 10px solid #2e8b57;
                    margin-right: 12px; transition: all 0.2s ease;
                }
                .lukul-audio-wrapper.playing .lukul-play-icon {
                    border: none; width: 10px; height: 12px; background-color: #cda434;
                    border-left: 3px solid #cda434; border-right: 3px solid #cda434; box-sizing: border-box;
                }
                .lukul-audio-text { color: #e0e0e0; font-size: 0.85rem; text-transform: uppercase; }
            </style>
            <div class="lukul-audio-wrapper">
                <div class="lukul-play-icon"></div>
                <span class="lukul-audio-text">Listen to Architectural Breakdown</span>
            </div>
        `;
        this.container.innerHTML = playerHTML;
    }

    setupAudio() {
        this.audioElement = new Audio(this.audioUrl);
        const btn = this.container.querySelector('.lukul-audio-wrapper');
        const text = btn.querySelector('.lukul-audio-text');

        btn.addEventListener('click', () => {
            if (this.isPlaying) {
                this.audioElement.pause();
                btn.classList.remove('playing');
                text.innerText = 'Listen to Architectural Breakdown';
            } else {
                this.audioElement.play().then(() => {
                    btn.classList.add('playing');
                    text.innerText = 'Playing...';
                    this.isPlaying = true;
                }).catch(e => console.error("Audio blocked:", e));
            }
        });

        this.audioElement.addEventListener('ended', () => {
            this.isPlaying = false;
            btn.classList.remove('playing');
            text.innerText = 'Listen to Architectural Breakdown';
        });
    }
}

document.addEventListener('DOMContentLoaded', () => {
    document.querySelectorAll(AUDIO_CONFIG.containerClass).forEach(c => new VoiceoverPlayer(c).init());
});
Enter fullscreen mode Exit fullscreen mode

If you are dealing with technical debt, securing Edge Functions, or mapping complex relational telemetry in Supabase, let’s connect.

Domain: lukulatelier.com/business

Stack: Next.js 14, Zustand, Supabase, Vanilla JS

Top comments (0)