Browse packs / Family / spikinglabs

Aura

A calm, serverless baby and child log for the phone: feeds, sleep, diapers, sick mode with a fever chart and doctor summary, paper documents kept page by page, and German vaccination and checkup reminders. The merge and backup rules, migrations, growth percentiles, schedules, reminders, AI redaction and calendar files specified exactly.

spikinglabs/auraversion 1Apache-2.0 74 decisions288 checks

Build this pack

Paste this into Claude Code, Codex or Cursor, with your language. Your agent runs every step below on its own, builds the product the pack describes, and stops when it works and the pack's checks pass.

Build https://symbola.sh/packs/spikinglabs/aura/ in Python
The steps, to run yourself or to see what your agent does
  1. Install the Symbola CLI (Python 3.11+): uv tool install symbola (or pipx install symbola). Not pip install symbolon: that PyPI name is another project.

  2. Download the pack: symbola pull spikinglabs/aura --dest spec.

  3. Read spec/AGENTS.md and follow it. Build only from spec/: don't look for the original product's source, the registry repository (it holds holdout tests) or other builds. Packs released before the rename say symbolon <command>: run symbola <command> instead. This is a product pack: spec/PRODUCT.md describes the whole product (its shape, surfaces and flows). Build that product, in the user's stack, with the components below as its core. Don't build a demo page around the components instead.

  4. Build each component in its own folder and run its checks as you go, fixing what fails:

    symbola impl-init impl/ai-redaction --contract spec/components/ai-redaction/versions/1
    symbola test spec/components/ai-redaction/versions/1 impl/ai-redaction
    

    In Python, define run(input) in impl.py: it takes and returns a dict, and raises ValueError for input the contract rejects. Pin third-party packages with == in requirements.lock. In another language, set language = "command" and command = [...] in symbolon-impl.toml; the program reads one JSON input per line on stdin and writes {"output": ...} per line. A component whose symbolon.toml says driver = "cli" is a command line: build the real program, set command to it, and symbola runs it once per check.

  5. When every component passes, run symbola keygen once, then for each component symbola attest spec/components/ai-redaction/versions/1 impl/ai-redaction -o attestations/ai-redaction.json. On macOS, attest needs Docker running and accepts Python, Node or a static Linux binary (for Go, GOOS=linux); symbola test runs the same checks without it.

You are done when every flow in spec/PRODUCT.md works in the product you built and attest reports PASSED for every component. Write open questions and the readings you chose in NOTES.md. Every command is described at https://kausalflow.github.io/symbola/cli/.

Components:

  • ai-redaction: spec/components/ai-redaction/versions/1
  • backup-retention: spec/components/backup-retention/versions/1
  • growth-percentile: spec/components/growth-percentile/versions/1
  • ics: spec/components/ics/versions/1
  • media-pack: spec/components/media-pack/versions/1
  • merge: spec/components/merge/versions/1
  • migrate: spec/components/migrate/versions/1
  • reminders: spec/components/reminders/versions/1
  • save-guard: spec/components/save-guard/versions/1
  • schedule: spec/components/schedule/versions/1

Every command: Symbola CLI docs. Agents can read these steps as plain text in llms.txt.

Evidence

Who has built it

Test results that ship with the pack, one column per build. 10 of 10 components pass a build · 1 build · 1 runner.

Componentspikinglabs/aura
ai-redaction ✓ 23 checks
backup-retention ✓ 22 checks
growth-percentile ✓ 47 checks
ics ✓ 19 checks
media-pack ✓ 14 checks
merge ✓ 33 checks
migrate ✓ 16 checks
reminders ✓ 48 checks
save-guard ✓ 15 checks
schedule ✓ 51 checks

Runners: runner-i · newest 2026-10-28. Hover a result for details.

Decisions

What a build must do

Each one is a decision a builder could get wrong. Decided is required, default may change in a fork with a note, and open is deliberately left to the builder.

product

  1. The app never gives medical, dose or diagnosis advice: no amount, no 'give', no illness named, no treatment. It shows reminders (the fixed rules of the reminders component), and when a medicine's minimum gap has passed. Every AI prompt carries the same rule, and an AI answer is only ever sorted into entries or a handover the parent reads. Schedules (vaccinations, checkups, dental) only remind of the published recommendation and say that the pediatrician decides; the app never signs in to a calendar. product.no-advice · 0 checks

merge

  1. Logs merge item by item, matched by id: an item of the other copy replaces the local one only if its updatedAt is strictly greater (missing counts as 0); on a tie the local item stays. Items are never combined field by field. merge.newest-wins · 5 checks
  2. A deletion is an item that stays with deleted true and a newer updatedAt, and is merged like any edit: a newer deletion wins, a later edit brings the item back, an older deletion loses. merge.tombstones · 4 checks
  3. The merged list keeps the local items in their order (a replaced item keeps its place), then appends the other copy's new items in their order; merging the same copy again changes nothing. merge.order · 4 checks
  4. All 14 synced collections (children, episodes, entries, meds, measurements, growth, products, vaccines, checkups, dental, appts, emergency, docs, pages) merge this way; a collection the other copy lacks is left alone. Anything new that syncs must be added to this list. merge.collections · 1 check
  5. A log that only holds example data is replaced by an empty log (settings kept) before merging, so example items never mix with real ones. merge.example-data · 1 check
  6. After a merge the selected child stays; without one, the first child that is not deleted is selected, else none. merge.selected-child · 2 checks
  7. Only Aura logs are merged in (app 'aura' or the old 'sick-day-log'); a log of a newer format version is refused with a message to update, and an older one is first brought up to the current format. merge.accept · 5 checks
  8. A Drive file counts as an Aura log only if app is 'aura' or 'sick-day-log' and entries is a list; the app never writes over anything else. merge.foreign-file · 5 checks
  9. After writing, the app checks that nothing of the phone's was lost to another phone's write: every item of the phone must be in the remote copy with at least its updatedAt. merge.covered · 5 checks
  10. Top-level parts of the Drive file that this version does not know (added by a later version) are written back unchanged; known keys are app, v, savedAt, example, settings, child, drive, recalls, docTr and the 14 collections. merge.unknown-parts · 2 checks

migrate

  1. A log's format version is its v if that is a positive integer, else 1. The current version is 3. A log of a higher version, or anything that is not an object, is returned unchanged and reported as too new. migrate.version · 7 checks
  2. Version 1 (the old sick-day log) becomes version 2 by building a fresh empty log that takes over only children, episodes, measurements, meds (or the two starting medicines) and settings (over the defaults); each entry gets the child of its illness; the selected child is the first child that is not deleted. Nothing else is carried over. migrate.v1 · 3 checks
  3. Version 2 becomes 3 by moving the book photos kept in vaccines and checkups (kind 'page') into documents and pages, with deterministic ids, times and tombstones, so two phones that upgrade separately end up with the same log. migrate.v2 · 5 checks
  4. Adding a collection or fields needs no version change (older apps keep parts they do not know); changing what existing data means needs the next version, a migration step and a test. Before a migration step runs, the log as it was is kept: as 'before-vN' (N the new version) in the phone's database and as backups/aura-log-before-vN.json in Drive (once); these copies are never pruned. An older app never writes a newer log. migrate.keep-before · 0 checks
  5. A log without a valid v is treated as version 1. The step from 1 to 2 converts the old collections and keeps every other collection and field of the log as it is, so a damaged or hand-edited log never loses data. migrate.v-less-log · 3 checks

save

  1. A log of a newer format version is never saved by this app. save.too-new · 1 check
  2. A log is saved only if it is an object with settings, all 14 collections are lists, and every item is an object with an id that is not missing or null (0 and '' are fine). save.well-formed · 4 checks
  3. A log with fewer items (over all collections) than the last saved one is not saved, and a refused save does not lower that bar; equal or larger logs are saved. Deletions are tombstones, so the count only falls when the parent removes everything. save.no-shrink · 6 checks
  4. A smaller log may be saved when the last saved log was example data, or when the parent chose something that removes items (allow_shrink, used up by the next save that passes the format checks). save.shrink-exceptions · 3 checks
  5. allow_shrink is used up by the next save attempt, whatever its outcome: a save refused as too new or malformed clears it too, so a later save that did not ask for it is refused if it shrinks. save.allow-shrink-once · 1 check

