Design Technologist · App Engineering Showcases

Cloud-managed themes, without rebuilding the portfolio.

A small, live Supabase integration turns site defaults into managed data while preserving local themes, visitor choices, and Cloudflare delivery.

01Problem & Scope
02Architecture Concepts
03System Architecture
04AI Prompt
05Audit
06Working System
07Verification
01

A static portfolio, with cloud-managed defaults

Add a data service without rebuilding the website or depending on the network to render.

Before: settings in source code

My resume already has seven theme packages and an independent light/dark setting. Changing the site-wide default or menu order previously required a source edit and deployment.

After: one public settings record

Supabase stores the default theme, mode, and menu order. Cloudflare still delivers the website. The browser validates configuration and reuses the existing theme controller.

Actors & non-goals. The site owner manages public defaults; visitors choose their own appearance. This prototype reads configuration only. It does not add visitor accounts, an administration screen, remote theme-code delivery, or a new hosting layer.

No visitor loginNo remote CSSNo public writesLocal fallback
02

The boundaries behind one small integration

Six concepts explain the connection, data ownership, and failure behavior.

03

How the cloud-managed theme system fits together

System Architecture · Three boundaries, separate responsibilities, one local renderer.

Website delivery, configuration data, and browser preferences have separate responsibilities. This explanatory diagram is not connection telemetry; live observations belong to the Working System panel.

Legend: Normal runtime path (Static delivery & direct API) Normal preference input & local rendering Failure path: validated cache or bundled defaults Operation grants + row-level SELECT policy
Cloud-Managed Themes System Architecture Diagram Three boundaries: Cloudflare delivers static files to the Visitor Browser. The Browser sends a direct HTTPS GET to the Supabase Data API, which returns configuration JSON. PostgreSQL operation grants and an RLS SELECT policy restrict browser access. Explicit preferences are normal inputs; validated cache or bundled defaults supply configuration on failure. Local packages render the appearance. EDGE HOSTINGCloudflareStatic website deliveryStatic portfoliobundleHTML structureBase CSSJavaScript logicTheme packagesLocal visual assetsHosting boundaryServes static files.Does not proxy theconfiguration API.No database access.CLIENT RUNTIMEVisitor’s BrowserExecutes the application; owns local renderingCloud Configuration LoaderDirect HTTPS client; publishable keyValidates default_theme, default_mode,and theme_order against local IDs.Preference Resolution EngineStyle and light/dark mode are independent.Explicit preferences override defaults.Resolve current choices after async work.Local ThemeControllerRegistry packagesown CSS and assets.Available localrenderers apply.Browser Storage& Page MemorySaved preferencesare normal inputs.localStorage holdsvalidated config cache.Bundled defaults are shipped in code, not storage.Blocked storage: choices last this page session.CLOUD BACKENDSupabaseData API + PostgreSQLData API /PostgRESTConfiguration JSONNo executable assetsPostgreSQLpublic.portfolio_theme_settingsSELECT grants + RLSfor the portfolio row.Browser roles: denyINSERT, UPDATE,DELETE. Admin editsremain possible.default_themedefault_modetheme_orderHTML/CSSJS/assetsHTTPSGETJSONRenderlocallyChoicesCache on failureDirect Browser → API request; API → Browser JSON response. Diagram, not telemetry.
Edge Hosting Static Only

Cloudflare

Hosts and delivers static bundle files to the visitor's browser. Does not proxy API calls or talk to PostgreSQL.

HTML CSS JavaScript Theme Packages
HTML / CSS / JavaScript / assets
Client Runtime Browser Engine

Visitor’s Browser

Runs the portfolio. Validates incoming configuration, resolves explicit preferences against defaults, and renders available local theme packages.

