← Back to list

I Have Thirty Repositories. Only One of Them Has a Customer.

Two years of Dart, Go, Python and React. A CLI tool to generate the architecture I no longer believe in. And a coffee shop app for a coffee…

Vin · 2026-08-09 17:06 · 0 claps · 8.3 min read
#coffee #coffeeapp #coffee-shop #mobile-apps #tech
Open on Medium ↗
Wiki topics: 🌐 · Web Development 🍳 · Food & Cooking 🏛️ · Architecture

I Have Thirty Repositories. Only One of Them Has a Customer.

Two years of Dart, Go, Python and React. A CLI tool to generate the architecture I no longer believe in. And a coffee shop app for a coffee shop that doesn’t exist yet — which is the only honest thing I’ve built.

If you scroll far enough down my GitHub, you’ll hit February 2024 and find a repository called ctf_solvers. Below that, BRS. Below that, imagy. Then ai-lab, then DAA_LAB — algorithm assignments in C, submitted for marks.

That’s the floor. Everything I know is stacked on top of it.

I’m going to walk up that stack, because I think the shape of it explains something I’ve been trying to say out loud for months: I’m leaving the tech industry to open a coffee shop, and the last thing I built before deciding that was an app for the shop.

Not a portfolio piece. Inventory.

Phase one: building what I was told to build

DAA_LAB. dwdm — data warehouse and mining algorithms in Jupyter. java. csitcodes.

This is the coursework layer, and I don’t want to be cynical about it, because it’s where I actually learned to think. Implementing algorithms badly rearranges your brain permanently.

But look at the verbs. Submitted. Completed. Graded. Nothing in that layer was built because a person needed it. It was built because a syllabus said so, and the reward for finishing was permission to move on.

Then, March 2025: LeetCode. "Solutions for LeetCode."

Everyone in this industry has this repository. It is the most honest artifact any of us produce, because it admits exactly what it is: not building, not learning, not making anything for anyone. Grinding a filter. Training for an interview that tests a skill the job will never require, so that a stranger will let me past a gate.

I don’t regret it. I just want to name it: that repo is where I stopped building things and started performing employability.

Phase two: the portfolio treadmill

Now watch what happens through 2025.

Ecommerce_MERN. Portfolio_Project. ecom. realfocus. flutter_blog_app. flutter_ecom_app. flutter_todo_app, and — because I was getting serious — flutter_todo_app_backend.

A todo app. A blog app. An ecommerce app. The holy trinity. Every developer alive has built these three, and every one of us built them for the same reason: not because we wanted a todo app, but because we wanted someone to believe we could build one.

Here’s my favourite detail on the whole profile, and it’s an accident.

GitHub lists flutter_todo_app as HTML. It lists flutter_ecom_app as C++.

Those are Flutter apps. They’re in Dart. GitHub says HTML and C++ because the generated platform folders — the web scaffolding, the CMake files Flutter drops in for desktop — contained more code than I wrote. The boilerplate outweighed the app. My own repositories, doing linguistic analysis on my effort, concluded there wasn’t much there.

They were right. Those apps were four screens deep and a mile wide. They existed to be screenshotted.

I was optimising for the moment someone glanced at my profile, which is a strange thing to optimise a life around.

The first crack: dotfiles-2.0

June 2025. “XMonad configuration with animated widgets.”

Nobody hires you for your window manager config. Nobody screenshots your status bar for a recruiter. I spent that time “forking” someone’s animated widgets in a tiling WM, and I did it because I wanted my computer to feel a specific way when I used it at 1am.

That’s the first repository on my profile “forked” purely because I cared how something felt.

Remember that. It comes back.

Phase three: getting good, and getting quiet

2026 opens strong. claude-ssh-daemon — a Go daemon acting as a secure local intermediary for SSH. fclean — a Python CLI that scaffolds Flutter Clean Architecture feature directories and Dart boilerplate. gopull — recursively find every git repo under a directory and pull them all.

This is a different developer. These aren’t tutorials. They’re tools, written in Go and Python, that solve problems I actually had. gopull exists because I had accumulated so many repositories that keeping them current had become a chore worth automating. Thirty repos is enough sprawl to need infrastructure. I'd built a tool to manage the archaeological site of my own ambition. (Well, it was for the microservice workers tbh, and they are not public)

And fclean is the one I need to talk about, because it's the hinge of this entire story.

fclean generates Clean Architecture folders. Domain, data, presentation. Entities, repositories, use cases, datasources — the full liturgy, scaffolded in one command, because typing it out by hand for every feature is soul-destroying.

I built a machine to produce ceremony faster.

And then five months of nothing

Between mid-December 2025 and mid-June 2026, my GitHub goes almost completely dark.

I’m not going to dress that period up. Anyone who has looked at their own contribution graph and seen a long grey stripe knows what it means, and it’s rarely a sabbatical. It’s the stretch where you’re still going to work, still shipping, and quietly running out of the reason you started.

I kept getting better the whole time. That was the confusing part. My Go was improving. I understood distributed systems, edge functions, event pipelines. My bio still says “Full-Stack Developer building at the intersection of mobile, web, and distributed backend systems,” and it’s true. I can do the thing.

I just couldn’t find the person on the other end of it anymore.

Everything I’d built for two years terminated in an abstraction: a grade, a recruiter, a green square, a hiring manager’s glance. Thirty repositories, and I couldn’t point at one and say this is used, by someone, on a Tuesday, for something they needed.

jatra

July 9, 2026. A Dart repo. “A living almanac of the great Newar festivals of the Kathmandu Valley.”

I don’t fully know why I started it. Nobody asked for it. It won’t get me a job — there is no company on earth screening candidates for Newar festival calendar expertise.

I built it because I’m from here, and because the calendar my grandparents lived by deserves better than being scattered across PDFs and half-remembered dates. It was the first time I’d pointed my skills at something that existed before the tech industry did and will exist after it.

That was the week the question changed shape. It stopped being what should I build next and became what do I actually want to spend my days doing.

The answer, embarrassingly, was: make coffee for people in my city and watch their faces when it’s good.

The last app

flutter_coffee_shop. Description, in full: "An app for my future coffee shop."

I started it in December 2025 — one commit, then silence — and picked it back up in July. And building it as a person with a plan to leave, rather than a person trying to get hired, changed every single technical decision I made. I want to show you four of them, because this is where the story and the code become the same thing.

Five dependencies, and no code generation

dependencies:
  flutter: { sdk: flutter }
  cupertino_icons: ^1.0.8
  flutter_riverpod: ^2.6.1
  google_fonts: ^6.3.3
  intl: ^0.20.2
  shared_preferences: ^2.5.3

That’s the whole list. No freezed. No json_serializable. No build_runner. No go_router. No get_it. No Clean Architecture.

I wrote fclean. I know the liturgy better than most. And when I built the thing I'd actually have to maintain alone, from behind a counter, at 6am, in the twenty minutes before opening — I didn't use any of it.

Clean Architecture is insurance against a team you don’t have and a rewrite that isn’t coming. I’ve got seven repository interfaces and a folder per feature. CartItem is a hand-written immutable class whose copyWith only copies quantity, because quantity is the only field anything ever changes. Change the milk and it's a different drink. Freezed would have generated me a copyWith for all six fields and quietly deleted that piece of knowledge from my codebase.

Building the tool taught me the pattern. Building for myself taught me the price.

I made my fake backend slow on purpose

There’s no server. Every repository is an interface with a shared_preferences implementation behind a Riverpod provider, swappable in one line when a real backend shows up.

And in the auth repository:

/// Artificial latency so loading states are actually visible locally.
static const _latency = Duration(milliseconds: 600);

Every sign-in sleeps for 600ms before doing anything.

A local read returns in microseconds. If the fake is instant, the spinner never renders, the disabled button never appears, and I ship an app whose loading states no human has ever seen — until a customer opens it on bad signal outside my door, taps “Sign In” twice, and creates two accounts.

I’ve never cared about that failure mode before, because it always used to happen to a hypothetical user. Now it happens in front of me, in a queue, while someone waits for their flat white.

The cart never stores a price

/// Prices are always computed against the current menu, never stored here.

CartItem has no price field. The total is derived from the live menu, every time.

Storing the price on the cart line makes the first sprint easier and it is the most common data-modelling bug in consumer commerce. Because one day the shop raises the price of an oat flat white — and now there’s a cart sitting on someone’s phone that will happily check out at last month’s number.

I will be the one at the till when the app says one number and my register says another. Not a support queue. Me. Standing there.

It costs me something: while the menu loads, the total shows 0. I'd rather show an honest zero for 200 milliseconds than a confident lie forever.

Reorder has to survive my own menu changing

Past orders store the drink’s name, not its ID — an order is a historical record and has to still read correctly after a coffee is delisted. Which means the reorder button has to match old names onto today’s menu:

/// lines whose coffee is gone are skipped. Returns how many were skipped.

Four drinks, one retired? Add three, tell them about the fourth. Don’t fail the whole order to protect an abstraction.

I’ve never written that code before, in any of the thirty repos. Tutorial menus don’t change. Real ones do — seasonally, deliberately, because I’ll be the one deciding in October that the summer cold brew is done. This is the first app I’ve written that assumes the world keeps moving after launch, and that’s not a technical insight. It’s what happens when you know who’s going to be standing behind the counter.

The one part that isn’t practical at all

The hot/iced toggle is a pill that stretches as it launches and squashes as it hits the far wall, like it has mass and surface tension. It’s 164 lines with its own test file, and the whole character comes from one function:

static double _lag(double t) => _squish * math.sin(math.pi * t) * (1 - 2 * t);

Zero at both ends, stretch in the first half, compress in the second. 260 milliseconds, and not a millisecond more — push it to 400 and the illusion dies, because you stop seeing liquid and start seeing a rectangle whose width is being animated, which is of course exactly what it is.

Nobody will notice it. It sells no coffee.

I built it for the same reason I “forked” animated widgets into a window manager nobody else uses. Somewhere between the LeetCode grind and here, I got the part of me back that makes things feel a certain way for no return. I don’t think that part survives long in a job where every ticket has a business justification.

What I’m actually doing

I will not be leaving because I’m bad at this. Two years, thirty repos, seven languages, a Go daemon — the skill is there. That’s precisely what makes it hard to explain to people.

I will be leaving because for two years, everything I made pointed at an abstraction. A grade. A filter. A recruiter’s four-second glance at a pinned repo. And I finally found something that points at a person: someone comes in on a wet morning, I hand them something warm, and I get to watch whether it worked. The feedback loop is about ninety seconds long and there’s no analytics dashboard in it.

The app will come with me. Not as proof I can code — as the till, the loyalty card, the order history. It’s the first software I’ve written where the roadmap is set by a business that will exist, and the first one where a bug costs somebody their morning instead of costing me a sprint.

flutter_coffee_shop is the first thing I'll build to run something.

Thirty repositories. Twenty-nine of them were arguments that I should be allowed to do this. One of them is me doing it.


메타데이터
post_id
e6ed087928cd
slug
i-have-thirty-repositories-only-one-of-them-has-a-customer-e6ed087928cd
url
https://medium.com/@vinick/i-have-thirty-repositories-only-one-of-them-has-a-customer-e6ed087928cd
canonical_url
https://medium.com/@vinick/i-have-thirty-repositories-only-one-of-them-has-a-customer-e6ed087928cd
author_url
https://medium.com/@vinick
status
ok
fetched_at
2026-08-10 21:00:01