Guidonica is a high-performance, client-only web engine for deliberate sight-reading and solfège practice, inspired by Guido d'Arezzo's historic pedagogical method. It continuously streams procedurally generated sheet music across a fixed playhead in sample-accurate synchronization with a Web Audio synthesized metronome—built with zero framework bloat in pure Vanilla TypeScript, pure CSS3 liquid glass, and 60/120 FPS GPU blitting.
Live Application: https://guidonica.it (mirror: hand-lock.github.io/guidonica) |
- Heritage & Pedagogical Rationale
- The "Suckless" Engineering Axioms
- System Architecture & Data Flow
- Comprehensive Feature Tour
- Complete Setticlavio Clef System
- Ergodic Metric Tree Rhythm Generation
- Arbitrary n-Tuplet Matrix Engine
- Multi-Interval Pitch Random Walk
- Solfège Syllable Overlays & Note Labels
- Synthesized Metronome & Woodblock Timbre
- Stationary Wait-In-Place Count-In
- Stationary Stave Header
- Device-Adaptive Zoom & Forereading
- Unassisted Sight-Reading Mode
- Native Device & Lifecycle Resilience
- Aero-Guidonica Skeuomorphic Design
- Keyboard Controls & Shortcuts
- Quickstart & Local Development
- macOS & Apple Silicon Guide
- Available Scripts
- Continuous Deployment & Custom Domain
- Architectural Decision Records (ADRs)
- License & Copyleft Terms
Guidonica takes its name from Guido d'Arezzo (c. 991 – after 1033), the Italian medieval Benedictine monk and music theorist whose treatises laid the bedrock of Western musical notation: the modern 4-line and 5-line staff notation, hexachordal solmization (ut, re, mi, fa, sol, la), and the celebrated Manus Guidonica (Guidonian Hand).
The manus guidonica was history's first spatial visual-mnemonic sight-singing interface: choir apprentices mapped musical intervals, hexachords, and syllables directly to the joints and tips of the human hand to internalize real-time pitch recognition and eliminate rote memorization. Guidonica translates this historical pedagogical breakthrough into a modern, continuous digital medium:
- Anticipatory Eye Scanning (Forereading): Traditional sheet music reading suffers from cognitive "page-turn panic", fixation stutter, and erratic eye wandering. Guidonica's unyielding, continuous horizontal tape trains the musician's eye to actively scan ahead of the playhead, recognizing upcoming interval patterns, melodic contours, and rhythmic groupings well before vocalizing or playing them.
- Frictionless Deliberate Practice (Zero Evaluation Overhead): Guidonica acts as an unwavering rhythmic pacing partner. It deliberately omits microphone pitch tracking, scoring algorithms, latency-inducing audio processing, or gamified leaderboards. The musician self-monitors their vocalized solfège or instrumental execution directly against the physical acoustic click and the oncoming notation.
-
The Ergodic Principle (State-Space Completeness):
Pedagogically, true sight-reading mastery requires confronting every syntactically valid permutation within a musical curriculum. If software artificially favors common clichés or censors complex figures (e.g., omitting quarter-eighth syncopations in 6/8 or quarter-half pairs in 3/4), the student develops severe cognitive blind spots. Guidonica treats the user's active configuration as a bounded musical universe
$\Omega$ : every mathematically valid measure possesses a strictly non-zero probability of generation ($P(\omega) > 0, \forall \omega \in \Omega$ ). -
Unassisted Sight-Reading Mode:
While the high-contrast playhead cursor provides immediate spatial grounding for beginners, advanced sight-reading requires reading unassisted without a visual crutch. Guidonica allows the playhead cursor to be toggled off at any moment (via UI or pressing
P), challenging the musician to track the flow purely from their internal pulse.
Guidonica is constructed upon an uncompromising suckless, ultra-lightweight, and zero-bloat engineering philosophy, rejecting the sluggish dependencies and virtual abstractions of modern web stacks:
- Zero Framework Bloat (Vanilla TypeScript):
- Written exclusively in Vanilla TypeScript driving native DOM APIs, HTML5 Canvas, and the Web Audio API directly.
- Zero React, Vue, Svelte, or Angular. Zero Virtual DOM reconciliation overhead.
- Zero external state management libraries (no Redux, MobX, Zustand, or Pinia).
- Entire application JavaScript (excluding VexFlow) is only ~16.8 kB gzipped (
67.6 kBuncompressed).
- Single Authoritative Hardware Clock (
AudioContext.currentTime):- Visual scroller movement and synthesized audio pulse scheduling are mathematically locked to the hardware audio clock (
AudioContext.currentTime). - Zero
setInterval,setTimeout, or visual delta-time accumulators. - Noteheads cross the playhead mark at the exact physical microsecond the speaker driver clicks—visual-auditory drift is mathematically impossible.
- Visual scroller movement and synthesized audio pulse scheduling are mathematically locked to the hardware audio clock (
- Hardware-Accelerated Measure Blitting Pipeline:
- VexFlow renders each measure once onto an offscreen
HTMLCanvasElement. - The 60/120 FPS animation loop (
requestAnimationFrame) exclusively executes GPU-accelerated bit-block transfers (ctx.drawImage()). - Zero per-frame layout recalculations, zero font parsing per frame, sub-millisecond per-frame CPU execution (< 1% CPU utilization).
- VexFlow renders each measure once onto an offscreen
- Bounded Ring-Buffer & Zero-Leak Memory Discipline:
- Only 4 to 6 measures exist in memory at any given time.
- Measures that scroll past the left edge of the viewport are immediately evicted from the ring-buffer and their offscreen canvases dereferenced.
- An infinite 3-hour practice session maintains the exact same memory footprint (~30–45 MB total process memory) as a 5-second quick test.
- Synthesized Hardware Audio (0-Byte Sample Downloads):
- Metronome pulses and woodblock timbres are synthesized live on the audio hardware using Web Audio
OscillatorNode(sine/triangle) and exponentialGainNodeenvelopes. - Zero audio sample files (MP3/WAV/OGG) downloaded across the network.
- Metronome pulses and woodblock timbres are synthesized live on the audio hardware using Web Audio
- Ergodic Metric Tree Procedural Generation:
- Rhythms are partitioned via recursive metric tree subdivision based on exact rational time signature fractions.
- Pitches are generated via an irreducible, strongly connected Markov random walk with boundary reflection bias. Zero heavyweight music theory AI, zero rule engines, zero network dependencies.
- Pure CSS3 Liquid Glass UI (Zero CSS Frameworks):
- The entire Frutiger Aero / Aqua / Liquid Glass visual design is constructed with 100% pure, hardware-composited CSS3 (
backdrop-filter, multi-stop linear/radial gradients, beveled glass borders, tactile inset/drop shadows). - Zero Tailwind runtime, zero CSS-in-JS runtimes, zero heavy sprite textures.
- Entire stylesheet is only ~5.9 kB gzipped (
34.8 kBuncompressed).
- The entire Frutiger Aero / Aqua / Liquid Glass visual design is constructed with 100% pure, hardware-composited CSS3 (
- Native Device & Lifecycle Resilience:
- Integrates modern Web APIs including Screen Wake Lock (
navigator.wakeLock), Page Visibility lifecycle auto-pause, dynamic iOSAVAudioSessioncategory switching (playbackmode to bypass physical silent switches), and Fullscreen API.
- Integrates modern Web APIs including Screen Wake Lock (
flowchart TD
subgraph HardwareClock["Hardware Audio Subsystem"]
AC["AudioContext.currentTime\n(Single Source of Truth Clock)"]
SCHED["Metronome Audio Scheduler\n(Lookahead Audio Queue)"]
SYNTH["Live Synthesis Engine\n(OscillatorNode + GainNode Envelope)\n• Resonant Woodblock\n• Electronic Triangle"]
AC --> SCHED
SCHED --> SYNTH
end
subgraph GenerationPipeline["Procedural Generation Pipeline"]
PARAM["Session Parameters\n(Clef, Meter, Subdivs, Dotted, Ties, Intervals, Rests)"]
ERGMET["Ergodic Metric Tree Partitioner\n(Compound 6/8 & Simple 4/4, 3/4, 2/4)"]
MARKOV["Pitch Random Walk\n(Clef Range ±3 Ledgers, Irreducible Digraph)"]
PARAM --> ERGMET
PARAM --> MARKOV
ERGMET --> MDATA["MeasureData\n(Exact Beat Offsets, Durations, Ties)"]
MARKOV --> MDATA
end
subgraph Rasterization["Hardware-Accelerated Blitting Pipeline"]
MDATA --> VEX["VexFlow Formatter\n(Single-Pass Layout per Measure)"]
VEX --> OFFCAN["Offscreen HTMLCanvasElement\n(Rasterized Measure Glyph Cache)"]
OFFCAN --> RBUF["Active Measure Ring-Buffer\n(4–6 Measures Bounded Capacity)"]
end
subgraph RenderingLoop["60 / 120 FPS Animation Loop (rAF)"]
AC --> RAF["requestAnimationFrame Loop\n(Calculate Exact Tape Offset from Hardware Clock)"]
RBUF --> BLIT["GPU Bit-Block Transfer\nctx.drawImage(offscreenCanvas, dx, dy)"]
RAF --> BLIT
BLIT --> VIEW["Main Viewport Canvas\n• Stationary Staff Lines\n• Pinned Clef & Meter Header\n• Stationary Count-In (Wait-in-Place)\n• Optional Playhead Mark"]
end
Guidonica supports the full historic Setticlavio (seven clefs) traditional vocal and instrumental clef system, featuring both historical positions of the baritone clef:
- Treble (G2) (
treble): G clef on line 2, range E3 – F6. - Soprano (C1) (
soprano): C clef on line 1, range C3 – D6. - Mezzo-Soprano (C2) (
mezzo-soprano): C clef on line 2, range A2 – B5. - Alto (C3) (
alto): C clef on line 3, range F2 – G5. - Tenor (C4) (
tenor): C clef on line 4, range D2 – E5. - Baritone (F3) (
baritone-f): F clef on line 3, range B1 – C5. - Baritone (C5) (
baritone-c): C clef on line 5, range B1 – C5. - Bass (F4) (
bass): F clef on line 4, range G1 – A4.
Pitches are strictly bounded to the stave lines plus exactly
The rhythm engine decomposes each measure top-down based on exact rational time signature fractions:
-
Compound Meter (6/8): Supports macro-dotted-half measures (
hd), paired dotted-quarters (qd qd), quarter-eighth figures (q 8and8 q), running eighth notes (8 8 8), and sixteenth-note subdivisions. -
Simple Triple Meter (3/4): Generates dotted-half notes (
hd), half-quarter pairings (h qandq h), and individual beat subdivisions. -
Simple Quadruple & Duple (4/4, 2/4): Partitions measures preserving metric half-bar clarity (beats 1–2 and beats 3–4), supporting whole notes (
w), half notes (h), dotted quarters with eighths (qd 8and8 qd), quarter notes (q), eighth notes (8), and sixteenth notes (16). -
Dotted Rhythms: Dedicated toggle enabling dotted figures (
hd,qd,8d) without breaking metric integrity. -
Cross-Beat Tied Notes: Ties notes across metric subdivisions with pitch preservation (
$p_{i+1} = p_i$ ) and VexFlowStaveTierendering. - Rhythmic Rests: Toggleable rests (quarter and eighth rests) embedded directly into metric subdivisions.
A dedicated tuplet configuration menu allows selecting any combinations of:
- Tuplet Ratios: Duplets (2:3), Triplets (3:2), Quadruplets (4:3), Quintuplets (5:4), Sextuplets (6:4), and Septuplets (7:4).
- Base Note Values: Quarter notes (
1/4), Eighth notes (1/8), and Sixteenth notes (1/16). - Engraving Polish: Automated unified stem direction grouping, bracketed ratio displays, and metric width compensation.
Pitch transitions are governed by an irreducible Markov chain with boundary reflection:
- Selectable Intervals: Granular checkboxes for Unison (1st), Second (2nd / stepwise), Third (3rd / skip), Fourth (4th), Fifth (5th), Sixth (6th), Seventh (7th), Octave (8ve leap), and Ninth Plus (9+ compound intervals).
-
Ledger Boundary Reflection: Inward boundary bias prevents notes from straying beyond the
$\pm 3$ ledger line range while maintaining ergodic exploration of the full clef gamut.
Overhead syllable and letter indicators assist ear training and note identification:
- Solfège (Fixed-Do / Anglo-American):
Do,Re,Mi,Fa,Sol,La,Ti. - Italian Solfège (Setticlavio Standard):
Do,Re,Mi,Fa,Sol,La,Si. - Note Letters:
C,D,E,F,G,A,B. - Vertical Clearance Transform: Offscreen canvas renders dynamically shift downward by 20px when labels are enabled, preventing text from colliding with upper ledger lines or beams.
- Sound Profiles:
- Woodblock (Default): Organic resonant woodblock synthesized via exponentially damped high-frequency sines with bandpass character.
- Electronic Triangle: Crisp, uncolored triangle-wave oscillator clicks.
- Accented Beats: Downbeats synthesize at a higher pitch (1200 Hz) than subsequent beats (800 Hz).
- 6/8 Pulse Grouping: Selectable between 2 compound beats (dotted-quarter pulses ♩.) or 6 metric beats (eighth-note pulses ♪).
- Volume & Mute: Direct volume slider with instant mute toggle.
- When Count-In is enabled, starting playback initiates a 1-measure preparatory count-in.
- Wait-In-Place Mechanics: The notation tape does not move during count-in; Measure 0 rests stationary directly under the playhead, giving the musician time to read the initial notes and internalize the tempo before tape motion begins on Beat 1.
- Visual Feedback: A stacked
COUNT-INbadge and dynamic animated beat dots flash in real time with each metronome strike.
- The active clef and selected time signature remain permanently pinned to the left edge of the stave canvas on an offscreen-rendered stationary header.
- A smooth linear gradient fade protects the stationary header from scrolling note glyphs, creating a seamless visual entry point.
- Automatic Sight-Reading Forereading: Sizing algorithms calculate the exact scale required to keep at least one full measure visible ahead of the playhead on any screen width (mobile, tablet, or desktop ultrawide).
- Integer Staff Quantization: Zoom scales are quantized to integer tenths (
10 * Z \in \mathbb{Z}) ensuring staff lines align cleanly with screen pixels without antialiasing blur. - Manual Controls & Floating Pill: On-canvas floating liquid glass zoom pill (
-,100%,+) alongside header slider and keyboard shortcuts.
- A stationary red playhead cursor with top and bottom guide triangles marks the exact instant of downbeat arrival.
- Musician can toggle the playhead off at any time using the UI switch or the
Pkey to practice unassisted eye-tracking for performance preparation.
- Page Lifecycle Auto-Pause: Automatically pauses playback when switching browser tabs or minimizing the window (
visibilitychange/pagehide), resuming cleanly without phase jitter. - AudioContext State Recovery: Restores Web Audio contexts interrupted by system sleep, phone calls, or audio route changes.
- Screen Wake Lock: Uses
navigator.wakeLockto prevent the device display from dimming or sleeping during long practice sessions. - iOS AudioSession Silent Mode Bypass: Uses the W3C WebKit
navigator.audioSessionAPI to engageplaybackmode during practice (enabling audio through the speaker even if the iPhone physical mute switch is toggled), dropping cleanly back toambienton pause. - Fullscreen API: Clean toggle to enter immersive full-window notation mode, with capability detection that hides the button on unsupported devices (e.g., iPhone Safari).
Constructed strictly following the Aero-Guidonica Design Manifesto:
- Liquid Glass Aesthetic: Translucent acrylic panels, hardware-composited
backdrop-filter: blur(16px), specular glass highlights, and multi-layered inner and drop shadows. - Olo Chromatic Accent (
#00FFCC): A high-luminance, 100% pure cyan-green accent inspired by classic 2000s media players, providing maximum perceptual contrast in both light and dark modes. - Curated Typography:
- Alegreya: Classic humanist serif with Renaissance calligraphic roots, used for brand identity and editorial titles.
- Alegreya Sans: Ergonomic humanist sans-serif for UI labels, buttons, and settings controls.
- Ubuntu Mono: Engineered monospace numerals for steady, non-jumping BPM and metric readouts.
- Handcrafted Vector Music Icons: Custom inlined SVG glyphs for quarter, eighth, half, whole, sixteenth, dotted, rest, tie, and playhead icons.
- Auto OS Night Mode: Dynamically follows the user's operating system dark/light mode preference (
prefers-color-scheme) with manual overrides.
| Key | Action | Description |
|---|---|---|
| Space | Start / Pause | Toggle playback or resume seamlessly from the current position |
| R or Esc | Reset | Rewind tape to measure 0 and re-seed the procedural generator |
| P | Toggle Playhead | Show or hide the stationary red playhead cursor (Unassisted Mode) |
| ↑ (Up) | Tempo +5 BPM | Increase tempo by 5 BPM |
| ↓ (Down) | Tempo -5 BPM | Decrease tempo by 5 BPM |
| Shift + ↑ | Tempo +1 BPM | Precision increase tempo by 1 BPM |
| Shift + ↓ | Tempo -1 BPM | Precision decrease tempo by 1 BPM |
| + or = | Zoom In | Increase notation scale by 10% |
| - or _ | Zoom Out | Decrease notation scale by 10% |
| 0 | Auto Zoom | Recalculate and reset to optimal device-adaptive forereading zoom |
- Node.js:
>= 22.13.0(Node 22 LTS). Check your active version withnode -v. - Package Manager:
[email protected](recommended) ornpm.
# 1. Clone the repository
git clone https://github.com/Hand-Lock/guidonica.git
cd guidonica
# 2. Install dependencies
pnpm install
# 3. Start local development server
pnpm devOpen your browser at http://localhost:3000 (or the port reported in your terminal).
Guidonica is fully tested and optimized for macOS and Apple Silicon:
- Native ARM64 Architecture:
pnpm-lock.yamlprovides pre-resolved native@esbuild/darwin-arm64and@rollup/rollup-darwin-arm64binaries;pnpm installexecutes with zero Rosetta 2 translation. - Web Audio Gesture Unlock:
WebKit and Chromium browsers enforce strict autoplay restrictions on macOS. Guidonica creates and unlocks the
AudioContextwithin the direct user gesture (clicking Start or pressing Space). - Retina Display Hi-DPI Scaling:
The scroller canvas automatically adapts to
window.devicePixelRatio: 2(or 3), supersampling the offscreen and display buffers so noteheads, stems, and staff lines remain razor-sharp. - macOS SSH Keychain for Remote Deployment:
When pushing updates from agent or non-interactive shells, load your Keychain credentials:
ssh-add --apple-load-keychain 2>&1 && git push origin main
| Command | Description |
|---|---|
pnpm dev |
Starts the Vite development server on http://localhost:3000 with instant HMR. |
pnpm typecheck |
Validates TypeScript types strictly (tsc --noEmit) with zero errors. |
pnpm test |
Runs the Vitest automated test suite (71 tests across 11 test suites). |
pnpm test:watch |
Runs Vitest in interactive watch mode for test-driven development. |
pnpm build |
Executes strict typecheck and compiles production bundle into dist/. |
pnpm preview |
Serves the production build locally for verification. |
This repository is configured for automated testing, building, and zero-downtime deployment to GitHub Pages via GitHub Actions.
Every commit pushed to the main branch automatically triggers .github/workflows/deploy.yml:
- Validation: Strictly typechecks TypeScript (
tsc --noEmit) and runs all unit tests. - Build: Compiles production bundles with relative asset paths (
base: './') and isolates VexFlow into a cached vendor chunk. - Deploy: Uploads the production artifact and publishes it to GitHub Pages.
The production application is served under the apex domain https://guidonica.it:
- DNS Configuration: Apex
@A-records pointing to GitHub Pages IP infrastructure (185.199.108.153,185.199.109.153,185.199.110.153,185.199.111.153) andwwwCNAME record pointing tohand-lock.github.io. - Repository Root CNAME: The
CNAMEfile in the root specifiesguidonica.it. - Automatic HTTPS: TLS certificates are provisioned and renewed automatically via Let's Encrypt through GitHub Pages.
All core architecture, math formulas, rendering mechanisms, and design decisions are formally documented in docs/adr/:
| ADR | Title | Status |
|---|---|---|
| 0001 | Core Architecture, Metric Linearity & Blitting Pipeline | Accepted |
| 0002 | Light Theme Standardization & High-Contrast Canvas Rendering | Accepted |
| 0003 | Infinite Streaming Buffer, Stave Alignment & Barline Rendering | Accepted |
| 0004 | Beaming Geometry, Stave Attachment & Stem Extension Alignment | Accepted |
| 0005 | Dynamic Subdivision Beat Width & Stave Padding Compensation | Accepted |
| 0006 | Multi-Interval Checkbox Selection & Clef-Dependent Pitch Pools (±3 Ledger Lines) | Accepted |
| 0007 | Comprehensive System Audit, Glitch Elimination & Performance Optimizations | Accepted |
| 0008 | Pause and Resume State Synchronization & Beat Grid Phase Alignment | Accepted |
| 0009 | Cross-Platform Portability, macOS Apple Silicon Support & GitHub Synchronization | Accepted |
| 0010 | Separate Tuplet Subdivision Matrix Menu & Arbitrary n-Tuplet Engine | Accepted |
| 0011 | Tuplet Beam Stem Direction Unification & Contiguous Non-Tuplet Grouping | Accepted |
| 0012 | Web Font Loading Synchronization & Pinned Clef Cache Invalidation | Accepted |
| 0013 | Production Readiness, High-DPI Retina Pipeline & Audio Polish | Accepted |
| 0014 | Solfège Label Context Transform & Vertical Clearance Architecture | Accepted |
| 0015 | Italian Solfège Syllables and Cross-Platform OS-Aligned Auto Night Mode | Accepted |
| 0016 | Default Woodblock Metronome Profile and Auto OS Theme Mode | Accepted |
| 0017 | Vector Music Notation Icons for Cross-Platform UI Controls | Accepted |
| 0018 | Continuous Deployment to GitHub Pages via GitHub Actions & Custom Domain Readiness | Accepted |
| 0019 | Strict Copyleft Open-Source Licensing (GNU AGPLv3) | Accepted |
| 0020 | In-App License and Repository Presentation Architecture | Accepted |
| 0021 | Project, Web-App, and Repository Rebranding to Guidonica | Accepted |
| 0022 | Aero-Guidonica Skeuomorphic Design System, Alegreya Typography, and Design Manifesto | Accepted |
| 0023 | Ubuntu Mono Monospace Typography and Numeric System | Accepted |
| 0024 | Technical Feasibility Evaluation and Rejection of Web Haptic Motor Feedback | Decided |
| 0025 | In-App Notation Zoom & Mobile Ergonomics | Accepted |
| 0026 | Stationary Selected Time Signature & Left Stave Header | Accepted |
| 0027 | Dynamic iOS AudioSession: Ambient UI & Playback Metronome | Accepted |
| 0028 | Device-Adaptive Zoom & Sight-Reading Forereading | Accepted |
| 0029 | Stationary Count-In Wait-In-Place | Accepted |
| 0030 | Stacked Count-In Indicator and Mobile Traffic Lights Geometry | Accepted |
| 0031 | Custom Domain Infrastructure (guidonica.it) via Register.it and GitHub Pages | Accepted |
| 0032 | Olo (#00FFCC) Chromatic Accent, Perceptual Color Principle, and Liquid Gel Palette Architecture | Accepted |
| 0033 | Fullscreen API Capability Detection & Selective UI Presentation | Accepted |
| 0034 | Matched Segmented-Square Fullscreen Icons & Inverted Exit Geometry | Accepted |
| 0035 | Page Lifecycle Auto-Pause, AudioContext State Recovery & Screen Wake Lock | Accepted |
| 0036 | Ergodic Metric Tree Procedural Generation, Dotted Rhythms & Tied Notes | Accepted |
| 0037 | Toggleable Playhead Mark Visibility & Unassisted Sight-Reading Mode | Accepted |
| 0038 | Setticlavio Complete Clef System: Soprano, Mezzo-Soprano, and Dual Baritone (F & C) Integration | Accepted |
This project is free and open-source software licensed under the GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later).
Copyright © 2026 A. C. Lo Cascio.
- User Freedoms: You are free to run, study, inspect, modify, and redistribute this software.
- Network Copyleft: In accordance with Section 13 of the GNU AGPLv3, if you modify this program and run it on a server or host it as a network or cloud service where users interact with it remotely over a computer network, you must make the complete Corresponding Source code of your modified version available to all users at no charge, via a prominent network facility (such as a public Git repository).
- Third-Party Acknowledgements: Music notation typesetting and stave vector layout are powered by VexFlow, licensed under the MIT License.