How I Built BackPocket and Submitted It to Both App Stores in Eight Days

How I Built BackPocket and Submitted It to Both App Stores in Eight Days

Eight days ago, our GitHub repo had one commit in it that said first commit. Today it has 167, an iOS build sitting in App Store review, and an Android build in closed testing on Play.The app is called "BackPocket: pin and reuse info". It saves the things you retype constantly — a policy number buried in a PDF, a Wi-Fi password, the reply you send ten times a week — and hands them back from a custom keyboard while you're typing in any other app. Everything stays on the device. No account, no server.I'm not going to write the version of this post where everything went well. The useful parts are the four or five moments where it didn't.The BackPocket TeamThis is the backstory of BackPocket. Arjun and I went to the same university, twelve years apart, so we never once overlapped on campus. He's in India. I'm in England and decided to participate in Shipaton with this idea.Backpocket AppWe killed six ideas before I wrote a line of app codeMy first concept was a food thing called ChefTurf. I spent a day on it and then wrote a document arguing against it, which felt insane at the time and was the best decision of the whole project.Out of that came five ideation documents and six concepts — Makeshift, Moreish, Sift, Packet, a couple of others — each one written up properly and then most of them killed. BackPocket was the last one standing.7 days of building. One and a half days of deciding what to build. If I did this again, I would spend the same ratio, maybe more.Why we were able to move fastBefore I built features, I wrote down invariants. Short, numbered, boring rules the app was not allowed to break. Things like:INV-01 — core functionality is local-first and account-freeINV-08 — only creating is paid; existing templates and Kits stay viewable, fillable, and exportable forever, even after a subscription lapsesThat second one exists because a lapsed subscription must never hold your own data hostage. I wanted it decided on day two, in writing, while I was calm — not on day eight while staring at a revenue chart.I did not expect these to matter as much as they did.I was moving fast and generating a lot of code. At one point a branch came back with a nice-looking onboarding redesign that also included a "Create an account" screen. It didn't even gate anything — both paths reached the same place. But it collected an email into a stub that went nowhere and planted an account concept in a product whose entire pitch is there is no account.Because INV-01 was written down, that was a ten-second decision instead of an argument with myself. Took the icon assets and the onboarding layout from that branch. Dropped the sign-up screen.The same review caught something considerably worse. There was a "smart autofill" feature that would helpfully fill in blank Employee Number: fields. It worked by inserting a hardcoded Emp1234 — the same value, for every user, marked as verified, skipping the review step entirely.So it would have fabricated identical, incorrect personal data for everybody who used it, and told them it was confirmed.I deleted the whole mechanism. Parsers, registry branch, hooks, and its tests, which were all passing.If you take one thing from this post: write the rules down before you're tired. Speed is only safe if something other than your judgement in the moment is holding the line.I redesigned the entire app four timesNot tweaks. Four genuinely different design languages in eight days.It started light and Notion-ish. Then a warm ivory palette I called Quiet Utility. Then a full teal-accent reskin on near-black. Somewhere in there I bundled Source Serif 4 because the titles needed an editorial voice, and moved every number in the app into a mono face — because a reference number is data, not prose, and it should look like it.The rule that finally made it cohere was almost stupidly simple: one accent colour, and it only ever marks what is live. Selected, focused, pinned, or the one primary action on screen. Nothing else gets to be teal.Before that rule, everything important was highlighted, which means nothing was.I also deleted features I'd built and liked. There was a "Ready to reuse" shelf on the home screen. It was fine. It was also one more thing between you and the search bar, so it's gone.Then Apple rejected itGuideline 2.1. Information needed. Not a design complaint, not a rules violation — they wanted to know how the keyboard actually gets enabled and whether anything needed an account.Which, honestly, is fair. A custom keyboard is invisible until you go into Settings and turn it on. If a reviewer can't find the feature, the feature doesn't exist.Before that, two other Apple things ate hours: I built the first release archive with a beta Xcode. App Store Connect rejects beta-built binaries — but only after you've completed the entire archive and upload. So you find out at the very end. I now have a preflight check that fails in about one second instead of ten minutes.And I spent real time trying to sign with an App Store Connect API key before working out that the key works fine for the REST API and dies against the older portal that xcodebuild talks to. I wrote down why, in the repo, specifically so I would never diagnose it twice.There's also a commit in this history called Never commit Apple private keys, which I'm going to let speak for itself.The bug I'll rememberDay five. Templates — one of the main features — crashed every single Android device. Not some. Every one.The cause was one character. The placeholder regex looked like this:\{([^{}]*)} That compiles on the JVM. My host tests passed. It compiles on iOS. It ran fine in every test I had.Android's regex engine is ICU-backed, and ICU refuses that unescaped closing brace at pattern-compile time. The pattern was a constant in a static initializer, so the failure wasn't "templates misbehave" — it was an ExceptionInInitializerError the instant anything touched that class. Open the template editor, the whole app dies.Two things I got right by accident and one I got right on purpose:The accident is that I only caught it because I was installing real builds on a real device constantly, rather than trusting green tests. Host tests told me the truth about the JVM. They knew nothing about ICU.The purpose is what I did next. Instead of only fixing the brace, I audited every other regex in the codebase for the same trap, and then added a default uncaught-exception handler that writes crashes to a file and offers a one-tap "Share report" on the next launch. No user data in it. I planted a fake report to verify the whole path worked.I never want a crash on someone else's phone to be invisible to me again. That fix went out as version 0.1.16. I shipped through 0.1.20 the same day.What I'd tell myself on day oneShip a signed build to a real device on day one, not day six. Every genuinely nasty bug I hit — the ICU crash, an image-orientation OCR failure, keyboard extensions silently not loading — was invisible on a simulator and obvious on hardware.Write the invariants before the features. They're not bureaucracy. They're the thing that lets you say no quickly when you're moving too fast to think.The store is not the last 10%. Icons at exactly the right pixel size, screenshots at exactly the right dimensions with no alpha channel, review notes, a privacy policy that actually exists, an answer for every questionnaire row. None of it is code and all of it can stop you.Decide the pricing ethics early. Writing down "your data stays yours even if you stop paying" on day two meant I never had to have that argument with myself later.Eight days, 167 commits, 21 Android builds, one Apple rejection, one crash that hit 100% of Android devices, and six ideas that never made it.As I wait for it to be approved, feel free to reach out so that I can invite you as early testers.If you want to watch the rest of it go wrong in public, I'm posting as I go.

Original Source

Read the full article at Hackernoon →

KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.