Free sight-reading and solfège practice in your browser. Endless fresh sheet music scrolls past a playhead in time with a metronome, at the level you choose, from first steps to every tuplet. No sign-up, no ads, no tracking, and it works on phones, tablets and desktops in English, Italian, French, German and Spanish.
▶ Practice now at guidonica.it
brag-landscape.mp4
24-second trailer: tempo 100→160, triplets, alto clef, wide leaps, five languages. Also on Instagram @guidonica.it.
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 |
- Heritage & Pedagogical Rationale
- The "Suckless" Engineering Axioms
- System Architecture & Data Flow
- Comprehensive Feature Tour
- Level Presets & Onboarding
- Settings at a Glance
- Complete Setticlavio Clef System
- Ergodic Grammar-Driven Rhythm Generation
- Arbitrary n-Tuplet Matrix Engine
- Multi-Interval Pitch Random Walk
- Note Labels: Syllables & Letters
- Tempo & Italian Markings
- Synthesized Metronome & Woodblock Timbre
- Stationary Wait-In-Place Count-In
- Stationary Stave Header
- Device-Adaptive Zoom & Forereading
- Unassisted Sight-Reading Mode
- Five Languages & National Note Names
- Shareable Exercise Links
- Tips & What's New
- Native Device & Lifecycle Resilience
- Aero-Guidonica Skeuomorphic Design
- Keyboard Controls & Shortcuts
- Quickstart & Local Development
- macOS & Apple Silicon Guide
- Available Scripts
- Releases & Nightly
- Continuous Deployment & Custom Domain
- Architectural Decision Records (ADRs)
- Contributing
- Contact
- 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. The project's logo is a Manus Guidonica: the student's own left palm, with the gamut thread starting at Γ (gamma ut) on the thumb tip and coiling down through A and B, the first steps of the hand's historical order (ADR 0047).
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 shipped JavaScript is ~130 kB gzipped: ~37 kB of application code (including the English dictionary) plus ~93 kB of VexFlow's font-free
vexflow/corebuild. Each other language is one lazy ~5.7 kB chunk (ADR 0059). The music font is a separate 19.6 kB Bravura subset (ADR 0058) instead of the ~600 kB of base64 fonts the full VexFlow entry inlines.
- Single Authoritative Hardware Clock (
AudioContext.currentTime):- Visual scroller movement and synthesized audio pulse scheduling are mathematically locked to the hardware audio clock (
AudioContext.currentTime). - Every click time and every tape offset is computed from
currentTime. A 25 mssetIntervalonly wakes the audio scheduler to queue clicks 100 ms ahead; it never measures time. There are no visual timers or 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:
- The buffer holds only the measures that cover the viewport plus 6 beats of lookahead, a few measures at any zoom.
- 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 Grammar-Driven Procedural Generation:
- Rhythms are sampled step by step over a 32nd grid from a grammar derived from the notehead, rest and tuplet placement tables, so every legal bar has P > 0.
- Pitches are generated via an irreducible, strongly connected, symmetric Markov random walk. 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 ~8.3 kB gzipped (
40 kBminified). The text fonts (Alegreya, Alegreya Sans, Ubuntu Mono) are self-hosted Latin subsets, so the page makes no third-party requests (ADR 0060).
- 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), Fullscreen API, and a hand-written offline service worker.
- 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• Woodblock Sine Sweep\n• Electronic Triangle"]
AC --> SCHED
SCHED --> SYNTH
end
subgraph GenerationPipeline["Procedural Generation Pipeline"]
PARAM["Session Parameters\n(Clef, Ledger Lines, Meter, Values, Dotted, Ties, Tuplets, Rests, Intervals, Notes)"]
ERGMET["Grammar-Driven Rhythm Sampler\n(32nd Grid: 2/4, 3/4, 4/4, 6/8, 9/8, 12/8)"]
MARKOV["Pitch Random Walk\n(Clef Range + 0–3 Ledgers, Selected Notes, 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(Viewport + Lookahead)"]
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
-
Three-step intro: on a first visit, Guidonica asks "What's your level?", then "Which clef would you like to read?" (Treble, Bass, Alto, Tenor), then "Which time signature would you like to read?" (4/4, 3/4, 2/4, 6/8, 9/8, 12/8). The welcome step also offers the five languages (ADRs 0049, 0071).
-
Five levels, each an ordinary set of visible settings (ADR 0070):
Level Tempo What it adds Beginner 60 BPM Do-pentatonic (C D E G A), 2nds and 3rds Elementary 70 BPM Every note; 4ths, 5ths and octaves Intermediate 80 BPM Every interval up to the octave; 16ths Advanced 90 BPM Every leap; 32nds Virtuoso 120 BPM Everything -
Notation previews: each level card shows freshly generated example bars of what that level reads (ADRs 0050–0052).
-
Level button: the dumbbell button in the header reopens the presets at any time. Its five-bar meter lights up to the current level, or reads "Custom" when the settings match no preset (ADRs 0053, 0073).
-
Presets never change the generator: each is one point of the configuration space
$\Omega$ .
The settings drawer has four sections:
| Section | Contents |
|---|---|
| Staff | Clef (8), ledger lines above and below (0–3) with a live range hint, time signature, compound pulse (♩. or ♪) |
| Rhythm | Note values (quarter, eighth, half, whole, 16th, 32nd), dotted, tuplets, rests, ties |
| Melody | Notes (C … B), intervals (unison … 9+) |
| Practice | Language, labels, assists (count-in, playhead, tips), click sound, volume, theme, exercise link |
Guidonica supports the full historic Setticlavio (seven clefs) traditional vocal and instrumental clef system, featuring both historical positions of the baritone clef. The ranges below are the widest, with 3 ledger lines above and below:
- 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.
Ledger lines are selectable separately above and below the staff, 0–3 each, from 11 diatonic pitches at 0/0 to 23 at 3/3. The range hint under the clef updates live, in the octave convention of the interface language (ADR 0044).
Each bar is sampled left to right over a 32nd grid from a grammar derived from the notehead, rest and tuplet placement tables, so every legal bar can appear (ADR 0065):
-
Note values: whole (
w, only in 4/4), half (h), quarter (q), eighth (8), sixteenth (16) and thirty-second (32) (ADR 0043). -
Simple meters (2/4, 3/4, 4/4): 4/4 keeps the middle of the bar visible (
q h qis the tolerated syncopation); 3/4 is one undivided unit, soh qandq hboth appear; 2/4 has no dotted half. -
Compound meters (6/8, 9/8, 12/8): the dotted-quarter beat stays visible. Dotted halves (
hd), paired dotted quarters (qd qd),q 8and8 q, running eighths and sub-eighth figures. 9/8 reads like 3/4 one level up (hd qdandqd hd); 12/8 like 4/4 (dotted wholewd, the toleratedqd hd qd). Beams group eighths in threes (ADR 0076). -
Dotted Rhythms: one toggle adds
wd(12/8 only),hd,qd,8dand16d. A dotted value appears only beside a shorter partner that completes its beat. -
Ties: written only where no single well-placed notehead can express the sound: across the middle of a 4/4 bar, across a dotted beat, into or out of tuplets, and across the barline, in chains (ADR 0040). Tied notes keep their pitch.
-
Rests: spelled on the beat grid (ADRs 0065, 0066):
- a silent bar is always one whole rest, in every meter;
- 4/4 has a half rest on either half of the bar;
- compound meters have a dotted-quarter rest on each beat, and 12/8 a dotted-half rest on either half;
- quarter, eighth, 16th and 32nd rests sit on multiples of their own length.
Rests can run on across tuplets and barlines.
A dedicated tuplet menu crosses ratio and base value:
- 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). - Meter-aware cells: only the cells that make metric sense in the current time signature are enabled; the rest are greyed out. For example, quintuplets to septuplets of quarters span a 4/4 bar, and 3/4 adds duplets of quarters (2:3) and quadruplets of eighths written 4:6 across the bar. Compound meters use duplets and quadruplets instead of triplets. Clear all empties the matrix.
- Mixed members: a group may merge members of different values, such as
3[q 8]or5[q 8 8 8](ADR 0066). - Engraving Polish: one beam per run of beamable members with a bracket unless one beam spans the group, unified stem directions, and metric width compensation.
Pitch transitions are governed by an irreducible, symmetric Markov chain:
- 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).
- Note Selection: Seven pitch-class toggles (C … B) narrow the walk to the chosen notes in every octave of the range, e.g. only C and G. Intervals that no two selected notes can form are dimmed, and if none of the selected ones can occur, every interval that joins two selected notes is used, with a hint (ADR 0070).
- Feasible, Symmetric Steps: Only intervals that fit inside the selected ledger-line range are drawn, and up and down are equally likely whenever both fit, so the walk never leaves the range and reaches every note of it, edges included.
Labels are None, Syllables or Letters, spelled by the interface language (ADR 0059):
| Language | Syllables | Letters |
|---|---|---|
| English | Do Re Mi Fa Sol La Ti | C D E F G A B |
| Italiano | Do Re Mi Fa Sol La Si | C D E F G A B |
| Español | Do Re Mi Fa Sol La Si | C D E F G A B |
| Français | Do Ré Mi Fa Sol La Si | C D E F G A B |
| Deutsch | Do Re Mi Fa So La Ti | C D E F G A H |
Each label is anchored to its notehead, 15 px away on the side opposite the stem, so it clears ledger lines, beams and tuplet numbers (ADR 0041).
- 30–240 BPM, set by slider, number input or the arrow keys.
- The classical Italian marking updates live: Grave, Largo, Larghetto, Adagio, Andante, Moderato, Allegro, Vivace, Presto, Prestissimo. Like "BPM", it stays untranslated.
-
Sound Profiles:
- Woodblock (Default): a sine wave with a fast downward pitch sweep (one octave in 25 ms) and an exponential decay.
- Electronic: a crisp triangle-wave click with a 35 ms exponential decay.
-
Three accent levels (ADR 0072), shared by the click and the beat lights:
Accent Beats Woodblock sweep Electronic Beat light Downbeat 1 1600 → 800 Hz 1300 Hz Ruby Secondary 4/4 beat 3; 6/8 beat 4; 9/8 beats 4, 7; 12/8 beats 4, 7, 10 1350 → 675 Hz 1050 Hz Orange Weak All others 1100 → 550 Hz 800 Hz Olo turquoise -
Compound Pulse Grouping: In 6/8, 9/8 and 12/8, the click sounds on every dotted-quarter beat (♩.) or on every eighth (♪). The beat lights read in threes either way.
-
Volume & Mute: Direct volume slider with instant mute toggle.
- When Count-In is enabled, starting playback initiates a 1-measure preparatory count-in. It can be switched off in Settings → Practice → Assists.
- 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). Auto zoom is orientation-aware: a phone in landscape gets a larger staff than the same phone in portrait (ADR 0055).
- Quantized Steps: Zoom moves in steps of 10 points between 30% and 150%, so staff lines align cleanly with screen pixels.
- Manual Controls & Floating Pill: An on-canvas liquid glass pill (
-,100%,+), keyboard shortcuts and pinch-to-zoom. Tap the percentage, or press 0, to return to auto zoom.
- 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.
- The interface is available in English, Italiano, Français, Deutsch and Español. English ships with the app; every other language is one small chunk loaded on demand (ADR 0059).
- The language also sets the note names (see Note Labels) and the octave convention of the range hint: scientific
E3 – F6in English, Franco-BelgianMi2 – Fa5in Italian, French and Spanish, Helmholtze – f³in German. - Language landing pages at guidonica.it/it/, /fr/, /de/ and /es/ carry translated titles, descriptions and social cards, so search engines and link previews show each language (ADR 0086).
- Settings → Practice → Exercise link copies (or shares, on phones) a link to the current exercise (ADR 0085).
- The link's
#x=1&…fragment carries clef, ledger lines, time signature, compound pulse, tempo, note values, dotted, tuplets, rests, ties, intervals, notes, labels and count-in. Language, theme, sound, volume, zoom and the playhead stay with each user. - Opening a link skips the intro and loads the exercise. Each student still reads different music under the same rules, because the generator is never seeded.
- Rotating tips: from the second visit on, one short tip per visit points to a feature the user's settings and device don't use yet (levels, labels, keyboard, pinch zoom, clefs, notes, tuplets, exercise links, installing, What's new…). One in four suggests following Guidonica or supporting it on Ko-fi. Start or the close button hides it, and the Tips chip in Settings → Practice → Assists turns them off (ADR 0087).
- What's new: after an update, a returning user sees what changed since their last visit, in their language. About shows the running version and the full history (ADR 0078).
- 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. - Works Offline: After the first visit, a hand-written, dependency-free service worker serves the app from its cache, so practice continues with no connection; online, every reload still fetches the newest version (ADR 0063).
- Installable: A web app manifest with standard and maskable icons lets Guidonica be added to the home screen or installed as a desktop app, where it opens in its own window (ADR 0048).
- Landscape Tip: On a small touch screen in portrait, a dismissible tip suggests rotating the device. Inside Instagram, Facebook or Threads, whose in-app browsers are locked to portrait, it suggests opening the page in the browser instead (ADRs 0055, 0083).
- 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.
- Guidonian Hand Brand Mark: The logo, favicon, iOS touch icon, Android/Chrome install icons (web app manifest, including a maskable variant) and the flat header glyph (
currentColorhand,--accentthread) are all generated from one deterministic, zero-dependency vector model byscripts/build-icons.mjs(ADRs 0046–0048). - Handcrafted Vector Music Icons: Custom inlined SVG glyphs for quarter, eighth, half, whole, sixteenth, thirty-second, dotted, rest, tie, and playhead icons.
- Theme: Auto (follows the operating system's
prefers-color-scheme), Light or Dark, in Settings → Practice. On wide screens a header button cycles through the three.
| 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 |
Shortcuts pause while a dialog (About, What's new, the level intro) is open. While the tuplet menu is open, Esc closes it first instead of resetting.
- Node.js:
>= 22.13.0(Node 22 LTS). Check your active version withnode -v. - Package Manager:
pnpm@11.8.0(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. |
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. |
pnpm build:site |
Builds the deployed site into site/: the latest release tag at the root, the working tree in site/nightly/ (ADR 0078). |
pnpm release |
Cuts the next CalVer release in CHANGELOG.md and package.json, without committing (maintainer only; ADR 0078). |
pnpm icons |
Regenerates the Guidonian Hand vector outputs (favicon.svg, the README logo, the header glyph) from scripts/build-icons.mjs. |
pnpm icons -- --raster |
Also re-renders the PNG/ICO icons (touch, manifest and favicon) through headless Firefox (must be installed). |
pnpm banners |
Regenerates the social profile banners in docs/brand/banners/ (Mastodon, Bluesky, X, YouTube) from live captures of the production build (ADR 0079). Dev-only, needs the run-guidonica Playwright setup; --guides also writes review copies with avatar and safe zones. |
pnpm ui-fonts |
Re-downloads the self-hosted text fonts (src/fonts/) and their licences from Google Fonts via scripts/fetch-ui-fonts.mjs. Dev-only; the output is committed, so normal development never runs it. |
pnpm music-font |
Regenerates the Guidonica Notation font (src/notation/fonts/) from Bravura via scripts/build-music-font.py. Dev-only, needs Python with pip install fonttools brotli; the output is committed, so normal development never runs it. |
Guidonica ships on two channels (ADR 0078):
| Channel | URL | Contents |
|---|---|---|
| Release | guidonica.it | The latest tagged release, chosen on purpose. |
| Nightly | guidonica.it/nightly/ | The latest commit on main, for testing. Its settings and offline cache are kept apart from the release's. |
Versions use calendar versioning, YEAR.MONTH.MICRO (for example 2026.10.0). Every change is recorded in CHANGELOG.md when it is made. After an update, returning users see what changed in a "What's new" dialog, in their language; About shows the running version and the full history. Each release also has a GitHub Release, and is announced on Bluesky and Mastodon.
This repository is configured for automated testing, building, and zero-downtime deployment to GitHub Pages via GitHub Actions.
.github/workflows/deploy.yml runs on pushes to main, on v* release tags, on pull requests to main (typecheck and tests only) and by manual dispatch:
- Validation: Strictly typechecks TypeScript (
tsc --noEmit) and runs all unit tests. - Build:
pnpm build:sitebuilds the latest release tag at the root and the pushed commit under/nightly/, with relative asset paths (base: './') and VexFlow in a cached vendor chunk. - Deploy: Uploads the site and publishes it to GitHub Pages.
- Release: A
v*tag run creates the tag's GitHub Release from itsCHANGELOG.mdsection. - Announce: After a release deploys, the
announcejob posts the release thread to Bluesky and Mastodon. It never posts twice, so a failed run can be re-run safely (ADR 0081).
Every job gets least-privilege permissions, only the deploy and release jobs can write, and every action is pinned to a full commit SHA (ADR 0069). A separate dco.yml checks the sign-off on every pull request commit.
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. - CNAME File:
public/CNAMEspecifiesguidonica.itand is copied into every build. The oldhand-lock.github.io/guidonica/address redirects to guidonica.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; amended by 0065, 0066, 0070 |
| 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; amended by 0065 |
| 0011 | Tuplet Beam Stem Direction Unification & Contiguous Non-Tuplet Grouping | Accepted; amended by 0065 |
| 0012 | Web Font Loading Synchronization & Pinned Clef Cache Invalidation | Accepted; amended by 0058, 0060 |
| 0013 | Production Readiness, High-DPI Retina Pipeline & Audio Polish | Accepted; superseded in part by 0042 |
| 0014 | Solfège Label Context Transform & Vertical Clearance Architecture | Accepted; superseded in part by 0041 |
| 0015 | Italian Solfège Syllables and Cross-Platform OS-Aligned Auto Night Mode | Accepted; amended by 0059 |
| 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; amended by 0069, 0077, 0078 |
| 0019 | Strict Copyleft Open-Source Licensing (GNU AGPLv3) | Accepted; amended by 0067 |
| 0020 | In-App License and Repository Presentation Architecture | Accepted; amended by 0067 |
| 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; amended by 0060 |
| 0024 | Technical Feasibility Evaluation and Rejection of Web Haptic Motor Feedback | Decided (Rejected) |
| 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; amended by 0072 |
| 0031 | Custom Domain Infrastructure (guidonica.it) via Register.it and GitHub Pages | Accepted; amended by 0068 |
| 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; rhythm sampler superseded by 0065 |
| 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 |
| 0039 | Repository Audit: Ergodicity Restoration, Clock Unification, and Configuration Hygiene | Accepted; superseded in part by 0040 |
| 0040 | Engraving Grammar for Ties and Cross-Barline Ties | Accepted; amended by 0065 |
| 0041 | Solfège Labels Anchored to Noteheads (dpr² Transform Fix) | Accepted; amended by 0057 |
| 0042 | Single-dpr Offscreen Backing Store (drop VexFlow resize()) |
Accepted |
| 0043 | Thirty-Second Notes & Dotted Sixteenths | Accepted; amended by 0064; rhythm sampler superseded by 0065 |
| 0044 | User-Selectable Ledger Lines (Above / Below, 0–3) | Accepted; amended by 0059, 0065, 0066 |
| 0045 | Aero-Guidonica 2: Material Hierarchy & Responsive Redesign | Accepted; amended by 0054 |
| 0046 | Guidonian Hand Brand Mark, Favicon & App Icon | Superseded in part by 0047 |
| 0047 | Guidonian Hand v2: Anatomical Proportions, Volume Shading & 3D Thread | Accepted |
| 0048 | Brand Mark Rollout: Web App Manifest & README Logo | Accepted; amended by 0063 |
| 0049 | Level Presets & Onboarding Intro ("What's your level?") | Accepted; amended by 0053, 0059, 0070, 0071 |
| 0050 | Procedural Notation Previews in the Onboarding Intro | Accepted; amended by 0051, 0052, 0071 |
| 0051 | Representation Presets for the Intro Level Previews | Accepted; amended by 0052, 0070 |
| 0052 | Signature Check for the Intro Level Previews | Accepted; amended by 0070, 0071 |
| 0053 | Header Level Button with a Live Difficulty Meter | Accepted; amended by 0054, 0073 |
| 0054 | Responsive Header Fit Audit | Accepted; amended by 0055, 0076 |
| 0055 | Orientation-Aware Auto Zoom & Portrait Landscape Tip | Accepted; amended by 0056, 0083, 0087 |
| 0056 | Notch-Safe Notation Stage | Accepted |
| 0057 | Canvas-Bounded Beams & Tuplet Numbers | Accepted |
| 0058 | Music Font Audit: Keep Bravura, Ship a Renamed Subset | Accepted |
| 0059 | Localization (en · it · fr · de · es) & National Note Naming | Accepted; amended by 0086 |
| 0060 | Self-Hosted Text Fonts & a No-Tracking Privacy Note | Accepted; amended by 0088 |
| 0061 | Social Preview Card & Share Metadata | Accepted |
| 0062 | robots.txt & sitemap.xml | Accepted; amended by 0086 |
| 0063 | Offline Service Worker | Accepted; amended by 0078, 0086 |
| 0064 | Sub-Eighth Half-Beat Slots in Two-Beat Groups | Superseded by 0065 |
| 0065 | Grammar-Driven Rhythm Sampler, Rest Spelling & Tuplet Merges | Accepted; amended by 0066, 0076 |
| 0066 | Ergodicity Audit: Connected Pitch Start, Rest Runs & Uniform Tuplet Shapes | Accepted; amended by 0070 |
| 0067 | Contribution Licensing (Inbound MIT + DCO) & Trademark Policy | Accepted; amended by 0068, 0069 |
| 0068 | Project Email on guidonica.it (Migadu), Contact Addresses & security.txt | Accepted; amended by 0069, 0077, 0088 |
| 0069 | Security & Privacy Audit: History Rewrite, CI Least Privilege & Repository Hardening | Accepted; amended by 0077, 0088 |
| 0070 | Note Selection Toggles & Reworked Level Progression | Accepted |
| 0071 | Time Signature Step in the Onboarding Intro | Accepted; amended by 0076 |
| 0072 | Three-Level Beat Accent Hierarchy in the Traffic Lights and Click | Accepted; amended by 0076 |
| 0073 | Dumbbell Icon for the Header Level Button | Accepted |
| 0074 | Donations: a Plain Ko-fi Link | Accepted; amended by 0088 |
| 0075 | AI-Assistance Disclosure in the About Dialog | Accepted |
| 0076 | Compound Triple and Quadruple Meters (9/8, 12/8) | Accepted |
| 0077 | CI Actions on Node 24 Releases | Accepted |
| 0078 | Release Channels, CalVer Changelog and "What's New" | Accepted |
| 0079 | Social Profile Banners | Accepted |
| 0080 | Social Profiles: rel="me" Verification and Bluesky Domain Handle | Accepted; amended by 0082, 0084 |
| 0081 | Release Announcements on Bluesky and Mastodon | Accepted |
| 0082 | Visible Bluesky and Mastodon Links | Accepted; amended by 0084 |
| 0083 | In-App Browser Landscape Tip | Accepted |
| 0084 | Instagram Link | Accepted |
| 0085 | Shareable Exercise Links | Accepted |
| 0086 | Language Landing Pages | Accepted |
| 0087 | Rotating Tips | Accepted |
| 0088 | Pre-release Audit 2026-10-06: Second History Rewrite, Privacy Policy | Accepted |
Issues, translations and code are welcome. Read CONTRIBUTING.md before opening a pull request: every commit is signed off under the Developer Certificate of Origin (git commit -s), and contributions are licensed under MIT so they can ship in every edition of Guidonica (see Dual Licensing).
- hello@guidonica.it: teachers, schools, press and general questions.
- legal@guidonica.it: trademark permissions, commercial licensing, takedown notices and privacy requests. How Guidonica handles personal data is in
PRIVACY.md. - security@guidonica.it: security vulnerabilities. Report them privately, never in a public issue; see
SECURITY.md. - Follow: Bluesky @guidonica.it, Mastodon @guidonica@mastodon.social and Instagram @guidonica.it.
- Support: Guidonica is free; voluntary tips go through Ko-fi.
Bugs and feature requests go to GitHub issues.
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.
How Guidonica is made: A. C. Lo Cascio designs, tests and maintains Guidonica, writes much of its code with an AI coding assistant (Anthropic's Claude) and reviews every change. No AI runs inside the app: exercises come from a random generator whose rules are documented in the source, and the metronome is synthesized live in the browser (ADR 0075).
- 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. Music glyphs come from Bravura © Steinberg Media Technologies GmbH, licensed under the SIL Open Font License 1.1 and shipped as the renamed subset "Guidonica Notation". Text is set in Alegreya and Alegreya Sans (SIL Open Font License 1.1: Alegreya, Alegreya Sans) and Ubuntu Mono (Ubuntu Font Licence 1.0), served from the same origin as the app.
The copyright holder also distributes Guidonica under other terms: paid app-store builds, Guidonica Studio for teachers and creators, and commercial licenses for the engine, for those who cannot accept the AGPL. That income funds the free web app, which stays AGPL-licensed and free forever. Outside contributions are accepted under the MIT License (CONTRIBUTING.md), which keeps this possible without changing the project license. For a commercial license, write to legal@guidonica.it with the subject "Commercial licensing".
Guidonica™ and the Guidonian Hand logo are trademarks of A. C. Lo Cascio. Under Section 7(e) of the AGPL, the license grants no rights to use them: you may share unmodified copies and say your project is "based on Guidonica", but a modified version you publish must use its own name and logo. See TRADEMARKS.md.