Project Info
Interactive guidance for TCM self-care routines.
Inspiration
Interactive TCM Coach was inspired by a real self-care problem from our team: someone wanted to try hand acupressure for period discomfort, but did not know whether the position, rhythm, or movement was correct. Static diagrams and videos were not enough. We wanted to build a system that gives immediate visual feedback while keeping clear safety boundaries. What It Does Interactive TCM Coach uses AR to guide users toward the correct hand acupressure area, then uses computer vision to analyze pressing rhythm, accuracy, and stability in real time. Instead of only showing where to press, it helps users understand whether they are doing the routine correctly. The demo also includes a front-end 3D body model with meridian visualization, so users can see the broader route/context of a point instead of only seeing a flat instruction. How We Built It We built a web-based demo with React, camera input, MediaPipe hand tracking, AR-style overlays, front-end 3D modeling, and computer vision logic for hand position and pressing frequency. We also created a video-to-JSON pipeline to extract fingertip position and rhythm features from training videos, which can support future model training. Challenges We Ran Into Fine-tuning a CV model to recognize exact acupressure position was too large for the hackathon scope. Our workaround was to use AR target circles to mark the intended area, so the software does not need to fully identify the acupoint from scratch. It only needs to check whether the user's finger reaches the marked region. Overlapping fingers made fingertip-level tracking noisy. Frequency and stability detection were also inconsistent: sometimes the signal worked, but sometimes it broke when the hand moved quickly or the finger was partially hidden. Since AR handles position guidance, we simplified frequency detection by measuring motion around the target region, such as centroid motion frequency, instead of requiring perfect fingertip landmark detection every frame. Fitting long meridian paths onto a 3D human model was difficult because the line has to follow the body surface instead of floating through the model. Our workaround was to split each long meridian into smaller segments, then fit and adjust the segments one by one. iOS camera access was also tricky during development because Safari is strict about camera permissions and secure origins. We had to adjust the local setup so the phone could open the demo with camera access instead of only testing on desktop. Accomplishments That We're Proud Of We are proud that we kept the idea small enough to actually demo. Instead of trying to build a huge health AI product, we focused on one simple user pain point: people can read acupressure instructions online, but they still do not know if they are pressing in the right area. We are also proud of the workaround we found for the vision problem. Exact acupoint detection is hard, especially in a hackathon, so we used hand landmarks and rough target regions to make the guidance understandable enough for a working demo. What We Learned We learned a lot about a new kind of software engineering workflow with AI. The challenge is not just writing code faster, but learning how to collaborate, define success, keep the right context, and design useful evaluation systems while the project is moving quickly. We also learned how to get the key information needed to contribute even when we did not fully understand every part of the project. Instead of trying to know everything first, we focused on the important constraints, acceptance criteria, and failure cases, then used those to guide the build. What's Next for Interactive TCM Coach Session: Expand from one-time pressing feedback into guided course-style sessions, where users complete structured routines over time instead of a single action. LLM: Add an assistant with RAG over curated TCM and safety content, so users can ask self-care questions while the system stays grounded in reviewed sources. More Content: Support more acupressure points, routines, and hand/wrist regions, with AR guidance, computer vision feedback, and progress summaries across sessions.
AcuGuide — Native iOS (SwiftUI)
A camera-guided acupressure coach for safe, non-diagnostic self-care, in an ink-and-gold palette: a 3D body atlas of 33 sourced points across fourteen meridians, an AR coaching window (Vision hand-pose, 8 camera-coached points), a guided timer for everything else, and a fully on-device AI chat coach.
Status: builds, tests, and ships green. The Xcode project is generated from
project.yml(XcodeGen).make build(generic iOS device, unsigned) andmake testboth pass — 136 tests, 0 failures. Every branch is gated by.github/workflows/merge-gate.ymlbefore it may merge.Not yet verified on real hardware: the meridian rendering and the hand-detection feel. Camera and Vision hand-pose do not run in the Simulator, so no amount of test coverage speaks to them.
Repository layout
The iOS app is this repository — it lives at the root.
AcuGuide/ # app sources (SwiftUI, Vision, SceneKit) — 51 files
AcuGuideTests/ # unit tests — 11 files, 136 tests
project.yml # XcodeGen spec — the project is generated, never hand-assembled
Makefile # make project / build / test
scripts/ # safety_scan.py (banned-claim scanner), pick_simulator.sh
.github/workflows/ # merge-gate.yml — the required check for anything landing on main
claude-deliverables/ # CV research, acupoint sources, and the replay fixtures the tests bundle
tools/voice/ # offline Kokoro renderer for the pre-rendered voice clips
store/metadata/ # App Store listing copy (en-US, zh-Hans) — scanned by the safety gate
licenses/ # full third-party license texts (OFL 1.1)
docs/ # privacy policy, release checklist, pre-release vision, icon drafts
archive/ # superseded work, kept for reference — nothing here is built (see below)
CLAUDE.md # working agreement + the traps that bite (read this before changing things)
acuguide-dashboard.html # project dashboard, regenerated from live git state
archive/ holds the pre-iOS work: web-camera-coach/ (the React + MediaPipe browser prototype
and its build config), MaiApp/ (the three.js 诗词山河 meridian atlas the visual design came from),
demo-app/ (the original vanilla-JS prototype), plus the hackathon-md/ and product/ planning
docs and the old web-era README-web-apps.md. Nothing in archive/ is part of the build.
What's in the app
Three tabs — Atlas · Practice · Coach AI (RootView.swift).
| Area | Files | What it does |
|---|---|---|
| Atlas | Body3DView, HandModel3DView, Meridians, Acupoints | SceneKit body (GLTFKit2), drill down body → hand → back; 33 bilingual points on 14 meridians, each with location, plain-language "how to find it", traditional-use text and read-aloud |
| Camera coach | ARCoachView, CameraCoach, Coach, HandModel, CameraGate, CameraSetupCard | Forced safety gate → first-run setup card → find-your-spot locate step → live overlay (ring / press dot / feedback) → recap. Position + hold + steadiness; no cadence |
| Guided timer | TimerSession, SessionUI, Routines | The camera-free path for the other 25 points, plus multi-step routines |
| Calibration | PointCalibration, "Your spots" in RootView | Saves your spot per point as a delta in the canonical hand frame; re-findable and resettable |
| Chat coach | ChatView, ChatLLM | Bilingual wellness Q&A over the atlas. Crisis and red-flag routing run first, before any answer |
| History | PracticeStore, HistoryView | Local-only practice log with export (ShareLink) and in-app deletion |
| Voice | Speech (incl. AtlasSpeaker), VoiceClips, LocateVoice | Pre-rendered clip playback, spoken cues, read-aloud, hands-free "this is my spot" |
| Settings & reference | Settings, SourcesView, CreditsView (holds PrivacyView), OnboardingView | Language, on-device AI toggle, daily reminder, sources, credits, privacy |
Setup (Xcode, on your Mac)
The project is generated from project.yml — no hand-assembly. You need
XcodeGen: brew install xcodegen.
- Generate + open:
Bundle idmake project # = xcodegen generate → AcuGuide.xcodeproj (git-ignored) open AcuGuide.xcodeprojapp.acuguide.ios, deployment target iOS 16.0, SwiftUI lifecycle, portrait-locked. The camera usage string andAccentColor/AppIconassets are baked in. - Build / test from the CLI (no Xcode UI needed):
make build # xcodebuild build for a generic iOS device (signing off) make test # xcodebuild test (auto-picks a simulator; override with SIM="iPhone 16")make testis the gate — CI re-runs it on a different toolchain plus a device build, the stress suite five times, and the whole suite twice to catchUserDefaultsstate leaks. - Signing: set your team on the
AcuGuidetarget to run on a physical device. - 3D models: loaded at runtime from
AcuGuide/Resources/*.glbvia the GLTFKit2 Swift package — no usdz conversion.make projectresolves the package (network needed once); if an SPM cleanup nukes the artifact, re-resolve before assuming the code broke. A capsule fallback shows only if an asset is missing. - Chat coach: fully offline. On iOS 26+ with Apple Intelligence it answers free-form
questions using Apple's on-device
FoundationModels; elsewhere it falls back to the built-in bilingual atlas helper. No API key, no network, no accounts. Red-flag symptoms → stop-and-seek care; crisis messages route to real help and never to acupressure. - Run on a real device — camera and Vision hand-pose don't work in the Simulator.
Voice
Every spoken line is a fixed string, so the whole script is pre-rendered offline into 102
bilingual AAC clips (AcuGuide/VoiceClips/, ~5.3 MB, Kokoro / Apache-2.0; pipeline in
tools/voice/). Playback is the primary path; AVSpeechSynthesizer is the fallback for any line
that has drifted from its clip.
The clip key is
sha256("<locale>|<normalized text>")— so rewording any spoken string orphans its clip and silently drops that line to the robotic fallback.VoiceScriptTestsfails in both directions (missing clip / orphaned clip); when it does, re-render withtools/voice/render_voice.py. SeeCLAUDE.mdbefore touching spoken copy.
Cues fire on phase change only; there's a mute toggle. .ambient session for coach cues (respects
the silent switch), .playback for read-aloud. Haptics (CoreHaptics, UIFeedbackGenerator
fallback): a tick on first entering the target, a success pattern at COMPLETE; nothing during
NO_HAND / WRONG_FACE.
Safety (immutable — enforced by tests and CI, not convention)
- No treat / cure / heal / diagnose copy anywhere, in either language.
scripts/safety_scan.pyscans Swift string literals and the store metadata; it runs in CI and locally. - The safety gate before the camera is forced — it cannot be skipped, and it stays scrollable so large Dynamic Type can never push its only exit off-screen.
- "Felt worse" after a routine → stop guidance, never "continue" (including for legacy stored keys).
- Each point's own caution is shown where the press happens, not only on the atlas card.
- LI4 is excluded entirely (pregnancy-contraindicated) — which is why the app needs no pregnancy screening. CI fails if it reappears.
- Crisis and red-flag routing run before any chat answer.
- Acupoint data is sourced and adversarially verified — see
claude-deliverables/references/and the in-app Sources screen.
Licensing
AcuGuide's own source is proprietary — all rights reserved (LICENSE). The repo is public so the source can be read and reviewed; it is not open-source, and redistribution or reuse in another product needs written permission.
The bundled third-party components keep their own licenses, several of which require attribution
that must be preserved when the app is distributed — see
THIRD-PARTY-NOTICES.md and licenses/.
Third-party assets / credits
All three bundled models are CC-BY 4.0 from Sketchfab and their attribution is a licence obligation. The same credits are shown in-app under Settings → Licenses & credits.
| Asset | Title | Author | Licence |
|---|---|---|---|
Resources/model.glb | Character Mannequin Male | muh.nurzidan | CC-BY 4.0 |
Resources/arms_hands_head_legs_and_feet__low_poly_female.glb | Arms, hands, head, legs and feet (low poly) — Female | pnhtuan | CC-BY 4.0 |
Resources/hand_low_poly.glb | Hand (low poly) | scribbletoad | CC-BY 4.0 |
Models were recolored and rescaled for display.
- Voice: Kokoro-82M v1.1 (Apache-2.0), rendered offline via sherpa-onnx.
- Fonts (
AcuGuide/Fonts/): Ma Shan Zheng and Cormorant Garamond, both SIL OFL 1.1 (the license text ships with them, as OFL requires). - GLTFKit2 by Warren Moore, MIT.
Notes / things to tune on-device
- Mirror / face gate: a calibration menu (slider icon) in the coach view flips the preview mirror and inverts the face gate at runtime, so no code edit is needed for field calibration.
- Vision orientation: derived from the capture connection (portrait-locked), not hardcoded.
- Two-person mode: the back camera coaches someone else's hand.
- Scope this build ships: camera coaching for 8 hand/wrist points — TE3, PC6, SJ5, PC8, HT7, SI3, TE4, PC7 (TE3 is the default demo point). Every other point is atlas + guided timer.
Analysis
View
Metric
- 11
- 5
- 4
- 1
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- CSSIn code
- HTMLIn code
- JavaScriptIn code
- PythonIn code
- ReactIn code
- SwiftIn code
- Tailwind CSSIn code
- TypeScriptIn code
8 of 8 appear in the indexed code.
AI coding agents
- Claude CodeConfig · Commits
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
491 KB
Source files
120
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
kany-e/AcuGuide
145 files · 3.2 MB · @ 41e15ff
Structure
Interface
11 files · 8%Screens, components and styles rendered to the user.
Application logic
48 files · 33%Domain rules, services and shared utilities.
+5 more
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- Markdown49%
- JavaScript21%
- TypeScript12%
- CSS8%
- Swift7%
- HTML2%
- Other (1)2%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
package.json
npm · 14- @mediapipe/tasks-vision
- react
- react-dom
- react-router-dom
- +10 more
MaiApp/package.json
npm · 8- @react-three/drei
- @react-three/fiber
- @react-three/postprocessing
- react
- react-dom
- three
- +2 more
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.