Skip to content

About

An open, portable haptic format + registry, built for AI agents. North star: hardware-free haptic braille.

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

haptics.md

An open, portable format for haptics — and the first built for AI agents.

License Patterns Spec PRs npm

Almost nobody ships haptics on the web, and barely anyone in apps — the APIs are fragmented, the good ones are buried in native code, and the feel is hard to author and impossible to port. Meanwhile AI agents scaffold entire UIs all day and never add a single line of touch feedback, because there is nothing for them to reach for.

haptics.md is an open, portable haptic format + registry. One human-readable descriptor — a .hap.md file — compiles to the best available feedback on iOS, Android, and the web, degrades honestly when the hardware can't deliver, and is legible enough that an agent can author, place, and compile it without guessing.


Why this exists

haptics.md is a developer tool, but its reason to exist is accessibility. The north star is haptic braille — giving any phone with a vibration motor a standardized, hardware-free way to convey a braille cell, a digit, a wayfinding cue, or a silent confirmation, and documenting how developers implement it consistently so every app stops inventing its own incompatible buzz.

Held honestly, because accessibility punishes hype:

  • Complement, never replacement. Blind and low-vision people already use phones fluently with screen readers and refreshable braille displays. This adds one hardware-free channel; it does not "enable" anyone.
  • Slow, by physics. One motor means roughly one braille cell per second — good for letters, digits, short codes, confirmations, and wayfinding cues, not for reading paragraphs. Any demo implying otherwise is wrong.
  • Web-limited. On the web it is Android-Chrome-only and a silent no-op on iPhone Safari and desktop. Rich braille needs a native app.
  • A draft proposal, not a shipped feature. Nothing here has been co-designed with blind braille readers yet. Per our governance, no default, timing, or claim is "recommended" until blind braille readers and the relevant braille authorities have shaped it — a careful, multi-year track (see the roadmap). We publish the starting point in the open precisely to invite that collaboration.

If you read braille, work in accessibility, or represent a braille authority or a blind-led organization, we want you shaping this — start with docs/haptic-braille.md and spec/braille.md.


Feel it

The fastest way to understand this is to feel it.

→ haptics.md — open on your phone.

Android (Chrome family) plays the duration-only web fallback — best-effort, no intensity or sharpness. The full track only renders in a native app. iPhone Safari shows an explicit "haptics unavailable" state — iOS Safari has no vibration API at all, and we will not fake it with a hacky buzz. All demo media leads on Android for the same reason.


Quickstart

npx haptics add pull-to-refresh --platform ios

This copies a pattern into your project — you own the file, edit it freely, there is no runtime dependency to install. The CLI vendors the registry into its own package, so add works offline and keeps working if the site is down. (It is not "no backend" — it is a snapshot shipped with the tool.)

Available platforms: ios, android, web, react-native, flutter.


What is a .hap.md

A .hap.md is a Markdown file with three parts: YAML frontmatter, human prose describing the feel, and exactly one fenced code block tagged haptic containing the JSON that is the compilable source of truth.

---
id: pull-to-refresh
title: Pull to refresh
spec: "0.1"
version: 1.0.0
category: gesture
intent: impact.light
requiredCapability: null
platforms: [ios, android, web:best-effort]
tags: [scroll, refresh, threshold]
feel: A light tick the instant the refresh threshold is crossed.
---

# Pull to refresh

Fires once, at the moment the user pulls past the refresh threshold — a
single light tick that says "released, we've got it." Not a confirmation
of success; that comes later, when the content actually lands.

```haptic
{
  "haptic": "0.1",
  "id": "pull-to-refresh",
  "intent": "impact.light",
  "track": [
    { "at": 0, "type": "transient", "intensity": 0.6, "sharpness": 0.7 }
  ],
  "fallbacks": {
    "web": [10],
    "reduced": "impact.light"
  }
}
```

The same descriptor compiles to:

iOS — UIFeedbackGenerator / iOS 17 .sensoryFeedback, resolving the intent to a native semantic primitive first (best feel):

.sensoryFeedback(.impact(weight: .light), trigger: didCrossThreshold)

Android — VibrationEffect.Composition primitives, with the VIBRATE manifest permission and an honest capability guard that falls back rather than lying:

// AndroidManifest.xml: <uses-permission android:name="android.permission.VIBRATE" />

val vib = vibratorManager.defaultVibrator // VibratorManager: API 31+
if (vib.areAllPrimitivesSupported(PRIMITIVE_LOW_TICK)) {
    vib.vibrate(
        VibrationEffect.startComposition()
            .addPrimitive(PRIMITIVE_LOW_TICK, 0.6f) // scale from track intensity
            .compose()
    )
} else {
    // No composition primitives (common on mid-range ERM devices):
    // drop to a duration-only effect. Never pretend amplitude worked.
    vib.vibrate(VibrationEffect.createOneShot(10, DEFAULT_AMPLITUDE))
}

