Sitelet https://github.com/Hand-Lock/guidonica
Skip to content

Repository files navigation

Guidonica logo: a Guidonian Hand wrapped by a gamut thread

Guidonica

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  |  License: AGPL v3 Node.js pnpm TypeScript Deploy


Table of Contents


Heritage & Pedagogical Rationale

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:

  1. 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.
  2. 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.
  3. 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$).
  4. 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.

The "Suckless" Engineering Axioms

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:

  1. 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/core build. 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.
  2. 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 ms setInterval only 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.
  3. 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).
  4. 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.
  5. 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 exponential GainNode envelopes.
    • Zero audio sample files (MP3/WAV/OGG) downloaded across the network.
  6. 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.
  7. 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 kB minified). The text fonts (Alegreya, Alegreya Sans, Ubuntu Mono) are self-hosted Latin subsets, so the page makes no third-party requests (ADR 0060).
  8. Native Device & Lifecycle Resilience:
    • Integrates modern Web APIs including Screen Wake Lock (navigator.wakeLock), Page Visibility lifecycle auto-pause, dynamic iOS AVAudioSession category switching (playback mode to bypass physical silent switches), Fullscreen API, and a hand-written offline service worker.

System Architecture & Data Flow

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
Loading

Comprehensive Feature Tour

1. Level Presets & Onboarding

  • 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$.

2. Settings at a Glance

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

3. Complete Setticlavio Clef System (8 Clefs)

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).

4. Ergodic Grammar-Driven Rhythm Generation

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 q is the tolerated syncopation); 3/4 is one undivided unit, so h q and q h both 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 8 and 8 q, running eighths and sub-eighth figures. 9/8 reads like 3/4 one level up (hd qd and qd hd); 12/8 like 4/4 (dotted whole wd, the tolerated qd hd qd). Beams group eighths in threes (ADR 0076).

  • Dotted Rhythms: one toggle adds wd (12/8 only), hd, qd, 8d and 16d. 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.

5. Arbitrary n-Tuplet Matrix Engine

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] or 5[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.

6. Multi-Interval Pitch Random Walk

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.

7. Note Labels: Syllables & Letters

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).

8. Tempo & Italian Markings

  • 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.

9. Synthesized Metronome & Woodblock Timbre

  • 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.

10. Stationary Wait-In-Place Count-In

  • 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-IN badge and dynamic animated beat dots flash in real time with each metronome strike.

11. Stationary Stave Header & Gradient Mask

  • 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.

12. Device-Adaptive Zoom & Sight-Reading Forereading

  • 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.

13. Unassisted Sight-Reading Mode (Toggleable Playhead)

  • 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 P key to practice unassisted eye-tracking for performance preparation.

14. Five Languages & National Note Names

  • 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 – F6 in English, Franco-Belgian Mi2 – Fa5 in Italian, French and Spanish, Helmholtz e – 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).

15. Shareable Exercise Links

  • 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.

16. Tips & What's New

  • 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).

17. Native Device & Lifecycle Resilience

  • 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.wakeLock to prevent the device display from dimming or sleeping during long practice sessions.
  • iOS AudioSession Silent Mode Bypass: Uses the W3C WebKit navigator.audioSession API to engage playback mode during practice (enabling audio through the speaker even if the iPhone physical mute switch is toggled), dropping cleanly back to ambient on 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).

18. Aero-Guidonica Skeuomorphic Design System

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 (currentColor hand, --accent thread) are all generated from one deterministic, zero-dependency vector model by scripts/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.

Keyboard Controls & Shortcuts

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.


Quickstart & Local Development

Prerequisites

  • Node.js: >= 22.13.0 (Node 22 LTS). Check your active version with node -v.
  • Package Manager: pnpm@11.8.0 (recommended) or npm.

Installation & Run

# 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 dev

Open your browser at http://localhost:3000 (or the port reported in your terminal).


macOS & Apple Silicon (M1/M2/M3/M4) Guide

Guidonica is fully tested and optimized for macOS and Apple Silicon:

  1. Native ARM64 Architecture: pnpm-lock.yaml provides pre-resolved native @esbuild/darwin-arm64 and @rollup/rollup-darwin-arm64 binaries; pnpm install executes with zero Rosetta 2 translation.
  2. Web Audio Gesture Unlock: WebKit and Chromium browsers enforce strict autoplay restrictions on macOS. Guidonica creates and unlocks the AudioContext within the direct user gesture (clicking Start or pressing Space).
  3. 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.
  4. 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

Available Scripts

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.

Releases & Nightly

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.


Continuous Deployment & Custom Domain

This repository is configured for automated testing, building, and zero-downtime deployment to GitHub Pages via GitHub Actions.

Automated CI/CD Workflow

.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:

  1. Validation: Strictly typechecks TypeScript (tsc --noEmit) and runs all unit tests.
  2. Build: pnpm build:site builds 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.
  3. Deploy: Uploads the site and publishes it to GitHub Pages.
  4. Release: A v* tag run creates the tag's GitHub Release from its CHANGELOG.md section.
  5. Announce: After a release deploys, the announce job 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.

Custom Domain Architecture (guidonica.it)

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) and www CNAME record pointing to hand-lock.github.io.
  • CNAME File: public/CNAME specifies guidonica.it and is copied into every build. The old hand-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.

Architectural Decision Records (ADRs)

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

Contributing

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).


Contact

Bugs and feature requests go to GitHub issues.


License & Copyleft Terms

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).

Copyleft & Network Reciprocity (Section 13)

  • 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.

Dual Licensing

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".

Trademarks

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.

About

Free sight-reading & solfège practice in your browser: endless fresh sheet music scrolls past a playhead in time with a metronome.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages