|
40455
|
PeriodicX by @Aditya_Jaiswal | Stardance
|
Aditya_Jaiswal
|
1
|
3.59
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-28T12:56:31Z", "hours": 3.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "PeriodicX is a modern interactive chemistry platform featuring a dynamic periodic table, 3D atomic structure visualization, flashcards, quizzes, element search, and educational tools to make learning chemistry engaging, visual, and accessible.", "repo": "https://github.com/programmeraj2011/PeriodicX", "demo": "https://perodicx.netlify.app/"}]...
|
[{"post_id": 57235, "ts": "202 [{"post_id": 57235, "ts": "2026-08-29T10:42:03Z", "hours": 0.5942, "text": "Devlog #4 updated Elements UI (and sorry for being late i was kinda busy soo)"}, {"post_id": 35759, "ts": "2026-07-27T12:20:35Z", "hours": 0.8558, "text": "Devlog #3 Hello everyone, I have just updated the CSS, added flashcards for each element with its information, included a 3D atomic viewer, and added tests and chemical reactions."}, {"post_id": 35713, "ts": "2026-07-27T09:56:06Z", "hours": 0.8856, "text": "Devlog #2 written all the data of the perodic table"}, {"post_id": 35676, "ts": "2026-07-27T08:40:49Z", "hours": 1.0439, "text": "I am working on my project called PerodicX"}]...
|
Title: PeriodicX by @Aditya_Jaiswal | Stardance
D Title: PeriodicX by @Aditya_Jaiswal | Stardance
Devlogs:
I am working on my project called PerodicX
Devlog #2 written all the data of the perodic table
Devlog #3 Hello everyone, I have just updated the CSS, added flashcards for each element with its information, included a 3D atomic viewer, and added tests and chemical reactions.
Devlog #4 updated Elements UI (and sorry for being late i was kinda busy soo)
Ships:
PeriodicX is a modern interactive chemistry platform featuring a dynamic periodic table, 3D atomic structure visualization, flashcards, quizzes, element search, and educational tools to make learning chemistry engaging, visual, and accessible....
|
1793825330.3814144
|
1793911730.3814144
|
|
27592
|
My awesome macropad! by @____ | Stardance
|
____
|
0
|
1.1
|
0
|
[]
|
[{"post_id": 19553, "ts": "202 [{"post_id": 19553, "ts": "2026-06-30T21:36:04Z", "hours": 0.2833, "text": "Finished PCB!!!"}, {"post_id": 19447, "ts": "2026-06-30T19:27:27Z", "hours": 0.8175, "text": "Finished the schematic editor portion!"}]...
|
Title: My awesome macropad! by @____ | Stardance
Title: My awesome macropad! by @____ | Stardance
Devlogs:
Finished the schematic editor portion!
Finished PCB!!!...
|
1793306930.1648579
|
1793911730.1648579
|
|
32459
|
A room automator by @navithachandrasiri | Stardanc A room automator by @navithachandrasiri | Stardance...
|
navithachandrasiri
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: A room automator by @navithachandrasiri | S Title: A room automator by @navithachandrasiri | Stardance...
|
1793306929.2777638
|
1793911729.2777638
|
|
28271
|
TANK GAME by @abhinavP | Stardance
|
abhinavP
|
0
|
13.23
|
0
|
[]
|
[{"post_id": 44244, "ts": "202 [{"post_id": 44244, "ts": "2026-08-09T21:27:15Z", "hours": 8.2333, "text": "This is the part where the game actually starts doing things. Wraps up arena generation, then jumps into shooting, movement, input, the bot’s brain, powerups, and bullets. begin_level and start_match are just glue, reset the tanks, build the level, flip the state to playing. start_match additionally zeroes out score and level since that only happens when a whole new match starts, not every round. fire_from is where powerups actually change what comes out of the barrel. Big shells make the bullet bigger and slower but harder hitting. Lock-On just flags the bullet as homing. Twin Cannons is the odd one out since it fires two bullets at a slight angle instead of changing one bullet’s stats. Bullets spawn a little in front of the tank’s nose too, otherwise they’d spawn inside their own tank and immediately register a hit on the guy who just fired. try_move_tank is the one function basically everything routes through, player and bot both. Clamp the position, check it against every obstacle, only actually move if nothing’s blocking, unless you’ve got the Dozer Blade and you’re hitting a crate specifically, then the crate just dies instead. handle_player_input is the “instant facing” control scheme. Read whichever movement keys are held, build a direction, normalize it so diagonals aren’t faster than straight lines, then just snap the tank’s angle straight to that direction. No gradual turning for humans, you press a direction and you’re already facing it. update_bot is the biggest one here and honestly the most fun to write. Every frame it loads its difficulty stats, decides whether to chase the player or detour for a nearby powerup, figures out how far off its aim is, probes a little bit ahead of itself to avoid walking into walls, turns gradually toward its goal since bots don’t get the instant snap the player gets, picks a speed based on distance to target, and only actually shoots if its aim is tight enough and the target’s in range. maybe_spawn_powerup and check_powerup_pickup are pretty simple, try random spots until one doesn’t overlap anything or spawn too close to a tank, and check distance for pickup. update_bullets is the long one. Homing bullets get nudged toward their target a little each frame instead of snapping straight at it, so they’re curveable and dodgeable, not laser guided. Then every bullet gets checked against the arena bounds, every obstacle, and both tanks, in that order, and whichever one it hits first is what actually happens to it. update_particles is just the tiny cosmetic bit, dots that drift, slow down over time, and fade out. Purely for hit sparks and crate destruction, doesn’t affect gameplay at all."}, {"post_id": 39901, "ts": "2026-08-03T06:00:02Z", "hours": 2.1333, "text": "Devlogs might be ragebait… Lines 1 to 217 are basically just setup, nothing’s actually running yet. Top of the file is the instruction manual docstring, how to install and run it. Then imports, math for angles and distances, random for scattering stuff and giving the bot some unpredictability, pygame doing the actual window and drawing and input work. After that’s a big constants block, basically a settings panel. Window size, tank stats, bullet speed, all the colors. The two fun ones are POWER_TYPES, which holds each powerup’s color and name in one place, and DIFFICULTIES, which is basically the bot’s stat sheet for easy medium and hard. Then MAPS, the four arenas, built so they’re mirror symmetric so nobody spawns with worse cover. Three small helper functions come next. clamp keeps a number in range. ang_diff figures out the short way to turn instead of spinning the long way around. circle_rect_hit checks if a circle touches a rectangle, and honestly this one function quietly handles every collision in the whole game. Then the entity classes, Obstacle, Powerup, Bullet, Tank. All pretty dumb on purpose, they just hold data like position and health, they don’t do anything themselves. Last bit is Game. init setting up empty lists and the score, and reset_tanks, which puts player one at the bottom facing up and player two or the bot at the top facing down. That’s it, that’s everything before the game logic actually kicks in."}, {"post_id": 32794, "ts": "2026-07-22T05:38:38Z", "hours": 2.8667, "text": "Making the base for the tank game and creating the maps, difficulty modes, colors, and upgrades."}]...
|
Title: TANK GAME by @abhinavP | Stardance
Devlogs Title: TANK GAME by @abhinavP | Stardance
Devlogs:
Making the base for the tank game and creating the maps, difficulty modes, colors, and upgrades.
Devlogs might be ragebait… Lines 1 to 217 are basically just setup, nothing’s actually running yet. Top of the file is the instruction manual docstring, how to install and run it. Then imports, math for angles and distances, random for scattering stuff and giving the bot some unpredictability, pygame doing the actual window and drawing and input work. After that’s a big constants block, basically a settings panel. Window size, tank stats, bullet speed, all the colors. The two fun ones are POWER_TYPES, which holds each powerup’s color and name in one place, and DIFFICULTIES, which is basically the bot’s stat sheet for easy medium and hard. Then MAPS, the four arenas, built so they’re mirror symmetric so nobody spawns with worse cover. Three small helper functions come next. clamp keeps a number in range. ang_diff figures out the short way to turn instead of spinning the long way around. circle_rect_hit checks if a circle touches a rectangle, and honestly this one function quietly handles every collision in the whole game. Then the entity classes, Obstacle, Powerup, Bullet, Tank. All pretty dumb on purpose, they just hold data like position and health, they don’t do anything themselves. Last bit is Game. init setting up empty lists and the score, and reset_tanks, which puts player one at the bottom facing up and player two or the bot at the top facing down. That’s it, that’s everything before the game logic actually kicks in.
This is the part where the game actually starts doing things. Wraps up arena generation, then jumps into shooting, movement, input, the bot’s brain, powerups, and bullets. begin_level and start_match are just glue, reset the tanks, build the level, flip the state to playing. start_match additionally zeroes out score and level since that only happens when a whole new match starts, not every round. fire_from is where powerups actually change what comes out of the barrel. Big shells make the bullet bigger and slower but harder hitting. Lock-On just flags the bullet as homing. Twin Cannons is the odd one out since it fires two bullets at a slight angle instead of changing one bullet’s stats. Bullets spawn a little in front of the tank’s nose too, otherwise they’d spawn inside their own tank and immediately register a hit on the guy who just fired. try_move_tank is the one function basically everything routes through, player and bot both. Clamp the position, check it against every obstacle, only actually move if nothing’s blocking, unless you’ve got the Dozer Blade and you’re hitting a crate specifically, then the crate just dies instead. handle_player_input is the “instant facing” control scheme. Read whichever movement keys are held, build a direction, normalize it so diagonals aren’t faster than straight lines, then just snap the tank’s angle straight to that direction. No gradual turning for humans, you press a direction and you’re already facing it. update_bot is the biggest one here and honestly the most fun to write. Every frame it loads its difficulty stats, decides whether to chase the player or detour for a nearby powerup, figures out how far off its aim is, probes a little bit ahead of itself to avoid walking into walls, turns gradually toward its goal since bots don’t get the instant snap the player gets, picks a speed based on distance to target, and only actually shoots if its aim is tight enough and the target’s in range. maybe_spawn_powerup and check_powerup_pickup are pretty simple, try random spots until one doesn’t overlap anything or spawn too close to a tank, and check distance for pickup. update_bullets is the long one. Homing bullets get nudged toward their target a little each frame instead of snapping straight at it, so they’re curveable and dodgeable, not laser guided. Then every bullet gets checked against the arena bounds, every obstacle, and both tanks, in that order, and whichever one it hits first is what actually happens to it. update_particles is just the tiny cosmetic bit, dots that drift, slow down over time, and fade out. Purely for hit sparks and crate destruction, doesn’t affect gameplay at all....
|
1793306926.8751314
|
1793911726.8751314
|
|
32797
|
my APOD site by @rndm | Stardance
|
rndm
|
1
|
15.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-22T17:57:34Z", "hours": 15.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a NASA APOD website with Vite", "repo": "https://github.com/random-72521/nasa_image_site", "demo": "https://random-72521.github.io/nasa_image_site/"}]...
|
[{"post_id": 33082, "ts": "202 [{"post_id": 33082, "ts": "2026-07-22T17:44:53Z", "hours": 6.0022, "text": "i finished it"}, {"post_id": 27940, "ts": "2026-07-13T21:39:49Z", "hours": 4.1178, "text": "made it look better with a cool loading anim also info but you cant see in ss"}, {"post_id": 24987, "ts": "2026-07-08T21:35:11Z", "hours": 4.5481, "text": "it works it just looks ugly 3 hours of this was spent trying to do gh pages"}]...
|
Title: my APOD site by @rndm | Stardance
Devlogs: Title: my APOD site by @rndm | Stardance
Devlogs:
it works it just looks ugly 3 hours of this was spent trying to do gh pages
made it look better with a cool loading anim also info but you cant see in ss
i finished it
Ships:
I made a NASA APOD website with Vite...
|
1793825325.659325
|
1793911725.659325
|
|
3881
|
Ultimate Space Dodger by @Eshwarg | Stardance
|
Eshwarg
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Ultimate Space Dodger by @Eshwarg | Stardan Title: Ultimate Space Dodger by @Eshwarg | Stardance...
|
1793306922.4236748
|
1793911722.4236748
|
|
16496
|
StarPad by @Aahil78 | Stardance
|
Aahil78
|
0
|
8.64
|
0
|
[]
|
[{"post_id": 84155, "ts": "202 [{"post_id": 84155, "ts": "2026-10-29T06:08:26Z", "hours": 0.8653, "text": "Okay so good news and bad news. Good news is that I’m finally back in Hack Club!!!!!!!!!!! Bad news is my PC broke and I lost the whole fucking project :(((((((( So im starting from scratch, im using the journal images for reference so its much much faster. Rn im like 90ish percent done with the schematic just gotta arrange and final check the schematic. Bye! Oh also here’s the lapse link! Lapse"}, {"post_id": 16455, "ts": "2026-06-26T19:42:28Z", "hours": 2.0617, "text": "I wrote all the QMK Firmware, having some compiling issues but I’ll try to fix that later when I get the hardware as itll be easier for me to debug and troubleshoot. Worst case I’ll switch to KMK or RMK as I have written in KMK before"}, {"post_id": 10998, "ts": "2026-06-18T00:50:40Z", "hours": 0.9686, "text": "Hi, I made the Plate of the Case and did some finishing touches. Now I’ll do the QMK so for that I’ll do everything in Github Codespaces bcz my laptop only has 100mb free on C Drive and no other storage. So rn I’ll make a git repo and upload all production and src files in one commit then start doing the QMK. Lapse Link: Lapse"}, {"post_id": 10487, "ts": "2026-06-17T07:20:47Z", "hours": 0.9119, "text": "I finished off the base of the case rn, I’ll do the top plate then start the QMK. I may not be writing much rn bcz my mood is rlly messed up (apparently 2hrs is too much to learn HTML and make ur first ever website - according to macondo, if you spend too long learning smthn it means u are foing fraud and they ban ur project that u made with ur whole heart) Lapse Link: https://lapse.hackclub.com/timelapse/3z5x-61gHgDi"}, {"post_id": 9768, "ts": "2026-06-16T06:29:37Z", "hours": 0.9028, "text": "Hi! Right now I finished the rest of the PCB, I: Rounded off the corners (3mm fillet) Finished all routing and changed some traces to make everything work (I used ALOT of vias hope that isn’t an issue!) Ran DRC - 3 times - to make sure nothing goes wrong Repositioned the LED Pad for easier soldering And I think that’s pretty much it! Oh yeah I crashed out a lot cz some traces were in the area of the LED which is the hole area (I can NOT speak rn) but u get the point like the hole that is cut out for the LED, over there, there were traces so i had to move them, then, some tracks were inside other tracks of totally different nets like I crashed out sm cz of this. Anyways, im done with my PCB i’ll just double check diode orientation (I can fix it later by soldering diodes other way around but i wanna make this easier for me) and then I’ll start working on the CAD. I hope I can use OnShape Hackatime instead of lapse cz i am tired of using lapse. Anyways, cyaaa!!!! Lapse Link: https://lapse.hackclub.com/timelapse/jHSqlRHYnwNE"}, {"post_id": 8537, "ts": "2026-06-14T06:11:59Z", "hours": 1.6903, "text": "Hi, back with another devlog, right now I added all the components to my PCB, routed alot, arranged everything, searched for footprints, and I did manual precise placement of LEDs. Right now theres still some routing left, gotta round the corners, add art, and make the entire thing just better in general. Then we can move on to the software. Lapse Link: https://lapse.hackclub.com/timelapse/04KqJEMffp7a"}, {"post_id": 7500, "ts": "2026-06-12T14:41:28Z", "hours": 0.6936, "text": "Hi! I added the RGB, double checked everything, and organized the schematic and made it prettier! I was also tryna add the stardance logo in the bottom left corner but it just wasnt working so I added the orpheus skating on a pcb image. For the RGB, I added a 330ohm resistor on the data line for Anti Ringing and to limit the data current so it dosent bounce around and cause data corruption or whatever, and I added a connector in the schematic at the RGB Pin, that will be an SMD Pad on the PCB so i solder a wire from the SMD Pad to the Xiao RGB Pin. Now I just gotta make the PCB then the case. Lapse Link: https://lapse.hackclub.com/timelapse/yA3oJffGrZsA"}, {"post_id": 7017, "ts": "2026-06-11T19:30:32Z", "hours": 0.5431, "text": "So I decided what components to use, I decided the following: 1x EC11 w/Switch 3x4 MX Layout 1x 0.91” i2c OLED Seeed Studio XIAO RP2040 12x SK6812 RGB LEDs Since there are only 11 GPIO Pins broken out, I’m going to solder the NeoPixel LED DIN Pin to the on-board RGB LED DIN Pin or via, this will allow me to also have RGB without having to compromise on my components selection. I could’ve tried using an I/O Expander IC like the MCP23017 or similar but that would’ve added cost and complexity, and since this will be the first time I make a macropad/keeb that will (or should) actually work, I wanna keep the hardware and firmware as easy as possible to reduce the chances of me fucking it up. After deciding everything, I created a KiCad proj, downloaded the libs and added them to KiCad, opened lapse, and locked in and designed the schematic. Some pauses where my mouse was moving but nothing going on in KiCad was me searching up on google to fact-check my decisions, like how to wire the matrix and stuff. Sometimes I was going to the Hackpad docs (like for the OLED part), and sometimes it was when I was adding footprints or net labels, so sorry for those pauses lol. Now all I have to do is add the RGB, double check everything, assign footprints, etc. Then I can move on to the PCB and CAD. Lapse Link: https://lapse.hackclub.com/timelapse/DoOaE3jAJ1TA"}]...
|
Title: StarPad by @Aahil78 | Stardance
Devlogs:
S Title: StarPad by @Aahil78 | Stardance
Devlogs:
So I decided what components to use, I decided the following: 1x EC11 w/Switch 3x4 MX Layout 1x 0.91” i2c OLED Seeed Studio XIAO RP2040 12x SK6812 RGB LEDs Since there are only 11 GPIO Pins broken out, I’m going to solder the NeoPixel LED DIN Pin to the on-board RGB LED DIN Pin or via, this will allow me to also have RGB without having to compromise on my components selection. I could’ve tried using an I/O Expander IC like the MCP23017 or similar but that would’ve added cost and complexity, and since this will be the first time I make a macropad/keeb that will (or should) actually work, I wanna keep the hardware and firmware as easy as possible to reduce the chances of me fucking it up. After deciding everything, I created a KiCad proj, downloaded the libs and added them to KiCad, opened lapse, and locked in and designed the schematic. Some pauses where my mouse was moving but nothing going on in KiCad was me searching up on google to fact-check my decisions, like how to wire the matrix and stuff. Sometimes I was going to the Hackpad docs (like for the OLED part), and sometimes it was when I was adding footprints or net labels, so sorry for those pauses lol. Now all I have to do is add the RGB, double check everything, assign footprints, etc. Then I can move on to the PCB and CAD. Lapse Link: https://lapse.hackclub.com/timelapse/DoOaE3jAJ1TA
Hi! I added the RGB, double checked everything, and organized the schematic and made it prettier! I was also tryna add the stardance logo in the bottom left corner but it just wasnt working so I added the orpheus skating on a pcb image. For the RGB, I added a 330ohm resistor on the data line for Anti Ringing and to limit the data current so it dosent bounce around and cause data corruption or whatever, and I added a connector in the schematic at the RGB Pin, that will be an SMD Pad on the PCB so i solder a wire from the SMD Pad to the Xiao RGB Pin. Now I just gotta make the PCB then the case. Lapse Link: https://lapse.hackclub.com/timelapse/yA3oJffGrZsA
Hi, back with another devlog, right now I added all the components to my PCB, routed alot, arranged everything, searched for footprints, and I did manual precise placement of LEDs. Right now theres still some routing left, gotta round the corners, add art, and make the entire thing just better in general. Then we can move on to the software. Lapse Link: https://lapse.hackclub.com/timelapse/04KqJEMffp7a
Hi! Right now I finished the rest of the PCB, I: Rounded off the corners (3mm fillet) Finished all routing and changed some traces to make everything work (I used ALOT of vias hope that isn’t an issue!) Ran DRC - 3 times - to make sure nothing goes wrong Repositioned the LED Pad for easier soldering And I think that’s pretty much it! Oh yeah I crashed out a lot cz some traces were in the area of the LED which is the hole area (I can NOT speak rn) but u get the point like the hole that is cut out for the LED, over there, there were traces so i had to move them, then, some tracks were inside other tracks of totally different nets like I crashed out sm cz of this. Anyways, im done with my PCB i’ll just double check diode orientation (I can fix it later by soldering diodes other way around but i wanna make this easier for me) and then I’ll start working on the CAD. I hope I can use OnShape Hackatime instead of lapse cz i am tired of using lapse. Anyways, cyaaa!!!! Lapse Link: https://lapse.hackclub.com/timelapse/jHSqlRHYnwNE
I finished off the base of the case rn, I’ll do the top plate then start the QMK. I may not be writing much rn bcz my mood is rlly messed up (apparently 2hrs is too much to learn HTML and make ur first ever website - according to macondo, if you spend too long learning smthn it means u are foing fraud and they ban ur project that u made with ur whole heart) Lapse Link: https://lapse.hackclub.com/timelapse/3z5x-61gHgDi
Hi, I made the Plate of the Case and did some finishing touches. Now I’ll do the QMK so for that I’ll do everything in Github Codespaces bcz my laptop only has 100mb free on C Drive and no other storage. So rn I’ll make a git repo and upload all production and src files in one commit then start doing the QMK. Lapse Link: Lapse
I wrote all the QMK Firmware, having some compiling issues but I’ll try to fix that later when I get the hardware as itll be easier for me to debug and troubleshoot. Worst case I’ll switch to KMK or RMK as I have written in KMK before
Okay so good news and bad news. Good news is that I’m finally back in Hack Club!!!!!!!!!!! Bad news is my PC broke and I lost the whole fucking project :(((((((( So im starting from scratch, im using the journal images for reference so its much much faster. Rn im like 90ish percent done with the schematic just gotta arrange and final check the schematic. Bye! Oh also here’s the lapse link! Lapse...
|
1793306919.8507342
|
1793911719.8507342
|
|
33390
|
My own site! by @Saontika | Stardance
|
Saontika
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My own site! by @Saontika | Stardance
|
1793306918.913288
|
1793911718.913288
|
|
4881
|
Media Review Webpage by @nic | Stardance
|
nic
|
1
|
5.0
|
41
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-24T01:00:17Z", "hours": 5.0, "multiplier": 8.68, "payout": 41, "blessing": "neutral", "text": "A small webpage built with HTML, CSS, and a speck of JavaScript for my personal TV show/movie anime reviews! Inspired by old website aesthetics from the y2k era. Presented like a personal blog, and used to track my currently watched/watching shows as well as occasionally sharing my thoughts about recently finished movies. [created in mind with the indie web movement on neocities]", "repo": "https://github.com/sodahaunted/sodahaunt.reviews", "demo": "https://sodahaunt.neocities.org/reviews"}]...
|
[{"post_id": 33196, "ts": "202 [{"post_id": 33196, "ts": "2026-07-22T21:44:56Z", "hours": 1.7128, "text": "Media Review Webpage #3 After a long time procrastinating, I’m finally done with the concept/prototype of my webpage. I wrote one full review for a recent movie I watched (Obsession), formatted it, added photos, and made sure the two lines of JavaScript code work properly. Not sure how to add more pages, though. I’ll figure that out for a future update (though if you know how, please lmk) The fundamentals of this page are pretty much finished! It has a watchlist which I can use to track shows/movies I’m watching, a (mostly) responsive layout, and all the CSS features I intended to add. Unfortunately lost an hour or two here and there because I forgot to unpause my recording, but oh well. The GIT repo for this page unfortunately doesn’t have many commits, since I wasn’t using GitHub to make this and was pretty unfamiliar with it when I started this project. It has all the code, just no visible edits/changes. Sorry about that. I used Neocities for the entirety of this site, which is what I mainly use to publish html/css projects."}, {"post_id": 15446, "ts": "2026-06-25T03:17:46Z", "hours": 2.5336, "text": "Media Review Webpage | Devlog #2 After a long hiatus, I came back to this project with a bit more motivation and inspiration than last time. I had a ton of ideas for what I wanted to do, but I wasn’t sure my skill level was high enough to program them. I only know HTML, CSS, and a bit of JavaScript, so even doing small things like showing/hiding elements takes me a long time. Challenges I wanted to make multiple pages using just one HTML file, since I wasn’t sure how many reviews I’d end up writing, and I wanted everything to be in one document. I got the text at the bottom to work properly like I wanted to, but I still don’t know how to show/hide more than one element at a time. Using Flexbox was also a pain since my images never resize how I want them to, and I want to make this page mobile-friendly. I might look back at my code from a previous project to try and figure that out in the next devlog. Additions I mainly focused on resizing everything to look a bit cleaner, and also because the previous layout was just a 500px box that barely showed any info. I changed the banner at the top and the background to something more library-themed."}, {"post_id": 4603, "ts": "2026-06-07T23:28:41Z", "hours": 0.5278, "text": "Media Review Webpage | Devlog #1 I had an idea for a while to make my own movie review/blog page, but I never really got around to doing it. Stardance was a good excuse for me to start making a lot of projects I’d procrastinated on for the past few months. short update to test lapse/hackatime changed the colours and fixed some sizing issues, planning to replace the photos and redo the actual layout next The majority of the code is carried over from a previous project I started in the past, which I’m planning to revamp and complete during Stardance."}]...
|
Title: Media Review Webpage by @nic | Stardance
D Title: Media Review Webpage by @nic | Stardance
Devlogs:
Media Review Webpage | Devlog #1 I had an idea for a while to make my own movie review/blog page, but I never really got around to doing it. Stardance was a good excuse for me to start making a lot of projects I’d procrastinated on for the past few months. short update to test lapse/hackatime changed the colours and fixed some sizing issues, planning to replace the photos and redo the actual layout next The majority of the code is carried over from a previous project I started in the past, which I’m planning to revamp and complete during Stardance.
Media Review Webpage | Devlog #2 After a long hiatus, I came back to this project with a bit more motivation and inspiration than last time. I had a ton of ideas for what I wanted to do, but I wasn’t sure my skill level was high enough to program them. I only know HTML, CSS, and a bit of JavaScript, so even doing small things like showing/hiding elements takes me a long time. Challenges I wanted to make multiple pages using just one HTML file, since I wasn’t sure how many reviews I’d end up writing, and I wanted everything to be in one document. I got the text at the bottom to work properly like I wanted to, but I still don’t know how to show/hide more than one element at a time. Using Flexbox was also a pain since my images never resize how I want them to, and I want to make this page mobile-friendly. I might look back at my code from a previous project to try and figure that out in the next devlog. Additions I mainly focused on resizing everything to look a bit cleaner, and also because the previous layout was just a 500px box that barely showed any info. I changed the banner at the top and the background to something more library-themed.
Media Review Webpage #3 After a long time procrastinating, I’m finally done with the concept/prototype of my webpage. I wrote one full review for a recent movie I watched (Obsession), formatted it, added photos, and made sure the two lines of JavaScript code work properly. Not sure how to add more pages, though. I’ll figure that out for a future update (though if you know how, please lmk) The fundamentals of this page are pretty much finished! It has a watchlist which I can use to track shows/movies I’m watching, a (mostly) responsive layout, and all the CSS features I intended to add. Unfortunately lost an hour or two here and there because I forgot to unpause my recording, but oh well. The GIT repo for this page unfortunately doesn’t have many commits, since I wasn’t using GitHub to make this and was pretty unfamiliar with it when I started this project. It has all the code, just no visible edits/changes. Sorry about that. I used Neocities for the entirety of this site, which is what I mainly use to publish html/css projects.
Ships:
A small webpage built with HTML, CSS, and a speck of JavaScript for my personal TV show/movie anime reviews! Inspired by old website aesthetics from the y2k era. Presented like a personal blog, and used to track my currently watched/watching shows as well as occasionally sharing my thoughts about recently finished movies. [created in mind with the indie web movement on neocities]...
|
1793825318.3207283
|
1793911718.3207283
|
|
3032
|
Untitled by @Callisto | Stardance
|
Callisto
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Untitled by @Callisto | Stardance
|
1793306916.7614982
|
1793911716.7614982
|
|
24009
|
My first slack bot! by @Gal | Stardance
|
Gal
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @Gal | Stardance
|
1793306914.6366663
|
1793911714.6366663
|
|
27798
|
Word Embeddings by @stockifab | Stardance
|
stockifab
|
1
|
28.0
|
556
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-25T19:47:36Z", "hours": 28.0, "multiplier": 16.45, "payout": 556, "blessing": "neutral", "text": "Word embeddings are a way to store the meaning of word (such as “plane” or “dog”) in a large vector (= a long list of numbers) These vectors can then be used to find words similar to each other. But they can also be used to calculate with English words, e.g.: dog - bark + meow –> cat (in fact, you can try this very example on the demo website, or come up with your own calculation) In order to retrieve these embeddings, I created a model that reads through billions of words to understand how they are used. It looks at the words appearing close to each other and assumes all words with the same nearby words must have similar meaning. This retrieval of the embeddings was the hardest part: My first model was okayish and could find related words, but I could not yet calculate with them like in the example before. For the final version I used a much larger dataset, with thought-out pre-processing steps, which was more complicated then I thought (You need to ensure the words you are grouping actually belong together, so you may only group within individual sentences, groups mustn’t overlap anything inside brackets, and you can’t make a group with words you filtered in pre-processing at the same time you shouldn’t skip any words, …) Additionally the challenge with a larger dataset was, that it didnt fit into my memory, so I had to read it in chunks and train the model incrementally. The training of the final model took over 50 hours.", "repo": "https://github.com/stockifab/word-embeddings", "demo": "https://word-embeddings.happierbit.com/"}]...
|
[{"post_id": 34783, "ts": "202 [{"post_id": 34783, "ts": "2026-07-25T19:30:48Z", "hours": 1.7033, "text": "Finish Demo Website (Pages 4-8) I completed the last part of the demo website including the most exciting part about the word arithmetic."}, {"post_id": 33127, "ts": "2026-07-22T19:08:07Z", "hours": 4.3458, "text": "Embedding Demo Website (Pages 1-3) I really like the way the embeddings turned out. That’s why I want to make a website to make word embeddings as accessible and understandable as possible. I’m assuming no prior knowledge from the visitors, and try to interactively guide them through the world of embeddings, with each slide explaining something about embeddings or being interactive to try it yourself. This time i finished slides 1-3, with the last one being the interactive one. Since it should feel engaging and alive, I focus a lot on subtle animations and micro-interactions. I’ve never built a website with heavy animations before so this is the perfect opportunity to try GSAP!"}, {"post_id": 27814, "ts": "2026-07-13T18:14:42Z", "hours": 3.6242, "text": "Maths with English words With the new dataset, training took a lot longer. My computer worked for around 50 hours to run through 26GB of training data. The long wait really payed off though, the model is so much better than the previous model and it is finally capable of doing the embedding arithmetic I’ve been chasing the whole time. Embedding arithmetic is so fun, here are some examples: throw - throwing + running -> run (-ing form) better - good + friendly -> friendlier (comparasion) woman - man + king -> queen (man compared to woman is like king compared to queen) germany - berlin + paris (capitals) The model learned a lot more syntactic and semantic meaning than I had expected. Next I want to build a web app, so that you can play with the embeddings yourself."}, {"post_id": 23582, "ts": "2026-07-06T16:54:41Z", "hours": 7.0792, "text": "New Dataset + Improved Pre-Processing In an effort to increase the model’s performance I switched from the previous model’s Wikipedia Simple English dataset to a subset of the Fine Web Edu dataset. As an additional measure to improve the results I decided to use a larger context of 4 words left and right to the root word. I also completely re-wrote all the preprocessing steps. Even though the dataset is high-quality, language is very nuanced and needs filtering. But since words next to each other (4 words before and after the root word) get grouped, filtering an entire word means the group mustn’t be formed (as information is now missing), on the other hand removing punctuation from the end of a word should still allow that word to appear in a group. Overall I filter/handle: quotes brackets non-English Characters apostrophes other special characters (dashes, underscores, etc.) Another challenge is ensuring that grouped words actually belong together. In the previous dataset I simply grouped the words next to each other in a giant blob of text. This time I only group words from the same text source (the same article, document, …) and only within the sentences of that source. This ensures groups don’t span multiple sentences. This taught me a lot about working with larger amounts of data - I couldn’t load everything in memory as it would be too large, but had to read from disk in batches to process the data. After ~50 min of leaving my computer untouched I had the final dataset with ~26GB (~18GB compressed using word IDs) of filtered word groups. Next, I will have to find a way to determine unrelated words, so that I can start training the third iteration of the model."}, {"post_id": 22251, "ts": "2026-07-04T16:59:44Z", "hours": 3.2306, "text": "New (worse) model In an effort to improve on the previous model, I created a new one. Now it uses separate weights for the context instead of re-using the embedding weights in the context. The new model has 30.000.000 parameters which is double the previous one. Yet unfortunately, the results I got were disappointingly miserable: In contrast to the previous model, it doesn’t even group related words. According to the embeddings, the word “cat” is very similar in meaning to “motor” or “caution” 😂😭 I don’t know why it’s performing so poorly, but I’m curious to find out."}, {"post_id": 22092, "ts": "2026-07-04T10:56:19Z", "hours": 4.3497, "text": "First Embedding Model Using the data obtained previously I could get my first embeddings 🎉 The model (image) has 15.000.000 parameters and took roughly 1/2 hour to train. Unfortunately, the performance is below my expectations: It’s not yet good enough so that “uncle - aunt + mum” would output “dad”. However, the embeddings definitely captured some meaning: For example, the vector of “android” is close to “ios” and to “smartphones”. The vector of “cat” is close to the words “goat”, “monkeys” and “snakes”. I want to improve this model significantly until it’s good enough to meaningfully calculate with the embedding vectors."}, {"post_id": 17825, "ts": "2026-06-28T19:15:17Z", "hours": 3.9069, "text": "Data preprocessing Before the model can train to retrieve the embeddings, it needs data. I found a dataset on Kaggle with the text of 249.396 wikipedia articles. Today I did some preprocessing, first I removed any non-english words and delete special characters, then I determined the 50.000 most frequent words, and limited my vocabulary to these words. To compute the embeddings, I took the left and right words of each word in the data and put them into a pandas data frame along with two other unrelated words: (left word, center word, right word, unrelated word 1, unrelated word 2) The final dataset has 24.780.670 rows, so I likely cant train on the full dataset on my computer. The goal is for the model, when presented with the center word to predict which of the other words are similar to it which it can only do by learning the meaning of each word - which is what we want."}]...
|
Title: Word Embeddings by @stockifab | Stardance
Title: Word Embeddings by @stockifab | Stardance
Devlogs:
Data preprocessing Before the model can train to retrieve the embeddings, it needs data. I found a dataset on Kaggle with the text of 249.396 wikipedia articles. Today I did some preprocessing, first I removed any non-english words and delete special characters, then I determined the 50.000 most frequent words, and limited my vocabulary to these words. To compute the embeddings, I took the left and right words of each word in the data and put them into a pandas data frame along with two other unrelated words: (left word, center word, right word, unrelated word 1, unrelated word 2) The final dataset has 24.780.670 rows, so I likely cant train on the full dataset on my computer. The goal is for the model, when presented with the center word to predict which of the other words are similar to it which it can only do by learning the meaning of each word - which is what we want.
First Embedding Model Using the data obtained previously I could get my first embeddings 🎉 The model (image) has 15.000.000 parameters and took roughly 1/2 hour to train. Unfortunately, the performance is below my expectations: It’s not yet good enough so that “uncle - aunt + mum” would output “dad”. However, the embeddings definitely captured some meaning: For example, the vector of “android” is close to “ios” and to “smartphones”. The vector of “cat” is close to the words “goat”, “monkeys” and “snakes”. I want to improve this model significantly until it’s good enough to meaningfully calculate with the embedding vectors.
New (worse) model In an effort to improve on the previous model, I created a new one. Now it uses separate weights for the context instead of re-using the embedding weights in the context. The new model has 30.000.000 parameters which is double the previous one. Yet unfortunately, the results I got were disappointingly miserable: In contrast to the previous model, it doesn’t even group related words. According to the embeddings, the word “cat” is very similar in meaning to “motor” or “caution” 😂😭 I don’t know why it’s performing so poorly, but I’m curious to find out.
New Dataset + Improved Pre-Processing In an effort to increase the model’s performance I switched from the previous model’s Wikipedia Simple English dataset to a subset of the Fine Web Edu dataset. As an additional measure to improve the results I decided to use a larger context of 4 words left and right to the root word. I also completely re-wrote all the preprocessing steps. Even though the dataset is high-quality, language is very nuanced and needs filtering. But since words next to each other (4 words before and after the root word) get grouped, filtering an entire word means the group mustn’t be formed (as information is now missing), on the other hand removing punctuation from the end of a word should still allow that word to appear in a group. Overall I filter/handle: quotes brackets non-English Characters apostrophes other special characters (dashes, underscores, etc.) Another challenge is ensuring that grouped words actually belong together. In the previous dataset I simply grouped the words next to each other in a giant blob of text. This time I only group words from the same text source (the same article, document, …) and only within the sentences of that source. This ensures groups don’t span multiple sentences. This taught me a lot about working with larger amounts of data - I couldn’t load everything in memory as it would be too large, but had to read from disk in batches to process the data. After ~50 min of leaving my computer untouched I had the final dataset with ~26GB (~18GB compressed using word IDs) of filtered word groups. Next, I will have to find a way to determine unrelated words, so that I can start training the third iteration of the model.
Maths with English words With the new dataset, training took a lot longer. My computer worked for around 50 hours to run through 26GB of training data. The long wait really payed off though, the model is so much better than the previous model and it is finally capable of doing the embedding arithmetic I’ve been chasing the whole time. Embedding arithmetic is so fun, here are some examples: throw - throwing + running -> run (-ing form) better - good + friendly -> friendlier (comparasion) woman - man + king -> queen (man compared to woman is like king compared to queen) germany - berlin + paris (capitals) The model learned a lot more syntactic and semantic meaning than I had expected. Next I want to build a web app, so that you can play with the embeddings yourself.
Embedding Demo Website (Pages 1-3) I really like the way the embeddings turned out. That’s why I want to make a website to make word embeddings as accessible and understandable as possible. I’m assuming no prior knowledge from the visitors, and try to interactively guide them through the world of embeddings, with each slide explaining something about embeddings or being interactive to try it yourself. This time i finished slides 1-3, with the last one being the interactive one. Since it should feel engaging and alive, I focus a lot on subtle animations and micro-interactions. I’ve never built a website with heavy animations before so this is the perfect opportunity to try GSAP!
Finish Demo Website (Pages 4-8) I completed the last part of the demo website including the most exciting part about the word arithmetic.
Ships:
Word embeddings are a way to store the meaning of word (such as “plane” or “dog”) in a large vector (= a long list of numbers) These vectors can then be used to find words similar to each other. But they can also be used to calculate with English words, e.g.: dog - bark + meow –> cat (in fact, you can try this very example on the demo website, or come up with your own calculation) In order to retrieve these embeddings, I created a model that reads through billions of words to understand how they are used. It looks at the words appearing close to each other and assumes all words with the same nearby words must have similar meaning. This retrieval of the embeddings was the hardest part: My first model was okayish and could find related words, but I could not yet calculate with them like in the example before. For the final version I used a much larger dataset, with thought-out pre-processing steps, which was more complicated then I thought (You need to ensure the words you are grouping actually belong together, so you may only group within individual sentences, groups mustn’t overlap anything inside brackets, and you can’t make a group with words you filtered in pre-processing at the same time you shouldn’t skip any words, …) Additionally the challenge with a larger dataset was, that it didnt fit into my memory, so I had to read it in chunks and train the model incrementally. The training of the final model took over 50 hours....
|
1793825313.55911
|
1793911713.55911
|
|
38204
|
Frictionless by @Ahmad_Abbas_Hashmi | Stardance
|
Ahmad_Abbas_Hashmi
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Frictionless by @Ahmad_Abbas_Hashmi | Stard Title: Frictionless by @Ahmad_Abbas_Hashmi | Stardance...
|
1793306912.514836
|
1793911712.514836
|
|
19894
|
P2P Mafia Tracker by @DJ_Laser | Stardance
|
DJ_Laser
|
0
|
2.02
|
0
|
[]
|
[{"post_id": 9910, "ts": "2026 [{"post_id": 9910, "ts": "2026-06-16T12:45:14Z", "hours": 2.0181, "text": "I added a menu to enable/disable roles. My friend came up with a bunch of example roles for me to add to the game for testing purposes. We played a game of Mafia using these roles at school and it worked quite well! I also made a bunch of small UX tweaks when running the website on a mobile device, specially for the host page. Most host page content boxes now render vertically when the screen is small to look better on mobile, and I fixed some overlapping or expanding pieces of content."}]...
|
Title: P2P Mafia Tracker by @DJ_Laser | Stardance
Title: P2P Mafia Tracker by @DJ_Laser | Stardance
Devlogs:
I added a menu to enable/disable roles. My friend came up with a bunch of example roles for me to add to the game for testing purposes. We played a game of Mafia using these roles at school and it worked quite well! I also made a bunch of small UX tweaks when running the website on a mobile device, specially for the host page. Most host page content boxes now render vertically when the screen is small to look better on mobile, and I fixed some overlapping or expanding pieces of content....
|
1793306910.3643932
|
1793911710.3643932
|
|
7152
|
My awesome macropad! by @CJ_B | Stardance
|
CJ_B
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @CJ_B | Stardance
|
1793306909.4725556
|
1793911709.4725556
|
|
24596
|
Space Weather Alert App by @aashvikumar67 | Starda Space Weather Alert App by @aashvikumar67 | Stardance...
|
aashvikumar67
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Space Weather Alert App by @aashvikumar67 | Title: Space Weather Alert App by @aashvikumar67 | Stardance...
|
1793306907.3300738
|
1793911707.3300738
|
|
8965
|
My awesome macropad! by @Iqbal67 | Stardance
|
Iqbal67
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @Iqbal67 | Stardanc Title: My awesome macropad! by @Iqbal67 | Stardance...
|
1793306906.4156349
|
1793911706.4156349
|
|
49577
|
CSGame by @potipek | Stardance
|
potipek
|
1
|
2.79
|
3
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-16T21:54:10Z", "hours": 2.0, "multiplier": 1.09, "payout": 3, "blessing": "neutral", "text": "I made my probably second game in csharp, I am a newbie, hope you like it and have a great day! :)", "repo": "https://github.com/tomk1440-cmyk/CSGame", "demo": "https://github.com/tomk1440-cmyk/CSGame/releases/tag/alpha5"}]...
|
[{"post_id": 51596, "ts": "202 [{"post_id": 51596, "ts": "2026-08-21T11:18:02Z", "hours": 0.4814, "text": "Fixed incorrect input so it no longer crashes you need to have dotnet 10 installed to run the game!"}, {"post_id": 48986, "ts": "2026-08-17T15:59:22Z", "hours": 0.3133, "text": "added new difficulty"}, {"post_id": 48508, "ts": "2026-08-16T21:52:20Z", "hours": 2.4808, "text": "Code looks good, code looks great! + github releases :)"}]...
|
Title: CSGame by @potipek | Stardance
Devlogs:
Co Title: CSGame by @potipek | Stardance
Devlogs:
Code looks good, code looks great! + github releases :)
added new difficulty
Fixed incorrect input so it no longer crashes you need to have dotnet 10 installed to run the game!
Ships:
I made my probably second game in csharp, I am a newbie, hope you like it and have a great day! :)...
|
1793825305.067116
|
1793911705.067116
|
|
27204
|
My very own WebOS by @wumgub | Stardance
|
wumgub
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My very own WebOS by @wumgub | Stardance
|
1793306904.3086743
|
1793911704.3086743
|
|
30470
|
My very own WebOS by @ainavv | Stardance
|
ainavv
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My very own WebOS by @ainavv | Stardance
|
1793306900.6487453
|
1793911700.6487453
|
|
44701
|
StudyBuddy by @Vedant_Daga | Stardance
|
Vedant_Daga
|
2
|
76.0
|
1064
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-12T03:35:26Z", "hours": 23.0, "multiplier": 18.54, "payout": 436, "blessing": "neutral", "text": "StudyBuddy - https://trystudybuddy.vercel.app fyi before u try it: reading runs on a free model with a shared daily cap, and ship day is way more traffic than a normal day. please use the sample worksheets wherever u can (they’re the first thing on the upload page, one click) and upload at most one of ur own pdfs for the next day or two. if the homepage says the free reads are used up, the samples still work. what it does upload a worksheet pdf. it reads every question off the page, tags each one by topic, and works out the answer key. u mark which ones u got wrong and it brings them back on an FSRS schedule (the algo anki uses). across every test u upload it turns “i got 12 wrong” into “ur bad at ratios”. what changed since last time runs on openrouter’s free tier instead of my gpu. not a proof of concept anymore one worksheet is ~4 requests instead of ~42. pages are read in groups the site says when the day’s free reads are running low. clear about the trial: 3 worksheets free, then still free, u just add questions by hand or plug in ur own key. what was hard free models reason before they answer and bill that against the output limit which ends up causing an error, but its really hard to figure out the embedding-only shortcut for sorting looked fine and was wrong a third of the time so fixed it", "repo": "https://github.com/DagaVedant/StudyBuddy", "demo": "https://trystudybuddy.vercel.app/"}, {"ship_num": 2, "ts": "2026-08-19T19:30:17Z", "hours": 53.0, "multiplier": 12.7, "payout": 628, "blessing": "neutral", "text": "StudyBuddy Turn the worksheets you have already done into a record of what you actually know. Try it: https://trystudybuddy.vercel.app Code: https://github.com/DagaVedant/StudyBuddy What I made Upload a worksheet you already finished, as a PDF or photos. A vision model pulls out every question, its options and its answer key. You mark what you got wrong. That is the only input it needs. It sorts questions into 87 topics across SAT and competition maths. Then it ranks your weak areas and schedules revision using FSRS, the algorithm behind Anki. It also writes practice questions on your weak topics and exports misses to Blooket. Built on my own past papers: 387 real questions from 22 worksheets. What was challenging The models can run in four places: my GPU, your API key, your own Ollama, or not at all. A student with a GPU should never send homework to my server. A student with nothing should still get something. Topic tagging needs an embedding model that serverless hosting cannot run. So the shortlist is a pgvector query on the server and the vector is computed anywhere, including in your browser under WebAssembly. Worst bug was three characters: I stored the global fetch on a class field, which passes the object as the receiver. Node allows it, browsers throw Illegal invocation. Every test passed and the only runtime that mattered was broken. What I am proud of It does not lie to you. Weak topics are ranked by a Wilson lower bound, not a raw percentage, so two unlucky answers cannot fake a weakness. Model-written questions are kept out of your accuracy, so the ranking cannot feed the questions it generates. Every model response is schema-checked before it reaches the database. Generated practice is sifted against thirteen specific failure modes. When my GPU is off, the upload screen says so instead of spinning. 1,459 unit tests, 84 end to end, 293 commits. How to test it Sign in with Google, or an email and password. Upload any worksheet you have already done. A past paper works well. Check what it read. Each question sits beside the page image it came from. Mark what you missed, then open the dashboard. The free trial reads three worksheets on my own GPU. If it is off, your upload queues and the app tells you. To skip the wait, settings takes your own API key or connects to Ollama on your machine. guys i wish this was markdown compatible but its not so sorry", "repo": "https://github.com/DagaVedant/StudyBuddy", "demo": "https://trystudybuddy.vercel.app/"}]...
|
[{"post_id": 66334, "ts": "202 [{"post_id": 66334, "ts": "2026-09-12T03:21:31Z", "hours": 3.7986, "text": "Devlog 24: StudyBuddy so a lot of the feedback said “cool but it needs ur gpu on”. that made it seem like a PoC, so now its running on the free tier of openrouter. making the free tier work one request per question was never going to fit a daily cap. extraction now sends up to 10 pages / 25 questions per call, sorting and answer key go 10 questions at a time. ~4 requests per worksheet instead of ~42 the homepage and upload page count the day’s calls. 80% says busy, 100% stops reading and points u at the samples. samples upload page leads with the three samples as one-click cards; ur own pdf is the second option and says how much of the shared allowance is used. removed phone photo uploads (highly innaccurate on the free tier of models i have)"}, {"post_id": 61499, "ts": "2026-09-04T13:23:50Z", "hours": 0.4864, "text": "Devlog 23 - StudyBuddy i just had some minutes left on this so im just making the devlog still waiting for my ship to be approved (been waiting a few days) no big changes at all (waiting for feedback)"}, {"post_id": 57722, "ts": "2026-08-29T23:49:06Z", "hours": 0.3544, "text": "Devlog 22 - StudyBuddy fixed more bugs and rewrote code by hand"}, {"post_id": 56688, "ts": "2026-08-28T15:28:49Z", "hours": 3.3164, "text": "Devlog 21 - StudyBuddy patched even more bugs rewrote tons of my code (ai to human) cleaned up old files (a lot of old features were removed and reupdated) just more QoL fixes"}, {"post_id": 55293, "ts": "2026-08-27T01:04:56Z", "hours": 0.7281, "text": "Devlog 20 - StudyBuddy more bug fixes continous reships (they keep saying its too AI generated even after i rebuilt the UI) started working on the API key integration (like almost there rn) tons of dead code removal and code clean up added support for firefox too (now it works on edge, firefox, chrome, and prolly a ton others i just havent really tested it)"}, {"post_id": 55212, "ts": "2026-08-26T19:29:14Z", "hours": 2.0147, "text": "Devlog 19 - StudyBuddy even more bug fixes so i pushed a change, and that somehow broke the entire pipeline so i patched it no real content just fixes going to add API key integration soon (follow to see it happen)"}, {"post_id": 54267, "ts": "2026-08-25T04:59:03Z", "hours": 1.3939, "text": "Devlog 18 - StudyBuddy lowk not a lot of content in this one but like 1000000 different bugs popped up and reviewers are pointing it out so thank you smmm ( @blowupthenoobs ur the goat) fixed the trials having no limit other fixes just check my commits"}, {"post_id": 53477, "ts": "2026-08-24T01:28:48Z", "hours": 6.445, "text": "Devlog 17 - StudyBuddy (ah im losing track of these devlogs uh my ship keeps getting rejected for look to AI, and ive literally rebuilt everything, removed all teh ai generated thing. (im gonna ship again rn) made a logo cuz i thought it would look cool added a Terms of Services page cuz its risky cuz people could upload worksheets they dont have access for an i could be fried so i made them agree to that cleaned up more code fixed a few more bugs"}, {"post_id": 51966, "ts": "2026-08-21T23:14:31Z", "hours": 0.5383, "text": "Devlog 16 - StudyBuddy added some sample worksheets so you can try it out added the borders back to the buttons because i accidently removed them before"}, {"post_id": 51893, "ts": "2026-08-21T19:51:51Z", "hours": 0.3522, "text": "Devlog 15 more cleaninggggggg cleaned up repo, removed more dead logic and stuff instead of a css wallpaper, i added a image of lined paper to really give that school/learning feel asked ai to help me get the ui to look kinda fresh and add the pencil style heading"}, {"post_id": 51715, "ts": "2026-08-21T15:23:46Z", "hours": 3.1414, "text": "Devlog 14 shipwrights rejected the project so im fixing their things decided to clean up the code, get rid of old functions, and i also cleaned up the UI because no one really needs the heading and then what it means, like i think you know that topics means topics and doesnt need a whole sentence after that. cleaned up the repo, got rid of ai generated code fixed a 500 error when uploading worksheets, cuz something happened and some linux kernel wasnt compaitble with the library i was using wrapped up my last few fixes lowk not a lot of new features, rather like fixes"}, {"post_id": 51288, "ts": "2026-08-20T20:55:12Z", "hours": 0.9239, "text": "Devlog 13 - StudyBuddy update the ui to make it look liek sticky notes and lined paper"}, {"post_id": 50557, "ts": "2026-08-19T19:22:57Z", "hours": 1.2472, "text": "ANYONE RATING THIS PROJECT - THE VIDEO ON THE SHIP IS OUTDATED, THERE IS ALSO ANOTHER FEW DEVLOGS SO CHECK THAT OUT BEFORE JUDGING BECAUSE IT GIVES MORE INFO ABOUT THE BUILDING AND WHY THE CHANGED A LOT SORRYYYY ALSO USE THE SAMPLE WORKSHEETS I ATTACHED OR EASILY PARSEABLE WORKSHEETS. TEMPORAILY IVE CLOSED THE API KEY VERSION AS MOST PEOPLE DONT HAVE THEM. COMPLEX WORKSHEETS ARE TO BE USED ONLY WITH LARGE LLM Devlog 12 - StudyBuddy got everything ready to ship turns out that ollama needed some permissions so fixed that and added it to readme for people to set up, and other stuff like that shipping it in 5 mins 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉"}, {"post_id": 49640, "ts": "2026-08-18T15:06:19Z", "hours": 3.8678, "text": "Devlog 11 - StudyBuddy this is a short one got the google sign in to work added email verification and forgot ur password thing cleaned up the overall UI made the topic tree standardized cleaned up some of the extraction issues added ollama integration for everyone added practice question generation, topic overview, etc tested everything fully the attached image is the app after a ton of testing *"}, {"post_id": 48576, "ts": "2026-08-17T00:58:42Z", "hours": 5.8406, "text": "Devlog 10 - StudyBuddy mostly the same bug wearing different clothes: a screen that exists, that u can get to, that quietly does less than it says tier C was sitting in settings doing nothing save an ollama address and the app resolves u to a browser executor. that executor had nowhere to go, so ur worksheet just sat there looking queued it claims the job now and reads each page against localhost:11434 , posting back through the same queue my gpu posts through has to run in the browser cuz a server cant reach ur localhost, so the tab stays open. checkpointed per page tho, closing it resumes instead of restarting the paper a mark u mis-tapped was permanent tap through 40 of these and ur going to hit the wrong one eventually that one tap feeds the FSRS schedule, the topic accuracy, the weakness ranking and the blooket export only way back was deleting the worksheet and uploading it again, which costs u a trial credit. so the fix for a mistap was paying for it two defences that were never on WORKER_ALLOWED_IPS was optional and empty meant no restriction empty is the state every deployment starts in, so the normal outcome was a defence thats off that nobody ever decided to turn off refused now. * still allows any address but somebody has to type it untagged worksheets looked identical to broken ones tier B cant auto-classify, the embedding model needs a native runtime the serverless host doesnt have so ur questions saved fine and were reviewable fine, they just had no topic and nothing said why. reads exactly like it silently failed every tier that can come back untagged says so now nothing told u when a worksheet finished u uploaded and then u guessed. sat on the status page or came back later and hoped in-app bell that needs zero setup, plus web push for a tab u closed also “Review these now” now reviews those questions. the word had drifted onto three screens meaning three different things dashboard was missing three of its panels, and the trend arrow was specified ages ago and never computed taxonomy had no front door and the subject panel only went one level deep. Math > Geometry > Triangles walks now pagination was capping at the fiftieth worksheet and saying nothing about it the AI setup prompt showed up after ur trial ran out, which is the one moment it cant help u grouped scripts/ by what it does to ur data. inspect/ reads, repair/ writes behind a guard, benchmark/ measures 1285 tests green. playwright hasnt run yet and app/ moved a lot this time, so thats next"}, {"post_id": 47159, "ts": "2026-08-14T20:52:31Z", "hours": 5.0856, "text": "Devlog 9 - StudyBuddy the merge tool could double up a question number renumbering the survivor of a duplicate pair used Math.min of just those two rows, blind to the rest of the paper merging a phantom #5 into a real #9 could hand the paper a second #5, the exact thing the tool exists to prevent zero tests on a function that deletes rows. five now, including the repro $15/hour was losing its sign, not just $5 the math-stripper runs from one $ to the next, so “earns $15/hour and $18/hour” reads the slash as a fraction and eats both signs. same with $40 = $25 + $15 on the = i wrote this down once as “one weird case.” it’s the whole unit-rate and equation category fix checks the char after the closing $ : a digit means it’s opening the next price, not real math figure crops didnt need a new pipeline, just reusing one filed as “never produced,” which reads like crop, store, backfill the verify screen already computes a crop window from the bbox over the stored page image. review got wired to the same math, every old worksheet gets it free the real work was the guards: zero-area, inverted, off-page, or no recorded page size all have to degrade to nothing rather than to the wrong crop a fence i built to be un-escapable, wasnt the comment says a new tag can’t be added without going through the escaping. page-seam work added two by typing them directly a page whose OCR contains the literal closing tag closes the fence early, and everything after reads as instructions instead of data tag list exists once now, every fence built from it every worksheets.status write was a bare UPDATE no guard on the current value, so a stale job retry could drag an already-reviewed worksheet back to failed one transitionWorksheet(from, to) now, every write through it preview deploys were migrating the prod database guard only checked VERCEL_ENV === 'production' , but previews fire on every push against one shared DATABASE_URL two finishing together were racing through the migration folder 9 tests could go quiet and nobody would know one e2e file, 12 tests serial in a single tab, everything past “verify” depending on a question a drag gesture created three tests earlier a drag regression silently skipped 9 unrelated tests instead of failing them api fixture, split the file, broke the drag on purpose to prove it. held the question list rendered all 114 cards for a screen that edits one at a time deferred a while back: virtualizing editable rows risks one unmounting mid-edit only one card can ever be expanded, so the risk surface is exactly one row virtualizes past 40 now, open row pinned into the rendered range wherever scrolling goes. typed into one at 60 questions, scrolled thousands of px away, still there, still focused, still holding the edit also profile save had devlog 4’s router.refresh() remount bug login rate limit skipped Auth.js’s own credentials endpoint ollama worker had no startup timeout and just hung worksheet text leaked into console logs on schema rejections review screen shipped every page’s OCR text on page-1 load admin console got merge, tree edit, queue, usage doc-count drift (third time), and a false-positive LaTeX check flagging real set notation as broken math"}, {"post_id": 46100, "ts": "2026-08-13T02:23:56Z", "hours": 3.2192, "text": "Devlog 8 - StudyBuddy im too lazy to have a full write up for this (watched spiderman tdy IT WAS REALLY GOOD) for each topic that a user gets wrong, a seperate model (gpt-oss:20b, sorry if i miswrote the model) gives a walkthrough of the topic also added missed questions to the csv export added a AI answer key system if the worksheet doesnt have one."}, {"post_id": 45521, "ts": "2026-08-12T02:04:02Z", "hours": 3.0014, "text": "Devlog 7 - StudyBuddy the drag box was broken in the real app. for months u upload a worksheet, u draw a box around question 1, it fills in. thats the whole manual editor, thats the whole free tier. and it didnt work. click through the app to get there and nothing responds. reload and its fine. four previous commits went looking for this. the test had a 24 line comment explaining why it was probably a test problem. it was not. elementFromPoint(100, 28) -> HTML elementsFromPoint(100, 28) -> [HTML] thats the browser saying nothing is at this pixel , for every pixel on the page. the cause was 8 view transition animations, 6 stuck running forever . one that never finishes sits in the top layer and covers everything. and its a pseudo element so it shows up in no ancestor walk and no element stack, which is why every previous investigation contradicted itself. bisected on clean builds: next flag react component result on on broken off on broken on off clean off off clean so its react’s <ViewTransition> , not next. three lines of css. the drag test used to fake the mouse with dispatched events, now it uses a real one, which is the only thing that proves anything. gemini has never completed a single request 4 providers in settings. one says “has a free tier worth starting on”. zero successful calls, ever. every nullable field is anyOf: [{type:'x'}, {type:'null'}] gemini doesnt understand anyOf , so a filter strips keywords it rejects the filter dropped anyOf and left {} behind, while leaving the field in required a required field with no type = rejected request. every time funny part: the allowlist already had nullable in it, gemini’s own word for the same idea. someone knew. nothing connected them. the landing page was lying about 3 of its 4 topics theres a comment above them saying “kept honest on purpose: these are real taxonomy names” . Ratio & proportion - not real Linear equations - not real Reading inference - not real Vocabulary in context - real so the one claim the page made about its own honesty was the false one lol. theres a test now instead of a comment. tests found 2 bugs i wasnt looking for new Date(\"sometime in 2010\") returns jan 1 2010, cuz v8 scrapes a year out of almost anything. and it parses as local midnight while everything next to it is UTC. on a 13th birthday thats the whole question one route answered 404 to someone with no session. the client sends u to sign in on a 401 and brings u back after, so a tab that sat open till the session expired just ate what u typed the rest a reload could cost u a 114 question paper. markup saves nothing till every question is marked, so its a local draft now / , /signin , /signup are static html now. the topbar called auth() from the root layout, which made all 39 routes render per request the 23mb embedding model was getting fetched inside a background task on every cold start, and failing silently one commit recorded 32 renames and none of the code . the git add failed and i’d redirected the error away so i never saw it"}, {"post_id": 44852, "ts": "2026-08-10T21:45:18Z", "hours": 1.3739, "text": "Devlog 6 - StudyBuddy u can throw everything u got wrong into blooket now button on the dashboard for the whole account, and one per worksheet if u only want that paper it gives u a file, u upload it to blooket, u get a set of exactly the questions u missed wrong means ever wrong, not currently wrong. if u got it wrong on paper and then right in review, its still in there. thats the one u actually want to drill and it wouldve been weird to leave out blooket hands u an .xlsx template so everyone calls this an xlsx export, but its uploader only accepts csv. took a while to work out also its importer just silently imports nothing if the file is slightly off. no error, no warning, zero questions. three separate ways to trip that picking a subject barely did anything theres a dropdown on upload for what subject the worksheet is. it offers things like “Algebra 1” only the first bit of that was ever used, so picking Algebra 1 searched all of high school maths. exactly the same as picking “all of high school maths” the one control u have over how ur questions get sorted, doing basically nothing long papers were quietly losing questions to a limit the topic tagger takes questions 100 at a time. fine except it grabbed 100 in no particular order and then removed the ones already done, so on a 114 question paper 14 never got looked at, and which 14 was down to whatever the database felt like that day worse on a second pass: if 100 were already tagged it handed back an empty list, which reads as “nothing left to do”, and the rest never got tagged at all two screens counting the same paper differently the worksheets page filters out page junk like “CONTINUE TO THE NEXT PAGE” before counting. the dashboard didnt so the same worksheet was 25 questions on one screen and 26 on the other, and nothing tells u which one is lying the chart was lying about time the accuracy chart draws a bar per week. it was only making bars for weeks u actually did something in so 12 bars looked like 12 weeks in a row but werent. practise in march and again in june and u see two bars side by side like it was steady every week is a bar now, empty ones included, and it says which weeks its showing scrolling changed my settings without me touching anything the page range and question count boxes were number inputs, and number inputs treat the scroll wheel as a way to change the value so scrolling down the upload page with ur cursor over one of them silently rewrote which pages get read found a pile of other accessibility stuff while i was in there: buttons a bit too small to reliably hit on a phone, cards that vanish in high contrast mode, and a “skip to content” link that didnt actually skip anything also asking to see an explanation u already had was using up ur hourly limit for generating new ones the topic picker was built in a way that made screen readers think the list had nothing in it button labels were half Title Case and half sentence case, sometimes on the same screen"}, {"post_id": 44789, "ts": "2026-08-10T20:01:20Z", "hours": 1.8522, "text": "Devlog 5 - StudyBuddy “accept the remaining 114” checked none of them that button fires one save per question, and on my test paper thats 114 of them at once nothing read the answers back, so a save that failed looked exactly like one that worked the tick stayed on, u moved to the next screen, and it was never stored deleting a question said “Saved” and then didnt delete it delete waits a few seconds so u can undo it. it dropped the question from the list first and threw away whatever came back from the server so if it failed u got told it saved, and the question showed up in ur study queue later like nothing happened also there was no undo button anywhere. it was just a slow delete $5 was being eaten maths sometimes comes wrapped in dollar signs so i strip them off. money also comes wrapped in dollar signs “Sam has $5 and Ana has $12” was being read as “Sam has 5 and Ana has 12” checked a real saved question and yep. paper says $5, database said 5 if my worker died, ur worksheet said “queued” forever the machine that reads the pages runs at my house. if it fell over mid job, nothing anywhere ever marked that job as failed it just sat there, and the free credit it charged u never came back the topic tagging could fail without failing it needs a bit of software thats not always there on the server. when it wasnt, it came back with “no matches” which is a completely normal answer. so the job finished, every question was untagged, ur weak areas page was empty, and nothing anywhere was an error one i was told to do and didnt had a note to cap the page number by how many pages the worksheet has except if u upload pages 10 to 15 of a pdf thats six pages numbered 10 to 15, so that check refuses every single one of them capped the two things separately instead also the screen asking u to check questions against the page never showed the page finishing a review session stopped saying u finished it the AI could print its own error onto ur status page, which sometimes meant quoting ur own worksheet back at u the upload checked the image size by asking the browser instead of opening the image"}, {"post_id": 44684, "ts": "2026-08-10T16:42:14Z", "hours": 2.2806, "text": "Devlog 4 - StudyBuddy no new features today. just went hunting for stuff that was quietly broken, and there was way more of it than i expected the sign-in page could send u to a different website if someone handed u a link like /signin?next=someothersite.com , u would log in and then land on their page immediately after typing ur password, which is about the worst possible moment for that to happen this one went first there was no limit on login attempts i had limits on signing up and on uploading. somehow not on the actual password box so u could sit there and guess forever getting blocked now looks identical to just getting the password wrong. telling someone “too many attempts” quietly confirms the account exists file storage was writing into the void if one setting went missing it silently saved ur page images somewhere that doesnt survive on the server uploads said they worked. returned a success. images just gone nothing errored anywhere, which is why it sat there so long now it refuses to start up at all instead of pretending everything is fine i almost broke my whole test suite fixing something unrelated locked down two internal-only routes with what seemed like the obvious check except my tests run against a production build, so that check wouldve locked the tests out too caught it before it shipped, then wrote a test explaining it so future me doesnt helpfully undo it added security headers and instantly caught myself put them in report-only mode first so nothing could actually break about 40 seconds later it flagged a script that my own analytics loads the strict version wouldve blocked it in prod. i absolutely wouldve shipped that one fix i deleted instead of shipping had a note to add another check to the duplicate-question detector actually tested it against real papers first, and it turns out it can never trigger. the answers on a maths paper are just “4” and “9” and stuff, way too short for it to match on wouldve quietly made things worse all tests green at the end of it. onto the next pile"}, {"post_id": 44340, "ts": "2026-08-10T01:14:54Z", "hours": 6.0992, "text": "Devlog 3 - StudyBuddy wrote a script that reads each papers own answer key out of the source pdf and diffs it against my database. so the paper grades me instead of me grading myself. those 14 sheets scored 1 of 14 the first time i pointed it at them. tonight theyre 14 of 14 . barely any of it was the model. one paper stored 8 of its 15 questions. the model had read all 15 the log said dropped 6 unreadable question(s) . a count. no reason. it said that for two days made it print which field rejected the question and it told me on the first run: choices.0.label: Too big: expected string to have <=8 characters answer labels are capped at 8 chars, but the cap runs before the function that shortens them. that function only exists cuz the model returns A. 60 instead of A so the cap was checked against exactly the thing the transform was written to fix. coordinate geometry paper, every option reads A. (-2, 3) , ten chars, binned a count with no reason cant tell u “model returned garbage” from “ur schema is stricter than the paper” and those have opposite fixes also 44 duplicate-answer flags, every one wrong: -2 and 2 both normalised to 2 lol. on a maths paper the sign IS the question."}, {"post_id": 43025, "ts": "2026-08-08T02:19:09Z", "hours": 0.3111, "text": "if any of you guys wanna try this out here is the link: https://trystudybuddy.vercel.app/ YOOOOO WE GOT OUR FIRST FEW USERS i just checked before sleeping and yo we have 14 worksheets in the processing queue right now i wonder how much we had before THANK YOU GUYS"}, {"post_id": 42970, "ts": "2026-08-07T23:33:19Z", "hours": 5.2603, "text": "Devlog 2 - StudyBuddy HERE IS THE LINK TO TRY IT ( https://trystudybuddy.vercel.app/ ) left a pile of worksheets extracting overnight cuz i was sick of testing every fix against the same two papers. woke up to 9 worksheets, 713 questions, 353 pages everything below only shipped after i swept it over all of that first. rule i have now, after two earlier “fixes” that read perfectly and were wrong on real data a question that shipped reading ?rac{44}{11} i tell the model to write plain text. it writes LaTeX anyway sometimes that fails loudly. \\sqrt isnt a valid JSON escape so the response explodes and i lose a page. thats fine?? at least i know the other half is the problem. \\f is a form feed and \\t is a tab, both totally valid , so \\frac{44}{11} parses perfectly and quietly becomes a form feed followed by rac{44}{11} i had an AMC8 question in my database reading ?rac{44}{11} and nothing anywhere reported a problem fix has to run before the first parse , not in the catch block, cuz the version that actually hurts u never throws it doubles the backslash on letter runs JSON would misread, but only the six that collide (b f n r t u) and only when the run spells a real command. otherwise a real line break stops being a line break, which is a fun way to make things worse questions torn in half by the page break extraction reads one page at a time and never sees the page before or after. so a question ending at the bottom of page 3 with its answer choices at the top of page 4 is never whole in either request . five of them on the AMC8 paper one fix folds the halves back together. the other is for the worse case where the extractor returned nothing at all for the second half, cuz a bare block of answer choices isnt a question so the model just drops it. theyre still sitting in the next pages text layer tho, u just have to go get them sorting questions within a page needed its own module cuz the bounding boxes lie . question 4 came back with a top of 1428 and question 5 with 1379, so pure geometry puts them backwards AMC8 went from 19 of 25 questions having their answer choices to 24 of 25 , zero false positives across 348 SHSAT pages stuff that broke a worksheet told me it had 26 questions when the paper has 25 . the extra one was the axis labels off a diagram, and the SHSAT ones had rows that just said CONTINUE TO THE NEXT PAGE. dropped 23 rows, all page furniture then immediately shipped a followup bug where the card read “Questions 25” next to “Unchecked 26” cuz i filtered one count and forgot the other one lol tried just asking the model to return a carried answer block as half a question. produced zero of them and started relabelling stem-only questions as free response, which hides the damage from every check i have. reverted the landing page every animation was gated behind prefers-reduced-motion , which sounds responsible until u find out some managed windows installs ship with animation effects off by default . so the page whose whole job is showing the product working was showing a static screenshot the hero panel gets dealt onto the page like a card now. needs a perspective on the parent or the rotations collapse into a shear and it just looks like a slide the forgetting curve draws itself left to right. stroke-dashoffset does not work here , pathLength is silently ignored under vector-effect: non-scaling-stroke so the dash tiles across the path instead of spanning it once. and i need non-scaling-stroke or the line renders 9x too thick . used a page-coloured shutter instead next things: that one AMC8 question needs reading off the page image since the text layer doesnt have it. and theres a cheaper reduced-motion compromise i wrote down but havent built."}, {"post_id": 42187, "ts": "2026-08-06T20:02:11Z", "hours": 13.8281, "text": "Devlog 1 - StudyBuddy so ive been doing SHSAT practice tests for a while and the thing that always got me is that after i mark one, i have like 20 wrong answers and no idea what to actually do with that info . like ok i got 12 questions wrong, but am i bad at geometry or did i just misread three questions? no clue. so id end up redoing entire sections i was already fine at. basically what im building is a web app where u upload a worksheet or a practice test (pdf or even just a photo of the page) and it reads every question off it, figures out what topic each one is, and then after u mark which ones u got wrong it schedules them to come back later using FSRS (same spaced repetition algo anki uses). the thing that makes it diff from just writing ur mistakes in a notebook is that it tracks topics across every test u ever upload . one test says nothing. five tests and it can actually tell u “ur bad at ratios” with a straight face. the AI runs on my own laptop i did not want to pay for an api. so the vision model that reads the pages runs on my own rtx 5080 . it sits at home and asks the deployed site for jobs, and it only ever dials outward so theres no port open on my home network. if my laptops off, uploads just queue instead of dying. the part i was most wrong about i picked the model i was using (qwen2.5vl:7b) literally because it was the first one i pulled . thats the whole reason. so i finally benchmarked it properly, 9 models on a real 58 page shsat paper, 114 questions . the one i already had won?? the 27b model is 4x bigger, scored 6 points WORSE , and took 183 seconds per page vs 7.8 . id been assuming for weeks that upgrading would fix my accuracy problems lol. also the grading was free which i was way too happy about. every question number 1-114 shows up exactly once on the paper so the test just grades itself , i never labelled a single page by hand. the bug that was actually my fault so when i looked at WHICH questions got missed they werent random, they came in chunks . one model dropped 17 questions in a row . turns out every single miss on every model was a page that came back completely empty . not a wrong answer. nothing. and that was my bug not the models . an empty reply gives 0 questions and no error, so my checker (which only looked for gaps in question numbering) saw nothing wrong and the upload said success while a whole page just quietly disappeared . fixed with one retry at a slightly higher temperature cuz a model that decided to output nothing will decide that again if u ask it the exact same way. stuff that broke i wrote a check to catch questions that got cut off mid sentence (flag anything not ending in punctuation) and it flagged 25 out of 114 questions on a CLEAN run . all wrong. turns out shsat questions end with like “by” or “through” all the time and the answer choices finish the sentence. fixed it and it changed literally zero outcomes so the rule was doing nothing the whole time. also added rate limiting and instantly locked myself out of my own test suite , which signs up way more than 5 times an hour from localhost. also deleted my entire email system . u need a domain u own to send emails (spf/dkim records) and a free .vercel.app subdomain cant do that. so instead of buying a domain i deleted 274 lines and made google sign in the front door. next things: tier B uploads dont get topic tags yet, and theres one test failing on purpose cuz FSRS says a question u just got wrong is due in 1 minute but i think it should be due immediately. gotta pick one."}]...
|
Title: StudyBuddy by @Vedant_Daga | Stardance
Dev Title: StudyBuddy by @Vedant_Daga | Stardance
Devlogs:
Devlog 1 - StudyBuddy so ive been doing SHSAT practice tests for a while and the thing that always got me is that after i mark one, i have like 20 wrong answers and no idea what to actually do with that info . like ok i got 12 questions wrong, but am i bad at geometry or did i just misread three questions? no clue. so id end up redoing entire sections i was already fine at. basically what im building is a web app where u upload a worksheet or a practice test (pdf or even just a photo of the page) and it reads every question off it, figures out what topic each one is, and then after u mark which ones u got wrong it schedules them to come back later using FSRS (same spaced repetition algo anki uses). the thing that makes it diff from just writing ur mistakes in a notebook is that it tracks topics across every test u ever upload . one test says nothing. five tests and it can actually tell u “ur bad at ratios” with a straight face. the AI runs on my own laptop i did not want to pay for an api. so the vision model that reads the pages runs on my own rtx 5080 . it sits at home and asks the deployed site for jobs, and it only ever dials outward so theres no port open on my home network. if my laptops off, uploads just queue instead of dying. the part i was most wrong about i picked the model i was using (qwen2.5vl:7b) literally because it was the first one i pulled . thats the whole reason. so i finally benchmarked it properly, 9 models on a real 58 page shsat paper, 114 questions . the one i already had won?? the 27b model is 4x bigger, scored 6 points WORSE , and took 183 seconds per page vs 7.8 . id been assuming for weeks that upgrading would fix my accuracy problems lol. also the grading was free which i was way too happy about. every question number 1-114 shows up exactly once on the paper so the test just grades itself , i never labelled a single page by hand. the bug that was actually my fault so when i looked at WHICH questions got missed they werent random, they came in chunks . one model dropped 17 questions in a row . turns out every single miss on every model was a page that came back completely empty . not a wrong answer. nothing. and that was my bug not the models . an empty reply gives 0 questions and no error, so my checker (which only looked for gaps in question numbering) saw nothing wrong and the upload said success while a whole page just quietly disappeared . fixed with one retry at a slightly higher temperature cuz a model that decided to output nothing will decide that again if u ask it the exact same way. stuff that broke i wrote a check to catch questions that got cut off mid sentence (flag anything not ending in punctuation) and it flagged 25 out of 114 questions on a CLEAN run . all wrong. turns out shsat questions end with like “by” or “through” all the time and the answer choices finish the sentence. fixed it and it changed literally zero outcomes so the rule was doing nothing the whole time. also added rate limiting and instantly locked myself out of my own test suite , which signs up way more than 5 times an hour from localhost. also deleted my entire email system . u need a domain u own to send emails (spf/dkim records) and a free .vercel.app subdomain cant do that. so instead of buying a domain i deleted 274 lines and made google sign in the front door. next things: tier B uploads dont get topic tags yet, and theres one test failing on purpose cuz FSRS says a question u just got wrong is due in 1 minute but i think it should be due immediately. gotta pick one.
Devlog 2 - StudyBuddy HERE IS THE LINK TO TRY IT ( https://trystudybuddy.vercel.app/ ) left a pile of worksheets extracting overnight cuz i was sick of testing every fix against the same two papers. woke up to 9 worksheets, 713 questions, 353 pages everything below only shipped after i swept it over all of that first. rule i have now, after two earlier “fixes” that read perfectly and were wrong on real data a question that shipped reading ?rac{44}{11} i tell the model to write plain text. it writes LaTeX anyway sometimes that fails loudly. \sqrt isnt a valid JSON escape so the response explodes and i lose a page. thats fine?? at least i know the other half is the problem. \f is a form feed and \t is a tab, both totally valid , so \frac{44}{11} parses perfectly and quietly becomes a form feed followed by rac{44}{11} i had an AMC8 question in my database reading ?rac{44}{11} and nothing anywhere reported a problem fix has to run before the first parse , not in the catch block, cuz the version that actually hurts u never throws it doubles the backslash on letter runs JSON would misread, but only the six that collide (b f n r t u) and only when the run spells a real command. otherwise a real line break stops being a line break, which is a fun way to make things worse questions torn in half by the page break extraction reads one page at a time and never sees the page before or after. so a question ending at the bottom of page 3 with its answer choices at the top of page 4 is never whole in either request . five of them on the AMC8 paper one fix folds the halves back together. the other is for the worse case where the extractor returned nothing at all for the second half, cuz a bare block of answer choices isnt a question so the model just drops it. theyre still sitting in the next pages text layer tho, u just have to go get them sorting questions within a page needed its own module cuz the bounding boxes lie . question 4 came back with a top of 1428 and question 5 with 1379, so pure geometry puts them backwards AMC8 went from 19 of 25 questions having their answer choices to 24 of 25 , zero false positives across 348 SHSAT pages stuff that broke a worksheet told me it had 26 questions when the paper has 25 . the extra one was the axis labels off a diagram, and the SHSAT ones had rows that just said CONTINUE TO THE NEXT PAGE. dropped 23 rows, all page furniture then immediately shipped a followup bug where the card read “Questions 25” next to “Unchecked 26” cuz i filtered one count and forgot the other one lol tried just asking the model to return a carried answer block as half a question. produced zero of them and started relabelling stem-only questions as free response, which hides the damage from every check i have. reverted the landing page every animation was gated behind prefers-reduced-motion , which sounds responsible until u find out some managed windows installs ship with animation effects off by default . so the page whose whole job is showing the product working was showing a static screenshot the hero panel gets dealt onto the page like a card now. needs a perspective on the parent or the rotations collapse into a shear and it just looks like a slide the forgetting curve draws itself left to right. stroke-dashoffset does not work here , pathLength is silently ignored under vector-effect: non-scaling-stroke so the dash tiles across the path instead of spanning it once. and i need non-scaling-stroke or the line renders 9x too thick . used a page-coloured shutter instead next things: that one AMC8 question needs reading off the page image since the text layer doesnt have it. and theres a cheaper reduced-motion compromise i wrote down but havent built.
if any of you guys wanna try this out here is the link: https://trystudybuddy.vercel.app/ YOOOOO WE GOT OUR FIRST FEW USERS i just checked before sleeping and yo we have 14 worksheets in the processing queue right now i wonder how much we had before THANK YOU GUYS
Devlog 3 - StudyBuddy wrote a script that reads each papers own answer key out of the source pdf and diffs it against my database. so the paper grades me instead of me grading myself. those 14 sheets scored 1 of 14 the first time i pointed it at them. tonight theyre 14 of 14 . barely any of it was the model. one paper stored 8 of its 15 questions. the model had read all 15 the log said dropped 6 unreadable question(s) . a count. no reason. it said that for two days made it print which field rejected the question and it told me on the first run: choices.0.label: Too big: expected string to have <=8 characters answer labels are capped at 8 chars, but the cap runs before the function that shortens them. that function only exists cuz the model returns A. 60 instead of A so the cap was checked against exactly the thing the transform was written to fix. coordinate geometry paper, every option reads A. (-2, 3) , ten chars, binned a count with no reason cant tell u “model returned garbage” from “ur schema is stricter than the paper” and those have opposite fixes also 44 duplicate-answer flags, every one wrong: -2 and 2 both normalised to 2 lol. on a maths paper the sign IS the question.
Devlog 4 - StudyBuddy no new features today. just went hunting for stuff that was quietly broken, and there was way more of it than i expected the sign-in page could send u to a different website if someone handed u a link like /signin?next=someothersite.com , u would log in and then land on their page immediately after typing ur password, which is about the worst possible moment for that to happen this one went first there was no limit on login attempts i had limits on signing up and on uploading. somehow not on the actual password box so u could sit there and guess forever getting blocked now looks identical to just getting the password wrong. telling someone “too many attempts” quietly confirms the account exists file storage was writing into the void if one setting went missing it silently saved ur page images somewhere that doesnt survive on the server uploads said they worked. returned a success. images just gone nothing errored anywhere, which is why it sat there so long now it refuses to start up at all instead of pretending everything is fine i almost broke my whole test suite fixing something unrelated locked down two internal-only routes with what seemed like the obvious check except my tests run against a production build, so that check wouldve locked the tests out too caught it before it shipped, then wrote a test explaining it so future me doesnt helpfully undo it added security headers and instantly caught myself put them in report-only mode first so nothing could actually break about 40 seconds later it flagged a script that my own analytics loads the strict version wouldve blocked it in prod. i absolutely wouldve shipped that one fix i deleted instead of shipping had a note to add another check to the duplicate-question detector actually tested it against real papers first, and it turns out it can never trigger. the answers on a maths paper are just “4” and “9” and stuff, way too short for it to match on wouldve quietly made things worse all tests green at the end of it. onto the next pile
Devlog 5 - StudyBuddy “accept the remaining 114” checked none of them that button fires one save per question, and on my test paper thats 114 of them at once nothing read the answers back, so a save that failed looked exactly like one that worked the tick stayed on, u moved to the next screen, and it was never stored deleting a question said “Saved” and then didnt delete it delete waits a few seconds so u can undo it. it dropped the question from the list first and threw away whatever came back from the server so if it failed u got told it saved, and the question showed up in ur study queue later like nothing happened also there was no undo button anywhere. it was just a slow delete $5 was being eaten maths sometimes comes wrapped in dollar signs so i strip them off. money also comes wrapped in dollar signs “Sam has $5 and Ana has $12” was being read as “Sam has 5 and Ana has 12” checked a real saved question and yep. paper says $5, database said 5 if my worker died, ur worksheet said “queued” forever the machine that reads the pages runs at my house. if it fell over mid job, nothing anywhere ever marked that job as failed it just sat there, and the free credit it charged u never came back the topic tagging could fail without failing it needs a bit of software thats not always there on the server. when it wasnt, it came back with “no matches” which is a completely normal answer. so the job finished, every question was untagged, ur weak areas page was empty, and nothing anywhere was an error one i was told to do and didnt had a note to cap the page number by how many pages the worksheet has except if u upload pages 10 to 15 of a pdf thats six pages numbered 10 to 15, so that check refuses every single one of them capped the two things separately instead also the screen asking u to check questions against the page never showed the page finishing a review session stopped saying u finished it the AI could print its own error onto ur status page, which sometimes meant quoting ur own worksheet back at u the upload checked the image size by asking the browser instead of opening the image
Devlog 6 - StudyBuddy u can throw everything u got wrong into blooket now button on the dashboard for the whole account, and one per worksheet if u only want that paper it gives u a file, u upload it to blooket, u get a set of exactly the questions u missed wrong means ever wrong, not currently wrong. if u got it wrong on paper and then right in review, its still in there. thats the one u actually want to drill and it wouldve been weird to leave out blooket hands u an .xlsx template so everyone calls this an xlsx export, but its uploader only accepts csv. took a while to work out also its importer just silently imports nothing if the file is slightly off. no error, no warning, zero questions. three separate ways to trip that picking a subject barely did anything theres a dropdown on upload for what subject the worksheet is. it offers things like “Algebra 1” only the first bit of that was ever used, so picking Algebra 1 searched all of high school maths. exactly the same as picking “all of high school maths” the one control u have over how ur questions get sorted, doing basically nothing long papers were quietly losing questions to a limit the topic tagger takes questions 100 at a time. fine except it grabbed 100 in no particular order and then removed the ones already done, so on a 114 question paper 14 never got looked at, and which 14 was down to whatever the database felt like that day worse on a second pass: if 100 were already tagged it handed back an empty list, which reads as “nothing left to do”, and the rest never got tagged at all two screens counting the same paper differently the worksheets page filters out page junk like “CONTINUE TO THE NEXT PAGE” before counting. the dashboard didnt so the same worksheet was 25 questions on one screen and 26 on the other, and nothing tells u which one is lying the chart was lying about time the accuracy chart draws a bar per week. it was only making bars for weeks u actually did something in so 12 bars looked like 12 weeks in a row but werent. practise in march and again in june and u see two bars side by side like it was steady every week is a bar now, empty ones included, and it says which weeks its showing scrolling changed my settings without me touching anything the page range and question count boxes were number inputs, and number inputs treat the scroll wheel as a way to change the value so scrolling down the upload page with ur cursor over one of them silently rewrote which pages get read found a pile of other accessibility stuff while i was in there: buttons a bit too small to reliably hit on a phone, cards that vanish in high contrast mode, and a “skip to content” link that didnt actually skip anything also asking to see an explanation u already had was using up ur hourly limit for generating new ones the topic picker was built in a way that made screen readers think the list had nothing in it button labels were half Title Case and half sentence case, sometimes on the same screen
Devlog 7 - StudyBuddy the drag box was broken in the real app. for months u upload a worksheet, u draw a box around question 1, it fills in. thats the whole manual editor, thats the whole free tier. and it didnt work. click through the app to get there and nothing responds. reload and its fine. four previous commits went looking for this. the test had a 24 line comment explaining why it was probably a test problem. it was not. elementFromPoint(100, 28) -> HTML elementsFromPoint(100, 28) -> [HTML] thats the browser saying nothing is at this pixel , for every pixel on the page. the cause was 8 view transition animations, 6 stuck running forever . one that never finishes sits in the top layer and covers everything. and its a pseudo element so it shows up in no ancestor walk and no element stack, which is why every previous investigation contradicted itself. bisected on clean builds: next flag react component result on on broken off on broken on off clean off off clean so its react’s <ViewTransition> , not next. three lines of css. the drag test used to fake the mouse with dispatched events, now it uses a real one, which is the only thing that proves anything. gemini has never completed a single request 4 providers in settings. one says “has a free tier worth starting on”. zero successful calls, ever. every nullable field is anyOf: [{type:'x'}, {type:'null'}] gemini doesnt understand anyOf , so a filter strips keywords it rejects the filter dropped anyOf and left {} behind, while leaving the field in required a required field with no type = rejected request. every time funny part: the allowlist already had nullable in it, gemini’s own word for the same idea. someone knew. nothing connected them. the landing page was lying about 3 of its 4 topics theres a comment above them saying “kept honest on purpose: these are real taxonomy names” . Ratio & proportion - not real Linear equations - not real Reading inference - not real Vocabulary in context - real so the one claim the page made about its own honesty was the false one lol. theres a test now instead of a comment. tests found 2 bugs i wasnt looking for new Date("sometime in 2010") returns jan 1 2010, cuz v8 scrapes a year out of almost anything. and it parses as local midnight while everything next to it is UTC. on a 13th birthday thats the whole question one route answered 404 to someone with no session. the client sends u to sign in on a 401 and brings u back after, so a tab that sat open till the session expired just ate what u typed the rest a reload could cost u a 114 question paper. markup saves nothing till every question is marked, so its a local draft now / , /signin , /signup are static html now. the topbar called auth() from the root layout, which made all 39 routes render per request the 23mb embedding model was getting fetched inside a background task on every cold start, and failing silently one commit recorded 32 renames and none of the code . the git add failed and i’d redirected the error away so i never saw it
Devlog 8 - StudyBuddy im too lazy to have a full write up for this (watched spiderman tdy IT WAS REALLY GOOD) for each topic that a user gets wrong, a seperate model (gpt-oss:20b, sorry if i miswrote the model) gives a walkthrough of the topic also added missed questions to the csv export added a AI answer key system if the worksheet doesnt have one.
Devlog 9 - StudyBuddy the merge tool could double up a question number renumbering the survivor of a duplicate pair used Math.min of just those two rows, blind to the rest of the paper merging a phantom #5 into a real #9 could hand the paper a second #5, the exact thing the tool exists to prevent zero tests on a function that deletes rows. five now, including the repro $15/hour was losing its sign, not just $5 the math-stripper runs from one $ to the next, so “earns $15/hour and $18/hour” reads the slash as a fraction and eats both signs. same with $40 = $25 + $15 on the = i wrote this down once as “one weird case.” it’s the whole unit-rate and equation category fix checks the char after the closing $ : a digit means it’s opening the next price, not real math figure crops didnt need a new pipeline, just reusing one filed as “never produced,” which reads like crop, store, backfill the verify screen already computes a crop window from the bbox over the stored page image. review got wired to the same math, every old worksheet gets it free the real work was the guards: zero-area, inverted, off-page, or no recorded page size all have to degrade to nothing rather than to the wrong crop a fence i built to be un-escapable, wasnt the comment says a new tag can’t be added without going through the escaping. page-seam work added two by typing them directly a page whose OCR contains the literal closing tag closes the fence early, and everything after reads as instructions instead of data tag list exists once now, every fence built from it every worksheets.status write was a bare UPDATE no guard on the current value, so a stale job retry could drag an already-reviewed worksheet back to failed one transitionWorksheet(from, to) now, every write through it preview deploys were migrating the prod database guard only checked VERCEL_ENV === 'production' , but previews fire on every push against one shared DATABASE_URL two finishing together were racing through the migration folder 9 tests could go quiet and nobody would know one e2e file, 12 tests serial in a single tab, everything past “verify” depending on a question a drag gesture created three tests earlier a drag regression silently skipped 9 unrelated tests instead of failing them api fixture, split the file, broke the drag on purpose to prove it. held the question list rendered all 114 cards for a screen that edits one at a time deferred a while back: virtualizing editable rows risks one unmounting mid-edit only one card can ever be expanded, so the risk surface is exactly one row virtualizes past 40 now, open row pinned into the rendered range wherever scrolling goes. typed into one at 60 questions, scrolled thousands of px away, still there, still focused, still holding the edit also profile save had devlog 4’s router.refresh() remount bug login rate limit skipped Auth.js’s own credentials endpoint ollama worker had no startup timeout and just hung worksheet text leaked into console logs on schema rejections review screen shipped every page’s OCR text on page-1 load admin console got merge, tree edit, queue, usage doc-count drift (third time), and a false-positive LaTeX check flagging real set notation as broken math
Devlog 10 - StudyBuddy mostly the same bug wearing different clothes: a screen that exists, that u can get to, that quietly does less than it says tier C was sitting in settings doing nothing save an ollama address and the app resolves u to a browser executor. that executor had nowhere to go, so ur worksheet just sat there looking queued it claims the job now and reads each page against localhost:11434 , posting back through the same queue my gpu posts through has to run in the browser cuz a server cant reach ur localhost, so the tab stays open. checkpointed per page tho, closing it resumes instead of restarting the paper a mark u mis-tapped was permanent tap through 40 of these and ur going to hit the wrong one eventually that one tap feeds the FSRS schedule, the topic accuracy, the weakness ranking and the blooket export only way back was deleting the worksheet and uploading it again, which costs u a trial credit. so the fix for a mistap was paying for it two defences that were never on WORKER_ALLOWED_IPS was optional and empty meant no restriction empty is the state every deployment starts in, so the normal outcome was a defence thats off that nobody ever decided to turn off refused now. * still allows any address but somebody has to type it untagged worksheets looked identical to broken ones tier B cant auto-classify, the embedding model needs a native runtime the serverless host doesnt have so ur questions saved fine and were reviewable fine, they just had no topic and nothing said why. reads exactly like it silently failed every tier that can come back untagged says so now nothing told u when a worksheet finished u uploaded and then u guessed. sat on the status page or came back later and hoped in-app bell that needs zero setup, plus web push for a tab u closed also “Review these now” now reviews those questions. the word had drifted onto three screens meaning three different things dashboard was missing three of its panels, and the trend arrow was specified ages ago and never computed taxonomy had no front door and the subject panel only went one level deep. Math > Geometry > Triangles walks now pagination was capping at the fiftieth worksheet and saying nothing about it the AI setup prompt showed up after ur trial ran out, which is the one moment it cant help u grouped scripts/ by what it does to ur data. inspect/ reads, repair/ writes behind a guard, benchmark/ measures 1285 tests green. playwright hasnt run yet and app/ moved a lot this time, so thats next
Devlog 11 - StudyBuddy this is a short one got the google sign in to work added email verification and forgot ur password thing cleaned up the overall UI made the topic tree standardized cleaned up some of the extraction issues added ollama integration for everyone added practice question generation, topic overview, etc tested everything fully the attached image is the app after a ton of testing *
ANYONE RATING THIS PROJECT - THE VIDEO ON THE SHIP IS OUTDATED, THERE IS ALSO ANOTHER FEW DEVLOGS SO CHECK THAT OUT BEFORE JUDGING BECAUSE IT GIVES MORE INFO ABOUT THE BUILDING AND WHY THE CHANGED A LOT SORRYYYY ALSO USE THE SAMPLE WORKSHEETS I ATTACHED OR EASILY PARSEABLE WORKSHEETS. TEMPORAILY IVE CLOSED THE API KEY VERSION AS MOST PEOPLE DONT HAVE THEM. COMPLEX WORKSHEETS ARE TO BE USED ONLY WITH LARGE LLM Devlog 12 - StudyBuddy got everything ready to ship turns out that ollama needed some permissions so fixed that and added it to readme for people to set up, and other stuff like that shipping it in 5 mins 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉
Devlog 13 - StudyBuddy update the ui to make it look liek sticky notes and lined paper
Devlog 14 shipwrights rejected the project so im fixing their things decided to clean up the code, get rid of old functions, and i also cleaned up the UI because no one really needs the heading and then what it means, like i think you know that topics means topics and doesnt need a whole sentence after that. cleaned up the repo, got rid of ai generated code fixed a 500 error when uploading worksheets, cuz something happened and some linux kernel wasnt compaitble with the library i was using wrapped up my last few fixes lowk not a lot of new features, rather like fixes
Devlog 15 more cleaninggggggg cleaned up repo, removed more dead logic and stuff instead of a css wallpaper, i added a image of lined paper to really give that school/learning feel asked ai to help me get the ui to look kinda fresh and add the pencil style heading
Devlog 16 - StudyBuddy added some sample worksheets so you can try it out added the borders back to the buttons because i accidently removed them before
Devlog 17 - StudyBuddy (ah im losing track of these devlogs uh my ship keeps getting rejected for look to AI, and ive literally rebuilt everything, removed all teh ai generated thing. (im gonna ship again rn) made a logo cuz i thought it would look cool added a Terms of Services page cuz its risky cuz people could upload worksheets they dont have access for an i could be fried so i made them agree to that cleaned up more code fixed a few more bugs
Devlog 18 - StudyBuddy lowk not a lot of content in this one but like 1000000 different bugs popped up and reviewers are pointing it out so thank you smmm ( @blowupthenoobs ur the goat) fixed the trials having no limit other fixes just check my commits
Devlog 19 - StudyBuddy even more bug fixes so i pushed a change, and that somehow broke the entire pipeline so i patched it no real content just fixes going to add API key integration soon (follow to see it happen)
Devlog 20 - StudyBuddy more bug fixes continous reships (they keep saying its too AI generated even after i rebuilt the UI) started working on the API key integration (like almost there rn) tons of dead code removal and code clean up added support for firefox too (now it works on edge, firefox, chrome, and prolly a ton others i just havent really tested it)
Devlog 21 - StudyBuddy patched even more bugs rewrote tons of my code (ai to human) cleaned up old files (a lot of old features were removed and reupdated) just more QoL fixes
Devlog 22 - StudyBuddy fixed more bugs and rewrote code by hand
Devlog 23 - StudyBuddy i just had some minutes left on this so im just making the devlog still waiting for my ship to be approved (been waiting a few days) no big changes at all (waiting for feedback)
Devlog 24: StudyBuddy so a lot of the feedback said “cool but it needs ur gpu on”. that made it seem like a PoC, so now its running on the free tier of openrouter. making the free tier work one request per question was never going to fit a daily cap. extraction now sends up to 10 pages / 25 questions per call, sorting and answer key go 10 questions at a time. ~4 requests per worksheet instead of ~42 the homepage and upload page count the day’s calls. 80% says busy, 100% stops reading and points u at the samples. samples upload page leads with the three samples as one-click cards; ur own pdf is the second option and says how much of the shared allowance is used. removed phone photo uploads (highly innaccurate on the free tier of models i have)
Ships:
StudyBuddy Turn the worksheets you have already done into a record of what you actually know. Try it: https://trystudybuddy.vercel.app Code: https://github.com/DagaVedant/StudyBuddy What I made Upload a worksheet you already finished, as a PDF or photos. A vision model pulls out every question, its options and its answer key. You mark what you got wrong. That is the only input it needs. It sorts questions into 87 topics across SAT and competition maths. Then it ranks your weak areas and schedules revision using FSRS, the algorithm behind Anki. It also writes practice questions on your weak topics and exports misses to Blooket. Built on my own past papers: 387 real questions from 22 worksheets. What was challenging The models can run in four places: my GPU, your API key, your own Ollama, or not at all. A student with a GPU should never send homework to my server. A student with nothing should still get something. Topic tagging needs an embedding model that serverless hosting cannot run. So the shortlist is a pgvector query on the server and the vector is computed anywhere, including in your browser under WebAssembly. Worst bug was three characters: I stored the global fetch on a class field, which passes the object as the receiver. Node allows it, browsers throw Illegal invocation. Every test passed and the only runtime that mattered was broken. What I am proud of It does not lie to you. Weak topics are ranked by a Wilson lower bound, not a raw percentage, so two unlucky answers cannot fake a weakness. Model-written questions are kept out of your accuracy, so the ranking cannot feed the questions it generates. Every model response is schema-checked before it reaches the database. Generated practice is sifted against thirteen specific failure modes. When my GPU is off, the upload screen says so instead of spinning. 1,459 unit tests, 84 end to end, 293 commits. How to test it Sign in with Google, or an email and password. Upload any worksheet you have already done. A past paper works well. Check what it read. Each question sits beside the page image it came from. Mark what you missed, then open the dashboard. The free trial reads three worksheets on my own GPU. If it is off, your upload queues and the app tells you. To skip the wait, settings takes your own API key or connects to Ollama on your machine. guys i wish this was markdown compatible but its not so sorry
StudyBuddy - https://trystudybuddy.vercel.app fyi before u try it: reading runs on a free model with a shared daily cap, and ship day is way more traffic than a normal day. please use the sample worksheets wherever u can (they’re the first thing on the upload page, one click) and upload at most one of ur own pdfs for the next day or two. if the homepage says the free reads are used up, the samples still work. what it does upload a worksheet pdf. it reads every question off the page, tags each one by topic, and works out the answer key. u mark which ones u got wrong and it brings them back on an FSRS schedule (the algo anki uses). across every test u upload it turns “i got 12 wrong” into “ur bad at ratios”. what changed since last time runs on openrouter’s free tier instead of my gpu. not a proof of concept anymore one worksheet is ~4 requests instead of ~42. pages are read in groups the site says when the day’s free reads are running low. clear about the trial: 3 worksheets free, then still free, u just add questions by hand or plug in ur own key. what was hard free models reason before they answer and bill that against the output limit which ends up causing an error, but its really hard to figure out the embedding-only shortcut for sorting looked fine and was wrong a third of the time so fixed it...
|
1793825300.3080952
|
1793911700.3080952
|
|
8545
|
flock camera detector by @joey2 | Stardance
|
joey2
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: flock camera detector by @joey2 | Stardance
|
1793306898.4161127
|
1793911698.4161127
|
|
54299
|
MeowMeow by @Dxkshh | Stardance
|
Dxkshh
|
1
|
3.59
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-02T05:54:33Z", "hours": 3.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I built MeowMeow My chaotic little corner of the internet that looks exactly like my bedroom after a 3AM coding session messy, loud, covered in stickers, and full of cats. It’s a portfolio that refuses to be clean or corporate, complete with floating text, a fake music player, project cards for stuff like WebTab and enough Gen-Z energy to make LinkedIn cry. The CSS was the real boss fight getting all the overlapping elements, glitch vibes, hover chaos, and that “everything is slightly broken on purpose” feel to actually work without the whole page collapsing was painful, especially keeping it somewhat usable on phone while still looking unhinged. I’m genuinely proud of how much personality it ended up having; it feels like me instead of another boring template. You can check the whole thing out live at https://Dxkshh-Codee.github.io/MeowMeow/ .", "repo": "https://github.com/Dxkshh-Codee/MeowMeow", "demo": "https://Dxkshh-Codee.github.io/MeowMeow/"}]...
|
[{"post_id": 60646, "ts": "202 [{"post_id": 60646, "ts": "2026-09-03T04:30:59Z", "hours": 0.595, "text": "DEVLOG 4 REWORKED ON THE DARK MODE IN CSS TO MAKE IT LOOK BETTER!! YOU GUYS CAN CHECK IT OUT AT https://dxkshh-codee.github.io/MeowMeow/ AND LET ME KNOW IF THERE IS SOMETHING TO CHANGE!!"}, {"post_id": 60048, "ts": "2026-09-02T04:52:33Z", "hours": 1.1392, "text": "DEVLOG 3 MY PERSONAL SITE IS READY !! ADD SOME TOUCH UPS TO IT IN CSS!!"}, {"post_id": 56491, "ts": "2026-08-28T08:59:51Z", "hours": 0.7311, "text": "DEVLOG 2 I’ve completed the HTML structure for my MeowMeow!"}, {"post_id": 55031, "ts": "2026-08-26T13:44:34Z", "hours": 0.8233, "text": "DEVLOG 1 Working on HTML for MeowMeow"}]...
|
Title: MeowMeow by @Dxkshh | Stardance
Devlogs:
D Title: MeowMeow by @Dxkshh | Stardance
Devlogs:
DEVLOG 1 Working on HTML for MeowMeow
DEVLOG 2 I’ve completed the HTML structure for my MeowMeow!
DEVLOG 3 MY PERSONAL SITE IS READY !! ADD SOME TOUCH UPS TO IT IN CSS!!
DEVLOG 4 REWORKED ON THE DARK MODE IN CSS TO MAKE IT LOOK BETTER!! YOU GUYS CAN CHECK IT OUT AT https://dxkshh-codee.github.io/MeowMeow/ AND LET ME KNOW IF THERE IS SOMETHING TO CHANGE!!
Ships:
I built MeowMeow My chaotic little corner of the internet that looks exactly like my bedroom after a 3AM coding session messy, loud, covered in stickers, and full of cats. It’s a portfolio that refuses to be clean or corporate, complete with floating text, a fake music player, project cards for stuff like WebTab and enough Gen-Z energy to make LinkedIn cry. The CSS was the real boss fight getting all the overlapping elements, glitch vibes, hover chaos, and that “everything is slightly broken on purpose” feel to actually work without the whole page collapsing was painful, especially keeping it somewhat usable on phone while still looking unhinged. I’m genuinely proud of how much personality it ended up having; it feels like me instead of another boring template. You can check the whole thing out live at https://Dxkshh-Codee.github.io/MeowMeow/ ....
|
1793825298.2733958
|
1793911698.2733958
|
|
609
|
My first slack bot! by @SGAGOATED | Stardance
|
SGAGOATED
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @SGAGOATED | Stardan Title: My first slack bot! by @SGAGOATED | Stardance...
|
1793306895.7046604
|
1793911695.7046604
|
|
54298
|
Quickfix by @shlokchavan | Stardance
|
shlokchavan
|
1
|
3.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-29T13:58:10Z", "hours": 3.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "my project is that helps to repair your texts and it makes you fast to text without any worry it is very nice for our daily life", "repo": "https://github.com/sangeetachavan9881-ux/frictionless", "demo": "https://sangeetachavan9881-ux.github.io/frictionless/"}]...
|
[{"post_id": 57345, "ts": "202 [{"post_id": 57345, "ts": "2026-08-29T13:54:15Z", "hours": 0.4303, "text": "working on errors and they are fixed"}, {"post_id": 57313, "ts": "2026-08-29T12:59:47Z", "hours": 3.0658, "text": "i am working on my quickfix project errors"}]...
|
Title: Quickfix by @shlokchavan | Stardance
Devlo Title: Quickfix by @shlokchavan | Stardance
Devlogs:
i am working on my quickfix project errors
working on errors and they are fixed
Ships:
my project is that helps to repair your texts and it makes you fast to text without any worry it is very nice for our daily life...
|
1793825294.53869
|
1793911694.53869
|
|
2987
|
A personal website inspired on space! by @Isabel | A personal website inspired on space! by @Isabel | Stardance...
|
Isabel
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: A personal website inspired on space! by @I Title: A personal website inspired on space! by @Isabel | Stardance...
|
1793306891.9032302
|
1793911691.9032302
|
|
54297
|
Zolt by @perr | Stardance
|
perr
|
1
|
25.99
|
118
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-28T17:45:21Z", "hours": 9.0, "multiplier": 12.82, "payout": 118, "blessing": "neutral", "text": "a tiny zig web server that speaks luau. when user request the server run the lua code and return them. kinda like php but with lua.", "repo": "https://github.com/iluvicecream/zolt", "demo": "https://zolt-doc.perr.dev/"}]...
|
[{"post_id": 73102, "ts": "202 [{"post_id": 73102, "ts": "2026-09-24T11:53:37Z", "hours": 2.3825, "text": "Template I guess so before all zolt app are written using .lua file and write to the response using echo which led to kind of bad dx so after the last ship there were some review on some kind of tsx like language so i been working on that and here zolt template build on top of go html/template with a lua block it will become a default way of writing app using zolt while .lua will be use for shared module and library"}, {"post_id": 72608, "ts": "2026-09-23T10:30:13Z", "hours": 3.2419, "text": "Documentation! just deploy a new version of documentation site and the go rewrite is complete! from the last update i also added http_request.header[“string”] let you get the header value http_request.query[“string”] let you get the parameters from request query http_request.method get the request method allow you to support POST and others turbokit module allow you to quickly create turbo-frame after this i will be working on form support so you can really build a web app with it"}, {"post_id": 71241, "ts": "2026-09-20T14:49:47Z", "hours": 1.5731, "text": "Merge!! no more experimental-go branch the go rewrite has been merge to the master branch along with the new releases 0.4.0 with support for windows too!. the documentation is currently wip so no doc yet sadd T_T but that the next thing am working on"}, {"post_id": 70774, "ts": "2026-09-19T18:57:20Z", "hours": 1.3961, "text": "Core Function is here after the go rewrite i have now implement 3 core function back but with some changes from zig version so when the go merge it will be a breaking changes http_set_status(status: int) let you set http response code such as 404 500 403 http_content_type(type: string) let you set content type header for usecase like json api http_header_add(key: string,value: string) let you add to the headers i also implement require for loading module and bring back hol now as htmlkit so yea looking forward to merge the go branch into main in a few days but it will 100% be a breaking changes not that who cared anyways except me cuz am the only one using it and now i have to fix my code"}, {"post_id": 68687, "ts": "2026-09-15T15:23:34Z", "hours": 5.3967, "text": "Sadly, There is such thing as a wrong decision when i first set out to make zolt i figure it will be a good place to learn zig i mean it such a small project just a simple http server that execute lua. but then i started using it myself and kept needing more feature but sadly even tho this project started as a way to learn zig. i just didn’t really click with it thus when implementing feature i kept having to relies a lot on codex. So what? so i started a new branch call experimental-go that contain a go rewrite of zoltd plan to be as much backward compatible as possible but not fully as zig zoltd use luau while go zoltd use gopher lua but otherwise i will try and implement all function in zig Naming even tho the project is being rewritten in go. the name will still remain zolt cuz golt sound worse What zolt go version like right now i just implement a lua runtime based on gopher-lua and implement 2 function echo() and print()"}, {"post_id": 64828, "ts": "2026-09-09T14:43:40Z", "hours": 1.845, "text": "HOL (Html On Lua) so from the last ship someone suggest that there should be a tsx like syntax that allow you to write html easier and i agree with that writing the whole layout in echo is a pain so i make hol a pretty simple html builder that ship with zolt so you can just import it anywhere without having to download it and am looking forward to add more feature such as native support for each element instead of H(“h1”) you can just do h1(“Header”) something like that"}, {"post_id": 60425, "ts": "2026-09-02T18:48:14Z", "hours": 1.1506, "text": "Query ! i added new api to the lua vm call request.query it accept 1 parameters field: string and return a string so if your url is host/?field1=value running request.query(“field1”) will return “value”"}, {"post_id": 56766, "ts": "2026-08-28T17:34:39Z", "hours": 0.9775, "text": "Quick Start i have added new entry to documentation such as installation using the new install script and your first zolt web guide along with lua api reference. for the zolt i have move status() and header() api into response.status() and response.header() to align more with request.path() and change webroot from current working dir to config parent dir."}, {"post_id": 55590, "ts": "2026-08-27T15:20:23Z", "hours": 2.4436, "text": "Documentation!! so i been working on a documentation for zolt with guess what zolt well the doc right now is pretty barebone with just intro and install for now but it is made with zolt,html,css,js i also use hotwire turbo and stimulus, and it also use this cute font by creators of grug. ( https://handdrawn.software/grug/ ) you can access the doc page here https://zolt-doc.perr.dev"}, {"post_id": 55153, "ts": "2026-08-26T17:01:52Z", "hours": 3.0167, "text": "Devlog 2 so from the last time i added new api such as require allow you to load other luau file and use them as a module header add header to the response status set http status code for the response with require you can now create function that help you build, for example i created a render module that help me to render html easier without having to deal with writing html tags manually apart from new api there has been a lot of changes behind the scene such as concurrency and performance improvements for the next devlog i will be working on adding api support for query params , form data , json body , and cookies so that you can build more complex web app with zolt! not only that am working on a documentation site that will also serve as an example on how to build web app using zolt"}, {"post_id": 54679, "ts": "2026-08-25T18:50:55Z", "hours": 2.7939, "text": "Zolt so this is php but with lua instead. well i wanted to learn zig and lately i been working on php project, and i just really love how stuff seem so simple but i kinda hate php syntax and the server around it. so yea here zolt it a zig web server that read the lua file you are requesting via query path then use luau to run it and give you the response. right now it just a plain text response but more coming!"}]...
|
Title: Zolt by @perr | Stardance
Devlogs:
Zolt so Title: Zolt by @perr | Stardance
Devlogs:
Zolt so this is php but with lua instead. well i wanted to learn zig and lately i been working on php project, and i just really love how stuff seem so simple but i kinda hate php syntax and the server around it. so yea here zolt it a zig web server that read the lua file you are requesting via query path then use luau to run it and give you the response. right now it just a plain text response but more coming!
Devlog 2 so from the last time i added new api such as require allow you to load other luau file and use them as a module header add header to the response status set http status code for the response with require you can now create function that help you build, for example i created a render module that help me to render html easier without having to deal with writing html tags manually apart from new api there has been a lot of changes behind the scene such as concurrency and performance improvements for the next devlog i will be working on adding api support for query params , form data , json body , and cookies so that you can build more complex web app with zolt! not only that am working on a documentation site that will also serve as an example on how to build web app using zolt
Documentation!! so i been working on a documentation for zolt with guess what zolt well the doc right now is pretty barebone with just intro and install for now but it is made with zolt,html,css,js i also use hotwire turbo and stimulus, and it also use this cute font by creators of grug. ( https://handdrawn.software/grug/ ) you can access the doc page here https://zolt-doc.perr.dev
Quick Start i have added new entry to documentation such as installation using the new install script and your first zolt web guide along with lua api reference. for the zolt i have move status() and header() api into response.status() and response.header() to align more with request.path() and change webroot from current working dir to config parent dir.
Query ! i added new api to the lua vm call request.query it accept 1 parameters field: string and return a string so if your url is host/?field1=value running request.query(“field1”) will return “value”
HOL (Html On Lua) so from the last ship someone suggest that there should be a tsx like syntax that allow you to write html easier and i agree with that writing the whole layout in echo is a pain so i make hol a pretty simple html builder that ship with zolt so you can just import it anywhere without having to download it and am looking forward to add more feature such as native support for each element instead of H(“h1”) you can just do h1(“Header”) something like that
Sadly, There is such thing as a wrong decision when i first set out to make zolt i figure it will be a good place to learn zig i mean it such a small project just a simple http server that execute lua. but then i started using it myself and kept needing more feature but sadly even tho this project started as a way to learn zig. i just didn’t really click with it thus when implementing feature i kept having to relies a lot on codex. So what? so i started a new branch call experimental-go that contain a go rewrite of zoltd plan to be as much backward compatible as possible but not fully as zig zoltd use luau while go zoltd use gopher lua but otherwise i will try and implement all function in zig Naming even tho the project is being rewritten in go. the name will still remain zolt cuz golt sound worse What zolt go version like right now i just implement a lua runtime based on gopher-lua and implement 2 function echo() and print()
Core Function is here after the go rewrite i have now implement 3 core function back but with some changes from zig version so when the go merge it will be a breaking changes http_set_status(status: int) let you set http response code such as 404 500 403 http_content_type(type: string) let you set content type header for usecase like json api http_header_add(key: string,value: string) let you add to the headers i also implement require for loading module and bring back hol now as htmlkit so yea looking forward to merge the go branch into main in a few days but it will 100% be a breaking changes not that who cared anyways except me cuz am the only one using it and now i have to fix my code
Merge!! no more experimental-go branch the go rewrite has been merge to the master branch along with the new releases 0.4.0 with support for windows too!. the documentation is currently wip so no doc yet sadd T_T but that the next thing am working on
Documentation! just deploy a new version of documentation site and the go rewrite is complete! from the last update i also added http_request.header[“string”] let you get the header value http_request.query[“string”] let you get the parameters from request query http_request.method get the request method allow you to support POST and others turbokit module allow you to quickly create turbo-frame after this i will be working on form support so you can really build a web app with it
Template I guess so before all zolt app are written using .lua file and write to the response using echo which led to kind of bad dx so after the last ship there were some review on some kind of tsx like language so i been working on that and here zolt template build on top of go html/template with a lua block it will become a default way of writing app using zolt while .lua will be use for shared module and library
Ships:
a tiny zig web server that speaks luau. when user request the server run the lua code and return them. kinda like php but with lua....
|
1793825291.5158327
|
1793911691.5158327
|
|
40299
|
My first slack bot! by @body-35 | Stardance
|
body-35
|
1
|
1.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-27T23:31:25Z", "hours": 1.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I do a slack bot with slash command /my-glitchy-bot-ping - Check latency /my-glitchy-bot-help - Show this menu /my-glitchy-bot-catfact - Random cat fact /my-glitchy-bot-joke - Random joke and I’m really proud of my self for my hard work", "repo": "https://github.com/Body-530/my-Glitchy-bot", "demo": "https://app.slack.com/client/E09V59WQY1E/C0BLDDB6UL9"}]...
|
[{"post_id": 36080, "ts": "202 [{"post_id": 36080, "ts": "2026-07-27T23:04:25Z", "hours": 0.5278, "text": "yaaaa!❤️🔥❤️🔥 really excited to share my first slack bot with 4 slash commands Bot build with Node.js and Slack BOT for the Hack Club (My Glitchy-Bot) is a 24/7 Bot on Hack Club Nest and responds to custome slash commands using the Slack API"}]...
|
Title: My first slack bot! by @body-35 | Stardance Title: My first slack bot! by @body-35 | Stardance
Devlogs:
yaaaa!❤️🔥❤️🔥 really excited to share my first slack bot with 4 slash commands Bot build with Node.js and Slack BOT for the Hack Club (My Glitchy-Bot) is a 24/7 Bot on Hack Club Nest and responds to custome slash commands using the Slack API
Ships:
I do a slack bot with slash command /my-glitchy-bot-ping - Check latency /my-glitchy-bot-help - Show this menu /my-glitchy-bot-catfact - Random cat fact /my-glitchy-bot-joke - Random joke and I’m really proud of my self for my hard work...
|
1793825287.7321963
|
1793911687.7321963
|
|
52177
|
645 Run Club by @k_nilesh | Stardance
|
k_nilesh
|
1
|
13.0
|
29
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-21T05:36:06Z", "hours": 13.0, "multiplier": 2.93, "payout": 29, "blessing": "neutral", "text": "I built 645 Run Club, a running community platform designed to bring runners together through runs, challenges, events, and community activities. The most challenging part was making the website functional beyond just the frontend, especially working with the backend, APIs, data handling, and fixing unexpected bugs. I’m proud that I took an idea and turned it into a real working project while learning how different parts of a full-stack application connect together. To test it, people can visit the 645 Run Club website, explore the available features, and sign up or log in where required to experience the platform.", "repo": "https://github.com/k-nilesh04/645-running-club", "demo": "https://645-running-club.vercel.app/"}]...
|
[{"post_id": 51453, "ts": "202 [{"post_id": 51453, "ts": "2026-08-21T05:33:12Z", "hours": 13.0578, "text": "645 Run Club is a community-based running platform/club that I’m building to bring people together through running and fitness. The idea is to create a space where people can join runs, participate in challenges and events, track their progress, and stay motivated with a community. I’m currently working on the website and backend, making the platform functional and building the features needed to manage members, runs, events, and communication."}]...
|
Title: 645 Run Club by @k_nilesh | Stardance
Devl Title: 645 Run Club by @k_nilesh | Stardance
Devlogs:
645 Run Club is a community-based running platform/club that I’m building to bring people together through running and fitness. The idea is to create a space where people can join runs, participate in challenges and events, track their progress, and stay motivated with a community. I’m currently working on the website and backend, making the platform functional and building the features needed to manage members, runs, events, and communication.
Ships:
I built 645 Run Club, a running community platform designed to bring runners together through runs, challenges, events, and community activities. The most challenging part was making the website functional beyond just the frontend, especially working with the backend, APIs, data handling, and fixing unexpected bugs. I’m proud that I took an idea and turned it into a real working project while learning how different parts of a full-stack application connect together. To test it, people can visit the 645 Run Club website, explore the available features, and sign up or log in where required to experience the platform....
|
1793825284.8929484
|
1793911684.8929484
|
|
11126
|
Untitled project by @anm | Stardance
|
anm
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Untitled project by @anm | Stardance
|
1793306883.76129
|
1793911683.76129
|
|
52163
|
ThirdView by @shivakaushal | Stardance
|
shivakaushal
|
2
|
21.0
|
144
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-31T06:33:18Z", "hours": 15.0, "multiplier": 7.18, "payout": 105, "blessing": "neutral", "text": "The project is finally complete, by the way. It was completed a month ago. But i really forgot this. Right now thirdview max uses two search @visual and @vocal , by the help of this. Evrything is working. t was fun when I was making it.", "repo": "https://github.com/ThisShivaKaushal/ThirdView-Max", "demo": "https://thirdviewmax.vercel.app"}, {"ship_num": 2, "ts": "2026-08-23T11:57:29Z", "hours": 6.0, "multiplier": 6.82, "payout": 39, "blessing": "neutral", "text": "I made ThirdView - you type a description of a scene and it jumps straight to that moment in a video, instead of scrubbing through the timeline forever. It runs fully in the browser using CLIP through Transformer.js, no uploads, no server. The hard part was getting an actual ML model to run smoothly with zero backend, plus CLIP wasn’t built for video, so figuring out how often to sample frames took a lot of trial and error. What we’re proud of is that it just works fully private, fully free, and it actually fixes something that annoys us every single time we watch something not together, without turning into some bloated overengineered app.", "repo": "https://github.com/ThisShivaKaushal/ThirdView-Max", "demo": "https://thirdviewmax.vercel.app"}]...
|
[{"post_id": 85361, "ts": "202 [{"post_id": 85361, "ts": "2026-10-31T06:30:26Z", "hours": 4.3994, "text": "Right now, I just commit my code, because at the last time, i skip this project without writing devlog and committing. The stardance is going to end, so I just going to ship it and the project is wroking perfectly."}, {"post_id": 71013, "ts": "2026-09-20T06:28:36Z", "hours": 0.9111, "text": "I have changed the UI, and some elements are hidden, because when we upload video then it appears. And now I’m going to write the logic(Javascript), i’m too fast because I have already made it, so basic things don’t take much time, but now i’m going to work on logic, and i also have to add some more features, so i think it usually takes 3-4 hours, and then the projects will get completed."}, {"post_id": 70990, "ts": "2026-09-20T05:14:27Z", "hours": 0.4422, "text": "HTML is completed, now I have to style it, and have to make the logic. Because our project is completely base on logic, so the javascript will be too long. Nd i also suffer sometimes with making logic, and let see what happen:D"}, {"post_id": 70487, "ts": "2026-09-19T08:41:14Z", "hours": 2.0139, "text": "Hey Everyone, I’m going to continue my ThirdView project again but this time, its name will be Thirdview Max, because it is the updated version, so. Now, you can also see the old version at github, which is at another repo. But Thirdview Max have more and extra feature then Thirdview, now it can give accurate result, but in past I said that it also have feature, by which you can just paste link, nd find the part. But because, i have to fetch the video in .mp4 first, which is difficult part, I tried, but i failed. That’s why I decided to skip this feature. and the main things, the Ui is going to completely change."}, {"post_id": 58121, "ts": "2026-08-30T13:56:28Z", "hours": 0.5769, "text": "#Devlog:6 of #Ship:2 I have made these files, but now my logic has hit a limitation because YouTube doesn’t allow frame extraction. To solve this, we are using a public API which helps a lot with YouTube search. I use yt-dlp to resolve the YouTube URL, specifically using an Invidious public API. I know it might get shut down sometimes by YouTube, but what can we do? I will use my own yt-dlp backend to get a CORS-friendly video stream. By doing this, we can access the YouTube video as a .mp4 file, which allows us to extract frames. Let’s see if it works perfectly or not. However, my own backend will work for only 7 days because it is an open-source project."}, {"post_id": 58009, "ts": "2026-08-30T10:54:52Z", "hours": 2.6042, "text": "#Devlog:5 of #Ship:2 I have made my UI, and now I have to write the logic. The best part is that I have messed up my style.css file. I want to improve it more, but I got confused with my colors. I gave names to the colors, but in the end, I could not understand my own color pattern or what I had decided to use each color for. By the way, I think the UI looks good. Now, let’s talk about the UI features: I have made the header sticky and also added a blur effect to it. Instead of taking YouTube’s color palette, I used a popular palette from coolors.co because I liked it at first sight. You can see the UI below."}, {"post_id": 57238, "ts": "2026-08-29T10:45:40Z", "hours": 0.9719, "text": "#Devlog:4 of #Ship:2 I have made the HTML, and now I’m working on the CSS. I am making the UI look good. By the way, I think I have done only 30-40% of the CSS, and I think I’ll try to complete it today. Then, I’ll start focusing on the logic, like JavaScript, because it is our main stuff. I’d take inspiration from YouTube, like using YouTube’s color palette, and the structure is like the old one."}, {"post_id": 57189, "ts": "2026-08-29T09:24:01Z", "hours": 0.2992, "text": "#Devlog:3 of #Ship:2 I have just put my real hosted website into maintenance mode. Normally, if I push code to GitHub, Vercel automatically hosts the new version. If someone visits suddenly during that time, they might think the website has a code error. That’s why I created a vercel.json file a week ago and now pushed it to GitHub. Now, I can continuously make changes for a while without any tension related to the main website, because it always shows that it is in maintenance."}, {"post_id": 57145, "ts": "2026-08-29T07:49:32Z", "hours": 0.5208, "text": "#Devlog:2 of #Ship:2 I have implemented two things: 1.Now you can paste the link of a YouTube video and it will help you find the timestamp. Although I have just created the HTML, this time I didn’t have an idea of how I will grab the frames. By the way, I think I’ll try to download the video in low quality, and then grab the frames. If anyone has any ideas, just let me know, or I’ll try to serch and understand an easier way. 2. I have implemented a new model (Audio Model). In the Shipwright review video, I saw that the reviewer typed “MrBeast saying ‘Red Light,’” and my website at that time was only able to search through visuals. But now it can walk through the vocal parts. It converts the video’s audio into text, and then it will match the query. But here’s an error: we can’t check the query’s exact result matching percentage, and it may create some problems. By the way, when you search, it has two options like @visual and @vocal . So when you select one, it only runs that one model. But if you have added say or said, then it also runs both things simultaneously. If you only put one thing, then it runs one model only, so it saves memory and works fast. But let’s suppose you didn’t select either one; then for accurate results, it runs both models."}, {"post_id": 57108, "ts": "2026-08-29T06:36:15Z", "hours": 0.7319, "text": "#Devlog:1 of #Ship:2 Hi guys, when I shipped my first project, 2-3 people said that I used AI. I really did use it, but in different ways, and now I am also feeling ashamed of myself. Why? Because that was my first project, and my manner of writing code is not good, I even dn’t like what I write myself. That’s why I used AI by giving it my own code and tellng it to make it professional, understandable, and much more. That was my mistake, but now after searching a lot, I understand it didn’t matter. So now I am going to write this project again with some more features, and mainly the UI, which looked very cheap (and I know people were also saying it is AI—by the way, I took color decisions from AI). But now, instead of asking any AI out of fear of making mistakes, that fear has gone, and I am going to design everything by myself. However, my JavaScript is a little bit weak, so I am gong to use AI for learning purposes, but now I will upload the raw code that I write. By the way, the new feature will contain a YouTube video link."}, {"post_id": 53602, "ts": "2026-08-24T07:22:10Z", "hours": 0.7489, "text": "Another new feature, I copied it from Github, because I have used it many time."}, {"post_id": 53591, "ts": "2026-08-24T06:28:53Z", "hours": 0.47, "text": "I built the Thirdview project, but after shipping it, I received requests to make the design more appealing. I didn’t love the original look either, so I am redesigning the UI and adding more color. By the way, I am also working on a new feature—see if you can guess what it is!"}, {"post_id": 52890, "ts": "2026-08-23T08:37:28Z", "hours": 0.9194, "text": "Guys, I was suffering from a problem. When my friends and I watch any movies or something else, mostly anime, then we surely find a scene where me and my boys melt. And when we meet physically, we have to tell each other about that. And this is the most time-consuming part. My one friend who doesn’t even know the episode, then how can we think he will remember the timestamp? That’s why, by the way, I’m also like my friend. That’s why I built this app. It means you just have to upload the videos and then tell about the scene, like, “the main character, who wears yellow clothes, is beating the man,” and you will get the timestamp without any problem. Now, my friends and I don’t have to waste more than 30 minutes for just a 10- to 15-second clip in a one-hour episode. Maybe we can get the correct timestamp in just two or three minutes. Hold a minute. If you are lucky, then you might get the correct timestamp randomly. But I know our and your luck are not that great. And it’s just HTML, CSS, and JavaScript. By the way, let me tell you how it is working. For this, you can read the README.md. For the trial, you can visit thirdview.vercel.app. By the way, for most people, it is just extra storage. But for me, this is my first project, such a great project I made. Bye-bye. Just visit the repo. Oh, and it completely works locally, means in the browser, but it’s not connected to the cloud. That’s why it may be slow. I have just host my project on Vercel, and I will ship this project today after making a show video."}, {"post_id": 52402, "ts": "2026-08-22T15:03:55Z", "hours": 4.8003, "text": "My first project is almost ready to ship! I can’t wait to show you guys. It’s just HTML, CSS, and JavaScript, but it solves a really annoying problem in our friend group. I’ll try to publish it tomorrow. Bye for now!"}]...
|
Title: ThirdView by @shivakaushal | Stardance
Dev Title: ThirdView by @shivakaushal | Stardance
Devlogs:
My first project is almost ready to ship! I can’t wait to show you guys. It’s just HTML, CSS, and JavaScript, but it solves a really annoying problem in our friend group. I’ll try to publish it tomorrow. Bye for now!
Guys, I was suffering from a problem. When my friends and I watch any movies or something else, mostly anime, then we surely find a scene where me and my boys melt. And when we meet physically, we have to tell each other about that. And this is the most time-consuming part. My one friend who doesn’t even know the episode, then how can we think he will remember the timestamp? That’s why, by the way, I’m also like my friend. That’s why I built this app. It means you just have to upload the videos and then tell about the scene, like, “the main character, who wears yellow clothes, is beating the man,” and you will get the timestamp without any problem. Now, my friends and I don’t have to waste more than 30 minutes for just a 10- to 15-second clip in a one-hour episode. Maybe we can get the correct timestamp in just two or three minutes. Hold a minute. If you are lucky, then you might get the correct timestamp randomly. But I know our and your luck are not that great. And it’s just HTML, CSS, and JavaScript. By the way, let me tell you how it is working. For this, you can read the README.md. For the trial, you can visit thirdview.vercel.app. By the way, for most people, it is just extra storage. But for me, this is my first project, such a great project I made. Bye-bye. Just visit the repo. Oh, and it completely works locally, means in the browser, but it’s not connected to the cloud. That’s why it may be slow. I have just host my project on Vercel, and I will ship this project today after making a show video.
I built the Thirdview project, but after shipping it, I received requests to make the design more appealing. I didn’t love the original look either, so I am redesigning the UI and adding more color. By the way, I am also working on a new feature—see if you can guess what it is!
Another new feature, I copied it from Github, because I have used it many time.
#Devlog:1 of #Ship:2 Hi guys, when I shipped my first project, 2-3 people said that I used AI. I really did use it, but in different ways, and now I am also feeling ashamed of myself. Why? Because that was my first project, and my manner of writing code is not good, I even dn’t like what I write myself. That’s why I used AI by giving it my own code and tellng it to make it professional, understandable, and much more. That was my mistake, but now after searching a lot, I understand it didn’t matter. So now I am going to write this project again with some more features, and mainly the UI, which looked very cheap (and I know people were also saying it is AI—by the way, I took color decisions from AI). But now, instead of asking any AI out of fear of making mistakes, that fear has gone, and I am going to design everything by myself. However, my JavaScript is a little bit weak, so I am gong to use AI for learning purposes, but now I will upload the raw code that I write. By the way, the new feature will contain a YouTube video link.
#Devlog:2 of #Ship:2 I have implemented two things: 1.Now you can paste the link of a YouTube video and it will help you find the timestamp. Although I have just created the HTML, this time I didn’t have an idea of how I will grab the frames. By the way, I think I’ll try to download the video in low quality, and then grab the frames. If anyone has any ideas, just let me know, or I’ll try to serch and understand an easier way. 2. I have implemented a new model (Audio Model). In the Shipwright review video, I saw that the reviewer typed “MrBeast saying ‘Red Light,’” and my website at that time was only able to search through visuals. But now it can walk through the vocal parts. It converts the video’s audio into text, and then it will match the query. But here’s an error: we can’t check the query’s exact result matching percentage, and it may create some problems. By the way, when you search, it has two options like @visual and @vocal . So when you select one, it only runs that one model. But if you have added say or said, then it also runs both things simultaneously. If you only put one thing, then it runs one model only, so it saves memory and works fast. But let’s suppose you didn’t select either one; then for accurate results, it runs both models.
#Devlog:3 of #Ship:2 I have just put my real hosted website into maintenance mode. Normally, if I push code to GitHub, Vercel automatically hosts the new version. If someone visits suddenly during that time, they might think the website has a code error. That’s why I created a vercel.json file a week ago and now pushed it to GitHub. Now, I can continuously make changes for a while without any tension related to the main website, because it always shows that it is in maintenance.
#Devlog:4 of #Ship:2 I have made the HTML, and now I’m working on the CSS. I am making the UI look good. By the way, I think I have done only 30-40% of the CSS, and I think I’ll try to complete it today. Then, I’ll start focusing on the logic, like JavaScript, because it is our main stuff. I’d take inspiration from YouTube, like using YouTube’s color palette, and the structure is like the old one.
#Devlog:5 of #Ship:2 I have made my UI, and now I have to write the logic. The best part is that I have messed up my style.css file. I want to improve it more, but I got confused with my colors. I gave names to the colors, but in the end, I could not understand my own color pattern or what I had decided to use each color for. By the way, I think the UI looks good. Now, let’s talk about the UI features: I have made the header sticky and also added a blur effect to it. Instead of taking YouTube’s color palette, I used a popular palette from coolors.co because I liked it at first sight. You can see the UI below.
#Devlog:6 of #Ship:2 I have made these files, but now my logic has hit a limitation because YouTube doesn’t allow frame extraction. To solve this, we are using a public API which helps a lot with YouTube search. I use yt-dlp to resolve the YouTube URL, specifically using an Invidious public API. I know it might get shut down sometimes by YouTube, but what can we do? I will use my own yt-dlp backend to get a CORS-friendly video stream. By doing this, we can access the YouTube video as a .mp4 file, which allows us to extract frames. Let’s see if it works perfectly or not. However, my own backend will work for only 7 days because it is an open-source project.
Hey Everyone, I’m going to continue my ThirdView project again but this time, its name will be Thirdview Max, because it is the updated version, so. Now, you can also see the old version at github, which is at another repo. But Thirdview Max have more and extra feature then Thirdview, now it can give accurate result, but in past I said that it also have feature, by which you can just paste link, nd find the part. But because, i have to fetch the video in .mp4 first, which is difficult part, I tried, but i failed. That’s why I decided to skip this feature. and the main things, the Ui is going to completely change.
HTML is completed, now I have to style it, and have to make the logic. Because our project is completely base on logic, so the javascript will be too long. Nd i also suffer sometimes with making logic, and let see what happen:D
I have changed the UI, and some elements are hidden, because when we upload video then it appears. And now I’m going to write the logic(Javascript), i’m too fast because I have already made it, so basic things don’t take much time, but now i’m going to work on logic, and i also have to add some more features, so i think it usually takes 3-4 hours, and then the projects will get completed.
Right now, I just commit my code, because at the last time, i skip this project without writing devlog and committing. The stardance is going to end, so I just going to ship it and the project is wroking perfectly.
Ships:
I made ThirdView - you type a description of a scene and it jumps straight to that moment in a video, instead of scrubbing through the timeline forever. It runs fully in the browser using CLIP through Transformer.js, no uploads, no server. The hard part was getting an actual ML model to run smoothly with zero backend, plus CLIP wasn’t built for video, so figuring out how often to sample frames took a lot of trial and error. What we’re proud of is that it just works fully private, fully free, and it actually fixes something that annoys us every single time we watch something not together, without turning into some bloated overengineered app.
The project is finally complete, by the way. It was completed a month ago. But i really forgot this. Right now thirdview max uses two search @visual and @vocal , by the help of this. Evrything is working. t was fun when I was making it....
|
1793825281.9241586
|
1793911681.9241586
|
|
23909
|
My very own WebOS by @itsmerudranshkh | Stardance
|
itsmerudranshkh
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My very own WebOS by @itsmerudranshkh | Sta Title: My very own WebOS by @itsmerudranshkh | Stardance...
|
1793306881.4741654
|
1793911681.4741654
|
|
24118
|
Untitled by @Charvik | Stardance
|
Charvik
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Untitled by @Charvik | Stardance
|
1793306880.5371869
|
1793911680.5371869
|
|
40484
|
RaidenScript by @RaidenTechnology | Stardance
|
RaidenTechnology
|
2
|
58.97
|
231
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-23T11:46:51Z", "hours": 31.0, "multiplier": 10.41, "payout": 104, "blessing": "neutral", "text": "RaidenScript v0.2 Update I wrote RaidenScript (RS) from scratch in C++20 as a small embeddable scripting language. In Ship #1 I had it running in three hosts. Since then I gave it a browser you can try it in, and I turned the Minecraft host into a real game running on a live server. I put the language in a browser. I compiled the C API to WebAssembly, served it from GitHub Pages, and wrote an editor with a Run button and four example programs: raidentechnology.github.io/raidenscript. I send nothing to a server; the page is the interpreter. I stopped treating the Minecraft host as a demo. I wrote 144 commits on it since the last devlog, and I keep the rules out of Java entirely: they sit in one .rai file the server loads at boot and reloads while players are online. I wrote a whole farming layer as script rules. Every crop got its own tool with its own level and rarity ladder, and I added tool enchants, XP bottles, an upgrade bench, and a 20 minute contest with medals and a shop of its own. I added pests. Twelve species, a spawn engine I tied to whatever crop is planted, a five-tier vacuum to kill them with, and a loot table I hooked into the same farming-luck stat every other system reads. I built a garden around it: 8 plots, a regeneration engine that rebuilds 13 farm patterns, 76 visitor NPCs I gave 53 signed skins, and a copper economy I priced off the live Bazaar API instead of numbers I made up. I added one host primitive, taslakModel, and let the script choose the model an item wears. Adding an item is now a script edit and nothing else. I fixed three bugs the live server found and no test of mine would have. An item-identity gate was cancelling every right click unconditionally, so the grappling hook silently never fired. The area hoe was catching its own synthetic event and moving the stack twice. And one wrong price in a shop table was failing the entire script at boot. Why did I do it like this? Because I think a language is judged by what runs on it, not by its grammar. The strongest thing I can say about my embedding API is that a 10,000 line ruleset runs on it every night, on a real server, with real players. Because I lose reviewers at the install wall. For Ship #1 I asked people to clone a repo and build it with MinGW. Now I ask for one click, and I am handing them the same interpreter, not a simplified twin. Because every rule I move out of Java is a rule I can change without a restart. I left no compile step in the script layer, so /rai reload changes the balance of a live game between two swings of a sword. Because item models were the last thing still forcing me into Java. I closed that hole, and I now keep the Java side as infrastructure only: it knows how to talk to the server and nothing about what the game is. Because I wanted the contest, the pests and the visitor queue to stress the C boundary. I pass numbers in the array and let strings travel beside it, and not one of these systems made me widen that contract. Because a bug a player hits at 2 AM is worth more to me than a bug I find in my own suite. All three above came from the server. Source (MIT): github.com/RaidenTechnology/raidenscript", "repo": "https://github.com/RaidenTechnology/raidenscript", "demo": "https://raidentechnology.github.io/raidenscript/"}, {"ship_num": 2, "ts": "2026-07-28T10:10:56Z", "hours": 7.0, "multiplier": 17.73, "payout": 127, "blessing": "neutral", "text": "RaidenScript v0.1 — an embeddable scripting language written from scratch in C++20. WHAT IT IS A small language (29 keywords) with Python’s readability and JavaScript’s runtime model, built to go inside another program and make it scriptable. The same interpreter runs in three hosts, and each one has a working demo in the repo: Terminal — native binary, “rai program.rai”, plus a REPL Browser — C API compiled to WebAssembly, running an animated store page JVM — C API through JNI, running a Paper Minecraft plugin The demo link is my shipped game STAR BREAKER: one of its weapons is not defined in the game at all, it is a RaidenScript file the game loads and runs through the WebAssembly build. WHAT IS IN IT Lexer, parser, resolver, tree-walking interpreter and REPL, all hand-written; no parser generator, no dependencies. 16 example programs that double as the regression suite, 20 C API checks, 7 WebAssembly checks, zero compiler warnings. A recursion-depth guard so a runaway script raises a catchable error instead of killing the host process — verified separately on native, wasm and the JVM. The cover image was computed pixel by pixel by a RaidenScript program (demo/kapak/kapak-ascii.rai) — no graphics library, in the program or in the language. HOW TO TRY IT git clone, then “make” (w64devkit/MinGW on Windows, gcc elsewhere), then “rai examples/01-temeller.rai”, or just “rai” for the REPL. The README is a full manual: language guide, standard library, embedding walkthrough. Known limits are written down there rather than hidden: an exception escaping a host function leaks stack, string += is quadratic, and a script returning a string to rs_call still yields 0. AI SPLIT The design of the language and its core — lexer, parser, resolver, interpreter, REPL, C API, string channel — is mine and was written by me. The host bindings, the demo apps, and this week’s seven interpreter bug fixes are AI-written from my designs and my audit. Logged hours are my editor time only. Source (MIT): github.com/RaidenTechnology/raidenscript", "repo": "https://github.com/RaidenTechnology/raidenscript", "demo": "https://raidentechnology.github.io/raidenscript/"}]...
|
[{"post_id": 53014, "ts": "202 [{"post_id": 53014, "ts": "2026-08-23T12:15:50Z", "hours": 20.9703, "text": "RaidenScript: the cover is a program, not a picture I gave the project a red and black cover, and I did it without opening an image editor. The cover generator is a RaidenScript program that prints a plain PPM to stdout, so I changed the palette in the script and ran it again: three radial glows, a faint grid, a vertical gradient on the bolt, and a 5x7 bitmap font that is data inside the file, not a system font. It computes 315,000 pixels in 43 seconds. That is my tree-walking interpreter doing arithmetic in a while loop, with no graphics library in the program and none in the language. My first render was wrong and I had to say so. The old cover put a turquoise bolt on a violet field, so the contrast came from hue. In red on red there is no hue left to lean on, and the bolt sank into the background. I cut the background glow to a third and pushed the bolt to a near-white core, so the contrast now comes from brightness. I cleaned the repository behind it. My README still linked to SPEC.md and WORKLOG.md after I deleted them, so anyone cloning it hit two dead links on the front page. I removed those links and rewrote the root README and two demo READMEs without tables. Why did I do it like this? Because a cover drawn in an image editor says nothing about my language, and a cover computed by it is the smallest honest benchmark I own. If the language cannot fill 315,000 pixels, I want to know that before someone else finds out. Because 43 seconds is a real number and I am not hiding it. It is fine for a cover I render once, and it is exactly why a bytecode VM sits on my roadmap instead of being marked done. Because a README that points at files I deleted is a promise I broke to whoever clones the repo, and that is the first thing a reviewer sees."}, {"post_id": 46568, "ts": "2026-08-13T21:53:11Z", "hours": 30.61, "text": "The loop that fixes the language is written in the language Since the last devlog the work split in two: a development loop that RaidenScript now drives itself, and a repository that finally stopped mixing the language with a game server. selfdev - the decision logic is a .rai file tools/selfdev.rai holds the loop’s rules: pick an area nobody touched last round, run the build, read the log, call the pass green or red, append its own entry to a round journal. Under it sits tools/rsdev.cpp, a sys.* host built on the same C API the browser game and the Minecraft plugin already use. The language had three hosts. The fourth one is its own toolchain. Pass 2 taught it what not to trust. tools/selfdev-build.cmd reported EXIT=0 for a run that failed to link. The cause is not in the language at all: exit /b inside a ( … ) » log 2>&1 block does not end a .cmd script, so control falls through to the final exit /b 0. A loop whose whole contract is “exit 0 means green” can commit on red - and it did once, on stale .o files. The rule now is read the log, not the exit code, and it is written in capitals at the top of SELFDEV-NOTES.md because I expect to forget it. What the passes actually fixed String building was quadratic. At 60,000 pieces: s += x took 1879 ms, s = s + x took 2382 ms, against a list.push + join baseline of 54 ms - 35x and 44x. Strings stay immutable (SPEC section 2), the fix is ownership: when the slot is the only owner, append in place. Both forms now run in about 25 ms. The indexed form d[k] += x was a separate code path and stayed quadratic after the first fix, so it took a second pass to catch. The measurement size was part of the test. At 24,000 pieces the s = s + x check passed green: 288 KB fits in L2 and quadratic copying looks cheap in cache. At 60,000 (720 KB) both went red. f-strings could not hold a quoted string inside an interpolation, although SPEC 9/3 said they could. f”{sys.read(“a.txt”)}” was a syntax error. The spec was right and the parser was wrong. A blank line in a CRLF file closed a block early. The lone \\r counted as content - the kind of bug that only shows up on someone else’s machine. Two C API bugs: rs_call could return an empty error message, and a nested rs_call corrupted the string channel of the outer primitive. The JVM bridge silently collapsed an int-returning host primitive to 0. Silent zeros are the worst class: the plugin keeps running and the numbers are simply wrong. 68 C API checks green, zero compiler warnings, sanitizer run clean. 29 keywords, still capped at 30. No C API signature changed. The branch split 227 commits had piled up unpushed and 216 of them were the Minecraft plugin demo. I reset main to origin, cherry-picked only the 13 language and tooling commits, and left the rest on its own branch. main is the language. Nothing else goes there. Most of the time logged on this project since the last devlog went into that plugin demo - the JVM binding exercised against a real server - and that branch is not on GitHub yet. The language fixes above came out of the unattended loop.I read every pass and hand-picked what entered main. The design, the spec and the original src/ are mine. Logged hours are my editor time only."}, {"post_id": 36295, "ts": "2026-07-28T09:44:35Z", "hours": 0.5578, "text": "Seven bugs, and the ones that were never reachable Last devlog promised a depth counter for the crash that hit all three hosts. I built it, then kept reading instead of building, and the audit found six more. THE COUNTER A script that recurses too deep does not raise an error. It kills the process. On a Minecraft server that means every player drops and the log has not one line about it - no Java exception, no hs_err file, exit code 127. The tempting fix is a bigger stack, but that only moves the wall: with -Xss16m the JVM dies at ~5000 frames instead of ~500, the same way. So the interpreter counts instead. Every script call goes through one function, and past the limit it raises an ordinary Error - catchable with try/catch, readable through rs_last_error. Picking the number mattered more than writing it. My notes said “4000”, my measurements said that was useless: native and wasm hit the wall near 1000 frames, a default JVM thread at ~500, because each script frame costs about 1.7 KB of native stack. A limit above the wall protects nobody. So: 800, and the JNI bridge drops it to 400 because it knows what stack it stands on. The counter also has to be restored no matter HOW a call exits - return, return signal, or exception. My restore lines covered two of those three paths; a destructor covers all three and cannot be forgotten. A CRASH ANY SCRIPT COULD TRIGGER \"a,b\".split(5) That was enough to kill the host. split assumed its argument was a string, dereferenced a checked cast without checking it, and got a null pointer. Eight builtins had the same line copied into them. In a standalone language that is a segfault. In an embedded one, any script author can take down the server with a typo. It is now a type error naming the method. OPERATORS THAT WERE NEVER REACHABLE The lexer produced tokens for & | ^ « ». The interpreter had the arithmetic for all five. Every test passed. But no rule in the parser ever read those tokens, so “flags & 4” got “expression expected, found ‘&’”, and the code in the other two layers had never once run. Three layers agreeing on a feature is not the same as three layers connected by it. The fix was four precedence levels, ordered like Python and C - no new keywords, so the language stays at 29 of 30. THE SMALL ONES throw Error(“amount missing”) reached the host as “”: the CLI path pulled out the message field, the embedding path did not. 2 ** 64 wrapped silently to 0. 1 « 64 was undefined behaviour - on x86 the CPU takes the shift count modulo 64, so it quietly evaluates to 1. And an exception thrown from a single-expression lambda left the interpreter in the lambda’s scope, so the catch block ran against the wrong variables. WHERE IT STANDS The C API suite is 20 checks now, five written for these bugs; the wasm suite 7; 11 examples still run; zero warnings. The guard is verified on native, wasm and JNI separately, and in each one the process was still alive after the limit was hit. Three problems stay open, in the README rather than hidden: an exception escaping a host function leaks stack, string += is quadratic, and a script returning a string to rs_call still yields 0. ON THE AI SPLIT This changes what I said last time, so I am saying it plainly. Until now AI had not touched src/. This round it did: I asked it to audit the interpreter and fix what it found, and the C++ in these seven fixes is AI-written from that audit. The language itself - lexer, parser, resolver, interpreter, REPL, C API, string channel - is still my design and was written by me. Host bindings and demo apps were already AI-written from my designs, as I said last devlog. Logged hours are my editor time only."}, {"post_id": 36104, "ts": "2026-07-27T23:51:06Z", "hours": 3.3964, "text": "One interpreter, three hosts Last devlog my language could define a weapon in my shipped game. Since then it left the browser too, and the way out taught me more than the way in. STRINGS WITHOUT LYING ABOUT NUMBERS The C boundary only carried doubles. That was a deliberate choice: a number is copied, so nobody has to ask who owns it. Then I tried to write a bank UI and stopped in the first ten minutes. An IBAN is text. An error message is text. The tempting fix is to pass a handle: “this double is really an index into a string table”. I did not do it. A contract like that is invisible, and the first time somebody misreads it the program moves the wrong money without a warning. So strings travel BESIDE the numbers instead of inside them. args[] did not change by a single byte, rs_host_fn kept its signature, and my already-shipped game’s bridge kept working untouched. Text is pulled by the script, not pushed by the host: script: iban = ui.input(\"iban\") host : reads the field name, returns the value THE 64 KILOBYTE FLOOR Then I asked whether the language could drive an animated web page, and measured instead of guessing. 490,000 host calls per second. 200 elements updated twice each = 1.45 ms, nine percent of a frame. Fine. What was not fine: recursion died at depth 130. Not with an error - with memory corruption. After it, the whole WebAssembly module was dead; I could not even open a fresh VM on it. Emscripten’s default stack is 64 KB, and a tree-walking interpreter spends several C++ frames per script frame. Adding -sSTACK_SIZE=8MB moved the safe depth past 1000 and turned overflow into a catchable error. Cost: the .wasm grew by three bytes. Then a worse one. If a host function throws, the exception unwinds through the interpreter’s frames without restoring the stack pointer, and that space never comes back. I measured the drift: 5,000 escaping exceptions took the safe depth from 1000 to 937. At 50,000 the module died. Fix: never let an exception cross the boundary - catch it in the bridge. THE THIRD HOST Then JNI, and the language went into a Minecraft server. Same C header, a different bridge, and the design copied deliberately: numbers in the array, strings in the channel beside it. The plugin is a custom enchanting table. Sixteen enchants, seven rarity tiers, slot limits per rarity, conflicts, an XP cost curve, and the block of text drawn on the item - all of it in one .rai file. The Java side is two classes that do not contain a single enchant name. Stats are written into the schema my existing combat plugin already reads, so enchants change real damage without one line changing in the plugins that were already there. Because there is no compile step, /rai reload changes the rules while players are online. A live server found a bug I had not: NamespacedKey only accepts [a-z0-9/._-] and my enchant ids are camelCase. The bridge’s catch turned what would have been a crash into a log line, and the log line named the key. THE SAME BUG THREE TIMES Native: depth 1000, then a silent death, exit code 127. WebAssembly: 130, then corruption. JVM: 500, then the whole server dies with no Java exception and no crash log. One cause - I recurse on the native stack and never count the depth. Three hosts made it obvious in a way one host never would have. That counter is next. ON THE AI SPLIT The core is mine: lexer, parser, resolver, interpreter, REPL, C API, the string channel. AI has not touched src/ and I checked the history before writing this. The host bindings and the demos are AI-written from my designs - the browser binding, the JNI bridge, and three demo apps. Logged hours are my editor time only."}, {"post_id": 35952, "ts": "2026-07-27T18:45:08Z", "hours": 2.4036, "text": "My language now defines a weapon in my shipped game Phase 1 gave RaidenScript a lexer, parser, resolver, interpreter and REPL. Today it got a design change of its own, and a way out of the terminal. TWO KEYWORDS, AND WHY THE FIRST VERSION WAS WEAK I had one keyword for pulling code in: use. I wanted hardware code to look different from application code, so I proposed include for boards and import for everything else. That rule was weak and I want to be honest about why. If include serial and import math do exactly the same thing, nothing stops anyone writing include math. A guide the compiler cannot check is not a guide, it is a convention with a syntax bill. So the difference moved onto something the compiler can enforce: import resolved at runtime: std library, a git repo, a pinned version include resolved when the host builds you in include now refuses quoted paths and @ “v0.3.1” version tags outright. On an ESP32 there is no filesystem and nothing to fetch, so a dependency needing the network at load time simply cannot be an include. Hardware and software separate as a side effect of a rule about resolution time — that is what earns two keywords instead of one. A file may use both, and that is the point: that is what a bridge looks like. 29 keywords now, hard-capped at 30 until v1.0. One slot left, and I would rather leave it empty than spend it on a synonym. A BUG ONLY TURKISH COULD PRODUCE Renaming use to import across 20 files, a bulk find-and-replace uppercased an i into U+0130 — the Turkish dotted capital, because in Turkish that is what the uppercase of i is. My editor did the case change in my own locale and handed C++ a character it cannot compile. The irony is sharp. RaidenScript deliberately accepts UTF-8 identifiers, so a Turkish variable name is legal in the language I am building. The language I am building it in has no such patience. OUT OF THE TERMINAL Then the embedding work: a C API, a WASM build, and one weapon. The C API was not the hard part. Lifetime was. Function values hold RAW pointers into the AST, and a host calls a script function long after loading it — so the VM has to own the source, the tree and the interpreter, and destroy them in the right order. One VM, one script; numbers across the boundary, not JSON. Then WASM aborted on the first return statement. Emscripten disables C++ exceptions by default, and this interpreter carries return, break and thrown errors on C++ exceptions. -fwasm-exceptions fixes it. The JS-based alternative would mean a trip to JavaScript on every single function return — unusable for a tree-walker. And the payoff: STAR BREAKER, the game I shipped last week, now has a weapon whose definition is not in the game. scripts/plazma.rai holds its damage, fire rate, spread and the shape of its shot. The engine calls fire(angle), the script calls back with game.spawnBullet, and the engine makes the bullets. The script only says where. Rarity, levels, reforges, evolution — all of it still works, untouched. The weapon is an ordinary table entry that happens to be filled from a language I wrote. I added a weapon rather than moving one: the game is shipped and its balance measured, so adding risks nothing. If the WASM fails to load, the weapon simply is not there. ON THE AI SPLIT The design is mine — the two keywords, the bridge pattern, the decision to add rather than move. I wrote the first pass of the rename; AI reviewed it, found what was missing, and wrote most of the embedding layer with me directing. That is more AI than my last devlog claimed, and I would rather correct it than let it stand. Repo (MIT): github.com/RaidenTechnology/raidenscript"}, {"post_id": 35673, "ts": "2026-07-27T08:35:48Z", "hours": 0.8014, "text": "I wrote a programming language. It runs. RaidenScript is an embeddable scripting language — the kind that goes inside another program and makes it programmable. It borrows readability from Python, the runtime model from JavaScript, optional types from C++, and declarative UI from HTML. Phase 1 is done: lexer, AST, parser, resolver, tree-walking interpreter, REPL. ~5,150 lines of C++20, zero warnings under -Wall -Wextra -Wpedantic -Wshadow -Wconversion. WHAT I DID FIRST WAS NOT WRITE CODE Phase 0 was pure design: a spec, a grammar, and 15 example programs — and no compiler at all. Writing those examples found 16 defects in the spec before a single line of the implementation existed. Two of them would have forced a rewrite later: Conditional expressions (a if cond else b) were missing from the grammar entirely — I typed one by reflex in example 4 and it couldn’t parse. => followed by { was genuinely ambiguous: block, or map literal? I took JavaScript’s answer — after =>, { is always a block, and returning a map needs ({…}). Finding this while writing the parser would have cost days. Then the parser found a third: my rule that brace-blocks suppress indentation was just wrong. It makes this impossible to write: register(\"hit\", (e) => { if e.critical: damage = damage * 2 }) Parentheses hold one expression; brace blocks hold statements, and statements need block structure. DECISIONS I’M HAPPY WITH Only nil and false are falsy. 0 and “” are truthy, which kills the classic if-count bug at the root. / always returns a float; // is integer division. C’s silent truncation is a bug factory. No package registry, ever. Modules resolve straight from a git repo, Go-style. I built the diagnostics engine before the lexer, because error messages bolted on afterwards always stay bolted on. Columns count UTF-8 characters, not bytes — so the caret lands correctly when a variable is named sayaç. Real output, Turkish for now (English messages are on the list): hata: beklenmeyen ‘!’ –> test.rai:3:7 | 3 | c = 5 ! 3 | ^ | = ipucu: olumsuzlama için ‘not’ kullan THE PART THAT MADE ME GRIN Example 15 is a calculator — a lexer, a Pratt parser and an evaluator, written in RaidenScript. I wrote it in Phase 0 as a rehearsal for the C++ I hadn’t written yet. Now it runs on the interpreter it was a rehearsal for: 2 ^ 3 ^ 2 gives 512, right-associative, not 64. The REPL I wrote by hand, and it immediately earned its keep by finding a bug nothing else could: Source::fromFile stripped the UTF-8 BOM, but the constructor didn’t. The REPL was the first code path to build a Source from an in-memory string instead of a file, so piped input carried a BOM into the lexer, which glued it onto the first identifier. A new entry point finds bugs no amount of staring finds. ON THE AI SPLIT The design is mine — spec, grammar, naming, and every decision above. Phases 0-6 of the implementation were written with AI assistance (Claude); the REPL, step 7, I wrote myself, and that is the mode from here on: I write the code, AI reviews it. WHAT’S NEXT Not phase 2. I’m skipping types and the bytecode VM and going straight to embedding — because a tree-walking interpreter is plenty fast for mod scripts, which run on events, not in the render loop. The goal: compile to WASM, bind a game.* API, and define one weapon in my published game STAR BREAKER using a language I wrote. A language nobody uses is a toy. A language shipping in a real product is not. Repo (MIT): github.com/RaidenTechnology/raidenscript"}]...
|
Title: RaidenScript by @RaidenTechnology | Stardan Title: RaidenScript by @RaidenTechnology | Stardance
Devlogs:
I wrote a programming language. It runs. RaidenScript is an embeddable scripting language — the kind that goes inside another program and makes it programmable. It borrows readability from Python, the runtime model from JavaScript, optional types from C++, and declarative UI from HTML. Phase 1 is done: lexer, AST, parser, resolver, tree-walking interpreter, REPL. ~5,150 lines of C++20, zero warnings under -Wall -Wextra -Wpedantic -Wshadow -Wconversion. WHAT I DID FIRST WAS NOT WRITE CODE Phase 0 was pure design: a spec, a grammar, and 15 example programs — and no compiler at all. Writing those examples found 16 defects in the spec before a single line of the implementation existed. Two of them would have forced a rewrite later: Conditional expressions (a if cond else b) were missing from the grammar entirely — I typed one by reflex in example 4 and it couldn’t parse. => followed by { was genuinely ambiguous: block, or map literal? I took JavaScript’s answer — after =>, { is always a block, and returning a map needs ({…}). Finding this while writing the parser would have cost days. Then the parser found a third: my rule that brace-blocks suppress indentation was just wrong. It makes this impossible to write: register("hit", (e) => { if e.critical: damage = damage * 2 }) Parentheses hold one expression; brace blocks hold statements, and statements need block structure. DECISIONS I’M HAPPY WITH Only nil and false are falsy. 0 and “” are truthy, which kills the classic if-count bug at the root. / always returns a float; // is integer division. C’s silent truncation is a bug factory. No package registry, ever. Modules resolve straight from a git repo, Go-style. I built the diagnostics engine before the lexer, because error messages bolted on afterwards always stay bolted on. Columns count UTF-8 characters, not bytes — so the caret lands correctly when a variable is named sayaç. Real output, Turkish for now (English messages are on the list): hata: beklenmeyen ‘!’ –> test.rai:3:7 | 3 | c = 5 ! 3 | ^ | = ipucu: olumsuzlama için ‘not’ kullan THE PART THAT MADE ME GRIN Example 15 is a calculator — a lexer, a Pratt parser and an evaluator, written in RaidenScript. I wrote it in Phase 0 as a rehearsal for the C++ I hadn’t written yet. Now it runs on the interpreter it was a rehearsal for: 2 ^ 3 ^ 2 gives 512, right-associative, not 64. The REPL I wrote by hand, and it immediately earned its keep by finding a bug nothing else could: Source::fromFile stripped the UTF-8 BOM, but the constructor didn’t. The REPL was the first code path to build a Source from an in-memory string instead of a file, so piped input carried a BOM into the lexer, which glued it onto the first identifier. A new entry point finds bugs no amount of staring finds. ON THE AI SPLIT The design is mine — spec, grammar, naming, and every decision above. Phases 0-6 of the implementation were written with AI assistance (Claude); the REPL, step 7, I wrote myself, and that is the mode from here on: I write the code, AI reviews it. WHAT’S NEXT Not phase 2. I’m skipping types and the bytecode VM and going straight to embedding — because a tree-walking interpreter is plenty fast for mod scripts, which run on events, not in the render loop. The goal: compile to WASM, bind a game.* API, and define one weapon in my published game STAR BREAKER using a language I wrote. A language nobody uses is a toy. A language shipping in a real product is not. Repo (MIT): github.com/RaidenTechnology/raidenscript
My language now defines a weapon in my shipped game Phase 1 gave RaidenScript a lexer, parser, resolver, interpreter and REPL. Today it got a design change of its own, and a way out of the terminal. TWO KEYWORDS, AND WHY THE FIRST VERSION WAS WEAK I had one keyword for pulling code in: use. I wanted hardware code to look different from application code, so I proposed include for boards and import for everything else. That rule was weak and I want to be honest about why. If include serial and import math do exactly the same thing, nothing stops anyone writing include math. A guide the compiler cannot check is not a guide, it is a convention with a syntax bill. So the difference moved onto something the compiler can enforce: import resolved at runtime: std library, a git repo, a pinned version include resolved when the host builds you in include now refuses quoted paths and @ “v0.3.1” version tags outright. On an ESP32 there is no filesystem and nothing to fetch, so a dependency needing the network at load time simply cannot be an include. Hardware and software separate as a side effect of a rule about resolution time — that is what earns two keywords instead of one. A file may use both, and that is the point: that is what a bridge looks like. 29 keywords now, hard-capped at 30 until v1.0. One slot left, and I would rather leave it empty than spend it on a synonym. A BUG ONLY TURKISH COULD PRODUCE Renaming use to import across 20 files, a bulk find-and-replace uppercased an i into U+0130 — the Turkish dotted capital, because in Turkish that is what the uppercase of i is. My editor did the case change in my own locale and handed C++ a character it cannot compile. The irony is sharp. RaidenScript deliberately accepts UTF-8 identifiers, so a Turkish variable name is legal in the language I am building. The language I am building it in has no such patience. OUT OF THE TERMINAL Then the embedding work: a C API, a WASM build, and one weapon. The C API was not the hard part. Lifetime was. Function values hold RAW pointers into the AST, and a host calls a script function long after loading it — so the VM has to own the source, the tree and the interpreter, and destroy them in the right order. One VM, one script; numbers across the boundary, not JSON. Then WASM aborted on the first return statement. Emscripten disables C++ exceptions by default, and this interpreter carries return, break and thrown errors on C++ exceptions. -fwasm-exceptions fixes it. The JS-based alternative would mean a trip to JavaScript on every single function return — unusable for a tree-walker. And the payoff: STAR BREAKER, the game I shipped last week, now has a weapon whose definition is not in the game. scripts/plazma.rai holds its damage, fire rate, spread and the shape of its shot. The engine calls fire(angle), the script calls back with game.spawnBullet, and the engine makes the bullets. The script only says where. Rarity, levels, reforges, evolution — all of it still works, untouched. The weapon is an ordinary table entry that happens to be filled from a language I wrote. I added a weapon rather than moving one: the game is shipped and its balance measured, so adding risks nothing. If the WASM fails to load, the weapon simply is not there. ON THE AI SPLIT The design is mine — the two keywords, the bridge pattern, the decision to add rather than move. I wrote the first pass of the rename; AI reviewed it, found what was missing, and wrote most of the embedding layer with me directing. That is more AI than my last devlog claimed, and I would rather correct it than let it stand. Repo (MIT): github.com/RaidenTechnology/raidenscript
One interpreter, three hosts Last devlog my language could define a weapon in my shipped game. Since then it left the browser too, and the way out taught me more than the way in. STRINGS WITHOUT LYING ABOUT NUMBERS The C boundary only carried doubles. That was a deliberate choice: a number is copied, so nobody has to ask who owns it. Then I tried to write a bank UI and stopped in the first ten minutes. An IBAN is text. An error message is text. The tempting fix is to pass a handle: “this double is really an index into a string table”. I did not do it. A contract like that is invisible, and the first time somebody misreads it the program moves the wrong money without a warning. So strings travel BESIDE the numbers instead of inside them. args[] did not change by a single byte, rs_host_fn kept its signature, and my already-shipped game’s bridge kept working untouched. Text is pulled by the script, not pushed by the host: script: iban = ui.input("iban") host : reads the field name, returns the value THE 64 KILOBYTE FLOOR Then I asked whether the language could drive an animated web page, and measured instead of guessing. 490,000 host calls per second. 200 elements updated twice each = 1.45 ms, nine percent of a frame. Fine. What was not fine: recursion died at depth 130. Not with an error - with memory corruption. After it, the whole WebAssembly module was dead; I could not even open a fresh VM on it. Emscripten’s default stack is 64 KB, and a tree-walking interpreter spends several C++ frames per script frame. Adding -sSTACK_SIZE=8MB moved the safe depth past 1000 and turned overflow into a catchable error. Cost: the .wasm grew by three bytes. Then a worse one. If a host function throws, the exception unwinds through the interpreter’s frames without restoring the stack pointer, and that space never comes back. I measured the drift: 5,000 escaping exceptions took the safe depth from 1000 to 937. At 50,000 the module died. Fix: never let an exception cross the boundary - catch it in the bridge. THE THIRD HOST Then JNI, and the language went into a Minecraft server. Same C header, a different bridge, and the design copied deliberately: numbers in the array, strings in the channel beside it. The plugin is a custom enchanting table. Sixteen enchants, seven rarity tiers, slot limits per rarity, conflicts, an XP cost curve, and the block of text drawn on the item - all of it in one .rai file. The Java side is two classes that do not contain a single enchant name. Stats are written into the schema my existing combat plugin already reads, so enchants change real damage without one line changing in the plugins that were already there. Because there is no compile step, /rai reload changes the rules while players are online. A live server found a bug I had not: NamespacedKey only accepts [a-z0-9/._-] and my enchant ids are camelCase. The bridge’s catch turned what would have been a crash into a log line, and the log line named the key. THE SAME BUG THREE TIMES Native: depth 1000, then a silent death, exit code 127. WebAssembly: 130, then corruption. JVM: 500, then the whole server dies with no Java exception and no crash log. One cause - I recurse on the native stack and never count the depth. Three hosts made it obvious in a way one host never would have. That counter is next. ON THE AI SPLIT The core is mine: lexer, parser, resolver, interpreter, REPL, C API, the string channel. AI has not touched src/ and I checked the history before writing this. The host bindings and the demos are AI-written from my designs - the browser binding, the JNI bridge, and three demo apps. Logged hours are my editor time only.
Seven bugs, and the ones that were never reachable Last devlog promised a depth counter for the crash that hit all three hosts. I built it, then kept reading instead of building, and the audit found six more. THE COUNTER A script that recurses too deep does not raise an error. It kills the process. On a Minecraft server that means every player drops and the log has not one line about it - no Java exception, no hs_err file, exit code 127. The tempting fix is a bigger stack, but that only moves the wall: with -Xss16m the JVM dies at ~5000 frames instead of ~500, the same way. So the interpreter counts instead. Every script call goes through one function, and past the limit it raises an ordinary Error - catchable with try/catch, readable through rs_last_error. Picking the number mattered more than writing it. My notes said “4000”, my measurements said that was useless: native and wasm hit the wall near 1000 frames, a default JVM thread at ~500, because each script frame costs about 1.7 KB of native stack. A limit above the wall protects nobody. So: 800, and the JNI bridge drops it to 400 because it knows what stack it stands on. The counter also has to be restored no matter HOW a call exits - return, return signal, or exception. My restore lines covered two of those three paths; a destructor covers all three and cannot be forgotten. A CRASH ANY SCRIPT COULD TRIGGER "a,b".split(5) That was enough to kill the host. split assumed its argument was a string, dereferenced a checked cast without checking it, and got a null pointer. Eight builtins had the same line copied into them. In a standalone language that is a segfault. In an embedded one, any script author can take down the server with a typo. It is now a type error naming the method. OPERATORS THAT WERE NEVER REACHABLE The lexer produced tokens for & | ^ « ». The interpreter had the arithmetic for all five. Every test passed. But no rule in the parser ever read those tokens, so “flags & 4” got “expression expected, found ‘&’”, and the code in the other two layers had never once run. Three layers agreeing on a feature is not the same as three layers connected by it. The fix was four precedence levels, ordered like Python and C - no new keywords, so the language stays at 29 of 30. THE SMALL ONES throw Error(“amount missing”) reached the host as “”: the CLI path pulled out the message field, the embedding path did not. 2 ** 64 wrapped silently to 0. 1 « 64 was undefined behaviour - on x86 the CPU takes the shift count modulo 64, so it quietly evaluates to 1. And an exception thrown from a single-expression lambda left the interpreter in the lambda’s scope, so the catch block ran against the wrong variables. WHERE IT STANDS The C API suite is 20 checks now, five written for these bugs; the wasm suite 7; 11 examples still run; zero warnings. The guard is verified on native, wasm and JNI separately, and in each one the process was still alive after the limit was hit. Three problems stay open, in the README rather than hidden: an exception escaping a host function leaks stack, string += is quadratic, and a script returning a string to rs_call still yields 0. ON THE AI SPLIT This changes what I said last time, so I am saying it plainly. Until now AI had not touched src/. This round it did: I asked it to audit the interpreter and fix what it found, and the C++ in these seven fixes is AI-written from that audit. The language itself - lexer, parser, resolver, interpreter, REPL, C API, string channel - is still my design and was written by me. Host bindings and demo apps were already AI-written from my designs, as I said last devlog. Logged hours are my editor time only.
The loop that fixes the language is written in the language Since the last devlog the work split in two: a development loop that RaidenScript now drives itself, and a repository that finally stopped mixing the language with a game server. selfdev - the decision logic is a .rai file tools/selfdev.rai holds the loop’s rules: pick an area nobody touched last round, run the build, read the log, call the pass green or red, append its own entry to a round journal. Under it sits tools/rsdev.cpp, a sys.* host built on the same C API the browser game and the Minecraft plugin already use. The language had three hosts. The fourth one is its own toolchain. Pass 2 taught it what not to trust. tools/selfdev-build.cmd reported EXIT=0 for a run that failed to link. The cause is not in the language at all: exit /b inside a ( … ) » log 2>&1 block does not end a .cmd script, so control falls through to the final exit /b 0. A loop whose whole contract is “exit 0 means green” can commit on red - and it did once, on stale .o files. The rule now is read the log, not the exit code, and it is written in capitals at the top of SELFDEV-NOTES.md because I expect to forget it. What the passes actually fixed String building was quadratic. At 60,000 pieces: s += x took 1879 ms, s = s + x took 2382 ms, against a list.push + join baseline of 54 ms - 35x and 44x. Strings stay immutable (SPEC section 2), the fix is ownership: when the slot is the only owner, append in place. Both forms now run in about 25 ms. The indexed form d[k] += x was a separate code path and stayed quadratic after the first fix, so it took a second pass to catch. The measurement size was part of the test. At 24,000 pieces the s = s + x check passed green: 288 KB fits in L2 and quadratic copying looks cheap in cache. At 60,000 (720 KB) both went red. f-strings could not hold a quoted string inside an interpolation, although SPEC 9/3 said they could. f”{sys.read(“a.txt”)}” was a syntax error. The spec was right and the parser was wrong. A blank line in a CRLF file closed a block early. The lone \r counted as content - the kind of bug that only shows up on someone else’s machine. Two C API bugs: rs_call could return an empty error message, and a nested rs_call corrupted the string channel of the outer primitive. The JVM bridge silently collapsed an int-returning host primitive to 0. Silent zeros are the worst class: the plugin keeps running and the numbers are simply wrong. 68 C API checks green, zero compiler warnings, sanitizer run clean. 29 keywords, still capped at 30. No C API signature changed. The branch split 227 commits had piled up unpushed and 216 of them were the Minecraft plugin demo. I reset main to origin, cherry-picked only the 13 language and tooling commits, and left the rest on its own branch. main is the language. Nothing else goes there. Most of the time logged on this project since the last devlog went into that plugin demo - the JVM binding exercised against a real server - and that branch is not on GitHub yet. The language fixes above came out of the unattended loop.I read every pass and hand-picked what entered main. The design, the spec and the original src/ are mine. Logged hours are my editor time only.
RaidenScript: the cover is a program, not a picture I gave the project a red and black cover, and I did it without opening an image editor. The cover generator is a RaidenScript program that prints a plain PPM to stdout, so I changed the palette in the script and ran it again: three radial glows, a faint grid, a vertical gradient on the bolt, and a 5x7 bitmap font that is data inside the file, not a system font. It computes 315,000 pixels in 43 seconds. That is my tree-walking interpreter doing arithmetic in a while loop, with no graphics library in the program and none in the language. My first render was wrong and I had to say so. The old cover put a turquoise bolt on a violet field, so the contrast came from hue. In red on red there is no hue left to lean on, and the bolt sank into the background. I cut the background glow to a third and pushed the bolt to a near-white core, so the contrast now comes from brightness. I cleaned the repository behind it. My README still linked to SPEC.md and WORKLOG.md after I deleted them, so anyone cloning it hit two dead links on the front page. I removed those links and rewrote the root README and two demo READMEs without tables. Why did I do it like this? Because a cover drawn in an image editor says nothing about my language, and a cover computed by it is the smallest honest benchmark I own. If the language cannot fill 315,000 pixels, I want to know that before someone else finds out. Because 43 seconds is a real number and I am not hiding it. It is fine for a cover I render once, and it is exactly why a bytecode VM sits on my roadmap instead of being marked done. Because a README that points at files I deleted is a promise I broke to whoever clones the repo, and that is the first thing a reviewer sees.
Ships:
RaidenScript v0.1 — an embeddable scripting language written from scratch in C++20. WHAT IT IS A small language (29 keywords) with Python’s readability and JavaScript’s runtime model, built to go inside another program and make it scriptable. The same interpreter runs in three hosts, and each one has a working demo in the repo: Terminal — native binary, “rai program.rai”, plus a REPL Browser — C API compiled to WebAssembly, running an animated store page JVM — C API through JNI, running a Paper Minecraft plugin The demo link is my shipped game STAR BREAKER: one of its weapons is not defined in the game at all, it is a RaidenScript file the game loads and runs through the WebAssembly build. WHAT IS IN IT Lexer, parser, resolver, tree-walking interpreter and REPL, all hand-written; no parser generator, no dependencies. 16 example programs that double as the regression suite, 20 C API checks, 7 WebAssembly checks, zero compiler warnings. A recursion-depth guard so a runaway script raises a catchable error instead of killing the host process — verified separately on native, wasm and the JVM. The cover image was computed pixel by pixel by a RaidenScript program (demo/kapak/kapak-ascii.rai) — no graphics library, in the program or in the language. HOW TO TRY IT git clone, then “make” (w64devkit/MinGW on Windows, gcc elsewhere), then “rai examples/01-temeller.rai”, or just “rai” for the REPL. The README is a full manual: language guide, standard library, embedding walkthrough. Known limits are written down there rather than hidden: an exception escaping a host function leaks stack, string += is quadratic, and a script returning a string to rs_call still yields 0. AI SPLIT The design of the language and its core — lexer, parser, resolver, interpreter, REPL, C API, string channel — is mine and was written by me. The host bindings, the demo apps, and this week’s seven interpreter bug fixes are AI-written from my designs and my audit. Logged hours are my editor time only. Source (MIT): github.com/RaidenTechnology/raidenscript
RaidenScript v0.2 Update I wrote RaidenScript (RS) from scratch in C++20 as a small embeddable scripting language. In Ship #1 I had it running in three hosts. Since then I gave it a browser you can try it in, and I turned the Minecraft host into a real game running on a live server. I put the language in a browser. I compiled the C API to WebAssembly, served it from GitHub Pages, and wrote an editor with a Run button and four example programs: raidentechnology.github.io/raidenscript. I send nothing to a server; the page is the interpreter. I stopped treating the Minecraft host as a demo. I wrote 144 commits on it since the last devlog, and I keep the rules out of Java entirely: they sit in one .rai file the server loads at boot and reloads while players are online. I wrote a whole farming layer as script rules. Every crop got its own tool with its own level and rarity ladder, and I added tool enchants, XP bottles, an upgrade bench, and a 20 minute contest with medals and a shop of its own. I added pests. Twelve species, a spawn engine I tied to whatever crop is planted, a five-tier vacuum to kill them with, and a loot table I hooked into the same farming-luck stat every other system reads. I built a garden around it: 8 plots, a regeneration engine that rebuilds 13 farm patterns, 76 visitor NPCs I gave 53 signed skins, and a copper economy I priced off the live Bazaar API instead of numbers I made up. I added one host primitive, taslakModel, and let the script choose the model an item wears. Adding an item is now a script edit and nothing else. I fixed three bugs the live server found and no test of mine would have. An item-identity gate was cancelling every right click unconditionally, so the grappling hook silently never fired. The area hoe was catching its own synthetic event and moving the stack twice. And one wrong price in a shop table was failing the entire script at boot. Why did I do it like this? Because I think a language is judged by what runs on it, not by its grammar. The strongest thing I can say about my embedding API is that a 10,000 line ruleset runs on it every night, on a real server, with real players. Because I lose reviewers at the install wall. For Ship #1 I asked people to clone a repo and build it with MinGW. Now I ask for one click, and I am handing them the same interpreter, not a simplified twin. Because every rule I move out of Java is a rule I can change without a restart. I left no compile step in the script layer, so /rai reload changes the balance of a live game between two swings of a sword. Because item models were the last thing still forcing me into Java. I closed that hole, and I now keep the Java side as infrastructure only: it knows how to talk to the server and nothing about what the game is. Because I wanted the contest, the pests and the visitor queue to stress the C boundary. I pass numbers in the array and let strings travel beside it, and not one of these systems made me widen that contract. Because a bug a player hits at 2 AM is worth more to me than a bug I find in my own suite. All three above came from the server. Source (MIT): github.com/RaidenTechnology/raidenscript...
|
1793825279.8564167
|
1793911679.8564167
|
|
37680
|
My first slack bot! by @isaachktdm | Stardance
|
isaachktdm
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @isaachktdm | Starda Title: My first slack bot! by @isaachktdm | Stardance...
|
1793306875.9726372
|
1793911675.9726372
|
|
22108
|
3D car made in blender by @hunterrossiter | Starda 3D car made in blender by @hunterrossiter | Stardance...
|
hunterrossiter
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: 3D car made in blender by @hunterrossiter | Title: 3D car made in blender by @hunterrossiter | Stardance...
|
1793306873.8725417
|
1793911673.8725417
|
|
49572
|
Nexus AI – Customer Support Agent by @Mohanaryan | Nexus AI – Customer Support Agent by @Mohanaryan | Stardance...
|
Mohanaryan
|
1
|
1.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-18T13:17:47Z", "hours": 1.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "NexusAI is an AI-powered customer support assistant built with Python and Streamlit. It uses semantic search with Sentence Transformers and cosine similarity to retrieve relevant answers from a customer-support knowledge base. The app provides real-time customer responses, retrieval confidence scoring, BLEU-based response evaluation, chat history, and CSV report export. I built and tested the project locally, focusing on making the interface simple and easy to use while learning more about semantic retrieval, NLP evaluation, and Streamlit. Tech: Python • Streamlit • Sentence Transformers • scikit-learn • NLTK • Pandas", "repo": "https://github.com/mohithkumar3413/nexus-ai-customer-support-agent", "demo": "https://youtu.be/lDnPkIN7MbI?si=RyjuZfs4S9Td45cu"}]...
|
[{"post_id": 49558, "ts": "202 [{"post_id": 49558, "ts": "2026-08-18T13:11:05Z", "hours": 0.4603, "text": "Today I continued working on NexusAI, my AI-powered customer support project.I focused on getting the Streamlit application running properly on my Mac and testing the main customer-support flow. I successfully launched the app locally and tested the knowledge-base retrieval with different customer queries.I also checked the interface and made sure the chat, confidence score, BLEU evaluation, and CSV export features are working together.Next, I want to continue testing the responses and improve the overall user experience.#AI #Python #Streamlit #CustomerSupport #BuildInPublic"}, {"post_id": 48849, "ts": "2026-08-17T12:18:15Z", "hours": 0.3442, "text": "Today I continued working on my Nexus AI Customer Support Agent. I connected the project with Hackatime and spent time testing the project locally in VS Code. I also checked the session handling and existing Clear Conversation feature and made sure the application was running properly.This was a useful session because I got more familiar with tracking development time and working with an existing AI project. I’m planning to continue improving the user experience and adding more useful features."}]...
|
Title: Nexus AI – Customer Support Agent by @Mohan Title: Nexus AI – Customer Support Agent by @Mohanaryan | Stardance
Devlogs:
Today I continued working on my Nexus AI Customer Support Agent. I connected the project with Hackatime and spent time testing the project locally in VS Code. I also checked the session handling and existing Clear Conversation feature and made sure the application was running properly.This was a useful session because I got more familiar with tracking development time and working with an existing AI project. I’m planning to continue improving the user experience and adding more useful features.
Today I continued working on NexusAI, my AI-powered customer support project.I focused on getting the Streamlit application running properly on my Mac and testing the main customer-support flow. I successfully launched the app locally and tested the knowledge-base retrieval with different customer queries.I also checked the interface and made sure the chat, confidence score, BLEU evaluation, and CSV export features are working together.Next, I want to continue testing the responses and improve the overall user experience.#AI #Python #Streamlit #CustomerSupport #BuildInPublic
Ships:
NexusAI is an AI-powered customer support assistant built with Python and Streamlit. It uses semantic search with Sentence Transformers and cosine similarity to retrieve relevant answers from a customer-support knowledge base. The app provides real-time customer responses, retrieval confidence scoring, BLEU-based response evaluation, chat history, and CSV report export. I built and tested the project locally, focusing on making the interface simple and easy to use while learning more about semantic retrieval, NLP evaluation, and Streamlit. Tech: Python • Streamlit • Sentence Transformers • scikit-learn • NLTK • Pandas...
|
1793825273.5708873
|
1793911673.5708873
|
|
40528
|
Untitled by @Sammy_gurram | Stardance
|
Sammy_gurram
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Untitled by @Sammy_gurram | Stardance
|
1793306872.9398615
|
1793911672.9398615
|
|
1952
|
FirstGame by @Rachel | Stardance
|
Rachel
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: FirstGame by @Rachel | Stardance
|
1793306872.015701
|
1793911672.015701
|
|
24222
|
My very own WebOS by @elaowl10 | Stardance
|
elaowl10
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My very own WebOS by @elaowl10 | Stardance
|
1793306869.7624311
|
1793911669.7624311
|
|
13094
|
My awesome macropad! by @jemimah | Stardance
|
jemimah
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @jemimah | Stardanc Title: My awesome macropad! by @jemimah | Stardance...
|
1793306868.7453618
|
1793911668.7453618
|
|
31819
|
CentauriLink by @dewandeljack | Stardance
|
dewandeljack
|
1
|
1.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-29T10:50:09Z", "hours": 1.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "It is an remote and local app to access your own 3D printer from elegoo (supports: CC1) the ETA time system was not easy to fix after a bug. Also the app optimizing was a big thing to do.", "repo": "https://github.com/CentauriLink/RemoteAccess", "demo": "https://play.google.com/store/apps/details?id=com.centaurilink.centaurilink"}]...
|
[{"post_id": 35896, "ts": "202 [{"post_id": 35896, "ts": "2026-07-27T16:59:14Z", "hours": 0.5483, "text": "I have updated and added new functions to the app"}]...
|
Title: CentauriLink by @dewandeljack | Stardance
Title: CentauriLink by @dewandeljack | Stardance
Devlogs:
I have updated and added new functions to the app
Ships:
It is an remote and local app to access your own 3D printer from elegoo (supports: CC1) the ETA time system was not easy to fix after a bug. Also the app optimizing was a big thing to do....
|
1793825268.1208034
|
1793911668.1208034
|
|
12488
|
coding by @j18lin | Stardance
|
j18lin
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: coding by @j18lin | Stardance
|
1793306866.5761604
|
1793911666.5761604
|
|
12615
|
Vocodio by @Achotna | Stardance
|
Achotna
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Vocodio by @Achotna | Stardance
|
1793306865.700751
|
1793911665.700751
|
|
18818
|
My first slack bot! by @hansi93 | Stardance
|
hansi93
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @hansi93 | Stardance
|
1793306863.5593126
|
1793911663.5593126
|
|
23874
|
My awesome macropad! by @Izabellab | Stardance
|
Izabellab
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @Izabellab | Starda Title: My awesome macropad! by @Izabellab | Stardance...
|
1793306862.6423335
|
1793911662.6423335
|
|
21535
|
Oliver the desk pall by @isa_emaman | Stardance
|
isa_emaman
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: Oliver the desk pall by @isa_emaman | Stard Title: Oliver the desk pall by @isa_emaman | Stardance...
|
1793306861.7482734
|
1793911661.7482734
|
|
39634
|
My own site! by @rush | Stardance
|
rush
|
1
|
2.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-05T12:21:05Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made my first ever website as a beginner at coding!", "repo": "https://github.com/integrusabusiness/MyWebsite", "demo": "https://integrusabusiness.github.io/MyWebsite/#home"}]...
|
[{"post_id": 41263, "ts": "202 [{"post_id": 41263, "ts": "2026-08-05T11:32:26Z", "hours": 0.7192, "text": "Added colours and more content to my website!"}, {"post_id": 40995, "ts": "2026-08-04T21:26:01Z", "hours": 0.6617, "text": "Today, I worked on making my personal website better and started writing “About me”!"}, {"post_id": 40336, "ts": "2026-08-03T19:35:49Z", "hours": 0.5147, "text": "Today I made my nav bar!"}]...
|
Title: My own site! by @rush | Stardance
Devlogs: Title: My own site! by @rush | Stardance
Devlogs:
Today I made my nav bar!
Today, I worked on making my personal website better and started writing “About me”!
Added colours and more content to my website!
Ships:
I made my first ever website as a beginner at coding!...
|
1793825260.8471894
|
1793911660.8471894
|
|
5695
|
My first slack bot! by @PlayerOne | Stardance
|
PlayerOne
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My first slack bot! by @PlayerOne | Stardan Title: My first slack bot! by @PlayerOne | Stardance...
|
1793306860.8428388
|
1793911660.8428388
|
|
15732
|
My awesome macropad! by @fatima_26 | Stardance
|
fatima_26
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: My awesome macropad! by @fatima_26 | Starda Title: My awesome macropad! by @fatima_26 | Stardance...
|
1793306858.631486
|
1793911658.631486
|