|
64430
|
Void Run by @rayyans4890 | Stardance
|
rayyans4890
|
1
|
24.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-19T17:33:38Z", "hours": 24.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Void Run is a 2D browser shooter I made for Stardance. You play as a ship in space and shoot aliens that keep coming at you. There are 3 enemy types: Drifter, Stinger and Brute. Stingers show up from wave 2 and Brutes from wave 4. A new wave starts every 25 seconds and the enemies spawn faster each time, so the game keeps getting harder. The hardest part was the JavaScript. The movement and shooting took a while to get working, and the title screen took a lot longer than I expected. I used AI to help with the sectioning of the title screen in a few places, but most of the code is my own. I’m proud that I finished it. I built the HUD, the menus, the three enemies and the wave system myself, and it works on a phone too. To test it, press Play or Enter to start. Move with WASD or the arrow keys, shoot with Space or the mouse, and press P to pause. Your best score is saved in your browser, so try to beat it.", "repo": "https://github.com/rayyans4890-png/Void-Run", "demo": "https://rayyans4890-png.github.io/Void-Run/"}]...
|
[{"post_id": 81015, "ts": "202 [{"post_id": 81015, "ts": "2026-10-19T16:18:36Z", "hours": 8.7747, "text": "Devlog 4: Final Version The game is finished. The JavaScript is fully complete and the final CSS file is done. I added 3 enemy types to the game, Drifter, Stinger and Brute, and I’m very satisfied with the result. The title screen was also updated with a new tagline and a bit more information, and the HUD now shows the best score and the current wave. The waves get faster as you play, so the game gets harder the longer you survive. Completed JavaScript Final CSS 3 enemies Final title screen and HUD Remaining Write the README Upload the project to GitHub Ship the project Next steps Only the README is left. I will write it, upload everything to GitHub and then ship the project. I really hope it gets a good rating, since my goal is the Aula F75 keyboard."}, {"post_id": 77833, "ts": "2026-10-08T13:27:17Z", "hours": 4.6917, "text": "Devlog 3: JavaScript I finally wrote the JavaScript. The main movement and shooting are now working, and enemies appear on the screen. The game is playable for the first time, even though it is still rough. The boss keeps giving me problems and I could not get it to work properly. I decided to leave it for later instead of wasting more time on it today. Another issue is that the ship can only move left and right along a horizontal line. I plan to change this so it moves freely in every direction while you control it. Completed Main JavaScript Shooting Movement (horizontal only for now) Enemies showing on screen Pause button Known issues The boss is not working properly The ship can only move along a horizontal line Remaining Fix the boss Add free movement in all directions Next steps Fixing the movement comes first, since it affects how the whole game feels. Then I will go back to the boss."}, {"post_id": 77202, "ts": "2026-10-06T02:31:58Z", "hours": 7.305, "text": "Devlog 2: Title Screen The title screen is finally finished. It took a lot longer than I expected, but I’m happy with how clean it looks. I used AI to help me with the sectioning of the title screen in a few places, but most of the code was written by me. The screen now has the Void Run logo, the tagline, and a Play button. You can also press Enter to start. The HUD shows the score, hull, best score and wave number. At the bottom there is a controls bar and a list of the enemy types, which are Drifter, Stinger and Brute. Completed Title screen with logo and tagline Play button and Enter shortcut HUD layout Controls bar and enemy list HTML and CSS Remaining JavaScript Next steps Only the JavaScript is left. That includes movement, shooting and the enemies. I will try to finish it tomorrow."}, {"post_id": 76178, "ts": "2026-10-02T16:26:20Z", "hours": 2.8008, "text": "Devlog 1: Project Start I started working on Void Run today. It is a 2D browser shooter set in space, where you play as a ship shooting aliens that are coming at you. The idea is simple on purpose, and I want to keep it that way so I can actually finish it. For now I focused on the base of the project. I set up the styles with a dark theme and built the basic HUD and the title screen. I wanted the layout in place first so the game logic has something to sit on later. Completed Project setup Basic HUD Title screen Base styles in style.css Remaining Player movement Shooting mechanics Main game design Next steps Later today I will start on movement, shooting and the main design of the game. After that I can begin adding the aliens."}]...
|
Title: Void Run by @rayyans4890 | Stardance
Devlo Title: Void Run by @rayyans4890 | Stardance
Devlogs:
Devlog 1: Project Start I started working on Void Run today. It is a 2D browser shooter set in space, where you play as a ship shooting aliens that are coming at you. The idea is simple on purpose, and I want to keep it that way so I can actually finish it. For now I focused on the base of the project. I set up the styles with a dark theme and built the basic HUD and the title screen. I wanted the layout in place first so the game logic has something to sit on later. Completed Project setup Basic HUD Title screen Base styles in style.css Remaining Player movement Shooting mechanics Main game design Next steps Later today I will start on movement, shooting and the main design of the game. After that I can begin adding the aliens.
Devlog 2: Title Screen The title screen is finally finished. It took a lot longer than I expected, but I’m happy with how clean it looks. I used AI to help me with the sectioning of the title screen in a few places, but most of the code was written by me. The screen now has the Void Run logo, the tagline, and a Play button. You can also press Enter to start. The HUD shows the score, hull, best score and wave number. At the bottom there is a controls bar and a list of the enemy types, which are Drifter, Stinger and Brute. Completed Title screen with logo and tagline Play button and Enter shortcut HUD layout Controls bar and enemy list HTML and CSS Remaining JavaScript Next steps Only the JavaScript is left. That includes movement, shooting and the enemies. I will try to finish it tomorrow.
Devlog 3: JavaScript I finally wrote the JavaScript. The main movement and shooting are now working, and enemies appear on the screen. The game is playable for the first time, even though it is still rough. The boss keeps giving me problems and I could not get it to work properly. I decided to leave it for later instead of wasting more time on it today. Another issue is that the ship can only move left and right along a horizontal line. I plan to change this so it moves freely in every direction while you control it. Completed Main JavaScript Shooting Movement (horizontal only for now) Enemies showing on screen Pause button Known issues The boss is not working properly The ship can only move along a horizontal line Remaining Fix the boss Add free movement in all directions Next steps Fixing the movement comes first, since it affects how the whole game feels. Then I will go back to the boss.
Devlog 4: Final Version The game is finished. The JavaScript is fully complete and the final CSS file is done. I added 3 enemy types to the game, Drifter, Stinger and Brute, and I’m very satisfied with the result. The title screen was also updated with a new tagline and a bit more information, and the HUD now shows the best score and the current wave. The waves get faster as you play, so the game gets harder the longer you survive. Completed JavaScript Final CSS 3 enemies Final title screen and HUD Remaining Write the README Upload the project to GitHub Ship the project Next steps Only the README is left. I will write it, upload everything to GitHub and then ship the project. I really hope it gets a good rating, since my goal is the Aula F75 keyboard.
Ships:
Void Run is a 2D browser shooter I made for Stardance. You play as a ship in space and shoot aliens that keep coming at you. There are 3 enemy types: Drifter, Stinger and Brute. Stingers show up from wave 2 and Brutes from wave 4. A new wave starts every 25 seconds and the enemies spawn faster each time, so the game keeps getting harder. The hardest part was the JavaScript. The movement and shooting took a while to get working, and the title screen took a lot longer than I expected. I used AI to help with the sectioning of the title screen in a few places, but most of the code is my own. I’m proud that I finished it. I built the HUD, the menus, the three enemies and the wave system myself, and it works on a phone too. To test it, press Play or Enter to start. Move with WASD or the arrow keys, shoot with Space or the mouse, and press P to pause. Your best score is saved in your browser, so try to beat it....
|
1792857132.190074
|
1793721132.190074
|
|
67845
|
BrainF#ckery Compiler by @mindstormpro3 | Stardanc BrainF#ckery Compiler by @mindstormpro3 | Stardance...
|
mindstormpro3
|
0
|
5.43
|
0
|
[]
|
[{"post_id": 81025, "ts": "202 [{"post_id": 81025, "ts": "2026-10-19T16:25:31Z", "hours": 2.5642, "text": "BrainF#ckery Devlog #3! What’s Changed? Well… I added command line arguments!!! Gone are the days of manually typing your BF code into the terminal, now you can specify and input and output file, as well as pass flags! I also published to PyPi!!! Find it Here! On top of all that, I also made a bunch of small changes and modifications to fix bugs and make my compiler work better. Command Line Args! Here’s the current full list: -h , or --Help -> Your basic help command, don’t need to say much here -v , or --Verbose -> Enables verbose (extra) logging -i or --Input -> Takes a file path as an input file (a .bf file) -o or --Output -> Takes a file path to be the outputted executable (a .exe file)| -r or --Run -> Runs the newly compiled executable right after it’s done being compiled. c or --Clean -> deletes the build files ( .obj and .asm product files) after compilation is complete ***And hopefully more to come! I already have some ideas! : b WE’RE ON PYPI!!!!!!!!!! Check it out HERE!!! And finally, the boring bugfixes… :( A couple things: I realized, after a very smart friend of mine pointed it out, that I was not popping the stack after pushing it to call a function… If I left this in, more complex programs would crash due to a stack overflow…. I added comment clearing! Originally, the compiler would only read BF code that happened to be one of the 8 valid characters, but what if you happened to put a valid BF char in a comment? Well now there’s a loop that runs before the rest of the compiler that strips all lines of their text after a ; character, meaning all comments get deleted! I also added more error handling, so in case of a file not found or something, instead of the code crashing it just prints an error to the logs and returns. Thanks for sticking around for my devlog! see ya next time! : b"}, {"post_id": 77560, "ts": "2026-10-07T14:07:07Z", "hours": 2.4694, "text": "BrainF#ckery Devlog #2! What’s Changed? A LOT! Since the last devlog, I’ve practically finished the BF -> Assembly compiler, and even used subprocess.run() to call NASM and GCC to build the script! It currently looks for a file called in.bf and then compiles it into an EXE that gets dumped straight into a build/ folder along with the out.asm and out.obj files! How does the Compiler actually work? Right now, all the compiler really does is go character by character in the input file, and if the character is one of the special 8, ( <>+-,.[] ) I just append some assembly into the out.asm file that corresponds with the instruction. For example, for + I just add inc byte [ebx] which increments the byte stored at the location the EBX register is pointing at. (EBX stores the tape pointer, and you manipulate it with < and > ). The cool thing about writing the compiler like this is that it literally just ignores everything else, so I don’t have to write code to “clean” the input file of newlines, tabs, spaces, comments, ect. Now for [ and ] , they’re a bit special. The way these guys work is I have a stack and counter. Whenever I add a [ to the assembly, I first increment the counter by 1 and then push the value to the stack. Then I use fstrings to modify the assembly I’m about to add by doing this: cmp byte [ebx], 0 jz loopEnd{bracketCounter} Now to break this down, cmp is comparing the current cell ( byte [ebx] ) with 0. Then, the next instruction, jz only jumps to the given location in code if the two values compared previously are equal to eachother. The fstrings come into play because they modify this jump location to be loopEnd(whatever the counter is) , and this location becomes the corrisponding ] when that instruction is read. What’s next? Well, firstly I need to make a bunch of QoL changes to the compiler, like allowing the user to pass custom input and output names/directories, specify whether or not to fully compile or leave it as a chunk of assembly, ect I also want to make a slightly higher level BF-esque language, where you can do stuff like + 2, 5 to increase cell 2 by 5, if statements, batch outputting, ect, but that’s not gonna be the easiest thing… See Ya Later! - Elio"}, {"post_id": 76632, "ts": "2026-10-04T06:57:23Z", "hours": 0.3983, "text": "BrainF#ckery Devlog #1! What is BrainF#ckery? BrainF#ckery, or BFery for short, is a compiler for Brainf#ck! It’s written fully in python and takes BF and converts it into working assembly that you can plug into NASM and gcc to turn BF into a working executable! But why? Shut Up. How will it work? BFery will essentially just read and translate any BF directly into assembly. It’s actually really simple, since most of BF converts into a single line of assembly, like > , which moves the tape pointer up one, translates to inc rbx . That’s it! the rest are as follows: < -> dec rbx (dec means to decrease) + -> inc byte [rbx] ( byte tells NASM to only write one byte of data, and the two brackets here are the equivalent of dereferencing a pointer in C.) - -> dec byte [rbx] the rest( [ ] , . ) I have yet to figure out… OK Thats really all for this devlog, thanks for stoppin’ by! Elio"}]...
|
Title: BrainF#ckery Compiler by @mindstormpro3 | S Title: BrainF#ckery Compiler by @mindstormpro3 | Stardance
Devlogs:
BrainF#ckery Devlog #1! What is BrainF#ckery? BrainF#ckery, or BFery for short, is a compiler for Brainf#ck! It’s written fully in python and takes BF and converts it into working assembly that you can plug into NASM and gcc to turn BF into a working executable! But why? Shut Up. How will it work? BFery will essentially just read and translate any BF directly into assembly. It’s actually really simple, since most of BF converts into a single line of assembly, like > , which moves the tape pointer up one, translates to inc rbx . That’s it! the rest are as follows: < -> dec rbx (dec means to decrease) + -> inc byte [rbx] ( byte tells NASM to only write one byte of data, and the two brackets here are the equivalent of dereferencing a pointer in C.) - -> dec byte [rbx] the rest( [ ] , . ) I have yet to figure out… OK Thats really all for this devlog, thanks for stoppin’ by! Elio
BrainF#ckery Devlog #2! What’s Changed? A LOT! Since the last devlog, I’ve practically finished the BF -> Assembly compiler, and even used subprocess.run() to call NASM and GCC to build the script! It currently looks for a file called in.bf and then compiles it into an EXE that gets dumped straight into a build/ folder along with the out.asm and out.obj files! How does the Compiler actually work? Right now, all the compiler really does is go character by character in the input file, and if the character is one of the special 8, ( <>+-,.[] ) I just append some assembly into the out.asm file that corresponds with the instruction. For example, for + I just add inc byte [ebx] which increments the byte stored at the location the EBX register is pointing at. (EBX stores the tape pointer, and you manipulate it with < and > ). The cool thing about writing the compiler like this is that it literally just ignores everything else, so I don’t have to write code to “clean” the input file of newlines, tabs, spaces, comments, ect. Now for [ and ] , they’re a bit special. The way these guys work is I have a stack and counter. Whenever I add a [ to the assembly, I first increment the counter by 1 and then push the value to the stack. Then I use fstrings to modify the assembly I’m about to add by doing this: cmp byte [ebx], 0 jz loopEnd{bracketCounter} Now to break this down, cmp is comparing the current cell ( byte [ebx] ) with 0. Then, the next instruction, jz only jumps to the given location in code if the two values compared previously are equal to eachother. The fstrings come into play because they modify this jump location to be loopEnd(whatever the counter is) , and this location becomes the corrisponding ] when that instruction is read. What’s next? Well, firstly I need to make a bunch of QoL changes to the compiler, like allowing the user to pass custom input and output names/directories, specify whether or not to fully compile or leave it as a chunk of assembly, ect I also want to make a slightly higher level BF-esque language, where you can do stuff like + 2, 5 to increase cell 2 by 5, if statements, batch outputting, ect, but that’s not gonna be the easiest thing… See Ya Later! - Elio
BrainF#ckery Devlog #3! What’s Changed? Well… I added command line arguments!!! Gone are the days of manually typing your BF code into the terminal, now you can specify and input and output file, as well as pass flags! I also published to PyPi!!! Find it Here! On top of all that, I also made a bunch of small changes and modifications to fix bugs and make my compiler work better. Command Line Args! Here’s the current full list: -h , or --Help -> Your basic help command, don’t need to say much here -v , or --Verbose -> Enables verbose (extra) logging -i or --Input -> Takes a file path as an input file (a .bf file) -o or --Output -> Takes a file path to be the outputted executable (a .exe file)| -r or --Run -> Runs the newly compiled executable right after it’s done being compiled. c or --Clean -> deletes the build files ( .obj and .asm product files) after compilation is complete ***And hopefully more to come! I already have some ideas! : b WE’RE ON PYPI!!!!!!!!!! Check it out HERE!!! And finally, the boring bugfixes… :( A couple things: I realized, after a very smart friend of mine pointed it out, that I was not popping the stack after pushing it to call a function… If I left this in, more complex programs would crash due to a stack overflow…. I added comment clearing! Originally, the compiler would only read BF code that happened to be one of the 8 valid characters, but what if you happened to put a valid BF char in a comment? Well now there’s a loop that runs before the rest of the compiler that strips all lines of their text after a ; character, meaning all comments get deleted! I also added more error handling, so in case of a file not found or something, instead of the code crashing it just prints an error to the logs and returns. Thanks for sticking around for my devlog! see ya next time! : b...
|
1793116112.2914374
|
1793720912.2914374
|
|
65921
|
Gamer's Baku by @PrakstheBruce | Stardance
|
PrakstheBruce
|
0
|
4.22
|
0
|
[]
|
[{"post_id": 81027, "ts": "202 [{"post_id": 81027, "ts": "2026-10-19T16:37:03Z", "hours": 4.2247, "text": "Gamer Baku — Game Development Devlog 1 Engine used - Godot “ WarioWare-style minigame collection” The Idea Gamer Baku is a fast-paced minigame project inspired by WarioWare. The idea is to create a fun collection of short challenges, starting with a Kung Fu Panda-inspired character jumping across platforms to catch dumplings. I began developing it using Godot and the Stardance WarioWare mission guide. Building the Game I started by creating the title screen and connecting the Start button to the main level. This took some debugging because of incorrect scene paths and button signals, but I eventually got the transition working. Next, I built the level interface with a timer, level display, and dumpling icons. I created a separate themed timer scene and worked on the countdown logic to make it reusable. Making the Gameplay Work I created the player using CharacterBody2D and implemented horizontal movement, jumping, and gravity. One of my biggest challenges was the player falling through platforms. After debugging the collision shapes, I discovered that two platforms shared the same RectangleShape2D resource. Separating them fixed the problem. Once movement and collisions worked, I added dumpling collectibles using Area2D . Collecting a dumpling increases the global counter, hides the dumpling, and makes it reappear after five seconds. I also added a UI counter that updates automatically. #Challenges and Learning Throughout development, I worked through issues involving scene transitions, collision detection, timers, signals, and global variables. Each bug helped me understand Godot’s scene system and how different gameplay components communicate. The project has taught me that game development isn’t just about writing code. It’s also about testing, debugging, and connecting individual systems into a working experience. What’s Next? My next goals are to: Connect the timer to proper win and failure conditions. Finish the lives system and minigame transitions. Build a second minigame with a different challenge. Create original Winner and Death screens. Polish the gameplay, write a README, and publish the finished game. -> Final Thoughts Gamer Baku is still a work in progress, but the foundation is taking shape. The title screen, player movement, platform collisions, and dumpling collection mechanics are working. What started as an idea inspired by WarioWare has become a hands-on learning experience in game development. Now, the goal is to turn these individual systems into a complete and enjoyable minigame collection. This is only the beginning of Gamer Baku."}]...
|
Title: Gamer's Baku by @PrakstheBruce | Starda Title: Gamer's Baku by @PrakstheBruce | Stardance
Devlogs:
Gamer Baku — Game Development Devlog 1 Engine used - Godot “ WarioWare-style minigame collection” The Idea Gamer Baku is a fast-paced minigame project inspired by WarioWare. The idea is to create a fun collection of short challenges, starting with a Kung Fu Panda-inspired character jumping across platforms to catch dumplings. I began developing it using Godot and the Stardance WarioWare mission guide. Building the Game I started by creating the title screen and connecting the Start button to the main level. This took some debugging because of incorrect scene paths and button signals, but I eventually got the transition working. Next, I built the level interface with a timer, level display, and dumpling icons. I created a separate themed timer scene and worked on the countdown logic to make it reusable. Making the Gameplay Work I created the player using CharacterBody2D and implemented horizontal movement, jumping, and gravity. One of my biggest challenges was the player falling through platforms. After debugging the collision shapes, I discovered that two platforms shared the same RectangleShape2D resource. Separating them fixed the problem. Once movement and collisions worked, I added dumpling collectibles using Area2D . Collecting a dumpling increases the global counter, hides the dumpling, and makes it reappear after five seconds. I also added a UI counter that updates automatically. #Challenges and Learning Throughout development, I worked through issues involving scene transitions, collision detection, timers, signals, and global variables. Each bug helped me understand Godot’s scene system and how different gameplay components communicate. The project has taught me that game development isn’t just about writing code. It’s also about testing, debugging, and connecting individual systems into a working experience. What’s Next? My next goals are to: Connect the timer to proper win and failure conditions. Finish the lives system and minigame transitions. Build a second minigame with a different challenge. Create original Winner and Death screens. Polish the gameplay, write a README, and publish the finished game. -> Final Thoughts Gamer Baku is still a work in progress, but the foundation is taking shape. The title screen, player movement, platform collisions, and dumpling collection mechanics are working. What started as an idea inspired by WarioWare has become a hands-on learning experience in game development. Now, the goal is to turn these individual systems into a complete and enjoyable minigame collection. This is only the beginning of Gamer Baku....
|
1793094441.3785517
|
1793699241.3785517
|
|
70339
|
MausOS by @dahmaus | Stardance
|
dahmaus
|
1
|
3.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-19T19:29:07Z", "hours": 3.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Finally done with MausOS , the most swaggy WebOS you’ve ever seen! Swagged out with music , live wallpaper , games and more. Check it out :D", "repo": "https://github.com/DahMaus/MausOS", "demo": "https://dahmaus.github.io/MausOS"}]...
|
[{"post_id": 81029, "ts": "202 [{"post_id": 81029, "ts": "2026-10-19T16:49:01Z", "hours": 1.5219, "text": "MausOS release! :D apps swag windows even more swag"}, {"post_id": 80978, "ts": "2026-10-19T14:06:16Z", "hours": 1.1642, "text": "MausOS added live wallpaper topbar music :D"}, {"post_id": 80685, "ts": "2026-10-18T14:46:01Z", "hours": 0.2658, "text": "Part1 of doing my Own WebOS!"}]...
|
Title: MausOS by @dahmaus | Stardance
Devlogs:
Pa Title: MausOS by @dahmaus | Stardance
Devlogs:
Part1 of doing my Own WebOS!
MausOS added live wallpaper topbar music :D
MausOS release! :D apps swag windows even more swag
Ships:
Finally done with MausOS , the most swaggy WebOS you’ve ever seen! Swagged out with music , live wallpaper , games and more. Check it out :D...
|
1793001142.5459473
|
1793087542.5459473
|
|
68159
|
willy's blog by @asherwandenreich | Stardance
|
asherwandenreich
|
0
|
5.52
|
0
|
[]
|
[{"post_id": 81035, "ts": "202 [{"post_id": 81035, "ts": "2026-10-19T17:01:55Z", "hours": 2.4525, "text": "Pushed “dark mode & about pg.” Deleted some unused files that came from installing next.js on the wrong layer/folder. Launched the website via npm run dev and used the VS Code Simple Browser feature. Took html notes in html.md, learned spacing, font size, and font color code. Found out I couldn’t use an apostrophe, and learned how to make next.js understand. Deleted all the default next.js features and started using Tailwind to make it look presentable. Finally made what I’m most proud of this devlog: the light/dark mode toggle switch. Switched dark mode from following the OS light/dark mode to following a class. Tested if it works by adding the class to layout.tsx. Made first client component (components/darkmode.tsx). Made my own button, troubleshooted an error caused by a missing return, and import/export."}, {"post_id": 79730, "ts": "2026-10-15T07:39:26Z", "hours": 0.7, "text": "Finished “Build Your Own Blog,” yay! In the repo there’s a little .md I created to take notes on the git commands and the flags I used. Spent a while pushing the code to GitHub through the terminal instead of using Claude, which I was used to doing because of a hackathon I did with my friends. Spent more time finnicking around with Vercel (time which wasn’t recorded for Stardance) and finally deploying the website. Super happy with the end result and I have ambitious plans for the next steps. I spent a few hours last night setting up Oracle Cloud and installing Headscape on that server. I want to use Cloudflare for DNS and buy my own domain, and host the Oracle Cloud / Headscape VPN on a subdomain."}, {"post_id": 79257, "ts": "2026-10-13T07:22:19Z", "hours": 2.3686, "text": "Following the tutorial, “Build your own Blog.” Currently on step 7/9, but somewhere along the line something went wrong. (screenshot attached below) Maybe because I wanted to type out the code instead of copy and pasting, but idk. Trying to finish the tutorial and deploy to Vercel, and then I want to start experimenting with 3D libraries and motion like you often see on Instagram reels."}]...
|
Title: willy's blog by @asherwandenreich | Sta Title: willy's blog by @asherwandenreich | Stardance
Devlogs:
Following the tutorial, “Build your own Blog.” Currently on step 7/9, but somewhere along the line something went wrong. (screenshot attached below) Maybe because I wanted to type out the code instead of copy and pasting, but idk. Trying to finish the tutorial and deploy to Vercel, and then I want to start experimenting with 3D libraries and motion like you often see on Instagram reels.
Finished “Build Your Own Blog,” yay! In the repo there’s a little .md I created to take notes on the git commands and the flags I used. Spent a while pushing the code to GitHub through the terminal instead of using Claude, which I was used to doing because of a hackathon I did with my friends. Spent more time finnicking around with Vercel (time which wasn’t recorded for Stardance) and finally deploying the website. Super happy with the end result and I have ambitious plans for the next steps. I spent a few hours last night setting up Oracle Cloud and installing Headscape on that server. I want to use Cloudflare for DNS and buy my own domain, and host the Oracle Cloud / Headscape VPN on a subdomain.
Pushed “dark mode & about pg.” Deleted some unused files that came from installing next.js on the wrong layer/folder. Launched the website via npm run dev and used the VS Code Simple Browser feature. Took html notes in html.md, learned spacing, font size, and font color code. Found out I couldn’t use an apostrophe, and learned how to make next.js understand. Deleted all the default next.js features and started using Tailwind to make it look presentable. Finally made what I’m most proud of this devlog: the light/dark mode toggle switch. Switched dark mode from following the OS light/dark mode to following a class. Tested if it works by adding the class to layout.tsx. Made first client component (components/darkmode.tsx). Made my own button, troubleshooted an error caused by a missing return, and import/export....
|
1793119741.215464
|
1793724541.215464
|
|
60348
|
Frenzi by @frenchwizz | Stardance
|
frenchwizz
|
0
|
0.38
|
0
|
[]
|
[{"post_id": 81037, "ts": "202 [{"post_id": 81037, "ts": "2026-10-19T17:05:02Z", "hours": 0.3778, "text": "Initial Devlog"}]...
|
Title: Frenzi by @frenchwizz | Stardance
Devlogs: Title: Frenzi by @frenchwizz | Stardance
Devlogs:
Initial Devlog...
|
1793033428.9715018
|
1793638228.9715018
|
|
70380
|
Cosmic Pulse by @ayush_madan2010 | Stardance
|
ayush_madan2010
|
0
|
1.0
|
0
|
[]
|
[{"post_id": 81039, "ts": "202 [{"post_id": 81039, "ts": "2026-10-19T17:20:41Z", "hours": 1.0033, "text": "Cosmic Pulse — Development Log Today, I built the initial Cosmic Pulse astronomy dashboard. I worked on the dark space-themed interface, live local clock, NASA astronomy image integration, and readable astronomy descriptions. I also worked through API and rendering issues to get the main features functioning. Next session Plans:*Add date navigation, explore previous astronomy discoveries, and improve the interactive experience. Time spent: Around an hour to set everything and start working"}]...
|
Title: Cosmic Pulse by @ayush_madan2010 | Stardanc Title: Cosmic Pulse by @ayush_madan2010 | Stardance
Devlogs:
Cosmic Pulse — Development Log Today, I built the initial Cosmic Pulse astronomy dashboard. I worked on the dark space-themed interface, live local clock, NASA astronomy image integration, and readable astronomy descriptions. I also worked through API and rendering issues to get the main features functioning. Next session Plans:*Add date navigation, explore previous astronomy discoveries, and improve the interactive experience. Time spent: Around an hour to set everything and start working...
|
1793008379.5380685
|
1793613179.5380685
|
|
16497
|
HYDRA by @JoonHyuk | Stardance
|
JoonHyuk
|
0
|
1.37
|
0
|
[]
|
[{"post_id": 8104, "ts": "2026 [{"post_id": 8104, "ts": "2026-06-13T15:01:43Z", "hours": 0.2733, "text": "FINISHED ALL WIRING!"}, {"post_id": 7263, "ts": "2026-06-12T03:36:02Z", "hours": 1.0928, "text": "FINSIHED DAY 1"}]...
|
Title: HYDRA by @JoonHyuk | Stardance
Devlogs:
FI Title: HYDRA by @JoonHyuk | Stardance
Devlogs:
FINSIHED DAY 1
FINISHED ALL WIRING!...
|
1792763260.9811487
|
1793368060.9811487
|
|
46067
|
My own site! by @nitikpsn | Stardance
|
nitikpsn
|
1
|
2.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-19T17:27:09Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "shipping my site ;)", "repo": "https://github.com/Nitikpsn/nitik-personal-siite", "demo": "https://www.nitikpsn.xyz/"}]...
|
[{"post_id": 81041, "ts": "202 [{"post_id": 81041, "ts": "2026-10-19T17:21:50Z", "hours": 2.3806, "text": "My personal site is done ;)"}]...
|
Title: My own site! by @nitikpsn | Stardance
Devl Title: My own site! by @nitikpsn | Stardance
Devlogs:
My personal site is done ;)
Ships:
shipping my site ;)...
|
1793047980.1119812
|
1793134380.1119812
|
|
32613
|
ImageTranslation by @nbth | Stardance
|
nbth
|
0
|
23.33
|
0
|
[]
|
[{"post_id": 81042, "ts": "202 [{"post_id": 81042, "ts": "2026-10-19T17:24:25Z", "hours": 0.4008, "text": "First Release work good on https://cubari.moe/read/mangadex/7a82d0ef-034e-427b-bf5c-ed7d08ddbd6b/1/1/ check the release note please https://github.com/code-ga/image-translate-extension/releases/tag/v0.1.0"}, {"post_id": 80698, "ts": "2026-10-18T15:29:22Z", "hours": 3.6092, "text": "Devlog TL;DR Translation: Experimented with local NLLB and Google Translate, weighing privacy against performance. Architecture: Moved translation into an offscreen document with a dedicated Web Worker. Performance: Added caching, task scheduling, and bounded concurrency. OCR: Improved error handling, caching, and image processing reliability. Release: Brought the core features together for Image Translate v0.1.0. Privacy vs. performance My original goal was to keep everything local, so users wouldn’t have to send their text to an external service. However, NLLB-200 comes with a hefty model size of around 2.4 GB, which can put serious pressure on browser memory. I experimented with Google Translate as an alternative. It’s much lighter on the user’s device, but there’s a trade-off: text sent for translation leaves the device and is processed by a third-party service. That means giving up some privacy for convenience and lower resource usage. Neither approach is perfect. Local inference costs memory and performance; hosted translation introduces an external data dependency. I’m still figuring out the right balance for an extension whose original motivation was privacy. Moving heavy work out of the background Chrome’s Manifest V3 service worker isn’t ideal for heavy inference. I moved translation into an offscreen document and added a dedicated Web Worker for model inference. The background script now mainly routes messages. I also switched to runtime.connect ports for longer-running communication to reduce messaging failures when the service worker gets suspended. Caching and scheduling Repeated requests were wasting time, so I added an L1 memory cache and an L2 IndexedDB cache, using SHA-256 keys to identify repeated requests. A priority queue, bounded concurrency, and admission control help prevent pages containing lots of images from overwhelming the extension. Debugging wasn’t fun I ran into WebGPU/WASM initialization failures, an OCR crash caused by getContext is not a function , and InvalidCharacterError from malformed Base64 data. Turns out, running an ML model is only half the battle. Browser APIs, cross-origin restrictions, and memory limits can be just as frustrating. Making OCR more reliable I switched batch processing to Promise.allSettled , allowing individual images to fail without breaking the whole batch. OCR results are cached locally with a seven-day TTL, and the popup now tracks errors per item. I also added script detection, a tinyld fallback, text normalization, OCR region grouping, and token protection to support the translation pipeline. What’s next? Image Translate v0.1.0 brings together automatic image and canvas detection, PaddleOCR, translation, hover popups, caching, domain settings, and error tracking. The next challenge is finding a sensible balance between translation quality, memory usage, and privacy. Ideally, users should have a clear choice between local translation and hosted services rather than having that trade-off hidden from them."}, {"post_id": 59653, "ts": "2026-09-01T15:55:27Z", "hours": 4.4203, "text": "TL;DR Messaging: Fixed a silent settings synchronization bug by introducing typed, namespaced messages. Hover Translation: Added a hover-to-translate popup with language selection and race-condition-safe handling. Default Language: Users can now configure a default translation language that syncs across tabs. Error Feedback: OCR and translation failures now show toast notifications instead of silently failing. Domain Rules: Fixed empty domain lists incorrectly allowing translation everywhere. Auto-translate: Restored automatic translation behavior that was accidentally removed during the refactor. Unified messaging I discovered a pretty annoying bug in the settings synchronization system. The popup was sending: ts\"notify-settings-changed\" while the background script was listening for: ts\"settings/notify-changed\" Because of this mismatch, settings changes were not propagated correctly and failed silently. To avoid this kind of problem in the future, I introduced types/messages.ts with typed, namespaced message routing. Now the message names are centralized instead of being manually written across different parts of the extension. Settings changes can now propagate correctly and update active tabs in real time. Hover translation popup The overlay can now translate individual OCR regions directly through a hover popup. When hovering over an OCR box, the extension displays: The original detected text A target language selector The translated result The popup uses a small debounce before appearing and has a delayed close behavior when the mouse leaves. If the user moves back into the popup, the close action is cancelled. I also had to handle race conditions. Translation requests can finish in a different order than they were created, so late responses are ignored when they no longer belong to the currently active popup. The popup handles its own translation request and lifecycle, which makes it much more self-contained. Default translation language (model error) Users can now choose a default target language in Settings. The current default is Vietnamese ( vi ), with support for 17 languages. The setting is stored using browser.storage.sync and changes are broadcast to active tabs. The language selected inside a hover popup is temporary, while the configured default language remains the user’s persistent preference. In the future we will switch from machine translate or deep learning translate Error feedback instead of silent failures Previously, OCR and translation errors could fail without giving the user any useful feedback. I added utils/toast.ts to provide inline error notifications. Errors are debounced and deduplicated so the user does not get spammed with notifications when multiple failures happen at once. I also extracted shared popup styling into utils/popup-base.ts to reduce duplicated UI logic. Empty domains fix There was another logic issue with enabledDomains . An empty domain list should mean: Translate nothing. However, the previous implementation treated an empty list as if every domain was allowed. This has now been fixed in both background.ts and isDomainAllowed() . An empty list correctly disables translation entirely. Auto-translate restored During the refactor, some of the automatic translation logic was accidentally removed. This included: autoTranslateIfAllowed() URL polling The live DOM observer As a result, the extension would remain inactive until the user manually triggered it. These behaviors have now been restored, so automatic translation works again when the page loads and when new content appears dynamically."}, {"post_id": 49630, "ts": "2026-08-18T14:56:13Z", "hours": 5.2028, "text": "tl;dr WXT.js: Refactored the extension into smaller, more maintainable modules. Context Menu: Inject content scripts on pages to reliably detect clicked elements — a privacy/resource trade-off. Overlay: Reworked image overlays to be more independent from the website’s DOM and avoid rendering on invisible images. SPA Support: Added DOM-change detection for React-style navigation, at the cost of some extra resource usage. PaddleOCR: Still fighting text-box grouping 😭. Current grouping is imperfect, and we’re considering a better OCR model. WXT.js This is really easy. Almost everything is guided on their introduction page, so I need to follow it. Also, I need to refactor code from 1 huge file into many smaller files, which helps me maintain this more easily better context menu ( and first trade-off) Uh, due to the main problem that extensions don’t know which one was clicked. So I need to trade off user privacy with convenience. From now on, extensions will inject a content script into every page that you open, including enabling and disabling auto-translation better overlay box Over time, the extension displays an image by adding an extension element to a div, which is the image tag’s parent. But now we switch the approach to create a separate div that does not depend ( or depends less) on how the page works. Also, we need to check whether the current image displays are visible, or we will not render an overlay box for them. Add case for SPA web For frameworks like React.js, navigation is often handled as a Single-Page Application (SPA) update rather than a traditional page reload. When the user navigates to a different page, the application may update the DOM and the URL in the browser without triggering a full page refresh.Because of this, the extension cannot rely only on events such as page reloads or tab switches to detect when it needs to update its state. We therefore need to listen for DOM changes so the extension can detect when the application has rendered new content and reload or reinitialize its functionality accordingly. This will consume more resources, but we are unable to measure them Paddle-OCR and grouping text box (I hate this; why yolo ) This is the very unsolved problem that may annoy the user and me. The problem is paddle-ocr working like this, meaning it will separate the text bubble into smaller parts, which will make translation crazy. Currently, we are adding grouping to solve the issue of text on the same line, but the solution is not ready yet. Also, we are considering switching models for a better experience"}, {"post_id": 36271, "ts": "2026-07-28T08:22:41Z", "hours": 6.1336, "text": "tl;dr I am trying to make the extension more convenient for the user and boost the performance of AI tasks. And switch to a new framework for a better development cycle ( https://crxjs.dev is really bad; don’t use that currently) Why Because I recently found a manga page that has the manga that I want to read, I tried to make the extension more useful by adding a domain system (URL matching system ) which will automatically translate pages that match the URL. CORS problem This is not the main section, but I want to tell you about why this extension has some limitations with strictly page. Due to the original idea, focus on local first, but Chrome’s security design mainly blocks other processes from accessing image data of pages that have a config to block ( their CORS config ), so our extension will unable to run on that page, also i will work on a local backend to handle this problem (in a good situation) #Domain system design This design is quite weird because that firstly working on all page start will that domain. Then I used that, and all image include thumnail will be translated, and so i switched to a regex design, which will be more dynamic for users Extension page I am trying to make them easier to use, so I designed a simple ui ( tell AI to do that ). That will be more useful in the future ( currently, that just helps me in debug stage ) Background change Because of real-time (auto-translation mode ), we need to switch from using single mode to batch mode of the OCR library. If we continue to use the legacy solution that will make the user’s computer overloaded and cause a huge delay ( and error rate ). So we are switching to this solution. Also, is the batching solution for the background ( manager process, orchestrator) The background process will collect tasks from the content.js process in all tabs and then send them to the OCR and translate process ( batchingly, like 5 images per step, in about 80ms if no image is in the queue to keep offscreen work) build problem Vite builds to modular JavaScript code. But browsers don’t like that due to backward compatibility, so they reject it. next step I will migrating to mordern framework ( https://wxt.dev/ ), which will help me in the build process (I have a build problem with the module webpack of Vite, sadly )"}, {"post_id": 24788, "ts": "2026-07-08T16:12:20Z", "hours": 3.5633, "text": "After many efforts, I can OCR the image locally. (pic. 1 ) Tech choosing Firstly, I need to find a way to help me use the npm ecosystem. So I know that I can use Vite ( because Chrome just cares about how you define config in manifest, other files are not important ). but their don’t support live-reload, which makes me feel very bad in development. I hope I can use https://crxjs.dev/guide/installation/create-crxjs/ for this. UI and UX development Then I think that I want to build up some menu in the extension page, which will make my extension very modern. But I think about that, if I try to translate just one image, how can the user translate just one image? Because of that, I decided to build up a context menu that allows users to choose what they want to translate and just leave the extension page there with hello text. (pic. 2 and pic. 3 ) CORS problem Then I need to solve some problem with CORS in Chrome ( legendary web development problem ). They won’t allow me to just read the image tag, so I need to send the image URL to the background Context problem But background doesn’t have the context (like document.createElement or canvas, which will be able to boost my OCR speed ) which normal HTML page has, so I need to create an offscreen. Then the CORS problem comes back, and I need to build up some indexed storage solution to fix this. Thanks to Chrome. TL;DR And after their cors problem, isolation problem, chrome problem i here to present you the image that has the box showing you text that you see 😢😢"}]...
|
Title: ImageTranslation by @nbth | Stardance
Devl Title: ImageTranslation by @nbth | Stardance
Devlogs:
After many efforts, I can OCR the image locally. (pic. 1 ) Tech choosing Firstly, I need to find a way to help me use the npm ecosystem. So I know that I can use Vite ( because Chrome just cares about how you define config in manifest, other files are not important ). but their don’t support live-reload, which makes me feel very bad in development. I hope I can use https://crxjs.dev/guide/installation/create-crxjs/ for this. UI and UX development Then I think that I want to build up some menu in the extension page, which will make my extension very modern. But I think about that, if I try to translate just one image, how can the user translate just one image? Because of that, I decided to build up a context menu that allows users to choose what they want to translate and just leave the extension page there with hello text. (pic. 2 and pic. 3 ) CORS problem Then I need to solve some problem with CORS in Chrome ( legendary web development problem ). They won’t allow me to just read the image tag, so I need to send the image URL to the background Context problem But background doesn’t have the context (like document.createElement or canvas, which will be able to boost my OCR speed ) which normal HTML page has, so I need to create an offscreen. Then the CORS problem comes back, and I need to build up some indexed storage solution to fix this. Thanks to Chrome. TL;DR And after their cors problem, isolation problem, chrome problem i here to present you the image that has the box showing you text that you see 😢😢
tl;dr I am trying to make the extension more convenient for the user and boost the performance of AI tasks. And switch to a new framework for a better development cycle ( https://crxjs.dev is really bad; don’t use that currently) Why Because I recently found a manga page that has the manga that I want to read, I tried to make the extension more useful by adding a domain system (URL matching system ) which will automatically translate pages that match the URL. CORS problem This is not the main section, but I want to tell you about why this extension has some limitations with strictly page. Due to the original idea, focus on local first, but Chrome’s security design mainly blocks other processes from accessing image data of pages that have a config to block ( their CORS config ), so our extension will unable to run on that page, also i will work on a local backend to handle this problem (in a good situation) #Domain system design This design is quite weird because that firstly working on all page start will that domain. Then I used that, and all image include thumnail will be translated, and so i switched to a regex design, which will be more dynamic for users Extension page I am trying to make them easier to use, so I designed a simple ui ( tell AI to do that ). That will be more useful in the future ( currently, that just helps me in debug stage ) Background change Because of real-time (auto-translation mode ), we need to switch from using single mode to batch mode of the OCR library. If we continue to use the legacy solution that will make the user’s computer overloaded and cause a huge delay ( and error rate ). So we are switching to this solution. Also, is the batching solution for the background ( manager process, orchestrator) The background process will collect tasks from the content.js process in all tabs and then send them to the OCR and translate process ( batchingly, like 5 images per step, in about 80ms if no image is in the queue to keep offscreen work) build problem Vite builds to modular JavaScript code. But browsers don’t like that due to backward compatibility, so they reject it. next step I will migrating to mordern framework ( https://wxt.dev/ ), which will help me in the build process (I have a build problem with the module webpack of Vite, sadly )
tl;dr WXT.js: Refactored the extension into smaller, more maintainable modules. Context Menu: Inject content scripts on pages to reliably detect clicked elements — a privacy/resource trade-off. Overlay: Reworked image overlays to be more independent from the website’s DOM and avoid rendering on invisible images. SPA Support: Added DOM-change detection for React-style navigation, at the cost of some extra resource usage. PaddleOCR: Still fighting text-box grouping 😭. Current grouping is imperfect, and we’re considering a better OCR model. WXT.js This is really easy. Almost everything is guided on their introduction page, so I need to follow it. Also, I need to refactor code from 1 huge file into many smaller files, which helps me maintain this more easily better context menu ( and first trade-off) Uh, due to the main problem that extensions don’t know which one was clicked. So I need to trade off user privacy with convenience. From now on, extensions will inject a content script into every page that you open, including enabling and disabling auto-translation better overlay box Over time, the extension displays an image by adding an extension element to a div, which is the image tag’s parent. But now we switch the approach to create a separate div that does not depend ( or depends less) on how the page works. Also, we need to check whether the current image displays are visible, or we will not render an overlay box for them. Add case for SPA web For frameworks like React.js, navigation is often handled as a Single-Page Application (SPA) update rather than a traditional page reload. When the user navigates to a different page, the application may update the DOM and the URL in the browser without triggering a full page refresh.Because of this, the extension cannot rely only on events such as page reloads or tab switches to detect when it needs to update its state. We therefore need to listen for DOM changes so the extension can detect when the application has rendered new content and reload or reinitialize its functionality accordingly. This will consume more resources, but we are unable to measure them Paddle-OCR and grouping text box (I hate this; why yolo ) This is the very unsolved problem that may annoy the user and me. The problem is paddle-ocr working like this, meaning it will separate the text bubble into smaller parts, which will make translation crazy. Currently, we are adding grouping to solve the issue of text on the same line, but the solution is not ready yet. Also, we are considering switching models for a better experience
TL;DR Messaging: Fixed a silent settings synchronization bug by introducing typed, namespaced messages. Hover Translation: Added a hover-to-translate popup with language selection and race-condition-safe handling. Default Language: Users can now configure a default translation language that syncs across tabs. Error Feedback: OCR and translation failures now show toast notifications instead of silently failing. Domain Rules: Fixed empty domain lists incorrectly allowing translation everywhere. Auto-translate: Restored automatic translation behavior that was accidentally removed during the refactor. Unified messaging I discovered a pretty annoying bug in the settings synchronization system. The popup was sending: ts"notify-settings-changed" while the background script was listening for: ts"settings/notify-changed" Because of this mismatch, settings changes were not propagated correctly and failed silently. To avoid this kind of problem in the future, I introduced types/messages.ts with typed, namespaced message routing. Now the message names are centralized instead of being manually written across different parts of the extension. Settings changes can now propagate correctly and update active tabs in real time. Hover translation popup The overlay can now translate individual OCR regions directly through a hover popup. When hovering over an OCR box, the extension displays: The original detected text A target language selector The translated result The popup uses a small debounce before appearing and has a delayed close behavior when the mouse leaves. If the user moves back into the popup, the close action is cancelled. I also had to handle race conditions. Translation requests can finish in a different order than they were created, so late responses are ignored when they no longer belong to the currently active popup. The popup handles its own translation request and lifecycle, which makes it much more self-contained. Default translation language (model error) Users can now choose a default target language in Settings. The current default is Vietnamese ( vi ), with support for 17 languages. The setting is stored using browser.storage.sync and changes are broadcast to active tabs. The language selected inside a hover popup is temporary, while the configured default language remains the user’s persistent preference. In the future we will switch from machine translate or deep learning translate Error feedback instead of silent failures Previously, OCR and translation errors could fail without giving the user any useful feedback. I added utils/toast.ts to provide inline error notifications. Errors are debounced and deduplicated so the user does not get spammed with notifications when multiple failures happen at once. I also extracted shared popup styling into utils/popup-base.ts to reduce duplicated UI logic. Empty domains fix There was another logic issue with enabledDomains . An empty domain list should mean: Translate nothing. However, the previous implementation treated an empty list as if every domain was allowed. This has now been fixed in both background.ts and isDomainAllowed() . An empty list correctly disables translation entirely. Auto-translate restored During the refactor, some of the automatic translation logic was accidentally removed. This included: autoTranslateIfAllowed() URL polling The live DOM observer As a result, the extension would remain inactive until the user manually triggered it. These behaviors have now been restored, so automatic translation works again when the page loads and when new content appears dynamically.
Devlog TL;DR Translation: Experimented with local NLLB and Google Translate, weighing privacy against performance. Architecture: Moved translation into an offscreen document with a dedicated Web Worker. Performance: Added caching, task scheduling, and bounded concurrency. OCR: Improved error handling, caching, and image processing reliability. Release: Brought the core features together for Image Translate v0.1.0. Privacy vs. performance My original goal was to keep everything local, so users wouldn’t have to send their text to an external service. However, NLLB-200 comes with a hefty model size of around 2.4 GB, which can put serious pressure on browser memory. I experimented with Google Translate as an alternative. It’s much lighter on the user’s device, but there’s a trade-off: text sent for translation leaves the device and is processed by a third-party service. That means giving up some privacy for convenience and lower resource usage. Neither approach is perfect. Local inference costs memory and performance; hosted translation introduces an external data dependency. I’m still figuring out the right balance for an extension whose original motivation was privacy. Moving heavy work out of the background Chrome’s Manifest V3 service worker isn’t ideal for heavy inference. I moved translation into an offscreen document and added a dedicated Web Worker for model inference. The background script now mainly routes messages. I also switched to runtime.connect ports for longer-running communication to reduce messaging failures when the service worker gets suspended. Caching and scheduling Repeated requests were wasting time, so I added an L1 memory cache and an L2 IndexedDB cache, using SHA-256 keys to identify repeated requests. A priority queue, bounded concurrency, and admission control help prevent pages containing lots of images from overwhelming the extension. Debugging wasn’t fun I ran into WebGPU/WASM initialization failures, an OCR crash caused by getContext is not a function , and InvalidCharacterError from malformed Base64 data. Turns out, running an ML model is only half the battle. Browser APIs, cross-origin restrictions, and memory limits can be just as frustrating. Making OCR more reliable I switched batch processing to Promise.allSettled , allowing individual images to fail without breaking the whole batch. OCR results are cached locally with a seven-day TTL, and the popup now tracks errors per item. I also added script detection, a tinyld fallback, text normalization, OCR region grouping, and token protection to support the translation pipeline. What’s next? Image Translate v0.1.0 brings together automatic image and canvas detection, PaddleOCR, translation, hover popups, caching, domain settings, and error tracking. The next challenge is finding a sensible balance between translation quality, memory usage, and privacy. Ideally, users should have a clear choice between local translation and hosted services rather than having that trade-off hidden from them.
First Release work good on https://cubari.moe/read/mangadex/7a82d0ef-034e-427b-bf5c-ed7d08ddbd6b/1/1/ check the release note please https://github.com/code-ga/image-translate-extension/releases/tag/v0.1.0...
|
1792799364.855267
|
1793404164.855267
|
|
28432
|
RadiaX (Mechanics) by @Marco_da_mechanic | Stardan RadiaX (Mechanics) by @Marco_da_mechanic | Stardance...
|
Marco_da_mechanic
|
0
|
19.49
|
0
|
[]
|
[{"post_id": 81051, "ts": "202 [{"post_id": 81051, "ts": "2026-10-19T17:46:48Z", "hours": 1.4336, "text": "ALR. This thing is finished, BOM is ready and Github repo too. The assembly guide will follow soon, cause I think it’ll make more sence with the actual hardware as a ref picture"}, {"post_id": 71280, "ts": "2026-09-20T15:52:45Z", "hours": 4.2839, "text": "The Scanner is now finished, atleast the mechanical principles. The only things missing now are @Luka ’s electronics and the Lead."}, {"post_id": 69270, "ts": "2026-09-16T18:24:02Z", "hours": 3.3336, "text": "Back to the Cad. I added and adjusted some stuff in the Dual X-Ray tube design. And fit @Luka ‘s electronics in there. Also I’ve kinda finished the first scanner prototype. Some adjustments needed"}, {"post_id": 45779, "ts": "2026-08-12T14:13:00Z", "hours": 1.15, "text": "One of the last steps. A small step for y’all but a big one for me. The filter system is done, I designed them and added the mounting. Now I need to find some magnets with a 10mm diameter and a threaded rod attached. The last things are the ventilation and the cable routing. Btw if someone followed the last logs you can see a huge diffrence, I was on vacation and had my laptop with me, and I didn’t have internet. So I couldn’t upload lapses. Smt around 40h are missing but they are in the fusion time tracker (it’s a add-on if someone cares). So yeah that’s it."}, {"post_id": 22450, "ts": "2026-07-04T22:24:56Z", "hours": 6.5544, "text": "The dual tube design is nearly finished yayy. So I can’t really tell all the things I did, but this was mostly CAD, the Important structual Parts are calculated and integrated. But this design was really fun due to the challanges I’ve experienced with it. The percicion needed, the integration of the HV electronics, Cooling, how to keep it sealed and yeah. There are still a few things missing, Luka’s PCB, a mounting for the movement shaft and the exact dimensions of the slip ring. And really important side notice, if you’re doing a longer CAD session, please safe every major step. Fusion crashed and I got the biggest scare of my life cause I thought everything was gone, so yeah thats it."}, {"post_id": 20254, "ts": "2026-07-01T20:00:41Z", "hours": 1.5203, "text": "(I know the CAD looks bad but it’s just a Dummy) Today I started with the design of the dual X-Ray tube design and It’s so much worse than a single tube design, the HV is still a problem, the sword like thingie you can see in the middle is a copper cooling pipe, and copper likes to conduct electricity. Transformer Oil will be used in there, but the metal residue and just dust can have a hugeee impact on the isolation factor, than the kables which don’t like to be twisted, the weight bc I only have one mounting point, or i take a second mounting with a bearing to suport the weight and use the other mounting point just for the rotation. And yeah that’s basically it for today"}, {"post_id": 18676, "ts": "2026-06-29T21:19:17Z", "hours": 1.2142, "text": "Stuff I’ve done in maccondo, summary is AI written . I’ve added radial bearings to handle the radial loads and updated the CAD model accordingly. I calculated everything for the radial force distribution and integrated it into the design. I also fixed issues in the Fusion assembly and rebuilt parts of the mounting plate–flange connection because components kept moving in the wrong direction during assembly. I created an assembly setup on the flange and mounting plate, then exported it into an animation for later use. I updated the technical drawings with additional parameters and spent around 1h45 in CAD work. I worked through a lot of math for the scanner design, mainly the lead shielding requirements and the geometry between the X-ray tube and the screen. That took most of the time since I had to go back and forth with missing values and references, and it also changed the overall tube-to-detector geometry. The calculations are done now and fully integrated into the design. I redesigned the entire enclosure because the old one looked like a shoe box. The new one is more like a proper housing/oven design. I also added cable mountings and defined parts of the internal lead geometry, which will later depend on the electronics. I realized the plate could slip or put load on the stepper motor if the object isn’t perfectly centered, so I added a proper flange connection part to stabilize it. I also started planning manufacturing, but it’s still unclear who will machine the 10mm aluminum plates or how exactly the parts will be produced. On the electronics side, I integrated components into the assembly. I also revisited the peristaltic pump design, which I originally built, printed, and assembled with a stepper motor. It generated pressure at first, but when I tried pumping water, the stepper motor stalled. I tried troubleshooting possible causes like tube compression, friction, and PLA interference, but nothing fully solved it yet. I started a new improved pump design with better geometry, even though the first version made me question the design. That’s basically everything I worked on so far. Lapse somehow doesn’t like me, and there are a pretty many hours missing. 12.4h after July 1"}]...
|
Title: RadiaX (Mechanics) by @Marco_da_mechanic | Title: RadiaX (Mechanics) by @Marco_da_mechanic | Stardance
Devlogs:
Stuff I’ve done in maccondo, summary is AI written . I’ve added radial bearings to handle the radial loads and updated the CAD model accordingly. I calculated everything for the radial force distribution and integrated it into the design. I also fixed issues in the Fusion assembly and rebuilt parts of the mounting plate–flange connection because components kept moving in the wrong direction during assembly. I created an assembly setup on the flange and mounting plate, then exported it into an animation for later use. I updated the technical drawings with additional parameters and spent around 1h45 in CAD work. I worked through a lot of math for the scanner design, mainly the lead shielding requirements and the geometry between the X-ray tube and the screen. That took most of the time since I had to go back and forth with missing values and references, and it also changed the overall tube-to-detector geometry. The calculations are done now and fully integrated into the design. I redesigned the entire enclosure because the old one looked like a shoe box. The new one is more like a proper housing/oven design. I also added cable mountings and defined parts of the internal lead geometry, which will later depend on the electronics. I realized the plate could slip or put load on the stepper motor if the object isn’t perfectly centered, so I added a proper flange connection part to stabilize it. I also started planning manufacturing, but it’s still unclear who will machine the 10mm aluminum plates or how exactly the parts will be produced. On the electronics side, I integrated components into the assembly. I also revisited the peristaltic pump design, which I originally built, printed, and assembled with a stepper motor. It generated pressure at first, but when I tried pumping water, the stepper motor stalled. I tried troubleshooting possible causes like tube compression, friction, and PLA interference, but nothing fully solved it yet. I started a new improved pump design with better geometry, even though the first version made me question the design. That’s basically everything I worked on so far. Lapse somehow doesn’t like me, and there are a pretty many hours missing. 12.4h after July 1
(I know the CAD looks bad but it’s just a Dummy) Today I started with the design of the dual X-Ray tube design and It’s so much worse than a single tube design, the HV is still a problem, the sword like thingie you can see in the middle is a copper cooling pipe, and copper likes to conduct electricity. Transformer Oil will be used in there, but the metal residue and just dust can have a hugeee impact on the isolation factor, than the kables which don’t like to be twisted, the weight bc I only have one mounting point, or i take a second mounting with a bearing to suport the weight and use the other mounting point just for the rotation. And yeah that’s basically it for today
The dual tube design is nearly finished yayy. So I can’t really tell all the things I did, but this was mostly CAD, the Important structual Parts are calculated and integrated. But this design was really fun due to the challanges I’ve experienced with it. The percicion needed, the integration of the HV electronics, Cooling, how to keep it sealed and yeah. There are still a few things missing, Luka’s PCB, a mounting for the movement shaft and the exact dimensions of the slip ring. And really important side notice, if you’re doing a longer CAD session, please safe every major step. Fusion crashed and I got the biggest scare of my life cause I thought everything was gone, so yeah thats it.
One of the last steps. A small step for y’all but a big one for me. The filter system is done, I designed them and added the mounting. Now I need to find some magnets with a 10mm diameter and a threaded rod attached. The last things are the ventilation and the cable routing. Btw if someone followed the last logs you can see a huge diffrence, I was on vacation and had my laptop with me, and I didn’t have internet. So I couldn’t upload lapses. Smt around 40h are missing but they are in the fusion time tracker (it’s a add-on if someone cares). So yeah that’s it.
Back to the Cad. I added and adjusted some stuff in the Dual X-Ray tube design. And fit @Luka ‘s electronics in there. Also I’ve kinda finished the first scanner prototype. Some adjustments needed
The Scanner is now finished, atleast the mechanical principles. The only things missing now are @Luka ’s electronics and the Lead.
ALR. This thing is finished, BOM is ready and Github repo too. The assembly guide will follow soon, cause I think it’ll make more sence with the actual hardware as a ref picture...
|
1792518795.6364994
|
1793123595.6364994
|
|
70531
|
Chess Trainer But better?? by @Trofek | Stardance
|
Trofek
|
0
|
0.5
|
0
|
[]
|
[{"post_id": 81053, "ts": "202 [{"post_id": 81053, "ts": "2026-10-19T17:54:43Z", "hours": 0.5036, "text": "I am currently working on something simillar to chess.com. I am a big chess enjoyer so i started a project to play chess like a video game, right now im wondering if it should be an app or website, i have a prototype of it right now setup. plz like"}]...
|
Title: Chess Trainer But better?? by @Trofek | Sta Title: Chess Trainer But better?? by @Trofek | Stardance
Devlogs:
I am currently working on something simillar to chess.com. I am a big chess enjoyer so i started a project to play chess like a video game, right now im wondering if it should be an app or website, i have a prototype of it right now setup. plz like...
|
1793040486.989727
|
1793645286.989727
|
|
22691
|
Scratcher by @BetterClient | Stardance
|
BetterClient
|
0
|
182.41
|
0
|
[]
|
[{"post_id": 81059, "ts": "202 [{"post_id": 81059, "ts": "2026-10-19T18:13:33Z", "hours": 5.56, "text": "CLI I did some small refactors and added a new CLI, built with Clikt It’s very simple to use: scratcher check file --options //check the file for any compilation errors without compiling scratcher compile file --options outFile //compile into a .sb3 file scratcher standard-library //print out the standard library Clikt also provides easy to use help menus I also added a sort function to the array and list libraries"}, {"post_id": 78430, "ts": "2026-10-10T19:47:24Z", "hours": 7.5478, "text": "PROPER ERRORS Errors are the one thing that I knew were terrible but I could never build up the courage to fix. So I just fixed them. Now all errors in the language are formatted nicely, show you exactly where the error happened and give you a nice description. Along with this, I made a new system for collecting errors, so now the compiler won’t stop at the first error and will continue going and give you all errors at once. This makes fixing code a lot easier. This also opens up the possibility of an LSP server later on (before and after in images)"}, {"post_id": 76716, "ts": "2026-10-04T12:20:48Z", "hours": 6.6447, "text": "More demos and QOL Try it out: https://scratch.mit.edu/projects/1387804691/ Demos Math lexer, parser and interpreter: New demo that lets you input math expressions (eg: 1 + 1 ) and get the result. 3d cube renderer: a spinning 3d cube and player controls QOL Smarter inlining cost calculation A math centered optimization for removing identities Get rid of PromoteToGlobals (temp) GC documentation Codegen fixes (receiver functions generate the same block, causing scratch to get confused) Stack size optimization (reuse stack slots of the same type) Fix crash when the garbage collector is disabled"}, {"post_id": 74467, "ts": "2026-09-27T13:15:50Z", "hours": 7.5128, "text": "Demo programs and general improvements I added demo programs to scratcher, these show the language actually being used Try one out! https://scratch.mit.edu/projects/1385339395/ General improvements Bug fixes Dummy sprite Make the type checker ignored in inlined functions Make topLevelInit smaller and remove unused functions from final compilation TurboWarp specific compilation mode with faster operations on strings/lists (not compatible with vanilla scratch if enabled)"}, {"post_id": 72783, "ts": "2026-09-23T18:48:59Z", "hours": 2.1378, "text": "Indexed repeat and general improvements Added a new indexed for and repeat statement which allows way easier index tracking: //Before: int index = 0; repeat(10) { ... index++; } //After: repeat(10) { index -> ... } I also made the PooledList get garbage collected with the refcount gc Did some really small refactors aswell"}, {"post_id": 71161, "ts": "2026-09-20T11:38:26Z", "hours": 2.5564, "text": "List pools Static lists are cool, but they are very limited expressiveness wise because they must be known at compile time Pools fix this by having a pool of static lists that the user code can allocate at any time PooledList a = allocate(); But because the pool is limited, the pooled list must be freed when not needed, the garbage collector will not handle it(yet) a.free(); Other than that, the PooledList behaves just like a List and can do almost anything a List does I also added proper documentation for Out of memory errors."}, {"post_id": 70752, "ts": "2026-09-19T18:17:22Z", "hours": 10.2792, "text": "QOL I added a shit ton of quality of life stuff: Tons of bug fixes Big array syntax: int[] myArray = [1, 2, 3, 4, 5, 6]; Safe casting for enums(previously a panic): Result.Success? a = res as? Result.Success; Out of memory detection: Scratch caps lists at 200k elements, after that it silently stops adding stuff to the list Compact int list: Store pretty much infinite integers without wasting heap space SHORT CIRCUITS: DONT EXECUTE RIGHT SIDE OF && or || if left side is false/true! If statements without braces: if(a) b++; CONTINUE AND BREAK: while(true) { if(a) break; if(b) continue; } STATIC LISTS: store data outside of the heap in scratch lists so that you dont run out of heap space: static str[] myList; This also allows for file reading: static str[] myList = \"hello.json\"; So you can properly store data(like ROMs) CASE SENSITIVE EQUALS: DID YOU KNOW THAT SCRATCH “=” BLOCK IS CASE INSENSITIVE??? And its pretty hard to make it case sensitive Now you can do “===” and its case sensitive: 'a' === 'A' RETURNS FALSE"}, {"post_id": 65445, "ts": "2026-09-10T16:08:38Z", "hours": 8.1706, "text": "DOCUMENTATION I do not want to touch any markdown ever again"}, {"post_id": 62828, "ts": "2026-09-06T11:04:43Z", "hours": 2.5681, "text": "Privates Added a “private” keyword, anything declared private cannot be accessed from outside the current file. This prevents the user from messing with internal states of libraries they are using For example, the list library from the standard library. Now you can’t directly mess with the list pointer triangles.ptr[5] = ...; This now results in an error because “ptr” is private! I also added some small optimizations for lambdas."}, {"post_id": 60869, "ts": "2026-09-03T14:48:30Z", "hours": 3.9831, "text": "Operator overloading Added operator overloading, now you can define overloads for specific operators so that code looks cleaner Just use the operator keyword with the correct signature and you’re done! You can overload the operators: +, -, /, *, %, [], []= For example: warp operator <T> void T[].set(int index, T item) { self::replace(this, item, index); } //use array[index] = item //compiler translates to set(array, index, item) I also realized that my previous refactor of arrays broke my nullability system: int[] a = Array(int, 5); say(a[3]); This would print null , which my type system missed I fixed this by moving arrays to a standard library module, the same array import works, but you have to change how you create the array: //before: int[] a = Array(int, 5); //doesn't need to be marked as null!!! int[] a = Array(int, 5); a[0] = ...; a[1] = ...; ... //after int?[] a = arrayOfNulls(5); //null filled int[] a = arrayOf(5, (int index) -> { return index * 5; //value of the array at that index });"}, {"post_id": 58837, "ts": "2026-08-31T12:49:12Z", "hours": 1.1706, "text": "Import some import names into unqualified co ntext Before: //import import list; //use list::List<str> myList = list::newList(); After: //import import list::*; //use List<str> myList = newList();"}, {"post_id": 58031, "ts": "2026-08-30T11:39:09Z", "hours": 1.2083, "text": "Pattern matching for sealed enums Previously if you wanted to check sealed enums types and use them, you had to do very ugly syntax for actually getting the variant instance: auto out = tryGet(); when(out) { Result.Success -> { auto suc = out as Result.Success; looks::say(\"Success! ${suc.out.x}\"); Now you don’t have to do all of this: when(tryGet()) { Result.Success suc -> { looks::say(\"Success! ${suc.out.x}\"); This is just syntax improvement, doesn’t change the generated code or anything, just helps the developer"}, {"post_id": 56767, "ts": "2026-08-28T17:36:33Z", "hours": 3.9356, "text": "ACTUAL ARRAYS!! Previously, scratcher “arrays” were just lists, you could add more items, it would dynamically resize, it was written in the kotlin DSL, so technically it was just a list. I removed the previous list code, reused some of it and added a new Array system Along with that, the normal lists got rewritten in 100% scratcher with no internal functions The new system is almost fully backwards compatible in source code, you just have to make a few changes The new implementation is more clear, more expressive and more like regular programming languages"}, {"post_id": 54379, "ts": "2026-08-25T10:59:05Z", "hours": 2.1919, "text": "I’m sorry For over 2 months, scratcher has had an “export” keyword, which was fully unused, until today: I implemented the export keyword on functions, which allows for code written in plain scratch to interact with scratcher code: export warp void myFunction() { ... } Export requires that your function arguments are all primitives and that the return is also a primitive, but other than that, it does not change anything, just exposes the function cleanly to regular scratch code. However, scratcher type checking still applies, so if the native scratch code passes in a string to a float argument, it will still cause a panic Even when you have obfuscation enabled, exports will stay and let native scratch use it with its original name"}, {"post_id": 52903, "ts": "2026-08-23T08:56:58Z", "hours": 3.9047, "text": "Sealed enums and faster GC I added a new type of object, sealed enums: sealed enum Animal { Cat(str name, int age, bool isMeowing), Dog(str name, int age), Unknown } They allow for storing data inside enums, they’re very similar to rust enums: sealed enum Result<T> { Success(T out), Failure } I also refactored lambdas to use a sealed enum instead of a big struct: //before struct LambdaCaptures(Lambda0Captures? c0, Lambda1Captures? c1, Lambda2Captures? c2); //after sealed enum LambdaCaptures { Lambda0Captures(Box$int capture0, ...), Lambda1Captures(Box$float capture0, ...) } Sealed enums only store a tag and a pointer, so if you use a lot of lambdas, this will save a TON of heap space Faster garbage collector! I made the marking phase of the mark and sweep collector faster by using an epoch based cleanup approach Now, instead of clearing and re-populating the marked list, we don’t ever clear it and we invalidate it by just increasing the epoch. This makes the isMarked check go from O(n) to O(1) while also improving marking speed because scratch doesn’t have to resize our list"}, {"post_id": 51327, "ts": "2026-08-20T22:21:05Z", "hours": 5.0097, "text": "MORE FUCKING ABSTRACTIONS!!! I added receiver/extension functions. These allow you to write code that takes in a type as a special argument You define them just like how it works in kotlin: warp <T, R> R T.let((T) -> R action) { return action(this); } It just compiles to a regular function warp <T, R> R let(T this, (T) -> R action) { return action(this); } But the compiler lets you call it with the special argument: thing.let((int a) -> ...); I also added a very big standard library module (written in scratcher!) with a ton of these functions built-in, they allow you to write more expressive code: triangles .filterNotNull() .filter((Triangle<float> t) -> t.x1 > 150) .filter((Triangle<float> t) -> t.y1 < 150) .forEach((Triangle<float> tri) -> ...) I also rewrote the entirety of string lib during this, now you have to use the extensions library to use strings, but its way more powerful (and written in scratcher)! I also added a new “char” type, which stores a single character (wow really???) I also added “safe dot calls” that allow you to use stuff as if they’re not null: triangles.forEach((Triangle<float>? t) -> { t?.x1?.let((float x1) -> { looks::say(\"x1: ${x1}\"); }); }); This only calls the let function if t?.x1 is not null There is a big problem with all this powerful new code though… the garbage collector can no longer keep up, a single mark and sweep takes over 1 second! Which is especially bad because the garbage collector needs the entire application to stop in order to run. You do not want your code to completely stop for a whole second(maybe you do? weirdo), so I have to fix this in my next few devlogs…"}, {"post_id": 49925, "ts": "2026-08-18T21:52:59Z", "hours": 6.2256, "text": "Lambdas I added lambdas to Scratcher! They allow you to write more expressive code like map(list, a -> a + 1) , which literally adds 1 to every element of list I also allow using outer variables within lambdas int a = ...; map(list, b -> { a++; b + a }); I allow this through boxing, the local variables become boxes and the lambdas get the local variable’s box, this makes lambdas more powerful than most languages as this allows for variables to be shared mutable state across lambdas, this also allows the local variables to get garbage collected. Of course, scratch doesn’t support this natively, so lambdas are 100% compiler sugar and just lowers to regular functions and uses function references(which is also 100% compiler sugar). void lambda::defunc@lambad@0(LambdaCaptures c, args...) { ... }"}, {"post_id": 46470, "ts": "2026-08-13T18:15:50Z", "hours": 1.7033, "text": "Fixed the garbage collector… turns out I broke it accidentally while cleaning up code in my last devlog, 3 line change but took a long time to find Made it so the stack allocator doesn’t do redundant operations like 1+1 and inlines them as 2 instead"}, {"post_id": 46037, "ts": "2026-08-12T23:23:02Z", "hours": 1.3453, "text": "100 hours! Evil hack part 4: Death of evil hack So I was using a really terrible hack to implement stuff like FunctionInlining, Safe dot and the elvis expression, the hack is basically (ab)using the when expression to do stuff like run code inside expressions and use local variables inside expressions. So to stop this from becoming a hack, I added it directly to the AST as StatementExpression(not to be confused with ExpressionStatement), which can be used to contain statements inside expressions. All of my evil hacks have been replaced by StatementExpression. I also added some small optimizations for StatementExpressions!"}, {"post_id": 45987, "ts": "2026-08-12T20:32:56Z", "hours": 5.7503, "text": "General language improvements Elvis expressions: If a value is nullable, it is not usable by anything that only accepts non-null values, to solve this, I added the elvis expression, which allows you to give a fallback for null values(compilation in image 2): //int doesn't have to be nullable because we have a fallback value! int x = functionThatReturnsNull()?: 5; String boxing and nullable primitives Previously, scratcher only supported having structs, enums and function references as nullable, now it also supports having primitive types as nullable: str? x = functionThatReturnsNullableString(); //distinguish between literal null and string null if(x == null) looks::say(\"null!\"); if(x == \"null\") looks::say(\"null as string!\"); //the compiler achieves this by boxing the string return with a struct: //struct StringBox(str value) //the actual type behind the scenes is: //StringBox? x = ...; Safe dot traversal If a struct instance is nullable, you cannot use regular struct.member because that may result in a NullPointerException, to solve this I added ?. which allows for null safe traversal(compilation in image 1): //if nullableTriangle == null, return null //if nullableTriangle != null, return nullableTriangle.x1 int? x1 = nullableTriangle?.x1; Deepseek fix I noticed that FunctionInlining completely ignored execution order, so I asked deepseek to solve it(this happened after I added string boxing). But I found a better solution to the same problem later on, so I reverted deepseek’s fix and wrote my own, which is 260 lines compared to deepseek’s 360 lines, over 100 lines shorter!"}, {"post_id": 42848, "ts": "2026-08-07T19:46:20Z", "hours": 7.4364, "text": "Second garbage collector! Added a second garbage collector! If your app does not contain any cyclic objects and needs high performance, you can now enable the ARC collector! This garbage collector works by automatically detecting when objects go out of scope and decrementing their reference count, if an object’s reference count goes to 0, it is freed. This is more performant than the mark and sweep collector because the objects are freed at the moment they are unused instead of stopping the entire program to collect garbage. This works for all cases, except for cases where there is a cyclic object. Because the cyclic object owns itself, so its reference count is always at 1."}, {"post_id": 32011, "ts": "2026-07-20T21:29:16Z", "hours": 4.2214, "text": "Even more abstractions please Added generics support, which allows the user to define generic functions/structs that apply with every type, for example: warp <T> void forEach(T[] a, (T) -> void action) { for(T t in a) { action(t); } } Depending on what type you used to call this, a new version of forEach gets generated, if you called it with an integer: warp void forEach@int(int[] a, (int) -> void action) { for(int t in a) { action(t); } } Of course I also allow this on structs: struct Triangle<Num>(Num x1, Num y1, Num x2, Num y2, Num x3, Num y3); Also did some small changes: Added an FPS counter to my test code Better optimizations that actually detect not(not(x)) Optimized triangle::fill even more (+2 fps) Made DynamicDispatchHandler actually use the apply return properly (it was always returning true)"}, {"post_id": 27929, "ts": "2026-07-13T21:08:14Z", "hours": 2.6361, "text": "More abstractions please! Added dynamic function dispatch which allows for functions to take in other functions as arguments, of course, this isn’t possible at all in normal scratch, so actually FunctionLiteral gets turned into an integer and a custom dispatch function gets created for every function literal’s signature which allows for a binary search to call the actual function Also made HeapConversion reuse stack slots instead of allocating one for every variable(mostly by AI)"}, {"post_id": 27608, "ts": "2026-07-13T10:50:48Z", "hours": 1.5486, "text": "Refactored the entire type system to use a sealed interface instead of an unsafe single class Nothing much to say, this doesn’t affect the input code or the output project, I did just cleanup"}, {"post_id": 27567, "ts": "2026-07-13T08:35:21Z", "hours": 0.8472, "text": "Did more syntax improvements Added ++ and – support: index++; Added type inference support: auto a = Triangle(5, 15, 60, -120, 240, 67); //type automatically becomes Triangle auto a = func(); //type automatically becomes the return type of func"}, {"post_id": 27415, "ts": "2026-07-12T23:35:13Z", "hours": 2.3778, "text": "Scratcher is at 100 commits! (Now 104 cause all of these refactors are different commits) Completely refactored all translation steps to use the ASTVisitor. Also did type resolving cleanup. Function Reachability : Went from 117 to 32 lines Function expression lowering : Went from 439 to 293 lines Re Parse Local Variables : Went from 34 to 27 lines Remove Empty Allocations : Went from 97 to 79 lines ConvertToHeapAccess : Biggest refactor of this whole devlog, went from 500 lines to 418, split into 5 files"}, {"post_id": 26200, "ts": "2026-07-10T21:13:19Z", "hours": 3.26, "text": "Fixed a lot of bugs with when expressions, also got deepseek to fix some of them Added If expressions, which allow using if statements inside other expressions, for example, here is some previously invalid code that is now valid: int max = if (a > b) a else b; str message = if (score >= 90) { looks::say(\"something\"); \"You win!\" } else { looks::say(\"something\"); \"You lose :(\" } triangles[15] = Triangle( utils::random(-240, 240), utils::random(-180, 180), utils::random(-240, 240), utils::random(-180, 180), utils::random(-240, 240), if(mode == TriangleRenderMode.OFF) { 5 } else { triangles[14].y3 } ); These still get lowered properly and just look like normal if statements in the final scratch code"}, {"post_id": 25224, "ts": "2026-07-09T10:42:23Z", "hours": 3.3289, "text": "Added more syntax improvements! Else if : Added support for else if, which replaces big blocks //Before: if(triangles[14].y1 >= 15) { looks::say(\">=15\"); } else { if(triangles[14].y2 >= 155) { looks::say(\"<=15\"); } else { looks::say(\"Both false!\"); } } //After: if(triangles[14].y1 >= 15) { looks::say(\">=15\"); } else if(triangles[14].y2 >= 155) { looks::say(\"<=15\"); } else { looks::say(\"Both false!\"); } Compound assignment : Added support for compound assignment //Before: triangles[15].y3 = triangles[15].y3 + 5; //After: triangles[15].y3 += 5; Enums : Added support for enums, which are just fancy integer wrappers enum TriangleRenderMode(OFF, RENDER, ITHINK); TriangleRenderMode mode = TriangleRenderMode.OFF; When : Added support for when expressions/statements that allow for matching a subject: //Before: if(answer == \"off\") { mode = TriangleRenderMode.OFF; } else if(answer == \"render\") { mode = TriangleRenderMode.RENDER; } else { mode = TriangleRenderMode.ITHINK; looks::say(\"If thinking is your power, what are you without it?\"); return; } //After: TriangleRenderMode mode = when(answer) { \"off\" -> TriangleRenderMode.OFF \"render\" -> TriangleRenderMode.RENDER else -> { looks::say(\"If thinking is your power, what are you without it?\"); TriangleRenderMode.ITHINK; } };"}, {"post_id": 24407, "ts": "2026-07-07T22:53:21Z", "hours": 2.6547, "text": "Tried to do turbowarp only return optimization, wasn’t able to make it very good… reverted it Improved the structure of CompilationConstants Added string::split and string::substring Made some of the list functions inlined (itemAt, clear, length)"}, {"post_id": 22179, "ts": "2026-07-04T14:42:02Z", "hours": 1.2922, "text": "Made the garbage collector treat top level variables as roots, this prevents top level variables from getting freed I added 2 modes to this Reflect: This uses a hacked block to read the variables by name and reduce script size if theres a lot of variables(this doesn’t render properly inside the editor but it works) NoReflect: Get all the top level variables at compile time and mark them one by one"}, {"post_id": 22122, "ts": "2026-07-04T12:41:23Z", "hours": 7.6808, "text": "Garbage collection Added a mark and sweep garbage collector to my language, it walks the roots, marks every used object, then frees all unused objects! Most impressive part of this(in my opinion) is that most of the garbage collector is actually written in my language Misc The garbage collector gets called automatically every 1 second, but you can turn it off (CompilationConstants.AUTOMATIC_GC) If you want to manage memory manually, you can turn off the garbage collector entirely (CompilationConstants.MANUAL_MEMORY)"}, {"post_id": 19412, "ts": "2026-06-30T18:41:23Z", "hours": 1.5931, "text": "Added a name parameter to alloc which acts as runtime type metadata, soon to be used."}, {"post_id": 18732, "ts": "2026-06-29T22:21:59Z", "hours": 0.6683, "text": "Added more compiler sugar for lists: list[index] replaces list::itemAt(list, index) list[index] = ...; replaces list::replace(list, item, index) for(type name in list) {} replaces int len = list::length(list); int i = 0; while (i < len) { type name = list::itemAt(list, i); i = i + 1; } (i am not proud of the shitcode that was used to get for(type name in list) working)"}, {"post_id": 18693, "ts": "2026-06-29T21:37:55Z", "hours": 3.1528, "text": "Added list support! A very barebones implementation that allows the user to create, add to, read from and delete items from lists!"}, {"post_id": 18194, "ts": "2026-06-29T08:15:19Z", "hours": 1.2822, "text": "Made “PromoteToGlobals” which is a more powerful version of OptimizeToGlobals which allows for recursive functions to have their locals turned into globals aswell This is something called liveness analysis, the compiler looks at the code paths and decides at which points a variable is “live”, which means it can’t get overwritten by a recursive call Example: warp int fib(int n) { return 0 if n <= 0; return 1 if n == 1; if (n == 2) { int b = n * 2; return otherFunc(b); } return fib(n - 1) + fib(n - 2); } In this function the “b” variable can be turned into a global because it cannot get overwritten by a recursive call, its used too early for that to happen"}, {"post_id": 17754, "ts": "2026-06-28T17:51:46Z", "hours": 1.5667, "text": "Did some compiler testing Fixed function inlining bugs Fixed a single use assignment bug Created a triangle library that allows for triangle rendering using the pen"}, {"post_id": 17603, "ts": "2026-06-28T13:52:43Z", "hours": 1.7214, "text": "Borrowed the “return expr if(cond)” syntax from ruby Implemented Tail call optimization which optimizes away recursion on tail calls Example: Before: str count(int amount) { return \"Done!\" if amount == 1; return count(amount - 1); } After: str count(int amount) { int tco@argument@amount = amount; while (true) { if (tco@argument@amount == 1) return \"Done !\"; tco@argument@amount = tco@argument@amount - 1; } }"}, {"post_id": 17283, "ts": "2026-06-28T00:21:23Z", "hours": 5.7767, "text": "Source code of the image: on GreenFlag { if(a() == 5) { looks::say(\"yo!\"); } int index = 0; index = index + 1; rgb(index, 5, 5); index = 5; while(true) { pen::eraseAll(); render(); } } The image is of the entire flow working perfectly: The index variable had their value propagated to “1” by the Sequential constant propagation optimization The variable got its uses removed by Inline single-use assignments Then the variable got fully removed by Dead store elimination The rgb function got inlined. Then while it was inlined, because the rgb function’s return wasn’t being used, it got fully removed(the inlining preserves side effects while removing its return value, but because it didn’t have any side effects it got fully removed) Same with the a() function: It got inlined Then the if statement became if(5 == 5) { looks::say(\"yo!\"); } Then Constant folding turned 5 == 5 into true Then Dead code elimination turned if(true) into just the then block I know most optimizations look like they aren’t that powerful, but when combined with other optimizations and ran in a loop, they can pile up and actually optimize code Optimizations Simplify boolean equality : Simplifies x == true to x , simplifies x == false to !x Simplify double negation : Simplifies !!x to x , simplifies --x to x Constant folding : Simplifies true == true to true , simplifies 5 + 5 to 10 Repeat to While : Converts repeat(amount) to a while loop Dead code elimination : Removes provably unreachable code blocks, eg: if(true) { ... } else { .. } turns into ... , removing the if and the else block entirely Now the big ones Sequential constant propagation : Analyzes the control flow of your program, removing useless variable assignments and inlining their expressions Inline single use assignment : Self explanatory Dead store elimination : Removes useless “set variable to x” blocks that don’t get used afterwards Function inlining : The compiler evaluates a cost for every function call is inside a function, if that total cost is less than 10,000, it gets inlined inside that function, removing call overhead and allowing for further optimization Other misc stuff: Fixed the while bug (if you called a function inside a while statement, it would only get called once) Made function lowering not allocate a stack slot if we’re ignoring return Made the OptimizeToGlobals optimization be called last to allow variable optimizations to happen first"}, {"post_id": 16526, "ts": "2026-06-26T21:46:14Z", "hours": 2.3836, "text": "Optimizations OptimizeToGlobals : If the compiler can prove that a function is not recursive and runs atomically(single threaded), it gets rid of the function’s primitive local variables, which improves performance as scratch’s list operations are more expensive than local variables InlineSingleUseVariables : Pretty self explanatory, if a variable is only used once, it will be inlined ConvertToHeapAccess : I did optimizations on the normal heap converter so that it doesn’t allocate a stack pointer for functions that don’t need one Images don’t show the OptimizeToGlobals optimization cause the testing function I have for that is too long Before and after on the RGB function"}, {"post_id": 16206, "ts": "2026-06-26T10:29:30Z", "hours": 1.5267, "text": "Created Motion and Pen library Added support for top level variables Made an optimization to get rid of useless “replace with -1” blocks(image 1 is before, image 2 is after), this greatly reduces the code size(images are only one example, it was being put everywhere)"}, {"post_id": 15894, "ts": "2026-06-25T20:34:04Z", "hours": 1.4264, "text": "Did warning cleanup Added a nullability “system”, I allow the ? to be put on struct fields, and you can put null as the argument on those fields, then you have to check if they are null and do !! to use them"}, {"post_id": 15790, "ts": "2026-06-25T17:47:54Z", "hours": 3.6944, "text": "Did a lot of refactors Created SensingLib and CalendarLib Made a system to allow standard libraries to be inlined into your code to reduce file size Added support for structs, Right now you have to manually free your structs"}, {"post_id": 15329, "ts": "2026-06-24T22:06:11Z", "hours": 1.2928, "text": "Created a library for casting primitives to other primitives Expanded the math library a lot Added duplicate function and struct detection(yes I forgot before) Added code to prioritize function(int) over function(float) if calling with an int Added “warp” and “export” modifiers to function declarations, the warp modifier maps to the “Run without screen refresh” field, and export is currently unused, but later it will be used to export a function so that its properly usable from normal scratch code"}, {"post_id": 15271, "ts": "2026-06-24T20:05:11Z", "hours": 1.885, "text": "Did general bug fixes Added more standard library functions Added runtime type checking and exceptions"}, {"post_id": 15169, "ts": "2026-06-24T17:20:15Z", "hours": 2.2017, "text": "Did a small refactor on obfuscation Created a type safe(kinda) kotlin DSL for making standard library functions way more readable and simpler to create I rewrote the Memory library with the kotlin DSL Image 1: Before Image 2: After"}, {"post_id": 15063, "ts": "2026-06-24T14:04:20Z", "hours": 1.6278, "text": "I added an event system, making it so your code can actually run on GreenFlag { main(); } on KeyPressed(W) { looks::say(\"W was pressed!\"); } These events are translated into functions and the compiler generates scratch events that call these on KeyPressed(W) { compiler@eventlistener@F(); } void compiler@eventlistener@F() { looks::say(\"W was pressed!\"); } The compiler also generates a initializer green flag block which clears the heap and reserves an index for every other entrypoint(image 2)"}, {"post_id": 14757, "ts": "2026-06-23T23:45:31Z", "hours": 8.0742, "text": "I finished the pipeline from my language’s AST to scratch, it was pretty mind numbing Stage 1: The code does reachability, from the source file(where the compilation started) and finds all functions that we can call from the source Stage 2: Using those functions, we lower call expressions to statements and returns to heap accesses, here’s how that looks in code: Before : void main() { looks::say(fib(5)); } After : void main() { int fibReturn = -1; fib(5, &fibReturn); looks::say(fibReturn); } Notice how the nested call turned into a seperate statement. Why do we need this? Because scratch does not support returning stuff from functions, only arguments. Stage 3: We re-parse all locals on the reachable functions because the last stage added more locals Stage 4: We add a parameter to all functions named “stack” Stage 5: We add free(stack) calls at the end or before the return statement, this frees our stack automatically. We also add alloc before function calls so that we have a stack to pass to the function Here’s how that looks like in code: Before : void main() { int fibReturn = -1; fib(5, &fibReturn); looks::say(fibReturn); } After : void main(int stack) { int fibReturn = -1; int fibStack = -1; alloc(UNKNOWN, &fibStack); //allocate a stack for fib fib(fibStack, 5, &fibReturn); looks::say(fibReturn); free(stack, UNKNOWN); //free our stack } Notice how we have UNKNOWN in place for a number in the allocation and freeing, this is because we just added more locals for the allocations and we can’t know how many slots we need. Standard library functions are already compiled to scratch statements so they don’t need a stack allocated for them Stage 6: We re-parse local variables so we have a count. Stage 7: We count the re-parsed locals for every function and figure out which local variables can be reached in every function Stage 8: We convert all local variables to heap slots We traverse all statements and expressions, replacing all variable accesses with heap[stack + variableIndex]. While in this process we also convert the unknowns into the actual sizes since we just counted the locals in stage 7 Here’s how this entire stage looks like in code: Before : void main(int stack) { int fibReturn = -1; int fibStack = -1; alloc(UNKNOWN, &fibStack); fib(fibStack, 5, &fibReturn); looks::say(fibReturn); free(stack, UNKNOWN); } After : void main(int stack) { heap[stack] = -1; heap[stack + 1] = -1; alloc(3, stack + 1); //we just pass the index here since alloc will write to that index fib(heap[stack + 1], 5, stack); looks::say(heap[stack]); free(stack, 2); //We have 2 locals } By using a stack we get access to a lot of things like returning, recursion and local variables. Scratch doesn’t even support local variables, so we have to hack it with a global list. Notice how we don’t free the allocation? That’s because all functions are compiled by the same compiler and that compiler added free() to all functions with a stack. Stage 9: If a function doesn’t have any local variables, this is where we delete their allocations and free’s so that they don’t mess up the heap For example : alloc(0, index); and the target function for this allocation will have its free(stack, 0) call removed. Stage 10: Finally we create dummy scratch functions for our very lowered AST And finally in stage 11 we create the code blocks for the scratch functions and write to disk And it successfully calculates fib(9) as 34"}, {"post_id": 13952, "ts": "2026-06-22T22:02:44Z", "hours": 2.9797, "text": "I made a wrapper for the raw opcode classes that make valid code easier to make, then I did a ton of bug fixes and did a small refactor"}, {"post_id": 13260, "ts": "2026-06-21T18:26:43Z", "hours": 0.5228, "text": "Did a refactor, and intellij decided to corrupt some of the files, so I had to fix it"}, {"post_id": 13207, "ts": "2026-06-21T17:10:57Z", "hours": 3.1617, "text": "Implemented 90% of scratch’s blocks in the wrapper"}, {"post_id": 13095, "ts": "2026-06-21T12:57:42Z", "hours": 2.4425, "text": "Worked on a very basic scratch wrapper, it can generate a recursive function, gonna add more scratch blocks so that actual logic can be generated in this wrapper"}, {"post_id": 12772, "ts": "2026-06-20T21:38:46Z", "hours": 0.7953, "text": "Added static type checking, which makes sure the correct types are used everywhere. It prevents the user from using a number in an if statement’s condition. It also prevents you from assigning a string to an integer field"}, {"post_id": 12746, "ts": "2026-06-20T20:50:32Z", "hours": 2.8928, "text": "I added the AST parsing, which is able to parse the ANTLR parse tree into an AST (sorry the image is bad, its all I can show)"}, {"post_id": 12579, "ts": "2026-06-20T15:22:11Z", "hours": 3.0503, "text": "Worked on the first stage of AST parsing: Only parse top level elements (imports, structs, variables) and don’t parse the insides of functions"}]...
|
Title: Scratcher by @BetterClient | Stardance
Dev Title: Scratcher by @BetterClient | Stardance
Devlogs:
Worked on the first stage of AST parsing: Only parse top level elements (imports, structs, variables) and don’t parse the insides of functions
I added the AST parsing, which is able to parse the ANTLR parse tree into an AST (sorry the image is bad, its all I can show)
Added static type checking, which makes sure the correct types are used everywhere. It prevents the user from using a number in an if statement’s condition. It also prevents you from assigning a string to an integer field
Worked on a very basic scratch wrapper, it can generate a recursive function, gonna add more scratch blocks so that actual logic can be generated in this wrapper
Implemented 90% of scratch’s blocks in the wrapper
Did a refactor, and intellij decided to corrupt some of the files, so I had to fix it
I made a wrapper for the raw opcode classes that make valid code easier to make, then I did a ton of bug fixes and did a small refactor
I finished the pipeline from my language’s AST to scratch, it was pretty mind numbing Stage 1: The code does reachability, from the source file(where the compilation started) and finds all functions that we can call from the source Stage 2: Using those functions, we lower call expressions to statements and returns to heap accesses, here’s how that looks in code: Before : void main() { looks::say(fib(5)); } After : void main() { int fibReturn = -1; fib(5, &fibReturn); looks::say(fibReturn); } Notice how the nested call turned into a seperate statement. Why do we need this? Because scratch does not support returning stuff from functions, only arguments. Stage 3: We re-parse all locals on the reachable functions because the last stage added more locals Stage 4: We add a parameter to all functions named “stack” Stage 5: We add free(stack) calls at the end or before the return statement, this frees our stack automatically. We also add alloc before function calls so that we have a stack to pass to the function Here’s how that looks like in code: Before : void main() { int fibReturn = -1; fib(5, &fibReturn); looks::say(fibReturn); } After : void main(int stack) { int fibReturn = -1; int fibStack = -1; alloc(UNKNOWN, &fibStack); //allocate a stack for fib fib(fibStack, 5, &fibReturn); looks::say(fibReturn); free(stack, UNKNOWN); //free our stack } Notice how we have UNKNOWN in place for a number in the allocation and freeing, this is because we just added more locals for the allocations and we can’t know how many slots we need. Standard library functions are already compiled to scratch statements so they don’t need a stack allocated for them Stage 6: We re-parse local variables so we have a count. Stage 7: We count the re-parsed locals for every function and figure out which local variables can be reached in every function Stage 8: We convert all local variables to heap slots We traverse all statements and expressions, replacing all variable accesses with heap[stack + variableIndex]. While in this process we also convert the unknowns into the actual sizes since we just counted the locals in stage 7 Here’s how this entire stage looks like in code: Before : void main(int stack) { int fibReturn = -1; int fibStack = -1; alloc(UNKNOWN, &fibStack); fib(fibStack, 5, &fibReturn); looks::say(fibReturn); free(stack, UNKNOWN); } After : void main(int stack) { heap[stack] = -1; heap[stack + 1] = -1; alloc(3, stack + 1); //we just pass the index here since alloc will write to that index fib(heap[stack + 1], 5, stack); looks::say(heap[stack]); free(stack, 2); //We have 2 locals } By using a stack we get access to a lot of things like returning, recursion and local variables. Scratch doesn’t even support local variables, so we have to hack it with a global list. Notice how we don’t free the allocation? That’s because all functions are compiled by the same compiler and that compiler added free() to all functions with a stack. Stage 9: If a function doesn’t have any local variables, this is where we delete their allocations and free’s so that they don’t mess up the heap For example : alloc(0, index); and the target function for this allocation will have its free(stack, 0) call removed. Stage 10: Finally we create dummy scratch functions for our very lowered AST And finally in stage 11 we create the code blocks for the scratch functions and write to disk And it successfully calculates fib(9) as 34
I added an event system, making it so your code can actually run on GreenFlag { main(); } on KeyPressed(W) { looks::say("W was pressed!"); } These events are translated into functions and the compiler generates scratch events that call these on KeyPressed(W) { compiler@eventlistener@F(); } void compiler@eventlistener@F() { looks::say("W was pressed!"); } The compiler also generates a initializer green flag block which clears the heap and reserves an index for every other entrypoint(image 2)
Did a small refactor on obfuscation Created a type safe(kinda) kotlin DSL for making standard library functions way more readable and simpler to create I rewrote the Memory library with the kotlin DSL Image 1: Before Image 2: After
Did general bug fixes Added more standard library functions Added runtime type checking and exceptions
Created a library for casting primitives to other primitives Expanded the math library a lot Added duplicate function and struct detection(yes I forgot before) Added code to prioritize function(int) over function(float) if calling with an int Added “warp” and “export” modifiers to function declarations, the warp modifier maps to the “Run without screen refresh” field, and export is currently unused, but later it will be used to export a function so that its properly usable from normal scratch code
Did a lot of refactors Created SensingLib and CalendarLib Made a system to allow standard libraries to be inlined into your code to reduce file size Added support for structs, Right now you have to manually free your structs
Did warning cleanup Added a nullability “system”, I allow the ? to be put on struct fields, and you can put null as the argument on those fields, then you have to check if they are null and do !! to use them
Created Motion and Pen library Added support for top level variables Made an optimization to get rid of useless “replace with -1” blocks(image 1 is before, image 2 is after), this greatly reduces the code size(images are only one example, it was being put everywhere)
Optimizations OptimizeToGlobals : If the compiler can prove that a function is not recursive and runs atomically(single threaded), it gets rid of the function’s primitive local variables, which improves performance as scratch’s list operations are more expensive than local variables InlineSingleUseVariables : Pretty self explanatory, if a variable is only used once, it will be inlined ConvertToHeapAccess : I did optimizations on the normal heap converter so that it doesn’t allocate a stack pointer for functions that don’t need one Images don’t show the OptimizeToGlobals optimization cause the testing function I have for that is too long Before and after on the RGB function
Source code of the image: on GreenFlag { if(a() == 5) { looks::say("yo!"); } int index = 0; index = index + 1; rgb(index, 5, 5); index = 5; while(true) { pen::eraseAll(); render(); } } The image is of the entire flow working perfectly: The index variable had their value propagated to “1” by the Sequential constant propagation optimization The variable got its uses removed by Inline single-use assignments Then the variable got fully removed by Dead store elimination The rgb function got inlined. Then while it was inlined, because the rgb function’s return wasn’t being used, it got fully removed(the inlining preserves side effects while removing its return value, but because it didn’t have any side effects it got fully removed) Same with the a() function: It got inlined Then the if statement became if(5 == 5) { looks::say("yo!"); } Then Constant folding turned 5 == 5 into true Then Dead code elimination turned if(true) into just the then block I know most optimizations look like they aren’t that powerful, but when combined with other optimizations and ran in a loop, they can pile up and actually optimize code Optimizations Simplify boolean equality : Simplifies x == true to x , simplifies x == false to !x Simplify double negation : Simplifies !!x to x , simplifies --x to x Constant folding : Simplifies true == true to true , simplifies 5 + 5 to 10 Repeat to While : Converts repeat(amount) to a while loop Dead code elimination : Removes provably unreachable code blocks, eg: if(true) { ... } else { .. } turns into ... , removing the if and the else block entirely Now the big ones Sequential constant propagation : Analyzes the control flow of your program, removing useless variable assignments and inlining their expressions Inline single use assignment : Self explanatory Dead store elimination : Removes useless “set variable to x” blocks that don’t get used afterwards Function inlining : The compiler evaluates a cost for every function call is inside a function, if that total cost is less than 10,000, it gets inlined inside that function, removing call overhead and allowing for further optimization Other misc stuff: Fixed the while bug (if you called a function inside a while statement, it would only get called once) Made function lowering not allocate a stack slot if we’re ignoring return Made the OptimizeToGlobals optimization be called last to allow variable optimizations to happen first
Borrowed the “return expr if(cond)” syntax from ruby Implemented Tail call optimization which optimizes away recursion on tail calls Example: Before: str count(int amount) { return "Done!" if amount == 1; return count(amount - 1); } After: str count(int amount) { int tco@argument@amount = amount; while (true) { if (tco@argument@amount == 1) return "Done !"; tco@argument@amount = tco@argument@amount - 1; } }
Did some compiler testing Fixed function inlining bugs Fixed a single use assignment bug Created a triangle library that allows for triangle rendering using the pen
Made “PromoteToGlobals” which is a more powerful version of OptimizeToGlobals which allows for recursive functions to have their locals turned into globals aswell This is something called liveness analysis, the compiler looks at the code paths and decides at which points a variable is “live”, which means it can’t get overwritten by a recursive call Example: warp int fib(int n) { return 0 if n <= 0; return 1 if n == 1; if (n == 2) { int b = n * 2; return otherFunc(b); } return fib(n - 1) + fib(n - 2); } In this function the “b” variable can be turned into a global because it cannot get overwritten by a recursive call, its used too early for that to happen
Added list support! A very barebones implementation that allows the user to create, add to, read from and delete items from lists!
Added more compiler sugar for lists: list[index] replaces list::itemAt(list, index) list[index] = ...; replaces list::replace(list, item, index) for(type name in list) {} replaces int len = list::length(list); int i = 0; while (i < len) { type name = list::itemAt(list, i); i = i + 1; } (i am not proud of the shitcode that was used to get for(type name in list) working)
Added a name parameter to alloc which acts as runtime type metadata, soon to be used.
Garbage collection Added a mark and sweep garbage collector to my language, it walks the roots, marks every used object, then frees all unused objects! Most impressive part of this(in my opinion) is that most of the garbage collector is actually written in my language Misc The garbage collector gets called automatically every 1 second, but you can turn it off (CompilationConstants.AUTOMATIC_GC) If you want to manage memory manually, you can turn off the garbage collector entirely (CompilationConstants.MANUAL_MEMORY)
Made the garbage collector treat top level variables as roots, this prevents top level variables from getting freed I added 2 modes to this Reflect: This uses a hacked block to read the variables by name and reduce script size if theres a lot of variables(this doesn’t render properly inside the editor but it works) NoReflect: Get all the top level variables at compile time and mark them one by one
Tried to do turbowarp only return optimization, wasn’t able to make it very good… reverted it Improved the structure of CompilationConstants Added string::split and string::substring Made some of the list functions inlined (itemAt, clear, length)
Added more syntax improvements! Else if : Added support for else if, which replaces big blocks //Before: if(triangles[14].y1 >= 15) { looks::say(">=15"); } else { if(triangles[14].y2 >= 155) { looks::say("<=15"); } else { looks::say("Both false!"); } } //After: if(triangles[14].y1 >= 15) { looks::say(">=15"); } else if(triangles[14].y2 >= 155) { looks::say("<=15"); } else { looks::say("Both false!"); } Compound assignment : Added support for compound assignment //Before: triangles[15].y3 = triangles[15].y3 + 5; //After: triangles[15].y3 += 5; Enums : Added support for enums, which are just fancy integer wrappers enum TriangleRenderMode(OFF, RENDER, ITHINK); TriangleRenderMode mode = TriangleRenderMode.OFF; When : Added support for when expressions/statements that allow for matching a subject: //Before: if(answer == "off") { mode = TriangleRenderMode.OFF; } else if(answer == "render") { mode = TriangleRenderMode.RENDER; } else { mode = TriangleRenderMode.ITHINK; looks::say("If thinking is your power, what are you without it?"); return; } //After: TriangleRenderMode mode = when(answer) { "off" -> TriangleRenderMode.OFF "render" -> TriangleRenderMode.RENDER else -> { looks::say("If thinking is your power, what are you without it?"); TriangleRenderMode.ITHINK; } };
Fixed a lot of bugs with when expressions, also got deepseek to fix some of them Added If expressions, which allow using if statements inside other expressions, for example, here is some previously invalid code that is now valid: int max = if (a > b) a else b; str message = if (score >= 90) { looks::say("something"); "You win!" } else { looks::say("something"); "You lose :(" } triangles[15] = Triangle( utils::random(-240, 240), utils::random(-180, 180), utils::random(-240, 240), utils::random(-180, 180), utils::random(-240, 240), if(mode == TriangleRenderMode.OFF) { 5 } else { triangles[14].y3 } ); These still get lowered properly and just look like normal if statements in the final scratch code
Scratcher is at 100 commits! (Now 104 cause all of these refactors are different commits) Completely refactored all translation steps to use the ASTVisitor. Also did type resolving cleanup. Function Reachability : Went from 117 to 32 lines Function expression lowering : Went from 439 to 293 lines Re Parse Local Variables : Went from 34 to 27 lines Remove Empty Allocations : Went from 97 to 79 lines ConvertToHeapAccess : Biggest refactor of this whole devlog, went from 500 lines to 418, split into 5 files
Did more syntax improvements Added ++ and – support: index++; Added type inference support: auto a = Triangle(5, 15, 60, -120, 240, 67); //type automatically becomes Triangle auto a = func(); //type automatically becomes the return type of func
Refactored the entire type system to use a sealed interface instead of an unsafe single class Nothing much to say, this doesn’t affect the input code or the output project, I did just cleanup
More abstractions please! Added dynamic function dispatch which allows for functions to take in other functions as arguments, of course, this isn’t possible at all in normal scratch, so actually FunctionLiteral gets turned into an integer and a custom dispatch function gets created for every function literal’s signature which allows for a binary search to call the actual function Also made HeapConversion reuse stack slots instead of allocating one for every variable(mostly by AI)
Even more abstractions please Added generics support, which allows the user to define generic functions/structs that apply with every type, for example: warp <T> void forEach(T[] a, (T) -> void action) { for(T t in a) { action(t); } } Depending on what type you used to call this, a new version of forEach gets generated, if you called it with an integer: warp void forEach@int(int[] a, (int) -> void action) { for(int t in a) { action(t); } } Of course I also allow this on structs: struct Triangle<Num>(Num x1, Num y1, Num x2, Num y2, Num x3, Num y3); Also did some small changes: Added an FPS counter to my test code Better optimizations that actually detect not(not(x)) Optimized triangle::fill even more (+2 fps) Made DynamicDispatchHandler actually use the apply return properly (it was always returning true)
Second garbage collector! Added a second garbage collector! If your app does not contain any cyclic objects and needs high performance, you can now enable the ARC collector! This garbage collector works by automatically detecting when objects go out of scope and decrementing their reference count, if an object’s reference count goes to 0, it is freed. This is more performant than the mark and sweep collector because the objects are freed at the moment they are unused instead of stopping the entire program to collect garbage. This works for all cases, except for cases where there is a cyclic object. Because the cyclic object owns itself, so its reference count is always at 1.
General language improvements Elvis expressions: If a value is nullable, it is not usable by anything that only accepts non-null values, to solve this, I added the elvis expression, which allows you to give a fallback for null values(compilation in image 2): //int doesn't have to be nullable because we have a fallback value! int x = functionThatReturnsNull()?: 5; String boxing and nullable primitives Previously, scratcher only supported having structs, enums and function references as nullable, now it also supports having primitive types as nullable: str? x = functionThatReturnsNullableString(); //distinguish between literal null and string null if(x == null) looks::say("null!"); if(x == "null") looks::say("null as string!"); //the compiler achieves this by boxing the string return with a struct: //struct StringBox(str value) //the actual type behind the scenes is: //StringBox? x = ...; Safe dot traversal If a struct instance is nullable, you cannot use regular struct.member because that may result in a NullPointerException, to solve this I added ?. which allows for null safe traversal(compilation in image 1): //if nullableTriangle == null, return null //if nullableTriangle != null, return nullableTriangle.x1 int? x1 = nullableTriangle?.x1; Deepseek fix I noticed that FunctionInlining completely ignored execution order, so I asked deepseek to solve it(this happened after I added string boxing). But I found a better solution to the same problem later on, so I reverted deepseek’s fix and wrote my own, which is 260 lines compared to deepseek’s 360 lines, over 100 lines shorter!
100 hours! Evil hack part 4: Death of evil hack So I was using a really terrible hack to implement stuff like FunctionInlining, Safe dot and the elvis expression, the hack is basically (ab)using the when expression to do stuff like run code inside expressions and use local variables inside expressions. So to stop this from becoming a hack, I added it directly to the AST as StatementExpression(not to be confused with ExpressionStatement), which can be used to contain statements inside expressions. All of my evil hacks have been replaced by StatementExpression. I also added some small optimizations for StatementExpressions!
Fixed the garbage collector… turns out I broke it accidentally while cleaning up code in my last devlog, 3 line change but took a long time to find Made it so the stack allocator doesn’t do redundant operations like 1+1 and inlines them as 2 instead
Lambdas I added lambdas to Scratcher! They allow you to write more expressive code like map(list, a -> a + 1) , which literally adds 1 to every element of list I also allow using outer variables within lambdas int a = ...; map(list, b -> { a++; b + a }); I allow this through boxing, the local variables become boxes and the lambdas get the local variable’s box, this makes lambdas more powerful than most languages as this allows for variables to be shared mutable state across lambdas, this also allows the local variables to get garbage collected. Of course, scratch doesn’t support this natively, so lambdas are 100% compiler sugar and just lowers to regular functions and uses function references(which is also 100% compiler sugar). void lambda::defunc@lambad@0(LambdaCaptures c, args...) { ... }
MORE FUCKING ABSTRACTIONS!!! I added receiver/extension functions. These allow you to write code that takes in a type as a special argument You define them just like how it works in kotlin: warp <T, R> R T.let((T) -> R action) { return action(this); } It just compiles to a regular function warp <T, R> R let(T this, (T) -> R action) { return action(this); } But the compiler lets you call it with the special argument: thing.let((int a) -> ...); I also added a very big standard library module (written in scratcher!) with a ton of these functions built-in, they allow you to write more expressive code: triangles .filterNotNull() .filter((Triangle<float> t) -> t.x1 > 150) .filter((Triangle<float> t) -> t.y1 < 150) .forEach((Triangle<float> tri) -> ...) I also rewrote the entirety of string lib during this, now you have to use the extensions library to use strings, but its way more powerful (and written in scratcher)! I also added a new “char” type, which stores a single character (wow really???) I also added “safe dot calls” that allow you to use stuff as if they’re not null: triangles.forEach((Triangle<float>? t) -> { t?.x1?.let((float x1) -> { looks::say("x1: ${x1}"); }); }); This only calls the let function if t?.x1 is not null There is a big problem with all this powerful new code though… the garbage collector can no longer keep up, a single mark and sweep takes over 1 second! Which is especially bad because the garbage collector needs the entire application to stop in order to run. You do not want your code to completely stop for a whole second(maybe you do? weirdo), so I have to fix this in my next few devlogs…
Sealed enums and faster GC I added a new type of object, sealed enums: sealed enum Animal { Cat(str name, int age, bool isMeowing), Dog(str name, int age), Unknown } They allow for storing data inside enums, they’re very similar to rust enums: sealed enum Result<T> { Success(T out), Failure } I also refactored lambdas to use a sealed enum instead of a big struct: //before struct LambdaCaptures(Lambda0Captures? c0, Lambda1Captures? c1, Lambda2Captures? c2); //after sealed enum LambdaCaptures { Lambda0Captures(Box$int capture0, ...), Lambda1Captures(Box$float capture0, ...) } Sealed enums only store a tag and a pointer, so if you use a lot of lambdas, this will save a TON of heap space Faster garbage collector! I made the marking phase of the mark and sweep collector faster by using an epoch based cleanup approach Now, instead of clearing and re-populating the marked list, we don’t ever clear it and we invalidate it by just increasing the epoch. This makes the isMarked check go from O(n) to O(1) while also improving marking speed because scratch doesn’t have to resize our list
I’m sorry For over 2 months, scratcher has had an “export” keyword, which was fully unused, until today: I implemented the export keyword on functions, which allows for code written in plain scratch to interact with scratcher code: export warp void myFunction() { ... } Export requires that your function arguments are all primitives and that the return is also a primitive, but other than that, it does not change anything, just exposes the function cleanly to regular scratch code. However, scratcher type checking still applies, so if the native scratch code passes in a string to a float argument, it will still cause a panic Even when you have obfuscation enabled, exports will stay and let native scratch use it with its original name
ACTUAL ARRAYS!! Previously, scratcher “arrays” were just lists, you could add more items, it would dynamically resize, it was written in the kotlin DSL, so technically it was just a list. I removed the previous list code, reused some of it and added a new Array system Along with that, the normal lists got rewritten in 100% scratcher with no internal functions The new system is almost fully backwards compatible in source code, you just have to make a few changes The new implementation is more clear, more expressive and more like regular programming languages
Pattern matching for sealed enums Previously if you wanted to check sealed enums types and use them, you had to do very ugly syntax for actually getting the variant instance: auto out = tryGet(); when(out) { Result.Success -> { auto suc = out as Result.Success; looks::say("Success! ${suc.out.x}"); Now you don’t have to do all of this: when(tryGet()) { Result.Success suc -> { looks::say("Success! ${suc.out.x}"); This is just syntax improvement, doesn’t change the generated code or anything, just helps the developer
Import some import names into unqualified co ntext Before: //import import list; //use list::List<str> myList = list::newList(); After: //import import list::*; //use List<str> myList = newList();
Operator overloading Added operator overloading, now you can define overloads for specific operators so that code looks cleaner Just use the operator keyword with the correct signature and you’re done! You can overload the operators: +, -, /, *, %, [], []= For example: warp operator <T> void T[].set(int index, T item) { self::replace(this, item, index); } //use array[index] = item //compiler translates to set(array, index, item) I also realized that my previous refactor of arrays broke my nullability system: int[] a = Array(int, 5); say(a[3]); This would print null , which my type system missed I fixed this by moving arrays to a standard library module, the same array import works, but you have to change how you create the array: //before: int[] a = Array(int, 5); //doesn't need to be marked as null!!! int[] a = Array(int, 5); a[0] = ...; a[1] = ...; ... //after int?[] a = arrayOfNulls(5); //null filled int[] a = arrayOf(5, (int index) -> { return index * 5; //value of the array at that index });
Privates Added a “private” keyword, anything declared private cannot be accessed from outside the current file. This prevents the user from messing with internal states of libraries they are using For example, the list library from the standard library. Now you can’t directly mess with the list pointer triangles.ptr[5] = ...; This now results in an error because “ptr” is private! I also added some small optimizations for lambdas.
DOCUMENTATION I do not want to touch any markdown ever again
QOL I added a shit ton of quality of life stuff: Tons of bug fixes Big array syntax: int[] myArray = [1, 2, 3, 4, 5, 6]; Safe casting for enums(previously a panic): Result.Success? a = res as? Result.Success; Out of memory detection: Scratch caps lists at 200k elements, after that it silently stops adding stuff to the list Compact int list: Store pretty much infinite integers without wasting heap space SHORT CIRCUITS: DONT EXECUTE RIGHT SIDE OF && or || if left side is false/true! If statements without braces: if(a) b++; CONTINUE AND BREAK: while(true) { if(a) break; if(b) continue; } STATIC LISTS: store data outside of the heap in scratch lists so that you dont run out of heap space: static str[] myList; This also allows for file reading: static str[] myList = "hello.json"; So you can properly store data(like ROMs) CASE SENSITIVE EQUALS: DID YOU KNOW THAT SCRATCH “=” BLOCK IS CASE INSENSITIVE??? And its pretty hard to make it case sensitive Now you can do “===” and its case sensitive: 'a' === 'A' RETURNS FALSE
List pools Static lists are cool, but they are very limited expressiveness wise because they must be known at compile time Pools fix this by having a pool of static lists that the user code can allocate at any time PooledList a = allocate(); But because the pool is limited, the pooled list must be freed when not needed, the garbage collector will not handle it(yet) a.free(); Other than that, the PooledList behaves just like a List and can do almost anything a List does I also added proper documentation for Out of memory errors.
Indexed repeat and general improvements Added a new indexed for and repeat statement which allows way easier index tracking: //Before: int index = 0; repeat(10) { ... index++; } //After: repeat(10) { index -> ... } I also made the PooledList get garbage collected with the refcount gc Did some really small refactors aswell
Demo programs and general improvements I added demo programs to scratcher, these show the language actually being used Try one out! https://scratch.mit.edu/projects/1385339395/ General improvements Bug fixes Dummy sprite Make the type checker ignored in inlined functions Make topLevelInit smaller and remove unused functions from final compilation TurboWarp specific compilation mode with faster operations on strings/lists (not compatible with vanilla scratch if enabled)
More demos and QOL Try it out: https://scratch.mit.edu/projects/1387804691/ Demos Math lexer, parser and interpreter: New demo that lets you input math expressions (eg: 1 + 1 ) and get the result. 3d cube renderer: a spinning 3d cube and player controls QOL Smarter inlining cost calculation A math centered optimization for removing identities Get rid of PromoteToGlobals (temp) GC documentation Codegen fixes (receiver functions generate the same block, causing scratch to get confused) Stack size optimization (reuse stack slots of the same type) Fix crash when the garbage collector is disabled
PROPER ERRORS Errors are the one thing that I knew were terrible but I could never build up the courage to fix. So I just fixed them. Now all errors in the language are formatted nicely, show you exactly where the error happened and give you a nice description. Along with this, I made a new system for collecting errors, so now the compiler won’t stop at the first error and will continue going and give you all errors at once. This makes fixing code a lot easier. This also opens up the possibility of an LSP server later on (before and after in images)
CLI I did some small refactors and added a new CLI, built with Clikt It’s very simple to use: scratcher check file --options //check the file for any compilation errors without compiling scratcher compile file --options outFile //compile into a .sb3 file scratcher standard-library //print out the standard library Clikt also provides easy to use help menus I also added a sort function to the array and list libraries...
|
1792482509.6003482
|
1793087309.6003482
|
|
67902
|
Refract by @mixidmb | Stardance
|
mixidmb
|
1
|
32.0
|
594
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-19T19:56:54Z", "hours": 32.0, "multiplier": 18.8, "payout": 594, "blessing": "neutral", "text": "Refract! Quest Games Translation Layer. Haii! I made a way to play Quest games like Batman, Iron Man VR and AC Nexus on PC, Or any PCVR headset. You can even play Resident Evil 4 now, which is one of the most requested one :P It runs on Windows or Linux. The Android Emulator on Windows is the most compatible one. Refract Native is also on Windows and runs the game’s ARM64 code directly on the CPU, so its faster but still experimental (While recording a demo i got a pink cube in AC nexus lol, but through android emulator works!). Linux uses waydroid that just shares kernel. It’s still experimental though, so not every game works yet. Here is a video of me yapping a ton about it, and showing some gameplay >_> https://youtu.be/OpW-374mX74", "repo": "https://github.com/MIXIDtheSilly/Refract", "demo": "https://github.com/MIXIDtheSilly/Refract/releases"}]...
|
[{"post_id": 81063, "ts": "202 [{"post_id": 81063, "ts": "2026-10-19T18:20:30Z", "hours": 6.1647, "text": "Bug fixes and compatibility Okay let’s start with the big things. Iron Man VR works and runs at 140+ fps. And one of the most requested games, Resident Evil 4, runs too! It’s at around 160+ fps. It uses the old VrApi, which now works (still experimental, and 32-bit games aren’t supported). Controller haptics, the Linux Android build tools fix (game imports work now), and viewer crash reporting also work. Crashes go to viewer.err with el reason."}, {"post_id": 80654, "ts": "2026-10-18T12:31:32Z", "hours": 8.0708, "text": "Its even faster now Since last devlog, I swapped default translation layer on linux to my optimized Digitalis, and from dynarmic to Digitalis on Refract Native (windows). AND DAMNN, no one can tell me dynarmic is faster lol, from 200 fps in one of the games to 300+. Batman also runs at 120+ Linux has a working launcher now, and windows got texture compression improvements (RIP Vram) Then there are a bunch of other fixes, like Meta audio SDK working on Linux, or /sdcard storage path now resolving properly. Oh and almost forgot, FINALLY OPTIMIZED THE MAIN THREAD! It can hit 100% now because of lighter code also being JIT. This was probably the last bottleneck."}, {"post_id": 79125, "ts": "2026-10-12T19:11:22Z", "hours": 9.4442, "text": "Refract without an emulator now hai again, so over the past week I worked on Linux support and Refract Native , now you can run Quest games directly (well, translation layer) on the CPU without using QEMU. Funny JIT floating point error lol, broke my friend’s rig apart. What about Linux progress? The games run great! I tried it on North Star and it’s hitting 80 fps, cuz as you probably know we also don’t have to emulate the kernel there as Linux and Android are basically the same thing. also I hit 12 issues on GitHub (help)"}, {"post_id": 77853, "ts": "2026-10-08T15:22:14Z", "hours": 7.9314, "text": "Haii! So some of you know i got banned for a while but i’m back! New Project Refract! (You can now play Meta Quest titles on PC & PCVR) Refract runs Quest games on a Windows PC (Linux support soon! ), and in a PC VR headset through SteamVR. The APK runs in Android on your machine, Refract gives it fake Quest calls, and the eye frames come back out to your headset. Refract is for games you own! credit required if you use the code :P It started as a fork of AXRB by Feline Reintgen (But now its using my code so ig we are superior lol), and the launcher’s Meta sign-in comes from RiftLift. Translator is Digitalis. Oh forgot to mention that i already worked on it for a while, but wasn’t able to track time because of the suspension. And here is my playing batman on it."}]...
|
Title: Refract by @mixidmb | Stardance
Devlogs:
H Title: Refract by @mixidmb | Stardance
Devlogs:
Haii! So some of you know i got banned for a while but i’m back! New Project Refract! (You can now play Meta Quest titles on PC & PCVR) Refract runs Quest games on a Windows PC (Linux support soon! ), and in a PC VR headset through SteamVR. The APK runs in Android on your machine, Refract gives it fake Quest calls, and the eye frames come back out to your headset. Refract is for games you own! credit required if you use the code :P It started as a fork of AXRB by Feline Reintgen (But now its using my code so ig we are superior lol), and the launcher’s Meta sign-in comes from RiftLift. Translator is Digitalis. Oh forgot to mention that i already worked on it for a while, but wasn’t able to track time because of the suspension. And here is my playing batman on it.
Refract without an emulator now hai again, so over the past week I worked on Linux support and Refract Native , now you can run Quest games directly (well, translation layer) on the CPU without using QEMU. Funny JIT floating point error lol, broke my friend’s rig apart. What about Linux progress? The games run great! I tried it on North Star and it’s hitting 80 fps, cuz as you probably know we also don’t have to emulate the kernel there as Linux and Android are basically the same thing. also I hit 12 issues on GitHub (help)
Its even faster now Since last devlog, I swapped default translation layer on linux to my optimized Digitalis, and from dynarmic to Digitalis on Refract Native (windows). AND DAMNN, no one can tell me dynarmic is faster lol, from 200 fps in one of the games to 300+. Batman also runs at 120+ Linux has a working launcher now, and windows got texture compression improvements (RIP Vram) Then there are a bunch of other fixes, like Meta audio SDK working on Linux, or /sdcard storage path now resolving properly. Oh and almost forgot, FINALLY OPTIMIZED THE MAIN THREAD! It can hit 100% now because of lighter code also being JIT. This was probably the last bottleneck.
Bug fixes and compatibility Okay let’s start with the big things. Iron Man VR works and runs at 140+ fps. And one of the most requested games, Resident Evil 4, runs too! It’s at around 160+ fps. It uses the old VrApi, which now works (still experimental, and 32-bit games aren’t supported). Controller haptics, the Linux Android build tools fix (game imports work now), and viewer crash reporting also work. Crashes go to viewer.err with el reason.
Ships:
Refract! Quest Games Translation Layer. Haii! I made a way to play Quest games like Batman, Iron Man VR and AC Nexus on PC, Or any PCVR headset. You can even play Resident Evil 4 now, which is one of the most requested one :P It runs on Windows or Linux. The Android Emulator on Windows is the most compatible one. Refract Native is also on Windows and runs the game’s ARM64 code directly on the CPU, so its faster but still experimental (While recording a demo i got a pink cube in AC nexus lol, but through android emulator works!). Linux uses waydroid that just shares kernel. It’s still experimental though, so not every game works yet. Here is a video of me yapping a ton about it, and showing some gameplay >_> https://youtu.be/OpW-374mX74...
|
1793008278.1309547
|
1793094678.1309547
|
|
67710
|
Self Learning AI Agents by @arushkalra52 | Stardan Self Learning AI Agents by @arushkalra52 | Stardance...
|
arushkalra52
|
1
|
5.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-20T13:47:11Z", "hours": 5.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a self-learning AI Agent that thinks, searches the web in real time, and remembers all information across sessions. It will reason through the answer and provide you with the answer by obtaining results directly from web. A simple dark-themed chat UI was built using streamlit. Challenging task was getting all the packages to get along as LangChain had major version conflicts with Gemini’s. So, I started building the agent loop from scratch by using Google’s genai package. The memory system is which I personally liked the most which means it becomes smarted every time you ask something as it stores and learns from that information. Also with the real-time web search it ensured that the agent gets you results from acquired knowledge along with saved information. Anyone can use it by just opening the link and start asking questions. You can try asking something out of which follow-up questions can be asked. You can also clear the memory anytime with the ‘Clear Memory’ button.", "repo": "https://github.com/arush4213/Self-Learning-AI-Agent", "demo": "https://selflearning-aiagent.streamlit.app/"}]...
|
[{"post_id": 81069, "ts": "202 [{"post_id": 81069, "ts": "2026-10-19T19:05:32Z", "hours": 0.5494, "text": "Updated UI with Streamlit."}, {"post_id": 80235, "ts": "2026-10-16T20:21:02Z", "hours": 4.2467, "text": "I created a self-learning AI agent entirely from scratch using Python. It uses Google Gemini, carries out real-time web searches using DuckDuckGo, and retains all the information between sessions with the help of persistent JSON memory."}]...
|
Title: Self Learning AI Agents by @arushkalra52 | Title: Self Learning AI Agents by @arushkalra52 | Stardance
Devlogs:
I created a self-learning AI agent entirely from scratch using Python. It uses Google Gemini, carries out real-time web searches using DuckDuckGo, and retains all the information between sessions with the help of persistent JSON memory.
Updated UI with Streamlit.
Ships:
I made a self-learning AI Agent that thinks, searches the web in real time, and remembers all information across sessions. It will reason through the answer and provide you with the answer by obtaining results directly from web. A simple dark-themed chat UI was built using streamlit. Challenging task was getting all the packages to get along as LangChain had major version conflicts with Gemini’s. So, I started building the agent loop from scratch by using Google’s genai package. The memory system is which I personally liked the most which means it becomes smarted every time you ask something as it stores and learns from that information. Also with the real-time web search it ensured that the agent gets you results from acquired knowledge along with saved information. Anyone can use it by just opening the link and start asking questions. You can try asking something out of which follow-up questions can be asked. You can also clear the memory anytime with the ‘Clear Memory’ button....
|
1793112841.90452
|
1793199241.90452
|
|
2617
|
Mossy by @dayfit | Stardance
|
dayfit
|
0
|
100.57
|
0
|
[]
|
[{"post_id": 81070, "ts": "202 [{"post_id": 81070, "ts": "2026-10-19T19:09:33Z", "hours": 1.1372, "text": "Devlog 24 After reading and analizing this flow today, I’ve realized that it’s better to keep each vault with it’s own passkey (one leak won’t expose your all keys). Also right now if you have already registered passkey for that vault you can choose to use exising passkey (so it’ll look it up on your device), or create new one (it might overwrite your old one (for same vault)). After reviewing this PR by myself and finding nothing that would make this insecure, I’ve used GPT Astra 6 as well to review it, so now I’m pretty sure that this branch is ready to go on main. See ya!"}, {"post_id": 80793, "ts": "2026-10-18T20:06:37Z", "hours": 4.1375, "text": "Devlog 23 I added one really important thing. Before, Mossy used a 4-digit PIN to unlock the vault (it was used as a wrapping key (after going through HKDF and Argon2)). It was 10,000 combinations. Argon2 made it take longer, but after some time (a few hours), it could be cracked (if someone had your encrypted encryption key (sounds funny :d)). After this change: We use PRF from WebAuthn (really secure stuff) that uses Touch ID, Windows Hello, or Yubico Security Keys (and others) to give deterministic random bytes. Think of it like a random function that remembers what it returned for which argument. Assuming that an attacker would try to brute-force this encryption key, even with 10^18 tries per second, it’d take 1.8 x 10^51 years to crack it (kinda looooong time). Oh, and for those who can’t or don’t wanna use PRF, I’ve added regular passwords. They’re not as good as PRF, but it still takes a really long time to crack those. Those changes are still in an open PR, but it’s 10 PM, and I need to take a closer look at it tomorrow (already did a code review myself, but I’m kinda sleepy, and I’d like to keep y’all secure <3). See ya!"}, {"post_id": 80415, "ts": "2026-10-17T15:50:11Z", "hours": 7.7453, "text": "Devlog 22 Frontend: Added light, dark, and auto themes support (with settings tab!) Settings tab with themes options and links to request new features Added dashboard onboarding to help users setup their vault and add their first password Reworked key synchronization (now users will provide 6-character code instead of 6-digits code (Also it lacks of ambiguous characters like “l” and “I”) Backend: Complete rework of key-sync microservice (HTTP + SSE instead of WebSockets) (so user can access synchronized passwords up to 5 minutes after they are sent) Improved scallability by completely rethinking key-sync flow (that was kinda tricky)"}, {"post_id": 79105, "ts": "2026-10-12T18:01:50Z", "hours": 10.0319, "text": "Devlog 21 Changelogs Frontend: Standarized colors, boders, shadows, and button styles using globals.css system Updated typography: Syne for body text and Geologica for headings Centered headers navigation links Redesigned home page hero Fixed the footer so it stays at the bottom of the page Added leaf decorations on home page Based on feedback (from flavortown) I’ve decided to add some links to docs and instructions on how to set something up. Backend: Added SSE endpoint for live device enrollment updates I am working on delivering some more things before end of stardance. Stay tuned!"}, {"post_id": 70708, "ts": "2026-09-19T17:00:52Z", "hours": 5.3025, "text": "Devlog 20 Here is what happend after last devlog (lots of improvements :D) On frontend: Improved secured passwords chart, so it does only show integer values, centered chart’s line Added total count of passwords chart (as default mode) Added email verification interface Improved recent actions section Removed website icon from recent action card (API was broken, and it didn’t looked good anyway) On backend: Finished and integrated email verification system (verification link and code expires after 15 minutes) Added limits for incorrect codes, resend cooldowns, and hourly email deliveries Added rate limiting to public verification endpoint Emails are sent asynchronously through RabbitMQ That’s all for now. I’ll focus on design consistency & responsiveness for now."}, {"post_id": 65279, "ts": "2026-09-10T09:25:36Z", "hours": 7.6328, "text": "Devlog 19 It’s been a long time from last devlog. Here is changelog: On frontend: Vault loading, refreshing, selection, etc are now centralized in zustand store Removed redundant useVault hook Now user can select vault from dashboard view Added clearer selected-vault indicators and improved keyboard accessibility Made dashboard vault cards presentational and reusable On backend: Fixed critical bug in resource server logic (refresh token could be used as auth token (very bad :c)) Improved and refactored jwt validation & generation Added correct typ claim in JWT tokens Simplified refresh token claims (some were unused or not necessary) Updated Authentication.md documentation Expanded JWT generation, management, and decoder tests Work in progress: Currently I’m working on new feature, central microservice that will handle sending emails to users This is what I got so far: Batched async communication through RabbitMQ Integration with resend and some templates Retry queue with 30 secounds delay Service requeue mail only if something went wrong with sending (429 or 5XX response), if recipient doesn’t exist, there is no requeue Added tests for duplicates, pending commands, successful sends, permanent failures, and retryable failures. See ya!"}, {"post_id": 59672, "ts": "2026-09-01T16:25:07Z", "hours": 1.7078, "text": "Devlog 18 Mock API is finished, now I’m working on frontend design & consistency Changelog Finished Mock API Renamed RippleButton to Button as it’s generic right now Made Button component generic (support for icon, ghost buttons etc) Replaced all buttons with generic Button component Also I adjusted some colors so design is more consistent. See ya!"}, {"post_id": 59001, "ts": "2026-08-31T16:08:03Z", "hours": 7.1164, "text": "Devlog 17 Device manager is now up and running on production! in code review I noticed: some edge cases (mostly related with multi-threading) user could not change accounts (persisted device id was the issue) probably more, but stardance was down so I couldn’t write this devlog Now I’m working on creating Mock API so frontend development will no longer require running real backend. Stay tuned!"}, {"post_id": 46463, "ts": "2026-08-13T18:01:12Z", "hours": 1.7533, "text": "Devlog 16 Finally device manager is ready to go. Refactored frontend side logic for key-sync to work with new API Fixed bugs, improved error handling (so error message is not misleading) Removed .idea folder from repo Introduced mossy-reactor (way to test micro-services with their dependencies without deploying them to main before tests) Now it’s time to work on frontend features + design (typography, colors, globals <– boring stuff ://)"}, {"post_id": 45388, "ts": "2026-08-11T20:21:14Z", "hours": 3.4439, "text": "Devlog 15 I’ve integrated API with frontend, created new tab for managing devices. Fixed some bugs related to interation of cross-microservice communication (maybe I’ll write some integration tests? who knows) I’ve added detection of OS and device type via user agent (using Yauaa library). Now I’ll have to think about how to create good risk-engine when at same time not storing too much user informations (to keep it privacy-first) If you guys have some idea how to do that let me know! To merge this feature to develop branch I need to fix some really minor bugs. see ya!"}, {"post_id": 44650, "ts": "2026-08-10T15:43:24Z", "hours": 9.4775, "text": "Devlog 14 Soo… Recently I saw that there was no way to add new devices (** facepalm **). From last devlog I created nice enrollment system that will require already verified device to accept new one before trusting it. I’ve utilized JWT scopes for that, so client authenticated with enrollment token can only access specific endpoints. All of that probably sounds pretty easy but e g. I didn’t wanted to duplicate existing code, enrollment token is issued by same /login endpoint etc etc. basically it was quite a hustle. Hopefully, next devlog will be about how I integrated API with frontend (cross your fingers!) BTW: test count jumped from 31 to 72 from last devlog so you can see how big is the difference!"}, {"post_id": 34100, "ts": "2026-07-24T16:02:15Z", "hours": 5.6378, "text": "Devlog 13 Device manager is pretty much ready to go to production from API pov (there are some things that I still need to code tho), from last devlog I integrated it with Auth microservice, with each login / session refreshment it’s checked if given device is blocked, if so, Mossy will refuse to provide user new tokens. PS: look at those green tests (so cool)!"}, {"post_id": 29715, "ts": "2026-07-16T20:09:15Z", "hours": 4.5417, "text": "Hello there! From last devlog I’ve managed to add some features for this new Device Trust Microservice. Right now device can be blocked by another device (it will stop this device from access to account) Nonce challenge is working and has really good test coverage (this whole microservice does too) thanks to TDD I’ve finished implementing controllers & their tests It might look like TDD is slowing me down, but my code is getting really mature (each scenario is prepared). For whole process of developing this MS I didn’t opened insomnia even once - and that’s cool, because running tests without running whole MS (and it’s dependencies) is much faster. See ya!"}, {"post_id": 29114, "ts": "2026-07-15T19:34:36Z", "hours": 10.0033, "text": "Hello everyone, For last 10 hours I’ve made major progress on Mossy development. First of all my custom JWKS system got replaced by Spring Boot OAuth2 Resource Server Starter (looong name isn’t it?), it’ll make future maintance & coding much easier. In futher I’m going to migrate it to use Authorization Server Starter to achive full OAuth2 compatibility. Also I’ve been learning how TDD works, and for last 4 hours I’ve been using it during coding, it makes life so much easier! I’m currently working on new feature - Device Manager, it’s really huge feature (I need to refactor existing Device MS), but it’s really exciting, it’ll show you what devices are added to your account & analyze risk of each login (based on your common IP & MAC & OS & some more) it requires me to change old Device Microservice domain to just key-sync. Also I’ll create 2 new microservices - one called Device Trust (I’m working on it currently), it’ll tell my Authentication system to allow login or not (before cryptography was just for key-sync) by using challenge - client’ll receive randomly generated nonce and it’ll have to sign it with it’s key. Then if everything is alright it’ll ask Risk Engine if it should send user an alert or not (in future it might require MFA from client detected as higher risk) This is my biggest project ever Stay tuned!"}, {"post_id": 12018, "ts": "2026-06-19T16:35:36Z", "hours": 1.5044, "text": "Mossy now supports ssh public keys as well Refactored actions in frontend code to achive cleaner code Added validation of ssh keys"}, {"post_id": 11466, "ts": "2026-06-18T18:57:58Z", "hours": 2.0375, "text": "Mossy now supports SSH keys! Old Add Password form got removed, and replaced by new, cleaner one. Also I’m on my way to refactor code, and make lifting of Mossy’s extension UI. Support for public keys, and other SSH specific features will be introduce later, right now, only private key is supported"}, {"post_id": 10739, "ts": "2026-06-17T17:00:53Z", "hours": 2.2661, "text": "Notes system is ready and works like a charm, I had minor problem with JPA while implementing it ( Cascade.ALL ) fixed issue. Notes are encrypted with vault encryption key, so it’s suitable for sensitive data. Next up I’ll implement usage history!"}, {"post_id": 10186, "ts": "2026-06-16T20:00:41Z", "hours": 2.2619, "text": "Now, I’m working on implementing notes for passwords, backend is already ready, and frontend logic is half-way there, probably I’ll finish everything tommorow. Also I’ve made major refactor in vault request handlers logic by creating AbstractVaultRequestHandler to keep boilerplate-code in one place."}, {"post_id": 10021, "ts": "2026-06-16T15:59:05Z", "hours": 0.8125, "text": "Mossy’s search engine works like a charm!"}, {"post_id": 9322, "ts": "2026-06-15T17:15:42Z", "hours": 0.7514, "text": "Currently, I’m working on a search engine for Mossy using Fuse.js. There are still a few things to implement, such as the UI for query search, and some bugs in the tag search logic to fix."}, {"post_id": 8271, "ts": "2026-06-13T19:19:54Z", "hours": 2.9025, "text": "I’ve finaly finished system of managing tags! I really like how it turned out. Next up I’ll work on searching and filtering passwords!"}, {"post_id": 5828, "ts": "2026-06-09T19:26:39Z", "hours": 2.2906, "text": "Whole tag system is ready on backend, currently I’m working on integrating frontend with API in nice way. stay tuned !!!"}, {"post_id": 5145, "ts": "2026-06-08T20:42:33Z", "hours": 4.7406, "text": "I’ve created vault <—> backend communication for adding, assigning, and getting tags. Also adding logic is ready on frontend. Whole system ’ll be ready by tommorow 😱"}, {"post_id": 2856, "ts": "2026-06-05T18:23:25Z", "hours": 1.3331, "text": "Currently, I’m writing tag management system, that will include CRUD on tags, searching for passwords with tags. Adding tags already works! Also I’ve made really nice roadmap of Mossy Development!"}]...
|
Title: Mossy by @dayfit | Stardance
Devlogs:
Curr Title: Mossy by @dayfit | Stardance
Devlogs:
Currently, I’m writing tag management system, that will include CRUD on tags, searching for passwords with tags. Adding tags already works! Also I’ve made really nice roadmap of Mossy Development!
I’ve created vault <—> backend communication for adding, assigning, and getting tags. Also adding logic is ready on frontend. Whole system ’ll be ready by tommorow 😱
Whole tag system is ready on backend, currently I’m working on integrating frontend with API in nice way. stay tuned !!!
I’ve finaly finished system of managing tags! I really like how it turned out. Next up I’ll work on searching and filtering passwords!
Currently, I’m working on a search engine for Mossy using Fuse.js. There are still a few things to implement, such as the UI for query search, and some bugs in the tag search logic to fix.
Mossy’s search engine works like a charm!
Now, I’m working on implementing notes for passwords, backend is already ready, and frontend logic is half-way there, probably I’ll finish everything tommorow. Also I’ve made major refactor in vault request handlers logic by creating AbstractVaultRequestHandler to keep boilerplate-code in one place.
Notes system is ready and works like a charm, I had minor problem with JPA while implementing it ( Cascade.ALL ) fixed issue. Notes are encrypted with vault encryption key, so it’s suitable for sensitive data. Next up I’ll implement usage history!
Mossy now supports SSH keys! Old Add Password form got removed, and replaced by new, cleaner one. Also I’m on my way to refactor code, and make lifting of Mossy’s extension UI. Support for public keys, and other SSH specific features will be introduce later, right now, only private key is supported
Mossy now supports ssh public keys as well Refactored actions in frontend code to achive cleaner code Added validation of ssh keys
Hello everyone, For last 10 hours I’ve made major progress on Mossy development. First of all my custom JWKS system got replaced by Spring Boot OAuth2 Resource Server Starter (looong name isn’t it?), it’ll make future maintance & coding much easier. In futher I’m going to migrate it to use Authorization Server Starter to achive full OAuth2 compatibility. Also I’ve been learning how TDD works, and for last 4 hours I’ve been using it during coding, it makes life so much easier! I’m currently working on new feature - Device Manager, it’s really huge feature (I need to refactor existing Device MS), but it’s really exciting, it’ll show you what devices are added to your account & analyze risk of each login (based on your common IP & MAC & OS & some more) it requires me to change old Device Microservice domain to just key-sync. Also I’ll create 2 new microservices - one called Device Trust (I’m working on it currently), it’ll tell my Authentication system to allow login or not (before cryptography was just for key-sync) by using challenge - client’ll receive randomly generated nonce and it’ll have to sign it with it’s key. Then if everything is alright it’ll ask Risk Engine if it should send user an alert or not (in future it might require MFA from client detected as higher risk) This is my biggest project ever Stay tuned!
Hello there! From last devlog I’ve managed to add some features for this new Device Trust Microservice. Right now device can be blocked by another device (it will stop this device from access to account) Nonce challenge is working and has really good test coverage (this whole microservice does too) thanks to TDD I’ve finished implementing controllers & their tests It might look like TDD is slowing me down, but my code is getting really mature (each scenario is prepared). For whole process of developing this MS I didn’t opened insomnia even once - and that’s cool, because running tests without running whole MS (and it’s dependencies) is much faster. See ya!
Devlog 13 Device manager is pretty much ready to go to production from API pov (there are some things that I still need to code tho), from last devlog I integrated it with Auth microservice, with each login / session refreshment it’s checked if given device is blocked, if so, Mossy will refuse to provide user new tokens. PS: look at those green tests (so cool)!
Devlog 14 Soo… Recently I saw that there was no way to add new devices (** facepalm **). From last devlog I created nice enrollment system that will require already verified device to accept new one before trusting it. I’ve utilized JWT scopes for that, so client authenticated with enrollment token can only access specific endpoints. All of that probably sounds pretty easy but e g. I didn’t wanted to duplicate existing code, enrollment token is issued by same /login endpoint etc etc. basically it was quite a hustle. Hopefully, next devlog will be about how I integrated API with frontend (cross your fingers!) BTW: test count jumped from 31 to 72 from last devlog so you can see how big is the difference!
Devlog 15 I’ve integrated API with frontend, created new tab for managing devices. Fixed some bugs related to interation of cross-microservice communication (maybe I’ll write some integration tests? who knows) I’ve added detection of OS and device type via user agent (using Yauaa library). Now I’ll have to think about how to create good risk-engine when at same time not storing too much user informations (to keep it privacy-first) If you guys have some idea how to do that let me know! To merge this feature to develop branch I need to fix some really minor bugs. see ya!
Devlog 16 Finally device manager is ready to go. Refactored frontend side logic for key-sync to work with new API Fixed bugs, improved error handling (so error message is not misleading) Removed .idea folder from repo Introduced mossy-reactor (way to test micro-services with their dependencies without deploying them to main before tests) Now it’s time to work on frontend features + design (typography, colors, globals <– boring stuff ://)
Devlog 17 Device manager is now up and running on production! in code review I noticed: some edge cases (mostly related with multi-threading) user could not change accounts (persisted device id was the issue) probably more, but stardance was down so I couldn’t write this devlog Now I’m working on creating Mock API so frontend development will no longer require running real backend. Stay tuned!
Devlog 18 Mock API is finished, now I’m working on frontend design & consistency Changelog Finished Mock API Renamed RippleButton to Button as it’s generic right now Made Button component generic (support for icon, ghost buttons etc) Replaced all buttons with generic Button component Also I adjusted some colors so design is more consistent. See ya!
Devlog 19 It’s been a long time from last devlog. Here is changelog: On frontend: Vault loading, refreshing, selection, etc are now centralized in zustand store Removed redundant useVault hook Now user can select vault from dashboard view Added clearer selected-vault indicators and improved keyboard accessibility Made dashboard vault cards presentational and reusable On backend: Fixed critical bug in resource server logic (refresh token could be used as auth token (very bad :c)) Improved and refactored jwt validation & generation Added correct typ claim in JWT tokens Simplified refresh token claims (some were unused or not necessary) Updated Authentication.md documentation Expanded JWT generation, management, and decoder tests Work in progress: Currently I’m working on new feature, central microservice that will handle sending emails to users This is what I got so far: Batched async communication through RabbitMQ Integration with resend and some templates Retry queue with 30 secounds delay Service requeue mail only if something went wrong with sending (429 or 5XX response), if recipient doesn’t exist, there is no requeue Added tests for duplicates, pending commands, successful sends, permanent failures, and retryable failures. See ya!
Devlog 20 Here is what happend after last devlog (lots of improvements :D) On frontend: Improved secured passwords chart, so it does only show integer values, centered chart’s line Added total count of passwords chart (as default mode) Added email verification interface Improved recent actions section Removed website icon from recent action card (API was broken, and it didn’t looked good anyway) On backend: Finished and integrated email verification system (verification link and code expires after 15 minutes) Added limits for incorrect codes, resend cooldowns, and hourly email deliveries Added rate limiting to public verification endpoint Emails are sent asynchronously through RabbitMQ That’s all for now. I’ll focus on design consistency & responsiveness for now.
Devlog 21 Changelogs Frontend: Standarized colors, boders, shadows, and button styles using globals.css system Updated typography: Syne for body text and Geologica for headings Centered headers navigation links Redesigned home page hero Fixed the footer so it stays at the bottom of the page Added leaf decorations on home page Based on feedback (from flavortown) I’ve decided to add some links to docs and instructions on how to set something up. Backend: Added SSE endpoint for live device enrollment updates I am working on delivering some more things before end of stardance. Stay tuned!
Devlog 22 Frontend: Added light, dark, and auto themes support (with settings tab!) Settings tab with themes options and links to request new features Added dashboard onboarding to help users setup their vault and add their first password Reworked key synchronization (now users will provide 6-character code instead of 6-digits code (Also it lacks of ambiguous characters like “l” and “I”) Backend: Complete rework of key-sync microservice (HTTP + SSE instead of WebSockets) (so user can access synchronized passwords up to 5 minutes after they are sent) Improved scallability by completely rethinking key-sync flow (that was kinda tricky)
Devlog 23 I added one really important thing. Before, Mossy used a 4-digit PIN to unlock the vault (it was used as a wrapping key (after going through HKDF and Argon2)). It was 10,000 combinations. Argon2 made it take longer, but after some time (a few hours), it could be cracked (if someone had your encrypted encryption key (sounds funny :d)). After this change: We use PRF from WebAuthn (really secure stuff) that uses Touch ID, Windows Hello, or Yubico Security Keys (and others) to give deterministic random bytes. Think of it like a random function that remembers what it returned for which argument. Assuming that an attacker would try to brute-force this encryption key, even with 10^18 tries per second, it’d take 1.8 x 10^51 years to crack it (kinda looooong time). Oh, and for those who can’t or don’t wanna use PRF, I’ve added regular passwords. They’re not as good as PRF, but it still takes a really long time to crack those. Those changes are still in an open PR, but it’s 10 PM, and I need to take a closer look at it tomorrow (already did a code review myself, but I’m kinda sleepy, and I’d like to keep y’all secure <3). See ya!
Devlog 24 After reading and analizing this flow today, I’ve realized that it’s better to keep each vault with it’s own passkey (one leak won’t expose your all keys). Also right now if you have already registered passkey for that vault you can choose to use exising passkey (so it’ll look it up on your device), or create new one (it might overwrite your old one (for same vault)). After reviewing this PR by myself and finding nothing that would make this insecure, I’ve used GPT Astra 6 as well to review it, so now I’m pretty sure that this branch is ready to go on main. See ya!...
|
1792486412.4775856
|
1793091212.4775856
|
|
69580
|
Spider game for CardputerADV by @Grant19 | Stardan Spider game for CardputerADV by @Grant19 | Stardance...
|
Grant19
|
1
|
9.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-19T19:32:56Z", "hours": 9.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I attempted to make a recreation of Daddy Long Legs, an IOS game by setSnail, on the cardputer ADV with Arduino C++", "repo": "https://github.com/GitDog1203/DaddyLongLegs", "demo": "https://youtu.be/QfPZ_8-vjX0?si=IZk7pHv-R4PdxiLq"}]...
|
[{"post_id": 81071, "ts": "202 [{"post_id": 81071, "ts": "2026-10-19T19:27:51Z", "hours": 1.1536, "text": "finished up the movment!"}, {"post_id": 80727, "ts": "2026-10-18T17:00:34Z", "hours": 8.0569, "text": "I’ve gotten so far on this project! Walking, colors, text, highscores, I’m going to make walking more smooth but other than that I’m almost done!"}]...
|
Title: Spider game for CardputerADV by @Grant19 | Title: Spider game for CardputerADV by @Grant19 | Stardance
Devlogs:
I’ve gotten so far on this project! Walking, colors, text, highscores, I’m going to make walking more smooth but other than that I’m almost done!
finished up the movment!
Ships:
I attempted to make a recreation of Daddy Long Legs, an IOS game by setSnail, on the cardputer ADV with Arduino C++...
|
1793008264.0237112
|
1793094664.0237112
|
|
70342
|
To do list by @Aisha_Shay | Stardance
|
Aisha_Shay
|
1
|
3.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-19T19:38:18Z", "hours": 3.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a chrome extension for keeping track of tasks! I added a storage as well so this could even be used for long term projects. I found it fun it wasnt really that hard. I had a lot of fun doing the html and colours. This is one of my fist projects so i got to learn alot doing this. Long term tasks, short reminders and a way to easily keep track of things. I feel like this would be really helpful in general.", "repo": "https://github.com/flowerkeji-ux/ToDo-list-Extension", "demo": "https://flowerkeji-ux.github.io/ToDo-list-Extension/"}]...
|
[{"post_id": 81073, "ts": "202 [{"post_id": 81073, "ts": "2026-10-19T19:32:14Z", "hours": 1.4106, "text": "i Think this is my final vesion. I really enjoyed this"}, {"post_id": 80730, "ts": "2026-10-18T17:10:48Z", "hours": 0.2625, "text": "I made the icon. kept the font."}, {"post_id": 80708, "ts": "2026-10-18T16:14:02Z", "hours": 1.4539, "text": "To-Do list. cant think of a good name for it .working on the icons now. dont really like the font might change it"}]...
|
Title: To do list by @Aisha_Shay | Stardance
Devl Title: To do list by @Aisha_Shay | Stardance
Devlogs:
To-Do list. cant think of a good name for it .working on the icons now. dont really like the font might change it
I made the icon. kept the font.
i Think this is my final vesion. I really enjoyed this
Ships:
I made a chrome extension for keeping track of tasks! I added a storage as well so this could even be used for long term projects. I found it fun it wasnt really that hard. I had a lot of fun doing the html and colours. This is one of my fist projects so i got to learn alot doing this. Long term tasks, short reminders and a way to easily keep track of things. I feel like this would be really helpful in general....
|
1793001145.1370926
|
1793087545.1370926
|
|
69914
|
Macropad esp32s3 universal software by @danielmb | Macropad esp32s3 universal software by @danielmb | Stardance...
|
danielmb
|
0
|
12.08
|
0
|
[]
|
[{"post_id": 81082, "ts": "202 [{"post_id": 81082, "ts": "2026-10-19T19:58:43Z", "hours": 2.4361, "text": "So the screen and the numpad are working, i still need to add some more config options to the display and fix a few small things in the keypad, so after that i only will need to add rgb led and potentiometor functionality, a check so that pins are not used twice and better authentication. Then ill probably be finished"}, {"post_id": 79866, "ts": "2026-10-15T17:33:51Z", "hours": 9.6406, "text": "Hi, i am making software for a macropad thats run by an esp32s3, at the moment i have the wifi, buttons and mqtt functions working. I am working on the screen and letting it act as a numlock keypad atm. I am planning to add functionality for potentiometors and rgb leds next, after that ill might add more mqtt functions."}]...
|
Title: Macropad esp32s3 universal software by @dan Title: Macropad esp32s3 universal software by @danielmb | Stardance
Devlogs:
Hi, i am making software for a macropad thats run by an esp32s3, at the moment i have the wifi, buttons and mqtt functions working. I am working on the screen and letting it act as a numlock keypad atm. I am planning to add functionality for potentiometors and rgb leds next, after that ill might add more mqtt functions.
So the screen and the numpad are working, i still need to add some more config options to the display and fix a few small things in the keypad, so after that i only will need to add rgb led and potentiometor functionality, a check so that pins are not used twice and better authentication. Then ill probably be finished...
|
1792957827.6366296
|
1793562627.6366296
|
|
69868
|
catpad by @lollo22 | Stardance
|
lollo22
|
0
|
5.59
|
0
|
[]
|
[{"post_id": 81083, "ts": "202 [{"post_id": 81083, "ts": "2026-10-19T20:02:52Z", "hours": 5.5947, "text": "my catpad, an hackpad that resembles a cat i worked hard on this project, just need to make the firmware to complete the design"}]...
|
Title: catpad by @lollo22 | Stardance
Devlogs:
my Title: catpad by @lollo22 | Stardance
Devlogs:
my catpad, an hackpad that resembles a cat i worked hard on this project, just need to make the firmware to complete the design...
|
1792878647.703754
|
1793483447.703754
|
|
34259
|
DungeonMan by @avycado13 | Stardance
|
avycado13
|
1
|
3.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-19T20:05:14Z", "hours": 3.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a library to implement RPG fight mechanics for text based games", "repo": "https://github.com/avycado13/dungeonman", "demo": "https://pypi.org/project/dungeonman/"}]...
|
[{"post_id": 81084, "ts": "202 [{"post_id": 81084, "ts": "2026-10-19T20:03:52Z", "hours": 0.3539, "text": "I added Documentation for the libraryand got it render via sphinx."}, {"post_id": 80983, "ts": "2026-10-19T14:45:43Z", "hours": 0.5758, "text": "I set it up to also be a library so you can use the exposed functions and classes fro basic RPGs"}, {"post_id": 80884, "ts": "2026-10-19T04:51:37Z", "hours": 0.3697, "text": "I added a room system and in the rooms you can pick up items and fight that room’s monsters."}, {"post_id": 27522, "ts": "2026-07-13T04:48:35Z", "hours": 1.5, "text": "i made some basic mechanics for fighting"}]...
|
Title: DungeonMan by @avycado13 | Stardance
Devlo Title: DungeonMan by @avycado13 | Stardance
Devlogs:
i made some basic mechanics for fighting
I added a room system and in the rooms you can pick up items and fight that room’s monsters.
I set it up to also be a library so you can use the exposed functions and classes fro basic RPGs
I added Documentation for the libraryand got it render via sphinx.
Ships:
I made a library to implement RPG fight mechanics for text based games...
|
1793047962.3189914
|
1793134362.3189914
|
|
41271
|
Fleer by @johan | Stardance
|
johan
|
1
|
76.21
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-30T21:52:34Z", "hours": 64.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "School is coming back soon, Stardance may be ending tomorrow, and I’m currently at 15% of what I want to do. I got an entire planning on Linear on what to do now. Fleer is a toxic-love project for me because of the numbers of issues I encountered, but I still want it to be done so bad. And yeah, I know testing is kinda hard now, I can’t publish an hosted testing instance so you will need to host it yourself (just one 30 MB Docker image to compile on any system and any architecture).", "repo": "https://github.com/johan-perso/fleer-relay", "demo": "https://github.com/johan-perso/fleer-cli#installation"}]...
|
[{"post_id": 81085, "ts": "202 [{"post_id": 81085, "ts": "2026-10-19T20:04:48Z", "hours": 4.6358, "text": "Fleer is a decentralized platform, meaning anyone can host one or multiple relay servers. This devlog brings this concept even more to the Fleer CLI. Three lists of relay servers are hosted (on the GitHub repo, on my main website, and obviously on the Fleer landing page itself). These lists contain the URL for the currently only hosted relay. You can also add your own custom lists. In the future, the officials lists will include many more relays, from me or from anyone that contributes to the ecosystem, and the CLI is already prepared for that! I’m on a hotspot with like not even 1 Mbps so the video is just here for illustrative purposes 💀"}, {"post_id": 72709, "ts": "2026-09-23T15:38:39Z", "hours": 7.5769, "text": "After a few weeks without being able to do proper coding sessions (only got time to do it while being at school), I can finally release a new feature for Fleer! Integrity checking: after sending files, the receiver can ask the sender for a list of SHA-256 hashes. All communications are using encrypted messages to reduce the amount of things a malicious relay server can do. Integrity checking allows the receiver to be sure that files are identical from the sent one, and that the relay didn’t skipped chunks/files. I also added proper (and definitive) instructions for selfhosting a relay server by using Docker Compose (with prebuilt images via GitHub Actions), by building the image yourself with a Dockerfile, or to run from source. Reduce chunkSize when sending files if network conditions were really really bad before starting to send chunks."}, {"post_id": 58469, "ts": "2026-08-30T21:45:51Z", "hours": 7.2975, "text": "Not sure if Stardance will get extended until something like the end of September, so here am I (didn’t got many times to update the app and encountered many problems). A new command fleer relay followed by any Fleer Relay URL will output details about it. Receiver device name was sent in clear to the relay, it is now exchanged using encrypted messages. The transfer will be deleted if too many restarts happen (because messages size exceeds the limit for example). A structure containing all files, folders and path is included to give the receiver some visuals indications. If it’s too large, the structure will be dropped entirely. The amount of received/sent bytes will be displayed in Kbps instead of Mbps if it’s slow asf. Many bugs fixes and optimizations. The relay can now pauses transfers if it’s processing too many transfers at once. The indicated transfer size will include an estimated encryption overhead (the algorithm used can add some bytes to files). Transfers that shares MANY messages can use a feature from the relay that give clients ability to select the amount of cached bytes for messages and chunks. Inactives shares are deleted from the memory of the relay. The build version and latest commit pulled is returned to clients from the relay. Rate limits now apply to WebSocket messages."}, {"post_id": 53427, "ts": "2026-08-23T23:35:26Z", "hours": 3.7667, "text": "Didn’t wrote many lines of code on this project the last few days, was busy with personnal things so I’m listing what I pushed this week: User can decide what to do if a file already exist in the current directory (replace it, rename the new one, or skip this file). A new command fdd allows to start a download even faster, by checking the first parameter ( fdd <share_link> ) or any URL in the clipboard. fleer send command can generate a QR Code image, and display it for supported terminals (such as the incredible Ghostty). Download speed is displayed live in Mbps. Some fixes concerning security and downloading in specific conditions."}, {"post_id": 49259, "ts": "2026-08-17T23:04:04Z", "hours": 4.8894, "text": "A few minors QoL changes: The CLI is automatically closed when download is finished, synced for both sender and receiver through an encrypted message that acts as a signal to tell both party they have done their job. Share Link is automatically copied into the clipboard of the sender, even if he’s remotely connected via SSH to another server. The directory in which files are saved is displayed at the end of execution (default to current folder). Improved performances when downloading. Some more verifications with the relay server used. Protect against Path Traversal vulnerability."}, {"post_id": 46633, "ts": "2026-08-14T01:00:19Z", "hours": 8.6061, "text": "Okay, changelog required even though I wasn’t planning on publishing it right now. Apart from some additions such as: --debug-socket flag that logs every actions happening between the client and a relay server Encryption protocol indicator (which is used by clients to know what algorithm and settings to use) is NOT known by the server anymore, as it is transferred in the share link itself Proper exit (and closure of spinner animations) when using Ctrl+C A few optimizations for responsive logs Downloading files is ALMOST done, I’m currently having many issues with slow file upload, and many attempts at optimizing it (that litteraly give me the idea of just quitting this project) and I’m making this changelog now because I think we might not finish this part of the CLI before at least 2 days. In the meantime, I daydreamed about many things I want to introduce into the project that will hopefully make a difference with others apps, even if I don’t have the same speed as them."}, {"post_id": 45231, "ts": "2026-08-11T15:54:32Z", "hours": 1.0211, "text": "Made a command to explain how Fleer relays, encryption and decryption work - always with a nice focus on terminal design, with colors, responsive and auto resize"}, {"post_id": 44327, "ts": "2026-08-10T00:30:37Z", "hours": 7.3697, "text": "We can send files using the CLI! I have some optimizations to make because sending small files is just as slow as sending large files, causing super low speed upload 💀 We also display the URL, command, and keys (used by the server) to connect as a receiver and start downloading files. The protocol is kinda complex and I’m planning to write a documentation on how to use it for any matter (like automations or 3rd party clients), and a terminal generally being for nerds (especially when a desktop GUI app is planned) make this the best place to showcase how the relay system really work, so I implemented a flag --debug-performances that log every actions into a file, also useful to debug performances (if you didn’t guessed…). The sender sends files to the relay, one by one, chunk by chunk to the relay, which will pipe them to the receiver afterwards. Chunks are fully encrypted on both clients and server cannot access their content whatsoever. To ensure even better security, I also display a warning with confirmation before continuing if the server is using HTTP instead of HTTPS. There is many things happening that isn’t easy to see, and many little details (like some responsive resizing for low sized terminals) that many people may never encounteer, and I’m proud of how those devlogs are only like 7h long?? Anyway, here’s a video of where I currently am, and thanks for reading all of that garbage nonsense written by a french guy that isn’t quite good at telling things in foreign languages."}, {"post_id": 42308, "ts": "2026-08-06T23:19:36Z", "hours": 6.6911, "text": "Spent a few hours starting the CLI! For now it can only search for files and directory to send, while excluding socket and symlinks, and asking user if he want to excludes some others directory (like node_modules, cache or trashed files on macOS/Linux). Interface use colors, spinners and terminal screen width detection to avoid overflowing texts on another lines, providing a nice display when displaying large quantity of text, even if it’s only on screen for a few milliseconds. The files searching is really fast thank to Bun and some optimizations I did, here is a demo."}, {"post_id": 41111, "ts": "2026-08-05T03:10:10Z", "hours": 6.4781, "text": "Receiver can now receive chunks of data even if he wasn’t connected when the sender started sending them. Also, some communications are added between the receiver and the sender, such as a warning when the other one disconnect, or any other form of encrypted message. Senders were informed when they reached the max cached data limit, but are also now informed when this limit can be ignored (when the receiver download those cached data to free some space). And the thing you can see in the demo video: it is now possible to, as the receiver, restart an entire transfer if you connect to the download, disconnect, and reconnect again (because cached data are cleaned by the backend, which mean the sender has to send them again). I know “sender” and “receiver” are repeated 300x but idk how to explain this in a better way 😭🙏 (+ i’m french idk we’re all bad in this language tbh)"}, {"post_id": 38550, "ts": "2026-08-01T00:54:39Z", "hours": 6.45, "text": "After starting to get some progress on a test CLI (with both sending and receiving sides), we can now encrypt/send, and decrypt/download chunks on storage. I will make a few changes on how files saving will be handled because for now the receiver only get chunks data, and don’t know how to reassemble them. If you want, one of my git commit got this long ahh description: - Many more checks - Receiver can set their name (sender get notified) - Chunks are sent to receiver - receiver can acknowledge when they receive one, and chunks sending is paused if they have at least three chunks not ack. - An encryption protocol indicator is exchanged (not encrypted) to let clients know what encryption parameters to use - Chunks that are in the memory of the server has a maximum, afterwards we stop accepting more - Auto removal of all in-memory data of acknowledged chunks"}, {"post_id": 36745, "ts": "2026-07-29T00:19:25Z", "hours": 11.2589, "text": "Just started this new project! I’ve already wrote a loooong list of things I want to do (and how I want them to be done), will not post it here to avoid spoiling so wait a few changelog to know how the service will work! For now, I’ve only implemented a basic API that allows to create a share, returning a shareId that allows to request details about it ; I also started the implementation of a socket that will allow someone to download a file while it’s being uploaded. The backend will be done in Dart to allow the build of a light executable file, allowing an easier self-hosting while consuming less ressources. This language also enable me the possibility of including the server directly inside a Flutter made client, but I’m not sure I will use this possibility, I guess we will see!"}]...
|
Title: Fleer by @johan | Stardance
Devlogs:
Just Title: Fleer by @johan | Stardance
Devlogs:
Just started this new project! I’ve already wrote a loooong list of things I want to do (and how I want them to be done), will not post it here to avoid spoiling so wait a few changelog to know how the service will work! For now, I’ve only implemented a basic API that allows to create a share, returning a shareId that allows to request details about it ; I also started the implementation of a socket that will allow someone to download a file while it’s being uploaded. The backend will be done in Dart to allow the build of a light executable file, allowing an easier self-hosting while consuming less ressources. This language also enable me the possibility of including the server directly inside a Flutter made client, but I’m not sure I will use this possibility, I guess we will see!
After starting to get some progress on a test CLI (with both sending and receiving sides), we can now encrypt/send, and decrypt/download chunks on storage. I will make a few changes on how files saving will be handled because for now the receiver only get chunks data, and don’t know how to reassemble them. If you want, one of my git commit got this long ahh description: - Many more checks - Receiver can set their name (sender get notified) - Chunks are sent to receiver - receiver can acknowledge when they receive one, and chunks sending is paused if they have at least three chunks not ack. - An encryption protocol indicator is exchanged (not encrypted) to let clients know what encryption parameters to use - Chunks that are in the memory of the server has a maximum, afterwards we stop accepting more - Auto removal of all in-memory data of acknowledged chunks
Receiver can now receive chunks of data even if he wasn’t connected when the sender started sending them. Also, some communications are added between the receiver and the sender, such as a warning when the other one disconnect, or any other form of encrypted message. Senders were informed when they reached the max cached data limit, but are also now informed when this limit can be ignored (when the receiver download those cached data to free some space). And the thing you can see in the demo video: it is now possible to, as the receiver, restart an entire transfer if you connect to the download, disconnect, and reconnect again (because cached data are cleaned by the backend, which mean the sender has to send them again). I know “sender” and “receiver” are repeated 300x but idk how to explain this in a better way 😭🙏 (+ i’m french idk we’re all bad in this language tbh)
Spent a few hours starting the CLI! For now it can only search for files and directory to send, while excluding socket and symlinks, and asking user if he want to excludes some others directory (like node_modules, cache or trashed files on macOS/Linux). Interface use colors, spinners and terminal screen width detection to avoid overflowing texts on another lines, providing a nice display when displaying large quantity of text, even if it’s only on screen for a few milliseconds. The files searching is really fast thank to Bun and some optimizations I did, here is a demo.
We can send files using the CLI! I have some optimizations to make because sending small files is just as slow as sending large files, causing super low speed upload 💀 We also display the URL, command, and keys (used by the server) to connect as a receiver and start downloading files. The protocol is kinda complex and I’m planning to write a documentation on how to use it for any matter (like automations or 3rd party clients), and a terminal generally being for nerds (especially when a desktop GUI app is planned) make this the best place to showcase how the relay system really work, so I implemented a flag --debug-performances that log every actions into a file, also useful to debug performances (if you didn’t guessed…). The sender sends files to the relay, one by one, chunk by chunk to the relay, which will pipe them to the receiver afterwards. Chunks are fully encrypted on both clients and server cannot access their content whatsoever. To ensure even better security, I also display a warning with confirmation before continuing if the server is using HTTP instead of HTTPS. There is many things happening that isn’t easy to see, and many little details (like some responsive resizing for low sized terminals) that many people may never encounteer, and I’m proud of how those devlogs are only like 7h long?? Anyway, here’s a video of where I currently am, and thanks for reading all of that garbage nonsense written by a french guy that isn’t quite good at telling things in foreign languages.
Made a command to explain how Fleer relays, encryption and decryption work - always with a nice focus on terminal design, with colors, responsive and auto resize
Okay, changelog required even though I wasn’t planning on publishing it right now. Apart from some additions such as: --debug-socket flag that logs every actions happening between the client and a relay server Encryption protocol indicator (which is used by clients to know what algorithm and settings to use) is NOT known by the server anymore, as it is transferred in the share link itself Proper exit (and closure of spinner animations) when using Ctrl+C A few optimizations for responsive logs Downloading files is ALMOST done, I’m currently having many issues with slow file upload, and many attempts at optimizing it (that litteraly give me the idea of just quitting this project) and I’m making this changelog now because I think we might not finish this part of the CLI before at least 2 days. In the meantime, I daydreamed about many things I want to introduce into the project that will hopefully make a difference with others apps, even if I don’t have the same speed as them.
A few minors QoL changes: The CLI is automatically closed when download is finished, synced for both sender and receiver through an encrypted message that acts as a signal to tell both party they have done their job. Share Link is automatically copied into the clipboard of the sender, even if he’s remotely connected via SSH to another server. The directory in which files are saved is displayed at the end of execution (default to current folder). Improved performances when downloading. Some more verifications with the relay server used. Protect against Path Traversal vulnerability.
Didn’t wrote many lines of code on this project the last few days, was busy with personnal things so I’m listing what I pushed this week: User can decide what to do if a file already exist in the current directory (replace it, rename the new one, or skip this file). A new command fdd allows to start a download even faster, by checking the first parameter ( fdd <share_link> ) or any URL in the clipboard. fleer send command can generate a QR Code image, and display it for supported terminals (such as the incredible Ghostty). Download speed is displayed live in Mbps. Some fixes concerning security and downloading in specific conditions.
Not sure if Stardance will get extended until something like the end of September, so here am I (didn’t got many times to update the app and encountered many problems). A new command fleer relay followed by any Fleer Relay URL will output details about it. Receiver device name was sent in clear to the relay, it is now exchanged using encrypted messages. The transfer will be deleted if too many restarts happen (because messages size exceeds the limit for example). A structure containing all files, folders and path is included to give the receiver some visuals indications. If it’s too large, the structure will be dropped entirely. The amount of received/sent bytes will be displayed in Kbps instead of Mbps if it’s slow asf. Many bugs fixes and optimizations. The relay can now pauses transfers if it’s processing too many transfers at once. The indicated transfer size will include an estimated encryption overhead (the algorithm used can add some bytes to files). Transfers that shares MANY messages can use a feature from the relay that give clients ability to select the amount of cached bytes for messages and chunks. Inactives shares are deleted from the memory of the relay. The build version and latest commit pulled is returned to clients from the relay. Rate limits now apply to WebSocket messages.
After a few weeks without being able to do proper coding sessions (only got time to do it while being at school), I can finally release a new feature for Fleer! Integrity checking: after sending files, the receiver can ask the sender for a list of SHA-256 hashes. All communications are using encrypted messages to reduce the amount of things a malicious relay server can do. Integrity checking allows the receiver to be sure that files are identical from the sent one, and that the relay didn’t skipped chunks/files. I also added proper (and definitive) instructions for selfhosting a relay server by using Docker Compose (with prebuilt images via GitHub Actions), by building the image yourself with a Dockerfile, or to run from source. Reduce chunkSize when sending files if network conditions were really really bad before starting to send chunks.
Fleer is a decentralized platform, meaning anyone can host one or multiple relay servers. This devlog brings this concept even more to the Fleer CLI. Three lists of relay servers are hosted (on the GitHub repo, on my main website, and obviously on the Fleer landing page itself). These lists contain the URL for the currently only hosted relay. You can also add your own custom lists. In the future, the officials lists will include many more relays, from me or from anyone that contributes to the ecosystem, and the CLI is already prepared for that! I’m on a hotspot with like not even 1 Mbps so the video is just here for illustrative purposes 💀
Ships:
School is coming back soon, Stardance may be ending tomorrow, and I’m currently at 15% of what I want to do. I got an entire planning on Linear on what to do now. Fleer is a toxic-love project for me because of the numbers of issues I encountered, but I still want it to be done so bad. And yeah, I know testing is kinda hard now, I can’t publish an hosted testing instance so you will need to host it yourself (just one 30 MB Docker image to compile on any system and any architecture)....
|
1793087902.8764782
|
1793174302.8764782
|
|
15004
|
PixieR by @Cryskyy | Stardance
|
Cryskyy
|
1
|
7.0
|
95
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-12T07:36:32Z", "hours": 6.0, "multiplier": 15.1, "payout": 95, "blessing": "neutral", "text": "I make a project called “PixieR”, PixieR is a 100% client-side web tool that converts any image into pixel art directly in your browser. no backend, no API calls — everything happens locally using the HTML5 Canvas API. The Challenging part in my project is managing all the logic such as main.js and whole web logic system Im so proud that I can make this project without any trouble, and I hope everyone can test out my project :) Check up my github to try my project :))", "repo": "https://github.com/cryskyyexp-ux/PixieR-Project", "demo": "https://pixier.netlify.app/"}]...
|
[{"post_id": 8109, "ts": "2026 [{"post_id": 8109, "ts": "2026-06-13T15:13:52Z", "hours": 1.0, "text": "PixieR Project Devlog — Fixing the Stretching Bug & Other Issues Compare Slider stretching (main issue) Cause: syncCmpCanvas() set cmp.style.width='100%' and cmp.style.height='100%' together with objectFit:'contain' . object-fit only works on replaced elements like <img> and <video> — it has no effect on <canvas> , so the canvas was forced to fill the wrapper’s full 100% x 100% box regardless of its actual pixel aspect ratio, stretching the pixel art. Fix: Compute the display size manually based on the pixel canvas’s own aspect ratio ( src.width / src.height ), fit it within the wrapper width and a max height of 400px, then explicitly set cmp-canvas and cmp-orig-img width/height in pixels (with horizontal centering via marginLeft ). Both layers now share identical dimensions so the slider overlay aligns correctly. Pixel Only view overflow/stretch Cause: solo-canvas had a fixed inline max-width:100%;max-height:480px , while syncSoloCanvas() separately set style.width / style.height to width*zoom / height*zoom in px. At high zoom levels this could overflow the frame, and the max-width/max-height constraints distorted the aspect ratio independently on each axis. Fix: Removed the conflicting inline max-width/max-height. syncSoloCanvas() now computes the zoomed size, then uniformly scales both dimensions down by the same factor if it exceeds the frame’s width or a 480px height cap, preserving aspect ratio. Eyedropper coordinate mismatch Cause: pixelCanvas mousemove/click handlers divided mouse coordinates by the zoom slider value to find the pixel under the cursor. This breaks if the canvas’s rendered size ever differs from width * zoom (e.g. after future layout changes), giving wrong color picks. Fix: Replaced the zoom-based division with a ratio of the canvas’s actual bitmap size to its rendered bounding box size ( pixelCanvas.width / rect.width ), which is robust to any CSS scaling. Compare slider not resizing on window resize Cause: No resize handler existed for the compare/pixel-only views, so resizing the browser left stale dimensions and a stretched look. Fix: Added a resize listener that re-runs syncCmpCanvas() or syncSoloCanvas() depending on the active view. Dead/unused popup duplication Cause: The star popup markup was hardcoded in the page AND re-inserted via createPopupHTML() using insertAdjacentHTML , creating a duplicate #starPopup risk and unnecessary DOM bloat. Fix: Removed the redundant insertAdjacentHTML injection since the markup already exists in the page; createPopupHTML() now just guards against duplicates. Toast fallback dead code Cause: showToast() inside the popup IIFE recreated a whole second #toast element with inline styles if the existing one wasn’t found — but it always exists in the page, making this branch dead and bug-prone (it referenced var(--text, ...) colors that may not exist)."}, {"post_id": 7336, "ts": "2026-06-12T07:27:25Z", "hours": 0.0, "text": "Detailing My Project README.md and adding some detail"}, {"post_id": 7282, "ts": "2026-06-12T04:18:31Z", "hours": 3.0, "text": "Hi Guys this is my project explaination how does the Pixelate work on steps: Step 1: Shrink (this is where the magic happens) jsconst small = document.createElement(‘canvas’); small.width = 64; small.height = 64; small.getContext(‘2d’).drawImage(srcImg, 0, 0, 64, 64); Imagine your photo is 1920×1080 pixels. You squish it down into a 64×64 canvas. To fit a million pixrls into 64×64, the browser has to merge groups of pixels into one. It looks at a chunk of the original image (say, a 30×17 block) and blends them all into a single average color. Result: you now have a real, tiny image — 64×64 actual pixels, each one a blended color from a chunk of the original. Step 2: Blow it bacl up (with no smoothing) jscanvas.style.width = ‘384px’; // 64 × 6 canvas.style.height = ‘384px’; cssimage-rendering: pixelated; Now you take that tiny 64×64 image and stretch it to be way bigger on screen. Normally, browsers smooth out stretched images (blurry). The pixelated setting turns smoothing off. So each of the 64×64 pixels just gets copied into a big solid square — no blending, no blur. Result: big, crisp, blocky squares = the pixel art look. Putting It Together big detailed photo ↓ (squish down — merges pixels, loses detail) tiny 64×64 image ↓ (stretch up — no smoothing, just copy each pixel bigger) big blocky pixel art The squish is what creates the pixel art (real data, real file). The stretch is just so you can see it clearly on screen — it adds zero new information. Why the Download File is Small When you hit download, it saves the tiny 64×64 image (from Step 1) — not the big stretched version. The “blow it back up” part was only for your screen. And this done in client side, we dont collect your image or saving ur image"}, {"post_id": 6742, "ts": "2026-06-11T09:10:40Z", "hours": 1.0, "text": "DEVLOG : Project: PixieR Version: 2.0.0 Type: Web App (100% client-side) Stack: Vanilla JS + Canvas API + CSS License: MIT Status: Beta [+] Built: - Basic HTML structure with card-based UI - File upload with drag & drop support - Canvas setup for pixelation using Canvas API - Dark/light theme toggle with CSS custom properties - Interactive grid background with cursor glow effect [+] Pixelation Engine: - doPixelate() function that downsamples images - Three scale modes: Fit, Stretch, Crop - Realtime preview with 120ms debounce - Custom grid size input (4×4 to 1024×1024) - Preset chips: 16, 32, 64, 128, 256 - Linked dimensions toggle (🔗 / 🔓) [+] How pixelation works: Original Image ↓ drawImage(src, 0, 0, pixelW, pixelH) Tiny Canvas (W×H pixels) ↓ CSS image-rendering: pixelated Final display (zoomed with crisp edges) [+] Core Code Snippet: const small = document.createElement('canvas'); small.width = sw; small.height = sh; const sc = small.getContext('2d'); sc.drawImage(srcImg, 0, 0, sw, sh); out.getContext('2d').drawImage(small, 0, 0); [+] Key Decisions: - No frameworks → keep it lightweight (~18KB) - Single HTML file → easy to share, no build step - Canvas API → native browser support, fast [+] Challenges & Solutions: Challenge: Crop mode required calculating source coordinates Solution: Used aspect ratio comparison to determine sx, sy, sW, sH Challenge: Maintaining aspect ratio in Fit mode Solution: Compare pw/ph vs srcRatio to determine scaling axis Challenge: Making chips highlight correctly on value change Solution: setChipActive() toggles .on class based on value [+] View Modes: - Side by Side (split-view) - Compare Slider (drag to compare original vs pixelated) - Pixel Only (fullscreen pixel art display) [+] Compare Slider Implementation: /* Clip the pixelated layer */ #compare-pixel { clip-path: inset(0 50% 0 0); } Drag updates percentage → changes clip-path value dynamically. Supports both mouse and touch events for mobile. [+] Eyedropper Tool: - Hover over any pixel to see hex color - Click to copy hex code to clipboard - Tooltip follows cursor with color preview [+] Eyedropper Logic: pixelCanvas.addEventListener('mousemove', (e) => { const cx = Math.floor((e.clientX - rect.left) / zoom); const cy = Math.floor((e.clientY - rect.top) / zoom); const px = ctx.getImageData(cx, cy, 1, 1).data; const hex = '#' + px[0].toString(16) + ...; tip.innerHTML = `${hex} (${cx},${cy})`; }); [+] Export Features: - Download as PNG, JPG, or WebP - Automatic filename: pixier_{W}x{H}.ext [+] Zoom Slider: - Range: 1× to 20× - CSS-based scaling, doesn’t re-render - Maintains crisp pixelated edges [+] The “Pixelate!” Button Experience: - Disabled until image loaded - 5-second “processing” animation (UX theater) - Controls unlock after first conversion - Shimmer effect on completion - After first use: realtime updates (120ms debounce)"}]...
|
Title: PixieR by @Cryskyy | Stardance
Devlogs:
DE Title: PixieR by @Cryskyy | Stardance
Devlogs:
DEVLOG : Project: PixieR Version: 2.0.0 Type: Web App (100% client-side) Stack: Vanilla JS + Canvas API + CSS License: MIT Status: Beta [+] Built: - Basic HTML structure with card-based UI - File upload with drag & drop support - Canvas setup for pixelation using Canvas API - Dark/light theme toggle with CSS custom properties - Interactive grid background with cursor glow effect [+] Pixelation Engine: - doPixelate() function that downsamples images - Three scale modes: Fit, Stretch, Crop - Realtime preview with 120ms debounce - Custom grid size input (4×4 to 1024×1024) - Preset chips: 16, 32, 64, 128, 256 - Linked dimensions toggle (🔗 / 🔓) [+] How pixelation works: Original Image ↓ drawImage(src, 0, 0, pixelW, pixelH) Tiny Canvas (W×H pixels) ↓ CSS image-rendering: pixelated Final display (zoomed with crisp edges) [+] Core Code Snippet: const small = document.createElement('canvas'); small.width = sw; small.height = sh; const sc = small.getContext('2d'); sc.drawImage(srcImg, 0, 0, sw, sh); out.getContext('2d').drawImage(small, 0, 0); [+] Key Decisions: - No frameworks → keep it lightweight (~18KB) - Single HTML file → easy to share, no build step - Canvas API → native browser support, fast [+] Challenges & Solutions: Challenge: Crop mode required calculating source coordinates Solution: Used aspect ratio comparison to determine sx, sy, sW, sH Challenge: Maintaining aspect ratio in Fit mode Solution: Compare pw/ph vs srcRatio to determine scaling axis Challenge: Making chips highlight correctly on value change Solution: setChipActive() toggles .on class based on value [+] View Modes: - Side by Side (split-view) - Compare Slider (drag to compare original vs pixelated) - Pixel Only (fullscreen pixel art display) [+] Compare Slider Implementation: /* Clip the pixelated layer */ #compare-pixel { clip-path: inset(0 50% 0 0); } Drag updates percentage → changes clip-path value dynamically. Supports both mouse and touch events for mobile. [+] Eyedropper Tool: - Hover over any pixel to see hex color - Click to copy hex code to clipboard - Tooltip follows cursor with color preview [+] Eyedropper Logic: pixelCanvas.addEventListener('mousemove', (e) => { const cx = Math.floor((e.clientX - rect.left) / zoom); const cy = Math.floor((e.clientY - rect.top) / zoom); const px = ctx.getImageData(cx, cy, 1, 1).data; const hex = '#' + px[0].toString(16) + ...; tip.innerHTML = `${hex} (${cx},${cy})`; }); [+] Export Features: - Download as PNG, JPG, or WebP - Automatic filename: pixier_{W}x{H}.ext [+] Zoom Slider: - Range: 1× to 20× - CSS-based scaling, doesn’t re-render - Maintains crisp pixelated edges [+] The “Pixelate!” Button Experience: - Disabled until image loaded - 5-second “processing” animation (UX theater) - Controls unlock after first conversion - Shimmer effect on completion - After first use: realtime updates (120ms debounce)
Hi Guys this is my project explaination how does the Pixelate work on steps: Step 1: Shrink (this is where the magic happens) jsconst small = document.createElement(‘canvas’); small.width = 64; small.height = 64; small.getContext(‘2d’).drawImage(srcImg, 0, 0, 64, 64); Imagine your photo is 1920×1080 pixels. You squish it down into a 64×64 canvas. To fit a million pixrls into 64×64, the browser has to merge groups of pixels into one. It looks at a chunk of the original image (say, a 30×17 block) and blends them all into a single average color. Result: you now have a real, tiny image — 64×64 actual pixels, each one a blended color from a chunk of the original. Step 2: Blow it bacl up (with no smoothing) jscanvas.style.width = ‘384px’; // 64 × 6 canvas.style.height = ‘384px’; cssimage-rendering: pixelated; Now you take that tiny 64×64 image and stretch it to be way bigger on screen. Normally, browsers smooth out stretched images (blurry). The pixelated setting turns smoothing off. So each of the 64×64 pixels just gets copied into a big solid square — no blending, no blur. Result: big, crisp, blocky squares = the pixel art look. Putting It Together big detailed photo ↓ (squish down — merges pixels, loses detail) tiny 64×64 image ↓ (stretch up — no smoothing, just copy each pixel bigger) big blocky pixel art The squish is what creates the pixel art (real data, real file). The stretch is just so you can see it clearly on screen — it adds zero new information. Why the Download File is Small When you hit download, it saves the tiny 64×64 image (from Step 1) — not the big stretched version. The “blow it back up” part was only for your screen. And this done in client side, we dont collect your image or saving ur image
Detailing My Project README.md and adding some detail
PixieR Project Devlog — Fixing the Stretching Bug & Other Issues Compare Slider stretching (main issue) Cause: syncCmpCanvas() set cmp.style.width='100%' and cmp.style.height='100%' together with objectFit:'contain' . object-fit only works on replaced elements like <img> and <video> — it has no effect on <canvas> , so the canvas was forced to fill the wrapper’s full 100% x 100% box regardless of its actual pixel aspect ratio, stretching the pixel art. Fix: Compute the display size manually based on the pixel canvas’s own aspect ratio ( src.width / src.height ), fit it within the wrapper width and a max height of 400px, then explicitly set cmp-canvas and cmp-orig-img width/height in pixels (with horizontal centering via marginLeft ). Both layers now share identical dimensions so the slider overlay aligns correctly. Pixel Only view overflow/stretch Cause: solo-canvas had a fixed inline max-width:100%;max-height:480px , while syncSoloCanvas() separately set style.width / style.height to width*zoom / height*zoom in px. At high zoom levels this could overflow the frame, and the max-width/max-height constraints distorted the aspect ratio independently on each axis. Fix: Removed the conflicting inline max-width/max-height. syncSoloCanvas() now computes the zoomed size, then uniformly scales both dimensions down by the same factor if it exceeds the frame’s width or a 480px height cap, preserving aspect ratio. Eyedropper coordinate mismatch Cause: pixelCanvas mousemove/click handlers divided mouse coordinates by the zoom slider value to find the pixel under the cursor. This breaks if the canvas’s rendered size ever differs from width * zoom (e.g. after future layout changes), giving wrong color picks. Fix: Replaced the zoom-based division with a ratio of the canvas’s actual bitmap size to its rendered bounding box size ( pixelCanvas.width / rect.width ), which is robust to any CSS scaling. Compare slider not resizing on window resize Cause: No resize handler existed for the compare/pixel-only views, so resizing the browser left stale dimensions and a stretched look. Fix: Added a resize listener that re-runs syncCmpCanvas() or syncSoloCanvas() depending on the active view. Dead/unused popup duplication Cause: The star popup markup was hardcoded in the page AND re-inserted via createPopupHTML() using insertAdjacentHTML , creating a duplicate #starPopup risk and unnecessary DOM bloat. Fix: Removed the redundant insertAdjacentHTML injection since the markup already exists in the page; createPopupHTML() now just guards against duplicates. Toast fallback dead code Cause: showToast() inside the popup IIFE recreated a whole second #toast element with inline styles if the existing one wasn’t found — but it always exists in the page, making this branch dead and bug-prone (it referenced var(--text, ...) colors that may not exist).
Ships:
I make a project called “PixieR”, PixieR is a 100% client-side web tool that converts any image into pixel art directly in your browser. no backend, no API calls — everything happens locally using the HTML5 Canvas API. The Challenging part in my project is managing all the logic such as main.js and whole web logic system Im so proud that I can make this project without any trouble, and I hope everyone can test out my project :) Check up my github to try my project :))...
|
1792878745.9209418
|
1793742745.9209418
|
|
70543
|
Maware by @cauadev | Stardance
|
cauadev
|
0
|
0.68
|
0
|
[]
|
[{"post_id": 81091, "ts": "202 [{"post_id": 81091, "ts": "2026-10-19T20:52:08Z", "hours": 0.6833, "text": "Hello! About Maware Maware (Ma WarioWare, pun with “Malware” kinda intended) is my own clone of WarioWare, meant to learn Godot and earn the Stardust it lacks for me to get the Bambu Lab A1 Mini 3D printer. What I did for now Only the main menu (at least the buttons do their work)"}]...
|
Title: Maware by @cauadev | Stardance
Devlogs:
He Title: Maware by @cauadev | Stardance
Devlogs:
Hello! About Maware Maware (Ma WarioWare, pun with “Malware” kinda intended) is my own clone of WarioWare, meant to learn Godot and earn the Stardust it lacks for me to get the Bambu Lab A1 Mini 3D printer. What I did for now Only the main menu (at least the buttons do their work)...
|
1793047698.1894777
|
1793652498.1894777
|
|
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
|
|
68590
|
CAR HOME THEATER by @GOST | Stardance
|
GOST
|
0
|
10.96
|
0
|
[]
|
[{"post_id": 81102, "ts": "202 [{"post_id": 81102, "ts": "2026-10-19T21:26:02Z", "hours": 0.3175, "text": "sub bracket desine"}, {"post_id": 80363, "ts": "2026-10-17T12:40:33Z", "hours": 0.5156, "text": "stand for seround speaker"}, {"post_id": 79777, "ts": "2026-10-15T11:06:48Z", "hours": 0.9733, "text": "emproving the centre sound speaker"}, {"post_id": 79767, "ts": "2026-10-15T10:02:51Z", "hours": 9.1583, "text": "i am working one using car items to mack a home theater"}]...
|
Title: CAR HOME THEATER by @GOST | Stardance
Devl Title: CAR HOME THEATER by @GOST | Stardance
Devlogs:
i am working one using car items to mack a home theater
emproving the centre sound speaker
stand for seround speaker
sub bracket desine...
|
1793123435.8605554
|
1793728235.8605554
|
|
69481
|
My awesome macropad! by @FineDust | Stardance
|
FineDust
|
1
|
0.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-19T22:33:13Z", "hours": 0.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Hackpad From the mission my awesome macropad one of the biger problems I faced was not understanding the software properly witch I was useing. apart from that the rest of the project was more less smooth sailing", "repo": "https://github.com/xxfinedustxx/HackPad", "demo": ""}]...
|
[{"post_id": 81107, "ts": "202 [{"post_id": 81107, "ts": "2026-10-19T22:12:14Z", "hours": 2.7911, "text": "Hackpad Hackpad at 99% done design stage"}, {"post_id": 80753, "ts": "2026-10-18T18:20:21Z", "hours": 9.6578, "text": "Devlog 3 Hi everyone! It’s a lil’ update today. Just made my HackPad CAD case model so it can be checked off the list: PCB layout HackPad case modeled Code & firmware It took about 8 hours of compromising with the CAD software, but the enclosure layout is roughly 90% done. So it’s about time to start cooking up some custom firmware."}, {"post_id": 80009, "ts": "2026-10-15T23:25:18Z", "hours": 4.5928, "text": "2. Devlog ~01:00 16.10.2026 Hey everyone! I’ve just finished the PCB layout for my HackPad project! Next up, I’ll be diving into the 3D design phase for the case. That’s all for this update—if you have any suggestions or questions, feel free to drop them below!"}, {"post_id": 79653, "ts": "2026-10-14T22:31:15Z", "hours": 1.6694, "text": "I did some work on the PCB but not that much to make a devlog. So here; who wants to rate my Linux setup x/10."}, {"post_id": 79417, "ts": "2026-10-13T21:43:00Z", "hours": 1.4689, "text": "This is a PCB (not yet, but still a PCB); it’s going to be a great Stream Deck one day."}]...
|
Title: My awesome macropad! by @FineDust | Stardan Title: My awesome macropad! by @FineDust | Stardance
Devlogs:
This is a PCB (not yet, but still a PCB); it’s going to be a great Stream Deck one day.
I did some work on the PCB but not that much to make a devlog. So here; who wants to rate my Linux setup x/10.
2. Devlog ~01:00 16.10.2026 Hey everyone! I’ve just finished the PCB layout for my HackPad project! Next up, I’ll be diving into the 3D design phase for the case. That’s all for this update—if you have any suggestions or questions, feel free to drop them below!
Devlog 3 Hi everyone! It’s a lil’ update today. Just made my HackPad CAD case model so it can be checked off the list: PCB layout HackPad case modeled Code & firmware It took about 8 hours of compromising with the CAD software, but the enclosure layout is roughly 90% done. So it’s about time to start cooking up some custom firmware.
Hackpad Hackpad at 99% done design stage
Ships:
Hackpad From the mission my awesome macropad one of the biger problems I faced was not understanding the software properly witch I was useing. apart from that the rest of the project was more less smooth sailing...
|
1793008232.779978
|
1793094632.779978
|
|
70556
|
80mm velocity stack by @kapkupi | Stardance
|
kapkupi
|
0
|
1.42
|
0
|
[]
|
[{"post_id": 81108, "ts": "202 [{"post_id": 81108, "ts": "2026-10-19T22:12:43Z", "hours": 1.42, "text": "Yeah while waiting for a print of another project to finish I decided to make this velocity stack. Nothing to difficult or complicated but useful maybe. Will probably get a crisp 10 stardust from this but who cares. It is not about the money it is about the airflow ,’) … I think it is a tad bit too big There is never too big >.>"}]...
|
Title: 80mm velocity stack by @kapkupi | Stardance Title: 80mm velocity stack by @kapkupi | Stardance
Devlogs:
Yeah while waiting for a print of another project to finish I decided to make this velocity stack. Nothing to difficult or complicated but useful maybe. Will probably get a crisp 10 stardust from this but who cares. It is not about the money it is about the airflow ,’) … I think it is a tad bit too big There is never too big >.>...
|
1793062316.162566
|
1793667116.162566
|
|
35722
|
GBWeb by @Doodl0 | Stardance
|
Doodl0
|
0
|
50.76
|
0
|
[]
|
[{"post_id": 81110, "ts": "202 [{"post_id": 81110, "ts": "2026-10-19T22:32:59Z", "hours": 6.6672, "text": "Devlog 10 - (basically) Finishing the CPU After the last devlog, I did some cleaning up with the graphics, which included fixing the last scanline not being rendered, and also adding a screen before the ROM is loaded, telling the user which key to press to load the ROM. I also set up some functions to allow easier access to the I/O registers related to the PPU, such as the x and y scroll and the control flags. Afterwards, I felt a bit burnt out of the PPU, so I went back to finish off most of the CPU. This started with implementing the CFL, CPL, CF, CPL, SCF, SLA, SRA, RL, RLA, RLC, RRC, RLCA, and RRCA instructions, most of which are bit rotations, so once I had a few implemented, it got easier to add the rest. This allowed me to pass CPU test ROM 9. Then, I implemented the rest of the CB prefix instructions, which were all bit related; BIT, RES and SET, which allowed me to pass ROM 10 After those, I implemented some stack pointer related instructions; ADD SP,d and LD HL SP+d, which then allowed me to pass ROM 3 Finally, I added DAA. This one is a bit more unique, as it is designed to convert the result of an add or subtract with binary coded decimal numbers, into a binary coded decimal number. This gets a bit complicated, but I used these resources ( Demystifying the GameBoy/SM83’s DAA Instruction and the RGBDS assembler/linker instruction documentation ) to implement this properly, allowing me to also pass test ROM 1 With a semi-functioning PPU, and some fixes, I was also able to boot into the copyright screen of Tetris for the first time, although I couldn’t get any further without implementing interrupts. The image below shows that, and my emulator passing all of the previously mentioned test ROMs. The only test ROM I haven’t passed yet is the 2nd one, which also requires interrupts."}, {"post_id": 80353, "ts": "2026-10-17T11:17:07Z", "hours": 4.04, "text": "Devlog 9 - Basic graphics (finally) I’ve finally gotten some basic picture processing unit (PPU) functionality implemented into the emulator, which will hopefully make debugging a lot easier going forward. Firstly, to implement this, I had to move the timing logic out of cpu.c and into cycles.c . This was so that, when the loop calls a CPU step, it also calls a PPU step at the same time. I also refactored some of the cycle functions and removed the ones that were no longer being used Then, I implemented the timing code for the PPU. This part and the actual rendering were mostly based on this tutorial series that shows you how to make a GB emulator in javascript, which I based my C code on. Basically, the PPU runs on the clock as the CPU, and a ‘dot’ on the PPU is equal to a T-cycle on the CPU. The PPU renders progressively, like a CRT television, and so also has modes to move the nonexistent electron beam down and back to the start of a scanline before it continutes rendering, known as VBLANK and HBLANK, (vertical and horizontal blank). The Pan Docs were also quite helpful for understanding the basic functionality, although the tutorial was useful to understand the programmatic side. The PPU also has 2 other modes, used for scanning the Object Attribute Memory (OAM) and actually drawing, and all 4 modes have a precise amount of dots that they run for. In terms of actual rendering, the Gameboy doesn’t have a full framebuffer, and instead uses different tiles to create a full image. I implemented a function that, when the CPU writes to VRAM, also updates the data in a separate tileset variables, for easier access in the render pipeline. Each tile is 16 bytes, with 2 bits per pixel colour depth, and 8 x 8 pixels per tile. As the Gameboy renders progressively, I then implemented the function to draw a scanline to the screen, based on the tile data in the background layer. The afformentioned tutorial series helped a lot here, as the tiles need to have a specific offset and mapping applied which would be quite hard to figure out on my own. Then, that function calls a draw pixel function for each each of the 160 pixels in a scanline, which writes the corresponding colour from the palette to an SDL_Surface as the framebuffer. Once the frame is finished, the surface is converted into a texture, which is then scaled to fit the screen size and rendered, with another frame being made afterwards. Below you can see the screen of the previously mentioned blargg’s test ROM 7."}, {"post_id": 79179, "ts": "2026-10-12T22:23:50Z", "hours": 6.5228, "text": "Devlog 8 - Organisation, and timing, again Ok, so this didn’t exactly go how I wanted (again), but most of this devlog time was spent fixing the past devlog, and organising code in a better way Firstly: I realised that before, my timing code checked based on M-cycles, rather than T-cycles. There’s a specific reason for the distinction, but for now all you need to know is that there’s 4 T-cycles in an M-cycle, so my code was targeting a 4x faster speed. I changed this to be correct, but changed it again later so it doesn’t really matter. Then, I cleaned up a lot of cpu.c , changing functions to return values directly rather than using a local variable first, pre-calculating some variables, et cetera. This was an attempt to speed up the CPU, as I was having a bit of trouble meeting the target speed with debug builds (mentioned in devlog 7), but again, this was a bit pointless because I changed the way the timing worked later. While doing this, I also replaced all of the numerical types with their stdint.h counterparts; for example, an unsigned char became a Uint8 (SDL has macros for the stdint types, so they have a slight naming difference from standard C in my code). This was mainly done for specificity and some Hail Mary for performance (although fruitless), and should make the code at least a bit more portable and easy to maintain. I also implemented a couple of new instructions; RST and SWAP. RST effectively calls from a set of pre-specified addresses , and SWAP just swaps the upper and lower 8 bits in a byte, so these weren’t too hard. I also had to fix some bugs with the flags register´s value after an SBC A instruction, which admittedly did take me a while to fix because I basically banged my head against the wall to fix it. The main change in this devlog was switching the timing system (again). Previously, the CPU ran one instruction for each loop of the SDL_AppIterate function. After reading the documentation and realising that this function is supposed to run each frame, I realised that I was causing all of my speed issues by only doing one cycle per iteration. Instead, the code now does as many instructions as it can until it has run enough T-cycles for a full frame to render (70224). It then renders (to be implemented), and moves on to the next iteration. This is way more performant, and has the added benefit of being more cross-platform, as SDL specifies that sometimes AppIterate may only run at the refresh rate on some devices. Tbh, this took me a while, maybe too long, to conceptualise and implement, and basically made all of the time on the other timing system wasted, but in the end it was worth it for a much better system. You can see the uncapped FPS (in a debug build mind you) here, although when actually playing games, the framerate will be locked to around 60 FPS. Finally, there was a few more miscellaneous changes: copying a ROM file into memory uses memcpy instead of a loop, which may or may not be faster; memory is now a union of smaller arrays of memory banks, for each function, such as work ram (WRAM), high ram (HRAM), ROM banks 0-n and etc; and lastly, some register code has been moved out of cpu.c for organisation."}, {"post_id": 77175, "ts": "2026-10-05T22:31:28Z", "hours": 5.0036, "text": "Devlog 7 - Timing The next main thing I implemented were some more instructions - namely SRL, RR, RRA and ADD HL. These weren’t too hard, as the first 3 are similar to regular bit shifts, and ADD HL is just adding. While I was working on these, I also fixed some bugs with the existing instructions This allowed me to finally pass the cpu_instrs 6 test ROM, which although not really a massive goal, did help to signify the progress I had made. I then moved onto the 7th test, for which I implemented some load functions for the stack pointer register The biggest improvement of this devlog was getting everything timing correctly. The Gameboy is supposed to run at 4.19 MHz and 59.7 FPS, but at the time, the emulator was just running as fast as possible. To solve this, I first made each instruction call a function to add the amount of cycles it takes to a unwaitedCycles variable. Then, I saved the current time in nanoseconds since the program started (provided by the SDL_GetTicksNS() function) into a variable at the start of an instruction’s execution. After the instruction is executed, a function is then called that finds the expected execution time the by doing the amount of cycles multiplied by the period of 4.19MHz (about 238 nanoseconds). This expected time is then subtracted from the actual time, which is the start time stored previously subtracted from the current time. The program is then delayed by the result, which should keep the CPU at around 4.19MHz, unless it takes too long. I did have some concerns with my emulator’s performance, as when running as a debug build, it wasn’t running nearly fast enough to reach 4.19MHz, but after compiling as a release build with optimisation, it was much faster and ran under the required time. However, I’m not sure how consistent this will be between devices, so I may have to optimise later Finally, I added a similar function to limit the FPS to around 60 (technically 59.7), which just checks the time since the last frame was rendered, and if it hasn’t been long enough, it continues CPU execution and doesn’t render. You can see the frame limit working in the screenshot, where the frametime is a consistent 16.8 ms and the FPS is locked to 60, as opposed to before where it was unlimited. (Ignore the text, it doesn’t change yet to show a ROM has been loaded)"}, {"post_id": 76068, "ts": "2026-10-02T07:40:09Z", "hours": 5.4931, "text": "Devlog 6 - An unfortunate amount of debugging This devlog is probably going to be shorter than the other, simply because I haven’t done as much as I hoped The main reason for this is that I got completely stuck on a bug, and wasted so much time trying to find it. I first noticed this bug when I got this error message (screenshot) in gameboy-doctor, with a mismatch with a load from memory not being the right value. This got me so stuck, because I didn’t know where to find when the memory was supposed to be written to, so I was basically blindly guessing what was wrong with any previous loads or register writes. Eventually, I caved and asked for help online, and I got my answer after asking on the EmuDev subreddit , where I found out it was an issue with my implementation of the LD (FF00+u8), A instructions, where I wrote LD_n16_n8((0xFF00 + address + 1), registers.a); instead of the correct LD_n16_n8((0xFF00 + ReadMemory(address + 1)), registers.a); so basically any writes to memory using that function were in the complete wrong location. Stupid mistake on my part, and I wasted way too much time on it. I also did implement some basic instructions, like EI and RETI. EI simply enables the emi register, and RETI basically just does that, then calls RET to return from a subroutine. In addition, I also restructured quite a lot of the code, as too much was piling up in the cpu.c file, and I also renamed quite a few functions to follow a Component_Function syntax, so it was easier to tell where they were located in the code"}, {"post_id": 73310, "ts": "2026-09-24T20:22:22Z", "hours": 6.5411, "text": "Devlog 5 - Adding instructions, the stack and lots of debugging After the last devlog, the first think I did was implement some more instructions, namely the jump instructions, and the increment and decrement functions. Luckily these were pretty simple; all the jumps do are set the program counter (effectively the next instruction) to a specified value, and the increment and decrement are pretty self explanatory, increasing or decreasing a register or memory byte by 1; After this, I started implementing the stack. The stack is a section of memory that is ordered, with values being written to it (pushed) and read off of it (popped). You must read the “top” value, meaning the most recently pushed, which is then removed and the next highest is the next available to read. This wasn’t too hard, although I did have to introduce a new register, the stack pointer (sp). While I was at it, I also implemented load functions, which load data into a specified memory byte or register. After realising it would cause issues down the line, I walked back my previous decision to make the flags register a struct of booleans, and instead made it a single byte with 4 bits representing the 4 flags, making it more accurate. I also made some functions to easily set or reset each flag, rather than use bitwise operations everywhere. Finally, I implemented logging support, so that I could use Gameboy Doctor , a brilliant debugging script that reads a log file from your emulator with a known ROM, and compares it to the correct result. All you have to do is write a line to a log file with all the register values and some memory bytes after each instruction, and it automatically tells you where the first error is, what register or piece of memory is wrong, and even the last instruction to give you a hint as to the problem. This didn’t take much time to implement, but I did spend a considerable amount of time debugging, as previously I hadn’t actually got a way to check that my functions worked correctly (which is why this devlog has quite a few more hours on it). You can see an example of a error in the screenshot; I intentionally changed the SUB instruction to add instead because I forgot to take screenshots of the actual errors 🥀. Next time, I want to implement more of the CPU, especially more complex behaviours like halting and interrupts, and also implement some of the graphics, so that the games can actually be seen visually."}, {"post_id": 71263, "ts": "2026-09-20T15:22:40Z", "hours": 5.355, "text": "Devlog 4 - Memory mapping and instruction stepping The next thing I worked on was getting a basic function set up for stepping through instructions and calling the execute function. To do this, I also had to make a program counter, which is a 16 bit register storing the address of the next instruction. Currently, the step function is pretty barebones, but it simply calls the execute function, passes it the PC as a parameter, and then sets the program counter to be the returned address. The execute function has also been modified, meaning it reads the instruction from memory (more on that later) rather than being passed it directly, and return the address plus 1 to 3 bytes, depending on the instruction that was executed. The next bit I made was the Game Boy’s memory. This is simply an char array with 64K values, equivalent to 64KiB of memory. Then, any address can be accessed simply by accessing the array value at an address. After working on the other parts of the CPU, I went back to working on some instructions, implementing the rest of the disassembly tables , including the condition call table, which checks the flags register before executing an instruction. I also implemented some of the instructions that require inputting an address in memory to use instead of a number or register. Finally, I also worked on some quality of life features. First, I made a function to replace missing functions, which simply sends an error message with the function name, and quits with an error code. Secondly, I made / edited some functions to actually move the loaded ROM file into the main GB memory rather than the program memory. I had a little trouble troubleshooting this, as I didn’t at first have a reliable way to verify that the data had been copied successfully, and after I did, I still had trouble with pointers, as I am still pretty new to C’s manual memory management (I usually just keep things in the stack, or have global variables that will persist throughout the program’s lifetime.). I also added basic functionality for loading a ROM on desktop rather than the web, but it doesn’t use the system dialog yet, only loading a rom.gb file in the executable directory. After everything was working, I added a debug message to send the ROM’s header title, showing that it actually works. You can see this in the screenshot. It sends the message twice, once when the file is loaded, and once when it’s moved to GB memory, which I did to make sure that the transfer didn’t mess up the data accidentally."}, {"post_id": 68852, "ts": "2026-09-15T21:21:15Z", "hours": 3.9186, "text": "Devlog 3 - Algorithmically parsing opcodes After getting things functioning well in the browser, I wanted to move onto the actual emulator bit of the project. Firstly, I looked at a bunch of examples and info, mostly compiled from gbdev.io . At first, I followed both the development blog of Cinoop and the guide DMG-01 . I used these guides to first write the register struct, which is basically just a struct of bytes (in char form as I’m using C), as well as the flags register, which I took inspiration from DMG-01 by making it primarily a struct of 4 bools rather than a binary value, for easier setting. I also wrote functions for converting this into binary though so that I didn’t lose compatibility. Next, I used Decoding Gameboy Z80 Opcodes to write an algorithmic way to decide which instruction correlates to an opcode, instead of a large switch case (although admittedly it does have a lot of nested switch cases). Finally, I added in the “alu” table instructions as the first few instructions, which also happened to be quite simple as they were basically just addition, subtraction and some bitwise operations. Next, I plan to fill in the remaining instructions, add them all to the algorithm and get started on the actual control flow for the CPU"}, {"post_id": 47709, "ts": "2026-08-15T20:02:53Z", "hours": 3.5792, "text": "Devlog 2 - SDL3 and File Loading After setting up the project basics, I spent some time on another project, also using SDL, but a desktop app. This used SDL3 instead of SDL2, which is default for Emscripten. I decided to switch this project to SDL3 as well, since I feel more comfortable with it and it has some features like main callbacks that should help with Emscripten. Instead of using the SDL library bundled with Emscripten, I instead added the SDL3 repo as a submodule, so I should be able to make a desktop version of the program later relatively easily. After switching to SDL3, I researched how to load a file from the user in the web browser into the webasm program. I found a StackOverflow thread that helped a lot, which included a link to a more developed header library, however I opted not to use this, as it was C++ based, and I wanted to remain using C. Instead I just implemented the bits I needed from the thread in C, which wasn’t too hard, although included some JS, which I’ve never used and some pointers which I made a few stupid mistakes with, causing me to think it didn’t work for a while. Finally, I also added a keybind to open the file dialog, which currently is tab, and also made sure that the keys only register on the down press, and not the up as well."}, {"post_id": 29056, "ts": "2026-07-15T18:26:42Z", "hours": 3.6419, "text": "Devlog 1 - Setup and basic input I took a while to find a toolchain that I liked, but I’ve settled on using Emscripten, and it’s built in version of SDL2. Emscripten is a library and compiler for CXX that allows direct compilation to web assembly and JavaScript, also allowing graphics and input with SDL. This makes it a lot easier for me to write the program, as I don’t really need to know as much JS or find multiple different libraries to use. Originally I wanted to use SDL3, but I couldn’t get the input to work automatically with Emscripten, and with this being my first major C and web project, I decided to take the easier path and simply use the fully supported SDL2. I also spent some time setting up a simple CMake system and some scripts for building and running, which took me a while to figure out, especially as I was also learning Emscripten for the first time, however it will hopefully save me time in the long run. Just to test my implementation, I set up some keybinds for the eventual emulator to come. I just used SDL scancodes to check for the key press, and they printed the corresponding Gameboy button to the output. You can see this in the video below. For simplicity, I decided to just set keys in code, with WASD being the dpad, J being A, K being B, Return being Start and Backspace being select."}]...
|
Title: GBWeb by @Doodl0 | Stardance
Devlogs:
Devl Title: GBWeb by @Doodl0 | Stardance
Devlogs:
Devlog 1 - Setup and basic input I took a while to find a toolchain that I liked, but I’ve settled on using Emscripten, and it’s built in version of SDL2. Emscripten is a library and compiler for CXX that allows direct compilation to web assembly and JavaScript, also allowing graphics and input with SDL. This makes it a lot easier for me to write the program, as I don’t really need to know as much JS or find multiple different libraries to use. Originally I wanted to use SDL3, but I couldn’t get the input to work automatically with Emscripten, and with this being my first major C and web project, I decided to take the easier path and simply use the fully supported SDL2. I also spent some time setting up a simple CMake system and some scripts for building and running, which took me a while to figure out, especially as I was also learning Emscripten for the first time, however it will hopefully save me time in the long run. Just to test my implementation, I set up some keybinds for the eventual emulator to come. I just used SDL scancodes to check for the key press, and they printed the corresponding Gameboy button to the output. You can see this in the video below. For simplicity, I decided to just set keys in code, with WASD being the dpad, J being A, K being B, Return being Start and Backspace being select.
Devlog 2 - SDL3 and File Loading After setting up the project basics, I spent some time on another project, also using SDL, but a desktop app. This used SDL3 instead of SDL2, which is default for Emscripten. I decided to switch this project to SDL3 as well, since I feel more comfortable with it and it has some features like main callbacks that should help with Emscripten. Instead of using the SDL library bundled with Emscripten, I instead added the SDL3 repo as a submodule, so I should be able to make a desktop version of the program later relatively easily. After switching to SDL3, I researched how to load a file from the user in the web browser into the webasm program. I found a StackOverflow thread that helped a lot, which included a link to a more developed header library, however I opted not to use this, as it was C++ based, and I wanted to remain using C. Instead I just implemented the bits I needed from the thread in C, which wasn’t too hard, although included some JS, which I’ve never used and some pointers which I made a few stupid mistakes with, causing me to think it didn’t work for a while. Finally, I also added a keybind to open the file dialog, which currently is tab, and also made sure that the keys only register on the down press, and not the up as well.
Devlog 3 - Algorithmically parsing opcodes After getting things functioning well in the browser, I wanted to move onto the actual emulator bit of the project. Firstly, I looked at a bunch of examples and info, mostly compiled from gbdev.io . At first, I followed both the development blog of Cinoop and the guide DMG-01 . I used these guides to first write the register struct, which is basically just a struct of bytes (in char form as I’m using C), as well as the flags register, which I took inspiration from DMG-01 by making it primarily a struct of 4 bools rather than a binary value, for easier setting. I also wrote functions for converting this into binary though so that I didn’t lose compatibility. Next, I used Decoding Gameboy Z80 Opcodes to write an algorithmic way to decide which instruction correlates to an opcode, instead of a large switch case (although admittedly it does have a lot of nested switch cases). Finally, I added in the “alu” table instructions as the first few instructions, which also happened to be quite simple as they were basically just addition, subtraction and some bitwise operations. Next, I plan to fill in the remaining instructions, add them all to the algorithm and get started on the actual control flow for the CPU
Devlog 4 - Memory mapping and instruction stepping The next thing I worked on was getting a basic function set up for stepping through instructions and calling the execute function. To do this, I also had to make a program counter, which is a 16 bit register storing the address of the next instruction. Currently, the step function is pretty barebones, but it simply calls the execute function, passes it the PC as a parameter, and then sets the program counter to be the returned address. The execute function has also been modified, meaning it reads the instruction from memory (more on that later) rather than being passed it directly, and return the address plus 1 to 3 bytes, depending on the instruction that was executed. The next bit I made was the Game Boy’s memory. This is simply an char array with 64K values, equivalent to 64KiB of memory. Then, any address can be accessed simply by accessing the array value at an address. After working on the other parts of the CPU, I went back to working on some instructions, implementing the rest of the disassembly tables , including the condition call table, which checks the flags register before executing an instruction. I also implemented some of the instructions that require inputting an address in memory to use instead of a number or register. Finally, I also worked on some quality of life features. First, I made a function to replace missing functions, which simply sends an error message with the function name, and quits with an error code. Secondly, I made / edited some functions to actually move the loaded ROM file into the main GB memory rather than the program memory. I had a little trouble troubleshooting this, as I didn’t at first have a reliable way to verify that the data had been copied successfully, and after I did, I still had trouble with pointers, as I am still pretty new to C’s manual memory management (I usually just keep things in the stack, or have global variables that will persist throughout the program’s lifetime.). I also added basic functionality for loading a ROM on desktop rather than the web, but it doesn’t use the system dialog yet, only loading a rom.gb file in the executable directory. After everything was working, I added a debug message to send the ROM’s header title, showing that it actually works. You can see this in the screenshot. It sends the message twice, once when the file is loaded, and once when it’s moved to GB memory, which I did to make sure that the transfer didn’t mess up the data accidentally.
Devlog 5 - Adding instructions, the stack and lots of debugging After the last devlog, the first think I did was implement some more instructions, namely the jump instructions, and the increment and decrement functions. Luckily these were pretty simple; all the jumps do are set the program counter (effectively the next instruction) to a specified value, and the increment and decrement are pretty self explanatory, increasing or decreasing a register or memory byte by 1; After this, I started implementing the stack. The stack is a section of memory that is ordered, with values being written to it (pushed) and read off of it (popped). You must read the “top” value, meaning the most recently pushed, which is then removed and the next highest is the next available to read. This wasn’t too hard, although I did have to introduce a new register, the stack pointer (sp). While I was at it, I also implemented load functions, which load data into a specified memory byte or register. After realising it would cause issues down the line, I walked back my previous decision to make the flags register a struct of booleans, and instead made it a single byte with 4 bits representing the 4 flags, making it more accurate. I also made some functions to easily set or reset each flag, rather than use bitwise operations everywhere. Finally, I implemented logging support, so that I could use Gameboy Doctor , a brilliant debugging script that reads a log file from your emulator with a known ROM, and compares it to the correct result. All you have to do is write a line to a log file with all the register values and some memory bytes after each instruction, and it automatically tells you where the first error is, what register or piece of memory is wrong, and even the last instruction to give you a hint as to the problem. This didn’t take much time to implement, but I did spend a considerable amount of time debugging, as previously I hadn’t actually got a way to check that my functions worked correctly (which is why this devlog has quite a few more hours on it). You can see an example of a error in the screenshot; I intentionally changed the SUB instruction to add instead because I forgot to take screenshots of the actual errors 🥀. Next time, I want to implement more of the CPU, especially more complex behaviours like halting and interrupts, and also implement some of the graphics, so that the games can actually be seen visually.
Devlog 6 - An unfortunate amount of debugging This devlog is probably going to be shorter than the other, simply because I haven’t done as much as I hoped The main reason for this is that I got completely stuck on a bug, and wasted so much time trying to find it. I first noticed this bug when I got this error message (screenshot) in gameboy-doctor, with a mismatch with a load from memory not being the right value. This got me so stuck, because I didn’t know where to find when the memory was supposed to be written to, so I was basically blindly guessing what was wrong with any previous loads or register writes. Eventually, I caved and asked for help online, and I got my answer after asking on the EmuDev subreddit , where I found out it was an issue with my implementation of the LD (FF00+u8), A instructions, where I wrote LD_n16_n8((0xFF00 + address + 1), registers.a); instead of the correct LD_n16_n8((0xFF00 + ReadMemory(address + 1)), registers.a); so basically any writes to memory using that function were in the complete wrong location. Stupid mistake on my part, and I wasted way too much time on it. I also did implement some basic instructions, like EI and RETI. EI simply enables the emi register, and RETI basically just does that, then calls RET to return from a subroutine. In addition, I also restructured quite a lot of the code, as too much was piling up in the cpu.c file, and I also renamed quite a few functions to follow a Component_Function syntax, so it was easier to tell where they were located in the code
Devlog 7 - Timing The next main thing I implemented were some more instructions - namely SRL, RR, RRA and ADD HL. These weren’t too hard, as the first 3 are similar to regular bit shifts, and ADD HL is just adding. While I was working on these, I also fixed some bugs with the existing instructions This allowed me to finally pass the cpu_instrs 6 test ROM, which although not really a massive goal, did help to signify the progress I had made. I then moved onto the 7th test, for which I implemented some load functions for the stack pointer register The biggest improvement of this devlog was getting everything timing correctly. The Gameboy is supposed to run at 4.19 MHz and 59.7 FPS, but at the time, the emulator was just running as fast as possible. To solve this, I first made each instruction call a function to add the amount of cycles it takes to a unwaitedCycles variable. Then, I saved the current time in nanoseconds since the program started (provided by the SDL_GetTicksNS() function) into a variable at the start of an instruction’s execution. After the instruction is executed, a function is then called that finds the expected execution time the by doing the amount of cycles multiplied by the period of 4.19MHz (about 238 nanoseconds). This expected time is then subtracted from the actual time, which is the start time stored previously subtracted from the current time. The program is then delayed by the result, which should keep the CPU at around 4.19MHz, unless it takes too long. I did have some concerns with my emulator’s performance, as when running as a debug build, it wasn’t running nearly fast enough to reach 4.19MHz, but after compiling as a release build with optimisation, it was much faster and ran under the required time. However, I’m not sure how consistent this will be between devices, so I may have to optimise later Finally, I added a similar function to limit the FPS to around 60 (technically 59.7), which just checks the time since the last frame was rendered, and if it hasn’t been long enough, it continues CPU execution and doesn’t render. You can see the frame limit working in the screenshot, where the frametime is a consistent 16.8 ms and the FPS is locked to 60, as opposed to before where it was unlimited. (Ignore the text, it doesn’t change yet to show a ROM has been loaded)
Devlog 8 - Organisation, and timing, again Ok, so this didn’t exactly go how I wanted (again), but most of this devlog time was spent fixing the past devlog, and organising code in a better way Firstly: I realised that before, my timing code checked based on M-cycles, rather than T-cycles. There’s a specific reason for the distinction, but for now all you need to know is that there’s 4 T-cycles in an M-cycle, so my code was targeting a 4x faster speed. I changed this to be correct, but changed it again later so it doesn’t really matter. Then, I cleaned up a lot of cpu.c , changing functions to return values directly rather than using a local variable first, pre-calculating some variables, et cetera. This was an attempt to speed up the CPU, as I was having a bit of trouble meeting the target speed with debug builds (mentioned in devlog 7), but again, this was a bit pointless because I changed the way the timing worked later. While doing this, I also replaced all of the numerical types with their stdint.h counterparts; for example, an unsigned char became a Uint8 (SDL has macros for the stdint types, so they have a slight naming difference from standard C in my code). This was mainly done for specificity and some Hail Mary for performance (although fruitless), and should make the code at least a bit more portable and easy to maintain. I also implemented a couple of new instructions; RST and SWAP. RST effectively calls from a set of pre-specified addresses , and SWAP just swaps the upper and lower 8 bits in a byte, so these weren’t too hard. I also had to fix some bugs with the flags register´s value after an SBC A instruction, which admittedly did take me a while to fix because I basically banged my head against the wall to fix it. The main change in this devlog was switching the timing system (again). Previously, the CPU ran one instruction for each loop of the SDL_AppIterate function. After reading the documentation and realising that this function is supposed to run each frame, I realised that I was causing all of my speed issues by only doing one cycle per iteration. Instead, the code now does as many instructions as it can until it has run enough T-cycles for a full frame to render (70224). It then renders (to be implemented), and moves on to the next iteration. This is way more performant, and has the added benefit of being more cross-platform, as SDL specifies that sometimes AppIterate may only run at the refresh rate on some devices. Tbh, this took me a while, maybe too long, to conceptualise and implement, and basically made all of the time on the other timing system wasted, but in the end it was worth it for a much better system. You can see the uncapped FPS (in a debug build mind you) here, although when actually playing games, the framerate will be locked to around 60 FPS. Finally, there was a few more miscellaneous changes: copying a ROM file into memory uses memcpy instead of a loop, which may or may not be faster; memory is now a union of smaller arrays of memory banks, for each function, such as work ram (WRAM), high ram (HRAM), ROM banks 0-n and etc; and lastly, some register code has been moved out of cpu.c for organisation.
Devlog 9 - Basic graphics (finally) I’ve finally gotten some basic picture processing unit (PPU) functionality implemented into the emulator, which will hopefully make debugging a lot easier going forward. Firstly, to implement this, I had to move the timing logic out of cpu.c and into cycles.c . This was so that, when the loop calls a CPU step, it also calls a PPU step at the same time. I also refactored some of the cycle functions and removed the ones that were no longer being used Then, I implemented the timing code for the PPU. This part and the actual rendering were mostly based on this tutorial series that shows you how to make a GB emulator in javascript, which I based my C code on. Basically, the PPU runs on the clock as the CPU, and a ‘dot’ on the PPU is equal to a T-cycle on the CPU. The PPU renders progressively, like a CRT television, and so also has modes to move the nonexistent electron beam down and back to the start of a scanline before it continutes rendering, known as VBLANK and HBLANK, (vertical and horizontal blank). The Pan Docs were also quite helpful for understanding the basic functionality, although the tutorial was useful to understand the programmatic side. The PPU also has 2 other modes, used for scanning the Object Attribute Memory (OAM) and actually drawing, and all 4 modes have a precise amount of dots that they run for. In terms of actual rendering, the Gameboy doesn’t have a full framebuffer, and instead uses different tiles to create a full image. I implemented a function that, when the CPU writes to VRAM, also updates the data in a separate tileset variables, for easier access in the render pipeline. Each tile is 16 bytes, with 2 bits per pixel colour depth, and 8 x 8 pixels per tile. As the Gameboy renders progressively, I then implemented the function to draw a scanline to the screen, based on the tile data in the background layer. The afformentioned tutorial series helped a lot here, as the tiles need to have a specific offset and mapping applied which would be quite hard to figure out on my own. Then, that function calls a draw pixel function for each each of the 160 pixels in a scanline, which writes the corresponding colour from the palette to an SDL_Surface as the framebuffer. Once the frame is finished, the surface is converted into a texture, which is then scaled to fit the screen size and rendered, with another frame being made afterwards. Below you can see the screen of the previously mentioned blargg’s test ROM 7.
Devlog 10 - (basically) Finishing the CPU After the last devlog, I did some cleaning up with the graphics, which included fixing the last scanline not being rendered, and also adding a screen before the ROM is loaded, telling the user which key to press to load the ROM. I also set up some functions to allow easier access to the I/O registers related to the PPU, such as the x and y scroll and the control flags. Afterwards, I felt a bit burnt out of the PPU, so I went back to finish off most of the CPU. This started with implementing the CFL, CPL, CF, CPL, SCF, SLA, SRA, RL, RLA, RLC, RRC, RLCA, and RRCA instructions, most of which are bit rotations, so once I had a few implemented, it got easier to add the rest. This allowed me to pass CPU test ROM 9. Then, I implemented the rest of the CB prefix instructions, which were all bit related; BIT, RES and SET, which allowed me to pass ROM 10 After those, I implemented some stack pointer related instructions; ADD SP,d and LD HL SP+d, which then allowed me to pass ROM 3 Finally, I added DAA. This one is a bit more unique, as it is designed to convert the result of an add or subtract with binary coded decimal numbers, into a binary coded decimal number. This gets a bit complicated, but I used these resources ( Demystifying the GameBoy/SM83’s DAA Instruction and the RGBDS assembler/linker instruction documentation ) to implement this properly, allowing me to also pass test ROM 1 With a semi-functioning PPU, and some fixes, I was also able to boot into the copyright screen of Tetris for the first time, although I couldn’t get any further without implementing interrupts. The image below shows that, and my emulator passing all of the previously mentioned test ROMs. The only test ROM I haven’t passed yet is the 2nd one, which also requires interrupts....
|
1792587169.3497012
|
1793191969.3497012
|
|
44323
|
FormCheck by @cluelessfr | Stardance
|
cluelessfr
|
0
|
52.92
|
0
|
[]
|
[{"post_id": 81112, "ts": "202 [{"post_id": 81112, "ts": "2026-10-19T22:36:03Z", "hours": 6.5611, "text": "Devlog 14: I started preparing for the feedback. I am planning to mostly give feedback on timing/tempos, so I started adding some functions for that. The first thing I did was correct the scaling of video coordinates before calculating knee angles to ensure higher accuracy. Then I added a lowering-time estimator that looks for sustained movement instead of just angles at timestamps. I ensured to account for rectangular frames, leg switches, observation gaps, and timing integration. All tests passed. The next steps are actually providing feedback from this data, and then connecting this to the UI."}, {"post_id": 77869, "ts": "2026-10-08T16:33:46Z", "hours": 3.5961, "text": "Devlog 13: This devlog was mostly some final touches. I did add 3 things, though. The first of which is a frame progress display on the UI. This shows the user of many of the total frames have been processed after they start the analysis. Second, I added some text that was a disclaimer on the limitations of the analysis. The third thing I added was a reset between long gaps. So if the squat takes too long to get to the next state, then the detection resets and it starts looking for another starting squat. The first test I did was that I sampled different repetition intervals to determine which had the most detail but didn’t take too long to process. I landed on sampling frames every 250 Ms. Then I tested all the different UI states on the emulator using different videos. I then added tests for all the new features that I just mentioned to you. The next step is probably going to be actually implementing feedback."}, {"post_id": 75113, "ts": "2026-09-29T05:01:41Z", "hours": 8.2819, "text": "Devlog 12: I added some more meaningful upgrades this time. I added functionality so that the app could detect a real squat repetition. This works by combining this with the pose sequence analyzer, which contains poses and their timestamps. By mapping the angle formed by the hip, knee, and ankle at different intervals of the video, the app is able to detect if the angle got gradually lower, then gradually got higher. If these angles pass the thresholds needed to create a straight leg angle and a squatted down angle, then we can conclude that a squat repetition was performed. To accomplish this I added many different smaller functions, then combined them all together to get the final result. This allowed me to test each part individually to ensure they all worked. I also added this to the UI of the app, which you can see in the image. Finally I added real video validation, which basically means that I tested the current state of the app with a real video of a person doing a squat. The app was able to successfully recognize the repetition of the squat."}, {"post_id": 70842, "ts": "2026-09-19T21:02:38Z", "hours": 6.1419, "text": "Devlog 11: Now I added a few things. First I added a function that can sample frames at different intervals and stores the MediaPipe result with the timestamp of the frame. I also added hip/knee/ankle extraction for both sides and also confidence-based leg section. Codex wrote a few methods (2-3), and I wrote the rest. I then added timestamped knee angle measurements, and also connected the leg selector to the angle calculator. Finally, I added a sequence analyzer that keeps the valid measurements and skips the unclear frames. I added test for all these functions. There is a little more than this, but this is the gist of what I have been working on right now."}, {"post_id": 65756, "ts": "2026-09-11T03:20:19Z", "hours": 6.9169, "text": "Devlog 10: This time was some meaningful upgrades. First of all I added a function to extract a bitmap from a video given a timestamp. Then I added a separate function in order to convert that bitmap into an MPImage. This allows me to access it from anywhere. Finally I created a new class that combines the decoding, conversion, and pose processing tasks into one pipeline. I also added tests for all of these. Currently only one frame processes, but soon I will start to improve this."}, {"post_id": 63969, "ts": "2026-09-08T01:55:46Z", "hours": 8.5042, "text": "Devlog 09: Now the app stores the selected video’s Uri in an activity field, meaning it can be accessed for later processing instead of only the status text. Also frame timestamps can now be generated. This means that you can input the video duration as well as the interval that you want the timestamps to be generated, then you will get a set of timestamps for the video. The video metadata can also now be read. It uses Android’s MediaMetadataRetriever to open the video. Currently only the duration of the video can be retrieved, but later you will be able to decode individual frames. Finally I added tests for all of these. For the metadata retriever specifically I uploaded a test video to confirm that I could get an accurate measurement. Also updated the documentation."}, {"post_id": 47722, "ts": "2026-08-15T20:26:10Z", "hours": 3.5783, "text": "Devlog 08: I finally added the MediaPipe dependency, as well as a few functions. First of all I also added the Pose Landmarker Full model for it to actually detect poses. Then I created a manager function to initialize and close MediaPipe. I then added a function that could process an already decoded video frame with a timestamp using MediaPipe. I added tests for all of these to ensure they work when the app runs, and updated all the logs."}, {"post_id": 46085, "ts": "2026-08-13T01:19:04Z", "hours": 1.9819, "text": "Devlog 07: I changed the emulator from being on device to remote via Firebase. This allows me to test the app cleanly without lagging my computer. The only problem is I get a limited 30 minutes per month, so I have to use them wisely. I also updated the Point2D function to reject non-finite points. This prevents errors on the future. I also added a class that combines all the other functionality into one. It returns an OptionalDouble, which is useful when you don’t know if you are going to get a result. This new function accepts three LandmarkObservations, Then if the result is valid, it returns the angle degrees between the points. If not, it returns nothing."}, {"post_id": 44348, "ts": "2026-08-10T01:32:26Z", "hours": 1.3133, "text": "Devlog 06: I added the landmark quality gate, which helps determine whether the visibility and presence of the point meet the minimum requirements. If it does, then it passes. If it doesn’t, then the point fails. From here there are two options, either the app tries to find another point, or the app says it cannot reliably determine your form from that video I also added the AI use log. I mainly did this because I will be submitting this to the Congressional App Challenge."}, {"post_id": 44307, "ts": "2026-08-09T23:40:20Z", "hours": 1.0214, "text": "Devlog 05: Today I added landmark storage and reliability tests. What this is is basically a new object that can store a point, its visibility, and presence. The point is the point itself, the visibility says how well the object can be seen, and the presence determines how much of the object is actually in the video frame. These three factors help determine how well the video can be analyzed. If the video cannot be analyzed well enough, then FormCheck will send a message saying so (This hasn’t been implemented yet, but this is the basic idea of why this is there in the first place)."}, {"post_id": 43747, "ts": "2026-08-09T05:12:50Z", "hours": 1.1897, "text": "Devlog 04: I added functions for measuring the angle based on three points (the joints). Basically how this works is that it first takes in three points, the first endpoint, a vertex, and a second endpoint. Then it uses the dot product formula with the two vectors to find the angle between the two lines."}, {"post_id": 43080, "ts": "2026-08-08T04:48:16Z", "hours": 1.5214, "text": "Devlog 03: I added the file picking dialogue. Now whenever you click the “Select a video” button the android folder picker opens and you can choose a video. I think next is working on the actual pose detection logic."}, {"post_id": 42951, "ts": "2026-08-07T22:46:59Z", "hours": 1.3858, "text": "Devlog 02: I added the initial video selection interface. I added some text to describe the app, and a button for the user to be able to select a video to upload. Currently, the button does not do anything. Next I will have to continue working on the button and the actual pose estimation part of this."}, {"post_id": 41569, "ts": "2026-08-05T21:12:03Z", "hours": 0.9278, "text": "Devlog 01: This is the first devlog of the FormCheck project, an Android app that helps you check your form during workouts. Currently I just set everything up in Android Studio, connected Hackatime, and set up GitHub."}]...
|
Title: FormCheck by @cluelessfr | Stardance
Devlo Title: FormCheck by @cluelessfr | Stardance
Devlogs:
Devlog 01: This is the first devlog of the FormCheck project, an Android app that helps you check your form during workouts. Currently I just set everything up in Android Studio, connected Hackatime, and set up GitHub.
Devlog 02: I added the initial video selection interface. I added some text to describe the app, and a button for the user to be able to select a video to upload. Currently, the button does not do anything. Next I will have to continue working on the button and the actual pose estimation part of this.
Devlog 03: I added the file picking dialogue. Now whenever you click the “Select a video” button the android folder picker opens and you can choose a video. I think next is working on the actual pose detection logic.
Devlog 04: I added functions for measuring the angle based on three points (the joints). Basically how this works is that it first takes in three points, the first endpoint, a vertex, and a second endpoint. Then it uses the dot product formula with the two vectors to find the angle between the two lines.
Devlog 05: Today I added landmark storage and reliability tests. What this is is basically a new object that can store a point, its visibility, and presence. The point is the point itself, the visibility says how well the object can be seen, and the presence determines how much of the object is actually in the video frame. These three factors help determine how well the video can be analyzed. If the video cannot be analyzed well enough, then FormCheck will send a message saying so (This hasn’t been implemented yet, but this is the basic idea of why this is there in the first place).
Devlog 06: I added the landmark quality gate, which helps determine whether the visibility and presence of the point meet the minimum requirements. If it does, then it passes. If it doesn’t, then the point fails. From here there are two options, either the app tries to find another point, or the app says it cannot reliably determine your form from that video I also added the AI use log. I mainly did this because I will be submitting this to the Congressional App Challenge.
Devlog 07: I changed the emulator from being on device to remote via Firebase. This allows me to test the app cleanly without lagging my computer. The only problem is I get a limited 30 minutes per month, so I have to use them wisely. I also updated the Point2D function to reject non-finite points. This prevents errors on the future. I also added a class that combines all the other functionality into one. It returns an OptionalDouble, which is useful when you don’t know if you are going to get a result. This new function accepts three LandmarkObservations, Then if the result is valid, it returns the angle degrees between the points. If not, it returns nothing.
Devlog 08: I finally added the MediaPipe dependency, as well as a few functions. First of all I also added the Pose Landmarker Full model for it to actually detect poses. Then I created a manager function to initialize and close MediaPipe. I then added a function that could process an already decoded video frame with a timestamp using MediaPipe. I added tests for all of these to ensure they work when the app runs, and updated all the logs.
Devlog 09: Now the app stores the selected video’s Uri in an activity field, meaning it can be accessed for later processing instead of only the status text. Also frame timestamps can now be generated. This means that you can input the video duration as well as the interval that you want the timestamps to be generated, then you will get a set of timestamps for the video. The video metadata can also now be read. It uses Android’s MediaMetadataRetriever to open the video. Currently only the duration of the video can be retrieved, but later you will be able to decode individual frames. Finally I added tests for all of these. For the metadata retriever specifically I uploaded a test video to confirm that I could get an accurate measurement. Also updated the documentation.
Devlog 10: This time was some meaningful upgrades. First of all I added a function to extract a bitmap from a video given a timestamp. Then I added a separate function in order to convert that bitmap into an MPImage. This allows me to access it from anywhere. Finally I created a new class that combines the decoding, conversion, and pose processing tasks into one pipeline. I also added tests for all of these. Currently only one frame processes, but soon I will start to improve this.
Devlog 11: Now I added a few things. First I added a function that can sample frames at different intervals and stores the MediaPipe result with the timestamp of the frame. I also added hip/knee/ankle extraction for both sides and also confidence-based leg section. Codex wrote a few methods (2-3), and I wrote the rest. I then added timestamped knee angle measurements, and also connected the leg selector to the angle calculator. Finally, I added a sequence analyzer that keeps the valid measurements and skips the unclear frames. I added test for all these functions. There is a little more than this, but this is the gist of what I have been working on right now.
Devlog 12: I added some more meaningful upgrades this time. I added functionality so that the app could detect a real squat repetition. This works by combining this with the pose sequence analyzer, which contains poses and their timestamps. By mapping the angle formed by the hip, knee, and ankle at different intervals of the video, the app is able to detect if the angle got gradually lower, then gradually got higher. If these angles pass the thresholds needed to create a straight leg angle and a squatted down angle, then we can conclude that a squat repetition was performed. To accomplish this I added many different smaller functions, then combined them all together to get the final result. This allowed me to test each part individually to ensure they all worked. I also added this to the UI of the app, which you can see in the image. Finally I added real video validation, which basically means that I tested the current state of the app with a real video of a person doing a squat. The app was able to successfully recognize the repetition of the squat.
Devlog 13: This devlog was mostly some final touches. I did add 3 things, though. The first of which is a frame progress display on the UI. This shows the user of many of the total frames have been processed after they start the analysis. Second, I added some text that was a disclaimer on the limitations of the analysis. The third thing I added was a reset between long gaps. So if the squat takes too long to get to the next state, then the detection resets and it starts looking for another starting squat. The first test I did was that I sampled different repetition intervals to determine which had the most detail but didn’t take too long to process. I landed on sampling frames every 250 Ms. Then I tested all the different UI states on the emulator using different videos. I then added tests for all the new features that I just mentioned to you. The next step is probably going to be actually implementing feedback.
Devlog 14: I started preparing for the feedback. I am planning to mostly give feedback on timing/tempos, so I started adding some functions for that. The first thing I did was correct the scaling of video coordinates before calculating knee angles to ensure higher accuracy. Then I added a lowering-time estimator that looks for sustained movement instead of just angles at timestamps. I ensured to account for rectangular frames, leg switches, observation gaps, and timing integration. All tests passed. The next steps are actually providing feedback from this data, and then connecting this to the UI....
|
1792583275.8698568
|
1793188075.8698568
|
|
67984
|
supder by @allenlin0728 | Stardance
|
allenlin0728
|
0
|
0.36
|
0
|
[]
|
[{"post_id": 81116, "ts": "202 [{"post_id": 81116, "ts": "2026-10-19T23:13:05Z", "hours": 0.3614, "text": "Set spooder back up After realizing all my old components were a little fried, I bought replacements on amazon and replaced them. Additionally, I put in the esp32-s3 dev board, however I had to use double sided tape to mount it because the screw holes for the raspbery pi did not fit the dev board. after I finished this, I rewired the entire thing. However, I realised I rewired it wrong, where I made one leg have three pins in sequential order, like where FRH was 0, FRF was 1, and FRT was 2, instead of 0, 3, 6. I decided to fix this in code instead of hardware because it was cleaner anyways and easier to do Lastly I had to reroute the new wires for i2c. The accelerometer I bought never arrived so i will not be doing anything PID cause im too stupid and my old one was fried. Also because I don’t have enough time I probably won’t set up the led matrix very well and might not even work, i just want reinbursements for now. tomorrow I want to actually start testing my code and see if i have to still do the stupid homing of all my servos again, also because all my code is in arduino ide, it has not been logged, and I JUST set it up for stardance, but I was told hours do not matter for just hardware reinbursements. hopefully i will finish and not be in debt anymore"}]...
|
Title: supder by @allenlin0728 | Stardance
Devlog Title: supder by @allenlin0728 | Stardance
Devlogs:
Set spooder back up After realizing all my old components were a little fried, I bought replacements on amazon and replaced them. Additionally, I put in the esp32-s3 dev board, however I had to use double sided tape to mount it because the screw holes for the raspbery pi did not fit the dev board. after I finished this, I rewired the entire thing. However, I realised I rewired it wrong, where I made one leg have three pins in sequential order, like where FRH was 0, FRF was 1, and FRT was 2, instead of 0, 3, 6. I decided to fix this in code instead of hardware because it was cleaner anyways and easier to do Lastly I had to reroute the new wires for i2c. The accelerometer I bought never arrived so i will not be doing anything PID cause im too stupid and my old one was fried. Also because I don’t have enough time I probably won’t set up the led matrix very well and might not even work, i just want reinbursements for now. tomorrow I want to actually start testing my code and see if i have to still do the stupid homing of all my servos again, also because all my code is in arduino ide, it has not been logged, and I JUST set it up for stardance, but I was told hours do not matter for just hardware reinbursements. hopefully i will finish and not be in debt anymore...
|
1793116297.889785
|
1793721097.889785
|
|
562
|
Chess in Python Turtle 🐢 by @Mehmet | Stardance
|
Mehmet
|
1
|
7.0
|
80
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-16T21:01:01Z", "hours": 7.0, "multiplier": 12.05, "payout": 80, "blessing": "neutral", "text": "I built pure chess inside Python Turtle. The entire idea of making a fully fledged game in Python’s Turtle seemed absurd, but there is tangible proof now. I’m proud of how I handled the piece moving and square highlighting code snippets; those were really fun to work on. Here are some tests you can do to see if my project holds up: Try clicking outside the board to move a piece, and you’ll see that it doesn’t. Try moving a piece outside the board. Try moving kings to squares that opposing pieces see. Try double pushing pawns. Right now, I haven’t added en passant or castling, but a 99% fledged chess game inside Python Turtle is ready for you to play.", "repo": "https://github.com/SameRainbows/Python-Turtle-Chess", "demo": "https://github.com/SameRainbows/Python-Turtle-Chess/releases/tag/V1"}]...
|
[{"post_id": 8112, "ts": "2026 [{"post_id": 8112, "ts": "2026-06-13T15:19:39Z", "hours": 1.8964, "text": "Finally, I can say that I’ve built chess—fully fledged chess—in Python Turtle. I added check, checks, checkmates, and all the logic that makes them up. I also created a new function called has_legal_moves, which takes one parameter to see if the attacker is white. In total, I defined 11 functions back to back in the Python file. It seems funny, but that’s what was needed. Thank you, every1!"}, {"post_id": 7080, "ts": "2026-06-11T21:14:12Z", "hours": 0.5017, "text": "Added basic promotions when the pawns go to the opposite side (for now they default to only queen promotions, more coming soon) and right now started working on the final boss of chess programming… Checks and checkmates. Wish me luck!"}, {"post_id": 5677, "ts": "2026-06-09T15:40:24Z", "hours": 0.9253, "text": "Welcome back to my pit of inevitable doom, where I’m trying to build fully fledged chess inside pure Python turtle. This devlog is because I finally managed to get a glimpse of the sunlight and add the special moves and captures for pawns. Before right now, pawns could only move one step forward no matter the place, and they actually captured by going forward into the enemy. If you play chess, you know it’s not like that. I have now implemented the following: Two-step support for pawns going on their first move. Logic so that pawns cannot capture pieces directly in front of them. Support for pawns capturing pieces only on their front diagonals. Follow along if you want to see if I ever get out of this!!! :D"}, {"post_id": 2915, "ts": "2026-06-05T20:22:29Z", "hours": 0.9917, "text": "Added legal moves and support for the knight, king, rook and pawn. The bishop is on the way"}, {"post_id": 2776, "ts": "2026-06-05T16:03:50Z", "hours": 0.7839, "text": "Added coordinates for the chessboard with a new function called print_coordinates. I also added a bouncer function to check if a piece is trying to move to a square that has a piece of the same color. If it’s trying to capture its own piece, it doesn’t allow the move. I implemented this by creating a new function called is_legal_move."}, {"post_id": 2264, "ts": "2026-06-04T17:37:49Z", "hours": 1.1539, "text": "Created functions for repeated tasks."}, {"post_id": 980, "ts": "2026-06-02T19:18:29Z", "hours": 0.47, "text": "Making fully fledged chess inside Python Turtle."}]...
|
Title: Chess in Python Turtle 🐢 by @Mehmet | Stard Title: Chess in Python Turtle 🐢 by @Mehmet | Stardance
Devlogs:
Making fully fledged chess inside Python Turtle.
Created functions for repeated tasks.
Added coordinates for the chessboard with a new function called print_coordinates. I also added a bouncer function to check if a piece is trying to move to a square that has a piece of the same color. If it’s trying to capture its own piece, it doesn’t allow the move. I implemented this by creating a new function called is_legal_move.
Added legal moves and support for the knight, king, rook and pawn. The bishop is on the way
Welcome back to my pit of inevitable doom, where I’m trying to build fully fledged chess inside pure Python turtle. This devlog is because I finally managed to get a glimpse of the sunlight and add the special moves and captures for pawns. Before right now, pawns could only move one step forward no matter the place, and they actually captured by going forward into the enemy. If you play chess, you know it’s not like that. I have now implemented the following: Two-step support for pawns going on their first move. Logic so that pawns cannot capture pieces directly in front of them. Support for pawns capturing pieces only on their front diagonals. Follow along if you want to see if I ever get out of this!!! :D
Added basic promotions when the pawns go to the opposite side (for now they default to only queen promotions, more coming soon) and right now started working on the final boss of chess programming… Checks and checkmates. Wish me luck!
Finally, I can say that I’ve built chess—fully fledged chess—in Python Turtle. I added check, checks, checkmates, and all the logic that makes them up. I also created a new function called has_legal_moves, which takes one parameter to see if the attacker is white. In total, I defined 11 functions back to back in the Python file. It seems funny, but that’s what was needed. Thank you, every1!
Ships:
I built pure chess inside Python Turtle. The entire idea of making a fully fledged game in Python’s Turtle seemed absurd, but there is tangible proof now. I’m proud of how I handled the piece moving and square highlighting code snippets; those were really fun to work on. Here are some tests you can do to see if my project holds up: Try clicking outside the board to move a piece, and you’ll see that it doesn’t. Try moving a piece outside the board. Try moving kings to squares that opposing pieces see. Try double pushing pawns. Right now, I haven’t added en passant or castling, but a 99% fledged chess game inside Python Turtle is ready for you to play....
|
1793130711.2842731
|
1793217111.2842731
|
|
43700
|
ngarnsworthy.dev by @ngarnsworthy | Stardance
|
ngarnsworthy
|
0
|
30.82
|
0
|
[]
|
[{"post_id": 81120, "ts": "202 [{"post_id": 81120, "ts": "2026-10-19T23:38:02Z", "hours": 14.3867, "text": "I got lost in the sauce and went over 10hrs Done Switched to express Added index page Project showcase Started blog TODO Guest book Outlinks Styling Retrospective It has been nice returning to express.js. I feel React and other modern web development tools are useful but are also cumbersome for many projects. I overall have enjoyed my experience with this “older” tool-chain. It has taken away a lot of the unnecessary abstraction I have seen through react. It has also let me look into accessibility way more so my website can be as accessible as possible! Reasoning When I started work on Termsite I was ready to delete a lot of the project structure from my personal website as Termsite rebuilt that functionality in a even better way. I just ended up deleting everything and starting again from scratch lol, but I like this web concept way more overall!"}, {"post_id": 69141, "ts": "2026-09-16T13:34:43Z", "hours": 7.7217, "text": "Done Added persistent env that can be used to store values between commands. Commands ls: created, a command to see the files in your current directory cat: created, a command to look at the contents of a file cd: created, a command to change your directory theme: created, a command to change your theme to one of the valid themes help: improved, added new commands to help TODO Add more themes Create mobile friendly interaction Create accessible interaction"}, {"post_id": 65025, "ts": "2026-09-09T20:36:07Z", "hours": 8.7106, "text": "Created a fake web terminal interface with each command running without state. Created the following test commands : help , startup, error. The error command is used when a command is not found. The startup command is ran on start and can be used to output usage information and setup state (when that is implemented). The help command outputs help information on all commands."}]...
|
Title: ngarnsworthy.dev by @ngarnsworthy | Stardan Title: ngarnsworthy.dev by @ngarnsworthy | Stardance
Devlogs:
Created a fake web terminal interface with each command running without state. Created the following test commands : help , startup, error. The error command is used when a command is not found. The startup command is ran on start and can be used to output usage information and setup state (when that is implemented). The help command outputs help information on all commands.
Done Added persistent env that can be used to store values between commands. Commands ls: created, a command to see the files in your current directory cat: created, a command to look at the contents of a file cd: created, a command to change your directory theme: created, a command to change your theme to one of the valid themes help: improved, added new commands to help TODO Add more themes Create mobile friendly interaction Create accessible interaction
I got lost in the sauce and went over 10hrs Done Switched to express Added index page Project showcase Started blog TODO Guest book Outlinks Styling Retrospective It has been nice returning to express.js. I feel React and other modern web development tools are useful but are also cumbersome for many projects. I overall have enjoyed my experience with this “older” tool-chain. It has taken away a lot of the unnecessary abstraction I have seen through react. It has also let me look into accessibility way more so my website can be as accessible as possible! Reasoning When I started work on Termsite I was ready to delete a lot of the project structure from my personal website as Termsite rebuilt that functionality in a even better way. I just ended up deleting everything and starting again from scratch lol, but I like this web concept way more overall!...
|
1792558281.4008505
|
1793163081.4008505
|
|
69065
|
Having fun messing with Godot Networking by @Flame Having fun messing with Godot Networking by @FlameWing | Stardance...
|
FlameWing
|
1
|
6.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-20T00:52:46Z", "hours": 6.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Pretty simple Godot game that shows the concepts of Godot’s networking tools. Simple host/join, with player data syncing across clients. Simple chatting, and spawning physics bodies. Also, local server broadcasting to easily join servers hosted on your local network. One of the first times I used Godot, and had a fun time learning the technical side of it. Got to learn how to use both Godot’s High Level Multiplayer, and Godot’s lower level networking to handle local broadcasting.", "repo": "https://github.com/FlameWing-Code/Godot-Networking-Testing", "demo": "https://github.com/FlameWing-Code/Godot-Networking-Testing/releases/tag/v1"}]...
|
[{"post_id": 81125, "ts": "202 [{"post_id": 81125, "ts": "2026-10-19T23:50:39Z", "hours": 3.1672, "text": "Added local server broadcasting When you host a game, it will constantly send a small packet to 255.255.255.255, which gets sent to every device in the local network. Its a small little packet that simply contains the server’s username and the port their hosting on. Clients can pick up this packet, and it gets displayed so you can join easily. Had to rely on godot’s lower level networking, compared to the rest of the project."}, {"post_id": 78633, "ts": "2026-10-11T04:19:44Z", "hours": 2.6972, "text": "Got chat and usernames working"}]...
|
Title: Having fun messing with Godot Networking by Title: Having fun messing with Godot Networking by @FlameWing | Stardance
Devlogs:
Got chat and usernames working
Added local server broadcasting When you host a game, it will constantly send a small packet to 255.255.255.255, which gets sent to every device in the local network. Its a small little packet that simply contains the server’s username and the port their hosting on. Clients can pick up this packet, and it gets displayed so you can join easily. Had to rely on godot’s lower level networking, compared to the rest of the project.
Ships:
Pretty simple Godot game that shows the concepts of Godot’s networking tools. Simple host/join, with player data syncing across clients. Simple chatting, and spawning physics bodies. Also, local server broadcasting to easily join servers hosted on your local network. One of the first times I used Godot, and had a fun time learning the technical side of it. Got to learn how to use both Godot’s High Level Multiplayer, and Godot’s lower level networking to handle local broadcasting....
|
1793008303.688808
|
1793094703.688808
|
|
46895
|
Wi-Fi Latency Analyzer by @aaryan_s | Stardance
|
aaryan_s
|
0
|
33.63
|
0
|
[]
|
[{"post_id": 81126, "ts": "202 [{"post_id": 81126, "ts": "2026-10-19T23:56:01Z", "hours": 3.4781, "text": "• Day 21 – Modern GUI and FlatLaf Setup – 10/19 • I installed FlatLaf, an open source java library for Java Swing applications . The goal with FlatLaf is to slowly “modernize” my app and overall make it look a lot more appealing to the user compared to it’s old basic java swing vibe. I struggled a lot with implementing FlatLaf and connecting it to my java swing application in VsCode, so I had to use some AI to figure out how to install FlatLat onto VsCode on a Windows desktop. I made a seperate folder called “Lib” and added the FlatLaf download file. For now, I have the core ping functionality/logic down, the basic GUI, and my next steps are clear: I want to have a working, publicly appealing app. Hopefully I can submit this into the Congressional App Challenge within the next week! • P.S: Starting from this post, from now on, I am beginning to change the format of my Devlogs. Originally, they were very structured and bullet pointed. However, after double checking StarDance guidelines for a proper post, I want to make my posts more understandable and readable starting now. Thank you!"}, {"post_id": 74297, "ts": "2026-09-27T04:19:12Z", "hours": 3.1344, "text": "Day 20 — UI Polish & APP Refinement/Debugging Further developed the UI to be more presentable to users: Consistent color theme: light background, blue primary color, dark text, and light-gray section backgrounds Improved the title section with a larger blue title and a subtitle describing the application’s purpose. Redesigned the test configuration section by grouping the DNS target, number of tests, and delay controls into a single bordered panel. o Added recognizable DNS provider names to the target dropdown, such as Cloudflare and Google, instead of displaying only IP addresses. Added a clean border and light-gray background to test configuration panel to match Live Results section. Improved Start Test button, including styling and a play-button icon. Worked on removing the default blue selection highlighting from the dropdown and customizing it renderer/colors. Redesigned LIVE RESULTS so it appears as a proper section heading above a bordered results box rather than relying on Swing’s default titled border. Added light-gray background + border to the Live Results panel for consistent dashboard-like appearance. Learned more about Swing layouts, panels, borders, colors, renderers, component alignment, etc. Core functionality is now running, with the desktop application connected to the existing ping backend and displaying latency statistics."}, {"post_id": 73738, "ts": "2026-09-25T20:14:06Z", "hours": 2.8808, "text": "Day 19 — Connecting the Desktop Application Connected the GUI to the existing src.ping() backend o Integrated calculations for average latency, min/max latency, packet loss, and jitter Added user input for number of tests and delay between tests o Added input validation for test count and delay values Used ArrayList to store multiple ping results Connected the calculated results to the GUI’s live result labels Learned why Double.MAX_VALUE is useful when calculating a minimum value and how Thread.sleep() creates the delay between tests Next: Test the full workflow, fix any bugs, and make the GUI responsive before moving toward final polish/shipping :DD"}, {"post_id": 73378, "ts": "2026-09-25T01:24:33Z", "hours": 1.4611, "text": "Day 18 - Desktop UI & Connecting the Program · Connected the UI to the existing src.java ping functionality · Connecting public classes and calling methods from src.java · Changed ping() to be accessible from the UI - Learned how classes communicate with each other · Learned how LatencyAnalyzerWindow → src.ping() → PingResult → GUI works · Crucial for connecting jitter, packet loss, etc. later · Kept latency stored as a double and only formatted it for display 3 days left, with ~6–7 hours planned to finish, test, and polish the project :D"}, {"post_id": 72860, "ts": "2026-09-23T21:36:03Z", "hours": 3.9839, "text": "Day 17 – Beginning the Desktop App Interface 1. Core program: (everything I have been doing thus far): o Improved name input validation, including rejecting blank/space-only names. o Made the name switch case-insensitive using .toLowerCase() 2. Desktop App: o Began building a Java desktop app version of my Wi‑Fi Latency Analyzer using Java Swing · Created LatencyAnalyzerWindow.java, which opens a real application window o Learned the purpose of Swing components such as JFrame, JPanel, JLabel, JButton o Added a target-selection dropdown with Cloudflare and Google DNS options · Added fields for the number of tests and delay between tests o Added a Start Test button and status message area o Added Live Results section, placeholders for latency, average latency, packet loss, and jitter · Edited the ReadMe to better reflect status of project and AI usage during the project · Planned to connect the interface to real ping data next"}, {"post_id": 72396, "ts": "2026-09-22T20:29:12Z", "hours": 3.64, "text": "Day 15/16 - Debugging, Jitter, Project Organization 15: · Reorganized my programming workspace so each project has a folder · Set up a “Coding Projects” folder to keep my future projects under one large folder · Kept my Wi‑Fi Latency Analyzer in its own project folder o its Java code, README, license, and VS Code settings stay together · Created separate Java Practice folder for smaller programs that help me practice Java concepts · Reviewed the project files and learned what each one is used for · Found and removed an empty unused Java folder from the project · Made sure my project folders are synced and accessible through OneDrive · Overall, continued building good habits for keeping my code organized, separate, and easy to find 16: · Removed duplicate for loop that was double-counting successful latency data · Added jitter to the Wi-Fi Latency Analyzer o Learned to calculate jitter by comparing each successful ping to the previous successful ping o Used Math.abs() to find the absolute latency difference · Added handling for cases where jitter can’t be calculated, displaying N/A (if/else) · Tested multiple cases to make sure the new jitter calculations and edge cases worked correctly"}, {"post_id": 60617, "ts": "2026-09-03T02:20:12Z", "hours": 0.8453, "text": "Day 14 – Terminal Readability / Debugging (Continuation of Day 13) · Made average/min/max display N/A when there are no successful tests o Improved failed-test output so failed pings don’t misleadingly show 0 ms · Fixed the test-number display (TEST 1 OF 2, TEST 2 OF 2) · Fixed the duplicate results caused by nested loops (loop within another loop) · Tested failed hostnames and verified that it results in a 100% packet loss · Kept debugging messages temporarily · Deferred method refactoring for later"}, {"post_id": 60010, "ts": "2026-09-02T03:14:31Z", "hours": 0.9733, "text": "Day 13 – Readability / Displaying Clean Info on User Terminal · Improved the readability of individual ping results by labeling each test (TEST 1 OF 2, TEST 2 OF 2, etc.) o Fixed the successful-test counter so successful tests are counted correctly · Fixed the duplicate test display caused by accidentally using nested loops (loop inside of another loop) · Added the foundation for minimum and maximum latency calculations · Added success/failure, total latency, + min/max latency analysis into stored results analysis section · Fixed a variable declaration issue with totalLatency and successfulLatencyTests (order matters in code) · Overall: Day 13 focused on making the output cleaner and turning the stored ping data into more useful statistics"}, {"post_id": 59281, "ts": "2026-08-31T23:56:46Z", "hours": 0.7761, "text": "Day 12 – Formatting and Proper Displaying of Data – 8/31/26 · Added packet-loss formatting using printf to display percentages to 2 decimal places. o Improved the final ping-test summary for readability. · Verified the program correctly calculates and displays: o Successful tests o Failed tests o Packet loss o Average latency · Debugged an issue where the old println formatting was still being used. · Learned how Java printf formatting works, including %.2f, %%, and %n. · Chose to postpone additional rounding/refinement work until later if needed. · Day 12 milestone: The analyzer can now perform multiple ping tests, store the results, analyze them, and presents the key network statistics in a clean summary to the user."}, {"post_id": 58374, "ts": "2026-08-30T19:44:01Z", "hours": 1.6194, "text": "Day 11 – Analyzing Multiple Ping Tests (Collecting Data) · Added successful and failed test tracking using PingResult.success. o Calculated the number of successful tests and failed tests. · Added packet loss calculation: o Failed Tests ÷ Total Tests × 100 · Implemented average latency calculation using ONLY successful tests o Failed tests do not measure any latency, so do not include within calculation · Fixed the average latency calculation by properly incrementing successfulLatencyTests. · Verified that multiple ping results are correctly stored in the ArrayList. · Added a final PING TEST SUMMARY displaying: o Successful Tests o Failed Tests o Packet Loss o Average Latency · Tested the program with 3 pings to Google, successfully producing: o 3 successful tests o 0 failed tests o 0% packet loss o ~11.67 ms average latency"}, {"post_id": 55263, "ts": "2026-08-26T23:10:31Z", "hours": 1.5486, "text": "Day 10 - Multiple Ping Tests & Result Storage Implemented an ArrayList to store results from multiple ping tests. Added user input for the number of ping tests to run Added input validation to ensure the number of tests is a valid positive whole number Created a for loop to automatically run the requested number of ping tests Stored each PingResult in the ArrayList after every successful test. Added a results counter using results.size() to verify that results are being stored correctly. Confirmed the program successfully ran 3 separate tests to Google and stored all 3 results Debugged the output and identified/removing the unnecessary extra ping test result Verified latency extraction, success/failure detection, and timestamp functionality alongside new multi-test Ping system for my code Key milestone: The analyzer can now run multiple"}, {"post_id": 54887, "ts": "2026-08-26T03:13:56Z", "hours": 1.1456, "text": "Day 9 – Heavy debugging and Two-Step Verification · Debugged and refined the program’s user-input and control-flow systems. o Implemented a two-step verification process using if / else if / else logic to confirm intended program usage before proceeding. · Improved the survey consent workflow, allowing users to decline the survey while still accessing the Wi-Fi Latency Analyzer. · Debugged several issues involving conditional statements, loops, and program termination o Including changing Scanner object name to Input (more consistent and widely accepted) · Improved timestamp readability o Replacing Java’s default timestamp format with a user-friendly date/time format o Continued testing the analyzer with real network connection o Verified that latency measurements and timestamps were being returned correctly. · Edited/added more relevant comments"}, {"post_id": 54206, "ts": "2026-08-25T02:57:30Z", "hours": 0.7028, "text": "Day 8 – Debugging and Data Collection (beta version) · Debugged and improved the control flow (survey ProcessBuilder, pingResult… etc.) o Fixed “if else” function displaying semi-colon o Added safer handling for latency extraction by checking whether “ms” was successfully found (extracting the number) · Verified the latency parser o Located time= o Extracted Latency text o Identified numerical value o Converting “[String]” à double · Tested program with multiple real DNS servers to verify successful connections · Kept detailed debugging output in terminal (eg. Time= …) to verify source code is running properly · Edited a few comments to be accurate/up to date · Began real world analysis and data collection (very important for future) · Refined the project’s architecture and long-term direction: desktop application as the actual tool + website as the project’s documentation, research, data, and presentation layer o Further down the road when I begin developing the GUI/user interface o Reasoning for choosing desktop app as tool: websites would only run ping analysis from my computer, not from user’s computer"}, {"post_id": 53398, "ts": "2026-08-23T22:45:49Z", "hours": 1.3758, "text": "Day 7 – 8/23/26 – Development and Debugging Improved survey/user-flow logic Changed the survey from automatically terminating the program when the user selects “no.” Added an option for users to skip the survey and continue to the Wi-Fi Latency Analyzer. Added if / else if / else control flow to handle valid and invalid responses. Improved input validation Continued using equalsIgnoreCase() so inputs such as YES, Yes, and yes are treated consistently. Added handling for invalid responses instead of allowing unexpected input to break the program. Identified and corrected an issue where multiple scanner.nextLine() calls were accidentally being used before the program needed the second input. Debugging and code cleanup Identified a major issue where scanner.close() was accidentally placed inside the age-validation loop. Recognized that closing the scanner could prevent the rest of program from receiving user input. Kept scanner closure at the end of the program instead. · Began Day 7 latency extraction Built on the existing BufferedReader that reads the operating system’s ping output. Added detection for lines containing “time=”. Used indexOf() to locate the position of the latency information within the ping output. Began learning how substring() can isolate the latency portion of the returned text. Next step of extracting the numerical ms value and converting it with Double.parseDouble() Improved program methodology Continued developing the project incrementally Practiced debugging by testing individual sections Key challenge/cool change: The program is becoming more user-friendly and robust. Users can now decline the optional survey without losing access to the actual Wi-Fi Latency Analyzer, while the program separately handles survey consent and analyzer participation."}, {"post_id": 48318, "ts": "2026-08-16T17:02:05Z", "hours": 1.1478, "text": "Day 5 — Detecting Ping Success or Failure. Today I implemented and debugged the logic needed to determine whether a real ping to a DNS server succeeds or fails. I learned how ProcessBuilder, waitFor(), and exit codes work together to interact with the operating system, and how they actually evaluate the result of a network test. I also strengthened my understanding of input validation, control flow, methods, and user inputs, including using if/else if/else logic and System.exit(0) terminating the program. I tested the program with both valid and invalid targets and confirmed that it can now identify successful and unsuccessful connections. I also updated my README to better reflect the project’s current development. Next: Day 6 — extract the latency measurement in milliseconds from successful ping results."}, {"post_id": 47673, "ts": "2026-08-15T18:49:14Z", "hours": 1.7606, "text": "Day 4 progress: I broke my Ping Latency Analyzer’s source code into two classes: one handling the intro, simple setup, and survey questions, and the other managing the actual ping measurements and user input. Most of today was spent debugging and reorganizing that structure, and I started tracking my work directly in comments (e.g., // Day4:) to keep changes easy to follow over time. I also ensure the project used a single, consistent Scanner object in the Main class instead of creating multiple instances. On the technical side, I learned how ProcessBuilder, Process, start(), and getInputStream() work together to launch and read output from an external process, and I looked into the difference between declaring void on a main method versus omitting it. I applied .equalsIgnoreCase() to make my survey questions case-insensitive, and I compared using while loops versus if/else blocks for validating user input, particularly useful for handling simple yes/no responses."}, {"post_id": 46672, "ts": "2026-08-14T03:35:01Z", "hours": 1.8378, "text": "Day 2/3: Learned what a target like Cloudfare or Google DNS is within the world of Cloud and Data Engineering. Public IP Addresses for Website Domains. Learned Arrays/List ( [] ). Learned purpose of Classes/Objects (other than Public Class). Create a numbered menu with safe public test targets. Cloudfare: 1.1.1.1; Google DNS: 8.8.8.8. Let the user choose one target. Print the chosen target back to them"}, {"post_id": 45463, "ts": "2026-08-11T23:09:17Z", "hours": 1.3167, "text": "Day 1: Hi! My name is Aaryan, and this is the very beginning of my journey towards creating my first long-term project with Java. I am very new to Java and this program, and the code below represents the beginning of my User Info data collection for my Wi-Fi Latency Analyzer Project. Any comments or suggestions towards my project would be well appreciated! This is NOT a traditional Wi-Fi speed test, and I am aiming to measure metrics like Packet Loss, Latency, and stability of connections during gaming and video calls."}]...
|
Title: Wi-Fi Latency Analyzer by @aaryan_s | Stard Title: Wi-Fi Latency Analyzer by @aaryan_s | Stardance
Devlogs:
Day 1: Hi! My name is Aaryan, and this is the very beginning of my journey towards creating my first long-term project with Java. I am very new to Java and this program, and the code below represents the beginning of my User Info data collection for my Wi-Fi Latency Analyzer Project. Any comments or suggestions towards my project would be well appreciated! This is NOT a traditional Wi-Fi speed test, and I am aiming to measure metrics like Packet Loss, Latency, and stability of connections during gaming and video calls.
Day 2/3: Learned what a target like Cloudfare or Google DNS is within the world of Cloud and Data Engineering. Public IP Addresses for Website Domains. Learned Arrays/List ( [] ). Learned purpose of Classes/Objects (other than Public Class). Create a numbered menu with safe public test targets. Cloudfare: 1.1.1.1; Google DNS: 8.8.8.8. Let the user choose one target. Print the chosen target back to them
Day 4 progress: I broke my Ping Latency Analyzer’s source code into two classes: one handling the intro, simple setup, and survey questions, and the other managing the actual ping measurements and user input. Most of today was spent debugging and reorganizing that structure, and I started tracking my work directly in comments (e.g., // Day4:) to keep changes easy to follow over time. I also ensure the project used a single, consistent Scanner object in the Main class instead of creating multiple instances. On the technical side, I learned how ProcessBuilder, Process, start(), and getInputStream() work together to launch and read output from an external process, and I looked into the difference between declaring void on a main method versus omitting it. I applied .equalsIgnoreCase() to make my survey questions case-insensitive, and I compared using while loops versus if/else blocks for validating user input, particularly useful for handling simple yes/no responses.
Day 5 — Detecting Ping Success or Failure. Today I implemented and debugged the logic needed to determine whether a real ping to a DNS server succeeds or fails. I learned how ProcessBuilder, waitFor(), and exit codes work together to interact with the operating system, and how they actually evaluate the result of a network test. I also strengthened my understanding of input validation, control flow, methods, and user inputs, including using if/else if/else logic and System.exit(0) terminating the program. I tested the program with both valid and invalid targets and confirmed that it can now identify successful and unsuccessful connections. I also updated my README to better reflect the project’s current development. Next: Day 6 — extract the latency measurement in milliseconds from successful ping results.
Day 7 – 8/23/26 – Development and Debugging Improved survey/user-flow logic Changed the survey from automatically terminating the program when the user selects “no.” Added an option for users to skip the survey and continue to the Wi-Fi Latency Analyzer. Added if / else if / else control flow to handle valid and invalid responses. Improved input validation Continued using equalsIgnoreCase() so inputs such as YES, Yes, and yes are treated consistently. Added handling for invalid responses instead of allowing unexpected input to break the program. Identified and corrected an issue where multiple scanner.nextLine() calls were accidentally being used before the program needed the second input. Debugging and code cleanup Identified a major issue where scanner.close() was accidentally placed inside the age-validation loop. Recognized that closing the scanner could prevent the rest of program from receiving user input. Kept scanner closure at the end of the program instead. · Began Day 7 latency extraction Built on the existing BufferedReader that reads the operating system’s ping output. Added detection for lines containing “time=”. Used indexOf() to locate the position of the latency information within the ping output. Began learning how substring() can isolate the latency portion of the returned text. Next step of extracting the numerical ms value and converting it with Double.parseDouble() Improved program methodology Continued developing the project incrementally Practiced debugging by testing individual sections Key challenge/cool change: The program is becoming more user-friendly and robust. Users can now decline the optional survey without losing access to the actual Wi-Fi Latency Analyzer, while the program separately handles survey consent and analyzer participation.
Day 8 – Debugging and Data Collection (beta version) · Debugged and improved the control flow (survey ProcessBuilder, pingResult… etc.) o Fixed “if else” function displaying semi-colon o Added safer handling for latency extraction by checking whether “ms” was successfully found (extracting the number) · Verified the latency parser o Located time= o Extracted Latency text o Identified numerical value o Converting “[String]” à double · Tested program with multiple real DNS servers to verify successful connections · Kept detailed debugging output in terminal (eg. Time= …) to verify source code is running properly · Edited a few comments to be accurate/up to date · Began real world analysis and data collection (very important for future) · Refined the project’s architecture and long-term direction: desktop application as the actual tool + website as the project’s documentation, research, data, and presentation layer o Further down the road when I begin developing the GUI/user interface o Reasoning for choosing desktop app as tool: websites would only run ping analysis from my computer, not from user’s computer
Day 9 – Heavy debugging and Two-Step Verification · Debugged and refined the program’s user-input and control-flow systems. o Implemented a two-step verification process using if / else if / else logic to confirm intended program usage before proceeding. · Improved the survey consent workflow, allowing users to decline the survey while still accessing the Wi-Fi Latency Analyzer. · Debugged several issues involving conditional statements, loops, and program termination o Including changing Scanner object name to Input (more consistent and widely accepted) · Improved timestamp readability o Replacing Java’s default timestamp format with a user-friendly date/time format o Continued testing the analyzer with real network connection o Verified that latency measurements and timestamps were being returned correctly. · Edited/added more relevant comments
Day 10 - Multiple Ping Tests & Result Storage Implemented an ArrayList to store results from multiple ping tests. Added user input for the number of ping tests to run Added input validation to ensure the number of tests is a valid positive whole number Created a for loop to automatically run the requested number of ping tests Stored each PingResult in the ArrayList after every successful test. Added a results counter using results.size() to verify that results are being stored correctly. Confirmed the program successfully ran 3 separate tests to Google and stored all 3 results Debugged the output and identified/removing the unnecessary extra ping test result Verified latency extraction, success/failure detection, and timestamp functionality alongside new multi-test Ping system for my code Key milestone: The analyzer can now run multiple
Day 11 – Analyzing Multiple Ping Tests (Collecting Data) · Added successful and failed test tracking using PingResult.success. o Calculated the number of successful tests and failed tests. · Added packet loss calculation: o Failed Tests ÷ Total Tests × 100 · Implemented average latency calculation using ONLY successful tests o Failed tests do not measure any latency, so do not include within calculation · Fixed the average latency calculation by properly incrementing successfulLatencyTests. · Verified that multiple ping results are correctly stored in the ArrayList. · Added a final PING TEST SUMMARY displaying: o Successful Tests o Failed Tests o Packet Loss o Average Latency · Tested the program with 3 pings to Google, successfully producing: o 3 successful tests o 0 failed tests o 0% packet loss o ~11.67 ms average latency
Day 12 – Formatting and Proper Displaying of Data – 8/31/26 · Added packet-loss formatting using printf to display percentages to 2 decimal places. o Improved the final ping-test summary for readability. · Verified the program correctly calculates and displays: o Successful tests o Failed tests o Packet loss o Average latency · Debugged an issue where the old println formatting was still being used. · Learned how Java printf formatting works, including %.2f, %%, and %n. · Chose to postpone additional rounding/refinement work until later if needed. · Day 12 milestone: The analyzer can now perform multiple ping tests, store the results, analyze them, and presents the key network statistics in a clean summary to the user.
Day 13 – Readability / Displaying Clean Info on User Terminal · Improved the readability of individual ping results by labeling each test (TEST 1 OF 2, TEST 2 OF 2, etc.) o Fixed the successful-test counter so successful tests are counted correctly · Fixed the duplicate test display caused by accidentally using nested loops (loop inside of another loop) · Added the foundation for minimum and maximum latency calculations · Added success/failure, total latency, + min/max latency analysis into stored results analysis section · Fixed a variable declaration issue with totalLatency and successfulLatencyTests (order matters in code) · Overall: Day 13 focused on making the output cleaner and turning the stored ping data into more useful statistics
Day 14 – Terminal Readability / Debugging (Continuation of Day 13) · Made average/min/max display N/A when there are no successful tests o Improved failed-test output so failed pings don’t misleadingly show 0 ms · Fixed the test-number display (TEST 1 OF 2, TEST 2 OF 2) · Fixed the duplicate results caused by nested loops (loop within another loop) · Tested failed hostnames and verified that it results in a 100% packet loss · Kept debugging messages temporarily · Deferred method refactoring for later
Day 15/16 - Debugging, Jitter, Project Organization 15: · Reorganized my programming workspace so each project has a folder · Set up a “Coding Projects” folder to keep my future projects under one large folder · Kept my Wi‑Fi Latency Analyzer in its own project folder o its Java code, README, license, and VS Code settings stay together · Created separate Java Practice folder for smaller programs that help me practice Java concepts · Reviewed the project files and learned what each one is used for · Found and removed an empty unused Java folder from the project · Made sure my project folders are synced and accessible through OneDrive · Overall, continued building good habits for keeping my code organized, separate, and easy to find 16: · Removed duplicate for loop that was double-counting successful latency data · Added jitter to the Wi-Fi Latency Analyzer o Learned to calculate jitter by comparing each successful ping to the previous successful ping o Used Math.abs() to find the absolute latency difference · Added handling for cases where jitter can’t be calculated, displaying N/A (if/else) · Tested multiple cases to make sure the new jitter calculations and edge cases worked correctly
Day 17 – Beginning the Desktop App Interface 1. Core program: (everything I have been doing thus far): o Improved name input validation, including rejecting blank/space-only names. o Made the name switch case-insensitive using .toLowerCase() 2. Desktop App: o Began building a Java desktop app version of my Wi‑Fi Latency Analyzer using Java Swing · Created LatencyAnalyzerWindow.java, which opens a real application window o Learned the purpose of Swing components such as JFrame, JPanel, JLabel, JButton o Added a target-selection dropdown with Cloudflare and Google DNS options · Added fields for the number of tests and delay between tests o Added a Start Test button and status message area o Added Live Results section, placeholders for latency, average latency, packet loss, and jitter · Edited the ReadMe to better reflect status of project and AI usage during the project · Planned to connect the interface to real ping data next
Day 18 - Desktop UI & Connecting the Program · Connected the UI to the existing src.java ping functionality · Connecting public classes and calling methods from src.java · Changed ping() to be accessible from the UI - Learned how classes communicate with each other · Learned how LatencyAnalyzerWindow → src.ping() → PingResult → GUI works · Crucial for connecting jitter, packet loss, etc. later · Kept latency stored as a double and only formatted it for display 3 days left, with ~6–7 hours planned to finish, test, and polish the project :D
Day 19 — Connecting the Desktop Application Connected the GUI to the existing src.ping() backend o Integrated calculations for average latency, min/max latency, packet loss, and jitter Added user input for number of tests and delay between tests o Added input validation for test count and delay values Used ArrayList to store multiple ping results Connected the calculated results to the GUI’s live result labels Learned why Double.MAX_VALUE is useful when calculating a minimum value and how Thread.sleep() creates the delay between tests Next: Test the full workflow, fix any bugs, and make the GUI responsive before moving toward final polish/shipping :DD
Day 20 — UI Polish & APP Refinement/Debugging Further developed the UI to be more presentable to users: Consistent color theme: light background, blue primary color, dark text, and light-gray section backgrounds Improved the title section with a larger blue title and a subtitle describing the application’s purpose. Redesigned the test configuration section by grouping the DNS target, number of tests, and delay controls into a single bordered panel. o Added recognizable DNS provider names to the target dropdown, such as Cloudflare and Google, instead of displaying only IP addresses. Added a clean border and light-gray background to test configuration panel to match Live Results section. Improved Start Test button, including styling and a play-button icon. Worked on removing the default blue selection highlighting from the dropdown and customizing it renderer/colors. Redesigned LIVE RESULTS so it appears as a proper section heading above a bordered results box rather than relying on Swing’s default titled border. Added light-gray background + border to the Live Results panel for consistent dashboard-like appearance. Learned more about Swing layouts, panels, borders, colors, renderers, component alignment, etc. Core functionality is now running, with the desktop application connected to the existing ping backend and displaying latency statistics.
• Day 21 – Modern GUI and FlatLaf Setup – 10/19 • I installed FlatLaf, an open source java library for Java Swing applications . The goal with FlatLaf is to slowly “modernize” my app and overall make it look a lot more appealing to the user compared to it’s old basic java swing vibe. I struggled a lot with implementing FlatLaf and connecting it to my java swing application in VsCode, so I had to use some AI to figure out how to install FlatLat onto VsCode on a Windows desktop. I made a seperate folder called “Lib” and added the FlatLaf download file. For now, I have the core ping functionality/logic down, the basic GUI, and my next steps are clear: I want to have a working, publicly appealing app. Hopefully I can submit this into the Congressional App Challenge within the next week! • P.S: Starting from this post, from now on, I am beginning to change the format of my Devlogs. Originally, they were very structured and bullet pointed. However, after double checking StarDance guidelines for a proper post, I want to make my posts more understandable and readable starting now. Thank you!...
|
1792493337.907051
|
1793098137.907051
|
|
20340
|
Audio Codec Module by @pui4 | Stardance
|
pui4
|
0
|
7.87
|
0
|
[]
|
[{"post_id": 81127, "ts": "202 [{"post_id": 81127, "ts": "2026-10-20T00:07:01Z", "hours": 1.2197, "text": "I finally got it working. This is a shot devlog just before I ship. I have found an issue with the design (that I have now fixed), I forgot to breakout the output pin on the chip meaning that the mic input doesn’t work. However speaker output works! Here I have attached a video of it hooked up to a pi pico acting as a usb audio device (ignore the messy desk)"}, {"post_id": 63906, "ts": "2026-09-07T22:54:44Z", "hours": 1.4167, "text": "THE BOARDS HAVE ARRIVED!!! JLC has finally delivered the boards and they look fantastic. But do they work? I will get to that shortly. Ordering the boards was a pain in the ass. When I added the boards to my cart and filled everything in, I got a price of 60 USD. I made my application for a grant for 60 USD and got accepted. Then when I later went to purchase the boards, I got hit with 11 USD of hidden taxes that JLC doesn’t show you until after you have already put you card information in and are ready to buy it. So I was 11 USD short to order my boards; so I made a support ticket on the slack to get my grant increased - just for it to get a couple (honestly useless) replies. So in desperation I looked to see if I could decrease the price to fit inside my grant budget and I was able to using a JLC coupon. So I purchased the boards and received an email asking me the orientation of the single IC that is on the board. They had the dot in the top right when it needed to be in the top left. I corrected them and even attached a screenshot from KiCad to further illustrate my point. They thanked me for correcting them and that was the end of it. Fast forward to yesterday and the boards arrived. I was filled with excitement and I hastily soldered on the headers to the board. I then went to test it with an esp32 and a simple vibe-coded (calm down it’s just for testing) esphome app. I wired everything up correctly and saw nothing on the I2C bus. I was scared I made a mistake but all the voltages and pins were where they were supposed to be. Then I noticed it, the IC was rotated 90 degrees from where it should have been; on all of the boards. It was in the original orientation that JLC sent me and not the corrected one that they confirmed. Even though I don’t have the correct tools for the job I attempted at fixing one. The one with the header already on it would have been annoying as I would have had to remove the headers which is a major pain in the ass. So I stuck another board on top of the hotplate that I got from hackclub blueprint and tried. The first attempt ended in destruction as I was using the wrong type of tweezers and so when I went to place the chip down it pinged off and knocked a capacitor and resistor off the board; and I chose to use absolutely tiny passives as the footprints in KiCad are incomprehensible and trying to compare them to LCSC parts was hard. On the third board and attempt I did (or at least I think I did as I don’t have a microscope to properly check it). I ran over to my computer to test it and I saw it on the I2C bus. Then esphome wasn’t letting me use it as a WiFi speaker so I played some rttti sounds on it and it worked! Of course all of this time was not logged (4-5~ hours of work) so what was the 1 hour and 25 mins. Well the original purpose for this board was to be used with Linux SBCs and so I tried to get it to work with the pi zero 2w. I picked the 2w to test with as it has 6.18 kernel which includes a driver for the es8311. However I know next to nothing about Linux embedded development, even though I’ve dail drove Linux on my pc for almost 2 years now - I know it more as a user than a developer. In other words, I couldn’t figure out how to properly write the device trees to get it to work and I couldn’t vibe-code it either as that didn’t work. Now I have to try and get this working on the pi before the end of Star dance so I can ship it. If you are reading this and have any experience in embedded Linux or device trees, please message me on slack: @pui4 . Thanks for reading, I hope to get this done soon. Also I have sent an email complaining about the boards to JLC and I will report when I have any news."}, {"post_id": 26093, "ts": "2026-07-10T17:57:38Z", "hours": 1.7836, "text": "Finally going to submit!! I’ve finished the PCB and the readme (for now). I made blender renders of the PCB. I used a random HDRI I found online and hit render. Also I had to change the PCB as the footprint I was using for the resistors and capacitors were too small for the ones that I actually wanted to use. In fairness to me; it’s difficult to pick the right one when all the footprint names are “R_0201_0603Metric”. It’s so confusing that even claude got it wrong. It said that the second number was metric and the first was imperial and that LCSC has there components listed in metric. That’s wrong, I’m not sure what part of it is wrong - all I know is that the number I wanted for LCSC was the first one. I also changed the footprints so they aren’t the hand-solder ones. This is after @heki told me that it may cause issues, yesterday. This will not be my final post on this design as I guarantee that there will be some issue with the design or repo that requires me to re-submit but we’ll see. I also updated the readme to a some-what final state (until I actually get the boards). It has more info if you want to check it out. The repo is a bit messy at the minute so I need to tidy that up at a later date. Now I just need to wait to get it rejected to do any more work on it. Until then, thanks for reading !!"}, {"post_id": 25557, "ts": "2026-07-09T21:33:20Z", "hours": 0.9833, "text": "I think I’m done. I finished the PCB and fixed some things with the help of @heki (thanks). I did a BOM with the help of the JLC kicad extension and uploaded it to JLC and got a price of $40! I still need to do a render and submit it but I think I’m done for today. Thank you for reading. (I spent a lot longer on this but forgot to record it)"}, {"post_id": 25420, "ts": "2026-07-09T18:06:17Z", "hours": 1.7333, "text": "Hopefully finished routing the PCB. As I said in my last post; I’m not entirely sure on if I have picked the correct footprints for my resistors and capacitors. I picked small ones as it won’t draw much power and is 3.3 volts anyway. Also I ended up keeping the aux jacks and fit them in as shown in the screenshot. Next I need to make a BOM for JLC to assemble it as I currently don’t have the capabilities or expertise to solder SMD components. I have never made a BOM before and I don’t really know how to start - if anyone can help me, please comment on this post or reach out to me on slack. After the BOM is complete, then I will need to see the cost of producing these modules and submit the project for funding. Also excuse the poor quality of my routing and the large amount of Vias, as this is my second PCB ever and I’m just learning by trial and error. I mean my last PCB worked (with some bodges) so surely this vastly more complex one will work too; right? I also need to add some art to the PCB as currently it is very bland (yes the text is in comic sans). I will also do a render in blender and properly add the models for components in a future devlog. I’m also going to post the PCB and the schematic into the slack to see if their is any obvious issues that I have overlooked. If you (the person reading this) spots any issues - comment them or reach me on slack. Thanks for reading and hopefully I’ll get this done soon. :))"}, {"post_id": 24959, "ts": "2026-07-08T20:59:19Z", "hours": 0.7328, "text": "(little annoyed as I am having to re-write this entire thing again as stardance refused to accept my last one) I have just finished the schematic for the module. It is copied from an implementation by waveshare in one of their ESP32 boards here. I’m not 100% sure that it is correct as I’m not good enough at electronics yet to read and understand datasheets. I haven’t yet assigned the footprints to the symbols yet as I need to do more research into the different sizes of SMD resistors and caps. It has 2 aux jacks - one for input and one for output, I’m not fully sure whether or not I’m going to keep these in the final design as they are already broken out to the pin headers; but they are there for now. They are also TRS jacks even though they are both mono, this is due to me requiring a TRS jack for the mic I plan to use for my other project (a Rode videomic shotgun mic). I know that a mono jack would work too, but I’ve chosen to use TRS jacks also because they are easier to obtain. The pin headers are separated into 2 groups of 6 as to keep it small and bread-board compatible - so I can use this module for prototyping other projects more easily. Right now I’m going to submit this schematic into the outpost and stardance slacks to ask for others opinions. I have no intention to go to open sauce as it is too expensive for me to go as I am in the UK; so I’m hoping for as much star dust as possible :) If you have any questions (or you spotted an issue in the design) feel free to reach out to me on slack @pui4 . Thank you for reading and being interested in my project :))"}]...
|
Title: Audio Codec Module by @pui4 | Stardance
De Title: Audio Codec Module by @pui4 | Stardance
Devlogs:
(little annoyed as I am having to re-write this entire thing again as stardance refused to accept my last one) I have just finished the schematic for the module. It is copied from an implementation by waveshare in one of their ESP32 boards here. I’m not 100% sure that it is correct as I’m not good enough at electronics yet to read and understand datasheets. I haven’t yet assigned the footprints to the symbols yet as I need to do more research into the different sizes of SMD resistors and caps. It has 2 aux jacks - one for input and one for output, I’m not fully sure whether or not I’m going to keep these in the final design as they are already broken out to the pin headers; but they are there for now. They are also TRS jacks even though they are both mono, this is due to me requiring a TRS jack for the mic I plan to use for my other project (a Rode videomic shotgun mic). I know that a mono jack would work too, but I’ve chosen to use TRS jacks also because they are easier to obtain. The pin headers are separated into 2 groups of 6 as to keep it small and bread-board compatible - so I can use this module for prototyping other projects more easily. Right now I’m going to submit this schematic into the outpost and stardance slacks to ask for others opinions. I have no intention to go to open sauce as it is too expensive for me to go as I am in the UK; so I’m hoping for as much star dust as possible :) If you have any questions (or you spotted an issue in the design) feel free to reach out to me on slack @pui4 . Thank you for reading and being interested in my project :))
Hopefully finished routing the PCB. As I said in my last post; I’m not entirely sure on if I have picked the correct footprints for my resistors and capacitors. I picked small ones as it won’t draw much power and is 3.3 volts anyway. Also I ended up keeping the aux jacks and fit them in as shown in the screenshot. Next I need to make a BOM for JLC to assemble it as I currently don’t have the capabilities or expertise to solder SMD components. I have never made a BOM before and I don’t really know how to start - if anyone can help me, please comment on this post or reach out to me on slack. After the BOM is complete, then I will need to see the cost of producing these modules and submit the project for funding. Also excuse the poor quality of my routing and the large amount of Vias, as this is my second PCB ever and I’m just learning by trial and error. I mean my last PCB worked (with some bodges) so surely this vastly more complex one will work too; right? I also need to add some art to the PCB as currently it is very bland (yes the text is in comic sans). I will also do a render in blender and properly add the models for components in a future devlog. I’m also going to post the PCB and the schematic into the slack to see if their is any obvious issues that I have overlooked. If you (the person reading this) spots any issues - comment them or reach me on slack. Thanks for reading and hopefully I’ll get this done soon. :))
I think I’m done. I finished the PCB and fixed some things with the help of @heki (thanks). I did a BOM with the help of the JLC kicad extension and uploaded it to JLC and got a price of $40! I still need to do a render and submit it but I think I’m done for today. Thank you for reading. (I spent a lot longer on this but forgot to record it)
Finally going to submit!! I’ve finished the PCB and the readme (for now). I made blender renders of the PCB. I used a random HDRI I found online and hit render. Also I had to change the PCB as the footprint I was using for the resistors and capacitors were too small for the ones that I actually wanted to use. In fairness to me; it’s difficult to pick the right one when all the footprint names are “R_0201_0603Metric”. It’s so confusing that even claude got it wrong. It said that the second number was metric and the first was imperial and that LCSC has there components listed in metric. That’s wrong, I’m not sure what part of it is wrong - all I know is that the number I wanted for LCSC was the first one. I also changed the footprints so they aren’t the hand-solder ones. This is after @heki told me that it may cause issues, yesterday. This will not be my final post on this design as I guarantee that there will be some issue with the design or repo that requires me to re-submit but we’ll see. I also updated the readme to a some-what final state (until I actually get the boards). It has more info if you want to check it out. The repo is a bit messy at the minute so I need to tidy that up at a later date. Now I just need to wait to get it rejected to do any more work on it. Until then, thanks for reading !!
THE BOARDS HAVE ARRIVED!!! JLC has finally delivered the boards and they look fantastic. But do they work? I will get to that shortly. Ordering the boards was a pain in the ass. When I added the boards to my cart and filled everything in, I got a price of 60 USD. I made my application for a grant for 60 USD and got accepted. Then when I later went to purchase the boards, I got hit with 11 USD of hidden taxes that JLC doesn’t show you until after you have already put you card information in and are ready to buy it. So I was 11 USD short to order my boards; so I made a support ticket on the slack to get my grant increased - just for it to get a couple (honestly useless) replies. So in desperation I looked to see if I could decrease the price to fit inside my grant budget and I was able to using a JLC coupon. So I purchased the boards and received an email asking me the orientation of the single IC that is on the board. They had the dot in the top right when it needed to be in the top left. I corrected them and even attached a screenshot from KiCad to further illustrate my point. They thanked me for correcting them and that was the end of it. Fast forward to yesterday and the boards arrived. I was filled with excitement and I hastily soldered on the headers to the board. I then went to test it with an esp32 and a simple vibe-coded (calm down it’s just for testing) esphome app. I wired everything up correctly and saw nothing on the I2C bus. I was scared I made a mistake but all the voltages and pins were where they were supposed to be. Then I noticed it, the IC was rotated 90 degrees from where it should have been; on all of the boards. It was in the original orientation that JLC sent me and not the corrected one that they confirmed. Even though I don’t have the correct tools for the job I attempted at fixing one. The one with the header already on it would have been annoying as I would have had to remove the headers which is a major pain in the ass. So I stuck another board on top of the hotplate that I got from hackclub blueprint and tried. The first attempt ended in destruction as I was using the wrong type of tweezers and so when I went to place the chip down it pinged off and knocked a capacitor and resistor off the board; and I chose to use absolutely tiny passives as the footprints in KiCad are incomprehensible and trying to compare them to LCSC parts was hard. On the third board and attempt I did (or at least I think I did as I don’t have a microscope to properly check it). I ran over to my computer to test it and I saw it on the I2C bus. Then esphome wasn’t letting me use it as a WiFi speaker so I played some rttti sounds on it and it worked! Of course all of this time was not logged (4-5~ hours of work) so what was the 1 hour and 25 mins. Well the original purpose for this board was to be used with Linux SBCs and so I tried to get it to work with the pi zero 2w. I picked the 2w to test with as it has 6.18 kernel which includes a driver for the es8311. However I know next to nothing about Linux embedded development, even though I’ve dail drove Linux on my pc for almost 2 years now - I know it more as a user than a developer. In other words, I couldn’t figure out how to properly write the device trees to get it to work and I couldn’t vibe-code it either as that didn’t work. Now I have to try and get this working on the pi before the end of Star dance so I can ship it. If you are reading this and have any experience in embedded Linux or device trees, please message me on slack: @pui4 . Thanks for reading, I hope to get this done soon. Also I have sent an email complaining about the boards to JLC and I will report when I have any news.
I finally got it working. This is a shot devlog just before I ship. I have found an issue with the design (that I have now fixed), I forgot to breakout the output pin on the chip meaning that the mic input doesn’t work. However speaker output works! Here I have attached a video of it hooked up to a pi pico acting as a usb audio device (ignore the messy desk)...
|
1792698589.5127926
|
1793303389.5127926
|
|
66920
|
My own site! by @PhantomStorm | Stardance
|
PhantomStorm
|
1
|
11.3
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-07T01:14:13Z", "hours": 6.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made an All about Me website, that portrays my skills, hobbies, and my profile. It was challenging to fit enough time into making this. I am really proud of the UI.", "repo": "https://github.com/Rephantom-Vortex/My-Personal-Website", "demo": "https://my-bio.boomurl.me/"}]...
|
[{"post_id": 81128, "ts": "202 [{"post_id": 81128, "ts": "2026-10-20T00:14:07Z", "hours": 0.2531, "text": "I WILL CRASH OUT, HOW AM I SUPPOSED TO LOWER AI USAGE IF I DIDN’T USE IT ALL. I am literally crying, I wish AI never existed, i took literally 11 hours to do this and I am still being accused of AI, like literally check the code, it is so messed up, there are DIVs everywhere, and random class names cuz I couldn’t make them up."}, {"post_id": 80226, "ts": "2026-10-16T19:50:37Z", "hours": 0.4592, "text": "Y r my projects always flagged as AI, I didn’t use it"}, {"post_id": 80021, "ts": "2026-10-16T00:17:11Z", "hours": 1.9803, "text": "I finished redoing the CSS!"}, {"post_id": 79162, "ts": "2026-10-12T20:56:21Z", "hours": 2.6044, "text": "Had to Redo the CSS, cuz it was flagged as AI. This time I DID NOT use a AI for anything (except for searching how to center a div)"}, {"post_id": 77441, "ts": "2026-10-07T00:55:58Z", "hours": 2.5144, "text": "FINALLY, Finished!"}, {"post_id": 77204, "ts": "2026-10-06T02:49:05Z", "hours": 0.7017, "text": "Got Started On CSS"}, {"post_id": 77194, "ts": "2026-10-06T01:14:40Z", "hours": 3.2092, "text": "Finished the HTML of My Personal Website, Got CSS Left"}]...
|
Title: My own site! by @PhantomStorm | Stardance
Title: My own site! by @PhantomStorm | Stardance
Devlogs:
Finished the HTML of My Personal Website, Got CSS Left
Got Started On CSS
FINALLY, Finished!
Had to Redo the CSS, cuz it was flagged as AI. This time I DID NOT use a AI for anything (except for searching how to center a div)
I finished redoing the CSS!
Y r my projects always flagged as AI, I didn’t use it
I WILL CRASH OUT, HOW AM I SUPPOSED TO LOWER AI USAGE IF I DIDN’T USE IT ALL. I am literally crying, I wish AI never existed, i took literally 11 hours to do this and I am still being accused of AI, like literally check the code, it is so messed up, there are DIVs everywhere, and random class names cuz I couldn’t make them up.
Ships:
I made an All about Me website, that portrays my skills, hobbies, and my profile. It was challenging to fit enough time into making this. I am really proud of the UI....
|
1793062225.8397465
|
1793148625.8397465
|
|
55085
|
Tidal-keys by @ElGOATFilipino | Stardance
|
ElGOATFilipino
|
0
|
43.53
|
0
|
[]
|
[{"post_id": 81131, "ts": "202 [{"post_id": 81131, "ts": "2026-10-20T00:44:53Z", "hours": 0.7167, "text": "Started making the BOM! Probably the thing that shocked me most were the Cherry MX2A prices (20 dollars for 36 keys!), so I tried hunting for the best key-value deal. In the end I settled for a 29 dollar 70 pcs on Aliexpress (cheapest option)"}, {"post_id": 80826, "ts": "2026-10-18T22:23:44Z", "hours": 0.9831, "text": "Finished debugging my code! It took a suprisingly long time since I had to wait like 5 minutes in between fixing sessions (16 git pushes!) to determine where the error is, though it was mainly syntax errors here and there."}, {"post_id": 80223, "ts": "2026-10-16T19:47:46Z", "hours": 1.3489, "text": "Finished the zmk code! Hi! Today I just added missing features like bluetooth, rgb, and battery level, though it took me a while because I constantly got lost in the guide and didnt understand what I was reading (especially the bluetooth part). Now all thats left is the bom and the github repo!"}, {"post_id": 80183, "ts": "2026-10-16T16:31:48Z", "hours": 4.16, "text": "Finished assembly!! Mainly took a bit longer on it because I had to fix some model errors, but apart from that everything went smoothly, the keyboard case is done! Also started working on the code, which is actually pretty simple, since im just following the zmk firmware guide."}, {"post_id": 77442, "ts": "2026-10-07T00:58:37Z", "hours": 7.2786, "text": "Hi everyone!! Sorry for not devolging in like what, more than 2 weeks? I just haven’t had a lot of time lately, had to study for a lot of test + school dances, ect,etc,etc. This means not a lot has happened these days, I’ve mainly been doing the assembly (which is almost completed) + modifying some parts bercause they didnt fit. I had a huge derail on this project, because I thought that each keycap had a litte 1mm spacing in between them, turn out that was definitely not true, so I had to work +3 hours to fix all that in the board and CAD. (I wish I had known that sooner! 😭) Trying to find keycaps for it is an actual PAIN, I really cant find 3u keycaps for DSA, so I had to improvise (just scaled a 1u horizontally, all add in the stumps later) *Right side is still in process! Also the enter key is kinda off scale, have to look into that."}, {"post_id": 70656, "ts": "2026-09-19T15:07:26Z", "hours": 5.9494, "text": "Right side CAD complete!! As planned in my figma sketch, I went with the beach themed right side split, I even added little starfish in that little empty space in the bottom right. I also decided to keep the dent that the left side has, that way they look symmetrical. Plus, I made a lid for the battery compartment with corresponding colors for each one! Now all thats left is to make the assembly! Shouldnt take long. I think I’ll do three designs: One for the left, the other for the right, and a 3rd one where both of them are together (for the picture!)"}, {"post_id": 68889, "ts": "2026-09-15T23:26:52Z", "hours": 3.9442, "text": "Finished the left splits components! Today I finished polishing the bottom part of the split, like adding the battery wire hole, and screw holes. I also made the top part of the split! I used the color stackup I said I was going to use in my figma sketch, mainly dark tones of blue. I also added white arrows (which appear in the TW title screen) on a little raised platform, and a few little bubbles as extra deco). An import change I made was changing the screws from M3 → M2, since the M2 are smaller and leave more space for clearances. Now all thats left is to make the assembly design of it! That means every single screw, key, keycap, heatset insert. And after that would come the right split and firmware!"}, {"post_id": 67682, "ts": "2026-09-13T21:02:03Z", "hours": 3.7714, "text": "(Almost) Finished making the bottom plate of the left side of my split keyboard!! As soon as I started modeling the plate, I realized I’m incredibly slow and bad at CAD, It took me almost 3 hours just to do it. Rewatching my recordings, I was probably anxious and kind of confused about the measurements and how the stackup will be. Hoepfully with the other plates I take less (I already know what to do). All I did was follow my figma drawings and I added a few modifications, such as a little wrist rest and a little thing at the top (planning to put the drawings there). Also added the little battery compartment on the bottom, and as I’m writing this, I just noticed that the battery box has no where to connect to the pcb, so I have to add that still. Another thing: I’m going to see what’s up with the hours I logged becasue according to stardance I’ve worked 4, but when I look at my lapse it only sums up to around 3 hours, so I’m going to ask in slack."}, {"post_id": 63137, "ts": "2026-09-06T19:31:10Z", "hours": 2.4481, "text": "Design time!!!!! 🌠🌠 Ok, so I didnt have much time to work on the split keyboard because I had to study for a LOT of tests. Usually before I desing something in fusion 360, I like to sketch it out first, I usually do it on my phone, but I decided to give figma a shot for this project. I probably took more time trying to figure out how properly use figma, I made some very messy stuff in it. I had two main ideas while working: First idea : Left → Wave Right → Beach But the little fleck that a wave has at the back would be bothersame while gaming. Second Idea : Based off the tidal wave title screen Left → top part of t.s Right → bottom part of t.s Cool color palette (Dark + Bright) Long story short, second idea won because its simpler and cleaner than the first one. Thats why its good to sketch it out first! Because if I had gone with my first idea immediately in fusion, I would’ve had to design all over again because I would’ve noticed the bad fleck- So now all thats left is to design the CAD!"}, {"post_id": 58429, "ts": "2026-08-30T20:56:12Z", "hours": 4.1267, "text": "PCB Finished!!! I am SUPER happy because I finished the split keyboards PCB! Though I had to redo some parts because I got confused with the footprints, so like an hour wasted right there because of a small mistake. Long story short , the LCSC SK6803 MINI-E footprint was NOT right, I discovered that all the leds in the SK series are reverse mounted (the LCSC was not), meaning that every single led in my pcb was wrong, and therefore, every single trace tied to it . Also, there were like 10000 DRC errors, because of the same LED footprint, the copper is incredibly close to the cut-out, so KiCAD just started freaking out. The cherry on top🍒🎂 : KiCAD crashed as soon as I finished everything that I just mentioned, so I had to do EVERYTHING again in 20 minutes. Other changes!: I moved some of the battery pads so I could route the LEDS easier Made all silkscreen texts face the same way so it’s easier to read + cool GD wave drawings Made each split keyboard have their own gnd net (KiCAD was trying to tie them together) Mousebites in between🐭 Assigned all the 3D models for every component! Soo, I could say the split keyboards PCB is finished , so now the next step is CAD, I still don’t know how I’m going to design the case so it looks like Tidal wave, probably going to make it cyan with fish maybe? I’ll see later."}, {"post_id": 57635, "ts": "2026-08-29T20:47:38Z", "hours": 3.6208, "text": "Almost finished with the second half of the split keyboard! I spent most of my time fighting with KiCad’s UI and trying to get the measurements of the board right, at some point I made the mistake of making the board 11.75cm and not the 11.73cm it was supposed to be (took me like 40 minutes to try and fix it), so all the wires and stuff had to be moved and replaced. I want to make each side of the board click somehow? Like not actually click but something like giving the illusion that you can merge them. Fun thing: I discovered that the key footprint library I’m using has more than just plain old keys, it has fun shapes! Like the “enter” key, plus, they are compatible with the Kailh hotswap I’m using! Another thing that I forgot to mention was that I added an extra button to the matrix, because there were some very big empty spaces near the thumb that could use an extra button, so the total button count for the split keyboard is 48. Also some keys that will use spaces slightly bigger than 1u (such as CAPS and Right shift) that are too small for the stabilizers (smallest is 2u), are a bit farther apart so they fit in the keyboard, and use the space they are supposed to. Right now I still have to check the DRC for errors + some power routing I forgot on the right side. I’m also thinking about adding some silkscreen designs to some of the free spaces on the board, so it doesnt look empty."}, {"post_id": 56781, "ts": "2026-08-28T18:00:22Z", "hours": 3.8422, "text": "Today I completed the left half of my split keyboard! I had a bit of a problem with the LED model I was going to use, since I was planning to sue the SK6812MINI-e, but discovered that it actually needs 5V to work, which is bad since we only have 3.7V coming from a 1S LiPo Battery. So, I switched to its 3mA counterpart “SK6803MINI-E” which can operate at 3.4V instead of 5. Routing wasn’t that much of a problem, a few vias usually fixed the problem. I still don’t know about the battery pads, I feel like they shouldn’t go where they are (maybe they are too close to the edge?). But apart from that, everything is ok! Now I just have to make the right side of the keyboard"}, {"post_id": 56217, "ts": "2026-08-27T21:47:10Z", "hours": 1.3364, "text": "Started making the schematic for the keyboard! I decided to go with the popular XIAO nRF52840 module, since it has wireless capabilities. The big problem for me was trying to manage my GPIO’s, since for 5 rows and 5 columns I need 10 GPIO’s, + a battery sensor, which is 11 gpio’s total (MCU max), but I was looking forward to adding sk6812mini-e leds. But I discovered that the nRF52840 has a battery sensor integrated so that would free up the necesary gpio for the leds. Another problem I had was trying to manage the button count, I was constantly switching from 6 rows, 4 columns to 5 rows 5 columns, and so on. I decided to use a 5x5 layout but leave one row (lowest one) with 3 thumb keys, which would be space, Lctrl, and LAlt. For the diodes, I decided to go with the classic 1N5819, and for the switches I decided to use the Kailh hotswap footprints."}]...
|
Title: Tidal-keys by @ElGOATFilipino | Stardance
Title: Tidal-keys by @ElGOATFilipino | Stardance
Devlogs:
Started making the schematic for the keyboard! I decided to go with the popular XIAO nRF52840 module, since it has wireless capabilities. The big problem for me was trying to manage my GPIO’s, since for 5 rows and 5 columns I need 10 GPIO’s, + a battery sensor, which is 11 gpio’s total (MCU max), but I was looking forward to adding sk6812mini-e leds. But I discovered that the nRF52840 has a battery sensor integrated so that would free up the necesary gpio for the leds. Another problem I had was trying to manage the button count, I was constantly switching from 6 rows, 4 columns to 5 rows 5 columns, and so on. I decided to use a 5x5 layout but leave one row (lowest one) with 3 thumb keys, which would be space, Lctrl, and LAlt. For the diodes, I decided to go with the classic 1N5819, and for the switches I decided to use the Kailh hotswap footprints.
Today I completed the left half of my split keyboard! I had a bit of a problem with the LED model I was going to use, since I was planning to sue the SK6812MINI-e, but discovered that it actually needs 5V to work, which is bad since we only have 3.7V coming from a 1S LiPo Battery. So, I switched to its 3mA counterpart “SK6803MINI-E” which can operate at 3.4V instead of 5. Routing wasn’t that much of a problem, a few vias usually fixed the problem. I still don’t know about the battery pads, I feel like they shouldn’t go where they are (maybe they are too close to the edge?). But apart from that, everything is ok! Now I just have to make the right side of the keyboard
Almost finished with the second half of the split keyboard! I spent most of my time fighting with KiCad’s UI and trying to get the measurements of the board right, at some point I made the mistake of making the board 11.75cm and not the 11.73cm it was supposed to be (took me like 40 minutes to try and fix it), so all the wires and stuff had to be moved and replaced. I want to make each side of the board click somehow? Like not actually click but something like giving the illusion that you can merge them. Fun thing: I discovered that the key footprint library I’m using has more than just plain old keys, it has fun shapes! Like the “enter” key, plus, they are compatible with the Kailh hotswap I’m using! Another thing that I forgot to mention was that I added an extra button to the matrix, because there were some very big empty spaces near the thumb that could use an extra button, so the total button count for the split keyboard is 48. Also some keys that will use spaces slightly bigger than 1u (such as CAPS and Right shift) that are too small for the stabilizers (smallest is 2u), are a bit farther apart so they fit in the keyboard, and use the space they are supposed to. Right now I still have to check the DRC for errors + some power routing I forgot on the right side. I’m also thinking about adding some silkscreen designs to some of the free spaces on the board, so it doesnt look empty.
PCB Finished!!! I am SUPER happy because I finished the split keyboards PCB! Though I had to redo some parts because I got confused with the footprints, so like an hour wasted right there because of a small mistake. Long story short , the LCSC SK6803 MINI-E footprint was NOT right, I discovered that all the leds in the SK series are reverse mounted (the LCSC was not), meaning that every single led in my pcb was wrong, and therefore, every single trace tied to it . Also, there were like 10000 DRC errors, because of the same LED footprint, the copper is incredibly close to the cut-out, so KiCAD just started freaking out. The cherry on top🍒🎂 : KiCAD crashed as soon as I finished everything that I just mentioned, so I had to do EVERYTHING again in 20 minutes. Other changes!: I moved some of the battery pads so I could route the LEDS easier Made all silkscreen texts face the same way so it’s easier to read + cool GD wave drawings Made each split keyboard have their own gnd net (KiCAD was trying to tie them together) Mousebites in between🐭 Assigned all the 3D models for every component! Soo, I could say the split keyboards PCB is finished , so now the next step is CAD, I still don’t know how I’m going to design the case so it looks like Tidal wave, probably going to make it cyan with fish maybe? I’ll see later.
Design time!!!!! 🌠🌠 Ok, so I didnt have much time to work on the split keyboard because I had to study for a LOT of tests. Usually before I desing something in fusion 360, I like to sketch it out first, I usually do it on my phone, but I decided to give figma a shot for this project. I probably took more time trying to figure out how properly use figma, I made some very messy stuff in it. I had two main ideas while working: First idea : Left → Wave Right → Beach But the little fleck that a wave has at the back would be bothersame while gaming. Second Idea : Based off the tidal wave title screen Left → top part of t.s Right → bottom part of t.s Cool color palette (Dark + Bright) Long story short, second idea won because its simpler and cleaner than the first one. Thats why its good to sketch it out first! Because if I had gone with my first idea immediately in fusion, I would’ve had to design all over again because I would’ve noticed the bad fleck- So now all thats left is to design the CAD!
(Almost) Finished making the bottom plate of the left side of my split keyboard!! As soon as I started modeling the plate, I realized I’m incredibly slow and bad at CAD, It took me almost 3 hours just to do it. Rewatching my recordings, I was probably anxious and kind of confused about the measurements and how the stackup will be. Hoepfully with the other plates I take less (I already know what to do). All I did was follow my figma drawings and I added a few modifications, such as a little wrist rest and a little thing at the top (planning to put the drawings there). Also added the little battery compartment on the bottom, and as I’m writing this, I just noticed that the battery box has no where to connect to the pcb, so I have to add that still. Another thing: I’m going to see what’s up with the hours I logged becasue according to stardance I’ve worked 4, but when I look at my lapse it only sums up to around 3 hours, so I’m going to ask in slack.
Finished the left splits components! Today I finished polishing the bottom part of the split, like adding the battery wire hole, and screw holes. I also made the top part of the split! I used the color stackup I said I was going to use in my figma sketch, mainly dark tones of blue. I also added white arrows (which appear in the TW title screen) on a little raised platform, and a few little bubbles as extra deco). An import change I made was changing the screws from M3 → M2, since the M2 are smaller and leave more space for clearances. Now all thats left is to make the assembly design of it! That means every single screw, key, keycap, heatset insert. And after that would come the right split and firmware!
Right side CAD complete!! As planned in my figma sketch, I went with the beach themed right side split, I even added little starfish in that little empty space in the bottom right. I also decided to keep the dent that the left side has, that way they look symmetrical. Plus, I made a lid for the battery compartment with corresponding colors for each one! Now all thats left is to make the assembly! Shouldnt take long. I think I’ll do three designs: One for the left, the other for the right, and a 3rd one where both of them are together (for the picture!)
Hi everyone!! Sorry for not devolging in like what, more than 2 weeks? I just haven’t had a lot of time lately, had to study for a lot of test + school dances, ect,etc,etc. This means not a lot has happened these days, I’ve mainly been doing the assembly (which is almost completed) + modifying some parts bercause they didnt fit. I had a huge derail on this project, because I thought that each keycap had a litte 1mm spacing in between them, turn out that was definitely not true, so I had to work +3 hours to fix all that in the board and CAD. (I wish I had known that sooner! 😭) Trying to find keycaps for it is an actual PAIN, I really cant find 3u keycaps for DSA, so I had to improvise (just scaled a 1u horizontally, all add in the stumps later) *Right side is still in process! Also the enter key is kinda off scale, have to look into that.
Finished assembly!! Mainly took a bit longer on it because I had to fix some model errors, but apart from that everything went smoothly, the keyboard case is done! Also started working on the code, which is actually pretty simple, since im just following the zmk firmware guide.
Finished the zmk code! Hi! Today I just added missing features like bluetooth, rgb, and battery level, though it took me a while because I constantly got lost in the guide and didnt understand what I was reading (especially the bluetooth part). Now all thats left is the bom and the github repo!
Finished debugging my code! It took a suprisingly long time since I had to wait like 5 minutes in between fixing sessions (16 git pushes!) to determine where the error is, though it was mainly syntax errors here and there.
Started making the BOM! Probably the thing that shocked me most were the Cherry MX2A prices (20 dollars for 36 keys!), so I tried hunting for the best key-value deal. In the end I settled for a 29 dollar 70 pcs on Aliexpress (cheapest option)...
|
1792482543.9873607
|
1793087343.9873607
|
|
16795
|
MAGNUS: DIY chess playing robot by @Leo_Zannoni | MAGNUS: DIY chess playing robot by @Leo_Zannoni | Stardance...
|
Leo_Zannoni
|
0
|
8.74
|
0
|
[]
|
[{"post_id": 81134, "ts": "202 [{"post_id": 81134, "ts": "2026-10-20T01:00:50Z", "hours": 8.3128, "text": "What MAGNUS is MAGNUS is a robot that plays chess on a real board against a person and says its moves out loud in Spanish. I’m building it for PRONAFECYT 2026, Costa Rica’s national science fair, and the voice is there for accessibility: you can follow the game without looking at a screen. I started on february with my first 3D models. Today it plays full games by itself and narrates them. About the hours Hackatime only logged about 8.5 h, because it only counts time in the code editor when i downloaded the app. Most of the work was CAD, printing, assembling and testing the arm. My log puts the real total at 350+ hours Vision Every piece is a 22.5 mm disc with an ArUco 4x4_50 marker and a white ring around it for contrast. The four board corners have their own markers, so the board is found from any camera angle. The camera is my phone through Iriun. A piece only counts after 5 detections in a row, and a GameTracker compares what the camera sees against every legal move to work out what the human played, including castling and en passant. Engine Stockfish runs through python-chess with 10 difficulty levels. Stockfish can’t play below about 1320 Elo, so the four easiest levels choose worse moves on purpose. Every move comes with metadata for captures, castling, en passant and promotion, so the arm never has to know any chess. The arm Shoulder and elbow use the encoder motors from the mBot2 kit on a CyberPi, with a LEGO Technic frame plus printed parts. I tried a 3:1 reduction on the shoulder, couldn’t make it work, and direct drive turned out to be enough. Instead of inverse kinematics I recorded the motor angles for all 64 squares once (teach and playback), with the motors powered, because the arm bends differently when you move it by hand. The encoders are incremental, so the arm homes against physical stops every time it starts. Magnets and the gripper The arm carries a 12x3 mm N52 magnet that grabs a piece from about 8 mm away. Each piece has two 10x2 mm magnets, one on top for the arm and one underneath for the board, and every square has a 6x3 mm magnet below it. Neighboring pieces 32 mm away don’t move. A servo lowers the magnet, lifts the piece and releases it. Without the lift step the arm dragged pieces and knocked over the neighbors. Problems I had to solve Magnet holes modeled at exactly 10 mm were too tight, so I made them 10.1 to 10.2 mm to allow for FDM tolerance. The CyberPi doesn’t report its IP, so my Mac runs a TCP server and the CyberPi connects to it as a client. The CyberPi only sees 2.4 GHz WiFi. mBlock’s mlink kept the serial port locked until I ran pkill -f mlink. How the software is organized There are three nodes (vision, engine and arm) that talk through typed messages, ROS2 style. Each hardware part has a fake backend, so the 482 tests run without the robot, and there’s a fully simulated pipeline for testing a whole game. What’s next Tuning arm precision: re-recording the squares where the magnet doesn’t land centered and testing the robot more with people with blind people. Also im working on a demo video with the robot working coming soon"}, {"post_id": 7867, "ts": "2026-06-13T03:49:51Z", "hours": 0.4319, "text": "Added the 3d chess models for the project"}]...
|
Title: MAGNUS: DIY chess playing robot by @Leo_Zan Title: MAGNUS: DIY chess playing robot by @Leo_Zannoni | Stardance
Devlogs:
Added the 3d chess models for the project
What MAGNUS is MAGNUS is a robot that plays chess on a real board against a person and says its moves out loud in Spanish. I’m building it for PRONAFECYT 2026, Costa Rica’s national science fair, and the voice is there for accessibility: you can follow the game without looking at a screen. I started on february with my first 3D models. Today it plays full games by itself and narrates them. About the hours Hackatime only logged about 8.5 h, because it only counts time in the code editor when i downloaded the app. Most of the work was CAD, printing, assembling and testing the arm. My log puts the real total at 350+ hours Vision Every piece is a 22.5 mm disc with an ArUco 4x4_50 marker and a white ring around it for contrast. The four board corners have their own markers, so the board is found from any camera angle. The camera is my phone through Iriun. A piece only counts after 5 detections in a row, and a GameTracker compares what the camera sees against every legal move to work out what the human played, including castling and en passant. Engine Stockfish runs through python-chess with 10 difficulty levels. Stockfish can’t play below about 1320 Elo, so the four easiest levels choose worse moves on purpose. Every move comes with metadata for captures, castling, en passant and promotion, so the arm never has to know any chess. The arm Shoulder and elbow use the encoder motors from the mBot2 kit on a CyberPi, with a LEGO Technic frame plus printed parts. I tried a 3:1 reduction on the shoulder, couldn’t make it work, and direct drive turned out to be enough. Instead of inverse kinematics I recorded the motor angles for all 64 squares once (teach and playback), with the motors powered, because the arm bends differently when you move it by hand. The encoders are incremental, so the arm homes against physical stops every time it starts. Magnets and the gripper The arm carries a 12x3 mm N52 magnet that grabs a piece from about 8 mm away. Each piece has two 10x2 mm magnets, one on top for the arm and one underneath for the board, and every square has a 6x3 mm magnet below it. Neighboring pieces 32 mm away don’t move. A servo lowers the magnet, lifts the piece and releases it. Without the lift step the arm dragged pieces and knocked over the neighbors. Problems I had to solve Magnet holes modeled at exactly 10 mm were too tight, so I made them 10.1 to 10.2 mm to allow for FDM tolerance. The CyberPi doesn’t report its IP, so my Mac runs a TCP server and the CyberPi connects to it as a client. The CyberPi only sees 2.4 GHz WiFi. mBlock’s mlink kept the serial port locked until I ran pkill -f mlink. How the software is organized There are three nodes (vision, engine and arm) that talk through typed messages, ROS2 style. Each hardware part has a fake backend, so the 482 tests run without the robot, and there’s a fully simulated pipeline for testing a whole game. What’s next Tuning arm precision: re-recording the squares where the magnet doesn’t land centered and testing the robot more with people with blind people. Also im working on a demo video with the robot working coming soon...
|
1792630225.427695
|
1793235025.427695
|
|
42860
|
Devlogs+ by @armadillomike | Stardance
|
armadillomike
|
0
|
90.31
|
0
|
[]
|
[{"post_id": 81135, "ts": "202 [{"post_id": 81135, "ts": "2026-10-20T01:00:52Z", "hours": 1.2564, "text": "I fully added docker support for both the backend and frontend. Both repos have dockerfiles and the main repo has a docker-compose file and env files for both in the parent repo. Since i am going to use this from now it helps me replicate what is on the server side."}, {"post_id": 78214, "ts": "2026-10-10T00:10:45Z", "hours": 1.1578, "text": "When creating a devlog it now automatically adds time spent since the last devlog/project creation. It shows the time spent as soon as you select a project in the devlog creation menu. Also, in the project page it shows time spent."}, {"post_id": 76543, "ts": "2026-10-03T21:50:14Z", "hours": 5.5261, "text": "There is now a full system (on the backend) to add time to a devlog. The wakatime part was way easier to implement as you could just use oauth to get time spent, but hackatime your had to get both the user id and api key just to get the time spent. That being said, there are also new routes to get the time since the last devlog (or since 1900 if there is not one)."}, {"post_id": 74196, "ts": "2026-09-26T22:06:39Z", "hours": 6.7117, "text": "I have added full wakatime/hackatime support to the website. Once your Hackatime/Wakatime accounts are connected you can connect time project to Devlog+ projects. Once those are connected you can view all time logged for projects. This was one of the hardest parts to setup as when I updated what the api expected on the backend, i kept forgetting to update what the frontend was sending."}, {"post_id": 68905, "ts": "2026-09-16T00:37:46Z", "hours": 3.8442, "text": "I have made it so you can link your hackatime and wakatime account. There are buttons on your profile that redirect to oauth pages for their respective platforms. Once connected the button will change to disconnect hackatime/wakatime"}, {"post_id": 66286, "ts": "2026-09-12T01:08:10Z", "hours": 2.5411, "text": "I have unified the time tracking and added the ability to add time spent to both projects and devlogs. By unifying the time spent It is way easier to get time spent and other factors. I will soon implement all of the stuff I have worked on to the frontend."}, {"post_id": 63152, "ts": "2026-09-06T19:54:01Z", "hours": 2.5064, "text": "I have added support for wakatime. Just like the hackatime integration it only has the api routes right now."}, {"post_id": 61171, "ts": "2026-09-03T23:30:38Z", "hours": 1.8917, "text": "I have added hackatime support (kinda) I have only added it to the backend so if you somehow call the backend (i have CORS) you can link your hackatime account and view your projects"}, {"post_id": 58498, "ts": "2026-08-30T22:31:38Z", "hours": 0.8897, "text": "I have updated the nav bar to be more stylish. I found that react router has a NavLink component which is designed for navigation panels."}, {"post_id": 57755, "ts": "2026-08-30T01:09:14Z", "hours": 1.1883, "text": "I have made it easier to add a collaborator for a project. Instead of entering the user id, you now enter the users email. This is in both the add and remove collaborator forms."}, {"post_id": 56967, "ts": "2026-08-29T00:42:18Z", "hours": 0.8475, "text": "I have made some changes to the collaborator pages. Instead of user ids, it now displays their display name. I also added back buttons to most form."}, {"post_id": 56280, "ts": "2026-08-27T23:45:54Z", "hours": 0.3936, "text": "I have added a small QoL update to the unpublished devlogs page, before the devlogs publish and edit button were not part of the devlog card and you had a hard time knowing what devlog it was for, now the devlog info, publish and edit button are all grouped together."}, {"post_id": 55284, "ts": "2026-08-27T00:39:28Z", "hours": 0.9608, "text": "I added a small improvement to the create a devlog page. Instead of inputting a devlog id, you can now click on a dropdown that shows all the projects you own/collaborate on. Even though this is quite small, I think it will be a big QoL update."}, {"post_id": 54837, "ts": "2026-08-26T00:20:03Z", "hours": 0.7464, "text": "You can now view the projects a user has made! Below the users info on their page there is a section with all their projects. The backend is essentially just the get projects route but instead of /projects it is /projects/user/user_id"}, {"post_id": 53456, "ts": "2026-08-24T00:54:49Z", "hours": 3.6408, "text": "I have fully added a system to reset your password. Using the previously setup resend service I setup the ability to get sent password reset emails to your email. Inside the email there is a link to the password reset form that asks for your new password twice. To request a password reset email there is a link on the bottom of the login page that redirects to the reset page."}, {"post_id": 50706, "ts": "2026-08-20T01:11:18Z", "hours": 2.2603, "text": "I setup resend for email sending. I chose to use a subdomain (email.devlogs.plus) instead of the base domain because if its reputation is lowered it wont affect the base domain, only the subdomain. I tested it out with some help from my little brother."}, {"post_id": 48594, "ts": "2026-08-17T01:34:45Z", "hours": 1.3717, "text": "I have added a way to change your password. There is a new button on your user page that redirects to a password change form. The form requires your old password and the new password."}, {"post_id": 48485, "ts": "2026-08-16T21:09:45Z", "hours": 0.3103, "text": "I have setup an actual domain for Devlogs+ instead of the provided render domain ( https://devlogs-plus-frontend.onrender.com ) I have bought https://devlogs.plus . Nothing in the codebase itself has really changed except for some simple bug changes."}, {"post_id": 47829, "ts": "2026-08-16T01:34:33Z", "hours": 1.3636, "text": "I added page titles to all (it think) pages across Devlogs+. And by everything I mean every component that renders a full page. I also added a favicon to look more ✨professional✨"}, {"post_id": 47720, "ts": "2026-08-15T20:22:50Z", "hours": 0.7208, "text": "I fixed a couple small bugs that stem from deleting users. The first was one where the user card was not showing for deleted users which was kinda easy to fix. The second one was on the backend where the user id 0 (which is for deleted users) was not getting made. It was like that because the deployed backend uses Gunicorn instead of the Flask dev server (which I was using) uses a different way to start up the server."}, {"post_id": 47242, "ts": "2026-08-15T01:13:46Z", "hours": 1.9656, "text": "I have added the ability for users to delete their accounts. Deleting ones account removes their account, sets the user id for projects and devlogs to 0, and removes them as a collaborator"}, {"post_id": 46642, "ts": "2026-08-14T01:30:55Z", "hours": 0.6589, "text": "I added another OAuth option, HackClub! a new user can now sign up with their HackClub account (if they have one) or login (if the emails match) I will soon make it so you can link accounts to existing accounts even if the email does not match"}, {"post_id": 46570, "ts": "2026-08-13T21:57:34Z", "hours": 2.3122, "text": "I have implemented a system to login/register with Github. I chose to use Authlib for the OAuth implementation beacuse if I want to (hint hint) I can easily add other OAuth systems."}, {"post_id": 45965, "ts": "2026-08-12T19:48:34Z", "hours": 2.5303, "text": "I added a system to upload avatars and add them to your user page. It currently uses hackclub cdn to upload the files. I have also added a default avatar for anybody that has not set an avatar. Avatar images have been added to basically everything that uses a user. User page User card Your user page (/me) Edit page On the edit page it is instead used a preview window."}, {"post_id": 45407, "ts": "2026-08-11T20:40:10Z", "hours": 1.1653, "text": "I finally added a feed for devlogs. It works by using the route provided by the backend, getting the devlog id, using getSingleProject to get the rest of the details and then puts it all in a DevlogCard. The feed shows all the devlogs posted in order of recency across all projects (As long as they are published)"}, {"post_id": 44865, "ts": "2026-08-10T21:59:46Z", "hours": 1.4372, "text": "I added a couple things A seperate page for each user A card for each user The card for each user displays the display name and user id The user page shows everything (including email) The user card shows up on the individual pages for devlogs and projects"}, {"post_id": 44344, "ts": "2026-08-10T01:21:59Z", "hours": 1.4228, "text": "I added 2 things to the frontend a page to view your own info a page to edit your info. On the backend i added a bit more then 2 Get a users info by email Get a users info by user id Edit your own user info I will soon make it so you can view other peoples profiles (thats what the backend stuff is for)"}, {"post_id": 44217, "ts": "2026-08-09T20:39:48Z", "hours": 1.9647, "text": "I did a bit more styling fixes and also added field validation The field validation i added was to the login and register pages to only allow valid emails, and also to add collaborator and make devlog page to only allow numbers for things like project id and user id"}, {"post_id": 43570, "ts": "2026-08-08T21:58:59Z", "hours": 1.2872, "text": "More styling I styling the link on the navbar, Styled the project cards to match the devlogs card, Added a border to both of the devlog and project cards, Styled the markdown renderer, And fixed some styling issues like some buttons not being the new <Button> component"}, {"post_id": 43489, "ts": "2026-08-08T19:48:09Z", "hours": 2.3425, "text": "I started with some basic styling for the site. The color theme I choose to use was nord. I choose it because I like the blue. The styles that I did was basic site wide styling with the background and font. The font I chose was Stack Sans Text. I have also styled the input, textarea, and buttons components."}, {"post_id": 42368, "ts": "2026-08-07T01:40:11Z", "hours": 1.1581, "text": "I added the ability to remove collaborators from a project. There is a button on the project page blah blah blah New page to remove collaborators blah blah blah While making this I found a small bug because I forgot to put {} around 2 variables which broke the entire page and I didn’t spot it until 20 mins later"}, {"post_id": 42262, "ts": "2026-08-06T21:51:36Z", "hours": 1.8364, "text": "I added a way for everyone to view the collaborators for a project. Once again, there is a button on the project page that redirects to a separate page. On the collaborator page it shows the owner of the project and all the collaborator user ids."}, {"post_id": 41683, "ts": "2026-08-06T01:51:51Z", "hours": 1.4222, "text": "I added a way to add collaborators to a project. There is a button on the project page that redirects you to the page to add collaborators by their user id. Right now collaborators are just a fancy title but soon they will be able to post devlogs. You can view your own user id from the home page now."}, {"post_id": 40991, "ts": "2026-08-04T21:20:48Z", "hours": 0.3333, "text": "I just added a very simple feature. There is now a button on the unpublished devlogs page that brings you to the edit page. You could still edit devlogs that were unpublished but now it is easier to edit them."}, {"post_id": 40951, "ts": "2026-08-04T20:14:58Z", "hours": 1.2297, "text": "I added a way for you to unpublish your devlogs. On the devlog page if you are the owner. Clicking the button redirects you to a page where you can unpublish it. When you unpublish it (without and error) it redirects you backwards. After that you can republish it from the unpublished devlog page."}, {"post_id": 40486, "ts": "2026-08-04T01:37:14Z", "hours": 1.3139, "text": "I made it so you can now edit devlogs You can edit a devlog you made by the url /projects/projectid/devlogs/devlogid/edit You can change the title and the markdown body. There is also a button on the devlog page the shows up if you are the owner."}, {"post_id": 39810, "ts": "2026-08-03T01:31:45Z", "hours": 1.2967, "text": "I added a way to view a full devlog on its on specific page. The page has the devlogs title, body, published at, project id, and devlog id. You can also get to this page by clicking on the individual devlogs on the project page"}, {"post_id": 39213, "ts": "2026-08-02T01:08:28Z", "hours": 0.5239, "text": "I made it so you can add multiple lines to the body for projects and devlogs by changing the to I also added a markdown renderer to render the markdown correctly."}, {"post_id": 39165, "ts": "2026-08-01T22:13:48Z", "hours": 23.975, "text": "Bringing over time I am bringing over all my time that was spent on unfold as it ended $ next to it means backend only route Features Auth Login Register Logout View your info $ Projects Create a project View all projects Get singular project Edit a project Delete a project Add a collaborator to the project $ Remove a collaborator $ Devlogs Get all devlogs for a project Create a devlog Get singular devlog $ Edit a devlog $ Publish a devlog Unpublish a devlog $ Get your unpublished devlogs"}]...
|
Title: Devlogs+ by @armadillomike | Stardance
Dev Title: Devlogs+ by @armadillomike | Stardance
Devlogs:
Bringing over time I am bringing over all my time that was spent on unfold as it ended $ next to it means backend only route Features Auth Login Register Logout View your info $ Projects Create a project View all projects Get singular project Edit a project Delete a project Add a collaborator to the project $ Remove a collaborator $ Devlogs Get all devlogs for a project Create a devlog Get singular devlog $ Edit a devlog $ Publish a devlog Unpublish a devlog $ Get your unpublished devlogs
I made it so you can add multiple lines to the body for projects and devlogs by changing the to I also added a markdown renderer to render the markdown correctly.
I added a way to view a full devlog on its on specific page. The page has the devlogs title, body, published at, project id, and devlog id. You can also get to this page by clicking on the individual devlogs on the project page
I made it so you can now edit devlogs You can edit a devlog you made by the url /projects/projectid/devlogs/devlogid/edit You can change the title and the markdown body. There is also a button on the devlog page the shows up if you are the owner.
I added a way for you to unpublish your devlogs. On the devlog page if you are the owner. Clicking the button redirects you to a page where you can unpublish it. When you unpublish it (without and error) it redirects you backwards. After that you can republish it from the unpublished devlog page.
I just added a very simple feature. There is now a button on the unpublished devlogs page that brings you to the edit page. You could still edit devlogs that were unpublished but now it is easier to edit them.
I added a way to add collaborators to a project. There is a button on the project page that redirects you to the page to add collaborators by their user id. Right now collaborators are just a fancy title but soon they will be able to post devlogs. You can view your own user id from the home page now.
I added a way for everyone to view the collaborators for a project. Once again, there is a button on the project page that redirects to a separate page. On the collaborator page it shows the owner of the project and all the collaborator user ids.
I added the ability to remove collaborators from a project. There is a button on the project page blah blah blah New page to remove collaborators blah blah blah While making this I found a small bug because I forgot to put {} around 2 variables which broke the entire page and I didn’t spot it until 20 mins later
I started with some basic styling for the site. The color theme I choose to use was nord. I choose it because I like the blue. The styles that I did was basic site wide styling with the background and font. The font I chose was Stack Sans Text. I have also styled the input, textarea, and buttons components.
More styling I styling the link on the navbar, Styled the project cards to match the devlogs card, Added a border to both of the devlog and project cards, Styled the markdown renderer, And fixed some styling issues like some buttons not being the new <Button> component
I did a bit more styling fixes and also added field validation The field validation i added was to the login and register pages to only allow valid emails, and also to add collaborator and make devlog page to only allow numbers for things like project id and user id
I added 2 things to the frontend a page to view your own info a page to edit your info. On the backend i added a bit more then 2 Get a users info by email Get a users info by user id Edit your own user info I will soon make it so you can view other peoples profiles (thats what the backend stuff is for)
I added a couple things A seperate page for each user A card for each user The card for each user displays the display name and user id The user page shows everything (including email) The user card shows up on the individual pages for devlogs and projects
I finally added a feed for devlogs. It works by using the route provided by the backend, getting the devlog id, using getSingleProject to get the rest of the details and then puts it all in a DevlogCard. The feed shows all the devlogs posted in order of recency across all projects (As long as they are published)
I added a system to upload avatars and add them to your user page. It currently uses hackclub cdn to upload the files. I have also added a default avatar for anybody that has not set an avatar. Avatar images have been added to basically everything that uses a user. User page User card Your user page (/me) Edit page On the edit page it is instead used a preview window.
I have implemented a system to login/register with Github. I chose to use Authlib for the OAuth implementation beacuse if I want to (hint hint) I can easily add other OAuth systems.
I added another OAuth option, HackClub! a new user can now sign up with their HackClub account (if they have one) or login (if the emails match) I will soon make it so you can link accounts to existing accounts even if the email does not match
I have added the ability for users to delete their accounts. Deleting ones account removes their account, sets the user id for projects and devlogs to 0, and removes them as a collaborator
I fixed a couple small bugs that stem from deleting users. The first was one where the user card was not showing for deleted users which was kinda easy to fix. The second one was on the backend where the user id 0 (which is for deleted users) was not getting made. It was like that because the deployed backend uses Gunicorn instead of the Flask dev server (which I was using) uses a different way to start up the server.
I added page titles to all (it think) pages across Devlogs+. And by everything I mean every component that renders a full page. I also added a favicon to look more ✨professional✨
I have setup an actual domain for Devlogs+ instead of the provided render domain ( https://devlogs-plus-frontend.onrender.com ) I have bought https://devlogs.plus . Nothing in the codebase itself has really changed except for some simple bug changes.
I have added a way to change your password. There is a new button on your user page that redirects to a password change form. The form requires your old password and the new password.
I setup resend for email sending. I chose to use a subdomain (email.devlogs.plus) instead of the base domain because if its reputation is lowered it wont affect the base domain, only the subdomain. I tested it out with some help from my little brother.
I have fully added a system to reset your password. Using the previously setup resend service I setup the ability to get sent password reset emails to your email. Inside the email there is a link to the password reset form that asks for your new password twice. To request a password reset email there is a link on the bottom of the login page that redirects to the reset page.
You can now view the projects a user has made! Below the users info on their page there is a section with all their projects. The backend is essentially just the get projects route but instead of /projects it is /projects/user/user_id
I added a small improvement to the create a devlog page. Instead of inputting a devlog id, you can now click on a dropdown that shows all the projects you own/collaborate on. Even though this is quite small, I think it will be a big QoL update.
I have added a small QoL update to the unpublished devlogs page, before the devlogs publish and edit button were not part of the devlog card and you had a hard time knowing what devlog it was for, now the devlog info, publish and edit button are all grouped together.
I have made some changes to the collaborator pages. Instead of user ids, it now displays their display name. I also added back buttons to most form.
I have made it easier to add a collaborator for a project. Instead of entering the user id, you now enter the users email. This is in both the add and remove collaborator forms.
I have updated the nav bar to be more stylish. I found that react router has a NavLink component which is designed for navigation panels.
I have added hackatime support (kinda) I have only added it to the backend so if you somehow call the backend (i have CORS) you can link your hackatime account and view your projects
I have added support for wakatime. Just like the hackatime integration it only has the api routes right now.
I have unified the time tracking and added the ability to add time spent to both projects and devlogs. By unifying the time spent It is way easier to get time spent and other factors. I will soon implement all of the stuff I have worked on to the frontend.
I have made it so you can link your hackatime and wakatime account. There are buttons on your profile that redirect to oauth pages for their respective platforms. Once connected the button will change to disconnect hackatime/wakatime
I have added full wakatime/hackatime support to the website. Once your Hackatime/Wakatime accounts are connected you can connect time project to Devlog+ projects. Once those are connected you can view all time logged for projects. This was one of the hardest parts to setup as when I updated what the api expected on the backend, i kept forgetting to update what the frontend was sending.
There is now a full system (on the backend) to add time to a devlog. The wakatime part was way easier to implement as you could just use oauth to get time spent, but hackatime your had to get both the user id and api key just to get the time spent. That being said, there are also new routes to get the time since the last devlog (or since 1900 if there is not one).
When creating a devlog it now automatically adds time spent since the last devlog/project creation. It shows the time spent as soon as you select a project in the devlog creation menu. Also, in the project page it shows time spent.
I fully added docker support for both the backend and frontend. Both repos have dockerfiles and the main repo has a docker-compose file and env files for both in the parent repo. Since i am going to use this from now it helps me replicate what is on the server side....
|
1792525961.1655416
|
1793130761.1655416
|
|
70564
|
Orbit by @amirmzte13 | Stardance
|
amirmzte13
|
0
|
10.31
|
0
|
[]
|
[{"post_id": 81137, "ts": "202 [{"post_id": 81137, "ts": "2026-10-20T01:04:53Z", "hours": 10.3089, "text": "Currently working on organizing the folders and linking this to vercel."}]...
|
Title: Orbit by @amirmzte13 | Stardance
Devlogs:
Title: Orbit by @amirmzte13 | Stardance
Devlogs:
Currently working on organizing the folders and linking this to vercel....
|
1793098104.8940303
|
1793702904.8940303
|
|
41865
|
Dungeon climber by @SiddhantVerma_04 | Stardance
|
SiddhantVerma_04
|
1
|
33.41
|
399
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-20T14:28:37Z", "hours": 20.0, "multiplier": 19.54, "payout": 399, "blessing": "neutral", "text": "Dungeon Climber A 2d platformer made in Godot 4 about a knight stuck in a dungeon. This is my game about a knight stuck in a dungeon trying to escape while opening chests along the way and not dying. This is my first Godot game that i made after a long time and it took me a while to learn Godot’s language and system, but I came back to it because I love creating games and I want to make many more in the future. You can play it on it’s itch.io page by clicking the button below. Please give me some feedback for future projects. Thank you for your time!", "repo": "https://github.com/siddhantverma04/dungeon-climber", "demo": "https://hacr7.itch.io/dungeon-climber"}]...
|
[{"post_id": 81138, "ts": "202 [{"post_id": 81138, "ts": "2026-10-20T01:20:13Z", "hours": 3.1644, "text": "Devlog 9 Finished level 2 I added a lot of new features since the last devlog but the most prominent maybe would be dialogue! I basically created a villager that you can talk to just to give you some instruction on what to do. Other than that I added more to the actual level and added another fox near the end. And I ended it with a castle that you have to enter."}, {"post_id": 72052, "ts": "2026-09-22T02:44:30Z", "hours": 5.7467, "text": "Devlog 8 Big update Continued building the game, and started by adding another level. This level will be above ground, with new enemies and features. So far I have set it up for building, as well as added a fox, that took way too much time to code its death, and animations. I will also add other animals soon. I finished up the enemies in the first level too. But currently haven’t added any more sound effects or music for the new stuff."}, {"post_id": 68366, "ts": "2026-09-15T00:46:53Z", "hours": 4.4953, "text": "Devlog 7 Added simple enemies. Shipped a while ago but decided to continue on the game. I chose to first start making some new enemies. It was easy until I had to code the animations and health loss, so a lot of my time went into that. But I pretty much got it to work. I still need to code the death of the enemy though."}, {"post_id": 51005, "ts": "2026-08-20T14:25:21Z", "hours": 1.0708, "text": "Devlog 6 Finished the game! Made some tweaks and then exported the game. I then made my own page on itch.io and uploaded the game there. Dungeon Climber is now live so go check it out!"}, {"post_id": 49902, "ts": "2026-08-18T21:19:03Z", "hours": 2.9467, "text": "Devlog 5 Added a win screen and a game over screen I created a simple win and lose screen with a restart and quit option each. It took a long time to make the win screen animation, but the music for both of them was really easy. I’m fairly done with the game, and just need to make some tweaks and fixes until I’m ready to ship."}, {"post_id": 48341, "ts": "2026-08-16T17:32:01Z", "hours": 4.0333, "text": "Devlog 4 Added music and sound effects. Put some background music for the main menu and level, and had to figure out how to make transitions between them using tweens. Also made some sound effects for stuff like opening chests and taking damage."}, {"post_id": 46430, "ts": "2026-08-13T17:04:46Z", "hours": 4.4311, "text": "Devlog 3 Added a health and points system. Created a simple health system with 3 lives that resets the level when you lose all of them. Took a long time for debugging and fixing the code to make the player die properly but I was finally able to make it work. Along with that I also made a point system which just counts the amount of chests you open, which was easy enough. Also made some changes to the main menu animations."}, {"post_id": 44923, "ts": "2026-08-11T00:04:59Z", "hours": 3.8533, "text": "Devlog 2 Finished level building, and added a main menu. It took about an hour just to find and extend the image for the animation, but actually making the animation was relatively easy. I also made sure the character can’t move after going in the exit door."}, {"post_id": 43004, "ts": "2026-08-08T01:06:07Z", "hours": 4.0833, "text": "Devlog 1/Catch up: Over the summer I was working on a 2d platformer in Godot about a knight that’s stuck in a dungeon. However, I just turned 13 so I couldn’t track those hours or post any updates. So this will serve as a “catch up” of everything I did in that time. I also followed some Coco Code tutorials along the way but mainly did it myself and did my own things. I have separated everything I did into 4 parts, with the last being what the currently logged hours are for. Part 1: I found and imported some asset packs (sprites, backgrounds, tilesheets) into the project. Created a tilemap and background(also added physics collisions). Started building some of the game. Added a CharacterBody2d, and its AnimatedSprite2d and collision shape. Also added the animations for the character. Wrote the core movement for the character set up player input mappings for wasd and arrow keys. Part 2: Added a Camera2d to the player so that the camera follows the player. Created ladders using the tilemap and coded their movement. Made moving and static platforms using an AnimatableBody2d and an AnimationPlayer(for the moving ones). Also added chests that you can find throughout the level and open(they currently don’t give or do anything). Part 3: Added traps(spikes), that reset the level. Continued building the level. Added an exit door and made its animation. Added an animation for ladder climbing."}]...
|
Title: Dungeon climber by @SiddhantVerma_04 | Star Title: Dungeon climber by @SiddhantVerma_04 | Stardance
Devlogs:
Devlog 1/Catch up: Over the summer I was working on a 2d platformer in Godot about a knight that’s stuck in a dungeon. However, I just turned 13 so I couldn’t track those hours or post any updates. So this will serve as a “catch up” of everything I did in that time. I also followed some Coco Code tutorials along the way but mainly did it myself and did my own things. I have separated everything I did into 4 parts, with the last being what the currently logged hours are for. Part 1: I found and imported some asset packs (sprites, backgrounds, tilesheets) into the project. Created a tilemap and background(also added physics collisions). Started building some of the game. Added a CharacterBody2d, and its AnimatedSprite2d and collision shape. Also added the animations for the character. Wrote the core movement for the character set up player input mappings for wasd and arrow keys. Part 2: Added a Camera2d to the player so that the camera follows the player. Created ladders using the tilemap and coded their movement. Made moving and static platforms using an AnimatableBody2d and an AnimationPlayer(for the moving ones). Also added chests that you can find throughout the level and open(they currently don’t give or do anything). Part 3: Added traps(spikes), that reset the level. Continued building the level. Added an exit door and made its animation. Added an animation for ladder climbing.
Devlog 2 Finished level building, and added a main menu. It took about an hour just to find and extend the image for the animation, but actually making the animation was relatively easy. I also made sure the character can’t move after going in the exit door.
Devlog 3 Added a health and points system. Created a simple health system with 3 lives that resets the level when you lose all of them. Took a long time for debugging and fixing the code to make the player die properly but I was finally able to make it work. Along with that I also made a point system which just counts the amount of chests you open, which was easy enough. Also made some changes to the main menu animations.
Devlog 4 Added music and sound effects. Put some background music for the main menu and level, and had to figure out how to make transitions between them using tweens. Also made some sound effects for stuff like opening chests and taking damage.
Devlog 5 Added a win screen and a game over screen I created a simple win and lose screen with a restart and quit option each. It took a long time to make the win screen animation, but the music for both of them was really easy. I’m fairly done with the game, and just need to make some tweaks and fixes until I’m ready to ship.
Devlog 6 Finished the game! Made some tweaks and then exported the game. I then made my own page on itch.io and uploaded the game there. Dungeon Climber is now live so go check it out!
Devlog 7 Added simple enemies. Shipped a while ago but decided to continue on the game. I chose to first start making some new enemies. It was easy until I had to code the animations and health loss, so a lot of my time went into that. But I pretty much got it to work. I still need to code the death of the enemy though.
Devlog 8 Big update Continued building the game, and started by adding another level. This level will be above ground, with new enemies and features. So far I have set it up for building, as well as added a fox, that took way too much time to code its death, and animations. I will also add other animals soon. I finished up the enemies in the first level too. But currently haven’t added any more sound effects or music for the new stuff.
Devlog 9 Finished level 2 I added a lot of new features since the last devlog but the most prominent maybe would be dialogue! I basically created a villager that you can talk to just to give you some instruction on what to do. Other than that I added more to the actual level and added another fox near the end. And I ended it with a castle that you have to enter.
Ships:
Dungeon Climber A 2d platformer made in Godot 4 about a knight stuck in a dungeon. This is my game about a knight stuck in a dungeon trying to escape while opening chests along the way and not dying. This is my first Godot game that i made after a long time and it took me a while to learn Godot’s language and system, but I came back to it because I love creating games and I want to make many more in the future. You can play it on it’s itch.io page by clicking the button below. Please give me some feedback for future projects. Thank you for your time!...
|
1793127068.326554
|
1793213468.326554
|
|
70073
|
last surprise project by @amateur_tech_guy | Stard last surprise project by @amateur_tech_guy | Stardance...
|
amateur_tech_guy
|
0
|
0.55
|
0
|
[]
|
[{"post_id": 81139, "ts": "202 [{"post_id": 81139, "ts": "2026-10-20T01:21:44Z", "hours": 0.5511, "text": "devlog #1: working on a surprise new project! I wont tell anyone what it is yet, try to guess, heres a hint"}]...
|
Title: last surprise project by @amateur_tech_guy Title: last surprise project by @amateur_tech_guy | Stardance
Devlogs:
devlog #1: working on a surprise new project! I wont tell anyone what it is yet, try to guess, heres a hint...
|
1792958012.9325871
|
1793562812.9325871
|
|
4994
|
Tamagochi pet by @S0l4Ce | Stardance
|
S0l4Ce
|
1
|
52.03
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-20T05:08:22Z", "hours": 45.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a tamagotchi pet (i am aware that throughout the project, the spelling of it has been inconsistent) But anyway, what i found most challenging was having to look through the loop constantly making adjustments based off minor errors during each test run and incorrect wiring making me feel like i had the code wrong. I am proud that I learned surprisingly a lot. The screenshot is merely just part of it and you should check it out yourself! both the source for the software and hardware is in there. The latest software build is in a separate branch and you may need to scope around for the latest hardware build. PLEASE note that all of the hardware additions - if you truly want to build it yourself, is pushing the limits of the esp32 so please run it while using a powerful cable.", "repo": "https://github.com/mootonlee/tamagotchi-", "demo": ""}]...
|
[{"post_id": 81143, "ts": "202 [{"post_id": 81143, "ts": "2026-10-20T02:14:13Z", "hours": 1.0578, "text": "spent this hour troubleshooting and figuring out how to add wires. was super unsucessful and wasted my time. im pretty annoyed"}, {"post_id": 80851, "ts": "2026-10-19T00:50:55Z", "hours": 2.3, "text": "Finished adding modules like the LEDs, resistors, etc. All i need now is the wiring which i heard is tedious"}, {"post_id": 80585, "ts": "2026-10-18T07:04:57Z", "hours": 1.4167, "text": "Im very proud of my work! i finished up the screen, fixed misalignments, ensured precision, and in the end, everything fit perfectly!"}, {"post_id": 80513, "ts": "2026-10-17T22:48:45Z", "hours": 2.26, "text": "got mad countless times. Im doing my CAD for my project because youll now get permanently rejected if you miss it and i never knew. Im making the screen myself because i cant find it online. Below is a picture of how its assembled so far, and i would post the part im making right now but this just looks better. Also, does the CAD have to be fully accurate? ive never done a CAD before so parts i make myself may look off but ill try my best to make the measurements right."}, {"post_id": 70980, "ts": "2026-09-20T04:48:45Z", "hours": 6.0014, "text": "finally finished the 2nd personality. will be shipping my project. only thing left to do is fix bugs (i already scanned software and hardware for bugs. though the code seems somewhat contradictory to itself, it still works but please report bugs under this one’s comment and check out my submission and the demo video!"}, {"post_id": 63407, "ts": "2026-09-07T07:10:06Z", "hours": 1.4625, "text": "im starting work on the radiobuttons for interchangable personality to wrap up the project. im using placeholders so the face looks red if the radiobuttons are selected so it would look unpleasant to see but yeah"}, {"post_id": 59986, "ts": "2026-09-02T02:11:14Z", "hours": 2.4203, "text": "Got back on track, finally! It now gets visibly dim below 50 value on light, and dark below 25, along with squint and sleep. Im now going to begin working on the other expressions after I finish adding the dim to smile and alone faces. This thing is ending soon so idk if i will be able to add the computer control functions as promised :( I also switched to cachyos so Idk how that would go either. Check out the hardware version on my page though! its finished"}, {"post_id": 52633, "ts": "2026-08-22T21:16:19Z", "hours": 0.5211, "text": "My windows OS broke, not sure how, so im running on my second SSD and my most recent work has been erased! (software version) random thumbnail ig but im gonna be re-doing whatever has been erased.."}, {"post_id": 41108, "ts": "2026-08-05T03:07:48Z", "hours": 3.4297, "text": "finally added a sleep system, dimming system, and a fully fixed and functional lonely system. when lights are at or below 50, the lights will go dim, and below 25, they will go even dimmer, and it will sleep (software) I will the face variants next, and then actual interactive computer controls. shy and moody are still not ready yet"}, {"post_id": 34593, "ts": "2026-07-25T13:29:57Z", "hours": 2.5967, "text": "added lonely, smile, and neutral, also added placeholders for the soon to be added personalities and a brightness slider. Both are unfunctional and i only have the 3 faces for now. go check out my hardware version, its fully functional"}, {"post_id": 32247, "ts": "2026-07-21T09:09:49Z", "hours": 1.2072, "text": "working on a software version of my project 🔥 I main micropython but I’m adjusting to python for this and learning the different ways things are written, and figuring out how to make faces. Can anyone tell me if theres a designer that gives you the code when you draw something on a canvas? similar to lopaka?? The software version is projected to have more features for computer control than the hardware version. After finishing the faces and overall logic, I will add the additional side controls for it, like light and stuff"}, {"post_id": 32144, "ts": "2026-07-21T03:23:42Z", "hours": 9.8794, "text": "built an extension for the pet. It connects to the pet using gnd and 4 labeled gpio pins, though the 4th one connects to 0 and not 40. It works somewhat like a stream deck; It opens 2 games, 2 code editors, a browser, and shuts off or closes tabs on my computer without needing special permissions, it is built for windows though. Most of the hours logged came from trial and error. Most of the time the buttons wouldnt register, spam the same commands, double clicks wouldnt register, and it was a mess for hours. did some bugfixes involving screen bugs during personality swaps, and the pet “forgetting” its personality. please suggest additional ideas."}, {"post_id": 30476, "ts": "2026-07-18T02:37:34Z", "hours": 1.7375, "text": "Rewired to remove clutter. Back isn’t looking too good but the front is, when I run out of ideas ill probably build a shell for it please make recommendations"}, {"post_id": 30124, "ts": "2026-07-17T13:22:42Z", "hours": 2.4481, "text": "Added another personality, shy. added “cores” that determine the personality when plugged in, red for moody and blue for shy. unplug for normal. The shy personality features new unique faces. led colors and shaken face remain same"}, {"post_id": 29977, "ts": "2026-07-17T06:07:54Z", "hours": 1.6644, "text": "Ignore devlog: Tried making online demo but i pressed a button and all my tabs refreshed all at once and reset my work. Im publishing the devlog because i still did the work and i dont want it to go to waste (IGNORE THIS DEVLOG)"}, {"post_id": 29812, "ts": "2026-07-16T23:08:57Z", "hours": 3.2333, "text": "Added extra personality. If you plug a red LED in, it will get a more of a moody personality. It will look angry, sleep angry, and will usually just be angry (shaken face does not change.) unplugging the red LED will make it instantly revert to default personality let me know other interchangeable personalities I should add, or other software and hardware suggestions. Thanks."}, {"post_id": 28868, "ts": "2026-07-15T13:02:50Z", "hours": 2.6472, "text": "Added a gyroscope so the pet can become dizzy when shook. It features a red backlight, and remains dizzy for about 5 seconds. It was really a 20-30 minute setup after learning how to code and use one, and installing the libraries, but that extra addition turned into hours of additional troubleshooting since I was unfamiliar with the hardware. I eventually got it working after plenty of trial and error, and the real issue was just a couple lines of code. I’m unfortunately not getting much views, which is discouraging, but if you do come across this and decide to click on it, please suggest something in the comments. Thanks."}, {"post_id": 28151, "ts": "2026-07-14T08:19:06Z", "hours": 0.6217, "text": "Added status lights; finishing off full basic functionality for the pet. any additional features would be improvements, hardware additions, and wiring. full explanation of functions below: The “pet” is a TFT resistive touchscreen. Its face, as you can see, is a simple white and black pixelated look. 4 functions (for now): lonely - after 30 seconds of no interaction, after waking up or not being pet, it will become lonely, which is a sad face of course. The backlight glows a gloomy blue, slightly purple. neutral - base face, the pet is neutral when it isn’t lonely, had just woken up, and had recently been pet. the 3 other moods can occur when it is neutral. the backlight is white. sleeping - when the ambient light is low enough the pet will sleep. It cannot be disturbed and cannot become lonely until woken up. This is what i personally thought was a nice addition to the pet and would bring more realism and life to the pet. This is done by having a photocell near the face for most light accuracy. the backlight features a light purple blue. happy - when you pet it (or interact with the screen), it will smile. the blush being blue and not red was both intentional and unintentional feature. The color system is inverted same with the screen rotation. I did not know how to correct it but i felt the blue looked different and I kinda liked it so I didn’t spend extra time troubleshooting. the backlight features a bright hot pink color. PLEASE add any suggestions and I will likely consider, like adding a thermistor, weather, USB OTG, etc. When i feel like it, I may add a USB mode where it can do things on my computer when plugged in, like opening an app or powering off my computer. (the 35 minutes logged was for fixing the code and adding the lights. Not the full code itself.)"}, {"post_id": 27970, "ts": "2026-07-13T22:34:39Z", "hours": 3.7561, "text": "added functionality to the pet and added made a separate smaller one. It now has multiple moods with the ability to sleep when lights are dimmed enough."}, {"post_id": 16541, "ts": "2026-06-26T22:02:40Z", "hours": 1.0939, "text": "working on the wiring of the tomogachi pet n stuff no coding yet has a touchscreen now"}]...
|
Title: Tamagochi pet by @S0l4Ce | Stardance
Devlo Title: Tamagochi pet by @S0l4Ce | Stardance
Devlogs:
working on the wiring of the tomogachi pet n stuff no coding yet has a touchscreen now
added functionality to the pet and added made a separate smaller one. It now has multiple moods with the ability to sleep when lights are dimmed enough.
Added status lights; finishing off full basic functionality for the pet. any additional features would be improvements, hardware additions, and wiring. full explanation of functions below: The “pet” is a TFT resistive touchscreen. Its face, as you can see, is a simple white and black pixelated look. 4 functions (for now): lonely - after 30 seconds of no interaction, after waking up or not being pet, it will become lonely, which is a sad face of course. The backlight glows a gloomy blue, slightly purple. neutral - base face, the pet is neutral when it isn’t lonely, had just woken up, and had recently been pet. the 3 other moods can occur when it is neutral. the backlight is white. sleeping - when the ambient light is low enough the pet will sleep. It cannot be disturbed and cannot become lonely until woken up. This is what i personally thought was a nice addition to the pet and would bring more realism and life to the pet. This is done by having a photocell near the face for most light accuracy. the backlight features a light purple blue. happy - when you pet it (or interact with the screen), it will smile. the blush being blue and not red was both intentional and unintentional feature. The color system is inverted same with the screen rotation. I did not know how to correct it but i felt the blue looked different and I kinda liked it so I didn’t spend extra time troubleshooting. the backlight features a bright hot pink color. PLEASE add any suggestions and I will likely consider, like adding a thermistor, weather, USB OTG, etc. When i feel like it, I may add a USB mode where it can do things on my computer when plugged in, like opening an app or powering off my computer. (the 35 minutes logged was for fixing the code and adding the lights. Not the full code itself.)
Added a gyroscope so the pet can become dizzy when shook. It features a red backlight, and remains dizzy for about 5 seconds. It was really a 20-30 minute setup after learning how to code and use one, and installing the libraries, but that extra addition turned into hours of additional troubleshooting since I was unfamiliar with the hardware. I eventually got it working after plenty of trial and error, and the real issue was just a couple lines of code. I’m unfortunately not getting much views, which is discouraging, but if you do come across this and decide to click on it, please suggest something in the comments. Thanks.
Added extra personality. If you plug a red LED in, it will get a more of a moody personality. It will look angry, sleep angry, and will usually just be angry (shaken face does not change.) unplugging the red LED will make it instantly revert to default personality let me know other interchangeable personalities I should add, or other software and hardware suggestions. Thanks.
Ignore devlog: Tried making online demo but i pressed a button and all my tabs refreshed all at once and reset my work. Im publishing the devlog because i still did the work and i dont want it to go to waste (IGNORE THIS DEVLOG)
Added another personality, shy. added “cores” that determine the personality when plugged in, red for moody and blue for shy. unplug for normal. The shy personality features new unique faces. led colors and shaken face remain same
Rewired to remove clutter. Back isn’t looking too good but the front is, when I run out of ideas ill probably build a shell for it please make recommendations
built an extension for the pet. It connects to the pet using gnd and 4 labeled gpio pins, though the 4th one connects to 0 and not 40. It works somewhat like a stream deck; It opens 2 games, 2 code editors, a browser, and shuts off or closes tabs on my computer without needing special permissions, it is built for windows though. Most of the hours logged came from trial and error. Most of the time the buttons wouldnt register, spam the same commands, double clicks wouldnt register, and it was a mess for hours. did some bugfixes involving screen bugs during personality swaps, and the pet “forgetting” its personality. please suggest additional ideas.
working on a software version of my project 🔥 I main micropython but I’m adjusting to python for this and learning the different ways things are written, and figuring out how to make faces. Can anyone tell me if theres a designer that gives you the code when you draw something on a canvas? similar to lopaka?? The software version is projected to have more features for computer control than the hardware version. After finishing the faces and overall logic, I will add the additional side controls for it, like light and stuff
added lonely, smile, and neutral, also added placeholders for the soon to be added personalities and a brightness slider. Both are unfunctional and i only have the 3 faces for now. go check out my hardware version, its fully functional
finally added a sleep system, dimming system, and a fully fixed and functional lonely system. when lights are at or below 50, the lights will go dim, and below 25, they will go even dimmer, and it will sleep (software) I will the face variants next, and then actual interactive computer controls. shy and moody are still not ready yet
My windows OS broke, not sure how, so im running on my second SSD and my most recent work has been erased! (software version) random thumbnail ig but im gonna be re-doing whatever has been erased..
Got back on track, finally! It now gets visibly dim below 50 value on light, and dark below 25, along with squint and sleep. Im now going to begin working on the other expressions after I finish adding the dim to smile and alone faces. This thing is ending soon so idk if i will be able to add the computer control functions as promised :( I also switched to cachyos so Idk how that would go either. Check out the hardware version on my page though! its finished
im starting work on the radiobuttons for interchangable personality to wrap up the project. im using placeholders so the face looks red if the radiobuttons are selected so it would look unpleasant to see but yeah
finally finished the 2nd personality. will be shipping my project. only thing left to do is fix bugs (i already scanned software and hardware for bugs. though the code seems somewhat contradictory to itself, it still works but please report bugs under this one’s comment and check out my submission and the demo video!
got mad countless times. Im doing my CAD for my project because youll now get permanently rejected if you miss it and i never knew. Im making the screen myself because i cant find it online. Below is a picture of how its assembled so far, and i would post the part im making right now but this just looks better. Also, does the CAD have to be fully accurate? ive never done a CAD before so parts i make myself may look off but ill try my best to make the measurements right.
Im very proud of my work! i finished up the screen, fixed misalignments, ensured precision, and in the end, everything fit perfectly!
Finished adding modules like the LEDs, resistors, etc. All i need now is the wiring which i heard is tedious
spent this hour troubleshooting and figuring out how to add wires. was super unsucessful and wasted my time. im pretty annoyed
Ships:
I made a tamagotchi pet (i am aware that throughout the project, the spelling of it has been inconsistent) But anyway, what i found most challenging was having to look through the loop constantly making adjustments based off minor errors during each test run and incorrect wiring making me feel like i had the code wrong. I am proud that I learned surprisingly a lot. The screenshot is merely just part of it and you should check it out yourself! both the source for the software and hardware is in there. The latest software build is in a separate branch and you may need to scope around for the latest hardware build. PLEASE note that all of the hardware additions - if you truly want to build it yourself, is pushing the limits of the esp32 so please run it while using a powerful cable....
|
1793004735.0102348
|
1793091135.0102348
|
|
67744
|
A custom cybersecurity oriented cyberdeck. by @mat A custom cybersecurity oriented cyberdeck. by @matthieu_obyrne | Stardance...
|
matthieu_obyrne
|
0
|
9.06
|
0
|
[]
|
[{"post_id": 81147, "ts": "202 [{"post_id": 81147, "ts": "2026-10-20T02:57:49Z", "hours": 0.9139, "text": "I finally added an up-to-date readme and cleared up my github"}, {"post_id": 81057, "ts": "2026-10-19T18:12:28Z", "hours": 0.8217, "text": "I updated my pcb back to the old fold version, and placed everything back on it, i think I am finally ready to print it, I also made a quick cad of the pcb that will allow me to make and design the case."}, {"post_id": 78901, "ts": "2026-10-11T23:24:19Z", "hours": 1.6881, "text": "Added a rough draft of the opensource proxmark 3 into my pcb integrated inside"}, {"post_id": 77728, "ts": "2026-10-08T03:19:34Z", "hours": 5.6342, "text": "I started working on the pcb and placing all the parts e"}]...
|
Title: A custom cybersecurity oriented cyberdeck. Title: A custom cybersecurity oriented cyberdeck. by @matthieu_obyrne | Stardance
Devlogs:
I started working on the pcb and placing all the parts e
Added a rough draft of the opensource proxmark 3 into my pcb integrated inside
I updated my pcb back to the old fold version, and placed everything back on it, i think I am finally ready to print it, I also made a quick cad of the pcb that will allow me to make and design the case.
I finally added an up-to-date readme and cleared up my github...
|
1793112896.473352
|
1793717696.473352
|
|
70132
|
Custom Pet by @DragonDev_27i | Stardance
|
DragonDev_27i
|
1
|
5.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-21T00:31:15Z", "hours": 5.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a Desktop pet that takes the sprite of Sans the Skelton from Undertale as my playground project and it was fun to make. The challenges that I experienced during the production of the project, not knowing how to interpret parts of the code, because some of it didn’t make sense. For example if I wanted to add functionality; I didn’t know that I could use a function such as _unhandled_input to handle inputs such as performing a certain action if a key is pressed. Thankfully, after reading the Godot documentation, and watching a couple of YouTube videos alongside a couple google searches I was able to overcome my challenges. Finally, I would say that I am proud because I was able to make a desktop pet, and now I get to see sans walk across my Desktop.", "repo": "https://github.com/JohhnyTech27i/DeskPet", "demo": "https://firedragon-27i.itch.io/sans-desktop-pet"}]...
|
[{"post_id": 81148, "ts": "202 [{"post_id": 81148, "ts": "2026-10-20T03:04:23Z", "hours": 1.0581, "text": "Devlog 2 Final devlog: I have worked on the pet and have decided that this will be the final devlog for stardance. I will continue to update the program, but due to time constraints I can’t keep making devlogs for this project in star dance. Great news is that I was able to add a menu that allows you to quit the game. Figured out how the @onready works how to handle inputs and other things; code seems a bit more oraganzied now. Sans now has a timer that says, I’m sans."}, {"post_id": 80745, "ts": "2026-10-18T18:08:50Z", "hours": 2.3864, "text": "Dev 1: In this devlog I was able to change the sprite to sans, changed the movement so that it only went in one direction. The guide was right it was supposed to be Vector2(1,0) not Vector(1,1) so that it could move smoothly in one direction instead of going off in all directions. Next, Sans can tell the user the time based on their own PC time when left clicked on. Also, sounds makes his iconic noise eeee when left clicked on. Now for the next devlog, the goals will to optimize the code in a way that it allows for sans to do more actions such as fall onto the taskbar, or create a popup screen that allows to quit the program or that could maybe change the sprite to Chara or any another Undertale characters."}, {"post_id": 80686, "ts": "2026-10-18T14:48:33Z", "hours": 1.6467, "text": "Just working to see how the DeskPet will work, so this will be the prototype. By following the guide I was able to get to the part where the sprite can move all across. There was some issues with following the code because, I had to change direction to Vector2(1,1) instead of keeping it at Vector2(1,0), so that the sprite can move in all directions. Hopefully for the next devlog I am able to move the sprite more gracefully, and there is interaction when I click on it or drag it. As I plan, to make, characters like sans or Chara, fight or do other animations."}]...
|
Title: Custom Pet by @DragonDev_27i | Stardance
D Title: Custom Pet by @DragonDev_27i | Stardance
Devlogs:
Just working to see how the DeskPet will work, so this will be the prototype. By following the guide I was able to get to the part where the sprite can move all across. There was some issues with following the code because, I had to change direction to Vector2(1,1) instead of keeping it at Vector2(1,0), so that the sprite can move in all directions. Hopefully for the next devlog I am able to move the sprite more gracefully, and there is interaction when I click on it or drag it. As I plan, to make, characters like sans or Chara, fight or do other animations.
Dev 1: In this devlog I was able to change the sprite to sans, changed the movement so that it only went in one direction. The guide was right it was supposed to be Vector2(1,0) not Vector(1,1) so that it could move smoothly in one direction instead of going off in all directions. Next, Sans can tell the user the time based on their own PC time when left clicked on. Also, sounds makes his iconic noise eeee when left clicked on. Now for the next devlog, the goals will to optimize the code in a way that it allows for sans to do more actions such as fall onto the taskbar, or create a popup screen that allows to quit the program or that could maybe change the sprite to Chara or any another Undertale characters.
Devlog 2 Final devlog: I have worked on the pet and have decided that this will be the final devlog for stardance. I will continue to update the program, but due to time constraints I can’t keep making devlogs for this project in star dance. Great news is that I was able to add a menu that allows you to quit the game. Figured out how the @onready works how to handle inputs and other things; code seems a bit more oraganzied now. Sans now has a timer that says, I’m sans.
Ships:
I made a Desktop pet that takes the sprite of Sans the Skelton from Undertale as my playground project and it was fun to make. The challenges that I experienced during the production of the project, not knowing how to interpret parts of the code, because some of it didn’t make sense. For example if I wanted to add functionality; I didn’t know that I could use a function such as _unhandled_input to handle inputs such as performing a certain action if a key is pressed. Thankfully, after reading the Godot documentation, and watching a couple of YouTube videos alongside a couple google searches I was able to overcome my challenges. Finally, I would say that I am proud because I was able to make a desktop pet, and now I get to see sans walk across my Desktop....
|
1793051305.0160825
|
1793137705.0160825
|
|
55524
|
Oi Site by @oishani | Stardance
|
oishani
|
0
|
2.73
|
0
|
[]
|
[{"post_id": 81158, "ts": "202 [{"post_id": 81158, "ts": "2026-10-20T04:22:46Z", "hours": 2.7278, "text": "First I was just making a simple link tree, then started playing around and adding new style elements. I plan to make it more of a real personal website now too, adding like a bio and interests and actual stuff about me."}]...
|
Title: Oi Site by @oishani | Stardance
Devlogs:
F Title: Oi Site by @oishani | Stardance
Devlogs:
First I was just making a simple link tree, then started playing around and adding new style elements. I plan to make it more of a real personal website now too, adding like a bio and interests and actual stuff about me....
|
1792500592.2460642
|
1793105392.2460642
|
|
2693
|
Stitch-Craft by @Peneroni | Stardance
|
Peneroni
|
1
|
44.0
|
798
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-20T04:42:02Z", "hours": 44.0, "multiplier": 17.93, "payout": 798, "blessing": "neutral", "text": "#Welcome to Stitch-Craft! Work in a dying costume shop with Dennis the costume designer as you build, pull, and buy new costumes. There are many ways to house and attain costumes, and it’s your job to do just that! This is my passion project that I’ve been working on for the past several and I’m ver excited to share the beginnings of it with you all! My mom gave me the idea because she works in a costume shop, and we both thought it would be a fun game to play. One thing to note that this is an early ship of the MVP I set for myself. Most of the assets are placeholders, you can’t fully make costumes and submit them for a show yet, and not all features that I plan to add are in the game yet. I wanted to ship what I have so far, which is the system of how you gain costumes in the dysfunctional costume shop of yours. Currently you can go through the tutorial with Dennis, play the sewing minigame for costumes, buy costumes, and store your costumes in the storage. This is what I shipped, and I hope you enjoy!", "repo": "https://github.com/Penn-the-Great/Stitch-Craft", "demo": "https://peneroni.itch.io/stitch-craft"}]...
|
[{"post_id": 81159, "ts": "202 [{"post_id": 81159, "ts": "2026-10-20T04:29:34Z", "hours": 1.5197, "text": "Build bugs and ship I know I said the last devlog would be the last one, but as expected there were a few last bugs, especially with rendering. There were lots of sizing bugs and technical Unity bugs, and I also had to get the Unity web building package and configure it to how I wanted. BUT, the biggest change is that I got my game on Itch, and I finally shipped! Main changes: Optimization and sizing bugs Added game to Itch.io SHIPPED"}, {"post_id": 81141, "ts": "2026-10-20T02:13:05Z", "hours": 3.3975, "text": "Tutorial and finishing touches The tutorial was created, and you can go around each of the rooms where Dennis will explain each of the features. The tutorial dialogue will also only appear ONCE, which took me forever to figure out. I also added some actual words to the end of the timer/weeks, and its just a thank you message to all who played the beta/demo with some buttons to return to title or quit. Some other smaller changes is I added some text to the Slamazon website to be a placeholder logo, I also changed the chapter select background, which used to be the picture of that cat eating chips in the distance of the windows xp wallpaper. I’m so excited because I think I have an MVP to ship, and it has been a very long journey. One thing I had to accept before shipping was that I was never going to get the full chapter 1 shipped in time for Stardance like I wanted it to be, which is okay. I was hoping for all the assets to be done in time, but there was still so much to do and no time to do it, and unfortunately the submission part of my game relied on having all of the mannequin assets done. My solution to this was to just have the demo be about exploring the clothing system and exploring the costume shop, and like someone once told me, it doesn’t have to look good to be good. However, I will not stop working on Stitch-Craft after Stardance is over, and I fully intend to keep adding and improving the game as much as I can. Thank you to all who have liked my devlogs and shown your support for my game and its progress. Main changes: Tutorial added that shows player around the shop Slight cosmetic changes to placeholders and other missing assets Completed MVP"}, {"post_id": 81089, "ts": "2026-10-19T20:37:54Z", "hours": 2.4767, "text": "Dialogue, cleaning, and more The dialogue system is finally in place! The player can now go down different dialogue “paths”, allowing them to choose between 2 options. I was also going back and cleaning up some of my older codes a little bit when I realized that not a single one had been commented. It was at that moment that I hated my entire existence and this whole project because I made one of the biggest mistakes of this whole thing. I had also not learned about commenting at all until I took a computer programming class this year, and that my video game development teacher last year did not teach us about commenting, and now I can’t remember how half of the code works. If any of you have any suggestions on how to go about this, that would be very helpful! There have also been small updates to assets as I am getting ready to ship. There are just a few things left to do to get the MVP since most finalized assets will not be finished by the time I ship, so I think the demo will just be an exploration of the clothing system. I’m expecting one more devlog, and the stitchcraft demo will be shipped! Main changes: Dialogue system with options and branching dialogue Code has been cleaned a little Final touches for shipping"}, {"post_id": 63920, "ts": "2026-09-07T23:26:53Z", "hours": 4.2289, "text": "Mannequin Assets! New assets for the mannequin, money/time labels, info panel, and other buttons. There were bugs, bugs, and many more bugs, especially with getting the sprites to show up, which was somewhat caused by me trying to use SVGs, but ultimately falling back to PNGs for now. Special thanks to my amazing mother for helping me create the mannequin assets, and my amazing father for teaching me how to use Figma. The tops now have basic assets (to be updated and more added later) that snap onto the mannequin, and can be taken off in a similar fashion (hehe, fashion) to the storage room. Some other bug fixes were making sure the purchasing system works completely, and slamazon looks good. Main changes: The clothing pieces have assets and are aligned with the mannequin New UI assets all around Slamazon delivery system bug fixes"}, {"post_id": 63687, "ts": "2026-09-07T16:52:49Z", "hours": 3.8639, "text": "Settings Overhaul I changed the settings’ visual look. Before, there was mostly placeholder images, placeholder sliders, and placeholder fonts. So I did some work in Figma, and lots of troubleshooting with the code to create the spinning pattern. My biggest challenge was that I was originally going to have the pattern slowly moving off screen to look like an infinite stream of icons, but I decided not to and to just have them spin slowly in place. This is the finished product, and more visual updates to all other screens to come! Main changes: Spinning icon pattern in the background of the settings New font chosen for most of the game UI style chosen and developed final settings UI"}, {"post_id": 30341, "ts": "2026-07-17T20:20:26Z", "hours": 4.4286, "text": "Submission system created Now you can submit costumes to the required amount for a chapter. You can put costumes on, and take them off with very similar logic as the storage system. You can only submit when the minimum requirement of a top and bottom, or full piece, is met. The image below is the layout of the UI. Everything is currently placeholders, which the rest of the project will be mostly a lot of drawing assets, so the demo is close to being ready! Main changes: Requirement costume amount added Clothing pieces can be placed as a child of the mannequin Clothing pieces can be sumitted towards the final costume count"}, {"post_id": 12889, "ts": "2026-06-21T03:34:51Z", "hours": 2.4853, "text": "Cosmetic minigame updates I made some cosmetic minigame updates to really finalize it. The different phases now slide into each other making a really nice looking transition. I also did tons of bug fixes around the actual creation of the final clothing piece, especially with canvases and canvas types. My main bug I had to fix was the workspace canvas being visible, but setting it as inactive made the hanger object spawn on the wrong canvas die to incorrect references, however, the problem was solved by using alpha values instead of setting the worspace canvas as inactive. The minigames look plain right now, but I will put animated backgrounds to show the different settings (like cutting out fabric, sewing, and ironing). Main changes: Sliding transitions between minigame phases Workspace canvas disappears during minigames Clothing piece confirmed to spawn after minigames with correct grade"}, {"post_id": 12221, "ts": "2026-06-19T22:59:05Z", "hours": 2.6964, "text": "Minigame updates! I made some updates to the minigame system. I mostly added things to the version from the last devlog. The line renderer shows up now, but I had to make it disconnected from the accuracy, so it’s purely cosmetic. The second phase is a timing minigame where you have to click the slider at the right time, and I changed it from a horizontal orientation to vertical. The buttons in phase 3 got a slight timing update and little steam puffs, which the video below is of that working. The last thing I updated was make the flow of starting and ending the minigame nice with the start minigame button. Main updates: Line renderer fixed Small cosmetic changes to phases 2 and 3 Minigames can be started with the start minigame button"}, {"post_id": 11410, "ts": "2026-06-18T17:53:30Z", "hours": 3.8108, "text": "Remade the minigame system. It comes in 3 phases still, and accuracy can be calculated. I had to take a pretty long break after the first attempt at the minigames because I got so burnt out from how badly the last one turned out, but I persist. My main struggle with this update was trying to get the line renderer to work, which I am still working on. The picture below is a look at what the first phase will look like, I’ll probably add more cosmetic changes later when I’m focusing on assets near the end of the game. Main changes Remade base minigames system 3 phases can be played, and accuracy is deducted Added a few more placeholder assets"}, {"post_id": 2556, "ts": "2026-06-05T03:19:02Z", "hours": 3.45, "text": "First minigame system I created a sewing system with a series of 3 mini games to cut, sew, and press costumes. Unfortunately it doesn’t run very smoothly, and I am unable to get a screenshot of it working. I am going to overhaul it later, but it’s good for getting the idea of what I want the mini games to be. The image below is what the main pattern picking UI will look like. Main changes: Made fabric a currency to use in sewing Made sewing draft games Made a few new assets"}, {"post_id": 2361, "ts": "2026-06-04T20:18:29Z", "hours": 2.135, "text": "Currency system I created a currency system for my game! It includes a storefront that refreshes every week to buy clothing pieces and fabric (which will come into play later) which get delivered to your storage after the amount of weeks it takes to deliver. The deliveries also show up in a calendar on the desk. Once again, it was a little bit of a struggle to get items to keep references across scenes and on start, but I figured it out. Everything is mostly placeholders right now, but that will change in the future. Main changes: Currency system created using unity gaming services Storefront created to refresh with new clothes to buy every week Calendar shows pending deliveries Completed deliveries get sent to the storage as a draggable hanger object to use Budget for each chapter gets set at the beginning, which players use to spend"}, {"post_id": 1797, "ts": "2026-06-04T00:26:59Z", "hours": 2.9922, "text": "Storage system I made a storage system for my hanger objects with a sorting system. The hardest part was making the hangers move from one canvas to another canvas on another scene. The hangers also kept spawning in all the wrong places, and there was a lot of scene management bugs. But, it works smoothly now as seen in the demo below. Main changes : Created storage system that moves hangers from player’s canvas to storage canvas in separate scene Hangers keep their properties when stored, and stay in storage when player loads and unloads scene Sorting system sorts the clothes in storage by attributes"}, {"post_id": 1280, "ts": "2026-06-03T05:15:27Z", "hours": 6.6208, "text": "Timer system I added a timer system in weeks for each chapter. I also updated my navigation system to support additive scenes rather than single scenes to preserve references. I also made sure that the timer worked for free play mode as well as the chapters. I ran into a lot of bugs with the scene logic, especially trying to get additive scenes to unload. However, I figured it out and it works nicely."}, {"post_id": 428, "ts": "2026-06-01T20:38:44Z", "hours": 0.3897, "text": "First official devlog! My progress before this includes a design document, I made most scenes that I anticipate will be used, made a navigation logic with a fader for smooth transitions, a few icons and visuals (I attached the title for now to this devlog), and a system to create hangers with data like clothing type, material, color, etc. There was a lot of unnecessary bugs that could’ve been avoided easily, but I learned a lot from them. All this to say that updates will be more recorded from now on."}]...
|
Title: Stitch-Craft by @Peneroni | Stardance
Devl Title: Stitch-Craft by @Peneroni | Stardance
Devlogs:
First official devlog! My progress before this includes a design document, I made most scenes that I anticipate will be used, made a navigation logic with a fader for smooth transitions, a few icons and visuals (I attached the title for now to this devlog), and a system to create hangers with data like clothing type, material, color, etc. There was a lot of unnecessary bugs that could’ve been avoided easily, but I learned a lot from them. All this to say that updates will be more recorded from now on.
Timer system I added a timer system in weeks for each chapter. I also updated my navigation system to support additive scenes rather than single scenes to preserve references. I also made sure that the timer worked for free play mode as well as the chapters. I ran into a lot of bugs with the scene logic, especially trying to get additive scenes to unload. However, I figured it out and it works nicely.
Storage system I made a storage system for my hanger objects with a sorting system. The hardest part was making the hangers move from one canvas to another canvas on another scene. The hangers also kept spawning in all the wrong places, and there was a lot of scene management bugs. But, it works smoothly now as seen in the demo below. Main changes : Created storage system that moves hangers from player’s canvas to storage canvas in separate scene Hangers keep their properties when stored, and stay in storage when player loads and unloads scene Sorting system sorts the clothes in storage by attributes
Currency system I created a currency system for my game! It includes a storefront that refreshes every week to buy clothing pieces and fabric (which will come into play later) which get delivered to your storage after the amount of weeks it takes to deliver. The deliveries also show up in a calendar on the desk. Once again, it was a little bit of a struggle to get items to keep references across scenes and on start, but I figured it out. Everything is mostly placeholders right now, but that will change in the future. Main changes: Currency system created using unity gaming services Storefront created to refresh with new clothes to buy every week Calendar shows pending deliveries Completed deliveries get sent to the storage as a draggable hanger object to use Budget for each chapter gets set at the beginning, which players use to spend
First minigame system I created a sewing system with a series of 3 mini games to cut, sew, and press costumes. Unfortunately it doesn’t run very smoothly, and I am unable to get a screenshot of it working. I am going to overhaul it later, but it’s good for getting the idea of what I want the mini games to be. The image below is what the main pattern picking UI will look like. Main changes: Made fabric a currency to use in sewing Made sewing draft games Made a few new assets
Remade the minigame system. It comes in 3 phases still, and accuracy can be calculated. I had to take a pretty long break after the first attempt at the minigames because I got so burnt out from how badly the last one turned out, but I persist. My main struggle with this update was trying to get the line renderer to work, which I am still working on. The picture below is a look at what the first phase will look like, I’ll probably add more cosmetic changes later when I’m focusing on assets near the end of the game. Main changes Remade base minigames system 3 phases can be played, and accuracy is deducted Added a few more placeholder assets
Minigame updates! I made some updates to the minigame system. I mostly added things to the version from the last devlog. The line renderer shows up now, but I had to make it disconnected from the accuracy, so it’s purely cosmetic. The second phase is a timing minigame where you have to click the slider at the right time, and I changed it from a horizontal orientation to vertical. The buttons in phase 3 got a slight timing update and little steam puffs, which the video below is of that working. The last thing I updated was make the flow of starting and ending the minigame nice with the start minigame button. Main updates: Line renderer fixed Small cosmetic changes to phases 2 and 3 Minigames can be started with the start minigame button
Cosmetic minigame updates I made some cosmetic minigame updates to really finalize it. The different phases now slide into each other making a really nice looking transition. I also did tons of bug fixes around the actual creation of the final clothing piece, especially with canvases and canvas types. My main bug I had to fix was the workspace canvas being visible, but setting it as inactive made the hanger object spawn on the wrong canvas die to incorrect references, however, the problem was solved by using alpha values instead of setting the worspace canvas as inactive. The minigames look plain right now, but I will put animated backgrounds to show the different settings (like cutting out fabric, sewing, and ironing). Main changes: Sliding transitions between minigame phases Workspace canvas disappears during minigames Clothing piece confirmed to spawn after minigames with correct grade
Submission system created Now you can submit costumes to the required amount for a chapter. You can put costumes on, and take them off with very similar logic as the storage system. You can only submit when the minimum requirement of a top and bottom, or full piece, is met. The image below is the layout of the UI. Everything is currently placeholders, which the rest of the project will be mostly a lot of drawing assets, so the demo is close to being ready! Main changes: Requirement costume amount added Clothing pieces can be placed as a child of the mannequin Clothing pieces can be sumitted towards the final costume count
Settings Overhaul I changed the settings’ visual look. Before, there was mostly placeholder images, placeholder sliders, and placeholder fonts. So I did some work in Figma, and lots of troubleshooting with the code to create the spinning pattern. My biggest challenge was that I was originally going to have the pattern slowly moving off screen to look like an infinite stream of icons, but I decided not to and to just have them spin slowly in place. This is the finished product, and more visual updates to all other screens to come! Main changes: Spinning icon pattern in the background of the settings New font chosen for most of the game UI style chosen and developed final settings UI
Mannequin Assets! New assets for the mannequin, money/time labels, info panel, and other buttons. There were bugs, bugs, and many more bugs, especially with getting the sprites to show up, which was somewhat caused by me trying to use SVGs, but ultimately falling back to PNGs for now. Special thanks to my amazing mother for helping me create the mannequin assets, and my amazing father for teaching me how to use Figma. The tops now have basic assets (to be updated and more added later) that snap onto the mannequin, and can be taken off in a similar fashion (hehe, fashion) to the storage room. Some other bug fixes were making sure the purchasing system works completely, and slamazon looks good. Main changes: The clothing pieces have assets and are aligned with the mannequin New UI assets all around Slamazon delivery system bug fixes
Dialogue, cleaning, and more The dialogue system is finally in place! The player can now go down different dialogue “paths”, allowing them to choose between 2 options. I was also going back and cleaning up some of my older codes a little bit when I realized that not a single one had been commented. It was at that moment that I hated my entire existence and this whole project because I made one of the biggest mistakes of this whole thing. I had also not learned about commenting at all until I took a computer programming class this year, and that my video game development teacher last year did not teach us about commenting, and now I can’t remember how half of the code works. If any of you have any suggestions on how to go about this, that would be very helpful! There have also been small updates to assets as I am getting ready to ship. There are just a few things left to do to get the MVP since most finalized assets will not be finished by the time I ship, so I think the demo will just be an exploration of the clothing system. I’m expecting one more devlog, and the stitchcraft demo will be shipped! Main changes: Dialogue system with options and branching dialogue Code has been cleaned a little Final touches for shipping
Tutorial and finishing touches The tutorial was created, and you can go around each of the rooms where Dennis will explain each of the features. The tutorial dialogue will also only appear ONCE, which took me forever to figure out. I also added some actual words to the end of the timer/weeks, and its just a thank you message to all who played the beta/demo with some buttons to return to title or quit. Some other smaller changes is I added some text to the Slamazon website to be a placeholder logo, I also changed the chapter select background, which used to be the picture of that cat eating chips in the distance of the windows xp wallpaper. I’m so excited because I think I have an MVP to ship, and it has been a very long journey. One thing I had to accept before shipping was that I was never going to get the full chapter 1 shipped in time for Stardance like I wanted it to be, which is okay. I was hoping for all the assets to be done in time, but there was still so much to do and no time to do it, and unfortunately the submission part of my game relied on having all of the mannequin assets done. My solution to this was to just have the demo be about exploring the clothing system and exploring the costume shop, and like someone once told me, it doesn’t have to look good to be good. However, I will not stop working on Stitch-Craft after Stardance is over, and I fully intend to keep adding and improving the game as much as I can. Thank you to all who have liked my devlogs and shown your support for my game and its progress. Main changes: Tutorial added that shows player around the shop Slight cosmetic changes to placeholders and other missing assets Completed MVP
Build bugs and ship I know I said the last devlog would be the last one, but as expected there were a few last bugs, especially with rendering. There were lots of sizing bugs and technical Unity bugs, and I also had to get the Unity web building package and configure it to how I wanted. BUT, the biggest change is that I got my game on Itch, and I finally shipped! Main changes: Optimization and sizing bugs Added game to Itch.io SHIPPED
Ships:
#Welcome to Stitch-Craft! Work in a dying costume shop with Dennis the costume designer as you build, pull, and buy new costumes. There are many ways to house and attain costumes, and it’s your job to do just that! This is my passion project that I’ve been working on for the past several and I’m ver excited to share the beginnings of it with you all! My mom gave me the idea because she works in a costume shop, and we both thought it would be a fun game to play. One thing to note that this is an early ship of the MVP I set for myself. Most of the assets are placeholders, you can’t fully make costumes and submit them for a show yet, and not all features that I plan to add are in the game yet. I wanted to ship what I have so far, which is the system of how you gain costumes in the dysfunctional costume shop of yours. Currently you can go through the tutorial with Dennis, play the sewing minigame for costumes, buy costumes, and store your costumes in the storage. This is what I shipped, and I hope you enjoy!...
|
1793051284.8271317
|
1793137684.8271317
|
|
48213
|
Level Up by @Lalith | Stardance
|
Lalith
|
4
|
78.0
|
654
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-20T05:23:19Z", "hours": 9.0, "multiplier": 12.16, "payout": 112, "blessing": "neutral", "text": "Shipped LevelUp! It started as a way to make a long self-development video easier to read. Now it has 28 chapters, practical plans, habits, focus timers, and a daily mission system. You can save an idea from a chapter and actually try it instead of forgetting it five minutes later. Milo is the little companion that reacts to your reading and focus activity. Everything important works locally, without an account or trackers. There’s also an offline progress system called Nexus, which handles changes across tabs and lets you move progress using encrypted files. This update mostly brought the different parts together. I fixed mobile layouts, added larger text and a quick tutorial, and made backups include the newer features. Cloud chat still needs work, and the app could be simpler, but the full version is live now. Try it: https://hustlenix.github.io/LevelUp/", "repo": "https://github.com/Hustlenix/LevelUp", "demo": "https://hustlenix.github.io/LevelUp/"}, {"ship_num": 2, "ts": "2026-09-30T12:09:06Z", "hours": 11.0, "multiplier": 9.76, "payout": 103, "blessing": "neutral", "text": "This is my final ship for Level Up. Level Up originally started as a simple idea: turn a 20-hour self-improvement video into something I could actually read, search, understand, and use. It started as basically a local-first book. Over time I kept asking the same question: “How do I make this useful after someone finishes reading?” So I kept rebuilding it. Now Level Up is much closer to a complete self-improvement app. The main experience is built around Today — you open the app, see what you are working toward, get a clear next action, start a focus/study session, and track your progress instead of just consuming more content. I also added Goals, Progress, Study Mode, a daily planner, tutor/coach tools, local AI through Ollama, chapter search, quizzes, streaks, highlights, backups, restore, and a much more consistent UI across the app. The hardest part was making all of this work while keeping the original idea of Level Up: no account required, no cloud database, and your personal progress stays on your device. I had to rebuild a lot of the local state system, handle migrations and corrupted data, improve backup/restore, and make sure the app still works properly offline or without local AI installed. The thing I’m most proud of is that it no longer feels like a book with random features added around it. It finally feels like one connected product. If you test it, don’t just click around. Actually use it: Create a goal Open Today and follow the next action Start a focus/study session Read or study a chapter Check your Progress Refresh/reopen the app and see your data persist There are definitely things I could keep polishing forever, but I don’t want this project to become an endless cycle of “one more redesign.” This is the version I’m calling finished. Try it: https://hustlenix.github.io/LevelUp/ Source: https://github.com/Hustlenix/LevelUp Thanks to everyone who tested it, gave feedback, or followed the devlogs while this went from a small reading website into this. LEVEL UP. 🚀", "repo": "https://github.com/Hustlenix/LevelUp", "demo": "https://hustlenix.github.io/LevelUp/"}, {"ship_num": 3, "ts": "2026-09-20T07:44:58Z", "hours": 18.0, "multiplier": 8.6, "payout": 153, "blessing": "neutral", "text": "I upgraded my MVP called Level Up: transforming a local-first self-development book into a full-featured, Today-first operating system—still running 100% in your browser. The Motivation While Ship #1 proved that a 20-hour video transcript could become a searchable, evidence-graded web book, the feedback was clear: the UI/UX felt fragmented. Having deep individual features wasn’t enough if the home experience didn’t tell you what to do right now. I set out to redesign Level Up from a passive reading interface into an actionable personal operating system. What’s New: The Today-First OS & Local AI Instead of a crowded home screen, the app now centers on a streamlined /today/ hub that answers one core question: “What should I do next?” Today Shell Navigation: Simplified navigation down to Today, Learn, Goals, Progress, and More, placing your current focus front and center. On-Device Study Workspace: Integrated a dedicated Study Mode featuring an automated Daily Planner, a Local Coach, and an interactive Tutor mode to explain or practice any of the 28 chapters. Smart Local AI Integration: Added support for local LLMs via Ollama with full offline fallback, letting you generate study plans and ask questions without leaking private data to external servers. How We Upgraded It Typed Local State Boundary: Replaced fragmented localStorage usage with a single, typed local repository boundary managed via pure TypeScript modules and useSyncExternalStore. Data Diagnostics & Migrations: Hardened JSON schema validation, improved backup/restore transaction handling, and added local data health checks to ensure offline state never gets corrupted. UI/UX Consistency System: Standardized spacing, card hierarchies, buttons, forms, and empty states across all routes so every tool feels like part of a unified product. Into the Trenches (Challenges & Learnings) The Monolith vs. Workspaces Tradeoff: Moving from a multi-tool dashboard to a focused Today-first layout meant rethinking information architecture. We hid creation forms behind empty states and compressed secondary features like inbox items into compact panels to avoid visual clutter. Local AI Fallbacks: Integrating Ollama required explicit status checks and graceful local degradation so non-technical users or fully offline environments still get a clean UI without broken promises. What I’m Proud Of Coherent OS Feel: Level Up no longer feels like separate utilities tacked together; it operates as one smooth, self-contained habit driver. Privacy Preserved: Despite adding AI study tools and custom daily planners, everything remains zero-tracking, zero-backend, and fully functional on-device. Try it out: Live site: https://hustlenix.github.io/LevelUp/ Source code: https://github.com/Hustlenix/LevelUp Tech Stack: Next.js 16, Tailwind v4, TypeScript, node:sqlite, MiniSearch, Ollama / On-Device Local State, GitHub Pages", "repo": "https://github.com/Hustlenix/LevelUp", "demo": "https://hustlenix.github.io/LevelUp/"}, {"ship_num": 4, "ts": "2026-09-11T17:51:26Z", "hours": 40.0, "multiplier": 16.67, "payout": 286, "blessing": "neutral", "text": "I built a free MVP called Level Up : a 28-chapter self-development book built from a 20-hour video transcript, running entirely in your browser. The Motivation It started with a simple question: What if you could turn a 20-hour self-dev video into something you could actually read, search, and verify? Most online self-development content exists to sell courses, not to present evidence. I wanted something honest. So, I built a real book where every notable claim is graded against cited research. What It Is: Zero Tracking, 100% Local The result is roughly 32k words across four pillars, a 30-claim evidence audit (graded A–D/U), 13 testable protocols, and full-text search. The best part? Zero tracking. No accounts, no APIs, no cookies. Your reading progress, streaks, highlights, themes, and quiz scores live entirely in your browser’s localStorage . Nothing leaves your machine. How We Built It The original video transcript was ~20k lines. We tag-teamed Claude, Gemini, and Opencode to compress it. From there, we built the site in layers: The Content Pipeline: scripts/build-data.mjs compiles Markdown chapters into SQLite using node:sqlite , then emits JSON data and a 30KB MiniSearch index. The Frontend: Next.js 16 static export and Tailwind v4. We used useSyncExternalStore for reactive local state via pure TypeScript modules. The Deploy: Automated via GitHub Actions straight to GitHub Pages. Into the Trenches (Challenges & Learnings) The CI Spiral: We added a React 19 QuoteCard. It built flawlessly locally (22/22 tests green), but failed eight consecutive GitHub Actions runs with a phantom TS error. It wasn’t a code bug; it was an environment disagreement. Lesson: Sometimes a feature just isn’t ready. We deleted it rather than fighting the environment or shipping it broken. Turbopack’s Quiet Types: The dev server uses Turbopack, which skips full type-checking for speed. We shipped a PR that built locally but failed in CI. Lesson: Always run tsc locally, or CI will aggressively remind you of the difference between “builds” and “types.” Case Sensitivity: GitHub Pages serves paths case-sensitively. NEXT_PUBLIC_BASE_PATH=/LevelUp is fundamentally different from /levelup . We learned this the hard way. What I’m Proud Of Honest Grading: No invented citations. If a famous “5x flow” stat is folklore, the site tells you so. Backend-less Magic: Search, quizzes, highlights, streaks, and schema-validated JSON backup/restore—all completely offline-capable. The Architecture: The data layer isn’t just a pile of JSON; it’s a statically served, compiled artifact from Markdown. Try it out: Live site: https://hustlenix.github.io/LevelUp/ Source code: https://github.com/Hustlenix/LevelUp Tech Stack: Next.js 16, Tailwind v4, node:sqlite, MiniSearch, GitHub Pages", "repo": "https://github.com/Hustlenix/LevelUp", "demo": "https://hustlenix.github.io/LevelUp/"}]...
|
[{"post_id": 81165, "ts": "202 [{"post_id": 81165, "ts": "2026-10-20T05:15:28Z", "hours": 9.1767, "text": "Finishing touches, i think this is coming to and end, so i lokced in in these 10 hours and did some major changes, like used HCB APi key and give MILO an life so it can interact with you guys, and bumped up the UI/UX to and next level and: Milo Talk with offline guidance and explicit approval before saving suggested actions. Replayable walkthrough and app-wide text sizing up to 150%. Distinct Deep Work/Cyberpunk themes; preserved Light/Dark. Install guidance, offline support, refreshed screenshots, and technical documentation. Fixed Settings headings and Deep Work contrast. As per your reviews and real time feedback, thank you guys!"}, {"post_id": 75526, "ts": "2026-09-30T11:33:39Z", "hours": 8.6486, "text": "I tried making this the final boss of Self Improvement APP, i think i am finally over, longin and start LEVELING UPPP!!!!!!!!!!!"}, {"post_id": 72287, "ts": "2026-09-22T16:18:34Z", "hours": 1.9244, "text": "I think there is nothing to be upgraded in this, all i have to do now is add subscryptions and make money!!!!!!!!!!!!"}, {"post_id": 71049, "ts": "2026-09-20T07:44:31Z", "hours": 0.8897, "text": "I upgraded my MVP called Level Up: transforming a local-first self-development book into a full-featured, Today-first operating system—still running 100% in your browser.The Motivation While Ship #1 proved that a 20-hour video transcript could become a searchable, evidence-graded web book, the feedback was clear: the UI/UX felt fragmented. Having deep individual features wasn’t enough if the home experience didn’t tell you what to do right now. I set out to redesign Level Up from a passive reading interface into an actionable personal operating system.What’s New: The Today-First OS & Local AI Instead of a crowded home screen, the app now centers on a streamlined /today/ hub that answers one core question: “What should I do next?”Today Shell Navigation: Simplified navigation down to Today, Learn, Goals, Progress, and More, placing your current focus front and center.On-Device Study Workspace: Integrated a dedicated Study Mode featuring an automated Daily Planner, a Local Coach, and an interactive Tutor mode to explain or practice any of the 28 chapters.Smart Local AI Integration: Added support for local LLMs via Ollama with full offline fallback, letting you generate study plans and ask questions without leaking private data to external servers.How We Upgraded ItTyped Local State Boundary: Replaced fragmented localStorage usage with a single, typed local repository boundary managed via pure TypeScript modules and useSyncExternalStore.Data Diagnostics & Migrations: Hardened JSON schema validation, improved backup/restore transaction handling, and added local data health checks to ensure offline state never gets corrupted.UI/UX Consistency System: Standardized spacing, card hierarchies, buttons, forms, and empty states across all routes so every tool feels like part of a unified product.Into the Trenches (Challenges & Learnings)The Monolith vs. Workspaces Tradeoff: Moving from a multi-tool dashboard to a focused Today-first layout meant rethinking information architecture. We hid creation forms behind empty states and compressed secondary features like inbox items into compact panels to avoid visual clutter.Local AI Fallbacks: Integrating Ollama required explicit status checks and graceful local degradation so non-technical users or fully offline environments still get a clean UI without broken promises.What I’m Proud OfCoherent OS Feel: Level Up no longer feels like separate utilities tacked together; it operates as one smooth, self-contained habit driver.Privacy Preserved: Despite adding AI study tools and custom daily planners, everything remains zero-tracking, zero-backend, and fully functional on-device.Try it out:Live site: https://hustlenix.github.io/LevelUp/Source code: https://github.com/Hustlenix/LevelUpTech Stack: Next.js 16, Tailwind v4, TypeScript, node:sqlite, MiniSearch, Ollama / On-Device Local State, GitHub Pages"}, {"post_id": 70978, "ts": "2026-09-20T04:38:42Z", "hours": 5.0881, "text": "Till now for my app i have like genrated the overall Backend and front end, but the frontend UI/UX is kinda mid. so i am thinking of improving it and opt for te second ship. In UI/UX i am thinking of doind this: 1. Today-first operating system shell — recommended Make /today/ the clear home of the product. Changes: Simplify navigation to: Today Learn Goals Progress More Make Today answer one question: “What should I do next?” Replace the long stacked Today page with a priority layout: Current goal One next action Start session Progress signal Recovery option Move goal creation into a focused onboarding/empty state instead of displaying a large form immediately. Turn Inbox, patterns, and reminders into compact secondary sections. Keep Goals, Focus, Review, Portfolio, and Roadmap as deep workspaces. Apply the same card, spacing, button, form, and empty-state system across all routes. Keep the existing editorial chapter experience intact. Backend/local-state work: Add a single typed local repository boundary. Harden localStorage validation and migrations. Improve backup/restore transaction handling. Make Ollama status and fallback behavior clearer. Add local data health diagnostics. Preserve offline use. Tradeoff: largest visible improvement, but touches navigation and the main execution surfaces. Editorial workspace polish Keep the existing navigation and route structure, but improve every page individually. Changes: Refine each page’s spacing and hierarchy. Upgrade cards, forms, progress indicators, and empty states. Add shared page headers and breadcrumbs. Improve mobile behavior without changing information architecture. Backend/local-state work remains the same. Tradeoff: lowest risk, but the product may still feel like multiple separate tools rather than one coherent operating system. Dashboard-centric command center Make /dashboard/ the main product and move most functionality into a dense professional workspace. Changes: Dashboard becomes a multi-panel command center. Today, Goals, Focus, Review, and Progress become dashboard tabs or panels. More information is visible at once. Strong for desktop power users. Tradeoff: efficient for experienced users but heavier, more complex, and less approachable on mobile."}, {"post_id": 70451, "ts": "2026-09-19T07:02:36Z", "hours": 8.2389, "text": "I thought to keep this as a normal book website for a 20 hr video, until i didnt i wanted to somehow plan to make money out of this, so I am not planning to improve this to a full App and Add pricing and make money out of it. The app is gonna be about implementing the things for the 20 hr video effectively in my website for a lil $. For now everyone can try it our for free on https://hustlenix.github.io/LevelUp"}, {"post_id": 68897, "ts": "2026-09-16T00:04:43Z", "hours": 1.1653, "text": "Me corrently using my own app to study and finish my home work🤣🤣. Youto use it on https://hustlenix.github.io/LevelUp/ for free"}, {"post_id": 67964, "ts": "2026-09-14T09:11:00Z", "hours": 2.6825, "text": "Instead of making this website feel like a simple website like a book, i am on a mission to make this website a full stack website for self improvement and i am thinking of adding paywall and make some money, but stripe isnt working from INDIA someone please help. STAY HARD!!!!!!!!!!!!!!!"}, {"post_id": 66090, "ts": "2026-09-11T17:47:02Z", "hours": 13.0997, "text": "I built a free MVP called Level Up: a 28-chapter self-development book built from a 20-hour video transcript, running entirely in your browser.The Motivation It started with a simple question: What if you could turn a 20-hour self-dev video into something you could actually read, search, and verify? Most online self-development content exists to sell courses, not to present evidence. I wanted something honest. So, I built a real book where every notable claim is graded against cited research.What It Is: Zero Tracking, 100% Local The result is roughly 32k words across four pillars, a 30-claim evidence audit (graded A–D/U), 13 testable protocols, and full-text search.The best part? Zero tracking. No accounts, no APIs, no cookies. Your reading progress, streaks, highlights, themes, and quiz scores live entirely in your browser’s localStorage. Nothing leaves your machine.How We Built It The original video transcript was ~20k lines. We tag-teamed Claude, Gemini, and Opencode to compress it. From there, we built the site in layers:The Content Pipeline: scripts/build-data.mjs compiles Markdown chapters into SQLite using node:sqlite, then emits JSON data and a 30KB MiniSearch index.The Frontend: Next.js 16 static export and Tailwind v4. We used useSyncExternalStore for reactive local state via pure TypeScript modules.The Deploy: Automated via GitHub Actions straight to GitHub Pages.Into the Trenches (Challenges & Learnings)The CI Spiral: We added a React 19 QuoteCard. It built flawlessly locally (22/22 tests green), but failed eight consecutive GitHub Actions runs with a phantom TS error. It wasn’t a code bug; it was an environment disagreement. Lesson: Sometimes a feature just isn’t ready. We deleted it rather than fighting the environment or shipping it broken.Turbopack’s Quiet Types: The dev server uses Turbopack, which skips full type-checking for speed. We shipped a PR that built locally but failed in CI. Lesson: Always run tsc locally, or CI will aggressively remind you of the difference between “builds” and “types.“Case Sensitivity: GitHub Pages serves paths case-sensitively. NEXT_PUBLIC_BASE_PATH=/LevelUp is fundamentally different from /levelup. We learned this the hard way.What I’m Proud OfHonest Grading: No invented citations. If a famous “5x flow” stat is folklore, the site tells you so.Backend-less Magic: Search, quizzes, highlights, streaks, and schema-validated JSON backup/restore—all completely offline-capable.The Architecture: The data layer isn’t just a pile of JSON; it’s a statically served, compiled artifact from Markdown.Try it out:Live site: https://hustlenix.github.io/LevelUp/Source code: https://github.com/Hustlenix/LevelUpTech Stack: Next.js 16, Tailwind v4, node:sqlite, MiniSearch, GitHub Pages"}, {"post_id": 50297, "ts": "2026-08-19T13:37:53Z", "hours": 12.4239, "text": "So called Devlog, 3 The agenda today is to simplify the home page. I paid attention to it for 8 hours and ended up with two fewer things on screen than when I started lol😅✌🏻. After removing the large hero box and changing the chapter list to an accordion, the homepage appeared empty. I created a big wishlists of items to add: heatmaps, quote-generators, streak-trackers, quiz-cards, XP-counters, etc. Everything was built local-first on Next.js 16 (static export on GitHub Pages) using localStorage keys like levelup-streak-v1 no tracking or backend APIs. I constructed a QuoteCard component to retrieve data from /data/quotes.json. All 22 tests passed on my machine, but for some reason, GitHub Actions fails a phantom TS7006 type error 8+ times in a row because of that one CI error. I kept spamming commit messages like “force CI re-run”, “force CI re-re-re-run, and this time ts-ignore…”. It turned out to be a weird CI environment mismatch that ate half my day. I discarded the quote card to avoid clutter. In what was shipped was a simple PrivacyBadge (“100% Private · On-Device Storage Only”) along with a ThemeTimeShift script that alters the –hue CSS variable based off your clock. Next thing we must do is transition smoothly into the chapter! Stay techulated or smtg. STAY HARD GNG!"}, {"post_id": 47521, "ts": "2026-08-15T14:15:55Z", "hours": 0.4181, "text": "Finished writing the git hub repo, and used AI to organise the words cause it was full of gramatical mistakes and stuff. I am ready to ship this project GNG, what did I miss, please check this out and give some valid review please."}, {"post_id": 47501, "ts": "2026-08-15T13:29:22Z", "hours": 13.9158, "text": "This is my trust worthy, non tracked website for leveling up in your life but somehow works without any login or stuff, the tracking just works, inspired by this 20 hour video: https://www.youtube.com/watch?v=wvaY5bG5p7A&t=65s which is totally worth it. To build this I started by getting the transcript for making this website, and with that 20k lines transcript I pasted it into claude to compact this, and it ran out of tokens, and i tried gemini too sadly it too ran out of tokens, and lastly I tried Opencode few time and it finally gave me the summary for this and after few hours i finished the website and pushed the code to git hub, branched it real good, and finally build and in actions started a build and deploy workflow and got this running. STAY HARD GNG!!!!!!!!"}]...
|
Title: Level Up by @Lalith | Stardance
Devlogs:
T Title: Level Up by @Lalith | Stardance
Devlogs:
This is my trust worthy, non tracked website for leveling up in your life but somehow works without any login or stuff, the tracking just works, inspired by this 20 hour video: https://www.youtube.com/watch?v=wvaY5bG5p7A&t=65s which is totally worth it. To build this I started by getting the transcript for making this website, and with that 20k lines transcript I pasted it into claude to compact this, and it ran out of tokens, and i tried gemini too sadly it too ran out of tokens, and lastly I tried Opencode few time and it finally gave me the summary for this and after few hours i finished the website and pushed the code to git hub, branched it real good, and finally build and in actions started a build and deploy workflow and got this running. STAY HARD GNG!!!!!!!!
Finished writing the git hub repo, and used AI to organise the words cause it was full of gramatical mistakes and stuff. I am ready to ship this project GNG, what did I miss, please check this out and give some valid review please.
So called Devlog, 3 The agenda today is to simplify the home page. I paid attention to it for 8 hours and ended up with two fewer things on screen than when I started lol😅✌🏻. After removing the large hero box and changing the chapter list to an accordion, the homepage appeared empty. I created a big wishlists of items to add: heatmaps, quote-generators, streak-trackers, quiz-cards, XP-counters, etc. Everything was built local-first on Next.js 16 (static export on GitHub Pages) using localStorage keys like levelup-streak-v1 no tracking or backend APIs. I constructed a QuoteCard component to retrieve data from /data/quotes.json. All 22 tests passed on my machine, but for some reason, GitHub Actions fails a phantom TS7006 type error 8+ times in a row because of that one CI error. I kept spamming commit messages like “force CI re-run”, “force CI re-re-re-run, and this time ts-ignore…”. It turned out to be a weird CI environment mismatch that ate half my day. I discarded the quote card to avoid clutter. In what was shipped was a simple PrivacyBadge (“100% Private · On-Device Storage Only”) along with a ThemeTimeShift script that alters the –hue CSS variable based off your clock. Next thing we must do is transition smoothly into the chapter! Stay techulated or smtg. STAY HARD GNG!
I built a free MVP called Level Up: a 28-chapter self-development book built from a 20-hour video transcript, running entirely in your browser.The Motivation It started with a simple question: What if you could turn a 20-hour self-dev video into something you could actually read, search, and verify? Most online self-development content exists to sell courses, not to present evidence. I wanted something honest. So, I built a real book where every notable claim is graded against cited research.What It Is: Zero Tracking, 100% Local The result is roughly 32k words across four pillars, a 30-claim evidence audit (graded A–D/U), 13 testable protocols, and full-text search.The best part? Zero tracking. No accounts, no APIs, no cookies. Your reading progress, streaks, highlights, themes, and quiz scores live entirely in your browser’s localStorage. Nothing leaves your machine.How We Built It The original video transcript was ~20k lines. We tag-teamed Claude, Gemini, and Opencode to compress it. From there, we built the site in layers:The Content Pipeline: scripts/build-data.mjs compiles Markdown chapters into SQLite using node:sqlite, then emits JSON data and a 30KB MiniSearch index.The Frontend: Next.js 16 static export and Tailwind v4. We used useSyncExternalStore for reactive local state via pure TypeScript modules.The Deploy: Automated via GitHub Actions straight to GitHub Pages.Into the Trenches (Challenges & Learnings)The CI Spiral: We added a React 19 QuoteCard. It built flawlessly locally (22/22 tests green), but failed eight consecutive GitHub Actions runs with a phantom TS error. It wasn’t a code bug; it was an environment disagreement. Lesson: Sometimes a feature just isn’t ready. We deleted it rather than fighting the environment or shipping it broken.Turbopack’s Quiet Types: The dev server uses Turbopack, which skips full type-checking for speed. We shipped a PR that built locally but failed in CI. Lesson: Always run tsc locally, or CI will aggressively remind you of the difference between “builds” and “types.“Case Sensitivity: GitHub Pages serves paths case-sensitively. NEXT_PUBLIC_BASE_PATH=/LevelUp is fundamentally different from /levelup. We learned this the hard way.What I’m Proud OfHonest Grading: No invented citations. If a famous “5x flow” stat is folklore, the site tells you so.Backend-less Magic: Search, quizzes, highlights, streaks, and schema-validated JSON backup/restore—all completely offline-capable.The Architecture: The data layer isn’t just a pile of JSON; it’s a statically served, compiled artifact from Markdown.Try it out:Live site: https://hustlenix.github.io/LevelUp/Source code: https://github.com/Hustlenix/LevelUpTech Stack: Next.js 16, Tailwind v4, node:sqlite, MiniSearch, GitHub Pages
Instead of making this website feel like a simple website like a book, i am on a mission to make this website a full stack website for self improvement and i am thinking of adding paywall and make some money, but stripe isnt working from INDIA someone please help. STAY HARD!!!!!!!!!!!!!!!
Me corrently using my own app to study and finish my home work🤣🤣. Youto use it on https://hustlenix.github.io/LevelUp/ for free
I thought to keep this as a normal book website for a 20 hr video, until i didnt i wanted to somehow plan to make money out of this, so I am not planning to improve this to a full App and Add pricing and make money out of it. The app is gonna be about implementing the things for the 20 hr video effectively in my website for a lil $. For now everyone can try it our for free on https://hustlenix.github.io/LevelUp
Till now for my app i have like genrated the overall Backend and front end, but the frontend UI/UX is kinda mid. so i am thinking of improving it and opt for te second ship. In UI/UX i am thinking of doind this: 1. Today-first operating system shell — recommended Make /today/ the clear home of the product. Changes: Simplify navigation to: Today Learn Goals Progress More Make Today answer one question: “What should I do next?” Replace the long stacked Today page with a priority layout: Current goal One next action Start session Progress signal Recovery option Move goal creation into a focused onboarding/empty state instead of displaying a large form immediately. Turn Inbox, patterns, and reminders into compact secondary sections. Keep Goals, Focus, Review, Portfolio, and Roadmap as deep workspaces. Apply the same card, spacing, button, form, and empty-state system across all routes. Keep the existing editorial chapter experience intact. Backend/local-state work: Add a single typed local repository boundary. Harden localStorage validation and migrations. Improve backup/restore transaction handling. Make Ollama status and fallback behavior clearer. Add local data health diagnostics. Preserve offline use. Tradeoff: largest visible improvement, but touches navigation and the main execution surfaces. Editorial workspace polish Keep the existing navigation and route structure, but improve every page individually. Changes: Refine each page’s spacing and hierarchy. Upgrade cards, forms, progress indicators, and empty states. Add shared page headers and breadcrumbs. Improve mobile behavior without changing information architecture. Backend/local-state work remains the same. Tradeoff: lowest risk, but the product may still feel like multiple separate tools rather than one coherent operating system. Dashboard-centric command center Make /dashboard/ the main product and move most functionality into a dense professional workspace. Changes: Dashboard becomes a multi-panel command center. Today, Goals, Focus, Review, and Progress become dashboard tabs or panels. More information is visible at once. Strong for desktop power users. Tradeoff: efficient for experienced users but heavier, more complex, and less approachable on mobile.
I upgraded my MVP called Level Up: transforming a local-first self-development book into a full-featured, Today-first operating system—still running 100% in your browser.The Motivation While Ship #1 proved that a 20-hour video transcript could become a searchable, evidence-graded web book, the feedback was clear: the UI/UX felt fragmented. Having deep individual features wasn’t enough if the home experience didn’t tell you what to do right now. I set out to redesign Level Up from a passive reading interface into an actionable personal operating system.What’s New: The Today-First OS & Local AI Instead of a crowded home screen, the app now centers on a streamlined /today/ hub that answers one core question: “What should I do next?”Today Shell Navigation: Simplified navigation down to Today, Learn, Goals, Progress, and More, placing your current focus front and center.On-Device Study Workspace: Integrated a dedicated Study Mode featuring an automated Daily Planner, a Local Coach, and an interactive Tutor mode to explain or practice any of the 28 chapters.Smart Local AI Integration: Added support for local LLMs via Ollama with full offline fallback, letting you generate study plans and ask questions without leaking private data to external servers.How We Upgraded ItTyped Local State Boundary: Replaced fragmented localStorage usage with a single, typed local repository boundary managed via pure TypeScript modules and useSyncExternalStore.Data Diagnostics & Migrations: Hardened JSON schema validation, improved backup/restore transaction handling, and added local data health checks to ensure offline state never gets corrupted.UI/UX Consistency System: Standardized spacing, card hierarchies, buttons, forms, and empty states across all routes so every tool feels like part of a unified product.Into the Trenches (Challenges & Learnings)The Monolith vs. Workspaces Tradeoff: Moving from a multi-tool dashboard to a focused Today-first layout meant rethinking information architecture. We hid creation forms behind empty states and compressed secondary features like inbox items into compact panels to avoid visual clutter.Local AI Fallbacks: Integrating Ollama required explicit status checks and graceful local degradation so non-technical users or fully offline environments still get a clean UI without broken promises.What I’m Proud OfCoherent OS Feel: Level Up no longer feels like separate utilities tacked together; it operates as one smooth, self-contained habit driver.Privacy Preserved: Despite adding AI study tools and custom daily planners, everything remains zero-tracking, zero-backend, and fully functional on-device.Try it out:Live site: https://hustlenix.github.io/LevelUp/Source code: https://github.com/Hustlenix/LevelUpTech Stack: Next.js 16, Tailwind v4, TypeScript, node:sqlite, MiniSearch, Ollama / On-Device Local State, GitHub Pages
I think there is nothing to be upgraded in this, all i have to do now is add subscryptions and make money!!!!!!!!!!!!
I tried making this the final boss of Self Improvement APP, i think i am finally over, longin and start LEVELING UPPP!!!!!!!!!!!
Finishing touches, i think this is coming to and end, so i lokced in in these 10 hours and did some major changes, like used HCB APi key and give MILO an life so it can interact with you guys, and bumped up the UI/UX to and next level and: Milo Talk with offline guidance and explicit approval before saving suggested actions. Replayable walkthrough and app-wide text sizing up to 150%. Distinct Deep Work/Cyberpunk themes; preserved Light/Dark. Install guidance, offline support, refreshed screenshots, and technical documentation. Fixed Settings headings and Deep Work contrast. As per your reviews and real time feedback, thank you guys!
Ships:
I built a free MVP called Level Up : a 28-chapter self-development book built from a 20-hour video transcript, running entirely in your browser. The Motivation It started with a simple question: What if you could turn a 20-hour self-dev video into something you could actually read, search, and verify? Most online self-development content exists to sell courses, not to present evidence. I wanted something honest. So, I built a real book where every notable claim is graded against cited research. What It Is: Zero Tracking, 100% Local The result is roughly 32k words across four pillars, a 30-claim evidence audit (graded A–D/U), 13 testable protocols, and full-text search. The best part? Zero tracking. No accounts, no APIs, no cookies. Your reading progress, streaks, highlights, themes, and quiz scores live entirely in your browser’s localStorage . Nothing leaves your machine. How We Built It The original video transcript was ~20k lines. We tag-teamed Claude, Gemini, and Opencode to compress it. From there, we built the site in layers: The Content Pipeline: scripts/build-data.mjs compiles Markdown chapters into SQLite using node:sqlite , then emits JSON data and a 30KB MiniSearch index. The Frontend: Next.js 16 static export and Tailwind v4. We used useSyncExternalStore for reactive local state via pure TypeScript modules. The Deploy: Automated via GitHub Actions straight to GitHub Pages. Into the Trenches (Challenges & Learnings) The CI Spiral: We added a React 19 QuoteCard. It built flawlessly locally (22/22 tests green), but failed eight consecutive GitHub Actions runs with a phantom TS error. It wasn’t a code bug; it was an environment disagreement. Lesson: Sometimes a feature just isn’t ready. We deleted it rather than fighting the environment or shipping it broken. Turbopack’s Quiet Types: The dev server uses Turbopack, which skips full type-checking for speed. We shipped a PR that built locally but failed in CI. Lesson: Always run tsc locally, or CI will aggressively remind you of the difference between “builds” and “types.” Case Sensitivity: GitHub Pages serves paths case-sensitively. NEXT_PUBLIC_BASE_PATH=/LevelUp is fundamentally different from /levelup . We learned this the hard way. What I’m Proud Of Honest Grading: No invented citations. If a famous “5x flow” stat is folklore, the site tells you so. Backend-less Magic: Search, quizzes, highlights, streaks, and schema-validated JSON backup/restore—all completely offline-capable. The Architecture: The data layer isn’t just a pile of JSON; it’s a statically served, compiled artifact from Markdown. Try it out: Live site: https://hustlenix.github.io/LevelUp/ Source code: https://github.com/Hustlenix/LevelUp Tech Stack: Next.js 16, Tailwind v4, node:sqlite, MiniSearch, GitHub Pages
I upgraded my MVP called Level Up: transforming a local-first self-development book into a full-featured, Today-first operating system—still running 100% in your browser. The Motivation While Ship #1 proved that a 20-hour video transcript could become a searchable, evidence-graded web book, the feedback was clear: the UI/UX felt fragmented. Having deep individual features wasn’t enough if the home experience didn’t tell you what to do right now. I set out to redesign Level Up from a passive reading interface into an actionable personal operating system. What’s New: The Today-First OS & Local AI Instead of a crowded home screen, the app now centers on a streamlined /today/ hub that answers one core question: “What should I do next?” Today Shell Navigation: Simplified navigation down to Today, Learn, Goals, Progress, and More, placing your current focus front and center. On-Device Study Workspace: Integrated a dedicated Study Mode featuring an automated Daily Planner, a Local Coach, and an interactive Tutor mode to explain or practice any of the 28 chapters. Smart Local AI Integration: Added support for local LLMs via Ollama with full offline fallback, letting you generate study plans and ask questions without leaking private data to external servers. How We Upgraded It Typed Local State Boundary: Replaced fragmented localStorage usage with a single, typed local repository boundary managed via pure TypeScript modules and useSyncExternalStore. Data Diagnostics & Migrations: Hardened JSON schema validation, improved backup/restore transaction handling, and added local data health checks to ensure offline state never gets corrupted. UI/UX Consistency System: Standardized spacing, card hierarchies, buttons, forms, and empty states across all routes so every tool feels like part of a unified product. Into the Trenches (Challenges & Learnings) The Monolith vs. Workspaces Tradeoff: Moving from a multi-tool dashboard to a focused Today-first layout meant rethinking information architecture. We hid creation forms behind empty states and compressed secondary features like inbox items into compact panels to avoid visual clutter. Local AI Fallbacks: Integrating Ollama required explicit status checks and graceful local degradation so non-technical users or fully offline environments still get a clean UI without broken promises. What I’m Proud Of Coherent OS Feel: Level Up no longer feels like separate utilities tacked together; it operates as one smooth, self-contained habit driver. Privacy Preserved: Despite adding AI study tools and custom daily planners, everything remains zero-tracking, zero-backend, and fully functional on-device. Try it out: Live site: https://hustlenix.github.io/LevelUp/ Source code: https://github.com/Hustlenix/LevelUp Tech Stack: Next.js 16, Tailwind v4, TypeScript, node:sqlite, MiniSearch, Ollama / On-Device Local State, GitHub Pages
This is my final ship for Level Up. Level Up originally started as a simple idea: turn a 20-hour self-improvement video into something I could actually read, search, understand, and use. It started as basically a local-first book. Over time I kept asking the same question: “How do I make this useful after someone finishes reading?” So I kept rebuilding it. Now Level Up is much closer to a complete self-improvement app. The main experience is built around Today — you open the app, see what you are working toward, get a clear next action, start a focus/study session, and track your progress instead of just consuming more content. I also added Goals, Progress, Study Mode, a daily planner, tutor/coach tools, local AI through Ollama, chapter search, quizzes, streaks, highlights, backups, restore, and a much more consistent UI across the app. The hardest part was making all of this work while keeping the original idea of Level Up: no account required, no cloud database, and your personal progress stays on your device. I had to rebuild a lot of the local state system, handle migrations and corrupted data, improve backup/restore, and make sure the app still works properly offline or without local AI installed. The thing I’m most proud of is that it no longer feels like a book with random features added around it. It finally feels like one connected product. If you test it, don’t just click around. Actually use it: Create a goal Open Today and follow the next action Start a focus/study session Read or study a chapter Check your Progress Refresh/reopen the app and see your data persist There are definitely things I could keep polishing forever, but I don’t want this project to become an endless cycle of “one more redesign.” This is the version I’m calling finished. Try it: https://hustlenix.github.io/LevelUp/ Source: https://github.com/Hustlenix/LevelUp Thanks to everyone who tested it, gave feedback, or followed the devlogs while this went from a small reading website into this. LEVEL UP. 🚀
Shipped LevelUp! It started as a way to make a long self-development video easier to read. Now it has 28 chapters, practical plans, habits, focus timers, and a daily mission system. You can save an idea from a chapter and actually try it instead of forgetting it five minutes later. Milo is the little companion that reacts to your reading and focus activity. Everything important works locally, without an account or trackers. There’s also an offline progress system called Nexus, which handles changes across tabs and lets you move progress using encrypted files. This update mostly brought the different parts together. I fixed mobile layouts, added larger text and a quick tutorial, and made backups include the newer features. Cloud chat still needs work, and the app could be simpler, but the full version is live now. Try it: https://hustlenix.github.io/LevelUp/...
|
1793004590.0500307
|
1793090990.0500307
|
|
70575
|
JuniorOS by @danielkosar | Stardance
|
danielkosar
|
0
|
10.77
|
0
|
[]
|
[{"post_id": 81167, "ts": "202 [{"post_id": 81167, "ts": "2026-10-20T05:25:51Z", "hours": 10.7706, "text": "So i made a basic web OS, where you will get met up with the welcome screen and when you click welcome, you will get into the OS for now there is a working file system, notebook app, settings tab of the OS"}]...
|
Title: JuniorOS by @danielkosar | Stardance
Devlo Title: JuniorOS by @danielkosar | Stardance
Devlogs:
So i made a basic web OS, where you will get met up with the welcome screen and when you click welcome, you will get into the OS for now there is a working file system, notebook app, settings tab of the OS...
|
1793119678.7039661
|
1793724478.7039661
|