Finite — A Different Way to See Time

Inspiration

Nobody tells you when you're experiencing something for the last time.

There is a last Saturday your child asks you to make pancakes. A last bedtime story before they decide they're too old for one. A last ordinary phone call with a parent that you never realize was the last.

The difficult part is that these moments rarely feel special while they're happening. They feel ordinary, repetitive, and almost endless.

I started thinking about how we understand time. We know that life is finite, but that knowledge is abstract. We can read a statistic, calculate an estimate, or promise ourselves to appreciate people more. Then everyday life takes over, and the feeling disappears.

What if, instead of reading a number, you could actually see time passing?

That question became Finite.

Finite turns recurring moments into a grid of squares, with one square representing each expected occurrence. Every square belongs to a real date, and as those dates pass, the grid changes automatically.

The idea isn't to make people anxious about the future. It's to help them notice the value of ordinary moments before they become memories.

What It Does

Finite allows users to create a timeline for a recurring ritual.

You choose a name, frequency, duration, and start date. It could be Saturday pancakes, a weekly call with your dad, Sunday lunch with your family, or any recurring moment that matters to you.

Finite calculates the expected occurrences and represents each one with a square.

The experience revolves around two numbers:

  • Left: The number of occurrences remaining in the timeline.
  • Kept: The number of past occurrences the user has marked as moments they were present for.

The distinction matters. Left changes as time passes, while Kept records the moments the user chooses to acknowledge.

The grid doesn't wait for you to open the app. If three months pass, the timeline reflects those three months. When you return after being away, Finite can show you how many moments have passed since your last visit.

You can mark a past occurrence by tapping its square, and tap it again to undo the action.

There are no streaks, productivity scores, or reminders demanding your attention. Finite isn't trying to measure how disciplined you are. It's trying to make the passage of time visible.

How We Built It

Finite was built with plain HTML, CSS, and JavaScript, using localStorage to preserve rituals in the browser.

The application has no framework, build step, external dependencies, backend, API keys, or network requests. It can run offline, keeping the experience lightweight and independent of external services.

The code is organized into three main files:

  • "index.html" provides the application structure, ritual form, and grid legend.
  • "styles.css" defines the typography, colors, layout, and visual states of the squares.
  • "app.js" handles the calculations, application state, rendering, keyboard interactions, and local persistence.

The occurrence calculation uses the duration, recurrence interval, and an appropriate day conversion to determine how many occurrences fit within a period.

For example, a weekly ritual lasting 12 years produces approximately 626 occurrences when using an average year length of 365.25 days:

[ \left\lfloor \frac{12 \times 365.25}{7} \right\rfloor = 626 ]

A yearly ritual lasting 20 years produces 20 occurrences.

Dates are calculated using calendar arithmetic rather than repeatedly adding fixed millisecond intervals. This avoids daylight-saving drift and handles month-end dates more predictably. For example, a monthly occurrence beginning on January 31 can proceed through February 28 and March 31.

The application stores the information needed to reconstruct each timeline, including the start date, occurrence count, marked occurrences, and last-opened day. It recalculates the passed and upcoming states from the device clock whenever the page renders.

This means the timeline can change without a background timer or a server continually updating it.

The project was developed for the Build With AI: Basics hackathon using an AI coding agent and a structured workflow covering project initialization, scope, requirements, specifications, implementation, and delivery. The corresponding planning documents are included in the repository.

Challenges We Faced

Making Time, Rather Than User Activity, Drive the Grid

The biggest challenge was making the central idea work as intended.

In the initial version, the squares changed only when the user interacted with them. Although the interface looked right, the timeline could remain unchanged even after weeks or months had passed.

That contradicted the purpose of Finite.

The solution was to tie every occurrence to its actual date and calculate its state whenever the application renders. Time, rather than user activity, now drives the depletion.

We also changed the meaning of tapping a square. Instead of consuming an occurrence, the action records whether the user was present for it. The action can be undone, making the grid a record of acknowledged moments rather than an irreversible counter.

Keeping Large Grids Readable

Some rituals produce hundreds of squares. Displaying all of them while keeping the grid understandable required careful decisions about square sizes, spacing, and visual contrast.

The interface adjusts square sizes according to the number of occurrences, while distinct visual states help users differentiate past and upcoming moments.

Making the Grid Accessible

A grid containing hundreds of interactive elements can become frustrating for keyboard users.

To address this, each grid is designed as a single tab stop, with arrow keys used to navigate internally. Keyboard movement is constrained to actionable squares so users aren't moved into disabled controls that cannot receive focus.

Preserving Rituals Reliably

Because Finite stores rituals locally, persistence is essential. Closing the browser should not mean losing the information that gives the application its meaning.

We prioritized checking whether saved rituals survived browser closure and reopening early in development rather than leaving this uncertainty until the final demonstration.

What I Learned

Building Finite taught me that a product can look correct while communicating the wrong thing.

The original grid worked as an interface, but it depended on the user's actions to change. That made it a measure of app usage rather than a representation of time. Connecting the grid to real dates changed the experience fundamentally.

I learned to question what a feature is actually measuring, not just whether it works technically. In Finite, the difference between time passing and a user recording a moment became the foundation of the entire product.

I also learned how useful structured planning can be when an idea changes during implementation. Defining the scope and requirements early made it easier to recognize when the implementation contradicted the intended experience and to correct that inconsistency without losing focus.

Most importantly, this project reminded me that a small, carefully considered interaction can communicate more than a complicated interface. Finite doesn't need to tell people that time is limited. It lets them see the evidence for themselves.

What's Next

Future improvements include allowing users to edit rituals after creating them and backdate occurrences that have already happened.

Notifications are deliberately excluded. Finite is designed to let people choose when to reflect, without turning the experience into another source of pressure.

Built With

  • HTML
  • CSS
  • JavaScript
  • localStorage
  • AI coding agent

The Idea Behind Finite

Finite doesn't predict how long a relationship will last or how many times you will see someone again. It works with the dates and durations you provide.

Its timeline is an estimate based on those inputs, not a prediction of anyone's lifespan. Its accuracy also depends on the device's clock.

What it offers is a different way to look at recurring moments.

A square is small. A grid can look ordinary. But when every square represents a real opportunity to be present, the grid begins to mean something different.

Time keeps moving, even when we aren't looking. Finite simply gives that movement a shape.

Built With

Share this project:

Updates

Submission history