Work Insights Hub File Namer Auto_Nerd FitFuel Weather Whiplash Friendlynk How I Work About Contact LinkedIn →
Explore
FitFuel app icon
Christopher Shadix · Prototype · 2025

FitFuel

Every fitness app wanted $15/mo to track a protein shake — so I just made my own. Zero code. Just clear creative direction and Claude doing the building.

Today
Monthly
Login
Check-In
Progress
Today
Monthly
Login
Check-In
Progress
Progress
Today
Check-In
Monthly
Login
Progress
Today
Check-In
Monthly
Login
Role
Everything
Type
Prototype / Webapp
Stack
HTML, JS, Node, Netlify
Version
v6 (Current)
FitFuel visual exploration — pink gradient
FitFuel visual exploration — teal mood
FitFuel visual exploration — warm variant
FitFuel visual exploration — coral bold
Visual direction · MidJourney explorations
01

Tired of decks. So I made something real.

FitFuel started because every fitness app either does too much or charges $15/mo to let you log a protein shake. I just wanted something simple that worked the way I think. So I made my own.

As a Creative Director, I've always believed the clearer the vision, the faster it moves. AI just removed the bottleneck. I opened Claude, directed every decision through conversation — UI patterns, data architecture, feature logic — and hit v6 before dinner. It's a working prototype I'm already using.

Daily Tracking Macro Logging Supplement Checklist Monthly Calendar Weekly Check-Ins Progress Dashboard Photo Upload Chart.js Visualizations User Auth Persistent Storage
FitFuel login screen
Login
FitFuel today view
Today
FitFuel monthly calendar
Monthly
FitFuel weekly check-in
Check-In
FitFuel progress dashboard
Progress
App screens · Figma exports
02

Design tools I know. Dev tools I learned.

This project lives at the intersection of two toolkits — the design tools I've used for years and the AI that wrote every line of code. Every screen started in Figma, every asset was refined in Illustrator and Photoshop, and early visual explorations came from MidJourney. But the real story is Claude — I directed the entire build through conversation, not a code editor.

