Native Shell
Native Shell은 모든 플랫폼의 앱 안에서 만들어지는 AI UI입니다
notae는 기타·피아노·현악기용 SVG 코드·스케일 다이어그램을 렌더링하며 의존성이 전혀 없다
SVG chord and scale diagram renderer for fretboard, piano, and bowed instruments. Zero dependencies.
개발 도구TypeScript · JavaScriptGitHub @memoriainfinita온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기SVG chord and scale diagram renderer for fretted, keyboard and bowed instruments. Zero dependencies, 23 kb.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗SVG chord and scale diagram renderer for fretted, keyboard, and bowed instruments. Zero runtime dependencies. 23 kb compiled bundle.
notae renders publication-quality SVG diagrams directly from a chord or scale description. No canvas, no DOM manipulation, no dependencies — just a function that returns an SVG string.
// Guitar — barre chord with finger numbers
Notae.renderFretboard({
name: 'F major',
frets: [1, 3, 3, 2, 1, 1],
fingers: [1, 3, 4, 2, 1, 1],
barres: [{ fret: 1, startString: 1, endString: 6 }],
tuning: ['E', 'A', 'D', 'G', 'B', 'E'],
})
// Banjo — drone string offset, scale with multiple notes per string
Notae.renderFretboard({
name: 'G major',
frets: [[5, 7], [0, 2, 4, 5], [0, 2, 4, 5], [0, 1, 3, 5], [0, 2, 4]],
tuning: ['G', 'D', 'G', 'B', 'D'],
stringOffset: [5, 0, 0, 0, 0],
root: 'G',
}, { numFrets: 7 })
// Piano — chord with per-key colors
Notae.renderPiano({
name: 'G major',
keys: ['G3', 'B3', 'D4'],
colors: ['#cc2244', '#5aaa5a', '#4466cc'],
root: 'G',
})
// Violin — G major scale, 1st position
Notae.renderBowed({
name: 'G major',
strings: [[0, 2, 4, 5], [0, 2, 4, 5], [0, 2, 3, 5], [0, 2, 3, 5]],
numSlots: 5,
tuning: ['G', 'D', 'A', 'E'],
position: 1,
root: 'G',
})
Browser — CDN (jsDelivr)
<script src="https://cdn.jsdelivr.net/gh/memoriainfinita/notae@master/dist/notae.js"></script>
Build from source
pnpm install
pnpm run build:lib # src/index.ts → dist/notae.js (IIFE, global Notae)
pnpm run dev # watch mode for the demo
Any fretted instrument: guitar, bass, ukulele, banjo, mandolin.
renderFretboard(chord: FretboardChord, style?: StyleOptions): string
// Barre chord with finger numbers
renderFretboard({
name: 'F major',
frets: [1, 3, 3, 2, 1, 1],
fingers: [1, 3, 4, 2, 1, 1],
barres: [{ fret: 1, startString: 1, endString: 6 }],
tuning: ['E', 'A', 'D', 'G', 'B', 'E'],
root: 'F',
})
// Scale position with per-dot colors (root · third · fifth)
renderFretboard({
name: 'G major',
frets: [3, 2, 0, 0, 0, 3],
tuning: ['E', 'A', 'D', 'G', 'B', 'E'],
root: 'G',
colors: ['#cc2244', '#4466cc', null, null, '#4466cc', '#cc2244'],
})
// Scale — multiple notes per string
renderFretboard({
name: 'Am pentatonic',
frets: [[5, 8], [5, 7], [5, 7], [5, 7], [5, 8], [5, 8]],
tuning: ['E', 'A', 'D', 'G', 'B', 'E'],
baseFret: 5,
root: 'A',
}, { numFrets: 4, orientation: 'horizontal' })
// Banjo — drone string with offset
renderFretboard({
name: 'G',
frets: [5, 0, 0, 0, 0],
tuning: ['G', 'D', 'G', 'B', 'D'],
stringOffset: [5, 0, 0, 0, 0],
root: 'G',
})
FretboardChord
| Field | Type | Description |
|---|---|---|
name | string | Chord or scale name (shown above diagram) |
frets | (number | number[])[] | Fret per string; -1 = muted, 0 = open. Array for multiple notes (scales). |
fingers? | number[] | Finger number per string (0 = none) |
barres? | { fret, startString, endString }[] | Barre indicators. Strings are 1-indexed from low. |
tuning? | string[] | Open-string names, used as labels |
baseFret? | number | First fret shown — triggers fret label |
stringOffset? | number[] | Fret where each string starts (banjo drone) |
root? | string | Root note — enables showDegrees |
colors? | (string | null)[] | Per-string dot color override |
dotColors? | (string | null)[][] | Per-dot color, parallel to each string's frets; wins over colors |
dotLabels? | (string | null)[][] | Per-dot text, parallel to each string's frets; wins over degrees, names and fingers ('' = none) |
renderPiano(chord: PianoChord, style?: StyleOptions): string
// Chord with finger numbers
renderPiano({
name: 'Cmaj7',
keys: ['C4', 'E4', 'G4', 'B4'],
fingers: [1, 2, 3, 5],
root: 'C',
})
// Scale over 2 octaves
renderPiano({
name: 'Am blues',
keys: ['A3', 'C4', 'D4', 'Eb4', 'E4', 'G4', 'A4', 'C5', 'D5', 'Eb5', 'E5', 'G5'],
root: 'A',
range: { from: 'A3', to: 'G5' },
})
// Per-key colors with scale degrees
renderPiano({
name: 'F# harmonic minor',
keys: ['F#3', 'G#3', 'A3', 'B3', 'C#4', 'D4', 'F4', 'F#4'],
colors: ['#cc2244', null, '#4466cc', null, '#5aaa5a', null, null, '#cc2244'],
root: 'F#',
}, { showDegrees: true })
PianoChord
| Field | Type | Description |
|---|---|---|
name | string | Chord or scale name |
keys | string[] | Active keys, e.g. 'C4', 'Bb3', 'F#5' |
fingers? | number[] | Finger number per key |
root? | string | Root note — enables showDegrees |
range? | { from: string, to: string } | Visible range of the keyboard |
colors? | (string | null)[] | Per-key color override |
Every key <rect> carries data-note (e.g. data-note="C#4", sharp spelling), so a host can attach click handlers without depending on render order.
Violin, viola, cello — slot-based (semitones from open string).
renderBowed(chord: BowedChord, style?: StyleOptions): string
// G major scale, violin, 1st position
renderBowed({
name: 'G major',
strings: [[0, 2, 4, 5], [0, 2, 4, 5], [0, 2, 3, 5], [0, 2, 3, 5]],
numSlots: 5,
tuning: ['G', 'D', 'A', 'E'],
position: 1,
root: 'G',
})
// Position chord, horizontal layout
renderBowed({
name: 'D',
strings: [3, 2, 1, null],
fingers: [3, 2, 1, null],
tuning: ['G', 'D', 'A', 'E'],
position: 3,
}, { orientation: 'horizontal' })
BowedChord
| Field | Type | Description |
|---|---|---|
name | string | Chord or scale name |
strings | (number | number[] | null)[] | Slot per string (semitones from open). null = not played. |
fingers? | (number | null)[] | Finger number per string |
tuning? | string[] | Open-string names |
position? | number | Position indicator shown left of diagram |
numSlots? | number | Number of slots to display (default: 4) |
root? | string | Root note — enables showDegrees |
All renderers accept an optional second argument. Every field is optional.
renderFretboard(chord, {
// Colors
dotColor: '#5aaa5a',
dotTextColor: '#ffffff',
chordNameColor: '#000000',
nutColor: '#333333',
stringColor: '#aaaaaa',
fretColor: '#cccccc',
barreColor: '#5aaa5a',
// Sizes
dotRadius: 9,
stringSpacing: 19,
fretSpacing: 23,
numFrets: 5,
nutWidth: 4,
// Layout
orientation: 'vertical', // 'vertical' | 'horizontal'
leftHanded: false,
showFingerNumbers: true,
showOpenNotes: false, // fretboard: a 0 among a string's frets drawn as the open ring
showDegrees: false, // requires chord.root
showNoteNames: false, // fretboard: note name on each dot (showDegrees wins)
preferFlats: false, // spell note names with flats (Bb, not A#)
showStringLabels: true,
stringLabelMode: 'tuning', // 'tuning' | 'notes'
// String / note labels
stringLabelGap: 4, // gap between nut/fret and label text (px)
pianoNoteLabelGap: 4, // gap between piano keys and note label text (px)
bowedTickSize: 5, // length of slot tick marks on bowed diagrams (px)
fretLabelGapH: 8, // bottom padding reserve for fret label in horizontal orientation (px)
// Filter effects
filterStyle: 'clean', // 'clean' | 'shadow' | 'glow'
shadowColor: '#000000',
shadowX: 2, shadowY: 3, shadowBlur: 2, shadowOpacity: 0.25,
glowColor: '#5aaa5a', glowBlur: 2.5, glowOpacity: 0.8,
// Box
backgroundColor: 'transparent',
borderColor: 'transparent',
borderWidth: 0,
borderRadius: 0,
diagramPadding: 0,
})
Full list of defaults in src/types.ts.
notae pairs with UMT for music theory computation. UMT generates the note data; notae renders the diagram.
<script src="https://cdn.jsdelivr.net/gh/memoriainfinita/notae@master/dist/notae.js"></script>
<script src="https://cdn.jsdelivr.net/gh/memoriainfinita/[email protected]/dist/umt.js"></script>
<script>
// Chord → piano
const chord = UMT.parseChordSymbol('Cmaj9');
const keys = chord.getNotes().map(n => n.name);
document.getElementById('piano').innerHTML = Notae.renderPiano({ name: 'Cmaj9', keys });
// Chord → fretboard voicings
const voicings = UMT.getFretboardVoicings(chord, UMT.GUITAR_STANDARD);
document.getElementById('fret').innerHTML = Notae.renderFretboard({ name: 'Cmaj9', ...voicings[0] });
// Scale → fretboard positions
const scale = UMT.parseScaleSymbol('D dorian');
const boxes = UMT.getFretboardScalePositions(scale, UMT.GUITAR_STANDARD);
boxes.slice(0, 5).forEach((box, i) => {
document.getElementById('box-' + i).innerHTML = Notae.renderFretboard(
{ name: 'D dorian', ...box },
{ numFrets: 4 }
);
});
</script>
pnpm test # 70 unit tests via vitest (fretboard, piano, bowed)
GPL-3.0. See LICENSE.
Developed by @memoriainfinita with the assistance of Claude (Anthropic): Opus 4.8, Sonnet 4.6 and Haiku 4.5.