Skip to content
MROOT

FIVEM COMMUNITY / PORTFOLIO + PRIVATE TOOLS

Katie
MonroePhotography.

A portfolio with
its own back office.

A FiveM photography portfolio with private content tools and an explicit missing-configuration fallback.

KATIE MONROE / BEHIND THE PORTFOLIO
Gallery01 / SYSTEM STUDY
Collections02 / SYSTEM STUDY
Enquiries03 / SYSTEM STUDY
Private tools04 / SYSTEM STUDY
ILLUSTRATED CONTACT SHEET · NOT PHOTOGRAPHS
Explanatory composition, not a capture of the live gallery or admin console. No portfolio photos are invented.
Documented project~3 min read
My contribution
Public portfolio, Worker API,
admin console & deployment
Context
FiveM photography project
June 2026 account
Built with
JavaScript · Vite · Worker
Turso · R2

01 / THE BUILDA portfolio with work happening behind it

Katie Monroe is a photographer character in a Los Santos roleplay community. The site pairs an image-led public portfolio with private tools for managing the work behind it: photo uploads, collections, commission enquiries, and shoot scheduling.

My contribution covered the public portfolio, Worker API, admin console, and deployment. This is a FiveM community project, not a claim about a commercial photography client's results.

The presentation here uses an illustrated contact sheet and system diagrams. A verified full-resolution gallery capture is not available in the supplied handoff, so the illustration is not presented as the finished application.

02 / THE BUILDTwo deployments, different responsibilities

The historical build uses vanilla JavaScript and Vite for the public front end, deployed on Vercel. Its gallery, lightbox, motion, and story routing are ES modules rather than a React application.

A separately deployed Cloudflare Worker handles the API. Turso provides libSQL storage, R2 holds images, and the account describes signed JWT authentication for protected operations.

KATIE / RESPONSIBILITIES

The system, with the boundaries left in.

Select a component to read what the supplied account says it does.

Vite + vanilla JavaScript

Static front end

The historical account describes ES modules for the gallery, lightbox, motion, and story routing, deployed on Vercel. It does not describe a React front end.

Static front end: The historical account describes ES modules for the gallery, lightbox, motion, and story routing, deployed on Vercel. It does not describe a React front end.

Private console: Private tools cover uploads, collections, commission enquiries, and shoot scheduling. These responsibilities are not a screenshot of the console.

Cloudflare Worker: A hand-written method/path router with gated() wrappers for admin operations. The account describes signed JWT authentication.

Turso / libSQL: The documented database stores application data and supports the fixed-window rate limiter.

R2: The source says images upload without a resizing step. Derivative sizes are listed as future work.

Bundled samples: The shown loader returns local SHOTS/CATS when no Worker URL is configured. That alone does not establish configured-outage recovery.

Explanatory component groups—not a complete network trace, permission audit, or capture of a live application.

This keeps the public-facing assets separate from the operations that need secrets. The private console manages content; it is not simply a second visual theme for the gallery.

03 / THE BUILDUseful without configuration—not a blanket outage promise

The supplied loader has a concrete fallback. With no Worker URL configured, it returns bundled sample photos and categories. With a Worker URL, it requests photos and collections from the API.

GALLERY / CONFIGURATION EXPLORER

Three situations. Only two branches shown.

An absent API configuration and a configured API failure are not the same condition.

LOAD PORTFOLIOWorker URL?if (!workerUrl)
NO CONFIGURATIONBundled samplessource: 'local'
CONFIGUREDPhotos + collectionsPromise.all([...])

Use the bundled sample collection.

The missing-configuration branch returns bundled SHOTS and CATS. It does not make an API call.

A reading of the supplied loadPortfolio excerpt, not a live outage test. Bundled sample content is development/demo content, not a substitute for a client’s current portfolio.

The original article made a broader “never blank” claim. Its excerpt does not show recovery from a failed configured API request. The request helper and calling code would need to be inspected to establish that behavior.

The commission flow has a different responsibility. The source describes an explicit failure when there is no way to deliver an enquiry, rather than a success message for a message that was not sent.

04 / THE BUILDThe private tools need clear boundaries

The Worker uses a hand-written method-and-path router. Protected routes call a gated() wrapper; the article's examples include private collection access, private photo access, and uploads.

That makes the intended boundary visible in the excerpt. It is not proof that every route is correctly protected. The account also describes a Turso-backed fixed-window rate limiter and 164 tests across the Worker, front end, and admin console. That test count belongs to the June 2026 source, not this portfolio pass.

05 / THE BUILDWhat I would improve next

The original account identifies three areas for further work: simplify the router as it grows beyond its reported 31 routes, add image derivatives rather than uploading only source-sized files, and share some rendering code between the public site and admin console.

Those remain next steps in this account. No image pipeline, routing refactor, or expanded test coverage is being claimed as newly delivered.

The technical article shows the loader and routing excerpts. The client-facing article explains why useful fallback content and truthful delivery feedback need different treatment.

Source, dates, and what this page verifies

This rewrite is grounded in the supplied project account and complete related articles. Publication dates describe those accounts, not a new release. The original application, its permissions, screenshots, test results, and deployment have not been re-audited.

The diagrams are local explanations with no API calls, database operations, test execution, or saved input. Source conflicts and unsupported outcomes are identified in the reading copy and the handoff. No production deployment occurred.

Ready to build?

Something here sparks an idea?

Start with your goal. We can work out the right shape together.

Quote before you commit · Reply within 1 business day · You own the finished custom code and content after final payment

Start a project