blog.hahash.com.
← blog.hahash.com
·6 min read

Why I Stopped Making Screenshots and Started Shipping 35 Live Apps

indie developerself-hostedportfolioshippingone-person studio

Screenshots Lie

A screenshot is a promise the code broke. By the time a visitor sees the polished PNG, three things have usually happened: the dependency updated, the API changed its rate limits, and the design has been "slightly tweaked" for the last six months.

For years my portfolio was a folder of screenshots. I had a section for "Web Apps" and another for "Tools" and a third for "Experiments." Every entry was a still image, two paragraphs of copy, and a link to a GitHub repo that may or may not have built on a fresh clone. It looked professional. It also told you nothing.

The screenshots showed what the apps did on the day I took the picture. They did not show whether the apps still worked, whether the data behind them was real, or whether I would answer a question about them if you emailed.

So I changed the rule. If it is not running on a server I can point you to, it does not go on the site.

The First Version Was Embarrassing

The first time I tried to put a live app on a portfolio page, I embedded an iframe of a tool I had built to track my reading list. It worked. It also had no styling, used a database schema I had written at 1 a.m., and broke the moment a user tried to filter by author.

I almost took it down. Then I left it up, because the alternative was admitting I had nothing running, and the alternative before that was another screenshot.

That reading-list tool is still on the site. It has been rewritten twice. It is still ugly in places. People use it, including me, every week.

The lesson was not "ship ugly things." The lesson was that running code, even running code with warts, is a more honest signal than a polished mock. A screenshot says "I made this once." A live app says "I keep this working."

The Switch From Showcase To Software

At some point the portfolio stopped being a list of things I had made and became a piece of software in its own right. The homepage is a gallery. The gallery loads 35 iframes. Each iframe is a real app. The gallery itself is a small frontend that handles the layout, the loading states, and the fact that some apps respond faster than others.

That shift changed how I think about the work in three ways.

First, every app has to survive contact with a stranger. When only I used a tool, the bug report was a shrug. Now the bug report can come from anyone, and it usually comes at the worst time. That pressure made me care about error states, empty states, and the small text below the input that explains why something failed. None of that shows up in a screenshot.

Second, the apps have to load fast enough that someone will actually click the second one. A portfolio page that takes 12 seconds to render 35 iframes teaches the visitor to bounce. So I learned, slowly, about lazy loading, about deferring heavy widgets, about putting the cheap apps on top and the expensive ones below the fold. This is a problem you never have with images.

Third, dead apps are visible. When a screenshot stops being accurate, nobody notices. When a live app stops responding, the iframe shows a broken icon and the page gets quieter. The site has a self-correcting property: anything that is not maintained will announce itself, and I have to deal with it or pull it.

One Server Changes The Math

All 35 apps run on one server. That is a constraint I chose on purpose, because constraints are the cheapest forcing function I know.

A single server means I cannot lean on managed services for everything. If I want a queue, I write a small one. If I want a database, I pick one and learn it well instead of swapping it every project. If an app uses a model that needs more RAM than the box has, the app does not get built, or it gets built with a smaller model, or it gets queued for a moment when the box is bored.

It also means I have to care about resource use. I have a graph. I look at the graph. There is a satisfying kind of work in watching 35 apps coexist on a box that cost less than a nice dinner, and in knowing that when one of them misbehaves, the graph will tell me before a user does.

The number 35 is not magic. It is what fit. Some of the apps are products I would sell if anyone asked. Some are tools I use to plan my week, track books, log runs, or escape recipe sites that refuse to show the actual recipe. Some are AI demos that exist to be poked at, broken, and borrowed from. The categories on the site are products, tools, and demos, and the boundaries are loose on purpose.

Why Live Beats Recorded, Almost Every Time

A demo video is a performance. A live app is a contract. The contract is small: this thing runs, here, right now, and you can use it.

I have watched people land on the gallery, open three or four apps in parallel, and start asking questions in the chat that I would never have predicted. They are not asking about my process. They are asking whether the recipe app handles fractional units, or whether the writing tool will export to a specific format, or whether the small AI widget in the corner can do a thing it was not designed to do. Those questions are the point. They are the part of the work I could not get from a screenshot, a case study, or a polished case-study PDF.

The "no screenshot" rule also killed a habit I did not like: polishing. I used to spend hours picking fonts for a fake dashboard, color-matching a chart that did not have real data, and writing copy that explained what a tool would do in a parallel universe where I had finished it. The portfolio got prettier and the actual apps got fewer.

Now the apps are the portfolio. If a tool is half-built, it ships as a half-built tool, and the site tells you it is a demo. If a product is real, you can click it, push it around, and decide for yourself whether it is worth your time. There is no marketing layer between the work and the visitor.

The Cost Of Keeping Things Alive

The honest version of this story has a part nobody puts on the about page. Keeping 35 live apps alive is more work than building them was.

There is the slow drift. Libraries update, language versions reach end of life, and the little services I stitched together to make an app work stop being little. There is the security side, which never ends. There is the moment, every few months, when I have to choose between spending a weekend rewriting a tool only I use and quietly taking the tool down. Sometimes I take it down. The site is fine with that. The site is more honest when the count is 33 than when it is 35 and three of them are broken.

There is also a kind of social cost. A screenshot is yours to control. A live app is a small public surface, and the people who find it will have opinions. Most of those opinions are useful. A few of them are not. I have learned to read the useful ones fast and skim the rest.

What The Gallery Is For

The gallery is not a store. It is not a pitch deck. It is an answer to one question: what does this person actually make?

If you are hiring, the gallery is a better signal than a résumé, because a résumé is also a kind of screenshot. If you are a developer who wants to borrow an idea, the gallery is a starting point: open the app, see if it solves your problem, copy the part that does. If you are a visitor who wandered in, the gallery is a small piece of software you can wander through, the way you might wander through a studio.

The line on the homepage, the one that does most of the work, is short: One person. One server. 35 live apps. It is not a tagline. It is a description of a working system.

A Rule That Might Work For You

If you are building a portfolio, here is the only piece of advice I have earned: pick one project, the smallest one that still feels real, and put it on a server you control. Do not screenshot it. Do not write a case study about it. Put it on a page with a link that works, and let it sit there for a month.

If it survives the month, you have learned something a screenshot could not teach you. If it does not, you have also learned something, and you have lost less time than you would have spent writing about it.

That is the whole trick. The rest is just maintenance.