|
41335
|
My own site! by @Vizuet | Stardance
|
Vizuet
|
0
|
4.58
|
0
|
[]
|
[{"post_id": 46717, "ts": "202 [{"post_id": 46717, "ts": "2026-08-14T05:02:20Z", "hours": 1.9408, "text": "I completely new at css and html programs, but I still talikng courses the rest of this days. Good news! I ha disovered resources for begginers LIKE COMICS, COLORING BOOKS AND VIDEOS THAT OBVIOUSLY IS GOING TO APPER IN THIS WEB"}, {"post_id": 44941, "ts": "2026-08-11T01:15:57Z", "hours": 0.755, "text": "Hiiii guyss Im basically started doing my links in order to visit the images and resources for childs who want know about NASA information. NASA provides us stories, also teach us how the missions where developed."}, {"post_id": 41156, "ts": "2026-08-05T05:59:02Z", "hours": 1.8889, "text": "Is the universe providing us with evidence? What information can help us understand what is happening beyond our planet? Welcome to this mysterious but exciting page for curious teenagers! Have you ever heard the news talk about extraterrestrial life? We always think about UFOs, don’t we? But there is much more to explore! Let me discover the fascinating world of astrobiology with you. This community is a place where we can gain knowledge, explore NASA’s research, and become more confident when talking about space, life beyond Earth, and the mysteries of the universe."}]...
|
Title: My own site! by @Vizuet | Stardance
Devlog Title: My own site! by @Vizuet | Stardance
Devlogs:
Is the universe providing us with evidence? What information can help us understand what is happening beyond our planet? Welcome to this mysterious but exciting page for curious teenagers! Have you ever heard the news talk about extraterrestrial life? We always think about UFOs, don’t we? But there is much more to explore! Let me discover the fascinating world of astrobiology with you. This community is a place where we can gain knowledge, explore NASA’s research, and become more confident when talking about space, life beyond Earth, and the mysteries of the universe.
Hiiii guyss Im basically started doing my links in order to visit the images and resources for childs who want know about NASA information. NASA provides us stories, also teach us how the missions where developed.
I completely new at css and html programs, but I still talikng courses the rest of this days. Good news! I ha disovered resources for begginers LIKE COMICS, COLORING BOOKS AND VIDEOS THAT OBVIOUSLY IS GOING TO APPER IN THIS WEB...
|
1793559434.2014296
|
1794164234.2014296
|
|
28172
|
PixelOS by @Praknoor | Stardance
|
Praknoor
|
2
|
3.0
|
13
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-13T19:57:16Z", "hours": 1.0, "multiplier": 12.83, "payout": 13, "blessing": "neutral", "text": "PixelOS — Session Recap 🟣 Big update across the board: Notepad — Save As dialog with VFS directory browser + overwrite warning Glass Diary — complete redesign: lined paper background, Cedarville Cursive font, auto-saves to ~/Diary/YYYY-MM-DD.txt, calendar popup to browse entries by date Timer — countdown fixed (was a rogue resetTimer() bug), custom hr:min:sec inputs, centisecond display Pixel Editor — save/load .pxl files to VFS Terminal — fixed text shrinking when output fills the window Snake — high-score notification Top bar — overhauled: running-app taskbar with click-to-focus, SVG bell + theme icons, blinking colon clock, cleaner glass look General — all apps start closed, desktop icons removed (dock only), taskbar shows open apps Next up: more polish, more apps, more surprises.", "repo": "https://github.com/GurnoorLog/PixelOS", "demo": "https://pixel-os-pied.vercel.app/"}, {"ship_num": 2, "ts": "2026-07-04T17:45:36Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "PixelOS — os in da browser bruh wat i made: a whole desktop os that runs in ur browser. terminal boot, windows u can drag n resize, dock, desktop icons, 6 apps (wikipedia, calculator wit sin/cos/tan/log/factorial, pixel art editor, lofi radio, spotify, clock/calendar), plus customize EVERYTHING — colors, blur, rain effects, sparkles, pixel cursors. zero frameworks, zero npm, just raw html/css/js. one file each. wat was hard: flood fill in the pixel editor. had to write my own bfs from scratch cuz canvas dont do that. also making glassmorphism + pixel art not look like garbage took way too many tries. wat im proud of: literally every pixel of this thing is hand-coded. no node_modules folder, no build script, no “npm install” — just open and it goes brr. 1500 lines of pure js.", "repo": "https://github.com/GurnoorLog/PixelOS", "demo": "https://pixel-os-pied.vercel.app/"}]...
|
[{"post_id": 27872, "ts": "202 [{"post_id": 27872, "ts": "2026-07-13T19:34:50Z", "hours": 1.0486, "text": "PixelOS Updates Notifications system Terminal Notepad — Save As dialog with file browser + overwrite warning Glass Diary — Paper styling, cursive font, auto-save, calendar to browse entries by date Timer — Countdown fixed, custom hr:min:sec inputs Pixel Editor — Save/Load .pxl files to VFS Snake — High score notification More coming soon 🟣"}, {"post_id": 22276, "ts": "2026-07-04T17:39:31Z", "hours": 0.4239, "text": "Final updates: Added terminal-style boot screen Refined calculator with expression input + scientific mode (sin, cos, tan, log, sqrt, factorial)"}, {"post_id": 22248, "ts": "2026-07-04T16:54:51Z", "hours": 0.2814, "text": "PixelOS comes with 6 apps: a Wikipedia API viewer that lets you search and read articles inside the desktop, a Calculator, a Pixel Art Editor with 16×16 grid and PNG export, a Lo-Fi Cafe with direct audio streams, a Glass Diary for writing with export support, and desktop widgets (analog clock + live calendar). Every app is fully draggable, resizable, and works inside the glass window system."}, {"post_id": 22159, "ts": "2026-07-04T14:07:44Z", "hours": 1.1053, "text": "Built PixelOS with just HTML, CSS, and JavaScript — no frameworks, no build tools, no dependencies. Inspired by old-school Windows desktops mixed with retro pixel art. I wanted to prove you can make something that looks premium with vanilla code."}]...
|
Title: PixelOS by @Praknoor | Stardance
Devlogs:
Title: PixelOS by @Praknoor | Stardance
Devlogs:
Built PixelOS with just HTML, CSS, and JavaScript — no frameworks, no build tools, no dependencies. Inspired by old-school Windows desktops mixed with retro pixel art. I wanted to prove you can make something that looks premium with vanilla code.
PixelOS comes with 6 apps: a Wikipedia API viewer that lets you search and read articles inside the desktop, a Calculator, a Pixel Art Editor with 16×16 grid and PNG export, a Lo-Fi Cafe with direct audio streams, a Glass Diary for writing with export support, and desktop widgets (analog clock + live calendar). Every app is fully draggable, resizable, and works inside the glass window system.
Final updates: Added terminal-style boot screen Refined calculator with expression input + scientific mode (sin, cos, tan, log, sqrt, factorial)
PixelOS Updates Notifications system Terminal Notepad — Save As dialog with file browser + overwrite warning Glass Diary — Paper styling, cursive font, auto-save, calendar to browse entries by date Timer — Countdown fixed, custom hr:min:sec inputs Pixel Editor — Save/Load .pxl files to VFS Snake — High score notification More coming soon 🟣
Ships:
PixelOS — os in da browser bruh wat i made: a whole desktop os that runs in ur browser. terminal boot, windows u can drag n resize, dock, desktop icons, 6 apps (wikipedia, calculator wit sin/cos/tan/log/factorial, pixel art editor, lofi radio, spotify, clock/calendar), plus customize EVERYTHING — colors, blur, rain effects, sparkles, pixel cursors. zero frameworks, zero npm, just raw html/css/js. one file each. wat was hard: flood fill in the pixel editor. had to write my own bfs from scratch cuz canvas dont do that. also making glassmorphism + pixel art not look like garbage took way too many tries. wat im proud of: literally every pixel of this thing is hand-coded. no node_modules folder, no build script, no “npm install” — just open and it goes brr. 1500 lines of pure js.
PixelOS — Session Recap 🟣 Big update across the board: Notepad — Save As dialog with VFS directory browser + overwrite warning Glass Diary — complete redesign: lined paper background, Cedarville Cursive font, auto-saves to ~/Diary/YYYY-MM-DD.txt, calendar popup to browse entries by date Timer — countdown fixed (was a rogue resetTimer() bug), custom hr:min:sec inputs, centisecond display Pixel Editor — save/load .pxl files to VFS Terminal — fixed text shrinking when output fills the window Snake — high-score notification Top bar — overhauled: running-app taskbar with click-to-focus, SVG bell + theme icons, blinking colon clock, cleaner glass look General — all apps start closed, desktop icons removed (dock only), taskbar shows open apps Next up: more polish, more apps, more surprises....
|
1793559435.3484504
|
1793645835.3484504
|
|
41336
|
My very own WebOS by @leela_saha | Stardance
|
leela_saha
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My very own WebOS by @leela_saha | Stardanc Title: My very own WebOS by @leela_saha | Stardance...
|
1793559436.572619
|
1794164236.572619
|
|
41337
|
My awesome macropad! by @ishaan22 | Stardance
|
ishaan22
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @ishaan22 | Stardan Title: My awesome macropad! by @ishaan22 | Stardance...
|
1793559437.4757316
|
1794164237.4757316
|
|
41338
|
DAY MAKER by @moganti_nehanth | Stardance
|
moganti_nehanth
|
0
|
1.98
|
0
|
[]
|
[{"post_id": 40124, "ts": "202 [{"post_id": 40124, "ts": "2026-08-03T14:56:12Z", "hours": 1.4489, "text": "continuing after college"}, {"post_id": 36832, "ts": "2026-07-29T04:19:05Z", "hours": 0.5322, "text": "working on the todo list part first, hoping to create first then modify"}]...
|
Title: DAY MAKER by @moganti_nehanth | Stardance
Title: DAY MAKER by @moganti_nehanth | Stardance
Devlogs:
working on the todo list part first, hoping to create first then modify
continuing after college...
|
1793559438.36324
|
1794164238.36324
|
|
41339
|
My very own WebOS by @Anonymous | Stardance
|
Anonymous
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My very own WebOS by @Anonymous | Stardance
|
1793559440.3976414
|
1794164240.3976414
|
|
41340
|
My awesome macropad! by @aryankumar_1st | Stardanc My awesome macropad! by @aryankumar_1st | Stardance...
|
aryankumar_1st
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @aryankumar_1st | S Title: My awesome macropad! by @aryankumar_1st | Stardance...
|
1793559442.981686
|
1794164242.981686
|
|
41342
|
Untitled project by @nshriniketan | Stardance
|
nshriniketan
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Untitled project by @nshriniketan | Stardan Title: Untitled project by @nshriniketan | Stardance...
|
1793559443.866816
|
1794164243.866816
|
|
41343
|
My awesome macropad! by @amyT | Stardance
|
amyT
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @amyT | Stardance
|
1793559445.9251654
|
1794164245.9251654
|
|
17830
|
UTAU.js by @NellowTCS | Stardance
|
NellowTCS
|
1
|
21.0
|
349
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-18T06:38:31Z", "hours": 21.0, "multiplier": 17.25, "payout": 349, "blessing": "neutral", "text": "I built UTAU.js, a fully synthetic singing voice engine that runs in the browser using pure DSP instead of samples or AI. It supports English, Japanese, and Mandarin, and it can import almost every major vocal synth format through a unified score system. The demo includes a piano roll editor, real-time streaming playback, voice presets, and a full set of controls for shaping the glottal source and formant model. I am proud of the coarticulation system, the pitch bend renderer, and the fact that the entire engine sings from math alone. You can try the demo, draw notes, type lyrics, and hear it perform immediately!!!!!!!!!!", "repo": "https://github.com/NellowTCS/UTAU.js", "demo": "https://nellowtcs.me/UTAU.js/"}]...
|
[{"post_id": 11132, "ts": "202 [{"post_id": 11132, "ts": "2026-06-18T06:36:00Z", "hours": 0.2928, "text": "v0.1.0 Well Stardance told me this: Warning You have 1h 14m logged that you haven't posted a devlog for. If you ship without posting a devlog, this time will be lost! IDK why, but i was planning to devlog my silly anyways so: five commits. all tagged v0.1.0. all fixing things that should have been done before I said “the project is ready.” the classic “wait I forgot” sequence. “Oops” - CI was trying to build docs without running npm ci first. added the install step. three words of actual code change. (this was wrong) “Huh. where did that come from.” - the pages deploy was creating a docs/ directory but the docs copy was still commented out. the demo was deploying fine but docs were going nowhere. fixed the mkdir. “Oooops guess who forgot to uncomment some code” - uncommented the actual docs copy in static.yml. also fixed the docs URL from nisoku.org (wrong domain) to nellowtcs.me/UTAU.js/docs. details. “You never saw that coming did you /sarc” - added all the npm publish metadata to package.json. license, author, repository, homepage, bugs URL, and keywords. the keywords are: utau, synthesis, singing, voice, speech, audio, dsp, lf-glottal, source-filter, formant. so if you npm search for any of those things, maybe you’ll find this. someday. (NPM release failed lol, that’s why I did this) “Badges hehe” - npm version badge, CI status badge, MIT license badge at the top of the README. because a project isn’t real until it has badges. everyone knows that. (/j) five commits to go from “done” to actually done. four of them are CI fixes. like i just said, this is software development. CI is green. docs are deployed. npm metadata is set. badges are shiny. v0.1.0 is tagged. so. that’s UTAU.js. six days. from “idk my voice tho” in an Obsidian doc to a parametric singing synthesizer with three languages, 14+ import/export formats, a Svelte demo app, a docs site, 160+ tests, and a v0.1.0 tag. it sounds mid. like, genuinely. the vowels are recognizable but the consonants are strange and the whole thing has this uncanny valley quality where you can tell it’s trying to be a voice but isn’t quite there. it’s really adorable when it tries :3 but it makes sound. from math. in a browser. and that’s the whole point of v0.1.0. it doesn’t have to be good. it has to exist. it exists now. :)"}, {"post_id": 11120, "ts": "2026-06-18T05:56:37Z", "hours": 1.6403, "text": "the docs exist and the README isn’t “Web-Template” anymore so uh. the README has said “Web-Template: My typical web dev starter project” for the entire life of this repo. six days. dozens of commits. a full synthesizer. and the README was still introducing it as a starter template. fixed that. also wrote an entire documentation site. in one sitting. because apparently that’s how I do things now. the README 133 lines replacing the 3-line placeholder. features list, quickstart code (Node.js WAV rendering + browser streaming in like 10 lines each), API overview table with every public export, development instructions, and a Mermaid architecture diagram. the mermaid diagram is a mindmap and it renders SO PRETTY on GitHub. multicolored branches for Core DSP, Languages, Synth, Voices, and IO. each branch fans out into its components. it’s AMAZINGGGGGGGGGGG I spent way too long picking which mermaid diagram type to use and I regret nothing. the docs site ten markdown pages built with DocMD. custom Ruby theme with blue/cyan gradient accents, dark mode support, semantic search via HuggingFace transformers, and a proper navigation structure: getting started : quickstart (5-step guide with code), installation (npm/CDN/source), core concepts (source-filter model explanation with a Mermaid flowchart showing glottal source -> formant cascade -> output) guide : architecture (module layout, data flow diagram, design decisions), renderer (6-step pipeline walkthrough from lyric to audio), languages (built-in language docs + how to register custom languages + cross-language aliasing) API reference : full export table, DSP primitives with code examples, VoiceConfig reference (264 lines of parameter documentation with perceptual effect tables for every single field. “openQuotient 0.3 = pressed tense voice, 0.5 = neutral modal voice, 0.7 = breathy soft voice.” that kind of detail.), import/export format support table the VoiceConfig page alone is probably the most thorough documentation of a formant synthesizer’s parameter space I’ve ever seen in a JS library. I might be biased. I’ve not seen many others. We don’t talk about that. also added UST and TSSLN to the export format list (they were import-only before). fixed the export function to handle generators that return arrays instead of single Uint8Arrays. CI workflows now build and audit the docs workspace too. the TODO is almost empty. just “README: quickstart, API overview, architecture diagram” which is now done. the project has: a synthesizer, three languages, 14+ import formats, 14+ export formats, a demo app with a piano roll, voice presets, undo/redo, settings, file import/export, WAV export, tempo control, buffer management, 160+ tests, JSDoc on everything, a full documentation site, and CI that’s green. six days :O"}, {"post_id": 11091, "ts": "2026-06-18T04:09:58Z", "hours": 0.5989, "text": "the documentation commit (part 1) JSDoc everywhere this is the kind of commit where the line count looks impressive and the actual behavior changes are zero. 118 lines became 216 lines in types.ts alone. every interface, every field, every function got documented. some highlights: (don’t ask why i did a double dash. i was being silly and just noticed somehow idk how) openQuotient : “fraction of the glottal cycle the vocal folds are open. Higher values produce a breathier, softer sound (0.2–0.9)” speedQuotient : “ratio of the opening phase to the closing phase. Higher values give a faster closure, increasing brightness (0.3–3.0)” FormantCascade : “cascade of anti-resonators followed by resonators, modelling the vocal-tract transfer function. Anti-resonators (zeros) come first, followed by resonators (poles), matching the source-filter model: S(f) = G(f) * Z(f) / P(f)” LFGlottalSource : “Liljencrants-Fant (LF) glottal pulse source with jitter, shimmer, aspiration noise, and DC blocking. See Fant (1986), Liljencrants (1985)” renderNote : documents the full pipeline: “lyric -> phoneme symbols -> phoneme lookup -> LF glottal pulse -> formant cascade -> noise mix -> amplitude envelope -> normalisation” every DSP class, every language module, every player method, every import/export function. the person reading this code in six months (probably me) will thank me. docs soon Docs next time, I will not be long heheeee TODO cleanup the languages section is fully checked off now. English CMUDict (124,911 words), Japanese EDICT2 (224,808 kanji-to-kana entries), Mandarin with full pinyin decomposition, and phoneme alias maps for cross-language compatibility. all done. all in previous commits I apparently forgot to devlog. oops. reorganized the remaining items: Documentation (JSDoc done, README and docs site still needed) and Future (scroll-to-playhead, seek, loop, Web Worker rendering). the TODO is getting short. that’s a weird feeling for a project that’s six days old."}, {"post_id": 11073, "ts": "2026-06-18T03:30:48Z", "hours": 3.4428, "text": "567,211 lines of “code” so about that line count. I added the CMU Pronouncing Dictionary as a git submodule. 134,000+ English words with their ARPABET pronunciations. the cmudict repo is… large. like, genuinely enormous. the diff says 567k lines and it’s almost entirely a text file of words and their phoneme sequences. the actual code changes across these four commits? probably 280 lines. the submodule? 567,131 lines. software engineering. the real G2P Build/data/cmudict is now a submodule pointing to cmusphinx/cmudict. this is THE pronunciation dictionary. the one that every TTS and speech recognition system uses. “BEAUTIFUL” -> “B Y UW1 T AH0 F AH0 L”. “SQUIRREL” -> “S K W ER1 AH0 L”. every word, every pronunciation variant, every stress marker. the 100-word hand-rolled dictionary was cute. this is the real thing. (chunk size warning in vite went from 500 to 13000 because bundling the dictionary is… yeah.) glottal pulse fix the LF glottal source had an audible click on every single cycle. the return phase (after the glottis closes) was a bare exponential decay: -exp(-epsilon * x * period) . the problem: it starts at -1 with non-zero slope, so at the boundary between cycles there’s a discontinuity. click. every. cycle. fix: multiply by sin(pi * x) . the sine term makes the slope match the open phase at t=te (C1 continuity) and reach 0 at t=tc. smooth transition. no click. this is how the actual LF model paper describes it but I’d skipped the sine modulation the first time around because I thought it was just cosmetic. it was not cosmetic. also killed the 0.8/0.2 smoothing filter. it was supposed to prevent clicks but was actually just low-passing the glottal pulse and adding phase distortion. the DC blocker handles drift on its own. coefficient went from 0.995 to 0.99 for faster response. renderer performance formant coefficient updates were happening every sample. that’s setFormants() with trig functions 44,100 times per second. formants don’t actually change that fast. throttled to every 5ms (221 samples at 44.1k). no audible difference, meaningful CPU savings. cascade reset came back at phoneme boundaries. I removed it two commits ago thinking filter state carryover was smoother. it is smoother, but it also causes wideband clicks when the coefficients jump. the reset is the right call. aspiration lowpass aspiration noise on vowels was full-spectrum white noise. real breathy voice has most of its noise energy below 4kHz. added a one-pole lowpass at 4kHz on the aspiration path. sounds warmer and less harsh. also re-added parallel filter resets at phoneme boundaries (matched the cascade reset fix). signal quality tests new test category: signal quality. a long 8-beat note must stay in [-1, 1], be finite throughout, and not be dominated by white noise. the “not white noise” check uses a crude HF proxy: ratio of RMS(sample-to-sample difference) to RMS(signal) in the steady state portion. pure white noise scores ~1.4, a clean tonal signal scores ~0.2. test asserts between 0.05 and 0.8. wrote these tests because the glottal fix could have easily introduced NaN propagation or DC drift and I wanted to catch it automatically."}, {"post_id": 10947, "ts": "2026-06-17T23:12:38Z", "hours": 7.0989, "text": "four commits, and failure I did not intend to do all of this in one sitting. and yet. player batching + buffer pool the player was creating a new AudioBuffer for every single chunk. for a 100-note score that’s 200 buffer allocations (stereo) plus 200 BufferSourceNodes. the garbage collector was not happy. rewrote the scheduling layer. chunks now accumulate into batches (~0.5s each) and get merged into a single AudioBuffer per channel before scheduling. acquireBuffer() checks a pool of previously used buffers by sampleRate and length before allocating new ones. onended releases them back to the pool. pre-buffer threshold bumped to 1.0s for more runway. the result: way fewer Web Audio nodes, way less GC pressure, smoother playback on longer scores. japanese UTAU compatibility imported UST files from real UTAU projects were breaking because Japanese has a bunch of special lyric conventions I didn’t handle: っ (sokuon) : geminate consonant marker. maps to a new sil (silence) phoneme. ※ (pronunciation alias) : text after ※ is the actual pronunciation. あ※ka uses “ka” not “あ”. dot-prefixed lyrics ( .sil , .S ): UTAU rest/silence commands. treated as empty. @ and % : stripped. @ also acts as a note-join marker in the renderer: if present, the initial consonant gets suppressed so the vowel carries through from the previous note. also removed the cascade.reset() between phonemes. filter state now carries through for smoother formant transitions instead of clicking at every phoneme boundary. settings panel new SettingsPanel.svelte . modal overlay, dark theme, closes on Escape or click-outside. currently has one setting: auto-scroll toggle (for a future scroll-to-playhead feature). settings gear icon in the header bar. undo/redo integrated undora for undo/redo history. 50-state capacity. snapshots are saved on mouse-up in the piano roll, delete key, pitch point changes, and lyric/note-number edits (on blur, not on every keystroke). Ctrl/Cmd+Z to undo. Ctrl/Cmd+Shift+Z or Ctrl/Cmd+Y to redo. Undo2 and Redo2 icons in the header bar, disabled when there’s nothing to undo/redo. history clears on language switch and file import. the formatting commit ran prettier again. removed a dead MIN_POOL_SIZE constant and an unused import. cleaned up a few TODO items. the usual. scrollToNotes also got a fix: it was centering on the midpoint of all notes which looked weird when the first note started late. now it clamps to the start of the earliest note so you always see the beginning. also I tried to fix the hissing and static and clicking but to no avail. i tried fixing a LOT of stuff. but. sadly ir only made things worse, so I had to retry. and retry. and retry. and retry. with no luck I’m not sure what the problem is tbh. Let me use Satori to debug some stuff ig"}, {"post_id": 8849, "ts": "2026-06-14T18:34:21Z", "hours": 1.2458, "text": "making it sound less terrible (two commits, one mission) these two commits are about one thing: the output was robotic and buzzy and I was tired of it. every change here is about making the synthesizer sound more like a voice and less like a modem. the renderer got smarter cross-note co-articulation. renderNote() now returns { chunk, finalFormants } . the stream passes the previous note’s final formants into the next note’s renderer, and the first phoneme interpolates from those formants instead of jumping cold. gaps between notes reset the chain. notes that follow each other seamlessly now blend their formants across the boundary. per-phoneme envelopes. the old global 5ms attack / 10ms release is gone. replaced with getPhonemeEnvelopeSamples() which gives each phoneme type its own envelope: plosives get 2ms attack / 15ms decay (sharp burst), consonants and vowels get 5ms / 3ms. every phoneme segment fades independently. diphthong formant sweeping. PhonemeDef got an endFormants field. if a diphthong has both formants and endFormants , the renderer sweeps between them over the phoneme duration. AY now actually glides from /aa/ to /ih/. EY glides from /eh/ to /ih/. OW glides from /oh/ to /uh/. they sound like diphthongs now instead of static vowels. vibratoOverride. was defined on Note but never read. now it is. per-note vibrato control works. everything got retuned glottal source. added shimmer (per-cycle amplitude variation driven by jitter, so the volume wobbles slightly like a real voice). aspiration noise is now high-pass filtered (subtract a lowpass from the raw noise) so it’s airy instead of muddy. aspiration gain bumped from 0.1 to 0.15. plosive bursts. noise envelope for plosives changed from symmetric fade to a fast 12ms exponential decay. “pa” now sounds like a burst instead of a pop. formant data for everything. Z, ZH, V, DH, Y, W, HH, JH in English all got formant targets. same for z, h, y, w, j in Japanese. consonants that were previously just noise bursts now resonate through the vocal tract. the difference is huge. vowel bandwidths tightened. defaults went from 80/100/120 to 70/90/130 Hz. narrower bandwidths = sharper resonant peaks = more vowel-like quality. voice presets retuned. male voice: lower open quotient (0.4), lower speed quotient (0.65), higher tenseness (0.65), less aspiration (0.05). sounds less breathy, more chest voice. female: formant scale 1.18. gender slider in scaleVoice now affects speed quotient and has a gender-dependent tenseness base. pitch accent. Japanese got resolveAccents() implementing heiban pattern (low first mora, high rest). the stream groups consecutive notes into phrases, calls resolveAccents, and applies the offsets as constant pitch shifts. it’s basic but it makes Japanese phrases have some melodic contour beyond what the score provides. four TODO items checked off in one go: co-articulation, phoneme envelopes, diphthong sweeping, vibratoOverride. pitch accent too. it still doesn’t sound human. but it’s starting to sound like it’s trying. and that’s a big step from where it was. if you can identify the song in the editor image, good job, you’re cool :D"}, {"post_id": 8467, "ts": "2026-06-14T02:23:14Z", "hours": 1.0867, "text": "CI arc (three commits, one story) three commits that are really one story: getting CI from “permanently red” to green. the setup “wrote” (aka copied and modified) six GitHub Actions workflows in one go: ci.yml : lint + test + build on push/PR. matrix tests Node 20 and 22. builds the library first, then typechecks the demo. (docs build is commented out because docs don’t exist yet. they will. eventually.) test.yml : dedicated test runner. same Node 20/22 matrix. runs jest in the Build workspace. release-npm.yml : publishes to npm on GitHub release. strips private/scripts/devDependencies from package.json, copies README and LICENSE into Build/, publishes with --provenance . has a workflow_dispatch with a dry-run option so I can test without actually publishing. security-audit.yml : runs npm audit --audit-level=high on all three workspaces (root, Build, Demo). daily cron plus on push when package files change. static.yml : reworked the GitHub Pages deployment. it was pointed at Build/dist (wrong, that’s the library output). now it builds the library, builds the demo, and deploys Demo/dist as the pages root. docs will go in pages-root/docs/ when they exist. single-file.yml : was still referencing Web-Template (the old template name). fixed to point at Demo, output file is now UTAUjsEditor.html. also integrated Updato (my own auto-updater library) into the demo. on load it checks the current build hash against the latest commit on main and shows an update notification if there’s a newer version. the build hash gets injected at build time via __BUILD_HASH__ in the vite config. cleaned up the TODO: removed all the completed checkboxes (they were cluttering the file), added detail to the remaining items. the fixes CI was 0/3 passing. then 1/8 passing. then 2/8. then eventually 8/8. the classic experience. the single-file and updato workflows needed the library built before the demo (workspace dependency). added npm ci at root level and a “Build Library” step before the demo build. also added vite-plugin-singlefile and cross-env for the build:single script. second fix commit added ts-node and unrun as dev deps because the ESM config loading was unhappy without them. three commits to go from red to green. could be worse honestly but whatever"}, {"post_id": 8388, "ts": "2026-06-13T23:00:15Z", "hours": 0.6642, "text": "the prettier commit (and a tiny bugfix) two commits. one has 19 lines of actual code. the other touched every single file in the project. the bugfix the piano roll’s resize handle wasn’t working for already-selected notes. you could resize on first click, but if you clicked a note to select it and THEN tried to drag the right edge, it would move the note instead of resizing. added a resize zone check that fires before the drag-to-move handler when a note is already selected. 19 lines. the formatting pass ran prettier on the entire codebase. every file. the diff is enormous and the actual logic changes are: zero. added .prettierrc (semicolons, double quotes, trailing commas, 140 char width, svelte plugin), .prettierignore , and eslint.config.ts . bumped eslint to 10.5 and typescript-eslint to 8.61. added jiti for ESM config loading. the one real improvement buried in here: replaced the Function type in ufdata.ts with a proper ParseFn type alias. eslint was right to yell at me for using bare Function . everything else is semicolons and line breaks. the codebase has a consistent style now. that’s the whole commit. sometimes you just gotta."}, {"post_id": 8353, "ts": "2026-06-13T21:40:48Z", "hours": 0.5894, "text": "open any vocal synth file ever made so you know how the TODO said “MIDI file import” as one little checkbox? I may have slightly exceeded scope on that one. UTAU.js can now import UST, USTX, VPR, VSQX, VSQ, SVP, MIDI, MusicXML, PPSF, S5P, TSSLN, CCS, DV, and UFData files. that’s UTAU, OpenUTAU, Vocaloid, Synthesizer V, Piapro Studio, CeVIO, DeepVocal, and standard MIDI. basically every vocal synth format that exists. this is thanks to utaformatix-ts by sevenc-nanashi, which is a universal parser for vocal synth project files. it converts everything into a common UfData format. I wrote a 145-line adapter ( ufdata.ts ) that converts UfData into UTAU.js Scores. lazy-loaded so the parser only gets pulled in when you actually import a file. pitch bends this was the hard part. vocal synth files have pitch curves. track-level arrays of tick-value pairs that describe how the pitch deviates from the written note. the importer splits the track-level curve into per-note pitch bends, handling absolute-to-relative conversion, null value filtering, start/end padding, and extrapolation from preceding points. the renderer now reads note.pitchBend and interpolates it per-sample alongside vibrato. the math: f0 = baseF0 * 2^((bendSemitones * 100 + vibratoCents) / 1200) . pitch bends and vibrato stack correctly in cents space. piano roll overhaul the piano roll was hardcoded to 3 octaves (ik bad, but will fix soon) and a fixed width. now it covers the full MIDI range (0-127) with virtual scrolling. wheel scrolls vertically, shift+wheel or trackpad scrolls horizontally. viewport culling so only visible notes and key labels get drawn. auto-scrolls to center on notes when you import a file. also: pitch curves render as yellow lines overlaid on note blocks. you can see the imported pitch data right there on the piano roll. other stuff added await setTimeout(0) in the streaming loop so the UI doesn’t freeze during long scores. the demo has an “Open” button that accepts all 14 supported file extensions. TODO got updated with a lot of checkboxes ticked. Some amount of lines of import tests covering note mapping, tempo conversion, pitch splitting (absolute, relative, null filtering, extrapolation, out-of-range skipping, pitch:false opt-out), and edge cases."}, {"post_id": 8316, "ts": "2026-06-13T20:40:13Z", "hours": 0.7764, "text": "uhhh tests (that was fast huh) the commit message says it all. 961 lines added. 10 test files. plus a WAV encoder, a bunch of bug fixes, and the entire player got an upgrade. in one sitting. tests jest config, ts-jest, ESM mode. ten test files covering everything that exists: envelope.test.ts : attack/release shape, mixBuffers offset and gain, edge cases filter.test.ts : FormantFilter resonator, FormantCascade noise.test.ts : NoiseSource output oscillator.test.ts : LFGlottalSource waveform shape wav.test.ts : encodeWav RIFF header english.test.ts : lexicon hits and fallback japanese.test.ts : hiragana, romaji, special cases renderer.test.ts : renderNote output shape, sample count, non-zero output stream.test.ts : streamScore chunk boundaries, mixChunks voices/index.test.ts : buildVoice, scaleVoice parameter ranges writing tests found bugs. writing tests always finds bugs. the bugs tests found OW was missing. the English phoneme table had every ARPABET vowel except OW. “HELLO” ends with OW. the demo word was literally broken and I didn’t notice because the fallback produced silence instead of crashing. added it. F1=470 F2=1000 F3=2400. anti-resonator formula was wrong. the pole radius was hardcoded to 0.99 with a random 0.95 frequency offset. now it derives the pole from bw * 1.5 like a real anti-resonator should. nasals sound less terrible. jitter was per-sample. it was recalculating a random f0 every single sample, which made the pitch wobble chaotically instead of naturally. moved it to recalculate once per glottal cycle. much more realistic. noise fadeout could go negative. phDur - segPos - 1 can be negative at the boundary. clamped to 0. gain normalization could divide by zero. clamped overallPeak to 1e-6 and gain to max 100. buildVoice spread order was wrong. ...overrides was before the sub-objects, so the glottal/formant/vibrato defaults always overwrote user values. flipped the order. WAV encoder (i’ve written manual WAV encoders before, I just copy-pasted that, it’s not that bad tbh) 62 lines. encodeWav() takes AudioChunks and writes a proper RIFF/WAVE file. 16-bit PCM, little-endian, handles mono and stereo. float-to-int16 conversion with clamping. exported from the barrel file. player upgrades setVolume() API. volume parameter on play() . progress events actually fire now (the type existed but was never emitted). stop does a 50ms gain ramp to zero before closing the AudioContext so it doesn’t click. scheduling uses Math.max(ctx.currentTime + 0.01, ...) to prevent scheduling in the past if rendering falls behind. stream tempo handling streamScore() was using a single currentTempo for the whole note. now it has tempoAt() for point lookups and noteSampleDuration() that integrates across tempo changes within a note. a note that spans a tempo change gets the right duration now. also added a cascade reset between phonemes in the renderer (was carrying filter state across phoneme boundaries causing ringing), added a missing phoneme console.warn so you can actually debug G2P failures, and fixed the Japanese romaji parser to skip spaces instead of treating them as unknown consonants. the TODO list is getting shorter. slowly but surely. …and i forgot to update it oops"}, {"post_id": 8294, "ts": "2026-06-13T19:45:25Z", "hours": 1.8264, "text": "it makes sound now okay so. I may have blacked out and written an entire synthesizer in one commit. 210 lines of renderer, 65 lines of streaming, a full Svelte demo app with a piano roll, and a dozen DSP fixes. this is flo-era hyperfocus energy except I can HEAR it this time. (well I could hear flo, it’s a audio format, so like, duh, but yk what i mean loll) the renderer renderNote() takes a Note + VoiceConfig + LanguageModule and produces actual audio. per-sample processing: vibrato with attack ramp, 30ms smoothstep formant interpolation between phonemes, glottal pulse through the cascade, shaped noise for consonants with per-segment fade in/out, smoothstep attack/release envelope, peak normalization. consonants get their default duration, vowels split the remaining time. if consonants would eat more than 40% of the note they get compressed. every filter, oscillator, and cascade got refactored from batch to per-sample. slower but I can morph formants sample-by-sample for smooth transitions. DSP fixes (there were several) the LF oscillator’s open phase was inverted. added a DC blocking filter because the pulse was making everything drift. added jitter for natural-sounding pitch variation. the resonator gain formula was wrong ( b0 = 1 - r*r should be b0 = 1 - B - C ). FormantCascade now runs anti-resonators before resonators (correct order for nasals). added setPassthrough() for unused filter slots. female formant scale went from 0.88 to 1.15. I had it backwards. scaling down shrinks the tract and sounds childlike. scaling up is what you want. streaming + demo streamScore() is an async generator. walks the score note by note, handles tempo changes, yields chunks. player starts playing before the score finishes rendering. the demo is a full Svelte 5 app. canvas piano roll (click to create, drag to move/resize, delete to remove), voice panel with easy sliders + expandable advanced params, transport bar, language switcher. Japanese demo says “ka na ta shi i ne”. English says “HELLO WORLD THIS IS A TEST”. press play and it synthesizes through Web Audio in real time. from math. everything else Japanese plosives got formant data (were noise-only). added “l” as an r-alias for loanwords. barrel file exports the full public API. wrote a comprehensive TODO.md because the list of things that aren’t done is very long. it sounds terrible. robotic and buzzy and the consonants are more like clicks. but it’s SOUND. generated from MATH. in a BROWSER. Peterson and Barney would be proud. (or horrified.)"}, {"post_id": 7973, "ts": "2026-06-13T09:17:37Z", "hours": 0.3825, "text": "voices, a player, and oh look a demo app three things in one commit because I couldn’t decide which to work on so I did all of them. voice presets two built-in voices: Male and Female. the male voice has a lower open quotient (0.45, vocal folds close faster), lower aspiration (0.08, less breathy), and formant scale of 1.0. the female voice has higher open quotient (0.55), more aspiration (0.12), and formant scale of 0.88 which shifts all the formant frequencies up to simulate a shorter vocal tract. vibrato differs too. male is 5.5 Hz rate with 30 cents depth. female is 6.0 Hz with 40 cents. these are rough averages from the singing voice literature. real vibrato varies wildly between singers but you have to start somewhere. buildVoice() lets you construct a custom voice with partial overrides. scaleVoice() is the fun one. it takes a voice config and five intuitive sliders: gender (-1 to +1), breathiness, tension, brightness, vibratoAmount. the gender parameter interpolates formant scale between 0.88 and 1.0. breathiness maps to open quotient and aspiration. tension maps to glottal tenseness. brightness maps to formant bandwidth (narrower bandwidths = brighter, more resonant sound). vibrato amount scales depth. the idea is you start with a preset and then tweak it with human-readable parameters instead of raw acoustic values. “make this voice breathier” is easier to think about than “increase open quotient to 0.55 and aspiration to 0.12”. registry pattern same as languages. getVoice(\"male\") , registerVoice(\"my-voice\", config) . stream player this is the thing that actually makes sound come out of your speakers. StreamPlayer takes an AsyncGenerator<AudioChunk> and schedules the audio through the Web Audio API. each chunk gets turned into an AudioBuffer, wired through a GainNode (fixed at 0.8 for now), and scheduled at its exact start time using ctx.currentTime + chunk.startSample / sampleRate . the generator can yield chunks as fast or as slow as it wants. the player just keeps scheduling them. async generator as the interface is the key design decision. the synthesizer can stream audio chunk by chunk as it renders each phoneme, and the player starts playing before the whole score is done. no waiting for the full render. just start. pause suspends the AudioContext. resume resumes it. stop aborts the generator via AbortController and closes the context. event system emits stateChange, progress, done, error. on() returns an unsubscribe function. clean lifecycle. the demo app svelte 5 + vite. the Demo/ workspace finally has code in it. just scaffolding for now, no UI components yet. but the package.json is wired up: utaujs as a workspace dependency so it pulls from the Build/ output, @sveltejs /vite-plugin-svelte, vite 8. I picked svelte because it’s the lightest framework that still gives me reactivity and components without a virtual DOM. for a music app where audio timing matters, I don’t want React’s reconciliation cycle anywhere near my render loop. svelte compiles to vanilla JS. no runtime overhead. (also I just like svelte.) the engine is almost wirable end to end now. language module produces phonemes, voice config provides the acoustic parameters, the DSP layer renders audio chunks, the stream player schedules them through Web Audio. the only missing piece is the actual synthesizer that takes a Score + Voice + Language and yields AudioChunks. that’s next. getting close to hearing actual sound."}, {"post_id": 7955, "ts": "2026-06-13T08:49:48Z", "hours": 0.6944, "text": "two languages walk into a synthesizer… so I said “next step is a basic ARPABET phoneme dictionary” and then I just… did both English AND Japanese in one sitting. because apparently my brain doesn’t know how to do things incrementally. english every phoneme in ARPABET, with real formant data from real papers. I’m going to be responsible and cite my sources (gasp): vowel formants are Peterson & Barney 1952 male speaker means. the classic dataset. 76 speakers, 10 monophthongal vowels. /IY/ is F1=270 F2=2290 F3=3010. /AA/ is F1=730 F2=1090 F3=2440. these numbers are from a 74-year-old paper and they’re still the standard reference. wild. consonant noise centres follow Jongman et al. 2000 for fricatives (sibilant spectral peaks), Stevens 1998 for plosive burst loci, and Fujimura 1962 for nasal formants/antiformants. I feel like an actual phonetician typing these citations. I am not an actual phonetician. the full set: 10 vowels, 4 diphthongs, 6 plosives, 9 fricatives, 3 nasals, 4 approximants, 2 affricates. every consonant has its noise shaping config. every nasal has antiformant data. every vowel has 5 formant targets (F1 through F5). there’s also a grapheme-to-phoneme dictionary with like 100 common English words. “HELLO” -> [“HH”, “EH”, “L”, “OW”]. “BEAUTIFUL” -> [“B”, “Y”, “UW”, “T”, “IH”, “F”, “UH”, “L”]. it’s a smol subset but it covers the words you’d actually want a singing synthesizer to say. sun, moon, star, dream, love, forever, together. very anime opening core vocabulary. I should expand it eventually but it’s fine for testing. the fallback for unknown words is fun: first it checks if the input is already ARPABET symbols separated by spaces/underscores. if not, it falls back to a dead simple single-character mapping where each letter gets one phoneme. it’s terrible but it won’t crash. japanese honestly? mapping Japanese to phonemes is SO much easier than English. kana are basically a syllabary. each character maps to exactly one consonant-vowel pair (or just a vowel). no ambiguity. no “through” being pronounced nothing like it looks. English is a disaster and Japanese is a joy. (I still don’t know Japanese. sighhh. but the internet is very helpful.) vowel formants are from Yazawa & Kondo 2019, specifically the short-vowel midpoint averages for male speakers from their ICPhS paper. that Japanese vowel formant displacement paper I was reading earlier today. /a/ F1=687 F2=1283, /i/ F1=301 F2=2154, etc. F3 values come from Kitamura et al. 2009, the ATR MRI vocal tract study. different paper, different research group, but the F3 data fills a gap that Yazawa didn’t cover in detail. the lyric parser handles: raw romaji (“ka”, “shi”, “tsu”), hiragana (あ, き, しゃ), and compound kana (きゃ, しゅ, ちょ). hiragana gets converted to romaji via a lookup table, then romaji gets split into consonant-vowel pairs via romajiToPhonemes() . special cases for し -> “shi”, ち -> “chi”, つ -> “tsu”, ふ -> “fu”. word-final ん becomes the moraic nasal N. geminate consonants (double letters) get handled. it’s not perfect but it covers standard Hepburn romanisation. the registry a Map of language IDs to modules. getLanguage(\"en\") or getLanguage(\"jp\") . registerLanguage() for future additions. both “jp” and “ja” point to Japanese because people use both and I’m not going to pick a side. the LanguageModule interface from types.ts is earning its keep already. both languages implement the same lyricToPhonemes() contract. the synthesizer won’t know or care which language is active. plug in English, plug in Japanese, plug in anything. the architecture handles it. I love this."}, {"post_id": 7946, "ts": "2026-06-13T08:00:27Z", "hours": 0.9586, "text": "new project. yes, another one. (penumbra is on pause btw) so uh. hi. I’m starting a new thing. penumbra is on pause. not abandoned, just… paused. the backend is solid, the architecture is clean, and the UI needs to catch up but I need to do the HTML mockup thing first and I’m not in the headspace for that right now. it’ll come back. I promise. in the meantime: UTAU.js. the idea: a browser-based singing synthesizer inspired by UTAU. but here’s the thing. it’s not sample-based like the original. it’s parametric. formant synthesis. generate the entire voice from math. no voicebank files, no platform dependencies, no 200MB sample libraries. just DSP and physics and the human vocal tract modeled in TypeScript. why TypeScript and not Rust this time? because. I scaffolded the repo from my Web-Template and then immediately ripped out everything that made it a web template. I replaced it with a proper library setup: tsdown for bundling (ESM + CJS + type declarations), npm workspaces (Build for the engine, Demo for a future demo app), TypeScript strict mode. renamed to utaujs. added jest, eslint, prettier, typescript-eslint. the foundation is there. also brought in @nisoku /satori as a dependency because I’ll want observability later and I might as well wire it up now. And like, it’s such a great observatory library like smh my head, why wouldn’t I use it the research rabbit hole (aka I read way too many papers) okay so today was one of those days where hackatime probably says like less than a hour but reality says 4-5. I spent most of half of today reading. papers. reference tables. phonetics Wikipedia articles. I have 20 browser tabs open right now (thank goodness for tab groups) and they’re all about formants and audio and human vocal behaviors. here’s the reading list: Peterson & Barney 1952 (a classic formant frequency dataset, 76 speakers, 10 American English vowels, F0 through F3) the Stanford CCRMA formant table (Peterson’s data averaged by gender and age group, the numbers everyone cites) ARPABET (the phonetic notation system CMU uses, 39 phonemes for General American English) CMU Pronouncing Dictionary (134,000+ words mapped to ARPABET, sheesh) a paper on Japanese vowel formant displacement (short vs long vowels have different formant targets, which matters a lot) Kitamura et al on vocal tract transfer functions from MRI-derived solid models (they literally 3D printed vocal tracts and measured the acoustic response) the MRI one is wild. they took volumetric MRI scans of people saying Japanese vowels, built physical 3D models of their vocal tracts via stereolithography, and then measured the frequency response by pumping sound through the models. but I also wrote code I remember a LOT of this from working on flo. types.ts is the big one. 91 lines of the full type stuff oscillator.ts is the glottal source. an LF (Liljencrants-Fant) model. this is the buzzing sound your vocal folds make before your throat and mouth shape it into speech. lots of math that i don’t want to talk about. filter.ts is the formant cascade. second-order IIR resonator (biquad) that can operate as either a resonator or anti-resonator. noise.ts is simple. white noise generator plus a function to shape it through formant resonators. this is how you get consonants like “s” and “sh”. they’re just filtered noise. envelope.ts is attack/release shaping with smoothstep curves plus a buffer mixing utility. Fun!"}]...
|
Title: UTAU.js by @NellowTCS | Stardance
Devlogs: Title: UTAU.js by @NellowTCS | Stardance
Devlogs:
new project. yes, another one. (penumbra is on pause btw) so uh. hi. I’m starting a new thing. penumbra is on pause. not abandoned, just… paused. the backend is solid, the architecture is clean, and the UI needs to catch up but I need to do the HTML mockup thing first and I’m not in the headspace for that right now. it’ll come back. I promise. in the meantime: UTAU.js. the idea: a browser-based singing synthesizer inspired by UTAU. but here’s the thing. it’s not sample-based like the original. it’s parametric. formant synthesis. generate the entire voice from math. no voicebank files, no platform dependencies, no 200MB sample libraries. just DSP and physics and the human vocal tract modeled in TypeScript. why TypeScript and not Rust this time? because. I scaffolded the repo from my Web-Template and then immediately ripped out everything that made it a web template. I replaced it with a proper library setup: tsdown for bundling (ESM + CJS + type declarations), npm workspaces (Build for the engine, Demo for a future demo app), TypeScript strict mode. renamed to utaujs. added jest, eslint, prettier, typescript-eslint. the foundation is there. also brought in @nisoku /satori as a dependency because I’ll want observability later and I might as well wire it up now. And like, it’s such a great observatory library like smh my head, why wouldn’t I use it the research rabbit hole (aka I read way too many papers) okay so today was one of those days where hackatime probably says like less than a hour but reality says 4-5. I spent most of half of today reading. papers. reference tables. phonetics Wikipedia articles. I have 20 browser tabs open right now (thank goodness for tab groups) and they’re all about formants and audio and human vocal behaviors. here’s the reading list: Peterson & Barney 1952 (a classic formant frequency dataset, 76 speakers, 10 American English vowels, F0 through F3) the Stanford CCRMA formant table (Peterson’s data averaged by gender and age group, the numbers everyone cites) ARPABET (the phonetic notation system CMU uses, 39 phonemes for General American English) CMU Pronouncing Dictionary (134,000+ words mapped to ARPABET, sheesh) a paper on Japanese vowel formant displacement (short vs long vowels have different formant targets, which matters a lot) Kitamura et al on vocal tract transfer functions from MRI-derived solid models (they literally 3D printed vocal tracts and measured the acoustic response) the MRI one is wild. they took volumetric MRI scans of people saying Japanese vowels, built physical 3D models of their vocal tracts via stereolithography, and then measured the frequency response by pumping sound through the models. but I also wrote code I remember a LOT of this from working on flo. types.ts is the big one. 91 lines of the full type stuff oscillator.ts is the glottal source. an LF (Liljencrants-Fant) model. this is the buzzing sound your vocal folds make before your throat and mouth shape it into speech. lots of math that i don’t want to talk about. filter.ts is the formant cascade. second-order IIR resonator (biquad) that can operate as either a resonator or anti-resonator. noise.ts is simple. white noise generator plus a function to shape it through formant resonators. this is how you get consonants like “s” and “sh”. they’re just filtered noise. envelope.ts is attack/release shaping with smoothstep curves plus a buffer mixing utility. Fun!
two languages walk into a synthesizer… so I said “next step is a basic ARPABET phoneme dictionary” and then I just… did both English AND Japanese in one sitting. because apparently my brain doesn’t know how to do things incrementally. english every phoneme in ARPABET, with real formant data from real papers. I’m going to be responsible and cite my sources (gasp): vowel formants are Peterson & Barney 1952 male speaker means. the classic dataset. 76 speakers, 10 monophthongal vowels. /IY/ is F1=270 F2=2290 F3=3010. /AA/ is F1=730 F2=1090 F3=2440. these numbers are from a 74-year-old paper and they’re still the standard reference. wild. consonant noise centres follow Jongman et al. 2000 for fricatives (sibilant spectral peaks), Stevens 1998 for plosive burst loci, and Fujimura 1962 for nasal formants/antiformants. I feel like an actual phonetician typing these citations. I am not an actual phonetician. the full set: 10 vowels, 4 diphthongs, 6 plosives, 9 fricatives, 3 nasals, 4 approximants, 2 affricates. every consonant has its noise shaping config. every nasal has antiformant data. every vowel has 5 formant targets (F1 through F5). there’s also a grapheme-to-phoneme dictionary with like 100 common English words. “HELLO” -> [“HH”, “EH”, “L”, “OW”]. “BEAUTIFUL” -> [“B”, “Y”, “UW”, “T”, “IH”, “F”, “UH”, “L”]. it’s a smol subset but it covers the words you’d actually want a singing synthesizer to say. sun, moon, star, dream, love, forever, together. very anime opening core vocabulary. I should expand it eventually but it’s fine for testing. the fallback for unknown words is fun: first it checks if the input is already ARPABET symbols separated by spaces/underscores. if not, it falls back to a dead simple single-character mapping where each letter gets one phoneme. it’s terrible but it won’t crash. japanese honestly? mapping Japanese to phonemes is SO much easier than English. kana are basically a syllabary. each character maps to exactly one consonant-vowel pair (or just a vowel). no ambiguity. no “through” being pronounced nothing like it looks. English is a disaster and Japanese is a joy. (I still don’t know Japanese. sighhh. but the internet is very helpful.) vowel formants are from Yazawa & Kondo 2019, specifically the short-vowel midpoint averages for male speakers from their ICPhS paper. that Japanese vowel formant displacement paper I was reading earlier today. /a/ F1=687 F2=1283, /i/ F1=301 F2=2154, etc. F3 values come from Kitamura et al. 2009, the ATR MRI vocal tract study. different paper, different research group, but the F3 data fills a gap that Yazawa didn’t cover in detail. the lyric parser handles: raw romaji (“ka”, “shi”, “tsu”), hiragana (あ, き, しゃ), and compound kana (きゃ, しゅ, ちょ). hiragana gets converted to romaji via a lookup table, then romaji gets split into consonant-vowel pairs via romajiToPhonemes() . special cases for し -> “shi”, ち -> “chi”, つ -> “tsu”, ふ -> “fu”. word-final ん becomes the moraic nasal N. geminate consonants (double letters) get handled. it’s not perfect but it covers standard Hepburn romanisation. the registry a Map of language IDs to modules. getLanguage("en") or getLanguage("jp") . registerLanguage() for future additions. both “jp” and “ja” point to Japanese because people use both and I’m not going to pick a side. the LanguageModule interface from types.ts is earning its keep already. both languages implement the same lyricToPhonemes() contract. the synthesizer won’t know or care which language is active. plug in English, plug in Japanese, plug in anything. the architecture handles it. I love this.
voices, a player, and oh look a demo app three things in one commit because I couldn’t decide which to work on so I did all of them. voice presets two built-in voices: Male and Female. the male voice has a lower open quotient (0.45, vocal folds close faster), lower aspiration (0.08, less breathy), and formant scale of 1.0. the female voice has higher open quotient (0.55), more aspiration (0.12), and formant scale of 0.88 which shifts all the formant frequencies up to simulate a shorter vocal tract. vibrato differs too. male is 5.5 Hz rate with 30 cents depth. female is 6.0 Hz with 40 cents. these are rough averages from the singing voice literature. real vibrato varies wildly between singers but you have to start somewhere. buildVoice() lets you construct a custom voice with partial overrides. scaleVoice() is the fun one. it takes a voice config and five intuitive sliders: gender (-1 to +1), breathiness, tension, brightness, vibratoAmount. the gender parameter interpolates formant scale between 0.88 and 1.0. breathiness maps to open quotient and aspiration. tension maps to glottal tenseness. brightness maps to formant bandwidth (narrower bandwidths = brighter, more resonant sound). vibrato amount scales depth. the idea is you start with a preset and then tweak it with human-readable parameters instead of raw acoustic values. “make this voice breathier” is easier to think about than “increase open quotient to 0.55 and aspiration to 0.12”. registry pattern same as languages. getVoice("male") , registerVoice("my-voice", config) . stream player this is the thing that actually makes sound come out of your speakers. StreamPlayer takes an AsyncGenerator<AudioChunk> and schedules the audio through the Web Audio API. each chunk gets turned into an AudioBuffer, wired through a GainNode (fixed at 0.8 for now), and scheduled at its exact start time using ctx.currentTime + chunk.startSample / sampleRate . the generator can yield chunks as fast or as slow as it wants. the player just keeps scheduling them. async generator as the interface is the key design decision. the synthesizer can stream audio chunk by chunk as it renders each phoneme, and the player starts playing before the whole score is done. no waiting for the full render. just start. pause suspends the AudioContext. resume resumes it. stop aborts the generator via AbortController and closes the context. event system emits stateChange, progress, done, error. on() returns an unsubscribe function. clean lifecycle. the demo app svelte 5 + vite. the Demo/ workspace finally has code in it. just scaffolding for now, no UI components yet. but the package.json is wired up: utaujs as a workspace dependency so it pulls from the Build/ output, @sveltejs /vite-plugin-svelte, vite 8. I picked svelte because it’s the lightest framework that still gives me reactivity and components without a virtual DOM. for a music app where audio timing matters, I don’t want React’s reconciliation cycle anywhere near my render loop. svelte compiles to vanilla JS. no runtime overhead. (also I just like svelte.) the engine is almost wirable end to end now. language module produces phonemes, voice config provides the acoustic parameters, the DSP layer renders audio chunks, the stream player schedules them through Web Audio. the only missing piece is the actual synthesizer that takes a Score + Voice + Language and yields AudioChunks. that’s next. getting close to hearing actual sound.
it makes sound now okay so. I may have blacked out and written an entire synthesizer in one commit. 210 lines of renderer, 65 lines of streaming, a full Svelte demo app with a piano roll, and a dozen DSP fixes. this is flo-era hyperfocus energy except I can HEAR it this time. (well I could hear flo, it’s a audio format, so like, duh, but yk what i mean loll) the renderer renderNote() takes a Note + VoiceConfig + LanguageModule and produces actual audio. per-sample processing: vibrato with attack ramp, 30ms smoothstep formant interpolation between phonemes, glottal pulse through the cascade, shaped noise for consonants with per-segment fade in/out, smoothstep attack/release envelope, peak normalization. consonants get their default duration, vowels split the remaining time. if consonants would eat more than 40% of the note they get compressed. every filter, oscillator, and cascade got refactored from batch to per-sample. slower but I can morph formants sample-by-sample for smooth transitions. DSP fixes (there were several) the LF oscillator’s open phase was inverted. added a DC blocking filter because the pulse was making everything drift. added jitter for natural-sounding pitch variation. the resonator gain formula was wrong ( b0 = 1 - r*r should be b0 = 1 - B - C ). FormantCascade now runs anti-resonators before resonators (correct order for nasals). added setPassthrough() for unused filter slots. female formant scale went from 0.88 to 1.15. I had it backwards. scaling down shrinks the tract and sounds childlike. scaling up is what you want. streaming + demo streamScore() is an async generator. walks the score note by note, handles tempo changes, yields chunks. player starts playing before the score finishes rendering. the demo is a full Svelte 5 app. canvas piano roll (click to create, drag to move/resize, delete to remove), voice panel with easy sliders + expandable advanced params, transport bar, language switcher. Japanese demo says “ka na ta shi i ne”. English says “HELLO WORLD THIS IS A TEST”. press play and it synthesizes through Web Audio in real time. from math. everything else Japanese plosives got formant data (were noise-only). added “l” as an r-alias for loanwords. barrel file exports the full public API. wrote a comprehensive TODO.md because the list of things that aren’t done is very long. it sounds terrible. robotic and buzzy and the consonants are more like clicks. but it’s SOUND. generated from MATH. in a BROWSER. Peterson and Barney would be proud. (or horrified.)
uhhh tests (that was fast huh) the commit message says it all. 961 lines added. 10 test files. plus a WAV encoder, a bunch of bug fixes, and the entire player got an upgrade. in one sitting. tests jest config, ts-jest, ESM mode. ten test files covering everything that exists: envelope.test.ts : attack/release shape, mixBuffers offset and gain, edge cases filter.test.ts : FormantFilter resonator, FormantCascade noise.test.ts : NoiseSource output oscillator.test.ts : LFGlottalSource waveform shape wav.test.ts : encodeWav RIFF header english.test.ts : lexicon hits and fallback japanese.test.ts : hiragana, romaji, special cases renderer.test.ts : renderNote output shape, sample count, non-zero output stream.test.ts : streamScore chunk boundaries, mixChunks voices/index.test.ts : buildVoice, scaleVoice parameter ranges writing tests found bugs. writing tests always finds bugs. the bugs tests found OW was missing. the English phoneme table had every ARPABET vowel except OW. “HELLO” ends with OW. the demo word was literally broken and I didn’t notice because the fallback produced silence instead of crashing. added it. F1=470 F2=1000 F3=2400. anti-resonator formula was wrong. the pole radius was hardcoded to 0.99 with a random 0.95 frequency offset. now it derives the pole from bw * 1.5 like a real anti-resonator should. nasals sound less terrible. jitter was per-sample. it was recalculating a random f0 every single sample, which made the pitch wobble chaotically instead of naturally. moved it to recalculate once per glottal cycle. much more realistic. noise fadeout could go negative. phDur - segPos - 1 can be negative at the boundary. clamped to 0. gain normalization could divide by zero. clamped overallPeak to 1e-6 and gain to max 100. buildVoice spread order was wrong. ...overrides was before the sub-objects, so the glottal/formant/vibrato defaults always overwrote user values. flipped the order. WAV encoder (i’ve written manual WAV encoders before, I just copy-pasted that, it’s not that bad tbh) 62 lines. encodeWav() takes AudioChunks and writes a proper RIFF/WAVE file. 16-bit PCM, little-endian, handles mono and stereo. float-to-int16 conversion with clamping. exported from the barrel file. player upgrades setVolume() API. volume parameter on play() . progress events actually fire now (the type existed but was never emitted). stop does a 50ms gain ramp to zero before closing the AudioContext so it doesn’t click. scheduling uses Math.max(ctx.currentTime + 0.01, ...) to prevent scheduling in the past if rendering falls behind. stream tempo handling streamScore() was using a single currentTempo for the whole note. now it has tempoAt() for point lookups and noteSampleDuration() that integrates across tempo changes within a note. a note that spans a tempo change gets the right duration now. also added a cascade reset between phonemes in the renderer (was carrying filter state across phoneme boundaries causing ringing), added a missing phoneme console.warn so you can actually debug G2P failures, and fixed the Japanese romaji parser to skip spaces instead of treating them as unknown consonants. the TODO list is getting shorter. slowly but surely. …and i forgot to update it oops
open any vocal synth file ever made so you know how the TODO said “MIDI file import” as one little checkbox? I may have slightly exceeded scope on that one. UTAU.js can now import UST, USTX, VPR, VSQX, VSQ, SVP, MIDI, MusicXML, PPSF, S5P, TSSLN, CCS, DV, and UFData files. that’s UTAU, OpenUTAU, Vocaloid, Synthesizer V, Piapro Studio, CeVIO, DeepVocal, and standard MIDI. basically every vocal synth format that exists. this is thanks to utaformatix-ts by sevenc-nanashi, which is a universal parser for vocal synth project files. it converts everything into a common UfData format. I wrote a 145-line adapter ( ufdata.ts ) that converts UfData into UTAU.js Scores. lazy-loaded so the parser only gets pulled in when you actually import a file. pitch bends this was the hard part. vocal synth files have pitch curves. track-level arrays of tick-value pairs that describe how the pitch deviates from the written note. the importer splits the track-level curve into per-note pitch bends, handling absolute-to-relative conversion, null value filtering, start/end padding, and extrapolation from preceding points. the renderer now reads note.pitchBend and interpolates it per-sample alongside vibrato. the math: f0 = baseF0 * 2^((bendSemitones * 100 + vibratoCents) / 1200) . pitch bends and vibrato stack correctly in cents space. piano roll overhaul the piano roll was hardcoded to 3 octaves (ik bad, but will fix soon) and a fixed width. now it covers the full MIDI range (0-127) with virtual scrolling. wheel scrolls vertically, shift+wheel or trackpad scrolls horizontally. viewport culling so only visible notes and key labels get drawn. auto-scrolls to center on notes when you import a file. also: pitch curves render as yellow lines overlaid on note blocks. you can see the imported pitch data right there on the piano roll. other stuff added await setTimeout(0) in the streaming loop so the UI doesn’t freeze during long scores. the demo has an “Open” button that accepts all 14 supported file extensions. TODO got updated with a lot of checkboxes ticked. Some amount of lines of import tests covering note mapping, tempo conversion, pitch splitting (absolute, relative, null filtering, extrapolation, out-of-range skipping, pitch:false opt-out), and edge cases.
the prettier commit (and a tiny bugfix) two commits. one has 19 lines of actual code. the other touched every single file in the project. the bugfix the piano roll’s resize handle wasn’t working for already-selected notes. you could resize on first click, but if you clicked a note to select it and THEN tried to drag the right edge, it would move the note instead of resizing. added a resize zone check that fires before the drag-to-move handler when a note is already selected. 19 lines. the formatting pass ran prettier on the entire codebase. every file. the diff is enormous and the actual logic changes are: zero. added .prettierrc (semicolons, double quotes, trailing commas, 140 char width, svelte plugin), .prettierignore , and eslint.config.ts . bumped eslint to 10.5 and typescript-eslint to 8.61. added jiti for ESM config loading. the one real improvement buried in here: replaced the Function type in ufdata.ts with a proper ParseFn type alias. eslint was right to yell at me for using bare Function . everything else is semicolons and line breaks. the codebase has a consistent style now. that’s the whole commit. sometimes you just gotta.
CI arc (three commits, one story) three commits that are really one story: getting CI from “permanently red” to green. the setup “wrote” (aka copied and modified) six GitHub Actions workflows in one go: ci.yml : lint + test + build on push/PR. matrix tests Node 20 and 22. builds the library first, then typechecks the demo. (docs build is commented out because docs don’t exist yet. they will. eventually.) test.yml : dedicated test runner. same Node 20/22 matrix. runs jest in the Build workspace. release-npm.yml : publishes to npm on GitHub release. strips private/scripts/devDependencies from package.json, copies README and LICENSE into Build/, publishes with --provenance . has a workflow_dispatch with a dry-run option so I can test without actually publishing. security-audit.yml : runs npm audit --audit-level=high on all three workspaces (root, Build, Demo). daily cron plus on push when package files change. static.yml : reworked the GitHub Pages deployment. it was pointed at Build/dist (wrong, that’s the library output). now it builds the library, builds the demo, and deploys Demo/dist as the pages root. docs will go in pages-root/docs/ when they exist. single-file.yml : was still referencing Web-Template (the old template name). fixed to point at Demo, output file is now UTAUjsEditor.html. also integrated Updato (my own auto-updater library) into the demo. on load it checks the current build hash against the latest commit on main and shows an update notification if there’s a newer version. the build hash gets injected at build time via __BUILD_HASH__ in the vite config. cleaned up the TODO: removed all the completed checkboxes (they were cluttering the file), added detail to the remaining items. the fixes CI was 0/3 passing. then 1/8 passing. then 2/8. then eventually 8/8. the classic experience. the single-file and updato workflows needed the library built before the demo (workspace dependency). added npm ci at root level and a “Build Library” step before the demo build. also added vite-plugin-singlefile and cross-env for the build:single script. second fix commit added ts-node and unrun as dev deps because the ESM config loading was unhappy without them. three commits to go from red to green. could be worse honestly but whatever
making it sound less terrible (two commits, one mission) these two commits are about one thing: the output was robotic and buzzy and I was tired of it. every change here is about making the synthesizer sound more like a voice and less like a modem. the renderer got smarter cross-note co-articulation. renderNote() now returns { chunk, finalFormants } . the stream passes the previous note’s final formants into the next note’s renderer, and the first phoneme interpolates from those formants instead of jumping cold. gaps between notes reset the chain. notes that follow each other seamlessly now blend their formants across the boundary. per-phoneme envelopes. the old global 5ms attack / 10ms release is gone. replaced with getPhonemeEnvelopeSamples() which gives each phoneme type its own envelope: plosives get 2ms attack / 15ms decay (sharp burst), consonants and vowels get 5ms / 3ms. every phoneme segment fades independently. diphthong formant sweeping. PhonemeDef got an endFormants field. if a diphthong has both formants and endFormants , the renderer sweeps between them over the phoneme duration. AY now actually glides from /aa/ to /ih/. EY glides from /eh/ to /ih/. OW glides from /oh/ to /uh/. they sound like diphthongs now instead of static vowels. vibratoOverride. was defined on Note but never read. now it is. per-note vibrato control works. everything got retuned glottal source. added shimmer (per-cycle amplitude variation driven by jitter, so the volume wobbles slightly like a real voice). aspiration noise is now high-pass filtered (subtract a lowpass from the raw noise) so it’s airy instead of muddy. aspiration gain bumped from 0.1 to 0.15. plosive bursts. noise envelope for plosives changed from symmetric fade to a fast 12ms exponential decay. “pa” now sounds like a burst instead of a pop. formant data for everything. Z, ZH, V, DH, Y, W, HH, JH in English all got formant targets. same for z, h, y, w, j in Japanese. consonants that were previously just noise bursts now resonate through the vocal tract. the difference is huge. vowel bandwidths tightened. defaults went from 80/100/120 to 70/90/130 Hz. narrower bandwidths = sharper resonant peaks = more vowel-like quality. voice presets retuned. male voice: lower open quotient (0.4), lower speed quotient (0.65), higher tenseness (0.65), less aspiration (0.05). sounds less breathy, more chest voice. female: formant scale 1.18. gender slider in scaleVoice now affects speed quotient and has a gender-dependent tenseness base. pitch accent. Japanese got resolveAccents() implementing heiban pattern (low first mora, high rest). the stream groups consecutive notes into phrases, calls resolveAccents, and applies the offsets as constant pitch shifts. it’s basic but it makes Japanese phrases have some melodic contour beyond what the score provides. four TODO items checked off in one go: co-articulation, phoneme envelopes, diphthong sweeping, vibratoOverride. pitch accent too. it still doesn’t sound human. but it’s starting to sound like it’s trying. and that’s a big step from where it was. if you can identify the song in the editor image, good job, you’re cool :D
four commits, and failure I did not intend to do all of this in one sitting. and yet. player batching + buffer pool the player was creating a new AudioBuffer for every single chunk. for a 100-note score that’s 200 buffer allocations (stereo) plus 200 BufferSourceNodes. the garbage collector was not happy. rewrote the scheduling layer. chunks now accumulate into batches (~0.5s each) and get merged into a single AudioBuffer per channel before scheduling. acquireBuffer() checks a pool of previously used buffers by sampleRate and length before allocating new ones. onended releases them back to the pool. pre-buffer threshold bumped to 1.0s for more runway. the result: way fewer Web Audio nodes, way less GC pressure, smoother playback on longer scores. japanese UTAU compatibility imported UST files from real UTAU projects were breaking because Japanese has a bunch of special lyric conventions I didn’t handle: っ (sokuon) : geminate consonant marker. maps to a new sil (silence) phoneme. ※ (pronunciation alias) : text after ※ is the actual pronunciation. あ※ka uses “ka” not “あ”. dot-prefixed lyrics ( .sil , .S ): UTAU rest/silence commands. treated as empty. @ and % : stripped. @ also acts as a note-join marker in the renderer: if present, the initial consonant gets suppressed so the vowel carries through from the previous note. also removed the cascade.reset() between phonemes. filter state now carries through for smoother formant transitions instead of clicking at every phoneme boundary. settings panel new SettingsPanel.svelte . modal overlay, dark theme, closes on Escape or click-outside. currently has one setting: auto-scroll toggle (for a future scroll-to-playhead feature). settings gear icon in the header bar. undo/redo integrated undora for undo/redo history. 50-state capacity. snapshots are saved on mouse-up in the piano roll, delete key, pitch point changes, and lyric/note-number edits (on blur, not on every keystroke). Ctrl/Cmd+Z to undo. Ctrl/Cmd+Shift+Z or Ctrl/Cmd+Y to redo. Undo2 and Redo2 icons in the header bar, disabled when there’s nothing to undo/redo. history clears on language switch and file import. the formatting commit ran prettier again. removed a dead MIN_POOL_SIZE constant and an unused import. cleaned up a few TODO items. the usual. scrollToNotes also got a fix: it was centering on the midpoint of all notes which looked weird when the first note started late. now it clamps to the start of the earliest note so you always see the beginning. also I tried to fix the hissing and static and clicking but to no avail. i tried fixing a LOT of stuff. but. sadly ir only made things worse, so I had to retry. and retry. and retry. and retry. with no luck I’m not sure what the problem is tbh. Let me use Satori to debug some stuff ig
567,211 lines of “code” so about that line count. I added the CMU Pronouncing Dictionary as a git submodule. 134,000+ English words with their ARPABET pronunciations. the cmudict repo is… large. like, genuinely enormous. the diff says 567k lines and it’s almost entirely a text file of words and their phoneme sequences. the actual code changes across these four commits? probably 280 lines. the submodule? 567,131 lines. software engineering. the real G2P Build/data/cmudict is now a submodule pointing to cmusphinx/cmudict. this is THE pronunciation dictionary. the one that every TTS and speech recognition system uses. “BEAUTIFUL” -> “B Y UW1 T AH0 F AH0 L”. “SQUIRREL” -> “S K W ER1 AH0 L”. every word, every pronunciation variant, every stress marker. the 100-word hand-rolled dictionary was cute. this is the real thing. (chunk size warning in vite went from 500 to 13000 because bundling the dictionary is… yeah.) glottal pulse fix the LF glottal source had an audible click on every single cycle. the return phase (after the glottis closes) was a bare exponential decay: -exp(-epsilon * x * period) . the problem: it starts at -1 with non-zero slope, so at the boundary between cycles there’s a discontinuity. click. every. cycle. fix: multiply by sin(pi * x) . the sine term makes the slope match the open phase at t=te (C1 continuity) and reach 0 at t=tc. smooth transition. no click. this is how the actual LF model paper describes it but I’d skipped the sine modulation the first time around because I thought it was just cosmetic. it was not cosmetic. also killed the 0.8/0.2 smoothing filter. it was supposed to prevent clicks but was actually just low-passing the glottal pulse and adding phase distortion. the DC blocker handles drift on its own. coefficient went from 0.995 to 0.99 for faster response. renderer performance formant coefficient updates were happening every sample. that’s setFormants() with trig functions 44,100 times per second. formants don’t actually change that fast. throttled to every 5ms (221 samples at 44.1k). no audible difference, meaningful CPU savings. cascade reset came back at phoneme boundaries. I removed it two commits ago thinking filter state carryover was smoother. it is smoother, but it also causes wideband clicks when the coefficients jump. the reset is the right call. aspiration lowpass aspiration noise on vowels was full-spectrum white noise. real breathy voice has most of its noise energy below 4kHz. added a one-pole lowpass at 4kHz on the aspiration path. sounds warmer and less harsh. also re-added parallel filter resets at phoneme boundaries (matched the cascade reset fix). signal quality tests new test category: signal quality. a long 8-beat note must stay in [-1, 1], be finite throughout, and not be dominated by white noise. the “not white noise” check uses a crude HF proxy: ratio of RMS(sample-to-sample difference) to RMS(signal) in the steady state portion. pure white noise scores ~1.4, a clean tonal signal scores ~0.2. test asserts between 0.05 and 0.8. wrote these tests because the glottal fix could have easily introduced NaN propagation or DC drift and I wanted to catch it automatically.
the documentation commit (part 1) JSDoc everywhere this is the kind of commit where the line count looks impressive and the actual behavior changes are zero. 118 lines became 216 lines in types.ts alone. every interface, every field, every function got documented. some highlights: (don’t ask why i did a double dash. i was being silly and just noticed somehow idk how) openQuotient : “fraction of the glottal cycle the vocal folds are open. Higher values produce a breathier, softer sound (0.2–0.9)” speedQuotient : “ratio of the opening phase to the closing phase. Higher values give a faster closure, increasing brightness (0.3–3.0)” FormantCascade : “cascade of anti-resonators followed by resonators, modelling the vocal-tract transfer function. Anti-resonators (zeros) come first, followed by resonators (poles), matching the source-filter model: S(f) = G(f) * Z(f) / P(f)” LFGlottalSource : “Liljencrants-Fant (LF) glottal pulse source with jitter, shimmer, aspiration noise, and DC blocking. See Fant (1986), Liljencrants (1985)” renderNote : documents the full pipeline: “lyric -> phoneme symbols -> phoneme lookup -> LF glottal pulse -> formant cascade -> noise mix -> amplitude envelope -> normalisation” every DSP class, every language module, every player method, every import/export function. the person reading this code in six months (probably me) will thank me. docs soon Docs next time, I will not be long heheeee TODO cleanup the languages section is fully checked off now. English CMUDict (124,911 words), Japanese EDICT2 (224,808 kanji-to-kana entries), Mandarin with full pinyin decomposition, and phoneme alias maps for cross-language compatibility. all done. all in previous commits I apparently forgot to devlog. oops. reorganized the remaining items: Documentation (JSDoc done, README and docs site still needed) and Future (scroll-to-playhead, seek, loop, Web Worker rendering). the TODO is getting short. that’s a weird feeling for a project that’s six days old.
the docs exist and the README isn’t “Web-Template” anymore so uh. the README has said “Web-Template: My typical web dev starter project” for the entire life of this repo. six days. dozens of commits. a full synthesizer. and the README was still introducing it as a starter template. fixed that. also wrote an entire documentation site. in one sitting. because apparently that’s how I do things now. the README 133 lines replacing the 3-line placeholder. features list, quickstart code (Node.js WAV rendering + browser streaming in like 10 lines each), API overview table with every public export, development instructions, and a Mermaid architecture diagram. the mermaid diagram is a mindmap and it renders SO PRETTY on GitHub. multicolored branches for Core DSP, Languages, Synth, Voices, and IO. each branch fans out into its components. it’s AMAZINGGGGGGGGGGG I spent way too long picking which mermaid diagram type to use and I regret nothing. the docs site ten markdown pages built with DocMD. custom Ruby theme with blue/cyan gradient accents, dark mode support, semantic search via HuggingFace transformers, and a proper navigation structure: getting started : quickstart (5-step guide with code), installation (npm/CDN/source), core concepts (source-filter model explanation with a Mermaid flowchart showing glottal source -> formant cascade -> output) guide : architecture (module layout, data flow diagram, design decisions), renderer (6-step pipeline walkthrough from lyric to audio), languages (built-in language docs + how to register custom languages + cross-language aliasing) API reference : full export table, DSP primitives with code examples, VoiceConfig reference (264 lines of parameter documentation with perceptual effect tables for every single field. “openQuotient 0.3 = pressed tense voice, 0.5 = neutral modal voice, 0.7 = breathy soft voice.” that kind of detail.), import/export format support table the VoiceConfig page alone is probably the most thorough documentation of a formant synthesizer’s parameter space I’ve ever seen in a JS library. I might be biased. I’ve not seen many others. We don’t talk about that. also added UST and TSSLN to the export format list (they were import-only before). fixed the export function to handle generators that return arrays instead of single Uint8Arrays. CI workflows now build and audit the docs workspace too. the TODO is almost empty. just “README: quickstart, API overview, architecture diagram” which is now done. the project has: a synthesizer, three languages, 14+ import formats, 14+ export formats, a demo app with a piano roll, voice presets, undo/redo, settings, file import/export, WAV export, tempo control, buffer management, 160+ tests, JSDoc on everything, a full documentation site, and CI that’s green. six days :O
v0.1.0 Well Stardance told me this: Warning You have 1h 14m logged that you haven't posted a devlog for. If you ship without posting a devlog, this time will be lost! IDK why, but i was planning to devlog my silly anyways so: five commits. all tagged v0.1.0. all fixing things that should have been done before I said “the project is ready.” the classic “wait I forgot” sequence. “Oops” - CI was trying to build docs without running npm ci first. added the install step. three words of actual code change. (this was wrong) “Huh. where did that come from.” - the pages deploy was creating a docs/ directory but the docs copy was still commented out. the demo was deploying fine but docs were going nowhere. fixed the mkdir. “Oooops guess who forgot to uncomment some code” - uncommented the actual docs copy in static.yml. also fixed the docs URL from nisoku.org (wrong domain) to nellowtcs.me/UTAU.js/docs. details. “You never saw that coming did you /sarc” - added all the npm publish metadata to package.json. license, author, repository, homepage, bugs URL, and keywords. the keywords are: utau, synthesis, singing, voice, speech, audio, dsp, lf-glottal, source-filter, formant. so if you npm search for any of those things, maybe you’ll find this. someday. (NPM release failed lol, that’s why I did this) “Badges hehe” - npm version badge, CI status badge, MIT license badge at the top of the README. because a project isn’t real until it has badges. everyone knows that. (/j) five commits to go from “done” to actually done. four of them are CI fixes. like i just said, this is software development. CI is green. docs are deployed. npm metadata is set. badges are shiny. v0.1.0 is tagged. so. that’s UTAU.js. six days. from “idk my voice tho” in an Obsidian doc to a parametric singing synthesizer with three languages, 14+ import/export formats, a Svelte demo app, a docs site, 160+ tests, and a v0.1.0 tag. it sounds mid. like, genuinely. the vowels are recognizable but the consonants are strange and the whole thing has this uncanny valley quality where you can tell it’s trying to be a voice but isn’t quite there. it’s really adorable when it tries :3 but it makes sound. from math. in a browser. and that’s the whole point of v0.1.0. it doesn’t have to be good. it has to exist. it exists now. :)
Ships:
I built UTAU.js, a fully synthetic singing voice engine that runs in the browser using pure DSP instead of samples or AI. It supports English, Japanese, and Mandarin, and it can import almost every major vocal synth format through a unified score system. The demo includes a piano roll editor, real-time streaming playback, voice presets, and a full set of controls for shaping the glottal source and formant model. I am proud of the coarticulation system, the pitch bend renderer, and the fact that the entire engine sings from math alone. You can try the demo, draw notes, type lyrics, and hear it perform immediately!!!!!!!!!!...
|
1793559453.6125157
|
1793645853.6125157
|
|
41345
|
genaral kenobi by @parshvgoyal | Stardance
|
parshvgoyal
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: genaral kenobi by @parshvgoyal | Stardance
|
1793559454.8916423
|
1794164254.8916423
|
|
41346
|
My first slack bot! by @easpecht09 | Stardance
|
easpecht09
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @easpecht09 | Starda Title: My first slack bot! by @easpecht09 | Stardance...
|
1793559455.784605
|
1794164255.784605
|
|
41347
|
Parcus Cosmos by @esvin_hernandez35 | Stardance
|
esvin_hernandez35
|
0
|
17.29
|
0
|
[]
|
[{"post_id": 47244, "ts": "202 [{"post_id": 47244, "ts": "2026-08-15T01:16:17Z", "hours": 5.3944, "text": "Finally finished the roller coaster, all of the aesthetics, and the roof top viewing of all the props used. I now have to just finish the GitHub, accrediting all of the models I used. I lost access to the VR headset I was using, so this is where I will ship it, but I might be able to get access soon again. (Don’t be surprised if I keep updating after this ship ;p )"}, {"post_id": 37781, "ts": "2026-07-30T18:16:47Z", "hours": 8.2844, "text": "I have edited the template, added new materials. Added a couch and other items to make it look cozier. Deleted the OG rock climbing wall to make more space for the roller coaster (The Red rocket following the balck lines with blue dots). I haven’t quite finished making the roller coaster functional, but I have decorated the slingshot, making it knock down UFO’s instead of Bullseye targets. I added a staircase to connect to the top, with the ferris wheel. And I added new material skins to the whack-a-mole like game"}, {"post_id": 36821, "ts": "2026-07-29T03:40:06Z", "hours": 3.6158, "text": "I’m currently working on the park entrance and aesthetics. I don’t really know much about the vr world to start from scratch, So I borrowed a template that unity provides. I am currently in the process of clearing it up and making it according to theme, as well as adding some of the first rides. My project was originally called multiplayer template by default, but I then renamed it to the Space theme park project (This explains why I have 2 hack time’s attached)."}]...
|
Title: Parcus Cosmos by @esvin_hernandez35 | Stard Title: Parcus Cosmos by @esvin_hernandez35 | Stardance
Devlogs:
I’m currently working on the park entrance and aesthetics. I don’t really know much about the vr world to start from scratch, So I borrowed a template that unity provides. I am currently in the process of clearing it up and making it according to theme, as well as adding some of the first rides. My project was originally called multiplayer template by default, but I then renamed it to the Space theme park project (This explains why I have 2 hack time’s attached).
I have edited the template, added new materials. Added a couch and other items to make it look cozier. Deleted the OG rock climbing wall to make more space for the roller coaster (The Red rocket following the balck lines with blue dots). I haven’t quite finished making the roller coaster functional, but I have decorated the slingshot, making it knock down UFO’s instead of Bullseye targets. I added a staircase to connect to the top, with the ferris wheel. And I added new material skins to the whack-a-mole like game
Finally finished the roller coaster, all of the aesthetics, and the roof top viewing of all the props used. I now have to just finish the GitHub, accrediting all of the models I used. I lost access to the VR headset I was using, so this is where I will ship it, but I might be able to get access soon again. (Don’t be surprised if I keep updating after this ship ;p )...
|
1793559457.6946275
|
1794164257.6946275
|
|
28494
|
MatchUp.AI by @espees | Stardance
|
espees
|
1
|
9.07
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-11T20:25:03Z", "hours": 6.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I built MatchUp.AI, a World Cup 2026 match predictor that uses a Poisson regression model (trained in Python) to guess scorelines, with the math running fully in the browser, no server needed. The hardest part was getting the model to work smoothly in JavaScript and making the results easy to read. I’m proud that it’s fast, simple, and runs the real math live instead of just guessing. To test it, just pick two teams and see the predicted score. It should load instantly since everything runs locally.", "repo": "https://github.com/sarthak-pant/MatchUp.AI/", "demo": "https://sarthak-pant.github.io/MatchUp.AI/"}]...
|
[{"post_id": 37700, "ts": "202 [{"post_id": 37700, "ts": "2026-07-30T16:27:57Z", "hours": 3.0717, "text": "I remodelled the entire UI! It has a new arcade based theme now, but everything else, including the model is still the same."}, {"post_id": 26143, "ts": "2026-07-10T19:25:54Z", "hours": 3.0478, "text": "Wrapped up the project today. The highlight was finally getting the whole pipeline working from start to finish. train_v1.py trains a Poisson GLM on old match data, dumps the coefficients into model.js. app.js grabs those in the browser to generate live win/draw/loss odds and full score predictions. Seeing everything actually work together for the first time was such a good feeling. It wasn’t at all smooth, though. First, I made a stupid typo: I wrote factorials(k) instead of factorials[k]. That completely killed the predictor for a while. Once I fixed that, I found an even dumber bug. I’d been multiplying the home team’s Poisson probabilities by… the home team’s Poisson probabilities. So the model had basically spent the afternoon thinking every match was a team playing against its own clone. Then JavaScript decided it wanted to be funny. I used regular quotes instead of backticks in a few places, so instead of showing the actual values, my UI was proudly displaying stuff like ${pct}%. A lot of debugging, a few “how is this even happening?” moments, and way too many commits later, it’s finally done. The predictions make sense, the frontend actually shows legit numbers, and I can stop lying to myself that bugs are “features.”"}, {"post_id": 21136, "ts": "2026-07-02T22:49:41Z", "hours": 2.6156, "text": "I am building a Poisson GLM model for predicting this FIFA world cup’s match outcomes! I’ve collected all the data I need, and the frontend’s finally alive (sort of). The dropdown menu, neutral venue toggle are up and rendering, and the loading screen for the entire results panel (expected goals, W/D/L bars, score matrix) works. I did spend a good chunk of my time convinced my CSS was cursed though. In the beginning stages of styling, no matter what I did, the web page didn’t change at all. Turns out I wrote style.css instead of styles.css when connecting it with my html, so the browser was just not loading any styles ever. Next up, app.js and model.js need to be coded. Right now the page is just a pretty shell with no logic behind it, so the dropdowns are sitting empty, and the results panel is stuck in the loading screen since there’s no data telling them what countries even exist!"}]...
|
Title: MatchUp.AI by @espees | Stardance
Devlogs: Title: MatchUp.AI by @espees | Stardance
Devlogs:
I am building a Poisson GLM model for predicting this FIFA world cup’s match outcomes! I’ve collected all the data I need, and the frontend’s finally alive (sort of). The dropdown menu, neutral venue toggle are up and rendering, and the loading screen for the entire results panel (expected goals, W/D/L bars, score matrix) works. I did spend a good chunk of my time convinced my CSS was cursed though. In the beginning stages of styling, no matter what I did, the web page didn’t change at all. Turns out I wrote style.css instead of styles.css when connecting it with my html, so the browser was just not loading any styles ever. Next up, app.js and model.js need to be coded. Right now the page is just a pretty shell with no logic behind it, so the dropdowns are sitting empty, and the results panel is stuck in the loading screen since there’s no data telling them what countries even exist!
Wrapped up the project today. The highlight was finally getting the whole pipeline working from start to finish. train_v1.py trains a Poisson GLM on old match data, dumps the coefficients into model.js. app.js grabs those in the browser to generate live win/draw/loss odds and full score predictions. Seeing everything actually work together for the first time was such a good feeling. It wasn’t at all smooth, though. First, I made a stupid typo: I wrote factorials(k) instead of factorials[k]. That completely killed the predictor for a while. Once I fixed that, I found an even dumber bug. I’d been multiplying the home team’s Poisson probabilities by… the home team’s Poisson probabilities. So the model had basically spent the afternoon thinking every match was a team playing against its own clone. Then JavaScript decided it wanted to be funny. I used regular quotes instead of backticks in a few places, so instead of showing the actual values, my UI was proudly displaying stuff like ${pct}%. A lot of debugging, a few “how is this even happening?” moments, and way too many commits later, it’s finally done. The predictions make sense, the frontend actually shows legit numbers, and I can stop lying to myself that bugs are “features.”
I remodelled the entire UI! It has a new arcade based theme now, but everything else, including the model is still the same.
Ships:
I built MatchUp.AI, a World Cup 2026 match predictor that uses a Poisson regression model (trained in Python) to guess scorelines, with the math running fully in the browser, no server needed. The hardest part was getting the model to work smoothly in JavaScript and making the results easy to read. I’m proud that it’s fast, simple, and runs the real math live instead of just guessing. To test it, just pick two teams and see the predicted score. It should load instantly since everything runs locally....
|
1793559460.3644524
|
1793645860.3644524
|
|
41348
|
My first slack bot! by @ocean | Stardance
|
ocean
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @ocean | Stardance
|
1793559463.129499
|
1794164263.129499
|
|
24225
|
arianepy by @sour | Stardance
|
sour
|
0
|
11.04
|
0
|
[]
|
[{"post_id": 54730, "ts": "202 [{"post_id": 54730, "ts": "2026-08-25T20:13:47Z", "hours": 5.6519, "text": "Is this… physically accurate ? I made the masses and fuel ejection accurate to Ariane 64…. hm"}, {"post_id": 46278, "ts": "2026-08-13T12:25:29Z", "hours": 5.1242, "text": "so, as you may know if you’ve seen the repo, the simulation has 3 versions (P1, P2, P3) with their respective “tests” and experiments, each version implementing something new. P1 was a basic simulation with the 4 aerodynamic forces, P2 introduced staging through a stage function my very swiss-french self named etage()… i’m glad to share that i figured P3 out and that our rocket now takes atmospheric pressure into account ! here’s how it’s doing…"}, {"post_id": 13997, "ts": "2026-06-22T23:30:48Z", "hours": 0.2622, "text": "err… well i made a repo and this is a graph of height across time for our rocket for the time being. i’ve taken its’ different stages into account but unfortunately not atmospheric pressure or gravity turn and just incline in general, so it does not enter orbit."}]...
|
Title: arianepy by @sour | Stardance
Devlogs:
err Title: arianepy by @sour | Stardance
Devlogs:
err… well i made a repo and this is a graph of height across time for our rocket for the time being. i’ve taken its’ different stages into account but unfortunately not atmospheric pressure or gravity turn and just incline in general, so it does not enter orbit.
so, as you may know if you’ve seen the repo, the simulation has 3 versions (P1, P2, P3) with their respective “tests” and experiments, each version implementing something new. P1 was a basic simulation with the 4 aerodynamic forces, P2 introduced staging through a stage function my very swiss-french self named etage()… i’m glad to share that i figured P3 out and that our rocket now takes atmospheric pressure into account ! here’s how it’s doing…
Is this… physically accurate ? I made the masses and fuel ejection accurate to Ariane 64…. hm...
|
1793559465.3502505
|
1794164265.3502505
|
|
3426
|
Untitled by @Naytik | Stardance
|
Naytik
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Untitled by @Naytik | Stardance
|
1793559466.2538128
|
1794164266.2538128
|
|
3793
|
My awesome macropad! by @siddd | Stardance
|
siddd
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @siddd | Stardance
|
1793559467.122511
|
1794164267.122511
|
|
35269
|
Untitled project by @blue_crystals | Stardance
|
blue_crystals
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Untitled project by @blue_crystals | Starda Title: Untitled project by @blue_crystals | Stardance...
|
1793559469.2524674
|
1794164269.2524674
|
|
14346
|
My awesome macropad! by @kumarabhay1029 | Stardanc My awesome macropad! by @kumarabhay1029 | Stardance...
|
kumarabhay1029
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @kumarabhay1029 | S Title: My awesome macropad! by @kumarabhay1029 | Stardance...
|
1793559471.9981449
|
1794164271.9981449
|
|
24217
|
Witchhat Atelier Magic Detector by @Neev | Stardan Witchhat Atelier Magic Detector by @Neev | Stardance...
|
Neev
|
0
|
1.94
|
0
|
[]
|
[{"post_id": 37368, "ts": "202 [{"post_id": 37368, "ts": "2026-07-30T01:12:44Z", "hours": 1.9392, "text": "I have just finished coding some basic image recognition in python to detect circles and their accuracy. I had to spend a lot of time making my picture-taker well-lit and the right size. Couple of notes: Through the process of trying to get lighting and everything correct to actually see the circles effectively I ended up realizing that the circles and sigils need to be very thickly outlined (in comparison to a single penstroke) which actually works out, since the anime uses magic ink (much thicker than normal) Based on the current average score, taking visible circle accuracy into account, I will likely be making 3 categories for the accuracy of the circle captured; Bad(<50), moderate(<80), and perfect(80+)."}]...
|
Title: Witchhat Atelier Magic Detector by @Neev | Title: Witchhat Atelier Magic Detector by @Neev | Stardance
Devlogs:
I have just finished coding some basic image recognition in python to detect circles and their accuracy. I had to spend a lot of time making my picture-taker well-lit and the right size. Couple of notes: Through the process of trying to get lighting and everything correct to actually see the circles effectively I ended up realizing that the circles and sigils need to be very thickly outlined (in comparison to a single penstroke) which actually works out, since the anime uses magic ink (much thicker than normal) Based on the current average score, taking visible circle accuracy into account, I will likely be making 3 categories for the accuracy of the circle captured; Bad(<50), moderate(<80), and perfect(80+)....
|
1793559472.9374833
|
1794164272.9374833
|
|
6658
|
Slack-ASM by @SeradedStripes | Stardance
|
SeradedStripes
|
1
|
40.0
|
562
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-04T18:50:51Z", "hours": 40.0, "multiplier": 13.9, "payout": 562, "blessing": "neutral", "text": "I made slack-asm! A slack bot written fully in x86_64 Assembly only. ARM support coming in the next ship. With 0.35MB ram usage and a peak of 0.52 CPU %, its a really really lightweight and fast slackbot. (The image below of ram and cpu usage may be slightly off from what I said here) Though it only has a small list of commands, it is very easy to add more to it!", "repo": "https://github.com/SeradedStripes/slack-asm", "demo": "https://hackclub.enterprise.slack.com/archives/C0B8BL6P3T3"}]...
|
[{"post_id": 61692, "ts": "202 [{"post_id": 61692, "ts": "2026-09-04T18:45:55Z", "hours": 0.7156, "text": "Finishing Touches So time to ship Basically finished up by: Doing example env Using a proper deploy workflow Add env reading support via CLI args Nuked docker compose And ofc, a bunch of readme updates"}, {"post_id": 28314, "ts": "2026-07-14T14:21:34Z", "hours": 1.7544, "text": "Updates Did a banner & Logo Add a pung command, it pings a certain user when you use it Added slash commands where the slash cmd msg is deleted instead of kept Fixed help cmd deleting slash cmd msg when it should not be"}, {"post_id": 27913, "ts": "2026-07-13T20:46:30Z", "hours": 1.2239, "text": "Updates Updated docker-compose Added pinging bot as a way to use its commands Auto reconnect ws after slack api decides to end it help cmd responds without threading due to slack api limitations Commands when pinging bot always responds in thread, even help cmd Added a meow cmd"}, {"post_id": 27407, "ts": "2026-07-12T23:16:02Z", "hours": 8.8964, "text": "Updates This Devlog took a while 😭 Anyway on to the changes.. Slack-asm help command Ability to respond in threads Roadmap updates Docker updates Minor help message updates Just check the commit messages 😭 Added Slack bot token handling and HTTP POST functionality Introduced load_bot_token function to extract the bot token from the environment buffer. Implemented slack_send_http_post function for making HTTP POST requests to Slack API with optional authorization. Updated slack_fetch_channel_ts to utilize the new bot token for API calls. Enhanced slash command handlers to send responses using slack_send_http_post . Added support for response URLs in slash command responses. Introduced memmem function for searching byte sequences in memory. Added debug logging for TLS operations to aid in troubleshooting. /slack-asm help now replies in a thread, though its not the correct thread The screeny below is from after i ram /slack-asm help What happened is it deleted the /slack-asm help msg and instead replied in my most recent other message"}, {"post_id": 22123, "ts": "2026-07-04T12:41:43Z", "hours": 2.9303, "text": "Updates We implemented a frick ton of tests sha256 hmac tests prf kdf tests tls record tests tls handshake tests tls connect tests aes cbc tests encrypted record tests x509 tests http tests rsa tests gcm tests"}, {"post_id": 21631, "ts": "2026-07-03T17:50:21Z", "hours": 1.6853, "text": "updates WE GOT WORKING SLASH COMMANDS (See screenshot below) Also fixed an indirect address displacement warning Fixed us not replying to the slack api with proper json Still not deployed Next up Messages that are visible to everyone It replying to certain phrases (maybe)"}, {"post_id": 21458, "ts": "2026-07-03T12:43:00Z", "hours": 5.3064, "text": "Updates FD might kill me We spent 2hrs fixing the first 3 bytes of keystream being wrong for the last block when we were calling the slack api. Implemented a ENV parser Yet another gitignore update Fixed parsing extensions wrong Reached 8.2K LOC"}, {"post_id": 20735, "ts": "2026-07-02T12:52:23Z", "hours": 1.1747, "text": "Updates/Status Report Changes for this devlog TLS alert Handling Updated content length from 32 to 64 bit for >4GB response bodies Status Report We have Full HTTPS working end-to-end This includes but not limited to: Full TLS 1.2 incl handshakes Full HTTP support TLS libraries: SHA-256 HMAC-SHA256 AES-128- CBC & GCM RSA support ECDHE key exchange They are implemented enough for TLS We have Linux syscalls We at 10161 lines of asm, 7.6k LOC, 1.2k Comments & 1.3K blanks What Next? We integrating this bad boy with slack api PS: ignore the bad request part in the image below"}, {"post_id": 19240, "ts": "2026-06-30T14:34:43Z", "hours": 3.335, "text": "Updates Padding fix HTTP versioning parsing implementation Chunked transfer encoding as https is horrible 2 commits i did were just random gitignore updates in between a massive 2k line addition commit Made an abbreviation YAGU or Yet another gitignore update Implemented P-256 elliptic curve primitives for ECDHE Key Exchange AES-128-GCM for TLS1.2 Tests for AES-128-GCM (they were horrible to do, purely because my GCM code was not working TLS code updates for aes128 & ecc Yes i am aware my gcm_tests below give horrible information to help lmao"}, {"post_id": 17549, "ts": "2026-06-28T11:40:19Z", "hours": 1.2286, "text": "Updates TLS Handshake fixes: Added server_ccs field to the tls_ctx struct Initialized server_ccs in tls_init Fixed PKCS#7 padding byte value in tls_send fixed big endian length field encoding in CCS header Removed CCS Peak Probably something I missed RSA Big integer rewrite Added STDERR & increased tls_ctx_buf Commented out test_harness call and added dump_keys stub Updated the Makefile Discovered i messed something up in compiled binary"}, {"post_id": 17004, "ts": "2026-06-27T16:17:17Z", "hours": 0.6667, "text": "Updates DNS resolution in pure assembly Fixed a bug where exit 255 was not in the RSA big_mod code, it was instead in the tls code for whatever reason We at like 5.4K LOC in Assembly now Thats it"}, {"post_id": 15053, "ts": "2026-06-24T13:29:51Z", "hours": 0.7378, "text": "Updates Removed the need of der file in the repo by hardcoding the value of the RSA-2048 test key Implemented Basic HTTP response parsing Began work on a very very basic dns resoultion system"}, {"post_id": 10506, "ts": "2026-06-17T08:05:55Z", "hours": 4.5422, "text": "Updates f952ca5 Added push rdp/ pop rbp to preserve rdp across sha256_transform updates rsa.asm RSA PKCS#1 RSA OAEP encoding Montgomery ladder modular exponentiation Big number helpers tls.asm New exports New externs More constants A bunch of file changes, see the actual commit for all of it test.asm Extend test_harness SHA256, HMAC-SHA256 test vectors KDF intermediate HMAC computation test PRF output comparison against known vector Key derivation: client/server write MAC keys, write keys, IVs Full TLS 1.2 handshake Some more i dont remember about Slack.asm Updated banner, added externs for new functions Cleaned up _start to call main then exit 2 Random commits just updating gitignore imbetween 38dad3c tls.asm Register clobber fix CCS read_seq MAC double-count fix Verify_data mismatch Removed debug writes Disconnect Comment test.asm ServerHello hash offset update PRF target address update Fix MAC length byte-order Seq number update Child ClientHello receive update socket.asm sys_send update Summary Frick me, most of this devlog what trying to fix one single bug. The hardest part of this devlog was fixing the stupid bugs i had."}, {"post_id": 6824, "ts": "2026-06-11T13:29:56Z", "hours": 1.0872, "text": "Updates Agents file and Contributing file X.509 certificate parsing & basic validity checking No longer include .der files (gitignore change) Updated Commenting, ie. made it more clearer and standardized it a bit. Updated Readme & Roadmap Code Now at 4.5k lines of assembly, 3.3k lines are actual code, 701 commenting lines. By the way its 3,300 lines exactly for the asm code lines"}, {"post_id": 5485, "ts": "2026-06-09T09:09:47Z", "hours": 1.6078, "text": "Updates Added AES-128-CBC encryption & decryption Implement pre_master_secret generation The line counts have increased Currently 3.7k lines of asm, (2.8k LOC) AES-128-CBC Notes: Most of my time was spent debugging it Thats it I think Oh Yeah and somehow all tests pass!"}, {"post_id": 3486, "ts": "2026-06-06T13:22:49Z", "hours": 0.8539, "text": "Updates Added Key derivation functions & its tests Added TLS 1.2 PRF implemnentation & its tests Sitting at 1759 lines of asm code now Still a bunch to go"}, {"post_id": 2722, "ts": "2026-06-05T13:40:16Z", "hours": 0.8997, "text": "Updates Stardance went off as I tried to post a devlog (this is redoing it) Added TLS 1.2 handshake & TLS record layer Finished RFC 4231 test cases"}, {"post_id": 2671, "ts": "2026-06-05T10:48:41Z", "hours": 0.85, "text": "Updates My wakatime broke Added SHA256 in pure asm Added hmac_sha256 in pure asm Fixed the sha256 error Comment out object files Readme & Roadmap polishing Update repo structure to now have code in src/"}, {"post_id": 2115, "ts": "2026-06-04T13:20:16Z", "hours": 0.6239, "text": "Updates Im sad from no md support in sd Added a makefile Thin TLS wrapper TLS stubs Test harness Dependabot for gh actions"}, {"post_id": 2081, "ts": "2026-06-04T12:26:21Z", "hours": 0.2942, "text": "Basic project repo setup & Skeleton of the app"}]...
|
Title: Slack-ASM by @SeradedStripes | Stardance
D Title: Slack-ASM by @SeradedStripes | Stardance
Devlogs:
Basic project repo setup & Skeleton of the app
Updates Im sad from no md support in sd Added a makefile Thin TLS wrapper TLS stubs Test harness Dependabot for gh actions
Updates My wakatime broke Added SHA256 in pure asm Added hmac_sha256 in pure asm Fixed the sha256 error Comment out object files Readme & Roadmap polishing Update repo structure to now have code in src/
Updates Stardance went off as I tried to post a devlog (this is redoing it) Added TLS 1.2 handshake & TLS record layer Finished RFC 4231 test cases
Updates Added Key derivation functions & its tests Added TLS 1.2 PRF implemnentation & its tests Sitting at 1759 lines of asm code now Still a bunch to go
Updates Added AES-128-CBC encryption & decryption Implement pre_master_secret generation The line counts have increased Currently 3.7k lines of asm, (2.8k LOC) AES-128-CBC Notes: Most of my time was spent debugging it Thats it I think Oh Yeah and somehow all tests pass!
Updates Agents file and Contributing file X.509 certificate parsing & basic validity checking No longer include .der files (gitignore change) Updated Commenting, ie. made it more clearer and standardized it a bit. Updated Readme & Roadmap Code Now at 4.5k lines of assembly, 3.3k lines are actual code, 701 commenting lines. By the way its 3,300 lines exactly for the asm code lines
Updates f952ca5 Added push rdp/ pop rbp to preserve rdp across sha256_transform updates rsa.asm RSA PKCS#1 RSA OAEP encoding Montgomery ladder modular exponentiation Big number helpers tls.asm New exports New externs More constants A bunch of file changes, see the actual commit for all of it test.asm Extend test_harness SHA256, HMAC-SHA256 test vectors KDF intermediate HMAC computation test PRF output comparison against known vector Key derivation: client/server write MAC keys, write keys, IVs Full TLS 1.2 handshake Some more i dont remember about Slack.asm Updated banner, added externs for new functions Cleaned up _start to call main then exit 2 Random commits just updating gitignore imbetween 38dad3c tls.asm Register clobber fix CCS read_seq MAC double-count fix Verify_data mismatch Removed debug writes Disconnect Comment test.asm ServerHello hash offset update PRF target address update Fix MAC length byte-order Seq number update Child ClientHello receive update socket.asm sys_send update Summary Frick me, most of this devlog what trying to fix one single bug. The hardest part of this devlog was fixing the stupid bugs i had.
Updates Removed the need of der file in the repo by hardcoding the value of the RSA-2048 test key Implemented Basic HTTP response parsing Began work on a very very basic dns resoultion system
Updates DNS resolution in pure assembly Fixed a bug where exit 255 was not in the RSA big_mod code, it was instead in the tls code for whatever reason We at like 5.4K LOC in Assembly now Thats it
Updates TLS Handshake fixes: Added server_ccs field to the tls_ctx struct Initialized server_ccs in tls_init Fixed PKCS#7 padding byte value in tls_send fixed big endian length field encoding in CCS header Removed CCS Peak Probably something I missed RSA Big integer rewrite Added STDERR & increased tls_ctx_buf Commented out test_harness call and added dump_keys stub Updated the Makefile Discovered i messed something up in compiled binary
Updates Padding fix HTTP versioning parsing implementation Chunked transfer encoding as https is horrible 2 commits i did were just random gitignore updates in between a massive 2k line addition commit Made an abbreviation YAGU or Yet another gitignore update Implemented P-256 elliptic curve primitives for ECDHE Key Exchange AES-128-GCM for TLS1.2 Tests for AES-128-GCM (they were horrible to do, purely because my GCM code was not working TLS code updates for aes128 & ecc Yes i am aware my gcm_tests below give horrible information to help lmao
Updates/Status Report Changes for this devlog TLS alert Handling Updated content length from 32 to 64 bit for >4GB response bodies Status Report We have Full HTTPS working end-to-end This includes but not limited to: Full TLS 1.2 incl handshakes Full HTTP support TLS libraries: SHA-256 HMAC-SHA256 AES-128- CBC & GCM RSA support ECDHE key exchange They are implemented enough for TLS We have Linux syscalls We at 10161 lines of asm, 7.6k LOC, 1.2k Comments & 1.3K blanks What Next? We integrating this bad boy with slack api PS: ignore the bad request part in the image below
Updates FD might kill me We spent 2hrs fixing the first 3 bytes of keystream being wrong for the last block when we were calling the slack api. Implemented a ENV parser Yet another gitignore update Fixed parsing extensions wrong Reached 8.2K LOC
updates WE GOT WORKING SLASH COMMANDS (See screenshot below) Also fixed an indirect address displacement warning Fixed us not replying to the slack api with proper json Still not deployed Next up Messages that are visible to everyone It replying to certain phrases (maybe)
Updates We implemented a frick ton of tests sha256 hmac tests prf kdf tests tls record tests tls handshake tests tls connect tests aes cbc tests encrypted record tests x509 tests http tests rsa tests gcm tests
Updates This Devlog took a while 😭 Anyway on to the changes.. Slack-asm help command Ability to respond in threads Roadmap updates Docker updates Minor help message updates Just check the commit messages 😭 Added Slack bot token handling and HTTP POST functionality Introduced load_bot_token function to extract the bot token from the environment buffer. Implemented slack_send_http_post function for making HTTP POST requests to Slack API with optional authorization. Updated slack_fetch_channel_ts to utilize the new bot token for API calls. Enhanced slash command handlers to send responses using slack_send_http_post . Added support for response URLs in slash command responses. Introduced memmem function for searching byte sequences in memory. Added debug logging for TLS operations to aid in troubleshooting. /slack-asm help now replies in a thread, though its not the correct thread The screeny below is from after i ram /slack-asm help What happened is it deleted the /slack-asm help msg and instead replied in my most recent other message
Updates Updated docker-compose Added pinging bot as a way to use its commands Auto reconnect ws after slack api decides to end it help cmd responds without threading due to slack api limitations Commands when pinging bot always responds in thread, even help cmd Added a meow cmd
Updates Did a banner & Logo Add a pung command, it pings a certain user when you use it Added slash commands where the slash cmd msg is deleted instead of kept Fixed help cmd deleting slash cmd msg when it should not be
Finishing Touches So time to ship Basically finished up by: Doing example env Using a proper deploy workflow Add env reading support via CLI args Nuked docker compose And ofc, a bunch of readme updates
Ships:
I made slack-asm! A slack bot written fully in x86_64 Assembly only. ARM support coming in the next ship. With 0.35MB ram usage and a peak of 0.52 CPU %, its a really really lightweight and fast slackbot. (The image below of ram and cpu usage may be slightly off from what I said here) Though it only has a small list of commands, it is very easy to add more to it!...
|
1793559475.945567
|
1793645875.945567
|
|
18197
|
My first slack bot! by @NicoR09 | Stardance
|
NicoR09
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @NicoR09 | Stardance
|
1793559478.2130716
|
1794164278.2130716
|
|
34498
|
WarioWare Game by @sohailsk3168 | Stardance
|
sohailsk3168
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: WarioWare Game by @sohailsk3168 | Stardance
|
1793559479.1192558
|
1794164279.1192558
|
|
16005
|
My very own WebOS by @Abdullah_101 | Stardance
|
Abdullah_101
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My very own WebOS by @Abdullah_101 | Starda Title: My very own WebOS by @Abdullah_101 | Stardance...
|
1793559480.3047714
|
1794164280.3047714
|
|
14879
|
My very own WebOS by @Shubham- | Stardance
|
Shubham-
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My very own WebOS by @Shubham- | Stardance
|
1793559482.3170974
|
1794164282.3170974
|
|
18066
|
My very own WebOS by @ioannis | Stardance
|
ioannis
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My very own WebOS by @ioannis | Stardance
|
1793559484.40535
|
1794164284.40535
|
|
2730
|
My awesome macropad! by @AyyDubb | Stardance
|
AyyDubb
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @AyyDubb | Stardanc Title: My awesome macropad! by @AyyDubb | Stardance...
|
1793559489.2341218
|
1794164289.2341218
|
|
4657
|
Untitled project by @caff02 | Stardance
|
caff02
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Untitled project by @caff02 | Stardance
|
1793559490.1590295
|
1794164290.1590295
|
|
4164
|
Untitled project by @Astrino | Stardance
|
Astrino
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Untitled project by @Astrino | Stardance
|
1793559492.2464976
|
1794164292.2464976
|
|
23006
|
My very own WebOS by @Zybmkwar_Ace26 | Stardance
|
Zybmkwar_Ace26
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My very own WebOS by @Zybmkwar_Ace26 | Star Title: My very own WebOS by @Zybmkwar_Ace26 | Stardance...
|
1793559493.4674659
|
1794164293.4674659
|
|
48104
|
KC16 by @Kxrtik1315 | Stardance
|
Kxrtik1315
|
1
|
1.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-16T11:18:33Z", "hours": 1.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "i built KC16, a fully custom Slack bot powered by Node.js and @slack /bolt that literally runs 24/7 on a linux Hack Club Nest container. what was challenging? honestly the slack api config was an absolute fkng nightmare to navigate, and dealing with systemd service network timeouts almost took me out, but we survived it fr. i’m proud asf that it’s now completely bulletproof and lives on a server so it responds even when my laptop is shut. you can test it rn by dropping /kc16-ping in the chat to check latency, or hit it with /kc16-catfact, /kc16-joke, or /kc16-8ball to see it in action. zero slacking, just pure peak engineering.", "repo": "https://github.com/Kxrtik13-A19/KC16", "demo": "https://hackclub.enterprise.slack.com/archives/C0BQCTH9RL3"}]...
|
[{"post_id": 48063, "ts": "202 [{"post_id": 48063, "ts": "2026-08-16T10:50:14Z", "hours": 0.2825, "text": "the absolute worst part of dev is always the config but we survived it fr. spent way too much time in the slack api dashboard registering these slash commands one by one. but tbh looking at this list of all my bot’s commands mapped out with their descriptions is satisfying asf. got ping, help, catfact, joke, cybernetics, soccer, 8ball, dog, and roll fully registered so slack actually knows wtf to do when i type them. backend admin work is finally done, holy cramp. everything is completely locked in and ready for production."}, {"post_id": 48026, "ts": "2026-08-16T09:53:05Z", "hours": 0.4292, "text": "bro writing out all this logic was a grind but finally all commands and coding is done 🗣️🔥 ten full slash commands slammed into index.js and the bolt app is officially ready for action. setting up the axios fetches for the random dog api and doing the javascript math for the dice rolls took a hot sec but the code is looking super clean. vs code terminal finally spitting out ‘kc16 bolt app is running and ready for action!’ is a massive w for today. stardance hours are pumped up and my fingers are dead fr. time to touch some grass."}]...
|
Title: KC16 by @Kxrtik1315 | Stardance
Devlogs:
b Title: KC16 by @Kxrtik1315 | Stardance
Devlogs:
bro writing out all this logic was a grind but finally all commands and coding is done 🗣️🔥 ten full slash commands slammed into index.js and the bolt app is officially ready for action. setting up the axios fetches for the random dog api and doing the javascript math for the dice rolls took a hot sec but the code is looking super clean. vs code terminal finally spitting out ‘kc16 bolt app is running and ready for action!’ is a massive w for today. stardance hours are pumped up and my fingers are dead fr. time to touch some grass.
the absolute worst part of dev is always the config but we survived it fr. spent way too much time in the slack api dashboard registering these slash commands one by one. but tbh looking at this list of all my bot’s commands mapped out with their descriptions is satisfying asf. got ping, help, catfact, joke, cybernetics, soccer, 8ball, dog, and roll fully registered so slack actually knows wtf to do when i type them. backend admin work is finally done, holy cramp. everything is completely locked in and ready for production.
Ships:
i built KC16, a fully custom Slack bot powered by Node.js and @slack /bolt that literally runs 24/7 on a linux Hack Club Nest container. what was challenging? honestly the slack api config was an absolute fkng nightmare to navigate, and dealing with systemd service network timeouts almost took me out, but we survived it fr. i’m proud asf that it’s now completely bulletproof and lives on a server so it responds even when my laptop is shut. you can test it rn by dropping /kc16-ping in the chat to check latency, or hit it with /kc16-catfact, /kc16-joke, or /kc16-8ball to see it in action. zero slacking, just pure peak engineering....
|
1793559495.4536877
|
1793645895.4536877
|
|
7858
|
My first slack bot! by @dhruvkamble154 | Stardance
|
dhruvkamble154
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @dhruvkamble154 | St Title: My first slack bot! by @dhruvkamble154 | Stardance...
|
1793559496.623015
|
1794164296.623015
|
|
3737
|
Submarine by @siddhant_samar | Stardance
|
siddhant_samar
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Submarine by @siddhant_samar | Stardance
|
1793559499.3622763
|
1794164299.3622763
|
|
38869
|
Han-Yang's page by @Han-Yang | Stardance
|
Han-Yang
|
1
|
2.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-24T17:30:22Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a simple 3 page website showing my hobbies, interests, and contacts.", "repo": "https://github.com/hydraprimus/My-personal-Site", "demo": "https://hydraprimus.github.io/My-personal-Site/"}]...
|
[{"post_id": 34140, "ts": "202 [{"post_id": 34140, "ts": "2026-07-24T17:19:59Z", "hours": 1.1225, "text": "I added a hobbies and contact section to my page. I removed the interests, cus that’s kind of the same thing as hobbies. Also all the navbar buttons work now and also change color when hovering!"}, {"post_id": 33735, "ts": "2026-07-23T21:46:30Z", "hours": 0.765, "text": "just finished making and styling the home page for my website."}]...
|
Title: Han-Yang's page by @Han-Yang | Stardanc Title: Han-Yang's page by @Han-Yang | Stardance
Devlogs:
just finished making and styling the home page for my website.
I added a hobbies and contact section to my page. I removed the interests, cus that’s kind of the same thing as hobbies. Also all the navbar buttons work now and also change color when hovering!
Ships:
I made a simple 3 page website showing my hobbies, interests, and contacts....
|
1793559501.9660025
|
1793645901.9660025
|
|
3787
|
Video game by @cartertreustephenson | Stardance
|
cartertreustephenson
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Video game by @cartertreustephenson | Stard Title: Video game by @cartertreustephenson | Stardance...
|
1793559503.1171489
|
1794164303.1171489
|
|
30051
|
My awesome macropad! by @Jacy | Stardance
|
Jacy
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @Jacy | Stardance
|
1793559503.9863505
|
1794164303.9863505
|
|
18536
|
FPV RC Car by @tfles28 | Stardance
|
tfles28
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: FPV RC Car by @tfles28 | Stardance
|
1793559504.8456051
|
1794164304.8456051
|
|
29857
|
IndianOS by @sk_zaidji | Stardance
|
sk_zaidji
|
1
|
3.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-03T14:33:45Z", "hours": 3.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I built IndianOS, a browser-based desktop operating system inspired by India using HTML, CSS, and JavaScript. It includes a desktop interface, Start Menu, draggable windows, Files, Notes, Calculator, a live IST clock, a boot screen, notification toasts, an About window, and support for maximizing windows by double-clicking the title bar. The most challenging part was implementing the draggable window system. I had to manage mouse events, calculate the correct window position while dragging, and handle the window stacking order (z-index) so the active window always appears on top. I also worked on making the maximize/restore behavior smooth and ensuring all the UI components worked together. I’m proud that I built a complete desktop-like experience from scratch without using any frameworks. The project has an original Indian-inspired theme, a clean interface, and several extra features beyond the basic tutorial, such as the boot screen, notification toasts, About window, and window maximize functionality. It gave me a much better understanding of JavaScript event handling and UI development.", "repo": "https://github.com/MdZaidji/my-first-webos", "demo": "https://mdzaidji.github.io/my-first-webos/"}]...
|
[{"post_id": 21492, "ts": "202 [{"post_id": 21492, "ts": "2026-07-03T13:57:55Z", "hours": 0.9119, "text": "🚀 Devlog #3 – Final Polish & Completion Today I completed IndianOS and focused on polishing the overall user experience.What I added🚀 Boot screen with a loading animation before the desktop appears.🔔 Notification toasts that display when applications are opened.🪟 Double-click on a window title bar to maximize and restore windows.ℹ️ An About IndianOS window with project information.🎨 Improved the desktop layout, taskbar, and window styling for a cleaner, more modern look.ChallengesThe biggest challenge was making the window system feel smooth and responsive. I refined the dragging logic, improved window layering with z-index, and made sure maximizing and restoring windows worked correctly without affecting other open applications.What I learnedManaging DOM events for draggable interfaces.Using JavaScript to control window states and interactions.Improving UI/UX with small visual details like animations and notifications.Organizing HTML, CSS, and JavaScript into a simple desktop-style application.Final Features🖥️ Desktop Interface📋 Start Menu🪟 Multiple Draggable Windows📁 Files App📝 Notes App🧮 Calculator🕒 Live IST Clock🚀 Boot Screen🔔 Notification Toasts🪟 Double-click to Maximize Windowsℹ️ About IndianOSBuilding IndianOS was a fun way to learn more about DOM manipulation, event handling, and designing a desktop-like interface entirely with HTML, CSS, and JavaScript. This project also gave me experience structuring a larger frontend project while keeping the interface simple and responsive."}, {"post_id": 21460, "ts": "2026-07-03T12:46:29Z", "hours": 1.0086, "text": "Devlog 2 – Window Manager Today I implemented the core of IndianOS: draggable windows. I built separate windows for Files, Notes, and Calculator, added close buttons, and made windows come to the front when clicked. The biggest challenge was handling dragging smoothly without affecting other windows, but after debugging the mouse events I got it working."}, {"post_id": 21427, "ts": "2026-07-03T11:35:16Z", "hours": 1.1467, "text": "Devlog 1 – Starting IndianOS 🇮🇳 Today I started building IndianOS, a browser-based desktop operating system inspired by India. Instead of copying the tutorial exactly, I wanted to create my own look and feel.So far I have:Created the project structure.Built the desktop layout.Added desktop icons.Added a taskbar with a live IST clock.Chosen an India-inspired theme for the UI.Next, I’ll work on draggable windows and build the core applications like Files, Notes, and Calculator."}]...
|
Title: IndianOS by @sk_zaidji | Stardance
Devlogs Title: IndianOS by @sk_zaidji | Stardance
Devlogs:
Devlog 1 – Starting IndianOS 🇮🇳 Today I started building IndianOS, a browser-based desktop operating system inspired by India. Instead of copying the tutorial exactly, I wanted to create my own look and feel.So far I have:Created the project structure.Built the desktop layout.Added desktop icons.Added a taskbar with a live IST clock.Chosen an India-inspired theme for the UI.Next, I’ll work on draggable windows and build the core applications like Files, Notes, and Calculator.
Devlog 2 – Window Manager Today I implemented the core of IndianOS: draggable windows. I built separate windows for Files, Notes, and Calculator, added close buttons, and made windows come to the front when clicked. The biggest challenge was handling dragging smoothly without affecting other windows, but after debugging the mouse events I got it working.
🚀 Devlog #3 – Final Polish & Completion Today I completed IndianOS and focused on polishing the overall user experience.What I added🚀 Boot screen with a loading animation before the desktop appears.🔔 Notification toasts that display when applications are opened.🪟 Double-click on a window title bar to maximize and restore windows.ℹ️ An About IndianOS window with project information.🎨 Improved the desktop layout, taskbar, and window styling for a cleaner, more modern look.ChallengesThe biggest challenge was making the window system feel smooth and responsive. I refined the dragging logic, improved window layering with z-index, and made sure maximizing and restoring windows worked correctly without affecting other open applications.What I learnedManaging DOM events for draggable interfaces.Using JavaScript to control window states and interactions.Improving UI/UX with small visual details like animations and notifications.Organizing HTML, CSS, and JavaScript into a simple desktop-style application.Final Features🖥️ Desktop Interface📋 Start Menu🪟 Multiple Draggable Windows📁 Files App📝 Notes App🧮 Calculator🕒 Live IST Clock🚀 Boot Screen🔔 Notification Toasts🪟 Double-click to Maximize Windowsℹ️ About IndianOSBuilding IndianOS was a fun way to learn more about DOM manipulation, event handling, and designing a desktop-like interface entirely with HTML, CSS, and JavaScript. This project also gave me experience structuring a larger frontend project while keeping the interface simple and responsive.
Ships:
I built IndianOS, a browser-based desktop operating system inspired by India using HTML, CSS, and JavaScript. It includes a desktop interface, Start Menu, draggable windows, Files, Notes, Calculator, a live IST clock, a boot screen, notification toasts, an About window, and support for maximizing windows by double-clicking the title bar. The most challenging part was implementing the draggable window system. I had to manage mouse events, calculate the correct window position while dragging, and handle the window stacking order (z-index) so the active window always appears on top. I also worked on making the maximize/restore behavior smooth and ensuring all the UI components worked together. I’m proud that I built a complete desktop-like experience from scratch without using any frameworks. The project has an original Indian-inspired theme, a clean interface, and several extra features beyond the basic tutorial, such as the boot screen, notification toasts, About window, and window maximize functionality. It gave me a much better understanding of JavaScript event handling and UI development....
|
1793559505.7281952
|
1793645905.7281952
|
|
5182
|
My awesome macropad! by @alokojha | Stardance
|
alokojha
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @alokojha | Stardan Title: My awesome macropad! by @alokojha | Stardance...
|
1793559506.9110084
|
1794164306.9110084
|
|
26767
|
Angel's WebOS by @angelneupane | Stardance
|
angelneupane
|
1
|
4.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-03T13:04:09Z", "hours": 4.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I present the AngelOS! I created a webOS with 4 app windows, which are: DateTime Window My LinkedIn A to-do list A coin flip app that uses the Math.random() function to pick heads or tails at random and tells the user if they win or lose. The greatest difficulty I faced was setting up hackatime on github codespaces. After I had that part down, everything was smooth. Figuring out how to implement the coin flip function was a challenge, too. Before deciding on the coin flip app, I tried creating a CPS counter app, but it was too difficult, so I dropped the idea.", "repo": "https://github.com/angelneupane/AngelOS", "demo": "https://angelneupane.github.io/AngelOS/"}]...
|
[{"post_id": 21461, "ts": "202 [{"post_id": 21461, "ts": "2026-07-03T12:46:54Z", "hours": 0.6733, "text": "Devlog [5] Created a coinflip app using the Math.random() function."}, {"post_id": 21400, "ts": "2026-07-03T10:07:39Z", "hours": 1.4547, "text": "Devlog [4] Added a button to close the windows and added icons to open specific windows and made a simple to-do list app that uses tag."}, {"post_id": 20769, "ts": "2026-07-02T13:46:16Z", "hours": 0.7914, "text": "Devlog [3] Changed the inline CSS that was common for all elements to Internal CSS, added the drag window feature, added headers to each window, made separate windows for date and time and LinkedIn, changed the background image, added multiple classes to classify div as draggable and windows."}, {"post_id": 20186, "ts": "2026-07-01T18:51:22Z", "hours": 0.4386, "text": "Devlog[2] Created a div for the heading, my LinkedIn profile and the date and time function and made it kinda fit the theme."}, {"post_id": 20161, "ts": "2026-07-01T18:20:39Z", "hours": 0.6114, "text": "Devlog[1] I added a background image to the body, added a heading and attached a link to github.com. Most of the time was spent trying to set up hackatime because I just couldn’t get it to work right."}]...
|
Title: Angel's WebOS by @angelneupane | Starda Title: Angel's WebOS by @angelneupane | Stardance
Devlogs:
Devlog[1] I added a background image to the body, added a heading and attached a link to github.com. Most of the time was spent trying to set up hackatime because I just couldn’t get it to work right.
Devlog[2] Created a div for the heading, my LinkedIn profile and the date and time function and made it kinda fit the theme.
Devlog [3] Changed the inline CSS that was common for all elements to Internal CSS, added the drag window feature, added headers to each window, made separate windows for date and time and LinkedIn, changed the background image, added multiple classes to classify div as draggable and windows.
Devlog [4] Added a button to close the windows and added icons to open specific windows and made a simple to-do list app that uses tag.
Devlog [5] Created a coinflip app using the Math.random() function.
Ships:
I present the AngelOS! I created a webOS with 4 app windows, which are: DateTime Window My LinkedIn A to-do list A coin flip app that uses the Math.random() function to pick heads or tails at random and tells the user if they win or lose. The greatest difficulty I faced was setting up hackatime on github codespaces. After I had that part down, everything was smooth. Figuring out how to implement the coin flip function was a challenge, too. Before deciding on the coin flip app, I tried creating a CPS counter app, but it was too difficult, so I dropped the idea....
|
1793559507.7976487
|
1793645907.7976487
|
|
724
|
slack bot by @Seb | Stardance
|
Seb
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: slack bot by @Seb | Stardance
|
1793559508.956752
|
1794164308.956752
|
|
27423
|
Adobe Lightroom Clone by @catlover125r | Stardance
|
catlover125r
|
1
|
4.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-28T06:55:21Z", "hours": 4.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Open-source, catalog-based, non-destructive RAW photo editor (Lightroom-class), GPLv3, 100% local AI. Engine in Rust, one wgpu shader codebase, ONNX Runtime for all ML. This repo contains the Phase-0 spike + a working Phase-1 (MVP) with a real desktop GUI — proven end-to-end on Apple Silicon (Metal + CoreML): crates/raw-decode — LibRaw → linear 16-bit RGB + metadata probe, via a stable C-ABI shim. crates/recipe — serde parametric edit-recipe (sparse, identity-default). crates/catalog — SQLite catalog: import folders of RAWs (with EXIF), read/write recipes, idempotent. crates/gpu — wgpu develop pipeline (WB, exposure, contrast, highlights/shadows/whites/blacks, vibrance/saturation, dehaze, 8-band HSL, post-crop vignette, grain), shared by the live preview and headless export. Preview == export. cargo run -p gpu –example modtest checks the modules. crates/app — egui desktop app: a Library grid (background-decoded thumbnails) and a Develop view with live sliders driving the GPU pipeline, plus the import / –recipe / –export / –selftest headless CLI. crates/ai-smoke — ONNX Runtime + CoreML EP smoke test for SAM2. catalog/schema.sql — full SQLite catalog schema (Task 3). docs/ — stack decisions, recipe format, develop pipeline, model packaging.", "repo": "https://github.com/catlover125r/AdobeMaybeLight", "demo": "https://github.com/catlover125r/AdobeMaybeLight/releases/tag/v0.1.0"}]...
|
[{"post_id": 17440, "ts": "202 [{"post_id": 17440, "ts": "2026-06-28T06:52:08Z", "hours": 3.8881, "text": "It’s looking good. I used Rust for the first time to make this project. As you can see below, the sliders work well!"}]...
|
Title: Adobe Lightroom Clone by @catlover125r | St Title: Adobe Lightroom Clone by @catlover125r | Stardance
Devlogs:
It’s looking good. I used Rust for the first time to make this project. As you can see below, the sliders work well!
Ships:
Open-source, catalog-based, non-destructive RAW photo editor (Lightroom-class), GPLv3, 100% local AI. Engine in Rust, one wgpu shader codebase, ONNX Runtime for all ML. This repo contains the Phase-0 spike + a working Phase-1 (MVP) with a real desktop GUI — proven end-to-end on Apple Silicon (Metal + CoreML): crates/raw-decode — LibRaw → linear 16-bit RGB + metadata probe, via a stable C-ABI shim. crates/recipe — serde parametric edit-recipe (sparse, identity-default). crates/catalog — SQLite catalog: import folders of RAWs (with EXIF), read/write recipes, idempotent. crates/gpu — wgpu develop pipeline (WB, exposure, contrast, highlights/shadows/whites/blacks, vibrance/saturation, dehaze, 8-band HSL, post-crop vignette, grain), shared by the live preview and headless export. Preview == export. cargo run -p gpu –example modtest checks the modules. crates/app — egui desktop app: a Library grid (background-decoded thumbnails) and a Develop view with live sliders driving the GPU pipeline, plus the import / –recipe / –export / –selftest headless CLI. crates/ai-smoke — ONNX Runtime + CoreML EP smoke test for SAM2. catalog/schema.sql — full SQLite catalog schema (Task 3). docs/ — stack decisions, recipe format, develop pipeline, model packaging....
|
1793559509.8511727
|
1793645909.8511727
|
|
3473
|
My awesome macropad! by @waelaly013 | Stardance
|
waelaly013
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @waelaly013 | Stard Title: My awesome macropad! by @waelaly013 | Stardance...
|
1793559510.9843085
|
1794164310.9843085
|
|
8681
|
Hack me Yash by @zoyashrj | Stardance
|
zoyashrj
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Hack me Yash by @zoyashrj | Stardance
|
1793559511.9041362
|
1794164311.9041362
|
|
59450
|
My awesome macropad! by @manka5 | Stardance
|
manka5
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @manka5 | Stardance
|
1793559512.774671
|
1794164312.774671
|
|
54669
|
BLACKBOX (complain filing application) by @Fabulou BLACKBOX (complain filing application) by @FabulousHippoOfOrangeLake | Stardance...
|
FabulousHippoOfOrangeLake
|
1
|
22.5
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-09T16:28:54Z", "hours": 15.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a python desktop app for student feedback, issue and complain management. The main idea was to provide students with one core place to report problems. Students use their roll number for logins, they can upvote issues to show its urgency, they can change their own password. There is also a separate admin dashboard with issues organised cleanly according to priority. I am proud of using Custom Tkinter for the first time but not proud of having 1200 lines of code in one file! I hope u find this project worthy and fun to use!", "repo": "https://github.com/sharmashashwat27-source/BLACKBOX", "demo": "https://github.com/sharmashashwat27-source/BLACKBOX/releases/tag/custom-Tkinter"}]...
|
[{"post_id": 72698, "ts": "202 [{"post_id": 72698, "ts": "2026-09-23T15:05:48Z", "hours": 7.5047, "text": "DEVLOG #9 idk SO i added so may features and it was such a pain in the ass to retain feature when adding new ones i kept messing up here and there and even forgot to call the simplest of functions. But now i’m here and this is what I added: Different types of admin (headmaster, housemaster senior master etc.) feature to chose who u want to submit the report too feature to forward the issue (as an admin) - if the particular admin finds its not for him logging in if ur in guest mode and logging out if ur in student mode my reports and all reports button added a view issue button which lets u view the full issue instead of the dot expanding thing i had before lastly the stupidest but most needed asterisk while entering passwords."}, {"post_id": 64289, "ts": "2026-09-08T15:59:34Z", "hours": 0.8783, "text": "DEVLOG#9 So today I finished the new gui design it isn’t as good and as clean as my refernce but I am still happ with it i even added the code from where the gui redesign started. by the way i had to change this exact code numerous timessssss. This devlog includes the most time i spent vibe coding , and regretted………….. So i hope to add 2-3 more features like allowing admins to change the password(maybe) and I hope to ship this project by day after tommorow :)"}, {"post_id": 63630, "ts": "2026-09-07T15:37:46Z", "hours": 1.7175, "text": "DEVLOG#8 Today I fixed ALL of the mistakes like when u get the admin passowrd wrong whilst changing the status of a Issue report shitt was working great i hope to ship this before the 10th buutttttttttttttt….. Life isn’t so easy, I wanted to UPGRADE the GUI one last time to make it look like a decent application and I am still in the middle of that but i will definitely update u according to my progress. Here my inspiration ( not where i am rn ) I am aiming for smthing like this for my app"}, {"post_id": 60904, "ts": "2026-09-03T15:40:22Z", "hours": 1.0444, "text": "DEVLOG #8 So today I gave the same functions i gave to student view yesterday to admin view but better I added a priority calculator, a show more show less thing from yesterday and the filter thingy"}, {"post_id": 60289, "ts": "2026-09-02T15:47:16Z", "hours": 1.0939, "text": "DEVOG#7 This took way more time than it should have, so when i ran the program today I realized that the filter function wasn’t working properly and to fix i ended up removing the show show less option which i got working after loads of struggles due to some of the STUPIDEST mistakes…"}, {"post_id": 59638, "ts": "2026-09-01T15:38:45Z", "hours": 2.1444, "text": "DEVLOG #6 SO today consisted of me correcting my stupid mistakes again…. But this time I actually fixed everything and I also added a show more, show less option/button because too much text was ending up pushing the upvote button off the screen, making it IMPOSSIBLE to upvote. I also add a feature that lets the users sort and classify the problems so its easier to manage rather than having like 20+ problems on your page and having to read through ALL of themm.. Along with that I even took the concept of taking urgency as input out of the equation as I didn’t want people to be writing “The urgency is 9999 bro trust me”; to deal with such larpers I added basic yet effective limiters…"}, {"post_id": 59536, "ts": "2026-09-01T12:40:57Z", "hours": 0.8722, "text": "DEVLOG#5 So I basically worked on adding a function to chage the status of a problem, something only admins can access. Liittle did I know I would mess up half of the code smhw, even Chatgpt wasn’t helping but after fixing some of the stupidest mistakes I got the code running, but yes there are still some problemss…"}, {"post_id": 57405, "ts": "2026-08-29T15:28:54Z", "hours": 1.0681, "text": "DEVLOG#4 so today included touching up and finessing because i forgot to add features, i also added a change password function messed around with customtkinter but failed miserably hope to do some absolute legendary progress tomorrow."}, {"post_id": 56566, "ts": "2026-08-28T11:29:59Z", "hours": 3.6278, "text": "DEVLOG#3 Absolutely Legendary progress, almost done with the final GUI looks awesome. I also worked on major backend code addes passwords and login statements for both students and admins and i also ensured that one person cannot upvote on an issue more than once. I also added guest mode. Tomorrow will include making loads of changes and making the GUI better!"}, {"post_id": 55581, "ts": "2026-08-27T15:05:38Z", "hours": 1.0158, "text": "DEVLOG#2 So today was a mess because I had to go around fighting teachers in my school just so I could have my OWN LAPTOP, a big pain in the *ss but all of that stuff aside. Today’s progress was decent i worked on the GUI alot messed around with Tkinter diferrent sizes and style and I also added a admin tab to the website which is still in progress because I ran into numerous errors and I am still pinpointing my mistakes. Along with the admin tab I added a login interface type of thig and that turned out to be a task because again MY FIRST TIME designing an OAUTH. Hope to improve the GUI a lotttttt!!!!!!! but i am satisfied with what i have right now. till we meet againnnnnn………."}, {"post_id": 55107, "ts": "2026-08-26T15:47:57Z", "hours": 1.0783, "text": "DEVLOG#1 First time working with JSON and Tkinter till now i have coded the frontend of the app to some extent and hope to start working on the backend soon. This was also my first time using JSON, I used it to make kind of like a database which store previous complains and uses this stored data to develop a combined report of similar issues. Lovely experience, but not going to lie Gemini helped me out a lot to spot my mistakes in like every 20-25 lines and it turned out to be somewhat a pain but I hope that JSON and Tkinter will help me developing future projects."}]...
|
Title: BLACKBOX (complain filing application) by @ Title: BLACKBOX (complain filing application) by @FabulousHippoOfOrangeLake | Stardance
Devlogs:
DEVLOG#1 First time working with JSON and Tkinter till now i have coded the frontend of the app to some extent and hope to start working on the backend soon. This was also my first time using JSON, I used it to make kind of like a database which store previous complains and uses this stored data to develop a combined report of similar issues. Lovely experience, but not going to lie Gemini helped me out a lot to spot my mistakes in like every 20-25 lines and it turned out to be somewhat a pain but I hope that JSON and Tkinter will help me developing future projects.
DEVLOG#2 So today was a mess because I had to go around fighting teachers in my school just so I could have my OWN LAPTOP, a big pain in the *ss but all of that stuff aside. Today’s progress was decent i worked on the GUI alot messed around with Tkinter diferrent sizes and style and I also added a admin tab to the website which is still in progress because I ran into numerous errors and I am still pinpointing my mistakes. Along with the admin tab I added a login interface type of thig and that turned out to be a task because again MY FIRST TIME designing an OAUTH. Hope to improve the GUI a lotttttt!!!!!!! but i am satisfied with what i have right now. till we meet againnnnnn……….
DEVLOG#3 Absolutely Legendary progress, almost done with the final GUI looks awesome. I also worked on major backend code addes passwords and login statements for both students and admins and i also ensured that one person cannot upvote on an issue more than once. I also added guest mode. Tomorrow will include making loads of changes and making the GUI better!
DEVLOG#4 so today included touching up and finessing because i forgot to add features, i also added a change password function messed around with customtkinter but failed miserably hope to do some absolute legendary progress tomorrow.
DEVLOG#5 So I basically worked on adding a function to chage the status of a problem, something only admins can access. Liittle did I know I would mess up half of the code smhw, even Chatgpt wasn’t helping but after fixing some of the stupidest mistakes I got the code running, but yes there are still some problemss…
DEVLOG #6 SO today consisted of me correcting my stupid mistakes again…. But this time I actually fixed everything and I also added a show more, show less option/button because too much text was ending up pushing the upvote button off the screen, making it IMPOSSIBLE to upvote. I also add a feature that lets the users sort and classify the problems so its easier to manage rather than having like 20+ problems on your page and having to read through ALL of themm.. Along with that I even took the concept of taking urgency as input out of the equation as I didn’t want people to be writing “The urgency is 9999 bro trust me”; to deal with such larpers I added basic yet effective limiters…
DEVOG#7 This took way more time than it should have, so when i ran the program today I realized that the filter function wasn’t working properly and to fix i ended up removing the show show less option which i got working after loads of struggles due to some of the STUPIDEST mistakes…
DEVLOG #8 So today I gave the same functions i gave to student view yesterday to admin view but better I added a priority calculator, a show more show less thing from yesterday and the filter thingy
DEVLOG#8 Today I fixed ALL of the mistakes like when u get the admin passowrd wrong whilst changing the status of a Issue report shitt was working great i hope to ship this before the 10th buutttttttttttttt….. Life isn’t so easy, I wanted to UPGRADE the GUI one last time to make it look like a decent application and I am still in the middle of that but i will definitely update u according to my progress. Here my inspiration ( not where i am rn ) I am aiming for smthing like this for my app
DEVLOG#9 So today I finished the new gui design it isn’t as good and as clean as my refernce but I am still happ with it i even added the code from where the gui redesign started. by the way i had to change this exact code numerous timessssss. This devlog includes the most time i spent vibe coding , and regretted………….. So i hope to add 2-3 more features like allowing admins to change the password(maybe) and I hope to ship this project by day after tommorow :)
DEVLOG #9 idk SO i added so may features and it was such a pain in the ass to retain feature when adding new ones i kept messing up here and there and even forgot to call the simplest of functions. But now i’m here and this is what I added: Different types of admin (headmaster, housemaster senior master etc.) feature to chose who u want to submit the report too feature to forward the issue (as an admin) - if the particular admin finds its not for him logging in if ur in guest mode and logging out if ur in student mode my reports and all reports button added a view issue button which lets u view the full issue instead of the dot expanding thing i had before lastly the stupidest but most needed asterisk while entering passwords.
Ships:
I made a python desktop app for student feedback, issue and complain management. The main idea was to provide students with one core place to report problems. Students use their roll number for logins, they can upvote issues to show its urgency, they can change their own password. There is also a separate admin dashboard with issues organised cleanly according to priority. I am proud of using Custom Tkinter for the first time but not proud of having 1200 lines of code in one file! I hope u find this project worthy and fun to use!...
|
1793559513.6685078
|
1793645913.6685078
|
|
59451
|
AIRWHEEL by @DikshitNeupane | Stardance
|
DikshitNeupane
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: AIRWHEEL by @DikshitNeupane | Stardance
|
1793559514.8933764
|
1794164314.8933764
|
|
4792
|
My awesome macropad! by @Dishsoap | Stardance
|
Dishsoap
|
0
|
0.28
|
0
|
[]
|
[{"post_id": 30006, "ts": "202 [{"post_id": 30006, "ts": "2026-07-17T07:44:39Z", "hours": 0.2836, "text": "(I actually did some stuff outside of the timelapse but I forgot to record it :/) Did a basic schematic and pcb design, so I hope that I can use these skills to make my own fully customised macropad. Also did a rough CAD design."}]...
|
Title: My awesome macropad! by @Dishsoap | Stardan Title: My awesome macropad! by @Dishsoap | Stardance
Devlogs:
(I actually did some stuff outside of the timelapse but I forgot to record it :/) Did a basic schematic and pcb design, so I hope that I can use these skills to make my own fully customised macropad. Also did a rough CAD design....
|
1793559515.8095233
|
1794164315.8095233
|
|
37361
|
Pixel-Art Robots by @Robot | Stardance
|
Robot
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Pixel-Art Robots by @Robot | Stardance
|
1793559516.7338703
|
1794164316.7338703
|