Figma + Figma Make
UI design, prototyping, and generative layout exploration with Figma's Make feature.
Illustrator
Icon design, logo refinement, and vector asset creation for the app's visual identity.
Photoshop
Image compositing, mockup generation, and asset optimization for web delivery.
MidJourney
Early-stage visual exploration and concept generation for brand direction and mood.
Claude AI
Every line of code — HTML, CSS, JS, and serverless functions — was written by Claude, directed through iterative prompting.
>_
Terminal + Node.js
Command line workflows, npm packages, and deployment pipelines — learned enough to ship, not to write from scratch.
Netlify
Deployment, Identity (auth), Blobs (storage), and serverless functions — the full platform.
import { getStore } from "@netlify/blobs"; const store = getStore("checkins"); const headers = { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", }; export default async (req) => { const token = req.headers .get("authorization") .replace("Bearer ", ""); const payload = JSON.parse( atob(token.split(".")[1]) ); const userId = payload.sub; const storeKey = `user-${userId}`; if (req.method === "GET") { const result = await store.get( storeKey, { type: "json" } ); return new Response( JSON.stringify(result || []), { status: 200, headers } ); } if (req.method === "POST") { const newEntry = await req.json(); const existing = await store.get( storeKey, { type: "json" } ) || []; existing.unshift(newEntry); await store.setJSON(storeKey, existing); return new Response( JSON.stringify({ success: true }), { status: 200, headers } ); } }; import { getStore } from "@netlify/blobs"; const store = getStore("checkins"); const headers = { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", }; export default async (req) => { const token = req.headers .get("authorization") .replace("Bearer ", ""); const payload = JSON.parse( atob(token.split(".")[1]) ); const userId = payload.sub; const storeKey = `user-${userId}`; };
const rings = [ { key: "calories", color: "#22d3ee" }, { key: "protein", color: "#f472b6" }, { key: "carbs", color: "#fbbf24" }, { key: "fat", color: "#a78bfa" }, { key: "water", color: "#60a5fa" }, { key: "activity", color: "#4ade80" }, ]; function drawRings(ctx, data) { rings.forEach((ring, i) => { const radius = 80 - (i * 12); const pct = data[ring.key] || 0; const angle = (pct / 100) * Math.PI * 2; ctx.beginPath(); ctx.arc(120, 120, radius, -Math.PI / 2, angle - Math.PI / 2 ); ctx.strokeStyle = ring.color; ctx.lineWidth = 8; ctx.lineCap = "round"; ctx.stroke(); }); } function updateDashboard() { const canvas = document .getElementById("ringChart"); const ctx = canvas.getContext("2d"); ctx.clearRect(0, 0, 240, 240); drawRings(ctx, dailyState); } const rings = [ { key: "calories", color: "#22d3ee" }, { key: "protein", color: "#f472b6" }, { key: "carbs", color: "#fbbf24" }, { key: "fat", color: "#a78bfa" }, { key: "water", color: "#60a5fa" }, { key: "activity", color: "#4ade80" }, ];
async function saveCheckin(data) { const user = netlifyIdentity .currentUser(); const token = await user .jwt(true); const res = await fetch( "/.netlify/functions/checkins", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify({ date: data.date, weight: data.weight, bodyFat: data.bodyFat, notes: data.notes, photo: data.photo, }), } ); if (res.ok) { showToast("Check-in saved!"); loadCheckins(); } } netlifyIdentity.on("login", () => { loadDailyState(); loadCheckins(); updateUI(); }); async function saveCheckin(data) { const user = netlifyIdentity .currentUser(); const token = await user .jwt(true); };
const chart = new Chart(ctx, { type: "bar", data: { labels: weekLabels, datasets: [{ data: weeklyHits, backgroundColor: "rgba(244, 114, 182, 0.6)", borderRadius: 8, }], }, options: { responsive: true, scales: { y: { beginAtZero: true, max: 7, grid: { color: "rgba(255,255,255,.05)" }, }, x: { grid: { display: false }, }, }, plugins: { legend: { display: false }, }, }, }); function updateWeeklyChart() { chart.data.datasets[0].data = getWeeklyHits(dailyHistory); chart.update(); } const chart = new Chart(ctx, { type: "bar", data: { labels: weekLabels, datasets: [{ data: weeklyHits, backgroundColor: "rgba(244, 114, 182, 0.6)", borderRadius: 8, }], }, });
function switchTab(tabId) { document.querySelectorAll( ".tab-content" ).forEach(t => t.classList.remove("active") ); document.querySelectorAll( ".nav-tab" ).forEach(n => n.classList.remove("active") ); document.getElementById(tabId) .classList.add("active"); event.currentTarget .classList.add("active"); } const supplements = [ "Omega-3", "Vitamin D", "Creatine", "Magnesium", "Zinc", "Ashwagandha", ]; function renderSupplements() { return supplements.map(s => ` <label class="toggle-switch"> <input type="checkbox" onchange="toggleSupplement( '${s}' )" /> ${s} </label> `).join(""); } function switchTab(tabId) { document.querySelectorAll( ".tab-content" ).forEach(t => t.classList.remove("active") ); };
03

Serverless architecture, no excuses.

FitFuel runs entirely on Netlify's serverless stack. User authentication is handled through Netlify Identity with JWT tokens. All persistent data — daily logs, weekly check-ins, measurements — is stored in Netlify Blobs via two serverless functions in Node.js. No traditional database, no backend server, no DevOps overhead.

The frontend is a single HTML file — nearly 3,000 lines of code, all generated by Claude and directed through iterative creative prompting. Chart.js powers the progress visualizations. Everything is designed mobile-first with a native-app feel: bottom navigation, card-based UI, glassmorphism, and smooth transitions. A brief for something like this would normally take weeks to see a first draft. We hit v6 in one session.

1
HTML File
~3K
Lines of Code
2
Serverless Functions
6
Versions Shipped
04

Things I didn't know six versions ago.

Every version of FitFuel taught me something that made me a better creative director. Not by learning to code — but by learning that clear creative direction moves fast when the tools match the vision. These tools are creative fuel, not a replacement for the people who use them.

01
Prompting Is a Design Skill
Describing UI behavior, data flow, and edge cases in plain language — and getting working code back. Directing AI requires the same clarity and intentionality as directing a team.
02
Serverless Changes Everything
Netlify Functions and Blobs meant real backend functionality — auth, persistent storage — without managing servers. I didn't need to understand every line, just enough to direct the architecture.
03
Show, Don't Deck
Instead of a 40-page brief that takes weeks to see a first draft, I had a working prototype people could tap through. That changes the entire conversation.
04
Ship, Then Iterate
Six versions taught me more than any tutorial. Each deploy revealed what actually needed to change — not what I imagined needed to change. Real feedback loops beat hypothetical ones.
05

Why this matters.

"AI doesn't replace taste, judgment, or craft. It just lets you show people what you mean instead of hoping they read the deck the way you intended. These tools are creative fuel."
Try the Live Demo →

Back to

All Work