Charts, symptom patterns and health tips for every phase. Encrypted on your phone. Free for Android and the web.
HealthHTML · JavaScriptGitHub @jclissoldyasa-boopOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Private period & cycle tracker: end-to-end encrypted, charts, symptom patterns, phase-based health tips. Web + Android.
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Private period and cycle tracker focused on cycle tracking and health optimisation (not pregnancy).
Web app + Android app, one account, data synced between devices and end-to-end encrypted.
Live: https://shark-week.shark-week-server.workers.dev — landing page at /, the app at /app,
Android APK at /download/SharkWeek.apk (also attached to every GitHub release).Read the full README ↗Private period and cycle tracker focused on cycle tracking and health optimisation (not pregnancy). Web app + Android app, one account, data synced between devices and end-to-end encrypted.
Live: https://shark-week.shark-week-server.workers.dev — landing page at /, the app at /app,
Android APK at /download/SharkWeek.apk (also attached to every GitHub release).
app.html — the whole app (single page, no external scripts or fonts), served at /applanding.html — the promo page at / (no scripts); screenshots in web/img/legal/ — Privacy Policy and Terms (filled in from site.json)server/ — Cloudflare Worker + D1 database (accounts, encrypted sync, security headers)android/ — WebView shell (reminders, privacy screen, file export); ./build.sh → SharkWeek.apksite.json — app name, public host, operator name, contact email, stateToday ring (cycle day, phase, next period, fertile window), quick "period started/ended", daily log (flow, 20 symptoms, pain 0–10, mood, energy, stress, sleep, BBT, cervical mucus, ovulation tests, sex drive, exercise, water/alcohol/caffeine, meds, notes), calendar with predictions and an "edit period days" mode, Insights (cycle & period length charts, symptom-by-cycle-day heatmap, energy/sleep/stress/pain by cycle day, BBT chart with three-over-six ovulation detection, plain-English pattern notes), phase-based health tips, "worth a chat with your GP" flags (healthdirect/Jean Hailes thresholds), printable doctor summary, JSON/CSV export, account deletion, devices list, Android reminders (optionally discreet).
Sleep report (Android): with Usage access, Sleep.java reads only screen on/off events (no app names)
and takes each morning's longest screen-off stretch between 6 pm and 2 pm (short checks under 6 min count as
"woke in the night"). The result goes into that day's encrypted log (sleepAuto) and fills in hours slept
unless typed manually. Today shows last night, a 7-night chart, bedtime consistency and sleep by cycle phase.
Partner heads-up (opt-in): /partner#ID.KEY shows a playful forecast (status level, countdown, likely
symptoms with "how to help", survival kit, golden rules). The owner's device encrypts it with KEY, which exists
only in the link; the server stores ciphertext (partner_shares). A nudge (in-app card + Android notification)
before days out sends a pre-written message via the share sheet. Turning it off deletes the forecast.
Password resets: (1) recovery code, keeps data; (2) a signed-in device resets it (Me → Forgot your password?), keeps data, and must prove it holds the data key, so a stolen session token isn't enough; (3) email link (needs a sending domain + Workers Paid; see below) starts the account fresh, since old logs can't be decrypted.
Add a domain to Cloudflare, onboard it in Email Service, upgrade to Workers Paid, then in wrangler.jsonc add
"send_email": [{ "name": "EMAIL" }] and "vars": { "EMAIL_FROM": "reset@yourdomain" } and deploy. The app shows
the email option automatically once /api/config reports emailReset: true.
./release.sh "What changed" builds a new APK (version code = minutes since 1970), deploys the site/API,
publishes the APK and /version.json, pushes to GitHub and creates a release.
/version.json on start, on resume (every 6 h) and from Me → Check for updates.
A newer version code shows an Update banner that downloads the APK; Android installs it over the old one
(same signing key).UpdateCheck runs once a day (≈10:30) and posts one notification per new version;
tapping it downloads the APK. Android always asks before installing (sideloaded apps can't update silently)./version.json shows Reload./qr.svg (built from site.json host).PBKDF2-SHA256(password, salt, 600k) → HKDF → login key (sent) and wrap key (never sent).day:YYYY-MM-DD, so the server can't see which dates exist.HMAC(AUTH_PEPPER, login key). Lose password and recovery code = data unrecoverable (by design).D1 is SQLite, which has no built-in RLS, so it is enforced in one place: rowsFor(env, userId) in
server/src/worker.js is the only code that touches a user's rows, and the user id comes from the verified
session. test/rls.test.mjs (also run before every deploy) fails if any SQL on users/docs/sessions isn't
pinned to a user; test/api.test.mjs attacks cross-account reads/writes against a running server.
On top of that, the data is ciphertext, so even a bypass would leak nothing readable.
TERMS_VERSION changes.--location oc (Oceania). Cloudflare is disclosed as an overseas recipient (APP 8).cd server && npm install
echo "AUTH_PEPPER=$(node -e 'console.log(require("crypto").randomBytes(32).toString("base64url"))')" > .dev.vars
npm run dev # http://127.0.0.1:8787
node test/api.test.mjs # in another terminal
The Cloudflare login for this project lives in server/.cf-home (gitignored), separate from any other
wrangler login on the machine. To log in again: cd server && XDG_CONFIG_HOME=$PWD/.cf-home npx wrangler login.
cd server
npx wrangler d1 create shark-week --location oc # put the database_id into wrangler.jsonc
node -e 'console.log(require("crypto").randomBytes(32).toString("base64url"))' | npx wrangler secret put AUTH_PEPPER
npm run deploy # builds, RLS check, migrations, deploy
Then set host in site.json to the deployed address, npm run deploy again, and cd ../android && ./build.sh.
Never change or lose AUTH_PEPPER (everyone would be locked out) or android/sharkweek.keystore.