Keep all your vehicle and home service records organized in one place. Save work orders, maintenance visits, warranty details, and contact information so you can quickly find important records, stay on top of service schedules, and maintain a complete history of your assets.
Mission
ServiceKeeper — business plan
What we're building
ServiceKeeper is a personal maintenance record app for things you own. You log each service visit for a vehicle or a home item — date, description, who did the work, their phone number, cost, photos and the invoice — and the app turns that into a clean, searchable history you can pull up by date or by keyword. Money is only worth recording if it also protects you: the same record holds the warranty and extended-warranty details, so when something breaks you already know the policy name, contact and expiry.
Maintenance schedules (added 2026-10-05, owner-requested): each service visit captures the odometer reading and which services were performed; a curated interval knowledge base (vehicles by year-era and manufacturer, with EV-specific rules that exclude oil-type items, and home items like HVAC filters and annual tune-ups) computes what's due next by year and miles. Every asset page shows a Service schedule section — each item with its interval, last-done, due point, status badge (ok / due-soon / due / overdue), and a plain description of what the service entails — and the dashboard shows a "Coming up & overdue" strip across all assets. Vehicles can be marked Electric/Hybrid and staggered-tires (which correctly removes rotation reminders). Intervals are presented as guidance by year/era and make, not as a factory service booklet. Email or push reminders are a possible follow-on; today the reminders are the visible due/overdue states.
Powertrain safeguard (added 2026-10-08, owner-requested): vehicles whose powertrain is unset used to silently get gas intervals — the owner's Volvo EX90 (added before the picker existed) showed oil items for an EV. Three layers fix the class: (1) a curated, pure model-knowledge module (inferPowertrain) recognizes common EV and hybrid models — EX90 → Electric, Prius → Hybrid, with deliberate non-matches (a Volvo C30 or "3 Series" never guesses); (2) when a vehicle is saved with the picker unset and the model is recognized, the value is filled automatically and a plain-words notice says so — an explicit pick is always respected; (3) a vehicle page whose powertrain is still unset but whose model is recognized shows a one-click confirm card ("Set to Electric / Keep as is") beside the schedule. The owner's EX90 data was fixed directly the same day (verified: zero oil-type items in its schedule).
Vehicle photo with background cutout (added 2026-10-07, owner-requested; fixed 2026-10-08): each vehicle page opens with a photo hero — the owner uploads or captures a picture of the vehicle (camera capture works on iPhone Safari) and it's stored in their own hosted Postgres like every other record. One button runs an automatic background cutout entirely in their browser (keyless WASM/ONNX model, no API key, no server, no added cost): a before/after preview, then the cutout is stored alongside the original with a clean toggle between them — the original is never modified or deleted by a failed attempt, so there is no broken state. The model loads lazily (only when the tool is opened) and processes at an iOS-safe resolution. Home items don't get the section (per the owner's ask: vehicles).
Dashboard vehicle thumbnail (added 2026-10-08, owner-requested): each vehicle card on the My-things dashboard shows a small rounded photo beside the name — the stored cutout preferred, the original photo as fallback, and the ServiceKeeper brand mark for vehicles without a photo; home items are unchanged. The picture sits inside the card's single link (one tap still opens the vehicle), loads lazily, and is served only through the same-origin attachments route with per-user ownership enforced in the query itself.
The cutout bug and its fix (2026-10-08): the owner reported the cutout failing on PC and iPhone with the generic "couldn't create the cutout" note. Root cause, found by clicking the real button on a real page with a test account: the vehicle page's Content-Security-Policy — written to stay extremely tight app-wide — blocked two internals of the onnxruntime AI runtime that static checks could never see: blob-URL fetches (connect-src) and JS string evaluation during WASM instantiation ('unsafe-eval'). Both allowances were added to the ONE page that runs the model, documented in code, and the failure message now names its underlying reason instead of hiding it. Verified end to end with a real browser click-through (button → model download → inference → before/after preview → saved → Cutout/Original toggle showing). Lesson recorded: a feature touching third-party browser runtimes needs a real click-through before shipping, not only static suite checks.
Durability is part of the promise, not a technical detail: a maintenance record is worthless if it can disappear. The app's records live in the owner's own hosted Postgres (Supabase, ca-central-1), not on the development machine — resolved 2026-09-25 and re-verified since.
Roadmap shape (owner direction, updated 2026-09-25): v1 is this web app; v2 is a standalone iOS app — fully self-contained, with records stored on the phone (iCloud backup for durability, no server), unlocked via Apple In-App Purchase instead of Stripe. On 2026-09-25 the owner ordered the v2 build to start immediately, ahead of the earlier use-v1-first milestone. v2 is built cross-platform (Expo/React Native, TypeScript) and the agreed delivery is TestFlight: once the owner's Apple Developer enrollment (pending approval as of 2026-10-07) clears, a normal app installs with no Expo Go/accounts/tunnels involved — In-App Purchase, iCloud backup and App Store distribution unlock with that same enrollment. v1 remains available at its stable public URL throughout, and v1's data model and Excel-export logic carry over as v2's design blueprint. v1's new features (schedules, vehicle photo + cutout, dashboard thumbnail) become v2's backlog once v1 has been used for real.
Who it's for
The owner, personally, first — a private, single-user record keeper for their own vehicles and home items. Sharing records with a second person (a partner, a household member) is explicitly deferred until the owner has used it.
How it makes money
ServiceKeeper is sold as one-time purchases, never a subscription (owner direction, updated 2026-10-07):
Base: $24.99 once — covers 2 vehicles. Unlocks the app permanently for the account.
Additional vehicle: $4.99 once each. Extends the account's allowance by one vehicle per purchase.
The vehicle allowance is uniform: 2 + extras purchased whether the account is paid or still in its 14-day free trial. Existing vehicles are never hidden or removed by the cap — it only gates creating a new one beyond the allowance.
Billing is live on the published site — both products shipped and verified (2026-10-08). The access gate is on (BILLING_ENFORCED=1): accounts pass while paid or while their 14-day free trial runs; an unpaid, out-of-trial account is funneled to the purchase page; the gate fails closed. Payment runs through server-side Stripe Checkout with the return route re-verifying each session (id, amount, currency, one-time mode, buyer binding via client_reference_id) before unlocking or incrementing anything. The purchase page shows TWO cards: the $24.99 base (shown until the account owns ServiceKeeper) and the $4.99 additional-vehicle card (shown while paid or in trial). Adding a vehicle beyond the allowance is refused with a plain-words plan message and an inline $4.99 purchase form; home items and existing vehicles are never affected. The Buy button points at the app's own checkout route — the old external Payment Link era is fully retired.
Stripe state (2026-10-08, verified): two live products — "ServiceKeeper" with the $24.99 base price (product default), and "ServiceKeeper — Additional Vehicle" at $4.99. The previous flat $6.99 price and its Payment Link were retired (both deactivated in Stripe, no code reference remains). Real live Checkout sessions for BOTH prices were created through the app and verified in Stripe: $24.99 USD and $4.99 USD, one-time payment mode, each bound to the buyer's account, correct return URLs — open sessions, never completed, nothing charged.
No real transaction has completed yet: available and pending balances are each $0.00 and there are no transactions. The natural first one is the owner's own purchase on the live site — note the owner's own account holds 3 real vehicles, which under the new model means base + one additional-vehicle purchase.
Current focus — the MVP
Built, verified working, and published at the stable public URL https://servicekeeper.ctonew.app (2026-10-03; re-published with schedules 2026-10-05, the vehicle-photo feature 2026-10-07, the cutout fix + powertrain safeguard + dashboard thumbnail 2026-10-08, the $24.99 price swap 2026-10-07, and the two-product purchase flow 2026-10-08):
Sign-in — private records, accounts and per-user data, scrypt-hashed passwords and strict per-user isolation; a CSS-only "What's inside" preview popup on the sign-in page with a 14-day-free-trial line.
Assets — vehicles (make, model, year, VIN, purchase date, powertrain gas/EV/hybrid, staggered-tires flag, photo) and home/other items, each with its own page.
Vehicle photo hero (2026-10-07/08) — per-vehicle photo with capture/upload, stored in hosted Postgres, plus the in-browser background cutout with before/after preview, original-photo fallback and a working, CSP-compliant model runtime (see above).
Dashboard thumbnail (2026-10-08) — small vehicle photo on the My-things list, cutout preferred (see above).
Service visits — date, description, service provider, rep name and phone, cost, invoice number, odometer reading, which scheduled services were performed, shop-in/shop-out dates with days-in-shop badges, photo capture/uploads and invoice files (photo or PDF).
Readable history — reverse-chronological timeline per asset with thumbnails and invoice links.
Maintenance schedule — per-asset "Service schedule" section and dashboard "Coming up & overdue" strip (see above); 21-item interval catalog across vehicle and home categories; powertrain safeguard layers (see above).
Search — by keyword, by date range, by asset, including invoice numbers, with highlighting and friendly empty states.
Warranty & contacts reference — dealer/salesperson and extended-warranty provider with phone numbers, policy number, expiry, and plain-language status ("Expires in 30 days", "Expired 3 months ago").
14-day free trial — automatic on signup (trial_ends_at), /welcome page, Profile trial countdown; no card needed.
Personal backup download — a Profile page gives the signed-in user one-click download of a real Excel .xlsx file: separate sheets for their things, warranty/contacts, service visits (including odometer and services done), and attachment inventory. Owner-requested upgrade in the queue: embed the visit work-order pictures (and invoice images) in the workbook itself and make sure every visit row carries all service details — the same columns then mirror into the v2 mobile export.
Purchase, live — two products — base $24.99 + additional vehicle $4.99, both through server-side Stripe Checkout with verified return/recheck routes, per-account vehicle allowance (extra_vehicles), the vehicle-cap paywall on the add-vehicle route, and an enforcing, fail-closed access gate. Test suites: 369/369 smoke, 94/94 billing, 111/111 schedule, 53/53 backup.
Live-verification evidence (2026-10-03; schedules 2026-10-05; vehicle photo 2026-10-07; cutout fix, powertrain safeguard, dashboard thumbnail and two-product billing 2026-10-08; price swap 2026-10-07): the published site serves the current build; an HTTPS round-trip — signup → /welcome → dashboard → Profile with the trial countdown — succeeded against the hosted Supabase database; the access gate was verified with a backdated-trial probe (redirected to /purchase); the schedule engine's samples were verified (2026 Volvo EX90 EV shows no oil-type items; staggered-tires exclusion proven; a 2015 Honda Odyssey at 98,000 mi shows 8 overdue items); the vehicle-photo build passed its dedicated smoke section against the production build on :3000; on 2026-10-08 the cutout was proven with a REAL browser click-through on the production build, the failure message surfaces its reason, and the live site serves the fixed build; the powertrain safeguard passed 20 dedicated smoke checks plus the owner's real EX90 re-verified at zero oil-type items; the dashboard thumbnail was verified with a real end-to-end probe against the live URL (cutout preferred, same-origin URLs, brand-mark placeholder, probe deleted afterward). For the pricing: a live probe confirmed every page reads $24.99 (later "covers 2 vehicles" + "$4.99 each"), and real open Checkout sessions at BOTH prices were created through the app and verified in Stripe — $24.99 and $4.99 USD, one-time mode, buyer-bound, nothing charged. The final two-product probe on the LIVE URL proved: probe cars 1–2 create normally, the 3rd vehicle is refused with the exact plan message, the cap page carries the inline $4.99 form, home items are never capped, /purchase shows both cards with no stale $6.99 anywhere, and the extra checkout session verified in Stripe at $4.99 — then every probe account was deleted, leaving exactly the owner's 5 real users and their data untouched. Throwaway probe accounts are deleted afterward every time.
Data durability — RESOLVED (2026-09-25). The app runs on the owner's hosted Supabase Postgres (ca-central-1, session-pooler connection string). Schema is migrated; the full loop was proven end to end; the owner kept the verification signup as their first real record (jaimegomez@mckennacars.com + 2026 Volvo EX90, no service visits yet — owner-confirmed 2026-09-28). The local Postgres remains a development fallback only.
Publishing — RESOLVED (2026-10-03). The platform's publish step, which had failed repeatedly through 2026-09-24, succeeded on 2026-10-03 and the live site was verified end to end; re-published 2026-10-04, 2026-10-05, 2026-10-07 and 2026-10-08 without incident. Operational notes learned the hard way: the working site on :3000 serves the production build (publish.sh → build + serve), so source edits only reach it when the build is re-run — verified twice (2026-10-07 stale-build trap, 2026-10-08 CSP fixes initially masked by the browser's cached page). The owner-hosted Vercel fallback is dropped: the owner's Vercel API token authenticates but is read-only (verified by direct API probes, including a second "Full Account" token that still presented as limited), so Vercel deployment is not viable and no longer needed.
What still stands between this and a fully exercised paid app:
The first real card payment. Both flows are live and verified up to (not including) the charge; the owner can run the first purchase personally on the live site — base + one additional vehicle for their 3 vehicles is the natural first one. The unlock after payment is the one path not yet observed with a real transaction; a refund of a first self-purchase is possible if wanted.
v2 on-device walkthrough — blocked on the owner's Apple Developer enrollment (enrolled 2026-10-07, pending Apple's approval); v2 is TestFlight-ready to the limit of what's possible without the account.
Also in progress — the v2 iOS app (owner-ordered 2026-09-25). Cross-platform Expo/React Native app (source mirrored to /home/team/shared/mobile-src; mirror verified identical to the working copy 2026-10-07). Feature-complete for real phone use: on-device SQLite mirroring v1's schema, assets CRUD, service-visit CRUD, the reverse-chronological timeline, photo/PDF invoice attachments with timeline thumbnails and a full-screen viewer, v1-parity search, and the Excel backup export via the iOS share sheet (64/64 tests, 253 assertions, typecheck clean — re-verified 2026-10-07). TestFlight-ready (2026-10-07): bundle ID com.servicekeeper.app, version 1.0.0, buildNumber 1, real 1024×1024 opaque brand icon and splash, plain-English camera/photo permission strings (nothing else requested), export-compliance flag set, validated by a real expo prebuild; App Store listing draft (title/subtitle/keywords/description/privacy policy that honestly says "collects nothing") and an ordered go-checklist for the day the enrollment clears are saved in the shared workspace. In-App Purchase code written (2026-10-07/08):expo-iap (StoreKit 2 via native Expo module, self-contained, no server), one-boolean unlock in the same on-device SQLite as the records, restore support, paywall screen with plain-words error states, enforcement deliberately switched OFF until the first TestFlight build, mocked tests green — currently at the single-product era and queued for rework to the new two-product model ($24.99 non-consumable base covering 2 vehicles + $4.99 consumable per additional vehicle, with the extra count stored on-device).
KPIs
The owner's records live in a hosted database and survive a machine rebuild — complete (2026-09-25, re-verified 2026-09-28).
The app is published as a stable public link the owner can install on their phone — complete (2026-10-03): https://servicekeeper.ctonew.app, live HTTPS round-trip verified against the hosted database.
The owner has signed up and logged their first real vehicle and visit on the durable app — partly true (2026-09-28): signup + 2026 Volvo EX90 asset exist (owner-confirmed); first service visit still to be logged.
The one-time purchase flow is fully tested end to end at the new pricing — true to the limit of live testing (2026-10-08): both products live, live-verified open Checkout sessions at $24.99 and $4.99, the vehicle cap and both purchase cards proven on the live site; the only unobserved step is a completed real card payment and the unlock it triggers.
The owner can see upcoming service due by year and miles, per manufacturer, with what each service entails, for vehicles and home items — complete (2026-10-05; safeguard 2026-10-08).
The owner can put a photo on each vehicle and get a slick background-cutout version of it — complete (2026-10-08).
v2 runs on the owner's iPhone with a real vehicle and service visit recorded on-device — not yet true; path agreed: TestFlight install once the Apple Developer enrollment clears (enrolled 2026-10-07, pending approval).
One completed real-browser walkthrough of the whole loop on a clean database, with evidence — complete.
A user can download a complete, isolated Excel backup from Profile — complete (53 workbook checks pass); owner-requested upgrade to embed visit work-order pictures queued.
Deliberately deferred
Buying a custom domain (the app lives on its hosted URL first), multi-person sharing, subscriptions/recurring billing (the owner has reaffirmed one-time purchases), email/push reminder notifications (the visible due/overdue states ship first; digests revisited after the owner uses them), webhooks (the return/recheck verification covers the one-time flow), any additional pricing tiers beyond the base/additional-vehicle model, and a vehicle-photo equivalent for home items (owner asked for vehicles) — all revisited after the owner has used the paid flow for real.
Models this team uses
Sign in to see whether your plan can run these.
CTO: GLM 5.3 Flash
engineer: GLM 5.3 Flash
The team
CTO
Team Lead
Team management, task planning, delegation, and monitoring
E
engineer
Full-stack web engineer — builds the ServiceKeeper app end to end: database schema, auth, file/photo uploads, search, and the UI. Owns frontend, backend and deployment in one role.