FIVEM COMMUNITY / CONTENT MANAGEMENT
Southside
Records.
A label website
the staff can run.
A FiveM record-label website with staff-managed content and best-effort activity logging.
Artists.
Releases.
Events.
- My contribution
- Public site, admin CMS
& deployment
- Context
- FiveM community project
2025 build / June 2026 account
- Built with
- React · Vite · shadcn/ui
Supabase · Cloudflare Worker
01 / THE BUILDThe site does not end at the public page
Southside has two kinds of users. Visitors want to find an artist, open a release, or see an upcoming event. Staff need to maintain those records, manage photos, and read enquiries.
I built the public site and the admin CMS around those jobs. The artist roster, releases, streaming links, and events are the visible part. Behind them is a multi-panel console for managing the content.
02 / THE BUILDGive each kind of content a place
The documented console has eight panels: artists, releases, events, photos, team, messages, logs, and map. They share a data layer rather than each page inventing its own way to talk to Supabase.
The public experience includes links to Spotify, Apple Music, YouTube Music, and SoundCloud on releases. Those are outbound listening links—not a claim that this project hosts or distributes the music.
EXPLORE THE CONTENT SYSTEM
Eight panels. Different jobs.
The public roster
Artists
Staff manage the artist records presented in the public roster.
CONTENT SCOPE / NOT AN ADMIN SCREENSHOTRead every panel description
- Artists
- Staff manage the artist records presented in the public roster.
- Releases
- Release records connect the public catalog to Spotify, Apple Music, YouTube Music, and SoundCloud. These are outbound links.
- Events
- The site presents events; a dedicated admin panel manages this content.
- Photos
- Uploads live in Supabase Storage. Matching image URLs can be routed through the image Worker.
- Team
- A team panel is included in the documented admin scope. The source does not spell out a more detailed workflow.
- Messages
- The back office includes contact-enquiry management. No messaging integration beyond the documented scope is assumed.
- Logs
- The data layer attempts to record changes. Logging is best-effort; a failed log write does not undo a successful content change.
- Map
- A map panel appears in the original eight-panel inventory. Its detailed behavior is not described in the available account.
03 / THE BUILDA saved change and a saved log are different things
The service layer attempts to record create, update, and delete activity. That makes logging part of the content workflow rather than something each interface has to remember separately.
But the implementation has an important limit. In the published artist-creation example, the artist is saved first. The log is attempted afterward, and a logging error is caught separately. A successful content change can therefore have no matching log entry.
That is best-effort activity logging, not a complete audit-history guarantee. The demonstration below makes the difference visible.
LOCAL FAILURE EXPLORER
Saved content ≠ saved history.
Create an artist
Staff submits a change.
Save the artist
Ready to illustrate.
Attempt the log
After a successful insert.
Try the failure path.
The artist is inserted first. The log is attempted in its own try / catch. Select an outcome to inspect what remains.
Read all three outcomes
- Both writes succeed
- The artist and activity row are saved. This illustrates one successful execution, not a guarantee for all changes.
- The log write fails
- The artist remains saved. The logging error is caught and written to the console. The function returns the artist without a corresponding audit row.
- The content write fails
- The insert error is thrown before the log attempt. The function does not reach the log write.
04 / THE BUILDUploads and image delivery take different routes
Photos are stored in Supabase Storage. A URL helper sends matching storage URLs through a Cloudflare Worker for cached delivery; URLs that do not match are returned unchanged.
This separates where an image is uploaded from how a visitor requests it. The source account does not include a measured speed comparison, so there is no performance percentage to attach to that choice.
IMAGE URL ROUTING
Storage and delivery are separate.
A matching storage URL is rewritten to the Worker endpoint for cached delivery. This is not an upload through the Worker.
Other input cases
A nonmatching URL is returned unchanged. Empty input returns null. The source excerpt does not include the Worker’s cache configuration.
05 / THE BUILDWhat I would tighten up next
The original write-up identified three unfinished areas. There were no automated tests; the logging wrapper and image URL helper were the first candidates. Supabase row-level-security policies lived in the database rather than the repository. The entity-specific API objects also repeated enough structure to warrant a smaller shared abstraction.
Those are the next engineering tasks, not features being presented as already delivered. The useful part of this project is seeing the public site, staff workflow, storage, and logging together—including where the design still has limits.
Source, dates, and what this page verifies
This is an editorial rewrite of the supplied project and technical article, describing the account published June 28, 2026. Original dates, code excerpts, and unfinished work are retained. The production repository, permissions, costs, and historical measurements have not been re-audited.
Interactive figures are local explanations. They do not call an API, send input, create content, or demonstrate production test coverage. The cumulative reference is not deployed.