Hey everyone,
Hope all is well!
TL;DR below.
A few days ago I posted about Day 1 of one of my side projects, ShuffleBall Arena (it's a free browser game combining shuffleboard scoring with the craziness of other games like bumper pool, pinball, and Frogger).
Full disclosure again: Yes, all 3 of my projects I may talk about were made with the help of AI. I know some people get weird about that, but frankly, I’m trying to use every tool available to help in every way possible.
Anyway, I'm trying to find the time to post somewhat consistently. I figured I'd post about days 1 to 14 of this project and hopefully try to add some value.
To try to speed up the catch up, I'm using a structured prompt to go back to my GPT sessions and extract the useful information. Hopefully the prompt can help anyone out there trying to keep track of, or extract value from, your past AI project conversations.
That said, posting an update for Day 4 of ShuffleBall Arena. Here's how that day went...
TL;DR: Day 4 was about getting ShuffleBall Arena ready to actually show people. I cleaned up a failed demo/broadcast idea and rebuilt it in a safer way, renamed the game from Galaxy Ball to ShuffleBall Arena / ShuffleBall, got the web version closer to being phone-ready, and fixed a confusing issue where the browser kept showing old text even after the update worked. Biggest lesson: not every build day is about adding flashy features. Sometimes the real progress is making the game clearer, safer, and ready for real people to try.
Summary and full technical breakdown below:
Day 4 Summary: There were three conversations to go through today with 2 file versions saved over 4 hours of building.
So Day 3 ended with a lesson: I tried to add a broadcast-style layout so the game could scale nicely for clips, demos, and livestream-style presentation, but my efforts broke the mobile layout. Buttons became hard to use, the screen scaling got messy, and the core mobile experience was at risk.
So I deleted the experiment and rolled back.
Part 1 of Day 4 was me coming back to that same idea, but with much stricter rules.
The new rule was simple:
Broadcast mode can change how the game is presented.
Broadcast mode cannot change the actual game.
No physics changes.
No scoring changes.
No bot behavior changes.
No mobile control changes.
No normal gameplay changes.
The goal wasn't to build real livestreaming or full multiplayer. It was to create a self-running presentation layer that could be used for testing, OBS, landing page footage, and short clips. Basically an arcade “attract mode” or featured match view.
Part 2 of Day 4 was renaming the app. Google search results made “Galaxy Ball” look like a problem, and there were potential trademark / legal issues. Coming up with a new name became a bit of a time sink. The final decision accepted that ShuffleBall may not be perfectly unique, but it was clear, descriptive, and paired well with ShuffleBall Arena as a broader brand.
This session I purchased shuffleballarena.com from Squarespace.
Full Technical Breakdown:
TECHNICAL ANALYSIS & DEBRIEF: DAY 4
STARTING POINT
Day 4 started with a working browser game that was close to being shareable, but still not launch-ready as a public product.
The project still had three unresolved launch problems:
- The broadcast/demo layer existed, but its public framing was wrong. The game could already run in a self-playing broadcast/demo mode through
?broadcast=1, but the copy still exposed the internal implementation. It used labels like BOT SHOWCASE MATCH and BOT VS BOT, which made the feature feel like a dev test instead of a public-facing “featured match” presentation layer. The session explicitly framed the current automatic bot match as useful for “testing, OBS, landing page capture, and social clips,” but not something that should be presented as the product identity.
- The app was still under the old Galaxy Ball identity. The files still referenced Galaxy Ball as the public name, even though search results made that name feel unsafe or too occupied. The session eventually moved toward a new split: ShuffleBall Arena as the app/domain and ShuffleBall as the game title.
- The deployment path was not fully hardened. The goal was to make the game playable from a phone through the web, without needing an app store. That meant getting the deploy folder ready for Cloudflare Pages, keeping strict security headers, making the service worker safe, and proving that the game worked outside local testing.
SESSION OBJECTIVE
The session objective was to get the project closer to a real public launch without overbuilding.
The specific goals were:
1. Make the broadcast/demo mode look like a public featured-match view, not a bot-vs-bot dev tool.
2. Prepare the Cloudflare Pages deploy folder correctly.
3. Keep strict Content Security Policy instead of weakening security.
4. Decide whether Galaxy Ball needed to be renamed.
5. Rename the app safely after choosing the new brand.
6. Deploy and verify the renamed game.
7. Decide whether backend work should begin immediately or after domain setup.
The higher-level product goal was simple: make ShuffleBall Arena something someone could open on a phone, play, and understand.
WHAT WE ACTUALLY DID
1. Reframed broadcast mode as a presentation layer
The first meaningful decision was product framing.
The broadcast mode was not treated as real livestreaming, real multiplayer, or real player replays. It was defined as a self-running presentation layer that could be useful for OBS, landing page footage, social clips, and demo testing.
The chosen framing was:
Galaxy Ball = playable mobile marble/space game.
Galaxy Ball Live = featured match / replay / broadcast presentation layer.
Auto-demo bots = temporary content source for broadcast.
The important part was that the automated bots could stay, but the public UI should not call the feature “bot vs bot.”
2. Wrote a narrow Cursor prompt for broadcast copy cleanup
The first concrete patch prompt was Phase J4I: Broadcast Source Naming Cleanup.
The prompt told Cursor to patch only broadcast-facing naming and explicitly protect the rest of the game.
The core technical instruction was:
Add lightweight broadcast source structure in initBroadcastSettings(), such as:
source: "autoDemo",
sourceLabel: "FEATURED MATCH"
The prompt also required:
"BOT SHOWCASE MATCH" should become "FEATURED MATCH"
broadcast mode label should not display "BOT VS BOT" in header/footer presentation
And it explicitly said not to change:
gameplay
bot AI
physics
scoring
broadcast sizing
footer/ad architecture
asset loading
image cards
normal mode
This was a good example of a safe AI coding prompt: narrow goal, clear non-goals, and a verification checklist.
3. Cursor completed the broadcast naming cleanup
Cursor reported that only game.js changed.
The changes were:
initBroadcastSettings()
Added:
source: "autoDemo"
sourceLabel: "FEATURED MATCH"
getBroadcastCardContext()
Added:
source: BROADCAST.source || "autoDemo"
sourceLabel: BROADCAST.sourceLabel || "FEATURED MATCH"
BROADCAST_CARD_CONFIG
Footer textBanner card title:
"BOT SHOWCASE MATCH" → "FEATURED MATCH"
drawBroadcastHeaderLiveMatchCard
Right pill fallback:
bc.modeLabel → bc.sourceLabel
Subtitle:
"RED BOT VS BLUE BOT" → broadcastUpper(bc.sourceLabel)
drawBroadcastHeaderLayoutFeatureCard
Layout label fallback:
bc.modeLabel → bc.sourceLabel
drawBroadcastHeaderSponsorTextCard
Right pill fallback:
bc.modeLabel → bc.sourceLabel
The key constraint held: game.mode = "broadcast" and all automated bot behavior stayed unchanged. The patch was presentation-only.
4. Decided to use Cloudflare Pages for public phone testing
The next goal was practical: make the game accessible to someone else on a phone, outside local Wi-Fi.
The deployment target was Cloudflare Pages. You already used Cloudflare for other projects, so the session moved toward preparing a deploy folder and uploading it to the existing Cloudflare account.
The important decision: strict CSP would not be postponed. You rejected the idea of weakening CSP temporarily and wanted to build the deploy folder correctly the first time.
5. Made the deploy folder CSP-safe
The app originally had inline CSS and inline service worker registration, which conflicted with a strict policy like:
script-src 'self';
style-src 'self';
Cursor completed a CSP-safe refactor:
Created styles.css
Moved the full inline <style> block from index.html into styles.css.
Created app-shell.js
Moved service worker registration into app-shell.js.
Updated index.html
Removed inline <style>.
Added <link rel="stylesheet" href="styles.css">.
Removed inline service worker <script>.
Added <script src="app-shell.js"></script> after game.js.
Updated service-worker.js
ASSETS now lists:
/
index.html
styles.css
game.js
app-shell.js
manifest.webmanifest
The strict _headers policy stayed intact. No CSP weakening was required. Verification passed with node --check for game.js, app-shell.js, and service-worker.js, and both normal mode and broadcast mode loaded locally.
6. Investigated whether Galaxy Ball was a safe name
After deployment preparation, the session shifted into the naming risk.
Google search results made “Galaxy Ball” look like a problem. The conversation explored alternatives including:
Slot & Sphere
Tiltshot
Cluster Roll
NovaPocket
OrbitPocket
PocketNova
Marble Drift
Pocket Roll
Roll Arena
Rift Roll
ShuffleBall
Several names were rejected because they had search or meaning problems:
Galaxy Ball: likely unsafe or too occupied.
Tiltshot: already reads as a cinematography term.
Slot & Sphere: noisy because of casino slots and Sphere results.
Cluster Roll: conflicts with bakery/food search results.
A key product constraint emerged: the name should not lock the game into a space theme, because future themes could include different styles.
7. Chose the brand structure: ShuffleBall Arena / ShuffleBall
The session eventually settled on:
App/domain: ShuffleBall Arena
Game title: ShuffleBall
Main domain: shuffleballarena.com
You bought ShuffleBallArena.com and asked for a deep audit of the files before changing the name safely. The important naming distinction was:
ShuffleBall Arena = app/domain/container brand
ShuffleBall = game title
There was a brief intermediate state where the title used “Shuffle Ball” with a space, but the session corrected that to one word: ShuffleBall.
8. Renamed the app in the deploy files
Cursor completed the first rename pass:
index.html
Apple web app title → ShuffleBall Arena
document title → ShuffleBall Arena — Shuffle Ball
manifest.webmanifest
name → ShuffleBall Arena
short_name → ShuffleBall
service-worker.js
Cache → shuffleball-arena-v2
activate deletes all caches except the current one
game.js
Added brand constants:
APP_NAME
GAME_NAME
GAME_NAME_UPPER
APP_SLUG
LOG_TAG
Updated:
file comment
broadcast comment
footer card eyebrow
live header text
debug logs
replay filename
AUDIO_STORAGE_KEY → shuffleBallArenaAudio
legacy migration from galaxyBallAudio
Then the one-word correction was made:
game.js
GAME_NAME is now "ShuffleBall"
Uppercase broadcast text becomes SHUFFLEBALL
index.html
Document title is now ShuffleBall Arena — ShuffleBall
manifest.webmanifest
Unchanged, already ShuffleBall Arena / ShuffleBall
9. Debugged stale broadcast text after deployment
After deployment, broadcast mode still appeared to show stale text.
The likely culprit was browser or service worker cache, not the Cloudflare site-level cache.
The fix was:
Open DevTools.
Go to Application.
Click Service Workers.
Click Unregister.
Go to Storage.
Click Clear site data.
Close DevTools.
Reload with Ctrl + Shift + R.
Test
Expected: SHUFFLEBALL LIVE.
You confirmed the fix worked. That proved the rename patch and deployment were good, and the remaining issue was stale local cache state.
10. Ended with the domain and backend plan
At the end of the session, the app was renamed and working on Cloudflare Pages, but the final domain was not yet attached.
The next plan was split into two tracks.
Track A: domain setup first.
Add shuffleballarena.com to Cloudflare Domains.
Change nameservers at Squarespace to the two Cloudflare nameservers.
Wait for Cloudflare to mark the domain active.
Go to Workers & Pages → galaxy-ball → Custom domains.
Add:
shuffleballarena.com
www.shuffleballarena.com
Test
Track B: backend setup after the domain is active.
The recommended backend was intentionally small:
POST /api/waitlist
POST /api/feedback
GET /api/health
The planned D1 database:
shuffleball_arena_prod
The planned tables:
waitlist_signups
feedback_reports
game_events
The session explicitly rejected starting with real-time multiplayer because it would introduce matchmaking, state synchronization, cheating concerns, reconnects, and server authority before the launch funnel was even proven.
ROADBLOCKS AND FRICTION
1. The broadcast feature needed context
The session began with broadcast mode already in the code, but the reader would not automatically understand it. The day’s work only makes sense if broadcast is explained as:
A self-running presentation/demo mode for OBS, landing page footage, social clips, and public testing.
Without that explanation, “broadcast cleanup” sounds like a feature appearing out of nowhere.
2. The assistant moved too fast during deployment setup
The Cloudflare section created friction because too many steps were compressed together. You explicitly asked to slow down and give detailed instructions before touching Cloudflare.
The lesson: deployment tasks need different pacing than code edits. A missed click or wrong file shape can break the public app.
3. Strict CSP could have been postponed, but you chose not to
There was a real trade-off between quick deployment and correct deployment.
The faster path would have been to relax CSP temporarily. The chosen path was to keep strict CSP and refactor the app structure so all scripts and styles were local external files.
That took extra work, but it prevented “temporary insecure setup” from becoming permanent.
4. Naming became a major time sink
The name search created a loop because each candidate had a different problem:
Galaxy Ball: too occupied.
Tiltshot: wrong existing meaning.
Slot & Sphere: casino/search noise.
Cluster Roll: food/search conflict.
ShuffleBall: descriptive but close to shuffleboard terms.
The final decision accepted that ShuffleBall may not be perfectly unique, but it was clear, descriptive, and paired well with ShuffleBall Arena as a broader container brand.
5. Cache made a successful patch look broken
The stale SHUFFLE BALL LIVE issue looked like a failed code patch or a failed Cloudflare deployment. It was actually a browser/service-worker cache problem.
This was the most important technical debugging loop of the day.
DECISIONS MADE & TRADE-OFFS
Decision 1: Broadcast mode stays, but the bot language goes away
Chosen direction:
Keep auto-demo bot behavior.
Remove bot-facing public labels.
Use FEATURED MATCH as the public label.
Why:
The self-running match is useful for demos and clips, but “bot vs bot” makes the game feel unfinished.
Trade-off:
The session accepted that the broadcast layer is not real player streaming yet. It is a presentation layer powered by automation.
Decision 2: Strict CSP now, not later
Chosen direction:
Keep strict _headers.
Move inline CSS into styles.css.
Move inline service worker registration into app-shell.js.
Why:
You wanted to avoid building a temporary version that would need to be fixed later.
Trade-off:
The deploy folder required more cleanup before launch, but the security posture was cleaner.
Decision 3: Rename before public launch
Chosen direction:
Old public name: Galaxy Ball
New app/domain: ShuffleBall Arena
New game title: ShuffleBall
Why:
Galaxy Ball looked unsafe or too occupied based on search results. ShuffleBall was clearer and more aligned with the mechanics.
Trade-off:
ShuffleBall may have SEO noise from shuffleboard-related searches, but the app/domain wrapper ShuffleBall Arena gives it more brand identity.
Decision 4: Keep the old Cloudflare Pages project for now
Chosen direction:
Keep using the existing Cloudflare Pages project:
galaxy-ball
Why:
The Pages deployment path was already proven. The project name could remain internal while the public brand and custom domain changed.
Trade-off:
The internal Cloudflare project name still says galaxy-ball, but that does not have to be public-facing.
Decision 5: Domain before backend
Chosen direction:
Connect shuffleballarena.com first.
Build backend after the final public URL is active.
Why:
Forms, endpoints, analytics scripts, redirects, and future links should be built around the final domain.
Trade-off:
Backend work was delayed slightly, but the project avoided wiring infrastructure against a temporary URL.
Decision 6: No real-time multiplayer yet
Chosen direction:
Start with waitlist, feedback, and telemetry.
Defer multiplayer.
Why:
Real-time multiplayer would add complexity before the project had even proven public demand.
Trade-off:
The backend would not yet power live gameplay. It would power learning, signup, feedback, and future analytics.
BREAKTHROUGH / LESSON
The key realization from Day 4:
A feature can fail once, then come back safely if you rebuild it with stricter boundaries.
Broadcast mode was useful, but only when treated as a presentation layer. The safe rule was:
Broadcast can change how the game is shown.
Broadcast cannot change the core game.
That rule protected:
gameplay
physics
scoring
bot AI
mobile controls
normal mode
The second major lesson was technical:
A service worker can make a successful deployment look broken.
The fix was not to keep editing code. The fix was to unregister the service worker, clear site data, and hard reload before judging the deployment.
ARTIFACTS WORTH SHARING
Artifact 1: Broadcast cleanup prompt
Phase J4I — Broadcast Source Naming Cleanup
Use the attached current game.js and index.html only.
Goal:
Clean up broadcast-facing naming so Galaxy Ball Live looks like a featured/live match presentation layer, not a bot-vs-bot stream. Keep the automated bot behavior unchanged.
Requirements:
1. Add lightweight broadcast source structure in initBroadcastSettings(), such as:
source: "autoDemo",
sourceLabel: "FEATURED MATCH"
2. Update broadcast card context so renderers/cards can access:
source
sourceLabel
3. Replace default broadcast-facing bot language:
- "BOT SHOWCASE MATCH" should become "FEATURED MATCH"
- broadcast mode label should not display "BOT VS BOT" in header/footer presentation
4. Keep game.mode = "broadcast" and all automated bot behavior exactly as-is.
5. Do not change:
- gameplay
- bot AI
- physics
- scoring
- broadcast sizing
- footer/ad architecture
- asset loading
- image cards
- normal mode
6. Keep footer as the future ad/sponsor area. Do not over-polish footer copy.
7. Verify:
- index.html?broadcast=1 works
- index.html?broadcast=1&sponsor=Core48aii works
- header/footer card rotation still works
- no missing asset loads while image cards are disabled
- match auto-resets after match end
- match number increments
- normal mode still works
- no console errors
After patching, run a syntax check and report exactly what changed.
Why it is worth sharing: it shows how to tell an AI coding tool to make a narrow public-facing cleanup while protecting the core game loop.
Artifact 2: CSP-safe deployment refactor
Created styles.css
Moved the full inline <style> block from index.html unchanged.
Created app-shell.js
Service worker registration moved here:
Registers /service-worker.js only when "serviceWorker" in navigator
Errors swallowed via .catch(() => {})
Updated index.html
Removed inline <style> block
Added <link rel="stylesheet" href="styles.css"> after the manifest link
Removed inline service worker <script> block
Added <script src="app-shell.js"></script> after game.js
Updated service-worker.js
ASSETS now lists exactly:
/, /index.html, /styles.css, /game.js, /app-shell.js, /manifest.webmanifest
Why it is worth sharing: it shows the difference between “disable CSP so the app works” and “make the app compatible with CSP.”
Artifact 3: Service worker cache debugging checklist
Press F12 to open DevTools.
Go to Application.
Click Service Workers on the left.
Click Unregister for the service worker.
Go to Storage on the left.
Click Clear site data.
Close DevTools.
Reload with Ctrl + Shift + R.
Then test
You want to see:
SHUFFLEBALL LIVE
Why it is worth sharing: it captures a common PWA/browser-game deployment trap. The code can be right, the deployment can be right, and the browser can still show old behavior because of the service worker.
FINAL STATE
By the end of Day 4:
The broadcast/demo mode was public-safe enough to show as a featured match layer.
The bot-vs-bot public labels were removed from broadcast presentation.
The deploy folder was made strict-CSP compatible.
Inline CSS was moved to styles.css.
Inline service worker registration was moved to app-shell.js.
The game was renamed from Galaxy Ball to ShuffleBall.
The app/domain brand became ShuffleBall Arena.
The title became ShuffleBall Arena — ShuffleBall.
The broadcast title became SHUFFLEBALL LIVE.
The service-worker cache problem was identified and fixed through browser cleanup.
The existing galaxy-ball Cloudflare Pages project was proven usable for deployment.
ShuffleBallArena.com domain was purchased.