1. Cloud Config Loader: Direct HTTPS fetch to Supabase, validating schema.
2. Preference Resolution: Style & light/dark mode are independent. Explicit selection overrides default.
3. Theme Controller: Uses the existing local registry and controller. Remote configuration supplies no executable JavaScript or CSS paths.
4. Normal preference input: Saved preferences from localStorage and current-page choices feed resolution on success too. When storage is blocked, memory-only choices last the current page session.
5. Failure configuration: A validated localStorage-backed configuration cache is used when available; otherwise bundled defaults shipped in code apply. Bundled defaults are not browser storage. This does not guarantee API availability or every theme asset.
Browser → API: HTTPS GETAPI → Browser: configuration JSON
Cloud Backend SELECT Only

Supabase (PostgREST + PostgreSQL)

Serves configuration JSON from public.portfolio_theme_settings. Operation grants allow SELECT; the RLS SELECT policy restricts the visible row. INSERT, UPDATE, and DELETE are denied for browser roles (anon/authenticated), not all PostgreSQL users: administrative edits remain possible. The publishable key is not a privileged secret.

Data API / PostgREST RLS Enabled default_theme default_mode theme_order
Text equivalent: ownership, flows & fallback

Three execution and trust boundaries, not a trace of a live request:

  1. Cloudflare → Browser: Static HTML, CSS, JavaScript, and local theme packages are delivered to the Visitor Browser. Cloudflare does not proxy this configuration API or access PostgreSQL.
  2. Browser → API: The browser sends a direct HTTPS GET with a publishable key to the Supabase Data API / PostgREST. API → Browser: The response is configuration JSON, not executable JavaScript, CSS, or arbitrary asset paths.
  3. Database boundary: PostgreSQL persists public.portfolio_theme_settings. SELECT operation grants and an RLS SELECT policy allow the portfolio row to be read. INSERT, UPDATE, and DELETE are denied for browser roles; administrative edits remain possible. RLS does not replace operation grants.
  4. Normal preference input: The browser validates default_theme, default_mode, and theme_order against its local whitelist. Saved preferences in localStorage and current-page choices are inputs even after a successful GET. Style and mode are independent; only explicit dimensions override configured defaults. Blocked storage leaves memory-only preferences for the current page session.
  5. Failure path: A validated configuration cache is localStorage-backed when available. Failed or timed-out reads use that cache, otherwise bundled defaults shipped in code—not preferences storage. Newer requests supersede older work; current choices are resolved after asynchronous loading.
  6. Local rendering: The existing controller activates available local packages. A successful API read does not prove every CSS or visual asset loaded. Bounded waiting and fallback reduce the dependency; they cannot guarantee API availability or complete asset rendering.
04

AI Prompt

Review → plan → build → verify. Use AI in small steps, then inspect the result.

  1. 01 · Review the existing app

    Give AI the current files and ask what must stay unchanged.

    Suggested prompt
    Step 01
    Review the attached portfolio files before editing.
    Identify the theme controller, local theme packages,
    navigation, and existing showcases.
    
    Explain which parts run in the browser and which
    settings could come from a remote service.
    List the files that must remain unchanged.
    Do not write code yet.
  2. 02 · Plan the connection

    Ask for a small, read-only design with clear ownership.

    Suggested prompt
    Step 02
    Using the review above, plan a read-only Supabase
    connection for theme defaults and menu order.
    
    Show Cloudflare delivery, a direct browser GET,
    PostgREST, PostgreSQL, SELECT grants, and RLS.
    Keep CSS and assets in the local theme packages.
    Explain visitor preferences, validation, timeout,
    and cache or bundled fallback. No browser writes.
    Return a focused plan before implementation.
  3. 03 · Build the working feature

    Use the implementation prompt alongside these steps, then inspect the changed files.

    Use the implementation prompt

  4. 04 · Verify and refine

    Return real test results to AI and request focused corrections.

    Suggested prompt
    Step 04
    Test the implementation against its requirements.
    Check a real read when reachable, independent
    style/mode choices, reload, reset, offline fallback,
    restricted storage, search, and keyboard access.
    Check installed themes and narrow layouts.
    
    Separate live observations from controlled tests.
    Report failures and blocked checks honestly.
    Fix only demonstrated defects; preserve the layout.
    Never invent a successful response or test result.
