|
58746
|
Creating a program for floriography ciphered messa Creating a program for floriography ciphered messages by @Mj1536 | Stardance...
|
Mj1536
|
1
|
31.28
|
156
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-29T23:04:42Z", "hours": 31.0, "multiplier": 5.12, "payout": 156, "blessing": "neutral", "text": "A project on the C language to decipher and create floriography messages This is a project written with the C language to decipher and create florigraphy messages. Nowadays, living among teenagers, it has become relatively common to notice people struggling to express themselves, especially about their feelings. The project came as a way to introduce people to floriography and provide another way, more indirect, to express themselves and their feelings with this beautiful cipher.", "repo": "https://github.com/Mj1536/A-project-to-decipher-and-create-floriography-messages", "demo": "https://floriografia.dino.icu/"}]...
|
[{"post_id": 75415, "ts": "202 [{"post_id": 75415, "ts": "2026-09-30T01:06:29Z", "hours": 0.2772, "text": "It is also available on OnlineGDB https://onlinegdb.com/v-gqiS9SV"}, {"post_id": 75368, "ts": "2026-09-29T21:10:28Z", "hours": 5.1086, "text": "Finished. Finished making the second part, allowing to get flowers for a specific meaning, debugging it, and correcting grammar."}, {"post_id": 74778, "ts": "2026-09-28T06:59:49Z", "hours": 2.1333, "text": "Doing some grammar correction and organization"}, {"post_id": 74748, "ts": "2026-09-28T04:12:38Z", "hours": 0.7333, "text": "Finishing debbuging"}, {"post_id": 74735, "ts": "2026-09-28T02:55:15Z", "hours": 1.1, "text": "Finishing adding the meanings"}, {"post_id": 74711, "ts": "2026-09-28T01:25:44Z", "hours": 4.8667, "text": "Adding the meanings! Unfortunately, I had to remove the combinations due to copyright laws"}, {"post_id": 72447, "ts": "2026-09-23T00:01:05Z", "hours": 5.3667, "text": "Finishing making the flower combinations and fixing some smaller problems"}, {"post_id": 72049, "ts": "2026-09-22T02:15:48Z", "hours": 1.6333, "text": "Continuing the flower combination system"}, {"post_id": 71038, "ts": "2026-09-20T07:29:19Z", "hours": 3.8, "text": "Two new flowers, and preparation for combination of flowers creating new meanings"}, {"post_id": 70942, "ts": "2026-09-20T02:38:55Z", "hours": 2.2333, "text": "Changed the if for switch for better performance and organization"}, {"post_id": 70902, "ts": "2026-09-20T00:03:30Z", "hours": 1.1, "text": "Organizing and making some changes on the code"}, {"post_id": 70882, "ts": "2026-09-19T22:52:58Z", "hours": 0.7, "text": "Finished adding flowers for now"}, {"post_id": 70869, "ts": "2026-09-19T22:03:36Z", "hours": 1.0019, "text": "Just adding some flowers"}, {"post_id": 68860, "ts": "2026-09-15T21:53:12Z", "hours": 0.7381, "text": "A first draft"}]...
|
Title: Creating a program for floriography ciphere Title: Creating a program for floriography ciphered messages by @Mj1536 | Stardance
Devlogs:
A first draft
Just adding some flowers
Finished adding flowers for now
Organizing and making some changes on the code
Changed the if for switch for better performance and organization
Two new flowers, and preparation for combination of flowers creating new meanings
Continuing the flower combination system
Finishing making the flower combinations and fixing some smaller problems
Adding the meanings! Unfortunately, I had to remove the combinations due to copyright laws
Finishing adding the meanings
Finishing debbuging
Doing some grammar correction and organization
Finished. Finished making the second part, allowing to get flowers for a specific meaning, debugging it, and correcting grammar.
It is also available on OnlineGDB https://onlinegdb.com/v-gqiS9SV
Ships:
A project on the C language to decipher and create floriography messages This is a project written with the C language to decipher and create florigraphy messages. Nowadays, living among teenagers, it has become relatively common to notice people struggling to express themselves, especially about their feelings. The project came as a way to introduce people to floriography and provide another way, more indirect, to express themselves and their feelings with this beautiful cipher....
|
1793008115.040829
|
1793094515.040829
|
|
58749
|
VulpeculaOS by @AuraMonster | Stardance
|
AuraMonster
|
1
|
23.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-21T21:42:54Z", "hours": 23.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made VulpeculaOS, a desktop app that is an OS but has a creepy twist to it. It is actually a horror game! (Of course, I am not going to spoil it for you, so it is up to figure it out!). Also, explore a lot and be patient, since this is meant to be 20 minutes long.", "repo": "https://github.com/mdmutahhar24-pixel/VulpeculaOS", "demo": "https://github.com/mdmutahhar24-pixel/VulpeculaOS/releases"}]...
|
[{"post_id": 71969, "ts": "202 [{"post_id": 71969, "ts": "2026-09-21T21:40:38Z", "hours": 1.7475, "text": "Seventh and Final Devlog for VulpeculaOS What is VulpeculaOS Really? VulpeculaOS is an OS that is actually a horror game. And no, this is not the webOS mission, since it is a desktop app. There will be several anomalies that the user goes through. If the user attempts to ask Vulp about it, Vulp is supposed to respond in a weird way. New Features: Debugged some stuff Added Vulp Text-To-Speech Updated some Horror events to actually give out vibes Ship will be coming soon!"}, {"post_id": 71453, "ts": "2026-09-20T21:11:48Z", "hours": 2.3394, "text": "Sixth Devlog for VulpeculaOS New Features: OS now has a start up Screen! [REDACTED] Happiness system was finished Calculator finished Browser Finished Vulp ? Finished Scrapped: Settings EXPECT NEXT DEVLOG TO BE FINAL **ERROR: VULP is slowly being taken over by… static ** NOTE: the truth about this OS will be revealed… in the next devlog and the ship."}, {"post_id": 69967, "ts": "2026-09-18T04:24:16Z", "hours": 6.5525, "text": "Fifth Devlog for VulpeculaOS New Features: SFX for UI In Progress: [REDACTED] happiness events Vulp Reactions Easter Eggs Smth idk Browser Planned Features (Subject to Change): More apps to store Settings Calculator Content Vulp is acting pretty strange today…"}, {"post_id": 65498, "ts": "2026-09-10T17:59:32Z", "hours": 5.0594, "text": "Fourth Devlog for VulpeculaOS New Features: You can now Maximize and Minimize windows OS System Error: AI: VULP has gained access to app window control In Progress: Store Browser [REDACTED] Happiness level Revamp of current OS Planned Features: Settings More apps in the store Actually being able to open a webpage inside of VulpeculaOS. (* static *) Too late to turn back"}, {"post_id": 63913, "ts": "2026-09-07T23:04:25Z", "hours": 2.1544, "text": "Third Devlog For VelpeculaOS New Features: Notes App completed Terminal, Files, and Notes are now all completely intertwined Command Menu added OS SYSTEM BREACH: VULP HAS GAINED THE ABILITY OF SPEECH Work in Progress: Vulp being able to Warn modify files Planned Features (Subject to change): [Redacted] level Settings You open Vulpecula OS again…Vulp has something to tell you. You were shocked by the next words Vulp said."}, {"post_id": 63750, "ts": "2026-09-07T18:23:12Z", "hours": 2.7758, "text": "Second Devlog for Vulpecula OS New Features: Terminal Complete Added a filesystem to keep track of you of your files Added Local Date In Progress: Notes Feature Vulp, your personal {REDACTED} assistant Planned Features (Subject to change): {REDACTED} level Command (like the windows button) As you keep exploring the OS, you notice something off… It’s nothing right?"}, {"post_id": 63120, "ts": "2026-09-06T19:03:19Z", "hours": 2.0158, "text": "Vulpecula OS First Devlog What is VulpeculaOS? Vulpecula OS is a [REDACTED] totally Normal OS on a Desktop App. Users are put through [REDACTED] normal OS stuff. New Features: Added Windows Added Time Added Background Future Features (Subject to Change): Your personal [REDACTED] Vulp Assistant Command [REDACTED] level More… OS System Error: He is already after you. It is too late, you know too much - Vulp"}]...
|
Title: VulpeculaOS by @AuraMonster | Stardance
De Title: VulpeculaOS by @AuraMonster | Stardance
Devlogs:
Vulpecula OS First Devlog What is VulpeculaOS? Vulpecula OS is a [REDACTED] totally Normal OS on a Desktop App. Users are put through [REDACTED] normal OS stuff. New Features: Added Windows Added Time Added Background Future Features (Subject to Change): Your personal [REDACTED] Vulp Assistant Command [REDACTED] level More… OS System Error: He is already after you. It is too late, you know too much - Vulp
Second Devlog for Vulpecula OS New Features: Terminal Complete Added a filesystem to keep track of you of your files Added Local Date In Progress: Notes Feature Vulp, your personal {REDACTED} assistant Planned Features (Subject to change): {REDACTED} level Command (like the windows button) As you keep exploring the OS, you notice something off… It’s nothing right?
Third Devlog For VelpeculaOS New Features: Notes App completed Terminal, Files, and Notes are now all completely intertwined Command Menu added OS SYSTEM BREACH: VULP HAS GAINED THE ABILITY OF SPEECH Work in Progress: Vulp being able to Warn modify files Planned Features (Subject to change): [Redacted] level Settings You open Vulpecula OS again…Vulp has something to tell you. You were shocked by the next words Vulp said.
Fourth Devlog for VulpeculaOS New Features: You can now Maximize and Minimize windows OS System Error: AI: VULP has gained access to app window control In Progress: Store Browser [REDACTED] Happiness level Revamp of current OS Planned Features: Settings More apps in the store Actually being able to open a webpage inside of VulpeculaOS. (* static *) Too late to turn back
Fifth Devlog for VulpeculaOS New Features: SFX for UI In Progress: [REDACTED] happiness events Vulp Reactions Easter Eggs Smth idk Browser Planned Features (Subject to Change): More apps to store Settings Calculator Content Vulp is acting pretty strange today…
Sixth Devlog for VulpeculaOS New Features: OS now has a start up Screen! [REDACTED] Happiness system was finished Calculator finished Browser Finished Vulp ? Finished Scrapped: Settings EXPECT NEXT DEVLOG TO BE FINAL **ERROR: VULP is slowly being taken over by… static ** NOTE: the truth about this OS will be revealed… in the next devlog and the ship.
Seventh and Final Devlog for VulpeculaOS What is VulpeculaOS Really? VulpeculaOS is an OS that is actually a horror game. And no, this is not the webOS mission, since it is a desktop app. There will be several anomalies that the user goes through. If the user attempts to ask Vulp about it, Vulp is supposed to respond in a weird way. New Features: Debugged some stuff Added Vulp Text-To-Speech Updated some Horror events to actually give out vibes Ship will be coming soon!
Ships:
I made VulpeculaOS, a desktop app that is an OS but has a creepy twist to it. It is actually a horror game! (Of course, I am not going to spoil it for you, so it is up to figure it out!). Also, explore a lot and be patient, since this is meant to be 20 minutes long....
|
1793008116.2340612
|
1793094516.2340612
|
|
53856
|
My very own WebOS by @mandeepswami | Stardance
|
mandeepswami
|
1
|
8.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-16T09:40:58Z", "hours": 8.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "This is my webOS named GalacticOS. It is my first project that i have ever built thanks to hackclub. I got stuck many times but finally it is finished", "repo": "https://github.com/Momentum122/glowing-broccoli", "demo": "https://momentum122.github.io/glowing-broccoli/code.html"}]...
|
[{"post_id": 64367, "ts": "202 [{"post_id": 64367, "ts": "2026-09-08T17:51:47Z", "hours": 3.1786, "text": "Completed web OS 1 . Go Check it out https://momentum122.github.io/glowing-broccoli/code.html"}, {"post_id": 59144, "ts": "2026-08-31T19:27:39Z", "hours": 0.9689, "text": "Completed part -3 of the guide looks good now and i am understanding some stuff n"}, {"post_id": 58027, "ts": "2026-08-30T11:31:09Z", "hours": 1.2381, "text": "It’s getting hard i cant understand stuff"}, {"post_id": 55611, "ts": "2026-08-27T16:01:15Z", "hours": 1.1794, "text": "Added a good background and a time"}, {"post_id": 54385, "ts": "2026-08-25T11:32:23Z", "hours": 1.1119, "text": "Begging of something good.Build my First own OS and also my first Project on html."}]...
|
Title: My very own WebOS by @mandeepswami | Starda Title: My very own WebOS by @mandeepswami | Stardance
Devlogs:
Begging of something good.Build my First own OS and also my first Project on html.
Added a good background and a time
It’s getting hard i cant understand stuff
Completed part -3 of the guide looks good now and i am understanding some stuff n
Completed web OS 1 . Go Check it out https://momentum122.github.io/glowing-broccoli/code.html
Ships:
This is my webOS named GalacticOS. It is my first project that i have ever built thanks to hackclub. I got stuck many times but finally it is finished...
|
1793008117.3522577
|
1793094517.3522577
|
|
53860
|
Epic MP3 Player by @Amanojaku | Stardance
|
Amanojaku
|
1
|
12.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-28T02:22:26Z", "hours": 12.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "It uses the dac pin to play audio instead of an actual audio module. Also whenever you plug in earbuds the voltage drops and the program resets which is cool. Its also really quiet and it’s way too big. My CAD is all messed up and nothing fits correctly. Anything but using a pcb", "repo": "https://github.com/zxcvbnmzxcvbnmzxcv/mymp3player", "demo": ""}]...
|
[{"post_id": 74719, "ts": "202 [{"post_id": 74719, "ts": "2026-09-28T02:07:29Z", "hours": 3.1833, "text": "Added the menu and a random song feature"}, {"post_id": 66991, "ts": "2026-09-13T00:18:34Z", "hours": 0.9667, "text": "I think it’s too small for an mp3 player I tried really hard to make it as big as I could but now it’s just too portable. Also I didn’t have any buttons so im just gonna use a potentiometer instead."}, {"post_id": 66315, "ts": "2026-09-12T02:30:49Z", "hours": 1.2489, "text": "I like food that is fun to eat. I’d rather eat pasta than noodles because it’s in a nicer shape. I’d rather eat the toblerone chocolate triangular prisms than a cube of chocolate. Cereal is fun to eat. Rice is fun to eat. Hardshell tacos are funner to eat. Cheese in the shape of little circles is more fun to eat."}, {"post_id": 65731, "ts": "2026-09-11T02:14:04Z", "hours": 0.8281, "text": "The pencil is a part of the structural integrity"}, {"post_id": 65119, "ts": "2026-09-10T01:11:20Z", "hours": 4.0808, "text": "3D modeled the case with ports"}, {"post_id": 57732, "ts": "2026-08-30T00:09:59Z", "hours": 0.9, "text": "Adding lcd and battery pack. Bumping the Banjo Kazooie soundtrack in 16-bit audio just like reggie intended"}, {"post_id": 56323, "ts": "2026-08-28T01:47:39Z", "hours": 0.5417, "text": "I need to wire the screen and buttons"}]...
|
Title: Epic MP3 Player by @Amanojaku | Stardance
Title: Epic MP3 Player by @Amanojaku | Stardance
Devlogs:
I need to wire the screen and buttons
Adding lcd and battery pack. Bumping the Banjo Kazooie soundtrack in 16-bit audio just like reggie intended
3D modeled the case with ports
The pencil is a part of the structural integrity
I like food that is fun to eat. I’d rather eat pasta than noodles because it’s in a nicer shape. I’d rather eat the toblerone chocolate triangular prisms than a cube of chocolate. Cereal is fun to eat. Rice is fun to eat. Hardshell tacos are funner to eat. Cheese in the shape of little circles is more fun to eat.
I think it’s too small for an mp3 player I tried really hard to make it as big as I could but now it’s just too portable. Also I didn’t have any buttons so im just gonna use a potentiometer instead.
Added the menu and a random song feature
Ships:
It uses the dac pin to play audio instead of an actual audio module. Also whenever you plug in earbuds the voltage drops and the program resets which is cool. Its also really quiet and it’s way too big. My CAD is all messed up and nothing fits correctly. Anything but using a pcb...
|
1793008118.4770267
|
1793094518.4770267
|
|
53873
|
MafiaParty by @casmin7 | Stardance
|
casmin7
|
2
|
15.29
|
92
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-21T20:34:43Z", "hours": 2.0, "multiplier": 13.54, "payout": 22, "blessing": "neutral", "text": "Hi there! MafiaParty: Last ship of the project? After polishing up the app a bit, I am content with it I have seen a comment about translations which seems feasible and actually a cool feature, will look into it! I was also thinking custom roles with priorities and badges and stuff But we’ll see! Thank you all for the support on the last ship! MafiaParty: Short Summery PWA with local caching, save-state and fun stuff like http3/quic A tool meant to aid in big games of Mafia made during summer camp as to solve that exact issue Battle tested up to 27 players lol What’s new this ship: Swipe to reveal IS MUCH BETTER Fixed some blue highlights on android(maybe IOS too but I can’t test) Added an option to reset the game when a win condition is triggered Sometimes when removing a card by clicking the x it would trigger the card animation and shrink it causing you to miss the x. Now fixed Added icons now to all the action buttons", "repo": "https://github.com/casmin7/MafiaParty", "demo": "https://mafia.casmin.eu"}, {"ship_num": 2, "ts": "2026-09-14T15:54:19Z", "hours": 13.0, "multiplier": 5.33, "payout": 70, "blessing": "neutral", "text": "Mafia Party: A helping hand for mafia games What it is: A small site/app (PWA) that facilitates when playing big games of the party game Mafia (Werewolf). Say you have 8 players, 2 killers, 1 medic, 1 detective, remembering what each did at night is quite easy for a storyteller who is experienced. But say that others join too since it seems fun. Great! Now you have 16 players… what now? That’s why I made this! It has been battled tested up to 28 players and the way it was coded theoretically allows for any combo of players and roles. Do you want 30 players, 10 doctors and one killer? Sure Do you want 120 players, 15 of each role, 10 kills per round and multiple eliminations at day? Sure Do whatever you want, do whatever your players need! What it isn’t: It isn’t a full game. It’s merely a tool to be used by a moderator instead of a piece of paper or remembering each action at night. You still need people to play with, a space to play and a deck of cards to give out roles Gameplay Management Dynamic Role Support: Works with any player count or role combo without pre-configuration. Built-in Role Library: Out-of-the-box support for Detective, Doctor/Medic, Cupid, Escort, Mutilator, and traditional Mafia/Villagers. State Tracking: Tracks live player counts, day/night cycles, contextual actions, and win conditions automatically. User Experience & Privacy Peeking Prevention: Draggable role cards reveal secret info only while active, preventing nearby players from seeing the moderator’s screen. Dynamic Players: Cards can be reordered when in the setup phase to prepare for a new game if players move around the room Adaptive Navigation: Contextual nav bar updates available actions based on the current phase of the game. Technical Performance Offline PWA Support: Service worker caching allows full offline usability in low-reception game areas. Persistent Game State: Automatically saves all game data locally so no progress is lost on page refreshes. Try it now at: mafia.casmin.eu", "repo": "https://github.com/casmin7/MafiaParty", "demo": "https://mafia.casmin.eu"}]...
|
[{"post_id": 72233, "ts": "202 [{"post_id": 72233, "ts": "2026-09-22T14:26:17Z", "hours": 0.2925, "text": "MafiaParty: fixParty? Fixed an issue with card dragging on android Now it actually works sorry xd It’s not pretty but works"}, {"post_id": 71824, "ts": "2026-09-21T16:46:49Z", "hours": 0.4075, "text": "Hey there I made another polishing update MafiaParty: Now polish (🇵🇱) Added icons to all the buttons that we’re missing Swipe-to-reveal no longer snaps open, making it harder to accidentally reveal a role to someone Added a new setting to reset the game upon win, you will still get a confirmation prompt"}, {"post_id": 71463, "ts": "2026-09-20T21:27:16Z", "hours": 1.2228, "text": "Hello there! First devlog after shipping whoa! Thank you all for checking it out Here’s what I improved: The X button will no longer trigger card animations making you miss it Reworked role reveal, now you drag the card to reveal so it no longer makes you accidentally trigger the vote confirmation and is generally nicer to use Removed tap highlight color so buttons look nicer on mobile(on my phone at least) A small update (took a while) but a nice qol update See you all soon!"}, {"post_id": 68105, "ts": "2026-09-14T14:57:34Z", "hours": 1.5928, "text": "MafiaParty: Now COMPLETE! What it is: A small site/app(PWA) that facilitates when playing big games of the party game Mafia (Werewolf) What it isn’t: Not a game, a tool. It does not replace the need of a storyteller or cards. Ohh boy this one was a big one, one final push before I call it good. I am happy in the state it is right now, finished up the last of the suggestions I had gotten while playing games using it (eg. player count) and I can say I am happy with it and I will soon also publish it ### What’s new: How the switches look Checkboxed save state upon reload Back button now works way better and will not mess up more that it fixes Card events (voting players, selecting targets) was cleaned up Cards can now be focused and interacted using tab Added optional settings Added night & day counter Added player count with total and alive players"}, {"post_id": 62081, "ts": "2026-09-05T10:17:40Z", "hours": 1.0728, "text": "MafiaParty: Now PWA! What it is: A small site/app(PWA) that facilitates when playing big games of the party game Mafia (Werewolf) What it isn’t: Not a game, a tool. It does not replace the need of a storyteller or cards. New with this update Added a manifest so now the app can be installed Service worker for offline support Favicons!!! (spent way to long on this) Renamed the site to be more inline with the github (MafiaHelper -> MafiaParty) Made nicer overlays scrollbars and added fixed gutters"}, {"post_id": 59100, "ts": "2026-08-31T18:38:49Z", "hours": 0.4144, "text": "Added some aria labels, fixed some issues and now site gets 100% on lighthouse! This does not mean it’s perfect but for me it’s a cool thing to brag about :)"}, {"post_id": 58780, "ts": "2026-08-31T11:03:47Z", "hours": 1.9997, "text": "MafiaHelper, updated look and better usability What it is: A small site/app(soon I hope, PWA) that facilitates when playing big games of the party game Mafia (Werewolf) What it isn’t: Not a game, a tool. It does not replace the need of a storyteller or cards. Battle tested, it was able to handle two games of 27 players! With multiple killers, doctors, detectives and other roles, we were able to handle two VERRRY long games of mafia without issues caused by the app. It wasn’t perfect, but it did showcase what the app is capable off and just how easy it is for the storyteller when using this tool. Since the last devlog I made it look much nicer on desktop and mobile by adding fixed bottom controls and better consistent cards. Players can now be deleted making usability much nicer since they also get saved, so starting a game with mostly the same players is easier."}, {"post_id": 55556, "ts": "2026-08-27T14:17:23Z", "hours": 3.315, "text": "Added saving and loading and redid all of the night roles checks to be easier to manage and change plus delete all button and individual delete"}, {"post_id": 53997, "ts": "2026-08-24T18:43:02Z", "hours": 4.7222, "text": "hihi, I made this during summer camp (and I still am there lol) to be used to help me moderate large games of mafia Mafia is an irl game similar to Among Us with roles and actions at night, and voting during the day This is not a full mafia app and is meant to only help the moderator not remember what happened every night since with many players IT GETS VERY HARD My experience hosting a game of mafia for 22 people without this was horrendous Try it out now at: https://mafia.casmin.eu More soon!"}]...
|
Title: MafiaParty by @casmin7 | Stardance
Devlogs Title: MafiaParty by @casmin7 | Stardance
Devlogs:
hihi, I made this during summer camp (and I still am there lol) to be used to help me moderate large games of mafia Mafia is an irl game similar to Among Us with roles and actions at night, and voting during the day This is not a full mafia app and is meant to only help the moderator not remember what happened every night since with many players IT GETS VERY HARD My experience hosting a game of mafia for 22 people without this was horrendous Try it out now at: https://mafia.casmin.eu More soon!
Added saving and loading and redid all of the night roles checks to be easier to manage and change plus delete all button and individual delete
MafiaHelper, updated look and better usability What it is: A small site/app(soon I hope, PWA) that facilitates when playing big games of the party game Mafia (Werewolf) What it isn’t: Not a game, a tool. It does not replace the need of a storyteller or cards. Battle tested, it was able to handle two games of 27 players! With multiple killers, doctors, detectives and other roles, we were able to handle two VERRRY long games of mafia without issues caused by the app. It wasn’t perfect, but it did showcase what the app is capable off and just how easy it is for the storyteller when using this tool. Since the last devlog I made it look much nicer on desktop and mobile by adding fixed bottom controls and better consistent cards. Players can now be deleted making usability much nicer since they also get saved, so starting a game with mostly the same players is easier.
Added some aria labels, fixed some issues and now site gets 100% on lighthouse! This does not mean it’s perfect but for me it’s a cool thing to brag about :)
MafiaParty: Now PWA! What it is: A small site/app(PWA) that facilitates when playing big games of the party game Mafia (Werewolf) What it isn’t: Not a game, a tool. It does not replace the need of a storyteller or cards. New with this update Added a manifest so now the app can be installed Service worker for offline support Favicons!!! (spent way to long on this) Renamed the site to be more inline with the github (MafiaHelper -> MafiaParty) Made nicer overlays scrollbars and added fixed gutters
MafiaParty: Now COMPLETE! What it is: A small site/app(PWA) that facilitates when playing big games of the party game Mafia (Werewolf) What it isn’t: Not a game, a tool. It does not replace the need of a storyteller or cards. Ohh boy this one was a big one, one final push before I call it good. I am happy in the state it is right now, finished up the last of the suggestions I had gotten while playing games using it (eg. player count) and I can say I am happy with it and I will soon also publish it ### What’s new: How the switches look Checkboxed save state upon reload Back button now works way better and will not mess up more that it fixes Card events (voting players, selecting targets) was cleaned up Cards can now be focused and interacted using tab Added optional settings Added night & day counter Added player count with total and alive players
Hello there! First devlog after shipping whoa! Thank you all for checking it out Here’s what I improved: The X button will no longer trigger card animations making you miss it Reworked role reveal, now you drag the card to reveal so it no longer makes you accidentally trigger the vote confirmation and is generally nicer to use Removed tap highlight color so buttons look nicer on mobile(on my phone at least) A small update (took a while) but a nice qol update See you all soon!
Hey there I made another polishing update MafiaParty: Now polish (🇵🇱) Added icons to all the buttons that we’re missing Swipe-to-reveal no longer snaps open, making it harder to accidentally reveal a role to someone Added a new setting to reset the game upon win, you will still get a confirmation prompt
MafiaParty: fixParty? Fixed an issue with card dragging on android Now it actually works sorry xd It’s not pretty but works
Ships:
Mafia Party: A helping hand for mafia games What it is: A small site/app (PWA) that facilitates when playing big games of the party game Mafia (Werewolf). Say you have 8 players, 2 killers, 1 medic, 1 detective, remembering what each did at night is quite easy for a storyteller who is experienced. But say that others join too since it seems fun. Great! Now you have 16 players… what now? That’s why I made this! It has been battled tested up to 28 players and the way it was coded theoretically allows for any combo of players and roles. Do you want 30 players, 10 doctors and one killer? Sure Do you want 120 players, 15 of each role, 10 kills per round and multiple eliminations at day? Sure Do whatever you want, do whatever your players need! What it isn’t: It isn’t a full game. It’s merely a tool to be used by a moderator instead of a piece of paper or remembering each action at night. You still need people to play with, a space to play and a deck of cards to give out roles Gameplay Management Dynamic Role Support: Works with any player count or role combo without pre-configuration. Built-in Role Library: Out-of-the-box support for Detective, Doctor/Medic, Cupid, Escort, Mutilator, and traditional Mafia/Villagers. State Tracking: Tracks live player counts, day/night cycles, contextual actions, and win conditions automatically. User Experience & Privacy Peeking Prevention: Draggable role cards reveal secret info only while active, preventing nearby players from seeing the moderator’s screen. Dynamic Players: Cards can be reordered when in the setup phase to prepare for a new game if players move around the room Adaptive Navigation: Contextual nav bar updates available actions based on the current phase of the game. Technical Performance Offline PWA Support: Service worker caching allows full offline usability in low-reception game areas. Persistent Game State: Automatically saves all game data locally so no progress is lost on page refreshes. Try it now at: mafia.casmin.eu
Hi there! MafiaParty: Last ship of the project? After polishing up the app a bit, I am content with it I have seen a comment about translations which seems feasible and actually a cool feature, will look into it! I was also thinking custom roles with priorities and badges and stuff But we’ll see! Thank you all for the support on the last ship! MafiaParty: Short Summery PWA with local caching, save-state and fun stuff like http3/quic A tool meant to aid in big games of Mafia made during summer camp as to solve that exact issue Battle tested up to 27 players lol What’s new this ship: Swipe to reveal IS MUCH BETTER Fixed some blue highlights on android(maybe IOS too but I can’t test) Added an option to reset the game when a win condition is triggered Sometimes when removing a card by clicking the x it would trigger the card animation and shrink it causing you to miss the x. Now fixed Added icons now to all the action buttons...
|
1793008119.3794603
|
1793094519.3794603
|
|
53878
|
Kiko(Focusing app) by @Davonys | Stardance
|
Davonys
|
1
|
23.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-05T19:35:49Z", "hours": 23.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Kiko is a productivity web application designed to help you stay focused. You can create both one-time and recurring tasks to manage your schedule. To keep you company, Kiko features an interactive character that works, studies, and relaxes with you. Stay motivated by competing on the leaderboard—but be careful! If you miss a deadline, your virtual garden will begin to wither.", "repo": "https://github.com/davitkhlghatyan2010-afk/Kiko", "demo": "https://kiko-frontend-eta.vercel.app/"}]...
|
[{"post_id": 77143, "ts": "202 [{"post_id": 77143, "ts": "2026-10-05T19:32:00Z", "hours": 3.2706, "text": "So, I fixed some mechanics and added interactivity!"}, {"post_id": 57324, "ts": "2026-08-29T13:17:17Z", "hours": 5.7256, "text": "I have already finished website and now I will work mostly on documentatin!1"}, {"post_id": 54702, "ts": "2026-08-25T19:31:46Z", "hours": 14.4011, "text": "I have done design and documentation(PRD)!!!"}]...
|
Title: Kiko(Focusing app) by @Davonys | Stardance
Title: Kiko(Focusing app) by @Davonys | Stardance
Devlogs:
I have done design and documentation(PRD)!!!
I have already finished website and now I will work mostly on documentatin!1
So, I fixed some mechanics and added interactivity!
Ships:
Kiko is a productivity web application designed to help you stay focused. You can create both one-time and recurring tasks to manage your schedule. To keep you company, Kiko features an interactive character that works, studies, and relaxes with you. Stay motivated by competing on the leaderboard—but be careful! If you miss a deadline, your virtual garden will begin to wither....
|
1793008120.3496406
|
1793094520.3496406
|
|
53888
|
Personal Website by @vanshikagera | Stardance
|
vanshikagera
|
1
|
2.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-15T13:31:21Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a personal website using HTML and CSS and tried to keep the design simple but still make it feel like my own. The hardest part was getting the layout, spacing and different sections to look right. I’m most proud of how the website came together and how I managed to make it look clean. People can test it by opening the deployed website and clicking through the different sections.", "repo": "https://github.com/Vanshika-Gera/personal-website", "demo": "https://vanshika-gera.github.io/personal-website/"}]...
|
[{"post_id": 68630, "ts": "202 [{"post_id": 68630, "ts": "2026-09-15T13:02:10Z", "hours": 0.8169, "text": "Just completed my personal website. This is how it’s looking :)."}, {"post_id": 65871, "ts": "2026-09-11T09:40:19Z", "hours": 1.2172, "text": "first draft of my personal website! I used vs code for this :D"}]...
|
Title: Personal Website by @vanshikagera | Stardan Title: Personal Website by @vanshikagera | Stardance
Devlogs:
first draft of my personal website! I used vs code for this :D
Just completed my personal website. This is how it’s looking :).
Ships:
I made a personal website using HTML and CSS and tried to keep the design simple but still make it feel like my own. The hardest part was getting the layout, spacing and different sections to look right. I’m most proud of how the website came together and how I managed to make it look clean. People can test it by opening the deployed website and clicking through the different sections....
|
1793008121.2163723
|
1793094521.2163723
|
|
53894
|
What's It Worth by @capyblaze | Stardance
|
capyblaze
|
1
|
8.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-29T09:59:04Z", "hours": 8.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "What did you make? A mini web game where you have to guess the price of random Amazon products and get as close as you can What was challenging? Finding the data and cleaning it up to keep only the good info What are you proud of? That it saves your score in local storage so even if you close the page, you don’t lose your progress What should people know so they can test your project? Just head to the site and start playing", "repo": "https://github.com/CapyBlaze/What-is-It-Worth", "demo": "https://capyblaze.github.io/What-is-It-Worth/"}]...
|
[{"post_id": 75152, "ts": "202 [{"post_id": 75152, "ts": "2026-09-29T09:43:05Z", "hours": 7.57, "text": "Hey everyone, just wanted to make a quick little game. It’s super simple: the app shows a random Amazon product and you gotta guess the price. The closer you get, the more points you score.The whole game was built in this devlog (fetching Amazon data, sorting it, and coding the site)"}]...
|
Title: What's It Worth by @capyblaze | Stardan Title: What's It Worth by @capyblaze | Stardance
Devlogs:
Hey everyone, just wanted to make a quick little game. It’s super simple: the app shows a random Amazon product and you gotta guess the price. The closer you get, the more points you score.The whole game was built in this devlog (fetching Amazon data, sorting it, and coding the site)
Ships:
What did you make? A mini web game where you have to guess the price of random Amazon products and get as close as you can What was challenging? Finding the data and cleaning it up to keep only the good info What are you proud of? That it saves your score in local storage so even if you close the page, you don’t lose your progress What should people know so they can test your project? Just head to the site and start playing...
|
1793008122.1188462
|
1793094522.1188462
|
|
32423
|
Hackpad for GD by @Jacube1234 | Stardance
|
Jacube1234
|
1
|
8.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-27T10:07:23Z", "hours": 8.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "What did I make? I made the GD Hackpad—a custom 4-key macro pad with a rotary encoder designed specifically for playing Geometry Dash Platformer levels (basically a DIY Sayo Device). It features a 3-piece 3D-printed angled case designed in Fusion 360, a custom PCB featuring a skull silkscreen created in KiCad, and is powered by a Seeed XIAO RP2040 running KMK firmware. What was challenging? Learning KiCad from scratch since I was originally much more comfortable with Fusion 360. Learning the stardance process and this general hackclub stuff. What are you proud of? How well the 3D-printed case fits together using M3 bolts and heat-set inserts, adding a custom skull emoji silkscreen to the PCB, and getting everything running smoothly with 100% tested code. What should people know so they can test your project? Everything you need to replicate it is in the repository, including the 3D print production files, Gerber files for ordering the PCB, the BOM, and a full guide on setting up CircuitPython and KMK firmware. Note: The photos of my physical build ldon’t have the RGB LEDs due to an early board error, but the updated KiCad and Gerber files in the repo feature the corrected LED routing!", "repo": "https://github.com/Jacube1234/GD-Hackpad", "demo": ""}]...
|
[{"post_id": 74394, "ts": "202 [{"post_id": 74394, "ts": "2026-09-27T09:56:29Z", "hours": 0.3356, "text": "Fixed up some other small readme stuff. I changed the kicanvas link, and added the yt video I posted in the last log. I’m only allowed one demo video so I changed it to me actually using the hackpad. The other link is https://youtu.be/eFOGvQzMtF8 if you want to see me explaining the project. I will hopefully promise to myself to not make anymore changes and just finish the project. Ima ship it. idk how this works. bye now."}, {"post_id": 73482, "ts": "2026-09-25T06:53:54Z", "hours": 0.5617, "text": "Realised I used the wrong footprint for the leds. SO I abandoned them :/ I fixed the kicad files and updated the gerbers, in different respective folders. https://youtu.be/FZbB-Cm0QQ0 video of me playing a level"}, {"post_id": 64086, "ts": "2026-09-08T08:15:43Z", "hours": 4.5919, "text": "Finally finished (I guess). I redesigned the case because I made some silly errors. In reality, my pcb sat lower than my CAD model so I fixed that. CAD model also used surface mounted SEEED XIAO RP2040 so there was a height change. Moved the port down twice. No longer silly circles on the lid because I made the top part way to thin in the first place. My knob was too tall so I sanded it down (I just wanted to get this project done 🫠) You can check my soldering process and stuff here if you really want. Idk how these images will order themselves but here are what they are. Me putting in a heatset insert (so satifying) the top plate underside with a notch for the rotary encoder weird bit Assembled thing Me playing GD Slicer Random completion photos"}, {"post_id": 54331, "ts": "2026-08-25T09:09:18Z", "hours": 2.5036, "text": "Got my parts. Quick fit and sanity check. Did I make my top plate to thin? I will look at the Orphues pad real quick. Please tell me if you get any info about normal heights or something."}, {"post_id": 26808, "ts": "2026-07-11T20:17:59Z", "hours": 0.6908, "text": "Added little bump at the top so a heatset insert can fit because the top shell is not thick enough. Added Gerber files."}, {"post_id": 26286, "ts": "2026-07-11T00:09:51Z", "hours": 1.9836, "text": "Added all 3d models to Kicad, and exported it into Fusion. (idk why gif is so cooked). Flipped the microcontroller so the usb port wasn’t inside the plate. Moved usb outlet on base to match the new location. Comment what I should do to let the led’s to shine through"}, {"post_id": 26219, "ts": "2026-07-10T21:40:34Z", "hours": 0.6361, "text": "Adding 3d models to Kicad"}, {"post_id": 25624, "ts": "2026-07-10T00:46:38Z", "hours": 1.3475, "text": "Added rotary knob. Made silkscreen art smaller"}, {"post_id": 25222, "ts": "2026-07-09T10:41:48Z", "hours": 1.0642, "text": "Sorted Github files and realised my LED’s were the wrong way lol"}, {"post_id": 25054, "ts": "2026-07-09T00:33:07Z", "hours": 2.0003, "text": "Built the case. Added a bunch of fillets and a chamfer to edges. Hole at the back for the USB port. About to code it and make the Github Repo. (This will probbaly take me ages because the tutorial doesn’t show how to program it)"}, {"post_id": 24632, "ts": "2026-07-08T11:02:27Z", "hours": 2.8, "text": "Building the case. Tutorial kinda sucks though so I am referencing qcoral’s “Orpheuspad” fusion model."}, {"post_id": 24546, "ts": "2026-07-08T05:22:14Z", "hours": 2.0336, "text": "Looked at qcorals 3d model to look at the pcb. Started connecting components together."}, {"post_id": 24504, "ts": "2026-07-08T03:02:46Z", "hours": 1.6833, "text": "Placing keys in the arrow key layout. about to wire them up. Also trying to add rgb lighting"}]...
|
Title: Hackpad for GD by @Jacube1234 | Stardance
Title: Hackpad for GD by @Jacube1234 | Stardance
Devlogs:
Placing keys in the arrow key layout. about to wire them up. Also trying to add rgb lighting
Looked at qcorals 3d model to look at the pcb. Started connecting components together.
Building the case. Tutorial kinda sucks though so I am referencing qcoral’s “Orpheuspad” fusion model.
Built the case. Added a bunch of fillets and a chamfer to edges. Hole at the back for the USB port. About to code it and make the Github Repo. (This will probbaly take me ages because the tutorial doesn’t show how to program it)
Sorted Github files and realised my LED’s were the wrong way lol
Added rotary knob. Made silkscreen art smaller
Adding 3d models to Kicad
Added all 3d models to Kicad, and exported it into Fusion. (idk why gif is so cooked). Flipped the microcontroller so the usb port wasn’t inside the plate. Moved usb outlet on base to match the new location. Comment what I should do to let the led’s to shine through
Added little bump at the top so a heatset insert can fit because the top shell is not thick enough. Added Gerber files.
Got my parts. Quick fit and sanity check. Did I make my top plate to thin? I will look at the Orphues pad real quick. Please tell me if you get any info about normal heights or something.
Finally finished (I guess). I redesigned the case because I made some silly errors. In reality, my pcb sat lower than my CAD model so I fixed that. CAD model also used surface mounted SEEED XIAO RP2040 so there was a height change. Moved the port down twice. No longer silly circles on the lid because I made the top part way to thin in the first place. My knob was too tall so I sanded it down (I just wanted to get this project done 🫠) You can check my soldering process and stuff here if you really want. Idk how these images will order themselves but here are what they are. Me putting in a heatset insert (so satifying) the top plate underside with a notch for the rotary encoder weird bit Assembled thing Me playing GD Slicer Random completion photos
Realised I used the wrong footprint for the leds. SO I abandoned them :/ I fixed the kicad files and updated the gerbers, in different respective folders. https://youtu.be/FZbB-Cm0QQ0 video of me playing a level
Fixed up some other small readme stuff. I changed the kicanvas link, and added the yt video I posted in the last log. I’m only allowed one demo video so I changed it to me actually using the hackpad. The other link is https://youtu.be/eFOGvQzMtF8 if you want to see me explaining the project. I will hopefully promise to myself to not make anymore changes and just finish the project. Ima ship it. idk how this works. bye now.
Ships:
What did I make? I made the GD Hackpad—a custom 4-key macro pad with a rotary encoder designed specifically for playing Geometry Dash Platformer levels (basically a DIY Sayo Device). It features a 3-piece 3D-printed angled case designed in Fusion 360, a custom PCB featuring a skull silkscreen created in KiCad, and is powered by a Seeed XIAO RP2040 running KMK firmware. What was challenging? Learning KiCad from scratch since I was originally much more comfortable with Fusion 360. Learning the stardance process and this general hackclub stuff. What are you proud of? How well the 3D-printed case fits together using M3 bolts and heat-set inserts, adding a custom skull emoji silkscreen to the PCB, and getting everything running smoothly with 100% tested code. What should people know so they can test your project? Everything you need to replicate it is in the repository, including the 3D print production files, Gerber files for ordering the PCB, the BOM, and a full guide on setting up CircuitPython and KMK firmware. Note: The photos of my physical build ldon’t have the RGB LEDs due to an early board error, but the updated KiCad and Gerber files in the repo feature the corrected LED routing!...
|
1793008122.977116
|
1793094522.977116
|
|
7165
|
Eve by @Light | Stardance
|
Light
|
1
|
294.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-20T20:53:22Z", "hours": 294.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Eve is a graphics engine written entirely in Vulkan , with the primary goal of learning Vulkan and C++ while simplifying their usage. Originally conceived as a simple, lightweight wrapper around Vulkan , Eve now includes: A Render Graph designed from scratch that leverages technologies such as memory aliasing (where multiple resources share the same memory space) and resource pooling (reusing resources across frames). It performs the core function of a Render Graph: by simply knowing how resources are utilized, it automatically issues the necessary synchronization barriers to the GPU. Developing the Render Graph was a grueling process, but it proved worthwhile in terms of both performance and the educational value of the experience. An ECS (Entity Component System) also designed from scratch, following the model of Unity’s DOTS ECS . Instead of scattering resources across VRAM—which slows down access due to constant memory jumps—game objects are organized into Archetypes. Components are distributed in contiguous memory batches, thereby minimizing cache misses. A rendering system that automates the insertion of transforms into buffers; these are subsequently processed into matrices via a compute shader and sent to the rendering shaders. It also features a material system that analyzes shader composition, looking for a struct named “Properties” that allows fields to be assigned by name from the C++ side. Support for the Slang shading language with a bindless system . Eve provides a file named Eve.slangh that simplifies and automates the retrieval of textures, buffers, and samplers from descriptors. Compute shader support is also included. An integrated, easy-to-use Input system inspired by Unity’s Input System , along with a lightweight UI wrapper that makes using Dear ImGui simpler and more intuitive. Eve also includes a demo featuring a gravitational simulation of thousands of entities orbiting a black hole, allowing various parameters to be adjusted in real-time.", "repo": "https://github.com/SonoUnBot09/Eve", "demo": "https://github.com/SonoUnBot09/Eve/releases/tag/v1.0.0"}]...
|
[{"post_id": 71422, "ts": "202 [{"post_id": 71422, "ts": "2026-09-20T19:52:09Z", "hours": 8.8461, "text": "DEVLOG 36 - Black Hole! Hi Stardance! Intro I’ve been working really hard lately, and I think I’ve reached a milestone with Eve that I honestly never expected to hit. The project is finally complete; now I just need to click that nice button to ship it. I’ve spent this time working on the README, improving the documentation, fixing bugs, and building a demo using Eve. Eve Demo The demo is a gravity simulation featuring hundreds of thousands of entities orbiting a black hole. You can tweak various parameters—such as time, the black hole’s gravitational pull, lighting, colors, meshes, and much more. If you’d like to test it out, you can find it in the GitHub releases; there’s a ready-to-use .exe, or the source code if you’re on Linux—or if you simply want to understand how Eve works or make some modifications yourself. Problems Encountered While building the demo, I ran into—and have since resolved—some very frustrating bugs, such as memory corruption in the ECS caused by the continuous creation and destruction of entities and their components. I also added UI text support and implemented the ability to register “stages” belonging to classes or structs that can be called by the engine."}, {"post_id": 70544, "ts": "2026-09-19T10:27:28Z", "hours": 8.0992, "text": "DEVLOG 35 - Documentation Hi Stardance! Intro I’ve finally finished writing the documentation for Eve—a rather tedious and repetitive process, but a necessary one. How The Docs Is Structured: Every part of the engine is documented; inside the docs folder, you’ll find instructions on how to launch the engine, along with subfolders for each component—graphics, input, window management, and so on. Next Last Steps: I still need to create the README and tidy up a few things in the project, as well as write instructions on how to configure Eve for use on one’s own PC… But after a whole summer, I’m finally close to shipping!"}, {"post_id": 69366, "ts": "2026-09-16T22:11:41Z", "hours": 2.8144, "text": "DEVLOG 34 - Icon, Windows & More Hi Stardance! Intro The release is getting close, so I’m tidying up a few final details; I’ve finally turned my attention to a slightly more relaxed and lighthearted part of the project. Engine Settings I added a method to start the engine that accepts configuration settings for how the app runs. You can also choose whether or not to enable VSync at runtime. Window Class I added a window management class that allows for various operations, such as toggling fullscreen mode and manually changing the resolution, position, title, etc. I also included a method to set the window icon using a PNG image. Eve’s Icon I also spent some time on Canva trying to create an icon—a logo—for Eve. After several attempts, I settled on the one in the attachment."}, {"post_id": 68288, "ts": "2026-09-14T21:13:02Z", "hours": 4.0392, "text": "DEVLOG 33 - Meshes & Fixes Hi Stardance! Intro We’re getting closer to the release build of Eve! I have to say that with this devlog, the engine is practically finished and ready for shipping; I just need to tweak a few final details and we’re all set… Meshes: In this devlog, I worked on the mesh system—fleshing it out and making it functional—and added standard meshes to Eve: a cube, a UV sphere, an icosphere, a plane, and a quad. Some Bugs Fixed While implementing this, the program kept crashing for no apparent reason; after two hours of debugging, I found the error in the Render Graph—caused by the order of Eve’s internal passes—which is now fixed. Internal Shaders Organization I also embedded the engine’s internal shaders directly into the executable, so there’s no need to remember to include them alongside the executable when creating an app. The video shows the same UI as the previous devlog—featuring controls for color, rotation, cube position, and direct light direction—but this time, you can change the meshes of the “thousand-odd” cubes at runtime using the standard Eve meshes listed above, via a simple UI dropdown menu."}, {"post_id": 67640, "ts": "2026-09-13T19:52:38Z", "hours": 7.8861, "text": "DEVLOG 32 - UI Support Hi Stardance, Intro I’ve been working on the UI lately, as I wanted to give the user a way to interact with the engine beyond just mouse and keyboard input. The UI in Eve I opted for Dear ImGui and created a lightweight wrapper that allows it to run within Eve. I stripped away some of the boilerplate code associated with the standard Begin and End calls, making it slightly simpler and safer to use than raw ImGui. I also added support for dockable windows. The video shows a scene with 1,000 cubes; thanks to the UI, you can modify their color, position, and rotation. You can also change the direction of the direct light. The code required by this UI is just five lines."}, {"post_id": 65309, "ts": "2026-09-10T11:36:28Z", "hours": 0.2975, "text": "DEVLOG 31 - It’s not my fault! Hi Stardance! Unlike the other devlogs, this one is very quick and simple. A Little Recap In devlog 29, I encountered some issues with RenderDoc, even though the app kept running fine and caused no problems outside of RenderDoc itself. What I Did After doing some online research, I discovered that RenderDoc has issues with AMD drivers, which can cause the app to crash. So, I decided to try AMD’s Radeon Developer Tools (a profiler similar to RenderDoc, designed specifically for AMD GPUs). No errors were reported and everything works perfectly, so the problem most likely lies in how AMD drivers interface with RenderDoc."}, {"post_id": 64811, "ts": "2026-09-09T14:20:04Z", "hours": 5.6439, "text": "DEVLOG 30 - Compute Shaders Hi Stardance! Intro I’ve finally implemented compute shaders—as the title suggests—alongside conducting some tests and reorganizing the project. Compute Shader Support I’ve added support for compute shaders, meaning they can now be used just like any other type of pass, whether graphics or transfer. Optimizations I’ve also utilized compute shaders internally within the engine to speed up matrix calculations; here are the results: With 100,000 entities using instanced rendering, I’m getting 800 FPS, up from the previous 250. With 1,000,000 entities using instanced rendering, I’m getting around 90 FPS, up from the previous 30. With 100,000 entities using independent draw calls, I’m getting around 90 FPS, up from the previous 30. I’d say the results speak for themselves, and I’m quite happy with these optimizations. As mentioned in the previous devlog, testing was performed on my PC, which is equipped with a Ryzen 5 5600X and an RX 6600. Swapchain & CMake I also made slight modifications to the swapchain recreation code to make it faster and reduce stuttering. Finally, I tidied up the CMakeLists file to make it more organized and prepare for the release. The video shows a scene with 1M entities rendered in real-time using instanced draw call at 90 FPS"}, {"post_id": 63615, "ts": "2026-09-07T15:19:57Z", "hours": 8.0778, "text": "DEVLOG 29 - 1M Entities! Hi Stardance! Intro Since the last day, I’ve been working alone and have run into several issues… Most of them have been resolved. Some Tests So I started running some tests to check the speed of my new rendering system, and with 100,000 entities drawn to the screen with a single draw call, I was getting 30 FPS. After parallelizing the code a bit and reducing the copies, the results are now better: 100,000 entities with single draw calls get 50-60 FPS. 100,000 entities with a single instanced draw call get 230-250 FPS. 1,000,000 entities with a single instanced draw call get 30 FPS. What Need To Be Optimized Actually, I could optimize even more and double these FPS, but the current problem is that I’m calculating the matrices on the CPU side, so I’m doing a lot of calculations that currently take up a good portion of the necessary CPU time, about 50%. The idea would be to move all the work to the GPU in the future with compute shaders, thus significantly reducing the CPU load. I’ll see if I can do this… Maybe in a while, when I add full support for compute shaders. (I have a Ryzen 5 5600 X and an RX 6600) Rendering System Time: Not counting the matrices, the rendering cycle along with the Render Graph takes about 2-2.5 ms, almost all of which is spent on the Render Graph. I have also fixed some problems with Swapchain Recreation when the window is minimized. Problems With RenderDoc Five of these eight hours have been pure frustration, as I don’t understand why, but the app crashes on RenderDoc. Normally, on my PC it starts and works, but on RenderDoc it crashes… I’ve tried every way to understand the problem, but unfortunately I haven’t been able to. I’ll also test on other PCs to better understand the problem. Unfortunately, I don’t have time on my side, so I’ve had to put the issue aside for now…"}, {"post_id": 61817, "ts": "2026-09-04T22:10:27Z", "hours": 10.2261, "text": "DEVLOG 28 - New Render System Hi Stardance! Intro I think this devlog is consistent with the next one I’m working on, since the work I’ve done in the last few hours isn’t quite finished, as there are still some bugs to resolve… Why a new render system? So far, I’ve been working on improving Eve’s rendering system. Instead of having to manually create buffers and the like, Eve has a completely automated system similar to the one used by Unity. For example, when you try to draw an object, you need things like object transformation matrices. If you then need more data, the limited size of push constants is no longer enough. Per Instance Params Eve, therefore, with its new rendering system, revolutionizes the way we write code, reduces bugs, and simplifies it. For each draw call sent to the GPU, the engine sends a buffer called InstanceParams to the GPU, which contains, for each drawing instance, its model matrix and its inverse. These matrices can then be retrieved using simple, custom functions ready for use in the shader. Per Render View Data For camera data, the process is similar. For each RenderView object, Eve allocates these objects on the GPU in a contiguous buffer from which the view, perspective, VP, and other matrices can be accessed. Custom Draw Info Data If you want to send custom data to the shader, each drawing function offers a pointer called DrawInfo that allows you to send data to the shader, which can then be accessed. If set to null, the shader will not send anything. GLM & A Flycam I also created a flycam and deprecated the Eve math package to use the glm one. Honestly, I want to focus on Eve and not the math, which is why I chose this option. Next Step: I still have some bugs to fix regarding making more than one draw call, but I’m working on it."}, {"post_id": 59920, "ts": "2026-09-01T23:02:30Z", "hours": 7.4931, "text": "DEVLOG 27 - Material System Intro After some code rewrites, such as the separation between shaders and materials, the materials system now works. It’s very similar to how it works in Unity. I’ve figured out how to set things like material properties (floats, integers, vectors, etc.) directly from C++ using their names, without manually binding code. How Vulkan Handle All Of This? In Vulkan, you can’t set a shader parameter directly with a name. You need to create a buffer on the GPU, specifically a UBO, typically used for materials, bind it using a descriptor, and then bind it on the CPU. All of this is hidden by Eve, making the code easier and faster to write. What It Does? Basically, once the shader is compiled, it’s analyzed and checked for a struct called Properties. If it exists, this struct will be used for the material properties. Each field within it will be settable directly from the CPU using its name. Eve, now knowing the size of the struct and the field offsets, creates a buffer for the materials (actually, one for each frame in flight) and uses it to write everything a material might need, thus allowing for very simple parameter setting. How To Use It: The material provides an ID via the GetPropertyUBOId function, which must always be retrieved at each frame since it is not the same from frame to frame. This ID can be sent to the shader via push constant, which then allows access to the material’s property UBO, which contains all the values set on the CPU side. A simple cube rotating on itself using the new Material System and simple direct lighting"}, {"post_id": 58517, "ts": "2026-08-30T23:07:29Z", "hours": 4.8986, "text": "DEVLOG 26 - Input System Hi Stardance! The New Input System Since I couldn’t interact much with the graphics engine at the moment, I chose to create an Input System that currently only supports keyboard and mouse. It has methods like IsKeyDown(...) , GetMouseState(...) , IsMouseUp(...) , and similar ones. It’s quite simple, but it allows you to interact with the world, for example by creating a camera or a moving player. The Cube For fun and to test a bit, I tried creating a scene with a slightly rotated cube with direct light, obviously using my Render Graph, which allows you to do all this in about 150 lines of code (CPU side) instead of having to manually write barriers, configure passes, and many other repetitive tasks. I’m still using glm for matrix math, but I’m trying to reach a more stable level with the Eve package."}, {"post_id": 57455, "ts": "2026-08-29T16:33:40Z", "hours": 7.1736, "text": "DEVLOG 25 - Eve is “Multi PC” Hi everyone! What’s changed since last time? More Device Supported As promised, Eve now uses Vulkan 1.2, so it can be used on multiple devices. Obviously, the device requires that, in addition to supporting Vulkan 1.2, it also supports some extensions that became core in Vulkan 1.3. Tests On Other PCs I then tried running the app on the only PC I had at home, but it crashed. I then tried updating the graphics driver, but that didn’t help; unfortunately, that PC is too old. I then asked a friend of mine to test the app. After fixing some issues, it started, but it would crash instantly. After hours of debugging, I found the problem: the problem was in resource allocation within the Render Graph, which only occurred with integrated GPUs (my heap selection algorithm for integrated GPUs was wrong). It’s now fixed. I also added my checks for failed Vulkan or VMA calls in places where they were missing, so now everything should work properly. Math Packet In Eve I also added a small mathematical component to Eve, including Vector2,3,4 ; Vector2Int,3Int,4Int ; Quaternion ; and Matrix4x4 . I must say that quaternions were difficult to understand at first, but once you understand how they work, it’s very easy to visualize them in your head. The first attachment shows Eve running on the PC of this friend of mine, whom I thank so much for his help, and the second image shows Eve running on my PC."}, {"post_id": 55554, "ts": "2026-08-27T14:10:22Z", "hours": 4.5942, "text": "DEVLOG 24 - Error Manager, Copies & More Intro Hi Stardance! Lately, I’ve been focusing mainly on improving error handling returned by Vulkan and fixing some code here and there. New Error Manager System I’ve created a system responsible for error handling so that when an error occurs, such as a failure to allocate memory due to fragmentation or any other critical error, the app places a text file with information about the error in a folder called logs (created on the fly if it doesn’t exist). Immediately afterward, an error message is displayed on the screen explaining what happened. When the user presses the OK button, the app closes in the pop-up by calling std::abort(); . Some Test On Other PCs I tried running Eve outside of my PC on two other PCs, but since they’re a bit older, they don’t have support for Vulkan 1.4, so the app can’t be started. Swapchain Improvements The code for creating the swapchain has been improved somewhat, making it more secure and robust. New Copy Support I’ve added support for buffer and texture copy operations between resources that aren’t the same type (one transient and one persistent). Next Step: I want to make Eve a little more portable, so in the next few hours I’ll try using Vulkan 1.2, trying not to mess with the code. If necessary, I might resort to using Vulkan 1.3; I’ll see…"}, {"post_id": 54816, "ts": "2026-08-25T23:26:03Z", "hours": 3.9353, "text": "DEVLOG 23 - Instanced Draw & Some Fixes Intro Devlog time!! In the last devlog, I had some issues with instanced drawing and reading a position buffer. What Was The Problem? I worked hard, but I managed to figure out where the problem was and fix it. (The problem was due to a for loop responsible for creating the address buffers. I was saving pointers outside the for loop with structs allocated inside the for loop; therefore, the pointers were pointing to corrupted memory or nothing.) Render Graph Fixes I fixed several things in the Render Graph that could cause future problems. I added small guards within the Render Graph so that if the user does something wrong, the application doesn’t crash unexpectedly. For example, previously, if the user set a texture to display that they’d never used (never involved in a transfer operation, never used as a graphic attachment), the program would crash. With these simple guards, everything is solved. Easier Resource Usage Declaration I’ve also added the ability to easily declare textures and buffers usage in the Graphics Pass class with dedicated methods like UseBufferReadOnlyVertex(...) , UseTextureVertex(...) , and others. The image shows a grid of 20x20 quad meshes drawn with a single draw call instead of 400 using instanced draw."}, {"post_id": 54096, "ts": "2026-08-24T21:43:20Z", "hours": 10.5117, "text": "DEVLOG 22 - ECS Bugs Fixed, Graphics Files Reorganized Hi Stardance! What I Did In this dev log, I fixed some of the last bugs the ECS code, so it now works and is very efficient. I ran several tests destroying, creating, and moving entities from one archtype to another, and everything works. I then worked on the project structure of the graphics part by fixing the graphics include files. What Went Wrong These updates mentioned so far have been successful. Two hours ago, I added a method in the graphics pass responsible for instanced drawing, so I took advantage of the opportunity to create a buffer to read the instance positions to see if it worked. I still don’t know why, but it doesn’t work. The application freezes, and sometimes the driver crashes (it scared me a little… :/ ). The Validation Layers don’t report anything wrong… So I need to figure out what’s wrong and fix it. The image shows some of the methods available after fixing the folders. The methods are in the Graphics class in the include folder."}, {"post_id": 51727, "ts": "2026-08-21T15:40:39Z", "hours": 10.1514, "text": "DEVLOG 21 - ECS Refactoring Intro Over the past ten hours, I’ve worked extensively on the ECS , making it more robust, easier to use, more secure, and more efficient. What’s changed: New Way To Record Entity Commands Entity Command Pools are still used, but they’re managed not by the user but by the Entity Manager. The old CreateCommandPool() method no longer exists. Now, to execute a command on entities, you make a request to the EntityManager , which takes the command and places it in an EntityCommandPool of its choosing. The EntityCommandPool is chosen based on the SystemId provided by the engine with methods like Start, Awake, Update, etc. This reduces complexity and allows for systems that can run natively in parallel on multiple threads. Improved Efficiency Internally, the Entity Manager has improved the way to compact batches after command execution, making it simpler and faster. Instead, iterating over all batches only iterates on the entities that are no longer valid, and those slots are refilled with the components of the valid entities at the end of the last batches. Batch creation and destruction is handled automatically by the EntityManager . New Way To Query Tables The way to find tables with certain requirements has improved; the old method required registering a query and then returning a “ticket” used to access the query results. The operation is now simpler and more unified: The EntityManager is asked for all tables that meet the QueryInfo structure requirements, such as the archtype. The EntityManager checks whether the query already exists; if it doesn’t, it calculates it on the fly and returns it. Queries Updated Only When Needed Queries are updated only when tables are created/destroyed; otherwise, they remain - static and aren’t updated, saving calculations . The next step will be to verify if everything works, since I haven’t tested anything yet because I’m forced to do this devlog due to the ten-hour time limit. :/ Sorry about the picture, it’s the same, I didn’t have time to do anything else"}, {"post_id": 48967, "ts": "2026-08-17T15:28:34Z", "hours": 5.8128, "text": "DEVLOG 20 - A Better Triangle Intro Hi Stardance! This triangle was created with Render Graph . The entire process is divided into two steps: the first draws the triangle on a user-selected image, and the second takes that image, samples it, and draws it on the swapchain so the triangle can be seen on screen. Clean and Simple API The beauty of this is evident in the photo (third attachment). You only need to write a few lines of code to achieve all this compared to the complexity and number of lines of code required by Vulkan. Render Graph thus creates all the resources needed for synchronization, such as barriers , and attempts to alias memory whenever possible. It also leverages Resource Pooling , so images aren’t destroyed and recreated at every frame. Instead, if they have identical requirements, they are reused, avoiding unnecessary Vulkan calls. MSAA Deprecated MSAA images have been deprecated because, from a desktop computer perspective, they aren’t worth using because they require a lot of computational resources. To achieve anti-aliasing, it’s best to use post-processing passes that use FXAA (Fast Approximate Anti-Aliasing) or TAA (Temporal Anti-Aliasing). There are probably some bugs still present in the Render Graph despite the many already fixed; I’ll work on them."}, {"post_id": 47136, "ts": "2026-08-14T20:10:25Z", "hours": 9.8778, "text": "DEVLOG 19 - Colors! Hi Stardance! I’ve made some progress and finally drew something on the screen! Improvements on the Swapchain Pass I’ve improved the Render Graph a bit by cleaning up old methods and making all the improvements discussed in the last devlog, such as improving the rendering code for the swapchain. Normally, you would set the 2D texture to display on the screen using the RenderGraph::SetPresentTexture(); In reality, this texture isn’t displayed directly on the screen but is first sampled and copied to the swapchain, so the Render Graph adds a hidden pass for this. When this texture hasn’t been assigned to any texture, the swapchain will be colored with the clear value set to black and sent to the screen. Push Constants Supported I’ve added the ability to use Vulkan Push Constants. Push Constants are data packets that can be sent to the GPU in parallel with the drawing command. Their size is very limited, 128 bytes, but their transfer speed is extremely fast. A hardware limitation is that the offset and size parameters must be multiples of four, so I used a struct called Words32 to dictate the 32-bit size and offset, not the 8-bit one. Furthermore, internally, the engine checks the state of the previous push constant for each push constant update, so as not to make unnecessary updates and to register the push constant command only when necessary, and only partially for the relevant bytes. Shaders Improvements I improved the shader code a bit by reducing the arguments needed to create a shader, and I also unified the layout; all shaders use the same VkPipelineLayout . The Problem and The Solution When I was writing the shaders to get these things on screen, I ran into errors telling me I was assigning a buffer descriptor to Descriptor Set 0 with binding 0, even though they’re actually textures. However, in the shader, I wasn’t requesting any of this, since the vertex data was written directly into the shader. After some research, I discovered that Slang shaders were creating bindings for these arrays outside the shader. To fix this, I simply moved the arrays into the vertex shader function, marking them with const. And note that all these images/videos use the swapchain pass, so this was all just a test. Now I’ll have to try declaring a real pass with Render Graph and try to draw something, hoping everything works correctly :/"}, {"post_id": 44624, "ts": "2026-08-10T14:56:52Z", "hours": 10.0239, "text": "DEVLOG 18 - More Refactoring Hi Stardance! I don’t know what to say about this devlog, since I’ve written a lot of code for my specific implementation… I’ll try to describe what I did without being too boring. Why I refactored again? As discussed in the previous devlog, I felt the code wasn’t “nice” or at least not very tidy, and honestly, I don’t like that very much, so I rewrote the Render Graph (partially) for the third time. Now, the Render Graph only manages single-frame resources, while all multi-frame resources are managed by a separate class called TransientResourcePool, which is therefore responsible for storing the resources. The Render Graph: A single frame responsibility The Render Graph is still responsible for memory aliasing and resource pooling, of course, as well as generating barriers and inserting the draw, copy, and, in the future, compute commands. (I still need to improve the code for compiling commands into the Command Buffers a bit.) Improvement in the searching of pooled resources Now, searching for resources to reuse is even faster, since resources are divided by their composition, for example. For textures, the parameters for this division are height, depth, width, samples, etc. This allows you to immediately find a resource if it’s available. More organization is the TransientResourcePool The TransientResourcePool is also responsible for permanently destroying unused resources for several frames. I had written the destruction code within the TransientResourcePool, but I thought maybe it wasn’t its responsibility, but rather an existing class called MemoryBin. The MemoryBin class was configured to work only for persistent resources, but now it handles the destruction of persistent and transient resources. What I need to fix: There’s a small problem in the code: Normally, when you want to destroy a resource, it’s queued and usually assigned a countdown. This countdown is a number that corresponds to the maximum frames in flight and decreases by one every frame. When this number reaches zero, the resource can be destroyed. This works perfectly, but when, for example, the swapchain needs to be recreated because the window size has changed, the GPU needs to be put into idle mode. This means that all in-flight frames have finished, and therefore all resources queued for destruction can and must be destroyed immediately, otherwise they would pile up. Otherwise, I think everything is perfect. I don’t think it will take me long to implement these little tricks, so I assume and hope :/ to start writing the code to display something on the screen soon. I’ll go back to my old, dear little triangle :)"}, {"post_id": 41971, "ts": "2026-08-06T14:41:01Z", "hours": 11.1292, "text": "DEVLOG 17 - Meshes & New Architecture Into See you again, Stardance. I’ve been implementing several things lately, as the title suggests, and I think we might soon have some geometry on the screen. Mesh System I’ve been working on meshes, creating everything needed to support mesh creation, editing, and destruction. Currently, if you create a mesh, you obviously create all the necessary buffers: one for vertex positions, one for normals, one for UVs, etc. So, for example, if I load position data and the buffer doesn’t exist, a new buffer is created and a CPU-GPU upload operation is performed. However, if the buffer exists and its size is greater than the new vertex size, the buffer isn’t reallocated to a smaller size but remains the same, reducing the number of vertices used for drawing. I’m not sure how useful this option is, but I plan to add an option to specify this in the future. Image Presentation Supported I’ve also been working on how to display an image on the screen. Currently, the Render Graph has a method that, given a texture’s Transient handle, sets that texture as the image to display on the screen. Internally, the Render Graph creates a draw pass at the end of all existing passes and then samples from the presentation texture set to draw on the swapchain. The code for all this might be a little rough at the moment; I’ll improve it later. The New Architecture For a while now, I’ve felt like the code was stepping on its own toes. I had a class called MemoryRegistry that was responsible for assigning slots to resources, allocating them, and managing their lifecycle. I didn’t like this, so I decided to rewrite much of it, splitting everything into multiple classes. Now I have a class called ResourceRegistry that provides resource IDs. A class called ResourceMapper that inserts resources into their respective global descriptors. A class called ResourceTracker that manages the resource lifecycle, their last use, which stage they were in, and similar information. Until recently, the MemoryRegistry managed both persistent and transient resources, which was a mess. I’ve decided that the MemoryRegistry should only manage persistent resources, while transient resources should be managed by a class called TransientResourcePool or something similar, which should be managed by the RenderGraph. That’s exactly what I’m working on. Some Stupid Bugs I overran the timeframe because I was partially testing the new code and encountered a stupid bug that made me lose time. (I was iterating an Array starting from the last element, but I forgot to subtract one from the size of the vector assigned to the for loop index, thus causing an out-of-memory access.) I think I’ll also rewrite a good portion of the RenderGraph first to adapt it to the new architecture. Advantages These changes will make developing new features faster and less cumbersome without having to adapt to an architecture that was poorly designed from the start. I swear that after I’ve done all this, I’ll render something to the screen, assuming there are no unforeseen issues ;)"}, {"post_id": 39763, "ts": "2026-08-02T22:53:53Z", "hours": 9.9536, "text": "DEVLOG 16 - Blank Window, Draw Calls & More The last ten hours have been very productive. As the devlog title suggests, I managed to get the classic black window, completed the code for draw calls, and also accomplished many other things. Draw Calls Commands I then completed the code for making draw calls with a simple mesh, integrating all the logic into the Render Graph. If you want to send any command to the GPU—a draw call, a copy, a dispatch, or anything else—it must necessarily go through the Render Graph. This allows me to have a central entity that can manage barriers and commands in a highly optimized, precise, and secure manner. When you want to draw something, you must declare a graphics pass. This pass has methods to execute the drawing commands, but it also has methods to set things like the texture depth/stencil to use, the target texture to draw on, etc. You can also have multiple color targets, as long as they have the same resolution. Blank Window Since I haven’t seen any tangible results on screen for a while, only code, I tried displaying a black window and then initializing the engine. The new context, window, and swapchain builders all work. The Resource Mapper, the class that manages the global descriptor set, also works. Testing the other classes will require a bit more work until I’ve got all the missing pieces, but it’s almost there. Persistent Resources Support Since creating a mesh also involves creating data and sending it to the GPU via buffers, I need a way to upload data from the CPU to the GPU. Mesh buffers are persistent, not transient. Currently, in the Render Graph code, I only had support for copying and uploading transient resources. From now on, this is also available for Persistent resources, as I’ve written the same code for them as well. I also implemented barrier generation for persistent resources so that synchronization is handled internally by the Render Graph, as with transient resources. New Resource Handles Up until now, each resource has been represented as a handle corresponding to an unsigned 32-bit number. From now on, resources are represented by two unsigned 32-bit numbers: one for the previously existing identification number and a generation number. By combining both numbers, each resource is unique, thus eliminating the possibility that if a resource is destroyed and recreated with the same ID, it could be mistaken for an older resource that no longer exists. Project Cleaning I finally cleaned up the project a bit and made it a bit more organized by dividing the files into more specific subfolders."}, {"post_id": 37211, "ts": "2026-07-29T19:14:02Z", "hours": 10.0533, "text": "DEVLOG 15 - Slang & Render Graph Reorganization So, I’ve been dividing the project into folders, making everything more organized, which wasn’t the case until now. The New Shader Language: Slang I saw that there was a more modern alternative to GLSL I could use, so I chose Slang. I created the code to create it in real time, and then I also changed the architecture of the Pipeline Builder a bit (the class responsible for creating Vulkan’s Pipeline and PipelineLayout objects). Vertex Fetch, Why Did I Choose It? I’ve been thinking for a while about forcing users of the engine to use Vertex Fetch. What is it? Well, normally when using a shader, before the Vertex Shader there’s a phase called Input Assembly that, based on the triangle indices, samples vertices from the vertex buffer, allowing them to be used directly in the Vertex Shader without manual sampling. However, this means that the layout of the vertex buffer must never change; if it were to change, you’d have to create another Pipeline object and bind it. Honestly, I don’t like this limitation very much. That’s why I removed this feature and adopted Vertex Fetch, which allows you to not specify a vertex layout, thus having as few Pipeline objects as possible. Obviously, you have to manually fetch the vertex from the respective buffer in the Vertex Shader, but frankly, it’s not a huge problem. Work In Progress On The Render Graph Another thing I’m implementing is commands that can be sent to the GPU via the Render Graph. So now you can draw, make GPU-GPU copies between buffers, between textures, and even between textures and buffers. Copies currently only support Transient resources; I’ll add the functionality for Persistent resources later. The same goes for using Compute Shaders. I’ve also added the ability to upload data from the CPU to the GPU, again for transient resources. For Persistent resources, I’ll also add this functionality later. I’m still writing the code for this, so I’m not finished yet, but I’m forced to devlog for the usual 10 hours of Stardance…"}, {"post_id": 34710, "ts": "2026-07-25T17:18:03Z", "hours": 9.9128, "text": "DEVLOG 14 - I Rewrote The Memory Aliasing Algorithm Intro Unfortunately, I don’t have anything exciting to say. I’m forced to do this devlog since I’ve reached ten hours since my last devlog, so I have to publish one, otherwise my hours wouldn’t count in full. I’ll try to share what I did, the problems I encountered, and how I solved them. The Problem I might sound crazy, but after working on the Render Graph for twenty hours, I rewrote it entirely from scratch. You might ask, why? The reason I did this was Vulkan itself. I discovered that, since I’d previously relied on VMA (Vulkan Memory Allocator) to manage memory, now that I was managing memory without it, there was something I’d overlooked: a parameter called Memory Type Index. The Memory Type Index indicates where to allocate memory. There could be a Memory Type Index for the GPU’s local memory, one for the Resizable BAR, etc. So, what’s the problem if all the Render Graph resources must live exclusively in the GPU’s local memory anyway? Wouldn’t it be enough to simply add a few lines of code and everything would be solved? Unfortunately, not because this index indicates in which memory to allocate that resource, but there’s also another parameter called Memory Type Bits, which is a bitmask that indicates in which Memory Type Indexes a resource can or cannot be allocated. All resources are allocated in the same Memory Type Index, but they may have different Memory Type Bits. This means, for example, that a texture without multi-samples cannot fit in the same memory space as a texture with multi-samples. This can also happen with the aspect mask, so a color texture and a depth texture might not fit in the same place. It could also happen with the format or tiling. The same goes for buffers, but these are more flexible than textures. The Solution My Memory Aliasing algorithm was designed without taking all this into account, so I chose to rewrite a large part of the Render Graph, trying to recycle some parts. Therefore, the Aliasing algorithm now operates on “Buckets,” which are in-memory containers containing resources that can fit in the same space. Without this distinction, memory aliasing wouldn’t be possible because a resource attempting to reuse memory used by previous resources must only check among resources with the same requirements, not among all resources. Therefore, it checks per bucket, not all existing resources. This has also made the code much cleaner and more organized."}, {"post_id": 32449, "ts": "2026-07-21T17:21:23Z", "hours": 10.0289, "text": "DEVLOG 13 - Memory Aliasing Recap In the last devlog, I explained what I did and why I was creating a Render Graph. I mentioned a concept called Memory Aliasing, but I explained it briefly. I’ve been working extensively on the Render Graph these past few hours to implement the Memory Aliasing algorithm. What is Memory Aliasing? Memory Aliasing involves having two or more resources use the same portions of memory, thus sharing that memory. For example, let’s take a texture we’ll call A. This texture is used as Depth in pass 1 and read in pass 2. Another texture, called B, is used in pass 3 and pass 4 (see photo). We could allocate both resources independently, but you can clearly see that the resources don’t overlap in the passes. Texture A begins its usage cycle in pass 1 and ends in pass 2, and immediately after, in pass 3, texture B is used for the first time. What we could do is have both textures occupy the same memory space to save VRAM. This is the concept of Memory Aliasing. Obviously, since the resources share the same memory space, barriers must be created to synchronize resource access, otherwise there would be a race condition (two threads operating in parallel on the same memory space, not just for read-only operations). Resource Pooling In addition to memory aliasing, I wanted to optimize another aspect that took me some time. In Vulkan, when you want to create resources, you use vkCreateImage and vkCreateBuffer. These functions create a handle without associating physical memory with these objects. Binding occurs later, after executing the memory aliasing algorithm, which determines which memory space to assign to a resource. This means that I have to create and destroy resource handles every frame, which apparently isn’t a light operation to perform on multiple resources. So I thought that if there was a possibility, I could reuse handles from previous frames by simply comparing whether the settings of the requested handle were the same as the one to be reused and then binding the memory. The Problem and the Solution This was the idea I had, but unfortunately it’s not feasible because Vulkan doesn’t allow memory binding to a resource more than once, so this approach wouldn’t have worked. After thinking for a while about how to solve this, I decided to include in the requirements for using old handles, in addition to the texture or buffer settings, the offset and stride of how they were bound in memory. This way, if the pass structure and usage hadn’t changed significantly during the user’s setup phase, the Memory Aliasing algorithm would always produce the same results, given the deterministic nature, making this all feasible. Finally, if the resources aren’t reused for an N number of consecutive frames, they are permanently destroyed."}, {"post_id": 30667, "ts": "2026-07-18T13:14:32Z", "hours": 9.9683, "text": "DEVLOG 12 - Render Graph, Code Refactoring A Little Recap In the last devlog, I mentioned I watched the 2017 GDC conference, where they explained how the Frostbite development team had created a Render Graph. But what is a Render Graph, and what is it used for? To answer this question, we must first understand how the GPU works. The Difference: CPU & GPU First, a GPU, unlike a CPU, performs all its operations in parallel. When we write code for the CPU, we say: do this operation, then this, then that, and so on. The CPU performs its operations synchronously, in sequential order. The GPU, however, doesn’t work that way. If we tell the GPU that we want to draw three objects, we can send it three draw calls, which we’ll call A, B, and C. These draw calls are sent in order, so first A, then B, and then C. The order in which the commands are sent doesn’t correspond to the order in which they are executed, because the GPU could execute the commands in this order: C, B, A, or B, A, C, or A, C, B, and so on. This is because, while operation A might be in progress, operation B might start executing, so both commands will use the same resources and therefore run into a race condition if both operations are not read-only. The Problem From this perspective, the GPU is very powerful because it tries to stay constantly busy, eliminating dead time. However, this greatly complicates things on the synchronization side. Let’s take two operations: operation A that writes an image and operation B that reads the image. How can we be sure that the GPU executes operation A first and not B? Who can assure us that the GPU, while executing A, doesn’t have to execute B? The answer to all these questions is no one. How Graphics APIs Handle All Of This In graphics APIs like OpenGL, all of this is hidden from the programmer, so they don’t have to worry about it. But in graphics APIs like Vulkan and DirectX 12, this is the programmer’s responsibility. The programmer must write a barrier and tell the GPU not to touch the image from operation B before A has finished. For a few barriers, this is feasible, but as soon as you write more complex applications, making the code sufficiently organized, non-repetitive, and fast to develop becomes very challenging. This is why the concept of a Render Graph exists. What A Render Graph Does A Render Graph allows the programmer to specify which steps the GPU should execute, which operations resources like images and textures will perform, and in what order. The Frame Graph looks at this graph constructed by the programmer at each frame and internally understands where barriers and sometimes semaphores are needed (if we’re working with multiple queues, that’s not the case for me). Another responsibility of the Frame Graph is to internally allocate and manage resources that only exist within a single frame, called transient resources. Finally, I’m implementing Memory Aliasing. This reduces the memory used by resources: for example, if resource A is used for the last time in pass 3 and resource B for the first time in pass 4, they can share the same physical memory, thus reducing the overall memory requirement. Bonus I’ve also restructured the texture creation methods, making them simpler and allowing for fewer specifications. The before and after is a good result… The same goes for 1D and 3D textures."}, {"post_id": 28272, "ts": "2026-07-14T12:58:23Z", "hours": 10.2439, "text": "DEVLOG 11 - BDA, Pipeline, Shaders In the last devlog, I explained how I wanted to structure my bindless descriptor set. With that approach, I had a buffer for each data type. This approach works, but it’s a bit cumbersome, so I switched to using Buffer Device Addresses (BDAs). The idea behind it is: Create buffers, around VRAM, placing the buffers within VRAM memory pools. Instead of saving the physical data inside the descriptor buffer, we can only save pointers to the buffers, so I’ll have a buffer of pointers to the buffers scattered across VRAM. Since the pointers take up 8 bytes, managing the buffer is very simple, as it will be very light. So, essentially, I separate the physical data of the buffers from the shader binding logic. Rather than using namespaces to hide the internal implementation, I chose to use Hadles, which are simply numbers that identify that resource. So I could have a BufferHandle, ImageHandle, SamplerHandle, PipelineHandle, and so on. I chose not to call the structure that manages all this with names that might be reminiscent of the Vulkan API, but instead called this system Resource Mapper. At the moment, I think I’ve done something wrong with the code: Since the buffers are simply exposed via a 32-bit index, internally the buffer index corresponds to the index of the vector in which the Vulkan buffer handles and all the allocation information are allocated. I think I’ve erred in saving the buffers in vector indices that don’t match their exposed handle index outside of Eve. This causes access to incorrect buffers or buffers that don’t even exist, causing UBs or crashes. I still need to verify this issue and, if it occurs, I’ll have to fix it. Furthermore, yesterday I added all the code responsible for creating the graphics pipeline and compiling the shaders. This code is still a bit rough and needs improvement. Furthermore, since I don’t want the user to have to manage synchronization outside of the engine, I’ve been thinking about how to structure a Render Graph. I saw Frostbite’s presentation at GDC 2017 where they explained how their Render Graph works and that gave me some insights."}, {"post_id": 25895, "ts": "2026-07-10T11:55:09Z", "hours": 11.2272, "text": "DEVLOG 10 - Working On The Vulkan Wrapper For now, I’m focused on creating a wrapper for Vulkan to make it simpler and less repetitive to use. I don’t want to create a wrapper that abstracts too much, thus losing control; instead, I’m creating a fairly thin wrapper. I’m currently restructured the Application class a bit and divided some of its parts into three “modules.” I’m structuring this using the Factory Pattern. I’ve created three Builders: one for the window and SDL initialization, one for creating a Vulkan context—VulkanInstace, PhysicalDevice, LogicalDevice, and the graphics queue—and the last one for building the swapchain. I chose this approach because I consider it flexible and I don’t want everything to fit into one huge monolith; I prefer having multiple modular classes. In addition to these more or less complete builders, I’m focusing on creating a system that can allow shaders to see and manipulate the data stored in VRAM. This is usually done with DescriptorSets, which have been the standard for years. They’re more or less like pointers to objects in VRAM so shaders can access them. In reality, they’re fat pointers because they contain other information besides the address. However, this approach is good but not optimal because it introduces CPU overhead. Since the draw calls may not share the same materials and therefore require different textures, a new DescriptorSet must be bound before each draw call, which, with many draw calls, incurs CPU overhead. What I’m doing to solve this problem is looking towards a more modern and efficient approach called Bindless. Basically, instead of having multiple small DescriptorSets, you have one huge global DescriptorSet that contains all the resources used by the application. So we could have a sort of array containing all the samplers, then another containing all the textures, another containing all the buffers of a specific type, etc. Then we just need to bind this DescriptorSet at the start of rendering, which will be used for the entire rendering process, and pass indices to the shader that will tell it which resources to use from the DescriptorSet. I’m a little slow in developing all this because I’ve never used Vulkan; in fact, I’m still learning. The second reason is that Vulkan is very complex and there’s a lot of boilerplate code. I still have to finish the ECS system since I don’t yet have a centralized approach for obtaining the IDs and GenerationIds of new entities, which are verified and therefore safely managed internally by the engine. But I think I’ll do it later since I’m a little tired of fiddling with entities and want to do something different for a while."}, {"post_id": 21085, "ts": "2026-07-02T21:28:10Z", "hours": 4.3578, "text": "DEVLOG 9 - 100K Entities After the last devlog, in which I rendered 1K entities, I tried increasing the number of entities to a 15x15x15 cube, or 3375 entities, and I saw the frame rate drop unexpectedly, 25 FPS. I was wondering if this was normal or not… Apparently, it wasn’t… I tried to figure out the problem, but it wasn’t easy. I tried using a tool called RenderDoc that lets you see what’s happening on the GPU, so all the calls, data passed to the GPU, buffers, textures, etc. That information also included the time, and the GPU indicated it was taking about 16 ms, which was quite strange. I started to suspect Vulkan’s validation layers. By disabling them, I got to 30 FPS or a little higher, I don’t remember exactly. Then I disabled ASan and set the swapchain to Immediate Mode so as not to be constrained by the screen refresh rate, and I got to about 100 FPS. Then I made several CPU-level optimizations at the code level by changing the way components are obtained from batches in my ECS system, specifically limiting those operations that can be avoided in the internal component iteration loop, and I got up to 140 fps. Finally, the thing that made me open my eyes and say WOW was compiling in Release and not Debug, the fps skyrocketed to around 2300… I couldn’t believe it either… After doing all this, I rendered 100,000 entities and my fps were stable at 90… Incredible! Finally, just for the sake of curiosity, I tested 1,000,000 entities and got 9 fps, which is good because it means the system scales linearly. This is what I’ve been doing for the last two hours. Before that, I spent some time revisiting my ECS code to make it more secure. For example, many of the Table and EntityManager methods now return references and not pointers. I’ve also made the ComponentRegistry class much more efficient by storing component information in contiguous arrays instead of lists, which therefore contain non-contiguous data. Next Steps: I need to implement a way to get verified IDs from the EntityManager, since currently the IDs are only manual and non-unique. And then I’ll need to refactor the rendering code again, making it more modular, since it’s currently all in a single class."}, {"post_id": 20319, "ts": "2026-07-01T21:44:13Z", "hours": 9.6286, "text": "DEVLOG 8 - 1K Entities I implemented several things: One of these is a manager that allows systems to register their functions so they can be called, for example, when Update, Start, LateUpdate, etc. I implemented Address Sanitizer in the project to detect leaks, overflows, or out-of-bounds reads, thus uncovering some bugs. I didn’t understand why, but ASan was having trouble integrating with the project; apparently, the shaderc library was causing problems because it had a different connotation than the project. I finally solved the problem by telling CMake to use the Release version of shaderc, not Debug. I created a test system called S_Test, which I used to verify that I could create and manage multiple entities (apparently, yes). After having several memory issues, which I resolved with the help of ASan, I also started creating a camera component so I could move freely in 3D space. I’ve improved the security of the code; Entity Command Pools now no longer need to be created by the programmer, but by the Entity Manager itself, which manages them. This minimizes the risk of freeing memory too early, resulting in cleaner code for the game. Furthermore, the EntityCommandInfo and QueryInfo classes can now be allocated on the stack rather than the heap, resulting in a more secure program. Finally, for fun, I wanted to try creating a thousand entities, also to see if the system was capable of it and if there were any problems. I have to say, I’m quite happy with the result. Next Step: I still have to improve several parts of the code to make it more secure and faster, such as the Component Registry."}, {"post_id": 18339, "ts": "2026-06-29T13:31:38Z", "hours": 6.0772, "text": "DEVLOG 7 - Code Reorganization I tried to reorganize the project so that the headers needed by users of the engine are visible, while the internal, and therefore unnecessary, ones are not. What do I mean? Let’s say we have a class called A. This class is used by the engine itself, but it can also be used by the developer, for example, to record commands or something similar. So the developer will include class A in their header or source files so it can be used. But there’s a problem: Header A could include other headers that aren’t necessarily needed by the developer using the engine, thus polluting the headers. How do I solve this problem? Since I haven’t used C++ for years, I’ve been researching the problem online for months and found the following solutions: Forward Declaration - This consists of declaring the required class in the header, in this case A, without using the include directive, which literally copies the headers included in the file containing the directive. This seems like a good method, but unfortunately the data can’t be variable by value, only by reference or pointer, since the compiler must know at compile time how much memory that specific object occupies. Pimpl Idiom - This involves enclosing or encapsulating the information needed for the internal functioning of A in a class or struct that is hidden from the developer using the engine. This method could work and is almost standard, but personally, I don’t really like the idea of having to create another structure to achieve this goal. It’s more of a workaround, since the language has significant limitations in this regard. C++20 Modules - Modules are a new way of programming in C++ because, among other things, they solve this problem. They also reduce compilation times and avoid separating the code into two separate files (.hpp and .cpp). I tried using them, and from a compiler perspective, they work great (I’m using Clang), but from a Clangd perspective, the situation is quite different: While the compiler support is fairly mature, Clangd still has several issues; in fact, it reported errors everywhere. I even tried modifying the .clangd file by adding various flags, but the situation didn’t improve. There are other methods, such as Fast Pimpl, but they aren’t as flexible. What I’m looking for is something flexible that generally works in all conditions and doesn’t introduce overhead, which Pimpl Idiom doesn’t. The final solution was to use namespaces . All the public headers that must be used by the developer using the engine are in the Eve/ namespace, while the internal headers that shouldn’t be used by the developer are in a namespace called Eve/Internal. If the developer uses these files, it’s their fault; they’re marked as internal to the engine and therefore shouldn’t be used. I also changed build system and switched to CMake as it is more widespread in the C++ community and this can also give an advantage in the engine configuration section for other users"}, {"post_id": 15067, "ts": "2026-06-24T14:08:55Z", "hours": 28.5411, "text": "DEVLOG 6 - Crash, Crash, Crash and…. Crash What I did After spending several hours designing my ECS architecture, I realized I could do better, so I basically started from scratch and, as I mentioned in the previous devlog, I chose to use Archtypes so everything would be extremely efficient. Maybe I’m a bit too obsessed with performance… The Problem Anyway, after finishing the entire system, I started the app and it crashed. After several hours of debugging with simple print(); I thought the problem was in the memory, but I couldn’t figure out where… I finally decided to use Address Sanitizer, a tool that alerts you to out-of-bounds writes or reads, which allowed me to pinpoint the problem. I had performed a nonsensical multiplication, so the memory pointer was pointing to the wrong place, specifically to the end of the allocated memory portion, causing the metadata to be overwritten. (Apparently, when allocating memory, the program itself allocates additional memory slices that store information about the allocated memory portion.) The problem was that the app didn’t always crash, only sometimes, and I didn’t understand why. But I finally managed to get it working… The Result At the moment, this is a single entity, and since I haven’t tested the rest of the code, such as the destruction logic and entity transitions from one archtype to another, there are likely other bugs waiting for me."}, {"post_id": 9873, "ts": "2026-06-16T10:28:19Z", "hours": 4.6411, "text": "DEVLOG 5 - The ECS Architecture Since I can now draw something on the screen, I’d say it’s time to start building the actual graphics engine. The first system I need to create for Eve is the management of game objects. There are two options: the first is to use the OOP programming paradigm and therefore manage game objects just like Unity does; the other, which is the one I chose, is to use the ECS (Entity, Component, System) architecture. To understand why I chose ECS, you need to understand how this architecture works. As I mentioned, the word ECS is an acronym for Entity, Component, and System, which represent the three pillars on which this architecture is based. In short, entities represent objects, the essence of the object; that object simply exists, and they are usually represented by a simple numeric ID. Components, on the other hand, represent pure data; therefore, each entity can have its own components and therefore its own data. Systems, on the other hand, are the part of the code that executes the logic. Let’s take the rendering system as an example. This will iterate over all entities that have mesh components, and a transform will take their data and send it to the GPU for rendering. This division of responsibilities ensures incredible efficiency, given how the CPU works, since the component data is stored contiguously in memory. This facilitates the work of a CPU component called the Hardware Prefetcher, which tries to predict which portion of RAM the CPU will use next, thus reducing cache misses. There are many ready-to-use libraries for this architecture, such as Flecs, EnTT, and others. I chose to try and create my own so I could learn and understand more. Currently, I’m using, broadly speaking, the same approach Unity uses with their ECS architecture, which is part of their Unity DOTS ecosystem. All entities in the game can be classified based on an ID called an Archtype, which identifies the type of entity being viewed based on its components. This way, you can have contiguous arrays and minimize cache misses, thus maximizing CPU efficiency. I’m still working on it, but I have to say it’s extremely interesting…"}, {"post_id": 8166, "ts": "2026-06-13T16:39:12Z", "hours": 4.5819, "text": "DEVLOG 4 - Textures! I finally managed to use textures; Vulkan has a bit of boilerplate in their configuration, especially with the descriptor sets. This was the part that slowed me down a bit. The code isn’t very tidy at the moment… For now, I’ve focused more on learning, so I haven’t written anything extremely tidy and readable. As I said, I’ve only learned the basics so far. Now that I feel more confident about the subject, I think I’ll start writing something. I’m thinking of a framework or something simple that allows you to draw geometry on the screen without having to write hundreds of lines of code directly with Vulkan. So, more generally, I think I’ll create a layer of abstraction while still trying to maintain excellent flexibility."}, {"post_id": 7178, "ts": "2026-06-11T23:53:28Z", "hours": 2.3814, "text": "DEVLOG 3 - First Cube!!! How satisfying, my first 3D object! Since previously all vertices were written manually in the shader, I opted to learn how to create buffers to load more complex 3D geometry onto the screen. I’m loading the resources directly into a specific portion of memory called Host Visible, where the CPU can also write, and the GPU’s reading isn’t as fast as it could be. If I instead allocate the memory in a portion of VRAM called Device Local, the GPU will be very fast at accessing the data, but the CPU, on the other hand, won’t be able to do anything with that memory. To modify it, you need to first allocate the data in an intermediate buffer called Staging Buffer, and then from there the data can go to Device Local memory (the GPU’s fast memory). I also added some transformations and rotations with GLM to rotate the cube, and this is the result, which is nice. I think I’ll try using Device Local memory by loading data to it, as discussed before, with a Staging Buffer and after that I think I’ll start experimenting with textures."}, {"post_id": 6502, "ts": "2026-06-10T22:34:52Z", "hours": 9.0367, "text": "DEVLOG 2 - Consolidation of things learned Well, What’s new? Just a square? It might not seem like much, but yes. I spent all these hours rewriting the entire code from scratch so I could understand where I had the most doubts and therefore review some concepts. Synchronization was and still is the most difficult concept to grasp; understanding how the semaphores and barriers are linked together wasn’t easy for me, and I must admit I still have some doubts about it, but certainly much less than before. Given the asynchronous nature of the graphics card, you can’t program operations that will be executed in order, unlike the CPU, and this is one of the graphics card’s strengths and weaknesses. You can parallelize many operations, but you have to be careful how they are linked together and synchronize them as correctly as possible. My next step, I think, will be to use buffers to give more complex geometry to the shaders, primarily for drawing 3D geometry. I also think I still have to delve deeper and better understand things like semaphores, timeline semaphores, and barriers, which are topics I feel I haven’t internalized as well as others."}, {"post_id": 5182, "ts": "2026-06-08T21:32:27Z", "hours": 11.6153, "text": "DEVLOG 1 - Hello Triangle!!! Finally, after several hours trying to understand how Vulkan works, watching and reading several tutorials, I got it, my first triangle, isn’t it cute?🫠🫠 I’ve figured out most of the things, but I think I need to delve a little deeper into the process of creating a pipeline with dynamic rendering and synchronization. These are the two topics that have been giving me the most trouble. I think the next step will be to re-explore the code and try to create something on my own, without a guided tutorial, to see if I’ve really understood the concepts."}]...
|
Title: Eve by @Light | Stardance
Devlogs:
DEVLOG Title: Eve by @Light | Stardance
Devlogs:
DEVLOG 1 - Hello Triangle!!! Finally, after several hours trying to understand how Vulkan works, watching and reading several tutorials, I got it, my first triangle, isn’t it cute?🫠🫠 I’ve figured out most of the things, but I think I need to delve a little deeper into the process of creating a pipeline with dynamic rendering and synchronization. These are the two topics that have been giving me the most trouble. I think the next step will be to re-explore the code and try to create something on my own, without a guided tutorial, to see if I’ve really understood the concepts.
DEVLOG 2 - Consolidation of things learned Well, What’s new? Just a square? It might not seem like much, but yes. I spent all these hours rewriting the entire code from scratch so I could understand where I had the most doubts and therefore review some concepts. Synchronization was and still is the most difficult concept to grasp; understanding how the semaphores and barriers are linked together wasn’t easy for me, and I must admit I still have some doubts about it, but certainly much less than before. Given the asynchronous nature of the graphics card, you can’t program operations that will be executed in order, unlike the CPU, and this is one of the graphics card’s strengths and weaknesses. You can parallelize many operations, but you have to be careful how they are linked together and synchronize them as correctly as possible. My next step, I think, will be to use buffers to give more complex geometry to the shaders, primarily for drawing 3D geometry. I also think I still have to delve deeper and better understand things like semaphores, timeline semaphores, and barriers, which are topics I feel I haven’t internalized as well as others.
DEVLOG 3 - First Cube!!! How satisfying, my first 3D object! Since previously all vertices were written manually in the shader, I opted to learn how to create buffers to load more complex 3D geometry onto the screen. I’m loading the resources directly into a specific portion of memory called Host Visible, where the CPU can also write, and the GPU’s reading isn’t as fast as it could be. If I instead allocate the memory in a portion of VRAM called Device Local, the GPU will be very fast at accessing the data, but the CPU, on the other hand, won’t be able to do anything with that memory. To modify it, you need to first allocate the data in an intermediate buffer called Staging Buffer, and then from there the data can go to Device Local memory (the GPU’s fast memory). I also added some transformations and rotations with GLM to rotate the cube, and this is the result, which is nice. I think I’ll try using Device Local memory by loading data to it, as discussed before, with a Staging Buffer and after that I think I’ll start experimenting with textures.
DEVLOG 4 - Textures! I finally managed to use textures; Vulkan has a bit of boilerplate in their configuration, especially with the descriptor sets. This was the part that slowed me down a bit. The code isn’t very tidy at the moment… For now, I’ve focused more on learning, so I haven’t written anything extremely tidy and readable. As I said, I’ve only learned the basics so far. Now that I feel more confident about the subject, I think I’ll start writing something. I’m thinking of a framework or something simple that allows you to draw geometry on the screen without having to write hundreds of lines of code directly with Vulkan. So, more generally, I think I’ll create a layer of abstraction while still trying to maintain excellent flexibility.
DEVLOG 5 - The ECS Architecture Since I can now draw something on the screen, I’d say it’s time to start building the actual graphics engine. The first system I need to create for Eve is the management of game objects. There are two options: the first is to use the OOP programming paradigm and therefore manage game objects just like Unity does; the other, which is the one I chose, is to use the ECS (Entity, Component, System) architecture. To understand why I chose ECS, you need to understand how this architecture works. As I mentioned, the word ECS is an acronym for Entity, Component, and System, which represent the three pillars on which this architecture is based. In short, entities represent objects, the essence of the object; that object simply exists, and they are usually represented by a simple numeric ID. Components, on the other hand, represent pure data; therefore, each entity can have its own components and therefore its own data. Systems, on the other hand, are the part of the code that executes the logic. Let’s take the rendering system as an example. This will iterate over all entities that have mesh components, and a transform will take their data and send it to the GPU for rendering. This division of responsibilities ensures incredible efficiency, given how the CPU works, since the component data is stored contiguously in memory. This facilitates the work of a CPU component called the Hardware Prefetcher, which tries to predict which portion of RAM the CPU will use next, thus reducing cache misses. There are many ready-to-use libraries for this architecture, such as Flecs, EnTT, and others. I chose to try and create my own so I could learn and understand more. Currently, I’m using, broadly speaking, the same approach Unity uses with their ECS architecture, which is part of their Unity DOTS ecosystem. All entities in the game can be classified based on an ID called an Archtype, which identifies the type of entity being viewed based on its components. This way, you can have contiguous arrays and minimize cache misses, thus maximizing CPU efficiency. I’m still working on it, but I have to say it’s extremely interesting…
DEVLOG 6 - Crash, Crash, Crash and…. Crash What I did After spending several hours designing my ECS architecture, I realized I could do better, so I basically started from scratch and, as I mentioned in the previous devlog, I chose to use Archtypes so everything would be extremely efficient. Maybe I’m a bit too obsessed with performance… The Problem Anyway, after finishing the entire system, I started the app and it crashed. After several hours of debugging with simple print(); I thought the problem was in the memory, but I couldn’t figure out where… I finally decided to use Address Sanitizer, a tool that alerts you to out-of-bounds writes or reads, which allowed me to pinpoint the problem. I had performed a nonsensical multiplication, so the memory pointer was pointing to the wrong place, specifically to the end of the allocated memory portion, causing the metadata to be overwritten. (Apparently, when allocating memory, the program itself allocates additional memory slices that store information about the allocated memory portion.) The problem was that the app didn’t always crash, only sometimes, and I didn’t understand why. But I finally managed to get it working… The Result At the moment, this is a single entity, and since I haven’t tested the rest of the code, such as the destruction logic and entity transitions from one archtype to another, there are likely other bugs waiting for me.
DEVLOG 7 - Code Reorganization I tried to reorganize the project so that the headers needed by users of the engine are visible, while the internal, and therefore unnecessary, ones are not. What do I mean? Let’s say we have a class called A. This class is used by the engine itself, but it can also be used by the developer, for example, to record commands or something similar. So the developer will include class A in their header or source files so it can be used. But there’s a problem: Header A could include other headers that aren’t necessarily needed by the developer using the engine, thus polluting the headers. How do I solve this problem? Since I haven’t used C++ for years, I’ve been researching the problem online for months and found the following solutions: Forward Declaration - This consists of declaring the required class in the header, in this case A, without using the include directive, which literally copies the headers included in the file containing the directive. This seems like a good method, but unfortunately the data can’t be variable by value, only by reference or pointer, since the compiler must know at compile time how much memory that specific object occupies. Pimpl Idiom - This involves enclosing or encapsulating the information needed for the internal functioning of A in a class or struct that is hidden from the developer using the engine. This method could work and is almost standard, but personally, I don’t really like the idea of having to create another structure to achieve this goal. It’s more of a workaround, since the language has significant limitations in this regard. C++20 Modules - Modules are a new way of programming in C++ because, among other things, they solve this problem. They also reduce compilation times and avoid separating the code into two separate files (.hpp and .cpp). I tried using them, and from a compiler perspective, they work great (I’m using Clang), but from a Clangd perspective, the situation is quite different: While the compiler support is fairly mature, Clangd still has several issues; in fact, it reported errors everywhere. I even tried modifying the .clangd file by adding various flags, but the situation didn’t improve. There are other methods, such as Fast Pimpl, but they aren’t as flexible. What I’m looking for is something flexible that generally works in all conditions and doesn’t introduce overhead, which Pimpl Idiom doesn’t. The final solution was to use namespaces . All the public headers that must be used by the developer using the engine are in the Eve/ namespace, while the internal headers that shouldn’t be used by the developer are in a namespace called Eve/Internal. If the developer uses these files, it’s their fault; they’re marked as internal to the engine and therefore shouldn’t be used. I also changed build system and switched to CMake as it is more widespread in the C++ community and this can also give an advantage in the engine configuration section for other users
DEVLOG 8 - 1K Entities I implemented several things: One of these is a manager that allows systems to register their functions so they can be called, for example, when Update, Start, LateUpdate, etc. I implemented Address Sanitizer in the project to detect leaks, overflows, or out-of-bounds reads, thus uncovering some bugs. I didn’t understand why, but ASan was having trouble integrating with the project; apparently, the shaderc library was causing problems because it had a different connotation than the project. I finally solved the problem by telling CMake to use the Release version of shaderc, not Debug. I created a test system called S_Test, which I used to verify that I could create and manage multiple entities (apparently, yes). After having several memory issues, which I resolved with the help of ASan, I also started creating a camera component so I could move freely in 3D space. I’ve improved the security of the code; Entity Command Pools now no longer need to be created by the programmer, but by the Entity Manager itself, which manages them. This minimizes the risk of freeing memory too early, resulting in cleaner code for the game. Furthermore, the EntityCommandInfo and QueryInfo classes can now be allocated on the stack rather than the heap, resulting in a more secure program. Finally, for fun, I wanted to try creating a thousand entities, also to see if the system was capable of it and if there were any problems. I have to say, I’m quite happy with the result. Next Step: I still have to improve several parts of the code to make it more secure and faster, such as the Component Registry.
DEVLOG 9 - 100K Entities After the last devlog, in which I rendered 1K entities, I tried increasing the number of entities to a 15x15x15 cube, or 3375 entities, and I saw the frame rate drop unexpectedly, 25 FPS. I was wondering if this was normal or not… Apparently, it wasn’t… I tried to figure out the problem, but it wasn’t easy. I tried using a tool called RenderDoc that lets you see what’s happening on the GPU, so all the calls, data passed to the GPU, buffers, textures, etc. That information also included the time, and the GPU indicated it was taking about 16 ms, which was quite strange. I started to suspect Vulkan’s validation layers. By disabling them, I got to 30 FPS or a little higher, I don’t remember exactly. Then I disabled ASan and set the swapchain to Immediate Mode so as not to be constrained by the screen refresh rate, and I got to about 100 FPS. Then I made several CPU-level optimizations at the code level by changing the way components are obtained from batches in my ECS system, specifically limiting those operations that can be avoided in the internal component iteration loop, and I got up to 140 fps. Finally, the thing that made me open my eyes and say WOW was compiling in Release and not Debug, the fps skyrocketed to around 2300… I couldn’t believe it either… After doing all this, I rendered 100,000 entities and my fps were stable at 90… Incredible! Finally, just for the sake of curiosity, I tested 1,000,000 entities and got 9 fps, which is good because it means the system scales linearly. This is what I’ve been doing for the last two hours. Before that, I spent some time revisiting my ECS code to make it more secure. For example, many of the Table and EntityManager methods now return references and not pointers. I’ve also made the ComponentRegistry class much more efficient by storing component information in contiguous arrays instead of lists, which therefore contain non-contiguous data. Next Steps: I need to implement a way to get verified IDs from the EntityManager, since currently the IDs are only manual and non-unique. And then I’ll need to refactor the rendering code again, making it more modular, since it’s currently all in a single class.
DEVLOG 10 - Working On The Vulkan Wrapper For now, I’m focused on creating a wrapper for Vulkan to make it simpler and less repetitive to use. I don’t want to create a wrapper that abstracts too much, thus losing control; instead, I’m creating a fairly thin wrapper. I’m currently restructured the Application class a bit and divided some of its parts into three “modules.” I’m structuring this using the Factory Pattern. I’ve created three Builders: one for the window and SDL initialization, one for creating a Vulkan context—VulkanInstace, PhysicalDevice, LogicalDevice, and the graphics queue—and the last one for building the swapchain. I chose this approach because I consider it flexible and I don’t want everything to fit into one huge monolith; I prefer having multiple modular classes. In addition to these more or less complete builders, I’m focusing on creating a system that can allow shaders to see and manipulate the data stored in VRAM. This is usually done with DescriptorSets, which have been the standard for years. They’re more or less like pointers to objects in VRAM so shaders can access them. In reality, they’re fat pointers because they contain other information besides the address. However, this approach is good but not optimal because it introduces CPU overhead. Since the draw calls may not share the same materials and therefore require different textures, a new DescriptorSet must be bound before each draw call, which, with many draw calls, incurs CPU overhead. What I’m doing to solve this problem is looking towards a more modern and efficient approach called Bindless. Basically, instead of having multiple small DescriptorSets, you have one huge global DescriptorSet that contains all the resources used by the application. So we could have a sort of array containing all the samplers, then another containing all the textures, another containing all the buffers of a specific type, etc. Then we just need to bind this DescriptorSet at the start of rendering, which will be used for the entire rendering process, and pass indices to the shader that will tell it which resources to use from the DescriptorSet. I’m a little slow in developing all this because I’ve never used Vulkan; in fact, I’m still learning. The second reason is that Vulkan is very complex and there’s a lot of boilerplate code. I still have to finish the ECS system since I don’t yet have a centralized approach for obtaining the IDs and GenerationIds of new entities, which are verified and therefore safely managed internally by the engine. But I think I’ll do it later since I’m a little tired of fiddling with entities and want to do something different for a while.
DEVLOG 11 - BDA, Pipeline, Shaders In the last devlog, I explained how I wanted to structure my bindless descriptor set. With that approach, I had a buffer for each data type. This approach works, but it’s a bit cumbersome, so I switched to using Buffer Device Addresses (BDAs). The idea behind it is: Create buffers, around VRAM, placing the buffers within VRAM memory pools. Instead of saving the physical data inside the descriptor buffer, we can only save pointers to the buffers, so I’ll have a buffer of pointers to the buffers scattered across VRAM. Since the pointers take up 8 bytes, managing the buffer is very simple, as it will be very light. So, essentially, I separate the physical data of the buffers from the shader binding logic. Rather than using namespaces to hide the internal implementation, I chose to use Hadles, which are simply numbers that identify that resource. So I could have a BufferHandle, ImageHandle, SamplerHandle, PipelineHandle, and so on. I chose not to call the structure that manages all this with names that might be reminiscent of the Vulkan API, but instead called this system Resource Mapper. At the moment, I think I’ve done something wrong with the code: Since the buffers are simply exposed via a 32-bit index, internally the buffer index corresponds to the index of the vector in which the Vulkan buffer handles and all the allocation information are allocated. I think I’ve erred in saving the buffers in vector indices that don’t match their exposed handle index outside of Eve. This causes access to incorrect buffers or buffers that don’t even exist, causing UBs or crashes. I still need to verify this issue and, if it occurs, I’ll have to fix it. Furthermore, yesterday I added all the code responsible for creating the graphics pipeline and compiling the shaders. This code is still a bit rough and needs improvement. Furthermore, since I don’t want the user to have to manage synchronization outside of the engine, I’ve been thinking about how to structure a Render Graph. I saw Frostbite’s presentation at GDC 2017 where they explained how their Render Graph works and that gave me some insights.
DEVLOG 12 - Render Graph, Code Refactoring A Little Recap In the last devlog, I mentioned I watched the 2017 GDC conference, where they explained how the Frostbite development team had created a Render Graph. But what is a Render Graph, and what is it used for? To answer this question, we must first understand how the GPU works. The Difference: CPU & GPU First, a GPU, unlike a CPU, performs all its operations in parallel. When we write code for the CPU, we say: do this operation, then this, then that, and so on. The CPU performs its operations synchronously, in sequential order. The GPU, however, doesn’t work that way. If we tell the GPU that we want to draw three objects, we can send it three draw calls, which we’ll call A, B, and C. These draw calls are sent in order, so first A, then B, and then C. The order in which the commands are sent doesn’t correspond to the order in which they are executed, because the GPU could execute the commands in this order: C, B, A, or B, A, C, or A, C, B, and so on. This is because, while operation A might be in progress, operation B might start executing, so both commands will use the same resources and therefore run into a race condition if both operations are not read-only. The Problem From this perspective, the GPU is very powerful because it tries to stay constantly busy, eliminating dead time. However, this greatly complicates things on the synchronization side. Let’s take two operations: operation A that writes an image and operation B that reads the image. How can we be sure that the GPU executes operation A first and not B? Who can assure us that the GPU, while executing A, doesn’t have to execute B? The answer to all these questions is no one. How Graphics APIs Handle All Of This In graphics APIs like OpenGL, all of this is hidden from the programmer, so they don’t have to worry about it. But in graphics APIs like Vulkan and DirectX 12, this is the programmer’s responsibility. The programmer must write a barrier and tell the GPU not to touch the image from operation B before A has finished. For a few barriers, this is feasible, but as soon as you write more complex applications, making the code sufficiently organized, non-repetitive, and fast to develop becomes very challenging. This is why the concept of a Render Graph exists. What A Render Graph Does A Render Graph allows the programmer to specify which steps the GPU should execute, which operations resources like images and textures will perform, and in what order. The Frame Graph looks at this graph constructed by the programmer at each frame and internally understands where barriers and sometimes semaphores are needed (if we’re working with multiple queues, that’s not the case for me). Another responsibility of the Frame Graph is to internally allocate and manage resources that only exist within a single frame, called transient resources. Finally, I’m implementing Memory Aliasing. This reduces the memory used by resources: for example, if resource A is used for the last time in pass 3 and resource B for the first time in pass 4, they can share the same physical memory, thus reducing the overall memory requirement. Bonus I’ve also restructured the texture creation methods, making them simpler and allowing for fewer specifications. The before and after is a good result… The same goes for 1D and 3D textures.
DEVLOG 13 - Memory Aliasing Recap In the last devlog, I explained what I did and why I was creating a Render Graph. I mentioned a concept called Memory Aliasing, but I explained it briefly. I’ve been working extensively on the Render Graph these past few hours to implement the Memory Aliasing algorithm. What is Memory Aliasing? Memory Aliasing involves having two or more resources use the same portions of memory, thus sharing that memory. For example, let’s take a texture we’ll call A. This texture is used as Depth in pass 1 and read in pass 2. Another texture, called B, is used in pass 3 and pass 4 (see photo). We could allocate both resources independently, but you can clearly see that the resources don’t overlap in the passes. Texture A begins its usage cycle in pass 1 and ends in pass 2, and immediately after, in pass 3, texture B is used for the first time. What we could do is have both textures occupy the same memory space to save VRAM. This is the concept of Memory Aliasing. Obviously, since the resources share the same memory space, barriers must be created to synchronize resource access, otherwise there would be a race condition (two threads operating in parallel on the same memory space, not just for read-only operations). Resource Pooling In addition to memory aliasing, I wanted to optimize another aspect that took me some time. In Vulkan, when you want to create resources, you use vkCreateImage and vkCreateBuffer. These functions create a handle without associating physical memory with these objects. Binding occurs later, after executing the memory aliasing algorithm, which determines which memory space to assign to a resource. This means that I have to create and destroy resource handles every frame, which apparently isn’t a light operation to perform on multiple resources. So I thought that if there was a possibility, I could reuse handles from previous frames by simply comparing whether the settings of the requested handle were the same as the one to be reused and then binding the memory. The Problem and the Solution This was the idea I had, but unfortunately it’s not feasible because Vulkan doesn’t allow memory binding to a resource more than once, so this approach wouldn’t have worked. After thinking for a while about how to solve this, I decided to include in the requirements for using old handles, in addition to the texture or buffer settings, the offset and stride of how they were bound in memory. This way, if the pass structure and usage hadn’t changed significantly during the user’s setup phase, the Memory Aliasing algorithm would always produce the same results, given the deterministic nature, making this all feasible. Finally, if the resources aren’t reused for an N number of consecutive frames, they are permanently destroyed.
DEVLOG 14 - I Rewrote The Memory Aliasing Algorithm Intro Unfortunately, I don’t have anything exciting to say. I’m forced to do this devlog since I’ve reached ten hours since my last devlog, so I have to publish one, otherwise my hours wouldn’t count in full. I’ll try to share what I did, the problems I encountered, and how I solved them. The Problem I might sound crazy, but after working on the Render Graph for twenty hours, I rewrote it entirely from scratch. You might ask, why? The reason I did this was Vulkan itself. I discovered that, since I’d previously relied on VMA (Vulkan Memory Allocator) to manage memory, now that I was managing memory without it, there was something I’d overlooked: a parameter called Memory Type Index. The Memory Type Index indicates where to allocate memory. There could be a Memory Type Index for the GPU’s local memory, one for the Resizable BAR, etc. So, what’s the problem if all the Render Graph resources must live exclusively in the GPU’s local memory anyway? Wouldn’t it be enough to simply add a few lines of code and everything would be solved? Unfortunately, not because this index indicates in which memory to allocate that resource, but there’s also another parameter called Memory Type Bits, which is a bitmask that indicates in which Memory Type Indexes a resource can or cannot be allocated. All resources are allocated in the same Memory Type Index, but they may have different Memory Type Bits. This means, for example, that a texture without multi-samples cannot fit in the same memory space as a texture with multi-samples. This can also happen with the aspect mask, so a color texture and a depth texture might not fit in the same place. It could also happen with the format or tiling. The same goes for buffers, but these are more flexible than textures. The Solution My Memory Aliasing algorithm was designed without taking all this into account, so I chose to rewrite a large part of the Render Graph, trying to recycle some parts. Therefore, the Aliasing algorithm now operates on “Buckets,” which are in-memory containers containing resources that can fit in the same space. Without this distinction, memory aliasing wouldn’t be possible because a resource attempting to reuse memory used by previous resources must only check among resources with the same requirements, not among all resources. Therefore, it checks per bucket, not all existing resources. This has also made the code much cleaner and more organized.
DEVLOG 15 - Slang & Render Graph Reorganization So, I’ve been dividing the project into folders, making everything more organized, which wasn’t the case until now. The New Shader Language: Slang I saw that there was a more modern alternative to GLSL I could use, so I chose Slang. I created the code to create it in real time, and then I also changed the architecture of the Pipeline Builder a bit (the class responsible for creating Vulkan’s Pipeline and PipelineLayout objects). Vertex Fetch, Why Did I Choose It? I’ve been thinking for a while about forcing users of the engine to use Vertex Fetch. What is it? Well, normally when using a shader, before the Vertex Shader there’s a phase called Input Assembly that, based on the triangle indices, samples vertices from the vertex buffer, allowing them to be used directly in the Vertex Shader without manual sampling. However, this means that the layout of the vertex buffer must never change; if it were to change, you’d have to create another Pipeline object and bind it. Honestly, I don’t like this limitation very much. That’s why I removed this feature and adopted Vertex Fetch, which allows you to not specify a vertex layout, thus having as few Pipeline objects as possible. Obviously, you have to manually fetch the vertex from the respective buffer in the Vertex Shader, but frankly, it’s not a huge problem. Work In Progress On The Render Graph Another thing I’m implementing is commands that can be sent to the GPU via the Render Graph. So now you can draw, make GPU-GPU copies between buffers, between textures, and even between textures and buffers. Copies currently only support Transient resources; I’ll add the functionality for Persistent resources later. The same goes for using Compute Shaders. I’ve also added the ability to upload data from the CPU to the GPU, again for transient resources. For Persistent resources, I’ll also add this functionality later. I’m still writing the code for this, so I’m not finished yet, but I’m forced to devlog for the usual 10 hours of Stardance…
DEVLOG 16 - Blank Window, Draw Calls & More The last ten hours have been very productive. As the devlog title suggests, I managed to get the classic black window, completed the code for draw calls, and also accomplished many other things. Draw Calls Commands I then completed the code for making draw calls with a simple mesh, integrating all the logic into the Render Graph. If you want to send any command to the GPU—a draw call, a copy, a dispatch, or anything else—it must necessarily go through the Render Graph. This allows me to have a central entity that can manage barriers and commands in a highly optimized, precise, and secure manner. When you want to draw something, you must declare a graphics pass. This pass has methods to execute the drawing commands, but it also has methods to set things like the texture depth/stencil to use, the target texture to draw on, etc. You can also have multiple color targets, as long as they have the same resolution. Blank Window Since I haven’t seen any tangible results on screen for a while, only code, I tried displaying a black window and then initializing the engine. The new context, window, and swapchain builders all work. The Resource Mapper, the class that manages the global descriptor set, also works. Testing the other classes will require a bit more work until I’ve got all the missing pieces, but it’s almost there. Persistent Resources Support Since creating a mesh also involves creating data and sending it to the GPU via buffers, I need a way to upload data from the CPU to the GPU. Mesh buffers are persistent, not transient. Currently, in the Render Graph code, I only had support for copying and uploading transient resources. From now on, this is also available for Persistent resources, as I’ve written the same code for them as well. I also implemented barrier generation for persistent resources so that synchronization is handled internally by the Render Graph, as with transient resources. New Resource Handles Up until now, each resource has been represented as a handle corresponding to an unsigned 32-bit number. From now on, resources are represented by two unsigned 32-bit numbers: one for the previously existing identification number and a generation number. By combining both numbers, each resource is unique, thus eliminating the possibility that if a resource is destroyed and recreated with the same ID, it could be mistaken for an older resource that no longer exists. Project Cleaning I finally cleaned up the project a bit and made it a bit more organized by dividing the files into more specific subfolders.
DEVLOG 17 - Meshes & New Architecture Into See you again, Stardance. I’ve been implementing several things lately, as the title suggests, and I think we might soon have some geometry on the screen. Mesh System I’ve been working on meshes, creating everything needed to support mesh creation, editing, and destruction. Currently, if you create a mesh, you obviously create all the necessary buffers: one for vertex positions, one for normals, one for UVs, etc. So, for example, if I load position data and the buffer doesn’t exist, a new buffer is created and a CPU-GPU upload operation is performed. However, if the buffer exists and its size is greater than the new vertex size, the buffer isn’t reallocated to a smaller size but remains the same, reducing the number of vertices used for drawing. I’m not sure how useful this option is, but I plan to add an option to specify this in the future. Image Presentation Supported I’ve also been working on how to display an image on the screen. Currently, the Render Graph has a method that, given a texture’s Transient handle, sets that texture as the image to display on the screen. Internally, the Render Graph creates a draw pass at the end of all existing passes and then samples from the presentation texture set to draw on the swapchain. The code for all this might be a little rough at the moment; I’ll improve it later. The New Architecture For a while now, I’ve felt like the code was stepping on its own toes. I had a class called MemoryRegistry that was responsible for assigning slots to resources, allocating them, and managing their lifecycle. I didn’t like this, so I decided to rewrite much of it, splitting everything into multiple classes. Now I have a class called ResourceRegistry that provides resource IDs. A class called ResourceMapper that inserts resources into their respective global descriptors. A class called ResourceTracker that manages the resource lifecycle, their last use, which stage they were in, and similar information. Until recently, the MemoryRegistry managed both persistent and transient resources, which was a mess. I’ve decided that the MemoryRegistry should only manage persistent resources, while transient resources should be managed by a class called TransientResourcePool or something similar, which should be managed by the RenderGraph. That’s exactly what I’m working on. Some Stupid Bugs I overran the timeframe because I was partially testing the new code and encountered a stupid bug that made me lose time. (I was iterating an Array starting from the last element, but I forgot to subtract one from the size of the vector assigned to the for loop index, thus causing an out-of-memory access.) I think I’ll also rewrite a good portion of the RenderGraph first to adapt it to the new architecture. Advantages These changes will make developing new features faster and less cumbersome without having to adapt to an architecture that was poorly designed from the start. I swear that after I’ve done all this, I’ll render something to the screen, assuming there are no unforeseen issues ;)
DEVLOG 18 - More Refactoring Hi Stardance! I don’t know what to say about this devlog, since I’ve written a lot of code for my specific implementation… I’ll try to describe what I did without being too boring. Why I refactored again? As discussed in the previous devlog, I felt the code wasn’t “nice” or at least not very tidy, and honestly, I don’t like that very much, so I rewrote the Render Graph (partially) for the third time. Now, the Render Graph only manages single-frame resources, while all multi-frame resources are managed by a separate class called TransientResourcePool, which is therefore responsible for storing the resources. The Render Graph: A single frame responsibility The Render Graph is still responsible for memory aliasing and resource pooling, of course, as well as generating barriers and inserting the draw, copy, and, in the future, compute commands. (I still need to improve the code for compiling commands into the Command Buffers a bit.) Improvement in the searching of pooled resources Now, searching for resources to reuse is even faster, since resources are divided by their composition, for example. For textures, the parameters for this division are height, depth, width, samples, etc. This allows you to immediately find a resource if it’s available. More organization is the TransientResourcePool The TransientResourcePool is also responsible for permanently destroying unused resources for several frames. I had written the destruction code within the TransientResourcePool, but I thought maybe it wasn’t its responsibility, but rather an existing class called MemoryBin. The MemoryBin class was configured to work only for persistent resources, but now it handles the destruction of persistent and transient resources. What I need to fix: There’s a small problem in the code: Normally, when you want to destroy a resource, it’s queued and usually assigned a countdown. This countdown is a number that corresponds to the maximum frames in flight and decreases by one every frame. When this number reaches zero, the resource can be destroyed. This works perfectly, but when, for example, the swapchain needs to be recreated because the window size has changed, the GPU needs to be put into idle mode. This means that all in-flight frames have finished, and therefore all resources queued for destruction can and must be destroyed immediately, otherwise they would pile up. Otherwise, I think everything is perfect. I don’t think it will take me long to implement these little tricks, so I assume and hope :/ to start writing the code to display something on the screen soon. I’ll go back to my old, dear little triangle :)
DEVLOG 19 - Colors! Hi Stardance! I’ve made some progress and finally drew something on the screen! Improvements on the Swapchain Pass I’ve improved the Render Graph a bit by cleaning up old methods and making all the improvements discussed in the last devlog, such as improving the rendering code for the swapchain. Normally, you would set the 2D texture to display on the screen using the RenderGraph::SetPresentTexture(); In reality, this texture isn’t displayed directly on the screen but is first sampled and copied to the swapchain, so the Render Graph adds a hidden pass for this. When this texture hasn’t been assigned to any texture, the swapchain will be colored with the clear value set to black and sent to the screen. Push Constants Supported I’ve added the ability to use Vulkan Push Constants. Push Constants are data packets that can be sent to the GPU in parallel with the drawing command. Their size is very limited, 128 bytes, but their transfer speed is extremely fast. A hardware limitation is that the offset and size parameters must be multiples of four, so I used a struct called Words32 to dictate the 32-bit size and offset, not the 8-bit one. Furthermore, internally, the engine checks the state of the previous push constant for each push constant update, so as not to make unnecessary updates and to register the push constant command only when necessary, and only partially for the relevant bytes. Shaders Improvements I improved the shader code a bit by reducing the arguments needed to create a shader, and I also unified the layout; all shaders use the same VkPipelineLayout . The Problem and The Solution When I was writing the shaders to get these things on screen, I ran into errors telling me I was assigning a buffer descriptor to Descriptor Set 0 with binding 0, even though they’re actually textures. However, in the shader, I wasn’t requesting any of this, since the vertex data was written directly into the shader. After some research, I discovered that Slang shaders were creating bindings for these arrays outside the shader. To fix this, I simply moved the arrays into the vertex shader function, marking them with const. And note that all these images/videos use the swapchain pass, so this was all just a test. Now I’ll have to try declaring a real pass with Render Graph and try to draw something, hoping everything works correctly :/
DEVLOG 20 - A Better Triangle Intro Hi Stardance! This triangle was created with Render Graph . The entire process is divided into two steps: the first draws the triangle on a user-selected image, and the second takes that image, samples it, and draws it on the swapchain so the triangle can be seen on screen. Clean and Simple API The beauty of this is evident in the photo (third attachment). You only need to write a few lines of code to achieve all this compared to the complexity and number of lines of code required by Vulkan. Render Graph thus creates all the resources needed for synchronization, such as barriers , and attempts to alias memory whenever possible. It also leverages Resource Pooling , so images aren’t destroyed and recreated at every frame. Instead, if they have identical requirements, they are reused, avoiding unnecessary Vulkan calls. MSAA Deprecated MSAA images have been deprecated because, from a desktop computer perspective, they aren’t worth using because they require a lot of computational resources. To achieve anti-aliasing, it’s best to use post-processing passes that use FXAA (Fast Approximate Anti-Aliasing) or TAA (Temporal Anti-Aliasing). There are probably some bugs still present in the Render Graph despite the many already fixed; I’ll work on them.
DEVLOG 21 - ECS Refactoring Intro Over the past ten hours, I’ve worked extensively on the ECS , making it more robust, easier to use, more secure, and more efficient. What’s changed: New Way To Record Entity Commands Entity Command Pools are still used, but they’re managed not by the user but by the Entity Manager. The old CreateCommandPool() method no longer exists. Now, to execute a command on entities, you make a request to the EntityManager , which takes the command and places it in an EntityCommandPool of its choosing. The EntityCommandPool is chosen based on the SystemId provided by the engine with methods like Start, Awake, Update, etc. This reduces complexity and allows for systems that can run natively in parallel on multiple threads. Improved Efficiency Internally, the Entity Manager has improved the way to compact batches after command execution, making it simpler and faster. Instead, iterating over all batches only iterates on the entities that are no longer valid, and those slots are refilled with the components of the valid entities at the end of the last batches. Batch creation and destruction is handled automatically by the EntityManager . New Way To Query Tables The way to find tables with certain requirements has improved; the old method required registering a query and then returning a “ticket” used to access the query results. The operation is now simpler and more unified: The EntityManager is asked for all tables that meet the QueryInfo structure requirements, such as the archtype. The EntityManager checks whether the query already exists; if it doesn’t, it calculates it on the fly and returns it. Queries Updated Only When Needed Queries are updated only when tables are created/destroyed; otherwise, they remain - static and aren’t updated, saving calculations . The next step will be to verify if everything works, since I haven’t tested anything yet because I’m forced to do this devlog due to the ten-hour time limit. :/ Sorry about the picture, it’s the same, I didn’t have time to do anything else
DEVLOG 22 - ECS Bugs Fixed, Graphics Files Reorganized Hi Stardance! What I Did In this dev log, I fixed some of the last bugs the ECS code, so it now works and is very efficient. I ran several tests destroying, creating, and moving entities from one archtype to another, and everything works. I then worked on the project structure of the graphics part by fixing the graphics include files. What Went Wrong These updates mentioned so far have been successful. Two hours ago, I added a method in the graphics pass responsible for instanced drawing, so I took advantage of the opportunity to create a buffer to read the instance positions to see if it worked. I still don’t know why, but it doesn’t work. The application freezes, and sometimes the driver crashes (it scared me a little… :/ ). The Validation Layers don’t report anything wrong… So I need to figure out what’s wrong and fix it. The image shows some of the methods available after fixing the folders. The methods are in the Graphics class in the include folder.
DEVLOG 23 - Instanced Draw & Some Fixes Intro Devlog time!! In the last devlog, I had some issues with instanced drawing and reading a position buffer. What Was The Problem? I worked hard, but I managed to figure out where the problem was and fix it. (The problem was due to a for loop responsible for creating the address buffers. I was saving pointers outside the for loop with structs allocated inside the for loop; therefore, the pointers were pointing to corrupted memory or nothing.) Render Graph Fixes I fixed several things in the Render Graph that could cause future problems. I added small guards within the Render Graph so that if the user does something wrong, the application doesn’t crash unexpectedly. For example, previously, if the user set a texture to display that they’d never used (never involved in a transfer operation, never used as a graphic attachment), the program would crash. With these simple guards, everything is solved. Easier Resource Usage Declaration I’ve also added the ability to easily declare textures and buffers usage in the Graphics Pass class with dedicated methods like UseBufferReadOnlyVertex(...) , UseTextureVertex(...) , and others. The image shows a grid of 20x20 quad meshes drawn with a single draw call instead of 400 using instanced draw.
DEVLOG 24 - Error Manager, Copies & More Intro Hi Stardance! Lately, I’ve been focusing mainly on improving error handling returned by Vulkan and fixing some code here and there. New Error Manager System I’ve created a system responsible for error handling so that when an error occurs, such as a failure to allocate memory due to fragmentation or any other critical error, the app places a text file with information about the error in a folder called logs (created on the fly if it doesn’t exist). Immediately afterward, an error message is displayed on the screen explaining what happened. When the user presses the OK button, the app closes in the pop-up by calling std::abort(); . Some Test On Other PCs I tried running Eve outside of my PC on two other PCs, but since they’re a bit older, they don’t have support for Vulkan 1.4, so the app can’t be started. Swapchain Improvements The code for creating the swapchain has been improved somewhat, making it more secure and robust. New Copy Support I’ve added support for buffer and texture copy operations between resources that aren’t the same type (one transient and one persistent). Next Step: I want to make Eve a little more portable, so in the next few hours I’ll try using Vulkan 1.2, trying not to mess with the code. If necessary, I might resort to using Vulkan 1.3; I’ll see…
DEVLOG 25 - Eve is “Multi PC” Hi everyone! What’s changed since last time? More Device Supported As promised, Eve now uses Vulkan 1.2, so it can be used on multiple devices. Obviously, the device requires that, in addition to supporting Vulkan 1.2, it also supports some extensions that became core in Vulkan 1.3. Tests On Other PCs I then tried running the app on the only PC I had at home, but it crashed. I then tried updating the graphics driver, but that didn’t help; unfortunately, that PC is too old. I then asked a friend of mine to test the app. After fixing some issues, it started, but it would crash instantly. After hours of debugging, I found the problem: the problem was in resource allocation within the Render Graph, which only occurred with integrated GPUs (my heap selection algorithm for integrated GPUs was wrong). It’s now fixed. I also added my checks for failed Vulkan or VMA calls in places where they were missing, so now everything should work properly. Math Packet In Eve I also added a small mathematical component to Eve, including Vector2,3,4 ; Vector2Int,3Int,4Int ; Quaternion ; and Matrix4x4 . I must say that quaternions were difficult to understand at first, but once you understand how they work, it’s very easy to visualize them in your head. The first attachment shows Eve running on the PC of this friend of mine, whom I thank so much for his help, and the second image shows Eve running on my PC.
DEVLOG 26 - Input System Hi Stardance! The New Input System Since I couldn’t interact much with the graphics engine at the moment, I chose to create an Input System that currently only supports keyboard and mouse. It has methods like IsKeyDown(...) , GetMouseState(...) , IsMouseUp(...) , and similar ones. It’s quite simple, but it allows you to interact with the world, for example by creating a camera or a moving player. The Cube For fun and to test a bit, I tried creating a scene with a slightly rotated cube with direct light, obviously using my Render Graph, which allows you to do all this in about 150 lines of code (CPU side) instead of having to manually write barriers, configure passes, and many other repetitive tasks. I’m still using glm for matrix math, but I’m trying to reach a more stable level with the Eve package.
DEVLOG 27 - Material System Intro After some code rewrites, such as the separation between shaders and materials, the materials system now works. It’s very similar to how it works in Unity. I’ve figured out how to set things like material properties (floats, integers, vectors, etc.) directly from C++ using their names, without manually binding code. How Vulkan Handle All Of This? In Vulkan, you can’t set a shader parameter directly with a name. You need to create a buffer on the GPU, specifically a UBO, typically used for materials, bind it using a descriptor, and then bind it on the CPU. All of this is hidden by Eve, making the code easier and faster to write. What It Does? Basically, once the shader is compiled, it’s analyzed and checked for a struct called Properties. If it exists, this struct will be used for the material properties. Each field within it will be settable directly from the CPU using its name. Eve, now knowing the size of the struct and the field offsets, creates a buffer for the materials (actually, one for each frame in flight) and uses it to write everything a material might need, thus allowing for very simple parameter setting. How To Use It: The material provides an ID via the GetPropertyUBOId function, which must always be retrieved at each frame since it is not the same from frame to frame. This ID can be sent to the shader via push constant, which then allows access to the material’s property UBO, which contains all the values set on the CPU side. A simple cube rotating on itself using the new Material System and simple direct lighting
DEVLOG 28 - New Render System Hi Stardance! Intro I think this devlog is consistent with the next one I’m working on, since the work I’ve done in the last few hours isn’t quite finished, as there are still some bugs to resolve… Why a new render system? So far, I’ve been working on improving Eve’s rendering system. Instead of having to manually create buffers and the like, Eve has a completely automated system similar to the one used by Unity. For example, when you try to draw an object, you need things like object transformation matrices. If you then need more data, the limited size of push constants is no longer enough. Per Instance Params Eve, therefore, with its new rendering system, revolutionizes the way we write code, reduces bugs, and simplifies it. For each draw call sent to the GPU, the engine sends a buffer called InstanceParams to the GPU, which contains, for each drawing instance, its model matrix and its inverse. These matrices can then be retrieved using simple, custom functions ready for use in the shader. Per Render View Data For camera data, the process is similar. For each RenderView object, Eve allocates these objects on the GPU in a contiguous buffer from which the view, perspective, VP, and other matrices can be accessed. Custom Draw Info Data If you want to send custom data to the shader, each drawing function offers a pointer called DrawInfo that allows you to send data to the shader, which can then be accessed. If set to null, the shader will not send anything. GLM & A Flycam I also created a flycam and deprecated the Eve math package to use the glm one. Honestly, I want to focus on Eve and not the math, which is why I chose this option. Next Step: I still have some bugs to fix regarding making more than one draw call, but I’m working on it.
DEVLOG 29 - 1M Entities! Hi Stardance! Intro Since the last day, I’ve been working alone and have run into several issues… Most of them have been resolved. Some Tests So I started running some tests to check the speed of my new rendering system, and with 100,000 entities drawn to the screen with a single draw call, I was getting 30 FPS. After parallelizing the code a bit and reducing the copies, the results are now better: 100,000 entities with single draw calls get 50-60 FPS. 100,000 entities with a single instanced draw call get 230-250 FPS. 1,000,000 entities with a single instanced draw call get 30 FPS. What Need To Be Optimized Actually, I could optimize even more and double these FPS, but the current problem is that I’m calculating the matrices on the CPU side, so I’m doing a lot of calculations that currently take up a good portion of the necessary CPU time, about 50%. The idea would be to move all the work to the GPU in the future with compute shaders, thus significantly reducing the CPU load. I’ll see if I can do this… Maybe in a while, when I add full support for compute shaders. (I have a Ryzen 5 5600 X and an RX 6600) Rendering System Time: Not counting the matrices, the rendering cycle along with the Render Graph takes about 2-2.5 ms, almost all of which is spent on the Render Graph. I have also fixed some problems with Swapchain Recreation when the window is minimized. Problems With RenderDoc Five of these eight hours have been pure frustration, as I don’t understand why, but the app crashes on RenderDoc. Normally, on my PC it starts and works, but on RenderDoc it crashes… I’ve tried every way to understand the problem, but unfortunately I haven’t been able to. I’ll also test on other PCs to better understand the problem. Unfortunately, I don’t have time on my side, so I’ve had to put the issue aside for now…
DEVLOG 30 - Compute Shaders Hi Stardance! Intro I’ve finally implemented compute shaders—as the title suggests—alongside conducting some tests and reorganizing the project. Compute Shader Support I’ve added support for compute shaders, meaning they can now be used just like any other type of pass, whether graphics or transfer. Optimizations I’ve also utilized compute shaders internally within the engine to speed up matrix calculations; here are the results: With 100,000 entities using instanced rendering, I’m getting 800 FPS, up from the previous 250. With 1,000,000 entities using instanced rendering, I’m getting around 90 FPS, up from the previous 30. With 100,000 entities using independent draw calls, I’m getting around 90 FPS, up from the previous 30. I’d say the results speak for themselves, and I’m quite happy with these optimizations. As mentioned in the previous devlog, testing was performed on my PC, which is equipped with a Ryzen 5 5600X and an RX 6600. Swapchain & CMake I also made slight modifications to the swapchain recreation code to make it faster and reduce stuttering. Finally, I tidied up the CMakeLists file to make it more organized and prepare for the release. The video shows a scene with 1M entities rendered in real-time using instanced draw call at 90 FPS
DEVLOG 31 - It’s not my fault! Hi Stardance! Unlike the other devlogs, this one is very quick and simple. A Little Recap In devlog 29, I encountered some issues with RenderDoc, even though the app kept running fine and caused no problems outside of RenderDoc itself. What I Did After doing some online research, I discovered that RenderDoc has issues with AMD drivers, which can cause the app to crash. So, I decided to try AMD’s Radeon Developer Tools (a profiler similar to RenderDoc, designed specifically for AMD GPUs). No errors were reported and everything works perfectly, so the problem most likely lies in how AMD drivers interface with RenderDoc.
DEVLOG 32 - UI Support Hi Stardance, Intro I’ve been working on the UI lately, as I wanted to give the user a way to interact with the engine beyond just mouse and keyboard input. The UI in Eve I opted for Dear ImGui and created a lightweight wrapper that allows it to run within Eve. I stripped away some of the boilerplate code associated with the standard Begin and End calls, making it slightly simpler and safer to use than raw ImGui. I also added support for dockable windows. The video shows a scene with 1,000 cubes; thanks to the UI, you can modify their color, position, and rotation. You can also change the direction of the direct light. The code required by this UI is just five lines.
DEVLOG 33 - Meshes & Fixes Hi Stardance! Intro We’re getting closer to the release build of Eve! I have to say that with this devlog, the engine is practically finished and ready for shipping; I just need to tweak a few final details and we’re all set… Meshes: In this devlog, I worked on the mesh system—fleshing it out and making it functional—and added standard meshes to Eve: a cube, a UV sphere, an icosphere, a plane, and a quad. Some Bugs Fixed While implementing this, the program kept crashing for no apparent reason; after two hours of debugging, I found the error in the Render Graph—caused by the order of Eve’s internal passes—which is now fixed. Internal Shaders Organization I also embedded the engine’s internal shaders directly into the executable, so there’s no need to remember to include them alongside the executable when creating an app. The video shows the same UI as the previous devlog—featuring controls for color, rotation, cube position, and direct light direction—but this time, you can change the meshes of the “thousand-odd” cubes at runtime using the standard Eve meshes listed above, via a simple UI dropdown menu.
DEVLOG 34 - Icon, Windows & More Hi Stardance! Intro The release is getting close, so I’m tidying up a few final details; I’ve finally turned my attention to a slightly more relaxed and lighthearted part of the project. Engine Settings I added a method to start the engine that accepts configuration settings for how the app runs. You can also choose whether or not to enable VSync at runtime. Window Class I added a window management class that allows for various operations, such as toggling fullscreen mode and manually changing the resolution, position, title, etc. I also included a method to set the window icon using a PNG image. Eve’s Icon I also spent some time on Canva trying to create an icon—a logo—for Eve. After several attempts, I settled on the one in the attachment.
DEVLOG 35 - Documentation Hi Stardance! Intro I’ve finally finished writing the documentation for Eve—a rather tedious and repetitive process, but a necessary one. How The Docs Is Structured: Every part of the engine is documented; inside the docs folder, you’ll find instructions on how to launch the engine, along with subfolders for each component—graphics, input, window management, and so on. Next Last Steps: I still need to create the README and tidy up a few things in the project, as well as write instructions on how to configure Eve for use on one’s own PC… But after a whole summer, I’m finally close to shipping!
DEVLOG 36 - Black Hole! Hi Stardance! Intro I’ve been working really hard lately, and I think I’ve reached a milestone with Eve that I honestly never expected to hit. The project is finally complete; now I just need to click that nice button to ship it. I’ve spent this time working on the README, improving the documentation, fixing bugs, and building a demo using Eve. Eve Demo The demo is a gravity simulation featuring hundreds of thousands of entities orbiting a black hole. You can tweak various parameters—such as time, the black hole’s gravitational pull, lighting, colors, meshes, and much more. If you’d like to test it out, you can find it in the GitHub releases; there’s a ready-to-use .exe, or the source code if you’re on Linux—or if you simply want to understand how Eve works or make some modifications yourself. Problems Encountered While building the demo, I ran into—and have since resolved—some very frustrating bugs, such as memory corruption in the ECS caused by the continuous creation and destruction of entities and their components. I also added UI text support and implemented the ability to register “stages” belonging to classes or structs that can be called by the engine.
Ships:
Eve is a graphics engine written entirely in Vulkan , with the primary goal of learning Vulkan and C++ while simplifying their usage. Originally conceived as a simple, lightweight wrapper around Vulkan , Eve now includes: A Render Graph designed from scratch that leverages technologies such as memory aliasing (where multiple resources share the same memory space) and resource pooling (reusing resources across frames). It performs the core function of a Render Graph: by simply knowing how resources are utilized, it automatically issues the necessary synchronization barriers to the GPU. Developing the Render Graph was a grueling process, but it proved worthwhile in terms of both performance and the educational value of the experience. An ECS (Entity Component System) also designed from scratch, following the model of Unity’s DOTS ECS . Instead of scattering resources across VRAM—which slows down access due to constant memory jumps—game objects are organized into Archetypes. Components are distributed in contiguous memory batches, thereby minimizing cache misses. A rendering system that automates the insertion of transforms into buffers; these are subsequently processed into matrices via a compute shader and sent to the rendering shaders. It also features a material system that analyzes shader composition, looking for a struct named “Properties” that allows fields to be assigned by name from the C++ side. Support for the Slang shading language with a bindless system . Eve provides a file named Eve.slangh that simplifies and automates the retrieval of textures, buffers, and samplers from descriptors. Compute shader support is also included. An integrated, easy-to-use Input system inspired by Unity’s Input System , along with a lightweight UI wrapper that makes using Dear ImGui simpler and more intuitive. Eve also includes a demo featuring a gravitational simulation of thousands of entities orbiting a black hole, allowing various parameters to be adjusted in real-time....
|
1793008124.1295273
|
1793094524.1295273
|
|
53903
|
MechSim by @rayzchen | Stardance
|
rayzchen
|
1
|
34.0
|
667
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-21T11:26:58Z", "hours": 34.0, "multiplier": 19.88, "payout": 667, "blessing": "neutral", "text": "MechSim MechSim is a mechanical system simulator that uses Lagrangian mechanics and Runge-Kutta methods to simulate various constrained systems. From expressions of energy it is capable of deriving equations of motion using symbolic differentiation and then stepping through them in time to simulate the motion of the system. How to use The homepage has links to each of the system simulator pages. Each page has an energy label and diagram, playback buttons and sometimes system equations. The Rolling Disk Pendulum has equations of motion too complex to display on the screen. There is also a button to view the Python system file that creates the solver. The page runs best on a landscape desktop orientation. Code structure The project is written in both Python and JavaScript: the main Lagrangian system solver uses Python for its polymorphism and flexible OOP, while the renderer uses JS to efficiently draw the system and update the GUI. Minimal external dependencies are used, so almost all of the code has been written from scratch. Neither component uses nor requires the internals of the other: the system solver simply outputs a few numbers representing the phase state of the system, and the renderer uses those numbers to calculate the positions of objects to draw. Challenges One of the first major issues encountered was how to simplify expressions. Many of the basic rules in algebra are rather complicated to systematically apply, such as collecting like terms or using index laws. In fact, since the expressions obtained from the Euler-Lagrange equations are of a specific format, this symbolic differentiation engine is not fully-featured. Another detail that required significant attention was how to embed Python into a JavaScript powered webpage. The library used for this, PyScript, has two different Python interpreters: Pyodide and MicroPython, the latter of which is 37x smaller in size. The symbolic differentiation engine does not require any external dependencies, but the RK4 time stepper does use NumPy, which is not available on MicroPython. This meant that much of the code needed to be rewritten using ulab, the MicroPython equivalent. In addition to this, many of the CPython-specific implementation details were different, such as dictionary key order and hash function limitations, had varying behaviour on MicroPython and had to be taken account of. One of the techniques I used was dynamically creating each simulation webpage entirely using JavaScript without any frameworks such as jQuery. This meant that each simulation would have almost identical HTML and simply differing diagram drawing JS, which made adding new simulations a matter of copying the template code and editing the rendering script. Merits The system code is extremely intuitive to the point where even non-programmers should be capable of understanding how the system is set up. The most complex system, the Rolling Disk Pendulum, has no less than 7 components exerting classical forces on each other, but the Euler-Lagrange equations convert this simply to a set of simultaneous equations that can be solved instantly for individual accelerations. This results in fluid motion appearing on the screen, no matter how chaotic the system is.", "repo": "https://github.com/rayzchen/mechsim", "demo": "https://rayzchen.github.io/mechsim/"}]...
|
[{"post_id": 71486, "ts": "202 [{"post_id": 71486, "ts": "2026-09-20T22:10:29Z", "hours": 0.3753, "text": "Final fixes Changed the behaviour of the playback button icons to keep sync with the simulation. Also fixed a layering issue in the CSS. The project should now be ready to ship! Temporary deployments can be found at https://rayzchen.github.io/mechsim/"}, {"post_id": 70744, "ts": "2026-09-19T18:11:01Z", "hours": 0.8522, "text": "Playback Controls Added reset, play/pause and step buttons! Temporary deployments can be found at https://rayzchen.github.io/mechsim/"}, {"post_id": 70180, "ts": "2026-09-18T17:06:37Z", "hours": 0.7183, "text": "Energy Bar Added a bar on the left to graphically show the ratio between kinetic and potential energies (the faster things are moving, the more light grey there is). Temporary deployments can be found at https://rayzchen.github.io/mechsim/"}, {"post_id": 70158, "ts": "2026-09-18T16:19:19Z", "hours": 0.7106, "text": "Homepage! Finally able to navigate through the six simulation systems from one place 🔥🔥 Had to wrestle with CSS flexbox and transitions to make nice animations! Temporary deployments can be found at https://rayzchen.github.io/mechsim/"}, {"post_id": 69204, "ts": "2026-09-16T16:21:41Z", "hours": 0.9172, "text": "Cart + Pendulum Added a simple cart and pendulum system, and realised the internal rotation angles were COMPLETELY opposite… Spent half an hour of unlogged time just to find out that all of the systems were symmetric in angles except ONE which had a wrong sign in the rendering code, making it LOOK symmetric… Fixed that without too much of a headache once found :D"}, {"post_id": 69138, "ts": "2026-09-16T13:30:59Z", "hours": 1.0844, "text": "System file viewer Added a button to view the Python code that sets up the physical system. Temporary deployments can be found at https://rayzchen.github.io/mechsim/"}, {"post_id": 65038, "ts": "2026-09-09T20:59:17Z", "hours": 0.6514, "text": "More simulations New simulations added: Swinging Atwood Machine Ball on Slope Simple Pendulum Temporary deployments can be found at https://rayzchen.github.io/mechsim/"}, {"post_id": 64996, "ts": "2026-09-09T19:25:27Z", "hours": 0.8075, "text": "Website structure rewrite To make adding new simulations easier, I restructured the file layout and added more dynamic code to the shared JS to create the elements required rather than copy pasting everything in every file. Also added labels to the tab title and bottom right corner. Also rewrote the drawing code for the rolling disk to add more details. Temporary deployments can be found at https://rayzchen.github.io/mechsim/disk/"}, {"post_id": 56937, "ts": "2026-08-28T23:23:50Z", "hours": 4.4119, "text": "Complex System Demo This system contains a semicircular anulus rocking on a rough plane, with a circular disk inside attached to a compound pendulum, and constrained with three springs. Adjusting the parameters took an awfully long time… Temporary deployments can be found at https://rayzchen.github.io/mechsim/disk.html"}, {"post_id": 56254, "ts": "2026-08-27T22:49:48Z", "hours": 5.4453, "text": "Circular Disks After much headache, two new constraints have been implemented: disk rolling on a plane and disk rolling in a circle. There were also lots of bugs in the LaTeX output, which I just kept encountering one by one, but hopefully they should now all be fixed. Temporary deployments can be found at https://rayzchen.github.io/mechsim/disk.html"}, {"post_id": 55340, "ts": "2026-08-27T02:46:15Z", "hours": 1.0178, "text": "GitHub deployment Temporary deployments can be found at https://rayzchen.github.io/mechsim/pend.html"}, {"post_id": 55304, "ts": "2026-08-27T01:35:48Z", "hours": 5.4156, "text": "LaTeX and more simplification This devlog was supposed to be two separate ones, but Stardance was refusing to calculate logged hours :( There’s a big list of changes here: Added a label to show kinetic and potential energies (and demonstrating conservation of energy!) Finally implemented combining like terms (3x + 2x = 5x) and like powers (sin(x) * sin(x) = sin^2(x)), which provides a huge speed increase since the equations of motion are now simpler Fixed a BUNCH of bugs that were cropping up under MicroPython (annoyingly CPython’s dict keys in order of assignment is an implementation detail that isn’t in MicroPython, and the hashing function in MicroPython is completely unreliable) Added LaTeX mode for converting expressions into strings, which automatically handles subscripts and symbols Added labels to the diagram also with LaTeX, tweaked for visibility"}, {"post_id": 55177, "ts": "2026-08-26T17:39:33Z", "hours": 3.4461, "text": "Officially brought to web! I had to wrestle with PyScript for an incredibly long time, but it’s finally running smoothly! Two big changes to the code are: micropython support, which runs and loads SO much faster than Pyodide (but meant I had to rewrite itertools.product and np.linalg.solve) helper classes to create a mechanical system and create energy formulae, which abstracts the math away into much more of an intuitive system! The code for setting up the system gets simpler and simpler each time…"}, {"post_id": 55036, "ts": "2026-08-26T13:50:10Z", "hours": 0.8836, "text": "PyScript testing Spent some time reading through the documentation of PyScript ( https://pyscript.net/ ) to see how well the code will run in the browser. Got the double pendulum code to run in the browser, and I will start writing a full demo soon."}, {"post_id": 54584, "ts": "2026-08-25T16:39:49Z", "hours": 1.2239, "text": "RK4 solver class I have implemented a class that handles solving, susbtitution and iteration of a system from the lagrangian and tested it with a pendulum-cart setup like the one found at https://www.myphysicslab.com/pendulum/cart-pendulum-en.html ."}, {"post_id": 54508, "ts": "2026-08-25T15:12:57Z", "hours": 1.5611, "text": "Better syntax and other tests The expressions can now be written in a much simpler syntax, making it easier to read! Below is also a test run simulating the angle of a rocking semicircle."}, {"post_id": 54158, "ts": "2026-08-25T00:26:04Z", "hours": 0.7797, "text": "Optimisations The old code used to substitute values and perform thousands of simplifications when they weren’t even necessary. Now the values are directly calculated, resulting in much better execution times."}, {"post_id": 54130, "ts": "2026-08-24T23:11:27Z", "hours": 1.7872, "text": "More complicated math The solver can now handle sin and cos, as well as expanding brackets! Also added the equation of motion solver to obtain a value for acceleration. Tested with a different rendering tool with a double pendulum setup. I will eventually create my own simulation using more math and rendering, this window is not part of the project. TODO: collecting like terms and cancelling down, optimising value substitution"}, {"post_id": 54084, "ts": "2026-08-24T21:19:34Z", "hours": 1.0189, "text": "Differentiation! The symbol engine is now capable of performing partial differentiation with respect to any variable, allowing the use of Euler-Lagrange to form differential equations. See https://en.wikipedia.org/wiki/Euler%E2%80%93Lagrange_equation"}, {"post_id": 54050, "ts": "2026-08-24T20:14:45Z", "hours": 0.4261, "text": "Basic expression manipulation The goal of this project is to write a library that can perform symbolic differentiation and solve for an “equation of motion” which can be used to run a simulation. The code for substituting variables is now complete. Here is a sample of how the substitution works."}]...
|
Title: MechSim by @rayzchen | Stardance
Devlogs:
Title: MechSim by @rayzchen | Stardance
Devlogs:
Basic expression manipulation The goal of this project is to write a library that can perform symbolic differentiation and solve for an “equation of motion” which can be used to run a simulation. The code for substituting variables is now complete. Here is a sample of how the substitution works.
Differentiation! The symbol engine is now capable of performing partial differentiation with respect to any variable, allowing the use of Euler-Lagrange to form differential equations. See https://en.wikipedia.org/wiki/Euler%E2%80%93Lagrange_equation
More complicated math The solver can now handle sin and cos, as well as expanding brackets! Also added the equation of motion solver to obtain a value for acceleration. Tested with a different rendering tool with a double pendulum setup. I will eventually create my own simulation using more math and rendering, this window is not part of the project. TODO: collecting like terms and cancelling down, optimising value substitution
Optimisations The old code used to substitute values and perform thousands of simplifications when they weren’t even necessary. Now the values are directly calculated, resulting in much better execution times.
Better syntax and other tests The expressions can now be written in a much simpler syntax, making it easier to read! Below is also a test run simulating the angle of a rocking semicircle.
RK4 solver class I have implemented a class that handles solving, susbtitution and iteration of a system from the lagrangian and tested it with a pendulum-cart setup like the one found at https://www.myphysicslab.com/pendulum/cart-pendulum-en.html .
PyScript testing Spent some time reading through the documentation of PyScript ( https://pyscript.net/ ) to see how well the code will run in the browser. Got the double pendulum code to run in the browser, and I will start writing a full demo soon.
Officially brought to web! I had to wrestle with PyScript for an incredibly long time, but it’s finally running smoothly! Two big changes to the code are: micropython support, which runs and loads SO much faster than Pyodide (but meant I had to rewrite itertools.product and np.linalg.solve) helper classes to create a mechanical system and create energy formulae, which abstracts the math away into much more of an intuitive system! The code for setting up the system gets simpler and simpler each time…
LaTeX and more simplification This devlog was supposed to be two separate ones, but Stardance was refusing to calculate logged hours :( There’s a big list of changes here: Added a label to show kinetic and potential energies (and demonstrating conservation of energy!) Finally implemented combining like terms (3x + 2x = 5x) and like powers (sin(x) * sin(x) = sin^2(x)), which provides a huge speed increase since the equations of motion are now simpler Fixed a BUNCH of bugs that were cropping up under MicroPython (annoyingly CPython’s dict keys in order of assignment is an implementation detail that isn’t in MicroPython, and the hashing function in MicroPython is completely unreliable) Added LaTeX mode for converting expressions into strings, which automatically handles subscripts and symbols Added labels to the diagram also with LaTeX, tweaked for visibility
GitHub deployment Temporary deployments can be found at https://rayzchen.github.io/mechsim/pend.html
Circular Disks After much headache, two new constraints have been implemented: disk rolling on a plane and disk rolling in a circle. There were also lots of bugs in the LaTeX output, which I just kept encountering one by one, but hopefully they should now all be fixed. Temporary deployments can be found at https://rayzchen.github.io/mechsim/disk.html
Complex System Demo This system contains a semicircular anulus rocking on a rough plane, with a circular disk inside attached to a compound pendulum, and constrained with three springs. Adjusting the parameters took an awfully long time… Temporary deployments can be found at https://rayzchen.github.io/mechsim/disk.html
Website structure rewrite To make adding new simulations easier, I restructured the file layout and added more dynamic code to the shared JS to create the elements required rather than copy pasting everything in every file. Also added labels to the tab title and bottom right corner. Also rewrote the drawing code for the rolling disk to add more details. Temporary deployments can be found at https://rayzchen.github.io/mechsim/disk/
More simulations New simulations added: Swinging Atwood Machine Ball on Slope Simple Pendulum Temporary deployments can be found at https://rayzchen.github.io/mechsim/
System file viewer Added a button to view the Python code that sets up the physical system. Temporary deployments can be found at https://rayzchen.github.io/mechsim/
Cart + Pendulum Added a simple cart and pendulum system, and realised the internal rotation angles were COMPLETELY opposite… Spent half an hour of unlogged time just to find out that all of the systems were symmetric in angles except ONE which had a wrong sign in the rendering code, making it LOOK symmetric… Fixed that without too much of a headache once found :D
Homepage! Finally able to navigate through the six simulation systems from one place 🔥🔥 Had to wrestle with CSS flexbox and transitions to make nice animations! Temporary deployments can be found at https://rayzchen.github.io/mechsim/
Energy Bar Added a bar on the left to graphically show the ratio between kinetic and potential energies (the faster things are moving, the more light grey there is). Temporary deployments can be found at https://rayzchen.github.io/mechsim/
Playback Controls Added reset, play/pause and step buttons! Temporary deployments can be found at https://rayzchen.github.io/mechsim/
Final fixes Changed the behaviour of the playback button icons to keep sync with the simulation. Also fixed a layering issue in the CSS. The project should now be ready to ship! Temporary deployments can be found at https://rayzchen.github.io/mechsim/
Ships:
MechSim MechSim is a mechanical system simulator that uses Lagrangian mechanics and Runge-Kutta methods to simulate various constrained systems. From expressions of energy it is capable of deriving equations of motion using symbolic differentiation and then stepping through them in time to simulate the motion of the system. How to use The homepage has links to each of the system simulator pages. Each page has an energy label and diagram, playback buttons and sometimes system equations. The Rolling Disk Pendulum has equations of motion too complex to display on the screen. There is also a button to view the Python system file that creates the solver. The page runs best on a landscape desktop orientation. Code structure The project is written in both Python and JavaScript: the main Lagrangian system solver uses Python for its polymorphism and flexible OOP, while the renderer uses JS to efficiently draw the system and update the GUI. Minimal external dependencies are used, so almost all of the code has been written from scratch. Neither component uses nor requires the internals of the other: the system solver simply outputs a few numbers representing the phase state of the system, and the renderer uses those numbers to calculate the positions of objects to draw. Challenges One of the first major issues encountered was how to simplify expressions. Many of the basic rules in algebra are rather complicated to systematically apply, such as collecting like terms or using index laws. In fact, since the expressions obtained from the Euler-Lagrange equations are of a specific format, this symbolic differentiation engine is not fully-featured. Another detail that required significant attention was how to embed Python into a JavaScript powered webpage. The library used for this, PyScript, has two different Python interpreters: Pyodide and MicroPython, the latter of which is 37x smaller in size. The symbolic differentiation engine does not require any external dependencies, but the RK4 time stepper does use NumPy, which is not available on MicroPython. This meant that much of the code needed to be rewritten using ulab, the MicroPython equivalent. In addition to this, many of the CPython-specific implementation details were different, such as dictionary key order and hash function limitations, had varying behaviour on MicroPython and had to be taken account of. One of the techniques I used was dynamically creating each simulation webpage entirely using JavaScript without any frameworks such as jQuery. This meant that each simulation would have almost identical HTML and simply differing diagram drawing JS, which made adding new simulations a matter of copying the template code and editing the rendering script. Merits The system code is extremely intuitive to the point where even non-programmers should be capable of understanding how the system is set up. The most complex system, the Rolling Disk Pendulum, has no less than 7 components exerting classical forces on each other, but the Euler-Lagrange equations convert this simply to a set of simultaneous equations that can be solved instantly for individual accelerations. This results in fluid motion appearing on the screen, no matter how chaotic the system is....
|
1793008125.6508908
|
1793094525.6508908
|
|
58752
|
cool personal site by @dakshsharma | Stardance
|
dakshsharma
|
1
|
3.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-20T14:22:34Z", "hours": 3.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Made a cool personal site! You can go to my github or linkedin by clicking the button(this js was so hard to do). I like the css. I was learning all of these for the first time really in this project!", "repo": "https://github.com/DakshSharma304/cool-personal-site", "demo": "https://dakshs.vercel.app"}]...
|
[{"post_id": 70948, "ts": "202 [{"post_id": 70948, "ts": "2026-09-20T02:52:12Z", "hours": 3.185, "text": "very cool personal site!!! you can click on the buttons AND THEY TAKE YOU TO THE WEBPAGE!!!(like github button to my github profile) very aura graphics future plans to add like mechanism where i can write text and post updates heehee link dakshs.vercel.app"}]...
|
Title: cool personal site by @dakshsharma | Starda Title: cool personal site by @dakshsharma | Stardance
Devlogs:
very cool personal site!!! you can click on the buttons AND THEY TAKE YOU TO THE WEBPAGE!!!(like github button to my github profile) very aura graphics future plans to add like mechanism where i can write text and post updates heehee link dakshs.vercel.app
Ships:
Made a cool personal site! You can go to my github or linkedin by clicking the button(this js was so hard to do). I like the css. I was learning all of these for the first time really in this project!...
|
1793008126.8507667
|
1793094526.8507667
|
|
58792
|
rememberance by @Tyo | Stardance
|
Tyo
|
1
|
25.0
|
331
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-27T14:28:52Z", "hours": 25.0, "multiplier": 13.41, "payout": 331, "blessing": "neutral", "text": "Remember me~ Oh shoot! Rememberance!~ Is a game I had in a dream!~ Imagine you had the biggest amnesia that you don’t even remember your name! Well then, 24 hours, find it, find other information about you and confront God!! Maybe?", "repo": "https://github.com/SteelyxEpic/Rememberance", "demo": "https://tyoepic.itch.io/rememberance"}]...
|
[{"post_id": 74487, "ts": "202 [{"post_id": 74487, "ts": "2026-09-27T14:23:34Z", "hours": 1.5094, "text": "It’s finally done! The ending, the VA, the everything! YESS, I can finally slep _"}, {"post_id": 73622, "ts": "2026-09-25T14:44:04Z", "hours": 8.2239, "text": "ARGHHHH, it’s been a week!~ and I’ve been busy adding all the voicelines and LOREEE into the gamee!~~~ All I need more is to do some more polishing and package it up into a sweet deal! p.s stardance is continuing until october! which means more time to finish this project!!! (I’m genuinely so burned out :p)"}, {"post_id": 69044, "ts": "2026-09-16T08:34:45Z", "hours": 2.3375, "text": "Quick break to add a lil bit of Sound effect!~~~ Okie that’s all, back to making the LOREEEE. Hehe~"}, {"post_id": 68951, "ts": "2026-09-16T03:12:18Z", "hours": 2.2036, "text": "The last room!!!! The last room has been added and therefore it’s now finally time to add contenttttt! Yey!~~~ <3 The plan is simple, you find notes, cassettes and other items to piece together who you are. Then when the day ends, God will ask for who you are, answer right and you wake from this nightmare. Answer wrong and you will dwell in eternity…. OMG I can’t wait to add all the LORE (if you can’t tell, I love game theory hehe~ :3) okie bai!"}, {"post_id": 67080, "ts": "2026-09-13T04:04:09Z", "hours": 1.5656, "text": "Hi Hi!~~~ Kinda small today but I just really wanna show you guys what I did!!!! I finally made the mirrors workinggggg!!!!! AND I LOVE IT <3 it’s exactly how I imagined the mirrors to act!!! Anyways, that’s all!~ I’m gonna go actually make the puzzles now. Bai~~"}, {"post_id": 66563, "ts": "2026-09-12T12:17:25Z", "hours": 3.0983, "text": "Woah! More kewl stuff!~ The lights are still out but I have reached an agreement, this game is like a rougelite, however the only thing carried over is information on yourself, and within 7 days, you have to have all the information about yourself. Yea! Keys are universal in this so it can unlock any type of door or other containers. That’s all, cya!~"}, {"post_id": 66002, "ts": "2026-09-11T14:56:46Z", "hours": 2.3408, "text": "Another day, another something I wanted to add! This time it’s the really cool Interaction circle. I thought it would be fun to add it and also allows me to be able to help in a lot of things like, using items in the future wink wink anyways that’s all! I think I wanna try my hands on something more extraterrestrial next, hehe~ cya! <3"}, {"post_id": 64612, "ts": "2026-09-09T04:08:46Z", "hours": 3.4489, "text": "Time for something new! I had this idea since I started godot while making the best minigame game ever (true to title :3) so I’m doing it now!~ I started off with this ominous little safe that took me much longer than I expected to make and also a bunch of artwork!~ (like 30 different drawings :p) hopefully the rest of the parts would be smooth sailing and I can finally make the game of my dreams (literally! Hehe~)"}]...
|
Title: rememberance by @Tyo | Stardance
Devlogs:
Title: rememberance by @Tyo | Stardance
Devlogs:
Time for something new! I had this idea since I started godot while making the best minigame game ever (true to title :3) so I’m doing it now!~ I started off with this ominous little safe that took me much longer than I expected to make and also a bunch of artwork!~ (like 30 different drawings :p) hopefully the rest of the parts would be smooth sailing and I can finally make the game of my dreams (literally! Hehe~)
Another day, another something I wanted to add! This time it’s the really cool Interaction circle. I thought it would be fun to add it and also allows me to be able to help in a lot of things like, using items in the future wink wink anyways that’s all! I think I wanna try my hands on something more extraterrestrial next, hehe~ cya! <3
Woah! More kewl stuff!~ The lights are still out but I have reached an agreement, this game is like a rougelite, however the only thing carried over is information on yourself, and within 7 days, you have to have all the information about yourself. Yea! Keys are universal in this so it can unlock any type of door or other containers. That’s all, cya!~
Hi Hi!~~~ Kinda small today but I just really wanna show you guys what I did!!!! I finally made the mirrors workinggggg!!!!! AND I LOVE IT <3 it’s exactly how I imagined the mirrors to act!!! Anyways, that’s all!~ I’m gonna go actually make the puzzles now. Bai~~
The last room!!!! The last room has been added and therefore it’s now finally time to add contenttttt! Yey!~~~ <3 The plan is simple, you find notes, cassettes and other items to piece together who you are. Then when the day ends, God will ask for who you are, answer right and you wake from this nightmare. Answer wrong and you will dwell in eternity…. OMG I can’t wait to add all the LORE (if you can’t tell, I love game theory hehe~ :3) okie bai!
Quick break to add a lil bit of Sound effect!~~~ Okie that’s all, back to making the LOREEEE. Hehe~
ARGHHHH, it’s been a week!~ and I’ve been busy adding all the voicelines and LOREEE into the gamee!~~~ All I need more is to do some more polishing and package it up into a sweet deal! p.s stardance is continuing until october! which means more time to finish this project!!! (I’m genuinely so burned out :p)
It’s finally done! The ending, the VA, the everything! YESS, I can finally slep _
Ships:
Remember me~ Oh shoot! Rememberance!~ Is a game I had in a dream!~ Imagine you had the biggest amnesia that you don’t even remember your name! Well then, 24 hours, find it, find other information about you and confront God!! Maybe?...
|
1793008127.7789595
|
1793094527.7789595
|
|
25598
|
itinerarey by @nate | Stardance
|
nate
|
1
|
25.0
|
369
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-25T03:25:36Z", "hours": 25.0, "multiplier": 14.57, "payout": 369, "blessing": "neutral", "text": "Itinerarey is the better way to plan out your trips! When getting ready for a vacation, it can be incredibly stressful to plan out flights, hotels, activities, and more! So, I built itinerarey to make it a bit easier! It uses APIs and web scrapers to compile information from across the internet to have a centralized place to get information. The most challenging part of Itinerarey was the flights and hotels system. There are no free APIs (with good limits) for showing either, so I had to get a bit creative and spend a few hours researching. The flights system runs by contacting an API that runs a python web scraper that is hosted on Render, while the hotels call from an online Booking.com scraper. I am really proud of the recap page, mainly. To me, it feels like a representation of the entire project in its entireity. It shows everything the user did, and it works as a confirmation of every system performing as it should. For testing, please be aware that the render server mmight take up to a minute to load up. Also, due to web scraping being a bit finnicky, some results might not show up. If this happens, try clearing your localstorage and using a new destination. Enjoy your vacations! -nate", "repo": "https://github.com/Np3-0/itinerarey", "demo": "https://itinerarey.vercel.app/"}]...
|
[{"post_id": 73441, "ts": "202 [{"post_id": 73441, "ts": "2026-09-25T03:12:47Z", "hours": 3.2119, "text": "Itinerarey is complete! The last thing that I needed to get done was the recap page, which takes all the data in your localstorage and displays it for you! I had to rewrite how the flights and hotels are displayed to show the booking links, but overall it was pretty simple. The main thing that I am proud of is the budget tracker, which shows the prices for everything, including how much is leftover in the budget! This is done with some pretty simple math, but it definitely ties the project together. Lastly, the user can save a copy of this page to their computer. They can then also reset their localstorage to create a brand new trip! Lastly, I got the readme and license done (id take a look if I were you!), and finished deploying everything on vercel. Overall, I am really happy with how Itinerarey came out. I learned a lot about web scrapping and hosting websites from this project, which I hope will come in handy in the future! Thank you all for the support, stardance has been incredible! feel free to dm me in slack! - nate"}, {"post_id": 72073, "ts": "2026-09-22T03:31:50Z", "hours": 3.2789, "text": "The activities portion of the website is done! I did some research, and it turns out that the best way for me to find information on local events is AI! The way it works is by using Google Gemini along with Zod, which allows me to format my API requests to return in JSON. Since it has the same information each time, I can then just treat it as a regular API call. However, I might change it and put this on the backend to try to hide the API key. Anyways, we are almost at the end! The last major portion of the project is the recap page, where I plan to show all info on the trip, let users download, and maybe more! Today went pretty well, and I am excited to finally get this thing done."}, {"post_id": 70976, "ts": "2026-09-20T04:34:37Z", "hours": 3.3614, "text": "So… quick update, I tore my ACL! havent really been able to do much since, but today I sat down and got work done. Mainly, I got the hotels done! It works pretty similar to flights system, where the user is prompted with a list, and they choose whichever they want. Now, if you remember, I have been struggling with finding a hotel API, since amadeus shut down. Originally, the plan was rapidAPI, but the rate limits are horrid for that. After some very intense googling, I found omkar.cloud ! They have a bunch of web scrappers with a 200/month limit, so their booking.com API works perfectly. I genuinely was considering dropping the project from this, and I am so happy I found something that worked. Now, the future. There is like 10 days left in stardance, and I need to do the activities, final page, and fix deployment. Activities shouldn’t be that dificult, my plan is to use gemini and prompt it for activity ideas, and then format it to look cool? Im going to still do some research. Now, the main issue is deployment. Github pages doesn’t really support having a .env, so I tried switching to vercel. However, I now need to get localstorage (which I had to use as the cookie got too big lol) working on that, plus the flight API and everything else."}, {"post_id": 65159, "ts": "2026-09-10T03:14:31Z", "hours": 2.3381, "text": "Did I get work done on the hotels part? No! BUT, I did some very needed work on the flight system so that it should work in general. The main issue was that there was no way to convert from cities to airport codes, but I sat down and actually got it done. When the user enters a city and goes to the flight screen, a modal now appears. In the background, a function runs that gets the coordinates of the city, and then creates a 100 km circle around the location, returning all airports inside of it! Originally, the plan was to use nominatim for the geolocating, since it’s free, open source, and the goat, but I may have gotten IP banned for having it run 60 times a second for a good few minutes. (This is around 60 times the amount I am supposed to do it). I forgot to remove a variable from a dependency array. ANYWAYS, I used Mapbox instead! I have some experience with it, and its free tier is pretty comprehensive. Once the locations show on the modal, they choose which ones, it reloads to show departures, and then the same system as before applies! This works SO much better, and I’m really proud of the system."}, {"post_id": 61266, "ts": "2026-09-04T03:42:26Z", "hours": 1.16, "text": "So, I got some work done on itinerarey since. Mainly, I’ve been working on error trapping and trying to find a hotel’s API. Firstly, I am trying to use airport-data-js to convert city names to airports, but it returns the incorrect values usually. Otherwise, I got the base for the hotel page done. It’s going to look pretty similar to the flights, just with different information. Currently, I need to find an API that works for hotels, but it’s going to be a bit of a struggle. I tried fast-hotels, but they are no longer maintained, or at least the current version broke on me. Wish me luck!"}, {"post_id": 59366, "ts": "2026-09-01T03:57:08Z", "hours": 1.375, "text": "The flight system is complete! To reiterate how it works, once you put in a date, a render server with an API is called that uses Python to scrape Google Flights and return (hopefully) accurate flight data. Then, a user chooses the flight they want, it gets saved to the cookie, and it does the same actions for the return flight. The main issue I had with this was getting to swap between departure and returns, since it required some refactoring of the code. It wasn’t anything too bad, though. Next up is going to be finding a hotel API. This is going to be probably just as annoying as with the flights, but there is only one way to find out. That’ll be tomorrow, though; I am so tired right now lol. Lastly, I am writing this 3 minutes before my time as a Stardance Ambassador ends. I want to thank the team for letting me take this role; Nay-nay and Alex for their help; and everyone whom I’ve interacted with. While the role is done, I’m going to finish this project!"}, {"post_id": 57779, "ts": "2026-08-30T02:17:46Z", "hours": 0.9856, "text": "Now, the flights will actually show up in the website! Using the API, I get an array, and then each flight is put into a custom object that allows it to be displayed! Each option includes basic info such as airline, price, legs, locations, timings, and more! Now that it is styled, the next goal is to save flights to the cookie, and than rerun the same process for the return flight! Overall, I think it looks pretty good!"}, {"post_id": 52020, "ts": "2026-08-22T01:49:59Z", "hours": 1.9211, "text": "This time is fully my bad, I sort of (100%) forgot about this. ANYWAYS, I got some of the biggest progress done yet. Firstly, I got trips to save as cookies in your browser, since its an easier way for me to store data across the website. dont worry, im not stealing your data or anything lol. Then, I did some research (with help from Claude) and found fast-flights, a Python library that is basically a Google Flights scraper, so it works perfectly. Except it’s a Python library… on a React website. So, I created a seperate repo that contains an API that requests the library and hosted it on render.com. One note is that the links supplied reroute to google flights, so users will have to be careful with choosing correctly. Sadly, theres really no good free options for a flight API (literally everyone shut theirs down lol). Lastly, I connected it all together by writing the base code for querying the API and getting the data back. I do need to actually format it, modify it to work with my data, and display it. But, its a good stopping point for now. By next time, I want to have the flights page looking good, and my API to be more polished!"}, {"post_id": 38419, "ts": "2026-07-31T19:38:47Z", "hours": 1.1278, "text": "So… its been a minute! I’ve been out of state doing an engineering program at ND for the past few weeks, and I am FINALLY back home! So, here’s what I got done today! I finished the layout (for now) on for the planning page. For now, you put in the departure/arrival, number of people, dates, and overall budgets. The worst part of getting it to work was the date picker. I spent like 2 hours researching different date-range pickers and trying them out, such as react aria, react-date-range, and more. Eventually, I settled on cally since its lightweight, easy to customize, and didn’t require me to spend 3 hours making it work! I also created a new input type to shrink the file size down. For the future, I plan to get data to actually save in the app, and then start looking for a flights API. The API is going to be an issue. There is really not a lot of choices for a free and large-scale API for what I want. But, its the internet. Theres gotta be something! the website thats published isn’t updated yet, since I have some code that needs to be implemented before I can redeploy."}, {"post_id": 23955, "ts": "2026-07-07T05:30:43Z", "hours": 2.0186, "text": "I started to get some work done on the planning settings! Mainly, I need to track budgets, dates, and what the user actually wants to do and spend money on. The main issue I am currently having is making the date system work. I am going to do more research, though!"}, {"post_id": 21772, "ts": "2026-07-03T21:28:54Z", "hours": 0.9672, "text": "The home page is completely done! I spent around an hour adding in all of the other info, mainly about how the program works. I also spent a decent amount of time redoing the file structure of the website, just so everything is more organized. Now, I have to find the APIs I need. Google Flights doesn’t have one, so I am going to need to do some deep research."}, {"post_id": 20522, "ts": "2026-07-02T04:20:43Z", "hours": 0.6714, "text": "Been on vacation so progress been slow but here’s what I got done! Mainly, the search bar is done! I haven’t been able to program my custom algorithm yet, so right now it just links to google maps. I tried to mimic websites like Kayak and Google Earth, and I think its pretty decent. The main issue I had was with the website crashing when clicking the search bar. ThreeJS couldnt handle the pointer event (it doesnt really make sense), but with changing the z-order and adding a LOT of e.stoppropagation() fixed it. Overall, good progress, and next post I want to get the home page done!"}, {"post_id": 18112, "ts": "2026-06-29T03:36:57Z", "hours": 0.5631, "text": "Two major things for today: I fixed responsiveness, so it looks better on small screens. Also, I started work on the search bar. I have to style it, but its coming along well! shoutout to my friends @ fallout, wish i was allowed to come with! enjoy!"}, {"post_id": 16726, "ts": "2026-06-27T05:22:25Z", "hours": 0.9508, "text": "Card system works! When you click on a point (I added more), with around 3 per continent except Australia, a popup with basic info, a photo, and a button shows up. The button will eventually go to the itinerary algorithim, but for now just links to google maps. I have to make it responsive, but tomorrow I will (hopefully) finish the base page. check it out here!"}, {"post_id": 15870, "ts": "2026-06-25T19:58:46Z", "hours": 1.4225, "text": "Itinerarey (get it?) is going to be a website where you can put in a plan for a trip and get a full detailed list of what you can do, taking into consideration price, dates, and suggested ideas. I got this idea while waiting at EWR for 3 hours before my flight got cancelled, lol. I was supposed to go to Atlanta, and I would have had a free day by myself. If I had this, I could have figured out what to do. The plan is to take data from APIs to get flights, hotels, and other stuff, and combine it with AI to get a full list of what to do! But, so far, all I got done is the start of the hero page. I want to have a globe spinning in the BG with points that can pop up some ideas, which I got done using globe.gl. The points are not coded in yet to pop up, but that’ll be later."}]...
|
Title: itinerarey by @nate | Stardance
Devlogs:
I Title: itinerarey by @nate | Stardance
Devlogs:
Itinerarey (get it?) is going to be a website where you can put in a plan for a trip and get a full detailed list of what you can do, taking into consideration price, dates, and suggested ideas. I got this idea while waiting at EWR for 3 hours before my flight got cancelled, lol. I was supposed to go to Atlanta, and I would have had a free day by myself. If I had this, I could have figured out what to do. The plan is to take data from APIs to get flights, hotels, and other stuff, and combine it with AI to get a full list of what to do! But, so far, all I got done is the start of the hero page. I want to have a globe spinning in the BG with points that can pop up some ideas, which I got done using globe.gl. The points are not coded in yet to pop up, but that’ll be later.
Card system works! When you click on a point (I added more), with around 3 per continent except Australia, a popup with basic info, a photo, and a button shows up. The button will eventually go to the itinerary algorithim, but for now just links to google maps. I have to make it responsive, but tomorrow I will (hopefully) finish the base page. check it out here!
Two major things for today: I fixed responsiveness, so it looks better on small screens. Also, I started work on the search bar. I have to style it, but its coming along well! shoutout to my friends @ fallout, wish i was allowed to come with! enjoy!
Been on vacation so progress been slow but here’s what I got done! Mainly, the search bar is done! I haven’t been able to program my custom algorithm yet, so right now it just links to google maps. I tried to mimic websites like Kayak and Google Earth, and I think its pretty decent. The main issue I had was with the website crashing when clicking the search bar. ThreeJS couldnt handle the pointer event (it doesnt really make sense), but with changing the z-order and adding a LOT of e.stoppropagation() fixed it. Overall, good progress, and next post I want to get the home page done!
The home page is completely done! I spent around an hour adding in all of the other info, mainly about how the program works. I also spent a decent amount of time redoing the file structure of the website, just so everything is more organized. Now, I have to find the APIs I need. Google Flights doesn’t have one, so I am going to need to do some deep research.
I started to get some work done on the planning settings! Mainly, I need to track budgets, dates, and what the user actually wants to do and spend money on. The main issue I am currently having is making the date system work. I am going to do more research, though!
So… its been a minute! I’ve been out of state doing an engineering program at ND for the past few weeks, and I am FINALLY back home! So, here’s what I got done today! I finished the layout (for now) on for the planning page. For now, you put in the departure/arrival, number of people, dates, and overall budgets. The worst part of getting it to work was the date picker. I spent like 2 hours researching different date-range pickers and trying them out, such as react aria, react-date-range, and more. Eventually, I settled on cally since its lightweight, easy to customize, and didn’t require me to spend 3 hours making it work! I also created a new input type to shrink the file size down. For the future, I plan to get data to actually save in the app, and then start looking for a flights API. The API is going to be an issue. There is really not a lot of choices for a free and large-scale API for what I want. But, its the internet. Theres gotta be something! the website thats published isn’t updated yet, since I have some code that needs to be implemented before I can redeploy.
This time is fully my bad, I sort of (100%) forgot about this. ANYWAYS, I got some of the biggest progress done yet. Firstly, I got trips to save as cookies in your browser, since its an easier way for me to store data across the website. dont worry, im not stealing your data or anything lol. Then, I did some research (with help from Claude) and found fast-flights, a Python library that is basically a Google Flights scraper, so it works perfectly. Except it’s a Python library… on a React website. So, I created a seperate repo that contains an API that requests the library and hosted it on render.com. One note is that the links supplied reroute to google flights, so users will have to be careful with choosing correctly. Sadly, theres really no good free options for a flight API (literally everyone shut theirs down lol). Lastly, I connected it all together by writing the base code for querying the API and getting the data back. I do need to actually format it, modify it to work with my data, and display it. But, its a good stopping point for now. By next time, I want to have the flights page looking good, and my API to be more polished!
Now, the flights will actually show up in the website! Using the API, I get an array, and then each flight is put into a custom object that allows it to be displayed! Each option includes basic info such as airline, price, legs, locations, timings, and more! Now that it is styled, the next goal is to save flights to the cookie, and than rerun the same process for the return flight! Overall, I think it looks pretty good!
The flight system is complete! To reiterate how it works, once you put in a date, a render server with an API is called that uses Python to scrape Google Flights and return (hopefully) accurate flight data. Then, a user chooses the flight they want, it gets saved to the cookie, and it does the same actions for the return flight. The main issue I had with this was getting to swap between departure and returns, since it required some refactoring of the code. It wasn’t anything too bad, though. Next up is going to be finding a hotel API. This is going to be probably just as annoying as with the flights, but there is only one way to find out. That’ll be tomorrow, though; I am so tired right now lol. Lastly, I am writing this 3 minutes before my time as a Stardance Ambassador ends. I want to thank the team for letting me take this role; Nay-nay and Alex for their help; and everyone whom I’ve interacted with. While the role is done, I’m going to finish this project!
So, I got some work done on itinerarey since. Mainly, I’ve been working on error trapping and trying to find a hotel’s API. Firstly, I am trying to use airport-data-js to convert city names to airports, but it returns the incorrect values usually. Otherwise, I got the base for the hotel page done. It’s going to look pretty similar to the flights, just with different information. Currently, I need to find an API that works for hotels, but it’s going to be a bit of a struggle. I tried fast-hotels, but they are no longer maintained, or at least the current version broke on me. Wish me luck!
Did I get work done on the hotels part? No! BUT, I did some very needed work on the flight system so that it should work in general. The main issue was that there was no way to convert from cities to airport codes, but I sat down and actually got it done. When the user enters a city and goes to the flight screen, a modal now appears. In the background, a function runs that gets the coordinates of the city, and then creates a 100 km circle around the location, returning all airports inside of it! Originally, the plan was to use nominatim for the geolocating, since it’s free, open source, and the goat, but I may have gotten IP banned for having it run 60 times a second for a good few minutes. (This is around 60 times the amount I am supposed to do it). I forgot to remove a variable from a dependency array. ANYWAYS, I used Mapbox instead! I have some experience with it, and its free tier is pretty comprehensive. Once the locations show on the modal, they choose which ones, it reloads to show departures, and then the same system as before applies! This works SO much better, and I’m really proud of the system.
So… quick update, I tore my ACL! havent really been able to do much since, but today I sat down and got work done. Mainly, I got the hotels done! It works pretty similar to flights system, where the user is prompted with a list, and they choose whichever they want. Now, if you remember, I have been struggling with finding a hotel API, since amadeus shut down. Originally, the plan was rapidAPI, but the rate limits are horrid for that. After some very intense googling, I found omkar.cloud ! They have a bunch of web scrappers with a 200/month limit, so their booking.com API works perfectly. I genuinely was considering dropping the project from this, and I am so happy I found something that worked. Now, the future. There is like 10 days left in stardance, and I need to do the activities, final page, and fix deployment. Activities shouldn’t be that dificult, my plan is to use gemini and prompt it for activity ideas, and then format it to look cool? Im going to still do some research. Now, the main issue is deployment. Github pages doesn’t really support having a .env, so I tried switching to vercel. However, I now need to get localstorage (which I had to use as the cookie got too big lol) working on that, plus the flight API and everything else.
The activities portion of the website is done! I did some research, and it turns out that the best way for me to find information on local events is AI! The way it works is by using Google Gemini along with Zod, which allows me to format my API requests to return in JSON. Since it has the same information each time, I can then just treat it as a regular API call. However, I might change it and put this on the backend to try to hide the API key. Anyways, we are almost at the end! The last major portion of the project is the recap page, where I plan to show all info on the trip, let users download, and maybe more! Today went pretty well, and I am excited to finally get this thing done.
Itinerarey is complete! The last thing that I needed to get done was the recap page, which takes all the data in your localstorage and displays it for you! I had to rewrite how the flights and hotels are displayed to show the booking links, but overall it was pretty simple. The main thing that I am proud of is the budget tracker, which shows the prices for everything, including how much is leftover in the budget! This is done with some pretty simple math, but it definitely ties the project together. Lastly, the user can save a copy of this page to their computer. They can then also reset their localstorage to create a brand new trip! Lastly, I got the readme and license done (id take a look if I were you!), and finished deploying everything on vercel. Overall, I am really happy with how Itinerarey came out. I learned a lot about web scrapping and hosting websites from this project, which I hope will come in handy in the future! Thank you all for the support, stardance has been incredible! feel free to dm me in slack! - nate
Ships:
Itinerarey is the better way to plan out your trips! When getting ready for a vacation, it can be incredibly stressful to plan out flights, hotels, activities, and more! So, I built itinerarey to make it a bit easier! It uses APIs and web scrapers to compile information from across the internet to have a centralized place to get information. The most challenging part of Itinerarey was the flights and hotels system. There are no free APIs (with good limits) for showing either, so I had to get a bit creative and spend a few hours researching. The flights system runs by contacting an API that runs a python web scraper that is hosted on Render, while the hotels call from an online Booking.com scraper. I am really proud of the recap page, mainly. To me, it feels like a representation of the entire project in its entireity. It shows everything the user did, and it works as a confirmation of every system performing as it should. For testing, please be aware that the render server mmight take up to a minute to load up. Also, due to web scraping being a bit finnicky, some results might not show up. If this happens, try clearing your localstorage and using a new destination. Enjoy your vacations! -nate...
|
1793008128.911999
|
1793094528.911999
|
|
27764
|
my hyprland dots by @Kristiyan | Stardance
|
Kristiyan
|
1
|
30.47
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-17T20:31:15Z", "hours": 28.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "uhh, i just tried ricing hyprland, it includes for hyprland (ofc) swaync, waybar, fastfetch, kitty, rofi, starship, and wlogout, i dont know if the scripts work but i did mention i was bad at scripting, but to my knowledge the switcher.sh and install.sh(for arch users only my bad) should work fine but anyway yeah, that’s all i have for now", "repo": "https://github.com/KristiyanCodes/hyprland-dots", "demo": "https://raw.githubusercontent.com/KristiyanCodes/hyprland-dots/main/install.sh"}]...
|
[{"post_id": 75345, "ts": "202 [{"post_id": 75345, "ts": "2026-09-29T19:59:08Z", "hours": 2.4667, "text": "uhh so my ship got denied so i’m gonna just post this devlog real quick to say that i significantly improved the install.sh"}, {"post_id": 69803, "ts": "2026-09-17T20:19:46Z", "hours": 1.0989, "text": "added a simple waybar switcher, didnt manage to do mutch, im not good at scripting :("}, {"post_id": 65030, "ts": "2026-09-09T20:43:57Z", "hours": 2.2372, "text": "finished starship config, it definitely took me some time to understand at first, but in the end i thing i got it pretty clean next thing im gonna do is try to make a theme switcher and add themes to switch to though they might be generic(ofc)"}, {"post_id": 61043, "ts": "2026-09-03T19:09:18Z", "hours": 2.0, "text": "so i finished the kitty config, now i’m gonna tinker and mess around with starship until i get something i like, i don’t know how long it’ll take so if your actually following this (which i don’t really think anyone is for now) just have patience if i take long"}, {"post_id": 59808, "ts": "2026-09-01T19:17:48Z", "hours": 8.0606, "text": "finished fastfetch config, from a blank file because i don’t like the ones “fastfetch –gen-config” provides, i also made it fit in half a terminal also switched from alacritty to kitty, idk what else to say, i might add a a kitty config now"}, {"post_id": 46494, "ts": "2026-08-13T19:00:39Z", "hours": 11.0997, "text": "so i kind forgot to devlog but apart from that lets get into what changed, last devlog we were working on waybar, now waybar is fully finished, and we also added wlogout, swaync, rofi(i decided to switch from wofi to rofi), and alacritty configurations, i also added a install.sh which only works on arch for now(because im not that good at shell scripts) and my wallpaper, we also improved the README.md quite a bit (i think), and currently im working on the fastfetch configuration"}, {"post_id": 22810, "ts": "2026-07-05T12:14:37Z", "hours": 1.1997, "text": "worked on waybar’s style.css and made some changes to config.jsonc"}, {"post_id": 20407, "ts": "2026-07-02T00:21:12Z", "hours": 2.3508, "text": "mostly finished hyprland configs, all i plan to add in the future is wlogout, started working on waybar configs"}]...
|
Title: my hyprland dots by @Kristiyan | Stardance
Title: my hyprland dots by @Kristiyan | Stardance
Devlogs:
mostly finished hyprland configs, all i plan to add in the future is wlogout, started working on waybar configs
worked on waybar’s style.css and made some changes to config.jsonc
so i kind forgot to devlog but apart from that lets get into what changed, last devlog we were working on waybar, now waybar is fully finished, and we also added wlogout, swaync, rofi(i decided to switch from wofi to rofi), and alacritty configurations, i also added a install.sh which only works on arch for now(because im not that good at shell scripts) and my wallpaper, we also improved the README.md quite a bit (i think), and currently im working on the fastfetch configuration
finished fastfetch config, from a blank file because i don’t like the ones “fastfetch –gen-config” provides, i also made it fit in half a terminal also switched from alacritty to kitty, idk what else to say, i might add a a kitty config now
so i finished the kitty config, now i’m gonna tinker and mess around with starship until i get something i like, i don’t know how long it’ll take so if your actually following this (which i don’t really think anyone is for now) just have patience if i take long
finished starship config, it definitely took me some time to understand at first, but in the end i thing i got it pretty clean next thing im gonna do is try to make a theme switcher and add themes to switch to though they might be generic(ofc)
added a simple waybar switcher, didnt manage to do mutch, im not good at scripting :(
uhh so my ship got denied so i’m gonna just post this devlog real quick to say that i significantly improved the install.sh
Ships:
uhh, i just tried ricing hyprland, it includes for hyprland (ofc) swaync, waybar, fastfetch, kitty, rofi, starship, and wlogout, i dont know if the scripts work but i did mention i was bad at scripting, but to my knowledge the switcher.sh and install.sh(for arch users only my bad) should work fine but anyway yeah, that’s all i have for now...
|
1793008130.1268609
|
1793094530.1268609
|
|
30067
|
ThickBerryPi by @kapkupi | Stardance
|
kapkupi
|
1
|
24.73
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-10T20:52:06Z", "hours": 24.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Hello everybody! I present to you my compact clamshell raspberry pi 5 handheld. It features a little keyboard and a 3.2 inch screen. The whole thing is also assembled with almost no screws! The only screws you will need are for the screen. Isn’t it wild what is possible with 3D printing? I mean getting the hinge or the latches right wasn’t easy but in the end having it be assembled with almost no tools really is amazing. I at least think so. It also has no battery because the pi 5 is a bit to picky and I carry powerbanks with me anyway so I decided not to package a battery with my project. Besides the additional size needed for it of course. So I am excited for others to try it out and maybe expand on it!", "repo": "https://github.com/Kapkupi/RPI5-Palmtop", "demo": ""}]...
|
[{"post_id": 81096, "ts": "202 [{"post_id": 81096, "ts": "2026-10-19T21:04:59Z", "hours": 0.7253, "text": "So I have started working on it again. I mean there is not much more to do besides waiting for it to get approved but after using it for a bit I did in fact made some changes. So first thing as you may have noticed is the bigger buttons on the screen. Not only are they way easier to assemble but also easier to use as they are bigger. The old ones were just too small and these are just more satisfying to click. click click :3 … There are also a few other small changes I might tackle so I’ll try doing a bit until October 22nd👀"}, {"post_id": 76224, "ts": "2026-10-02T19:01:07Z", "hours": 0.3236, "text": "I feel like I need to do this devlog. As you may have noticed is that I still have not shipped. The reason for that is that I have not been able to finish it last weekend and then fell sick on monday and am still sick. I am In better shape now and want to finally finish my project and collect my promised startdust /j >:3. I am very relieved that the challenge has been extended and I am not sure what I would have done without that. You can see my progress on github. (The first picture you see there is just a place holder dw)"}, {"post_id": 71496, "ts": "2026-09-20T22:36:34Z", "hours": 0.4603, "text": "Wow, about 7 hours of hardware work (which I didn’t record because nobody needs to see that ¬w¬) which consists of pretty much only soldering is behind me. I completely butchered my cardkb but everything still works. My immaculate cable management is also questionable but it works so now time to write and then ship. I should probably go to bed but it’s fine."}, {"post_id": 71182, "ts": "2026-09-20T12:25:21Z", "hours": 1.2714, "text": "So, I have finished my design and I won’t be needing to make any more changes. I am currently waiting for my final print which has a few tweaks such as an additional latch but other then that I am done. I have also made a version with an open back so any heatsink should work, not only my specific one. Now I only need to do some soldering and documenting before I can finally ship! I am soo excited"}, {"post_id": 70875, "ts": "2026-09-19T22:15:13Z", "hours": 2.0283, "text": "Yes another devlog. I made my changes and am printing again! As you can see there is another latch in the back. Of course that is not all I did but it is the most notable change. Some small details to actually make it fit were my priorities and now that I am finished with them I am printing. Excited to wake up tomorrow and see if I am ready to ship or not."}, {"post_id": 70789, "ts": "2026-09-19T19:20:43Z", "hours": 0.8183, "text": "Intermission! I have reprinted the face plate in a different orientation and now the latches are strong enough! I will still add another one to the back. Also I am sorry if my pictures look like memories but I was to lazy to use my phone and instead just used a webcam :P"}, {"post_id": 70737, "ts": "2026-09-19T17:50:23Z", "hours": 2.5175, "text": "So, I have made the first print and it is looking very promising. The hinge only needs slight changes in terms of tolerance so it can be easily disassembled, it also seems sturdy enough! What did not work is, as you can see, the RPI did not fit. I will need to make some changes to the ports on the right side. The latches are also not too bad but they both broke off. I will also need to add another latch in the back because it is too sloppy for my taste. The screen and buttons for it are pretty good. Gives me hope for the power button. But for now time to make some changes before I ship hopefully tomorrow."}, {"post_id": 70249, "ts": "2026-09-18T20:02:27Z", "hours": 2.4361, "text": "I am almost finished with the first version! I only need to do some buttons and holes and a bit of little extras and then I am finished and can print. I will not ship yet because I want to make a few different versions so most people can find enjoyment in what fits for them but I will probably do that tomorrow. Today I did a majority of the hinge in terms of function. I made a spring which makes the hinge snap into different places and makes the lid stay shut. Which you can see in the picture bellow. I am excited to be almost finished!"}, {"post_id": 69817, "ts": "2026-09-17T20:44:27Z", "hours": 1.8333, "text": "oh wow, I have added the ports on the back. You can see the seam where the holes are split which divides it into the top part which snaps on to the bottom. Easy to assemble as long as the latches do not break. I am trying my best to make the print possible with normal PLA and a 0.4mm nozzle size which currently should still be possible. I am really confident that the final product (which I am pretty close to ;3) should not be too difficult to print for the average user but I need to print it to judge that which hopefully happens this week as I will not be able to work on it next week :<"}, {"post_id": 68282, "ts": "2026-09-14T20:51:48Z", "hours": 0.5514, "text": "Did the second hinge. Of course this is far from the finished design it would not even work right now but to at least have something. I am also not completely sure on how I should do the back. Like should I leave it open, cover it completely or partially. Well I will eventually find something which I like. But still not entirely sure on how the back will look like."}, {"post_id": 67692, "ts": "2026-09-13T21:27:06Z", "hours": 3.1181, "text": "So I have continued with the display case and have added most things already. I have also started with the hinge which gave me such a headache I spent too much time finding a solution for my space requirements but I have decided on my current setup which should work well enough. And an important decision I took is that the whole hinge will be completely 3D printed! This could fail miserably and then I would need to revert back to a more simpler design with screws but if it works which I am confident it will then that would be really cool."}, {"post_id": 66939, "ts": "2026-09-12T22:16:44Z", "hours": 1.2167, "text": "Started with the display case. Just some simple things to finish off the day. And also because y’all have not seen it yet here is a view from the top of my current progress where you can see the keyboard holder which will connect to the bottom via latches."}, {"post_id": 66819, "ts": "2026-09-12T18:36:11Z", "hours": 2.8147, "text": "Wow, I would say that I am almost completely done with the enclosure for the keyboard and raspberry pi. Now the screen remains and thus the hinge. Should not be too difficult but I need to watch out for the space I need for the HDMI cables. Could be a tight fit. Notable things I have done since the last devlog are: latches, I hope they will work after finally printing exhaust and additional heat dissipation openings intake “optimisation”; will probably not make a difference but still fun small additional details"}, {"post_id": 65403, "ts": "2026-09-10T14:59:11Z", "hours": 2.7164, "text": "Did a bunch of openings for i/o such as sd card, gpio, usb and such. The back is still open but that will be addressed later on. Opening for the cooling fan was also added, no exhaust tho. I also split my main case into top and bottom because I realised that I would not be able to assemble it otherwise. Also lost my sticky streak because I am lowkey delusional :<"}, {"post_id": 61814, "ts": "2026-09-04T21:58:43Z", "hours": 0.6942, "text": "After coming back from my vacation I continued working on my project. Had to stop the recording because I havent uploaded today. Streaks and all. Today I started building the main body of my case which is not nearly finished. Tomorrow I will probably do the side with usb and ethernet port and an opening for the gpio and heatsink entry and exit."}, {"post_id": 46314, "ts": "2026-08-13T13:42:10Z", "hours": 0.9797, "text": "Ok I lied. I did in fact not start building the next day but 10 days later . Well now I am working again. I did some reference planes of the pcbs so I can use them to create my case more easier. Edited cardkb. I also was very sceptical that lapse just did not record as there were some problems but it somehow still worked. Now I can really start working on it :3"}, {"post_id": 40381, "ts": "2026-08-03T20:58:47Z", "hours": 0.45, "text": "Added my components to my assembly :D Real building will start tomorrow :P"}]...
|
Title: ThickBerryPi by @kapkupi | Stardance
Devlo Title: ThickBerryPi by @kapkupi | Stardance
Devlogs:
Added my components to my assembly :D Real building will start tomorrow :P
Ok I lied. I did in fact not start building the next day but 10 days later . Well now I am working again. I did some reference planes of the pcbs so I can use them to create my case more easier. Edited cardkb. I also was very sceptical that lapse just did not record as there were some problems but it somehow still worked. Now I can really start working on it :3
After coming back from my vacation I continued working on my project. Had to stop the recording because I havent uploaded today. Streaks and all. Today I started building the main body of my case which is not nearly finished. Tomorrow I will probably do the side with usb and ethernet port and an opening for the gpio and heatsink entry and exit.
Did a bunch of openings for i/o such as sd card, gpio, usb and such. The back is still open but that will be addressed later on. Opening for the cooling fan was also added, no exhaust tho. I also split my main case into top and bottom because I realised that I would not be able to assemble it otherwise. Also lost my sticky streak because I am lowkey delusional :<
Wow, I would say that I am almost completely done with the enclosure for the keyboard and raspberry pi. Now the screen remains and thus the hinge. Should not be too difficult but I need to watch out for the space I need for the HDMI cables. Could be a tight fit. Notable things I have done since the last devlog are: latches, I hope they will work after finally printing exhaust and additional heat dissipation openings intake “optimisation”; will probably not make a difference but still fun small additional details
Started with the display case. Just some simple things to finish off the day. And also because y’all have not seen it yet here is a view from the top of my current progress where you can see the keyboard holder which will connect to the bottom via latches.
So I have continued with the display case and have added most things already. I have also started with the hinge which gave me such a headache I spent too much time finding a solution for my space requirements but I have decided on my current setup which should work well enough. And an important decision I took is that the whole hinge will be completely 3D printed! This could fail miserably and then I would need to revert back to a more simpler design with screws but if it works which I am confident it will then that would be really cool.
Did the second hinge. Of course this is far from the finished design it would not even work right now but to at least have something. I am also not completely sure on how I should do the back. Like should I leave it open, cover it completely or partially. Well I will eventually find something which I like. But still not entirely sure on how the back will look like.
oh wow, I have added the ports on the back. You can see the seam where the holes are split which divides it into the top part which snaps on to the bottom. Easy to assemble as long as the latches do not break. I am trying my best to make the print possible with normal PLA and a 0.4mm nozzle size which currently should still be possible. I am really confident that the final product (which I am pretty close to ;3) should not be too difficult to print for the average user but I need to print it to judge that which hopefully happens this week as I will not be able to work on it next week :<
I am almost finished with the first version! I only need to do some buttons and holes and a bit of little extras and then I am finished and can print. I will not ship yet because I want to make a few different versions so most people can find enjoyment in what fits for them but I will probably do that tomorrow. Today I did a majority of the hinge in terms of function. I made a spring which makes the hinge snap into different places and makes the lid stay shut. Which you can see in the picture bellow. I am excited to be almost finished!
So, I have made the first print and it is looking very promising. The hinge only needs slight changes in terms of tolerance so it can be easily disassembled, it also seems sturdy enough! What did not work is, as you can see, the RPI did not fit. I will need to make some changes to the ports on the right side. The latches are also not too bad but they both broke off. I will also need to add another latch in the back because it is too sloppy for my taste. The screen and buttons for it are pretty good. Gives me hope for the power button. But for now time to make some changes before I ship hopefully tomorrow.
Intermission! I have reprinted the face plate in a different orientation and now the latches are strong enough! I will still add another one to the back. Also I am sorry if my pictures look like memories but I was to lazy to use my phone and instead just used a webcam :P
Yes another devlog. I made my changes and am printing again! As you can see there is another latch in the back. Of course that is not all I did but it is the most notable change. Some small details to actually make it fit were my priorities and now that I am finished with them I am printing. Excited to wake up tomorrow and see if I am ready to ship or not.
So, I have finished my design and I won’t be needing to make any more changes. I am currently waiting for my final print which has a few tweaks such as an additional latch but other then that I am done. I have also made a version with an open back so any heatsink should work, not only my specific one. Now I only need to do some soldering and documenting before I can finally ship! I am soo excited
Wow, about 7 hours of hardware work (which I didn’t record because nobody needs to see that ¬w¬) which consists of pretty much only soldering is behind me. I completely butchered my cardkb but everything still works. My immaculate cable management is also questionable but it works so now time to write and then ship. I should probably go to bed but it’s fine.
I feel like I need to do this devlog. As you may have noticed is that I still have not shipped. The reason for that is that I have not been able to finish it last weekend and then fell sick on monday and am still sick. I am In better shape now and want to finally finish my project and collect my promised startdust /j >:3. I am very relieved that the challenge has been extended and I am not sure what I would have done without that. You can see my progress on github. (The first picture you see there is just a place holder dw)
So I have started working on it again. I mean there is not much more to do besides waiting for it to get approved but after using it for a bit I did in fact made some changes. So first thing as you may have noticed is the bigger buttons on the screen. Not only are they way easier to assemble but also easier to use as they are bigger. The old ones were just too small and these are just more satisfying to click. click click :3 … There are also a few other small changes I might tackle so I’ll try doing a bit until October 22nd👀
Ships:
Hello everybody! I present to you my compact clamshell raspberry pi 5 handheld. It features a little keyboard and a 3.2 inch screen. The whole thing is also assembled with almost no screws! The only screws you will need are for the screen. Isn’t it wild what is possible with 3D printing? I mean getting the hinge or the latches right wasn’t easy but in the end having it be assembled with almost no tools really is amazing. I at least think so. It also has no battery because the pi 5 is a bit to picky and I carry powerbanks with me anyway so I decided not to package a battery with my project. Besides the additional size needed for it of course. So I am excited for others to try it out and maybe expand on it!...
|
1793008131.3079033
|
1793094531.3079033
|
|
5265
|
Abohisham-Web by @Abohisham | Stardance
|
Abohisham
|
1
|
4.0
|
7
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-01T15:15:31Z", "hours": 4.0, "multiplier": 1.7, "payout": 7, "blessing": "neutral", "text": "I have mainly focused on fixing some of the issues for this ship, previously i shipped to flavortown, and got a lot of bad comments cuz this didnt work probably on safari browser. so i had to do some internal fixes. Aside from that, i have done some changes in the ui to make this look a lot better.", "repo": "https://github.com/MohamadAminGhanoum/Abohisham-Web", "demo": "https://abohisham-web.vercel.app/index.html"}]...
|
[{"post_id": 58088, "ts": "202 [{"post_id": 58088, "ts": "2026-08-30T13:20:19Z", "hours": 1.8464, "text": "In this session, i have done some changes to the homepage look, especially the navigation bar, made it float, and have a transparent bg. did some small changes to the page paddings to make the bg fit the whole page even when zooming out, and also made padding to the navigation bar, which leaves some distance between the navbar and the contents on the screen. i also did osme changes to the folders, where i made all the images become in one folder, since when i looked in my repo, it really looked messed up. So i got that fixed, but it did ruin some places, where the image would not load, so i will fix that b4 the next devlog."}, {"post_id": 2412, "ts": "2026-06-04T21:34:31Z", "hours": 1.4092, "text": "Pheew, this took long to fix. I finally was able to upload .md files into my hardware projects folder. I just focused right now on configuring how the pictures should load. I will work more on later on how to customize it more."}, {"post_id": 956, "ts": "2026-06-02T18:40:51Z", "hours": 0.8381, "text": "I was just able to add the time into the center of my website, and i managed to do some additional changes in the top navigation bar, so now it is more transparent. I also learned about the overflow-x, because i actually found it really annoying that the page would move left and right, so now it is only moving vertical. I will try to work on the content next time, i will try to make this more useful in a person’s everyday life. So that i can put this on my pc, and use this while studying, to avoid distractions If u have any suggestions, please lmk."}]...
|
Title: Abohisham-Web by @Abohisham | Stardance
De Title: Abohisham-Web by @Abohisham | Stardance
Devlogs:
I was just able to add the time into the center of my website, and i managed to do some additional changes in the top navigation bar, so now it is more transparent. I also learned about the overflow-x, because i actually found it really annoying that the page would move left and right, so now it is only moving vertical. I will try to work on the content next time, i will try to make this more useful in a person’s everyday life. So that i can put this on my pc, and use this while studying, to avoid distractions If u have any suggestions, please lmk.
Pheew, this took long to fix. I finally was able to upload .md files into my hardware projects folder. I just focused right now on configuring how the pictures should load. I will work more on later on how to customize it more.
In this session, i have done some changes to the homepage look, especially the navigation bar, made it float, and have a transparent bg. did some small changes to the page paddings to make the bg fit the whole page even when zooming out, and also made padding to the navigation bar, which leaves some distance between the navbar and the contents on the screen. i also did osme changes to the folders, where i made all the images become in one folder, since when i looked in my repo, it really looked messed up. So i got that fixed, but it did ruin some places, where the image would not load, so i will fix that b4 the next devlog.
Ships:
I have mainly focused on fixing some of the issues for this ship, previously i shipped to flavortown, and got a lot of bad comments cuz this didnt work probably on safari browser. so i had to do some internal fixes. Aside from that, i have done some changes in the ui to make this look a lot better....
|
1793008132.5503554
|
1793094532.5503554
|
|
58812
|
Cyber Rider by @srauniyar311 | Stardance
|
srauniyar311
|
1
|
4.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-21T12:01:33Z", "hours": 4.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I have made physics based website explaning the concept of Electron in a interactive and beautiful way. Most of the the explaination is done in readme of how this website was build and what were its flaws and how it was fixed", "repo": "https://github.com/srauniyar-bit/Electron", "demo": "https://electron-gold.vercel.app/"}]...
|
[{"post_id": 71724, "ts": "202 [{"post_id": 71724, "ts": "2026-09-21T11:53:49Z", "hours": 3.7561, "text": "Its normal jump game , a first website game making it as simple and understanding the mechanics of the website game"}]...
|
Title: Cyber Rider by @srauniyar311 | Stardance
D Title: Cyber Rider by @srauniyar311 | Stardance
Devlogs:
Its normal jump game , a first website game making it as simple and understanding the mechanics of the website game
Ships:
I have made physics based website explaning the concept of Electron in a interactive and beautiful way. Most of the the explaination is done in readme of how this website was build and what were its flaws and how it was fixed...
|
1793008133.652175
|
1793094533.652175
|
|
58819
|
Tab Rot VS Code by @madushankarajapaksha999 | Star Tab Rot VS Code by @madushankarajapaksha999 | Stardance...
|
madushankarajapaksha999
|
1
|
15.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-27T05:23:53Z", "hours": 15.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I built Tab Rot, a VS Code extension that makes your files visually decay if you ignore them. The most annoying part was mocking the VS Code API to write unit tests, plus fixing a random Node js crash when I tried to publish. Im super proud of the actual visual rot effect and that the state save even if you restart VS Code. If you wanna test it, just drop the decay timer in the setting to like 1 minute, otherwise you’ll be waiting an hour to see it work.", "repo": "https://github.com/MadushankaRajapaksha/Tab-Rot-VS-Code", "demo": "https://github.com/MadushankaRajapaksha/Tab-Rot-VS-Code/releases/tag/v1.0.1"}]...
|
[{"post_id": 74312, "ts": "202 [{"post_id": 74312, "ts": "2026-09-27T05:12:52Z", "hours": 1.1833, "text": "deployed manually with vsce publish instead. Wrote a full README with install guide, all settings, presets, and troubleshooting. Extension is live on the Repo Releases.."}, {"post_id": 73902, "ts": "2026-09-26T09:16:51Z", "hours": 0.7158, "text": "Fixedd command registration, compilation paths, settings panel display, and database state persistence acrosssrc/extension.ts`, src/settingsPanel.ts, and src/tabTracker.ts"}, {"post_id": 73863, "ts": "2026-09-26T06:49:16Z", "hours": 2.0989, "text": "I built a proper settings webview panel for Tab Rot because asking users to edit raw JSON for threhold values felt hostile. Made a settingsPanel.ts that opens a dedicated webview tab with a clean form — three number inputs for the decay thresholds (stage 1, 2, 3 in minute), three toggle switches for decorations, status bar, and notifications. The whole thing uses VS Code’s CSS variables so it automatically matches the user’s theme — dark mode, light mode, high contrast, whatever. It looks native.The panel is a singleton — if you already have it open, running the command again just focuses the existing panel instead of spawning duplicates. The HTML is inline because it’s small enough that a separate file feels like overkill, but it’s structured with proper labels, hints explaining what each value means, and a little visual preview of the three decay stages as colored badges. The toggles are custom CSS switches that feels nicer than raw checkboxes."}, {"post_id": 73539, "ts": "2026-09-25T10:57:58Z", "hours": 1.6992, "text": "Testing today I finally sat down to write unit tests for tabTracker.ts. I’ve been putting this off becaus, honestly, testing feels like homework when you just want to see the thing work. But I knew if I didn’t write tests now, Id never catch the bug s hiding in the decay logic."}, {"post_id": 72968, "ts": "2026-09-24T04:05:08Z", "hours": 2.2619, "text": "built the sidebar tree view for Tab Rot. Made a decayView.ts with a DecayTreeProvider that implements VS Code s TreeDataProvider interface. It pulls all decayed tabs from the tracker, sorts them by stage with the worst rot first, and renders each one as a DecayItem with the filename as the label, a stage emoji + name as the description (like “🍂 Faded” or “💀 Cracked”), and a tooltip showing how long it’s been since the file was last visited. Each item gets a stage-specific SVG icon and clicking it’s opens the file in the editor.I also created four littl SVG leaf icons in resources/icons/ — a green one for fresh tabs, orange-yellow for faded, brown with dots for grainy, and a dark cracked one for stage 3. They’re just simple leaf shapes but the color coding makes the sidebar immediately scannable.Wired the tree provider into extension.ts and registered it under the view ID tabRot.decayedTabs in package.json. The view lives in the Explorer sidebar and only shows up when there are actually decayed tabs, thanks to a context key tabRot.hasDecayedTabs that I set on every refresh. So if all your tabs are fresh, the sidebar section disappears completely instead of sitting there empty and sad.Added a tabRot.openDecayedTab command that the tree items use to open files when clicked. Since opening the file triggers onDidChangeActiveTextEditor, the tab gets touched and restored automatically, complete with the green flash animation from Phase 5. So the flow is: see rotting tab in sidebar → click it → file opens → green flash → tab is fresh again. Very satisfying.I also updated all the refresh calls so the sidebar stays in sync — it refreshes after every tab touch, close, restore command, and interval tick. And the showDecayedTabs command from Phase 4 now actually works because the view is registered, so that unhandled rejection error is gone."}, {"post_id": 69019, "ts": "2026-09-16T07:07:50Z", "hours": 0.6325, "text": "I builts the restoration flash animation today because instantly snapping from cracked stage-3 to pristine stage-0 felt robotic. I wanted a little “healing” moment — like the file is literally coming back to life. Added a flashRestore() method to tabDecorator.ts that chains two temporary decoration flashes: a bright green pulse at 0ms, a softer second pulse at 300ms, then clear at 600ms. The tab breathes green for a second and then settles into its clean state. I also added a “✨ Tab restored!” info message because I’m a sucker for positive feedback.I wired the flash into two places: when you actively switch to a decayed tab (it detects the old stage was > 0, touches it, then flashes), and when you run the restoreTab comand manually. So whether you click into a rotting file or hit the command palette, you get the dopamine hit.I also added an optional decay notification system. Every 60 seconds during the interval tick, it checks if any tab crossed into a higher decay stage. If tabRot.showNotifications is enabled, it pops a toast like “📉 utils.ts reached stage 2 (unvisited for 1440 minutes)”. I defaulted it to false because getting spammed every minute that your tabs are dying would make people uninstall immediatey. But for accountability masochists, its there."}, {"post_id": 68591, "ts": "2026-09-15T11:16:32Z", "hours": 1.4983, "text": "I built the status bar and command layer for Tab Rot. Made a statusBar.ts that creates a StatusBarItem shoved over to the right side of the bar at priority 100. It shows a little 🍂 leaf emoji followed by how many tabs are rotting — like “🍂 3 rotting” — but only when there’s actually something decaying. When the count hits zero it hides itself completely so it’s not sitting there being useless and cluttering the bar. Clicking it is supposed to focus the sidebar view later, but since I haven’t built the sidebar yet, it’s basically a button that promises something it can’t deliver. I also gated it behind the tabRot.enableStatusBar config so people can kill it if they want.Registered three commands in package.json — tabRot.restoreTab to freshen up whatever file I’m currently staring at, tabRot.restoreAllTabs to reset every tracked tab back to stage 0, and tabRot.showDecayedTabs which is supposed to focus the sidebar. I wired all the handlers in extension.ts. restoreTab grabs the active editor URI, calls tracker.restoreTab(), then immediately refreshes the decorations and status bar so the rot vanishes right away. restoreAllTabs does the same thing but for everything and pops up a little info message saying “✨ All tabs restored!” because I wanted it to feel satisfying. showDecayedTabs tries to execute tabRot.decayedTabs.focus which is a VS Code auto-generated command for tree views.I also added a context menu to contributes.menus.editor/title/context so when you right-click in the editor area you get “Restore Tab” and “Restore All Tabs” right there without having to open the Command Palette. I grouped them under 9_tabRot so they sit in their own little section instead of getting drowned in the giant VS Code right-click menu."}, {"post_id": 65256, "ts": "2026-09-10T08:09:52Z", "hours": 1.3453, "text": "Implimented Visual Decay Decorations I built the entire visual decay layer for Tab Rot over the past two days. Created tabDecorator.ts with three TextEditorDecorationTyp instances one for each decay stage. Stage 1 is a slight washout with opacity: 0.75 and a warm background tint. Stage 2 gets heavier with opacity: 0.55, a dashed brown border, and a darker background. Stage 3 is the nasty one — opacity: 0.4, solid border, wavy strikethrough, and a dark background that makes the code genuinely look abandoned. The updateDecorations() method loops through all visibleTextEditors, grabs the decay stage from the tracker, clears any previous decorations (super important so they dont stack), and applies a full-document Range if the stage is above zero. I register all decoration types in context.subscriptions so VS Code cleans them up on deactivate. I also registered custom theme colors in package.json under contributes.colors — background tints and overview ruler colors for all three stages, with separate defaults for dark, light, and high-contrast themes. Then I swapped out all the hardcoded rgba() values in the decorator for new vscode.ThemeColor(…) so user can customize the palette in their settings.json if they want. Wired everything into extension.ts — updateDecorations() gets called after activation, after every onDidChangeActiveTextEditor (so visiting a tab instantly removes the rot), after onDidCloseTextDocument (cleanup), inside the 60-second interval (so decay progresses live), and on onDidChangeVisibleTextEditors (for split views)."}, {"post_id": 64655, "ts": "2026-09-09T07:04:21Z", "hours": 0.8492, "text": "Wiring the Engine + Config Schema I wired up the TabTracker into the actual extension entry point today. Made an extension.ts that instantiates the trackr when VS Code activates the extension, then immediately scans all already-open text documents and registers them with touchTab() so nothing gets lost if the user already has files open. I hooked into onDidChangeActiveTextEditr to call touchTab() every time the user switches tabs, and onDidCloseTextDocument to remove tabs when files close. I also set up a setInterval that fires every 60 second to call updateAllStages() so the decay actually progresses in real time without waiting for someone to interact.I also completely redid the configuration schem in package.json. Instead of the array-based thresholds I had before, I switched to individual keys : tabRot.stage1Threshold, stage2Threshold, and stage3Threshold with defaults of 60, 1440, and 10080 minutes respectively. That maps to 1 hour, 1 day, and 1 week which feels way more intuitive than the old array. I also added two boolean flags — enableDecorations and enableStatusBar — so users can toggle the UI features later without digging through code.I updated tabTracker.ts to read from the individual config key instead of the array, and kept the hot-reload listener so if someone edits their settings the thresholds update live. I peppered console.log everywhere for debugging — activation messages, tab touch events, removals, and a periodic log of how many decayed tabs exist."}, {"post_id": 63613, "ts": "2026-09-07T15:18:58Z", "hours": 1.4383, "text": "Core State Engine — tabTracker.ts I finally started the actual VS Code extension part of Tab Rot after planning everything out. Today’s goal was just the core state engine — basically tracking when each file was last visited and making sure it survives if you close and reopen VS Code. I made a tabTracker.ts file that has a TabState interface and a TabTracker class. The interface is super strict with the decay stages locked to 0 | 1 | 2 | 3 which felt like good TypeScript practice but also kind of a pain later.The tracker uses a Map to hold everything in memory, but it loads from and saves to context.workspaceState so the data persists across restarts. I added all the main methods — touchTab() to mark something as visited right now, removeTab() when a file closes, getDecayStage() to figure out how rotten a tab is based on the time thresholds, and getDecayedTabs() to spit out everything that’s stage 1 or higher sorted by how dead it is. I also threw in restoreTab() and restoreAllTabs() for when you want to pretend you never abandoned that file.I set it up to read the decay thresholds from VS Code settings (tabRot.decayThresholds) and even made it hot-reload when you change the config without restarting the whole editor. Oh and I added a debounced save because I realized it would be stupid to write to disk every single time you switch tab"}, {"post_id": 63394, "ts": "2026-09-07T06:24:47Z", "hours": 0.5092, "text": "Planned the Tab Root Project Today, I planned the development roadmap for my Tab Root VS Code extension. After finishing the initial project setup, I broke the project into smaller tasks and subtasks so I can develop the extenssion step by step.I created a task list covering the main parts of the project, including tab tracking, the decay system, tab activity detection, visual tab changes, restore functionality, user configuration, testing, documentation, and the final release.Breaking the project into small tasks should make it easier to track my progress and understand what I need to work on next. I also organized the tasks into diffarent phase so I can focus on building the core functionality before moving on to the UI and release."}, {"post_id": 62927, "ts": "2026-09-06T13:53:50Z", "hours": 0.7317, "text": "Implemented Project Structure What I worked on:Today, I started working on my first VS Code extension, called Tab Root. I initialized the project and set up Git for version control. I also created the basic file and folder structure for the extension and configured the project to use TypeScript.After setting everything up, I created my first working VS Code extension. I added a basic VS Code command and tested it successfully inside VS Code. This was my first time creating and running an extension, so getting the basic setup working was an important first step for the project."}]...
|
Title: Tab Rot VS Code by @madushankarajapaksha999 Title: Tab Rot VS Code by @madushankarajapaksha999 | Stardance
Devlogs:
Implemented Project Structure What I worked on:Today, I started working on my first VS Code extension, called Tab Root. I initialized the project and set up Git for version control. I also created the basic file and folder structure for the extension and configured the project to use TypeScript.After setting everything up, I created my first working VS Code extension. I added a basic VS Code command and tested it successfully inside VS Code. This was my first time creating and running an extension, so getting the basic setup working was an important first step for the project.
Planned the Tab Root Project Today, I planned the development roadmap for my Tab Root VS Code extension. After finishing the initial project setup, I broke the project into smaller tasks and subtasks so I can develop the extenssion step by step.I created a task list covering the main parts of the project, including tab tracking, the decay system, tab activity detection, visual tab changes, restore functionality, user configuration, testing, documentation, and the final release.Breaking the project into small tasks should make it easier to track my progress and understand what I need to work on next. I also organized the tasks into diffarent phase so I can focus on building the core functionality before moving on to the UI and release.
Core State Engine — tabTracker.ts I finally started the actual VS Code extension part of Tab Rot after planning everything out. Today’s goal was just the core state engine — basically tracking when each file was last visited and making sure it survives if you close and reopen VS Code. I made a tabTracker.ts file that has a TabState interface and a TabTracker class. The interface is super strict with the decay stages locked to 0 | 1 | 2 | 3 which felt like good TypeScript practice but also kind of a pain later.The tracker uses a Map to hold everything in memory, but it loads from and saves to context.workspaceState so the data persists across restarts. I added all the main methods — touchTab() to mark something as visited right now, removeTab() when a file closes, getDecayStage() to figure out how rotten a tab is based on the time thresholds, and getDecayedTabs() to spit out everything that’s stage 1 or higher sorted by how dead it is. I also threw in restoreTab() and restoreAllTabs() for when you want to pretend you never abandoned that file.I set it up to read the decay thresholds from VS Code settings (tabRot.decayThresholds) and even made it hot-reload when you change the config without restarting the whole editor. Oh and I added a debounced save because I realized it would be stupid to write to disk every single time you switch tab
Wiring the Engine + Config Schema I wired up the TabTracker into the actual extension entry point today. Made an extension.ts that instantiates the trackr when VS Code activates the extension, then immediately scans all already-open text documents and registers them with touchTab() so nothing gets lost if the user already has files open. I hooked into onDidChangeActiveTextEditr to call touchTab() every time the user switches tabs, and onDidCloseTextDocument to remove tabs when files close. I also set up a setInterval that fires every 60 second to call updateAllStages() so the decay actually progresses in real time without waiting for someone to interact.I also completely redid the configuration schem in package.json. Instead of the array-based thresholds I had before, I switched to individual keys : tabRot.stage1Threshold, stage2Threshold, and stage3Threshold with defaults of 60, 1440, and 10080 minutes respectively. That maps to 1 hour, 1 day, and 1 week which feels way more intuitive than the old array. I also added two boolean flags — enableDecorations and enableStatusBar — so users can toggle the UI features later without digging through code.I updated tabTracker.ts to read from the individual config key instead of the array, and kept the hot-reload listener so if someone edits their settings the thresholds update live. I peppered console.log everywhere for debugging — activation messages, tab touch events, removals, and a periodic log of how many decayed tabs exist.
Implimented Visual Decay Decorations I built the entire visual decay layer for Tab Rot over the past two days. Created tabDecorator.ts with three TextEditorDecorationTyp instances one for each decay stage. Stage 1 is a slight washout with opacity: 0.75 and a warm background tint. Stage 2 gets heavier with opacity: 0.55, a dashed brown border, and a darker background. Stage 3 is the nasty one — opacity: 0.4, solid border, wavy strikethrough, and a dark background that makes the code genuinely look abandoned. The updateDecorations() method loops through all visibleTextEditors, grabs the decay stage from the tracker, clears any previous decorations (super important so they dont stack), and applies a full-document Range if the stage is above zero. I register all decoration types in context.subscriptions so VS Code cleans them up on deactivate. I also registered custom theme colors in package.json under contributes.colors — background tints and overview ruler colors for all three stages, with separate defaults for dark, light, and high-contrast themes. Then I swapped out all the hardcoded rgba() values in the decorator for new vscode.ThemeColor(…) so user can customize the palette in their settings.json if they want. Wired everything into extension.ts — updateDecorations() gets called after activation, after every onDidChangeActiveTextEditor (so visiting a tab instantly removes the rot), after onDidCloseTextDocument (cleanup), inside the 60-second interval (so decay progresses live), and on onDidChangeVisibleTextEditors (for split views).
I built the status bar and command layer for Tab Rot. Made a statusBar.ts that creates a StatusBarItem shoved over to the right side of the bar at priority 100. It shows a little 🍂 leaf emoji followed by how many tabs are rotting — like “🍂 3 rotting” — but only when there’s actually something decaying. When the count hits zero it hides itself completely so it’s not sitting there being useless and cluttering the bar. Clicking it is supposed to focus the sidebar view later, but since I haven’t built the sidebar yet, it’s basically a button that promises something it can’t deliver. I also gated it behind the tabRot.enableStatusBar config so people can kill it if they want.Registered three commands in package.json — tabRot.restoreTab to freshen up whatever file I’m currently staring at, tabRot.restoreAllTabs to reset every tracked tab back to stage 0, and tabRot.showDecayedTabs which is supposed to focus the sidebar. I wired all the handlers in extension.ts. restoreTab grabs the active editor URI, calls tracker.restoreTab(), then immediately refreshes the decorations and status bar so the rot vanishes right away. restoreAllTabs does the same thing but for everything and pops up a little info message saying “✨ All tabs restored!” because I wanted it to feel satisfying. showDecayedTabs tries to execute tabRot.decayedTabs.focus which is a VS Code auto-generated command for tree views.I also added a context menu to contributes.menus.editor/title/context so when you right-click in the editor area you get “Restore Tab” and “Restore All Tabs” right there without having to open the Command Palette. I grouped them under 9_tabRot so they sit in their own little section instead of getting drowned in the giant VS Code right-click menu.
I builts the restoration flash animation today because instantly snapping from cracked stage-3 to pristine stage-0 felt robotic. I wanted a little “healing” moment — like the file is literally coming back to life. Added a flashRestore() method to tabDecorator.ts that chains two temporary decoration flashes: a bright green pulse at 0ms, a softer second pulse at 300ms, then clear at 600ms. The tab breathes green for a second and then settles into its clean state. I also added a “✨ Tab restored!” info message because I’m a sucker for positive feedback.I wired the flash into two places: when you actively switch to a decayed tab (it detects the old stage was > 0, touches it, then flashes), and when you run the restoreTab comand manually. So whether you click into a rotting file or hit the command palette, you get the dopamine hit.I also added an optional decay notification system. Every 60 seconds during the interval tick, it checks if any tab crossed into a higher decay stage. If tabRot.showNotifications is enabled, it pops a toast like “📉 utils.ts reached stage 2 (unvisited for 1440 minutes)”. I defaulted it to false because getting spammed every minute that your tabs are dying would make people uninstall immediatey. But for accountability masochists, its there.
built the sidebar tree view for Tab Rot. Made a decayView.ts with a DecayTreeProvider that implements VS Code s TreeDataProvider interface. It pulls all decayed tabs from the tracker, sorts them by stage with the worst rot first, and renders each one as a DecayItem with the filename as the label, a stage emoji + name as the description (like “🍂 Faded” or “💀 Cracked”), and a tooltip showing how long it’s been since the file was last visited. Each item gets a stage-specific SVG icon and clicking it’s opens the file in the editor.I also created four littl SVG leaf icons in resources/icons/ — a green one for fresh tabs, orange-yellow for faded, brown with dots for grainy, and a dark cracked one for stage 3. They’re just simple leaf shapes but the color coding makes the sidebar immediately scannable.Wired the tree provider into extension.ts and registered it under the view ID tabRot.decayedTabs in package.json. The view lives in the Explorer sidebar and only shows up when there are actually decayed tabs, thanks to a context key tabRot.hasDecayedTabs that I set on every refresh. So if all your tabs are fresh, the sidebar section disappears completely instead of sitting there empty and sad.Added a tabRot.openDecayedTab command that the tree items use to open files when clicked. Since opening the file triggers onDidChangeActiveTextEditor, the tab gets touched and restored automatically, complete with the green flash animation from Phase 5. So the flow is: see rotting tab in sidebar → click it → file opens → green flash → tab is fresh again. Very satisfying.I also updated all the refresh calls so the sidebar stays in sync — it refreshes after every tab touch, close, restore command, and interval tick. And the showDecayedTabs command from Phase 4 now actually works because the view is registered, so that unhandled rejection error is gone.
Testing today I finally sat down to write unit tests for tabTracker.ts. I’ve been putting this off becaus, honestly, testing feels like homework when you just want to see the thing work. But I knew if I didn’t write tests now, Id never catch the bug s hiding in the decay logic.
I built a proper settings webview panel for Tab Rot because asking users to edit raw JSON for threhold values felt hostile. Made a settingsPanel.ts that opens a dedicated webview tab with a clean form — three number inputs for the decay thresholds (stage 1, 2, 3 in minute), three toggle switches for decorations, status bar, and notifications. The whole thing uses VS Code’s CSS variables so it automatically matches the user’s theme — dark mode, light mode, high contrast, whatever. It looks native.The panel is a singleton — if you already have it open, running the command again just focuses the existing panel instead of spawning duplicates. The HTML is inline because it’s small enough that a separate file feels like overkill, but it’s structured with proper labels, hints explaining what each value means, and a little visual preview of the three decay stages as colored badges. The toggles are custom CSS switches that feels nicer than raw checkboxes.
Fixedd command registration, compilation paths, settings panel display, and database state persistence acrosssrc/extension.ts`, src/settingsPanel.ts, and src/tabTracker.ts
deployed manually with vsce publish instead. Wrote a full README with install guide, all settings, presets, and troubleshooting. Extension is live on the Repo Releases..
Ships:
I built Tab Rot, a VS Code extension that makes your files visually decay if you ignore them. The most annoying part was mocking the VS Code API to write unit tests, plus fixing a random Node js crash when I tried to publish. Im super proud of the actual visual rot effect and that the state save even if you restart VS Code. If you wanna test it, just drop the decay timer in the setting to like 1 minute, otherwise you’ll be waiting an hour to see it work....
|
1793008134.5266228
|
1793094534.5266228
|
|
53979
|
Tetr.AI by @caleb_welch | Stardance
|
caleb_welch
|
1
|
25.41
|
401
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-20T04:54:20Z", "hours": 23.0, "multiplier": 17.26, "payout": 401, "blessing": "neutral", "text": "Tetr.AI This is the first release of Tetr.AI, my first ever reinforcement-learning project built for the Hack Club Stardance YSWS. Tetr.AI includes: A custom built Tetris environment built with PyGame which allows you to train and run your own models as well as just play Tetris A PyTorch neural network Deep-Q-learning Model checkpoint saving and loading Saving of training statistics into a CSV file A graphing script to allow you to visualize how well your model trained Windows and Linux setup scripts Model status The training pipeline is completely functional, but due to time constraints this release won’t contain a model which can play Tetris well. I completed two long duration training experiments during development which revealed problems with reward shaping, epsilon, and sparse rewards. Everything on this is documented in the README. Training and experimentation will continue after stardance", "repo": "https://github.com/sourcream1012/Tetr.AI", "demo": "https://github.com/sourcream1012/Tetr.AI/releases/tag/v1.0.1-stardance"}]...
|
[{"post_id": 74121, "ts": "202 [{"post_id": 74121, "ts": "2026-09-26T18:31:12Z", "hours": 2.4075, "text": "Not to big of a devlog but I added executable files for easy running for this project. Also added a training_config json file to easily change training values."}, {"post_id": 70969, "ts": "2026-09-20T04:09:44Z", "hours": 2.9878, "text": "DEVLOG 8: I think I may ship soon… Ok so I’ve hit a road block. Stardance ends soon which means I don’t really have much time left. My project is a completely working reinforcement learning AI which can play Tetris but not well. Originally I wanted to perfect a model and then ship the project but due to Stardance ending soon I may change that. Recent additions Added the ability to resume training on a model you made at your most recent checkpoint Added setup automation scripts for windows and linux Refined README with a getting started section and more detail in the Model History section to give the project more story Because I’m essentially prepped for shipping and it is a completely working project I will probably ship soon. Wish me luck. The screenshots shown are the results from training Tetr.AI-V2"}, {"post_id": 69842, "ts": "2026-09-17T21:48:57Z", "hours": 4.3036, "text": "DEVLOG 7: more AI training (hint: FAILED) This graph shows the results of my first training session of my AI showing how well the AI does over time through the reward. In total it lasted ~17 hours and its obviously not nearly enough time. The reward is supposed to go up over time, which it is. But not fast enough. Overall it only seems to increase in reward over time just by VERY little. Moving onto the other graph which shows the rows cleared over time. As you can see it never really increases on average. This shows that: MY AI SUCKSSSSSSS My AI is dumb Overall my AI can’t learn and I need to just keep on adjusting numbers over and over again."}, {"post_id": 63361, "ts": "2026-09-07T04:24:31Z", "hours": 2.3192, "text": "DEVLOG 6: actual learning Wow two devlogs in pretty much a day… I need to touch grass… But that is not the point. IT IS FINALLY LEARNING (just very inefficiently) Currently it only learns from two things: How many rows it cleared on a single run Whether or not it sold the game Now pretty much the rest of this project will just be tweaking and experimenting with things. Before I ship I do want to train and release a demo model that you can test locally on your PC ( and I may want to test if it would work on android phones too ) that will come with the project. I also want to make it to where you can create and train your own models and potentially share them with other people. CAN’T WAIT FOR EVERYTHING TO BE DONE!!!!!!"}, {"post_id": 63183, "ts": "2026-09-06T21:02:14Z", "hours": 1.6347, "text": "DEVLOG 5: Random movements An update from my previous devlog where I started learning pytorch. I have not learned pytorch to the point to where I can explain everything down to its finest details but enough to make my “AI” do some random junk with no direction. Pretty much I’m just initializing random weights and letting it go. I have 200 input neurons for my 20x10 board. The video I attached below shows the AI just doing some random stuff like rotating non stop and moving left and right."}, {"post_id": 61233, "ts": "2026-09-04T02:07:36Z", "hours": 3.1531, "text": "DEVLOG 4: The beginning of learning PyTorch & Working AI-Tetris-Environment Pretty much the title sums up what I’ve been doing for the past 3h and 9m of this. I have some prior knowledge of the basics of machine learning ( from The Nature Of Code by Daniel Shiffman awesome book about coding would recommend ) by making a single layer perceptron ( basically a single neuron algorithm ) that can separate linearly separable data. I attempted to make a multi layered perceptron which actually puts the network in neural network. But I got stuck on back propagation. I don’t really know what to put as the picture for this devlog so I’ll just show a visualization of a neural network."}, {"post_id": 58338, "ts": "2026-08-30T18:37:11Z", "hours": 2.1031, "text": "DEVLOG 3: TETRIS ✅ THE TETRIS GAME IS PRETTY MUCH COMPLETE (besides some finishing touches) the game is completely playable with: Moving pieces with arrow keys Rotating pieces Deleting rows And the game restarts after there is no more valid places to go So pretty much complete. Now it is time to dive into the deep waters that is… NEURAL NETWORKS Oh boy this is going to be fun (and hard). I already know that the kind of training that I have to do for this is reinforcement learning . Which basically is like giving dopamine to your artificial brain when it does something good and giving it a slap in the neck when it does something bad. Which in return it changes its weights based on its previous performance. But for the first thing I got to do is set up all of the mumbo jumbo that will actually allow the neural network to see. And I think I have a rough understanding on how I’m going to implement that. Stay tuned on this awesome journey of making an AI play Tetris!"}, {"post_id": 57362, "ts": "2026-08-29T14:21:46Z", "hours": 1.8567, "text": "DEVLOG 2 Ok it’s been a couple days but I’ve added key presses where: - Left Arrow = Piece moves to the left - Right Arrow = Piece moves to the right - Down Arrow = Piece soft drops. - Space Bar = Piece hard drops. Overall it wasn’t that hard to implement but I had this bug where after soft dropping it saves that position to the locked pieces array. Which in return kind of broke the whole game. Here is the broken code block: if event . type == pygame . KEYDOWN : if event . key == pygame . K_LEFT : self . currentPiece . x -= 1 if not validSpace ( self . currentPiece , self . grid ): self . currentPiece . x += 1 lockPiece ( self . currentPiece , self . locked_pos ) The problem was the last line where it says lockPiece ( self . currentPiece , self . locked_pos ) So all I had to do was remove that and it works perfectly. Now I need to make the game rules where if you finish a row it deletes it and then the hardest part… ROTATION."}, {"post_id": 55349, "ts": "2026-08-27T04:09:15Z", "hours": 4.8822, "text": "DEVLOG 1: Basic foundations It took me way longer than it should have but I finally did it. I learned how to use PyGame and now I’m on my way to remaking Tetris. I set up a function that puts a random Tetris shape onto the 2D array that is essentially the one source of truth in Tetris at least that’s how I think of it. With PyGame I then update every frame what it should display based on that 2D array. The picture below shows me spinning up 3 instances of this code working. Currently the blocks don’t do much but I’ll start working on that tomorrow. Plus I really want to get the Tetris remake done quick so I can start building and training the neural network to actually play the game for me."}]...
|
Title: Tetr.AI by @caleb_welch | Stardance
Devlog Title: Tetr.AI by @caleb_welch | Stardance
Devlogs:
DEVLOG 1: Basic foundations It took me way longer than it should have but I finally did it. I learned how to use PyGame and now I’m on my way to remaking Tetris. I set up a function that puts a random Tetris shape onto the 2D array that is essentially the one source of truth in Tetris at least that’s how I think of it. With PyGame I then update every frame what it should display based on that 2D array. The picture below shows me spinning up 3 instances of this code working. Currently the blocks don’t do much but I’ll start working on that tomorrow. Plus I really want to get the Tetris remake done quick so I can start building and training the neural network to actually play the game for me.
DEVLOG 2 Ok it’s been a couple days but I’ve added key presses where: - Left Arrow = Piece moves to the left - Right Arrow = Piece moves to the right - Down Arrow = Piece soft drops. - Space Bar = Piece hard drops. Overall it wasn’t that hard to implement but I had this bug where after soft dropping it saves that position to the locked pieces array. Which in return kind of broke the whole game. Here is the broken code block: if event . type == pygame . KEYDOWN : if event . key == pygame . K_LEFT : self . currentPiece . x -= 1 if not validSpace ( self . currentPiece , self . grid ): self . currentPiece . x += 1 lockPiece ( self . currentPiece , self . locked_pos ) The problem was the last line where it says lockPiece ( self . currentPiece , self . locked_pos ) So all I had to do was remove that and it works perfectly. Now I need to make the game rules where if you finish a row it deletes it and then the hardest part… ROTATION.
DEVLOG 3: TETRIS ✅ THE TETRIS GAME IS PRETTY MUCH COMPLETE (besides some finishing touches) the game is completely playable with: Moving pieces with arrow keys Rotating pieces Deleting rows And the game restarts after there is no more valid places to go So pretty much complete. Now it is time to dive into the deep waters that is… NEURAL NETWORKS Oh boy this is going to be fun (and hard). I already know that the kind of training that I have to do for this is reinforcement learning . Which basically is like giving dopamine to your artificial brain when it does something good and giving it a slap in the neck when it does something bad. Which in return it changes its weights based on its previous performance. But for the first thing I got to do is set up all of the mumbo jumbo that will actually allow the neural network to see. And I think I have a rough understanding on how I’m going to implement that. Stay tuned on this awesome journey of making an AI play Tetris!
DEVLOG 4: The beginning of learning PyTorch & Working AI-Tetris-Environment Pretty much the title sums up what I’ve been doing for the past 3h and 9m of this. I have some prior knowledge of the basics of machine learning ( from The Nature Of Code by Daniel Shiffman awesome book about coding would recommend ) by making a single layer perceptron ( basically a single neuron algorithm ) that can separate linearly separable data. I attempted to make a multi layered perceptron which actually puts the network in neural network. But I got stuck on back propagation. I don’t really know what to put as the picture for this devlog so I’ll just show a visualization of a neural network.
DEVLOG 5: Random movements An update from my previous devlog where I started learning pytorch. I have not learned pytorch to the point to where I can explain everything down to its finest details but enough to make my “AI” do some random junk with no direction. Pretty much I’m just initializing random weights and letting it go. I have 200 input neurons for my 20x10 board. The video I attached below shows the AI just doing some random stuff like rotating non stop and moving left and right.
DEVLOG 6: actual learning Wow two devlogs in pretty much a day… I need to touch grass… But that is not the point. IT IS FINALLY LEARNING (just very inefficiently) Currently it only learns from two things: How many rows it cleared on a single run Whether or not it sold the game Now pretty much the rest of this project will just be tweaking and experimenting with things. Before I ship I do want to train and release a demo model that you can test locally on your PC ( and I may want to test if it would work on android phones too ) that will come with the project. I also want to make it to where you can create and train your own models and potentially share them with other people. CAN’T WAIT FOR EVERYTHING TO BE DONE!!!!!!
DEVLOG 7: more AI training (hint: FAILED) This graph shows the results of my first training session of my AI showing how well the AI does over time through the reward. In total it lasted ~17 hours and its obviously not nearly enough time. The reward is supposed to go up over time, which it is. But not fast enough. Overall it only seems to increase in reward over time just by VERY little. Moving onto the other graph which shows the rows cleared over time. As you can see it never really increases on average. This shows that: MY AI SUCKSSSSSSS My AI is dumb Overall my AI can’t learn and I need to just keep on adjusting numbers over and over again.
DEVLOG 8: I think I may ship soon… Ok so I’ve hit a road block. Stardance ends soon which means I don’t really have much time left. My project is a completely working reinforcement learning AI which can play Tetris but not well. Originally I wanted to perfect a model and then ship the project but due to Stardance ending soon I may change that. Recent additions Added the ability to resume training on a model you made at your most recent checkpoint Added setup automation scripts for windows and linux Refined README with a getting started section and more detail in the Model History section to give the project more story Because I’m essentially prepped for shipping and it is a completely working project I will probably ship soon. Wish me luck. The screenshots shown are the results from training Tetr.AI-V2
Not to big of a devlog but I added executable files for easy running for this project. Also added a training_config json file to easily change training values.
Ships:
Tetr.AI This is the first release of Tetr.AI, my first ever reinforcement-learning project built for the Hack Club Stardance YSWS. Tetr.AI includes: A custom built Tetris environment built with PyGame which allows you to train and run your own models as well as just play Tetris A PyTorch neural network Deep-Q-learning Model checkpoint saving and loading Saving of training statistics into a CSV file A graphing script to allow you to visualize how well your model trained Windows and Linux setup scripts Model status The training pipeline is completely functional, but due to time constraints this release won’t contain a model which can play Tetris well. I completed two long duration training experiments during development which revealed problems with reward shaping, epsilon, and sparse rewards. Everything on this is documented in the README. Training and experimentation will continue after stardance...
|
1793008135.7356422
|
1793094535.7356422
|
|
53985
|
Charlie's Terminal Game Compendium by @Charlie Charlie's Terminal Game Compendium by @Charlie_Coder | Stardance...
|
Charlie_Coder
|
1
|
14.29
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-20T05:41:25Z", "hours": 14.0, "multiplier": 1.38, "payout": 0, "blessing": "neutral", "text": "I have made a simple game compendium which runs in the terminal and is text based. It is a python based compendium, which stores data in text files, and is installed using pip (instructions on the pypi project). There are three games: Connect 4, Tic Tac Toe, and Number Guesser. These games challenged my abilities in coding, as this was a very challenging game to code. I have only very basic knowledge of python coding. However, number guesser was noticeably easier as it was single lines, rather than me trying to invent a way to store the data of where various tokens were positioned. Overall, I put a lot of effort and time into this game compendium. While I am a beginner coder, and while it is only text based, I am proud of what I have managed to create, and that it can now be installed with pip. I hope you enjoy this game :)", "repo": "https://github.com/CharlieLindsay/charlie-s-game-compendium", "demo": "https://pypi.org/project/charlie-game-compendium/"}]...
|
[{"post_id": 77179, "ts": "202 [{"post_id": 77179, "ts": "2026-10-05T23:02:53Z", "hours": 0.2889, "text": "My last shipment failed because I was getting the user to manually state when they win. While this was intentional, as in real life, part of Connect 4 and Tic Tac Toe (noughts and crosses) is keeping track. However, I like the suggestion, and the 2 games that didn’t have win detection now do. Now I believe I am ready to ship. This project was supposed to be a small code I was writing for me to learn Python skills, but it has turned out much bigger than I expected, and now I am proud of that implementation, so I am going to ship again :)"}, {"post_id": 70994, "ts": "2026-09-20T05:35:19Z", "hours": 0.5897, "text": "Hopefully time to ship! I have done some of the final touches, and I got it on pypi, so it can now be installed using pip command: pip install charlie-game-compendium and run using: charlie-games"}, {"post_id": 69773, "ts": "2026-09-17T19:19:40Z", "hours": 1.5142, "text": "I have completed the tic tac toe game and leaderboard. The overall shell of the game is complete :)"}, {"post_id": 69023, "ts": "2026-09-16T07:36:00Z", "hours": 2.2769, "text": "I have fixed lots of the problems with the game failing on bad values, and have started the Tic Tac Toe game (and the number guesser which is very easy compared to the others), which works in a similar way to the Connect 4 game."}, {"post_id": 68480, "ts": "2026-09-15T06:10:56Z", "hours": 8.4733, "text": "I completely forgot to do development logs!! So frustrated but I will try to name my progress over the 8 hours of work. I have recorded what the game does now, it doesn’t work on most boundary cases and there are a lot of ways to break it, such as saying a number too high in Connect 4 creates an uncaught IndexError. However, I am just proud to get a Connect 4 board that renders the positions of the tokens, and makes sure they fall to the bottom. It also stores the leaderboard in a text file in a slightly weird looking syntax I created. Also, the user name is saved."}, {"post_id": 59888, "ts": "2026-09-01T21:32:29Z", "hours": 1.4994, "text": "I’ve got the basics sorted, a laid out plan and have started the menu. My main highlight so far has been getting the file checking working, so it greets the user by it’s name if they have it stored in the user data file and otherwise it catches it rather than crashing on FileNotFoundError."}]...
|
Title: Charlie's Terminal Game Compendium by @ Title: Charlie's Terminal Game Compendium by @Charlie_Coder | Stardance
Devlogs:
I’ve got the basics sorted, a laid out plan and have started the menu. My main highlight so far has been getting the file checking working, so it greets the user by it’s name if they have it stored in the user data file and otherwise it catches it rather than crashing on FileNotFoundError.
I completely forgot to do development logs!! So frustrated but I will try to name my progress over the 8 hours of work. I have recorded what the game does now, it doesn’t work on most boundary cases and there are a lot of ways to break it, such as saying a number too high in Connect 4 creates an uncaught IndexError. However, I am just proud to get a Connect 4 board that renders the positions of the tokens, and makes sure they fall to the bottom. It also stores the leaderboard in a text file in a slightly weird looking syntax I created. Also, the user name is saved.
I have fixed lots of the problems with the game failing on bad values, and have started the Tic Tac Toe game (and the number guesser which is very easy compared to the others), which works in a similar way to the Connect 4 game.
I have completed the tic tac toe game and leaderboard. The overall shell of the game is complete :)
Hopefully time to ship! I have done some of the final touches, and I got it on pypi, so it can now be installed using pip command: pip install charlie-game-compendium and run using: charlie-games
My last shipment failed because I was getting the user to manually state when they win. While this was intentional, as in real life, part of Connect 4 and Tic Tac Toe (noughts and crosses) is keeping track. However, I like the suggestion, and the 2 games that didn’t have win detection now do. Now I believe I am ready to ship. This project was supposed to be a small code I was writing for me to learn Python skills, but it has turned out much bigger than I expected, and now I am proud of that implementation, so I am going to ship again :)
Ships:
I have made a simple game compendium which runs in the terminal and is text based. It is a python based compendium, which stores data in text files, and is installed using pip (instructions on the pypi project). There are three games: Connect 4, Tic Tac Toe, and Number Guesser. These games challenged my abilities in coding, as this was a very challenging game to code. I have only very basic knowledge of python coding. However, number guesser was noticeably easier as it was single lines, rather than me trying to invent a way to store the data of where various tokens were positioned. Overall, I put a lot of effort and time into this game compendium. While I am a beginner coder, and while it is only text based, I am proud of what I have managed to create, and that it can now be installed with pip. I hope you enjoy this game :)...
|
1793008136.9155364
|
1793094536.9155364
|
|
53994
|
Godot - Froken by @martycat111 | Stardance
|
martycat111
|
1
|
23.0
|
143
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-03T20:07:34Z", "hours": 23.0, "multiplier": 6.22, "payout": 143, "blessing": "neutral", "text": "A silly Godot game. I made it to learn Godot. Signals are hard when instantiating. Physics are annoying. It was fun.", "repo": "https://github.com/Martycat111/Froken", "demo": "https://martycat111.itch.io/froken"}]...
|
[{"post_id": 76518, "ts": "202 [{"post_id": 76518, "ts": "2026-10-03T19:55:11Z", "hours": 4.9028, "text": "Final build, will ship unless i find bugs. Improved tutorial, transitions, and gameplay tweaks. Check out my itch. :)"}, {"post_id": 75482, "ts": "2026-09-30T07:06:36Z", "hours": 8.635, "text": "Huge Updates - Title screen, art, terrain, and so, so much more…"}, {"post_id": 74309, "ts": "2026-09-27T05:06:09Z", "hours": 6.7633, "text": "Fixed most aspects of my game. Its not a 1/10 anymore."}, {"post_id": 58552, "ts": "2026-08-31T00:12:15Z", "hours": 2.6772, "text": "Godot game chicken flies"}]...
|
Title: Godot - Froken by @martycat111 | Stardance
Title: Godot - Froken by @martycat111 | Stardance
Devlogs:
Godot game chicken flies
Fixed most aspects of my game. Its not a 1/10 anymore.
Huge Updates - Title screen, art, terrain, and so, so much more…
Final build, will ship unless i find bugs. Improved tutorial, transitions, and gameplay tweaks. Check out my itch. :)
Ships:
A silly Godot game. I made it to learn Godot. Signals are hard when instantiating. Physics are annoying. It was fun....
|
1793008138.0533867
|
1793094538.0533867
|
|
16571
|
mocha by @Glitchy | Stardance
|
Glitchy
|
1
|
101.0
|
1806
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-13T18:57:02Z", "hours": 101.0, "multiplier": 17.94, "payout": 1806, "blessing": "neutral", "text": "I made a package manager for Windows, which is somewhat backwards compatible with scoop packages. To be honest there’s still a lot of work that I want to do, but I have exams and college application coming up soon so I can’t. That’s not to say I’m not happy with the state of the ship. At the very least it has all the core features that a package manager should have, but there are still a lot of bugs which is why this is only v0.0.1. The biggest challenge by far was trying to figure out how Scoop does things internally. A lot of stuff just doesn’t have documentation, so you have to dig through the really messy PowerShell source code.", "repo": "https://github.com/Protract-123/mocha", "demo": "https://github.com/Protract-123/mocha/releases/latest"}]...
|
[{"post_id": 67579, "ts": "202 [{"post_id": 67579, "ts": "2026-09-13T18:33:17Z", "hours": 1.7761, "text": "So I wrote a README, added a license (MIT of course) and setup CI/CD so that releases are automatically built and deployed. Honestly I forgot how hard it is to write a good README. You need to get a lot of information through without it looking like a wall of text."}, {"post_id": 67267, "ts": "2026-09-13T10:36:48Z", "hours": 5.8047, "text": "I forgot to make a devlog in between so this will be like 2 bigger devlogs. I parallelized bucket updates, which speeds it up quite a bit. This also allowed me to try out parallelism even more, which I plan to apply throughout the CLI later on. I also added configuration options for the runners which mocha shim will use to run certain file types. For example, you can set the python-runner to select the python version that’ll be used to run python scripts that are shimmed. Downloads now have a progress bar, so you don’t need to wonder whether something is happening or not during a long download. Finally env_set is fully supported since I added the relevant variable parsing. This was pretty much just me cleaning out the TODO list before I ship. I also did a lot of smaller bug fixes and refactors as seen below. fix(commands): prevent app installation if already installed (cb27d07) fix(commands): fix config opening with “start” (74f3679) fix(commands): correctly handle non-apps when upgrading (f7419f6) fix: make LogOutput go to Stdout not Stderr (bc10357) fix: handle empty versions correctly (2287da9) fix(pkg): remove correct temp dir (33189b6) fix(shim): warn for unknown shim extension (622c2b4) fix: skip downloads with no hash by default (69d4e35) fix: use correct timeout for downloads (44e527b) fix: drop unnecessary return value from GetExecutableEntries (9fd845c) fix(config): remove unused option (1339971) fix(commands): don’t error for valid results (87c4d6c) refactor(config): rename variables/functions (f253d9d) fix: use unique temp directories (a159e23) refactor: use fmt.Fprintln directly (d2d54bf)"}, {"post_id": 65401, "ts": "2026-09-10T14:55:22Z", "hours": 2.5386, "text": "Lots of small bug fixes and changes, I’ll just list them out: feat(cmd): allow removal of multiple shims in one execution (f2fae3f) fix(manifest): correctly ignore invalid shortcut entries (6a08478) fix(fileops): use correct registry type (5d5d796) fix(config): seed config with defaults (9dfaaff) fix(cmd): use correct release sources (a2a9ba1) fix(cmd): use bucket from install info (5a9109b) I also added support for more file types being shimmed, which helps a lot with compatibility. The file types are .py , .bat , .cmd , .jar and .ps1 ."}, {"post_id": 52474, "ts": "2026-08-22T16:37:15Z", "hours": 4.6758, "text": "Lot of time going into this devlog, but it makes sense since I did do a lot. I did this sweeping refactor of the entire commands module which moved around a lot of code. Essentially each command now gets it’s own directory under the commands module that represents it’s children/parents. For example commands/shim/remove/cmd.go contains code for the mocha shim remove command. Each cmd.go contains a Command struct that has the relevant fields and functions attached to it. This structure just makes things more organized and also means adding test files will be a bit easier since functionality is now isolated. I also sorted out the shim binary. So essentially https://github.com/ScoopInstaller/Shim offers different version of the shim binary which can be installed. Previously I hard coded the code to install cpp v0.1.0 but now users can run mocha shim binary releases to see the options and mocha shim binary setup to install their chosen binary. This also means we actually get the latest releases from GitHub."}, {"post_id": 51141, "ts": "2026-08-20T17:11:51Z", "hours": 3.6722, "text": "Finally got a bit of time to do a bit of development. First thing I did was remove a field from install.json to match scoop . This means that mocha should be a drop in replacement for existing scoop installs. Then I added partial support for env_set and env_add_path . The main thing I need to do to complete the feature is parse variables and replace them with the appropriate paths. These 2 fields are some of the last manifest fields I need to support besides pre/post (un)install hooks."}, {"post_id": 34596, "ts": "2026-07-25T13:39:02Z", "hours": 2.5778, "text": "My summer break has ended so development is going to be a lot slower from now. I added mocha outdated so you can list outdated apps before upgrading them to a newer version. Besides that I tweaked a lot of stuff related to CLI output. For example I changed search to output one table, and simply outputting exact matches at the top of that table. I also changed a lot of messages which were using LogOutput to LogInfo so they use the correct color and output to stderr and not stdout ."}, {"post_id": 31801, "ts": "2026-07-20T14:04:04Z", "hours": 1.5481, "text": "Not sure why I didn’t do this earlier, but I’ve added success messages to commands where it makes sense. Also added a success color to the config so you can change what the success color is. I do still need to improve CLI output quite a bit, but it’s slowly getting there."}, {"post_id": 30693, "ts": "2026-07-18T14:02:54Z", "hours": 2.1922, "text": "I’m writing this one right before F1 Qualifying at Spa! Continuing with the trend of some of my recent work, I improved what table outputs look like to be a little bit more readable. We now use proper separators in the form of Unicode Box Drawing Characters . I also made column alignment configurable, which improves legibility for some commands like mocha bucket list and mocha cache show . I’ve attached an image of the scoop and mocha versions of bucket list so you can compare for yourself."}, {"post_id": 30286, "ts": "2026-07-17T18:51:34Z", "hours": 3.4797, "text": "I love refactoring!!!! I’ll probably end up spending another 20 hours just on refactoring because it’s so fun!!!! This time around I wanted to refactor the code so that our commands orchestrate stuff instead of the helper functions. For example, pkg.Install would first download a package, then install it, and then link it through shims and shortcuts all by itself. This causes issues because it means error messages become slightly worse, and it creates a class of bugs due to edge cases where we don’t necessarily want this order of orchestration. Hence I did a lot of refactoring in the pkg module. I also ended up adding a way to skip verification of downloads when downloading, installing or updating a package through --skip-verify . It’s a useful option in situations where there is a malformed manifest or simply no hash to begin with."}, {"post_id": 30054, "ts": "2026-07-17T10:28:53Z", "hours": 4.6269, "text": "mocha now supports a user defined theme for output colors. In the process I ended up doing a lot of stuff related to the config. First thing I did was swap to fatih/color for colored output, since it handles stuff like colors in command prompt and removing color when output is piped. Then I refactored the config module. Earlier I would pass around a MochaConfiguration object through every function. Now I use a config singleton that’s accessible from any function. Why? Because it means I don’t need to pass the object every time I want to log information. Also means I don’t need to pass mochaDir through almost every function in the codebase. Getting user defined themes was a bit complicated because I needed a good way to handle a default theme so output doesn’t look bad if parsing fails. I handled this by only using the configured theme if every color resolves properly. Otherwise output falls back to the already loaded default theme. Due to this you still get colored output even if there are errors or warning before the configuration and theme is loaded."}, {"post_id": 29066, "ts": "2026-07-15T18:30:47Z", "hours": 4.7214, "text": "So I’ve been doing a bit of refactoring, a bit of bug fixing and a bit of optimization. Essentially just polishing mocha before I work on the next feature. Here’s some of the stuff I did: created tests for ParseRefString to validate behavior cache manifest json between info calls since I/O is really slow bumped dependency versions refactored manifest/info.go Besides that I fixed the uninstall flow since it was really bugged after the latest changes. Essentially mocha would uninstall apps with incorrect info. It would also try to remove shims/shortcuts for apps which don’t have any active shims/shortcuts. I then added a bit of logging since the uninstall command didn’t give any user output for whatever reason (i forgot to earlier)."}, {"post_id": 27086, "ts": "2026-07-12T10:29:45Z", "hours": 6.4975, "text": "This is going to be the equivalent of 2 devlogs since I thought I made one earlier for persists but I didn’t. New feature! We now handle persist items in order to store data between versions. These are files which are persisted between versions of an app. Lets take git as an example to explain why persist exists. Say you want to make sure your git config isn’t deleted every time you update. The issue with this is that the config file is saved in the version specfic directory. To resolve this we can keep the config in $MOCHA_DIR/persist and then symlink the config to where it needs to be, which is essentially what persist tells us to do. Since we handled persist items last time we can now implement mocha upgrade to update apps. The way scoop handles updates is by first removing anything that references the app, like shortcuts or shims . Then we just follow the install process from scratch. This leaves the old version available in case a user wants to revert versions due to a bug, while also updating to the latest available version. This can be seen in the video below, which shows me updating llama.cpp-hip-radeon ."}, {"post_id": 23572, "ts": "2026-07-06T16:39:13Z", "hours": 3.53, "text": "We now create shortcuts! This means any GUI apps should show up properly in the start menu, just like they do when you install with scoop . All I really had to do was a bit of orchestration since I decided to vendor in an implementation from https://github.com/jxeng/shortcut Besides that I expanded the number of apps that are supported by implementing a bit of code that handle architecture specific bin fields, along with bin fields which store 2D arrays. I also cleared up some of the TODO items. I swapped the junction implementation to an implementation from https://github.com/nyaosorg/go-windows-junction since we were previously shelling out to CLI. That and I added a bit more zip bomb protection For the purposes of the video below I changed the location which shortcuts get put to my desktop. It’ll probably be configurable, and match scoop by putting shortcuts in the startup menu by default"}, {"post_id": 22839, "ts": "2026-07-05T13:36:18Z", "hours": 3.3089, "text": "As I mentioned in the previous devlog I added good help information to every bit of the CLI. It’s surprisingly difficult to write good help messages which explains everything to users in a few words I also changed the behaviour of the mocha cache clear command to not clear all cache by default. That’s now gated behind the --all flag in order to match scoop a bit more"}, {"post_id": 21420, "ts": "2026-07-03T11:02:24Z", "hours": 1.0722, "text": "Typically I don’t want to make devlogs for small stuff like this, but this is something I found really cool. So I was working on help messages for all the commands when I realized that mocha bucket list felt a bit slower than pretty much every other command. This is because we need to shell out to git 2 times per bucket, and I had 4 buckets added. While 8 git commands might not sound like a lot, it was enough to make mocha bucket list feel slow. So what I did is I parallelized the metadata fetching through an errgroup . Instead of fetching the metadata for each bucket in order, we fetch the metadata for all 4 buckets simultaneously. This led to a big performance uplift. About 3 times faster than the old version of mocha , and just over 12 times faster than scoop for this operation. See the video below."}, {"post_id": 21386, "ts": "2026-07-03T09:17:07Z", "hours": 2.2464, "text": "I finished up mocha uninstall and mocha list , which means you can actually manage installed apps instead of manually deleting them. There’s not much that goes into mocha uninstall . You just need to remove the relevant shims and app directories since the apps that mocha supports are all portable. mocha list is similarly simple. It’s just loops over the directories in $MOCHA_DIR/apps and looks for apps along with the versions installed for each app."}, {"post_id": 19910, "ts": "2026-07-01T10:53:02Z", "hours": 5.4625, "text": "So I added support for more apps by implementing more extractors. This means in theory any apps which don’t need a pre-install or post-install should work. To be more specific, I handle a few more properties on manifests. Those being extract_dir and innosetup , which inform how an app needs to be installed. I also implement 7zip and innounp as extractors to support more file formats which applications are distributed in. Of course there’s still a lot of work before I consider this ready for public use. I need to create commands for some basic operations like uninstalling, updating and listing apps. I also need to handle shortcuts otherwise GUI apps can’t be accessed from the start menu. Besides that I need to improve the user experience. As you can see in the video below mocha just sort of dumps everything to the console even if it’s not relevant. Help menus are also critical to get working properly."}, {"post_id": 18238, "ts": "2026-06-29T09:51:16Z", "hours": 3.7839, "text": "Finished up the code cleanup in commands , fileops and manifests . I did catch a few edge cases and some incorrect behavior in the process, which is why I always spend so much time reviewing code. I did use AI to assist with code review because I think it’s an area where AI shines. AI is really good at finding small errors or inconsistencies in the codebase which I probably wouldn’t notice. For example, it identified that the ManifestReferences argument was not a required argument for the download command, which meant no help message was displayed on incorrect usage like the other commands. One big thing I will work on eventually is console output. Right now errors are well formatted but a lot of the time commands just run stuff without providing a lot of insight into what actions they are taking which isn’t great. Even the help menu is pretty useless right now (see the image below). Extra context: A manifest reference is a pointer to an app (e.g. main/ [email protected] )"}, {"post_id": 17027, "ts": "2026-06-27T17:10:53Z", "hours": 5.3025, "text": "Before working on more features and expanding the amount of apps mocha actually supports I wanted to go through the codebase and do a lot of cleanup since the codebase is quite messy. There are silly mistakes in some files and bad implementations in others. Hence the time I spent during this period was focused on moving code to where it should be and cleaning up some edge cases, specifically related to the bucket , config and shim modules. A good example of this is moving the code to get the active config to the config module instead of leaving it in main.go . Next up will be refactoring the commands , fileops , and manifest modules. I don’t have much to show so I figured I would present a feature I added but didn’t show earlier: the ability to skip cache hits with the --force flag when installing or downloading an app. Some context I forgot to add initially: I renamed the app module to manifest since I felt it was more accurate to what it actually handles scope wise."}, {"post_id": 15814, "ts": "2026-06-25T18:17:50Z", "hours": 2.5558, "text": "Huge milestone!!! I’ve gotten mocha install working for very basic apps! This means the entire process of downloading a file, then extracting it, then creating a junction and finally creating a shim now works for basic pieces of software! So in terms of what I actually did this devlog, I added cache hits to the download command since it’s relevant to the install command. I then implemented the aforementioned .zip extraction and junction creation. Then all that was left was a bit of orchestration, getting everything to work together properly. See a working install of innounp using mocha install below!"}, {"post_id": 15668, "ts": "2026-06-25T14:03:10Z", "hours": 0.7572, "text": "mocha update is another command which does very little but is very important. All it does is update the known_buckets file, and run git pull on all added buckets to update them. It can also update just the buckets you specify if you pass in an argument. I do need to improve the output of the command since it outputs raw git right now, but at least it’s functional. See the demo below."}, {"post_id": 14392, "ts": "2026-06-23T14:41:51Z", "hours": 6.9436, "text": "Spent a bit longer between devlogs this time, but it was worth it. So I realized the error messages were really bad. I was pretty much just passing errors up the call stack without adding any context, which isn’t great since it means our error messages will be useless to people reading them I therefore went through every single file of the codebase and wrote good error messages which add a bit of context every time we pass it up the call stack. I also did a bit of refactoring where I thought it would be worth it. For example in the shim module I now set the PE subsystem of the shim binary while it’s in memory instead of writing to disk twice. A few good examples of what the new error messages look like can be seen in the video below."}, {"post_id": 13054, "ts": "2026-06-21T10:47:05Z", "hours": 3.4069, "text": "Shims are simple in concept, complicated in reality. So essentially a shim in mocha is just an executable which calls another executable. It’s similar to a shortcut in that sense, except it shows up in $PATH Thankfully the scoop project already has a repository with 4 different implementations for the shim binary, so I can just have mocha shim download one of those binaries. The complicated part was the PE Subsystem. The PE subsystem is basically a bit of info in each binary which tells Windows whether it’s a console application, or a GUI application. We need to set the PE subsystem of the shim exe to the PE subsystem of the binary we are calling for Windows to execute the binary properly. Hence I need to read and write raw binary data. All of this is just the implementation for exe shims. Scoop itself contains implementations for .bat/.cmd , .ps1 , .jar , .py and linux binaries , all of which have wildly different implementations compared to .exe shims. The video below shows the working set of mocha shim commands (those being add , remove and list )."}, {"post_id": 12032, "ts": "2026-06-19T16:57:37Z", "hours": 1.8778, "text": "mocha cache is a simple command. It shows you what files are currently in $MOCHA_DIR/cache directory and it clears them out. One thing I noticed was that scoop cache show actually displays raw bytes instead of human readable file sizes for each cache entry, which is a bit odd since the total they display is human readable. Therefore I made my implementation mocha cache list display human readable sizes since that’s a more reasonable default."}, {"post_id": 11234, "ts": "2026-06-18T11:50:44Z", "hours": 2.2589, "text": "Fuzzy search is really really good. While implementing mocha search I noticed the results returned by scoop search were in alphabetical order, which doesn’t make a lot of sense. If I do scoop search git the first result should probably be git As a result my implementation of search uses github.com/sahilm/fuzzy which is a small library which provides a fuzzy search implementation. Scoop also checks for binary name matches, e.g. package biodiff can provide a binary called git-biodiff and show up in search results. I decided to remove this for now, since I personally find it a bit unnecessary. scoop search also lists all search results, which is okay when results are sorted alphabetically but doesn’t make sense when searches are relevance based. Therefore, by default mocha search will list exact matches plus the 20 most relevant search results. This can be overridden by the --count argument, where setting it to 0 displays all results. A demonstration of mocha search vs scoop search can be seen in the video below."}, {"post_id": 10748, "ts": "2026-06-17T17:14:41Z", "hours": 2.1597, "text": "I finished up mocha download , which surprisingly does a bit more than simply downloading files. The first thing it does is well… download the file. This is a bit more complicated than it seems though, since we need to identify the right file to download based on cpu architecture. Hence the very cursed JSON parsing I had to create. After downloading a file, we also do a hash check. We support the 4 types of file hashes which scoop support, those being sha256 , sha512 , md5 and sha1 . Currently files get downloaded to the $MOCHA_DIR/cache directory like in scoop, however we don’t actually check if there’s anything cached which can lead to repeated downloads. That’s something I’ll need to fix later on"}, {"post_id": 10131, "ts": "2026-06-16T18:54:22Z", "hours": 1.4081, "text": "I was working on the mocha download command so I can sort out fetching files, and during it I realized my current app format makes things a bit weird. mocha cat previously took in a flag for bucket through -b and a name. Scoop on the other hand uses an application reference in the format bucket/name@version . Scoop’s format is really important for downloads and installs, so it didn’t make sense to not standardize it between mocha download and mocha cat . Hence this shorter devlog! See the video below for the new usage (version numbers are ignored for mocha cat )."}, {"post_id": 10004, "ts": "2026-06-16T15:21:57Z", "hours": 2.9753, "text": "I did a bit of refactoring to split the core functionality from the command files. This means that the code for downloading and deleting buckets is separated from the code for the various commands. I’m doing this primarily for better code organization, and also to prevent import cycles. I also finished up the config system I mentioned last time. It’ll be one of the bigger improvements over scoop, which has a basic set of configuration options. TOML was the obvious choice for the config format since it is really easy to read and write. I made sure that you can put it in any of the standard locations, such as %APPDATA% and .config or in $MOCHA_DIR . Running mocha config will open the configuration in your preferred app, and also generate the default config if a configuration hasn’t been detected in any of the valid locations. Currently the configuration can be used to make mocha cat run an external program for printing manifests to stdout . See the video below for an example using bat"}, {"post_id": 8826, "ts": "2026-06-14T17:52:54Z", "hours": 2.6147, "text": "So this is a spot where I think the improvements over scoop start becoming really apparent. The scoop cat command simply prints an app’s manifest to console. However due to the long startup time of PowerShell scripts (scoop is written in PowerShell) basic stuff like scoop cat takes a second. mocha cat on the other hand is nearly instantaneous since it’s a compiled binary with almost 0 startup time. You can see how this plays out in real usage in the video below. I also half baked a config system, but it’s not finished so I’ll talk about that in the next devlog."}, {"post_id": 8586, "ts": "2026-06-14T08:48:35Z", "hours": 2.85, "text": "I finished off the remaining mocha bucket subcommands, those being add , rm and list . These commands manage “buckets” which are pretty much just package sources. mocha bucket add uses git to clone the relevant bucket into the [MOCHA_DIR]/buckets directory. By default MOCHA_DIR is [USER]/mocha mocha bucket list simply loops over the [MOCHA_DIR]/buckets directory and gets relevant info for each bucket. mocha bucket rm removes a bucket by just deleting the folder containing the bucket. For example, removing the main bucket deletes [MOCHA_DIR]/buckets/main"}, {"post_id": 8208, "ts": "2026-06-13T17:32:25Z", "hours": 2.0261, "text": "I started off with something a bit simple: mocha bucket known The known bucket list in scoop is a list of buckets which are known by the package manager in advance. These buckets don’t require the full URL to be used when using scoop bucket sub-commands. For example instead of running scoop bucket add https://github.com/ScoopInstaller/Main you can instead run scoop bucket add main As seen in the video below, mocha bucket known doesn’t do much. First it downloads buckets.json if it doesn’t exist. Then it parses the json and outputs it to console."}]...
|
Title: mocha by @Glitchy | Stardance
Devlogs:
I s Title: mocha by @Glitchy | Stardance
Devlogs:
I started off with something a bit simple: mocha bucket known The known bucket list in scoop is a list of buckets which are known by the package manager in advance. These buckets don’t require the full URL to be used when using scoop bucket sub-commands. For example instead of running scoop bucket add https://github.com/ScoopInstaller/Main you can instead run scoop bucket add main As seen in the video below, mocha bucket known doesn’t do much. First it downloads buckets.json if it doesn’t exist. Then it parses the json and outputs it to console.
I finished off the remaining mocha bucket subcommands, those being add , rm and list . These commands manage “buckets” which are pretty much just package sources. mocha bucket add uses git to clone the relevant bucket into the [MOCHA_DIR]/buckets directory. By default MOCHA_DIR is [USER]/mocha mocha bucket list simply loops over the [MOCHA_DIR]/buckets directory and gets relevant info for each bucket. mocha bucket rm removes a bucket by just deleting the folder containing the bucket. For example, removing the main bucket deletes [MOCHA_DIR]/buckets/main
So this is a spot where I think the improvements over scoop start becoming really apparent. The scoop cat command simply prints an app’s manifest to console. However due to the long startup time of PowerShell scripts (scoop is written in PowerShell) basic stuff like scoop cat takes a second. mocha cat on the other hand is nearly instantaneous since it’s a compiled binary with almost 0 startup time. You can see how this plays out in real usage in the video below. I also half baked a config system, but it’s not finished so I’ll talk about that in the next devlog.
I did a bit of refactoring to split the core functionality from the command files. This means that the code for downloading and deleting buckets is separated from the code for the various commands. I’m doing this primarily for better code organization, and also to prevent import cycles. I also finished up the config system I mentioned last time. It’ll be one of the bigger improvements over scoop, which has a basic set of configuration options. TOML was the obvious choice for the config format since it is really easy to read and write. I made sure that you can put it in any of the standard locations, such as %APPDATA% and .config or in $MOCHA_DIR . Running mocha config will open the configuration in your preferred app, and also generate the default config if a configuration hasn’t been detected in any of the valid locations. Currently the configuration can be used to make mocha cat run an external program for printing manifests to stdout . See the video below for an example using bat
I was working on the mocha download command so I can sort out fetching files, and during it I realized my current app format makes things a bit weird. mocha cat previously took in a flag for bucket through -b and a name. Scoop on the other hand uses an application reference in the format bucket/name@version . Scoop’s format is really important for downloads and installs, so it didn’t make sense to not standardize it between mocha download and mocha cat . Hence this shorter devlog! See the video below for the new usage (version numbers are ignored for mocha cat ).
I finished up mocha download , which surprisingly does a bit more than simply downloading files. The first thing it does is well… download the file. This is a bit more complicated than it seems though, since we need to identify the right file to download based on cpu architecture. Hence the very cursed JSON parsing I had to create. After downloading a file, we also do a hash check. We support the 4 types of file hashes which scoop support, those being sha256 , sha512 , md5 and sha1 . Currently files get downloaded to the $MOCHA_DIR/cache directory like in scoop, however we don’t actually check if there’s anything cached which can lead to repeated downloads. That’s something I’ll need to fix later on
Fuzzy search is really really good. While implementing mocha search I noticed the results returned by scoop search were in alphabetical order, which doesn’t make a lot of sense. If I do scoop search git the first result should probably be git As a result my implementation of search uses github.com/sahilm/fuzzy which is a small library which provides a fuzzy search implementation. Scoop also checks for binary name matches, e.g. package biodiff can provide a binary called git-biodiff and show up in search results. I decided to remove this for now, since I personally find it a bit unnecessary. scoop search also lists all search results, which is okay when results are sorted alphabetically but doesn’t make sense when searches are relevance based. Therefore, by default mocha search will list exact matches plus the 20 most relevant search results. This can be overridden by the --count argument, where setting it to 0 displays all results. A demonstration of mocha search vs scoop search can be seen in the video below.
mocha cache is a simple command. It shows you what files are currently in $MOCHA_DIR/cache directory and it clears them out. One thing I noticed was that scoop cache show actually displays raw bytes instead of human readable file sizes for each cache entry, which is a bit odd since the total they display is human readable. Therefore I made my implementation mocha cache list display human readable sizes since that’s a more reasonable default.
Shims are simple in concept, complicated in reality. So essentially a shim in mocha is just an executable which calls another executable. It’s similar to a shortcut in that sense, except it shows up in $PATH Thankfully the scoop project already has a repository with 4 different implementations for the shim binary, so I can just have mocha shim download one of those binaries. The complicated part was the PE Subsystem. The PE subsystem is basically a bit of info in each binary which tells Windows whether it’s a console application, or a GUI application. We need to set the PE subsystem of the shim exe to the PE subsystem of the binary we are calling for Windows to execute the binary properly. Hence I need to read and write raw binary data. All of this is just the implementation for exe shims. Scoop itself contains implementations for .bat/.cmd , .ps1 , .jar , .py and linux binaries , all of which have wildly different implementations compared to .exe shims. The video below shows the working set of mocha shim commands (those being add , remove and list ).
Spent a bit longer between devlogs this time, but it was worth it. So I realized the error messages were really bad. I was pretty much just passing errors up the call stack without adding any context, which isn’t great since it means our error messages will be useless to people reading them I therefore went through every single file of the codebase and wrote good error messages which add a bit of context every time we pass it up the call stack. I also did a bit of refactoring where I thought it would be worth it. For example in the shim module I now set the PE subsystem of the shim binary while it’s in memory instead of writing to disk twice. A few good examples of what the new error messages look like can be seen in the video below.
mocha update is another command which does very little but is very important. All it does is update the known_buckets file, and run git pull on all added buckets to update them. It can also update just the buckets you specify if you pass in an argument. I do need to improve the output of the command since it outputs raw git right now, but at least it’s functional. See the demo below.
Huge milestone!!! I’ve gotten mocha install working for very basic apps! This means the entire process of downloading a file, then extracting it, then creating a junction and finally creating a shim now works for basic pieces of software! So in terms of what I actually did this devlog, I added cache hits to the download command since it’s relevant to the install command. I then implemented the aforementioned .zip extraction and junction creation. Then all that was left was a bit of orchestration, getting everything to work together properly. See a working install of innounp using mocha install below!
Before working on more features and expanding the amount of apps mocha actually supports I wanted to go through the codebase and do a lot of cleanup since the codebase is quite messy. There are silly mistakes in some files and bad implementations in others. Hence the time I spent during this period was focused on moving code to where it should be and cleaning up some edge cases, specifically related to the bucket , config and shim modules. A good example of this is moving the code to get the active config to the config module instead of leaving it in main.go . Next up will be refactoring the commands , fileops , and manifest modules. I don’t have much to show so I figured I would present a feature I added but didn’t show earlier: the ability to skip cache hits with the --force flag when installing or downloading an app. Some context I forgot to add initially: I renamed the app module to manifest since I felt it was more accurate to what it actually handles scope wise.
Finished up the code cleanup in commands , fileops and manifests . I did catch a few edge cases and some incorrect behavior in the process, which is why I always spend so much time reviewing code. I did use AI to assist with code review because I think it’s an area where AI shines. AI is really good at finding small errors or inconsistencies in the codebase which I probably wouldn’t notice. For example, it identified that the ManifestReferences argument was not a required argument for the download command, which meant no help message was displayed on incorrect usage like the other commands. One big thing I will work on eventually is console output. Right now errors are well formatted but a lot of the time commands just run stuff without providing a lot of insight into what actions they are taking which isn’t great. Even the help menu is pretty useless right now (see the image below). Extra context: A manifest reference is a pointer to an app (e.g. main/ [email protected] )
So I added support for more apps by implementing more extractors. This means in theory any apps which don’t need a pre-install or post-install should work. To be more specific, I handle a few more properties on manifests. Those being extract_dir and innosetup , which inform how an app needs to be installed. I also implement 7zip and innounp as extractors to support more file formats which applications are distributed in. Of course there’s still a lot of work before I consider this ready for public use. I need to create commands for some basic operations like uninstalling, updating and listing apps. I also need to handle shortcuts otherwise GUI apps can’t be accessed from the start menu. Besides that I need to improve the user experience. As you can see in the video below mocha just sort of dumps everything to the console even if it’s not relevant. Help menus are also critical to get working properly.
I finished up mocha uninstall and mocha list , which means you can actually manage installed apps instead of manually deleting them. There’s not much that goes into mocha uninstall . You just need to remove the relevant shims and app directories since the apps that mocha supports are all portable. mocha list is similarly simple. It’s just loops over the directories in $MOCHA_DIR/apps and looks for apps along with the versions installed for each app.
Typically I don’t want to make devlogs for small stuff like this, but this is something I found really cool. So I was working on help messages for all the commands when I realized that mocha bucket list felt a bit slower than pretty much every other command. This is because we need to shell out to git 2 times per bucket, and I had 4 buckets added. While 8 git commands might not sound like a lot, it was enough to make mocha bucket list feel slow. So what I did is I parallelized the metadata fetching through an errgroup . Instead of fetching the metadata for each bucket in order, we fetch the metadata for all 4 buckets simultaneously. This led to a big performance uplift. About 3 times faster than the old version of mocha , and just over 12 times faster than scoop for this operation. See the video below.
As I mentioned in the previous devlog I added good help information to every bit of the CLI. It’s surprisingly difficult to write good help messages which explains everything to users in a few words I also changed the behaviour of the mocha cache clear command to not clear all cache by default. That’s now gated behind the --all flag in order to match scoop a bit more
We now create shortcuts! This means any GUI apps should show up properly in the start menu, just like they do when you install with scoop . All I really had to do was a bit of orchestration since I decided to vendor in an implementation from https://github.com/jxeng/shortcut Besides that I expanded the number of apps that are supported by implementing a bit of code that handle architecture specific bin fields, along with bin fields which store 2D arrays. I also cleared up some of the TODO items. I swapped the junction implementation to an implementation from https://github.com/nyaosorg/go-windows-junction since we were previously shelling out to CLI. That and I added a bit more zip bomb protection For the purposes of the video below I changed the location which shortcuts get put to my desktop. It’ll probably be configurable, and match scoop by putting shortcuts in the startup menu by default
This is going to be the equivalent of 2 devlogs since I thought I made one earlier for persists but I didn’t. New feature! We now handle persist items in order to store data between versions. These are files which are persisted between versions of an app. Lets take git as an example to explain why persist exists. Say you want to make sure your git config isn’t deleted every time you update. The issue with this is that the config file is saved in the version specfic directory. To resolve this we can keep the config in $MOCHA_DIR/persist and then symlink the config to where it needs to be, which is essentially what persist tells us to do. Since we handled persist items last time we can now implement mocha upgrade to update apps. The way scoop handles updates is by first removing anything that references the app, like shortcuts or shims . Then we just follow the install process from scratch. This leaves the old version available in case a user wants to revert versions due to a bug, while also updating to the latest available version. This can be seen in the video below, which shows me updating llama.cpp-hip-radeon .
So I’ve been doing a bit of refactoring, a bit of bug fixing and a bit of optimization. Essentially just polishing mocha before I work on the next feature. Here’s some of the stuff I did: created tests for ParseRefString to validate behavior cache manifest json between info calls since I/O is really slow bumped dependency versions refactored manifest/info.go Besides that I fixed the uninstall flow since it was really bugged after the latest changes. Essentially mocha would uninstall apps with incorrect info. It would also try to remove shims/shortcuts for apps which don’t have any active shims/shortcuts. I then added a bit of logging since the uninstall command didn’t give any user output for whatever reason (i forgot to earlier).
mocha now supports a user defined theme for output colors. In the process I ended up doing a lot of stuff related to the config. First thing I did was swap to fatih/color for colored output, since it handles stuff like colors in command prompt and removing color when output is piped. Then I refactored the config module. Earlier I would pass around a MochaConfiguration object through every function. Now I use a config singleton that’s accessible from any function. Why? Because it means I don’t need to pass the object every time I want to log information. Also means I don’t need to pass mochaDir through almost every function in the codebase. Getting user defined themes was a bit complicated because I needed a good way to handle a default theme so output doesn’t look bad if parsing fails. I handled this by only using the configured theme if every color resolves properly. Otherwise output falls back to the already loaded default theme. Due to this you still get colored output even if there are errors or warning before the configuration and theme is loaded.
I love refactoring!!!! I’ll probably end up spending another 20 hours just on refactoring because it’s so fun!!!! This time around I wanted to refactor the code so that our commands orchestrate stuff instead of the helper functions. For example, pkg.Install would first download a package, then install it, and then link it through shims and shortcuts all by itself. This causes issues because it means error messages become slightly worse, and it creates a class of bugs due to edge cases where we don’t necessarily want this order of orchestration. Hence I did a lot of refactoring in the pkg module. I also ended up adding a way to skip verification of downloads when downloading, installing or updating a package through --skip-verify . It’s a useful option in situations where there is a malformed manifest or simply no hash to begin with.
I’m writing this one right before F1 Qualifying at Spa! Continuing with the trend of some of my recent work, I improved what table outputs look like to be a little bit more readable. We now use proper separators in the form of Unicode Box Drawing Characters . I also made column alignment configurable, which improves legibility for some commands like mocha bucket list and mocha cache show . I’ve attached an image of the scoop and mocha versions of bucket list so you can compare for yourself.
Not sure why I didn’t do this earlier, but I’ve added success messages to commands where it makes sense. Also added a success color to the config so you can change what the success color is. I do still need to improve CLI output quite a bit, but it’s slowly getting there.
My summer break has ended so development is going to be a lot slower from now. I added mocha outdated so you can list outdated apps before upgrading them to a newer version. Besides that I tweaked a lot of stuff related to CLI output. For example I changed search to output one table, and simply outputting exact matches at the top of that table. I also changed a lot of messages which were using LogOutput to LogInfo so they use the correct color and output to stderr and not stdout .
Finally got a bit of time to do a bit of development. First thing I did was remove a field from install.json to match scoop . This means that mocha should be a drop in replacement for existing scoop installs. Then I added partial support for env_set and env_add_path . The main thing I need to do to complete the feature is parse variables and replace them with the appropriate paths. These 2 fields are some of the last manifest fields I need to support besides pre/post (un)install hooks.
Lot of time going into this devlog, but it makes sense since I did do a lot. I did this sweeping refactor of the entire commands module which moved around a lot of code. Essentially each command now gets it’s own directory under the commands module that represents it’s children/parents. For example commands/shim/remove/cmd.go contains code for the mocha shim remove command. Each cmd.go contains a Command struct that has the relevant fields and functions attached to it. This structure just makes things more organized and also means adding test files will be a bit easier since functionality is now isolated. I also sorted out the shim binary. So essentially https://github.com/ScoopInstaller/Shim offers different version of the shim binary which can be installed. Previously I hard coded the code to install cpp v0.1.0 but now users can run mocha shim binary releases to see the options and mocha shim binary setup to install their chosen binary. This also means we actually get the latest releases from GitHub.
Lots of small bug fixes and changes, I’ll just list them out: feat(cmd): allow removal of multiple shims in one execution (f2fae3f) fix(manifest): correctly ignore invalid shortcut entries (6a08478) fix(fileops): use correct registry type (5d5d796) fix(config): seed config with defaults (9dfaaff) fix(cmd): use correct release sources (a2a9ba1) fix(cmd): use bucket from install info (5a9109b) I also added support for more file types being shimmed, which helps a lot with compatibility. The file types are .py , .bat , .cmd , .jar and .ps1 .
I forgot to make a devlog in between so this will be like 2 bigger devlogs. I parallelized bucket updates, which speeds it up quite a bit. This also allowed me to try out parallelism even more, which I plan to apply throughout the CLI later on. I also added configuration options for the runners which mocha shim will use to run certain file types. For example, you can set the python-runner to select the python version that’ll be used to run python scripts that are shimmed. Downloads now have a progress bar, so you don’t need to wonder whether something is happening or not during a long download. Finally env_set is fully supported since I added the relevant variable parsing. This was pretty much just me cleaning out the TODO list before I ship. I also did a lot of smaller bug fixes and refactors as seen below. fix(commands): prevent app installation if already installed (cb27d07) fix(commands): fix config opening with “start” (74f3679) fix(commands): correctly handle non-apps when upgrading (f7419f6) fix: make LogOutput go to Stdout not Stderr (bc10357) fix: handle empty versions correctly (2287da9) fix(pkg): remove correct temp dir (33189b6) fix(shim): warn for unknown shim extension (622c2b4) fix: skip downloads with no hash by default (69d4e35) fix: use correct timeout for downloads (44e527b) fix: drop unnecessary return value from GetExecutableEntries (9fd845c) fix(config): remove unused option (1339971) fix(commands): don’t error for valid results (87c4d6c) refactor(config): rename variables/functions (f253d9d) fix: use unique temp directories (a159e23) refactor: use fmt.Fprintln directly (d2d54bf)
So I wrote a README, added a license (MIT of course) and setup CI/CD so that releases are automatically built and deployed. Honestly I forgot how hard it is to write a good README. You need to get a lot of information through without it looking like a wall of text.
Ships:
I made a package manager for Windows, which is somewhat backwards compatible with scoop packages. To be honest there’s still a lot of work that I want to do, but I have exams and college application coming up soon so I can’t. That’s not to say I’m not happy with the state of the ship. At the very least it has all the core features that a package manager should have, but there are still a lot of bugs which is why this is only v0.0.1. The biggest challenge by far was trying to figure out how Scoop does things internally. A lot of stuff just doesn’t have documentation, so you have to dig through the really messy PowerShell source code....
|
1793008139.1576834
|
1793094539.1576834
|
|
58854
|
pixeli by @Zephyr | Stardance
|
Zephyr
|
1
|
50.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-07T16:33:10Z", "hours": 50.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I added a GUI to pixeli! currently, it only supports grid merge, but it fully works and is up and running (runs on port 3000). Make beautiful image mosaics, now outside of your terminal! Make sure to check out the beta release for the latest version of everything, as this is a beta release and not available on the main branch :) it’s on the “pixeli-gui” branch. Hope yall enjoy this last project from me!", "repo": "https://github.com/pakdad-mousavi/pixeli/tree/pixeli-gui", "demo": "https://www.npmjs.com/package/pixeli/v/1.0.6-beta.3"}]...
|
[{"post_id": 77604, "ts": "202 [{"post_id": 77604, "ts": "2026-10-07T16:30:25Z", "hours": 5.0356, "text": "Final devlog… forever (turning 19 tomorrow, so this is the last devlog :D) I finally released the beta!!! We got the GUI running (only for grid merge so far) but it works! I added state management inside of local storage so changes dont keep disappearing, and I also added the export button functionality! Have fun!"}, {"post_id": 74358, "ts": "2026-09-27T07:21:57Z", "hours": 9.205, "text": "LADIES AND GENTLEMEN, GUESS WHAT TIME IT IS. (devlog time ) First of all, I added a summary and continue section in the sidebar on the right to provide a more “guided” user experience I guess you could say. :> Then, I also, changed the left sidebar to make things simpler; there will only be a single page for all merges now. :D And the rest? I’ve just been adding fields in the merge page for all the different settings the user can mess around with (there’s a LOT). Once I finish with that, I’ll be actually rendering the final product to the user so they can see what they get once they export!"}, {"post_id": 72996, "ts": "2026-09-24T05:54:31Z", "hours": 9.8092, "text": "DEVLOG! Okay SO. Image selection is now complete: users can choose which images they want to proceed with. I also added shift-clicking, so users can select multiple images more easily (see the video!). Next: Responsiveness ✨ I made the main sidebar responsive so far, so the layout of the page seems to be working fine, at least up until around the sm / md breakpoints. I’ll also have to handle making the secondary sidebar responsive in mobile screens. Finally: Light mode and dark mode! FINALLY, I added a button to toggle between the two, should be much easier to design either theme now :> Next step is to add a bar on the bottom of the screen which helps guide the user’s next step. Then we can start with the merge pages!"}, {"post_id": 71045, "ts": "2026-09-20T07:40:21Z", "hours": 9.9878, "text": "NEW DEVLOG! Alright ladies and gentlemen, I’ve made a layout for the images, where the user can choose either a compact layout or a normal (slot-like) layout. I’m using animejs for the smooth, snappy animations, in case anyone out there was curious :> Now, I need to allow the user to select which images they want, then, I’d also like to add some sort of utility bar on the top/bottom. Then, I’ll use those images to make the merge pages! wish me luck :>"}, {"post_id": 66402, "ts": "2026-09-12T06:48:35Z", "hours": 5.9064, "text": "OKAY. Some progress (and some setbacks :>) So I’ve worked on the uploaded design, as well as the backend that was meant to write the file to the /tmp directory. The problem I needed to solve was to figure out a way to store the files on the backend that didn’t involve writing duplicates to the user’s disk. This is a very difficult task, because I can’t get file paths from the input field in the frontend, only the filename and file content (and some other unrelated details). Solution? Implement a different system that DOESN’T involve file uploads :D If I just use the directory im in when the user runs the command to start the loopback GUI, I can define a “project scope” in a sense, where I only try to use images in that directory. This way, it’s up to the user to choose which folder they want to use as their project. :> So now I need to refactor BOTH my design and backend to support this HA. Awesome"}, {"post_id": 64620, "ts": "2026-09-09T04:51:06Z", "hours": 9.5767, "text": "Initial Devlog! Okay so: I’m back. :> I’ve started working on a project I’ve been meaning to do for a while, called “Pixeli”, a CLI for merging images together! I actually already made this project before, and now I’m adding a GUI to it. Currently, I’m working on the file upload and rendering mechanisms. :D Will also be doing dark mode :0"}]...
|
Title: pixeli by @Zephyr | Stardance
Devlogs:
Ini Title: pixeli by @Zephyr | Stardance
Devlogs:
Initial Devlog! Okay so: I’m back. :> I’ve started working on a project I’ve been meaning to do for a while, called “Pixeli”, a CLI for merging images together! I actually already made this project before, and now I’m adding a GUI to it. Currently, I’m working on the file upload and rendering mechanisms. :D Will also be doing dark mode :0
OKAY. Some progress (and some setbacks :>) So I’ve worked on the uploaded design, as well as the backend that was meant to write the file to the /tmp directory. The problem I needed to solve was to figure out a way to store the files on the backend that didn’t involve writing duplicates to the user’s disk. This is a very difficult task, because I can’t get file paths from the input field in the frontend, only the filename and file content (and some other unrelated details). Solution? Implement a different system that DOESN’T involve file uploads :D If I just use the directory im in when the user runs the command to start the loopback GUI, I can define a “project scope” in a sense, where I only try to use images in that directory. This way, it’s up to the user to choose which folder they want to use as their project. :> So now I need to refactor BOTH my design and backend to support this HA. Awesome
NEW DEVLOG! Alright ladies and gentlemen, I’ve made a layout for the images, where the user can choose either a compact layout or a normal (slot-like) layout. I’m using animejs for the smooth, snappy animations, in case anyone out there was curious :> Now, I need to allow the user to select which images they want, then, I’d also like to add some sort of utility bar on the top/bottom. Then, I’ll use those images to make the merge pages! wish me luck :>
DEVLOG! Okay SO. Image selection is now complete: users can choose which images they want to proceed with. I also added shift-clicking, so users can select multiple images more easily (see the video!). Next: Responsiveness ✨ I made the main sidebar responsive so far, so the layout of the page seems to be working fine, at least up until around the sm / md breakpoints. I’ll also have to handle making the secondary sidebar responsive in mobile screens. Finally: Light mode and dark mode! FINALLY, I added a button to toggle between the two, should be much easier to design either theme now :> Next step is to add a bar on the bottom of the screen which helps guide the user’s next step. Then we can start with the merge pages!
LADIES AND GENTLEMEN, GUESS WHAT TIME IT IS. (devlog time ) First of all, I added a summary and continue section in the sidebar on the right to provide a more “guided” user experience I guess you could say. :> Then, I also, changed the left sidebar to make things simpler; there will only be a single page for all merges now. :D And the rest? I’ve just been adding fields in the merge page for all the different settings the user can mess around with (there’s a LOT). Once I finish with that, I’ll be actually rendering the final product to the user so they can see what they get once they export!
Final devlog… forever (turning 19 tomorrow, so this is the last devlog :D) I finally released the beta!!! We got the GUI running (only for grid merge so far) but it works! I added state management inside of local storage so changes dont keep disappearing, and I also added the export button functionality! Have fun!
Ships:
I added a GUI to pixeli! currently, it only supports grid merge, but it fully works and is up and running (runs on port 3000). Make beautiful image mosaics, now outside of your terminal! Make sure to check out the beta release for the latest version of everything, as this is a beta release and not available on the main branch :) it’s on the “pixeli-gui” branch. Hope yall enjoy this last project from me!...
|
1793008142.0020316
|
1793094542.0020316
|
|
40695
|
Agamemnon Armor From The Odyssey by @nejenabinupa Agamemnon Armor From The Odyssey by @nejenabinupa | Stardance...
|
nejenabinupa
|
1
|
46.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-05T22:14:49Z", "hours": 46.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "my Agamemnon Armor From The Odyssey that i make in 3d, all of the details are in the readme", "repo": "https://github.com/binupax6699/AGEMENMNON-ARMOR-3D-MODLE", "demo": "https://sketchfab.com/3d-models/agemenmnon-armor-3d-modle-ddb5b8fa0023412498e85a3ae109d622"}]...
|
[{"post_id": 75331, "ts": "202 [{"post_id": 75331, "ts": "2026-09-29T19:24:31Z", "hours": 3.1283, "text": "Finsh up the stuff and it’s good to go"}, {"post_id": 43114, "ts": "2026-08-08T06:24:45Z", "hours": 1.4717, "text": "Remake the textures with depth and more realistic colors,next will be baking the textures"}, {"post_id": 41351, "ts": "2026-08-05T14:41:59Z", "hours": 4.1028, "text": "I added a Sword to the armor set and make sum tweaks to the rig and now it’s good for animation"}, {"post_id": 38695, "ts": "2026-08-01T06:46:28Z", "hours": 10.6783, "text": "It took around 15h my addon got deactivated for no reason and that 5h got lost 😞, but i completed the armor and the rigging part fully need to add sum normal maps to give it sum small details for everything."}, {"post_id": 37106, "ts": "2026-07-29T16:12:54Z", "hours": 10.58, "text": "After long long time make thing much progress on making the body, now just need to clone up sum polygons Make the face from sculpting because of that there’s around 400k + faces and vertices but make the body light and have only 8.5 K faces and vertices"}, {"post_id": 36401, "ts": "2026-07-28T14:18:30Z", "hours": 9.4525, "text": "Agamemnon Helmet Cleaned up the helmet topology and cheek guards, Added the vertebrae spine, I optimization hair without a particle hair but with a custom alpha png images to make it fast And I Applied the final satin black metal, gold filigree trim. Now moving to the body and armor"}, {"post_id": 35922, "ts": "2026-07-27T17:52:20Z", "hours": 6.6144, "text": "Agamemnon Helmet Complete Base Mesh modeling for the Agamemnon helmet. "}]...
|
Title: Agamemnon Armor From The Odyssey by @nejena Title: Agamemnon Armor From The Odyssey by @nejenabinupa | Stardance
Devlogs:
Agamemnon Helmet Complete Base Mesh modeling for the Agamemnon helmet.
Agamemnon Helmet Cleaned up the helmet topology and cheek guards, Added the vertebrae spine, I optimization hair without a particle hair but with a custom alpha png images to make it fast And I Applied the final satin black metal, gold filigree trim. Now moving to the body and armor
After long long time make thing much progress on making the body, now just need to clone up sum polygons Make the face from sculpting because of that there’s around 400k + faces and vertices but make the body light and have only 8.5 K faces and vertices
It took around 15h my addon got deactivated for no reason and that 5h got lost 😞, but i completed the armor and the rigging part fully need to add sum normal maps to give it sum small details for everything.
I added a Sword to the armor set and make sum tweaks to the rig and now it’s good for animation
Remake the textures with depth and more realistic colors,next will be baking the textures
Finsh up the stuff and it’s good to go
Ships:
my Agamemnon Armor From The Odyssey that i make in 3d, all of the details are in the readme...
|
1793008143.1659122
|
1793094543.1659122
|
|
21103
|
Ritualia by @gabriel_ferreira | Stardance
|
gabriel_ferreira
|
1
|
148.7
|
2310
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-23T23:45:29Z", "hours": 148.0, "multiplier": 18.45, "payout": 2310, "blessing": "neutral", "text": "What did i made I made an complete music play system that will help users to learn while listening to musics! I used youtube, flask, python, mysql, js and hope to make this! What else Solved a lot of painful bugs that were stopping the project from working Finished and made the music queue work Added music description labels Improved a lot the performance Made the website responsive Added a keyboard based navigation Fixed so much errors at the cover-flow that now i forgot how many Added bug checks before the play of each video on the player Created an toast component to show errors or infos Added 54 musics to choose and listen Challenges The most painful code was the player and the cover-flow, they were with a lot of hidden bugs that i had to figure out, feats that i had to make and pain to suffer! Now i figured out that i love and HATE making a website responsive! What im proud of MutationObserver: An observer that loads / hides an image based on its position at the cover-flow, this system took a while and worked very well. Error checks at player: The system can handle the error that happen and dont crash! Keyboard navigation: Everyone can use the keyboard to navigate now! Oracle VM: For the first time i used an ssh and hosted an website in my own machine (oracle, not mine)! How to test Access http://ritualia.duckdns.org/ , when you join and the page loads you will find a screen to choose an genre, select which one you want, after you will see an emotion selector, select the emotion that you wanna feel! You will see the player screen and an audio explaining the music (The audio is in portuguese), after the audio the music will play. Notice: The github and the website are in portuguese, please use your browser built-in translator or any that you want to use the software properly! Follow the installation guides at github if you want to install", "repo": "https://github.com/GF-Silva/Ritualia", "demo": "https://ritualia.hackclub.app"}]...
|
[{"post_id": 73067, "ts": "202 [{"post_id": 73067, "ts": "2026-09-24T09:47:16Z", "hours": 0.6983, "text": "Added english readme I created an english readme, api and install Guide, so it will be easier to read and more accessible for worl-wide users"}, {"post_id": 72881, "ts": "2026-09-23T22:36:56Z", "hours": 0.3906, "text": "It is time to ship! Now the system is working perfectly fine running at a vm in oracle cloud with a public domain, and a dns with duckdns at http://ritualia.duckdns.org/ Warning: It is just HTTP!"}, {"post_id": 72810, "ts": "2026-09-23T19:36:13Z", "hours": 1.3461, "text": "Configuring an ssh server! I configured an oracle cloud vm with ubuntu to host my website 24/7, that was because nest wasnt working in a while. Im running it at a local IP with http only, i will configure https today and maybe an domain, the IP is http://164.152.55.252 , notice that some browsers may block you from accessing and http website. UPDATE AFTER THE DEVLOG: I put an domain using duck dns: http://ritualia.duckdns.org Hardwork I had absolutely not a single knowledge about oracle cloud vm, so configuring it was an hell. Sometime my internet stopped working so i had to use my smartphone, this lead me to configuring an invalid ssh key and i had do configure everything from scratch, i spent 5 hours configuring everything, but that was ssh and wasnt tracked. But now everything is working fine. Thx oracle This vm is a 24/7 entire OS (Virtual Machine) that has some good free plans, without any cold start. Thx stardance Stardance now will have one more mount!!!!!! I still has roughly 40 hours of deep development to do after this ship, i will love to finish that in stardance!"}, {"post_id": 70936, "ts": "2026-09-20T02:22:48Z", "hours": 2.9706, "text": "Added install guides Now there is guides to help the user install for ubuntu, arch and windows. Notice that im a linux user and my pc is weak, so i could not test it on another operational system. Also the guide is in portuguese (all of them), please use your browser built-in translator or any of them to read if u dont understands portuguese I could test it on another linux distro, but i would have to go through all the install steps. Also i cannot try installing windows because it normally wipe out another OS installed on the same disc (i know that it just replaces the bootloader) and using a VM was not possible due to the amount of RAM and the processor that i have."}, {"post_id": 69913, "ts": "2026-09-18T01:53:38Z", "hours": 0.3256, "text": "All done, it is time to ship Every metric at lighthouse it nearly perfect, im so exited to ship it!"}, {"post_id": 69904, "ts": "2026-09-18T01:19:42Z", "hours": 4.9561, "text": "The accessibility workings is done Features Now the system has a new navigation system that allow users to navigate with just the keyboard! (The video was with just the keyboard) Why Why not? It was meant to improve the accessibility for users without mouse, or any another problem and because i was tired of having to use the mouse to debug something. How it was made Again with a lot of pain, the feature itself was easy but i had to fix some errors that went unnoticed, so it took more time. The feature detects when the user press a key and do an action based on wich key was. The accessibility was easy to get 100, but the metrics at lighthouse dont give all what the users will need, i had to think about the website usage and how would be the easiest way for the user. Results The accessibility went from nearly 69 to 100! What next Now i will work on the best practices! Update after the devlog: Nearly every metric is already maxed out lol, i will ship it very soon!"}, {"post_id": 69444, "ts": "2026-09-17T02:13:13Z", "hours": 1.6906, "text": "The performance workings is finished and bug fix Fixes Now the logo z-index is lower, that is because the logo was ‘eating’ the click in more important elements. Also i did a small change at the cover-flow, that change fix the bug of the scroll at the element sudently stoping when at a certain position. The copa script had some old references to images that were leading to bugs, i changed it. Performance I already finished it in the past devlog, i was just checking if there was anything worth improving, but everything is working fine and now is time to improve acessibility. Most of the logged time was me trying to improve more some metrics at the lighthouse, but the work was too much for anything that is already good, so i decided to stop before i started focusing too much in it."}, {"post_id": 69395, "ts": "2026-09-16T23:43:00Z", "hours": 1.505, "text": "Fixing an error at the youtubeHelper Now the youtubeHelpers checks if the youtube API is ready before sending commands. Why Sometimes the API maybe is not finished yet, that was leaving an untreated error that was braking the entire website. How was made With a lot of pain and suffer. I thought “Oh hey, that will be a 15 minutes fix” - i spent 1 HOUR FIGHTING with the iframe itself, nothing was working and at some point i started thinking that even the API of YOUTUBE wasnt working, even the most basic function that should be triggered when the youtube finished the loading wasnt beeing activated, even the console.log(“Api READY!”) wasnt working, even when it worked it wasnt working well, the variable of the player was a promise and not the result. At the end i shut down my PC, defeated, without any energy left, with just hope that in the next day (this) that would be fixed (if not i was planning to ignore and make it a feature “Easter egg, if u dont join the website for a while it will not load!”. The problem here was just the position were the iframe api was in the HTML, it was being loaded before the helper script, so the helper was not there to check if it the iframe was ready or not, the fix was just move it a little down. Architecture It was just an promise, if the function checks that the iframe isnt available it await for it to be available. The check if it was available use the onYoutubeIframeAPIReady, easy easy (except for all the suffer that i went into)."}, {"post_id": 68896, "ts": "2026-09-15T23:59:43Z", "hours": 1.1389, "text": "The loading is done and working! Fix I fixed the error that were happening when the cover had a certain amount of elements. Problems The fix itself was very easy to do, but doing it in a readable or without using 10 lines of code (i want things concise) was way harder than i expected. So i spent this entire time trying different ways to do it, each of them making everything worse. Reasoning The bug were with less than 14 elements, the script were calculating the first and last element index, it happened that these elements were behind the screen focus. Why? Because the values that the system was using were leaving these values, so i had to fix the way it was calculating things."}, {"post_id": 68865, "ts": "2026-09-15T22:15:27Z", "hours": 1.3303, "text": "The loading is done Features Now the loading at the mutationObserver is finished, it finally loads or unloads the images that should be (or not) loaded! The new observer is way faster, because it can detect the image way before it enters the screen, loading it before and having more time to do it. Also the system loads just a maximum of images (with the configs that i put it is 13), so it will not fry an cellphone. Problems The loading part was easy to do, i already done it before in the past observer (intersectionObserver), so i just had to pass the old code to the new part. But when the cover-flow element dont got atleast 13 elements the mutationObserver code breaks completely! Im still pondering how to solve it, when i do i will post about! Results The performance went from 78 to 100! The system is way faster! The user does not see a blank image anymore! Why The old method was slow even with a good internet connection, because it was loading the images just when the element was already in the screen, leaving to a perceptive delay for the user and a blank image to the user. Also i thought about creating an observer from scratch (maybe i was a little off my ideas, because that was insane), but the browser already had exactly what i wanted (the mutationObserver) Videos The new features The performance of the new feats The old features Reasoning While i was trying to sleep i thought about a system that fill the cover-flow with a maximum of images (like 10, or 13, or the code decides) at the DOM, using less memory to run. That system will free a lot of memory based on how many cards the cover-flow have. But that will have noticeable effects just with a lot of elements and probably would be hard to develop, maybe i will do in next updates. What next Im leading to the shipping, so i will improve metrics about the lighthouse, improve the readme and post it."}, {"post_id": 68449, "ts": "2026-09-15T04:25:35Z", "hours": 7.2278, "text": "Adding a mutationObserver Now, instead of an intersectionObserver, the system use a mutationObserver that monitors the angle of the cylinder itself. With that the loading of the images will be insanely better, faster and user-friendly. Now the changes in the cover-flow is observed at the cylinder angle, not at each card. There was some problems in the journey like, for some reason, unexpected cards being loaded or not, the loading script at the observer dont triggering at all (that was caused by the speed of the observer) and an insane amount of cards being triggered at the same time (i still did not figured out why, but that isnt ‘harmful’). But man, i had to be creative here and remember about some concepts like concurrent programming, buffer / queue and apply some delays (because the mutationObserver is insanely fast and can trigger every millisecond). That all was meant to decrease the speed of the mutationObserver, because it was triggering with the most small change in the cylinder, so i made it trigger just when an expected amount of movement was made. The red/yellow collor is for me to visualize the loading state, it is just for debug The code isnt finished, i still need to implement the loading part, for now i just implemented the observer and basics of the loading part"}, {"post_id": 67841, "ts": "2026-09-14T03:19:48Z", "hours": 4.2825, "text": "The observer is finished (nearly) Now the cover-flow has an observer that checks the position of the images and changes it styles based on that, so the images that the user is seeing is loaded while the others is hide. It still has some bugs and space for improvements that im still figuring out how to solve, like the image loading too late on the screen or, in slow internet connections, the image takes too long to load. Most of these bugs are because the observer (an intersectionObserver ) was designed for 2d contexts, not 3d (that were and still is an giant problem to solve). For this reason i was thinking about creating an observer from scratch in C++ that can work better in my 3d element, but the overhead would be high so im trying to solve in other ways before that. The feature was made using fetchPriority, contentVisibility and src (the system add the source just when the image is near the screen). OBS: I found about MutationObserver after this post, maybe i will use that instead of insersectionObserver. Oh man, at least if had found about this before… Aaaaaahhhhh i spent 9 hours in that, but at least a Lot of the new logic will be used. Anyway, lets cook"}, {"post_id": 67151, "ts": "2026-09-13T06:53:12Z", "hours": 5.4219, "text": "Adding an observer Now the script observe the card elements at the cover-flow component, classify their position and changes it visibility based on that. Im using an IntersectionObserver to observe every card, but it was designed to observe the position of 2d elements, so i had to figure out how to make it work well in an 3d element. The way it works is when the observe activates (it basically means that some card is in the range to load) it get the card info (like position and angle) and changes it visibility state based on that. Simple, right? No, it was a headache for the start to the top, nearly 4 hours of what i did was to fix the fact that it was meant for 2d. The observer were activating for cards that were in the back of the element, so i had to classify the card position into back or front by using its angle. But if i tried to use the card angle without anything else the script would broke (and did for 3 hours until i realized how to fix), so i had to use an second angle which is 360 - cardAngle (the 360 is the angle of an circle), so this new angle is based on the circle end while the other is based on the circle start. But the system still broke, because at some point one of these values would become negative and makes the if that classify the elements fail. The fix was using the absolute value in the if (it took 1 hour until i figured that; oh i were so happy when it worked). Why To improve the performance, so the browser will just load what is really important and not 50 images that the user cant even see. What else All that work definitely improved a lot my logic thinking and for the first time i used the truth table well. Now i just need to use the new code to change more the style of the images that are not in the screen. I did not deleted the code that i wrote in the past devlog, it was used in the new code to select how many images should be loaded in the same time. ** The first video is the result, the others is some problems that i had **"}, {"post_id": 66316, "ts": "2026-09-12T02:31:12Z", "hours": 4.5481, "text": "Improving the loading performance Now the system selects some images that needs to be shown faster than the others and making them load with priority. It was made by selecting the images that the user is seeing and defining some params like fetchPriority = \"high\" and decoding=\"sync\" , the other images have the params: decoding=\"async\"; loading=\"lazy\"; contentVisibility=\"auto\"; . With that config the LCP went from 2.4s to 0.5s . Also it loads the image in the start and dont change that config again, so the browser will be lazy while downloading these images. The problem is: only the first images are chosen as high priority, but their positions will be changed while the configs stays the same, that makes the browser lazy while loading them and makes the runtime performance became worse. To fix that i found about IntersectionObserver, that are meant to solve the problem of updating the images position fast. It was not applied yet, i found about it like 1 hour ago. What else Now the perspective of the emotionDrum is based on the elements that it have, before it was based just in the screen and would broke if something changes. I did a little change in the way that the script checks for clicks in the screen, now it has more accuracy (I changed the round system)."}, {"post_id": 64533, "ts": "2026-09-09T00:41:52Z", "hours": 7.6869, "text": "Improving the LCP (Largest content paint) performance I am improving the way that the website create and downloads the images, the main reason is to make the user see something faster. Before the system were doing 2 main things: Go trough the entire list of images, creating the elements and placing them into the page. Position them. But the position of the items were being done after the creation of the images, in another function. Now they are in the same function: it create the element, position it and add it to the page. That does not seem like much, but the code got way faster with that, probably because it dont need to go item by item in an list twice just to create an element. I tested the time to load the first element and it went from 8.63s to 6.43s , the test was made with 2200 elements (Yeah ik, it is a lot and normally it isnt that much, but i had to see how they were holding with more than 22 items). Also i fixed a bug that passed unnoticed while improving the responsiveness: At some point of images the visibility of the elements broke, that was because the perspective (what makes the 3D perspective of the component, and makes it visible with 3D effects) was based on the screen size, not the elements itself. What was the problem in that: Each element takes a size in the screen ‘makes the circle that shows the element be more and more near of our point of view’ (i cant explain it any better, search what is ‘perspective in an 3d element at HTML’ ). While it was approaching our point of view (POV), our POV were exactly at the same position (based on the screen size), so at some point the circle perspective would pass the POV and we would be unable of seeing it well. Now it is based on the elements: The 3d elements were basically a circle, i just used the diameter to change the perspective based on it. TODO: Maybe i lowered the image quality too much… I will fix it in the next updates. Also i were trying to improve the font settings to improve the performance, but that wast working so i decided to move on to this because it was more critical (took a while for me to jump to this, maybe like 2 hours trying and trying values in the font settings). i am also working in a way to load the images in parallel, with that it will take way less time (I didnt known about LCP before so i spent a while figuring out the way it works)."}, {"post_id": 63656, "ts": "2026-09-07T16:11:33Z", "hours": 2.6633, "text": "Improving the performance After finishing the improvements in the responsiveness, now i decided to improve the performance. I used lighthouse to get insights (i learned about it in an tiktok video) and figured out that the images size were too high (were an png of 1280x1280px), so i saw more about that in the page: https://developer.chrome.com/docs/performance/insights/image-delivery (an link that google lighthouse gave). With that i saw how to decrease the size while staying with quality, i reached up to the sharp-cli tool, that makes the work of resize, convert and compress the image for me. The command used was that: npx sharp-cli -i * .png -o ./output resize 320 -f avif -q 50 --effort 6 --smartDeblock --preset photo The 320 is the size that i want it to be at the end, i got that value by seeing what was the computed value (the value that is being used in the website) in an high resolution pc (not the most higher one, the high but normal pc) with the resolution of 2500x1714px . With this simple changing the image went from 2mb to 40Kb! Nearly 100% decrease, and take in mind that there is more than one img, so the change were even higher. Also i created 5 different images: 320px, 480px, 640px, 960px e 1280px. With them the browser can choose which one is better for each device. With these changes i went from 35 points of performance to 59."}, {"post_id": 63459, "ts": "2026-09-07T10:10:31Z", "hours": 0.8717, "text": "The home is now fully responsive Ah that took a while, but finally it is fully responsive. Now the description at the player UI resizes based on the screen size and active a scroll behaviour when need, also i did some minor change at the emotionDrum perspective to make it show more emotions at the same time, removed the padding in the arrows at the emotionDrum so they will have more space and fixed an error in the genre drum that was making it perspective broke. After all these devlogs i improved how i make a code responsive."}, {"post_id": 63436, "ts": "2026-09-07T08:55:04Z", "hours": 2.5378, "text": "The emotionDrum is now responsive! Now the buttons that you use to select the emotion are in the same side as the div that displays the emotion, so they dont fight for space anymore. This change is meant to fix the low size of the items in screens that are too small, in the new way we have more free space to display the emotions, there is not much to say. What else I did some minor changes in the size of some items at the player area, now they are easier to read! (I increased the size of some items)"}, {"post_id": 63379, "ts": "2026-09-07T05:17:01Z", "hours": 6.6125, "text": "Im nearly finishing the workings on the responsiveness. Now the entire player screen is responsive and do not breaks the texts anymore (except for the description area), also the buttons that show you the next screen (the ones that displays ‘player’ and ‘generos’) are responsive too, the music queue is working perfectly fine, and the area that is used to select an emotion is nearly responsive too, it just needs some adjusts in the two buttons that change the current emotion because they become too small and uses a lot of space when the screen is too small, after that this screen will be finished. It is taking a really long time, the fact of how many different screen sizes exists makes it harder to finish, but now there is times that i even cannot see if i changed the resolution in some areas, because the system looks the same. I spent quite a while testing different resolutions and combinations of size, i didnt even noticed that i where 6 hours here, but now ik more about css (things like container-type + container based sizes and more ways to set the size of an text) The video shows how it is now, if u want to see the before just checks the past devlog."}, {"post_id": 62723, "ts": "2026-09-06T06:59:19Z", "hours": 0.7094, "text": "Finished the correction of the errors at the perspective and click in the cover-flow component. Now the perspective stays the same 150vw value (that is based on the screen width) and stays normal, with everything working. Oh man, that needed a lot of logic and out of box thinking finding another ways to check where the user clicked without using an normal click event listener (for those who lost the past devlog or didnt understood, i cannot use a normal eventListener in that because the clicks is detected in another element or in nothing, even with z-index or more in css, so the solution should be done entirely on javascript logic). The first video is the new way, the second is how it was before all changes in it"}, {"post_id": 62679, "ts": "2026-09-06T05:10:34Z", "hours": 5.5194, "text": "i finished the workings on the section of the home page that i where doing before, now has a good responsiveness for pc and a decent one for mobile. Now im working on the main area of the home page, the one where the user selects the desired genre for the music (second img). It may looks completely fine, but that same element already was a headache before and is here again. The given area is the cover-flow component, before i already fixed it (or so i thought), but it was looking bad (the 3d perspective where a bit strange) and would probably broken if i added new genres. I were trying to figure out a way to listen to the clicks in the card without any problems, that seems easy at first glance, but the 3d perspective in the element make other elements eat the click from one another, make the clicks dont be listened and so many problems that i nearly decided to erase it and write from scratch. I already found a way to do it by using the mouse position, the center of the screen and the card width (the genre img) to transform it in an value that can be used to select the exact card without any dependencies on the doom selector. It basically uses just some values, put in some calcs and get the difference between the current card (genre) index and the clicked. Im nearly finishing it, but i still need to figure out some values and more."}, {"post_id": 61879, "ts": "2026-09-05T01:17:53Z", "hours": 1.1772, "text": "Im improving the responsiveness at the home page (before was the player page), but for some reason that idk the emotion selection div is having a strange behavior, i will update what it is after i fix it. Take a look: (the item in the center should be centered)"}, {"post_id": 61218, "ts": "2026-09-04T01:30:11Z", "hours": 0.725, "text": "Hi again! Like said in the past devlog, im improving the responsiveness of the website, specifically in the player part. But it had some problems and where distorting when playing an video, now it resizes based on the screen size in a way that it stays ¨normal¨. The first video is the new way, the second is the old way. It still needs a lot of improvements, but it is going!"}, {"post_id": 60619, "ts": "2026-09-03T02:22:12Z", "hours": 1.4631, "text": "Making the website responsive Hi again! Like i said in some devlog, the website dont have support for mobile, that was because it was designed to be at kiosk mode and work just in desktops. but i decided to change that. First of all: the site where using a lot of absolute values of dimensions, so it where braking even in the desktops (it wasnt responsive at all). But i spent a while changing it, it is isnt ready and has some problems, but is better than before. (The mobile is still strange, i did not started fixing it yet). Credits: https://css-tricks.com/snippets/css/fluid-typography/ - This website shows about a way to make the texts become responsive for the screen using some calcs, it is worth seeing. The first video is how it was before, the second is how it is now"}, {"post_id": 60559, "ts": "2026-09-02T23:48:07Z", "hours": 0.7944, "text": "Creating a new helper Context: There was an class called youtubeFrameControls , this class basically where designed as an structure to help using the youtube iframe API, but with the time this class where becoming basically to hold just an function (and in a very inefficient way), because the methods that it had before (like the one that runs when the iframe is loaded) had to have more and more specific logic in the codes that used it, so they where useless (because the codes that where using it where rewriting it). What i did: I picked the only function that where being used and transformed it in an helpers (that can easily be customized). This function was the one that creates the player of the musics, and the function where called createPlayer . Also i removed the old class (youtubeFrameControls) and replaced it for this helper in every place that used it. It now is way more simple than before and can me more customized."}, {"post_id": 60001, "ts": "2026-09-02T02:58:53Z", "hours": 2.1603, "text": "Refactoring the copa script I where placing some scripts in a class. These scripts are related with the player functions of the copa script, so i pick all of them and placed in the same class. I did it to follow best practices, but i confess that i still got some doubts about when to create an class and when the variable or method should be static or private (#property), i will search and learn more about because maybe i will have to refactor some parts of the code following these rules of best practices. That was all for now, see ya!"}, {"post_id": 59339, "ts": "2026-09-01T02:28:57Z", "hours": 2.4744, "text": "Adding more bug checks I added some checks in the player class at the startExplication function that checks if the src (the url for the audio) is valid or not by doing an fetch with the HEAD method and checking if the return is an valid audio before trying anything in this function. Also i solved this error in the same function: Uncaught (in promise) AbortError: The play() request was interrupted because the media was removed from the document. https://goo.gl/LdLk22 This error was because the startExplication function where trying to play the audio before it was loaded, i solved it by making it play the audio just after it was load with the event listener canplaythrough . There was another error at the playMusic function where the code where trying to play the youtube video before it was loaded, i solved it by making it wait until it was CUED (Where the video isnt playing, but is loaded and showed). (The website was not created to be in mobile and dont has a lot of support, the video where recorded in my smartphone because i had to record the audio and the audio on my pc dont work. In the Future i Will add mobile suport, but right now im finishing the bugs and etc)"}, {"post_id": 58653, "ts": "2026-08-31T04:27:35Z", "hours": 2.7947, "text": "Adding a new description feature So basically there was an place where was designed to have the description about an music, but that was empty and where only finished today What it do It is petty simple, it just show an text about the music that is currently playing, also there is an audio that plays before the music starts playing, but this audios is played just one time before the music so if someone loses it or didnt listen well there was not a second chance to listen for that audio. Now there is this place that holds the same content, but in the format of an text that can be read whenever they want while the music is being played, that was what i added. Also that text can be hidden, so it will not stay using half of the screen every time (in the screenshot it is active) What this audios do This audio / text is part of the main purpose of the website, they give some fun facts about the music that may be useful someday in some kind of quiz or essay. Also the audio is played before the music and the music plays just after the audio finishes. That is to make whoever is listening listen to the entire audio before having what he (or she) wants, so they will not listen to the music and skip the audio."}, {"post_id": 58526, "ts": "2026-08-30T23:20:27Z", "hours": 1.3911, "text": "Studing about cache So basically i where studing about cache, the main ideia was to implement it in the sistem, but then i realized something: Theres is nearly no difference between cache and a normal request in an localhost project, adding the cache would not improve anything, sometimes it maybe even slow the website, because the page would need load more code. I realized it afther a while studing about it, but anyway lets focus on another thing. Also i where studing with google for devs: https://developer.chrome.com/docs/workbox/caching-strategies-overview"}, {"post_id": 56374, "ts": "2026-08-28T03:45:15Z", "hours": 1.0169, "text": "Toast applied and tested The toast notification component is now being used at the player class, i did some tests and it is working very nice, hopefully the user will not see it very often (because that would be a problem, the user must not see it unless there is an error playing the music). But why did i make it? It is used to show more about what is going on for the user, so they will not become anxious if it something is working or not. Why not use another notification system? Each notification system has its own use cases, the others would be very painful for the user. Imagine every time a simple error (that is simple for me) like the music fail to play there was an error that interrupt the use of the app with an popup or alert, that would be painful, dont it? That is why i used an toast notification, because it is temporary (disappears after some seconds) and dont stop the use of the website. Also there is a feature that i implemented for the same reason a few devlogs ago that add a fallback in the music search, so it wont show a message at every single combination. Lets calculate how many combinations we have: there is around 50 musics in the database, 22 genres and around 40 emotions, multiplying the genres and the music 880 combinations that the user can make. Now lets see how many musics we can get: each music have around 1.2 emotions and 1.2 genres, so we get 72 combinations that lead to an music . With that in mind, we can see that from 880 combinations, just 72 of them are useful combinations, so we get a 8.18% for getting a music, and 91,12% of not getting one. Consider that each failed attempt shows an error that stop the use flow of the website, but that was before the past devlog, now it tries again and again and only afther failing everything it shows an error, at that point it must really show an error. Thats all, sorry for the long boring text and thanks everyone that read, see yall later"}, {"post_id": 56331, "ts": "2026-08-28T01:58:42Z", "hours": 3.1336, "text": "The toast notification is finished So i finished it, it is a component that u adds in the code that u wants to use. I added 2 icons, 1 for infos and another for warnings. What i used and did The element that holds it all is an dialog , the icons are svg , the text is a span and the element that shows the time left is an progress . To update the time left i used an setInterval that runs at a 10ms delay and deduce 0.01 of the dialog value, so it will be smooth to see. Also there is an if inside that destroy the element and clear the interval when the value of the dialog reaches zero or less (In the past devlog i said about not using an if, but considering how low the cost for an if in that time is i decided to use it anyway). The function that creates the toast receives some params that will let it be customized by whoever is calling it: const icons = Object . freeze ({ INFO : infoIcon (), WARNING : warningIcon () }); function createToast ({ message , time = 5 , styles , icon = icons . INFO }) // the `message` is the displayed message // the `time` is the time until close // the `styles` is custom css styles for the element, it uses the dictionary format {} // the `icon` is the svg icon What else? I will apply it in some elements and post about. See you later!"}, {"post_id": 56188, "ts": "2026-08-27T20:27:52Z", "hours": 1.5956, "text": "Creating a toast notification system So rn im creating what i said in the past devlog about a toast navigation. This isnt finished yet, im still figuring out an way to check the end of the timer, i found some ways to do it, like using an simple if inside the countdown. I didnt comment but i am using an setInterval to decrease the time and an <progress> tag to show the value but that is a bad ideia, imagine doing 1 if every 50 ms? that dont cost a lot of processing power, but i still will search for other ways to do it just to check, if yall got any hints or ideas leave a comment. Also i will improve the design, the design is petty poor."}, {"post_id": 55334, "ts": "2026-08-27T02:23:29Z", "hours": 4.2383, "text": "Fixing errors and adding bug checks Hi everyone, so i were fixing some bugs that i saw that may broke the app, i fixed all of them (for now), here they are: There was a logic bug that a class (the one that controls the youtube iframe) where doing stuff that it wasnt supposed to do (not an unexpected behavior, but a logic that should be outside of it), it was an easy fix. There was a bug at the player class that when the provided sourceId (for the youtube iframe) where wrong or unable to use it crash and stopped doing anything else (like playing another musics). I tryied solving it in various ways, one was beffore the changes that i did in my last devlog, but i failed because the class that holds the player where hard to fix, this devlog fix it. I fixed it by adding some bug checks and, when some error ocurred, it play the next music. There was also a bug at the player class and youtube-iframe-controls class, that for a couple seconds in the start of the website it would broke if u tried to play a music. It was because in the start of the program the youtube API where unable to be used. To fix it i just made it wait until the API where ready using an ASYNC function. There was also a bug that, afther the past devlog, it was doing and request at the /api/songs with params at the wrong format. Afther the past devlog the API started using the params genre_id and emotion_id , but the frontend where passing with the incorrect name (genre, emotion). Something that i implemented I upgraded the mysql query that where being used to get more infos about the music, before it where just returning infos like name, author, sourceId, etc, but now it also returns the genre and emotion from that given music. I added a bug check at the player class, now if it fails it pass to the next music. Something that i want implement I want to implement a simple toast notification system that will apear when something fails, like the playing of some music. Others The youtube docs for the iframe where very helpful for this changes, check it out: https://developers.google.com/youtube/iframe_api_reference?hl=pt-br"}, {"post_id": 54690, "ts": "2026-08-25T19:06:05Z", "hours": 3.2633, "text": "Optimizating some piece of code So there was a certain part of the code responsible for the songs queue in the main route, that piece is a core function but where running a while true loop for no reason , here is the part: async start () { while ( true ) { // { emotion, genre, author, name, sourceId } const musicData = await this . #musicQueue . get (); this . createPlayer ( musicData [ ' sourceId ' ], null ); this . #showMusicInfos ( musicData [ ' name ' ], musicData [ ' author ' ]); this . #queueList . removeChild ( this . #queueList . children [ 0 ]); await this . #startExplication ( `/storage/ ${ musicData [ ' explicationSource ' ]} ` ); this . player . playVideo (); await this . #musicFinished . when ( true ); this . #musicFinished . set ( false ); } } Basically the code were calling it at the start and running it forever, but that code where a nightmare to maintain / implement, i tried to implement a safe check here for over 2 hours, but wasnt possible. I replaced it for a more efficient approach that do a loop in a different way, here it is: when adding a music, it checks if it is already playing, if no starts to play. when start to play it checks if there is a music in the queue for it to play, if no it stops playing, if yes it get it and play. When the music that is playing ends, it call the play function (from the above topic). That is just it, no while or constant loops, no overhead, it works by basically connecting all the codes in a way that they work together to maintain (or stop) the loop (notice how i said loop, it uses a loop but isnt a while or for loop, it connects the end of one code and the start of another, like a chain . I made it in the pull request #2, check it out: here"}, {"post_id": 54151, "ts": "2026-08-24T23:51:28Z", "hours": 5.8114, "text": "Fixing some forgoten code and more So at this devlog i were fixing some bugs in a specific ui / route called ¨copa¨, this is a special route added because a teacher asked our team to create them to use at some football games in our school. But since it was a hiddend route and mostly like a easter egg it hasnt been updated in a while and wasnt working anymore. What i fixed i was following a pattern where most of the images that each route used should be in a special foulder of storage (literally called /storage), but this mode (copa) where created before it and was following the old way Also there was some errors ocurred afther i changed the entire folder structure, so the copa mode where completely broken, i fixed it too. What i added I had a class about PHP + Laravel | API | Controlers in my course, afther that class i realized that the way the API (copa) where searching for data based on ID where wrong (was doing copa?id=…), i changed it to /copa/id There is a function that show the teams to the user to select one that he wants, but the teams list where hard coded and wasnt synced with the database. I made it use the database data instead of a hardcoded value ** That where all for that mode, but i didnt spent 5 hours just on it, i made more: ** Fixing (or making) some other bugs There is a script that controls the database that where holding and infinite single connection with the database, something like this conn = mysql . connector . connect ( ** configs ) cursor = conn . cursor ( Dictionary = True ) But all the codes where using the same connection and cursor, so i decided to apply a connecton pool and make each database call get a connection and a new cursor. Also i added some functions to abstrac the connection and query part: def __get_connection ( self ): conn = self . db_pool . get_connection () conn . ping ( reconnect = True , attempts = 3 , delay = 1 ) return conn def __execute_query ( self , query : str , params : list | None = None , dictionary = True , query_type : QueryTypes = QueryTypes . ALL ): conn = self . __get_connection () try : with conn . cursor ( dictionary = dictionary ) as cursor : cursor . execute ( query , ( params ) or ()) match query_type : case QueryTypes . ALL : return cursor . fetchall () case QueryTypes . ONE : return cursor . fetchone () case QueryTypes . EXECUTE : cursor . commit () return cursor . lastrowid or cursor . rowcount case _ : raise ValueError ( f \" Tipo de consulta não suportado: { query_type } \" ) If yall want to see it check here at my repo That was also the first time that i used a Enum (on code) and branchs (on github, but i didnt used them properly) Others There was also some other changes, check the repo GF-Silva/Ritualia What next Now i will add some bug checks on a piece of code that handle the video display using an youtube iframe."}, {"post_id": 52754, "ts": "2026-08-23T03:00:03Z", "hours": 4.8206, "text": "Changing some values to be relative I spent a while (more than i expected) changing some strange values that control some settings of a component called cover-flow (this component create and control the images that are displayed in the home screen). I spent more time figuring out what where each variable and lhe logic behind than acually writing.Before it had some hardcoded values that would probably broke if anything changes, i saw it and solved. I wasnt here for it, i was fixing another bug and fixed it before it broke. I also used some basic math of circles like angle of an arc. That is all for today"}, {"post_id": 52465, "ts": "2026-08-22T16:18:22Z", "hours": 3.1097, "text": "I spent some time correcting errors and logic problems, here they are: Error Correction Music playback would freeze when the music queue ended : This problem would break the app until you restarted it, but it was very simple to solve. I had simply made it remove the first instance of music from the HTML twice, which caused it to try to remove an element that didn’t exist, thus freezing the app. Removed an unnecessary loop : In the player section, there was a loop that iterated through all the elements (emotions) in a list to toggle the state of ONLY 1 ELEMENT. With the few elements it had (there were 3), this was minimal, but adding more could be detrimental to functionality. It only did this to toggle the state of the PREVIOUS element from active to inactive. I solved this simply by making it save the index of the last element and use that to access it. It took a while to work because javascript was treating 0 (the first indice / old indice when u start) as false in the if, but afther i figured out why it was simple to solve (if oldIndice != null) Implementations / Changes I separated the API/WEB routes : Previously, the routes exposed by the backend (such as /songs) were in the same file. This wasn’t a problem before, but with the addition of new functions, it could become difficult to maintain and prone to various errors, as the routes weren’t separated (a name could be the same). Therefore, I separated them into: /api (backend API codes) and / (frontend web codes). I put the genres in the database : Previously, the genres were in the frontend, and to add a new one, I would have to update both the backend and the frontend. To solve this, I simply added a route that retrieves the current genres (from the database) and uses the data (name / location) to load them into the frontend. I added the emotions to the database : The emotions had the same problem; although both (they and the genres) were in the database, the frontend wasn’t based on that data, so I did the same thing I did with the genres. I changed the name of where the music explanations were saved : I must have mentioned in a devlog that the folder inside storage was called /explication_source, and I also mentioned that the name was incorrect (because the audio source wasn’t there, nor would it be; the audio files themselves are there), so I changed it to /explication_audios"}, {"post_id": 48602, "ts": "2026-08-17T02:01:56Z", "hours": 3.6708, "text": "Updating the README I saw a post about how to structure a README, how to make it clear and etc. Afther i realized how wrong the old README was (it was confusing, and also was months out of date). So I chose some topics that would be interesting to include in and filled in a skeleton, spending some time learning what to do and what not to do. I also didn’t fill in some fields because they aren’t ready yet (they now are stored in my memory to add later). How it was before: https://github.com/GF-Silva/RitualIa/blob/9a2a7756c777a7042eca28309924e5a408bd561f/README.md How it is now: https://github.com/GF-Silva/RitualIa/blob/2dea5f80266f06e8633af1aa3c9430065cde9231/README.md There is a huge difference. Also i did some bugs and noticed how bad my commits are"}, {"post_id": 47776, "ts": "2026-08-15T22:55:35Z", "hours": 32.5314, "text": "After a development pause, here are the various changes made. Also, I never mentioned it, but this project was made by students focused on the school environment. (This time I finally got around to writing the devlog myself): Structure Moved main.py to the root Replaced mysql-connector with the official version : The added library was a version I didn’t recognize; I added the official one instead. Cleanup Removed some Code that wasnt being used. Backend Change the return value of the SQL cursor : Previously, the cursor returned an array, but for code readability and security, I opted to change it to an array. Structured Error 404 : The backend used abort in certain parts, but it returns HTML and certain parts of the frontend expected JSON, so I formatted the abort to JSON. This caused a headache, I hadn’t tested it (again lol) and when I saw it, it was time to present the project at school and I was having this error. frontend Fixed the CoverFlow component : An error went unnoticed in the creation of the component, this made the size and spacing of the images look strange, it was fixed to a certain extent. I implemented a new playback policy : The text about it got so long that I decided to open an extra topic. Playback Policy Now it search for the requested emotion + genre that the user choose, If It fails It search Just for the genre, if It fails again it search for anything. Now it falls into a fallback: This policy change was motivated by having to find a song to show in a presentation and failing. I reflected that if it was annoying for me, it would be for the end user (students) as well. Database Added new songs : I added 50 extras and their respective genres/emotions. (Also i wrote some helpers in python to help me categorize and search for the musics in youtube and get and structured sql output, that took quite a while) Saved the songs locally : Topic local saving Local saving But why would saving the songs in the cloud be a problem? Nothing comes for free, the server we were using to host the music had a monthly access limit, which was a silent problem that, thankfully, was noticed before it happened. My mistake, I didn’t even think about the possibility of saving locally and went straight to saving in the cloud, it must have been due to haste and inattention (always plan well what you are going to do before you do it, weigh the risks and benefits). Now, how it works The audios are saved inside the /storage folder. The database still saves the location, but this time it saves the relative path (e.g., /explication_audiis/fun_audio.extension). Why save the folder path as well? Won’t the audios always be there? Yes, but at some point the path might change (e.g., explication_source/youtube/audio_legal.extension). Future plans I’m going to improve my devlogs lol, this one got huge"}, {"post_id": 12818, "ts": "2026-06-20T23:46:13Z", "hours": 5.5386, "text": "RitualIa in Evolution: Refactoring, Optimization, and New Features 🎶 Hey everyone! I’m back with a cool update on what’s been happening here at RitualIa. After that commit where we transformed some scripts into helpers, things have evolved quite a bit. We’ve been doing a heavy refactoring of the project, focusing on organization, performance, and better code architecture . What’s changed: Structure & Organization: I removed legacy folders that weren’t being used, did a mega merge bringing everything from /frontend (the folder that where holding ALL the frontend logics) to the project root (with that the frontend and backend are in the same folder), and switched from FastAPI to Flask on the backend. Why the change of FastAPI to Flask: Because my supervisor or mentor (something like this) said and said again to, because there was other guys in the project (still is, but im the main developer, the others stopped doing anything like mounths Ago, and even while they where doing something i still was the main dev), these other guys where total starters and could not hold the learning curve of FastAPI (even with the fact that was Just me that where using It, because it was at the backend and i was the only developing at back). Code Quality: We made several methods private in the PlayerControls class, making the API cleaner and more secure. We also fixed the “enclosing class errors” that appeared. These small fixes make a huge difference in code reliability. UI/UX Improvements: We created a new CoverFlow component to replace GenreCylinder on the homepage – it’s much smoother and prettier now. We added support for async onClick, grab + touch in CoverFlow, and adjusted visual positioning to keep everything aligned. Oh, and we removed that unnecessary playerText that was cluttering the interface. New Features: A really cool feature that was added was the checking for duplicate songs in the queue . Nothing worse than accidentally playing the same song twice, right? Now that doesn’t happen anymore. Maintenance & Updates: We updated the fetches to call the new routes, moved the favicon to assets (because everything has its place), and focused on the details. What’s coming next: We are in a consolidation phase, laying a solid foundation for the upcoming features. The focus now is on ensuring that each component is doing exactly what it needs to do, nothing more, nothing less. Thanks for following along!"}, {"post_id": 11702, "ts": "2026-06-19T02:03:07Z", "hours": 1.0236, "text": "I’m transforming some duplicate code into helpers so they can be more easily used in new code."}, {"post_id": 11412, "ts": "2026-06-18T17:53:37Z", "hours": 1.2881, "text": "Introducing: The ‘Ritualia’ project is a project developed by me and some colleagues with the help of the school. In it, we have done and continue to do research and assembly with the aim of impacting the daily lives of students in our school and (in the future) other schools. It is an open-source project with an article soon to be published detailing the foundations used, etc. The readme is currently outdated because I am redoing part of the current architecture, but I will update it later to include information on how to assemble and create your own version. The project is divided into hardware and software. I, along with other members, am responsible for the software (which is usable on most computers), and the hardware is relatively simple (it only depends on a display + sound + a controller with an OS + the preparations for installation)."}]...
|
Title: Ritualia by @gabriel_ferreira | Stardance
Title: Ritualia by @gabriel_ferreira | Stardance
Devlogs:
Introducing: The ‘Ritualia’ project is a project developed by me and some colleagues with the help of the school. In it, we have done and continue to do research and assembly with the aim of impacting the daily lives of students in our school and (in the future) other schools. It is an open-source project with an article soon to be published detailing the foundations used, etc. The readme is currently outdated because I am redoing part of the current architecture, but I will update it later to include information on how to assemble and create your own version. The project is divided into hardware and software. I, along with other members, am responsible for the software (which is usable on most computers), and the hardware is relatively simple (it only depends on a display + sound + a controller with an OS + the preparations for installation).
I’m transforming some duplicate code into helpers so they can be more easily used in new code.
RitualIa in Evolution: Refactoring, Optimization, and New Features 🎶 Hey everyone! I’m back with a cool update on what’s been happening here at RitualIa. After that commit where we transformed some scripts into helpers, things have evolved quite a bit. We’ve been doing a heavy refactoring of the project, focusing on organization, performance, and better code architecture . What’s changed: Structure & Organization: I removed legacy folders that weren’t being used, did a mega merge bringing everything from /frontend (the folder that where holding ALL the frontend logics) to the project root (with that the frontend and backend are in the same folder), and switched from FastAPI to Flask on the backend. Why the change of FastAPI to Flask: Because my supervisor or mentor (something like this) said and said again to, because there was other guys in the project (still is, but im the main developer, the others stopped doing anything like mounths Ago, and even while they where doing something i still was the main dev), these other guys where total starters and could not hold the learning curve of FastAPI (even with the fact that was Just me that where using It, because it was at the backend and i was the only developing at back). Code Quality: We made several methods private in the PlayerControls class, making the API cleaner and more secure. We also fixed the “enclosing class errors” that appeared. These small fixes make a huge difference in code reliability. UI/UX Improvements: We created a new CoverFlow component to replace GenreCylinder on the homepage – it’s much smoother and prettier now. We added support for async onClick, grab + touch in CoverFlow, and adjusted visual positioning to keep everything aligned. Oh, and we removed that unnecessary playerText that was cluttering the interface. New Features: A really cool feature that was added was the checking for duplicate songs in the queue . Nothing worse than accidentally playing the same song twice, right? Now that doesn’t happen anymore. Maintenance & Updates: We updated the fetches to call the new routes, moved the favicon to assets (because everything has its place), and focused on the details. What’s coming next: We are in a consolidation phase, laying a solid foundation for the upcoming features. The focus now is on ensuring that each component is doing exactly what it needs to do, nothing more, nothing less. Thanks for following along!
After a development pause, here are the various changes made. Also, I never mentioned it, but this project was made by students focused on the school environment. (This time I finally got around to writing the devlog myself): Structure Moved main.py to the root Replaced mysql-connector with the official version : The added library was a version I didn’t recognize; I added the official one instead. Cleanup Removed some Code that wasnt being used. Backend Change the return value of the SQL cursor : Previously, the cursor returned an array, but for code readability and security, I opted to change it to an array. Structured Error 404 : The backend used abort in certain parts, but it returns HTML and certain parts of the frontend expected JSON, so I formatted the abort to JSON. This caused a headache, I hadn’t tested it (again lol) and when I saw it, it was time to present the project at school and I was having this error. frontend Fixed the CoverFlow component : An error went unnoticed in the creation of the component, this made the size and spacing of the images look strange, it was fixed to a certain extent. I implemented a new playback policy : The text about it got so long that I decided to open an extra topic. Playback Policy Now it search for the requested emotion + genre that the user choose, If It fails It search Just for the genre, if It fails again it search for anything. Now it falls into a fallback: This policy change was motivated by having to find a song to show in a presentation and failing. I reflected that if it was annoying for me, it would be for the end user (students) as well. Database Added new songs : I added 50 extras and their respective genres/emotions. (Also i wrote some helpers in python to help me categorize and search for the musics in youtube and get and structured sql output, that took quite a while) Saved the songs locally : Topic local saving Local saving But why would saving the songs in the cloud be a problem? Nothing comes for free, the server we were using to host the music had a monthly access limit, which was a silent problem that, thankfully, was noticed before it happened. My mistake, I didn’t even think about the possibility of saving locally and went straight to saving in the cloud, it must have been due to haste and inattention (always plan well what you are going to do before you do it, weigh the risks and benefits). Now, how it works The audios are saved inside the /storage folder. The database still saves the location, but this time it saves the relative path (e.g., /explication_audiis/fun_audio.extension). Why save the folder path as well? Won’t the audios always be there? Yes, but at some point the path might change (e.g., explication_source/youtube/audio_legal.extension). Future plans I’m going to improve my devlogs lol, this one got huge
Updating the README I saw a post about how to structure a README, how to make it clear and etc. Afther i realized how wrong the old README was (it was confusing, and also was months out of date). So I chose some topics that would be interesting to include in and filled in a skeleton, spending some time learning what to do and what not to do. I also didn’t fill in some fields because they aren’t ready yet (they now are stored in my memory to add later). How it was before: https://github.com/GF-Silva/RitualIa/blob/9a2a7756c777a7042eca28309924e5a408bd561f/README.md How it is now: https://github.com/GF-Silva/RitualIa/blob/2dea5f80266f06e8633af1aa3c9430065cde9231/README.md There is a huge difference. Also i did some bugs and noticed how bad my commits are
I spent some time correcting errors and logic problems, here they are: Error Correction Music playback would freeze when the music queue ended : This problem would break the app until you restarted it, but it was very simple to solve. I had simply made it remove the first instance of music from the HTML twice, which caused it to try to remove an element that didn’t exist, thus freezing the app. Removed an unnecessary loop : In the player section, there was a loop that iterated through all the elements (emotions) in a list to toggle the state of ONLY 1 ELEMENT. With the few elements it had (there were 3), this was minimal, but adding more could be detrimental to functionality. It only did this to toggle the state of the PREVIOUS element from active to inactive. I solved this simply by making it save the index of the last element and use that to access it. It took a while to work because javascript was treating 0 (the first indice / old indice when u start) as false in the if, but afther i figured out why it was simple to solve (if oldIndice != null) Implementations / Changes I separated the API/WEB routes : Previously, the routes exposed by the backend (such as /songs) were in the same file. This wasn’t a problem before, but with the addition of new functions, it could become difficult to maintain and prone to various errors, as the routes weren’t separated (a name could be the same). Therefore, I separated them into: /api (backend API codes) and / (frontend web codes). I put the genres in the database : Previously, the genres were in the frontend, and to add a new one, I would have to update both the backend and the frontend. To solve this, I simply added a route that retrieves the current genres (from the database) and uses the data (name / location) to load them into the frontend. I added the emotions to the database : The emotions had the same problem; although both (they and the genres) were in the database, the frontend wasn’t based on that data, so I did the same thing I did with the genres. I changed the name of where the music explanations were saved : I must have mentioned in a devlog that the folder inside storage was called /explication_source, and I also mentioned that the name was incorrect (because the audio source wasn’t there, nor would it be; the audio files themselves are there), so I changed it to /explication_audios
Changing some values to be relative I spent a while (more than i expected) changing some strange values that control some settings of a component called cover-flow (this component create and control the images that are displayed in the home screen). I spent more time figuring out what where each variable and lhe logic behind than acually writing.Before it had some hardcoded values that would probably broke if anything changes, i saw it and solved. I wasnt here for it, i was fixing another bug and fixed it before it broke. I also used some basic math of circles like angle of an arc. That is all for today
Fixing some forgoten code and more So at this devlog i were fixing some bugs in a specific ui / route called ¨copa¨, this is a special route added because a teacher asked our team to create them to use at some football games in our school. But since it was a hiddend route and mostly like a easter egg it hasnt been updated in a while and wasnt working anymore. What i fixed i was following a pattern where most of the images that each route used should be in a special foulder of storage (literally called /storage), but this mode (copa) where created before it and was following the old way Also there was some errors ocurred afther i changed the entire folder structure, so the copa mode where completely broken, i fixed it too. What i added I had a class about PHP + Laravel | API | Controlers in my course, afther that class i realized that the way the API (copa) where searching for data based on ID where wrong (was doing copa?id=…), i changed it to /copa/id There is a function that show the teams to the user to select one that he wants, but the teams list where hard coded and wasnt synced with the database. I made it use the database data instead of a hardcoded value ** That where all for that mode, but i didnt spent 5 hours just on it, i made more: ** Fixing (or making) some other bugs There is a script that controls the database that where holding and infinite single connection with the database, something like this conn = mysql . connector . connect ( ** configs ) cursor = conn . cursor ( Dictionary = True ) But all the codes where using the same connection and cursor, so i decided to apply a connecton pool and make each database call get a connection and a new cursor. Also i added some functions to abstrac the connection and query part: def __get_connection ( self ): conn = self . db_pool . get_connection () conn . ping ( reconnect = True , attempts = 3 , delay = 1 ) return conn def __execute_query ( self , query : str , params : list | None = None , dictionary = True , query_type : QueryTypes = QueryTypes . ALL ): conn = self . __get_connection () try : with conn . cursor ( dictionary = dictionary ) as cursor : cursor . execute ( query , ( params ) or ()) match query_type : case QueryTypes . ALL : return cursor . fetchall () case QueryTypes . ONE : return cursor . fetchone () case QueryTypes . EXECUTE : cursor . commit () return cursor . lastrowid or cursor . rowcount case _ : raise ValueError ( f " Tipo de consulta não suportado: { query_type } " ) If yall want to see it check here at my repo That was also the first time that i used a Enum (on code) and branchs (on github, but i didnt used them properly) Others There was also some other changes, check the repo GF-Silva/Ritualia What next Now i will add some bug checks on a piece of code that handle the video display using an youtube iframe.
Optimizating some piece of code So there was a certain part of the code responsible for the songs queue in the main route, that piece is a core function but where running a while true loop for no reason , here is the part: async start () { while ( true ) { // { emotion, genre, author, name, sourceId } const musicData = await this . #musicQueue . get (); this . createPlayer ( musicData [ ' sourceId ' ], null ); this . #showMusicInfos ( musicData [ ' name ' ], musicData [ ' author ' ]); this . #queueList . removeChild ( this . #queueList . children [ 0 ]); await this . #startExplication ( `/storage/ ${ musicData [ ' explicationSource ' ]} ` ); this . player . playVideo (); await this . #musicFinished . when ( true ); this . #musicFinished . set ( false ); } } Basically the code were calling it at the start and running it forever, but that code where a nightmare to maintain / implement, i tried to implement a safe check here for over 2 hours, but wasnt possible. I replaced it for a more efficient approach that do a loop in a different way, here it is: when adding a music, it checks if it is already playing, if no starts to play. when start to play it checks if there is a music in the queue for it to play, if no it stops playing, if yes it get it and play. When the music that is playing ends, it call the play function (from the above topic). That is just it, no while or constant loops, no overhead, it works by basically connecting all the codes in a way that they work together to maintain (or stop) the loop (notice how i said loop, it uses a loop but isnt a while or for loop, it connects the end of one code and the start of another, like a chain . I made it in the pull request #2, check it out: here
Fixing errors and adding bug checks Hi everyone, so i were fixing some bugs that i saw that may broke the app, i fixed all of them (for now), here they are: There was a logic bug that a class (the one that controls the youtube iframe) where doing stuff that it wasnt supposed to do (not an unexpected behavior, but a logic that should be outside of it), it was an easy fix. There was a bug at the player class that when the provided sourceId (for the youtube iframe) where wrong or unable to use it crash and stopped doing anything else (like playing another musics). I tryied solving it in various ways, one was beffore the changes that i did in my last devlog, but i failed because the class that holds the player where hard to fix, this devlog fix it. I fixed it by adding some bug checks and, when some error ocurred, it play the next music. There was also a bug at the player class and youtube-iframe-controls class, that for a couple seconds in the start of the website it would broke if u tried to play a music. It was because in the start of the program the youtube API where unable to be used. To fix it i just made it wait until the API where ready using an ASYNC function. There was also a bug that, afther the past devlog, it was doing and request at the /api/songs with params at the wrong format. Afther the past devlog the API started using the params genre_id and emotion_id , but the frontend where passing with the incorrect name (genre, emotion). Something that i implemented I upgraded the mysql query that where being used to get more infos about the music, before it where just returning infos like name, author, sourceId, etc, but now it also returns the genre and emotion from that given music. I added a bug check at the player class, now if it fails it pass to the next music. Something that i want implement I want to implement a simple toast notification system that will apear when something fails, like the playing of some music. Others The youtube docs for the iframe where very helpful for this changes, check it out: https://developers.google.com/youtube/iframe_api_reference?hl=pt-br
Creating a toast notification system So rn im creating what i said in the past devlog about a toast navigation. This isnt finished yet, im still figuring out an way to check the end of the timer, i found some ways to do it, like using an simple if inside the countdown. I didnt comment but i am using an setInterval to decrease the time and an <progress> tag to show the value but that is a bad ideia, imagine doing 1 if every 50 ms? that dont cost a lot of processing power, but i still will search for other ways to do it just to check, if yall got any hints or ideas leave a comment. Also i will improve the design, the design is petty poor.
The toast notification is finished So i finished it, it is a component that u adds in the code that u wants to use. I added 2 icons, 1 for infos and another for warnings. What i used and did The element that holds it all is an dialog , the icons are svg , the text is a span and the element that shows the time left is an progress . To update the time left i used an setInterval that runs at a 10ms delay and deduce 0.01 of the dialog value, so it will be smooth to see. Also there is an if inside that destroy the element and clear the interval when the value of the dialog reaches zero or less (In the past devlog i said about not using an if, but considering how low the cost for an if in that time is i decided to use it anyway). The function that creates the toast receives some params that will let it be customized by whoever is calling it: const icons = Object . freeze ({ INFO : infoIcon (), WARNING : warningIcon () }); function createToast ({ message , time = 5 , styles , icon = icons . INFO }) // the `message` is the displayed message // the `time` is the time until close // the `styles` is custom css styles for the element, it uses the dictionary format {} // the `icon` is the svg icon What else? I will apply it in some elements and post about. See you later!
Toast applied and tested The toast notification component is now being used at the player class, i did some tests and it is working very nice, hopefully the user will not see it very often (because that would be a problem, the user must not see it unless there is an error playing the music). But why did i make it? It is used to show more about what is going on for the user, so they will not become anxious if it something is working or not. Why not use another notification system? Each notification system has its own use cases, the others would be very painful for the user. Imagine every time a simple error (that is simple for me) like the music fail to play there was an error that interrupt the use of the app with an popup or alert, that would be painful, dont it? That is why i used an toast notification, because it is temporary (disappears after some seconds) and dont stop the use of the website. Also there is a feature that i implemented for the same reason a few devlogs ago that add a fallback in the music search, so it wont show a message at every single combination. Lets calculate how many combinations we have: there is around 50 musics in the database, 22 genres and around 40 emotions, multiplying the genres and the music 880 combinations that the user can make. Now lets see how many musics we can get: each music have around 1.2 emotions and 1.2 genres, so we get 72 combinations that lead to an music . With that in mind, we can see that from 880 combinations, just 72 of them are useful combinations, so we get a 8.18% for getting a music, and 91,12% of not getting one. Consider that each failed attempt shows an error that stop the use flow of the website, but that was before the past devlog, now it tries again and again and only afther failing everything it shows an error, at that point it must really show an error. Thats all, sorry for the long boring text and thanks everyone that read, see yall later
Studing about cache So basically i where studing about cache, the main ideia was to implement it in the sistem, but then i realized something: Theres is nearly no difference between cache and a normal request in an localhost project, adding the cache would not improve anything, sometimes it maybe even slow the website, because the page would need load more code. I realized it afther a while studing about it, but anyway lets focus on another thing. Also i where studing with google for devs: https://developer.chrome.com/docs/workbox/caching-strategies-overview
Adding a new description feature So basically there was an place where was designed to have the description about an music, but that was empty and where only finished today What it do It is petty simple, it just show an text about the music that is currently playing, also there is an audio that plays before the music starts playing, but this audios is played just one time before the music so if someone loses it or didnt listen well there was not a second chance to listen for that audio. Now there is this place that holds the same content, but in the format of an text that can be read whenever they want while the music is being played, that was what i added. Also that text can be hidden, so it will not stay using half of the screen every time (in the screenshot it is active) What this audios do This audio / text is part of the main purpose of the website, they give some fun facts about the music that may be useful someday in some kind of quiz or essay. Also the audio is played before the music and the music plays just after the audio finishes. That is to make whoever is listening listen to the entire audio before having what he (or she) wants, so they will not listen to the music and skip the audio.
Adding more bug checks I added some checks in the player class at the startExplication function that checks if the src (the url for the audio) is valid or not by doing an fetch with the HEAD method and checking if the return is an valid audio before trying anything in this function. Also i solved this error in the same function: Uncaught (in promise) AbortError: The play() request was interrupted because the media was removed from the document. https://goo.gl/LdLk22 This error was because the startExplication function where trying to play the audio before it was loaded, i solved it by making it play the audio just after it was load with the event listener canplaythrough . There was another error at the playMusic function where the code where trying to play the youtube video before it was loaded, i solved it by making it wait until it was CUED (Where the video isnt playing, but is loaded and showed). (The website was not created to be in mobile and dont has a lot of support, the video where recorded in my smartphone because i had to record the audio and the audio on my pc dont work. In the Future i Will add mobile suport, but right now im finishing the bugs and etc)
Refactoring the copa script I where placing some scripts in a class. These scripts are related with the player functions of the copa script, so i pick all of them and placed in the same class. I did it to follow best practices, but i confess that i still got some doubts about when to create an class and when the variable or method should be static or private (#property), i will search and learn more about because maybe i will have to refactor some parts of the code following these rules of best practices. That was all for now, see ya!
Creating a new helper Context: There was an class called youtubeFrameControls , this class basically where designed as an structure to help using the youtube iframe API, but with the time this class where becoming basically to hold just an function (and in a very inefficient way), because the methods that it had before (like the one that runs when the iframe is loaded) had to have more and more specific logic in the codes that used it, so they where useless (because the codes that where using it where rewriting it). What i did: I picked the only function that where being used and transformed it in an helpers (that can easily be customized). This function was the one that creates the player of the musics, and the function where called createPlayer . Also i removed the old class (youtubeFrameControls) and replaced it for this helper in every place that used it. It now is way more simple than before and can me more customized.
Making the website responsive Hi again! Like i said in some devlog, the website dont have support for mobile, that was because it was designed to be at kiosk mode and work just in desktops. but i decided to change that. First of all: the site where using a lot of absolute values of dimensions, so it where braking even in the desktops (it wasnt responsive at all). But i spent a while changing it, it is isnt ready and has some problems, but is better than before. (The mobile is still strange, i did not started fixing it yet). Credits: https://css-tricks.com/snippets/css/fluid-typography/ - This website shows about a way to make the texts become responsive for the screen using some calcs, it is worth seeing. The first video is how it was before, the second is how it is now
Hi again! Like said in the past devlog, im improving the responsiveness of the website, specifically in the player part. But it had some problems and where distorting when playing an video, now it resizes based on the screen size in a way that it stays ¨normal¨. The first video is the new way, the second is the old way. It still needs a lot of improvements, but it is going!
Im improving the responsiveness at the home page (before was the player page), but for some reason that idk the emotion selection div is having a strange behavior, i will update what it is after i fix it. Take a look: (the item in the center should be centered)
i finished the workings on the section of the home page that i where doing before, now has a good responsiveness for pc and a decent one for mobile. Now im working on the main area of the home page, the one where the user selects the desired genre for the music (second img). It may looks completely fine, but that same element already was a headache before and is here again. The given area is the cover-flow component, before i already fixed it (or so i thought), but it was looking bad (the 3d perspective where a bit strange) and would probably broken if i added new genres. I were trying to figure out a way to listen to the clicks in the card without any problems, that seems easy at first glance, but the 3d perspective in the element make other elements eat the click from one another, make the clicks dont be listened and so many problems that i nearly decided to erase it and write from scratch. I already found a way to do it by using the mouse position, the center of the screen and the card width (the genre img) to transform it in an value that can be used to select the exact card without any dependencies on the doom selector. It basically uses just some values, put in some calcs and get the difference between the current card (genre) index and the clicked. Im nearly finishing it, but i still need to figure out some values and more.
Finished the correction of the errors at the perspective and click in the cover-flow component. Now the perspective stays the same 150vw value (that is based on the screen width) and stays normal, with everything working. Oh man, that needed a lot of logic and out of box thinking finding another ways to check where the user clicked without using an normal click event listener (for those who lost the past devlog or didnt understood, i cannot use a normal eventListener in that because the clicks is detected in another element or in nothing, even with z-index or more in css, so the solution should be done entirely on javascript logic). The first video is the new way, the second is how it was before all changes in it
Im nearly finishing the workings on the responsiveness. Now the entire player screen is responsive and do not breaks the texts anymore (except for the description area), also the buttons that show you the next screen (the ones that displays ‘player’ and ‘generos’) are responsive too, the music queue is working perfectly fine, and the area that is used to select an emotion is nearly responsive too, it just needs some adjusts in the two buttons that change the current emotion because they become too small and uses a lot of space when the screen is too small, after that this screen will be finished. It is taking a really long time, the fact of how many different screen sizes exists makes it harder to finish, but now there is times that i even cannot see if i changed the resolution in some areas, because the system looks the same. I spent quite a while testing different resolutions and combinations of size, i didnt even noticed that i where 6 hours here, but now ik more about css (things like container-type + container based sizes and more ways to set the size of an text) The video shows how it is now, if u want to see the before just checks the past devlog.
The emotionDrum is now responsive! Now the buttons that you use to select the emotion are in the same side as the div that displays the emotion, so they dont fight for space anymore. This change is meant to fix the low size of the items in screens that are too small, in the new way we have more free space to display the emotions, there is not much to say. What else I did some minor changes in the size of some items at the player area, now they are easier to read! (I increased the size of some items)
The home is now fully responsive Ah that took a while, but finally it is fully responsive. Now the description at the player UI resizes based on the screen size and active a scroll behaviour when need, also i did some minor change at the emotionDrum perspective to make it show more emotions at the same time, removed the padding in the arrows at the emotionDrum so they will have more space and fixed an error in the genre drum that was making it perspective broke. After all these devlogs i improved how i make a code responsive.
Improving the performance After finishing the improvements in the responsiveness, now i decided to improve the performance. I used lighthouse to get insights (i learned about it in an tiktok video) and figured out that the images size were too high (were an png of 1280x1280px), so i saw more about that in the page: https://developer.chrome.com/docs/performance/insights/image-delivery (an link that google lighthouse gave). With that i saw how to decrease the size while staying with quality, i reached up to the sharp-cli tool, that makes the work of resize, convert and compress the image for me. The command used was that: npx sharp-cli -i * .png -o ./output resize 320 -f avif -q 50 --effort 6 --smartDeblock --preset photo The 320 is the size that i want it to be at the end, i got that value by seeing what was the computed value (the value that is being used in the website) in an high resolution pc (not the most higher one, the high but normal pc) with the resolution of 2500x1714px . With this simple changing the image went from 2mb to 40Kb! Nearly 100% decrease, and take in mind that there is more than one img, so the change were even higher. Also i created 5 different images: 320px, 480px, 640px, 960px e 1280px. With them the browser can choose which one is better for each device. With these changes i went from 35 points of performance to 59.
Improving the LCP (Largest content paint) performance I am improving the way that the website create and downloads the images, the main reason is to make the user see something faster. Before the system were doing 2 main things: Go trough the entire list of images, creating the elements and placing them into the page. Position them. But the position of the items were being done after the creation of the images, in another function. Now they are in the same function: it create the element, position it and add it to the page. That does not seem like much, but the code got way faster with that, probably because it dont need to go item by item in an list twice just to create an element. I tested the time to load the first element and it went from 8.63s to 6.43s , the test was made with 2200 elements (Yeah ik, it is a lot and normally it isnt that much, but i had to see how they were holding with more than 22 items). Also i fixed a bug that passed unnoticed while improving the responsiveness: At some point of images the visibility of the elements broke, that was because the perspective (what makes the 3D perspective of the component, and makes it visible with 3D effects) was based on the screen size, not the elements itself. What was the problem in that: Each element takes a size in the screen ‘makes the circle that shows the element be more and more near of our point of view’ (i cant explain it any better, search what is ‘perspective in an 3d element at HTML’ ). While it was approaching our point of view (POV), our POV were exactly at the same position (based on the screen size), so at some point the circle perspective would pass the POV and we would be unable of seeing it well. Now it is based on the elements: The 3d elements were basically a circle, i just used the diameter to change the perspective based on it. TODO: Maybe i lowered the image quality too much… I will fix it in the next updates. Also i were trying to improve the font settings to improve the performance, but that wast working so i decided to move on to this because it was more critical (took a while for me to jump to this, maybe like 2 hours trying and trying values in the font settings). i am also working in a way to load the images in parallel, with that it will take way less time (I didnt known about LCP before so i spent a while figuring out the way it works).
Improving the loading performance Now the system selects some images that needs to be shown faster than the others and making them load with priority. It was made by selecting the images that the user is seeing and defining some params like fetchPriority = "high" and decoding="sync" , the other images have the params: decoding="async"; loading="lazy"; contentVisibility="auto"; . With that config the LCP went from 2.4s to 0.5s . Also it loads the image in the start and dont change that config again, so the browser will be lazy while downloading these images. The problem is: only the first images are chosen as high priority, but their positions will be changed while the configs stays the same, that makes the browser lazy while loading them and makes the runtime performance became worse. To fix that i found about IntersectionObserver, that are meant to solve the problem of updating the images position fast. It was not applied yet, i found about it like 1 hour ago. What else Now the perspective of the emotionDrum is based on the elements that it have, before it was based just in the screen and would broke if something changes. I did a little change in the way that the script checks for clicks in the screen, now it has more accuracy (I changed the round system).
Adding an observer Now the script observe the card elements at the cover-flow component, classify their position and changes it visibility based on that. Im using an IntersectionObserver to observe every card, but it was designed to observe the position of 2d elements, so i had to figure out how to make it work well in an 3d element. The way it works is when the observe activates (it basically means that some card is in the range to load) it get the card info (like position and angle) and changes it visibility state based on that. Simple, right? No, it was a headache for the start to the top, nearly 4 hours of what i did was to fix the fact that it was meant for 2d. The observer were activating for cards that were in the back of the element, so i had to classify the card position into back or front by using its angle. But if i tried to use the card angle without anything else the script would broke (and did for 3 hours until i realized how to fix), so i had to use an second angle which is 360 - cardAngle (the 360 is the angle of an circle), so this new angle is based on the circle end while the other is based on the circle start. But the system still broke, because at some point one of these values would become negative and makes the if that classify the elements fail. The fix was using the absolute value in the if (it took 1 hour until i figured that; oh i were so happy when it worked). Why To improve the performance, so the browser will just load what is really important and not 50 images that the user cant even see. What else All that work definitely improved a lot my logic thinking and for the first time i used the truth table well. Now i just need to use the new code to change more the style of the images that are not in the screen. I did not deleted the code that i wrote in the past devlog, it was used in the new code to select how many images should be loaded in the same time. ** The first video is the result, the others is some problems that i had **
The observer is finished (nearly) Now the cover-flow has an observer that checks the position of the images and changes it styles based on that, so the images that the user is seeing is loaded while the others is hide. It still has some bugs and space for improvements that im still figuring out how to solve, like the image loading too late on the screen or, in slow internet connections, the image takes too long to load. Most of these bugs are because the observer (an intersectionObserver ) was designed for 2d contexts, not 3d (that were and still is an giant problem to solve). For this reason i was thinking about creating an observer from scratch in C++ that can work better in my 3d element, but the overhead would be high so im trying to solve in other ways before that. The feature was made using fetchPriority, contentVisibility and src (the system add the source just when the image is near the screen). OBS: I found about MutationObserver after this post, maybe i will use that instead of insersectionObserver. Oh man, at least if had found about this before… Aaaaaahhhhh i spent 9 hours in that, but at least a Lot of the new logic will be used. Anyway, lets cook
Adding a mutationObserver Now, instead of an intersectionObserver, the system use a mutationObserver that monitors the angle of the cylinder itself. With that the loading of the images will be insanely better, faster and user-friendly. Now the changes in the cover-flow is observed at the cylinder angle, not at each card. There was some problems in the journey like, for some reason, unexpected cards being loaded or not, the loading script at the observer dont triggering at all (that was caused by the speed of the observer) and an insane amount of cards being triggered at the same time (i still did not figured out why, but that isnt ‘harmful’). But man, i had to be creative here and remember about some concepts like concurrent programming, buffer / queue and apply some delays (because the mutationObserver is insanely fast and can trigger every millisecond). That all was meant to decrease the speed of the mutationObserver, because it was triggering with the most small change in the cylinder, so i made it trigger just when an expected amount of movement was made. The red/yellow collor is for me to visualize the loading state, it is just for debug The code isnt finished, i still need to implement the loading part, for now i just implemented the observer and basics of the loading part
The loading is done Features Now the loading at the mutationObserver is finished, it finally loads or unloads the images that should be (or not) loaded! The new observer is way faster, because it can detect the image way before it enters the screen, loading it before and having more time to do it. Also the system loads just a maximum of images (with the configs that i put it is 13), so it will not fry an cellphone. Problems The loading part was easy to do, i already done it before in the past observer (intersectionObserver), so i just had to pass the old code to the new part. But when the cover-flow element dont got atleast 13 elements the mutationObserver code breaks completely! Im still pondering how to solve it, when i do i will post about! Results The performance went from 78 to 100! The system is way faster! The user does not see a blank image anymore! Why The old method was slow even with a good internet connection, because it was loading the images just when the element was already in the screen, leaving to a perceptive delay for the user and a blank image to the user. Also i thought about creating an observer from scratch (maybe i was a little off my ideas, because that was insane), but the browser already had exactly what i wanted (the mutationObserver) Videos The new features The performance of the new feats The old features Reasoning While i was trying to sleep i thought about a system that fill the cover-flow with a maximum of images (like 10, or 13, or the code decides) at the DOM, using less memory to run. That system will free a lot of memory based on how many cards the cover-flow have. But that will have noticeable effects just with a lot of elements and probably would be hard to develop, maybe i will do in next updates. What next Im leading to the shipping, so i will improve metrics about the lighthouse, improve the readme and post it.
The loading is done and working! Fix I fixed the error that were happening when the cover had a certain amount of elements. Problems The fix itself was very easy to do, but doing it in a readable or without using 10 lines of code (i want things concise) was way harder than i expected. So i spent this entire time trying different ways to do it, each of them making everything worse. Reasoning The bug were with less than 14 elements, the script were calculating the first and last element index, it happened that these elements were behind the screen focus. Why? Because the values that the system was using were leaving these values, so i had to fix the way it was calculating things.
Fixing an error at the youtubeHelper Now the youtubeHelpers checks if the youtube API is ready before sending commands. Why Sometimes the API maybe is not finished yet, that was leaving an untreated error that was braking the entire website. How was made With a lot of pain and suffer. I thought “Oh hey, that will be a 15 minutes fix” - i spent 1 HOUR FIGHTING with the iframe itself, nothing was working and at some point i started thinking that even the API of YOUTUBE wasnt working, even the most basic function that should be triggered when the youtube finished the loading wasnt beeing activated, even the console.log(“Api READY!”) wasnt working, even when it worked it wasnt working well, the variable of the player was a promise and not the result. At the end i shut down my PC, defeated, without any energy left, with just hope that in the next day (this) that would be fixed (if not i was planning to ignore and make it a feature “Easter egg, if u dont join the website for a while it will not load!”. The problem here was just the position were the iframe api was in the HTML, it was being loaded before the helper script, so the helper was not there to check if it the iframe was ready or not, the fix was just move it a little down. Architecture It was just an promise, if the function checks that the iframe isnt available it await for it to be available. The check if it was available use the onYoutubeIframeAPIReady, easy easy (except for all the suffer that i went into).
The performance workings is finished and bug fix Fixes Now the logo z-index is lower, that is because the logo was ‘eating’ the click in more important elements. Also i did a small change at the cover-flow, that change fix the bug of the scroll at the element sudently stoping when at a certain position. The copa script had some old references to images that were leading to bugs, i changed it. Performance I already finished it in the past devlog, i was just checking if there was anything worth improving, but everything is working fine and now is time to improve acessibility. Most of the logged time was me trying to improve more some metrics at the lighthouse, but the work was too much for anything that is already good, so i decided to stop before i started focusing too much in it.
The accessibility workings is done Features Now the system has a new navigation system that allow users to navigate with just the keyboard! (The video was with just the keyboard) Why Why not? It was meant to improve the accessibility for users without mouse, or any another problem and because i was tired of having to use the mouse to debug something. How it was made Again with a lot of pain, the feature itself was easy but i had to fix some errors that went unnoticed, so it took more time. The feature detects when the user press a key and do an action based on wich key was. The accessibility was easy to get 100, but the metrics at lighthouse dont give all what the users will need, i had to think about the website usage and how would be the easiest way for the user. Results The accessibility went from nearly 69 to 100! What next Now i will work on the best practices! Update after the devlog: Nearly every metric is already maxed out lol, i will ship it very soon!
All done, it is time to ship Every metric at lighthouse it nearly perfect, im so exited to ship it!
Added install guides Now there is guides to help the user install for ubuntu, arch and windows. Notice that im a linux user and my pc is weak, so i could not test it on another operational system. Also the guide is in portuguese (all of them), please use your browser built-in translator or any of them to read if u dont understands portuguese I could test it on another linux distro, but i would have to go through all the install steps. Also i cannot try installing windows because it normally wipe out another OS installed on the same disc (i know that it just replaces the bootloader) and using a VM was not possible due to the amount of RAM and the processor that i have.
Configuring an ssh server! I configured an oracle cloud vm with ubuntu to host my website 24/7, that was because nest wasnt working in a while. Im running it at a local IP with http only, i will configure https today and maybe an domain, the IP is http://164.152.55.252 , notice that some browsers may block you from accessing and http website. UPDATE AFTER THE DEVLOG: I put an domain using duck dns: http://ritualia.duckdns.org Hardwork I had absolutely not a single knowledge about oracle cloud vm, so configuring it was an hell. Sometime my internet stopped working so i had to use my smartphone, this lead me to configuring an invalid ssh key and i had do configure everything from scratch, i spent 5 hours configuring everything, but that was ssh and wasnt tracked. But now everything is working fine. Thx oracle This vm is a 24/7 entire OS (Virtual Machine) that has some good free plans, without any cold start. Thx stardance Stardance now will have one more mount!!!!!! I still has roughly 40 hours of deep development to do after this ship, i will love to finish that in stardance!
It is time to ship! Now the system is working perfectly fine running at a vm in oracle cloud with a public domain, and a dns with duckdns at http://ritualia.duckdns.org/ Warning: It is just HTTP!
Added english readme I created an english readme, api and install Guide, so it will be easier to read and more accessible for worl-wide users
Ships:
What did i made I made an complete music play system that will help users to learn while listening to musics! I used youtube, flask, python, mysql, js and hope to make this! What else Solved a lot of painful bugs that were stopping the project from working Finished and made the music queue work Added music description labels Improved a lot the performance Made the website responsive Added a keyboard based navigation Fixed so much errors at the cover-flow that now i forgot how many Added bug checks before the play of each video on the player Created an toast component to show errors or infos Added 54 musics to choose and listen Challenges The most painful code was the player and the cover-flow, they were with a lot of hidden bugs that i had to figure out, feats that i had to make and pain to suffer! Now i figured out that i love and HATE making a website responsive! What im proud of MutationObserver: An observer that loads / hides an image based on its position at the cover-flow, this system took a while and worked very well. Error checks at player: The system can handle the error that happen and dont crash! Keyboard navigation: Everyone can use the keyboard to navigate now! Oracle VM: For the first time i used an ssh and hosted an website in my own machine (oracle, not mine)! How to test Access http://ritualia.duckdns.org/ , when you join and the page loads you will find a screen to choose an genre, select which one you want, after you will see an emotion selector, select the emotion that you wanna feel! You will see the player screen and an audio explaining the music (The audio is in portuguese), after the audio the music will play. Notice: The github and the website are in portuguese, please use your browser built-in translator or any that you want to use the software properly! Follow the installation guides at github if you want to install...
|
1793008144.3293169
|
1793094544.3293169
|
|
27008
|
Cascade by @sheepex_ | Stardance
|
sheepex_
|
3
|
50.0
|
111
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-25T19:13:23Z", "hours": 23.0, "multiplier": 18.99, "payout": 0, "blessing": "neutral", "text": "It’s been a pretty busy couple of weeks working on Cascade, so here’s a recap of what’s changed. One of the biggest additions has been the social system. Cascade now has proper user profiles with osu! stats, badges, beatmaps and mapping activity. You can search for other mappers, add friends, see who’s online and send private messages. I’ve also added replies, reactions, GIFs, notifications and privacy settings. Another thing I’ve been working on is mapping statistics. Cascade now tracks how much time you actually spend mapping, including individual maps and difficulties, playtesting, and other editing activity. There’s also an activity calendar on your profile. More recently, I’ve been focusing on making Cascade feel more like a proper desktop application. The main menu has been redesigned around osu!lazer, including new animations, a new logo, intro/outro sequences and improved scaling. There’s also a new Graphics tab with fullscreen, borderless and windowed modes, as well as FPS limiting. The editor has received some improvements too: A floating map overview inspired by Malody A dedicated playtest button Better audio time-stretching when slowing down songs Customizable export locations Settings search and shortcut conflict detection Various UI improvements and fixes I’ve also spent quite a bit of time on performance and stability, especially with larger map libraries, collaborative editing and the desktop app. There’s still a lot I want to improve, but I’m pretty happy with how Cascade has been progressing lately. Thanks to everyone who’s been trying it out and giving feedback!", "repo": "https://github.com/sheepexx/cascade", "demo": "https://cascade.sheepex.net/"}, {"ship_num": 2, "ts": "2026-09-28T11:54:50Z", "hours": 2.0, "multiplier": 12.33, "payout": 25, "blessing": "neutral", "text": "This update is all about making Cascade feel more polished and consistent. I unified every dropdown across the app, added new settings for original map metadata, hold-to-confirm timing and background parallax, and improved the HUD editor with a timeline scrubber and more reliable previews. The desktop app also now asks before closing.", "repo": "https://github.com/sheepexx/cascade", "demo": "https://cascade.sheepex.net/"}, {"ship_num": 3, "ts": "2026-09-26T18:42:10Z", "hours": 25.0, "multiplier": 8.56, "payout": 86, "blessing": "neutral", "text": "This update is mostly about making playtesting feel like the real game and making it easier to share your maps. The biggest change is the playtest. I rebuilt it on osu!mania’s actual rules, so hold note tails, note lock, timing and offsets now behave the way they do in osu!. On top of that there’s a new HUD editor: your map plays on autoplay while you click and drag anything on screen to move or resize it. Scroll speed and audio offset moved in there too, so the playtest settings are a lot less cluttered now. I also added Map Cards. With one click you get a clean image of your map with its MSD, skillsets, BPM, length and note stats, ready to post on Discord or anywhere else. There’s also a skillset graph under the timeline now that shows which skillset makes each part of the song hard, so you can see where a map spikes without playing it. There are a bunch of smaller changes too: Malody charts can be opened and exported, hitsounds can be copied onto every difficulty at once, there’s a colourblind-friendly lane colour option, keybinds work like osu!stable so you just type your keys in order, and the whole editor is now translated into German, Russian, Portuguese and Chinese. You can try it here: https://cascade.sheepex.net", "repo": "https://github.com/sheepexx/cascade", "demo": "https://cascade.sheepex.net/"}]...
|
[{"post_id": 82756, "ts": "202 [{"post_id": 82756, "ts": "2026-10-25T19:02:32Z", "hours": 9.1194, "text": "Been working on quite a few things lately, especially the overall look and feel of Cascade. The main menu has been reworked to feel more like osu!lazer, with new animations, an intro/outro and a new logo. I’ve also added fullscreen support for dekstop versions, graphics settings and customizable export locations. The editor now has a better map overview, a playtest button and improved audio stretching. There’s also a settings search, better messaging with GIFs and reactions, and a bunch of performance improvements and bug fixes. Still plenty more to work on!"}, {"post_id": 79533, "ts": "2026-10-14T14:21:22Z", "hours": 2.03, "text": "I changed the design language, to a more professional, simpler one. It using less system resources and its better for lower end devices."}, {"post_id": 79371, "ts": "2026-10-13T18:05:26Z", "hours": 12.2481, "text": "I worked on making new Social features, like profiles a messaging system and friend system."}, {"post_id": 74822, "ts": "2026-09-28T11:41:53Z", "hours": 1.9969, "text": "This update is mostly about polishing the interface and giving you more control over how Cascade looks and feels. One of the bigger changes is that every dropdown in Cascade now uses the same custom menu instead of mixing Cascade’s UI with native operating system selects. This affected quite a few places: dan ladders and keymodes, skins, Discord presence, collaborator roles, pack creation, batch timing, audio output, shared map difficulties and even the admin sorting menus. The dropdown component itself also got more capable. Menus can now have grouped sections, which is used to separate built-in playtest skin presets from your saved skins, and options can be shown as unavailable without completely hiding them. For example, an unsupported exclusive audio mode can still be displayed so you know the option exists, just without being able to select it. Dropdowns also behave better inside panels now. Some menus, especially ones opened from the HUD editor, could previously end up rendering underneath the panel they belonged to and look like an empty menu. They now use the proper UI layer, so menus always appear above panels while still staying underneath things like the command palette. There are three new interface settings as well. You can now tell Cascade to prefer a map’s original title and artist instead of the romanised metadata. If an osu! map contains both versions, Cascade will use the original script in the editor header, project list, now playing card and Discord Rich Presence. Maps that only have one version of their metadata behave exactly as before, and this doesn’t change anything stored in or exported with the map. The hold-to-confirm duration is customizable now too. Destructive actions previously always required holding for 750ms; you can now choose anything from 200ms up to 3 seconds depending on how quickly or carefully you want those controls to react. There’s also a new parallax strength setting for Cascade’s backgrounds. 100% gives you the movement Cascade had before, while 0% keeps the background completely still. You can also choose anything in between if you like the effect but want it to be more subtle. The HUD editor got another small usability upgrade with a proper timeline scrubber. You can drag through the song and quickly preview the HUD at any point in the map instead of having to wait for the autoplay to reach it. Seeking also keeps the full chart context intact, so things like the density graph and note count don’t suddenly change just because you’ve jumped further into the song. The HUD preview itself is more predictable now as well. Its autoplay always runs perfectly regardless of your normal humanized autoplay settings, impossible autoplay situations are ignored instead of being counted as misses, and combo and accuracy stop changing while you’re actively moving HUD elements around. And finally, the desktop app now asks before closing. Both the Exit button on the start screen and the Exit action in the command palette show the same confirmation dialog Cascade already uses for other destructive actions. Confirming still uses the normal fade-out and menu music transition, but an accidental click can’t immediately close the app anymore. You can try it here: https://cascade.sheepex.net"}, {"post_id": 74124, "ts": "2026-09-26T18:33:33Z", "hours": 24.71, "text": "Hello! I worked on Cascade a lot, mostly on playtesting and on sharing maps. The biggest change is the playtest. I rebuilt it on osu!mania’s actual rules, so hold note tails, note lock and timing now behave like in the real game. I also added a HUD editor: the map plays on autoplay and you click and drag anything on screen to move or resize it. Scroll speed and offsets live there now too, which cleaned up the settings a lot. I also made “Map Cards”. You get an image of your map with its MSD, skillsets, BPM and other stats that you can post anywhere. There’s also a skillset graph under the timeline now, so you can see which skillset makes each part of the song hard. Smaller stuff: Malody charts can be opened and exported hitsounds can be copied onto every difficulty at once a colourblind-friendly lane colour option keybinds work like osu!stable, so you just type your keys in order the whole editor is translated into German, Russian, Portuguese and Chinese Try it here: https://cascade.sheepex.net"}]...
|
Title: Cascade by @sheepex_ | Stardance
Devlogs:
Title: Cascade by @sheepex_ | Stardance
Devlogs:
Hello! I worked on Cascade a lot, mostly on playtesting and on sharing maps. The biggest change is the playtest. I rebuilt it on osu!mania’s actual rules, so hold note tails, note lock and timing now behave like in the real game. I also added a HUD editor: the map plays on autoplay and you click and drag anything on screen to move or resize it. Scroll speed and offsets live there now too, which cleaned up the settings a lot. I also made “Map Cards”. You get an image of your map with its MSD, skillsets, BPM and other stats that you can post anywhere. There’s also a skillset graph under the timeline now, so you can see which skillset makes each part of the song hard. Smaller stuff: Malody charts can be opened and exported hitsounds can be copied onto every difficulty at once a colourblind-friendly lane colour option keybinds work like osu!stable, so you just type your keys in order the whole editor is translated into German, Russian, Portuguese and Chinese Try it here: https://cascade.sheepex.net
This update is mostly about polishing the interface and giving you more control over how Cascade looks and feels. One of the bigger changes is that every dropdown in Cascade now uses the same custom menu instead of mixing Cascade’s UI with native operating system selects. This affected quite a few places: dan ladders and keymodes, skins, Discord presence, collaborator roles, pack creation, batch timing, audio output, shared map difficulties and even the admin sorting menus. The dropdown component itself also got more capable. Menus can now have grouped sections, which is used to separate built-in playtest skin presets from your saved skins, and options can be shown as unavailable without completely hiding them. For example, an unsupported exclusive audio mode can still be displayed so you know the option exists, just without being able to select it. Dropdowns also behave better inside panels now. Some menus, especially ones opened from the HUD editor, could previously end up rendering underneath the panel they belonged to and look like an empty menu. They now use the proper UI layer, so menus always appear above panels while still staying underneath things like the command palette. There are three new interface settings as well. You can now tell Cascade to prefer a map’s original title and artist instead of the romanised metadata. If an osu! map contains both versions, Cascade will use the original script in the editor header, project list, now playing card and Discord Rich Presence. Maps that only have one version of their metadata behave exactly as before, and this doesn’t change anything stored in or exported with the map. The hold-to-confirm duration is customizable now too. Destructive actions previously always required holding for 750ms; you can now choose anything from 200ms up to 3 seconds depending on how quickly or carefully you want those controls to react. There’s also a new parallax strength setting for Cascade’s backgrounds. 100% gives you the movement Cascade had before, while 0% keeps the background completely still. You can also choose anything in between if you like the effect but want it to be more subtle. The HUD editor got another small usability upgrade with a proper timeline scrubber. You can drag through the song and quickly preview the HUD at any point in the map instead of having to wait for the autoplay to reach it. Seeking also keeps the full chart context intact, so things like the density graph and note count don’t suddenly change just because you’ve jumped further into the song. The HUD preview itself is more predictable now as well. Its autoplay always runs perfectly regardless of your normal humanized autoplay settings, impossible autoplay situations are ignored instead of being counted as misses, and combo and accuracy stop changing while you’re actively moving HUD elements around. And finally, the desktop app now asks before closing. Both the Exit button on the start screen and the Exit action in the command palette show the same confirmation dialog Cascade already uses for other destructive actions. Confirming still uses the normal fade-out and menu music transition, but an accidental click can’t immediately close the app anymore. You can try it here: https://cascade.sheepex.net
I worked on making new Social features, like profiles a messaging system and friend system.
I changed the design language, to a more professional, simpler one. It using less system resources and its better for lower end devices.
Been working on quite a few things lately, especially the overall look and feel of Cascade. The main menu has been reworked to feel more like osu!lazer, with new animations, an intro/outro and a new logo. I’ve also added fullscreen support for dekstop versions, graphics settings and customizable export locations. The editor now has a better map overview, a playtest button and improved audio stretching. There’s also a settings search, better messaging with GIFs and reactions, and a bunch of performance improvements and bug fixes. Still plenty more to work on!
Ships:
This update is mostly about making playtesting feel like the real game and making it easier to share your maps. The biggest change is the playtest. I rebuilt it on osu!mania’s actual rules, so hold note tails, note lock, timing and offsets now behave the way they do in osu!. On top of that there’s a new HUD editor: your map plays on autoplay while you click and drag anything on screen to move or resize it. Scroll speed and audio offset moved in there too, so the playtest settings are a lot less cluttered now. I also added Map Cards. With one click you get a clean image of your map with its MSD, skillsets, BPM, length and note stats, ready to post on Discord or anywhere else. There’s also a skillset graph under the timeline now that shows which skillset makes each part of the song hard, so you can see where a map spikes without playing it. There are a bunch of smaller changes too: Malody charts can be opened and exported, hitsounds can be copied onto every difficulty at once, there’s a colourblind-friendly lane colour option, keybinds work like osu!stable so you just type your keys in order, and the whole editor is now translated into German, Russian, Portuguese and Chinese. You can try it here: https://cascade.sheepex.net
This update is all about making Cascade feel more polished and consistent. I unified every dropdown across the app, added new settings for original map metadata, hold-to-confirm timing and background parallax, and improved the HUD editor with a timeline scrubber and more reliable previews. The desktop app also now asks before closing.
It’s been a pretty busy couple of weeks working on Cascade, so here’s a recap of what’s changed. One of the biggest additions has been the social system. Cascade now has proper user profiles with osu! stats, badges, beatmaps and mapping activity. You can search for other mappers, add friends, see who’s online and send private messages. I’ve also added replies, reactions, GIFs, notifications and privacy settings. Another thing I’ve been working on is mapping statistics. Cascade now tracks how much time you actually spend mapping, including individual maps and difficulties, playtesting, and other editing activity. There’s also an activity calendar on your profile. More recently, I’ve been focusing on making Cascade feel more like a proper desktop application. The main menu has been redesigned around osu!lazer, including new animations, a new logo, intro/outro sequences and improved scaling. There’s also a new Graphics tab with fullscreen, borderless and windowed modes, as well as FPS limiting. The editor has received some improvements too: A floating map overview inspired by Malody A dedicated playtest button Better audio time-stretching when slowing down songs Customizable export locations Settings search and shortcut conflict detection Various UI improvements and fixes I’ve also spent quite a bit of time on performance and stability, especially with larger map libraries, collaborative editing and the desktop app. There’s still a lot I want to improve, but I’m pretty happy with how Cascade has been progressing lately. Thanks to everyone who’s been trying it out and giving feedback!...
|
1793008145.9285038
|
1793094545.9285038
|
|
54063
|
TermTab by @bhlcusd | Stardance
|
bhlcusd
|
1
|
15.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-11T23:29:27Z", "hours": 15.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "TermTab GUIs are boring; try a terminal window instead! Quick Start Explore TermTab: Try It Now! Features Clean & Modern Design - Dynamic scaling with dark mode support inspired by Apple Terminal’s Basic theme. Search the Web - use goto and search to navigate to a website or search with your favorite search engine, respectively. Get Info - use loc and info to fetch info about your current IP address or US zip code or information about your session, respectively. Check the Weather - use weather (and any subsequent flags) to fetch the current and forecasted weather for your estimated location or US zip code. Technicals Built on Svelte - Chosen for its highly interactive design, Svelte helps remove the tedious DOM manipulation that comes with basic JavaScript and HTML. With its direct implementation of TypeScript, Svelte made it easy to develop the website without the HTML and CSS getting in the way. TailwindCSS - TailwindCSS was chosen for most of the styling because it provided and easy, plug-and-play solution for this simple application. It streamlined the codebase by removing verbose CSS. Custom TypeScript - The most substantial aspects of this project is the custom TypeScript implementation to abstract the terminal-DOM manipulations from the commands. Using Vite’s import.meta.glob , the website dynamically fetches the commands from $lib/terminal/commands , making it easy for new commands to be created or altered. However, much of the work was dedicated to developing the Terminal class outlined in the next section. The Terminal Seperating the Frontend and Backend - The bulk of the terminal’s logic resides in the Terminal class. It provides functions for commands to “print” to the console (appends the information as unique “lines” in a list), acting similar to any other terminal I/O program. Using TypeScript - One of the most useful features that comes with TypeScript is the ability to describe how objects can behave relative to each other. For example, a Command class is created as the “blueprint” for any terminal command and has methods for executing and providing help. By not hard-coding the commands directly in the terminal, users can create commands to supplement the default commands. Commands Vary in Complexity - Although most of the commands are quite straightforward, some are more complex and use the user’s computer to complete its task. Take for example the weather command. It uses OpenMeteo’s API to fetch the weather, but that API requires longitude and latitude coordinates. To resolve this issue, the loc command was created to use the user’s estimated location fetched from freeipapi.com or, using a US zip code, zippopotam.us . Then, the information is converted into a user-friendly output, with the number of forecasted days being controlled by the user. All Local - Notably, TermTab does not have any centeralized server to phone home to. Instead, the entire website is run “locally” by the user’s browser. Since there is no need to host a centeralized database, TermTab is shipped like any other static webpage (just with some JS/TS on top). Acknowledgements Svelte & SvelteKit Documentation - Assisted in the setup process and converting it into a static webpage using adapter-static and information about dynamically importing TypeScript files. TailwindCSS Documentation - Assisted in finding corresponding CSS tags", "repo": "https://github.com/brandonfglx/TermTab", "demo": "https://brandonfglx.github.io/TermTab/"}]...
|
[{"post_id": 66007, "ts": "202 [{"post_id": 66007, "ts": "2026-09-11T15:00:13Z", "hours": 0.3653, "text": "Devlog 5: Get Those Minutes Whoops, I didn’t configure Svelte’s adapter-static correctly and Hack Club is punishing me for it! Apparently, the website detector requires it to be completely static with an index.html . The only fix was this one line:"}, {"post_id": 65767, "ts": "2026-09-11T03:57:24Z", "hours": 1.605, "text": "Devlog 4: The Final Touches After a little more refinement (and an embarassingly long time for a README), I finally got TermTab in a polished enough state for a ship! Here’s a GIF demo-ing TermTab:"}, {"post_id": 65210, "ts": "2026-09-10T05:41:07Z", "hours": 5.0369, "text": "Devlog 3: Wrapping Things Up After a few more hours, I finally integrated a stable production-ready API to TermTab. Right now, there are two new commands: loc and weather . Loc uses the user’s local IP address (from freeipapi.com) or a provided US zip code (uses zippopotam.us) to find coordinates, city, state, and country name (and IP address, if applicable). I also rewrote the search command to allow the user to use their preferred search engine (and incorporated the ask command into it). Now, you can search YouTube, Wikipedia, and DuckDuckGo! I am considering on shipping TermTab as it is after finishing up on the rest of the project (like README.md)."}, {"post_id": 63849, "ts": "2026-09-07T20:35:26Z", "hours": 4.1411, "text": "Devlog 2: What Makes a Terminal a Terminal? After a few hours of work, I was able to rewrite how commands work for TermTab. Before, commands were hardcoded into the execute() method in the Terminal class, which itself was integrated as part of the Terminal component. Now, the Terminal class is its own svelte.ts file and commands are fetched dynamically using Vite’s import.meta.glob() . I also added/modified a few commands including: time , info , and help . help now uses a dynamic fetching system, with each command managing its own help menu with command parameters as a string[] . As before, if you have any suggestions, feel free to comment!"}, {"post_id": 62622, "ts": "2026-09-06T02:51:22Z", "hours": 3.7725, "text": "Devlog 1: Making Something Familiar Just began on my second project for Stardance. I started very late, but I want to complete this and the basic OS missions before Stardance is over. Currently, I created a class in TypeScript to manage input and output and implemented a few programs. The input is directly taken from DOM listeners instead of an element because some functionality, like ctrl+c wouldn’t work with basic input. Besides, the custom code wasn’t a lot, with most of it dedicated to parse() which uses a simple switch statement. Currently, there isn’t much in the way of interactivity, but I plan on implementing a few programs: weather (fetches current weather based on IP address or inputed zip code/city) calc (currently similar to eval(), but likely a custom dual stack calculator) snake (what can I even say?) If you have another ideas for programs, feel free to share/comment."}]...
|
Title: TermTab by @bhlcusd | Stardance
Devlogs:
D Title: TermTab by @bhlcusd | Stardance
Devlogs:
Devlog 1: Making Something Familiar Just began on my second project for Stardance. I started very late, but I want to complete this and the basic OS missions before Stardance is over. Currently, I created a class in TypeScript to manage input and output and implemented a few programs. The input is directly taken from DOM listeners instead of an element because some functionality, like ctrl+c wouldn’t work with basic input. Besides, the custom code wasn’t a lot, with most of it dedicated to parse() which uses a simple switch statement. Currently, there isn’t much in the way of interactivity, but I plan on implementing a few programs: weather (fetches current weather based on IP address or inputed zip code/city) calc (currently similar to eval(), but likely a custom dual stack calculator) snake (what can I even say?) If you have another ideas for programs, feel free to share/comment.
Devlog 2: What Makes a Terminal a Terminal? After a few hours of work, I was able to rewrite how commands work for TermTab. Before, commands were hardcoded into the execute() method in the Terminal class, which itself was integrated as part of the Terminal component. Now, the Terminal class is its own svelte.ts file and commands are fetched dynamically using Vite’s import.meta.glob() . I also added/modified a few commands including: time , info , and help . help now uses a dynamic fetching system, with each command managing its own help menu with command parameters as a string[] . As before, if you have any suggestions, feel free to comment!
Devlog 3: Wrapping Things Up After a few more hours, I finally integrated a stable production-ready API to TermTab. Right now, there are two new commands: loc and weather . Loc uses the user’s local IP address (from freeipapi.com) or a provided US zip code (uses zippopotam.us) to find coordinates, city, state, and country name (and IP address, if applicable). I also rewrote the search command to allow the user to use their preferred search engine (and incorporated the ask command into it). Now, you can search YouTube, Wikipedia, and DuckDuckGo! I am considering on shipping TermTab as it is after finishing up on the rest of the project (like README.md).
Devlog 4: The Final Touches After a little more refinement (and an embarassingly long time for a README), I finally got TermTab in a polished enough state for a ship! Here’s a GIF demo-ing TermTab:
Devlog 5: Get Those Minutes Whoops, I didn’t configure Svelte’s adapter-static correctly and Hack Club is punishing me for it! Apparently, the website detector requires it to be completely static with an index.html . The only fix was this one line:
Ships:
TermTab GUIs are boring; try a terminal window instead! Quick Start Explore TermTab: Try It Now! Features Clean & Modern Design - Dynamic scaling with dark mode support inspired by Apple Terminal’s Basic theme. Search the Web - use goto and search to navigate to a website or search with your favorite search engine, respectively. Get Info - use loc and info to fetch info about your current IP address or US zip code or information about your session, respectively. Check the Weather - use weather (and any subsequent flags) to fetch the current and forecasted weather for your estimated location or US zip code. Technicals Built on Svelte - Chosen for its highly interactive design, Svelte helps remove the tedious DOM manipulation that comes with basic JavaScript and HTML. With its direct implementation of TypeScript, Svelte made it easy to develop the website without the HTML and CSS getting in the way. TailwindCSS - TailwindCSS was chosen for most of the styling because it provided and easy, plug-and-play solution for this simple application. It streamlined the codebase by removing verbose CSS. Custom TypeScript - The most substantial aspects of this project is the custom TypeScript implementation to abstract the terminal-DOM manipulations from the commands. Using Vite’s import.meta.glob , the website dynamically fetches the commands from $lib/terminal/commands , making it easy for new commands to be created or altered. However, much of the work was dedicated to developing the Terminal class outlined in the next section. The Terminal Seperating the Frontend and Backend - The bulk of the terminal’s logic resides in the Terminal class. It provides functions for commands to “print” to the console (appends the information as unique “lines” in a list), acting similar to any other terminal I/O program. Using TypeScript - One of the most useful features that comes with TypeScript is the ability to describe how objects can behave relative to each other. For example, a Command class is created as the “blueprint” for any terminal command and has methods for executing and providing help. By not hard-coding the commands directly in the terminal, users can create commands to supplement the default commands. Commands Vary in Complexity - Although most of the commands are quite straightforward, some are more complex and use the user’s computer to complete its task. Take for example the weather command. It uses OpenMeteo’s API to fetch the weather, but that API requires longitude and latitude coordinates. To resolve this issue, the loc command was created to use the user’s estimated location fetched from freeipapi.com or, using a US zip code, zippopotam.us . Then, the information is converted into a user-friendly output, with the number of forecasted days being controlled by the user. All Local - Notably, TermTab does not have any centeralized server to phone home to. Instead, the entire website is run “locally” by the user’s browser. Since there is no need to host a centeralized database, TermTab is shipped like any other static webpage (just with some JS/TS on top). Acknowledgements Svelte & SvelteKit Documentation - Assisted in the setup process and converting it into a static webpage using adapter-static and information about dynamically importing TypeScript files. TailwindCSS Documentation - Assisted in finding corresponding CSS tags...
|
1793008147.875222
|
1793094547.875222
|
|
54069
|
My personal site :) by @Abis-Aman | Stardance
|
Abis-Aman
|
1
|
2.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-19T10:50:10Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "this is my first every that is made with my taste i am thinking that my web eventhough all in one web it has all the requirmants like my web is has the home about and projects that all and the when clicked the page moves to the destination with a smooth glid", "repo": "https://github.com/AbisAman-Dev/My-Personal-Site", "demo": "https://abisaman-dev.github.io/My-Personal-Site/"}]...
|
[{"post_id": 70547, "ts": "202 [{"post_id": 70547, "ts": "2026-09-19T10:47:47Z", "hours": 0.8708, "text": "**Dev log:**so after 2 hours of codding i thought of ending the project as i would only have this lap for two days"}, {"post_id": 70192, "ts": "2026-09-18T17:43:57Z", "hours": 1.1756, "text": "#Devlog-1 so i started doing the html and now only the css part is left and some little html"}]...
|
Title: My personal site :) by @Abis-Aman | Stardan Title: My personal site :) by @Abis-Aman | Stardance
Devlogs:
#Devlog-1 so i started doing the html and now only the css part is left and some little html
**Dev log:**so after 2 hours of codding i thought of ending the project as i would only have this lap for two days
Ships:
this is my first every that is made with my taste i am thinking that my web eventhough all in one web it has all the requirmants like my web is has the home about and projects that all and the when clicked the page moves to the destination with a smooth glid...
|
1793008149.0976737
|
1793094549.0976737
|
|
2879
|
productive home by @Tony1292 | Stardance
|
Tony1292
|
1
|
10.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-28T01:07:48Z", "hours": 10.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I have made a website that solves most of my family problems. The point is that you don’t forget anything and the whole family works together. This website will help your family. This was such a helpful project becasue it shows that coding and being on the computer in not a waste of time as my family says but can solve real promblems.", "repo": "https://github.com/tonymurilloambriz-bit/My-personal-webiste", "demo": "https://hom22.oneapp.dev/"}]...
|
[{"post_id": 74694, "ts": "202 [{"post_id": 74694, "ts": "2026-09-28T00:42:32Z", "hours": 0.5506, "text": "I have finished my project I have finished the chores and the shopping list section of the website. I have really enjoyed this project."}, {"post_id": 47188, "ts": "2026-08-14T22:20:39Z", "hours": 1.1003, "text": "I have made some more changes on the colors but it will be hard to make the chores list an shopping list. Since I decided to make all the apps. The reason why it took so long was that I did not save the code and will big brain me lost the code."}, {"post_id": 7218, "ts": "2026-06-12T01:33:32Z", "hours": 1.3825, "text": "I was able to make the website look more modern and overall better looking. Before I did this I accidentally deleted the tab where I had my code and I did not save the code."}, {"post_id": 5160, "ts": "2026-06-08T20:54:21Z", "hours": 2.7561, "text": "I made the chore app with Lovable.AI and put it into the html file so know when you click on the chore menu it takes you there. The next step is to add a button in the Lovable app so you can go back to the main menu."}, {"post_id": 4532, "ts": "2026-06-07T21:29:51Z", "hours": 1.1172, "text": "So I made the main home page with html but the apps inside the website where made by me using lovable.AI. So the main website is all most ready."}, {"post_id": 3751, "ts": "2026-06-06T20:00:00Z", "hours": 1.0525, "text": "I got the button to work for one of the menu icons. But now I know how to do the rest. So now when you click on the chores word, it brings you to the chores page."}, {"post_id": 3205, "ts": "2026-06-06T01:11:34Z", "hours": 1.3958, "text": "I got the the buttons to work so when you click the button it brings you to another page."}, {"post_id": 2978, "ts": "2026-06-05T22:02:21Z", "hours": 1.0089, "text": "So I am making a website where the user lists what is needed in the house like food or basic supplies. So when the user runs out of the supplies they will mark it as needed. there will also be a section for chores so you can add the family and each person has chores they have to complete before the day ends."}]...
|
Title: productive home by @Tony1292 | Stardance
D Title: productive home by @Tony1292 | Stardance
Devlogs:
So I am making a website where the user lists what is needed in the house like food or basic supplies. So when the user runs out of the supplies they will mark it as needed. there will also be a section for chores so you can add the family and each person has chores they have to complete before the day ends.
I got the the buttons to work so when you click the button it brings you to another page.
I got the button to work for one of the menu icons. But now I know how to do the rest. So now when you click on the chores word, it brings you to the chores page.
So I made the main home page with html but the apps inside the website where made by me using lovable.AI. So the main website is all most ready.
I made the chore app with Lovable.AI and put it into the html file so know when you click on the chore menu it takes you there. The next step is to add a button in the Lovable app so you can go back to the main menu.
I was able to make the website look more modern and overall better looking. Before I did this I accidentally deleted the tab where I had my code and I did not save the code.
I have made some more changes on the colors but it will be hard to make the chores list an shopping list. Since I decided to make all the apps. The reason why it took so long was that I did not save the code and will big brain me lost the code.
I have finished my project I have finished the chores and the shopping list section of the website. I have really enjoyed this project.
Ships:
I have made a website that solves most of my family problems. The point is that you don’t forget anything and the whole family works together. This website will help your family. This was such a helpful project becasue it shows that coding and being on the computer in not a waste of time as my family says but can solve real promblems....
|
1793008149.973047
|
1793094549.973047
|
|
40776
|
Generic Functional Programming Language by @Yoyodo Generic Functional Programming Language by @Yoyodotpy | Stardance...
|
Yoyodotpy
|
1
|
17.51
|
274
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-12T20:18:20Z", "hours": 17.0, "multiplier": 15.69, "payout": 274, "blessing": "neutral", "text": "This is a simple interpretted functional programming language. Originally, I intended for it to be compiled, but after dealing with llvm for a few days I gave up on this and just made it be interpretted. I struggled a lot with making the language not look incredibly ugly as I was designing it, but in the end I managed to make it look half decent. It also only works in the cli and has no options beyond just putting the file path to run a program. Despite all that, I think that this went pretty well. It was my first time trying to make a language, and I learnt a whole lot about the backend and design of programming languages (and gained a couple more strong opinions about programming syntax). It ended up being functional in both ways, and capable of making and running simple programs. I’ll probably try to make a new language in the future, with everything I’ve learnt.", "repo": "https://github.com/Yoyodotpy/programming-language", "demo": "https://github.com/Yoyodotpy/programming-language/releases/latest"}]...
|
[{"post_id": 67443, "ts": "202 [{"post_id": 67443, "ts": "2026-09-13T15:32:25Z", "hours": 0.5092, "text": "I added help text and changed the demo folder to be called examples."}, {"post_id": 66866, "ts": "2026-09-12T20:04:18Z", "hours": 1.7833, "text": "I got this ready to ship because I lost interest in this, but i might make another project in the remaining time in Stardance. Either way, i finished the README.md, added a release with prebuilt binaries, and made a demo using asciinema."}, {"post_id": 40916, "ts": "2026-08-04T19:04:54Z", "hours": 2.2236, "text": "llvm is pain it compiles but it doesnt work i might just pivot and make it interpretted only, maybe have it transpile to scheme instead."}, {"post_id": 39809, "ts": "2026-08-03T01:30:00Z", "hours": 3.8047, "text": "I got started on making the compiler convert my language to LLVM IR code, and it genuinely sucks. I basically need to make my language un-functional itself into a primitive language, and I need to deal with the limits of my own language, golang, and C at the same time and it’s torture. I’m powering through though and I’m almost at a point where it’ll actually manage to compile my language."}, {"post_id": 38588, "ts": "2026-08-01T02:06:56Z", "hours": 3.6814, "text": "This is now technically a usable programming language! It can interpret code, and I even made a Fibonacci program. I spent most of the day making some basic primitives, alongside starting the standard library with things like true, false, or, and, not, nil, print, addition, multiplication, subtraction, division and more! Tomorrow I’ll set it up with LLVM and try my best to get it to actually compile. Wish me luck! Also, if any of you have ideas for how I can make the code less ugly, I would appreciate some advice."}, {"post_id": 37999, "ts": "2026-07-31T03:30:44Z", "hours": 3.1147, "text": "I pretty much finished the AST and I’m basically ready to start working on the interpretter."}, {"post_id": 37267, "ts": "2026-07-29T20:48:55Z", "hours": 2.8633, "text": "I finalized the lexer and I’m almost done with generating the AST, so nearly done with the boring bit! I also made some very basic test programs."}]...
|
Title: Generic Functional Programming Language by Title: Generic Functional Programming Language by @Yoyodotpy | Stardance
Devlogs:
I finalized the lexer and I’m almost done with generating the AST, so nearly done with the boring bit! I also made some very basic test programs.
I pretty much finished the AST and I’m basically ready to start working on the interpretter.
This is now technically a usable programming language! It can interpret code, and I even made a Fibonacci program. I spent most of the day making some basic primitives, alongside starting the standard library with things like true, false, or, and, not, nil, print, addition, multiplication, subtraction, division and more! Tomorrow I’ll set it up with LLVM and try my best to get it to actually compile. Wish me luck! Also, if any of you have ideas for how I can make the code less ugly, I would appreciate some advice.
I got started on making the compiler convert my language to LLVM IR code, and it genuinely sucks. I basically need to make my language un-functional itself into a primitive language, and I need to deal with the limits of my own language, golang, and C at the same time and it’s torture. I’m powering through though and I’m almost at a point where it’ll actually manage to compile my language.
llvm is pain it compiles but it doesnt work i might just pivot and make it interpretted only, maybe have it transpile to scheme instead.
I got this ready to ship because I lost interest in this, but i might make another project in the remaining time in Stardance. Either way, i finished the README.md, added a release with prebuilt binaries, and made a demo using asciinema.
I added help text and changed the demo folder to be called examples.
Ships:
This is a simple interpretted functional programming language. Originally, I intended for it to be compiled, but after dealing with llvm for a few days I gave up on this and just made it be interpretted. I struggled a lot with making the language not look incredibly ugly as I was designing it, but in the end I managed to make it look half decent. It also only works in the cli and has no options beyond just putting the file path to run a program. Despite all that, I think that this went pretty well. It was my first time trying to make a language, and I learnt a whole lot about the backend and design of programming languages (and gained a couple more strong opinions about programming syntax). It ended up being functional in both ways, and capable of making and running simple programs. I’ll probably try to make a new language in the future, with everything I’ve learnt....
|
1793008151.3031917
|
1793094551.3031917
|
|
54108
|
Pantry_Scanner by @theodora | Stardance
|
theodora
|
1
|
20.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-13T17:11:38Z", "hours": 20.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Finally, I finished my first version of my pantry scanner. Due to camera quality, sometimes it can read the expiry date; sometimes it can’t, but I already tried my best to make it work What I actually built –Firmware on ESP32-CAM: press a button, it captures a photo and uploads it over WI-Fi – A local Python backend that reads the photo, tries OCR for the expiry date, attempts barcode decoding using an external API and saves everything to a database – A web dashboard showing every scanned item sorted by soonest-expiring first, with edit and remove buttons for fixing up anything the camera couldn’t capture The hard part The hardest part is to get the camera to read text and turn it into the dashboard. I went through extensive debugging, more than I have recorded in the devlog. Fixing the lens, dealing with blur, and looking at the barcode-decoding problem, it turned out the camera quality is the major issue. Next Step – Use a dedicated barcode scanner instead of relying on the camera –Create a fixed scanning stand using 3D printing for more consistent capture quality than hand positioning. – Attach a macro lens attachment for the camera to improve small print in OCR", "repo": "https://github.com/theodora-sin/pantry_scanner", "demo": ""}]...
|
[{"post_id": 67514, "ts": "202 [{"post_id": 67514, "ts": "2026-09-13T17:08:53Z", "hours": 3.7453, "text": "Devlog 5: Finally, I finish my first version of my pantry scanner, due to camera quality, sometime it can read the expiry date, sometime it can’t, but I already try my best to make it work. I can’t film the whole process, but I try to snip a bit of how this camera actually work in screenshot and a video"}, {"post_id": 65995, "ts": "2026-09-11T14:43:02Z", "hours": 1.2389, "text": "Devlog 4: Today, I connected the front and back end; however, the camera quality wasn’t as good as I expected, and it couldn’t scan the barcode to retrieve the data. Now, I am rethinking how to retrieve the data and what the next step should be."}, {"post_id": 64241, "ts": "2026-09-08T14:30:46Z", "hours": 9.4747, "text": "Devlog3: ##Working on front end My front end is using Python as the main language, alongside html and css, the website look plain as I just built the basic version Next step: connect front end and back end"}, {"post_id": 59594, "ts": "2026-09-01T14:40:45Z", "hours": 1.7883, "text": "Devlog 2: This devlog, it records how the front end works. I use arduino IDE with coding language C+ to make the ESP32 Camera work, It can capture 1600x1200px, which is useful for the backend. The backend is used to store the captured picture and analyse the expiry date of the food."}, {"post_id": 57898, "ts": "2026-08-30T07:12:02Z", "hours": 3.9806, "text": "#Devlog 1: Hi, welcome to a hardware project devlog. In this project, I am creating a pantry scanner. I have drawn my schematic board and am soldering the PCB. I forgot to record my soldering part, but here is the overview of the project."}]...
|
Title: Pantry_Scanner by @theodora | Stardance
De Title: Pantry_Scanner by @theodora | Stardance
Devlogs:
#Devlog 1: Hi, welcome to a hardware project devlog. In this project, I am creating a pantry scanner. I have drawn my schematic board and am soldering the PCB. I forgot to record my soldering part, but here is the overview of the project.
Devlog 2: This devlog, it records how the front end works. I use arduino IDE with coding language C+ to make the ESP32 Camera work, It can capture 1600x1200px, which is useful for the backend. The backend is used to store the captured picture and analyse the expiry date of the food.
Devlog3: ##Working on front end My front end is using Python as the main language, alongside html and css, the website look plain as I just built the basic version Next step: connect front end and back end
Devlog 4: Today, I connected the front and back end; however, the camera quality wasn’t as good as I expected, and it couldn’t scan the barcode to retrieve the data. Now, I am rethinking how to retrieve the data and what the next step should be.
Devlog 5: Finally, I finish my first version of my pantry scanner, due to camera quality, sometime it can read the expiry date, sometime it can’t, but I already try my best to make it work. I can’t film the whole process, but I try to snip a bit of how this camera actually work in screenshot and a video
Ships:
Finally, I finished my first version of my pantry scanner. Due to camera quality, sometimes it can read the expiry date; sometimes it can’t, but I already tried my best to make it work What I actually built –Firmware on ESP32-CAM: press a button, it captures a photo and uploads it over WI-Fi – A local Python backend that reads the photo, tries OCR for the expiry date, attempts barcode decoding using an external API and saves everything to a database – A web dashboard showing every scanned item sorted by soonest-expiring first, with edit and remove buttons for fixing up anything the camera couldn’t capture The hard part The hardest part is to get the camera to read text and turn it into the dashboard. I went through extensive debugging, more than I have recorded in the devlog. Fixing the lens, dealing with blur, and looking at the barcode-decoding problem, it turned out the camera quality is the major issue. Next Step – Use a dedicated barcode scanner instead of relying on the camera –Create a fixed scanning stand using 3D printing for more consistent capture quality than hand positioning. – Attach a macro lens attachment for the camera to improve small print in OCR...
|
1793008152.4330242
|
1793094552.4330242
|
|
58952
|
My own site! by @kajamaniyograj | Stardance
|
kajamaniyograj
|
1
|
0.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-11T14:00:05Z", "hours": 0.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "i used ai but i tryed my best to complete this project", "repo": "https://github.com/kajamaniyograj-cyber/personal-site", "demo": "https://kajamaniyograj-cyber.github.io/personal-site"}]...
|
[{"post_id": 65448, "ts": "202 [{"post_id": 65448, "ts": "2026-09-10T16:15:50Z", "hours": 0.4186, "text": "added standoffs to hold the display in place. With this the project is finally complete(atleast i hope so:)"}]...
|
Title: My own site! by @kajamaniyograj | Stardance Title: My own site! by @kajamaniyograj | Stardance
Devlogs:
added standoffs to hold the display in place. With this the project is finally complete(atleast i hope so:)
Ships:
i used ai but i tryed my best to complete this project...
|
1793008153.5667408
|
1793094553.5667408
|
|
54137
|
Telegram assistent bot by @kdenis | Stardance
|
kdenis
|
1
|
18.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-24T14:27:28Z", "hours": 18.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "What did you make? I built a simple Telegram bot that helps users track their daily activities (like sleep, workouts, or study time) and generates visual weekly charts using matplotlib to track progress over time. What was challenging? The most challenging part was understanding how to implement multi-step input flows using conversation handlers (like chaining prompts for logging data) and structuring the memory logic to track user activities dynamically over a week without needing a heavy database setup. What are you proud of? I am proud that I successfully learned Python from scratch while building this project! I used AI purely as a tutor—to explain concepts and guide me—rather than writing the code for me, meaning I wrote and understood every line myself. I am also proud to have mastered building fully functional Telegram bots, dynamic chart rendering, and asynchronous handling. What should people know so they can test your project? Simply open Telegram, search for @MySimpleAssistentBot (or use the link https://t.me/MySimpleAssistentBot ( https://t.me/MySimpleAssistentBot?utm_source=gemini )), and hit /start . You can use /log to record activities, /getstatistic to view your weekly graph, and /help for a list of all commands.", "repo": "https://github.com/deniska-design/telegram-bot", "demo": "https://t.me/MySimpleAssistentBot"}]...
|
[{"post_id": 69656, "ts": "202 [{"post_id": 69656, "ts": "2026-09-17T14:50:21Z", "hours": 7.7464, "text": "Devlog #4: Bot Architecture Cleanup, Persistence & Statistical Charts Hey everyone! Here’s an update on what I’ve been working on for my project over the past few days. 1. Weekly Activity Charts & Statistics The biggest new feature is visual weekly statistics! Now users can see a chart/graph of their activity over the course of the week. The Challenge: Storing data per user, per specific activity, and across each day of the week. The Solution: Kept it clean and simple using user_data . Persistence: Added persistent storage so data isn’t lost on restart. Honestly, I was mind-blown by how powerful Python persistence is—enabling this took literally just a couple of lines of code! 2. Refactoring & Modularizing Code I decided it was time to break up my codebase into multiple modules/files: Separation of Concerns: Initially, my architecture felt a bit messy—files knew too much about each other’s internal logic and were tightly coupled. I refactored the project so that each file and module is more autonomous and encapsulated. Troubleshooting: Splitting the code broke a few things at first, but after a bit of debugging, everything is working smoothly now. 3. User Experience & Input Validation I made several quality-of-life improvements to make the bot feel much more robust: Daily Log Reminders: Added a daily reminder prompting users to log their data for the day. (Note: Users just need to run /start once to initialize reminders and resets). Strict Input Validation: Added input filters. If a step requires a number, invalid text is rejected; if it asks to pick an activity, custom inputs are blocked. Python vs C++ appreciation: Coming from a C++ background, it constantly amazes me how complex user interactions and data handling can be written in just a few lines of Python! What’s Next? Writing a solid README.md Submitting the project!"}, {"post_id": 60747, "ts": "2026-09-03T09:55:40Z", "hours": 3.9458, "text": "Devlog #3: Changes In this update, I focused on refining the user metrics and implementing the automated weekly reset mechanism. Metric Adjustments: Removed water intake tracking from the list of monitored metrics. Simply put, I personally don’t track my daily water intake, so I decided to streamline the bot’s focus. Automated Weekly Reset: Spent most of my development time implementing a scheduled automated reset system that triggers every Saturday at 12:00 PM . While the underlying logic isn’t overly complex, working through it while learning Python took more time than expected. As shown in the screenshot, where test data entered before 11:31 AM was automatically cleared upon trigger. Learnings Logging ( logger.info ): Discovered how extremely valuable logger.info is for debugging scheduled jobs and tracking state transitions. Without proper logging, diagnosing automated execution bugs would have been significantly harder. Next Steps End-of-Week Summary Reporting: Implement logic to show results right before the automated reset occurs. Weekly Analytics & Graphs: Add visual statistics showing daily progress over the past week"}, {"post_id": 56574, "ts": "2026-08-28T11:53:37Z", "hours": 4.8633, "text": "DevLog #2: Switching Libraries Initially, I started building this bot using another library. However, I decided to rewrite the codebase using python-telegram-bot Why? python-telegram-bot is much more practical and scalable for complex, multi-step projects. Since I plan to build bigger features in the future, I figured it was best to learn and adopt a solid framework right now. I spent about an hour migrating my previous logic to PTB, and it was definitely worth it! New Features I added core bot commands and integrated custom reply keyboards: /help : Shows available commands. /log : Prompts you to pick an activity via a custom reply keyboard and log your stats. /analytic : Allows you to select an activity and view your current recorded progress. The trickiest part: was figuring out how to handle sequential user inputs : First function: Catches the initial command (e.g., /log ). Second function: Receives the chosen activity (e.g., Sport ), asks a follow-up question (e.g., “How long have you been doing this?” ) Third function: Takes the entered number/value and saves it to the selected activity state. fix-it list: Custom Prompts per Activity: Currently, selecting “Water” asks “How long have you been doing this?” instead of “How much water did you drink?” . I need to customize questions based on the activity type. Data Accumulation: Right now, logging a value overwrites context.user_data[activity] instead of adding to it. I will fix this so values accumulate properly over time. Weekly Reset: I need to implement an automated mechanism to reset tracking data every Saturday. Since fixing these remaining issues won’t take too much time, I’ll soon be ready to add new features. So let me know if you got any ideas in the comments below"}, {"post_id": 54384, "ts": "2026-08-25T11:25:35Z", "hours": 1.6775, "text": "DevLog #1: Learning Python Through Practice This is my first Python project. Instead of just memorizing syntax from tutorials, I decided to learn the language through hands-on practice. To test this approach, I’m building a simple Telegram Bot designed to track daily health habits. The Core Concept The bot will allow users to quickly log their daily metrics: Sleep duration Water intake Physical activity / workouts It stores this data and, upon clicking a button, generates a weekly summary analysis to track progress. Current Progress So far, I have: Created and structured the GitHub repository. Added essential initial files ( .gitignore , dependencies, configuration). Developed a basic, functional Telegram bot prototype. The Experiment This project isn’t meant to be a full-scale commercial application; it’s a personal challenge: Can I effectively master Python by building functional, real-world projects from scratch?"}]...
|
Title: Telegram assistent bot by @kdenis | Stardan Title: Telegram assistent bot by @kdenis | Stardance
Devlogs:
DevLog #1: Learning Python Through Practice This is my first Python project. Instead of just memorizing syntax from tutorials, I decided to learn the language through hands-on practice. To test this approach, I’m building a simple Telegram Bot designed to track daily health habits. The Core Concept The bot will allow users to quickly log their daily metrics: Sleep duration Water intake Physical activity / workouts It stores this data and, upon clicking a button, generates a weekly summary analysis to track progress. Current Progress So far, I have: Created and structured the GitHub repository. Added essential initial files ( .gitignore , dependencies, configuration). Developed a basic, functional Telegram bot prototype. The Experiment This project isn’t meant to be a full-scale commercial application; it’s a personal challenge: Can I effectively master Python by building functional, real-world projects from scratch?
DevLog #2: Switching Libraries Initially, I started building this bot using another library. However, I decided to rewrite the codebase using python-telegram-bot Why? python-telegram-bot is much more practical and scalable for complex, multi-step projects. Since I plan to build bigger features in the future, I figured it was best to learn and adopt a solid framework right now. I spent about an hour migrating my previous logic to PTB, and it was definitely worth it! New Features I added core bot commands and integrated custom reply keyboards: /help : Shows available commands. /log : Prompts you to pick an activity via a custom reply keyboard and log your stats. /analytic : Allows you to select an activity and view your current recorded progress. The trickiest part: was figuring out how to handle sequential user inputs : First function: Catches the initial command (e.g., /log ). Second function: Receives the chosen activity (e.g., Sport ), asks a follow-up question (e.g., “How long have you been doing this?” ) Third function: Takes the entered number/value and saves it to the selected activity state. fix-it list: Custom Prompts per Activity: Currently, selecting “Water” asks “How long have you been doing this?” instead of “How much water did you drink?” . I need to customize questions based on the activity type. Data Accumulation: Right now, logging a value overwrites context.user_data[activity] instead of adding to it. I will fix this so values accumulate properly over time. Weekly Reset: I need to implement an automated mechanism to reset tracking data every Saturday. Since fixing these remaining issues won’t take too much time, I’ll soon be ready to add new features. So let me know if you got any ideas in the comments below
Devlog #3: Changes In this update, I focused on refining the user metrics and implementing the automated weekly reset mechanism. Metric Adjustments: Removed water intake tracking from the list of monitored metrics. Simply put, I personally don’t track my daily water intake, so I decided to streamline the bot’s focus. Automated Weekly Reset: Spent most of my development time implementing a scheduled automated reset system that triggers every Saturday at 12:00 PM . While the underlying logic isn’t overly complex, working through it while learning Python took more time than expected. As shown in the screenshot, where test data entered before 11:31 AM was automatically cleared upon trigger. Learnings Logging ( logger.info ): Discovered how extremely valuable logger.info is for debugging scheduled jobs and tracking state transitions. Without proper logging, diagnosing automated execution bugs would have been significantly harder. Next Steps End-of-Week Summary Reporting: Implement logic to show results right before the automated reset occurs. Weekly Analytics & Graphs: Add visual statistics showing daily progress over the past week
Devlog #4: Bot Architecture Cleanup, Persistence & Statistical Charts Hey everyone! Here’s an update on what I’ve been working on for my project over the past few days. 1. Weekly Activity Charts & Statistics The biggest new feature is visual weekly statistics! Now users can see a chart/graph of their activity over the course of the week. The Challenge: Storing data per user, per specific activity, and across each day of the week. The Solution: Kept it clean and simple using user_data . Persistence: Added persistent storage so data isn’t lost on restart. Honestly, I was mind-blown by how powerful Python persistence is—enabling this took literally just a couple of lines of code! 2. Refactoring & Modularizing Code I decided it was time to break up my codebase into multiple modules/files: Separation of Concerns: Initially, my architecture felt a bit messy—files knew too much about each other’s internal logic and were tightly coupled. I refactored the project so that each file and module is more autonomous and encapsulated. Troubleshooting: Splitting the code broke a few things at first, but after a bit of debugging, everything is working smoothly now. 3. User Experience & Input Validation I made several quality-of-life improvements to make the bot feel much more robust: Daily Log Reminders: Added a daily reminder prompting users to log their data for the day. (Note: Users just need to run /start once to initialize reminders and resets). Strict Input Validation: Added input filters. If a step requires a number, invalid text is rejected; if it asks to pick an activity, custom inputs are blocked. Python vs C++ appreciation: Coming from a C++ background, it constantly amazes me how complex user interactions and data handling can be written in just a few lines of Python! What’s Next? Writing a solid README.md Submitting the project!
Ships:
What did you make? I built a simple Telegram bot that helps users track their daily activities (like sleep, workouts, or study time) and generates visual weekly charts using matplotlib to track progress over time. What was challenging? The most challenging part was understanding how to implement multi-step input flows using conversation handlers (like chaining prompts for logging data) and structuring the memory logic to track user activities dynamically over a week without needing a heavy database setup. What are you proud of? I am proud that I successfully learned Python from scratch while building this project! I used AI purely as a tutor—to explain concepts and guide me—rather than writing the code for me, meaning I wrote and understood every line myself. I am also proud to have mastered building fully functional Telegram bots, dynamic chart rendering, and asynchronous handling. What should people know so they can test your project? Simply open Telegram, search for @MySimpleAssistentBot (or use the link https://t.me/MySimpleAssistentBot ( https://t.me/MySimpleAssistentBot?utm_source=gemini )), and hit /start . You can use /log to record activities, /getstatistic to view your weekly graph, and /help for a list of all commands....
|
1793008154.4501352
|
1793094554.4501352
|
|
58974
|
Terminator by @Hamzacross100 | Stardance
|
Hamzacross100
|
1
|
1.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-13T11:53:21Z", "hours": 1.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Its Done After 2 Weeks", "repo": "https://github.com/Hamzacross/Terminator", "demo": "https://www.hamzacross100.online/projects/terminator"}]...
|
[{"post_id": 63603, "ts": "202 [{"post_id": 63603, "ts": "2026-09-07T15:09:21Z", "hours": 0.7156, "text": "Working On V1.0 The Main Working Version"}]...
|
Title: Terminator by @Hamzacross100 | Stardance
D Title: Terminator by @Hamzacross100 | Stardance
Devlogs:
Working On V1.0 The Main Working Version
Ships:
Its Done After 2 Weeks...
|
1793008155.543786
|
1793094555.543786
|
|
58991
|
HEY GUYS LOOK AT MY DOG by @fish-in-a-puddle | Sta HEY GUYS LOOK AT MY DOG by @fish-in-a-puddle | Stardance...
|
fish-in-a-puddle
|
1
|
7.0
|
44
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-12T23:54:00Z", "hours": 7.0, "multiplier": 6.45, "payout": 44, "blessing": "neutral", "text": "I have spent the past couple weeks, I have made a website where you can look at pictures of my dog. That’s it. Just my dog. I wanted the site to be pretty simple, as a fun practice project, and I’m very happy with how it’s turned out. One of 55 images is chosen with Javascript when the page loads and the corresponding caption is shown as well. The function repeats any time the “New Image” button is clicked. The “Share” button copies the URL of the site to the visitor’s clipboard. The hardest part of this project was probably getting the random image generation to work. I started by making a CSS class setting the background of an empty div as well as its height and width, but this did not work at all. I don’t know why, but I replaced the div with an image element and used Javascript to change the SRC of the element depending on the result of a random number generated in a variable. Most of the other elements were pretty easy to work with, though. I hope that someone enjoys this fun little project and the pictures of my dog!", "repo": "https://github.com/fish-in-a-puddle/heyguyslookatmydog", "demo": "https://fish-in-a-puddle.github.io/heyguyslookatmydog/"}]...
|
[{"post_id": 66251, "ts": "202 [{"post_id": 66251, "ts": "2026-09-11T23:34:31Z", "hours": 0.6711, "text": "Devlog 5 - Fixed a few formatting issues, added a custom paw print cursor and made a share button that copies the (currently nonexistent) URL to the visitor’s keyboard. I’m very happy with how this site is turning out, so this is probably the last devlog for the actual coding. Next I need to do some shipping prep - writing a README and making a demo page - but that’s probably only about half an hour of work, tops."}, {"post_id": 65582, "ts": "2026-09-10T20:24:54Z", "hours": 1.2819, "text": "Devlog 4 - Finished writing the JS for the image generating and added a “New Image” button so you don’t have to reload the page to see another picture. The project is getting close to done, but there’s one more thing I want to add - a paw print custom cursor. Last time I tried to add that on another project it didn’t work, but I’m hoping I’ll be able to figure it out."}, {"post_id": 65024, "ts": "2026-09-09T20:34:56Z", "hours": 1.8703, "text": "Devlog 3 - Ok, so all that time writing out the CSS classes may have been pointless…. After trying a lot of different stuff, I found that the only way I could get the image to show was by turning the original div into an img element and changing the src to match different files in Javascript. Oh well, live and learn and all that. I’m back in buisness with the old copy paste for now, though, as I use a switch() function to check the variable that stores the random number and the case/break parts are all very similar (save the src, caption and, you know, the number it checks for). I’m feeling fairly confident that this will work out, though. After I finish this part, I’ll add a button to change the picture and caption so you don’t have to reload the page every time."}, {"post_id": 64392, "ts": "2026-09-08T18:38:21Z", "hours": 0.6322, "text": "Devlog 2 - Hooray, I finished making the CSS classes. It was very boring as I had to copy paste basically the same thing fifty times and check and change the dimensions of the image each time but it’s finally done. Now that all the images exist for the website to choose from, I have to venture into Javascript to make the images change. Time to look up a random number generator tutorial and distort it beyond recognition"}, {"post_id": 63206, "ts": "2026-09-06T21:37:26Z", "hours": 2.3839, "text": "Devlog 1 - Today I started a project I’ve been thinking about for a while - a website to show the viewer pictures of my dog. When it’s done, it will show an image of my dog picked randomly with a corresponding caption. So far I have resized 56 photos to fit the page (which took about an hour) and created 14 of the 56 classes in CSS. Each class includes the image and dimensions to the image doesn’t get stretched. The idea is that the script will pick a random number and using a switch/case function will set the class of the image div as well as the appropriate caption depending on the number. I have basically no experience coding in Javascript except for the couple of hours I spent working on it for the WebOS challenge, so this project will be a good way to get some practice."}]...
|
Title: HEY GUYS LOOK AT MY DOG by @fish-in-a-puddl Title: HEY GUYS LOOK AT MY DOG by @fish-in-a-puddle | Stardance
Devlogs:
Devlog 1 - Today I started a project I’ve been thinking about for a while - a website to show the viewer pictures of my dog. When it’s done, it will show an image of my dog picked randomly with a corresponding caption. So far I have resized 56 photos to fit the page (which took about an hour) and created 14 of the 56 classes in CSS. Each class includes the image and dimensions to the image doesn’t get stretched. The idea is that the script will pick a random number and using a switch/case function will set the class of the image div as well as the appropriate caption depending on the number. I have basically no experience coding in Javascript except for the couple of hours I spent working on it for the WebOS challenge, so this project will be a good way to get some practice.
Devlog 2 - Hooray, I finished making the CSS classes. It was very boring as I had to copy paste basically the same thing fifty times and check and change the dimensions of the image each time but it’s finally done. Now that all the images exist for the website to choose from, I have to venture into Javascript to make the images change. Time to look up a random number generator tutorial and distort it beyond recognition
Devlog 3 - Ok, so all that time writing out the CSS classes may have been pointless…. After trying a lot of different stuff, I found that the only way I could get the image to show was by turning the original div into an img element and changing the src to match different files in Javascript. Oh well, live and learn and all that. I’m back in buisness with the old copy paste for now, though, as I use a switch() function to check the variable that stores the random number and the case/break parts are all very similar (save the src, caption and, you know, the number it checks for). I’m feeling fairly confident that this will work out, though. After I finish this part, I’ll add a button to change the picture and caption so you don’t have to reload the page every time.
Devlog 4 - Finished writing the JS for the image generating and added a “New Image” button so you don’t have to reload the page to see another picture. The project is getting close to done, but there’s one more thing I want to add - a paw print custom cursor. Last time I tried to add that on another project it didn’t work, but I’m hoping I’ll be able to figure it out.
Devlog 5 - Fixed a few formatting issues, added a custom paw print cursor and made a share button that copies the (currently nonexistent) URL to the visitor’s keyboard. I’m very happy with how this site is turning out, so this is probably the last devlog for the actual coding. Next I need to do some shipping prep - writing a README and making a demo page - but that’s probably only about half an hour of work, tops.
Ships:
I have spent the past couple weeks, I have made a website where you can look at pictures of my dog. That’s it. Just my dog. I wanted the site to be pretty simple, as a fun practice project, and I’m very happy with how it’s turned out. One of 55 images is chosen with Javascript when the page loads and the corresponding caption is shown as well. The function repeats any time the “New Image” button is clicked. The “Share” button copies the URL of the site to the visitor’s clipboard. The hardest part of this project was probably getting the random image generation to work. I started by making a CSS class setting the background of an empty div as well as its height and width, but this did not work at all. I don’t know why, but I replaced the div with an image element and used Javascript to change the SRC of the element depending on the result of a random number generated in a variable. Most of the other elements were pretty easy to work with, though. I hope that someone enjoys this fun little project and the pictures of my dog!...
|
1793008156.4370959
|
1793094556.4370959
|
|
15394
|
Unbound Bionix by @araadh3111 | Stardance
|
araadh3111
|
1
|
1.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-26T17:55:51Z", "hours": 1.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Bionix, A prosthetic hand that works from design to circuit everything", "repo": "https://github.com/Araadh3111/Bionix", "demo": ""}]...
|
[{"post_id": 74099, "ts": "202 [{"post_id": 74099, "ts": "2026-09-26T17:55:03Z", "hours": 1.3017, "text": "I could not make the full project but Now I am going to submit the design and I have made some changes in code which I will be commiting in a day"}, {"post_id": 40846, "ts": "2026-08-04T17:06:55Z", "hours": 9.9639, "text": "OH MY DAYS! I MOVED A SERVO FROM MY MUSCLE SIGNALS! this is definetely my lifes greatest achievement ok so I used electrodes and muscle sensor and wrote some basic code to move the servo based on muscle sensors output! I printed bionix a lot of times reiterated designs added arches in fingers for thread routing curled the index finger too! too much achieved im proud of myself! ### Lets Keep Rocking!"}, {"post_id": 26118, "ts": "2026-07-10T18:29:39Z", "hours": 4.9028, "text": "Update on Bionix I am finished with my basic hand structure i printed it irl and saw some errors and then fixed it in CAD next is to work on the thread routing channels!! keep following and checking out my github"}, {"post_id": 11544, "ts": "2026-06-18T20:49:08Z", "hours": 5.1958, "text": "Devlog: Final Engineering Push – Kinematics, Power Architecture, and Assembly Readiness Date: June 19, 2026 Status: Design Locked / Fabrication Ready The past several intensive engineering sessions have brought Bionix from a conceptual CAD model to a fully robust, physically viable electro-mechanical prototype. With the core palm and phalange geometry finalized, power distribution mapped out, and the bill of materials optimized, the project is officially ready for the physical fabrication and assembly phase. ⚙️ Mechanical Engineering & Kinematics The primary mechanical challenge for a tendon-driven bionic hand is managing friction and preventing catastrophic mechanical failure during repeated flexion cycles. We entirely overhauled the internal routing and joint mechanisms to achieve competition-grade reliability. Frictionless Revolute Joints: We stripped out the threaded M2 screws from the phalange joints. The joints have been re-engineered to accept smooth 2.2mm solid brass dowel pins , providing a low-friction, high-strength pivot point that ensures fluid finger movement. Optimized Flexion Routing (The Active Grip): To eliminate the “bowstring” effect, we redesigned the entry tunnels on the palm. The four main finger tension lines now enter the palm cavity via perfectly aligned tunnels featuring a -10° downward draft angle . This forces the high-tensile braided line flush against the joint grooves, maximizing servo leverage. All sharp 90-degree channel exits were filleted into smooth “trumpet flares” to prevent the threads from shearing under load. Antagonistic Elastic Extension (Passive Return): For the fingers to snap back open instantaneously when the servos release, we implemented an external elastic extensor system. We modeled a Unified Wrist Anchor block at the base of the palm. 1mm shock cord anchors at the fingertips, routes seamlessly over the knuckles, and ties off securely at the base of the palm, providing the exact passive tension required for a lifelike, snappy release. Removable Maintenance Hatch: The palm features a custom-traced, screw-mounted top plate with a generous cutout for full thumb articulation. This protects the internal servo array while allowing rapid access for tension-line adjustments. ⚡ Electronics & Power Architecture Running five high-torque micro servos simultaneously while reading delicate analog muscle signals requires isolating the high-current demands of the actuators from the logic board. Main Controller: The system is governed by a Raspberry Pi Pico (RP2040), chosen for its robust hardware PWM processing capabilities. Power Distribution: A 7.4V 2S Li-ion battery serves as the primary power source. This is routed through a high-efficiency 5V Buck Converter (rated for ≥3 Amps) directly to the servo power rails. The Pico is powered safely without having to sink the massive stall currents generated when the hand grips an object. A 1000uF decoupling capacitor bridges the 5V rail to smooth out transient voltage spikes. Biometric Input: We integrated the MyoWare 2.0 muscle sensor, passing raw electromyography (EMG) signals directly to the Pico’s ADC0 (GPIO26) pin."}, {"post_id": 9357, "ts": "2026-06-15T18:12:24Z", "hours": 1.1767, "text": "devlog 5 or 4 i honestly dont remember lol: I am done with the Palm!!!! and I also assembled the fingers to check !!! yes lets goo!! Printing the index finger tomorrow"}, {"post_id": 8851, "ts": "2026-06-14T18:37:40Z", "hours": 0.7619, "text": "Devlog 4: I was already done with 2 fingers earlier, I made the 3rd one today and I used Ai to build the pinky and thumb finger as it was just copying the dimensions editing the sketch and fixing the hole problem What I set out to build : I wanted to complete the fingers in this session which I did achieve + I am done with palm’s basic layout and structure planning, In next session I will be improving and finalising the palm assembling all of it together for once to check it all fits then work on the forearm"}, {"post_id": 8053, "ts": "2026-06-13T13:09:17Z", "hours": 0.4603, "text": "Devlog 3 : Bionix Ring finger design has been done and assembled in a sepearate folder I did not face any problems while making this design, Only pinky finger and thumb are left then I will start with palm and forearm respectively!"}, {"post_id": 8034, "ts": "2026-06-13T12:08:26Z", "hours": 1.7147, "text": "Devlog2 : Unbound bionix, Update: last devlog I was finished with the index finger dimensions well I just printed index finger to confirm movement and it’s moving as expected, I also Made the middle finger design by editing sketch of index finger but fixing the hole sliding issue, failures: I encountered multiple failures planning the design of index finger, but I did make it work and I am really happy for that, what is left? designing all fingers and thumb according to their dimensions and then designing the palm and forearm respectively and then moving on to the electronics part session pic: here is one session pic where I show the assembled middle finger design, for the middle finger the proximal phalange is 5 cm long, the distal phalange is 2 cm and the middle phalange is 3 cm!"}, {"post_id": 6780, "ts": "2026-06-11T11:08:36Z", "hours": 2.8783, "text": "Everyday tasks such as holding a bottle, typing on a keyboard, opening a door, or picking up a pen are actions most of us perform without thinking. For millions of people living with upper-limb loss, these simple activities can become significant challenges that affect independence, confidence, and quality of life. While modern prosthetic technology has advanced considerably, many solutions remain prohibitively expensive, difficult to customize, or inaccessible to students, researchers, and people in developing regions. Devices that offer advanced functionality often cost thousands of dollars, creating a gap between innovation and accessibility. Prosthetic Arm V1 is an attempt to bridge that gap. The goal of this project is to design a lightweight, modular, and affordable prosthetic arm that can be manufactured using 3D printing and standard electronic components. Rather than focusing solely on appearance, the design prioritizes practical functionality, durability, and ease of maintenance. Current Objectives Design an anatomically inspired finger and joint mechanism. Develop smooth and reliable tendon-driven motion. Create a modular structure that allows individual parts to be replaced or upgraded. Keep manufacturing costs as low as possible without sacrificing functionality. Build a foundation for future versions with improved dexterity and sensor integration. Progress Today, I completed the initial CAD model for one of the fingers and started testing the joint geometry. The focus is on achieving a balance between strength, range of motion, and ease of assembly before moving on to full-hand integration. This is only Version 1, and there is still a long way to go, but every iteration brings the project one step closer to creating an accessible prosthetic solution that anyone can build, improve, and use. Next milestone: Complete the middle finger and begin integrating the tendon routing system."}]...
|
Title: Unbound Bionix by @araadh3111 | Stardance
Title: Unbound Bionix by @araadh3111 | Stardance
Devlogs:
Everyday tasks such as holding a bottle, typing on a keyboard, opening a door, or picking up a pen are actions most of us perform without thinking. For millions of people living with upper-limb loss, these simple activities can become significant challenges that affect independence, confidence, and quality of life. While modern prosthetic technology has advanced considerably, many solutions remain prohibitively expensive, difficult to customize, or inaccessible to students, researchers, and people in developing regions. Devices that offer advanced functionality often cost thousands of dollars, creating a gap between innovation and accessibility. Prosthetic Arm V1 is an attempt to bridge that gap. The goal of this project is to design a lightweight, modular, and affordable prosthetic arm that can be manufactured using 3D printing and standard electronic components. Rather than focusing solely on appearance, the design prioritizes practical functionality, durability, and ease of maintenance. Current Objectives Design an anatomically inspired finger and joint mechanism. Develop smooth and reliable tendon-driven motion. Create a modular structure that allows individual parts to be replaced or upgraded. Keep manufacturing costs as low as possible without sacrificing functionality. Build a foundation for future versions with improved dexterity and sensor integration. Progress Today, I completed the initial CAD model for one of the fingers and started testing the joint geometry. The focus is on achieving a balance between strength, range of motion, and ease of assembly before moving on to full-hand integration. This is only Version 1, and there is still a long way to go, but every iteration brings the project one step closer to creating an accessible prosthetic solution that anyone can build, improve, and use. Next milestone: Complete the middle finger and begin integrating the tendon routing system.
Devlog2 : Unbound bionix, Update: last devlog I was finished with the index finger dimensions well I just printed index finger to confirm movement and it’s moving as expected, I also Made the middle finger design by editing sketch of index finger but fixing the hole sliding issue, failures: I encountered multiple failures planning the design of index finger, but I did make it work and I am really happy for that, what is left? designing all fingers and thumb according to their dimensions and then designing the palm and forearm respectively and then moving on to the electronics part session pic: here is one session pic where I show the assembled middle finger design, for the middle finger the proximal phalange is 5 cm long, the distal phalange is 2 cm and the middle phalange is 3 cm!
Devlog 3 : Bionix Ring finger design has been done and assembled in a sepearate folder I did not face any problems while making this design, Only pinky finger and thumb are left then I will start with palm and forearm respectively!
Devlog 4: I was already done with 2 fingers earlier, I made the 3rd one today and I used Ai to build the pinky and thumb finger as it was just copying the dimensions editing the sketch and fixing the hole problem What I set out to build : I wanted to complete the fingers in this session which I did achieve + I am done with palm’s basic layout and structure planning, In next session I will be improving and finalising the palm assembling all of it together for once to check it all fits then work on the forearm
devlog 5 or 4 i honestly dont remember lol: I am done with the Palm!!!! and I also assembled the fingers to check !!! yes lets goo!! Printing the index finger tomorrow
Devlog: Final Engineering Push – Kinematics, Power Architecture, and Assembly Readiness Date: June 19, 2026 Status: Design Locked / Fabrication Ready The past several intensive engineering sessions have brought Bionix from a conceptual CAD model to a fully robust, physically viable electro-mechanical prototype. With the core palm and phalange geometry finalized, power distribution mapped out, and the bill of materials optimized, the project is officially ready for the physical fabrication and assembly phase. ⚙️ Mechanical Engineering & Kinematics The primary mechanical challenge for a tendon-driven bionic hand is managing friction and preventing catastrophic mechanical failure during repeated flexion cycles. We entirely overhauled the internal routing and joint mechanisms to achieve competition-grade reliability. Frictionless Revolute Joints: We stripped out the threaded M2 screws from the phalange joints. The joints have been re-engineered to accept smooth 2.2mm solid brass dowel pins , providing a low-friction, high-strength pivot point that ensures fluid finger movement. Optimized Flexion Routing (The Active Grip): To eliminate the “bowstring” effect, we redesigned the entry tunnels on the palm. The four main finger tension lines now enter the palm cavity via perfectly aligned tunnels featuring a -10° downward draft angle . This forces the high-tensile braided line flush against the joint grooves, maximizing servo leverage. All sharp 90-degree channel exits were filleted into smooth “trumpet flares” to prevent the threads from shearing under load. Antagonistic Elastic Extension (Passive Return): For the fingers to snap back open instantaneously when the servos release, we implemented an external elastic extensor system. We modeled a Unified Wrist Anchor block at the base of the palm. 1mm shock cord anchors at the fingertips, routes seamlessly over the knuckles, and ties off securely at the base of the palm, providing the exact passive tension required for a lifelike, snappy release. Removable Maintenance Hatch: The palm features a custom-traced, screw-mounted top plate with a generous cutout for full thumb articulation. This protects the internal servo array while allowing rapid access for tension-line adjustments. ⚡ Electronics & Power Architecture Running five high-torque micro servos simultaneously while reading delicate analog muscle signals requires isolating the high-current demands of the actuators from the logic board. Main Controller: The system is governed by a Raspberry Pi Pico (RP2040), chosen for its robust hardware PWM processing capabilities. Power Distribution: A 7.4V 2S Li-ion battery serves as the primary power source. This is routed through a high-efficiency 5V Buck Converter (rated for ≥3 Amps) directly to the servo power rails. The Pico is powered safely without having to sink the massive stall currents generated when the hand grips an object. A 1000uF decoupling capacitor bridges the 5V rail to smooth out transient voltage spikes. Biometric Input: We integrated the MyoWare 2.0 muscle sensor, passing raw electromyography (EMG) signals directly to the Pico’s ADC0 (GPIO26) pin.
Update on Bionix I am finished with my basic hand structure i printed it irl and saw some errors and then fixed it in CAD next is to work on the thread routing channels!! keep following and checking out my github
OH MY DAYS! I MOVED A SERVO FROM MY MUSCLE SIGNALS! this is definetely my lifes greatest achievement ok so I used electrodes and muscle sensor and wrote some basic code to move the servo based on muscle sensors output! I printed bionix a lot of times reiterated designs added arches in fingers for thread routing curled the index finger too! too much achieved im proud of myself! ### Lets Keep Rocking!
I could not make the full project but Now I am going to submit the design and I have made some changes in code which I will be commiting in a day
Ships:
Bionix, A prosthetic hand that works from design to circuit everything...
|
1793008157.5501306
|
1793094557.5501306
|
|
54181
|
LifeCalc by @nameer | Stardance
|
nameer
|
1
|
11.41
|
30
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-20T16:05:18Z", "hours": 11.0, "multiplier": 2.83, "payout": 30, "blessing": "neutral", "text": "Ok so I made a web based calculator that makes life easier and smoother its called LifeCalc. It has age calculator, date calculator, BMI calculator, tip calculator, percentage calculator, discount calculator, unit converter and interest calculator. The difficulties I faced was mainly the unfamiliarity with Github. Hopefully this will make life easier.", "repo": "https://github.com/nameerhassannhr-glitch/lifecalc", "demo": "https://nameerhassannhr-glitch.github.io/lifecalc/"}]...
|
[{"post_id": 72114, "ts": "202 [{"post_id": 72114, "ts": "2026-09-22T06:10:37Z", "hours": 0.415, "text": "I fixed the broken readme that was being flagged and fixed the picture error i have been getting"}, {"post_id": 71270, "ts": "2026-09-20T15:37:39Z", "hours": 0.7178, "text": "ok so as Iam was in the last step of the lifecalc i tested out all 8 of the calculators fixed a issue in the unit converter that was lead by an extra gap what an idiot iam so after it i finished the markdown file aded the screenshot made the website live and fixed a few other calculation bug"}, {"post_id": 70159, "ts": "2026-09-18T16:24:22Z", "hours": 10.0422, "text": "ok so ever since the last devlog things have changed i was in a science camp recently so after i came from the science camp i changed the calc style added the new calculators, fixed bugs, checked things and now its almost over"}]...
|
Title: LifeCalc by @nameer | Stardance
Devlogs:
o Title: LifeCalc by @nameer | Stardance
Devlogs:
ok so ever since the last devlog things have changed i was in a science camp recently so after i came from the science camp i changed the calc style added the new calculators, fixed bugs, checked things and now its almost over
ok so as Iam was in the last step of the lifecalc i tested out all 8 of the calculators fixed a issue in the unit converter that was lead by an extra gap what an idiot iam so after it i finished the markdown file aded the screenshot made the website live and fixed a few other calculation bug
I fixed the broken readme that was being flagged and fixed the picture error i have been getting
Ships:
Ok so I made a web based calculator that makes life easier and smoother its called LifeCalc. It has age calculator, date calculator, BMI calculator, tip calculator, percentage calculator, discount calculator, unit converter and interest calculator. The difficulties I faced was mainly the unfamiliarity with Github. Hopefully this will make life easier....
|
1793008158.7421737
|
1793094558.7421737
|
|
32480
|
Pac-Man by @raslanyossif | Stardance
|
raslanyossif
|
1
|
95.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-27T04:21:15Z", "hours": 95.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a Pac-man but with power ups and more ghosts as you proceed to level up. challenging part was making the maze I struggled a lot. I’m proud that I was able to complete such a project. When you get one of the power ups which is Shield your Pac-man becomes blue, so the ghosts can’t eat you and you can’t eat them. It isn’t a bug I made it that way.", "repo": "https://github.com/Yossifraslan/Pac-Man", "demo": "https://yossifraslan.github.io/Pac-Man/"}]...
|
[{"post_id": 74295, "ts": "202 [{"post_id": 74295, "ts": "2026-09-27T04:15:28Z", "hours": 9.2853, "text": "It’s DEVLOG TIME:» Just pushed a much-needed update to the project! First up, I finally tracked down and killed a frustrating maze error in Level 10 that was completely breaking the game right near the finish line—so the final levels are officially working and playable now. While I was at it, I also took the time to write a proper README. It covers everything from setup instructions to gameplay mechanics, making the codebase a lot more welcoming and less of a black box for anyone who wants to test it out or contribute. Next up is getting some feedback and seeing how quickly people can break it! Also, when you are shielded for the power up, you can’t eat the ghosts."}, {"post_id": 49457, "ts": "2026-08-18T09:45:17Z", "hours": 9.5264, "text": "IT’S DEVLOG TIMEE :»> It’s been a tough few days trying to figure out how to fix the MAZE, but I finally figured out how to do it through A* pathfinding. Fixed all the maps. Which took me so longggg. Also, Fixed speed inconsistency bugs and collision detection to eliminate Pac-Man getting stuck at maze tiles - movement now uses tile-based physics that checks every frame with no edge-case stalls, plus input buffering lets players queue moves ahead for responsive controls. Implemented proper ghost freeze behavior where frozen ghosts stop completely for 5 seconds, stay visible, and remain killable while frozen. Made the Extra Life now work on the screen when you get an Extra life it will update in the UI top middle and see a new Pac-man face get added. On the side of the Maps you can see there is no wall blocking, because now I made it a teleport to the other side."}, {"post_id": 46650, "ts": "2026-08-14T01:56:32Z", "hours": 9.1808, "text": "Fixed all six power-up behaviours this session. Speed boost and double points were already working. The main rework was on shield, freeze, and slow. Shield now stays active until a ghost physically touches the player, when that happens, the ghost turns scared/blue instead of the player dying, and the shield remains active for future hits on a 15-second timer. Freeze keeps ghosts in their normal colour but completely stops their movement for 3 seconds - they’re still killable while frozen. Slow keeps ghosts at their normal appearance but skips movement every other frame, effectively halving their speed for 5 seconds. Also implemented proper ghost spawn behavior. Ghosts now spawn at the center of the maze (on or near the ghost house tiles) and release one by one first ghost after 2 seconds, then one every 3 seconds. While waiting to release they bob up and down inside the house. After death, the release sequence resets so ghosts trickle out again rather than all rushing at once. Pac-Man now spawns at a random open tile at least a third of the maze width away from the centre, so every life and every game starts from a different position. Maze connectivity fix was attempted this session but not completed - some maps still have corridors that can trap the player. Carrying this into the next session"}, {"post_id": 43330, "ts": "2026-08-08T15:07:17Z", "hours": 9.7428, "text": "I fixed up my previous issues with lives resetting to 3 for each level completed as well as start Game taking you back to level 1 rather than starting at the highest level you’ve unlocked. The ghost speed has been halved (from 2px to 1px/frame) which makes everything seem much more balanced with me running around at 60fps! I’ve added a proper pause menu overlay along with options to toggle Music & SFX - I had previously run into an issue where if you paused the game then played again the menu music would keep playing. To fix this I’m keeping track of all active WebAudio Oscillators and automatically stop them whenever we begin gameplay. We’ve added some really nice little touches too! For example, when you die Pac-Man will close his mouth, spin twice and slowly shrink away over 80 frames before disappearing completely. You’ll also get a sweet animation when you spawn growing up from 0 to full size over 40 frames. We originally couldn’t get the death animation working because we’d set our global variable gameActive = false during dying which turned off the entire update loop so I’ve updated Pac-Man’s update method to continue updating even when he’s dying / spawning. Finally, I made sure to make Pac-Man disappear once he dies to ensure no weird visuals happen after respawning. We added a yellow flash on finishing a level. Floating score popups show up every time you eat a ghost. Now there’s an animated HUD that shows your current score. Previously, canvas animations were off due to transform translation applied twice (once during animation and once more when drawing). Now we translate to our sprite’s center before applying any additional transformation."}, {"post_id": 40526, "ts": "2026-08-04T03:32:16Z", "hours": 9.2125, "text": "DEVLOG TIME:> During this session, I incorporated complete mobile compatibility. The directional pad appears automatically on touch devices through (pointer:coarse) through CSS thus eliminating the need for any device detection as it will be shown as soon as the browser detects a device with touch input. Each button utilizes touchstart instead of click , so there is no 300ms tap delay that would make the controls slow or laggy. I also introduced swipe detection on the canvas as a substitute for the directional pad. The minimum distance for swipe detection is 30px, filtering unintended touches and also utilizing the main axis (horizontal or vertical) in order to identify the direction even in case of diagonal swipes. I added responsive CSS for screens smaller than 480px thus allowing the fonts, buttons, and HUD to resize, so no overflowing occurs on small screens. I verified this by checking the local network IP through my mobile, as both devices were connected to the same Wi-Fi network. The InputManager is now capable of working with three types of input in one place - keyboard, touch directional pad, and swipe, all of them leading to a single nextDirection property, which is accessed by the main game loop."}, {"post_id": 39312, "ts": "2026-08-02T06:34:55Z", "hours": 9.3164, "text": "Added an audio system using the WebAudio API. No external sound files everything is generated programmatically using oscillators and gain nodes. Each game event has its sound: a short square wave blip for eating dots a sawtooth drop for eating pellets, a triangle tone for eating ghosts a descending three-note jingle for death and a rising three-note fanfare for level complete. The main menu has a looping chiptune melody. 25 Notes scheduled ahead of time using ctx.currentTime, which avoids timing drift that would happen with repeated setTimeout calls. It loops by scheduling the playthrough when the current one ends. The trickiest part was the browser autoplay policy. Browsers block AudioContext from making sound until the user interacts with the page. The fix was checking ctx.state === suspended on the click and calling ctx.resume() before trying to play anything. Finished power-up effects. Freeze and slow work via frame timers (_frozenTimer _slowTimer) set directly on each monster. The monster update method checks these at the top before doing anything effectively pausing or slowing it without touching core movement logic. Known issue: menu music doesn’t stop immediately when the game starts. There’s a 1-2 overlap before it cuts out. Will fix session along with, in-game sound effects not always triggering. Investigating AudioContext state management across the menu-> game transition."}, {"post_id": 33922, "ts": "2026-07-24T07:11:48Z", "hours": 9.5589, "text": "DEVLOG TIME!!! Added ghosts to the game this session. The ghost AI has 4 behavior types - chaser, ambusher, predictor, and patroller, targeting player based on various positions. Also added A* path finding to have the ghosts go around walls instead of choosing adjacent tiles that are closer to them. Majority of time in this session was spent debugging the movement. It turned out to be a floating-point problem where, when the ghost speed is not divisible by the tile size (20 px), the pixelX % tileSize is never equal to 0 and therefore the alignment function is never called resulting in the ghost moving for 2 px per frame. Fixed this by making the ghost speed fixed at an integer value (2) that is divisible by 20. Eating the power pellet causes the ghost to go into the frighten state which makes the ghost turn blue and move randomly. The player receives 200 points and the respawn timer starts when a ghost in the frighten state is eaten."}, {"post_id": 31207, "ts": "2026-07-19T12:53:56Z", "hours": 9.6542, "text": "WHAT’s NEW:> Devlog Time!!! Got Pac-Man actually moving through the maze this session. Built the Player class with grid-based movement - Pac-Man only changes direction when pixel position is exactly aligned to a tile, which prevents clipping through walls. Added direction queuing so if you press a turn slightly early it still registers when the next tile is reached, making controls feel responsive instead of stiff. Also split out InputManager , CollisionSystem , and UIManager into their own modules. Dot collection works - eating a dot removes it from the array, updates the grid, and increments score. Level completes when all dots and pellets are cleared, with a 500 x level bonus. One thing worth noting from Devlog 2 - the maze connectivity issue. After designing all 10 maze layouts, levels 3-10 had isolated sections where dots were completely unreachable. Wrote a flood-fill validator that BFS traverses from the first dot and counts how many dots are reachable. Then wrote an auto-fixer that finds disconnected sections and carves the shortest Manhattan path between them. All 10 levels now pass with 100% dots reachable."}, {"post_id": 29256, "ts": "2026-07-16T01:45:12Z", "hours": 9.4397, "text": "DEVLOG TIME:> !! I have improved the maze system used in my game, Pac-Man. Originally, I thought of not only using one maze and having a full leveling system. In this, I calculated and created 10 mazes with different sizes, difficulties, and complexity levels. In addition, I modified the class MazeManager in such a way that our game automatically changes levels without requiring a manual change of the mazes. In testing new mazes, I introduced a checking mechanism so that we will know whether our mazes have any unreachable dots. For some reason, it turned out that some parts of the maze were blocked. Maze validation: 195/218 dots reachable Blocked sections were identified. Some of the dots can’t be accessed. Interestingly, the maze looked perfectly okay visually, but the navigation test indicated that some of the areas of my maze were not accessible. At the moment, I plan on fixing the blocked paths and test out each level. I might also change some things later once the game is fully playable and I can properly test the difficulty, such as: maze layouts ghost difficulty level progression number of ghosts/speed scaling Right now the goal is getting the core gameplay working first, then balancing everything afterwards."}, {"post_id": 26506, "ts": "2026-07-11T10:41:25Z", "hours": 9.9617, "text": "I’ve been really busy but here is the first DEVLOG for Pac-man:> I’m planning on doing unique things in this Pac-man it won’t be a normal Pac-man. What I did: Built all 5 screens for the game - main menu, level select, how to play, game screen and game over. No gameplay yet, just the full UI shell. Screen switching works by toggling a single. active class, all screens live in the DOM simultaneously. Biggest challenge was the SVG ghosts. Drew them in pure SVG using and so the shape is defined once and reused everywhere with different colors via a CSS variable –gc. Also styled elements in the How to Play screen to look like actual keyboard keys. Ghost bobbing animation on the menu uses staggered animation-delay so they move in a wave instead of all at once."}]...
|
Title: Pac-Man by @raslanyossif | Stardance
Devlo Title: Pac-Man by @raslanyossif | Stardance
Devlogs:
I’ve been really busy but here is the first DEVLOG for Pac-man:> I’m planning on doing unique things in this Pac-man it won’t be a normal Pac-man. What I did: Built all 5 screens for the game - main menu, level select, how to play, game screen and game over. No gameplay yet, just the full UI shell. Screen switching works by toggling a single. active class, all screens live in the DOM simultaneously. Biggest challenge was the SVG ghosts. Drew them in pure SVG using and so the shape is defined once and reused everywhere with different colors via a CSS variable –gc. Also styled elements in the How to Play screen to look like actual keyboard keys. Ghost bobbing animation on the menu uses staggered animation-delay so they move in a wave instead of all at once.
DEVLOG TIME:> !! I have improved the maze system used in my game, Pac-Man. Originally, I thought of not only using one maze and having a full leveling system. In this, I calculated and created 10 mazes with different sizes, difficulties, and complexity levels. In addition, I modified the class MazeManager in such a way that our game automatically changes levels without requiring a manual change of the mazes. In testing new mazes, I introduced a checking mechanism so that we will know whether our mazes have any unreachable dots. For some reason, it turned out that some parts of the maze were blocked. Maze validation: 195/218 dots reachable Blocked sections were identified. Some of the dots can’t be accessed. Interestingly, the maze looked perfectly okay visually, but the navigation test indicated that some of the areas of my maze were not accessible. At the moment, I plan on fixing the blocked paths and test out each level. I might also change some things later once the game is fully playable and I can properly test the difficulty, such as: maze layouts ghost difficulty level progression number of ghosts/speed scaling Right now the goal is getting the core gameplay working first, then balancing everything afterwards.
WHAT’s NEW:> Devlog Time!!! Got Pac-Man actually moving through the maze this session. Built the Player class with grid-based movement - Pac-Man only changes direction when pixel position is exactly aligned to a tile, which prevents clipping through walls. Added direction queuing so if you press a turn slightly early it still registers when the next tile is reached, making controls feel responsive instead of stiff. Also split out InputManager , CollisionSystem , and UIManager into their own modules. Dot collection works - eating a dot removes it from the array, updates the grid, and increments score. Level completes when all dots and pellets are cleared, with a 500 x level bonus. One thing worth noting from Devlog 2 - the maze connectivity issue. After designing all 10 maze layouts, levels 3-10 had isolated sections where dots were completely unreachable. Wrote a flood-fill validator that BFS traverses from the first dot and counts how many dots are reachable. Then wrote an auto-fixer that finds disconnected sections and carves the shortest Manhattan path between them. All 10 levels now pass with 100% dots reachable.
DEVLOG TIME!!! Added ghosts to the game this session. The ghost AI has 4 behavior types - chaser, ambusher, predictor, and patroller, targeting player based on various positions. Also added A* path finding to have the ghosts go around walls instead of choosing adjacent tiles that are closer to them. Majority of time in this session was spent debugging the movement. It turned out to be a floating-point problem where, when the ghost speed is not divisible by the tile size (20 px), the pixelX % tileSize is never equal to 0 and therefore the alignment function is never called resulting in the ghost moving for 2 px per frame. Fixed this by making the ghost speed fixed at an integer value (2) that is divisible by 20. Eating the power pellet causes the ghost to go into the frighten state which makes the ghost turn blue and move randomly. The player receives 200 points and the respawn timer starts when a ghost in the frighten state is eaten.
Added an audio system using the WebAudio API. No external sound files everything is generated programmatically using oscillators and gain nodes. Each game event has its sound: a short square wave blip for eating dots a sawtooth drop for eating pellets, a triangle tone for eating ghosts a descending three-note jingle for death and a rising three-note fanfare for level complete. The main menu has a looping chiptune melody. 25 Notes scheduled ahead of time using ctx.currentTime, which avoids timing drift that would happen with repeated setTimeout calls. It loops by scheduling the playthrough when the current one ends. The trickiest part was the browser autoplay policy. Browsers block AudioContext from making sound until the user interacts with the page. The fix was checking ctx.state === suspended on the click and calling ctx.resume() before trying to play anything. Finished power-up effects. Freeze and slow work via frame timers (_frozenTimer _slowTimer) set directly on each monster. The monster update method checks these at the top before doing anything effectively pausing or slowing it without touching core movement logic. Known issue: menu music doesn’t stop immediately when the game starts. There’s a 1-2 overlap before it cuts out. Will fix session along with, in-game sound effects not always triggering. Investigating AudioContext state management across the menu-> game transition.
DEVLOG TIME:> During this session, I incorporated complete mobile compatibility. The directional pad appears automatically on touch devices through (pointer:coarse) through CSS thus eliminating the need for any device detection as it will be shown as soon as the browser detects a device with touch input. Each button utilizes touchstart instead of click , so there is no 300ms tap delay that would make the controls slow or laggy. I also introduced swipe detection on the canvas as a substitute for the directional pad. The minimum distance for swipe detection is 30px, filtering unintended touches and also utilizing the main axis (horizontal or vertical) in order to identify the direction even in case of diagonal swipes. I added responsive CSS for screens smaller than 480px thus allowing the fonts, buttons, and HUD to resize, so no overflowing occurs on small screens. I verified this by checking the local network IP through my mobile, as both devices were connected to the same Wi-Fi network. The InputManager is now capable of working with three types of input in one place - keyboard, touch directional pad, and swipe, all of them leading to a single nextDirection property, which is accessed by the main game loop.
I fixed up my previous issues with lives resetting to 3 for each level completed as well as start Game taking you back to level 1 rather than starting at the highest level you’ve unlocked. The ghost speed has been halved (from 2px to 1px/frame) which makes everything seem much more balanced with me running around at 60fps! I’ve added a proper pause menu overlay along with options to toggle Music & SFX - I had previously run into an issue where if you paused the game then played again the menu music would keep playing. To fix this I’m keeping track of all active WebAudio Oscillators and automatically stop them whenever we begin gameplay. We’ve added some really nice little touches too! For example, when you die Pac-Man will close his mouth, spin twice and slowly shrink away over 80 frames before disappearing completely. You’ll also get a sweet animation when you spawn growing up from 0 to full size over 40 frames. We originally couldn’t get the death animation working because we’d set our global variable gameActive = false during dying which turned off the entire update loop so I’ve updated Pac-Man’s update method to continue updating even when he’s dying / spawning. Finally, I made sure to make Pac-Man disappear once he dies to ensure no weird visuals happen after respawning. We added a yellow flash on finishing a level. Floating score popups show up every time you eat a ghost. Now there’s an animated HUD that shows your current score. Previously, canvas animations were off due to transform translation applied twice (once during animation and once more when drawing). Now we translate to our sprite’s center before applying any additional transformation.
Fixed all six power-up behaviours this session. Speed boost and double points were already working. The main rework was on shield, freeze, and slow. Shield now stays active until a ghost physically touches the player, when that happens, the ghost turns scared/blue instead of the player dying, and the shield remains active for future hits on a 15-second timer. Freeze keeps ghosts in their normal colour but completely stops their movement for 3 seconds - they’re still killable while frozen. Slow keeps ghosts at their normal appearance but skips movement every other frame, effectively halving their speed for 5 seconds. Also implemented proper ghost spawn behavior. Ghosts now spawn at the center of the maze (on or near the ghost house tiles) and release one by one first ghost after 2 seconds, then one every 3 seconds. While waiting to release they bob up and down inside the house. After death, the release sequence resets so ghosts trickle out again rather than all rushing at once. Pac-Man now spawns at a random open tile at least a third of the maze width away from the centre, so every life and every game starts from a different position. Maze connectivity fix was attempted this session but not completed - some maps still have corridors that can trap the player. Carrying this into the next session
IT’S DEVLOG TIMEE :»> It’s been a tough few days trying to figure out how to fix the MAZE, but I finally figured out how to do it through A* pathfinding. Fixed all the maps. Which took me so longggg. Also, Fixed speed inconsistency bugs and collision detection to eliminate Pac-Man getting stuck at maze tiles - movement now uses tile-based physics that checks every frame with no edge-case stalls, plus input buffering lets players queue moves ahead for responsive controls. Implemented proper ghost freeze behavior where frozen ghosts stop completely for 5 seconds, stay visible, and remain killable while frozen. Made the Extra Life now work on the screen when you get an Extra life it will update in the UI top middle and see a new Pac-man face get added. On the side of the Maps you can see there is no wall blocking, because now I made it a teleport to the other side.
It’s DEVLOG TIME:» Just pushed a much-needed update to the project! First up, I finally tracked down and killed a frustrating maze error in Level 10 that was completely breaking the game right near the finish line—so the final levels are officially working and playable now. While I was at it, I also took the time to write a proper README. It covers everything from setup instructions to gameplay mechanics, making the codebase a lot more welcoming and less of a black box for anyone who wants to test it out or contribute. Next up is getting some feedback and seeing how quickly people can break it! Also, when you are shielded for the power up, you can’t eat the ghosts.
Ships:
I made a Pac-man but with power ups and more ghosts as you proceed to level up. challenging part was making the maze I struggled a lot. I’m proud that I was able to complete such a project. When you get one of the power ups which is Shield your Pac-man becomes blue, so the ghosts can’t eat you and you can’t eat them. It isn’t a bug I made it that way....
|
1793008159.6180859
|
1793094559.6180859
|
|
28283
|
Robot Arm by @jake18 | Stardance
|
jake18
|
1
|
28.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-21T03:43:04Z", "hours": 28.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I built a 5-DOF robotic arm that can move manually or remotely using coordinate control. The arm uses 5 servo motors for the arm and 1 stepper motor for the base to provide movement. Every joint in this arm is controlled through a local web app that I am running on my laptop. All of the controls, calculations, etc., are all on my laptop. The ESP32 only acts as a motor controller, receiving commands through wifi and controlling the motors. The thing that I am most proud of is the code and coordinate control. This was the first time I did a project with this scale of code, and I am proud that it works well. This was also the first time I made a web app and combining it with an ESP32. The most challenging part about this project was definitely the mechanical design. Everything in CAD worked smoothly with no mistakes, but when I printed it out, big and small errors kept showing up that delayed my project by a few weeks. I had to go through many iterations until I got one that worked. FYI the angle processing in the code is tailored to my specific motor angles and position.", "repo": "https://github.com/jakecao18/Robot-Arm", "demo": ""}]...
|
[{"post_id": 70721, "ts": "202 [{"post_id": 70721, "ts": "2026-09-19T17:29:25Z", "hours": 8.8356, "text": "Devlog #6 So i have just finished assembling the arm and making all the gears, motors and joints properly now what I have done: fixed the shoulder joint by removing the belt completely, now it runs on a 1:1.5 spur gear reduction I added the stepper motor so now the arm can rotate by its base, allowing it to move in 3d I redesigned the gripper since the old one (finray style gripper) was too weak and couldn’t pick things up. this new gripper is a rack and pinion gripper that is much stronger I have connected the SMPS power supply and now every motor can run on full power I have connected the website to the esp so now my slider control works and is accurate But there are still some problems: the backlash of all the joints add up, which means the end effector wobbles too much. My coordinate control still isn’t accurate So before shipping this project, I will fix the coordinate control code so that it is now accurate. The backlash is a separate problem that I dont think ill be able to solve in time."}, {"post_id": 47845, "ts": "2026-08-16T02:11:50Z", "hours": 10.0933, "text": "Devlog #5 I have now finished the local web server to control the robot, it includes 6 sliders for the 5 servos and 1 stepper motor and also a coordinate control. for the coordinate control, you simply plug in your x, y, z coordinates it will return j1, j2, j3, and j4 angles to you. on the coding side of that, i just wrote some simple analytical ik, mostly triangle geometry. the website is ran by flask and i am using udp sockets to send the angles to my esp32 via wifi. everything is ran on my computer, so the esp would only have to control the motors with the angles. i also did some cad to redesign the shoulder base to fix the belt problem, will start printing soon."}, {"post_id": 42286, "ts": "2026-08-06T22:24:53Z", "hours": 9.0053, "text": "Devlog #4 So ive finished the CAD for the new parts and assembled the robot arm, but the wrist roll and gripper will be attached later. the elbow and wrist pitch of the robot works smoothly now, no skipping or anything, however. the shoulder belt is still skipping under load, i have now used more teeth but it still skips. I think that this is because the belt itself is not tensioned properly (its a little loose), i will have to return the current belt and buy a new one. if anyone have any suggestions to help prevent skipping please let me know. for now that is the only major problem in this build. I am working on the gripper right now since the old design didnt work. also i have been working on a web app to control the arm from my computer to the esp via wifi. I am almost done the app and soon will be able to send data to the esp. that is all for now but i think more problems will apear later."}, {"post_id": 35021, "ts": "2026-07-26T05:31:37Z", "hours": 9.3075, "text": "Devlog #3 So now i have printed all the parts and assembled the arm up to the wrist, but a few problems prevented the arm from moving properly. The gears at the elbow are slipping when under load and also the shafts supporting them are not stable. I think I can fix this by locking the two shafts together and using wider M2 gears. The belt at the shoulder is also slipping under load. I think that i just need the gears to be bigger so that they can tension the belt better. The elbow joint servo doesnt have enough movement to drive the whole elbow 180 degrees because of the gears. I messed up this part because i was supposed to buy the 270 degree servo not the 180 one. Ill be waiting for the 270 servo to arrive. Aside from those problems I have written code so that I can control the servos by angle and not PWM pulses. The base of the arm works fine, Ill be controlling that as soon as i learn how to control a stepper motor. For now I have redesigned most of the arm to fix these problems, but as i wait for the servo and all the parts to print, ill try to work on a web that can control the arm."}, {"post_id": 27505, "ts": "2026-07-13T04:01:09Z", "hours": 4.1847, "text": "Devlog #2 Finished printing everything and started testing if everything fit together. Some of the components had weak spots or didn’t fit together well. I had to go back and forth between CAD and printing for a while because my tolerances weren’t quite correct. Everything fits nicely now. I also made a GitHub repo and added all the CAD files, BOM, pictures etc. I will update GitHub frequently, and everything needed to recreate this project will be there. I also made a wiring diagram and in the process realized that I needed a few more components to make sure that the arm would work smoothly and safely. I was kinda hard to learn why I needed all these different components but in the end I think it makes sense to me now. The next steps now is probably to buy the components and then assemble the robot. In the meantime though I think I can start writing some code on Inverse Kinematics for the Robot. I want it to be able to move all the servos to the correct angle when given some coordinates."}, {"post_id": 21070, "ts": "2026-07-02T20:57:09Z", "hours": 1.2269, "text": "Devlog #1 Completed the CAD assembly for my robot arm. I plan it to be a 5-DOF arm with 5 motors for movement and 1 motor for the claw. I’m using 5 servos and 1 stepper motor right now but I don’t know if I should change it all into servos. I also made the arm be able to swap grippers pretty easily. Im gonna print everything for this arm, gears, gripper, etc. I can also 3d print the ball bearings but I think its better to buy them. The next step is to start printing everything, buying all the parts and start assembling it. Once Im done assembling Ill start coding it. I plan for the arm to run on a Raspberry Pi and be controlled via an app."}]...
|
Title: Robot Arm by @jake18 | Stardance
Devlogs:
Title: Robot Arm by @jake18 | Stardance
Devlogs:
Devlog #1 Completed the CAD assembly for my robot arm. I plan it to be a 5-DOF arm with 5 motors for movement and 1 motor for the claw. I’m using 5 servos and 1 stepper motor right now but I don’t know if I should change it all into servos. I also made the arm be able to swap grippers pretty easily. Im gonna print everything for this arm, gears, gripper, etc. I can also 3d print the ball bearings but I think its better to buy them. The next step is to start printing everything, buying all the parts and start assembling it. Once Im done assembling Ill start coding it. I plan for the arm to run on a Raspberry Pi and be controlled via an app.
Devlog #2 Finished printing everything and started testing if everything fit together. Some of the components had weak spots or didn’t fit together well. I had to go back and forth between CAD and printing for a while because my tolerances weren’t quite correct. Everything fits nicely now. I also made a GitHub repo and added all the CAD files, BOM, pictures etc. I will update GitHub frequently, and everything needed to recreate this project will be there. I also made a wiring diagram and in the process realized that I needed a few more components to make sure that the arm would work smoothly and safely. I was kinda hard to learn why I needed all these different components but in the end I think it makes sense to me now. The next steps now is probably to buy the components and then assemble the robot. In the meantime though I think I can start writing some code on Inverse Kinematics for the Robot. I want it to be able to move all the servos to the correct angle when given some coordinates.
Devlog #3 So now i have printed all the parts and assembled the arm up to the wrist, but a few problems prevented the arm from moving properly. The gears at the elbow are slipping when under load and also the shafts supporting them are not stable. I think I can fix this by locking the two shafts together and using wider M2 gears. The belt at the shoulder is also slipping under load. I think that i just need the gears to be bigger so that they can tension the belt better. The elbow joint servo doesnt have enough movement to drive the whole elbow 180 degrees because of the gears. I messed up this part because i was supposed to buy the 270 degree servo not the 180 one. Ill be waiting for the 270 servo to arrive. Aside from those problems I have written code so that I can control the servos by angle and not PWM pulses. The base of the arm works fine, Ill be controlling that as soon as i learn how to control a stepper motor. For now I have redesigned most of the arm to fix these problems, but as i wait for the servo and all the parts to print, ill try to work on a web that can control the arm.
Devlog #4 So ive finished the CAD for the new parts and assembled the robot arm, but the wrist roll and gripper will be attached later. the elbow and wrist pitch of the robot works smoothly now, no skipping or anything, however. the shoulder belt is still skipping under load, i have now used more teeth but it still skips. I think that this is because the belt itself is not tensioned properly (its a little loose), i will have to return the current belt and buy a new one. if anyone have any suggestions to help prevent skipping please let me know. for now that is the only major problem in this build. I am working on the gripper right now since the old design didnt work. also i have been working on a web app to control the arm from my computer to the esp via wifi. I am almost done the app and soon will be able to send data to the esp. that is all for now but i think more problems will apear later.
Devlog #5 I have now finished the local web server to control the robot, it includes 6 sliders for the 5 servos and 1 stepper motor and also a coordinate control. for the coordinate control, you simply plug in your x, y, z coordinates it will return j1, j2, j3, and j4 angles to you. on the coding side of that, i just wrote some simple analytical ik, mostly triangle geometry. the website is ran by flask and i am using udp sockets to send the angles to my esp32 via wifi. everything is ran on my computer, so the esp would only have to control the motors with the angles. i also did some cad to redesign the shoulder base to fix the belt problem, will start printing soon.
Devlog #6 So i have just finished assembling the arm and making all the gears, motors and joints properly now what I have done: fixed the shoulder joint by removing the belt completely, now it runs on a 1:1.5 spur gear reduction I added the stepper motor so now the arm can rotate by its base, allowing it to move in 3d I redesigned the gripper since the old one (finray style gripper) was too weak and couldn’t pick things up. this new gripper is a rack and pinion gripper that is much stronger I have connected the SMPS power supply and now every motor can run on full power I have connected the website to the esp so now my slider control works and is accurate But there are still some problems: the backlash of all the joints add up, which means the end effector wobbles too much. My coordinate control still isn’t accurate So before shipping this project, I will fix the coordinate control code so that it is now accurate. The backlash is a separate problem that I dont think ill be able to solve in time.
Ships:
I built a 5-DOF robotic arm that can move manually or remotely using coordinate control. The arm uses 5 servo motors for the arm and 1 stepper motor for the base to provide movement. Every joint in this arm is controlled through a local web app that I am running on my laptop. All of the controls, calculations, etc., are all on my laptop. The ESP32 only acts as a motor controller, receiving commands through wifi and controlling the motors. The thing that I am most proud of is the code and coordinate control. This was the first time I did a project with this scale of code, and I am proud that it works well. This was also the first time I made a web app and combining it with an ESP32. The most challenging part about this project was definitely the mechanical design. Everything in CAD worked smoothly with no mistakes, but when I printed it out, big and small errors kept showing up that delayed my project by a few weeks. I had to go through many iterations until I got one that worked. FYI the angle processing in the code is tailored to my specific motor angles and position....
|
1793008160.788182
|
1793094560.788182
|
|
54220
|
Cognitive Arena by @Qlz | Stardance
|
Qlz
|
1
|
4.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-14T15:58:19Z", "hours": 4.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "A web based cognitive testing suite featuring five interactive benchmarks for reaction speed, aim training, visual memory, number memory, and a wpm test where users can test, track or imrpove their cognitive skills from these tests.Along the way the challenging part was improving the cognitive tests making it accurste enough,refining the test flow with clearer instructions, countdowns, and live wpm test for what the user types over it and getting the code right based on what i intented and accuracy tracking rigs for the grid shot .I still have plenty of ideas to add on to this like a better tracking chart or other accurate tests. Right now, the project feels fast, responsive, and accurate enough to stand on its own as an experience.", "repo": "https://github.com/aqvoz/Cognitive-Arena", "demo": "https://aqvoz.github.io/Cognitive-Arena/"}]...
|
[{"post_id": 68069, "ts": "202 [{"post_id": 68069, "ts": "2026-09-14T13:50:45Z", "hours": 1.4433, "text": "I was able to improve the current five cognitive tests which is the important part of this project, each test has a detailed indroduction upon hovering over it so u can choose swiftly .I was focused on the dialing of the typing test mechanics so that keystrokes feel smooth and responsive, complete with live wpm and accuracy tracking right over an endless stream of text. I spent much time squashing bugs across the visual memory and aim tests, cleaning up performance leaks, and polishing the overall flow of each test especially the wpm test,I overhauled the event listeners and timer logic to eliminate performance leaks, fixed layout shift issues during high-speed clicks, and polished the overall visual flow between transitions Along the way, I refined the test flow with clearer instructions, countdowns, better feedback, and more consistent scoring across each challenge. Paid alot of attention to the smaller details from making the reaction test more precise to keeping the different tests feeling responsive and fair across different setups which makes Cognitive Arena feels less like a collection of mini games but more like a complete cognitive approximated testing experience . There are still plenty of things I could keep tweaking and later on i am planning to update this, but I think it’s finally at a point where it’s ready to be shared before upcoming cool updates like adding more tests or a progression chart to maoe it more challenging but right now its enough as a quick test of your cognitive skills"}, {"post_id": 66793, "ts": "2026-09-12T17:58:03Z", "hours": 0.4992, "text": "Instead of going straight into the test i needed a startup page before users launch a benchmark,so I designed a retro landing screen . Made the whole UI feel much more cleaner before jumping into the actual benchmarks for a startup indroduction and also designed the layout for cogintive tests.i made 5 simple tests so far which needs a rework so next devlog i will be improving my mini cognitive tests that i had made to publish"}, {"post_id": 66431, "ts": "2026-09-12T08:14:00Z", "hours": 2.0428, "text": "Started my new project Cognitive Arena . Set up the core HTML structure and styled the base interface with a clean, modern layout to handle the interactive elements and still adding the benchmarks"}]...
|
Title: Cognitive Arena by @Qlz | Stardance
Devlog Title: Cognitive Arena by @Qlz | Stardance
Devlogs:
Started my new project Cognitive Arena . Set up the core HTML structure and styled the base interface with a clean, modern layout to handle the interactive elements and still adding the benchmarks
Instead of going straight into the test i needed a startup page before users launch a benchmark,so I designed a retro landing screen . Made the whole UI feel much more cleaner before jumping into the actual benchmarks for a startup indroduction and also designed the layout for cogintive tests.i made 5 simple tests so far which needs a rework so next devlog i will be improving my mini cognitive tests that i had made to publish
I was able to improve the current five cognitive tests which is the important part of this project, each test has a detailed indroduction upon hovering over it so u can choose swiftly .I was focused on the dialing of the typing test mechanics so that keystrokes feel smooth and responsive, complete with live wpm and accuracy tracking right over an endless stream of text. I spent much time squashing bugs across the visual memory and aim tests, cleaning up performance leaks, and polishing the overall flow of each test especially the wpm test,I overhauled the event listeners and timer logic to eliminate performance leaks, fixed layout shift issues during high-speed clicks, and polished the overall visual flow between transitions Along the way, I refined the test flow with clearer instructions, countdowns, better feedback, and more consistent scoring across each challenge. Paid alot of attention to the smaller details from making the reaction test more precise to keeping the different tests feeling responsive and fair across different setups which makes Cognitive Arena feels less like a collection of mini games but more like a complete cognitive approximated testing experience . There are still plenty of things I could keep tweaking and later on i am planning to update this, but I think it’s finally at a point where it’s ready to be shared before upcoming cool updates like adding more tests or a progression chart to maoe it more challenging but right now its enough as a quick test of your cognitive skills
Ships:
A web based cognitive testing suite featuring five interactive benchmarks for reaction speed, aim training, visual memory, number memory, and a wpm test where users can test, track or imrpove their cognitive skills from these tests.Along the way the challenging part was improving the cognitive tests making it accurste enough,refining the test flow with clearer instructions, countdowns, and live wpm test for what the user types over it and getting the code right based on what i intented and accuracy tracking rigs for the grid shot .I still have plenty of ideas to add on to this like a better tracking chart or other accurate tests. Right now, the project feels fast, responsive, and accurate enough to stand on its own as an experience....
|
1793008161.9909537
|
1793094561.9909537
|
|
54225
|
YACK by @Definitly-Not-Me | Stardance
|
Definitly-Not-Me
|
1
|
57.5
|
186
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-22T18:45:35Z", "hours": 55.0, "multiplier": 3.44, "payout": 186, "blessing": "neutral", "text": "I tried to build a language model Model. My expectation were not high. I just hoped he would be multilingual (English + French + My Mother tongue) and that I would learn how LLMs works along the way. Overall the experience was pretty rewarding. Except for the Kaggle Part: This one, I hated it with passion. Due to monetary requirement both models are under-trained but they can produce coherent sentences. So I consider it a win. I’m hosting the project on my laptop so whoever review this: Don’t take your time >:( ** Just Kidding ☺️**", "repo": "https://github.com/Definitly-Not-Me/Patrick", "demo": "https://definitlynotme.site"}]...
|
[{"post_id": 75633, "ts": "202 [{"post_id": 75633, "ts": "2026-09-30T16:32:34Z", "hours": 2.0122, "text": "Dear shipwrights I don’t know if you’ll read this but I still feel like writing it since I’ve nothing else to write. In response to the feedback provided, here’s what changed: I deleted some part of my README as well as corrected grammar mistakes since it seemed to “contain” part written by AI. Honestly the grammar mistakes should’ve given me an alibi but … nevermind. I have patched garbage characters generation during inference. I truly hope that was the “ bug ” you mentioned in your review. If it was not, I’m afraid there’s not more I can do without spending ton of time/money on computing to improve my Language Model output (NOT chatbot). Which would be sad. Really sad. For the planet and for me. Detailed AI usage in the project description. I really hope the third time will pay home 🥲"}, {"post_id": 72678, "ts": "2026-09-23T13:59:13Z", "hours": 0.4858, "text": "Dear shipwrights My Cloudflared tunnel went down and I don’t know why. Thus the link in my shipping devlog is now invalid. I looked up if there was any way to get a more lasting url and all solutions I found were either paid services (domain name) or required a credit card. I have neither. I will wait for your message and try to improve networking skills for the next ship. Thanks for reading me. Sadly, @Definitly-Not-Me"}, {"post_id": 72349, "ts": "2026-09-22T18:37:55Z", "hours": 2.0403, "text": "Wait ! shipping require you to post a devlog ? Bad luck on top of bad luck. I found no cloud hosting platform that check all my requirements so for the time being, I’m a cloud provider :) For those who will review my project, I ask for your understanding. Nothing to show for this one. So here is picture of my Language Model mascot. Patrick Star"}, {"post_id": 71936, "ts": "2026-09-21T20:21:38Z", "hours": 10.3194, "text": "Last devlog before shipping: Against my best wishes, none of my models reached a usable state. Even though their best loss is quite low (2.94 and 2.81) I didn’t manage to reach the finetuning stage. To continue training I would have to start pouring money to get more compute power. And I don’t have that…. So that’ll be all. I will finish the UI and deploy locally first until I manage to find a vps before my project get a reviewer."}, {"post_id": 68777, "ts": "2026-09-15T18:51:37Z", "hours": 9.3614, "text": "Premature optimization is the root of all evils I still fell in the trap… I struggled for weeks to produce a model that can generate coherent text. Now all what is left is to ship or perhaps even fine-tune and be done. But nooooo, we need to atleast make PeRfOrmAnt . Ended adding some mods to the original GPT-2. I found that there’s even a whole community around this . I gained a lot from them. Now, the project is a Frankenstein DeepSeek . Time will tell if this was a good idea (-_-) Here’s a picture of the last training round. Things went quite well despite a bug affecting the learning rate."}, {"post_id": 65660, "ts": "2026-09-10T23:05:05Z", "hours": 1.6197, "text": "Updates and Bloopers Even though Kaggle runs on Google Collab, it turn out Collab is much more easier to use than Kaggle. To my grand deception, Collab is not as generous as Kaggle. So I will not change my workflow. I think I also need to change dataset. Also what’s up with Stardance and all those auxiliary events/challenges ?"}, {"post_id": 65020, "ts": "2026-09-09T20:25:25Z", "hours": 8.3361, "text": "Now we’re talking folks Reached a milestone. After nearly 10 hours of training on OpenwebText , the model can now formulate somewhat grammatically correct sentences. It’s not over though. Training was interrupted because apparently kaggle has a time limit for how long a notebook can run (on top on the weekly time limit). Sadly I have no interest in buying cloud compute for that, so I will just look for a richer dataset, reduce the number of epoch and crank up the learning rate."}, {"post_id": 63205, "ts": "2026-09-06T21:31:41Z", "hours": 4.2356, "text": "I’m tired boss Sorry, stardance but for my own good and sanity, I think I will have to give up or half bake this project. I really tried 😞"}, {"post_id": 59298, "ts": "2026-09-01T00:37:38Z", "hours": 3.1833, "text": "Two steps before the throne Finally deployed the training script to Kaggle. Now all there’s to be is wait and hope. A quick list of what’s new: Divided the training loop in many functions to handle dataloading, parsing, logging and more; Managed to find a copy of gutenberg books to serve as dataset; Implemented checkpoints in the training so that I will not lose all progress if I run out of compute; Dataloading is now done using np.memmap ensuring that only a portion of tokens are loaded in memory; Scaled the value of hyprparameters based on configuration of gpt-2 small (my main source is Chatgpt/GLM and a rough guess of number of epochs); Fixed a “ storage leak ” where the best model checkpoints where saved per epoch instead of overwriting previous one (totally my fault) Next: Fix my nonexistant git history while waiting for the training to finish"}, {"post_id": 58245, "ts": "2026-08-30T16:34:58Z", "hours": 7.7647, "text": "Small update on building a Language Model So after getting the architecture down and adding collecting some data, I started the training phase. That was one week ago …. Training is surprisingly (or not ?) actually more than just shoving in more data and expect it to work. Right now I’m struggling with finding sensible hyperparameters and getting the model to output something coherent. What’s new I mainly worked on the training loop and minor optimizations to hidden layers to distract myself while Pytorch was frying my APU. Of course there were also bugs in the code that had to fix on the way. For monitoring the training I decided to use plain TUI built with Rich but I’m currently adding a csv logging for better history tracking. At first I was planning to run the training on my laptop but I understood why billions dollar companies needed so many datacenters. Anyway, I deployed it on Kaggle which also was harder than it should be. Next Take a break, Improve training loop, Deploy on Kaggle Forget about it"}, {"post_id": 54745, "ts": "2026-08-25T20:38:12Z", "hours": 7.6444, "text": "Devlog 0: Build a Large/Small/Whatever LM Overview Hello Stardance! Hello world appetIntern disdainwartsnine . Those were the first words of my Language Model, am feeling so fogging proud right now. I’m trying to get into ML for the next year (not just because of the hype). For my first projects, I tried building a simple perceptron as well as understanding the algorithm behind Tic-Tac-Toe. Nothing grandiose. Why aim so high for my next project since I’m not that knowledgeable ? Because I’m short of time and there are full tutorial available, that’s all. Goal & MVP The MVP goal is to be able to generate coherent text (will probably be gibberish since I’m not a billion dollars corpo) and implement simple RAG to compensate for the lack of intelligence. I plan to upgrade it as I learn more about LLMs and Transformers. The Current State I just got the basic unoptimized architecture down. It tooks so much time to understand the Transformer architecture and all the maths that goes behind it (thanks to 3Blue1Brown it was manageable). Now I need to train & evaluate the “Advanced Autocomplete Machine” so that It can start acting more like GPT2. Picture: Liking my rice ? 😏"}]...
|
Title: YACK by @Definitly-Not-Me | Stardance
Devl Title: YACK by @Definitly-Not-Me | Stardance
Devlogs:
Devlog 0: Build a Large/Small/Whatever LM Overview Hello Stardance! Hello world appetIntern disdainwartsnine . Those were the first words of my Language Model, am feeling so fogging proud right now. I’m trying to get into ML for the next year (not just because of the hype). For my first projects, I tried building a simple perceptron as well as understanding the algorithm behind Tic-Tac-Toe. Nothing grandiose. Why aim so high for my next project since I’m not that knowledgeable ? Because I’m short of time and there are full tutorial available, that’s all. Goal & MVP The MVP goal is to be able to generate coherent text (will probably be gibberish since I’m not a billion dollars corpo) and implement simple RAG to compensate for the lack of intelligence. I plan to upgrade it as I learn more about LLMs and Transformers. The Current State I just got the basic unoptimized architecture down. It tooks so much time to understand the Transformer architecture and all the maths that goes behind it (thanks to 3Blue1Brown it was manageable). Now I need to train & evaluate the “Advanced Autocomplete Machine” so that It can start acting more like GPT2. Picture: Liking my rice ? 😏
Small update on building a Language Model So after getting the architecture down and adding collecting some data, I started the training phase. That was one week ago …. Training is surprisingly (or not ?) actually more than just shoving in more data and expect it to work. Right now I’m struggling with finding sensible hyperparameters and getting the model to output something coherent. What’s new I mainly worked on the training loop and minor optimizations to hidden layers to distract myself while Pytorch was frying my APU. Of course there were also bugs in the code that had to fix on the way. For monitoring the training I decided to use plain TUI built with Rich but I’m currently adding a csv logging for better history tracking. At first I was planning to run the training on my laptop but I understood why billions dollar companies needed so many datacenters. Anyway, I deployed it on Kaggle which also was harder than it should be. Next Take a break, Improve training loop, Deploy on Kaggle Forget about it
Two steps before the throne Finally deployed the training script to Kaggle. Now all there’s to be is wait and hope. A quick list of what’s new: Divided the training loop in many functions to handle dataloading, parsing, logging and more; Managed to find a copy of gutenberg books to serve as dataset; Implemented checkpoints in the training so that I will not lose all progress if I run out of compute; Dataloading is now done using np.memmap ensuring that only a portion of tokens are loaded in memory; Scaled the value of hyprparameters based on configuration of gpt-2 small (my main source is Chatgpt/GLM and a rough guess of number of epochs); Fixed a “ storage leak ” where the best model checkpoints where saved per epoch instead of overwriting previous one (totally my fault) Next: Fix my nonexistant git history while waiting for the training to finish
I’m tired boss Sorry, stardance but for my own good and sanity, I think I will have to give up or half bake this project. I really tried 😞
Now we’re talking folks Reached a milestone. After nearly 10 hours of training on OpenwebText , the model can now formulate somewhat grammatically correct sentences. It’s not over though. Training was interrupted because apparently kaggle has a time limit for how long a notebook can run (on top on the weekly time limit). Sadly I have no interest in buying cloud compute for that, so I will just look for a richer dataset, reduce the number of epoch and crank up the learning rate.
Updates and Bloopers Even though Kaggle runs on Google Collab, it turn out Collab is much more easier to use than Kaggle. To my grand deception, Collab is not as generous as Kaggle. So I will not change my workflow. I think I also need to change dataset. Also what’s up with Stardance and all those auxiliary events/challenges ?
Premature optimization is the root of all evils I still fell in the trap… I struggled for weeks to produce a model that can generate coherent text. Now all what is left is to ship or perhaps even fine-tune and be done. But nooooo, we need to atleast make PeRfOrmAnt . Ended adding some mods to the original GPT-2. I found that there’s even a whole community around this . I gained a lot from them. Now, the project is a Frankenstein DeepSeek . Time will tell if this was a good idea (-_-) Here’s a picture of the last training round. Things went quite well despite a bug affecting the learning rate.
Last devlog before shipping: Against my best wishes, none of my models reached a usable state. Even though their best loss is quite low (2.94 and 2.81) I didn’t manage to reach the finetuning stage. To continue training I would have to start pouring money to get more compute power. And I don’t have that…. So that’ll be all. I will finish the UI and deploy locally first until I manage to find a vps before my project get a reviewer.
Wait ! shipping require you to post a devlog ? Bad luck on top of bad luck. I found no cloud hosting platform that check all my requirements so for the time being, I’m a cloud provider :) For those who will review my project, I ask for your understanding. Nothing to show for this one. So here is picture of my Language Model mascot. Patrick Star
Dear shipwrights My Cloudflared tunnel went down and I don’t know why. Thus the link in my shipping devlog is now invalid. I looked up if there was any way to get a more lasting url and all solutions I found were either paid services (domain name) or required a credit card. I have neither. I will wait for your message and try to improve networking skills for the next ship. Thanks for reading me. Sadly, @Definitly-Not-Me
Dear shipwrights I don’t know if you’ll read this but I still feel like writing it since I’ve nothing else to write. In response to the feedback provided, here’s what changed: I deleted some part of my README as well as corrected grammar mistakes since it seemed to “contain” part written by AI. Honestly the grammar mistakes should’ve given me an alibi but … nevermind. I have patched garbage characters generation during inference. I truly hope that was the “ bug ” you mentioned in your review. If it was not, I’m afraid there’s not more I can do without spending ton of time/money on computing to improve my Language Model output (NOT chatbot). Which would be sad. Really sad. For the planet and for me. Detailed AI usage in the project description. I really hope the third time will pay home 🥲
Ships:
I tried to build a language model Model. My expectation were not high. I just hoped he would be multilingual (English + French + My Mother tongue) and that I would learn how LLMs works along the way. Overall the experience was pretty rewarding. Except for the Kaggle Part: This one, I hated it with passion. Due to monetary requirement both models are under-trained but they can produce coherent sentences. So I consider it a win. I’m hosting the project on my laptop so whoever review this: Don’t take your time >:( ** Just Kidding ☺️**...
|
1793008163.0882738
|
1793094563.0882738
|
|
54232
|
Birthday hunt by @Necry | Stardance
|
Necry
|
1
|
9.62
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-15T14:56:07Z", "hours": 9.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "This is honestly the hardest project I have ever made but it was fun. I am so ready for the next one(which is already started).", "repo": "https://github.com/necrymere/birthday-treasure-hunt", "demo": "https://necrymere.github.io/birthday-treasure-hunt/"}]...
|
[{"post_id": 73769, "ts": "202 [{"post_id": 73769, "ts": "2026-09-25T22:10:37Z", "hours": 0.2794, "text": "I remade parts of the CSS again. Please I am begging you to accept it this time as I do not want to spend too much on the design, again the game itself is the important part(which I am really proud of) not the design. This is one of the rare times I do not care that much about design but this looks nicer, I have to admit. Please if anything else is the matter tell me exactly what you feel is off(hopefully nothing). Genuinely I have no idea what to change. Also I learned how firebase works which is pretty cool."}, {"post_id": 72316, "ts": "2026-09-22T17:26:05Z", "hours": 0.3375, "text": "I fixed a few things about the README and design but it is quite annoying that they keep rejecting me cause of the design because it was not the focal point, playing the game is and I spent most of the time implementing the game and not focusing on the design. I did delete the border and I think it looks a bit better now. It looking like this is a design choice"}, {"post_id": 67632, "ts": "2026-09-13T19:39:24Z", "hours": 0.7811, "text": "I am so glad I am FINALLY done with the README. Now I can ship this project at last. It was fun but I am happy it is done."}, {"post_id": 67564, "ts": "2026-09-13T18:18:32Z", "hours": 1.3917, "text": "I decided to make my life harder by adding a gallery at the end with the photos of the missions. So many bugs but it was worth it. I started writing the readme and I am so happy I did it."}, {"post_id": 66889, "ts": "2026-09-12T20:45:56Z", "hours": 1.4214, "text": "I am sososo happy with myself. I finally finished after countless problems to link my database with the project for live approval of the photos. I am too happy about this. Oh also I decided to make a wall at the end with all the photos gathered on the mission so I will get to that next."}, {"post_id": 64924, "ts": "2026-09-09T17:22:12Z", "hours": 1.3994, "text": "So I am done with the game(I made the buttons match) and I added a end screen after all the missions are completed. Maybe I will finish this tomorrow."}, {"post_id": 55621, "ts": "2026-08-27T16:15:50Z", "hours": 1.6353, "text": "This was a bit faster and I am done with the game itself(I think) and now only maybe something at the end and also testing. Hopefully it works."}, {"post_id": 54449, "ts": "2026-08-25T13:59:24Z", "hours": 2.1542, "text": "Gosh did I really code that long? Oh well. All this time was spent trying to make a page as a joke. This is a page about the “AI” that is behind the site(actually me verifying all the images in real time). So glad I finished it. It has a minor glitch on the version but I will leave it as is. Call it a “stylistic choice”"}]...
|
Title: Birthday hunt by @Necry | Stardance
Devlog Title: Birthday hunt by @Necry | Stardance
Devlogs:
Gosh did I really code that long? Oh well. All this time was spent trying to make a page as a joke. This is a page about the “AI” that is behind the site(actually me verifying all the images in real time). So glad I finished it. It has a minor glitch on the version but I will leave it as is. Call it a “stylistic choice”
This was a bit faster and I am done with the game itself(I think) and now only maybe something at the end and also testing. Hopefully it works.
So I am done with the game(I made the buttons match) and I added a end screen after all the missions are completed. Maybe I will finish this tomorrow.
I am sososo happy with myself. I finally finished after countless problems to link my database with the project for live approval of the photos. I am too happy about this. Oh also I decided to make a wall at the end with all the photos gathered on the mission so I will get to that next.
I decided to make my life harder by adding a gallery at the end with the photos of the missions. So many bugs but it was worth it. I started writing the readme and I am so happy I did it.
I am so glad I am FINALLY done with the README. Now I can ship this project at last. It was fun but I am happy it is done.
I fixed a few things about the README and design but it is quite annoying that they keep rejecting me cause of the design because it was not the focal point, playing the game is and I spent most of the time implementing the game and not focusing on the design. I did delete the border and I think it looks a bit better now. It looking like this is a design choice
I remade parts of the CSS again. Please I am begging you to accept it this time as I do not want to spend too much on the design, again the game itself is the important part(which I am really proud of) not the design. This is one of the rare times I do not care that much about design but this looks nicer, I have to admit. Please if anything else is the matter tell me exactly what you feel is off(hopefully nothing). Genuinely I have no idea what to change. Also I learned how firebase works which is pretty cool.
Ships:
This is honestly the hardest project I have ever made but it was fun. I am so ready for the next one(which is already started)....
|
1793008164.275476
|
1793094564.275476
|
|
2593
|
Live Space Tracker (working title) by @dspace1015 Live Space Tracker (working title) by @dspace1015 | Stardance...
|
dspace1015
|
1
|
50.33
|
201
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-30T04:46:03Z", "hours": 48.0, "multiplier": 4.22, "payout": 201, "blessing": "neutral", "text": "I made a web app that lets you explore the positions of the planets in the solar system in real time. Change time with (< > /) keys to view the solar system in the past or future. Change your camera with the (c) key to view objects from their own orientation as they rotate around each other. Zoom out and see the positions of stars in our neighborhood. Plug in your home location on the map and you can view your own current night sky. Track the space station in low Earth orbit, and watch when it appears overhead.", "repo": "https://github.com/dspace1015/space", "demo": "https://dspace1015.github.io/space/"}]...
|
[{"post_id": 76034, "ts": "202 [{"post_id": 76034, "ts": "2026-10-02T04:28:06Z", "hours": 2.3267, "text": "Fixed some bugs that came up after launch Added text that when hovered shows controlls (most asked for feature) Fixed(mostly) the constant pop up bug, you may need to refresh the page once but it should be mostly gone by now"}, {"post_id": 75454, "ts": "2026-09-30T04:32:38Z", "hours": 3.7503, "text": "Final devlog for now, finished map view and added camera information I have added camera controls where you can change to view a planet from its own axis or rotation by pressing (c) to cycle through modes, and you can track objects by pressing (t). Also added more information on the ground view, light time calculation and finally the map view where once opened you can change your position by clicking on it."}, {"post_id": 74746, "ts": "2026-09-28T04:07:38Z", "hours": 8.5467, "text": "Finished all the continents, added saturns rings and and Mars and Jupiter’s moons. I have made decent progress, most of my time was spent debugging and optimizing since I’m only using the cpu to render everything. I also added more camera controls so that when you press (c) you can tilt the camera to match the planets axis tilt, or rotate along with it. The final parts I need to add at this point is a menu where you can choose your location and a information panel for the object that you select."}, {"post_id": 74325, "ts": "2026-09-27T05:34:21Z", "hours": 8.4517, "text": "Added continent outlines and object occlusion After spending way too much time trying to figure out webgl and three.js I decided that it was not worth the extra effort for slightly better graphics. Running out of time, I decided to stick to the system that I already had and decided to just draw the coastlines so you can make out the earths orientation better. Right now I have only added N&S America, Antarctica, and Australia. Ill add the rest later but for now this is what I got. Running out of time to ship this so I’m going to add a location selector and call this good."}, {"post_id": 40892, "ts": "2026-08-04T18:15:05Z", "hours": 2.5356, "text": "Added ground perspective and fixed stars Added a feature where you can select a position on the earth and view from there. You do have to manually add your latitude and longitude but eventually you will be able to select from a map or search for a specific city. (The demo shows London UK’s position so I don’t reveal my own) I also fixed the lag from the stars that was making the site slow, now it can display 3500 stars and all the other objects just fine."}, {"post_id": 11528, "ts": "2026-06-18T20:32:13Z", "hours": 5.48, "text": "Added grid based on your location, and stars from the Henry Draper (HD) catalogue. https://in-the-sky.org/data/catalogue.php?cat=HD&const=1&sort=1&view=1&page=1 Unfortunately now the framerate has dropped a lot, so I’ll need to figure out how to handle all the objects separately and only update the planets. Until then that’s enough programming for me today."}, {"post_id": 8955, "ts": "2026-06-14T22:02:27Z", "hours": 2.1864, "text": "Added TLE support https://en.wikipedia.org/wiki/Two-line_element_set (A common file format for earth orbit satellites). I’ve realized that I might have to switch to using a graphics api like webgl to improve the graphics from here, but for now I will focus on functionality. Better graphics should not matter at the moment from a ground level perspective."}, {"post_id": 7557, "ts": "2026-06-12T17:12:34Z", "hours": 6.3506, "text": "Finally added a way to read separate files into the web app. Objects are now stored in json files with all their orbital parameters and physical characteristics. Next steps for this project will be to start adding detail on the planets and reference frame transformations from your local position to space."}, {"post_id": 5140, "ts": "2026-06-08T20:33:11Z", "hours": 2.9439, "text": "You can now click on objects to select them. Orbits now also accurately precess. The moon’s orbit is now close enough to reality to predict solar eclipses, which is accurate enough for this project. All the inner rocky planet’s procession has been implemented as well according to NASA horizon’s approximation. They should now be reasonably accurate a few hundred yrs into the future. Next steps will be adding more objects like Jovian moons and spacecraft, as well as improving graphics."}, {"post_id": 2510, "ts": "2026-06-05T01:16:11Z", "hours": 3.0403, "text": "Added the main 8 planets in the solar system and a time control feature. You can now speed up, slow down, or reverse time to see the solar system on different dates, or reset to the current time. You can also scroll through the list of planets and watch from their perspective. As far as I can tell I succeeded in making the planets positions accurate (or at least enough for my project)."}, {"post_id": 1200, "ts": "2026-06-03T01:43:11Z", "hours": 0.8872, "text": "Added functionality for objects to orbit other objects. Progress is coming along nicely so far, all orbits of type e<1 are displayable and can be centered around any object. The next steps I plan on taking are plugging in the values for our actual solar system and switching camera controls to be centered on planets, then adding time control and other UI."}, {"post_id": 1103, "ts": "2026-06-02T22:39:41Z", "hours": 1.4622, "text": "I added mouse controls, Kepler’s 2nd law, and a grid that will come in handy for identifying places in the sky. Next I will continue to add features for adding celestial bodies and different spacecraft."}, {"post_id": 963, "ts": "2026-06-02T18:53:07Z", "hours": 0.8086, "text": "Added orbit calculations to the planetarium web app so I can start adding other objects in the display. A few more functions will need to be implemented but very soon I should be able to start plugging in data."}, {"post_id": 621, "ts": "2026-06-02T03:49:47Z", "hours": 1.2097, "text": "Starting the basic foundation of the web app, I plan on using only JavaScript and HTML5’s canvas to draw all the objects, using data from celestrack and NASA horizons to find all the data I need. Screenshot is just of a test of the basic 3d drawing function with axis visible. Because it is just night sky objects no fancy 3d engine will be needed."}]...
|
Title: Live Space Tracker (working title) by @dspa Title: Live Space Tracker (working title) by @dspace1015 | Stardance
Devlogs:
Starting the basic foundation of the web app, I plan on using only JavaScript and HTML5’s canvas to draw all the objects, using data from celestrack and NASA horizons to find all the data I need. Screenshot is just of a test of the basic 3d drawing function with axis visible. Because it is just night sky objects no fancy 3d engine will be needed.
Added orbit calculations to the planetarium web app so I can start adding other objects in the display. A few more functions will need to be implemented but very soon I should be able to start plugging in data.
I added mouse controls, Kepler’s 2nd law, and a grid that will come in handy for identifying places in the sky. Next I will continue to add features for adding celestial bodies and different spacecraft.
Added functionality for objects to orbit other objects. Progress is coming along nicely so far, all orbits of type e<1 are displayable and can be centered around any object. The next steps I plan on taking are plugging in the values for our actual solar system and switching camera controls to be centered on planets, then adding time control and other UI.
Added the main 8 planets in the solar system and a time control feature. You can now speed up, slow down, or reverse time to see the solar system on different dates, or reset to the current time. You can also scroll through the list of planets and watch from their perspective. As far as I can tell I succeeded in making the planets positions accurate (or at least enough for my project).
You can now click on objects to select them. Orbits now also accurately precess. The moon’s orbit is now close enough to reality to predict solar eclipses, which is accurate enough for this project. All the inner rocky planet’s procession has been implemented as well according to NASA horizon’s approximation. They should now be reasonably accurate a few hundred yrs into the future. Next steps will be adding more objects like Jovian moons and spacecraft, as well as improving graphics.
Finally added a way to read separate files into the web app. Objects are now stored in json files with all their orbital parameters and physical characteristics. Next steps for this project will be to start adding detail on the planets and reference frame transformations from your local position to space.
Added TLE support https://en.wikipedia.org/wiki/Two-line_element_set (A common file format for earth orbit satellites). I’ve realized that I might have to switch to using a graphics api like webgl to improve the graphics from here, but for now I will focus on functionality. Better graphics should not matter at the moment from a ground level perspective.
Added grid based on your location, and stars from the Henry Draper (HD) catalogue. https://in-the-sky.org/data/catalogue.php?cat=HD&const=1&sort=1&view=1&page=1 Unfortunately now the framerate has dropped a lot, so I’ll need to figure out how to handle all the objects separately and only update the planets. Until then that’s enough programming for me today.
Added ground perspective and fixed stars Added a feature where you can select a position on the earth and view from there. You do have to manually add your latitude and longitude but eventually you will be able to select from a map or search for a specific city. (The demo shows London UK’s position so I don’t reveal my own) I also fixed the lag from the stars that was making the site slow, now it can display 3500 stars and all the other objects just fine.
Added continent outlines and object occlusion After spending way too much time trying to figure out webgl and three.js I decided that it was not worth the extra effort for slightly better graphics. Running out of time, I decided to stick to the system that I already had and decided to just draw the coastlines so you can make out the earths orientation better. Right now I have only added N&S America, Antarctica, and Australia. Ill add the rest later but for now this is what I got. Running out of time to ship this so I’m going to add a location selector and call this good.
Finished all the continents, added saturns rings and and Mars and Jupiter’s moons. I have made decent progress, most of my time was spent debugging and optimizing since I’m only using the cpu to render everything. I also added more camera controls so that when you press (c) you can tilt the camera to match the planets axis tilt, or rotate along with it. The final parts I need to add at this point is a menu where you can choose your location and a information panel for the object that you select.
Final devlog for now, finished map view and added camera information I have added camera controls where you can change to view a planet from its own axis or rotation by pressing (c) to cycle through modes, and you can track objects by pressing (t). Also added more information on the ground view, light time calculation and finally the map view where once opened you can change your position by clicking on it.
Fixed some bugs that came up after launch Added text that when hovered shows controlls (most asked for feature) Fixed(mostly) the constant pop up bug, you may need to refresh the page once but it should be mostly gone by now
Ships:
I made a web app that lets you explore the positions of the planets in the solar system in real time. Change time with (< > /) keys to view the solar system in the past or future. Change your camera with the (c) key to view objects from their own orientation as they rotate around each other. Zoom out and see the positions of stars in our neighborhood. Plug in your home location on the map and you can view your own current night sky. Track the space station in low Earth orbit, and watch when it appears overhead....
|
1793008165.409136
|
1793094565.409136
|
|
20231
|
Tao - a wearable digital pet by @academicalvin | S Tao - a wearable digital pet by @academicalvin | Stardance...
|
academicalvin
|
1
|
0.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-24T03:29:03Z", "hours": 0.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I tried replicating this digital pet I’ve seen on the internet and I absolutely love it. It’s not as sensor packed as the real thing but Tao packs an IMU, round LCD screen, haptic motor, and a temperature sensor. When turned on, it has a fun little expressive face that reacts to the world around it. Shake it –> it’ll get dizzy Leave it alone –> it gets sleepy Drop it –> it feels that Move it around –> its eyes moves", "repo": "https://github.com/alvi-n/TaoTheWearableDigitalPet", "demo": ""}]...
|
[{"post_id": 24416, "ts": "202 [{"post_id": 24416, "ts": "2026-07-07T23:22:51Z", "hours": 1.25, "text": "Time skip - I finished all the CAD and code for the project and I think it’s about time to submit! I added a charzard silkscreen design and it looks pretty cool the case has a pretty big back for the battery but I guess it’s not too noticable the main thing i’m not too sure about is the schematic and pcb wiring but hopefully if the design comes back to be for a redo I can do that fast this was a really fun project and I’m suprised myself i was able to remain consistent with this project"}, {"post_id": 22293, "ts": "2026-07-04T18:01:39Z", "hours": 1.9775, "text": "Taking out the NFC, Retracing Everything This took a little too long. Turns out since I didn’t have a LCD screen footprint I didn’t really know where the middle of the screen would be relative to the rest of the PCB. When I put everything into my 3d modeling software (Shapr3d), I realized it would be better if the screen was directly in the middle of the pcb by making it vertical. Which ultimately means I have to retrace almost everything."}, {"post_id": 18122, "ts": "2026-06-29T04:08:06Z", "hours": 3.1003, "text": "Honestly, I do not think I can get past the cut Spent too long trying to figure out how to make my own NFC chip antenna and for the time I’m trying to rush this project I don’t think I can. I think I will end up using a module with header pins for it instead of making it myself, it’s really devastating but for the sake of maintaining my enjoyment throughout this project I’m going to lower my scope."}, {"post_id": 15494, "ts": "2026-06-25T05:55:08Z", "hours": 1.3628, "text": "PCB routing - continued So far I believe I setted up the temperature sensor, motor driver, and accelerometer well and by that, I mean just the capacitors and resistors. I’m planning on putting this esp32 on the back side where I’ll also keep the battery so it doesn’t interfere with the lcd screen. This has been quite fun so far."}, {"post_id": 15364, "ts": "2026-06-24T23:49:22Z", "hours": 0.5, "text": "Outlining my pcb Not much was done in these 30 minutes, just imported a drawing of the shape of the pet."}, {"post_id": 14894, "ts": "2026-06-24T05:50:35Z", "hours": 0.8503, "text": "A little bit of this and a little bit of that. Today I started on my actual PCB design and turns out it’s harder than I thought. My schematic is like a maze, some lines in my schematic going two directions. Figuring out the best way to put everything is definitely a challenge. Tomorrow, I’ll start working on the edge cuts first and try to get 50% of the pcb wired."}, {"post_id": 13558, "ts": "2026-06-22T06:08:19Z", "hours": 2.3167, "text": "Tao Now Has an Accelerometer, NFC Reader, and a Temperature Sensor all powered by the xiao esp-32 s3 I never realized how powerful development boards are. Last session, I took an hour trying to figure out how make a buck converter, battery charger, and an external usb-c connector -> turns out the xiao board does all of that for me. Now instead of focusing my time on the power managing side of my project which was really confusing for me, I could now focus on adding additional fun elements to my project such as a haptic motor and temperature sensor Overall this project has been pretty fun so far, next step is working on the pcb layout and thinking about the shape of my digital pet."}, {"post_id": 10451, "ts": "2026-06-17T05:41:13Z", "hours": 1.0139, "text": "No modules, everything on a PCB. I’ve been seeing these digital pet accessories, similar to a Tamagotchi, on my feed a lot and the company selling these were listing them for ~$300 and I thought “I could definitely make this myself”. These things interact with the environment with some basic sensors which gives the face a signal to change its animation. Turns out its wayy harder than I thought to make myself. considering my only hardware project I’ve made was a macropad. There is a lot of pieces and I obviously haven’t built anything like this ever. Instead of adding modules that hook up to a breadboard, I realized that all of those parts can be added to the PCB itself and it all starts with the chip. I looked for the best chip for each of the different features and looked at the schematic for each. The only chip with a datasheet that actually made sense was for the battery charger, the rest…it took a bit more work. Anyways tomorrow, I’m planning on trying to finish the schematics so make sure to follow!"}]...
|
Title: Tao - a wearable digital pet by @academical Title: Tao - a wearable digital pet by @academicalvin | Stardance
Devlogs:
No modules, everything on a PCB. I’ve been seeing these digital pet accessories, similar to a Tamagotchi, on my feed a lot and the company selling these were listing them for ~$300 and I thought “I could definitely make this myself”. These things interact with the environment with some basic sensors which gives the face a signal to change its animation. Turns out its wayy harder than I thought to make myself. considering my only hardware project I’ve made was a macropad. There is a lot of pieces and I obviously haven’t built anything like this ever. Instead of adding modules that hook up to a breadboard, I realized that all of those parts can be added to the PCB itself and it all starts with the chip. I looked for the best chip for each of the different features and looked at the schematic for each. The only chip with a datasheet that actually made sense was for the battery charger, the rest…it took a bit more work. Anyways tomorrow, I’m planning on trying to finish the schematics so make sure to follow!
Tao Now Has an Accelerometer, NFC Reader, and a Temperature Sensor all powered by the xiao esp-32 s3 I never realized how powerful development boards are. Last session, I took an hour trying to figure out how make a buck converter, battery charger, and an external usb-c connector -> turns out the xiao board does all of that for me. Now instead of focusing my time on the power managing side of my project which was really confusing for me, I could now focus on adding additional fun elements to my project such as a haptic motor and temperature sensor Overall this project has been pretty fun so far, next step is working on the pcb layout and thinking about the shape of my digital pet.
A little bit of this and a little bit of that. Today I started on my actual PCB design and turns out it’s harder than I thought. My schematic is like a maze, some lines in my schematic going two directions. Figuring out the best way to put everything is definitely a challenge. Tomorrow, I’ll start working on the edge cuts first and try to get 50% of the pcb wired.
Outlining my pcb Not much was done in these 30 minutes, just imported a drawing of the shape of the pet.
PCB routing - continued So far I believe I setted up the temperature sensor, motor driver, and accelerometer well and by that, I mean just the capacitors and resistors. I’m planning on putting this esp32 on the back side where I’ll also keep the battery so it doesn’t interfere with the lcd screen. This has been quite fun so far.
Honestly, I do not think I can get past the cut Spent too long trying to figure out how to make my own NFC chip antenna and for the time I’m trying to rush this project I don’t think I can. I think I will end up using a module with header pins for it instead of making it myself, it’s really devastating but for the sake of maintaining my enjoyment throughout this project I’m going to lower my scope.
Taking out the NFC, Retracing Everything This took a little too long. Turns out since I didn’t have a LCD screen footprint I didn’t really know where the middle of the screen would be relative to the rest of the PCB. When I put everything into my 3d modeling software (Shapr3d), I realized it would be better if the screen was directly in the middle of the pcb by making it vertical. Which ultimately means I have to retrace almost everything.
Time skip - I finished all the CAD and code for the project and I think it’s about time to submit! I added a charzard silkscreen design and it looks pretty cool the case has a pretty big back for the battery but I guess it’s not too noticable the main thing i’m not too sure about is the schematic and pcb wiring but hopefully if the design comes back to be for a redo I can do that fast this was a really fun project and I’m suprised myself i was able to remain consistent with this project
Ships:
I tried replicating this digital pet I’ve seen on the internet and I absolutely love it. It’s not as sensor packed as the real thing but Tao packs an IMU, round LCD screen, haptic motor, and a temperature sensor. When turned on, it has a fun little expressive face that reacts to the world around it. Shake it –> it’ll get dizzy Leave it alone –> it gets sleepy Drop it –> it feels that Move it around –> its eyes moves...
|
1793008166.6069274
|
1793094566.6069274
|
|
59107
|
Start Assistant by @kis904 | Stardance
|
kis904
|
1
|
31.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-23T07:07:24Z", "hours": 31.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "It is a program built in python, can record and perform user’s actions. It was hard to make the app look good and not like an old from the 90s. I’m proud of it as it’s now a working useful app.", "repo": "https://github.com/kis904/Start-Assistant", "demo": "https://github.com/kis904/Start-Assistant/releases/tag/StartAssistantv1"}]...
|
[{"post_id": 66883, "ts": "202 [{"post_id": 66883, "ts": "2026-09-12T20:38:02Z", "hours": 31.4297, "text": "hey everyone, I will copy the more important previous posts from Macondo. If you’re interested all posts are amonf the pictures as screenshots. You can also find plenty of logs on the project’s github page. 29th of July 2026 hey everyone, today I was experimenting a lot with speech recognition with python’s SpeechRecognition library and available Vosk offline engines. I found an example code on a guy’s vlog and modified it to my engine, but all I discovered is just that my laptop is too weak to run it so I guess that’s it. Unfortunately it took another 60 minutes to read github readme-s, the library’s documentation, vlogs, vosk’s official page just get to know that. Screenshots among the attachments. 3rd of July 2026 hey, I have a window a few buttons and a pop up window. My first and only feature yet is that it can change the size of the window based on user input and changes it’s config file that it handles itself. It was a hell a lot of work to make that config text file work… It always had some problem e.g. when it was writing the new settings it wanted string not list, or the \\n that signed a new line stayed there so it didn’t recognize the settings in the conf file or couldn’t apply it. To sum it up, it was a lot of time, but now I will work on its main feature."}]...
|
Title: Start Assistant by @kis904 | Stardance
Dev Title: Start Assistant by @kis904 | Stardance
Devlogs:
hey everyone, I will copy the more important previous posts from Macondo. If you’re interested all posts are amonf the pictures as screenshots. You can also find plenty of logs on the project’s github page. 29th of July 2026 hey everyone, today I was experimenting a lot with speech recognition with python’s SpeechRecognition library and available Vosk offline engines. I found an example code on a guy’s vlog and modified it to my engine, but all I discovered is just that my laptop is too weak to run it so I guess that’s it. Unfortunately it took another 60 minutes to read github readme-s, the library’s documentation, vlogs, vosk’s official page just get to know that. Screenshots among the attachments. 3rd of July 2026 hey, I have a window a few buttons and a pop up window. My first and only feature yet is that it can change the size of the window based on user input and changes it’s config file that it handles itself. It was a hell a lot of work to make that config text file work… It always had some problem e.g. when it was writing the new settings it wanted string not list, or the \n that signed a new line stayed there so it didn’t recognize the settings in the conf file or couldn’t apply it. To sum it up, it was a lot of time, but now I will work on its main feature.
Ships:
It is a program built in python, can record and perform user’s actions. It was hard to make the app look good and not like an old from the 90s. I’m proud of it as it’s now a working useful app....
|
1793008167.7809482
|
1793094567.7809482
|
|
21500
|
HCR2 Setups Guide by @Alloy | Stardance
|
Alloy
|
1
|
63.0
|
846
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-25T11:58:58Z", "hours": 63.0, "multiplier": 13.44, "payout": 846, "blessing": "neutral", "text": "I made a web based information app that shows setups for each vehicle and track combination in the time attack game mode of Hill Climb Racing 2 (HCR2). The hardest thing was all of the queries for specific statistics, and since some of them also filtered by world records I just made a function to make world record queries cleaner and less messy. A second major problem was the filters on the search page, at the start were just simple select elements but they only take one value so the user can’t filter by more than one of each at once, to fix this I wanted to add a checkbox to each option but selects don’t support that so I needed to break my entire css by switching to details elements and restyling them so they stack nicely like the select elements before.", "repo": "https://github.com/Alloy-MVP/HCR2-Setups-Guide", "demo": "https://frenchtoast.pythonanywhere.com/"}]...
|
[{"post_id": 73537, "ts": "202 [{"post_id": 73537, "ts": "2026-09-25T10:57:09Z", "hours": 0.8028, "text": "FINAL DEVLOG: Added the new parts; Echo and Amplifier, added another part slot, increasing it to 4 since all world records use 4 parts now instead of 3. Took 4 hours to insert the world record setups (only all vehicle world records) for all 197 tracks as of 25/9/2026."}, {"post_id": 73425, "ts": "2026-09-25T02:03:28Z", "hours": 4.7644, "text": "Fixed a bug where inserting setups with a negative number were getting through because they are the only inputs not validated by sqlalchemy. Changed the validation to use the database data instead of the lists at the top of the .py, and therefore also added every single vehicle, part, and track to replace it in the db. Installed pylint to help my code look cleaner and changed everything it was complaining about. Also cleared the database so its empty and added all of the in game tracks and vehicles to replace the test data."}, {"post_id": 52034, "ts": "2026-08-22T02:16:53Z", "hours": 2.0461, "text": "Changed the tuning parts on setups and search page to icons, reversed the order of setups on the setups page so recently added ones are shown at the top, added a max time limit (32 bit integer limit). Tons of bug fixes: the search filters now handle more than one value, checking “World Records” doesnt wipe other filters, filters arent wiped when the page reloads after searching for a setup, rows per page defaults to 50, fixed the settings returning the error statement if rows per page is empty."}, {"post_id": 51494, "ts": "2026-08-21T07:31:36Z", "hours": 0.7431, "text": "Small tweak to the backend validation for the settings inputs, database path is now relative instead of absolute, added a second SQLAlchemy error catcher on top of the python ones, removed the .venv so a new one is made when the repository is cloned. (now it should be runable)"}, {"post_id": 51359, "ts": "2026-08-20T23:45:02Z", "hours": 0.8308, "text": "Changed most of the lists to now use list comprehension, made the error handler handle every error code from 400 to 599. Updated the error page to not break the flow. The app is now fully runable (hopefully) with instructions on the readme."}, {"post_id": 50800, "ts": "2026-08-20T06:19:49Z", "hours": 2.0058, "text": "Added a clear filters button to the insert form, added a shadow to the home page title. Changed the backend for time to not allow times > 32 bit int limit, changed the rows per page setting to be able to type custom amounts while still suggesting 5,10,20,30,40,50 with back end validation. Added a small section in information about insert field parameters. The setups table order is now reversed so new inserts are shown at the top. Settings errors are now shown on pages. Cleaned up some backend validation, the error messages now dont show for empty fields, created a requrements.txt and a readme on how to run the app."}, {"post_id": 49273, "ts": "2026-08-17T23:45:16Z", "hours": 0.8703, "text": "Added a 404 error handler and images of tuning parts to replace the text."}, {"post_id": 47929, "ts": "2026-08-16T06:12:15Z", "hours": 3.1731, "text": "Finished most of the home page, added a information section with a video, added 3 containers with quick navigation links, statistics, and fastest times on the home page, also added a background."}, {"post_id": 47790, "ts": "2026-08-15T23:28:52Z", "hours": 1.8481, "text": "Made the button borders brighter to be more visible, changed the content backgrounds to a gradient. Changed the setups table to look identical to search. Added a delete button to the all setups table to easily delete specific setups."}, {"post_id": 47320, "ts": "2026-08-15T06:19:10Z", "hours": 4.9217, "text": "Big Update: Moved links to the right and added a settings menu, added a title, made all inputs and filters have hover effects. Settings menu has a toggle for light/dark theme, and a way to select how many rows are shown in all tables (default is 10). Changed all of the css colors to variables for the settings."}, {"post_id": 46610, "ts": "2026-08-13T23:34:27Z", "hours": 2.1578, "text": "Search bar now fully supports searching for more than one word."}, {"post_id": 45471, "ts": "2026-08-11T23:30:33Z", "hours": 1.6261, "text": "The player, vehicle, and track filters can all take more than one filter so the search page can now show results from multiple players, vehicles, and tracks."}, {"post_id": 43698, "ts": "2026-08-09T03:15:24Z", "hours": 2.5139, "text": "Revamped the css again, the insert and delete forms are being moved to the setups table. No screenshot until the next devlog because its a mess right now."}, {"post_id": 43069, "ts": "2026-08-08T04:14:05Z", "hours": 1.5303, "text": "Added a leaderboard for the most used part setups, Changed how the parts are submitted, they are now sorted so there cant be multiple setups of the same parts combination but different orders, duplicates will just reuse an already existing one."}, {"post_id": 42928, "ts": "2026-08-07T22:11:58Z", "hours": 2.7381, "text": "Added a script that counts how many wrs every single player has and displays on the leaderboard page. Made the player field autoselect a name if you type it with wrong capitalization, for example ndwg will autoswitch to Ndwg."}, {"post_id": 39258, "ts": "2026-08-02T03:35:36Z", "hours": 2.9344, "text": "Completely finished styling the search page, also changed the filters to details instead of select so i can use checkboxes inside."}, {"post_id": 39170, "ts": "2026-08-01T22:55:05Z", "hours": 0.7469, "text": "World records filter is fully finished"}, {"post_id": 38508, "ts": "2026-07-31T22:44:24Z", "hours": 3.4031, "text": "Finished the backend of the wr filter, the fastest time with x vehicle and y track is highlighted in yellow."}, {"post_id": 36188, "ts": "2026-07-28T03:29:06Z", "hours": 1.2111, "text": "Finally found out about back_populates, players that arent currently in a setup now get deleted."}, {"post_id": 35045, "ts": "2026-07-26T06:34:23Z", "hours": 1.4058, "text": "Styled the filters section, added hover styling for links, buttons, and table data."}, {"post_id": 34983, "ts": "2026-07-26T03:54:43Z", "hours": 3.9231, "text": "Completely restarted the css, started styling the search bar filters and navigation bar."}, {"post_id": 29886, "ts": "2026-07-17T01:32:40Z", "hours": 1.055, "text": "Changed the filters to only show players,tracks, and vehicles that actually have a setup. Made the vehicle and track filter setups by time (lowest to highes) so the first time (fastest) is at the top."}, {"post_id": 29282, "ts": "2026-07-16T02:58:34Z", "hours": 0.8175, "text": "Added warnings for invalid filters (changed the values using inspect)"}, {"post_id": 28723, "ts": "2026-07-15T05:01:13Z", "hours": 1.4858, "text": "Made the filter fields functional but are misssing back end validation"}, {"post_id": 26951, "ts": "2026-07-12T01:24:49Z", "hours": 2.71, "text": "Added a stats/search page and moved the search bar there, also added a way to filter by players and vehicles (unfuctional)."}, {"post_id": 21229, "ts": "2026-07-03T02:00:51Z", "hours": 1.4261, "text": "Added a search bar to filter specific setups but still has some bugs (first table is all data, second table is data from the search)"}, {"post_id": 19058, "ts": "2026-06-30T07:43:15Z", "hours": 1.2028, "text": "Made the delete table functional and removes rows from setups but not the sub tables where the individual data is."}, {"post_id": 16718, "ts": "2026-06-27T05:02:23Z", "hours": 2.5661, "text": "Added checks for duplicates, missing fields, and times automatically updates if a time that is faster than the previous for a specific setup is submitted. Automatically adds the data to the setups table and puts the individual field data into their respective tables as well."}, {"post_id": 15998, "ts": "2026-06-25T23:45:29Z", "hours": 2.5778, "text": "Added some back end validation checks and added a list to check if the track field matches what can actually be inserted, also used a jinja loop to make options for each individual track in the list for the form."}, {"post_id": 14169, "ts": "2026-06-23T04:56:34Z", "hours": 2.9508, "text": "Basic input form for the database if every field is filled and correct"}]...
|
Title: HCR2 Setups Guide by @Alloy | Stardance
De Title: HCR2 Setups Guide by @Alloy | Stardance
Devlogs:
Basic input form for the database if every field is filled and correct
Added some back end validation checks and added a list to check if the track field matches what can actually be inserted, also used a jinja loop to make options for each individual track in the list for the form.
Added checks for duplicates, missing fields, and times automatically updates if a time that is faster than the previous for a specific setup is submitted. Automatically adds the data to the setups table and puts the individual field data into their respective tables as well.
Made the delete table functional and removes rows from setups but not the sub tables where the individual data is.
Added a search bar to filter specific setups but still has some bugs (first table is all data, second table is data from the search)
Added a stats/search page and moved the search bar there, also added a way to filter by players and vehicles (unfuctional).
Made the filter fields functional but are misssing back end validation
Added warnings for invalid filters (changed the values using inspect)
Changed the filters to only show players,tracks, and vehicles that actually have a setup. Made the vehicle and track filter setups by time (lowest to highes) so the first time (fastest) is at the top.
Completely restarted the css, started styling the search bar filters and navigation bar.
Styled the filters section, added hover styling for links, buttons, and table data.
Finally found out about back_populates, players that arent currently in a setup now get deleted.
Finished the backend of the wr filter, the fastest time with x vehicle and y track is highlighted in yellow.
World records filter is fully finished
Completely finished styling the search page, also changed the filters to details instead of select so i can use checkboxes inside.
Added a script that counts how many wrs every single player has and displays on the leaderboard page. Made the player field autoselect a name if you type it with wrong capitalization, for example ndwg will autoswitch to Ndwg.
Added a leaderboard for the most used part setups, Changed how the parts are submitted, they are now sorted so there cant be multiple setups of the same parts combination but different orders, duplicates will just reuse an already existing one.
Revamped the css again, the insert and delete forms are being moved to the setups table. No screenshot until the next devlog because its a mess right now.
The player, vehicle, and track filters can all take more than one filter so the search page can now show results from multiple players, vehicles, and tracks.
Search bar now fully supports searching for more than one word.
Big Update: Moved links to the right and added a settings menu, added a title, made all inputs and filters have hover effects. Settings menu has a toggle for light/dark theme, and a way to select how many rows are shown in all tables (default is 10). Changed all of the css colors to variables for the settings.
Made the button borders brighter to be more visible, changed the content backgrounds to a gradient. Changed the setups table to look identical to search. Added a delete button to the all setups table to easily delete specific setups.
Finished most of the home page, added a information section with a video, added 3 containers with quick navigation links, statistics, and fastest times on the home page, also added a background.
Added a 404 error handler and images of tuning parts to replace the text.
Added a clear filters button to the insert form, added a shadow to the home page title. Changed the backend for time to not allow times > 32 bit int limit, changed the rows per page setting to be able to type custom amounts while still suggesting 5,10,20,30,40,50 with back end validation. Added a small section in information about insert field parameters. The setups table order is now reversed so new inserts are shown at the top. Settings errors are now shown on pages. Cleaned up some backend validation, the error messages now dont show for empty fields, created a requrements.txt and a readme on how to run the app.
Changed most of the lists to now use list comprehension, made the error handler handle every error code from 400 to 599. Updated the error page to not break the flow. The app is now fully runable (hopefully) with instructions on the readme.
Small tweak to the backend validation for the settings inputs, database path is now relative instead of absolute, added a second SQLAlchemy error catcher on top of the python ones, removed the .venv so a new one is made when the repository is cloned. (now it should be runable)
Changed the tuning parts on setups and search page to icons, reversed the order of setups on the setups page so recently added ones are shown at the top, added a max time limit (32 bit integer limit). Tons of bug fixes: the search filters now handle more than one value, checking “World Records” doesnt wipe other filters, filters arent wiped when the page reloads after searching for a setup, rows per page defaults to 50, fixed the settings returning the error statement if rows per page is empty.
Fixed a bug where inserting setups with a negative number were getting through because they are the only inputs not validated by sqlalchemy. Changed the validation to use the database data instead of the lists at the top of the .py, and therefore also added every single vehicle, part, and track to replace it in the db. Installed pylint to help my code look cleaner and changed everything it was complaining about. Also cleared the database so its empty and added all of the in game tracks and vehicles to replace the test data.
FINAL DEVLOG: Added the new parts; Echo and Amplifier, added another part slot, increasing it to 4 since all world records use 4 parts now instead of 3. Took 4 hours to insert the world record setups (only all vehicle world records) for all 197 tracks as of 25/9/2026.
Ships:
I made a web based information app that shows setups for each vehicle and track combination in the time attack game mode of Hill Climb Racing 2 (HCR2). The hardest thing was all of the queries for specific statistics, and since some of them also filtered by world records I just made a function to make world record queries cleaner and less messy. A second major problem was the filters on the search page, at the start were just simple select elements but they only take one value so the user can’t filter by more than one of each at once, to fix this I wanted to add a checkbox to each option but selects don’t support that so I needed to break my entire css by switching to details elements and restyling them so they stack nicely like the select elements before....
|
1793008168.6604137
|
1793094568.6604137
|
|
59117
|
Greatest Tab by @Vasilakos | Stardance
|
Vasilakos
|
1
|
3.56
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-12T17:25:21Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Finally finished my Web Tab and I am gonna say I am quite satisfied with everything I did! It’s extremely usable, has a lot of features and it looks good! I would love for people to try it and if you do, don’t be afraid to send me a message even if you hate it because any criticism is good criticism!", "repo": "https://github.com/Vasilakos1821/Greatest-Tab", "demo": "https://vasilakos1821.github.io/Greatest-Tab/"}]...
|
[{"post_id": 67287, "ts": "202 [{"post_id": 67287, "ts": "2026-09-13T11:09:03Z", "hours": 1.5639, "text": "Spent some time changing the front-end because the truth is I relied too much on Gemini and it was visible on the final result so I put some of my own pizzaz and changed a lot of the CSS code to make it more of my own. To be honest I like it way more now just because it looks way more like something that’s real and human."}, {"post_id": 66232, "ts": "2026-09-11T22:39:42Z", "hours": 2.0308, "text": "I spent some actual time on this today and had a nightmare trying to put the Google Calendar Api for seamless google calendar integration but I am gonna currently give up on that and just make it so you export your google calendar as a file and input into the tab. Other than that I think I am very close to achieving my goal on making it very usable and nice so can’t wait to finish this tomorrow!"}, {"post_id": 64349, "ts": "2026-09-08T17:29:08Z", "hours": 0.3197, "text": "Just started on this tab and putting some boilerplate code gonna try to make it real nice and actually usable."}]...
|
Title: Greatest Tab by @Vasilakos | Stardance
Dev Title: Greatest Tab by @Vasilakos | Stardance
Devlogs:
Just started on this tab and putting some boilerplate code gonna try to make it real nice and actually usable.
I spent some actual time on this today and had a nightmare trying to put the Google Calendar Api for seamless google calendar integration but I am gonna currently give up on that and just make it so you export your google calendar as a file and input into the tab. Other than that I think I am very close to achieving my goal on making it very usable and nice so can’t wait to finish this tomorrow!
Spent some time changing the front-end because the truth is I relied too much on Gemini and it was visible on the final result so I put some of my own pizzaz and changed a lot of the CSS code to make it more of my own. To be honest I like it way more now just because it looks way more like something that’s real and human.
Ships:
Finally finished my Web Tab and I am gonna say I am quite satisfied with everything I did! It’s extremely usable, has a lot of features and it looks good! I would love for people to try it and if you do, don’t be afraid to send me a message even if you hate it because any criticism is good criticism!...
|
1793008169.9509337
|
1793094569.9509337
|
|
1836
|
Thought Galaxy by @Jewelia | Stardance
|
Jewelia
|
1
|
10.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-08T22:53:59Z", "hours": 10.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "We are finally shipping! This summer, I tried making my first website with React! I was really tired of all the ads in diary apps, writing in journals took a long time, and I wanted the aesthetic of a nice diary website rather than a plain google doc. This is my result for now, I will definitely keep developing it when I have more time in the future as it’s quite basic (my first time learning CSS) This is the DIARY FRONTEND ONLY so entries you make will not save on reload. My goal for the future is to be able to make a backend so you can make accounts. The original goal was to also have a place for to-do lists but that hasn’t been developed yet. (I ended up focusing a lot on my collaborative game project which took up most my time; go check it out if you haven’t already!)", "repo": "https://github.com/julia-duck/ThoughtGalaxy", "demo": "https://thoughtgalaxy.onrender.com/"}]...
|
[{"post_id": 70300, "ts": "202 [{"post_id": 70300, "ts": "2026-09-18T21:59:22Z", "hours": 1.2722, "text": "Hello Again! Back with a few tweaks and updates! I fixed the weird bugs where it would change multiple entries and also the bug where there would be a line you could see behind the expanded entry! I made it so that the “discard changes” button only appears when you make changes. (This has to do with the fact that I made it so that you can’t save entries that aren’t titled) I also started on the search function. But it will only give an alert with what you searched for testing purposes; I want to wait until we have a backend to implement that actual functionality. Thanks for reading!! I’m hoping I can ship the frontend of this for you all to test out, although I won’t have time to make the backend until school gets less stressful!"}, {"post_id": 66669, "ts": "2026-09-12T15:10:56Z", "hours": 4.6636, "text": "New Frontend Features! The sticker streak motivated me to keep adding a little bit by bit to my diary project even though school has started. 🥳 So, what’s new? New Entries ! In the past, clicking “New Entry” would just open the old entry. Now it adds a fresh new entry to your list of entries! Entry List As you make new entries, it will show all of your entries in concise boxes for you to scroll through, displaying the title and date. Discard Changes A fancy new button that will close your entry without saving your changes Arrow Buttons The newest addition yet that I’ve been meaning to do: adding arrows that let you click through your entries! Now VSCode will stop bugging me about my unused variables haha So, what’s next? Bug Fixes Unfortunately, the bug where saving an entry causes others to become duplicates of it has arose again and must be smashed Deleting Entries Shouldn’t be too hard, just gotta leave stuff for future me to do Search Function Eventually I want to be able to search for entries at least by title Backend One day I will get to it…so I can finally save my entries on browser reload…"}, {"post_id": 32130, "ts": "2026-07-21T02:43:49Z", "hours": 3.3975, "text": "I’ve gotten started on adding the ability of entries to pre-populate stored text (title and body). Since I haven’t implemented a backend yet (sooo I kinda got a bit carried away working on Boba Cats! And this project hasn’t gotten as much love and attention…but I’m hoping to get it working eventually!), I used a temporary entry variable for testing purposes (you can see it in the code if you take a careful look!) And yes, I shared a screenshot of the code this time instead of the actual site since there’s not much change in the visuals of the site! Next, I’m working on adding a date function (but the element is in the wrong place! So I won’t show until I fix it haha)"}, {"post_id": 362, "ts": "2026-06-01T18:12:12Z", "hours": 0.7664, "text": "Fixed problems so website can be deployed, added functionality to close button for entries For background, I started this project the month before June. It was very basic though, I didn’t get too much done… because most of the time spent was battling the error of the blank screen of death! It had something to do with dependencies not being installed and NavLink (which I was using to have different pages for the main page, diary, and to-do list) acting up. But I figured it out eventually!"}]...
|
Title: Thought Galaxy by @Jewelia | Stardance
Dev Title: Thought Galaxy by @Jewelia | Stardance
Devlogs:
Fixed problems so website can be deployed, added functionality to close button for entries For background, I started this project the month before June. It was very basic though, I didn’t get too much done… because most of the time spent was battling the error of the blank screen of death! It had something to do with dependencies not being installed and NavLink (which I was using to have different pages for the main page, diary, and to-do list) acting up. But I figured it out eventually!
I’ve gotten started on adding the ability of entries to pre-populate stored text (title and body). Since I haven’t implemented a backend yet (sooo I kinda got a bit carried away working on Boba Cats! And this project hasn’t gotten as much love and attention…but I’m hoping to get it working eventually!), I used a temporary entry variable for testing purposes (you can see it in the code if you take a careful look!) And yes, I shared a screenshot of the code this time instead of the actual site since there’s not much change in the visuals of the site! Next, I’m working on adding a date function (but the element is in the wrong place! So I won’t show until I fix it haha)
New Frontend Features! The sticker streak motivated me to keep adding a little bit by bit to my diary project even though school has started. 🥳 So, what’s new? New Entries ! In the past, clicking “New Entry” would just open the old entry. Now it adds a fresh new entry to your list of entries! Entry List As you make new entries, it will show all of your entries in concise boxes for you to scroll through, displaying the title and date. Discard Changes A fancy new button that will close your entry without saving your changes Arrow Buttons The newest addition yet that I’ve been meaning to do: adding arrows that let you click through your entries! Now VSCode will stop bugging me about my unused variables haha So, what’s next? Bug Fixes Unfortunately, the bug where saving an entry causes others to become duplicates of it has arose again and must be smashed Deleting Entries Shouldn’t be too hard, just gotta leave stuff for future me to do Search Function Eventually I want to be able to search for entries at least by title Backend One day I will get to it…so I can finally save my entries on browser reload…
Hello Again! Back with a few tweaks and updates! I fixed the weird bugs where it would change multiple entries and also the bug where there would be a line you could see behind the expanded entry! I made it so that the “discard changes” button only appears when you make changes. (This has to do with the fact that I made it so that you can’t save entries that aren’t titled) I also started on the search function. But it will only give an alert with what you searched for testing purposes; I want to wait until we have a backend to implement that actual functionality. Thanks for reading!! I’m hoping I can ship the frontend of this for you all to test out, although I won’t have time to make the backend until school gets less stressful!
Ships:
We are finally shipping! This summer, I tried making my first website with React! I was really tired of all the ads in diary apps, writing in journals took a long time, and I wanted the aesthetic of a nice diary website rather than a plain google doc. This is my result for now, I will definitely keep developing it when I have more time in the future as it’s quite basic (my first time learning CSS) This is the DIARY FRONTEND ONLY so entries you make will not save on reload. My goal for the future is to be able to make a backend so you can make accounts. The original goal was to also have a place for to-do lists but that hasn’t been developed yet. (I ended up focusing a lot on my collaborative game project which took up most my time; go check it out if you haven’t already!)...
|
1793008171.1251595
|
1793094571.1251595
|
|
59128
|
CHRONO // BLINK by @Ander507 | Stardance
|
Ander507
|
1
|
10.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-15T14:06:21Z", "hours": 10.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "What I made CHRONO BLINK is a top-down HTML5 arena where time only flows when you move. Stand still and the world crawls at 0.08×. Start moving and it wakes up. Your only attack is a blink-dash: a short invulnerable lunge. Slice an enemy and the dash refunds. Miss and you sit in 1.2s of lockout. The whole game is one canvas in one index.html . No engine, no build, no install. What was challenging Getting the time scale to feel like a mechanic instead of a pause. A hard stop looks broken. It had to lerp, and combos / dash cooldown still run on real seconds so you cannot hide in slow-mo forever. Phone was the other fight. Glow, scanlines, and chromatic aberration were eating frames, so DPR is capped, scanlines are a 1×4 pattern instead of a fill per row, and the RGB split only composites while the punch is actually on screen. Dash distance is capped so the landing reticle stays on screen. On rotate, resize waits ~120ms because mobile browsers still report the old viewport if you measure on the orientation event. Shop layout had to reflow too: two columns in short landscape, stacked in portrait, or the buttons become un-tappable. What I’m proud of The loop actually clicks. You freeze, the arena goes quiet, you pick a line, you blink through a stalker and the dash comes back. That moment is the whole game. Also that it runs from a local file on desktop and thumbs on a phone, with AZERTY as first-class, not an afterthought. CrazyGames SDK only loads on CrazyGames (or localhost / ?cg=1 ). Everywhere else it just uses localStorage and never fetches it. How to test Clone the repo and open index.html . Double-click is enough. file:// works. Stand still. Time should crawl. Move. The arena should speed up. Blink through something (refund). Miss on purpose (1.2s lockout). Desktop: WASD, ZQSD, or arrows. Blink with Space or right-click toward the reticle. M mutes. X skips the tutorial. Phone: left thumb to move, right-side drag then release to blink. First run has a skippable tutorial. Coins bank into Reach / Recovery / Magnet between deaths. Progress lives in localStorage ( chronoBlink.* ) if you want a fresh start.", "repo": "", "demo": ""}]...
|
[{"post_id": 68653, "ts": "202 [{"post_id": 68653, "ts": "2026-09-15T13:58:58Z", "hours": 2.4931, "text": "Devlog #4 Published to crazy games and to a domain https://chronoblink.xyz/ rn waiting for aproval for"}, {"post_id": 68057, "ts": "2026-09-14T13:21:30Z", "hours": 5.6639, "text": "Devlog #3 Added two gameplay videos this week: landscape and portrait. The covers look fine but they don’t show the actual hook. Time slows down when you stop moving. That’s hard to get from a still image, so I recorded some real runs instead of another screenshot. I did both orientations because the game isn’t the same crop on a phone. Desktop is mouse + WASD (ZQSD works too), blink with space or right click. Phone is left thumb to move and right drag to blink. The HUD and shop reflow with the screen — landscape can split the death screen into two columns, portrait stacks so the buttons stay tappable. One horizontal trailer cropped vertical would just look wrong. The clips are just me playing. I stand still for a second so you can see the slow-mo, blink through a stalker (that refunds the dash), miss one so the 1.2s cooldown is obvious, then some gunners / phantoms, coins, and the shop. I left a bit of the phone tutorial in (hold still, then drag & release) since that’s what you actually need on mobile. That’s the whole update. Videos are on the page if you want to see it moving."}, {"post_id": 67365, "ts": "2026-09-13T13:28:30Z", "hours": 1.1092, "text": "Devlog #2 Made the main menu and a little gameplay (not really good right now very goofy physics) and found the design i wanna use"}, {"post_id": 63145, "ts": "2026-09-06T19:45:32Z", "hours": 0.5339, "text": "Devlog #1 First i started making a mindmap and planing the game out and made the index.html file The other default files does not count and the readme also wont count cause its not a part of the game Goal: Fun Easy to understand Can be published on Crazy Games with ads later"}]...
|
Title: CHRONO // BLINK by @Ander507 | Stardance
D Title: CHRONO // BLINK by @Ander507 | Stardance
Devlogs:
Devlog #1 First i started making a mindmap and planing the game out and made the index.html file The other default files does not count and the readme also wont count cause its not a part of the game Goal: Fun Easy to understand Can be published on Crazy Games with ads later
Devlog #2 Made the main menu and a little gameplay (not really good right now very goofy physics) and found the design i wanna use
Devlog #3 Added two gameplay videos this week: landscape and portrait. The covers look fine but they don’t show the actual hook. Time slows down when you stop moving. That’s hard to get from a still image, so I recorded some real runs instead of another screenshot. I did both orientations because the game isn’t the same crop on a phone. Desktop is mouse + WASD (ZQSD works too), blink with space or right click. Phone is left thumb to move and right drag to blink. The HUD and shop reflow with the screen — landscape can split the death screen into two columns, portrait stacks so the buttons stay tappable. One horizontal trailer cropped vertical would just look wrong. The clips are just me playing. I stand still for a second so you can see the slow-mo, blink through a stalker (that refunds the dash), miss one so the 1.2s cooldown is obvious, then some gunners / phantoms, coins, and the shop. I left a bit of the phone tutorial in (hold still, then drag & release) since that’s what you actually need on mobile. That’s the whole update. Videos are on the page if you want to see it moving.
Devlog #4 Published to crazy games and to a domain https://chronoblink.xyz/ rn waiting for aproval for
Ships:
What I made CHRONO BLINK is a top-down HTML5 arena where time only flows when you move. Stand still and the world crawls at 0.08×. Start moving and it wakes up. Your only attack is a blink-dash: a short invulnerable lunge. Slice an enemy and the dash refunds. Miss and you sit in 1.2s of lockout. The whole game is one canvas in one index.html . No engine, no build, no install. What was challenging Getting the time scale to feel like a mechanic instead of a pause. A hard stop looks broken. It had to lerp, and combos / dash cooldown still run on real seconds so you cannot hide in slow-mo forever. Phone was the other fight. Glow, scanlines, and chromatic aberration were eating frames, so DPR is capped, scanlines are a 1×4 pattern instead of a fill per row, and the RGB split only composites while the punch is actually on screen. Dash distance is capped so the landing reticle stays on screen. On rotate, resize waits ~120ms because mobile browsers still report the old viewport if you measure on the orientation event. Shop layout had to reflow too: two columns in short landscape, stacked in portrait, or the buttons become un-tappable. What I’m proud of The loop actually clicks. You freeze, the arena goes quiet, you pick a line, you blink through a stalker and the dash comes back. That moment is the whole game. Also that it runs from a local file on desktop and thumbs on a phone, with AZERTY as first-class, not an afterthought. CrazyGames SDK only loads on CrazyGames (or localhost / ?cg=1 ). Everywhere else it just uses localStorage and never fetches it. How to test Clone the repo and open index.html . Double-click is enough. file:// works. Stand still. Time should crawl. Move. The arena should speed up. Blink through something (refund). Miss on purpose (1.2s lockout). Desktop: WASD, ZQSD, or arrows. Blink with Space or right-click toward the reticle. M mutes. X skips the tutorial. Phone: left thumb to move, right-side drag then release to blink. First run has a skippable tutorial. Coins bank into Reach / Recovery / Magnet between deaths. Progress lives in localStorage ( chronoBlink.* ) if you want a fresh start....
|
1793008172.2513978
|
1793094572.2513978
|