Frinter is my longest-running project and the best laboratory of how I think about products. It started with a simple observation: productivity tools solve one problem at a time. A timer measures time, a tracker counts days, a notebook holds tasks, and a sleep app lives in a world of its own. Creative work does not happen in isolation, though. Focus depends on sleep, energy shapes decisions, and how much time the people you care about actually get only becomes visible once someone writes it down. I wanted one place where the daily plan, focus sessions, sleep and activity meet in a single picture. Today Frinter presents itself as a "Life OS for AI builders": it runs in the browser and as a PWA, in Polish and English, and I also describe its journey from prototype to the current architecture on przemyslawfilipiak.com.
The problem I wanted to solve
I work with AI every day and I know the pattern well: agents do their part while I switch between tasks, check results, rewrite instructions and come back to the code. The day ends, the project does not. I noticed that the hardest part was not focusing itself but knowing where my attention really went. At the end of a week I struggled to answer a simple question: how many hours did I give to deep work, how many to myself, and how many to the people who matter to me?
So instead of yet another timer I designed a system that connects three things: what I plan, what I actually spend time on, and how I rate the way I function. The word "connects" matters to me. The goal was not to staple five features into one menu but to make data from one part meaningful in another: a focus session lands in the history of its sphere, sleep feeds the energy bar, and the weekly self-assessment shows whether the numbers match how I feel.
Validate first, then build for years
My first decision was to consciously postpone the "perfect" architecture. In March 2025 I built a prototype on Replit: a few weeks of work, the first timer, a basic tracker and the first data. The aim was not a beautiful repository but an answer to whether I would actually use this every day. I did, so between August and November 2025 I added more modules: rankings, gamification, onboarding, an admin panel, the seed of an AI assistant and the foundation of a mobile app.
In December 2025 I moved the project to Railway: a real server, a database and automatic deployments. That was when the product started asking me hard questions. With several modules, "does it work" is no longer enough. The more important question becomes "how are these parts connected, and what happens when one of them grows". I believe the order was right: value for the user first, scale second. Had I started with heavy infrastructure, I would have been building something nobody needed yet.
Three spheres instead of a hundred categories
I spent more time on the product model than on code. Frinter organises time in three fixed spheres: Flourishing (growth and self-care), Relationships (the people close to you) and Deep work (focused work and learning). Each sphere can hold your own activities, but the spheres themselves cannot be multiplied at will. I considered a free-form taxonomy because it feels empowering, and rejected it: with unlimited categories the analysis stops saying anything, and users spend their time arranging the system instead of living. Three spheres are a frame that forces the question of balance.
I gave the spheres the same three colours, turquoise, violet and yellow, in a shared brand package used by the website, the web app and the mobile client. I also separated two models that are easy to confuse. Spheres describe time, while the weekly check-in, which I called Pełnostan, collects a subjective rating of five dimensions: flow, relationships, inner balance, recovery and a sense of meaning. I deliberately do not derive these ratings from minutes. How much time I gave to relationships is a different question from how I feel in them.
Many decisions were about small rules that build trust. A focus session, which I called a Frint, starts with choosing a sphere and an optional intention. Ending a session does not automatically close a task, because time spent is not proof of a finished result. The 1–10 depth rating starts empty and can be skipped: a missing rating is not a zero. These are small things, but they decide whether the data tells the truth.
An architecture that grows piece by piece
Between February and March 2026 I designed the target architecture from scratch, and from March to June 2026 I rewrote the backend on Cloudflare Workers. Instead of describing every decision, I show the whole system in the diagram, layer by layer, with service names exactly as they are in the code.
At the top are the channels: the frinter.app website on Cloudflare Pages, the web.frinter.app app, the mobile app for iOS and Android, and an MCP client, an AI assistant that works on a user's Frinter data with their consent. The website and the app send analytics events to PostHog in the EU. Below sit three public gateways: api.frinter.app takes all app traffic and enforces rate limits, auth.frinter.app handles sign-in with Better Auth and Google accounts, and mcp.frinter.app grants MCP clients access through OAuth.
The gateway talks to the services through service bindings, internal calls between workers that never leave for the public internet. The core service holds the timer, tracker and journal, the community service holds posts, rankings and badges, and a separate service runs the AI layer and product research. Postgres on Neon is the main source of truth, Cloudflare KV serves fast reads, and files go to two R2 buckets. Longer jobs go to a queue read by a separate worker that a cron trigger also starts every hour. A job that fails lands in a dead letter queue instead of disappearing. Everything lives in one monorepo with TypeScript and shared API contracts, so the web app, the mobile app and the services speak the same language.
Being honest with users
A product that collects data about sleep, habits and relationships touches very personal ground. That is why it mattered to me what Frinter does not promise. The energy bar is a heuristic computed from sleep entries, not a physiological measurement. When I aimed the messaging also at people who find it hard to start a task or return to it after a break, I wrote plainly that the app does not diagnose, does not treat and does not promise to improve symptoms. Analytics respects consent and never includes task content or session intentions.
The same rule applies to how I describe the product in public. The website shows the real interface on demo data and says so. Users can download their history to Excel from their account, and through the MCP server share it as JSON with their own AI tool for analysis. The data belongs to them, and I do not want to build a product that keeps people inside because they cannot leave.
What was hard
The migration turned out to be harder than writing new features. Moving from one server to several services meant keeping track of who really owns each API route. During a review I found duplicated families of handlers across services, so a folder name did not yet tell you which service answers a public request. I solved it by making the gateway's routing the source of truth and by keeping documentation that separates code from confirmed deployment.
The second challenge was session state consistency. A timer running in the background has to survive a lost connection. Starting a session requires confirmation from the API; after a read error the app keeps the last confirmed state and blocks a risky write; and if the response to finishing a session is lost, it requires a fresh read from the server. The third was security. Before a wider release I went through a hardening phase: per-route policies, a secrets matrix and automated production smoke tests that fail closed when their inputs are missing.
What came out of it and what is next
Today Frinter has a public website, a web app with PWA support, Polish and English versions and an AI assistant available through MCP. What matters most to me, though, is that the architecture no longer needs rewriting at every step. A new service is a new worker behind the same gateway, not a rebuild of the whole system.
The decision to use MCP came from the same thinking as the whole project. Instead of building yet another chat inside the app to compete with the tools AI builders already use, I made Frinter's data available where those people already work. The assistant can look at the daily plan or session history when the user asks for it, not when the product wants attention. I removed an earlier mascot with its prompts because it added noise instead of helping. To me that is a good example of how dropping a feature can be as important a product decision as adding one.
Ahead of me are the Expo mobile client, which already uses the shared API contracts, and an honest check of who this way of working is genuinely useful for. I plan to answer that through conversations and usage data, not by assuming the method works because I designed it.
Why this project matters to me
Frinter is my answer to a problem I know from my own days: AI speeds up the work, but my attention still has limits. Building it taught me more than any course, because every stage forced me to make a decision nobody else would make for me: what is the core, what is an experiment, what is a promise and what is only a hope. It is a project that shows how I work: I start with a simple prototype, I listen to what the product tells me, and I plan for scale only once I know it is worth it. It is also a reminder that focus equals freedom: the point is not to work more, but to know where your energy really goes and leave room for the rest of your life.