Implementation specification · AI build prompt
Suggested implementation prompt
Add cloud configuration to the existing static
portfolio without replacing its local rendering
system.

1. Preserve the portfolio. Existing pages,
   showcases, theme packages, and navigation remain
   usable independently of the configuration
   request.

2. Verify the architecture. PostgreSQL stores one
   public settings record; the Supabase Data API
   exposes permitted reads through PostgREST. The
   record controls the default theme, color mode,
   and menu order, not CSS or assets.

3. Restrict access. Use a publishable browser key
   with SELECT grants and a row-level SELECT policy.
   Browser roles cannot insert, update, or delete
   settings. Keep database passwords and privileged
   keys out of the frontend.

4. Reuse the renderer. Validate remote values
   against installed local theme IDs. The shared
   theme controller applies local CSS and assets;
   remote configuration cannot execute code or
   supply arbitrary asset paths.

5. Handle failure and preferences. Render
   immediately. Use validated cache or bundled
   settings when a request fails. Override defaults
   only in dimensions the visitor explicitly
   selects, including choices made while requests or
   metadata loads are pending. Save choices when
   browser storage is available; otherwise keep them
   for the current page session.

6. Verify observable behavior. Show actual request
   status, duration, and returned settings. Label
   offline simulation. Exercise reads, permission
   checks, independent preferences, malformed data,
   failure recovery, keyboard access, responsive
   layouts, and Chromium/Firefox behavior. Keep
   executed results separate from explanatory
   diagrams and pending deployment checks.
05

Audit

Check the generated code against the boundaries that matter.

Permission contract · excerpt, not the complete migration
alter table public.portfolio_theme_settings
  enable row level security;
revoke all on table public.portfolio_theme_settings
  from public, anon, authenticated;
grant select on table public.portfolio_theme_settings
  to anon, authenticated;
-- Add a SELECT-only policy for id = 'portfolio'.
-- Full rerunnable migration: setup.sql

Check access

SELECT grants and RLS allow the public record to be read. Browser roles cannot write; administrative edits remain possible.

Validate the response

Accept only known theme IDs from the local whitelist and supported modes—not remote CSS or executable code.

Preserve visitor choices

Resolve style and mode independently. If storage is blocked, choices last the current page session.

Test failure honestly

Use validated cache or bundled defaults on failure. Label simulations and show the actual configuration source.

06

Inspect the connection. Try the result.

This panel and the connected resume read the same public configuration record. The diagram explains service responsibilities; request metrics come from this browser.

APPLICATION STRUCTURES · SUPABASE

Cloud-managed themes

One database record. Seven local design systems.

Starting…

Live browser observation · Read the current metrics below. Section 03 explains the architecture; it does not report connection health.

Previews keep your choice for the current page session and save it for later visits when browser storage is available. “Use cloud defaults” removes current-page style/mode overrides and removes saved choices when browser storage permits. If removal is blocked, existing saved choices can return on reload. Offline simulation skips the request; it does not change Supabase.

Configuration source
Bundled defaults
Last request HTTP
—
Request duration
—
Records returned
—

Waiting for the first request.

An empty search shows all themes. Up to 80 characters.

Cloudflare delivers the static application. Supabase supplies configuration. Local theme packages render the result, and visitor choices override site defaults.

Open the connected resume · Database setup SQL · Setup, disclosure, and QA notes

07

Verification

Try the feature, inspect the evidence, and refine only what fails.

  1. Reload and compare the configured default with the current appearance.
  2. Choose a style and mode; check persistence and reset behavior.
  3. Try offline simulation and confirm the fallback source.
  4. Test search, Tab, Enter, and visible focus.
  5. Check all installed themes at desktop and mobile widths.

Cloud settings choose defaults; local packages render the result. The useful trade-off is flexibility without handing rendering ownership to the backend.