Web — navigator.vibrate, duration-only and best-effort:

// web (Android Chrome), best-effort, duration-only.
// No intensity, no sharpness — a gesture-gated on/off buzz, and a
// no-op on iOS Safari and desktop. This is the crudest rung, by design.
navigator.vibrate?.([10]);

The degradation ladder

Every target resolves top-down, deterministically, and stops at the first rung it can deliver:

  1. intent — a native semantic primitive (best feel).
  2. track — the synthesized timeline of transient/continuous events.
  3. fallbacks.web — crude duration-only on/off milliseconds.
  4. silent no-op — a valid outcome.

A device with no actuator is a valid target that produces nothing. App logic must never gate on haptic success, and a runtime must never report that intensity or sharpness "worked" when it was flattened away.


Platform support (honest)

Platform Tier Note
iOS First-class UIFeedbackGenerator, iOS 17 .sensoryFeedback, Core Haptics + AHAP. Full intent + track.
Android First-class VibrationEffect + Composition primitives. VibratorManager is API 31+; amplitude control is API 26+ and many devices report hasAmplitudeControl() = false; mid-range ERM devices often fail areAllPrimitivesSupported(). Guard and fall back.
Web First-class, best-effort navigator.vibrate: Android Chrome family only, duration-only, gesture-gated, throttled. Does not exist on iOS Safari or desktop. Intensity and sharpness never survive to this target.
React Native Intent-tier only expo-haptics exposes semantic constants only. Custom track/sharpness needs a native module that has not shipped.
Flutter Intent-tier only HapticFeedback exposes semantic constants only. Same limitation as React Native.
Game controllers Rumble-only escape hatch Gamepad rumble is weak/strong motors, no waveform. An escape hatch, not a target for authored feel.

The full in-scope / out-of-scope matrix lives in SPEC.md.

The frozen Tier-0 intent vocabulary

These nine tokens are stable and safe to build on:

impact.light · impact.medium · impact.heavy · impact.soft · impact.rigid · notification.success · notification.warning · notification.error · selection

Everything else in the spec is haptic/0.1-draft and explicitly unstable. RFC-2119 MUST/SHOULD language applies only to this vocabulary and to the degradation contract above. Unknown future fields must be ignored, never treated as fatal.

Accessibility

Haptics are a feedback channel — including for deaf and hard-of-hearing users — delivered with consent. Runtimes respect the OS system-haptics setting (iOS: Settings > Accessibility > Touch > Vibration), not prefers-reduced-motion. Vibration and motion are different channels with different user intent behind them.


Built for AI agents

Agents generate most new UI and add no touch feedback — they build the screens and skip the feel. haptics.md gives them something to reach for.

Now:

  • Six authored Skills covering pattern selection, .hap.md authoring, compilation, capability-guarding, honest degradation, and haptic braille.
  • An llms.txt that describes the format, the frozen vocabulary, and the degradation contract in a form an agent can load directly.

Later:

  • A compiler-backed MCP server so an agent can author a .hap.md, compile it to a target, and verify the capability guards in one loop.

Contribute a pattern in 10 minutes

  1. Copy an existing .hap.md from the registry.
  2. Rewrite the frontmatter, the prose, and the one haptic JSON block for your interaction.
  3. Keep to the frozen intent vocabulary where you can; add a track for the feel; always include a fallbacks.web and a sane reduced intent.
  4. Open a PR with a DCO sign-off (git commit -s).

Patterns are built only from public, documented platform APIs. See CONTRIBUTING.md for the full checklist.


Links

  • ROADMAP.md — where this is going and what is frozen vs. provisional.
  • SPEC.md — the haptic/0.1-draft grammar, the intent vocabulary, and the scope matrix.
  • CONTRIBUTING.md — pattern checklist, DCO, and review bar.
  • docs/haptic-braille.md — the haptic-braille developer guide (the north star).
  • spec/braille.md — the braille/0.1-draft cell-to-haptic encoding.

Built with

The site is Astro, deployed on Cloudflare Pages; the registry ships as static JSON so the CLI works offline and from the CDN edge. Local dev: npm install, then npm run dev.


License

Code — Apache-2.0 © Bimbi-Digital. Pattern snippets — CC0 (public domain), copy and own them freely.

A note on patents: Apache-2.0's patent grant covers only patents held by contributors on their own contributions. It does not provide freedom-to-operate against third-party haptic patents (e.g. Immersion). These patterns are built only from public, documented platform APIs, with no clearance guarantee — evaluate your own exposure before shipping.

About

An open, portable haptic format + registry, built for AI agents. North star: hardware-free haptic braille.

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages