Source
This app’s code and revision history are public. Download a copy or explore the files below.
Public
The app’s code and revision history are public.
Run it yourself
Take the whole tree and run it on your own machine. The download needs no account. Cloning needs a sign-in.
Download .zip
bounded clone e8a688fd21351d04b05468df
A copy you download is not bounded. The guarantees this app runs under - declared egress, proven invariants, writes that fail closed - live in the runtime serving this page, not in the files. What you get is auditable source you can read and run, with no runtime guarantees attached.
AGENTS.md
# Habits Habits is a free habit tracker with streaks, and a free alternative to Streaks, Habitica and HabitNow premium. It is an OpenApp in the OpenApps free apps store (https://openapps.free/), owned by the OpenApps team. ## What it promises - Free, with no limit on habits, no ads, no tracking and no paid tier. Never add a cap, an upsell or tracking. - No sign-up to start. Every visitor is a guest account created in the browser; habits are kept on the device and in that account. - "Keep my habits on all devices" signs in with Bounded hosted email login, and the guest's habits merge into the account. - Habits are private. Sharing is one habit at a time, by link: the people with the link see each other's name, current and best streak and last day done for that habit, and nothing else. - Honest about reminders: a web page cannot reliably remind anyone without a server sending pushes, so Habits offers a repeating calendar event (.ics or a Google Calendar link) instead and says so. - No API, on purpose: habits are personal. `public/llms.txt` explains the app and the `/new?name=...` links that open the add sheet filled in. Keep that file true. ## How it is built - `index.html` is the static landing page that search engines and AI crawlers read. The quick start mounts into `#start`; the app's tabs mount into `#app-nav` on wide screens. Keep its copy, comparison (figures from `docs/research/next-wave-pricing.md`, marked as reported in 2026), FAQ and JSON-LD in step with what the app does. `public/index.md` is the same page as plain markdown for AI agents (linked from `index.html` and `public/llms.txt`); keep it in step too. - `src/main.tsx` keeps `/` as the landing; `/today`, `/new`, `/week`, `/habits`, `/settings`, `/h/<habitId>` and `/s/<shareId>` hide it and show the app (`src/Shell.tsx`). - `src/lib/habits.ts` is the habit model and all the counting: schedules (every day, chosen weekdays, times a week, every n days), kinds (check, count, avoid), streaks per period, completion rate, what is due today, merging two copies, and CSV. `src/lib/dates.ts` keeps days as local `YYYY-MM-DD` and does arithmetic on day numbers. - `src/lib/store.ts` keeps the state in localStorage (`habits:v1`). Every check-in carries a timestamp, so two devices merge day by day without losing a check-in or an undo; habit settings merge by their own timestamp; a deleted habit stays as a marker. - `src/lib/sync.ts` syncs with Bounded: it reads the account's copy, merges, then writes only what changed, and reads again when the app comes back to the front (at most every 30 seconds). It never writes before the first successful read, so an offline device cannot overwrite newer check-ins. It also writes this person's streak row on each shared habit. - `src/lib/ics.ts` builds the reminder (.ics with an RRULE matching the schedule, and the Google Calendar link). - `policy.json`: - `people/<userId>`: settings JSON (name on shared habits, first day of the week). Owner only. - `people/<userId>/habits/<habitId>`: one habit with all its check-ins and notes as JSON. Owner only, no deletes (deleted habits are markers). - `teams/<shareId>` (Pattern A, the link is the permission): the shared habit's name and schedule; readable after a join; never changes. - `teams/<shareId>/joins/<userId>`: made by opening the link; only lets you read that one shared habit. - `teams/<shareId>/members/<userId>`: one person's streak row; only that person writes it. - `policy-tests/` covers every access rule: run `bounded tests run`. - `src/sw.js` becomes `/sw.js` at build (`vite.config.ts` fills in the file list) and keeps the app on the device, so it opens offline. `public/manifest.webmanifest` and `public/icons/` (crops of the card art) make it installable. ## Working on it `npm install && npm run build` typechecks and builds `dist/`. `npm run dev` serves it on port 4337. Ship changes through previews and releases as your runtime instructions describe; the app is an OpenApp, so nobody deploys it directly. Check a change by adding one habit of each kind and schedule, checking off and undoing on Today, setting a count and a note on a past day from the calendar, using the week view, reloading, downloading a reminder and the CSV, and sharing a habit with a second browser that opens the link. ## Voice Plain words, short sentences, warm, no jargon, no em dashes. Say what happens, and say plainly what Habits does not do.
Change history
Point OpenApps links to openapps.free
Bind agent address in policy
Use OpenApp service URLs and add contribution strip
Bounded source sync
Bounded source sync
Bounded source sync