Five public apps, and what shipping small things in the open actually teaches
A resume builder that stores nothing, a VS Code extension that interrupts you, a tax-registry API, an image tool, and a game. Each one is a decision about scope, and one of them I would not build again.
Context
Five public applications, all live, all built and operated by one person: Cresum (resume builder), Code Time Limiter (VS Code extension), Consulta RUC (Peruvian taxpayer lookup API and MCP server), CodeToImage (HTML/CSS to image), and Ropasclisp (Rock, Paper, Scissors, Lizard, Spock).
They are not a portfolio in the decorative sense. They are the cheapest way I know to keep practising the part of product work that does not survive being theoretical: choosing scope, shipping, and then living with what you shipped.
Problem
Each one started from a specific irritation rather than a market.
Cresum. Every resume builder wants an account, then stores your employment history, address and phone number on their servers indefinitely. For a document you may edit twice a year, that is a bad trade.
Code Time Limiter. I would sit down to code at 9pm and stop at 2am. Existing timers were either whole-system blockers or too easy to dismiss.
Consulta RUC. In Peru, validating a taxpayer identifier against the SUNAT registry is a routine need for anyone building invoicing or onboarding. Doing it programmatically was more annoying than it should be.
CodeToImage. I needed code and markup snapshots for documentation and slides, and the existing tools either imposed their own styling or required an account.
Ropasclisp. No problem. It was fun.
Product decision
Cresum: make the constraint the product. No account, no server-side storage. The entire resume is encoded in the URL, with optional link shortening for when that URL gets long. The privacy claim is structural rather than a policy promise — there is no database to breach. The cost is real and I accepted it: no cross-device sync, no autosave, and a share link that is opaque. Some people will bounce off that. The ones who stay get something no account-based competitor can offer.
Code Time Limiter: interrupt in the place the work happens. Rather than blocking the OS, the extension lives in the VS Code status bar and, when the budget is exceeded, surfaces lint errors — turning the editor itself into the nudge. No telemetry, no background service. Whether the mechanism is good is genuinely arguable; it is at least a real design position rather than another countdown.
Consulta RUC: ship the same capability through two interfaces. REST for applications, remote MCP for agents. Same data, same index, two consumers. This is the smallest useful example of the platform argument I make elsewhere: one capability, more than one named consumer, which is what justifies treating it as a product rather than a script.
CodeToImage: no install, no account, browser-only. The whole conversion runs client-side.
Ropasclisp: keep it a toy, and say so. No roadmap, no ambition.
Technical decision
Almost everything runs on Cloudflare — Pages for the front ends, Workers and D1 for the tax registry, with an ingest worker handling SUNAT updates. That choice was about operating cost per product: with five live things and no support team, per-product operational overhead is the binding constraint, so I optimised for near-zero idle cost and no servers to patch.
Stacks differ by fit, not by preference: Vue 3 with Pinia for Cresum’s URL-driven state; Next.js 15 on Workers for the tax lookup’s frontend; Astro for CodeToImage; plain TypeScript against the VS Code API for the extension. Licensing splits along the same lines — MIT where I want reuse, GPL-3.0 for Cresum and Ropasclisp.
Evidence
The live inventory, current stack, and feature list for each app is on the apps section, and the packages and repositories are on open source, both populated from npm and GitHub at build time.
I do not have user counts to publish. These products carry no analytics by design, and I would rather say that plainly than produce a number I cannot defend. What is verifiable: five products live, four with public source, three deployed on Cloudflare Pages, one serving both a REST API and a remote MCP endpoint, and a VS Code extension published in the Marketplace.
Constraints
- No support capacity. One person, best-effort. This shapes what I am willing to build: anything requiring guaranteed availability is out of scope.
- No analytics. A deliberate trade that leaves me without usage evidence. I know what exists, not what is used.
- Regulatory dependency on one product. Consulta RUC depends on SUNAT continuing to publish its registry in a usable form. If that changes, the product’s value changes with it and I do not control the timeline.
- Personal-need selection bias. Five products, one user profile: mine. Adoption beyond that is unvalidated.
Lessons
A refusal can be a position. Cresum’s “we store nothing” is more differentiating than any feature I could have added, and it cost less to build than a login system. I now look for the version of a product that is defined by what it declines to do.
If you cannot fund maintenance, do not ship. Five live products generate a permanent floor of work — dependency updates, platform migrations, upstream API changes — that arrives whether or not anyone is using them. This is exactly the continuity problem I argue about at work, experienced at small scale with nobody else to blame. It is the most transferable lesson here.
Two consumers change the design. Consulta RUC only became coherent once it served both applications and agents. The second consumer forced the interface to be a capability rather than a page.
Shipping is a separate skill from building. Deciding something is done, publishing it, and leaving it alone is a distinct discipline from making it work. Small public products are the cheapest place to keep that muscle alive.
Keeping a toy is a decision too. Ropasclisp has no strategic value and I keep it live and honestly labelled. A portfolio where everything is retroactively justified as strategy is less credible, not more.