← Back
005 IRONWARD

IRONWARD

Always moving forward.

ActiveAdvancedUpdated Oct 2026View Live
Role
Solo build
Type
Personal · Live
Systems
React · IndexedDB · Google Drive · Capacitor
Scale
Web + Android/iOS · ~920 exercises
01

Objective

Most gym apps are a spreadsheet with a nicer font. You still have to decide what to lift. Ironward decides for you. Open it, and the Train screen shows the next session in your plan with one big Start button. Every set shows a grey target: same weight plus one rep, or +2.5 kg once you hit the top of the rep range on every set. Tick the box and the target is logged.

Like Waypoint, there is no backend it requires. With no account, everything lives in the phone's or browser's IndexedDB. Sign in with Google and your logs become one file in an Ironward folder in your own Drive, under the drive.file scope, so the app cannot see anything else there. There is no database of mine to run or to leak.

Around that core: a rest timer that alerts even with the phone locked, PRs on finish, history by month, weekly volume, hard sets per muscle against the 10 to 20 range, estimated 1RM charts, stalled-lift detection with deload suggestions, a muscle heat map, body weight, protein and measurements, a warm-up ramp and plate calculator, supersets, failure and drop sets, Strong and Hevy CSV import, and a shareable monthly recap image.

Plans come built in (Push/Pull/Legs, Upper/Lower, Full body), can be built from scratch, or can be written by any AI chat. Answer six questions, paste the generated prompt into ChatGPT, Claude or Gemini, paste the reply back, and it becomes your plan. No API key, no server.

Why it is hard: a gym is the worst place for an app to fail. The signal drops, the phone locks between sets, and a lost workout is a lost session of data. Every part of it has to keep working offline and survive a refresh mid-set.

02

Decisions

Double progression decides the next set

Each exercise has a rep range. Until every set hits the top of it, the target is the same weight plus one rep. Once it does, the weight goes up by the smallest jump you can actually load, and reps reset. It's the simplest rule that keeps working, and it means the app always has an answer for "what now" instead of a blank box.

Bring your own AI instead of an API key

The AI coach writes a prompt, including your recent best lifts, and you paste it into whatever chat you already use. The parser digs the JSON out of a whole chat reply, tolerates trailing commas and smart quotes, and matches exercise names to the library so history carries over. Unknown ones become custom exercises. That keeps the app free to run, with no key to protect and nothing sent anywhere without you doing it.

Offline first, because gyms have no signal

Data is cached on the device. The workout in progress is saved locally on every change, so a refresh or a closed app loses nothing. A workout finished with no connection goes into an outbox, shows in History as if saved, and syncs when the signal comes back.

The same Backend interface as Waypoint

No-account (IndexedDB) and Google Drive (one JSON file) implement one Backend interface, so no page knows which is active. A no-account log can be moved into an account in one step. The Drive sign-in uses a stateless function that swaps Google's codes for tokens and stores nothing.

A real exercise library, not just names

About 50 hand-tuned exercises carry muscles, compound or isolation, and rest times. Behind them sits a public-domain library of ~870 more, each with a demo and step-by-step how-to. AI plans and Strong/Hevy imports match against both, so reports stay accurate. Anything still unknown gets a muscle picker instead of silently counting for nothing.

Self-updating native apps

The Android and iOS apps are Capacitor shells. New web bundles download in the background and apply on next launch, with automatic rollback if one fails to start, ported from Waypoint. A new native build is offered as a download only when it actually needs a new plugin or permission.

03

Architecture

Storage

Page / hook → Backend interface → No account (IndexedDB) → Google Drive (one JSON file)

  • The drive.file scope limits the app to its own folder. Google enforces that, not application code.
  • The client secret lives only in a stateless serverless function. It never reaches the browser.

Logging a set

Last session → Double progression target → Tick ✓ → Rest timer + locked-screen alert → Draft saved on device → Finish → PRs → Saved / queued in outbox

  • Empty boxes accept the target, so a normal set is one tap.
  • The next set copies the weight you just used.

AI plan import

6 questions → Prompt with recent best lifts → Any AI chat → Paste reply → Parse + match exercises → Preview → Your plan

  • The same path takes a 4-week training review and turns any suggested plan back into a real one.
04

Result

A live web app and Android app that covers the whole gym loop: pick or generate a plan, log sets in a tap with the next target already filled in, rest with an alert even on a locked phone, and see from the reports which lifts and muscles are moving and which have stalled. It works with no account, or follows you across devices through your own Google Drive, and keeps working with no signal.

05

By the numbers

~920
EXERCISES
3
BUILT-IN PLANS
2
STORAGE BACKENDS
0
API KEYS NEEDED
06

Stack

React, TypeScript, Vite, Tailwind CSS, TanStack Query, IndexedDB, Google Drive API, Capacitor

07

Lessons learned

  • Building on Waypoint's Backend interface and update system made Ironward fast to stand up. I'd keep extracting those shared pieces deliberately rather than copying them between projects.
  • A plain gym log isn't enough. The value is in telling you what to do next, so the progression rule had to come before the features around it.
  • Asking an AI for a plan is easy. Trusting what comes back is the hard part. The parser, name matching and preview step turned out to be most of the AI feature.