growth

  1. Percentiles use the WHO tables as given in fixtures/who-lms.json (L, M, S per month by sex: 2006 standards to 5 years, 2007 reference after; weight to 10 y, height to 19 y, head to 5 y), interpolated linearly in L, M and S between whole months. growth.tables · 14 checks
  2. Age in months is (measurement time - birth date at 00:00 UTC) / 30.4375 days, with fractions; at birth the first row is used. growth.age · 2 checks
  3. z = ((value/M)^L - 1)/(L*S) and the percentile is 100 times the normal distribution function computed with the Abramowitz and Stegun 7.1.26 approximation given in the description, not an exact one. growth.z-and-cdf · 5 checks
  4. For weight only, beyond 3 SD either way z is replaced by WHO's adjustment (3 SD plus the distance beyond, counted in steps of the 2-to-3 SD distance); height and head are not adjusted. growth.weight-adjustment · 4 checks
  5. Without sex f or m, a birth date, a value, or a table row for that age (before birth, beyond 10 y for weight, 19 y for height, 5 y for head), there is no percentile: all outputs are null. growth.no-table · 12 checks
  6. A percentile is described only as 'below 1st percentile', 'above 99th percentile' or the rounded (halves up) number with its English ordinal and 'percentile'; no wording judges it (no 'too small', 'normal', 'worrying'). growth.wording · 15 checks

