GlassKit

The 6 SDK + AI showcase demos

SDK + AI integration showcases. Each demo wires one sensor primitive to one AI call so you have a working starting point, not a finished product.

These are showcases, not finished products

The Vite glasses app ships as a launcher with six SDK + AI integration showcases behind it. They exist to demonstrate how each platform primitive (GPS, motion, orientation, Neural Band) composes with an AI call inside the 600×600 + D-pad constraints. Clone the repo, run it, walk through every combo on real hardware (or in the browser with DevTools sensors), and fork the one whose primitives fit your product. None are meant to ship as-is.

All six live in app/src/apps/. The launcher that opens them is app/src/App.tsx. Each demo is ~80–115 lines of single-file React.

The 6 demos at a glance

DemoSensorsAI prompt shapeColor
AI WayfinderGPS, Orientation"Walking direction to nearest landmark, given lat/lon + heading"Cyan
AI Tour GuideGPS, Orientation"One fascinating fact about this spot, facing this direction"Violet
AI Running CoachMotion (accelerometer), Timer"Form cue for runner at $effort after $elapsed"Orange
AI Sous-ChefNeural Band (pinch)"Elaborate on current recipe step: substitution, technique, timing"Coral
AI Presentation CoachNeural Band (pinch), Timer"Critique pacing: $words in $seconds = $wpm wpm"Amber
AI Trail CompanionGPS, Motion"Safety / pacing note for hiker at lat/lon, effort $level"Forest green

Each demo:

  • Owns its own color palette + iconography (you'll keep this for your fork)
  • Wires useAi() from app/src/lib/useAi.ts to call api.ai.complete
  • Renders an <AiResponse> for the result + loading + error state
  • Accepts a single onExit prop the launcher uses to navigate back

Pick the right starting point

Match by interaction model, not by sensor list. If two demos look right, fork the simpler one; it's faster to add a second sensor to Tour Guide than to remove an unused gesture hook from Sous-Chef.

Voice-and-place product

Show me X about here. Fork Tour Guide (GPS + orientation + a one-line AI lookup).

Turn-by-turn product

Guide me along a route, where to next. Fork Wayfinder (GPS heading + AI navigation cue).

Effort / training product

Coach my workout, my session, my long run. Fork Running Coach (motion + timer + AI feedback).

Step-through product

Walk me through a recipe, manual, procedure. Fork Sous-Chef (Neural Band pinch advances state + AI elaboration).

Performance product

Script a talk, a pitch, a script delivery, with hands-free advance. Fork Presentation Coach (pinch + timer + AI critique).

Hike-tier outdoors product

Outdoor activity with safety + location awareness. Fork Trail Companion (GPS + motion + AI brief).

File map

App.tsx
Wayfinder.tsx
TourGuide.tsx
RunningCoach.tsx
SousChef.tsx
PresentationCoach.tsx
TrailCompanion.tsx
PairingGate.tsx

Every demo has the same shape:

A typical demo
export function MyDemo({ onExit }: { onExit: () => void }) {
  const { position } = useGeolocation();   // or useDeviceMotion / useNeuralBand
  const ai = useAi();

  function askAi() {
    ai.ask("prompt with ${sensor values}", {
      system: "You are a ...",
      maxTokens: 80,
    });
  }

  return (
    <div className="screen" style={{ gap: 14 }}>
      <div className="app-head">…label + status…</div>
sensor readout
      <AiResponse ai={ai} placeholder="..." />
      <div className="row">
        <button className="focusable" onClick={askAi}>Action</button>
        <button className="focusable" onClick={onExit}>← Back</button>
      </div>
    </div>
  );
}

Once you've internalized that shape, swapping a demo for your own is mechanical.

The fork workflow

Goal: turn Wayfinder.tsx into MyApp.tsx (or whatever your demo is called). Five steps.

Copy the demo

cp app/src/apps/Wayfinder.tsx app/src/apps/MyApp.tsx

Rename the export

app/src/apps/MyApp.tsx
export function MyApp({ onExit }: { onExit: () => void }) { … }

Replace the launcher entry

In app/src/App.tsx, the APPS const is the source of truth for which demos appear in the launcher. Edit it:

app/src/App.tsx
import { MyApp } from "./apps/MyApp";

const APPS = {
  myApp: {
    label: "My App",
    tagline: "GPS · AI",
    Component: MyApp,
  },
  // …keep the demos you still want, drop the ones you don't…
} as const;

APPS is the only place the launcher knows about. Add, remove, or reorder freely.

Swap the prompt + the system instruction

The AI call is the only product-specific bit. Edit the call inside your demo:

function askAi() {
  if (!position) return;
  ai.ask(
    `I'm at ${position.lat}, ${position.lon}. Tell me X about Y.`,
    {
      system: "You are a {your-product-role}. {Your tone rules}.",
      maxTokens: 90,
    },
  );
}

Keep prompts terse; under ~200 tokens of output looks best on the 600×600 surface. The AiResponse component handles loading and error states; you don't need to do anything else.

Brand the colors + iconography

Each demo has a single color constant at the top:

const CYAN = "#5ad8ff";        // Wayfinder
const VIOLET = "#b48cff";      // Tour Guide
const ORANGE = "#ff9b52";      // Running Coach

Rename to your product, pick a hex that contrasts well against the black-on-additive-display background. The platform's additive display means dark pixels are invisible; design for a glowing mark on black. See Theming for the full palette story.

Replace the inline SVG with your icon. The pattern is:

<svg viewBox="0 0 64 64" width="86" height="86"
     style={{ color: YOUR_HEX, filter: `drop-shadow(0 0 16px ${YOUR_HEX})` }}>
  <path d="…" stroke="currentColor" />
</svg>

The drop-shadow with the same color is what gives the icon its emitted-light look on real glasses.

Removing a demo entirely

Delete the file in app/src/apps/ and remove its entry from APPS in app/src/App.tsx. TypeScript will flag any stale import. No other touchpoints; the launcher renders from APPS keys alone.

Adding a NEW demo type

If none of the six fit, start from the simplest (Tour Guide) and add the sensors you need. The available sensor hooks are in glasses-ui:

  • useGeolocation(){ position, error }
  • useDeviceOrientation(){ alpha, beta, gamma, error }
  • useDeviceMotion(){ x, y, z, error }
  • useNeuralBand()"pinch" | "fist" | "swipe" | null

D-pad navigation is automatic: anything with className="focusable" participates. useDpad() is wired once in App.tsx's root so buttons inside your demo "just work."

Testing demos locally

See Quickstart §5. TL;DR: open localhost:5173 in the same browser you signed into the companion with, use arrow keys for the D-pad, use Chrome DevTools' Sensors panel to override GPS / motion / orientation.

For real-glasses testing, tunnel localhost:5173 with cloudflared tunnel --url http://localhost:5173 and paste the returned HTTPS URL into the Meta AI app's "Add Web App" flow. The Clerk session shared with the companion (via Convex) propagates automatically.

On this page