Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@ build/
.env
.secrets

local_build/
local_build/

# Next.js (web/)
web/.next/
web/node_modules/
web/.env*.local
web/out/
58 changes: 58 additions & 0 deletions web/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# TrackWeight Web

A Next.js website version of TrackWeight — includes a marketing landing page and an interactive browser-based scale that uses the [`PointerEvent.pressure`](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pressure) API to read Force Touch pressure from a MacBook trackpad.

## Pages

| Route | Description |
|-------|-------------|
| `/` | Landing page — hero, how it works, tech stack, download links |
| `/scale` | Interactive scale app with full weighing state machine |

## Getting Started

```bash
cd web
npm install
npm run dev
```

Open [http://localhost:3000](http://localhost:3000).

## Browser Compatibility

| Browser | Pressure Support |
|---------|-----------------|
| Safari (macOS) | ✅ Full Force Touch via `webkitmouseforcechanged` + `PointerEvent.pressure` |
| Chrome (macOS) | ⚠️ Limited — trackpad pressure not reliably exposed |
| Firefox | ❌ No Force Touch support |

For the best experience, use **Safari on macOS** with a MacBook that has a Force Touch trackpad.

## How the Scale Works

The web version mirrors the native app's state machine:

```
welcome → waitingForFinger → waitingForItem → weighing → result
```

1. **waitingForFinger** — listens for sustained pointer pressure for 3 s to set a zero baseline
2. **waitingForItem** — detects a rate-of-change spike (object placed on trackpad)
3. **weighing** — applies a 10-sample moving average; locks result when weight is stable (±5 g) for 3 s
4. **result** — displays the final weight in grams

Pressure values (0–1) are multiplied by a user-adjustable **calibration factor** (default 500 g). Use the Settings panel to tune this for your specific MacBook model.

## Tech Stack

- **Next.js 14** (App Router)
- **TailwindCSS**
- **Lucide React** icons
- **PointerEvent API** + **WebKit Force Touch events**

## Limitations

- Requires a MacBook with a **Force Touch trackpad** (2015 MacBook Pro or newer)
- The native macOS app is significantly more accurate — it uses Apple's private `MultitouchSupport` framework which returns pressure values already calibrated in grams
- The web version is an approximation and requires manual calibration
47 changes: 47 additions & 0 deletions web/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
--background: #ffffff;
--foreground: #0a0a0a;
}

* {
box-sizing: border-box;
}

body {
background: var(--background);
color: var(--foreground);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
-webkit-font-smoothing: antialiased;
}

@keyframes float {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-10px); }
}

@keyframes glow {
0%, 100% { box-shadow: 0 0 8px rgba(20, 184, 166, 0.4); }
50% { box-shadow: 0 0 20px rgba(20, 184, 166, 0.8); }
}

@keyframes ring-fill {
from { stroke-dashoffset: 283; }
to { stroke-dashoffset: 0; }
}

.scale-float {
animation: float 3s ease-in-out infinite;
}

.display-glow {
animation: glow 2s ease-in-out infinite;
}

.no-select {
user-select: none;
-webkit-user-select: none;
}
27 changes: 27 additions & 0 deletions web/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { Metadata } from "next";
import "./globals.css";

export const metadata: Metadata = {
title: "TrackWeight – MacBook Trackpad Scale",
description:
"Turn your MacBook's Force Touch trackpad into a precision digital scale. Weighs objects with gram-level accuracy using Apple's multitouch pressure sensors.",
openGraph: {
title: "TrackWeight",
description: "Turn your MacBook trackpad into a digital scale",
type: "website",
},
};

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className="min-h-screen bg-white text-gray-900 antialiased">
{children}
</body>
</html>
);
}
Loading