Skip to content

Repository files navigation

Off the Clock app icon

Off the Clock

Find out what your boss owes you.

An Android app for working teenagers in Washington State. Log the shifts you already worked,
by hand or from a photo of the posted schedule, and see which ones broke the law,
which statute they broke, and what the unpaid time is worth in dollars.


Android Expo SDK 57 TypeScript RevenueCat Tests License MIT



Opening of the demo video: the app name, then $92.38 owed across 12 shifts

▶  Watch the full demo on YouTube (1:46)


Home screen showing $138.57 owed across 18 shifts  A missed rest break opened to the statute it broke  Adding a shift with the breaks actually given  Scanning a posted schedule

What you are owed  ·  the rule behind each problem  ·  logging a shift  ·  scanning a posted schedule



Why it exists

Washington limits how much a 16 or 17 year old can work during a school week.

The ruleWhere it is written
At most 20 hours in a school weekWAC 296-125-101(2)(a)
At most 4 hours on a school day before another school dayWAC 296-125-101(2)(a)
Nothing before 7am, nothing after 10pm before a school dayWAC 296-125-101(2)(a)
A paid 10 minute rest break, never more than 3 hours without oneWAC 296-125-121(2)
A 30 minute meal break, never more than 5 hours without oneWAC 296-125-121(1)

Almost no teenager knows these rules exist, and almost none would push back if they did,
because the person breaking the rule is the person who writes the schedule.
Off the Clock closes that gap with one number: what your employer owes you.


How it works

1  Log 2  Check 3  Total
Type a shift in, or photograph the schedule your manager posted. Text recognition runs on the phone, the photo never leaves it, and nothing is saved until you confirm it. A schedule never shows the breaks you were actually given, so those stay yours to fill in. That gap is usually where the money is. Every shift runs through a rules engine built from chapter 296-125 WAC as amended by WSR 26-11-048, effective July 1 2026, plus WAC 296-126-092 and RCW 49.46.130. Each problem quotes the statute it broke and links the published text. Missed rest breaks, docked time, pay under the wage floor and unpaid overtime are summed in integer cents and shown as a single figure, with every problem listed underneath it.

Monetization with RevenueCat

Finding out is free. Proving it costs $4.99, and a parent pays.

Logging shifts and finding violations is free and always will be. Charging a teenager to discover
they are being underpaid would be a toll on the person with the least money in the arrangement.
What costs money is the evidence record: a dated PDF listing every shift, every rule broken,
and the full statute behind each one, in the form you hand to someone else.


The locked record, a Web Purchase Link opened on a parent's phone, a sandbox payment, and the record unlocking on the teen's phone

The parent rail · Web Purchase Link The in-app rail · RevenueCat SDK
The app mints its own customer ID and hands the same string to the SDK and to a RevenueCat Web Purchase Link. The teenager sends the link over whatever they already use to talk to their parent. The parent pays in a browser, on their own phone, through RevenueCat Web Billing on Stripe, and the record opens on the teenager's phone. Nobody creates an account and no card touches the teenager's device. An ordinary one-time purchase of the first package in the current offering, for anyone who would rather just buy it. When the teenager taps A parent already paid, the app invalidates the SDK's cached customer before asking again, so a web payment unlocks on the first tap instead of the second.

Both rails grant the same entitlement, evidence_export, and the app checks nothing else.

src/entitlement.tsThe entitlement ID, the customer ID, and the Web Purchase Link, with no native imports so it runs under test
src/purchases.tsxSDK setup, offerings, the purchase, and the refresh after a parent pays
app/export.tsxThe locked record, both ways to unlock it, and saving it as a PDF

Purchases in this build run on the RevenueCat Test Store and Stripe test mode. No real money moves. See the sandbox terms.



Built with

AppExpo SDK 57 · React Native 0.86 on the New Architecture · TypeScript · expo-router
InterfaceReact Native Paper (Material 3), light and dark themes
MonetizationRevenueCat react-native-purchases · Test Store · Web Billing on Stripe
Schedule scanML Kit text recognition on the device via expo-mlkit-ocr
Evidence recordexpo-print for the PDF · expo-sharing to send it
StorageAsyncStorage on the device. No account, no server, no upload.

Tested where it counts

The money and time math is what makes this app worth anything, so it is the part that is tested.
Fifty five tests run under plain node --test with no framework.

evaluate.test.tsDaily and weekly hour caps, night cutoffs, break math for each age band, the wage floor, the overtime premium
schedule.test.tsRegrouping OCR blocks into schedule rows, real schedule time formats, and the readings that have to be refused
record.test.tsThe printed record, including the escaping that keeps an employer name out of the markup
palette.test.tsEvery text color in both themes clears WCAG AA against the surface it sits on
entitlement.test.tsThe entitlement check, the customer ID, and the parent link

Run it yourself

Requires Node and the Expo tooling. Android only.

npm install
npm test
npx expo run:android

The app builds and runs with no keys at all. Logging and violation detection work, and the record screen says purchases are switched off. To turn purchases on, copy .env.example to .env and fill in both values:

  1. Create a RevenueCat project.
  2. Under Apps and providers, add a Test Store. It needs no Play Store account and no developer account. Copy its key into EXPO_PUBLIC_REVENUECAT_KEY.
  3. In the Product Catalog, create an entitlement with the identifier evidence_export. The app reads that exact string from src/entitlement.ts and unlocks on nothing else.
  4. Create a product for the record, attach it to that entitlement, and put it in an offering marked current. The app buys the first package in the current offering.
  5. Add a Web Purchase Link for the same offering. Copy the token out of the sandbox URL into EXPO_PUBLIC_REVENUECAT_WEB_TOKEN, without any customer ID, because the app appends its own. Web Billing runs on Stripe, so connect a Stripe account in sandbox mode and pay with a Stripe test card.

A build carrying a Test Store key has to be a debug build. The SDK refuses to run a release build with a Test Store key.

The icon is drawn rather than stored. tools/icon.mjs writes the mark as SVG and every size is rendered from that one source:

node tools/icon.mjs full       | rsvg-convert -w 1024 -h 1024 -o assets/icon.png
node tools/icon.mjs foreground | rsvg-convert -w 512  -h 512  -o assets/android-icon-foreground.png
node tools/icon.mjs mono       | rsvg-convert -w 512  -h 512  -o assets/android-icon-monochrome.png

Off the Clock does not give legal advice and does not file anything on your behalf. It shows you the regulation and your own record.
What you do with that is your decision, and it is worth talking to an adult you trust or to Washington State Labor & Industries.



MIT License · see LICENSE

Releases

Packages

Contributors

Languages