Public
Remixed
Pill tracking with nfc
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.

πŸ’§ Water Intake Tracker

A modern web app to track your daily water intake with a 2L daily goal. Features manual logging, NFC device registration for quick taps, and automatic daily reset at 5 AM UTC.

Features

  • βœ… Daily Goal Tracking - Visual progress bar towards 2L daily target
  • πŸ“± Quick Add Buttons - Log common amounts (250ml, 500ml, 750ml, 1L) with one tap
  • 🎯 Custom Amount - Add any custom amount you drank
  • 🏷️ Water Log History - View all today's entries with timestamps
  • πŸ“΄ NFC Integration - Register NFC devices/tags that auto-log water on tap
  • πŸ”„ Daily Reset - Automatic reset at 5 AM UTC each day
  • πŸ” Authentication - Magic link sign-in via Better Auth
  • πŸ“Š Stats - Track your water intake over time

Architecture

β”œβ”€β”€ config/
β”‚   └── constants.ts          # All configuration constants in one place
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ schema.ts             # SQLite schema with water & NFC tables
β”‚   β”œβ”€β”€ water-utils.ts        # Utility functions for water tracking
β”‚   └── auth.ts               # Better Auth configuration
β”œβ”€β”€ frontend/
β”‚   β”œβ”€β”€ index.html            # Main HTML template
β”‚   └── index.tsx             # React app with tab-based UI
└── index.ts                  # Hono API server with all endpoints

Configuration

All constants are defined in config/constants.ts:

export const WATER_CONFIG = { DAILY_TARGET_ML: 2000, // Change daily goal here (in ml) RESET_HOUR_UTC: 5, // Change reset time here (UTC) QUICK_ADD_AMOUNTS: [250, 500, 750, 1000], MIN_ML_PER_TAP: 100, // Minimum per NFC tap MAX_ML_PER_TAP: 1000, // Maximum per NFC tap DEFAULT_ML_PER_TAP: 500, // Default amount for new NFC devices };

API Endpoints

Water Tracking

  • POST /api/water/log - Log water intake

    { "milliliters": 500, "source": "manual" }
  • GET /api/water/today - Get today's intake and logs

  • GET /api/water/history?days=7 - Get intake history

  • DELETE /api/water/:id - Delete a log entry

NFC Devices

  • POST /api/nfc/register - Start NFC device registration (returns registration URL)
  • POST /api/nfc/device - Complete NFC device registration
  • GET /api/nfc/devices - Get user's registered NFC devices
  • PATCH /api/nfc/device/:id - Update device settings
  • DELETE /api/nfc/device/:id - Delete a device
  • GET /api/nfc/tap/:token - NFC tap endpoint (logs water automatically)

How NFC Works

  1. Register Device

    • Click "Start Registration" in NFC Devices tab
    • A QR code is generated with a registration URL
    • Share/scan the QR with your NFC device/app
  2. Complete Registration

    • When the device scans the link, you specify the water amount (default 500ml)
    • Device is saved and ready to use
  3. Log Water

    • Each tap of the registered NFC device logs water automatically
    • Shows success page with logged amount

Database Schema

water_logs

  • id - Auto-increment primary key
  • userId - User who logged the water
  • timestamp - When water was logged
  • milliliters - Amount of water (in ml)
  • source - "manual" or "nfc"
  • createdAt - Record creation time

nfc_devices

  • id - Device UUID
  • userId - Owner of the device
  • token - Unique tap token
  • milliliters - Amount logged per tap
  • name - Device name
  • createdAt - When registered
  • updatedAt - Last update time

nfc_tokens

  • token - Registration token (UUID)
  • userId - User registering the device
  • createdAt - Token creation time

Daily Reset

The app automatically treats the day as starting at 5 AM UTC and ending at the next 5 AM UTC. This is calculated server-side in getTodayStartTime() so it works regardless of user timezone.

To change the reset time, edit RESET_HOUR_UTC in config/constants.ts.

Usage

  1. Sign in with magic link
  2. Click quick-add buttons or enter custom amount
  3. Watch your progress bar fill up
  4. Optionally register NFC devices for one-tap logging
  5. Check history anytime

Tech Stack

  • Backend: Hono (TypeScript)
  • Database: SQLite with Val Town blob storage
  • Frontend: React with Twind CSS
  • Auth: Better Auth with magic links
  • Runtime: Deno on Val Town