PHASOR · SOLO OPERATION
SHEET 07 · PART 06 DETAIL · CLIENT WORK STATUS: IN DEVELOPMENT
PART 06 · CLIENT WORK · BACKEND + CMS

Fusion Edge

Corporate site and a custom content panel for a Guwahati infrastructure & real-estate firm.

IN DEVELOPMENT · FUSIONEDGESOLUTIONS.IN ↗

FUNCTION
Marketing site + staff-run CMS
CLIENT
Fusion Edge Solutions · NE India
STATUS
In active development
ROLE
Backend · CMS · DB · security
Fusion Edge registry-driven admin panel
FIG. 01 — ADMIN PANEL · REGISTRY-DRIVEN FORMS
Fusion Edge staff submission inbox
FIG. 02 — STAFF INBOX · ENQUIRIES + APPLICATIONS

00Scope

WHAT I OWNED ON THIS PROJECT

Mine: the entire backend and data layer — database schema, the registry-driven admin/CMS, Supabase auth + RLS, security hardening, rate limiting, private résumé storage, and the Google Sheets + email integrations.

Not mine: most of the public-facing frontend. I contributed only a small part of it. This sheet covers the work I actually did.

01The problem

A diversified Northeast-India firm — hotels, real estate, retail, transit developments — needed a public presence that non-technical staff could keep current without calling a developer for every copy change.

Project listings, news, events, job postings: all of it had to be editable in-house. Generic CMS platforms were too heavy, too expensive at this scale, or locked behind a managed subscription the client didn't want.

02Approach

A thin custom CMS built directly on Supabase — Postgres, Auth, Storage — instead of a third-party headless CMS. A single TypeScript registry file declares every content type once; all list, form, and detail admin views are generic, so there's no duplicated page per entity.

The whole admin surface runs under the staff member's own auth session, with RLS enforcing access — no service-role key ever reaches the browser. Rate limiting, instead of living in memory (which breaks across serverless instances), is enforced by a SECURITY DEFINER Postgres function that is the sole writer to a zero-policy RLS table.

03How it works

  1. Visitors hit Next.js App Router pages; featured projects and copy are fetched server-side from Supabase, falling back to hard-coded defaults when no CMS row exists yet.
  2. Contact and careers forms submit via Server Actions; a per-IP sliding-window check runs in Postgres before any row is inserted.
  3. Résumés upload to a private Storage bucket; row and file are written atomically — a failed insert removes the orphaned file immediately.
  4. Staff log in at /admin (Supabase email auth); the session is validated server-side on every panel request.
  5. Content is edited through registry-driven forms — Tiptap rich text, image/gallery pickers, spec tables; publishing flips a status column that RLS turns into public visibility.
  6. New submissions land in a real-time inbox with unread badges; a Google Sheets mirror and a Resend email hook fire best-effort in parallel, so a side-channel failure never blocks the visitor.

04Capabilities

  • CMS for projects, news, events, jobs, team, pages
  • Staff inbox: enquiries + applications, unread badges
  • Private résumé storage, signed-URL staff download
  • Per-IP rate limiting at the Postgres layer
  • Honeypot + MIME/size limits, app & bucket layer
  • Google Sheets mirror + Resend email, best-effort

05Stack

LANGUAGE
TypeScript 5
FRONTEND
Next.js 16 (App Router) · React 19 · Tailwind CSS 4 · Framer Motion 12
BACKEND / DATA
Supabase (Postgres + Auth + Storage) · Tiptap 3 · Zod 4 · sanitize-html
SERVICES
Google Sheets API (mirror) · Resend (email)
INFRA / DEPLOY
Vercel (x-forwarded-for IP extraction pattern)

06Engineering notes

  1. Rate limiting across serverless. In-memory counters reset on every cold start, so a SECURITY DEFINER function (check_rate_limit) writes to a private table with RLS enabled and zero policies — write-only through the function, unreachable to anon/authenticated roles directly.

  2. Anon insert without RETURNING. RLS lets anon INSERT to submission tables but grants no SELECT; adding .select() would trigger a RETURNING clause that fails the policy check. The server action explicitly avoids it — a subtle constraint documented in the migration.

  3. Two-layer storage hardening. App-level MIME/size validation covers the happy path; Supabase bucket-level file_size_limit and allowed_mime_types cover direct Storage REST callers who bypass the app entirely with the publishable key.

  4. Media enumeration closed. The public media bucket serves objects by URL with no SELECT policy; the original broad SELECT policy allowed listing every object in the bucket. Dropping it closed that vector with no functional impact.

07What's next

  1. Leaked-password protection and MFA for admin accounts — flagged in the security audit.
  2. Activate the Google Sheets mirror once the GCP service account is provisioned.