schedule

  1. The schedules are the German ones as of 2026: STIKO standard vaccinations (RSV antibody, rotavirus, 6-in-1, pneumococcus, meningococcus B, MMR, chickenpox, Tdap and Tdap-polio boosters, HPV, meningococcus ACWY; MenC at 12 months dropped, MenACWY at 12 to 14 years added), the U-Heft checkups U1 to U9, U10 (new, paid from 2027) and J1, and the dental checkups Z1 to Z6, with exactly the ages and periods in the description. schedule.tables · 7 checks
  2. A checkup that is not recorded or booked is 'later' until 28 days before its window, 'soon' from then, 'due' while its window is open (the window's last day included), 'missed' after, and 'open' (usual age only) without a birth date. schedule.checkup-status · 9 checks
  3. A vaccine dose is 'due' from half a month before its usual age, 'late' after the plan's upto age (default usual age + 2 months), 'missed' after the plan's until age, 'later' before; doses recorded count per vaccine, a dose recorded against several vaccines counts for each, deleted doses do not; all doses recorded is 'done'. schedule.vaccine-status · 12 checks
  4. A vaccine the parents do not plan is 'skip'; without a birth date nothing is due and only the usual ages are shown. schedule.skip-and-no-dob · 4 checks
  5. A recorded visit makes a checkup 'done' whatever else is known (an appointment never replaces a recorded checkup); deleted records do not count. schedule.recorded-wins · 4 checks
  6. A booked appointment for an item shows instead of the usual time: 'booked' until its day has passed (a later hour that day is still booked), then 'went' (the app asks to record the visit); for vaccines it must name the vaccine and the next dose number; the newest appointment wins; deleted ones are ignored. schedule.appointments · 8 checks
  7. Today and the Documents tab point out: due or late vaccines, due or soon checkups and dental checkups, and appointments that went or fall in the next 15 days (start of today + 15 days). schedule.today-line · 8 checks
  8. A schedule the parent turned off (vaccinations, checkups or dental) points nothing out and puts nothing in the calendar; statuses may still be shown. schedule.plan-off · 5 checks
  9. Calendar dates cover the next 365 days: an all-day event on the later of today and the start of the usual period (checkups), the window start (dental) or the usual age of the next dose (vaccines); a booked appointment on its own day and time. Unique uids: '<child>-<key>', '<child>-vax-<key>-<dose>', '<child>-appt-<id>'. Sorted by date and time. schedule.calendar-dates · 7 checks
  10. Months are counted on the calendar from the birth date; when the target month is shorter than the birth day, the date is that month's last day (31 August + 3 months = 30 November, 29 February + 12 months = 28 February). schedule.month-end · 3 checks

reminders

  1. A reminder that fever has come and gone for more than 3 days appears when the first and last temperature of 38.0 °C or more are 3 days or more apart. reminders.fever-days · 3 checks
  2. A baby under 3 months (30.44-day months; birth date needed) with a temperature of 38.0 °C or more gets the reminder to be seen by a doctor promptly. reminders.young-baby · 3 checks
  3. A temperature of 40 °C or more in the last 24 hours is pointed out. reminders.high-temp · 2 checks
  4. In an illness that is not ended and has at least one diaper logged, more than 8 hours since the last wet diaper (wet or both; else since the illness start) is pointed out. reminders.wet-diaper · 5 checks
  5. Three or more vomits in the last 6 hours are pointed out. reminders.vomiting · 2 checks
  6. Symptoms the parent noted in the last 24 hours among: fast breathing, very sleepy / floppy, not drinking, wheezing are repeated back as 'You noted: ...' (reminding, not judging). reminders.worrying-symptoms · 1 check
  7. The reminders appear in the fixed order of fever days, young baby, high temperature, wet diaper, vomiting, symptoms, each at most once, and test the rules above exactly. reminders.order · 3 checks
  8. For each medicine in an illness the last dose is shown with 'gap passed' once its last dose plus the parent's minimum gap (hours) has passed, else 'gap at <time>'; no gap set means nothing is shown. The app never says what or how much to give. reminders.medicine-gap · 6 checks
  9. Today asks for a backup until there is a copy off the phone: when nothing was ever backed up, or the log changed after the last backup and that is more than 2 days old; it can be snoozed to tomorrow, and is not shown for example data or without a child. reminders.backup · 10 checks
  10. A product on the family's list matches a recall when every word of its name (lower-cased, accents stripped, ß as ss, words of one character dropped) is a word of the recall's title or company. Matching happens on the phone; the product list is never sent anywhere. reminders.recall-match · 8 checks
  11. Only recalls of the countries the parent tracks (all when none chosen) count: 'new' ones are from the last 30 days and not yet seen in the list; alerts are matches with the family's products not dismissed. reminders.recall-lists · 5 checks
  12. The recall list (one public JSON file, RECALL_URL) is fetched at most every 12 hours (every hour after a failure), kept on the phone and used offline, not synced; seen ids are kept only for ids still in the list. reminders.recall-refresh · 0 checks

retention

  1. Hourly Drive copies are kept as: the 48 newest, then the newest of each calendar day for 60 days (days among the 48 newest are not counted); everything else is deleted, newest first in the answer. retention.drive-prune · 9 checks
  2. Before overwriting the Drive file the app saves it as aura-backup-YYYY-MM-DD-HH.json in Aura/backups, at most once per local hour (not again if that name exists, not again after a snapshot this hour), then prunes. retention.hourly · 6 checks
  3. aura-log-before-vN.json copies and any foreign files in the backups folder are never pruned. retention.before-upgrade · 3 checks
  4. The phone keeps one copy of the whole log per local day (snap-YYYY-MM-DD, newest 14) beside the log; example data is not copied; before-vN is never deleted. retention.phone-copies · 6 checks
  5. Restoring from a Drive backup or a daily copy adds back anything missing (a merge); it never deletes and does not undo later edits or deletions. retention.restore · 2 checks

sync

  1. A Drive sync reads the file, merges, writes, and checks the file's version is still its own write's (else reads and merges again, up to 3 rounds, then retries after 20 s); an idle check is one small request for the version; it never writes over a file it cannot read as an Aura log; a log over 4.5 MB is written with a resumable upload; the partner's backups go to an Aura folder in their own Drive. sync.safe-write · 0 checks

media

  1. In a Drive backup, every direct field of an item in the synced collections that holds a base64 data URL is replaced by 'aura-media:<sha256 hex of the URL>.<ext>#<header>' and the bytes go once to backups/media under that name; names already there are not uploaded again. media.pack · 5 checks
  2. Everything else stays as it is: non-base64 data URLs, links, values nested deeper than a field, other parts of the log. media.untouched · 2 checks
  3. Restoring puts each reference back as header + ',' + base64 of the file, so pack then unpack gives the original log. media.restore · 3 checks
  4. An item whose file cannot be found in backups/media (or whose reference has no header) is left out of the restored list and counted once, so a restore never blanks a picture on the phone. media.missing · 4 checks

ai

  1. Before any AI call, names of children (not deleted), the parent's own name and the names of people who logged entries are replaced by placeholders [CHILD], [CHILD 2]..., [PARENT 1]...; the child asked about is [CHILD]; names are put back into the answer on the phone. ai.names-out · 8 checks
  2. A name is replaced anywhere (any case) unless a letter of any alphabet touches it on either side; the longest name goes first; a name of one character is left (its number is still used). ai.word-boundary · 5 checks
  3. Names of deleted children, and the names on deleted entries, are replaced like any other, because they can still be in notes; deleted children are numbered after the live ones. ai.deleted-children · 2 checks
  4. Placeholders are replaced by names in every string of the answer at any depth; keys and other values stay; placeholders the model invented stay as written. ai.restore · 2 checks
  5. The system text is sent with the sentence 'Names are replaced by placeholders such as [CHILD]; keep each placeholder exactly as written.' appended, and 'See exactly what was sent' shows the system text and the redacted user text exactly as sent. ai.sent-text · 2 checks
  6. Images (pages of the vaccination book or U-Heft, only when the parent switched reading on and was asked once) go only to the parent's own AI service (key needed); with another provider the call fails; with AI off the call fails first. ai.images · 6 checks
  7. Photos, sounds, links, birth dates (age is sent instead), contacts and insurance data never go into a prompt; AI is off until the parent chooses a service and gives a key, which stays on the phone and is never synced; only https addresses (or http://localhost) are accepted. ai.nothing-else · 0 checks

ics

  1. The calendar file is RFC 5545: CRLF lines (also at the end), VCALENDAR with VERSION 2.0, PRODID -//Aura//Baby log//EN, CALSCALE GREGORIAN, METHOD PUBLISH, one VEVENT per event with UID '<uid>@aura' and DTSTAMP in UTC. ics.shape · 4 checks
  2. A date is an all-day event (DTSTART/DTEND;VALUE=DATE, end = next day) so it never shifts with the time zone; a booked appointment with a time is a one-hour event in local time (no zone letter). ics.all-day-and-timed · 4 checks
  3. Reminders: a timed event gets one the day before (-P1D) and one an hour before (-PT1H); an all-day event one at 9:00 on the day (PT9H); each is a display alarm with the title. ics.alarms · 3 checks
  4. A booked appointment carries URL (the app's address plus ?open=appts); a timed booked one is OPAQUE, everything else TRANSPARENT; LOCATION only when there is one. ics.booked · 2 checks
  5. In text values every backslash, ';' and ',' gets a backslash and a line break becomes \n (RFC 5545). ics.escape · 2 checks
  6. Lines are folded at 75 octets of UTF-8 (RFC 5545): each physical line, including the space that starts a continuation, is at most 75 octets; pieces are filled greedily and a character is never split. ics.fold · 4 checks
  7. A single event is saved as aura-<title up to ' ·', lower-cased, runs of non a-z0-9 as '-'>.ics; several events as aura-dates.ics. ics.filename · 5 checks
  8. For one event the Google Calendar link is calendar.google.com/calendar/render with action=TEMPLATE, text, dates (start/end as in the file), details and location (if any), form-urlencoded; for several events there is none. ics.google-link · 5 checks
Assumptions

What it takes for granted

Facts about the world the pack relies on, and how to notice when one stops holding.

K-ai-service

The AI service the parent chooses is trusted by them with the redacted text: how long it keeps text and whether it trains on it is that service's own policy.

Watch for: The AI card says which service is in use and every answer has 'See exactly what was sent'.

K-device-clocks

The clocks of the phones that share a log agree to within a few minutes, so the newest updatedAt is the latest edit.

Watch for: none

K-drive-version

Google Drive increases a file's integer 'version' with every change to its content, and returns the version produced by an upload.

Watch for: A sync that finds the version unchanged while the content differs would be caught by the read-back round; no monitor otherwise.

K-google-client

Aura's Google client ID and Picker key are public by design and Google accepts them only from the app's own web address; the drive.file scope lets the app see only files it created or that the parent picked.

Watch for: The sign-in or the picker fails with a Google error page if the origin or the key is wrong.

K-ids-unique

Item ids are unique across all phones that share a log.

Watch for: none

K-one-timezone

All dates of the schedules and the calendar are calendar days in the phone's own time zone, and a day is 24 hours.

Watch for: none

K-recall-feed

The Recall Tracker keeps publishing one public JSON list of baby and children's product recalls at the same address and with the same fields (id, title, company, country_sold_in, publish_datetime, scraped_datetime, url, reason, source).

Watch for: The app shows the error text of a failed fetch under More; a feed that stops updating shows an old 'scraped' date.

K-small-log

The whole log (text, plus photos, pages and sound clips of about 100 KB each) fits in one file that a phone can download and upload in full.

Watch for: Sync time grows with the number of photos; the size shows under More, Your data.

K-stiko-gba-2026

The German schedules in the schedule component (STIKO childhood vaccinations, G-BA U-Heft checkups U1 to U10 and J1, G-BA dental checkups Z1 to Z6) are the rules as of 2026.

Watch for: Re-read the STIKO calendar and the Kinder-Richtlinie each year and when either is amended; update the tables and the version of this pack.

K-who-tables

The WHO LMS tables in fixtures/who-lms.json are the published WHO Child Growth Standards (2006) and Growth Reference (2007) and are the right reference for the family's children.

Watch for: none

Brief

Aura

Aura is a calm, phone-first log for a baby and, later, a child. Parents log feeds (with a breastfeeding timer), sleep (with a timer), diapers, solids, temperature, medicine, growth, teeth and notes, mostly in a few taps or by talking ("Say it"). When the child is sick, sick mode moves temperature, medicine and symptoms to the top and gives a fever chart and a day-by-day summary for the doctor. Paper documents (vaccination book, yellow U-Heft, dental pass, Kita papers) are kept as digital twins page by page, with the German schedules for vaccinations, checkups and dental checkups as reminders.

It has no server of its own. The family's log is one JSON document on the phone and, if the parent connects it, one file in their own Google Drive that a partner can share. Everything runs in the browser as an installable page that works offline. The product is made for German-speaking families, the text is English, and the doctor summary can also be shown in German.

A rebuild is faithful when the family's data is as safe and as private as in the original and the rules below behave exactly: logs from the original (and every earlier version) open and merge; a partner's phone and a rebuild can share one Drive file; the schedules, reminders and percentiles say what the original says. The components in this pack pin exactly those rules; PRODUCT.md says what the rest of the app is.

Non-goals

  • Medical advice of any kind: no doses, no diagnoses, no treatment suggestions, no judging of a percentile. Aura reminds and records; the pediatrician decides.
  • A server, accounts or any service run by the publisher. No analytics. No connection to kidsfox (the family's Kita app has no API) and no sign-in to any calendar.
  • Other countries' schedules, other languages beyond English and the German doctor summary, and a store-style native app. The look (colours, layout, icons, exact wording of texts) is the builder's, within PRODUCT.md.
  • Real-time collaboration beyond item-by-item merge; there is no locking or turn-taking.
  • Encrypting the Drive file with a passphrase, "Ask" chat and a weekly digest (planned, not built).

Priorities

When goals conflict, earlier ones win:

  1. Never lose or corrupt the family's data: the merge, migration, save guard, backups and media rules, exactly.
  2. Privacy: names, photos, sounds, links and birth dates stay on the phone and in the parent's own Drive; AI and recall features send only what the AI-redaction and recall rules allow.
  3. No advice: nothing the app says tells anyone what to give or what illness it is.
  4. Schedules and reminders: the vaccination, checkup and dental status, the reminders and percentiles, exactly.
  5. Calendar files and links as specified.
  6. The rest of the app as PRODUCT.md describes (screens, flows, sick mode, documents); styling is the builder's.

Who resolves gaps

spikinglabs, as the namespace holder. If the pack doesn't settle something, record the question and the reading you chose in NOTES.md next to your build; obligations marked open in obligations.toml are yours to choose.

Product

aura: the product

A build of Aura is one installable web page (a PWA) for phones. The ten components in this pack are its pure core (merge, migrate, save guard, percentiles, schedules, reminders, backup retention, media packing, AI redaction, calendar files); everything below wraps them. Where this file and a component disagree, the component wins.

Shape

  • A static, client-side web app: one HTML page with its script and styles, a web app manifest, a service worker for offline use, an icon and a privacy page. No server of the publisher's own, no build-time backend. The only network use: Google (sign-in with Google Identity Services, Drive API v3 with the drive.file scope, the Google Picker for joining a shared log), the AI service the parent configures, one public recall list, and loading the app itself.
  • Opens at 375 px width without sideways scrolling; works offline once loaded; installable to the home screen (manifest with a shortcut "Emergency card" -> ?open=card). Deep links: ?open=card, ?open=appts.
  • The log is one JSON document held in the browser's IndexedDB (database aura, store kv, key state); localStorage (aura.v2, and the older sickdaylog.v1) is only read to move older data over. The app asks the browser to keep storage permanently. Saves replace the one record in a single transaction (save-guard rules).
  • Look: "Night light": warm dark colours at night (from 19:00 to 7:00 by default, or as set), warm cream by day; colour tokens defined once. Calm, few words. Text is English; the doctor summary and the emergency card also come in German (a language setting; AI translation of free text is optional).
  • Google client ID and Picker key are built in at build time from two environment variables (public by design; users can enter their own under More -> Google Drive -> Advanced). Without them Drive features ask for them.
  • Secrets: the AI key and tokens stay on the phone and are never synced or backed up into the log's synced part.

Surfaces

Four tabs at the bottom: Today, Growth, Documents, More. A round "Say it" button floats on Today, the sick view and Growth.

  • Today: greeting and child picker (several children), the emergency-card button beside the child; banners (example data, backup due, recall matches); lines for due vaccinations, due checkups, due dental checkups and appointments in the next two weeks (schedule component); quick buttons and summary cards for what is tracked; the day's timeline; running timers (breastfeeding, sleep); a switch to the sick view while an illness is open.
  • Sick view (sick mode, per child and illness): Overview (last temperature, fluids and wet diapers over 24 h, illness day, last doses with "gap passed", reminders from the reminders component, quick buttons for temperature, medicine, symptoms, sounds), Chart (fever chart), For the doctor (day-by-day summary, doses, vaccinations in the two weeks before, emergency-card facts, photos and sound clips, in English or German; text to copy/share; an AI "handover" optionally). Ending an illness ("is better: end sick mode") and reopening it.
  • Add/edit entry sheet: one sheet per entry type: feed (breast with side and timer, bottle or cup with amount), sleep (timer, woke up at, quality), diaper (wet, poop, both, dry; stool look), solids, temperature (°C or °F setting; stored in °C), medicine (name from the medicine list, amount, unit), symptoms (free text with preset tags such as Fever, Cough), vomit, doctor's notes (free text fields: thinks, advice, medicine, come back if), photo, sound (up to 30 s with microphone, or a pasted link to a video), note. Free-text boxes have dictation. Entries remember who logged them ("by", set under Share with a partner).
  • Tracking per child: which trackers are on, with separate lists for everyday and for sick mode (defaults by age: feed under 30 months, diapers under 42, solids from 5 months). Changing one list never changes the other. Anything tied to a tracker (quick button, summary card, timeline rows, doctor table column) hides when off.
  • Say it: type or dictate free text; with AI on, it is sorted into entries the parent reviews and adds; without AI the text is saved as a note.
  • Growth: weight, height and head measurements with the WHO percentile curves (3, 15, 50, 85, 97) and the child's line (growth-percentile component; needs sex and birth date), a tooth map (types, jaw order, dates), milestones, and a link to the dental checkups.
  • Documents tab: the emergency card; Appointments; Vaccinations; Checkups (U-Heft); Dental checkups; a Kita card (contract, measles proof, doctor's note, other; with the measles doses already recorded, facts only); other documents. Documents are digital twins of paper documents: one item per page in the paper's order (add via camera or photo library, replace in place, move, delete), a note, and a PDF (made on the phone without a library; JPEG pages go in as they are).
  • Emergency card: one record per child: allergies, conditions, regular medicines, blood group, pediatrician, insurance, contacts; opens from the card button on every main screen, from the child's sheet and the home-screen shortcut; allergies, conditions and medicines also go into the doctor summary and AI handover; contacts and insurance never go into a prompt.
  • Vaccinations: the schedule rows with status (schedule component), doses as written in the book (date, vaccines it was against, batch/doctor notes), "not planned", appointments, add to calendar; its pages are a document. Checkups: U1 to U10/J1 rows and visits (date, who, note); pages are a document. Dental checkups: Z1 to Z6 and other visits (fluoride, teeth seen added to the tooth map); pages are the dental pass document. Reading a document's pages with AI (when switched on, asked once) produces only a review list; nothing is saved until the parent checks it. The U-Heft reader routes Z entries to dental.
  • Appointments (one per checkup or dental checkup; one vaccination appointment can cover several vaccines; any other appointment has a title and an optional linked document): date, optional time, place, note; once the day has passed the app asks to record the visit; saving a coming appointment offers the calendar (Google link, .ics file, or sharing the file) from the ics component.
  • More: Children (add, edit, delete, sex, birth date, tracker lists); Illnesses; Look (theme auto/day/night, unit °C/°F); Medicines (name and minimum gap in hours; starting list Paracetamol (acetaminophen) 4 h and Ibuprofen 6 h); Google Drive backup and sync (connect, sync now, restore from a Drive backup, join a shared log, advanced client ID); Share with a partner (their Google email; who has access; remove); AI helper (service, address, model, key; "Read new and replaced pages with AI"); Your data (storage used, save a backup file via the share sheet, restore from a backup file or a daily copy, export/import, wipe); product list and recall feed (countries tracked, "Seen"); document language.
  • Files: Aura/aura-log.json in the parent's Drive; Aura/backups/aura-backup-<hour>.json, aura-log-before-vN.json, backups/media/<sha256>.<ext>; Aura/documents/<name>.pdf (one PDF per document with pages, remade only when changed, a deleted document's PDF moved to the Drive trash); backup files saved by the parent; .ics files.

Flows

  1. First use: open the page; example data shows with a banner "Start with my child"; add the child (name, birth date, sex); the app then asks for a backup (Google Drive or a file). Uses save-guard on every save.
  2. Log a day: tap a quick button, fill the sheet or start a timer; the entry appears in the timeline and summary; the log saves (save-guard) and syncs about 2 seconds later if connected.
  3. Sick mode: turn it on for a child; temperature, medicine and symptoms come first; each temperature or medicine entry updates the reminders and "gap passed" pills (reminders component); "For the doctor" builds the summary (and optionally an AI handover through ai-redaction); end sick mode when better.
  4. Connect Drive: More -> Google Drive -> Connect: sign in, find or create Aura/aura-log.json; first sync writes the phone's log. Each later sync: read, merge (merge), write, check the version, repeat up to three times; before writing, a backup copy is saved (backup-retention, media-pack for photos/sounds); the PDFs of documents are kept in documents. Older logs on Drive are upgraded (migrate) after a before-vN copy.
  5. Share with a partner: owner shares the one file by Google email; partner uses Join a shared log (Picker); both phones merge item by item; entries show who logged them; the partner's backups go to their own Drive.
  6. Restore: from a Drive backup (media references fetched back with media-pack), a daily copy on the phone, or a backup file: the chosen copy is merged in (merge), never replacing, and never deleting.
  7. Vaccinations, checkups, dental: open the screen from Documents; rows show status and "usually" times from the schedule component; tap a row to record the visit/dose, add an appointment, or add to calendar (ics); Today points out what is due. Birth date is needed for statuses.
  8. Documents: add pages by photo; reorder, replace, delete; save as PDF; with page reading on, new or replaced pages of the vaccination book/U-Heft/dental pass go (images) to the parent's own AI service (ai-redaction rules), and the answer is a review list.
  9. Growth: add a measurement; the curves and percentile text come from growth-percentile; tooth map and milestones are free of schedules.
  10. Recalls: on opening, at most every 12 h, fetch the public recall list; match against the family's product list on the phone (reminders component); a banner with "Details" and "Seen" for matches; "new product recalls" line for the last 30 days.
  11. Upgrade: opening an older log or a newer app version: migrate runs once and keeps before-vN; an older app that meets a newer log stops and asks to be updated, changing nothing.

Interfaces

  • Google Identity Services token flow (drive.file), Drive API v3 (files list/get/create/update/delete, multipart and resumable upload), Google Picker (needs the API key).
  • AI: Anthropic Messages API (default model claude-opus-5-5 in the original) or any OpenAI-style chat API (address, model, key set by the parent; https or http://localhost only), or the on-device sampling API of the host when the page runs inside one; images only to the parent's own service.
  • Recall Tracker: GET a public JSON list (array of {id, title, company, country_sold_in, publish_datetime, scraped_datetime, url, reason (text or {en: ...}), source}); at most every 12 h.
  • Browser: IndexedDB, Web Share API for files, MediaRecorder for sounds, SpeechRecognition (optional), camera/file inputs, service worker.

Order

  1. The ten components and the log: storage, save guard, migration, merge.
  2. Today, entry sheets, timers, the example data, tracking lists.
  3. Drive sync with backups and media; backup file save/restore.
  4. Sick mode and the doctor summary; reminders.
  5. Growth with percentiles; schedules, appointments and calendar files; documents and PDFs; emergency card.
  6. AI features, partner sharing, recalls, Kita, German doctor summary.
Files

Everything in the pack

/ 5
assumptions 10
components/ai-redaction/versions/1 4
components/ai-redaction/versions/1/schema 2
components/backup-retention/versions/1 4
components/backup-retention/versions/1/schema 2
components/growth-percentile/versions/1 4
components/growth-percentile/versions/1/fixtures 1
components/growth-percentile/versions/1/schema 2
components/ics/versions/1 4
components/ics/versions/1/schema 2
components/media-pack/versions/1 4
components/media-pack/versions/1/schema 2
components/merge/versions/1 4
components/merge/versions/1/schema 2
components/migrate/versions/1 4
components/migrate/versions/1/schema 2
components/reminders/versions/1 4
components/reminders/versions/1/schema 2
components/save-guard/versions/1 4
components/save-guard/versions/1/schema 2
components/schedule/versions/1 4
components/schedule/versions/1/schema 2