|
38017
|
Frictionless by @joelj | Stardance
|
joelj
|
2
|
3.0
|
33
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-13T15:48:25Z", "hours": 0.0, "multiplier": 6.97, "payout": 3, "blessing": "neutral", "text": "I made a Pygame code checker . š it helps out the hardworking coders to find out hidden bugs that can be annoying to deal with. My project brilliantly use pythonās built in AST to check code line by line , it detects unmonitored loops that might fry your pc , Hardcoded window sizes so that you u can easily change it and many more! I faced many challenges , the prominent one was outside the computerā¦Finding time to code , i was struggling to balance school and coding , but at last i did it . š„³ Thank you all for looking at my project and hope you all liked it š", "repo": "https://github.com/Johan-jim123/pygame-code-inspector", "demo": "https://pygame-code-inspector.vercel.app/"}, {"ship_num": 2, "ts": "2026-07-30T16:05:44Z", "hours": 3.0, "multiplier": 9.85, "payout": 30, "blessing": "neutral", "text": "I built a web tool designed to make life easier for Pygame developers: the Pygame Code Inspector. Instead of running a game script, waiting for it to crash, or spending hours searching for sneaky performance bugs, you can just paste your Python code directly into the app. It uses Pythonās built-in ast (Abstract Syntax Tree) module to parse your code safely without executing it. In seconds, it checks for missing initialization/quit calls, unmonitored infinite loops, hardcoded window sizes, uncapped frame rates, and memory leaks from unused assets. Then, it gives your project a clean Code Health Score (0ā100) and a letter grade (A through F) so you immediately know what to fix. š ļø What Was Challenging Safe Code Parsing: Getting the ast visitor logic working to reliably detect anti-patternsālike unmonitored while loops or dangling pygame.mixer assetsāwithout actually running user-submitted code required careful structural logic. Deployment Realities: Uploading the project to GitHub threw a few curveballs! I accidentally dragged an entire virtual environment folder with thousands of extra files at first, and later hit a tricky ModuleNotFoundError on Streamlit Cloud caused by a subtle uppercase/lowercase mismatch in my filenames (Code_Checker.py vs. code_checker.py). Diagnosing and fixing environment issues in Linux deployment environments was a huge learning moment. ⨠What Iām Proud Of Zero-Setup Web Access: Turning a local Python script into a fully hosted, interactive web application on Streamlit Cloud that anyone can access in their browser with zero local setup. Actionable Developer Feedback: Creating a tool that isnāt just a basic syntax checker, but an actual quality-of-life upgrade for game devs that translates technical code analysis into an easy-to-understand score and grade. Full Open-Source Setup: Shipping the full package from scratchāclean repo structure, proper requirements.txt, clear README documentation, and an MIT License. -summary created by gemini because im too lazy to write", "repo": "https://github.com/Johan-jim123/pygame-code-inspector", "demo": "https://pygame-code-inspector.vercel.app/"}]...
|
[{"post_id": 45679, "ts": "202 [{"post_id": 45679, "ts": "2026-08-12T10:14:52Z", "hours": 0.4161, "text": "Finally finished , worked on the issues and changed the colour scheme . thanks for the support guys"}, {"post_id": 35290, "ts": "2026-07-26T16:31:02Z", "hours": 2.2919, "text": "Over the past few days, I built and launched Pygame Code Inspector, an automated static analysis web app that checks Pygame scripts for common bugs, bad practices, and performance bottlenecksāall without needing to run the code. Using Pythonās built-in ast (Abstract Syntax Tree) module, the backend parses source code in real time to catch missing setup/teardown calls (pygame.init() / pygame.quit()), unmonitored game loops, uncapped frame rates, hardcoded resolutions, unused memory assets, and missing error handling. It aggregates these checks into a clean 0ā100 health score and assigns an overall letter grade (A through F).Once the core inspector logic was solid, I built an interactive frontend using Streamlit so users can paste their code directly into the browser for instant feedback. After setting up open-source documentation under an MIT License, I pushed the repository to GitHub and deployed it live via Streamlit Cloud. Navigating server-side requirements and case-sensitive imports on Linux was a great learning experience, but seeing the app live on the web and giving instant feedback on real Pygame code made it completely worth it!"}, {"post_id": 32434, "ts": "2026-07-21T16:42:30Z", "hours": 0.7286, "text": "Hey everyone! Iām a 9th-grade developer logging my first 40-minute Hackatime session for Stardance on my journey to earn 90 Stardust points for a Google Play Developer License. Iām building an Automated Code Health Checker in Pythonāa pre-flight tool that scans project files line-by-line to catch missing frame-rate caps (.tick()), unmonitored infinite loops, and missing error handlers (try/except) before you even run your code. The core terminal inspector is live and running in PyCharm, and my next step is building out a full visual diagnostic UI!"}]...
|
Title: Frictionless by @joelj | Stardance
Devlogs Title: Frictionless by @joelj | Stardance
Devlogs:
Hey everyone! Iām a 9th-grade developer logging my first 40-minute Hackatime session for Stardance on my journey to earn 90 Stardust points for a Google Play Developer License. Iām building an Automated Code Health Checker in Pythonāa pre-flight tool that scans project files line-by-line to catch missing frame-rate caps (.tick()), unmonitored infinite loops, and missing error handlers (try/except) before you even run your code. The core terminal inspector is live and running in PyCharm, and my next step is building out a full visual diagnostic UI!
Over the past few days, I built and launched Pygame Code Inspector, an automated static analysis web app that checks Pygame scripts for common bugs, bad practices, and performance bottlenecksāall without needing to run the code. Using Pythonās built-in ast (Abstract Syntax Tree) module, the backend parses source code in real time to catch missing setup/teardown calls (pygame.init() / pygame.quit()), unmonitored game loops, uncapped frame rates, hardcoded resolutions, unused memory assets, and missing error handling. It aggregates these checks into a clean 0ā100 health score and assigns an overall letter grade (A through F).Once the core inspector logic was solid, I built an interactive frontend using Streamlit so users can paste their code directly into the browser for instant feedback. After setting up open-source documentation under an MIT License, I pushed the repository to GitHub and deployed it live via Streamlit Cloud. Navigating server-side requirements and case-sensitive imports on Linux was a great learning experience, but seeing the app live on the web and giving instant feedback on real Pygame code made it completely worth it!
Finally finished , worked on the issues and changed the colour scheme . thanks for the support guys
Ships:
I built a web tool designed to make life easier for Pygame developers: the Pygame Code Inspector. Instead of running a game script, waiting for it to crash, or spending hours searching for sneaky performance bugs, you can just paste your Python code directly into the app. It uses Pythonās built-in ast (Abstract Syntax Tree) module to parse your code safely without executing it. In seconds, it checks for missing initialization/quit calls, unmonitored infinite loops, hardcoded window sizes, uncapped frame rates, and memory leaks from unused assets. Then, it gives your project a clean Code Health Score (0ā100) and a letter grade (A through F) so you immediately know what to fix. š ļø What Was Challenging Safe Code Parsing: Getting the ast visitor logic working to reliably detect anti-patternsālike unmonitored while loops or dangling pygame.mixer assetsāwithout actually running user-submitted code required careful structural logic. Deployment Realities: Uploading the project to GitHub threw a few curveballs! I accidentally dragged an entire virtual environment folder with thousands of extra files at first, and later hit a tricky ModuleNotFoundError on Streamlit Cloud caused by a subtle uppercase/lowercase mismatch in my filenames (Code_Checker.py vs. code_checker.py). Diagnosing and fixing environment issues in Linux deployment environments was a huge learning moment. ⨠What Iām Proud Of Zero-Setup Web Access: Turning a local Python script into a fully hosted, interactive web application on Streamlit Cloud that anyone can access in their browser with zero local setup. Actionable Developer Feedback: Creating a tool that isnāt just a basic syntax checker, but an actual quality-of-life upgrade for game devs that translates technical code analysis into an easy-to-understand score and grade. Full Open-Source Setup: Shipping the full package from scratchāclean repo structure, proper requirements.txt, clear README documentation, and an MIT License. -summary created by gemini because im too lazy to write
I made a Pygame code checker . š it helps out the hardworking coders to find out hidden bugs that can be annoying to deal with. My project brilliantly use pythonās built in AST to check code line by line , it detects unmonitored loops that might fry your pc , Hardcoded window sizes so that you u can easily change it and many more! I faced many challenges , the prominent one was outside the computerā¦Finding time to code , i was struggling to balance school and coding , but at last i did it . š„³ Thank you all for looking at my project and hope you all liked it š...
|
1793505126.1572256
|
1793591526.1572256
|
|
29024
|
NimbusLoft by @SML_365 | Stardance
|
SML_365
|
2
|
11.77
|
169
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-06T21:26:26Z", "hours": 2.0, "multiplier": 8.76, "payout": 21, "blessing": "neutral", "text": "Ship #2 for NimbusLoft - A visual clipboard engine This is NimbusLofts ship for v1.2.0. NimbusLoft is a Python-based visual clipboard for all the files you need to use, but donāt want to go hunting in your filesystem for. Just drag them to the dock, and they get saved instantly. This ship includes: Colored files URL saving (Thank you to an anonymous reviewer for this idea!) Bugfixes File size display And more, which you can try out by downloading the executable on GitHub! Please note that NimbusLoft is intended for 64-bit Windows systems.", "repo": "https://github.com/SML365/NimbusLoft", "demo": "https://github.com/SML365/NimbusLoft/releases/"}, {"ship_num": 2, "ts": "2026-07-02T04:51:07Z", "hours": 8.0, "multiplier": 18.75, "payout": 148, "blessing": "neutral", "text": "I made a utility dock for storing temporary files so you donāt have to juggle three instances of File Explorer.", "repo": "https://github.com/SML365/NimbusLoft", "demo": "https://github.com/SML365/NimbusLoft/releases/"}]...
|
[{"post_id": 70117, "ts": "202 [{"post_id": 70117, "ts": "2026-09-18T14:32:24Z", "hours": 1.7656, "text": "Devlog #6 for NimbusLoft It was mainly just bug fixes. I fixed a couple of style issues as well as the version number. I also made it slightly more stable. No new features were added. Anyways, thatās it from me, and have a nice day/night!"}, {"post_id": 23733, "ts": "2026-07-06T21:04:28Z", "hours": 1.31, "text": "Devlog #5 for NimbusLoft - A visual clipboard engine NimbusLoft is a Python-based visual clipboard for all the files you need to use, but donāt want to go hunting in your filesystem for. Just drag them to the dock, and they get saved instantly. This devlog is focused on adding URL saving and loading support and stabilizing existing features, along with the releases of v1.1.1 and v2.1.0, available to try on GitHub! Added: URL saving and loading: You can now drag in URLs to save, drag them out into a browser, and open them with the browser. Everything shoulf work as expected 1-second pause before hiding the window upon startup: It helps first-time users find where NimbusLoft is located on their screen, since it might be different depending on monitor setups Adjusted color-code colors: The purple was a bit too strong, and Iāll be adjusting the yellow in an upcoming stability fix (v1.2.1) to make it a bit less green Upcoming: Settings menu (v2.0.0 planned) Persistent items (v2.0.0 planned) Search and Sort functionality (also mentioned in Devlog #4 ) (v2.0.0 planned) Multi-monitor support (v1.4.0 planned) Custom thumbnails for URLs depending on webpage (v1.3.0 planned)"}, {"post_id": 23255, "ts": "2026-07-06T03:11:47Z", "hours": 1.1003, "text": "Devlog #4 for NimbusLoft - A visual clipboard engine NimbusLoft is a Python-based visual clipboard for all the files you need to use, but donāt want to go hunting in your filesystem for. Just drag them to the dock, and they get saved instantly. This devlog is focused on getting all the features working for the v1.1.0 release, available to try on GitHub! Added: Right click context menu for each file entry, with options to open and remove file, as well as color changes Change background color of file for organization, with over 6 color options (as well as the default color) Contextual title also shows file size along with full file name Upcoming: Sort by color to improve organization Search functionality (sort) Settings panel to configure options such as auto startup, themes, and more"}, {"post_id": 20525, "ts": "2026-07-02T04:24:09Z", "hours": 1.5339, "text": "Devlog #3 for NimbusLoft - A visual clipboard engine NimbusLoft is a Python-based visual clipboard for all the files you need to use, but donāt want to go hunting in your filesystem for. Just drag them to the dock, and they get saved instantly. This devlog is focused on getting everything up and running for the v1.0.0 release, available to try on GitHub! Done: Horizontal scrolling Clear button now works Stability improvements Common filetypes tested (.mp3, .mp4, .png, .jpg, .html) Folders tested Upcoming (In later versions): Theming More stability improvements Removed: Settings button (Maybe coming in later versions)"}, {"post_id": 20287, "ts": "2026-07-01T20:55:22Z", "hours": 3.5933, "text": "Devlog #2 for NimbusLoft - A visual clipboard engine NimbusLoft is a Python-based visual clipboard for all the files you need to use, but donāt want to go hunting in your filesystem for. Just drag them to the dock, and they get saved instantly. This devlog was mostly focused on implementing the file drag/drop and having it all showing up. The next high-priority update involves adding a scrolling shelf, a vital element needed to actually make NimbusLoft scale. Done: File drag + drop Folder drag + drop File cards with icons Blurred background Updated styling Upcoming: Drag out to paste Paste whole folders at once Scrolling shelf! Settings panel Clear button functionality Maybe Adding: Custom icons Context menu for each file with remove, copy, delete, etc. functionality"}, {"post_id": 19699, "ts": "2026-07-01T02:47:31Z", "hours": 2.7972, "text": "Devlog #1 for NimbusLoft - A visual clipboard engine NimbusLoft is a Python-based visual clipboard for all the files you need to use, but donāt want to go hunting in your filesystem for. Just drag them to the dock, and they get saved instantly. Done: Basic structure Quit button Transparent UI language Hides in alt+tab menu / taskbar Upcoming: Clear button File drag + drop support Show + hide when the mouse touches the top of the screen Settings menu Title and filename preview in the remaining space in the top of the bar"}]...
|
Title: NimbusLoft by @SML_365 | Stardance
Devlogs Title: NimbusLoft by @SML_365 | Stardance
Devlogs:
Devlog #1 for NimbusLoft - A visual clipboard engine NimbusLoft is a Python-based visual clipboard for all the files you need to use, but donāt want to go hunting in your filesystem for. Just drag them to the dock, and they get saved instantly. Done: Basic structure Quit button Transparent UI language Hides in alt+tab menu / taskbar Upcoming: Clear button File drag + drop support Show + hide when the mouse touches the top of the screen Settings menu Title and filename preview in the remaining space in the top of the bar
Devlog #2 for NimbusLoft - A visual clipboard engine NimbusLoft is a Python-based visual clipboard for all the files you need to use, but donāt want to go hunting in your filesystem for. Just drag them to the dock, and they get saved instantly. This devlog was mostly focused on implementing the file drag/drop and having it all showing up. The next high-priority update involves adding a scrolling shelf, a vital element needed to actually make NimbusLoft scale. Done: File drag + drop Folder drag + drop File cards with icons Blurred background Updated styling Upcoming: Drag out to paste Paste whole folders at once Scrolling shelf! Settings panel Clear button functionality Maybe Adding: Custom icons Context menu for each file with remove, copy, delete, etc. functionality
Devlog #3 for NimbusLoft - A visual clipboard engine NimbusLoft is a Python-based visual clipboard for all the files you need to use, but donāt want to go hunting in your filesystem for. Just drag them to the dock, and they get saved instantly. This devlog is focused on getting everything up and running for the v1.0.0 release, available to try on GitHub! Done: Horizontal scrolling Clear button now works Stability improvements Common filetypes tested (.mp3, .mp4, .png, .jpg, .html) Folders tested Upcoming (In later versions): Theming More stability improvements Removed: Settings button (Maybe coming in later versions)
Devlog #4 for NimbusLoft - A visual clipboard engine NimbusLoft is a Python-based visual clipboard for all the files you need to use, but donāt want to go hunting in your filesystem for. Just drag them to the dock, and they get saved instantly. This devlog is focused on getting all the features working for the v1.1.0 release, available to try on GitHub! Added: Right click context menu for each file entry, with options to open and remove file, as well as color changes Change background color of file for organization, with over 6 color options (as well as the default color) Contextual title also shows file size along with full file name Upcoming: Sort by color to improve organization Search functionality (sort) Settings panel to configure options such as auto startup, themes, and more
Devlog #5 for NimbusLoft - A visual clipboard engine NimbusLoft is a Python-based visual clipboard for all the files you need to use, but donāt want to go hunting in your filesystem for. Just drag them to the dock, and they get saved instantly. This devlog is focused on adding URL saving and loading support and stabilizing existing features, along with the releases of v1.1.1 and v2.1.0, available to try on GitHub! Added: URL saving and loading: You can now drag in URLs to save, drag them out into a browser, and open them with the browser. Everything shoulf work as expected 1-second pause before hiding the window upon startup: It helps first-time users find where NimbusLoft is located on their screen, since it might be different depending on monitor setups Adjusted color-code colors: The purple was a bit too strong, and Iāll be adjusting the yellow in an upcoming stability fix (v1.2.1) to make it a bit less green Upcoming: Settings menu (v2.0.0 planned) Persistent items (v2.0.0 planned) Search and Sort functionality (also mentioned in Devlog #4 ) (v2.0.0 planned) Multi-monitor support (v1.4.0 planned) Custom thumbnails for URLs depending on webpage (v1.3.0 planned)
Devlog #6 for NimbusLoft It was mainly just bug fixes. I fixed a couple of style issues as well as the version number. I also made it slightly more stable. No new features were added. Anyways, thatās it from me, and have a nice day/night!
Ships:
I made a utility dock for storing temporary files so you donāt have to juggle three instances of File Explorer.
Ship #2 for NimbusLoft - A visual clipboard engine This is NimbusLofts ship for v1.2.0. NimbusLoft is a Python-based visual clipboard for all the files you need to use, but donāt want to go hunting in your filesystem for. Just drag them to the dock, and they get saved instantly. This ship includes: Colored files URL saving (Thank you to an anonymous reviewer for this idea!) Bugfixes File size display And more, which you can try out by downloading the executable on GitHub! Please note that NimbusLoft is intended for 64-bit Windows systems....
|
1793505120.989491
|
1793591520.989491
|
|
21768
|
Hacky by @emmanuell | Stardance
|
emmanuell
|
1
|
0.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-20T13:12:53Z", "hours": 0.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "A custom mechanical macropad built on the Seeed XIAO RP2040, running QMK/VIA firmware.", "repo": "https://github.com/hacker9335/hacky", "demo": ""}]...
|
[{"post_id": 12012, "ts": "202 [{"post_id": 12012, "ts": "2026-06-19T16:28:16Z", "hours": 0.4033, "text": "uhm dun w everytng irdk how all this wrks so like jus posting this to like ship it"}]...
|
Title: Hacky by @emmanuell | Stardance
Devlogs:
u Title: Hacky by @emmanuell | Stardance
Devlogs:
uhm dun w everytng irdk how all this wrks so like jus posting this to like ship it
Ships:
A custom mechanical macropad built on the Seeed XIAO RP2040, running QMK/VIA firmware....
|
1793505119.9646633
|
1793591519.9646633
|
|
31246
|
Pick-A-Path by @Charlie_Coder | Stardance
|
Charlie_Coder
|
2
|
11.0
|
95
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-21T04:17:31Z", "hours": 4.0, "multiplier": 5.16, "payout": 19, "blessing": "neutral", "text": "Pick-A-Path: I have created a simple pick-a-path website game :) I have made a pick-a-path game with simple storylines that the user transports through. It is a website-based game hosted by myself. Why: I am not a particularly good storyteller, but my goal with this was to improve my understanding of html, CSS, and JavaScript. How to use Click try project, and you will be transported to my website! The scaling should be fine for most screens. If the sizing doesnāt seem right to you, you can judge proportions off my screenshots (that is how intended). Select a level (I recommend starting at level 1) Read the story, and press the buttons to make your decisions as you go through the story Once you finish a level, it will make the level button go green (using localstorage) to keep track of completed levels. Thank you for having the time to read this, and I hope you love it :)", "repo": "https://github.com/CharlieLindsay/pickapath", "demo": "https://pickapath.charleilei.dpdns.org"}, {"ship_num": 2, "ts": "2026-07-11T09:10:57Z", "hours": 7.0, "multiplier": 11.7, "payout": 76, "blessing": "neutral", "text": "Pick-A-Path A simple pick-a-path website game :) What I have made: I have made a pick-a-path game website, with simple storylines that the user transports through. Why: I am not a particularly good storyteller, but my goal with this was to improve my understanding of html, CSS, and JavaScript. How to use Click try project, and you will be transported to my website! The scaling should be fine for most screens. If the sizing doesnāt seem right to you, you can judge proportions off my screenshots (that is how intended). Select a level (I recommend starting at level 1) Read the story, and press the buttons to make your decisions as you go through the story Thank you for having the time to read this, and I hope you love it :)", "repo": "https://github.com/CharlieLindsay/pickapath", "demo": "https://pickapath.charleilei.dpdns.org"}]...
|
[{"post_id": 32165, "ts": "202 [{"post_id": 32165, "ts": "2026-07-21T04:15:28Z", "hours": 0.5828, "text": "I have done lots of small touch-ups, fixes, and other small adjustments like making the completion saving to localstorage work in all cases. I also slightly changed the README, and changed the screenshot there. I am ready for my second ship!"}, {"post_id": 31669, "ts": "2026-07-20T08:36:40Z", "hours": 1.0203, "text": "This took a lot of effort, but I have finally got it so the site remembers what levels you have completed! (Through localstorage). The level in question goes green after it has been completed some way or another. Failing the level doesnāt count."}, {"post_id": 31641, "ts": "2026-07-20T06:27:04Z", "hours": 0.4992, "text": "I have improved some of the CSS. One of the problems I had was with the āaboutā part on my main screen being over top of other containers with different scaled screens. I made some improvements for that. I also changed some colours, including with the buttons. I made it so the header slightly fades on hover. I also did some other minor changes."}, {"post_id": 31044, "ts": "2026-07-19T03:48:03Z", "hours": 0.2644, "text": "I made some UI changes. I did some others changes, but my main goal was to start on the user interface and CSS. I have made some changes, including changing the top header margin, the colours, and the font family (I got one from Google Fonts)."}, {"post_id": 30574, "ts": "2026-07-18T08:28:32Z", "hours": 0.4794, "text": "I have made some slight improvements to the header and, also, I have made it so every level links back to the menu page. In my demonstration the domain changes. That is because I have a separate domain that caching is bypassing currently for debugging, but the one the site uses is the one still at deployment readiness. (So while I go cmlin.win -> charleilei.dpdns.org, everyone else will stay the same)."}, {"post_id": 30433, "ts": "2026-07-17T23:38:50Z", "hours": 0.8908, "text": "Thanks for all the feedback from the first ship! I appreciate all the help! Here is everything I have done since the last ship: My free domain grant came through, so now I have a domain that I have set on Cloudflare to not cache, allowing me to keep hosting my site fast through cloudflare, while also using the domain for testing. Started working on level four files Improving CSS, following suggestions Updated README slightly Fixed some grammar and incorrect coding I missed (but didnāt affect the visibility at this point) Removed the footer from all the actual level pages as it kind of got in the way in cases, this got mentioned in feedback, and it isnāt really necessary, so it is only on the main page What I plan to do: I didnāt get any feedback about not enough stories, so that isnāt a priority here (but eventually I will do a lot more with the levels IMPORTANT: I did get a lot of feedback about improving the UI and CSS, and keep consistency especially with the rounding of corners Other small adjustments based off feedback Link to the menu through the heading on each page Add images Improve endings Addressing other feedback I got feedback suggesting adding a back button. This is quite a good idea, although I wonāt implement it in this case. Lots of the stories have endings and I donāt think the user should be able to back out. And, in some cases, it goes to a separate html file. In those cases the user can simply press the back button on their browser. Thanks for reading this!"}, {"post_id": 26468, "ts": "2026-07-11T08:51:48Z", "hours": 1.1014, "text": "Changes I have made prior to first ship: Completed the storylines Changed file namings Added more files for story continuing Changed README and screenshot Modified CSS, especially with :hover Other small changes My thoughts I think I am ready to present a first shipment of my project. I may add more in the future, but I am happy with what I have got now. I hope you like it! Below is my introductory ship message properly formatted: Pick-A-Path What I made I have made a pick-a-path game website, with simple storylines that the user transports through. Why I am not a particularly good storyteller, but my goal with this was to improve my understanding of html, CSS, and JavaScript. How I have been coding all this through Visual Studio Code in my browser to my Raspberry Pi through Codeserver I have learned some basics of html through my school, some of which I implemented here How to use Click try project, and you will be transported to my website! The scaling should be fine for most screens. If the sizing doesnāt seem right to you, you can judge proportions off my screenshots (that is how intended). Select a level (I recommend starting at level 1) Read the story, and press the buttons to make your decisions as you go through the story Thank you for having the time to read this, and I hope you love it :)"}, {"post_id": 26412, "ts": "2026-07-11T05:59:19Z", "hours": 0.6231, "text": "Completed level two coding and writing! I have made it more simple for this level with the file structure, as can be seen in the screenshot. There is less JavaScript, and more separate html files, to accommodate for a different storyline than the first one. Also, in this one the left and right JavaScript buttons are swapped around."}, {"post_id": 26396, "ts": "2026-07-11T05:00:52Z", "hours": 1.9219, "text": "Some of the additions I have made Added some different background colours depending on the location of the part of the story Added more to the story, started level 2 Improved some files, and changed JavaScript and also improved readability"}, {"post_id": 25744, "ts": "2026-07-10T05:45:38Z", "hours": 0.9931, "text": "I have done more changes than I can list, but here are some of the main ones: CSS styling improvements Improved the buttons and their animations Added more to the storyline Improved file organisation Added a website icon"}, {"post_id": 25035, "ts": "2026-07-08T23:43:35Z", "hours": 0.4406, "text": "I added more to the storyline and changed some colours."}, {"post_id": 23967, "ts": "2026-07-07T06:24:58Z", "hours": 0.4794, "text": "I have added some more of the story to the pick-a-path and done a lot of file and folder organisation to make it easier to continue to develop."}, {"post_id": 23935, "ts": "2026-07-07T04:30:23Z", "hours": 0.6892, "text": "I have achieved the following: Levels Menu Start of story for level one Buttons that can be selected and activate JavaScript functions A stage tracker Separate html files only once games branch off"}, {"post_id": 23356, "ts": "2026-07-06T08:40:33Z", "hours": 0.3256, "text": "I setup the following: Repo Initialised Hackatime Tracking Main files created Hosting live from my server Made available globally, and disabled Cloudflare caching during development Added title and sub-header Added simple CSS"}]...
|
Title: Pick-A-Path by @Charlie_Coder | Stardance
Title: Pick-A-Path by @Charlie_Coder | Stardance
Devlogs:
I setup the following: Repo Initialised Hackatime Tracking Main files created Hosting live from my server Made available globally, and disabled Cloudflare caching during development Added title and sub-header Added simple CSS
I have achieved the following: Levels Menu Start of story for level one Buttons that can be selected and activate JavaScript functions A stage tracker Separate html files only once games branch off
I have added some more of the story to the pick-a-path and done a lot of file and folder organisation to make it easier to continue to develop.
I added more to the storyline and changed some colours.
I have done more changes than I can list, but here are some of the main ones: CSS styling improvements Improved the buttons and their animations Added more to the storyline Improved file organisation Added a website icon
Some of the additions I have made Added some different background colours depending on the location of the part of the story Added more to the story, started level 2 Improved some files, and changed JavaScript and also improved readability
Completed level two coding and writing! I have made it more simple for this level with the file structure, as can be seen in the screenshot. There is less JavaScript, and more separate html files, to accommodate for a different storyline than the first one. Also, in this one the left and right JavaScript buttons are swapped around.
Changes I have made prior to first ship: Completed the storylines Changed file namings Added more files for story continuing Changed README and screenshot Modified CSS, especially with :hover Other small changes My thoughts I think I am ready to present a first shipment of my project. I may add more in the future, but I am happy with what I have got now. I hope you like it! Below is my introductory ship message properly formatted: Pick-A-Path What I made I have made a pick-a-path game website, with simple storylines that the user transports through. Why I am not a particularly good storyteller, but my goal with this was to improve my understanding of html, CSS, and JavaScript. How I have been coding all this through Visual Studio Code in my browser to my Raspberry Pi through Codeserver I have learned some basics of html through my school, some of which I implemented here How to use Click try project, and you will be transported to my website! The scaling should be fine for most screens. If the sizing doesnāt seem right to you, you can judge proportions off my screenshots (that is how intended). Select a level (I recommend starting at level 1) Read the story, and press the buttons to make your decisions as you go through the story Thank you for having the time to read this, and I hope you love it :)
Thanks for all the feedback from the first ship! I appreciate all the help! Here is everything I have done since the last ship: My free domain grant came through, so now I have a domain that I have set on Cloudflare to not cache, allowing me to keep hosting my site fast through cloudflare, while also using the domain for testing. Started working on level four files Improving CSS, following suggestions Updated README slightly Fixed some grammar and incorrect coding I missed (but didnāt affect the visibility at this point) Removed the footer from all the actual level pages as it kind of got in the way in cases, this got mentioned in feedback, and it isnāt really necessary, so it is only on the main page What I plan to do: I didnāt get any feedback about not enough stories, so that isnāt a priority here (but eventually I will do a lot more with the levels IMPORTANT: I did get a lot of feedback about improving the UI and CSS, and keep consistency especially with the rounding of corners Other small adjustments based off feedback Link to the menu through the heading on each page Add images Improve endings Addressing other feedback I got feedback suggesting adding a back button. This is quite a good idea, although I wonāt implement it in this case. Lots of the stories have endings and I donāt think the user should be able to back out. And, in some cases, it goes to a separate html file. In those cases the user can simply press the back button on their browser. Thanks for reading this!
I have made some slight improvements to the header and, also, I have made it so every level links back to the menu page. In my demonstration the domain changes. That is because I have a separate domain that caching is bypassing currently for debugging, but the one the site uses is the one still at deployment readiness. (So while I go cmlin.win -> charleilei.dpdns.org, everyone else will stay the same).
I made some UI changes. I did some others changes, but my main goal was to start on the user interface and CSS. I have made some changes, including changing the top header margin, the colours, and the font family (I got one from Google Fonts).
I have improved some of the CSS. One of the problems I had was with the āaboutā part on my main screen being over top of other containers with different scaled screens. I made some improvements for that. I also changed some colours, including with the buttons. I made it so the header slightly fades on hover. I also did some other minor changes.
This took a lot of effort, but I have finally got it so the site remembers what levels you have completed! (Through localstorage). The level in question goes green after it has been completed some way or another. Failing the level doesnāt count.
I have done lots of small touch-ups, fixes, and other small adjustments like making the completion saving to localstorage work in all cases. I also slightly changed the README, and changed the screenshot there. I am ready for my second ship!
Ships:
Pick-A-Path A simple pick-a-path website game :) What I have made: I have made a pick-a-path game website, with simple storylines that the user transports through. Why: I am not a particularly good storyteller, but my goal with this was to improve my understanding of html, CSS, and JavaScript. How to use Click try project, and you will be transported to my website! The scaling should be fine for most screens. If the sizing doesnāt seem right to you, you can judge proportions off my screenshots (that is how intended). Select a level (I recommend starting at level 1) Read the story, and press the buttons to make your decisions as you go through the story Thank you for having the time to read this, and I hope you love it :)
Pick-A-Path: I have created a simple pick-a-path website game :) I have made a pick-a-path game with simple storylines that the user transports through. It is a website-based game hosted by myself. Why: I am not a particularly good storyteller, but my goal with this was to improve my understanding of html, CSS, and JavaScript. How to use Click try project, and you will be transported to my website! The scaling should be fine for most screens. If the sizing doesnāt seem right to you, you can judge proportions off my screenshots (that is how intended). Select a level (I recommend starting at level 1) Read the story, and press the buttons to make your decisions as you go through the story Once you finish a level, it will make the level button go green (using localstorage) to keep track of completed levels. Thank you for having the time to read this, and I hope you love it :)...
|
1793505117.8007085
|
1793591517.8007085
|
|
14011
|
My very own WebOS by @Mats | Stardance
|
Mats
|
1
|
2.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-09T15:11:01Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Well, this is a WebOS. It contains an about me section, w/o photo bc I dont know yall. It also contains a MatsAI basic window, which just tells you to buy MatsAI premium, which is a whink to me, when I dont know an answer.", "repo": "https://github.com/MatsDevOfficial/MatsDevOfficial.github.io", "demo": "https://matsdevofficial.github.io"}]...
|
[{"post_id": 5649, "ts": "2026 [{"post_id": 5649, "ts": "2026-06-09T15:00:30Z", "hours": 0.6572, "text": "Made an easy app, normal MatsAI. It will just respond to buy MatsAI premium, adding working AI in WebOS 2"}, {"post_id": 5511, "ts": "2026-06-09T09:58:30Z", "hours": 0.3858, "text": "Made the about me go WEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, added opening and closing"}, {"post_id": 5492, "ts": "2026-06-09T09:25:03Z", "hours": 0.3581, "text": "Added info on myself, added a bg, top bar."}, {"post_id": 5472, "ts": "2026-06-09T08:24:23Z", "hours": 0.4914, "text": "Fixed color, text and basic outline"}]...
|
Title: My very own WebOS by @Mats | Stardance
Dev Title: My very own WebOS by @Mats | Stardance
Devlogs:
Fixed color, text and basic outline
Added info on myself, added a bg, top bar.
Made the about me go WEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE, added opening and closing
Made an easy app, normal MatsAI. It will just respond to buy MatsAI premium, adding working AI in WebOS 2
Ships:
Well, this is a WebOS. It contains an about me section, w/o photo bc I dont know yall. It also contains a MatsAI basic window, which just tells you to buy MatsAI premium, which is a whink to me, when I dont know an answer....
|
1793505116.5532668
|
1793591516.5532668
|
|
27369
|
Jolly-ify by @iamalive | Stardance
|
iamalive
|
1
|
2.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-28T05:54:00Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made jolly-ify, a small project that relies on the public cachet api which can grab slack pfps, and then you have the ability to make them jolly through a multitude of tools :)", "repo": "https://github.com/CKacha/jolly-ify", "demo": "https://ckacha.github.io/jolly-ify/"}]...
|
[{"post_id": 17417, "ts": "202 [{"post_id": 17417, "ts": "2026-06-28T05:51:27Z", "hours": 0.7328, "text": "more jollyness + pages more festive options have been added, and now the project is ready to be shipped - its on github pages now!"}, {"post_id": 17369, "ts": "2026-06-28T04:00:39Z", "hours": 1.4706, "text": "JOLLY using cachet api which can grab slack profile names/pictures through the UID, ive made it possible to make someoneās profile picture jolly!"}]...
|
Title: Jolly-ify by @iamalive | Stardance
Devlogs Title: Jolly-ify by @iamalive | Stardance
Devlogs:
JOLLY using cachet api which can grab slack profile names/pictures through the UID, ive made it possible to make someoneās profile picture jolly!
more jollyness + pages more festive options have been added, and now the project is ready to be shipped - its on github pages now!
Ships:
I made jolly-ify, a small project that relies on the public cachet api which can grab slack pfps, and then you have the ability to make them jolly through a multitude of tools :)...
|
1793505113.6936815
|
1793591513.6936815
|
|
49735
|
THE travel planer for mangalore by @Ajith | Starda THE travel planer for mangalore by @Ajith | Stardance...
|
Ajith
|
1
|
8.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-26T08:59:03Z", "hours": 8.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "hellow my project kudla travel planner is a travel guide to the visitors who come to my city . the interesting features about this is you can share your plan with your other group members it is very fun try this website and building it from scratch is different level of happiness the happeist movement while building this was when the map started givning proper directions and shortcut root through the road . I HOPE YOU GUYS ENJOY TRYING AND TESTING MY WEBSITE", "repo": "https://github.com/ajith-h-acharya/kudla-travel-planner", "demo": "https://kudla-travel-planneers.netlify.app"}]...
|
[{"post_id": 48291, "ts": "202 [{"post_id": 48291, "ts": "2026-08-16T16:30:13Z", "hours": 7.5389, "text": "A travel planer that allows user to download a view the map of the city which they are in and navigate to place with low internet of null and ai assitant just order where you want to go it suggest you the best way to go and book a drive and if you are confused it will provide a location based on you mode and many more feature check it out (āāā”āā) https://kudla-travel-planneers.netlify.app/"}]...
|
Title: THE travel planer for mangalore by @Ajith | Title: THE travel planer for mangalore by @Ajith | Stardance
Devlogs:
A travel planer that allows user to download a view the map of the city which they are in and navigate to place with low internet of null and ai assitant just order where you want to go it suggest you the best way to go and book a drive and if you are confused it will provide a location based on you mode and many more feature check it out (āāā”āā) https://kudla-travel-planneers.netlify.app/
Ships:
hellow my project kudla travel planner is a travel guide to the visitors who come to my city . the interesting features about this is you can share your plan with your other group members it is very fun try this website and building it from scratch is different level of happiness the happeist movement while building this was when the map started givning proper directions and shortcut root through the road . I HOPE YOU GUYS ENJOY TRYING AND TESTING MY WEBSITE...
|
1793505111.5174077
|
1793591511.5174077
|
|
28714
|
MY PORTFOLIO by @TXJ_PROGRAMER | Stardance
|
TXJ_PROGRAMER
|
1
|
1.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-02T07:15:28Z", "hours": 1.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "This is my personal portfolio website where I showcase who I am, the projects Iāve built, and the skills Iām learning as a developer. It currently includes a hero section, an about section, a projects section, and a contact section with smooth scrolling and a responsive layout.", "repo": "https://github.com/srinj-ai/MY-PORTFOLIO", "demo": "https://srinj-ai.github.io/MY-PORTFOLIO/"}]...
|
[{"post_id": 19928, "ts": "202 [{"post_id": 19928, "ts": "2026-07-01T11:30:06Z", "hours": 0.3189, "text": "DevLog #2 ā More Pages! Hey everyone, welcome back to another WebOS update! Today I worked on two new sections of the portfolio: the Projects section and the About section. The Projects page is where Iāll showcase everything Iāve built, and About section gives a quick introduction about who I am and what I do. Thereās still a lot I want to improve, but Iām happy with the progress. New Features Added the Projects section Added the About section Kept the same UI style across the new pages I added a porject.js file to add and control all project and links at same time. It still feels a bit empty, but the main structure is finally taking shape. Next, Iāll be working on: Adding a Skills section Making the site fully responsive Thatās it for this devlog. See you in the next one!"}, {"post_id": 19196, "ts": "2026-06-30T13:44:15Z", "hours": 0.7292, "text": "DevLog #1 ā The Beginning Hey everyone, welcome to my first devlog for my portfolio! Iāve wanted to make my own portfolio for a while, so I finally started working on it. Itās pretty simple right now. The current design is based on a gradient text effect: <span class= \"text-transparent bg-clip-text bg-gradient-to-r from-red-500 to-blue-400\" > TXJ </span> I also added a rounded container to give it a cleaner and more modern look. Thatās pretty much all Iāve done for now, but Iāll be adding a lot more in the next devlogs. New Features Basic portfolio layout Gradient text logo Rounded UI design The project is still in its early stages, but Iām happy with how itās looks so far. Next, Iāll be working on: Adding more sections Thatās it for this devlog. Bye, see you in the next one!"}]...
|
Title: MY PORTFOLIO by @TXJ_PROGRAMER | Stardance
Title: MY PORTFOLIO by @TXJ_PROGRAMER | Stardance
Devlogs:
DevLog #1 ā The Beginning Hey everyone, welcome to my first devlog for my portfolio! Iāve wanted to make my own portfolio for a while, so I finally started working on it. Itās pretty simple right now. The current design is based on a gradient text effect: <span class= "text-transparent bg-clip-text bg-gradient-to-r from-red-500 to-blue-400" > TXJ </span> I also added a rounded container to give it a cleaner and more modern look. Thatās pretty much all Iāve done for now, but Iāll be adding a lot more in the next devlogs. New Features Basic portfolio layout Gradient text logo Rounded UI design The project is still in its early stages, but Iām happy with how itās looks so far. Next, Iāll be working on: Adding more sections Thatās it for this devlog. Bye, see you in the next one!
DevLog #2 ā More Pages! Hey everyone, welcome back to another WebOS update! Today I worked on two new sections of the portfolio: the Projects section and the About section. The Projects page is where Iāll showcase everything Iāve built, and About section gives a quick introduction about who I am and what I do. Thereās still a lot I want to improve, but Iām happy with the progress. New Features Added the Projects section Added the About section Kept the same UI style across the new pages I added a porject.js file to add and control all project and links at same time. It still feels a bit empty, but the main structure is finally taking shape. Next, Iāll be working on: Adding a Skills section Making the site fully responsive Thatās it for this devlog. See you in the next one!
Ships:
This is my personal portfolio website where I showcase who I am, the projects Iāve built, and the skills Iām learning as a developer. It currently includes a hero section, an about section, a projects section, and a contact section with smooth scrolling and a responsive layout....
|
1793505102.1560047
|
1793591502.1560047
|
|
292
|
Connie the conentbot by @AloneAlex | Stardance
|
AloneAlex
|
1
|
4.0
|
26
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-04T14:11:25Z", "hours": 4.0, "multiplier": 5.98, "payout": 26, "blessing": "neutral", "text": "Connie is a Slack bot that can fetch a random interesting article or video submitted by another hackclubber, and to which you can submit any interesting videos and articles you find! Featuring simple commands and a nice pfp for the bot!", "repo": "https://github.com/thealonealex/contentbot", "demo": "https://hackclub.enterprise.slack.com/archives/C0B78BSN086"}]...
|
[{"post_id": 2141, "ts": "2026 [{"post_id": 2141, "ts": "2026-06-04T14:05:59Z", "hours": 0.6419, "text": "Slack links create an extra newline on the database, which would mean that if the bot tried to fetch that row, itād be empty and it would just no reply. Fixed that! Also added a proper readme and license file. Project is ready to ship!"}, {"post_id": 1385, "ts": "2026-06-03T11:55:51Z", "hours": 0.5164, "text": "Drew a nice pfp for Connie! Itās so nice that Lapse can count art and hardware time too"}, {"post_id": 1057, "ts": "2026-06-02T21:16:58Z", "hours": 0.5361, "text": "I was wrong, it did work after a restart of the nest service. Hooray! The first version is basically done? /article or /video fetches a random video or article a hackclubber has submitted to the bot /submit-article or /submit-video letās you add to the list of articles and videos! You can try it right now using /cn-help to view all commands!"}, {"post_id": 1038, "ts": "2026-06-02T20:33:10Z", "hours": 2.0692, "text": "Would you believe me if I said writing this line properly took me two full hours of testing and failing? sadly it now doesnāt work on the server side Iāll have to rewrite this again"}, {"post_id": 773, "ts": "2026-06-02T13:10:11Z", "hours": 0.5469, "text": "To begin the project, I followed the slack bot missionās tutorial! Iāll build on top of that as a base"}]...
|
Title: Connie the conentbot by @AloneAlex | Starda Title: Connie the conentbot by @AloneAlex | Stardance
Devlogs:
To begin the project, I followed the slack bot missionās tutorial! Iāll build on top of that as a base
Would you believe me if I said writing this line properly took me two full hours of testing and failing? sadly it now doesnāt work on the server side Iāll have to rewrite this again
I was wrong, it did work after a restart of the nest service. Hooray! The first version is basically done? /article or /video fetches a random video or article a hackclubber has submitted to the bot /submit-article or /submit-video letās you add to the list of articles and videos! You can try it right now using /cn-help to view all commands!
Drew a nice pfp for Connie! Itās so nice that Lapse can count art and hardware time too
Slack links create an extra newline on the database, which would mean that if the bot tried to fetch that row, itād be empty and it would just no reply. Fixed that! Also added a proper readme and license file. Project is ready to ship!
Ships:
Connie is a Slack bot that can fetch a random interesting article or video submitted by another hackclubber, and to which you can submit any interesting videos and articles you find! Featuring simple commands and a nice pfp for the bot!...
|
1793505099.1031468
|
1793591499.1031468
|
|
56086
|
Cosmic flappy bird by @j_pichon12 | Stardance
|
j_pichon12
|
1
|
5.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-03T23:55:34Z", "hours": 5.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a space flappy bird in were you have to avoid the Pillers and spikes it gets harder the farther you progress. And some of the challenges while making this game were how to ācodeā but I had fun it was my first game so ye donāt expect too much its ok but still check it out its fun btw its on scratch.", "repo": "https://github.com/jpichon12/cosmic-flappy-bird/blob/main/README.md", "demo": "https://scratch.mit.edu/projects/1376391653/"}]...
|
[{"post_id": 60537, "ts": "202 [{"post_id": 60537, "ts": "2026-09-02T22:50:53Z", "hours": 0.9333, "text": "cosmic flappy bird 7"}, {"post_id": 59882, "ts": "2026-09-01T21:28:13Z", "hours": 1.0333, "text": "Cosmic flappy bird 6"}, {"post_id": 59266, "ts": "2026-08-31T23:20:45Z", "hours": 1.1167, "text": "Cosmic flappy bird 5 a few new bugs because of a few new things put into it : ) ."}, {"post_id": 59188, "ts": "2026-08-31T20:47:23Z", "hours": 0.8333, "text": "Cosmic flappy bird (4) Am having so much fun its interesting how all the blocks interact with each other i made it a little harder to play"}, {"post_id": 58996, "ts": "2026-08-31T15:56:09Z", "hours": 0.65, "text": "My cosmic flappy bird game is coming along good for my first ever game."}, {"post_id": 58567, "ts": "2026-08-31T00:46:57Z", "hours": 0.4833, "text": "A update to my flappy birds game"}, {"post_id": 58431, "ts": "2026-08-30T20:58:25Z", "hours": 0.35, "text": "I set up my scratch project and recorded my first 19 min of time idk what am doing but i think i can do it ."}]...
|
Title: Cosmic flappy bird by @j_pichon12 | Stardan Title: Cosmic flappy bird by @j_pichon12 | Stardance
Devlogs:
I set up my scratch project and recorded my first 19 min of time idk what am doing but i think i can do it .
A update to my flappy birds game
My cosmic flappy bird game is coming along good for my first ever game.
Cosmic flappy bird (4) Am having so much fun its interesting how all the blocks interact with each other i made it a little harder to play
Cosmic flappy bird 5 a few new bugs because of a few new things put into it : ) .
Cosmic flappy bird 6
cosmic flappy bird 7
Ships:
I made a space flappy bird in were you have to avoid the Pillers and spikes it gets harder the farther you progress. And some of the challenges while making this game were how to ācodeā but I had fun it was my first game so ye donāt expect too much its ok but still check it out its fun btw its on scratch....
|
1793505094.7165034
|
1793591494.7165034
|
|
15290
|
Undertale OS by @ThaoVi | Stardance
|
ThaoVi
|
2
|
29.0
|
190
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-19T13:02:50Z", "hours": 15.0, "multiplier": 12.46, "payout": 190, "blessing": "neutral", "text": "WebOS I made an Undertale themed WebOs presenting me, with some other apps such as countdowns! This is the very first Stardance project i did, and also very first html project overall (including webos1) Features A top-bar with a live clock and a healthbar Draggable windows Closable windows Applications TrueNotes (personal) A personnal app where I put thoughts about true crime stories I enjoyed :D The design is centered around Undertaleās field of flowers, with each footstep being a story; I wanted to make it more original than the side bar I had in WebOS 1. To do app A very basic to do app. Countdown app A simple countdown app where you can set countdowns and a new window appears for each countdown. They are editable and deleteable :D You can also change the precision shown on each windows (in case seeing seconds stresses you out) Skeletale (personal) An undertale - anatomy based āautobiographyā of me, itās part of my WebOs 1 and I havenāt really updated it since. Future plans Undertale music player An intro page (WIP) where you can chose your character and background image. Make the notes apps more interactive by making the user add their own notes Undertale references The close button is a heart and it breaks when you hover on it to close the window! The field in TrueNotes are the yellow flowers from undertale. The health bar is also a reference from undertale. The fonts! They are from https://github.com/hujgup/Undertale-CSS", "repo": "https://github.com/TVDVT/webOS", "demo": "https://tvdvt.github.io/webOS/"}, {"ship_num": 2, "ts": "2026-06-27T15:46:19Z", "hours": 14.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I just finished my first WebOS. It has a top bar, welcome window and two apps. All the windows are draggable and closable, and both of the apps are representative of me :D One is about the true crimes I enjoy and the other one is a presentation of me through a skeleton. I had zero experience in website coding until I started the project, I am very proud of the result!", "repo": "https://github.com/TVDVT/webOS", "demo": "https://tvdvt.github.io/webOS/"}]...
|
[{"post_id": 70359, "ts": "202 [{"post_id": 70359, "ts": "2026-09-19T01:17:40Z", "hours": 4.2636, "text": "Pre-ship adjustments Iām shipping it, finally! I tried to make the user experience better by making the design more coherent (grayscale), although I am planning to add a lot more undertale references. I also changed my footprints color to contrast more with the yellow background. The countdown looks a little better, i removed some overlapping gaps that made everything look awkward but itās better now!"}, {"post_id": 60796, "ts": "2026-09-03T12:03:37Z", "hours": 3.7294, "text": "i COMPLETELY changed the design of my OS to be full on undertale I found an amazing undertale css pack by chance and loved it so much so i went from wow blue aesthetic to undertale yay. I still have some customization to do I changed the close button to a heart and when you hover on it it becomes a broken heart im really proud of that Iām also almost done with the to do app the tasks are just not overflowing the way I want them to new ideas: music player to play undertale songs map to make wallpaper change based on map location have a preload screen that makes you choose your location and choose character"}, {"post_id": 57001, "ts": "2026-08-29T02:14:47Z", "hours": 2.5986, "text": "countdown working! I made it look a little better but Iām not completely satisfied yet. You can now edit and delete countdowns, change precision and some other stuff but now I want to work on making windows pinnable :^ I also want make a todo list app, Iām really thinking of making this OS my study compagnion haha but idk if its too basic for this mission. But anyways ill do it for myself not the stardust hee hee haw haw"}, {"post_id": 48918, "ts": "2026-08-17T14:13:01Z", "hours": 2.3319, "text": "Countdown app I added a countdown app/widget for some motivation so you can have something to look forward to! The CSS is definitely lacking so I will work on it once im done with JS. It was a bit hard to convert every input and change precision but I figured it out thanks to W3S. I still need to: Show a list of the cooldowns in the main window and make them editable and deleteable Make the new window closeable & pinnable Make the time input optionnal Make an icon for the app Find a way to save changes? (maybe)"}, {"post_id": 48335, "ts": "2026-08-16T17:26:05Z", "hours": 0.7083, "text": "First feature done My notes app is now cooler: Footprints instead of a text based sidebar Links open in new tab Upon first opening of the app, only footprints show on a grassy field Animations on footprints and sidebar after clicking the first footprint Things to add after finishing other features: More notes content A way to go back to the grassy field To work on next More animations Gamify Skeletale app"}, {"post_id": 47085, "ts": "2026-08-14T18:36:15Z", "hours": 1.0469, "text": "Devlog My side bar is now a menu? I made it so that content will only show after clicking on the footsteps (not yet but thatās the goal). For that, I need to write a new function in Java Script and add a blue grassy background to match with the cloudy background. My animations are now smoother as I added transitions and larger margins so that the icons getting bigger donāt impede on the other ones. I also added hover text so that we can know which story is selected when hovering on each footstep."}, {"post_id": 43615, "ts": "2026-08-08T23:50:59Z", "hours": 0.5525, "text": "WebOS 2 Itās been a month since I didnāt work on this so I forgot how to code a little. Looking at my old code is helping me remember the coding though. First new feature (Working on this) As my first new feature, I am revamping my True Notes app side bar . I want to change to to footsteps I can click on. As of now, I only imported the image and made the footprints appear for each entry. I have yet to make them as a path, center them and just have a better general layout. Second new feature I want to have hover animations. Eg if I hover on the footprints they get bigger, hovering on an app would change the top bar of the window header, etc. Third feature I havenāt really thought about it yet, either Iāll make my Skeletale app more interactive by changing back and next buttons to directly clicking on the skeleton either I will make a new app"}, {"post_id": 16967, "ts": "2026-06-27T15:30:36Z", "hours": 1.0411, "text": "Done!"}, {"post_id": 16632, "ts": "2026-06-27T01:42:50Z", "hours": 3.1203, "text": "Almost done with my second app My second app is an anatomical map of myself inspired by Undertale (not really, itās just a pixelized skeleton). I just really like anatomy in general so I thought this would represent me well. I assigned a part of myself to many bones, the text is just placeholder right now, I will develop on it later. -I added back and next buttons for navigation to make it simpler than a side bar, It also takes less space I finished my first app a while ago but I do want to change the layout in WebOS 2 (have some art & a better side bar) Right now my goals for tomorrow are to: Put the back&next buttons inside the window Hide the skeleton image on the first tab of the app Zoom on each bone for each body part or have a heart cursor that goes in each body part like in Undertale Finish the content"}, {"post_id": 14671, "ts": "2026-06-23T21:10:04Z", "hours": 2.6467, "text": "I finished part 4, it took me a while to get it to work so I will focus on the aesthetic after i finish part 5. My notes app will show my thoughts about some true crime stories. My next app is going to be Undertale related I hope."}, {"post_id": 11551, "ts": "2026-06-18T20:54:43Z", "hours": 2.9986, "text": "Added a Notes App, but Iām not sure what its exact purpose will be"}, {"post_id": 10908, "ts": "2026-06-17T21:40:50Z", "hours": 1.8064, "text": "Iām done with part 3! Now I have: A pretty header A pretty background A CSS file with my window and window header designs that I will be able to use for my next windows. Draggable windows that can close (but will completely disappear, so I have to make a āminimizeā button to be able to open it later) An open button thatās not very useful and doesnāt really work."}, {"post_id": 9556, "ts": "2026-06-15T22:40:55Z", "hours": 1.3453, "text": "Working on part 3"}, {"post_id": 6827, "ts": "2026-06-11T13:35:07Z", "hours": 0.6017, "text": "I just learned about dividers! The welcome still looks a bit awkward but itās gonna be fine."}, {"post_id": 6805, "ts": "2026-06-11T12:41:43Z", "hours": 0.3239, "text": "First 15 minutes"}]...
|
Title: Undertale OS by @ThaoVi | Stardance
Devlog Title: Undertale OS by @ThaoVi | Stardance
Devlogs:
First 15 minutes
I just learned about dividers! The welcome still looks a bit awkward but itās gonna be fine.
Working on part 3
Iām done with part 3! Now I have: A pretty header A pretty background A CSS file with my window and window header designs that I will be able to use for my next windows. Draggable windows that can close (but will completely disappear, so I have to make a āminimizeā button to be able to open it later) An open button thatās not very useful and doesnāt really work.
Added a Notes App, but Iām not sure what its exact purpose will be
I finished part 4, it took me a while to get it to work so I will focus on the aesthetic after i finish part 5. My notes app will show my thoughts about some true crime stories. My next app is going to be Undertale related I hope.
Almost done with my second app My second app is an anatomical map of myself inspired by Undertale (not really, itās just a pixelized skeleton). I just really like anatomy in general so I thought this would represent me well. I assigned a part of myself to many bones, the text is just placeholder right now, I will develop on it later. -I added back and next buttons for navigation to make it simpler than a side bar, It also takes less space I finished my first app a while ago but I do want to change the layout in WebOS 2 (have some art & a better side bar) Right now my goals for tomorrow are to: Put the back&next buttons inside the window Hide the skeleton image on the first tab of the app Zoom on each bone for each body part or have a heart cursor that goes in each body part like in Undertale Finish the content
Done!
WebOS 2 Itās been a month since I didnāt work on this so I forgot how to code a little. Looking at my old code is helping me remember the coding though. First new feature (Working on this) As my first new feature, I am revamping my True Notes app side bar . I want to change to to footsteps I can click on. As of now, I only imported the image and made the footprints appear for each entry. I have yet to make them as a path, center them and just have a better general layout. Second new feature I want to have hover animations. Eg if I hover on the footprints they get bigger, hovering on an app would change the top bar of the window header, etc. Third feature I havenāt really thought about it yet, either Iāll make my Skeletale app more interactive by changing back and next buttons to directly clicking on the skeleton either I will make a new app
Devlog My side bar is now a menu? I made it so that content will only show after clicking on the footsteps (not yet but thatās the goal). For that, I need to write a new function in Java Script and add a blue grassy background to match with the cloudy background. My animations are now smoother as I added transitions and larger margins so that the icons getting bigger donāt impede on the other ones. I also added hover text so that we can know which story is selected when hovering on each footstep.
First feature done My notes app is now cooler: Footprints instead of a text based sidebar Links open in new tab Upon first opening of the app, only footprints show on a grassy field Animations on footprints and sidebar after clicking the first footprint Things to add after finishing other features: More notes content A way to go back to the grassy field To work on next More animations Gamify Skeletale app
Countdown app I added a countdown app/widget for some motivation so you can have something to look forward to! The CSS is definitely lacking so I will work on it once im done with JS. It was a bit hard to convert every input and change precision but I figured it out thanks to W3S. I still need to: Show a list of the cooldowns in the main window and make them editable and deleteable Make the new window closeable & pinnable Make the time input optionnal Make an icon for the app Find a way to save changes? (maybe)
countdown working! I made it look a little better but Iām not completely satisfied yet. You can now edit and delete countdowns, change precision and some other stuff but now I want to work on making windows pinnable :^ I also want make a todo list app, Iām really thinking of making this OS my study compagnion haha but idk if its too basic for this mission. But anyways ill do it for myself not the stardust hee hee haw haw
i COMPLETELY changed the design of my OS to be full on undertale I found an amazing undertale css pack by chance and loved it so much so i went from wow blue aesthetic to undertale yay. I still have some customization to do I changed the close button to a heart and when you hover on it it becomes a broken heart im really proud of that Iām also almost done with the to do app the tasks are just not overflowing the way I want them to new ideas: music player to play undertale songs map to make wallpaper change based on map location have a preload screen that makes you choose your location and choose character
Pre-ship adjustments Iām shipping it, finally! I tried to make the user experience better by making the design more coherent (grayscale), although I am planning to add a lot more undertale references. I also changed my footprints color to contrast more with the yellow background. The countdown looks a little better, i removed some overlapping gaps that made everything look awkward but itās better now!
Ships:
I just finished my first WebOS. It has a top bar, welcome window and two apps. All the windows are draggable and closable, and both of the apps are representative of me :D One is about the true crimes I enjoy and the other one is a presentation of me through a skeleton. I had zero experience in website coding until I started the project, I am very proud of the result!
WebOS I made an Undertale themed WebOs presenting me, with some other apps such as countdowns! This is the very first Stardance project i did, and also very first html project overall (including webos1) Features A top-bar with a live clock and a healthbar Draggable windows Closable windows Applications TrueNotes (personal) A personnal app where I put thoughts about true crime stories I enjoyed :D The design is centered around Undertaleās field of flowers, with each footstep being a story; I wanted to make it more original than the side bar I had in WebOS 1. To do app A very basic to do app. Countdown app A simple countdown app where you can set countdowns and a new window appears for each countdown. They are editable and deleteable :D You can also change the precision shown on each windows (in case seeing seconds stresses you out) Skeletale (personal) An undertale - anatomy based āautobiographyā of me, itās part of my WebOs 1 and I havenāt really updated it since. Future plans Undertale music player An intro page (WIP) where you can chose your character and background image. Make the notes apps more interactive by making the user add their own notes Undertale references The close button is a heart and it breaks when you hover on it to close the window! The field in TrueNotes are the yellow flowers from undertale. The health bar is also a reference from undertale. The fonts! They are from https://github.com/hujgup/Undertale-CSS...
|
1793505092.4545486
|
1793591492.4545486
|
|
56068
|
nootab by @willexists | Stardance
|
willexists
|
1
|
2.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-30T21:29:10Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "this is the silliest noo-est tab in the face of the world! it has the magical things known as features weather cool stuff :) will", "repo": "https://github.com/ooowillexistsooo/nootab", "demo": "https://nootab.willexists.space"}]...
|
[{"post_id": 58456, "ts": "202 [{"post_id": 58456, "ts": "2026-08-30T21:27:15Z", "hours": 0.2858, "text": "fin i finished im so cutesy~!"}, {"post_id": 58409, "ts": "2026-08-30T20:24:40Z", "hours": 0.2967, "text": "i added a weather widget thing imma go read me now it actually workes"}, {"post_id": 58386, "ts": "2026-08-30T19:53:52Z", "hours": 0.5603, "text": "added a mac background and made it look more mac-y with a translucent background woah iām using the ~fancy ~ words today it took me way too much time to learn how to make that not strikeoutā¦"}, {"post_id": 57824, "ts": "2026-08-30T03:58:21Z", "hours": 0.4733, "text": "added a dock o.o"}, {"post_id": 57804, "ts": "2026-08-30T03:15:16Z", "hours": 0.755, "text": "i did the thing its a thing woa"}]...
|
Title: nootab by @willexists | Stardance
Devlogs: Title: nootab by @willexists | Stardance
Devlogs:
i did the thing its a thing woa
added a dock o.o
added a mac background and made it look more mac-y with a translucent background woah iām using the ~fancy ~ words today it took me way too much time to learn how to make that not strikeoutā¦
i added a weather widget thing imma go read me now it actually workes
fin i finished im so cutesy~!
Ships:
this is the silliest noo-est tab in the face of the world! it has the magical things known as features weather cool stuff :) will...
|
1793505090.2888756
|
1793591490.2888756
|
|
55009
|
Kage by @Kaze_97 | Stardance
|
Kaze_97
|
1
|
0.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-29T08:12:55Z", "hours": 0.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a Slack bot named Kage using the guide given by stardance and it was a quite a new and fun experience to build an bot. The coding was honestly not that hard but the deploying of the bot on NEST got me took a lot more time. The great experience i got from this project is to use NEST container and deploy bots on it. It is really a simple bot with two or three basic commands but it is great thing to me that i build it. It was my first experience I pretty much liked it(except the parts where i am have lost the NEST access key). No need to have much experience to use the bot cz it is very basic and simple.", "repo": "https://github.com/kenshikaze/Kage", "demo": "https://app.slack.com/client/E09V59WQY1E/C0BTCTFNSQ6?_gl=1*1v8s5x9*_gcl_au*ODg3NDQ5ODcyLjE3ODc4MzM2OTEuNTA0NjExMTI0LjE3ODc4MzM2OTUuMTc4NzgzMzcxMC4zNDM1MDk0NTYuMTc4NzgzMzY5NS4xNzg3ODMzNzUw"}]...
|
[{"post_id": 56644, "ts": "202 [{"post_id": 56644, "ts": "2026-08-28T14:16:40Z", "hours": 0.455, "text": "This is another of my project. It is a slack bot which I made to just work on something new rather than my OS project. itās name is kage and it has pretty basic commands like time , ping and joke. I wrote the code very easily but the uploading on NEST took much longer because It was my first time using a server and the SSH in was a bit hard cause I messed up with the private key . Somehow I got the bot running in the #bot- server ."}]...
|
Title: Kage by @Kaze_97 | Stardance
Devlogs:
This Title: Kage by @Kaze_97 | Stardance
Devlogs:
This is another of my project. It is a slack bot which I made to just work on something new rather than my OS project. itās name is kage and it has pretty basic commands like time , ping and joke. I wrote the code very easily but the uploading on NEST took much longer because It was my first time using a server and the SSH in was a bit hard cause I messed up with the private key . Somehow I got the bot running in the #bot- server .
Ships:
I made a Slack bot named Kage using the guide given by stardance and it was a quite a new and fun experience to build an bot. The coding was honestly not that hard but the deploying of the bot on NEST got me took a lot more time. The great experience i got from this project is to use NEST container and deploy bots on it. It is really a simple bot with two or three basic commands but it is great thing to me that i build it. It was my first experience I pretty much liked it(except the parts where i am have lost the NEST access key). No need to have much experience to use the bot cz it is very basic and simple....
|
1793505088.1573138
|
1793591488.1573138
|
|
49725
|
Nexn's Personal Site. by @NexnReal | Stardance
|
NexnReal
|
2
|
8.0
|
7
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-29T13:41:19Z", "hours": 5.0, "multiplier": 1.39, "payout": 7, "blessing": "neutral", "text": "Nexnās personal site, basically a tiny portfolio i made to let yall know bout me.", "repo": "https://gitlab.com/NexnBased/personalsite", "demo": "https://nexnsportfolio.vercel.app/"}, {"ship_num": 2, "ts": "2026-08-25T09:52:41Z", "hours": 3.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "This is my personal site, about me and about me, my skills, education, tech stack and all.", "repo": "https://gitlab.com/NexnBased/personalsite", "demo": "https://nexnsportfolio.vercel.app/"}]...
|
[{"post_id": 84272, "ts": "202 [{"post_id": 84272, "ts": "2026-10-29T11:47:03Z", "hours": 0.3292, "text": "Devlog 3 Updated Core Updated Projects Added a tiny note"}, {"post_id": 55461, "ts": "2026-08-27T10:12:27Z", "hours": 4.4331, "text": "Devlog 2 Added more info about myself Added interests section Removed some bloat Added a tiny floating footer at the left bottom corner Modified navbar a lil bit Updated projects section"}, {"post_id": 48199, "ts": "2026-08-16T14:27:07Z", "hours": 3.1556, "text": "Devlog 1 Very basic personal site. Made this just to finish that mission. Look fine. No projects to show, Iāve abandoned all of them for no reason. Tech stack About me Contact Thatās all, nothing else. Used DevIcons for the icons. Wanted to add dark mode toggle but it is good now and it will be enough, i guess."}]...
|
Title: Nexn's Personal Site. by @NexnReal | St Title: Nexn's Personal Site. by @NexnReal | Stardance
Devlogs:
Devlog 1 Very basic personal site. Made this just to finish that mission. Look fine. No projects to show, Iāve abandoned all of them for no reason. Tech stack About me Contact Thatās all, nothing else. Used DevIcons for the icons. Wanted to add dark mode toggle but it is good now and it will be enough, i guess.
Devlog 2 Added more info about myself Added interests section Removed some bloat Added a tiny floating footer at the left bottom corner Modified navbar a lil bit Updated projects section
Devlog 3 Updated Core Updated Projects Added a tiny note
Ships:
This is my personal site, about me and about me, my skills, education, tech stack and all.
Nexnās personal site, basically a tiny portfolio i made to let yall know bout me....
|
1793505086.0300484
|
1793591486.0300484
|
|
25790
|
StartupOS Monorepo Final by @to_aarav_g | Stardanc StartupOS Monorepo Final by @to_aarav_g | Stardance...
|
to_aarav_g
|
1
|
22.85
|
39
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-27T14:53:19Z", "hours": 6.0, "multiplier": 7.93, "payout": 39, "blessing": "neutral", "text": "š Shipped the complete StartupOS Monorepo ! StartupOS is an AI Operating System for founders that compresses weeks of startup work into hours. From a single idea, StartupOS helps founders: ā
Validate ideas ā
Generate startup blueprints ā
Create brands and ICPs ā
Build revenue models and roadmaps ā
Analyze competitors ā
Generate launch-ready websites ā
Receive AI founder feedback ā
Manage everything in a unified workspace Monorepo Architecture š§ Frontend: Next.js + React + Tailwind āļø Backend: Fastify + Prisma + PostgreSQL š¤ AI Layer: Gemini, Groq, OpenRouter, NVIDIA NIM š Deployment: Vercel + Railway š¦ Shared packages and types Building StartupOS taught me full-stack architecture, production deployments, AI orchestration, and large-scale debugging. Excited to keep improving it and onboard real users soon š #HackClub #Stardance #Monorepo #FullStack #AI #StartupOS #TypeScript #WebDev", "repo": "https://github.com/Theuser1211/startupos", "demo": "https://startupos-black.vercel.app/"}]...
|
[{"post_id": 23441, "ts": "202 [{"post_id": 23441, "ts": "2026-07-06T12:55:13Z", "hours": 11.76, "text": "The website generation is pretty irritation, partialy fixed it. Needs more work"}, {"post_id": 17660, "ts": "2026-06-28T15:23:18Z", "hours": 2.2361, "text": "Added proper guest mode to StartupOS! Users can now complete the founder interview, generate a blueprint, and explore the workspace without creating an account. Also fixed a bunch of authentication edge cases, improved session handling, and ran a full Playwright audit to make the app much more stable."}, {"post_id": 17414, "ts": "2026-06-28T05:42:22Z", "hours": 2.8567, "text": "Thanks for the reviews, those helped really well. For some reasons my app broke during the QA Testing and I would apologize for that. (I have fixed it now hope so!). Also I have reworked the CSS(to make it less AI slop). Also this is 100% AI free. I hope you like it"}, {"post_id": 16120, "ts": "2026-06-26T06:31:53Z", "hours": 6.2292, "text": "StartupOS ā The AI Operating System for FoundersInspirationStarting a startup is hard. Founders often spend weeks validating ideas, researching competitors, defining their target audience, creating business plans, and building an initial online presence.We wanted to build a platform that could compress this entire process into hours instead of weeks.Thatās how StartupOS was born ā an AI-powered operating system that helps founders go from a raw idea to a launch-ready startup.What it doesStartupOS acts as an AI co-founder that guides users through the earliest and most important stages of building a company.Users complete a guided founder interview, and StartupOS automatically generates:Comprehensive startup blueprintsBrand identitiesIdeal Customer Profiles (ICP)Revenue modelsProduct roadmapsCompetitor intelligenceDaily founder briefsAI startup roasts and feedbackLaunch-ready websitesEverything is managed through a unified founder workspace.How we built itStartupOS is built as a modern full-stack monorepo.FrontendNext.jsReactTypeScriptTailwind CSSshadcn/uiBackendFastifyTypeScriptPrisma ORMPostgreSQLAI InfrastructureMulti-provider AI routingGoogle GeminiGroqOpenRouterNVIDIA NIMDeploymentVercelRailwayDockerThe monorepo architecture allows the frontend, backend, and shared packages to evolve together while maintaining a clean developer experience.Challenges we ran intoBuilding StartupOS involved solving numerous engineering challenges:Designing a reliable multi-provider AI failover systemHandling provider outages and rate limits gracefullyMigrating from a monolithic architecture to dedicated frontend and backend servicesDebugging complex deployment issues across Railway and VercelImplementing persistent AI-generated assets and state managementCreating robust error handling and production-grade fallback systemsMaintaining a smooth user experience despite long-running AI tasksAccomplishments that weāre proud ofSuccessfully shipped a production-ready full-stack AI SaaS platformBuilt a complete founder workflow from idea to launchImplemented resilient AI failover across multiple providersDeployed scalable frontend and backend infrastructureAchieved successful end-to-end testing across the entire platformCreated a responsive experience across desktop, tablet, and mobile devicesWhat we learnedThrough StartupOS, we learned a tremendous amount about:Full-stack architectureProduction deploymentsAI orchestrationAPI reliabilityError recovery strategiesMonorepo development workflowsBuilding products for real usersWhatās next for StartupOSOur roadmap includes:Visual website editorOne-click domain setupTeam collaboration featuresStartup analytics and trackingPDF and pitch deck exportsAI growth recommendationsMarketplace integrationsAdditional deployment providersStartupOS is just getting started. Our vision is to build the ultimate operating system for founders ā an AI platform that helps anyone transform ideas into successful startups."}]...
|
Title: StartupOS Monorepo Final by @to_aarav_g | S Title: StartupOS Monorepo Final by @to_aarav_g | Stardance
Devlogs:
StartupOS ā The AI Operating System for FoundersInspirationStarting a startup is hard. Founders often spend weeks validating ideas, researching competitors, defining their target audience, creating business plans, and building an initial online presence.We wanted to build a platform that could compress this entire process into hours instead of weeks.Thatās how StartupOS was born ā an AI-powered operating system that helps founders go from a raw idea to a launch-ready startup.What it doesStartupOS acts as an AI co-founder that guides users through the earliest and most important stages of building a company.Users complete a guided founder interview, and StartupOS automatically generates:Comprehensive startup blueprintsBrand identitiesIdeal Customer Profiles (ICP)Revenue modelsProduct roadmapsCompetitor intelligenceDaily founder briefsAI startup roasts and feedbackLaunch-ready websitesEverything is managed through a unified founder workspace.How we built itStartupOS is built as a modern full-stack monorepo.FrontendNext.jsReactTypeScriptTailwind CSSshadcn/uiBackendFastifyTypeScriptPrisma ORMPostgreSQLAI InfrastructureMulti-provider AI routingGoogle GeminiGroqOpenRouterNVIDIA NIMDeploymentVercelRailwayDockerThe monorepo architecture allows the frontend, backend, and shared packages to evolve together while maintaining a clean developer experience.Challenges we ran intoBuilding StartupOS involved solving numerous engineering challenges:Designing a reliable multi-provider AI failover systemHandling provider outages and rate limits gracefullyMigrating from a monolithic architecture to dedicated frontend and backend servicesDebugging complex deployment issues across Railway and VercelImplementing persistent AI-generated assets and state managementCreating robust error handling and production-grade fallback systemsMaintaining a smooth user experience despite long-running AI tasksAccomplishments that weāre proud ofSuccessfully shipped a production-ready full-stack AI SaaS platformBuilt a complete founder workflow from idea to launchImplemented resilient AI failover across multiple providersDeployed scalable frontend and backend infrastructureAchieved successful end-to-end testing across the entire platformCreated a responsive experience across desktop, tablet, and mobile devicesWhat we learnedThrough StartupOS, we learned a tremendous amount about:Full-stack architectureProduction deploymentsAI orchestrationAPI reliabilityError recovery strategiesMonorepo development workflowsBuilding products for real usersWhatās next for StartupOSOur roadmap includes:Visual website editorOne-click domain setupTeam collaboration featuresStartup analytics and trackingPDF and pitch deck exportsAI growth recommendationsMarketplace integrationsAdditional deployment providersStartupOS is just getting started. Our vision is to build the ultimate operating system for founders ā an AI platform that helps anyone transform ideas into successful startups.
Thanks for the reviews, those helped really well. For some reasons my app broke during the QA Testing and I would apologize for that. (I have fixed it now hope so!). Also I have reworked the CSS(to make it less AI slop). Also this is 100% AI free. I hope you like it
Added proper guest mode to StartupOS! Users can now complete the founder interview, generate a blueprint, and explore the workspace without creating an account. Also fixed a bunch of authentication edge cases, improved session handling, and ran a full Playwright audit to make the app much more stable.
The website generation is pretty irritation, partialy fixed it. Needs more work
Ships:
š Shipped the complete StartupOS Monorepo ! StartupOS is an AI Operating System for founders that compresses weeks of startup work into hours. From a single idea, StartupOS helps founders: ā
Validate ideas ā
Generate startup blueprints ā
Create brands and ICPs ā
Build revenue models and roadmaps ā
Analyze competitors ā
Generate launch-ready websites ā
Receive AI founder feedback ā
Manage everything in a unified workspace Monorepo Architecture š§ Frontend: Next.js + React + Tailwind āļø Backend: Fastify + Prisma + PostgreSQL š¤ AI Layer: Gemini, Groq, OpenRouter, NVIDIA NIM š Deployment: Vercel + Railway š¦ Shared packages and types Building StartupOS taught me full-stack architecture, production deployments, AI orchestration, and large-scale debugging. Excited to keep improving it and onboard real users soon š #HackClub #Stardance #Monorepo #FullStack #AI #StartupOS #TypeScript #WebDev...
|
1793505082.9217668
|
1793591482.9217668
|
|
40640
|
Barometer Node for Godot by @Tanmayg1801 | Stardan Barometer Node for Godot by @Tanmayg1801 | Stardance...
|
Tanmayg1801
|
1
|
3.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-01T06:46:56Z", "hours": 3.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I finally made my first Godot Node in GDExtension! It is going to be used in my new game RoW: RUle of the wind, more info on that later in Stardance. But about this project, it was my first time dealing with C++ on this level and not just writing code for basic programs. But I am proud of myself for getting it to work, though not many android devices support Barometer⦠(I might make one for iOS later as it has a much better Barometer sensor support). Signing out until the next project!", "repo": "https://github.com/Tanmayg1801/Godot-Barometer-Node-Android", "demo": "https://tanmayg1801.itch.io/godot-barometer-node-android"}]...
|
[{"post_id": 38693, "ts": "202 [{"post_id": 38693, "ts": "2026-08-01T06:42:09Z", "hours": 0.4756, "text": "Just wrote a tad bit of README and struggled with push on Github xD"}, {"post_id": 35907, "ts": "2026-07-27T17:16:20Z", "hours": 2.7922, "text": "I made a Barometer node for Godot. Only the Android part of it is done for now, I might expand it for iOS support later >< I hope it works!!"}]...
|
Title: Barometer Node for Godot by @Tanmayg1801 | Title: Barometer Node for Godot by @Tanmayg1801 | Stardance
Devlogs:
I made a Barometer node for Godot. Only the Android part of it is done for now, I might expand it for iOS support later >< I hope it works!!
Just wrote a tad bit of README and struggled with push on Github xD
Ships:
I finally made my first Godot Node in GDExtension! It is going to be used in my new game RoW: RUle of the wind, more info on that later in Stardance. But about this project, it was my first time dealing with C++ on this level and not just writing code for basic programs. But I am proud of myself for getting it to work, though not many android devices support Barometer⦠(I might make one for iOS later as it has a much better Barometer sensor support). Signing out until the next project!...
|
1793505080.7394087
|
1793591480.7394087
|
|
22784
|
Flappy Bird Game by @billet | Stardance
|
billet
|
1
|
7.0
|
25
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-04T16:36:44Z", "hours": 7.0, "multiplier": 3.84, "payout": 25, "blessing": "neutral", "text": "Hello Everyone! I have created a replication of Flappy Bird. The goal of the game is to survive for as long as possible while dodging the pipes that come your way. FEATURES: My version of Flappy Bird includes a scoreboard and 3 difficulties for the game, as well as hand-drawn assets that were created in Piskelapp.com. The background also moves in various speeds. Flappy will rotate depending on if he is going up or falling down. The game will become harder as time goes on, as the pipes will speed up everytime you score a point. The scoreboard holds the 3 highest scores for each difficulties, it doesnāt get saved into a cookie or locally on the computer, so DONāT reload the page if you donāt want to erase the data. CHANGES: I started this project before stardance had started, but I made some improvements to the hitboxes that check for collision with the pipes, and UI improvements, like background color changes and moving the title somewhere more appropriate. As well, as created a tutorial page with some animations and images for more clarity as to how to play the game. PROBLEMS ISSUES: During development I had some problems with Flappyās hitbox and how it worked, but eventually with the help of one of my teachers we got it to work pretty well, although since this is HTML + CSS, when I made flappy rotate when clicked the hitboxes which were referenced from the top left corner didnāt calculate the collision math correctly. I improved on this by making the hitbox like a circle and with a couple cases which is explained in the JS code, the hitbox becomes way more accurate. Thank you.", "repo": "https://github.com/Iexist67/Flappy-Bird", "demo": "https://iexist67.github.io/Flappy-Bird/"}]...
|
[{"post_id": 21992, "ts": "202 [{"post_id": 21992, "ts": "2026-07-04T06:52:25Z", "hours": 3.2242, "text": "I made some UI changes to my flappy bird game and included a little tutorial page to make people who donāt understand the game or donāt know the controls have more clarity to how the game should be played. Here is also a gif of the gameplay."}, {"post_id": 17124, "ts": "2026-06-27T20:09:12Z", "hours": 3.3228, "text": "Finished the updated hit box for flappy in my flappy-bird game! I redid the hit box logic and added a span element inside of my flappy element in HTML to āactā as a hitbox. You can try my game out here: https://iexist67.github.io/Flappy-Bird/"}]...
|
Title: Flappy Bird Game by @billet | Stardance
De Title: Flappy Bird Game by @billet | Stardance
Devlogs:
Finished the updated hit box for flappy in my flappy-bird game! I redid the hit box logic and added a span element inside of my flappy element in HTML to āactā as a hitbox. You can try my game out here: https://iexist67.github.io/Flappy-Bird/
I made some UI changes to my flappy bird game and included a little tutorial page to make people who donāt understand the game or donāt know the controls have more clarity to how the game should be played. Here is also a gif of the gameplay.
Ships:
Hello Everyone! I have created a replication of Flappy Bird. The goal of the game is to survive for as long as possible while dodging the pipes that come your way. FEATURES: My version of Flappy Bird includes a scoreboard and 3 difficulties for the game, as well as hand-drawn assets that were created in Piskelapp.com. The background also moves in various speeds. Flappy will rotate depending on if he is going up or falling down. The game will become harder as time goes on, as the pipes will speed up everytime you score a point. The scoreboard holds the 3 highest scores for each difficulties, it doesnāt get saved into a cookie or locally on the computer, so DONāT reload the page if you donāt want to erase the data. CHANGES: I started this project before stardance had started, but I made some improvements to the hitboxes that check for collision with the pipes, and UI improvements, like background color changes and moving the title somewhere more appropriate. As well, as created a tutorial page with some animations and images for more clarity as to how to play the game. PROBLEMS ISSUES: During development I had some problems with Flappyās hitbox and how it worked, but eventually with the help of one of my teachers we got it to work pretty well, although since this is HTML + CSS, when I made flappy rotate when clicked the hitboxes which were referenced from the top left corner didnāt calculate the collision math correctly. I improved on this by making the hitbox like a circle and with a couple cases which is explained in the JS code, the hitbox becomes way more accurate. Thank you....
|
1793505078.5350113
|
1793591478.5350113
|
|
1352
|
Kinetic Cam by @Pranav | Stardance
|
Pranav
|
1
|
2.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-23T00:51:41Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made KineticCam, a portable two-axis gimbal that uses an ESP32, servos, and an IMU to help keep the camera stable while recording. I designed the full case, power bank holder, camera stand, servo mounts, and added a standard camera screw so the camera can be attached securely. The hardest part was fitting all of the electronics and moving parts into a small design while fixing servo spacing and tolerence problems. I am most proud of how the design slowly became a complete pan-and-tilt system instead of just a basic camera mount. People testing it should make sure the camera and servos can move seperate from each other, check that its balanced, and test how stable it stay while both axes are moving.", "repo": "https://github.com/CyberBrainiac1/kinetic-cam", "demo": ""}]...
|
[{"post_id": 14043, "ts": "202 [{"post_id": 14043, "ts": "2026-06-23T00:47:57Z", "hours": 0.7264, "text": "I worked on the blue camera support today and fixed a few more servo spacing and tolerance problems. I adjusted the holes and gaps so the parts should fit together better when its printed. I also added the camera stand and a camera screw so the GoPro can attach securely to the moving frame.I added the IMU to the design so the system can measure the cameras angle and movement. The hardest part was fitting the camera mount, servo, and IMU together without making the top section to large."}, {"post_id": 13796, "ts": "2026-06-22T16:50:03Z", "hours": 1.2414, "text": "I added a second degree of freedom to KineticCam, so the camera can now tilt up and down as well as turn left and right. I designed a new bracket to hold the camera and connect it to another servo above the main case. The hardest part was fitting the servo, camera mount, and moving parts together without making the top too large.I also fixed a few random problems in the button case and adjusted some tolerences so the parts should fit together better when printed. I made sure the camera has enough room to move without hitting the frame."}, {"post_id": 5100, "ts": "2026-06-08T19:45:26Z", "hours": 2.0853, "text": "I finalized the first basic internal enclosure for my 3D printed KineticCam GoPro tracker and 3D printed a v1 to get the sizing, wiring, and fits correct. The device uses an ESP32 microcontroller to control an SG90 servo that can be used for smoother panning motions while recording a camera. The enclosure is in 2 separate parts where the ESP32 fits in the lower compartment and the servo mount and camera mount fits on the top of the device. After the parts came off the 3D printer, I tested how the wires would feed into the system and how everything would fit inside. I noticed here that I shouldnāt be using power directly from the ESP32 for the servo as it needs an independent 5V supply. Iām planning on using a cylindrical power bank for the supply to keep the device portable. I also designed a separate power bank holder and a servo top mounting bracket. These will also keep the device very compact and stable while it is moving. The prototype was a good test for the layout, the power, and the mounting method of the tracker before I make a fully refined version."}]...
|
Title: Kinetic Cam by @Pranav | Stardance
Devlogs Title: Kinetic Cam by @Pranav | Stardance
Devlogs:
I finalized the first basic internal enclosure for my 3D printed KineticCam GoPro tracker and 3D printed a v1 to get the sizing, wiring, and fits correct. The device uses an ESP32 microcontroller to control an SG90 servo that can be used for smoother panning motions while recording a camera. The enclosure is in 2 separate parts where the ESP32 fits in the lower compartment and the servo mount and camera mount fits on the top of the device. After the parts came off the 3D printer, I tested how the wires would feed into the system and how everything would fit inside. I noticed here that I shouldnāt be using power directly from the ESP32 for the servo as it needs an independent 5V supply. Iām planning on using a cylindrical power bank for the supply to keep the device portable. I also designed a separate power bank holder and a servo top mounting bracket. These will also keep the device very compact and stable while it is moving. The prototype was a good test for the layout, the power, and the mounting method of the tracker before I make a fully refined version.
I added a second degree of freedom to KineticCam, so the camera can now tilt up and down as well as turn left and right. I designed a new bracket to hold the camera and connect it to another servo above the main case. The hardest part was fitting the servo, camera mount, and moving parts together without making the top too large.I also fixed a few random problems in the button case and adjusted some tolerences so the parts should fit together better when printed. I made sure the camera has enough room to move without hitting the frame.
I worked on the blue camera support today and fixed a few more servo spacing and tolerance problems. I adjusted the holes and gaps so the parts should fit together better when its printed. I also added the camera stand and a camera screw so the GoPro can attach securely to the moving frame.I added the IMU to the design so the system can measure the cameras angle and movement. The hardest part was fitting the camera mount, servo, and IMU together without making the top section to large.
Ships:
I made KineticCam, a portable two-axis gimbal that uses an ESP32, servos, and an IMU to help keep the camera stable while recording. I designed the full case, power bank holder, camera stand, servo mounts, and added a standard camera screw so the camera can be attached securely. The hardest part was fitting all of the electronics and moving parts into a small design while fixing servo spacing and tolerence problems. I am most proud of how the design slowly became a complete pan-and-tilt system instead of just a basic camera mount. People testing it should make sure the camera and servos can move seperate from each other, check that its balanced, and test how stable it stay while both axes are moving....
|
1793505076.5700598
|
1793591476.5700598
|
|
37016
|
Finn's Domain of Knowledge by @Tacocat12 | Sta Finn's Domain of Knowledge by @Tacocat12 | Stardance...
|
Tacocat12
|
1
|
5.4
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-19T20:00:54Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a personal website that shows off projects I made, projects I am working on, and some info about me. I met all the requirements and only used AI for spell check on my blog and main page.", "repo": "https://github.com/tacocat991763/my-site", "demo": "https://tacocat991763.github.io/my-site/"}]...
|
[{"post_id": 37650, "ts": "202 [{"post_id": 37650, "ts": "2026-07-30T15:18:04Z", "hours": 3.4042, "text": "I have now revamped the UI and added more personalized backgrounds to the main page, next I will be working on the blog"}, {"post_id": 31421, "ts": "2026-07-19T19:31:29Z", "hours": 1.1797, "text": "SO MANY ERRORS. I have been debugging for 30 minutes of this hour. GitHub pages DID NOT want to collaborate but finally I got it sort of working. It doesnāt work anywhere other than GitHub pages but it does work. Anyway⦠I am going to go keep coding."}, {"post_id": 30916, "ts": "2026-07-18T22:00:15Z", "hours": 0.8814, "text": "My first version!"}]...
|
Title: Finn's Domain of Knowledge by @Tacocat1 Title: Finn's Domain of Knowledge by @Tacocat12 | Stardance
Devlogs:
My first version!
SO MANY ERRORS. I have been debugging for 30 minutes of this hour. GitHub pages DID NOT want to collaborate but finally I got it sort of working. It doesnāt work anywhere other than GitHub pages but it does work. Anyway⦠I am going to go keep coding.
I have now revamped the UI and added more personalized backgrounds to the main page, next I will be working on the blog
Ships:
I made a personal website that shows off projects I made, projects I am working on, and some info about me. I met all the requirements and only used AI for spell check on my blog and main page....
|
1793505074.435153
|
1793591474.435153
|
|
32326
|
Bounce Game by @OggyW0ppy | Stardance
|
OggyW0ppy
|
1
|
9.0
|
22
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-15T05:31:40Z", "hours": 9.0, "multiplier": 2.33, "payout": 22, "blessing": "neutral", "text": "I made a collision demo with a ball bouncing around your window with walls that you can place. One of the most challenging parts of this was not actually the collision physics, but getting the right libraries to make a screen and draw stuff on that screen the way I wanted to. I am actually pretty impressed with the graphics I managed to make because I normally leave projects with their bad, simple graphics until the end. If you want to play it check out my github repo and download the jar file.", "repo": "https://github.com/OggyWoppy36/symmetrical-bassoon", "demo": "https://github.com/OggyWoppy36/symmetrical-bassoon/releases"}]...
|
[{"post_id": 27231, "ts": "202 [{"post_id": 27231, "ts": "2026-07-12T16:48:07Z", "hours": 1.1128, "text": "DEVLOG 3.5 I didnāt really add much just cleared up some code and made the pause system better (I tried to add a blur effect and failed so its just a text box now :P). However I plan to try some new things rather than working forever on this test project, as it is incredibly cumbersome to work in Java. I want to learn python, which I have minimal experience in (even though its the most popular language, I know). End."}, {"post_id": 27008, "ts": "2026-07-12T04:35:31Z", "hours": 3.3883, "text": "DEVLOG 3 - Project Repo Additions greatly improved graphics ball has shading boxes have a design and shading changed wall placement style (ROTATION!) created new class for the selection selection box is always visible change width/height with scroll wheel and holding alt/shift change rotation by scrolling normally checks if colliding with ball to prevent illegal placements left click to place wall game updates 5 steps per frame this helps prevent glitches through thin walls added some comments in the code to make it clearer Plans Try to improve lighting / shadows currently colors and shadow positions are preset also means more vector math!!! add an objective currently planning to make a puzzle to guide a ball into an endzone with minimal walls/bounces"}, {"post_id": 26370, "ts": "2026-07-11T03:44:04Z", "hours": 3.2878, "text": "DEVLOG 2 Additions added the ability to place your own walls can speed up/slow down ball with left/right added github repo added compatibility to rotate walls, collision not updated yet added anti aliasing Plans change wall placing mechanism to allow rotation allow new balls to be added some main goal of the game?"}, {"post_id": 24470, "ts": "2026-07-08T01:30:49Z", "hours": 1.6522, "text": "DEVLOG 1 using java to make a game (flame me all you want) -started with making a ball bounce along the screen -added separate collision shape object to allow rectangular walls to be put anywhere -added ball class to allow multiple balls at once -added pause functionality (no visual indication yet however, only movement stops) -plan to add dynamic wall placement as the game is running using the mouse"}]...
|
Title: Bounce Game by @OggyW0ppy | Stardance
Devl Title: Bounce Game by @OggyW0ppy | Stardance
Devlogs:
DEVLOG 1 using java to make a game (flame me all you want) -started with making a ball bounce along the screen -added separate collision shape object to allow rectangular walls to be put anywhere -added ball class to allow multiple balls at once -added pause functionality (no visual indication yet however, only movement stops) -plan to add dynamic wall placement as the game is running using the mouse
DEVLOG 2 Additions added the ability to place your own walls can speed up/slow down ball with left/right added github repo added compatibility to rotate walls, collision not updated yet added anti aliasing Plans change wall placing mechanism to allow rotation allow new balls to be added some main goal of the game?
DEVLOG 3 - Project Repo Additions greatly improved graphics ball has shading boxes have a design and shading changed wall placement style (ROTATION!) created new class for the selection selection box is always visible change width/height with scroll wheel and holding alt/shift change rotation by scrolling normally checks if colliding with ball to prevent illegal placements left click to place wall game updates 5 steps per frame this helps prevent glitches through thin walls added some comments in the code to make it clearer Plans Try to improve lighting / shadows currently colors and shadow positions are preset also means more vector math!!! add an objective currently planning to make a puzzle to guide a ball into an endzone with minimal walls/bounces
DEVLOG 3.5 I didnāt really add much just cleared up some code and made the pause system better (I tried to add a blur effect and failed so its just a text box now :P). However I plan to try some new things rather than working forever on this test project, as it is incredibly cumbersome to work in Java. I want to learn python, which I have minimal experience in (even though its the most popular language, I know). End.
Ships:
I made a collision demo with a ball bouncing around your window with walls that you can place. One of the most challenging parts of this was not actually the collision physics, but getting the right libraries to make a screen and draw stuff on that screen the way I wanted to. I am actually pretty impressed with the graphics I managed to make because I normally leave projects with their bad, simple graphics until the end. If you want to play it check out my github repo and download the jar file....
|
1793505072.1257226
|
1793591472.1257226
|
|
1172
|
Unity Motion Matching System by @NintedoAsh12 | St Unity Motion Matching System by @NintedoAsh12 | Stardance...
|
NintedoAsh12
|
1
|
150.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-28T04:05:22Z", "hours": 150.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a motion matching system. It took 11 months and over 200 hours of work. I originally made it for my own project but after seeing how bad motion matchers that were made for unity where I decided I might as well give it a shot and make something others can use. Its not perfect and its quite finicky but under the right conditions as seen by the ITCH.IO demo it can do its job. this project has lead me to tour my local university VICON motion capture set up as well as email the legendary Daniel Holden who did lots of work on a fancy type of motion matching called learned motion matching. if you donāt know what motion matching is itās a data driven animation technique where it uses a data base of animation frames and associated data to match the best looking movement to the characters current state and player input hopefully delivering the best and most realistic movement possible⦠if it works perfectly that is. examples of Motion Matching in action is: The last of us part 2 and 007 First Light. Thank you good people of stardance its been fun. Ash out for now. :-> bye", "repo": "https://github.com/nintendoAsh/Two-Nerds-Studios-Motion-Matching-System", "demo": "https://two-nerds-studios.itch.io/motion-matching-demo"}]...
|
[{"post_id": 83539, "ts": "202 [{"post_id": 83539, "ts": "2026-10-28T03:53:56Z", "hours": 3.4581, "text": "THIS IS IT FOLKS IM ABOUT TO SHIP! I HAVE BEEN WORKING REALLY HARD ON READMES EDITING AND UPLOADING THAT VIDEO OF HOW TO USE THE SYSTEM AND FINALY IT DONE. we are done⦠wow⦠I.. THANK YOU ALL! and with this here comes my curtain call."}, {"post_id": 82550, "ts": "2026-10-25T06:28:10Z", "hours": 3.8092, "text": "ITS ONLY BEEN A DAY. man I say that again⦠BUT NOW ITS EVEN CRAZYER yeah I worked for like 3 hours today not fun I donāt recommend my butt hurts from sitting. BUT I GOT DONE WHAT I WANTTED TO WHICH IS: We made another unity project (Yes another one) and I recorded 1 hour and 10 minutes of how to use the system.. yeah its not really a how it its a how to not do because OOOF I really donāt know how my own code works somedays and I had to pause recording for awhile to debug some stuff WHICH GOT IMPROVED UPON which is good. I just have to edit that video now (which wont be included in the project time sadly) I exported the motion matcher as a package got that into github and yeah⦠thatās about it⦠I have 1 readme to write and a video to edit and then SHIP its been fun hack clubbers (though sometimes it was very much not fun and I was ready to kick my laptop across the room light it on fire and run it over with my car."}, {"post_id": 82176, "ts": "2026-10-24T05:26:37Z", "hours": 2.5136, "text": "WOW ITS ONLY BEEN A DAY! LOTS HAS BEEN ACOMPLISHED! I hope. I have created a middle-man script that takes in data then gives it to the motion matcher trajectory thing. tomorrow I am going to make a tutorial of how to make it work. WOWOWOOWOWOWOWOWOW! we are getting close to being done and we only got 7 days to getter done. so lets GOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO!!!!!!!!!!!! btw if you are wondering how I made the middle man I learned a lot about C# inheritance. I have a custom class script that has all the variables that the motion matcher trajectory maker that script basically only holds the variables and does nothing else other then inherit from the normal unity thing MonoBehavior. then we have a script that inherits from that script that holds the variables. then the new script does all the math and grabbing of the data takes it and then since it inherits from the script it inherits the variables then we set the variables and then donāt have to hard code anything in the motion matching stuff. I hope I explained it right. Iām really eepy seepy and done for the day so I guess who cares."}, {"post_id": 81951, "ts": "2026-10-23T04:55:45Z", "hours": 4.4681, "text": "I finished all the code comments. I know. WOW 4 HOURS OF CODE COMMENTS yeah but I was also cleaning some other parts of it up and fixing some of the indentations. anyways thatās done now only a few more things till we get to ship! but also a note to other devs like me⦠please comment your code while writing it because I have gotten in the habit of not doing that and as seeing here by 4 hours logged of code comments PLEASE JUST DO IT WHILE WRITING IT BECUASE THIS SUCKS"}, {"post_id": 81124, "ts": "2026-10-19T23:48:27Z", "hours": 3.2969, "text": "Not much changed I made an Itch.io for the demo. I also started adding comments to all of my code yeah its hard to remember what does what but I also got the dataset editor done or almost done. then its onto the matcher and then the trajectory maker then we are done there and then onto a tutorial of how to use it then we are done"}, {"post_id": 80294, "ts": "2026-10-17T05:11:06Z", "hours": 4.6256, "text": "OK its fixed now but first test build didnāt go so well (see video) the problem was unity wasnāt saving any of my data running in the background because it wasnāt serialized. I also organized project files plus removing unneeded scripts (I reuse code a lot and sometimes things get replaced and just left there) I also if you canāt tell from the video a dropped frame counter to show matches that where canceled because the current frame was good enough to meet the cost threshold. anyways I think now most of what I have to do it package everything up into⦠well a package then send it off into the world for you the hack clubbers to mess around with. EDIT: I added a demo for Windows to the github if you want to try it early"}, {"post_id": 79321, "ts": "2026-10-13T14:51:10Z", "hours": 2.2531, "text": "The demo UI has been finished and it works quite well! I have a few more things to add like a looping map so that the Character doesnāt just walk off the end of the world and die plus some more main menu stuff I think too. anyways progress has been fast so far so expect more soon!"}, {"post_id": 78971, "ts": "2026-10-12T06:56:58Z", "hours": 5.7781, "text": "LOTS OF DEBUG UI COMEING YOUR WAY! I have added lots of UI stuff to display internal values such as costs as stuff. I have also added the ability to adjust motion matching settings from in the demo so when I upload it to itch.io all of you can play with the system as much as you want and tell me how bad you broke it. to do wise its a bit more UI (some of it doesnāt work or I want it to look better) and then the data points kinda like the unity gizmo stuff I have been showing you here on star dance. anyways its like 1 AM I should have gone to bed HOURS AGO so Iāmma go brush my teeth and work some more tomorrowā¦. my keyboard is starting to fail :-< Goodnight yāall. or good morning to the folk around the world like in Norway or something"}, {"post_id": 78190, "ts": "2026-10-09T22:29:56Z", "hours": 1.3486, "text": "I finally made a git hub repository. I also made a new unity project and moved everything into it to clean everything up for the demo I am starting to work on. I also made Bone Rotation matching but it doesnāt contribute all that match. I should be ready to ship/ Have a demo ready soon"}, {"post_id": 77746, "ts": "2026-10-08T04:44:35Z", "hours": 6.5831, "text": "OK OK IT WORKS ENOUGH OK DONT TOUCH IT Iām a fraud you guys. I couldnāt figure out the velocity thing so Iā¦. I USED AI! I SWARE I HAVENT BEEN THIS ENTIRE TIMEā¦. ok heres what happened I couldnāt figure it out so I had some AI going through some Motion Matching related thesis stuff and explaining it to me and then I ended up giving it a small chunk of my matcher code use to generate the cost and it pointed out my problemsā¦.. so 1. The way I was calculating local position was wrong which is funny because when I do it the other way it also breaks but then that leads into the second part. 2. I was inverting data and that was what was keeping the system working for some reason awhile back and even when I tried removing it a bit ago it broke which was really weird. anyways if you change both of them they fix each other so YAY I guess⦠sorry for the AI usage. it didnāt re write my code for me though I hand fixed my problem which I can proudly say all of the code is all hand typedā¦. (other then stuff I copy and pasted and or reused from other code I wrote⦠TRUST ME I NEVER WANT TO REWRITE UI SYSTEMS please unity fix the uitoolkit its bad)"}, {"post_id": 75040, "ts": "2026-09-28T23:29:30Z", "hours": 4.0911, "text": "Working on velocity matching. its kinda working now better then it was but its really weird that it slows the character down so much but its better then random snapping poses"}, {"post_id": 72963, "ts": "2026-09-24T03:42:38Z", "hours": 3.4628, "text": "HOLY CRAP IT WALKS!!! I canāt believe it. I am so FLIIPING happy ITS MOTION MATCHING! THAT IS ACTAUL REAL MOVEMENT AND NOT JUST WIGGLES!!!!! AAAAAAHHHHHH!!!!!! HECK YEAH!!!!!!! ok so in reality its still not fully working. I had to disable bone velocity matching completely to get it to work but I think I figured out why it doesnāt work. for trajectory matching I realized that the character is scaled to 1.83 instead of just 1 so that will affect the matching and I have to implement an offset (and I did it for the bone positions too but I never did it to the velocities) anyways I think I will fiddle with it till that work epeshly since STARDANCE WAS EXETENDED UNTILL OCTOBER 30TH THANK YOU HACK CLUB!!!! Video is of it working, not working and me playing with settings."}, {"post_id": 70896, "ts": "2026-09-19T23:38:42Z", "hours": 9.4997, "text": "WE HAVE HIT 100 HOURS LOGGED!!!! wow the amount of time I spent on this is CRAZY! anyways we have had little improvements on the matcher I have been trying to get it to give me a full animation but it refuses instead kinda just wiggling its arms up and down pretending to be a bird OR snapping between poses that have NOTHING to do with walking. I have spent the last few hours attempting to calibrate it to work as well as writing a better dataset debug script so then it will be easier to visualize what every frame of animation contains Data-wise so then I can attempt to manually match frames and see what the matcher ranks them vs what it normally matches so the I can maybe weight it or bias it a bit. we only have a week and bit left LET LOCK IN!!!!!!!!!!!!!!!!!!!!"}, {"post_id": 67146, "ts": "2026-09-13T06:34:17Z", "hours": 6.7892, "text": "we have done it! MOTION MATCHING FROM SCRATCH! the last week has been crazy. I have found more data from a unity demo of a long discontinued motion matching asset and I have retargeted the animation in blender and brought it into unity with proper root motion. since this was my first time using more then one animation clip with EVERYTHING I expected bugs and errors AND THAT I GOT. I had to go in and rewrite a really small chunk of how the dataset maker compiles the trajectory data. I had to make the matcher actually handle more then one clip as well as dig into a null reference error it was giving me so I had to dig into it more and learn that the dataset was still flawed and go back and do more to the editor AND THEN ONCE the data was good now the matcher scales the character to like 300% or something and I never even told it to touch scale so now I have to properly set up multi-animation unity playables since before I didnāt know that you couldnāt just set all the blend weights to one and hope for the best. now finally after all of that. it appears to match and hold onto a frame. I have a few last features to implement into it that being velocity matching so then it wont just hold a frame but understand that arms move and swing. as well as debug info for both me while testing as well as for you my dear hackclubbers so when I ship you all can see a bit into the inner workings of it. thank you for coming with me on this journey I never expected it to go this long but it feels good to have at least one person interested in what Iām working on for once and not just get shrugged off. - Ash ā¤ļø Video is of the matcher working photos are of the scaling issue"}, {"post_id": 63393, "ts": "2026-09-07T06:09:06Z", "hours": 5.9814, "text": "sheesh Iāve done a bit in the last week. So we have added the ability to match bones in the matcher got the matcher to handle multiple animation clips and I guess thatās it⦠I honestly thought I did more⦠on paper it doesnāt actually seem like that much.. huh. OH WELL! I also found a MASIVE collection of animation from a unreal engine demo project so Iām probably going to extract that and retarget TONS of that over the next few days because imma say it the problem with the matcher is the lack of good data at this point. Pink/Purple - Animation frame data position Red/green - predicted trajectory"}, {"post_id": 60036, "ts": "2026-09-02T04:33:58Z", "hours": 1.2344, "text": "OK OK OK IT WORKS!!!!! so we got bone positions to work. Iām done for the day. anyways I literally just had to flip my subtraction around⦠yes⦠its stupidā¦. anyways went from this: RootPositions[i][j] - BoneTransform.position to this: BoneTransform.position - RootPositions[i][j]. ok mic drop⦠I did say I would ship by the end of the month of august and clearly that didnāt happen but it will (hopefully) be this week Pink sphere is the foot pos from data set Blue is the other models foot pos not from dataset then red is root position (Also 2 devlogs in one day! Iām on fire!)"}, {"post_id": 59736, "ts": "2026-09-01T17:45:26Z", "hours": 8.6739, "text": "IM SO CLOSE!!!!!!!!! LIKE LATER TODAY (maybe canāt promise anything or the programing gods will kill me) I WILL HAVE MOTION MATCHING IN A GOOD DEMOABLE STATE FOR ME TO SHIP! I have got the bone data to work and actually spit out something useful by changing my whole approach and instead of sampling curves (which could work I just gotta deal with all the weird problems) I have created a unity scene in memory it spawns in the rig samples all the bone transform.positrons making unity do all the math and hard work before it returns me world positions of all of the bones I told it to track. the only problem I am having now is that I got to convert those world positions back into local position so that they can work anywhere (and yes I just converted them from local position to world position and this might sound counter intuitive but I need to change the parent of the local position) I remember this being easy for trajectory matching but maybe since this is WAYY more sensitive to rotation I need to try a different approach. the final stretch is approaching us dear hack clubbers. I got the rest of today then school starts tomorrow. LETS! LOCK! IN! YEAAAAAAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH!!!! btw the pink sphere is the foot potion⦠or what should be the foot position. Blue is the actual foot position. Red is root Position"}, {"post_id": 54275, "ts": "2026-08-25T05:45:45Z", "hours": 8.4231, "text": "Note to self⦠donāt freehand code⦠plan everything out on paper because Iām just experiencing Murpheyās law at this point :-< soā¦. the data that I didnāt know if it was right or not was incorrect⦠VERY incorrect (kinda) so that data was in local space I need it in world space but to convert it you either need to do the conversion through a transform (which requires a transform to reference) or do what I am doing (since I donāt have a easily accessible transform (unless Iām stupid and donāt know of one)) so I am going up the paths and for each object extracting their position and transforms (in local position) then adding it up until I eventually hit the root which would be in world space so now its converted (Iām doing the same for rotation too with more math) anyways my code for this entire project was never pre planned and I never normally pre plan but this is one of the times where once it works Iām going to figure out how it works (because who am I kidding I donāt really know) then Iām writing all of it down on paper and optimizing the loops and everything before jumping back into the editor to re-write the bake() function from scratch leading to MUCH BETTER READABILTY and hopefully speed because it takes a good 5 seconds from my for loops and brute force. anyways if you cant tell this is VERY BORING WORK and I really just want it to work SO BADLY because once I get everything in world position the next steps should be really easy but I shouldnāt say that because at this point if I do I might jinx myself"}, {"post_id": 46135, "ts": "2026-08-13T04:38:45Z", "hours": 3.9642, "text": "WOW JUST WOW!!! So I toured the Vicon Set-up at my local univercity and it was amazing. I loved every moment of it. they even put markers on me and captured some data (not any I can use for motion matching but still WOW THAT TECH IS COOL) In more on topic news I got the dataset maker to output bone data into the database. is it the correct data⦠idk but I will figure that out! (Photo of me standing forward is just a general photo with the markers. photo of me looking away from camera with hand in air is me showing off all the retroreflective markers (and EMGs) then there is a photo of the compiled dataset)"}, {"post_id": 43104, "ts": "2026-08-08T06:02:03Z", "hours": 2.9892, "text": "THERE WE GO! finally we can select what bones we want to track from a nested dropdown. now I just need to implement it into the baking logic so I can get a finished dataset out of dataset maker. perfect timing too. I have gotten a few emails back from the university and they are willing to give me a tour of the Vicon system and there may be a chance one day to capture data on it so hopefully everything works out and I can capture on the same tech that AAA game studios use which would be a dream come true and would blow my mind."}, {"post_id": 40564, "ts": "2026-08-04T06:14:32Z", "hours": 3.9083, "text": "There we go. I think I finally got it working. JEEZ UNITY NEEDS BETTER DOCUMENTATION ON THE UI TOOLKIT LIKE WOW ITS THAT BADā¦. anyway I got the custom lists working now I just gotta add the actual bone selections then write in the logic to add everything to the datasets. if you look at the photo thatās roughly how it will look to use the dataset maker. not sure if I mentioned this in the last devlog but I finally messaged my local university to see if they will let me either tour or use their vicon system so Iām hoping something comes of that because that would be really cool. anyways its really late I pulled another programmer and stayed up till midnight working. see yall later."}, {"post_id": 38041, "ts": "2026-07-31T06:49:07Z", "hours": 7.1853, "text": "Pretty boring stuff happening right now. I have been working to implement bone positional and velocity tracking into the dataset builder but since I wanted to use a custom class to do it the unity UI Toolkit decided to pick a fight and be really annoying to do it in. if anyone wants to write a custom class in unity and have it show up in a list view use this: link I also am working on processing some mocap data but its not going so well right now and I am getting pretty tired with dealing with these markerless systems so we will see if my local university will let me use or even tour their 10 cam Vicon setup (cross your fingers for me) anyways I still have one mocap session to prosses so I will probably do that tomorrow since I can just let it run while I am doing other things. also I just watched these videos where this guy is building open sourced optical mocap cameras and I think I might just funnel all my hack club hours into pcb credits to build a few of them. part 1 vid: https://youtu.be/kYVqL_DqBis?si=CPKxKiLa8cxf3M1t Part 2 vid: https://youtu.be/WJ13C_1hDIA?si=hMlQ8u5ofEBf-cFS"}, {"post_id": 34122, "ts": "2026-07-24T16:47:29Z", "hours": 8.3331, "text": "#MOTION MATCHING SYSTEM V1 DEVLOG ok its been a few days and we have gotten a few things done including started work on feet and hand bone tracking (the secret sause to motion matching) I finished making the large Charuco Board so I can calibrate FreeMoCap. so its coming along⦠slowly but thatās ok. the hardest part of all of this is the motion capture though since my setup is really bad (I wish my city had a capture studio somewhere even if it was small)"}, {"post_id": 29976, "ts": "2026-07-17T06:02:22Z", "hours": 10.1758, "text": "sheesh its been awhile since I last posted a devlog. MOTION MATCHING SYSTEM V1 - HIP Better matching Change Log/Updates Matching changed from world space to local space started work on recording motion capture I got more consistent matching now thanks to changing how it store the data in the dataset and how it matches to it. originally the future trajectory positions where stored as world space values in the dataset and the matcher would match it to the players world space values. if you know how transform systems work in game engines or blender you might know that because of that I had to be in the EXACT same position in the world that the data was recorded (you can see this in my last devlog where I kinda wiggle around in a few areas and get flurries of matches) in which⦠doesnāt work very well for this because if you had to record your self walking forwards backwards and side to side for ever single value in the game world that would take you FOREVER! so I switched it to local space which is basically where you are in the world based off of something. so like instead of 0, 0, 0 being the root of the world it would be where the character is so the trajectory positions are based around the character transform⦠do you know what I mean? I hope so because I cant think of a better way to explain it at the moment. Right now the biggest thing holding me back is the actual motion capture data that I am feeding into this thing because the recording I downloaded⦠is really bad. so I have been experimenting with a free open sourced software called FreeMoCap which is a marker less triangulation based motion capture software. I will report back when I get some good results out of it (hopefully soon) TODO hand and feet position and velocity matching 6 to 8 camera motion capture data finish Charuco board for FreeMoCap camera calibration Video is of the new matching in action the red (and 1 green) points are the players future predicted trajectory the pinkish purple points are the animation fames current trajectory. they should be aligned most of the time"}, {"post_id": 19015, "ts": "2026-06-30T05:40:05Z", "hours": 2.9392, "text": "FIRST MATCH!!! WE DID IT! This past week I started working on code to compare and chose a frame to play (the actual matcher) and it works⦠Kind of? YES IT MACHES⦠Is it a good match? HECK NO!!!! BUT IT MATCHES!!!! AND THAT JUST MADE 9 MONTHS OF WORK WORTH IT AS I HYPERVENTILATE WATCHING MY MATCHER STUGGLE BADLY LAGING EVERYTHING BUT IT WORKS! now the next step is making it work⦠properly. the video is of it trying to match. i kinda move around a bit to get it changing data but you can tell when it finds⦠something because the character will lock onto a frame or start playing the animation."}, {"post_id": 15199, "ts": "2026-06-24T18:20:54Z", "hours": 10.0492, "text": "WE HAVE A WORKING DATASET! Hello hack club! Didja miss me? NO?! WELL TOO BAD!!!!! I now got my motion capture data outputting a dataset with trajectory samples and root positions which is a VERY big step forwards. so as I have mentioned in the past motion matching is literally what MOTION MATCHING is doing. Matching the motion. I have had player predicted trajectory working since before stardance even started but only recently have we started to make progress on the motion capture data that we can MATCH to the players predicted trajectory. the set up I have going on for running the motion data extraction is really cool if I do say so myself. I have a custom editor menu where I can add animation clips and tell it what times in the future I want the trajectory to sampled from then it will compile everything into a scriptable object. plus I also added cool loading bars! anyways we are getting very close to having actual motion matching made from scratch. wow. 9 months this has took so far. its been fun. well⦠technically not done yet so lets keep up the good work and build the matching algorithm"}, {"post_id": 8844, "ts": "2026-06-14T18:22:33Z", "hours": 7.4806, "text": "DataSet Baker V1 Alpha - HIP is in the works!!!!! Now you might be asking why itās named HIP, and unless you are from Canada you will most likely not know who I am going to talk about, but the motion matching editor versions are going to be named after Tragically Hip album names (the first one is self titled so HIP). Anyways, in the last week I have gotten a lot done. I started work on actually figuring out the logic to get the trajectory out of the animation (and I donāt remember if I talked about this before but there were 2 ideas I had. 1 is I put the animationās root motion through a lot more math to get a proper predicted trajectory just like how the input trajectory works. Or just sample the actual future, but then you would get problems like a 90 degree turn where the animation isnāt even anticipating it yet but the trajectory says it should be.) I actually got really confused and stuck so I emailed someone. That someone is Daniel Holden, the creator of Learned Motion Matching (and he runs the website where I learned the first input trajectory math). And WOW!!!! HE RESPONDED: Hi Asher, Sorry for the late reply, I have been travelling the last couple of days. First of all I just wanted to say that it is awesome that you are looking into advanced animation techniques like these already. (email removed for space) (i might put it in the comments if you want to read it) I hope that helps! All the best, Dan LIKE HOLY COW!!! I am talking to a LEGEND!!!! Normal motion matching works as such: you got 2 trajectories, a predicted one from the input then a true trajectory from the animation, then you load all that animation into RAM and use a matcher to play the correct frame. But what he made was use a neural network instead of the matcher and database WHICH SHRUNK RAM USAGE LIKE CRAZY (and I might have to get working on something like that sometime soon because RAM prices donāt appear to be dropping anytime soon). Anyways, in the email he said that my second idea was actually right. The idea that I thought was wrong, but he says is just a sad limitation of it and nobody has figured it out yet (yetā¦). So that will make life easier because I WILL BE ABLE TO FINISH THE DATASET STUFF HOPEFULLY IN A WEEK!!!!!!! And to make that dataset I started messing around with Unityās UI Toolkit and custom editors. So now I have several custom drop downs and then you can open the MOTION MATCHING DATASET EDITOR where you can define all of your animation clips and once I write the rest, be able to press the bake button. It will process every frame and then spit out a Scriptable Object or database. Now hopefully writing the rest will be easier than writing the UI code because the UI stuff is powerful but not like normal runtime coding."}, {"post_id": 5233, "ts": "2026-06-08T22:55:23Z", "hours": 1.5761, "text": "HELLO STARDANCE!!!!!! I THINK I FIXED IT!!! Now I am not going to even mention that root motion is working this time because if you have been following along you know that the second āIT WORKS!ā comes out of my mouth something breaks. So last devlog I said I thought it was working but⦠my character was half way in the floor. after a bit of fiddling around and some google I discovered that the problem was that I had put the root bone in the hips of the character. And apparently in unity thatās a big no no. So one hour and eight minutes of blender B.S later I Fixed it (hopefully). I ended up using a blender addon called RootMaker to create a proper root bone at the feet where unity wants it. then I used the addon to transfer all of the root motion data from the hips into the new dedicated root bone. so now hopefully unity will be happy that it has a proper root bone to work with and wont try to shove my character into the earths mantle. The crazy part of all of this is that I have been doing more of blender and fighting animation during Stardance than actually working on the motion matching so if this continues to work I can get to work on what I am supposed to be doing; working on the actual motion matching. since I am the music variety of nerd I spend most of my time coding jamming to music and I think I started measuring my programing time in albums rather then hours XD. Over the course of just this weekend I have listened front to back to: 21st Century Breakdown - Green Day American Idiot - Green Day Back in Black - AC/DC Black Holes and Revelations - Muse The Black Parade - My Chemical Romance and if you add all of the runtimes of those albums up it matches very close to the time logged in Stardance so it might work XD. anyways I am going to go stretch my legs then maybe play some of The Last of Us Part 2 (which is very appropriate since it too uses motion matching as its animation system)"}, {"post_id": 5031, "ts": "2026-06-08T18:06:54Z", "hours": 1.1372, "text": "at this point I should stop saying that I have root motion working because every time I say that I jinx it and something falls apart. so I set everything up wrong (of course) so I need to pull all of the rigs apart once more to fix some errors that I made there and how I set up the root bone (its set at the hips not at the feet). so its been a fun ride (not) plus my laptop keeps trying to update my graphics drivers and every time it crashes unity, blender, plus all of the audio drivers with it. XD. I hope after today I can start work back up on motion matching and not dealing with blender and its shenanigans."}, {"post_id": 4545, "ts": "2026-06-07T21:49:20Z", "hours": 0.8836, "text": "Ok. I may have celebrated a little bit early. but I think I finally got root motion working for real this time. the problem was a combination of blender being blender, transformation offsets, weird scaling and just the names of objects/bones being wrong. though I did get an awesome video from when I was testing and comparing two animations together and root motion sent one of them into the floor so we got a beautiful video of one guy riding the other guys head. anyways lets hope that this keeps working because I just want to get my math mathing and dataset datasetting"}, {"post_id": 4362, "ts": "2026-06-07T17:35:54Z", "hours": 1.3164, "text": "This morning I got root motion finally set up in unity. since that now works I can begin working on a data set for the motion matching. I guess I never really explained how motion matching works in any of my other devlogs so I am going to do that right now: Motion matching is a animating technique where instead of using classic state machines that go if walking play walking animation they go this is your current position, velocity, trajectory, and a lot more and try to MATCH that MOTION to a large database of motion captured animations. so what I will be working on next is building that database/dataset of animations and the code to pull the current position, velocity, trajectory out of the animations then store each frame in a dataset for the matching code to search though to find one that matches what the character is currently doing on screen. its sounds kinda easy but trust me unless you are a big math/physics person (which I am not) its quite difficult to figure out how it al l works (plus you also need to know animations and blender which SUCKSSSS!) Also the video is of root motion NOT WORKING!"}, {"post_id": 1659, "ts": "2026-06-03T19:53:43Z", "hours": 1.2667, "text": "fighting unity and blender animation systems"}, {"post_id": 335, "ts": "2026-06-01T17:11:13Z", "hours": 0.4014, "text": "I got input trajectory working. The reason it wasnāt before was that movement and the prediction where in different update types (one was in fixed update and one was in regular update) so that works really well now. Now I am setting stuff up to make a animation dataset which involve me modifying my trajectory code to make it work with PRE RECORDED animations Devlogs From flavortown: Devlog 1: Lots of research and trial and error. I have spent all this time looking for an algorithm that works to generate a predicted trajectory from an input. I think I found the right one (I havenāt tested it yet) but if not then I know that I am looking in the right place at Daniel Holdenās articles on spring dampers check it out here: https://theorangeduck.com/page/spring-roll-call#controllers Devlog 2: I got the Trajectory prediction working!!!! after all of that math, research, and pain. it works! I wish I could truly express in words how happy I am. everything is based off of the work of Daniel Holden you can find it here: https://theorangeduck.com/page/spring-roll-call#controllers Devlog 3: Fixed jittering issue by adding a lerp to desired trajectory."}]...
|
Title: Unity Motion Matching System by @NintedoAsh Title: Unity Motion Matching System by @NintedoAsh12 | Stardance
Devlogs:
I got input trajectory working. The reason it wasnāt before was that movement and the prediction where in different update types (one was in fixed update and one was in regular update) so that works really well now. Now I am setting stuff up to make a animation dataset which involve me modifying my trajectory code to make it work with PRE RECORDED animations Devlogs From flavortown: Devlog 1: Lots of research and trial and error. I have spent all this time looking for an algorithm that works to generate a predicted trajectory from an input. I think I found the right one (I havenāt tested it yet) but if not then I know that I am looking in the right place at Daniel Holdenās articles on spring dampers check it out here: https://theorangeduck.com/page/spring-roll-call#controllers Devlog 2: I got the Trajectory prediction working!!!! after all of that math, research, and pain. it works! I wish I could truly express in words how happy I am. everything is based off of the work of Daniel Holden you can find it here: https://theorangeduck.com/page/spring-roll-call#controllers Devlog 3: Fixed jittering issue by adding a lerp to desired trajectory.
fighting unity and blender animation systems
This morning I got root motion finally set up in unity. since that now works I can begin working on a data set for the motion matching. I guess I never really explained how motion matching works in any of my other devlogs so I am going to do that right now: Motion matching is a animating technique where instead of using classic state machines that go if walking play walking animation they go this is your current position, velocity, trajectory, and a lot more and try to MATCH that MOTION to a large database of motion captured animations. so what I will be working on next is building that database/dataset of animations and the code to pull the current position, velocity, trajectory out of the animations then store each frame in a dataset for the matching code to search though to find one that matches what the character is currently doing on screen. its sounds kinda easy but trust me unless you are a big math/physics person (which I am not) its quite difficult to figure out how it al l works (plus you also need to know animations and blender which SUCKSSSS!) Also the video is of root motion NOT WORKING!
Ok. I may have celebrated a little bit early. but I think I finally got root motion working for real this time. the problem was a combination of blender being blender, transformation offsets, weird scaling and just the names of objects/bones being wrong. though I did get an awesome video from when I was testing and comparing two animations together and root motion sent one of them into the floor so we got a beautiful video of one guy riding the other guys head. anyways lets hope that this keeps working because I just want to get my math mathing and dataset datasetting
at this point I should stop saying that I have root motion working because every time I say that I jinx it and something falls apart. so I set everything up wrong (of course) so I need to pull all of the rigs apart once more to fix some errors that I made there and how I set up the root bone (its set at the hips not at the feet). so its been a fun ride (not) plus my laptop keeps trying to update my graphics drivers and every time it crashes unity, blender, plus all of the audio drivers with it. XD. I hope after today I can start work back up on motion matching and not dealing with blender and its shenanigans.
HELLO STARDANCE!!!!!! I THINK I FIXED IT!!! Now I am not going to even mention that root motion is working this time because if you have been following along you know that the second āIT WORKS!ā comes out of my mouth something breaks. So last devlog I said I thought it was working but⦠my character was half way in the floor. after a bit of fiddling around and some google I discovered that the problem was that I had put the root bone in the hips of the character. And apparently in unity thatās a big no no. So one hour and eight minutes of blender B.S later I Fixed it (hopefully). I ended up using a blender addon called RootMaker to create a proper root bone at the feet where unity wants it. then I used the addon to transfer all of the root motion data from the hips into the new dedicated root bone. so now hopefully unity will be happy that it has a proper root bone to work with and wont try to shove my character into the earths mantle. The crazy part of all of this is that I have been doing more of blender and fighting animation during Stardance than actually working on the motion matching so if this continues to work I can get to work on what I am supposed to be doing; working on the actual motion matching. since I am the music variety of nerd I spend most of my time coding jamming to music and I think I started measuring my programing time in albums rather then hours XD. Over the course of just this weekend I have listened front to back to: 21st Century Breakdown - Green Day American Idiot - Green Day Back in Black - AC/DC Black Holes and Revelations - Muse The Black Parade - My Chemical Romance and if you add all of the runtimes of those albums up it matches very close to the time logged in Stardance so it might work XD. anyways I am going to go stretch my legs then maybe play some of The Last of Us Part 2 (which is very appropriate since it too uses motion matching as its animation system)
DataSet Baker V1 Alpha - HIP is in the works!!!!! Now you might be asking why itās named HIP, and unless you are from Canada you will most likely not know who I am going to talk about, but the motion matching editor versions are going to be named after Tragically Hip album names (the first one is self titled so HIP). Anyways, in the last week I have gotten a lot done. I started work on actually figuring out the logic to get the trajectory out of the animation (and I donāt remember if I talked about this before but there were 2 ideas I had. 1 is I put the animationās root motion through a lot more math to get a proper predicted trajectory just like how the input trajectory works. Or just sample the actual future, but then you would get problems like a 90 degree turn where the animation isnāt even anticipating it yet but the trajectory says it should be.) I actually got really confused and stuck so I emailed someone. That someone is Daniel Holden, the creator of Learned Motion Matching (and he runs the website where I learned the first input trajectory math). And WOW!!!! HE RESPONDED: Hi Asher, Sorry for the late reply, I have been travelling the last couple of days. First of all I just wanted to say that it is awesome that you are looking into advanced animation techniques like these already. (email removed for space) (i might put it in the comments if you want to read it) I hope that helps! All the best, Dan LIKE HOLY COW!!! I am talking to a LEGEND!!!! Normal motion matching works as such: you got 2 trajectories, a predicted one from the input then a true trajectory from the animation, then you load all that animation into RAM and use a matcher to play the correct frame. But what he made was use a neural network instead of the matcher and database WHICH SHRUNK RAM USAGE LIKE CRAZY (and I might have to get working on something like that sometime soon because RAM prices donāt appear to be dropping anytime soon). Anyways, in the email he said that my second idea was actually right. The idea that I thought was wrong, but he says is just a sad limitation of it and nobody has figured it out yet (yetā¦). So that will make life easier because I WILL BE ABLE TO FINISH THE DATASET STUFF HOPEFULLY IN A WEEK!!!!!!! And to make that dataset I started messing around with Unityās UI Toolkit and custom editors. So now I have several custom drop downs and then you can open the MOTION MATCHING DATASET EDITOR where you can define all of your animation clips and once I write the rest, be able to press the bake button. It will process every frame and then spit out a Scriptable Object or database. Now hopefully writing the rest will be easier than writing the UI code because the UI stuff is powerful but not like normal runtime coding.
WE HAVE A WORKING DATASET! Hello hack club! Didja miss me? NO?! WELL TOO BAD!!!!! I now got my motion capture data outputting a dataset with trajectory samples and root positions which is a VERY big step forwards. so as I have mentioned in the past motion matching is literally what MOTION MATCHING is doing. Matching the motion. I have had player predicted trajectory working since before stardance even started but only recently have we started to make progress on the motion capture data that we can MATCH to the players predicted trajectory. the set up I have going on for running the motion data extraction is really cool if I do say so myself. I have a custom editor menu where I can add animation clips and tell it what times in the future I want the trajectory to sampled from then it will compile everything into a scriptable object. plus I also added cool loading bars! anyways we are getting very close to having actual motion matching made from scratch. wow. 9 months this has took so far. its been fun. well⦠technically not done yet so lets keep up the good work and build the matching algorithm
FIRST MATCH!!! WE DID IT! This past week I started working on code to compare and chose a frame to play (the actual matcher) and it works⦠Kind of? YES IT MACHES⦠Is it a good match? HECK NO!!!! BUT IT MATCHES!!!! AND THAT JUST MADE 9 MONTHS OF WORK WORTH IT AS I HYPERVENTILATE WATCHING MY MATCHER STUGGLE BADLY LAGING EVERYTHING BUT IT WORKS! now the next step is making it work⦠properly. the video is of it trying to match. i kinda move around a bit to get it changing data but you can tell when it finds⦠something because the character will lock onto a frame or start playing the animation.
sheesh its been awhile since I last posted a devlog. MOTION MATCHING SYSTEM V1 - HIP Better matching Change Log/Updates Matching changed from world space to local space started work on recording motion capture I got more consistent matching now thanks to changing how it store the data in the dataset and how it matches to it. originally the future trajectory positions where stored as world space values in the dataset and the matcher would match it to the players world space values. if you know how transform systems work in game engines or blender you might know that because of that I had to be in the EXACT same position in the world that the data was recorded (you can see this in my last devlog where I kinda wiggle around in a few areas and get flurries of matches) in which⦠doesnāt work very well for this because if you had to record your self walking forwards backwards and side to side for ever single value in the game world that would take you FOREVER! so I switched it to local space which is basically where you are in the world based off of something. so like instead of 0, 0, 0 being the root of the world it would be where the character is so the trajectory positions are based around the character transform⦠do you know what I mean? I hope so because I cant think of a better way to explain it at the moment. Right now the biggest thing holding me back is the actual motion capture data that I am feeding into this thing because the recording I downloaded⦠is really bad. so I have been experimenting with a free open sourced software called FreeMoCap which is a marker less triangulation based motion capture software. I will report back when I get some good results out of it (hopefully soon) TODO hand and feet position and velocity matching 6 to 8 camera motion capture data finish Charuco board for FreeMoCap camera calibration Video is of the new matching in action the red (and 1 green) points are the players future predicted trajectory the pinkish purple points are the animation fames current trajectory. they should be aligned most of the time
#MOTION MATCHING SYSTEM V1 DEVLOG ok its been a few days and we have gotten a few things done including started work on feet and hand bone tracking (the secret sause to motion matching) I finished making the large Charuco Board so I can calibrate FreeMoCap. so its coming along⦠slowly but thatās ok. the hardest part of all of this is the motion capture though since my setup is really bad (I wish my city had a capture studio somewhere even if it was small)
Pretty boring stuff happening right now. I have been working to implement bone positional and velocity tracking into the dataset builder but since I wanted to use a custom class to do it the unity UI Toolkit decided to pick a fight and be really annoying to do it in. if anyone wants to write a custom class in unity and have it show up in a list view use this: link I also am working on processing some mocap data but its not going so well right now and I am getting pretty tired with dealing with these markerless systems so we will see if my local university will let me use or even tour their 10 cam Vicon setup (cross your fingers for me) anyways I still have one mocap session to prosses so I will probably do that tomorrow since I can just let it run while I am doing other things. also I just watched these videos where this guy is building open sourced optical mocap cameras and I think I might just funnel all my hack club hours into pcb credits to build a few of them. part 1 vid: https://youtu.be/kYVqL_DqBis?si=CPKxKiLa8cxf3M1t Part 2 vid: https://youtu.be/WJ13C_1hDIA?si=hMlQ8u5ofEBf-cFS
There we go. I think I finally got it working. JEEZ UNITY NEEDS BETTER DOCUMENTATION ON THE UI TOOLKIT LIKE WOW ITS THAT BADā¦. anyway I got the custom lists working now I just gotta add the actual bone selections then write in the logic to add everything to the datasets. if you look at the photo thatās roughly how it will look to use the dataset maker. not sure if I mentioned this in the last devlog but I finally messaged my local university to see if they will let me either tour or use their vicon system so Iām hoping something comes of that because that would be really cool. anyways its really late I pulled another programmer and stayed up till midnight working. see yall later.
THERE WE GO! finally we can select what bones we want to track from a nested dropdown. now I just need to implement it into the baking logic so I can get a finished dataset out of dataset maker. perfect timing too. I have gotten a few emails back from the university and they are willing to give me a tour of the Vicon system and there may be a chance one day to capture data on it so hopefully everything works out and I can capture on the same tech that AAA game studios use which would be a dream come true and would blow my mind.
WOW JUST WOW!!! So I toured the Vicon Set-up at my local univercity and it was amazing. I loved every moment of it. they even put markers on me and captured some data (not any I can use for motion matching but still WOW THAT TECH IS COOL) In more on topic news I got the dataset maker to output bone data into the database. is it the correct data⦠idk but I will figure that out! (Photo of me standing forward is just a general photo with the markers. photo of me looking away from camera with hand in air is me showing off all the retroreflective markers (and EMGs) then there is a photo of the compiled dataset)
Note to self⦠donāt freehand code⦠plan everything out on paper because Iām just experiencing Murpheyās law at this point :-< soā¦. the data that I didnāt know if it was right or not was incorrect⦠VERY incorrect (kinda) so that data was in local space I need it in world space but to convert it you either need to do the conversion through a transform (which requires a transform to reference) or do what I am doing (since I donāt have a easily accessible transform (unless Iām stupid and donāt know of one)) so I am going up the paths and for each object extracting their position and transforms (in local position) then adding it up until I eventually hit the root which would be in world space so now its converted (Iām doing the same for rotation too with more math) anyways my code for this entire project was never pre planned and I never normally pre plan but this is one of the times where once it works Iām going to figure out how it works (because who am I kidding I donāt really know) then Iām writing all of it down on paper and optimizing the loops and everything before jumping back into the editor to re-write the bake() function from scratch leading to MUCH BETTER READABILTY and hopefully speed because it takes a good 5 seconds from my for loops and brute force. anyways if you cant tell this is VERY BORING WORK and I really just want it to work SO BADLY because once I get everything in world position the next steps should be really easy but I shouldnāt say that because at this point if I do I might jinx myself
IM SO CLOSE!!!!!!!!! LIKE LATER TODAY (maybe canāt promise anything or the programing gods will kill me) I WILL HAVE MOTION MATCHING IN A GOOD DEMOABLE STATE FOR ME TO SHIP! I have got the bone data to work and actually spit out something useful by changing my whole approach and instead of sampling curves (which could work I just gotta deal with all the weird problems) I have created a unity scene in memory it spawns in the rig samples all the bone transform.positrons making unity do all the math and hard work before it returns me world positions of all of the bones I told it to track. the only problem I am having now is that I got to convert those world positions back into local position so that they can work anywhere (and yes I just converted them from local position to world position and this might sound counter intuitive but I need to change the parent of the local position) I remember this being easy for trajectory matching but maybe since this is WAYY more sensitive to rotation I need to try a different approach. the final stretch is approaching us dear hack clubbers. I got the rest of today then school starts tomorrow. LETS! LOCK! IN! YEAAAAAAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH!!!! btw the pink sphere is the foot potion⦠or what should be the foot position. Blue is the actual foot position. Red is root Position
OK OK OK IT WORKS!!!!! so we got bone positions to work. Iām done for the day. anyways I literally just had to flip my subtraction around⦠yes⦠its stupidā¦. anyways went from this: RootPositions[i][j] - BoneTransform.position to this: BoneTransform.position - RootPositions[i][j]. ok mic drop⦠I did say I would ship by the end of the month of august and clearly that didnāt happen but it will (hopefully) be this week Pink sphere is the foot pos from data set Blue is the other models foot pos not from dataset then red is root position (Also 2 devlogs in one day! Iām on fire!)
sheesh Iāve done a bit in the last week. So we have added the ability to match bones in the matcher got the matcher to handle multiple animation clips and I guess thatās it⦠I honestly thought I did more⦠on paper it doesnāt actually seem like that much.. huh. OH WELL! I also found a MASIVE collection of animation from a unreal engine demo project so Iām probably going to extract that and retarget TONS of that over the next few days because imma say it the problem with the matcher is the lack of good data at this point. Pink/Purple - Animation frame data position Red/green - predicted trajectory
we have done it! MOTION MATCHING FROM SCRATCH! the last week has been crazy. I have found more data from a unity demo of a long discontinued motion matching asset and I have retargeted the animation in blender and brought it into unity with proper root motion. since this was my first time using more then one animation clip with EVERYTHING I expected bugs and errors AND THAT I GOT. I had to go in and rewrite a really small chunk of how the dataset maker compiles the trajectory data. I had to make the matcher actually handle more then one clip as well as dig into a null reference error it was giving me so I had to dig into it more and learn that the dataset was still flawed and go back and do more to the editor AND THEN ONCE the data was good now the matcher scales the character to like 300% or something and I never even told it to touch scale so now I have to properly set up multi-animation unity playables since before I didnāt know that you couldnāt just set all the blend weights to one and hope for the best. now finally after all of that. it appears to match and hold onto a frame. I have a few last features to implement into it that being velocity matching so then it wont just hold a frame but understand that arms move and swing. as well as debug info for both me while testing as well as for you my dear hackclubbers so when I ship you all can see a bit into the inner workings of it. thank you for coming with me on this journey I never expected it to go this long but it feels good to have at least one person interested in what Iām working on for once and not just get shrugged off. - Ash ā¤ļø Video is of the matcher working photos are of the scaling issue
WE HAVE HIT 100 HOURS LOGGED!!!! wow the amount of time I spent on this is CRAZY! anyways we have had little improvements on the matcher I have been trying to get it to give me a full animation but it refuses instead kinda just wiggling its arms up and down pretending to be a bird OR snapping between poses that have NOTHING to do with walking. I have spent the last few hours attempting to calibrate it to work as well as writing a better dataset debug script so then it will be easier to visualize what every frame of animation contains Data-wise so then I can attempt to manually match frames and see what the matcher ranks them vs what it normally matches so the I can maybe weight it or bias it a bit. we only have a week and bit left LET LOCK IN!!!!!!!!!!!!!!!!!!!!
HOLY CRAP IT WALKS!!! I canāt believe it. I am so FLIIPING happy ITS MOTION MATCHING! THAT IS ACTAUL REAL MOVEMENT AND NOT JUST WIGGLES!!!!! AAAAAAHHHHHH!!!!!! HECK YEAH!!!!!!! ok so in reality its still not fully working. I had to disable bone velocity matching completely to get it to work but I think I figured out why it doesnāt work. for trajectory matching I realized that the character is scaled to 1.83 instead of just 1 so that will affect the matching and I have to implement an offset (and I did it for the bone positions too but I never did it to the velocities) anyways I think I will fiddle with it till that work epeshly since STARDANCE WAS EXETENDED UNTILL OCTOBER 30TH THANK YOU HACK CLUB!!!! Video is of it working, not working and me playing with settings.
Working on velocity matching. its kinda working now better then it was but its really weird that it slows the character down so much but its better then random snapping poses
OK OK IT WORKS ENOUGH OK DONT TOUCH IT Iām a fraud you guys. I couldnāt figure out the velocity thing so Iā¦. I USED AI! I SWARE I HAVENT BEEN THIS ENTIRE TIMEā¦. ok heres what happened I couldnāt figure it out so I had some AI going through some Motion Matching related thesis stuff and explaining it to me and then I ended up giving it a small chunk of my matcher code use to generate the cost and it pointed out my problemsā¦.. so 1. The way I was calculating local position was wrong which is funny because when I do it the other way it also breaks but then that leads into the second part. 2. I was inverting data and that was what was keeping the system working for some reason awhile back and even when I tried removing it a bit ago it broke which was really weird. anyways if you change both of them they fix each other so YAY I guess⦠sorry for the AI usage. it didnāt re write my code for me though I hand fixed my problem which I can proudly say all of the code is all hand typedā¦. (other then stuff I copy and pasted and or reused from other code I wrote⦠TRUST ME I NEVER WANT TO REWRITE UI SYSTEMS please unity fix the uitoolkit its bad)
I finally made a git hub repository. I also made a new unity project and moved everything into it to clean everything up for the demo I am starting to work on. I also made Bone Rotation matching but it doesnāt contribute all that match. I should be ready to ship/ Have a demo ready soon
LOTS OF DEBUG UI COMEING YOUR WAY! I have added lots of UI stuff to display internal values such as costs as stuff. I have also added the ability to adjust motion matching settings from in the demo so when I upload it to itch.io all of you can play with the system as much as you want and tell me how bad you broke it. to do wise its a bit more UI (some of it doesnāt work or I want it to look better) and then the data points kinda like the unity gizmo stuff I have been showing you here on star dance. anyways its like 1 AM I should have gone to bed HOURS AGO so Iāmma go brush my teeth and work some more tomorrowā¦. my keyboard is starting to fail :-< Goodnight yāall. or good morning to the folk around the world like in Norway or something
The demo UI has been finished and it works quite well! I have a few more things to add like a looping map so that the Character doesnāt just walk off the end of the world and die plus some more main menu stuff I think too. anyways progress has been fast so far so expect more soon!
OK its fixed now but first test build didnāt go so well (see video) the problem was unity wasnāt saving any of my data running in the background because it wasnāt serialized. I also organized project files plus removing unneeded scripts (I reuse code a lot and sometimes things get replaced and just left there) I also if you canāt tell from the video a dropped frame counter to show matches that where canceled because the current frame was good enough to meet the cost threshold. anyways I think now most of what I have to do it package everything up into⦠well a package then send it off into the world for you the hack clubbers to mess around with. EDIT: I added a demo for Windows to the github if you want to try it early
Not much changed I made an Itch.io for the demo. I also started adding comments to all of my code yeah its hard to remember what does what but I also got the dataset editor done or almost done. then its onto the matcher and then the trajectory maker then we are done there and then onto a tutorial of how to use it then we are done
I finished all the code comments. I know. WOW 4 HOURS OF CODE COMMENTS yeah but I was also cleaning some other parts of it up and fixing some of the indentations. anyways thatās done now only a few more things till we get to ship! but also a note to other devs like me⦠please comment your code while writing it because I have gotten in the habit of not doing that and as seeing here by 4 hours logged of code comments PLEASE JUST DO IT WHILE WRITING IT BECUASE THIS SUCKS
WOW ITS ONLY BEEN A DAY! LOTS HAS BEEN ACOMPLISHED! I hope. I have created a middle-man script that takes in data then gives it to the motion matcher trajectory thing. tomorrow I am going to make a tutorial of how to make it work. WOWOWOOWOWOWOWOWOW! we are getting close to being done and we only got 7 days to getter done. so lets GOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO!!!!!!!!!!!! btw if you are wondering how I made the middle man I learned a lot about C# inheritance. I have a custom class script that has all the variables that the motion matcher trajectory maker that script basically only holds the variables and does nothing else other then inherit from the normal unity thing MonoBehavior. then we have a script that inherits from that script that holds the variables. then the new script does all the math and grabbing of the data takes it and then since it inherits from the script it inherits the variables then we set the variables and then donāt have to hard code anything in the motion matching stuff. I hope I explained it right. Iām really eepy seepy and done for the day so I guess who cares.
ITS ONLY BEEN A DAY. man I say that again⦠BUT NOW ITS EVEN CRAZYER yeah I worked for like 3 hours today not fun I donāt recommend my butt hurts from sitting. BUT I GOT DONE WHAT I WANTTED TO WHICH IS: We made another unity project (Yes another one) and I recorded 1 hour and 10 minutes of how to use the system.. yeah its not really a how it its a how to not do because OOOF I really donāt know how my own code works somedays and I had to pause recording for awhile to debug some stuff WHICH GOT IMPROVED UPON which is good. I just have to edit that video now (which wont be included in the project time sadly) I exported the motion matcher as a package got that into github and yeah⦠thatās about it⦠I have 1 readme to write and a video to edit and then SHIP its been fun hack clubbers (though sometimes it was very much not fun and I was ready to kick my laptop across the room light it on fire and run it over with my car.
THIS IS IT FOLKS IM ABOUT TO SHIP! I HAVE BEEN WORKING REALLY HARD ON READMES EDITING AND UPLOADING THAT VIDEO OF HOW TO USE THE SYSTEM AND FINALY IT DONE. we are done⦠wow⦠I.. THANK YOU ALL! and with this here comes my curtain call.
Ships:
I made a motion matching system. It took 11 months and over 200 hours of work. I originally made it for my own project but after seeing how bad motion matchers that were made for unity where I decided I might as well give it a shot and make something others can use. Its not perfect and its quite finicky but under the right conditions as seen by the ITCH.IO demo it can do its job. this project has lead me to tour my local university VICON motion capture set up as well as email the legendary Daniel Holden who did lots of work on a fancy type of motion matching called learned motion matching. if you donāt know what motion matching is itās a data driven animation technique where it uses a data base of animation frames and associated data to match the best looking movement to the characters current state and player input hopefully delivering the best and most realistic movement possible⦠if it works perfectly that is. examples of Motion Matching in action is: The last of us part 2 and 007 First Light. Thank you good people of stardance its been fun. Ash out for now. :-> bye...
|
1793505060.4570944
|
1793591460.4570944
|
|
30372
|
Auto Subscriber by @atomic925 | Stardance
|
atomic925
|
1
|
4.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-04T21:46:14Z", "hours": 4.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Auto subscriber- a python bot that automatically subscribes to youtube channels with many other features. FEATURES: a dark/light mode the ability to turn on and off notifications of a channel the ability to subscribe to multiple channels at once the ability to automatically close the chrome window after subscribing a sleek ui made in custom tkinter", "repo": "https://github.com/atomic92511/Auto-Subscriber", "demo": "https://drive.google.com/file/d/1mg0eNU8AlKM2RM_k_09XeQIZXhQWhj4A/view?usp=sharing"}]...
|
[{"post_id": 22191, "ts": "202 [{"post_id": 22191, "ts": "2026-07-04T15:02:43Z", "hours": 0.5239, "text": "Auto Subscriber - Python Bot, added the ability to subscribe to multiple accounts at once, here I subbed to hackclubhq and veritasium in a matter of seconds, and now instead of the bot typing the code letter by letter, it uses pyclip to automatically copy and paste it all and it saves up to 30 seconds"}, {"post_id": 21883, "ts": "2026-07-04T01:51:02Z", "hours": 0.8222, "text": "Auto Subscriber - python bot, I added a new customization where it auto closes the chrome window so you dont have to manually do it. it also now displays what number subscriber you were of the last channel you subscribed to"}, {"post_id": 21818, "ts": "2026-07-03T23:05:01Z", "hours": 0.5297, "text": "Auto subscriber - python bot, I have added a sleek new gui design and changed from tkinter to customtkinter there are now 2 customizations, which both work"}, {"post_id": 21762, "ts": "2026-07-03T21:08:01Z", "hours": 0.3728, "text": "Auto subscriber - python bot added a gui and im pretty much done, but I want to add some more customizations"}, {"post_id": 21744, "ts": "2026-07-03T20:40:27Z", "hours": 1.3239, "text": "Auto subscriber python bot - does automatically subscribe but I want to add a little more like a gui to select the channel"}, {"post_id": 21626, "ts": "2026-07-03T17:44:25Z", "hours": 0.3917, "text": "Auto Subscriber - Got PyAutoGui working and am now able to open youtube and go to a channel"}]...
|
Title: Auto Subscriber by @atomic925 | Stardance
Title: Auto Subscriber by @atomic925 | Stardance
Devlogs:
Auto Subscriber - Got PyAutoGui working and am now able to open youtube and go to a channel
Auto subscriber python bot - does automatically subscribe but I want to add a little more like a gui to select the channel
Auto subscriber - python bot added a gui and im pretty much done, but I want to add some more customizations
Auto subscriber - python bot, I have added a sleek new gui design and changed from tkinter to customtkinter there are now 2 customizations, which both work
Auto Subscriber - python bot, I added a new customization where it auto closes the chrome window so you dont have to manually do it. it also now displays what number subscriber you were of the last channel you subscribed to
Auto Subscriber - Python Bot, added the ability to subscribe to multiple accounts at once, here I subbed to hackclubhq and veritasium in a matter of seconds, and now instead of the bot typing the code letter by letter, it uses pyclip to automatically copy and paste it all and it saves up to 30 seconds
Ships:
Auto subscriber- a python bot that automatically subscribes to youtube channels with many other features. FEATURES: a dark/light mode the ability to turn on and off notifications of a channel the ability to subscribe to multiple channels at once the ability to automatically close the chrome window after subscribing a sleek ui made in custom tkinter...
|
1793505058.2995634
|
1793591458.2995634
|
|
30625
|
studpid ai chatting program by @yagmur | Stardance
|
yagmur
|
1
|
13.0
|
72
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-16T13:48:36Z", "hours": 13.0, "multiplier": 5.36, "payout": 72, "blessing": "neutral", "text": "get your key here!! the premise of what iāve done is very simple. make something that makes models on ai.hackclub.com very easy to use. (by that choice it also includes openrouter) i wanted it to be a lightweight terminal application instead of a hefty website with five bajillion frameworks and stupid simple to use: install the python package set your api key select your model start chatting as this is the first ship it is bare bones, hopefully in the future ill make it more tui-ish and add streaming and other nice settings", "repo": "https://github.com/yagmurpog/stupid-llm-chat", "demo": "https://pypi.org/project/dumbassllmchattingprogram"}]...
|
[{"post_id": 29487, "ts": "202 [{"post_id": 29487, "ts": "2026-07-16T13:42:34Z", "hours": 1.4344, "text": "welp it is ready"}, {"post_id": 29386, "ts": "2026-07-16T09:41:43Z", "hours": 1.8694, "text": "after a bit of polish, its ready for shipping!!!! atleast for linux not sure about windows and macā¦ā¦ā¦ā¦."}, {"post_id": 27684, "ts": "2026-07-13T13:56:00Z", "hours": 2.5444, "text": "wrote my own dumbass wrapper for openrouter because for some damn reason openrouterās doesnāt work on windows"}, {"post_id": 24272, "ts": "2026-07-07T18:47:38Z", "hours": 1.1189, "text": "hereās the foundtains for saving config and chats and stuff. it was going well until i found out that responses from the model arent easily dumpable aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, {"post_id": 23295, "ts": "2026-07-06T05:09:23Z", "hours": 3.4983, "text": "so choosing python for this job was kind of a stupid idea, there is no framework that does what i want it to do. (static webapp) i wasted a crap ton of time trying different stuff only to scrap it all and turn it back into a tui program"}, {"post_id": 22256, "ts": "2026-07-04T17:08:33Z", "hours": 1.4936, "text": "heres a lil demo"}, {"post_id": 22109, "ts": "2026-07-04T11:58:09Z", "hours": 1.4847, "text": "yup, its just an interface to chat with models on ai.hackclub.com, currently its just a tui program, maybe iāll turn it into a web app (no idea how iām going to do that) or make an gui with tkinter"}]...
|
Title: studpid ai chatting program by @yagmur | St Title: studpid ai chatting program by @yagmur | Stardance
Devlogs:
yup, its just an interface to chat with models on ai.hackclub.com, currently its just a tui program, maybe iāll turn it into a web app (no idea how iām going to do that) or make an gui with tkinter
heres a lil demo
so choosing python for this job was kind of a stupid idea, there is no framework that does what i want it to do. (static webapp) i wasted a crap ton of time trying different stuff only to scrap it all and turn it back into a tui program
hereās the foundtains for saving config and chats and stuff. it was going well until i found out that responses from the model arent easily dumpable aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
wrote my own dumbass wrapper for openrouter because for some damn reason openrouterās doesnāt work on windows
after a bit of polish, its ready for shipping!!!! atleast for linux not sure about windows and macā¦ā¦ā¦ā¦.
welp it is ready
Ships:
get your key here!! the premise of what iāve done is very simple. make something that makes models on ai.hackclub.com very easy to use. (by that choice it also includes openrouter) i wanted it to be a lightweight terminal application instead of a hefty website with five bajillion frameworks and stupid simple to use: install the python package set your api key select your model start chatting as this is the first ship it is bare bones, hopefully in the future ill make it more tui-ish and add streaming and other nice settings...
|
1793505056.0203788
|
1793591456.0203788
|
|
6590
|
Flower by @IvyMycelia | Stardance
|
IvyMycelia
|
2
|
104.2
|
1193
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-07T02:27:02Z", "hours": 27.0, "multiplier": 19.07, "payout": 503, "blessing": "neutral", "text": "The compiler is written in Flower itself and currently targets C, so this release was mostly geared towards making the type system have actual Flower semantics instead of a thin little blanket over whatever the backend happened to be doing. The big additions in v1.4 were: transparent type aliases real null nullable types as ?T == T | null semantic unions like int | string explicit narrowing with is explicit extraction with as That support now works across locals, parameters, return types, struct fields, and stable field-expression chains. The work had to touch parser logic, typecheck, narrowing, lowering, codegen, bootstrap, and then all the weird regressions those changes politely dragged into the room. It was.. a process for sure What Iām most proud of is that v1.4 pushed Flower toward a clearer identity that wasnāt defined by C as much anymore. This release also brought the docs back in line with the compiler, which was LONGGGGG overdue. If you want to test it, the main things to look at are the Better Types examples and the self-hosting flow. The compiler should bootstrap cleanly, the test suite should pass, and the examples now cover aliases, nullable values, semantic unions, inference, and struct/field narrowing behavior. For those who will be testing it, DO NOTE that I develop exclusively on my MacBook which is a UNIX system! I do not have the ability to properly develop and provide releases for Linux-specificalities or non-POSIX systems. Iām extremely sorry for this, but alternatively watch the provided video to see Flower in action :) If youāre not able to test it, watch this short (crappy) video instead: https://youtube.com/shorts/DyPtIru6cjY?feature=share", "repo": "https://github.com/IvyMycelia/flower", "demo": "https://github.com/IvyMycelia/flower/releases"}, {"ship_num": 2, "ts": "2026-06-18T16:00:30Z", "hours": 38.0, "multiplier": 18.19, "payout": 690, "blessing": "neutral", "text": "Flower is a self-hosted programming language for writing simple, explicit systems code without the abstraction bloat and OOP-heavy direction a lot of modern languages have. The compiler is written in Flower itself, currently targets C, and follows a straightforward pipeline: lexing, parsing, module loading, typechecking, and code generation. Over the past few months, Flower grew from a small lexer/parser/codegen experiment in C into a way bigger language project than I couldvāe imagined. This wasnāt my first attempt at a language, but it has been my favorite! I implemented compiler-enforced module semantics, stronger type-aware codegen, real boolean support, real string support, and a small standard library foundation. Strings now have equality, .length, indexing, and explicit casts to and from @char , while modules support exported prop declarations, aliases as namespaces, and private-by-default top-level declarations. The hardest part was bootstrap stability. I ran into idempotency failures, parser edge cases, compiler corruption scares, and plenty of my own bad logic. A lot of the challenge was getting new features to work not just once, but consistently enough for the compiler to rebuild itself cleanly. One bootstrap it succeeds, and then the next Iām scrambling to figure out why the new binary executable has a corrupted parser despite just working (Still havenāt fixed that yet! It.. was really confusing and Iāve got no clue why it happened lol). Iām proud that I kept pushing through that and ended up with something much more fun to use than where I started ā I mean, I donāt even have to write that much C anymore!! If people want to test Flower, the important thing to know is that it is self-hosted and still experimental, but it does work. The repo includes a bootstrap path, a test suite, and example programs covering types, control flow, memory, imports, strings, and bools. The current release is focused on making the core language feel real and usable before moving on to a larger standard library and a future non-C backend, so donāt be surprised if a C file is shoved in your face!", "repo": "https://github.com/IvyMycelia/flower", "demo": "https://github.com/IvyMycelia/flower/releases"}]...
|
[{"post_id": 79537, "ts": "202 [{"post_id": 79537, "ts": "2026-10-14T14:44:10Z", "hours": 10.3042, "text": "Integers, Integers, Integers Hello!! Been a while :) Lately I have been working on v1.6. I call it the āUsefullnessā update ā rhymes with Grug ā because it adds a ton of long awaited features and various convenience implementations Flower DESPERATELY needs. For example, currently the progress has to do with v1.6.1, or Fixed-Width Integers . When it comes to systems programming and in-general efficiency, having various integer sizes is important as it provides an additional layer of manual control over memory and sizes. I know I would have to add them eventualy, so why not put them at the start of the Usefulness update?? Iām sure theyāll come in handy later on. What Actually Changed? Well, for starters, thereās now fixed-width integers (yay)! Theyāre built in types, so you declare them as you would with any other atom / primitive: type Byte = u8 type Choice = Byte | u16 type OptionalByte = ?Byte struct Packet { pair: Byte[2], size: Choice, owner: OptionalByte } A whole bunch of commits and integer-specific changes regarding indices, arity, unions, nullables, etc etc etc have been made, and they all wonāt fit here so instead, take a look at the current branch ! Whatās In Store? Plenty more features, you can assure yourself! Thereās maybe 6 or 7 ā I swear ā or so commits left for this specific addition, and after that a lot more features laid out in the roadmap for 1.6! As always, thanks for sticking around and watching the fiasco that is this project become more and more estranged with every hour. Love yāall!! Ivy <3"}, {"post_id": 75225, "ts": "2026-09-29T15:04:00Z", "hours": 9.9331, "text": "Integer Types, Parser Fixes, and Segfaults! Phew ā this one was biiiiiggg. Flower is pretty much just a glorified C transpiler, which is NOT what I want for it! In order to move on, the data has to be handled explicitly by the FloC. So essentially, I implemented i8 , u8 , i16 , u16 , i32 , u32 , i64 , and u64 . For now, int canonically refers to an i32 value. A New Era? With these new literals, the old hoist-sized representation had to go. The decimal source text is preserved, meaning values such as 18446744073709551615 remain after parsing without causing any overflow. Types are picked up from declarations, assignments, function arguments, return values, field writes, array-element writes, * breath in * and binary expressions! Oof, that was a mouthful. That, of course, resulted in proper errors for things like: 256 assigned to u8 ā1 assigned to an unsigned type values beyond u64 unconstrained literals outside the default i32 range I Hate Memory During printing, every width is handled. Integer conditions retain existing zero / nonzero behavior, and literal types print their values rather than a character. Halfway through, I ran into sudden segfaults and memory leaks. I was taken aback, because I didnāt even change anything parser related yet. Turns out, I forgot an assignment in a declaration, which apparently the parser wasnāt able to handle (whoops!). Anyways, I fixed it by propagating errors through the compilation process, so the compiler doesnāt try to typecheck or code gen if the parser reports back errors, and instead will print them out. And thatās it! Not thatās it, but thatās all Iām going to explain for now. More specifics available on the GitHub, of course. Speaking of GitHub thank you so much to S1monr3dst0ne07 on GitHub for fixing some memory leaks in the previous version of Flower ā I forgot to prune allocations before returning from a function :p Love yāall!! <3 P.S.: So glad I gave up on documentation, I was genuinely dreading workong on the project and thatās why Iāve been ianctive for a long time :c"}, {"post_id": 53525, "ts": "2026-08-24T03:18:35Z", "hours": 9.7706, "text": "Hey, itās been a while! Iāve been finding it difficult to stay motivated for this project, especially with how the new payout system works and just my in-general inability to keep commitment despite having a lot of passion. That said, I am going back to working on this diligently, and I think to start Iām going to cut down on the documentation by making perhaps one or two changes, and then going right back to the compiler work. Documentation writing has not been the most fun for me, especially with how long it takes and how itās so difficult to not only write language reference that works, but also keeping the same whimsy Flower should have. Thank you to everyone whoās been following this journey, and I canāt wait to see yāall later!!! With Love, - Ivy <3"}, {"post_id": 26743, "ts": "2026-07-11T18:25:46Z", "hours": 9.1964, "text": "Devlog: v1.5.1 ā v1.5.5 Following all of the changes Flower has undergone, I felt it was time for some much-needed documentation. On paper this was supposed to be fairly quick, simple, and not require much brain power. Unfortunately for me I got a bit too over-zealous, and included things I thought should work, but in reality hadnāt. For example, in a lot of the code snippets Iād have something like: for i in range 0..10: print(i) end Printing non-string values was not yet supported in Flower. To fix this, I took a small detour back to v1.4 and implemented support for it ā mostly in a single codegen case: if ast.data._print.value_type.base == TOKEN_FLOAT or ast.data._print.value_type.base == TOKEN_DOUBLE: fprintf(out, \"printf(\\\"%%f\\\", \") gen_expr(ast.data._print.value, out, src) fprintf(out, \");\\n\") end Afterwards I added more smoke-tests in examples/io/print.flo . Every few runs, however, Iād get a segfault. This was especially odd because it wasnāt simply an error but rather a silent memory bug. Eventually I found out where it was originating ā thanks, ASan! Turns out after the new type system changes, I had forgotten to initialize some values to null / 0 in for loop handlers and a few other places. I just added typeInfo.data = null / 0 where applicable and it fixed the issue! What is v1.5, and why is this devlog so long? To answer the latter first.. I lowkey just forgot to post a devlog for the first two docs I made. Thatās it. For the former question, v1.5 is supposed to be explicitly a documentation pass. First thing I worked on was structure. I cleaned up the docs layout, moved things toward a more consistent lowercase docs/ tree ā I had been trying for so long to do that and I just finally got it to work ā and wrote down the documentation process itself so new pages arenāt just floating about. The point was to try and make the docs feel like a book instead of a folder full of unrelated notes. I wrote and checked the language pages for types, functions, and control flow by reading the compiler itself, not by trusting my (poor) memory. That meant checking parser rules, typecheck behavior, codegen boundaries, and example files before writing anything solid. Types especially needed this, given how Flower now has enough real type machinery that the docs can quickly go from being coherent to completely incorrect: nullable sugar, semantic unions, explicit casts after narrowing, alias behavior, current member limits, and the difference between what the language wants to become and what the compiler supports currently. Functions and control flow had a similar issue. I had to document prop , return rules, direct call forms, logical conditions, range-based for , and the rough edges like break and continue not yet being enforced cleanly as loop-only. That kind of thing is small until someone learns the language from the docs and hits the edge head-first (been there, done that). What Now? Iām just going to keep writing docs. Maybe do one devlog for every new doc, or a batch of docs, who knows! I certainly donāt :p"}, {"post_id": 23761, "ts": "2026-07-06T21:49:25Z", "hours": 0.6008, "text": "Devlog: Syncing Flowerās Docs Back to Reality Just a doc cleanup lol. No code change or compiler updates. Probably did more than needed for now but oh well! The mismatch was REALLY bad. The old docs preserve old assumptions, and someone reading them could walk away with a version of Flower that no longer really exists (or, in some cases, doesnāt exist yet or never ever existed)! What changed I updated the docs that had drifted the most from reality (relatable): README.md now reflects the current type-system shape ROADMAP.md treats v1.4 as accomplished the v1.4.0 milestone doc now includes more of the outcome, not just the original plan contributor docs no longer have stale semantics structure.md is more accurate to what Flower currently is, and what still needs a fuller rewrite later Yea, thatās it."}, {"post_id": 23618, "ts": "2026-07-06T18:01:45Z", "hours": 1.6556, "text": "Devlog: Finishing Nullable Field Narrowing At this point, Flower could already narrow semantic unions through field access in the is / as case, and nullable field checks were supposed to be the obvious follow-through: if maybe_box.value != null: label: string = maybe_box.value as string end Instead, I had forgotten to remove a LOT of stale code, and thus part of it was still behaving like only plain local variables could ever be narrowed. There was also a second, smaller mismatch hiding, where null in type position was not lining up with the compilerās actual internal null representation. ?string and string | null werenāt leading to a congruent output and at times were wobblier than they should be. So the fix was mostly cleanup, but the meaningful kind: make null in type syntax lower the same way the compiler expects remove the stale var-only branches in nullable narrowing let stable field paths like maybe_box.value and holder.box.value narrow properly The funny part is that this felt bigger initially than it actually was once fixed. Nothing fundamentally new had to be invented, I just had to stop the old code from interfering with the newer code, which once I figured out how to do so it was quite quick. I spent an embarrassingly long time figuring it outā¦"}, {"post_id": 22284, "ts": "2026-07-04T17:48:44Z", "hours": 1.8161, "text": "Devlog: Letting Union Narrowing Follow Field Access Before v1.4.13 , union narrowing only really worked when the thing being narrowed had a variable name due to almost every similarity check relying on name_start and name_length . This was dumb, because semantic unions already knew how to test tags and extract members. Codegen was not the issue, but rather the annoying part was that the typechecker could remember this: if value is int: n: int = value as int end but not this: if box.value is int: n: int = box.value as int end So I still had to do a little temp-variable ritual: tmp: Value = box.value if tmp is int: n: int = tmp as int end Which was gross. Not necessarily catastrophic, just gross and annoying. I wanted needed convenience What changed The compiler was remembering narrowings by variable name, not by expression shape, so box.value looked obvious in source (to me, at least), but to the typechecker it was basically some random expression and not something it could reliably recognize again later. A variable name already had a stable identity, whereas field access chain did not. So the change was to let narrowable expressions represent more than just AST_VAR_REF . For now, that only means stable dot-access chains. The typechecker can record a narrowing for an expression like: box.value and then recognize the same expression later when a cast shows up. So this works directly now: if box.value is int: n: int = box.value as int end Same for the other union members, like string . The detour My first example accidentally wandered into a different feature: if maybe_box.value != null: That exposed a real nullable-field-guard gap, but that is not what this was supposed to be about. Very rude of the test case to have ambition hmph >:( Where this leaves it Semantic union narrowing now persists past field access ā at least for stable dot-access chains ā and the temp-local is no longer needed. Butttt now I gotta work on nullable-field-guards, ugh (hehe)"}, {"post_id": 21926, "ts": "2026-07-04T03:34:19Z", "hours": 0.4592, "text": "Devlog: Direct Semantic Union Parameters Now instead of having to do this workaround: type Value = int | string func accept(value: Value): bool You can just pass semantic unions directly: func accept(value: int | string): bool That was it. All I had to do was remove a stale type_error clause in register_params and allow binding variables. Then I updated the two relevant accept functions in /examples."}, {"post_id": 21751, "ts": "2026-07-03T20:51:30Z", "hours": 4.9086, "text": "Devlog: Making ?T Actually Mean T | null Before v1.4.10 , ?T was treated as its own nullable system and not really integrated with the rest of the semantic unions. This was unideal, because it created a separation of logic which was cumbersome to maintain. The idea was to make the following be the default: ?int == int | null ?string == string | null ?@int == @int | null Prior to the refactor, nullable types were still mostly pointer-oriented. That worked when ?T basically meant āmaybe this pointer is null,ā but it did not really fit anymore once semantic unions became actual runtime values. If Flower has T | null , then ?T should use that instead of being its own special thing. This is a more pragmatic choice, as it keeps the compiler easier to manage and update later on. What changed Typecheck now lowers ?T into the same semantic-union machinery used by normal unions. That means nullable values now go through the same general path as union values: null checks use union-aware narrowing narrowed nullable values can be extracted with as codegen emits tagged union storage assignments pack into the right union member So this now works as an actual nullable flow: maybe: ?@int = raw if maybe == null: return false end real: @int = maybe as @int The annoying part is that Flower has to track two things at once: the type the programmer is allowed to see after narrowing, and the actual union shape that remains underneath it. After the guard, maybe behaves like an @int . But codegen still has to remember it came from @int | null , because apparently the compiler cannot simply āvibeā its way through storage layout. Tragic! The bugs that annoyed the heck out of me Most of the work was not surface syntax. The syntax was just standing nearby looking innocent. The actual bugs were in the places where Flower knew āthis is non-null now,ā but then forgot how to lower, such as: narrowed nullable values falling back to raw C casts like (int*)(maybe) false branches of == null / != null narrowing to the wrong side (this was my fault lol) null getting packed into the wrong union member That last one was the rude one. For ?@int , generated C could end up doing something like: . tag = 1 , . m0 = NULL instead of packing into the actual null member. So the value looked almost right, but the tag/member pairing was wrong. Then later null checks would fail, because the compiler had technically put null somewhere. Just not the correct somewhere. Very helpful. The fix was separating two questions I had accidentally merged: is this type compatible with this union? which exact union member should this value occupy? Those look related, but they are not the same question. Flower was using the first answer for the second problem, and then acting surprised when everything became soup. Where this leaves Better Types ?T now lowers through the same path as T | null , which means null checks, narrowing, extraction, and storage all line up with the semantic union model. This should make later work cleaner, such as nullable inference, nicer union ergonomics, maybe pattern-like narrowing eventually. Not easy. I am not saying easy near a compiler. That is how they hear you. You do not want them to hear you .."}, {"post_id": 19626, "ts": "2026-07-01T00:18:08Z", "hours": 0.4472, "text": "Devlog: Teaching Flower to Understand Guard Clauses gave Flower branch-local inference. Last update, I added support for branch-local inference, so the compiler could understand things like: if maybe == null: return false else: real: @int = maybe end and: if value is int: return false else: s: string = value as string end That was an improvement, but it still meant narrowing stopped at the end of the branch. That meant stuff like returninging in some conditions still did not really work as naturally as it should: if maybe == null: return false end real: @int = maybe or: if value is string: return false end n: int = value as int In v1.4.9 I fixed that. What changed Now narrowing propagates past very obvious guard clauses. If one branch definitely returns and the other falls through, the compiler now carries the interpretation forward after the if . This means that the compiler can now understand: after if x == null: return ... , x is non-null after if x is string: return ... , a two-member semantic union can narrow to its remaining member I kept this intentionally conservative for now. The compiler is not doing full control-flow analysis yet. It is only recognizing the simplest and most explicit early-exit shape. How it works The main addition was a small semantic check for ādoes this branch definitely return?ā Right now that means: direct return if where both branches definitely return Once the compiler knows one side exits and the other survives, it applies the branchās narrowing to the following statements. Yea.. thatās it lol."}, {"post_id": 19014, "ts": "2026-06-30T05:39:45Z", "hours": 1.2028, "text": "Devlog: Adding Obvious Branch-Local Inference to Flower Before this, narrowing mostly worked in the obvious ātrue branchā cases: if maybe != null: real: @int = maybe end and: if value is string: s: string = value as string end But the else branch was still kind of standing there empty-headed, even when the meaning was extremely obvious. Like, if this happens: if maybe == null: return false else: real: @int = maybe end then inside the else , maybe is clearly not null. So now it doesnāt!! What changed Flower now does branch-local narrowing in else for small, explicit cases. That means these now work: if maybe == null: return false else: real: @int = maybe end and: if value is int: return false else: s: string = value as string end It is only applying inference when the condition says something directly and the opposite branch has one obvious meaning. Nullable narrowing For nullable pointer-like values, Flower now understands both sides of simple null checks: if x != null narrows x to non-null in the if body if x == null narrows x to non-null in the else body the opposite side can narrow to null when that is the only meaning left Semantic union narrowing The same idea applies to semantic unions, but a bit more āheld back.ā Essentially, if Flower sees: if value is int: then the if branch narrows to int , like before. Now, if the union only has one other possible member, the else branch can narrow too. So for: int | string the else after if value is int can be treated as string . This is not full control-flow wizardry, since it doesnāt reason across deep boolean chains, early-returns, or giant branches yet. It is deliberately small and local, because I do not want Flower āhelpingā so much that I need a detective board to figure out what type something is."}, {"post_id": 18478, "ts": "2026-06-29T17:18:49Z", "hours": 0.8039, "text": "Devlog: Letting Semantic Unions Work In Functions After getting semantic unions working in local declarations, the next problem was fairly obvious (and in my roadmap hehe). This did not work before: func make_value(): int | string return 7 end func accept_value(value: int | string): bool return value is int end Which was annoying, because int | string was already a real union type at this point. Flower could use it in locals, it could pack assigned values, it could check variants. But if I returned 7 from a function declared as int | string , or passed 7 into a parameter expecting int | string , the compiler did not know how to carry that union-lowering information across the boundary. This has been one of the easier changes Iāve made in a long while. It compiled properly first try (if you ignore a tiny misspell I made which I fixed really quickly), and there were no prior hidden bugs that surfaced. This.. is too suspicious. What changed The compiler now carries semantic union info through: function parameters function returns imported alias calls If a function expects: int | string and I call: accept_value(7) typecheck records that 7 needs to be packed as the int member of that union. Same for returns: func make_value(): int | string return 7 end That matters because codegen cannot guess later due to the separation of responsibilities Iāve laid out. By the time Flower is emitting C, it needs to know which tag to set and which member to write. Lowering it properly Codegen already knew how to pack union values for declarations and assignments. The missing part was doing the same thing for call arguments and return statements. So now a value can be packed into a tagged union when it is: stored locally passed into a function returned from a function Alias calls got handled too, so things like: remote.accept(11) remote.make_string() do not become their own weird little cursed island. Why this mattered Without this, semantic unions only worked as long as I never organized my code. They worked in local tests, but not in helper functions, imported providers, or normal inputs and outputs. Now union values can actually move around the program instead of being trapped in the one scope where they were declared ā and for me, forgotten! Very exciting, the union can leave the house. They grow up so fast āāĢ“Ģ ā āĢ“Ģā"}, {"post_id": 18151, "ts": "2026-06-29T05:17:03Z", "hours": 3.3186, "text": "Devlog: Semantic Unions Become Actual Values (Part I) In v1.4.6 , I made semantic unions actual runtime values instead of just parsed/typechecked shapes. Before this, Flower could understand: type Value = int | string as a type. It could point at it and say, āyes, that is a union,ā but that was mostly theoretical. The goal was to make this work-work for realsies: type Value = int | string value: Value = 7 if value is int: n: int = value as int end value = \"Ivy\" if value is string: s: string = value as string end That meant Flower needed more than TypeInfo.is_union = true . It needed a full path from syntax, to type proof, to lowered storage, to runtime extraction. Otherwise unions would just be fancy typechecker thingy-ma-bobbies, which is not very useful when the backend still emits C. What changed Instead of treating a union as a vague āone of these types, probably,ā Flower now lowers it into a tagged structure. Conceptually, this: type Value = int | string becomes something like: struct Value { int tag ; union { int as_int ; flower_string as_string ; } data ; }; Not the final sacred form forever, but that is the shape of it: a tag saying which variant is active, plus storage for the possible members. Since Flower emits C right now, the lowering is C-shaped. I am not fully sure how I want this to look in ASM yet, but I do know it would be way more technical, and uglier. This required a few things to play nicely with one another: if value is int creates a union proof the guarded branch stores narrowing information value as int is only allowed after proof assignments pack values into the right tagged member explicit casts extract the right member from storage Otherwise the compiler is just writing checks its own backend cannot cash. The part that makes it ACTUALLY semantic For pointer narrowing, if value is T mostly refines how the compiler treats an existing value. For semantic unions, the check also becomes a runtime tag test. So this: if value is int: means: check the active tag of value , then inside this branch, treat it as the int variant. Then this becomes valid: n: int = value as int because the branch already proved the active variant. Without that proof, value as int should not be casually allowed. Flower is supposed to be explicit, not psychic, and I am not confident enough yet to implement a proper intuitive implicit checker without summoning something cursed. Assignment and extraction This: value: Value = 7 now packs 7 into the int member and sets the tag to the int variant. Then this: value = \"Ivy\" does the same thing, but for the string member. So a semantic union is not just some bytes, but rather a tagged runtime object where Flower knows which member is active. Then explicit casts like: value as string can lower into extracting the string member, but only when the typechecker has accepted that the operation is safe in that control-flow path. Why this checkpoint matters Flower can now store variant values, prove which variant is active, and require explicit extraction instead of relying on random magic I threw together. The flower has grown another concerning little organ."}, {"post_id": 16395, "ts": "2026-06-26T17:55:41Z", "hours": 2.0825, "text": "Devlog: is Checks v1.4.5 added is checks, mostly so code like this can work: if maybe_ptr is @int: real_ptr: @int = maybe_ptr end The idea is (fairly) simple: if the condition proves maybe_ptr is an @int , the inside of the branch should be allowed to treat it like one. Flower did not know how to do that before. It knew what a variable was declared as, but it did not really learn anything from control flow yet. Now it can, at least for the pointer/nullable-ish cases I care about first. This touched the parser, AST, typechecker, narrowing logic, and codegen. So, naturally, the āsmall featureā went everywhere. Iād actually consider this one of the bigger refactors so far, mostly because it added a new TypeAtom structure. Before this, types were still a bit too attached to the places they appeared, and all fell under the TypeInfo . That worked for simpler declarations, but is checks needed type syntax to have something the compiler could pass around to use for comparisons, validations, and narrowing. The parser had to recognize the new expression shape. The AST had to store the left side and the tested type. The typechecker had to make sure the test was allowed and not totally garbage. Then the narrowing logic had to say, āinside this branch, this variable has the proven type of x and therefore we wonāt flag you for being an idiot.ā That last part was where the bug goblin lived. Iām calling them a goblin because they were sneaky (and I also think itās quite a funny and cute name). For a while, Flower had applied narrowing from the if body instead of the if condition, which meant the compiler saw this: if maybe_ptr is @int: real_ptr: @int = maybe_ptr end and somehow still failed on the assignment inside the branch. Very helpful. Thank you, compiler. EVen though itās obviously 100% my fault, I made the compiler, but oh well!! Once I changed the narrowing step to inspect the actual condition expression, it started behaving like it should. The typechecker could see maybe_ptr is @int , attach that narrowed type to the branch scope, and allow maybe_ptr to be used as @int inside the guarded block. For now this explicitness is how I want it. There may come a time in the near future where I decide some implicity is ok, but weāll see ;) is checks are the first real step towards control-flow-aware typing in Flower. Not full union support yet, but definitely the beginning of that road soon to come. Right now it mostly helps with nullable and pointer-like cases. Later, the same idea can support richer unions, better narrowing, and more type-driven control flow without making the programmer manually restate everything the compiler should already know. Also, it bootstrapped cleanly twice ā which.. is obviously the bare minimum, but still!!"}, {"post_id": 15458, "ts": "2026-06-25T04:05:50Z", "hours": 2.4619, "text": "v1.4.4 Devlog: Giving Flower Real Semantic Union Types I made it so that semantic unions are now in Flowerās parser and type system ā but not yet its codegen. The goal was to support types like: value: int | string next: @Node | null type Result = int | string Whatās new The parser now understands | inside type positions and builds semantic union type information instead of relying on those old plain aliases or backend-shaped hacks. On the typecheck side, unions are now carried through normal type copying and alias resolution. That means named aliases like: type MaybeName = string | null make sense after resolution, instead of collapsing into nonsense. The typechecker also now accepts union-compatible usage in the places that matter for a foundation: variable initialization assignment parameter passing return checking alias resolution So if a value matches one union member, it is accepted. This is sorta implicit behavior, but I think it gets a pass due to its somewhat explicit nature? What it does not do yet This version was intentionally strict about using unions as values. You cannot yet directly: index a semantic union access a field on a semantic union use arithmetic / comparison operators on one print one directly Instead, Flower now requires an explicit cast before using a union value that way. That may sound harsh, but it is the right restriction.. for now. There is not any narrowing yet, so pretending unions were fully usable would just make the language lie and spit out 2,000 errors. Where this leaves v1.4 Flower now has: transparent type aliases null as a real type-system concept pointer-first nullable types semantic union type representation The next step is the part that will make unions actually usable rather than merely legal: narrowing with is better explicit extraction with as eventually making ?T truly become T | null instead of remaining pointer-first for now No fun screenshot this time :p just frontend work for now⦠Ivy, signing off <3"}, {"post_id": 14511, "ts": "2026-06-23T17:31:39Z", "hours": 1.8206, "text": "Devlog: Adding Pointer-First Nullable Types to Flower I worked on giving Flower its first real nullable type surface without being overambitious and pretending the compiler is ready for full optional-everything semantics yet. The new syntax now works like this: ptr: ?@int = null text: ?@char = null That means there is now an explicit way to say āthis pointer-like value may be absent,ā instead of relying entirely on raw pointer habits from C (If you couldnāt tell by now, I despise C). What changed The main work was split across lexer, parser, and typecheck. I added: ? as a type marker in type positions is_nullable tracking in TypeInfo type rules for nullable pointer/reference values explicit compatibility for: assigning null into nullable pointer-like types comparing nullable values against null casting between @T and ?@T I also kept the scope intentionally narrow: this implementation is pointer-first nullable support , not full nullable scalars. So ?@int makes sense right now, but ?int is still deferred until I make a better semantic union / optional representation for plain values. Why this matters It would have been easy to overreach here and claim ānullable types are done,ā but that would have been a big phat lie. Pointer-like nullability lowers naturally enough with the current backend and current compiler model. Scalar nullability, however, does not. Once you let int or bool become nullable, you need a more real representation for āhas value / no value,ā and that belongs in the later union work, not here. Result explicit absence compiler-owned semantics better future unions stronger type meaning without hidden magic The next real step after this is not more patching around null ā I consider that done for now ā but instead giving Flower the deeper machinery needed for nullable non-pointer values and semantic unions later in v1.4 so it doesnāt come back to bite me in my butt."}, {"post_id": 13935, "ts": "2026-06-22T21:20:58Z", "hours": 0.355, "text": "Devlog: Formalizing Flowerās Null Foundation Flower already had some of the pieces for null , but they were a bit scattered. The goal here was to make it explicit, consistent, and safe before moving on to nullable syntax like ?T or full union-based nullability later in v1.4 . Another shorter devlog, but still important and distinct enough for me to think āHmm devlog time? Yes, devlog time!ā What changed The main work was in typechecking. I added to the compilerās idea of what null is, how it is represented internally, and what kinds of values are actually allowed to accept it. Rather than letting null-related behavior stay implicit across a few checks, null now follows a clearer rule set: null has one centralized internal type representation pointer-like values can explicitly accept null null comparisons and assignments now go through the same semantic path Why this matters This isnāt all that important on its own, but it matters a lot for where Flower is going next. If null is not defined well, then later features like: ?T better unions smarter narrowing more expressive type flow all become more error-prone (or so I assume given my track record) than I want need them to be. Validation I also expanded the example coverage so null : it now has dedicated behavior checks around assignment, passing values around, and comparison behavior."}, {"post_id": 13918, "ts": "2026-06-22T20:30:15Z", "hours": 1.0089, "text": "Devlog: Fixing Flowerās Compiler Process So It Stops Fighting the Host This wasnāt really about language design at all buttttt it is much more embarrassing , AND more important: Flowerās compiler process itself was too fragile. The immediate issue showed up on Linux, specifically NixOS (thanks shipwrights <3). The build flow was assuming too much: a previously existing bin/Flower could be reused safely bash would exist at the expected path clang would always be available the checked-in compiler binary would be runnable on whatever machine the repo landed on That worked well enough on my machine until it didnāt. On NixOS ā and by extension probably any other machine without the prexisting binaries I had ā it broke: make targets were inconsistent, the shell script failed on interpreter assumptions, and the compiler binary itself could be the wrong format for the host. What changed The fix was to separate āthe compiler source existsā from āthe current compiler binary is usable on this machine.ā The build process now starts by compiling a fresh host-native bootstrap compiler from bin/Flower.c , instead of trusting whatever happens to already exist in bin/Flower . That means the flow is now: bin/Flower.c -> host-native bootstrap compiler -> new Flower compiler -> self-check instead of: maybe existing bin/Flower -> hopefully works -> maybe bootstrap Ok well thatās kinda a lie; it still relies on hopes and dreams to bootstrap sometimes. BUT itās MUCH safer! And now everyone gets to experience crippling bootstrap anxiety, instead of being met with a failure before the actual compiler gets to.. well, do its thign! I also cleaned up the surrounding tooling: switched the bootstrap script to portable sh restored a clearer build / bootstrap / rebuild / test / clean structure made the compiler use CC and CFLAGS from the environment instead of hardcoding clang What this actually improves Flower is still not universally cross-platform yet. The compiler driver still has POSIX-shaped assumptions in places, and the emitted C can still depend on host APIs depending on what the program uses. Iām not yet at the point of wanting to make it completely universal, especially given how Iām only one person and with v2.0 coming up soon itād ā in my humblest of opinions ā be a waste of time. I am honestly grateful for people reviewing my code and otherwise viewing it catching onto details I have overlooked. My goal is to not make a ājust-barely working on my machineā project; I enjoy sharing development with others, and it hurts knowing people canāt appreciate code, whether it be mine or othersā, due to something as simple as hard-coded sh flags."}, {"post_id": 13822, "ts": "2026-06-22T17:23:16Z", "hours": 3.7814, "text": "Devlog: Making Flowerās Type Aliases Transparent This version was simple to develop on paper (and even in practice it wasnāt too bad, only around 4 or so hours!): type Count = int type Total = Count type Name = string and then have those aliases behave like the real type everywhere: n: Count = 12 total: Total = identity(n) name: Name = \"Ivy\" if name != \"Ivy\": return false end if name.length != 3: return false end That meant aliases could not just be parsed and stored, but rather had to be transparent to the compilerās semantic checks. What changed I added type alias declarations to the AST, parser, and type environment, then added the ability to resolve aliases in typechecking before comparing types. That included: return type checks variable initializers function call arguments binary comparisons string-specific comparison logic struct field access The important rule here is that aliases are semantic, not codegen-facing. Count should behave as int , Name should behave as string , and chained aliases like Total -> Count -> int should collapse correctly. In the future, especially post v2.0 , this could change and custom types might become real ā but for now, theyāre just aliases. The bug that exploded bootstrap The first real failure was not in aliases themselves, but in function argument checking. Inside check_call_args(...) , the compiler was resolving the argument expression into expected_type instead of arg_type . That overwrote the parameter type, left the actual argument type uninitialized, and caused the second bootstrap stage to explode into over a thousand misleading errors. This was not a pre-existing issue, it was instead from human error (my error) during the initial implementation where I accidentally put the wrong variable. Once that was fixed, the remaining failures were much more helpful than the bright flash of red and āTypecheck failed with 1224 error(s)ā message! Where this leaves v1.4 With the first step toward ābetter typesā done, aliases are no longer just syntax. That gives v1.4 a solid base for whatever comes next in the type system without having to fake around raw names. During this whole dev session, I did discover that a whole lot more of the source code was left using legacy work-arounds: int instead of bool , name_start; name_length and @char instead of string . In all fairness, some of these arenāt exactly the easiest to refactor. However, I will probably hold off on refactoring the codebase until either right before v2.0 , or right after. Just know itās on my radar ;)"}, {"post_id": 11351, "ts": "2026-06-18T15:46:42Z", "hours": 1.4231, "text": "Devlog: Cleaning Up v1.3 For Release After many hours of work, bool and `string finally became real, and it was time to cleanup the mess I left behind from the versionās development. Mainly the only thing worked on was some cleanup: roadmap now reflects actual v1.3 features and implementations updated README and contribution documents to match the current compiler pipeline cleaned up string examples so they have the full intended v1.3 style instead of some leftover testing usage pushed the compilerās version to 1.3.0 updated help / usage text so it matches the new output-path and auto-run behavior Prior to this, if I had just merged and shipped, the release wouldvāe been messy: README, Contributing, example files, and guidance commands were all mixing older details which made it confusing ā even for me ā when trying to explore the language and what it has to offer. For a bootstrapped compiler especially, making sure everything is cleaned up and polished is something that should not be ignored. Iām definitely guilty of overlooking this, but Iāve outlayed a whole plan for v1.3 unlike past versions, and part of it was setting up a proper versioning system and polishing its release as it goes. This format will be adopted in future versions, since itās just way cleaner and nicer to look at. Future work At this point, v1.3 is done and has implemented, at minimum, a concrete foundation for post-v2 bools and strings. Next will likely be more subtle improvements, and features that are currently reliant explicitly on C rather than Flower-hosted code. In order for v2.0 , Flower will have to be effectively independent from C if it wants to emit machine code. Currently I am planning on adding features such as Type Aliases and maybe a stdlib prior to that, but anything can change!! Thanks for being here for all of v1.3 <3"}, {"post_id": 11116, "ts": "2026-06-18T05:51:28Z", "hours": 1.7269, "text": "Devlog: Giving Flower an Internal cstr Foundation Even after Flower got a real string type, the compiler itself was still leaning directly on C-style string helpers for its own internal work. That meant a lot of Flower source was still semantically depending on libc behavior: !strncmp(...) strcmp(...) strlen(...) strcpy(...) strncpy(...) strdup(...) strrchr(...) That is not where I want the language to stay. What changed I added a new internal module: import \"src/stdlib/cstr.flo\" as cstr and gave it compiler-facing helpers like: prop func len(s: @char): int prop func eq(a: @char, b: @char): bool prop func eq_n(a: @char, b: @char, n: int): bool prop func copy(dst: @char, src: @char): @char prop func copy_n(dst: @char, src: @char, n: int): @char prop func dup(src: @char): @char prop func find_last(src: @char, ch: char): @char This helper module is essentially the precursor to a future strings.flo library that can be distributed. But for now, it uses a basic API layer purely meant for in-house usage. Then I migrated compiler internals over to that module across: src/parser.flo src/module.flo src/lexer.flo src/typecheck.flo src/codegen.flo src/globals.flo src/main.flo So instead of using C-string behavior directly everywhere, the compiler now goes through Flower-owned helpers first. The Compiler Strikes Back This was one of those changes that sounds mechanical until it absolutely is not. A big trap was that old code often relied on C comparison functions returning 0 on equality, so patterns looked like this: not strncmp(...) But cstr.eq_n(...) returns an actual bool , which means blindly rewriting those calls gives inverted logic. So this: if ps.alias_lengths[i] == tok.length and not cstr.eq_n(...): was completely wrong. It had to become: if ps.alias_lengths[i] == tok.length and cstr.eq_n(...): That bug showed up in alias parsing first, which made it especially cursed, because it caused normal namespace-style calls like cstr.eq(...) to stop parsing correctly and crash the bootstrap path in confusing ways. I spent way longer than I wish to admit on trying to figure out why it wasnāt playing nice. But, once I figured it out, it was a really quick fix (I literally just cmd + f ād not cstr and replaced it with cstr lol). Are we done yet..? This does not mean Flower is free from the C backend yet. It does mean something important, though: compiler logic is starting to depend on Flower-defined helper semantics instead of scattered raw libc calls. That is a much better stage for the future backend story, because when C eventually stops being the primary lowering target, the compiler will already have more of its own vocabulary. In other words, this was less about āremove Cā and more about āstop letting C define the languageās internal habits.ā Nah just kidding, I really wanted that bloated ābuiltin_c_callā stuff gone. Unfortunately I only managed to skim it, but thatās closer than before! Result After fixing the migration mistakes and the alias/parser fallout, the compiler bootstrapped successfully again. Flower now has an internal cstr layer, and compiler string handling is a little more its own."}, {"post_id": 11068, "ts": "2026-06-18T03:16:30Z", "hours": 1.2611, "text": "Devlog: Fixing Flowerās Output Driver and Starting the String Stdlib This checkpoint was really two different kinds of progress that ended up helping each other a lot. The first part was not glamorous, but it was necessary: Flowerās compile driver was tripping over its own default output naming. This was a known issue that I had been putting off, but for some reason it really annoyed me this time so I decided enough and to fix it. If no explicit output path was provided, the compiler would generate output.c , then strip the .c and try to emit a binary named output . That worked fine right up until the repo itself already had an output/ directory. At that point, linking failed because the compiler was trying to create a file where a directory already existed. Worse ā because it annoyed me more ā the driver logic was also mixing up āthe generated program exited non-zeroā with ācompilation failed.ā That became especially annoying during bootstrap, because the generated compiler binary would run without CLI arguments, print its own usage error, and then cause bootstrap to report failure even though codegen and C compilation had both succeeded. So I finally got off my butt and cleaned that up. Driver Cleanup The default output path now goes to: output/out.c which naturally produces: output/out as the binary. That avoids the old output filename collision. I also separated compile success from auto-run behavior: explicit output path: compile only default output path: compile, then auto-run if appropriate That means bootstrap no longer āfailsā just because the compiled compiler exits non-zero with missing arguments, and demo/test files can still run automatically when that is actually useful. This sounds like a small driver fix, but honestly it removed a lot of noise from string work ā and more ā immediately. String Stdlib Beginnings Once that output weirdness was under control, I could finish doing what I just started and actually wanted: making string behavior live in Flower instead of endlessly leaning on ad hoc C calls (Call back to last devlog, absolute ball knowledge!!). So I added the first real reusable helpers in src/stdlib/string.flo : is_empty(s) starts_with(s, prefix) ends_with(s, suffix) find_char(s, ch) These are intentionally simple. They mostly exist to prove that the current string support is now strong enough for normal library code to be written on top of it. Not incredibly useful, at least at the level the compiler needs, but at least I could translate some AP Comp Sci A into Flower hehe A string feature does not really feel ārealā until I can build helpers with the language itself instead of only teaching the compiler more special cases. The day I remove the builtin C handlers is the day Iām at peace⦠Validation To exercise that new library surface, I changed string_pass.flo to now act as a small pass file for the experimental library. Its job is not to be impressive. Its job is to answer a more important question: can I import string helpers, call them from normal Flower code, and get expected results through the full compile pipeline? At this point, yes. Where this leaves things This checkpoint did not remove all C string dependencies from the compiler. In fact, it removed essentially none! That is still a separate step, one that may even be in v1.3.7 ;) But it did establish two important things: Flowerās output/driver behavior is now much less annoying. We can start growing a real string library in Flower itself. That is a good place to be, because the next string work can build outward from a stable driver and an actual library surface instead of piling more special behavior into the compiler."}, {"post_id": 11013, "ts": "2026-06-18T01:18:51Z", "hours": 1.0825, "text": "Devlog: Adding String Indexing to Flower This one was fairly quick, and was about making one very normal-looking thing actually work: name: string = \"Ivy\" as string first: char = name[0] That sounds small, but once string became a real Flower type, indexing could no longer piggyback on the old āarrays and pointers onlyā behavior. The compiler needed to understand that string[index] is its own case. What changed I taught the typechecker to treat string subscripts as char . That means: string[index] now resolves to char the index expression must be an integer string indexing is readonly for now So this is valid: first: char = name[0] but this is not: name[0] = 'X' I wanted reads first, writes later. That keeps the rules simple while the string representation is still compiler-owned. Iām not sure how writes would work with a C backend, due to how āstringsā are allocated. Perhaps a feature for post-v2.0? Lowering it to C Since Flower strings currently lower to a struct with .data and .length , codegen needed a special path for string subscripts. Normal arrays and pointers still lower like: arr [ index ] but strings now lower like: name . data [ index ] That keeps the generated C valid without changing how regular subscripts work elsewhere in the language. So something conceptually like: This checkpoint also forced one strict-but-correct rule that required me to update a WHOLE SINGLE LINE (hehe): arg[i] = tolower(arg[i] as char) to arg[i] = tolower(arg[i] as char) as char Because tolower(...) is effectively treated as returning int , assigning it back into a char subscript needs an explicit cast. I kept that strictness on purpose. I do not want Flower silently narrowing values just because C would let it. Validation I expanded the string example coverage to check: string indexing returns the expected chars string[index] works alongside string <-> @char casts bootstrap still succeeds repeated bootstrap succeeds tests still pass Which, after all the recent bootstrap chaos, was very nice to see. Where this leaves v1.3 Now we can: store strings compare strings print strings inspect length index into them as char This should make it much easier to replace the builtin C functions with a Flower library in the near-near future."}, {"post_id": 10953, "ts": "2026-06-17T23:26:21Z", "hours": 3.3353, "text": "Devlog: Finishing Flowerās String Interop Bridge The last round got string into Flower as a real type. This round was about making that foundation actually work lol. The big problem was that once string became real, plain string literals started living in an in-between state: Flower wanted them to mean āFlower string,ā but the compilerās own source still has plenty of places that really mean āraw C string,ā like: RED: @char = \"\\033[0;31m\" if not strcmp(arg, \"help\") or not strcmp(arg, \"h\"): ... end Those cases worked before only because everything was basically pretending string literals were already @char . Once that stopped being true, bootstrap started throwing a fit (my spoiled child). What changed The main fix was to make string literal lowering contextual instead of all-or-nothing. If a literal is being used as a real Flower string , it stays a string . If a literal is being used in a C interop position, it gets lowered as a C string instead. That meant tightening a few compiler rules so this kind of thing works cleanly again: name: string = \"Ivy\" as string raw: @char = name as @char if strcmp(raw, \"Ivy\") == 0: print(name) end I also fixed top-level declarations so globals like: RED: @char = \"\\033[0;31m\" no longer generate nonsense like: char * RED = (( flower_string ){ ... }); which, unsurprisingly, C does not appreciate. The subtle compiler bug The nastiest issue wasnāt even the globals. It was that builtin C calls like strcmp , strncmp , printf , snprintf , and friends are not real Flower functions. That meant the typechecker could hit one of them inside a larger expression, fail early, and stop walking the rest of the tree. So something like: if not strcmp(arg, \"help\") or not strcmp(arg, \"h\"): could partially resolve one side, then leave the other side unprocessed. Very cool. Very stable. Definitely what I wanted. The fix was to add a temporary builtin C-call bridge so the compiler can recognize these calls well enough to keep type resolution and literal lowering consistent during bootstrap. Iām not happy with this fix by any means, but due to the limitations of emitting C, it was the only solution I found that made sense at the time. Tests and examples Once that stopped exploding, I finally wired string testing into the normal types suite instead of leaving it commented out and pretending Iād āget back to it later.ā The string tests now cover: string <-> @char casts string equality / inequality .length empty strings printing strings literal use in current interop cases And the full test suite passed with string included as a first-class part of Types on its first try . Now thatās what I like to see :D What this means This does not mean Flowerās long-term answer is āhardcode libc into the compiler forever.ā It means Flower now has a temporary interop bridge that keeps self-hosting stable while string is worked on. The actual language semantics stay in Flower; the backend-specific weirdness is just being tolerated for now so progress does not stall. In the near, Iāll probably replace all of the necessary C libs with minimal Flower-equivalents. Where this leaves v1.3 At this point, the string foundation feels much sturdier. Not ādone forever,ā not backend-agnostic, and definitely not free of cursed bootstrap energy ā but it works. The next work is no longer rescue work. It is actual forward work: string operations, stdlib basics, and eventually replacing this temporary C bridge with something cleaner when Flower grows past the C backend."}, {"post_id": 9012, "ts": "2026-06-15T01:03:21Z", "hours": 2.7858, "text": "Devlog: Building Flowerās String Type Foundation The core goal was to make this work in a meaningful, compiler-owned way: name: string = \"Ivy\" as string raw: @char = name as @char other: string = raw as string if name == other: print(\"same\\n\") end print(name.length) That meant Flower needed more than a typedef in generated C. It needed actual type rules, actual lowering rules, and I needed enough hairs on my head to not be bald after the amount of scares that occurred. What changed The first step was giving string real compiler support without going too far too fast. I added support for: explicit casts between string and @char string equality / inequality string.length runtime helpers in generated C for: flower_string_from_cstr(...) flower_string_eq(...) flower_print_string(...) That gave Flower a usable string foundation while still keeping literals conservative for self-hosting. Right now, string literals are not fully ānative string values everywhereā yet; the compiler still uses explicit casts like \"Ivy\" as string as the safe bridge. The reason for this āsafe bridgeā is because when I got too ambitious, the compiler would break since everywhere @char was used with a string literal itād break due to no implicity being allowed. I had to comment out the following new changes and keep the legacy support so itād compile: else if ast.kind == AST_STRING_LIT: // fprintf(out, \"flowe_string_from_cst(\") // fprintf(out, \"%.*s\", ast.data._string.str_length, src + ast.data._string.str_start) // fprintf(out, \")\") // LEGACY CODE HERE and else if expr.kind == AST_STRING_LIT: // set_plain_type(out, TOKEN_STRING) // LEGACY CODE HERE return 1 The part that broke The most annoying issue was not string equality or .length . It was print . Originally, non-string print(...) was basically lowered like this: printf ( expr ); That only works when expr is already a C format string. So something like: print(name.length) generated invalid C: printf ( name . length ); The fix was to make print(...) type-aware. Typecheck now records the operand type, and codegen lowers print differently for string , @char , char , floats/doubles, and integer-like values. That sounds small, but it matters a lot: once string became real, print could no longer get away with pretending every printable value was already a C string. An Unsolved Bootstrap Mystery Somehow Flowerās bootstrap process was breaking, and it will probably break again. Despite the bootstrap requiring it to compile itself, somehow afterwords the binary could become corrupted. l-2: ~/Documents/GitHub/FloC % make bootstrap === Building new version === Compiled ./bin/Flower_new.c ā ./bin/Flower_new === Testing new compiler === Compiled ./bin/Flower_test.c ā ./bin/Flower_test Verified bootstrap build complete l-2: ~/Documents/GitHub/FloC % make bootstrap === Building new version === Luckily, I always make sure to keep a backup Flower bin stored under /bin/Flower_backup so I used that to compile the new binary and then it worked. Where this leaves v1.3 What still remains is the bigger ergonomic question: how fully native string literals should behave, and how to migrate the compilerās own source to that world without setting bootstrap on fire again. Iām not sure yet how I want to approach this question, or what the goals for it should even be, but I guess Iāll have to find out soon enough! That is the next fight. But at least now, it is a fight on solid ground."}, {"post_id": 8529, "ts": "2026-06-14T05:55:45Z", "hours": 3.8414, "text": "Devlog: Making Bool Real Without Breaking Bootstrap The original goal, asper usual, was straightforward: before moving on to string , Flower needed bool to actually mean something semantically. Up to this point, boolean-ish behavior mostly worked by accident. Comparisons, conditions, returns, and general expression checking were still loose enough that the compiler could get away with treating a lot of things as āclose enough,ā especially since the C backend ultimately lowers bool to int anyway. That was not going to hold once v1.3 started leaning on richer typing. So this was about drawing a clean line between Flower semantics and C lowering. The Goal In Flower: bool should be its own real type comparisons and logical operators should produce bool arithmetic should not quietly accept bool implicit conversion should stay narrow and predictable explicit casting should remain available through as In C: bool can still lower to int That distinction ended up being the easy part. What Changed The typechecker now treats bool as a proper language type instead of an int-shaped placeholder. Condition checks were tightened so if , while , and not use condition-compatible rules. Arithmetic paths now reject boolean operands, and return / initializer / argument checking now runs through more explicit conversion rules. I also kept implicit widening one-directional: int -> float -> double while leaving narrowing conversions as explicit casts. The actual implementation of booleans and their typing, enforcement, and semantics was a breeze. Itās what came after that got me. What Actually Broke As usual, bootstrap had opinions. The stricter type work exposed older weaknesses that were easy to miss before (This is my coping): function argument checks needed array-to-pointer decay alias and module call lookup paths were too narrow unresolved calls could prevent nested expressions from being fully type-resolved that, in turn, broke some dot-access lowering and caused bad . vs -> emission in generated C So part of this checkpoint turned into compiler stabilization work rather than just bool semantics due to my crappy ātemporaryā logic, error handling ā or lack thereof, and impeccable ability to miss very important details. Iām an amazing programmer, if you couldnāt tell :p Result Flower now has a much firmer semantic base for bool, and the compiler is back to bootstrapping cleanly with those rules in place. That matters because this was really the floor for the next part of v1.3: string . And.. maybe Iāll fix the bootstrap process so it doesnāt blow up in my face again. Oh yea, forgot to mention that. The bootstrapper bootstrapped itself into this very broken parser state that refused to go away so I had to stash my changes, checkout the prior merge (detached), and then recompile manually and fix the parser. Toodles!"}, {"post_id": 6924, "ts": "2026-06-11T16:28:33Z", "hours": 1.3047, "text": "Devlog: Fixing the Typechecker After Bool Enforcement Getting bool into Flower exposed a reallyyyy annoying problem: the typechecker had a couple of tiny logic mistakes (Iām so good at this) which caused the bootstrap to blow up in my face and I ahd no idea why. At first the errors looked unrelated. The compiler started reporting huge numbers of mismatches across main.flo , lexer.flo , module.flo , typecheck.flo , and codegen.flo . I was so confused as to why out of nowhere 903 lines were reporting various typechecking errors when they shouldnāt be. As it turns out, types_match() was the culprit. The function had been inverted in a few places: Mismatched base types and pointer depths were returning success, while normal matching primitive types were falling through to failure. That made the new compiler think ordinary initializers, assignments, comparisons, and returns were all invalid. Once that was fixed, the remaining failures turned out to be a second real compiler bug: pointer arithmetic over arrays was decaying in the wrong direction. Expressions like: mods.modules + j env.structs + env.struct_count arr + 1 should produce pointer types. Instead, the typechecker was reducing pointer depth when arrays decayed, which made perfectly normal indexed access and table walking look type-invalid. So this dev session ended up doing three important things: fixed types_match(...) so actual matches succeed and actual mismatches fail preserved decimal compatibility for float / double matching fixed array-to-pointer decay in pointer arithmetic so compiler internals and examples resolve correctly again What made this especially annoying is that the symptoms looked much larger than the cause. A couple of bad returns in the typechecker created hundreds of downstream errors, and because Flower is self-hosting, that meant the compiler started rejecting its own source. After correcting those core issues, both bootstrap and the example test suite started working again. That is the real value of issues like this: not just āfewer errors,ā but restoring (MY) trust in the compiler and its ability to enforce Flowerās rules and report issues. With that stable again, the path forward is much clearer: continue bool work from a solid base, then move on to the remaining numeric and string improvements without the whole compiler collapsing under one bad predicate."}, {"post_id": 6207, "ts": "2026-06-10T12:52:51Z", "hours": 4.0928, "text": "Devlog: Making Flowerās Bool Support Real Enough to Survive Bootstrap The goal sounded small at first: add proper boolean support, while still lowering booleans to integers in C. In practice, this turned into an overarching type-system problem (typical!). Flower had reached a point where bool could not just be a naming trick over 1 and 0 . The compiler itself needed to understand when an expression was semantically boolean, when it was integer, and when older bootstrap-era shortcuts were no longer valid. A lot of those shortcuts had survived because the backend lowers bool to int anyway. But self-hosting exposed a major issue: source-level typing and C lowering are not the same thing. Things like these started breaking: val: int = parser_peek(ps).kind == TOKEN_TRUE and helper predicates that returned comparison expressions from int -typed functions. So the checkpoint became: keep C lowering simple, but make Flowerās typechecker treat booleans as a real source-level type. The main changes were: parser -> typecheck -> codegen true / false now parse into AST_BOOL_LIT bool literals are still emitted as 0 / 1 in C logical and comparison expressions now resolve to bool arithmetic rejects bool operands if , while , and not now validate condition-compatible expressions variable initializers, assignments, and returns now check types more strictly One of the more annoying bugs turned out not to be āabout boolsā at all. When code like this failed inside the compiler: defined_structs[i].length emitted_imports[i].path the real problem was that for i in 0..count was never registering i in the type environment, so indexed access looked broken when really the loop variable itself had no known type. Once loop indices were typed as int , those field-access failures disappeared (yay!!). The result is a much better place to build from: bool is now semantically distinct in Flower it still lowers cleanly to integer values in generated C bootstrap works again the compiler is stricter without collapsing under its own source That makes the next step much easier: real string support, instead of trying to build strings on top of a type system that still half-thinks everything is an int ."}, {"post_id": 5369, "ts": "2026-06-09T03:37:15Z", "hours": 5.4503, "text": "Devlog: Giving Flower Real Module Support v1.2.x was the point where Flowerās impors had to stop being āyou can import stuff.. and thereās a fake layer of securityā to a prop er (get it?) module system. Before this work, imports and aliases mostly behaved like naming conveniences. You could write: import \"math.flo\" as math math.add(1, 2) but the compiler was still too loose about what that really meant . Alias names were in emitted C symbol names, top-level declarations were not private, and prop existed more as syntax than as a real feature. That was fine for early bootstrap work, but it was not strong enough for the next stage of the language. So the main goal of v1.2.x became: make imported aliases act like real namespaces make prop define the public interface of a module make top-level declarations private by default lay groundwork for field visibility rules like hidden and readonly Module Semantics Instead of Alias Tricks One of the biggest changes was separating Flower semantics from C lowering. Previously, imported aliases were drifting toward becoming part of emitted symbol identity. A local alias should just be a source-level name bound to a module, not the backend symbol. So now each module has its own lowered symbol prefix, and alias lookup happens semantically during compilation. That means: import \"math.flo\" as math math.add(1, 2) is resolved as ālook up exported add in module math.flo ,ā not āinvent a C symbol from the local alias text as math_add() .ā That change also forced a cleanup of emitted names so they stopped leaking absolute filesystem paths. Generated symbols now use project-relative module prefixes instead of machine-specific paths. prop Became Real Another major part of this was making prop actually do something. Instead of treating it as a thin wrapper around only functions, the compiler now recognizes prop as a real top-level export marker. That means the moduleās public interface is defined by what it explicitly exports, while non- prop declarations remain internal. This moved Flower closer to the model I wanted all along: explicit modules, explicit public APIs, no heavy object system (OOP), no fake privacy delegated to the C backend. Dot Access, Pointers, and the Annoying Middle Part This work also exposed a weakness in the compilerās dot-access resolution. Flower source always uses . , while the C backend must decide whether a given access becomes . or -> . That mostly worked already, but nested pointer-heavy field chains exposed cases where the type tracker was not propagating enough information, which caused bad fallback behavior during self-hosting. So before field visibility could be trusted, I had to harden nested dot-access resolution. Not fun, but necessary. As it turns out, I was missing several AST kinds which caused the logic to fall through. Very tedious work, but it was well-worth it in the end! Field Flags Groundwork With module ownership and access resolution in better shape, I added the first field visibility modifiers: hidden readonly frozen Originally I debated having these as bitwise operations, but I decided itād be best to stay within the current updateās scope, so sometime in the future Iāll refactor. Right now, hidden and readonly are the meaningful additions: hidden blocks external field access readonly blocks external assignment frozen is groundwork for later. It is parsed, stored, and carried through the compiler, but full assignment-once enforcement is still deferred. Unsure how Iāll go about it, but thatās an issue for future me :p"}, {"post_id": 4525, "ts": "2026-06-07T21:22:43Z", "hours": 3.6428, "text": "Devlog: Replacing Flowerās Old Function Syntax with func name(...): type This feature started out as what I thought would be a straightforward syntax cleanup. Flowerās old function syntax looked like this: int add(a: int, b: int): return a + b end and exported functions looked like this: prop int test(): return 1 end It worked, technically, but it had started to annoy me more. The biggest issue was that function declarations did not visually match the direction Flower was already heading in, and instead felt much more C-like than I wanted. prop func create(...): Person func main(): int This style says āthis is a functionā up front, gives a clean place for modifiers like prop , and keeps the return type attached to the signature rather than awkwardly leading it. The goal was simple: func name(...): type instead of: type name(...): Simple in theory. not so much when the compiler is written in the language being refactored. The Problem Flowerās parser assumes top-level function definitions start with a type. Old parser logic was built around that: int main(): means: parse a type, an identifier, params, and a body That assumption was scattered through a few different places: normal function definitions prop function declarations forward declarations examples and docs the compilerās own source Now, in retrospect, this was actually one of the easier changes. It didnāt take a whole lot of planning nor brain power, and I was able to change it pretty quickly. Luckily for me, Iāve built codegen to rely purely on ast values rather than shaping. The New Shape The new syntax is: func add(a: int, b: int): int return a + b end and exported functions now look like: prop func test(): int return 1 end This is nicer because: func makes declarations immediately recognizable prop composes more cleanly with func return types now live where people expect them to future syntax has more room to grow without feeling backwards It also feels more in line with Flowerās broader goals: explicit, readable, and not complex. The Refactor Previously, parse_func_def looked for a return type first: type name(...): Now it expects: func name(...): type So the order changed to: expect func parse function name parse parameter list expect : parse return type parse body until end That part was conceptually easy. The more annoying part was updating all the places that assumed if it isnāt a var decl and it looks like a func, itās a func. That fallback had to go (Good riddance!). Instead, top-level parsing needed to become more explicit: prop func ā exported function func ā normal function forward func ā forward declaration The old one worked, but it relied on vague āanything else is probably a functionā rules. The Bootstrap Mistake At one point, I made a bootstrap build so I could use a Flower_new binary to compile the refactored compiler. Unfortunately, I had made a mistake in parse_forward : advancing before peek checks. Feel free to check out the bootstrapper to see why this was an issue ;) This meant my ānew compiler to compile the new compilerā was built from a broken parser. The workaround was cursed, but it worked : check out the commit before the refactor fix the bug compile a new binary switch to the refactor branch use the binary to compile the new version Since the compiled binary was ignored by Git, this was actually fairly simple. Not the most elegant bootstrap story, but it got the compiler to, well, compile."}, {"post_id": 3962, "ts": "2026-06-07T03:08:31Z", "hours": 8.2967, "text": "Devlog: Making Flowerās Type Tracking āEnoughā for Stdlib / String Work The original motivation was simple and ā supposedly ā quick; I wanted to move on to v1.1.1 , āstdlib basics,ā especially string utilities. But Flowerās current compiler did not really know what types expressions had. It mostly had pointer_depth on declarations, which was enough to generate * in C types and sometimes guess whether field access should become . or -> . That worked for very simple cases: p: @Vector2 = new Vector2 p.x = 5 But it broke down for nested access: outer.inner.value outer.inner_ptr.value The compiler could see the syntax chain, but it did not know whether inner was a value field or pointer field. Since Flower source only uses . , the C backend needs to decide whether each hop becomes . or -> . That meant stdlib work was blocked. If I want something like: if strings.equal(string_a, string_b): print(\"same\\n\") end then Flower needs to understand that string_a.length , string_a.data , etc. are real typed fields, not just random syntax to dump into C. Originally I thought I could just simply create a Symbol Table to get that to work. Unfortunately, that plan soon failed as it introduced a mariad of issues relating to the import system. At the time, this frustrated me because I knew the import system sucked, but I didnāt want to fix it until a later version. Eventually, I settled on a specific plan which did actually end up changing how imports are handled.. kinda. The Plan The design I landed on was to add a typecheck/type-tracking stage between parsing and codegen: lexer -> parser -> typecheck -> codegen The parser should stay mostly syntax-only. It builds AST nodes like ādot access,ā so I didnāt really change it. The typecheck pass now collects declarations into a TypeEnv : struct TypeEnv { structs: StructInfo[1024], struct_count: int, vars: VarInfo[8192], var_count: int, funcs: FuncInfo[8192], func_count: int, error_count: int } Then it walks expressions and annotates dot access nodes with an access kind: ACCESS_UNKNOWN: int = 0 ACCESS_DOT: int = 1 ACCESS_ARROW: int = 2 So codegen no longer has to fully guess. It can do: if ast.data._dot_access.access_kind == ACCESS_ARROW: fprintf(out, \"->%.*s\", ...) else if ast.data._dot_access.access_kind == ACCESS_DOT: fprintf(out, \".%.*s\", ...) else: // fallback end That fallback is important because Flower is self-hosted-ish right now. The compiler is written in Flower, and the compilerās own source code is full of field access. If the new typechecker is too strict too early, it breaks the compiler while trying to compile the compiler. Very elegant. Very cursed. Just how I like it ;) Import-Aware Type Tracking At first, typechecking only saw the main file, so I added a module loading pass. Instead of codegen discovering and parsing imports late, the compiler now loads modules earlier: load main module load imports recursively collect declarations from all modules typecheck all modules codegen all modules That required a new module structure: struct Module { path: @char, src: @char, tokens: @TokenStream, ast: @AST } struct ModuleSet { modules: Module[128], count: int } Unfortunately, it didnāt go as smoothly as I wanted. Near the end when I was sure everything would work, I ran into an Idempotency failure due to the new handling of system imports. I.. just manually passed it :p"}]...
|
Title: Flower by @IvyMycelia | Stardance
Devlogs: Title: Flower by @IvyMycelia | Stardance
Devlogs:
Devlog: Making Flowerās Type Tracking āEnoughā for Stdlib / String Work The original motivation was simple and ā supposedly ā quick; I wanted to move on to v1.1.1 , āstdlib basics,ā especially string utilities. But Flowerās current compiler did not really know what types expressions had. It mostly had pointer_depth on declarations, which was enough to generate * in C types and sometimes guess whether field access should become . or -> . That worked for very simple cases: p: @Vector2 = new Vector2 p.x = 5 But it broke down for nested access: outer.inner.value outer.inner_ptr.value The compiler could see the syntax chain, but it did not know whether inner was a value field or pointer field. Since Flower source only uses . , the C backend needs to decide whether each hop becomes . or -> . That meant stdlib work was blocked. If I want something like: if strings.equal(string_a, string_b): print("same\n") end then Flower needs to understand that string_a.length , string_a.data , etc. are real typed fields, not just random syntax to dump into C. Originally I thought I could just simply create a Symbol Table to get that to work. Unfortunately, that plan soon failed as it introduced a mariad of issues relating to the import system. At the time, this frustrated me because I knew the import system sucked, but I didnāt want to fix it until a later version. Eventually, I settled on a specific plan which did actually end up changing how imports are handled.. kinda. The Plan The design I landed on was to add a typecheck/type-tracking stage between parsing and codegen: lexer -> parser -> typecheck -> codegen The parser should stay mostly syntax-only. It builds AST nodes like ādot access,ā so I didnāt really change it. The typecheck pass now collects declarations into a TypeEnv : struct TypeEnv { structs: StructInfo[1024], struct_count: int, vars: VarInfo[8192], var_count: int, funcs: FuncInfo[8192], func_count: int, error_count: int } Then it walks expressions and annotates dot access nodes with an access kind: ACCESS_UNKNOWN: int = 0 ACCESS_DOT: int = 1 ACCESS_ARROW: int = 2 So codegen no longer has to fully guess. It can do: if ast.data._dot_access.access_kind == ACCESS_ARROW: fprintf(out, "->%.*s", ...) else if ast.data._dot_access.access_kind == ACCESS_DOT: fprintf(out, ".%.*s", ...) else: // fallback end That fallback is important because Flower is self-hosted-ish right now. The compiler is written in Flower, and the compilerās own source code is full of field access. If the new typechecker is too strict too early, it breaks the compiler while trying to compile the compiler. Very elegant. Very cursed. Just how I like it ;) Import-Aware Type Tracking At first, typechecking only saw the main file, so I added a module loading pass. Instead of codegen discovering and parsing imports late, the compiler now loads modules earlier: load main module load imports recursively collect declarations from all modules typecheck all modules codegen all modules That required a new module structure: struct Module { path: @char, src: @char, tokens: @TokenStream, ast: @AST } struct ModuleSet { modules: Module[128], count: int } Unfortunately, it didnāt go as smoothly as I wanted. Near the end when I was sure everything would work, I ran into an Idempotency failure due to the new handling of system imports. I.. just manually passed it :p
Devlog: Replacing Flowerās Old Function Syntax with func name(...): type This feature started out as what I thought would be a straightforward syntax cleanup. Flowerās old function syntax looked like this: int add(a: int, b: int): return a + b end and exported functions looked like this: prop int test(): return 1 end It worked, technically, but it had started to annoy me more. The biggest issue was that function declarations did not visually match the direction Flower was already heading in, and instead felt much more C-like than I wanted. prop func create(...): Person func main(): int This style says āthis is a functionā up front, gives a clean place for modifiers like prop , and keeps the return type attached to the signature rather than awkwardly leading it. The goal was simple: func name(...): type instead of: type name(...): Simple in theory. not so much when the compiler is written in the language being refactored. The Problem Flowerās parser assumes top-level function definitions start with a type. Old parser logic was built around that: int main(): means: parse a type, an identifier, params, and a body That assumption was scattered through a few different places: normal function definitions prop function declarations forward declarations examples and docs the compilerās own source Now, in retrospect, this was actually one of the easier changes. It didnāt take a whole lot of planning nor brain power, and I was able to change it pretty quickly. Luckily for me, Iāve built codegen to rely purely on ast values rather than shaping. The New Shape The new syntax is: func add(a: int, b: int): int return a + b end and exported functions now look like: prop func test(): int return 1 end This is nicer because: func makes declarations immediately recognizable prop composes more cleanly with func return types now live where people expect them to future syntax has more room to grow without feeling backwards It also feels more in line with Flowerās broader goals: explicit, readable, and not complex. The Refactor Previously, parse_func_def looked for a return type first: type name(...): Now it expects: func name(...): type So the order changed to: expect func parse function name parse parameter list expect : parse return type parse body until end That part was conceptually easy. The more annoying part was updating all the places that assumed if it isnāt a var decl and it looks like a func, itās a func. That fallback had to go (Good riddance!). Instead, top-level parsing needed to become more explicit: prop func ā exported function func ā normal function forward func ā forward declaration The old one worked, but it relied on vague āanything else is probably a functionā rules. The Bootstrap Mistake At one point, I made a bootstrap build so I could use a Flower_new binary to compile the refactored compiler. Unfortunately, I had made a mistake in parse_forward : advancing before peek checks. Feel free to check out the bootstrapper to see why this was an issue ;) This meant my ānew compiler to compile the new compilerā was built from a broken parser. The workaround was cursed, but it worked : check out the commit before the refactor fix the bug compile a new binary switch to the refactor branch use the binary to compile the new version Since the compiled binary was ignored by Git, this was actually fairly simple. Not the most elegant bootstrap story, but it got the compiler to, well, compile.
Devlog: Giving Flower Real Module Support v1.2.x was the point where Flowerās impors had to stop being āyou can import stuff.. and thereās a fake layer of securityā to a prop er (get it?) module system. Before this work, imports and aliases mostly behaved like naming conveniences. You could write: import "math.flo" as math math.add(1, 2) but the compiler was still too loose about what that really meant . Alias names were in emitted C symbol names, top-level declarations were not private, and prop existed more as syntax than as a real feature. That was fine for early bootstrap work, but it was not strong enough for the next stage of the language. So the main goal of v1.2.x became: make imported aliases act like real namespaces make prop define the public interface of a module make top-level declarations private by default lay groundwork for field visibility rules like hidden and readonly Module Semantics Instead of Alias Tricks One of the biggest changes was separating Flower semantics from C lowering. Previously, imported aliases were drifting toward becoming part of emitted symbol identity. A local alias should just be a source-level name bound to a module, not the backend symbol. So now each module has its own lowered symbol prefix, and alias lookup happens semantically during compilation. That means: import "math.flo" as math math.add(1, 2) is resolved as ālook up exported add in module math.flo ,ā not āinvent a C symbol from the local alias text as math_add() .ā That change also forced a cleanup of emitted names so they stopped leaking absolute filesystem paths. Generated symbols now use project-relative module prefixes instead of machine-specific paths. prop Became Real Another major part of this was making prop actually do something. Instead of treating it as a thin wrapper around only functions, the compiler now recognizes prop as a real top-level export marker. That means the moduleās public interface is defined by what it explicitly exports, while non- prop declarations remain internal. This moved Flower closer to the model I wanted all along: explicit modules, explicit public APIs, no heavy object system (OOP), no fake privacy delegated to the C backend. Dot Access, Pointers, and the Annoying Middle Part This work also exposed a weakness in the compilerās dot-access resolution. Flower source always uses . , while the C backend must decide whether a given access becomes . or -> . That mostly worked already, but nested pointer-heavy field chains exposed cases where the type tracker was not propagating enough information, which caused bad fallback behavior during self-hosting. So before field visibility could be trusted, I had to harden nested dot-access resolution. Not fun, but necessary. As it turns out, I was missing several AST kinds which caused the logic to fall through. Very tedious work, but it was well-worth it in the end! Field Flags Groundwork With module ownership and access resolution in better shape, I added the first field visibility modifiers: hidden readonly frozen Originally I debated having these as bitwise operations, but I decided itād be best to stay within the current updateās scope, so sometime in the future Iāll refactor. Right now, hidden and readonly are the meaningful additions: hidden blocks external field access readonly blocks external assignment frozen is groundwork for later. It is parsed, stored, and carried through the compiler, but full assignment-once enforcement is still deferred. Unsure how Iāll go about it, but thatās an issue for future me :p
Devlog: Making Flowerās Bool Support Real Enough to Survive Bootstrap The goal sounded small at first: add proper boolean support, while still lowering booleans to integers in C. In practice, this turned into an overarching type-system problem (typical!). Flower had reached a point where bool could not just be a naming trick over 1 and 0 . The compiler itself needed to understand when an expression was semantically boolean, when it was integer, and when older bootstrap-era shortcuts were no longer valid. A lot of those shortcuts had survived because the backend lowers bool to int anyway. But self-hosting exposed a major issue: source-level typing and C lowering are not the same thing. Things like these started breaking: val: int = parser_peek(ps).kind == TOKEN_TRUE and helper predicates that returned comparison expressions from int -typed functions. So the checkpoint became: keep C lowering simple, but make Flowerās typechecker treat booleans as a real source-level type. The main changes were: parser -> typecheck -> codegen true / false now parse into AST_BOOL_LIT bool literals are still emitted as 0 / 1 in C logical and comparison expressions now resolve to bool arithmetic rejects bool operands if , while , and not now validate condition-compatible expressions variable initializers, assignments, and returns now check types more strictly One of the more annoying bugs turned out not to be āabout boolsā at all. When code like this failed inside the compiler: defined_structs[i].length emitted_imports[i].path the real problem was that for i in 0..count was never registering i in the type environment, so indexed access looked broken when really the loop variable itself had no known type. Once loop indices were typed as int , those field-access failures disappeared (yay!!). The result is a much better place to build from: bool is now semantically distinct in Flower it still lowers cleanly to integer values in generated C bootstrap works again the compiler is stricter without collapsing under its own source That makes the next step much easier: real string support, instead of trying to build strings on top of a type system that still half-thinks everything is an int .
Devlog: Fixing the Typechecker After Bool Enforcement Getting bool into Flower exposed a reallyyyy annoying problem: the typechecker had a couple of tiny logic mistakes (Iām so good at this) which caused the bootstrap to blow up in my face and I ahd no idea why. At first the errors looked unrelated. The compiler started reporting huge numbers of mismatches across main.flo , lexer.flo , module.flo , typecheck.flo , and codegen.flo . I was so confused as to why out of nowhere 903 lines were reporting various typechecking errors when they shouldnāt be. As it turns out, types_match() was the culprit. The function had been inverted in a few places: Mismatched base types and pointer depths were returning success, while normal matching primitive types were falling through to failure. That made the new compiler think ordinary initializers, assignments, comparisons, and returns were all invalid. Once that was fixed, the remaining failures turned out to be a second real compiler bug: pointer arithmetic over arrays was decaying in the wrong direction. Expressions like: mods.modules + j env.structs + env.struct_count arr + 1 should produce pointer types. Instead, the typechecker was reducing pointer depth when arrays decayed, which made perfectly normal indexed access and table walking look type-invalid. So this dev session ended up doing three important things: fixed types_match(...) so actual matches succeed and actual mismatches fail preserved decimal compatibility for float / double matching fixed array-to-pointer decay in pointer arithmetic so compiler internals and examples resolve correctly again What made this especially annoying is that the symptoms looked much larger than the cause. A couple of bad returns in the typechecker created hundreds of downstream errors, and because Flower is self-hosting, that meant the compiler started rejecting its own source. After correcting those core issues, both bootstrap and the example test suite started working again. That is the real value of issues like this: not just āfewer errors,ā but restoring (MY) trust in the compiler and its ability to enforce Flowerās rules and report issues. With that stable again, the path forward is much clearer: continue bool work from a solid base, then move on to the remaining numeric and string improvements without the whole compiler collapsing under one bad predicate.
Devlog: Making Bool Real Without Breaking Bootstrap The original goal, asper usual, was straightforward: before moving on to string , Flower needed bool to actually mean something semantically. Up to this point, boolean-ish behavior mostly worked by accident. Comparisons, conditions, returns, and general expression checking were still loose enough that the compiler could get away with treating a lot of things as āclose enough,ā especially since the C backend ultimately lowers bool to int anyway. That was not going to hold once v1.3 started leaning on richer typing. So this was about drawing a clean line between Flower semantics and C lowering. The Goal In Flower: bool should be its own real type comparisons and logical operators should produce bool arithmetic should not quietly accept bool implicit conversion should stay narrow and predictable explicit casting should remain available through as In C: bool can still lower to int That distinction ended up being the easy part. What Changed The typechecker now treats bool as a proper language type instead of an int-shaped placeholder. Condition checks were tightened so if , while , and not use condition-compatible rules. Arithmetic paths now reject boolean operands, and return / initializer / argument checking now runs through more explicit conversion rules. I also kept implicit widening one-directional: int -> float -> double while leaving narrowing conversions as explicit casts. The actual implementation of booleans and their typing, enforcement, and semantics was a breeze. Itās what came after that got me. What Actually Broke As usual, bootstrap had opinions. The stricter type work exposed older weaknesses that were easy to miss before (This is my coping): function argument checks needed array-to-pointer decay alias and module call lookup paths were too narrow unresolved calls could prevent nested expressions from being fully type-resolved that, in turn, broke some dot-access lowering and caused bad . vs -> emission in generated C So part of this checkpoint turned into compiler stabilization work rather than just bool semantics due to my crappy ātemporaryā logic, error handling ā or lack thereof, and impeccable ability to miss very important details. Iām an amazing programmer, if you couldnāt tell :p Result Flower now has a much firmer semantic base for bool, and the compiler is back to bootstrapping cleanly with those rules in place. That matters because this was really the floor for the next part of v1.3: string . And.. maybe Iāll fix the bootstrap process so it doesnāt blow up in my face again. Oh yea, forgot to mention that. The bootstrapper bootstrapped itself into this very broken parser state that refused to go away so I had to stash my changes, checkout the prior merge (detached), and then recompile manually and fix the parser. Toodles!
Devlog: Building Flowerās String Type Foundation The core goal was to make this work in a meaningful, compiler-owned way: name: string = "Ivy" as string raw: @char = name as @char other: string = raw as string if name == other: print("same\n") end print(name.length) That meant Flower needed more than a typedef in generated C. It needed actual type rules, actual lowering rules, and I needed enough hairs on my head to not be bald after the amount of scares that occurred. What changed The first step was giving string real compiler support without going too far too fast. I added support for: explicit casts between string and @char string equality / inequality string.length runtime helpers in generated C for: flower_string_from_cstr(...) flower_string_eq(...) flower_print_string(...) That gave Flower a usable string foundation while still keeping literals conservative for self-hosting. Right now, string literals are not fully ānative string values everywhereā yet; the compiler still uses explicit casts like "Ivy" as string as the safe bridge. The reason for this āsafe bridgeā is because when I got too ambitious, the compiler would break since everywhere @char was used with a string literal itād break due to no implicity being allowed. I had to comment out the following new changes and keep the legacy support so itād compile: else if ast.kind == AST_STRING_LIT: // fprintf(out, "flowe_string_from_cst(") // fprintf(out, "%.*s", ast.data._string.str_length, src + ast.data._string.str_start) // fprintf(out, ")") // LEGACY CODE HERE and else if expr.kind == AST_STRING_LIT: // set_plain_type(out, TOKEN_STRING) // LEGACY CODE HERE return 1 The part that broke The most annoying issue was not string equality or .length . It was print . Originally, non-string print(...) was basically lowered like this: printf ( expr ); That only works when expr is already a C format string. So something like: print(name.length) generated invalid C: printf ( name . length ); The fix was to make print(...) type-aware. Typecheck now records the operand type, and codegen lowers print differently for string , @char , char , floats/doubles, and integer-like values. That sounds small, but it matters a lot: once string became real, print could no longer get away with pretending every printable value was already a C string. An Unsolved Bootstrap Mystery Somehow Flowerās bootstrap process was breaking, and it will probably break again. Despite the bootstrap requiring it to compile itself, somehow afterwords the binary could become corrupted. l-2: ~/Documents/GitHub/FloC % make bootstrap === Building new version === Compiled ./bin/Flower_new.c ā ./bin/Flower_new === Testing new compiler === Compiled ./bin/Flower_test.c ā ./bin/Flower_test Verified bootstrap build complete l-2: ~/Documents/GitHub/FloC % make bootstrap === Building new version === Luckily, I always make sure to keep a backup Flower bin stored under /bin/Flower_backup so I used that to compile the new binary and then it worked. Where this leaves v1.3 What still remains is the bigger ergonomic question: how fully native string literals should behave, and how to migrate the compilerās own source to that world without setting bootstrap on fire again. Iām not sure yet how I want to approach this question, or what the goals for it should even be, but I guess Iāll have to find out soon enough! That is the next fight. But at least now, it is a fight on solid ground.
Devlog: Finishing Flowerās String Interop Bridge The last round got string into Flower as a real type. This round was about making that foundation actually work lol. The big problem was that once string became real, plain string literals started living in an in-between state: Flower wanted them to mean āFlower string,ā but the compilerās own source still has plenty of places that really mean āraw C string,ā like: RED: @char = "\033[0;31m" if not strcmp(arg, "help") or not strcmp(arg, "h"): ... end Those cases worked before only because everything was basically pretending string literals were already @char . Once that stopped being true, bootstrap started throwing a fit (my spoiled child). What changed The main fix was to make string literal lowering contextual instead of all-or-nothing. If a literal is being used as a real Flower string , it stays a string . If a literal is being used in a C interop position, it gets lowered as a C string instead. That meant tightening a few compiler rules so this kind of thing works cleanly again: name: string = "Ivy" as string raw: @char = name as @char if strcmp(raw, "Ivy") == 0: print(name) end I also fixed top-level declarations so globals like: RED: @char = "\033[0;31m" no longer generate nonsense like: char * RED = (( flower_string ){ ... }); which, unsurprisingly, C does not appreciate. The subtle compiler bug The nastiest issue wasnāt even the globals. It was that builtin C calls like strcmp , strncmp , printf , snprintf , and friends are not real Flower functions. That meant the typechecker could hit one of them inside a larger expression, fail early, and stop walking the rest of the tree. So something like: if not strcmp(arg, "help") or not strcmp(arg, "h"): could partially resolve one side, then leave the other side unprocessed. Very cool. Very stable. Definitely what I wanted. The fix was to add a temporary builtin C-call bridge so the compiler can recognize these calls well enough to keep type resolution and literal lowering consistent during bootstrap. Iām not happy with this fix by any means, but due to the limitations of emitting C, it was the only solution I found that made sense at the time. Tests and examples Once that stopped exploding, I finally wired string testing into the normal types suite instead of leaving it commented out and pretending Iād āget back to it later.ā The string tests now cover: string <-> @char casts string equality / inequality .length empty strings printing strings literal use in current interop cases And the full test suite passed with string included as a first-class part of Types on its first try . Now thatās what I like to see :D What this means This does not mean Flowerās long-term answer is āhardcode libc into the compiler forever.ā It means Flower now has a temporary interop bridge that keeps self-hosting stable while string is worked on. The actual language semantics stay in Flower; the backend-specific weirdness is just being tolerated for now so progress does not stall. In the near, Iāll probably replace all of the necessary C libs with minimal Flower-equivalents. Where this leaves v1.3 At this point, the string foundation feels much sturdier. Not ādone forever,ā not backend-agnostic, and definitely not free of cursed bootstrap energy ā but it works. The next work is no longer rescue work. It is actual forward work: string operations, stdlib basics, and eventually replacing this temporary C bridge with something cleaner when Flower grows past the C backend.
Devlog: Adding String Indexing to Flower This one was fairly quick, and was about making one very normal-looking thing actually work: name: string = "Ivy" as string first: char = name[0] That sounds small, but once string became a real Flower type, indexing could no longer piggyback on the old āarrays and pointers onlyā behavior. The compiler needed to understand that string[index] is its own case. What changed I taught the typechecker to treat string subscripts as char . That means: string[index] now resolves to char the index expression must be an integer string indexing is readonly for now So this is valid: first: char = name[0] but this is not: name[0] = 'X' I wanted reads first, writes later. That keeps the rules simple while the string representation is still compiler-owned. Iām not sure how writes would work with a C backend, due to how āstringsā are allocated. Perhaps a feature for post-v2.0? Lowering it to C Since Flower strings currently lower to a struct with .data and .length , codegen needed a special path for string subscripts. Normal arrays and pointers still lower like: arr [ index ] but strings now lower like: name . data [ index ] That keeps the generated C valid without changing how regular subscripts work elsewhere in the language. So something conceptually like: This checkpoint also forced one strict-but-correct rule that required me to update a WHOLE SINGLE LINE (hehe): arg[i] = tolower(arg[i] as char) to arg[i] = tolower(arg[i] as char) as char Because tolower(...) is effectively treated as returning int , assigning it back into a char subscript needs an explicit cast. I kept that strictness on purpose. I do not want Flower silently narrowing values just because C would let it. Validation I expanded the string example coverage to check: string indexing returns the expected chars string[index] works alongside string <-> @char casts bootstrap still succeeds repeated bootstrap succeeds tests still pass Which, after all the recent bootstrap chaos, was very nice to see. Where this leaves v1.3 Now we can: store strings compare strings print strings inspect length index into them as char This should make it much easier to replace the builtin C functions with a Flower library in the near-near future.
Devlog: Fixing Flowerās Output Driver and Starting the String Stdlib This checkpoint was really two different kinds of progress that ended up helping each other a lot. The first part was not glamorous, but it was necessary: Flowerās compile driver was tripping over its own default output naming. This was a known issue that I had been putting off, but for some reason it really annoyed me this time so I decided enough and to fix it. If no explicit output path was provided, the compiler would generate output.c , then strip the .c and try to emit a binary named output . That worked fine right up until the repo itself already had an output/ directory. At that point, linking failed because the compiler was trying to create a file where a directory already existed. Worse ā because it annoyed me more ā the driver logic was also mixing up āthe generated program exited non-zeroā with ācompilation failed.ā That became especially annoying during bootstrap, because the generated compiler binary would run without CLI arguments, print its own usage error, and then cause bootstrap to report failure even though codegen and C compilation had both succeeded. So I finally got off my butt and cleaned that up. Driver Cleanup The default output path now goes to: output/out.c which naturally produces: output/out as the binary. That avoids the old output filename collision. I also separated compile success from auto-run behavior: explicit output path: compile only default output path: compile, then auto-run if appropriate That means bootstrap no longer āfailsā just because the compiled compiler exits non-zero with missing arguments, and demo/test files can still run automatically when that is actually useful. This sounds like a small driver fix, but honestly it removed a lot of noise from string work ā and more ā immediately. String Stdlib Beginnings Once that output weirdness was under control, I could finish doing what I just started and actually wanted: making string behavior live in Flower instead of endlessly leaning on ad hoc C calls (Call back to last devlog, absolute ball knowledge!!). So I added the first real reusable helpers in src/stdlib/string.flo : is_empty(s) starts_with(s, prefix) ends_with(s, suffix) find_char(s, ch) These are intentionally simple. They mostly exist to prove that the current string support is now strong enough for normal library code to be written on top of it. Not incredibly useful, at least at the level the compiler needs, but at least I could translate some AP Comp Sci A into Flower hehe A string feature does not really feel ārealā until I can build helpers with the language itself instead of only teaching the compiler more special cases. The day I remove the builtin C handlers is the day Iām at peace⦠Validation To exercise that new library surface, I changed string_pass.flo to now act as a small pass file for the experimental library. Its job is not to be impressive. Its job is to answer a more important question: can I import string helpers, call them from normal Flower code, and get expected results through the full compile pipeline? At this point, yes. Where this leaves things This checkpoint did not remove all C string dependencies from the compiler. In fact, it removed essentially none! That is still a separate step, one that may even be in v1.3.7 ;) But it did establish two important things: Flowerās output/driver behavior is now much less annoying. We can start growing a real string library in Flower itself. That is a good place to be, because the next string work can build outward from a stable driver and an actual library surface instead of piling more special behavior into the compiler.
Devlog: Giving Flower an Internal cstr Foundation Even after Flower got a real string type, the compiler itself was still leaning directly on C-style string helpers for its own internal work. That meant a lot of Flower source was still semantically depending on libc behavior: !strncmp(...) strcmp(...) strlen(...) strcpy(...) strncpy(...) strdup(...) strrchr(...) That is not where I want the language to stay. What changed I added a new internal module: import "src/stdlib/cstr.flo" as cstr and gave it compiler-facing helpers like: prop func len(s: @char): int prop func eq(a: @char, b: @char): bool prop func eq_n(a: @char, b: @char, n: int): bool prop func copy(dst: @char, src: @char): @char prop func copy_n(dst: @char, src: @char, n: int): @char prop func dup(src: @char): @char prop func find_last(src: @char, ch: char): @char This helper module is essentially the precursor to a future strings.flo library that can be distributed. But for now, it uses a basic API layer purely meant for in-house usage. Then I migrated compiler internals over to that module across: src/parser.flo src/module.flo src/lexer.flo src/typecheck.flo src/codegen.flo src/globals.flo src/main.flo So instead of using C-string behavior directly everywhere, the compiler now goes through Flower-owned helpers first. The Compiler Strikes Back This was one of those changes that sounds mechanical until it absolutely is not. A big trap was that old code often relied on C comparison functions returning 0 on equality, so patterns looked like this: not strncmp(...) But cstr.eq_n(...) returns an actual bool , which means blindly rewriting those calls gives inverted logic. So this: if ps.alias_lengths[i] == tok.length and not cstr.eq_n(...): was completely wrong. It had to become: if ps.alias_lengths[i] == tok.length and cstr.eq_n(...): That bug showed up in alias parsing first, which made it especially cursed, because it caused normal namespace-style calls like cstr.eq(...) to stop parsing correctly and crash the bootstrap path in confusing ways. I spent way longer than I wish to admit on trying to figure out why it wasnāt playing nice. But, once I figured it out, it was a really quick fix (I literally just cmd + f ād not cstr and replaced it with cstr lol). Are we done yet..? This does not mean Flower is free from the C backend yet. It does mean something important, though: compiler logic is starting to depend on Flower-defined helper semantics instead of scattered raw libc calls. That is a much better stage for the future backend story, because when C eventually stops being the primary lowering target, the compiler will already have more of its own vocabulary. In other words, this was less about āremove Cā and more about āstop letting C define the languageās internal habits.ā Nah just kidding, I really wanted that bloated ābuiltin_c_callā stuff gone. Unfortunately I only managed to skim it, but thatās closer than before! Result After fixing the migration mistakes and the alias/parser fallout, the compiler bootstrapped successfully again. Flower now has an internal cstr layer, and compiler string handling is a little more its own.
Devlog: Cleaning Up v1.3 For Release After many hours of work, bool and `string finally became real, and it was time to cleanup the mess I left behind from the versionās development. Mainly the only thing worked on was some cleanup: roadmap now reflects actual v1.3 features and implementations updated README and contribution documents to match the current compiler pipeline cleaned up string examples so they have the full intended v1.3 style instead of some leftover testing usage pushed the compilerās version to 1.3.0 updated help / usage text so it matches the new output-path and auto-run behavior Prior to this, if I had just merged and shipped, the release wouldvāe been messy: README, Contributing, example files, and guidance commands were all mixing older details which made it confusing ā even for me ā when trying to explore the language and what it has to offer. For a bootstrapped compiler especially, making sure everything is cleaned up and polished is something that should not be ignored. Iām definitely guilty of overlooking this, but Iāve outlayed a whole plan for v1.3 unlike past versions, and part of it was setting up a proper versioning system and polishing its release as it goes. This format will be adopted in future versions, since itās just way cleaner and nicer to look at. Future work At this point, v1.3 is done and has implemented, at minimum, a concrete foundation for post-v2 bools and strings. Next will likely be more subtle improvements, and features that are currently reliant explicitly on C rather than Flower-hosted code. In order for v2.0 , Flower will have to be effectively independent from C if it wants to emit machine code. Currently I am planning on adding features such as Type Aliases and maybe a stdlib prior to that, but anything can change!! Thanks for being here for all of v1.3 <3
Devlog: Making Flowerās Type Aliases Transparent This version was simple to develop on paper (and even in practice it wasnāt too bad, only around 4 or so hours!): type Count = int type Total = Count type Name = string and then have those aliases behave like the real type everywhere: n: Count = 12 total: Total = identity(n) name: Name = "Ivy" if name != "Ivy": return false end if name.length != 3: return false end That meant aliases could not just be parsed and stored, but rather had to be transparent to the compilerās semantic checks. What changed I added type alias declarations to the AST, parser, and type environment, then added the ability to resolve aliases in typechecking before comparing types. That included: return type checks variable initializers function call arguments binary comparisons string-specific comparison logic struct field access The important rule here is that aliases are semantic, not codegen-facing. Count should behave as int , Name should behave as string , and chained aliases like Total -> Count -> int should collapse correctly. In the future, especially post v2.0 , this could change and custom types might become real ā but for now, theyāre just aliases. The bug that exploded bootstrap The first real failure was not in aliases themselves, but in function argument checking. Inside check_call_args(...) , the compiler was resolving the argument expression into expected_type instead of arg_type . That overwrote the parameter type, left the actual argument type uninitialized, and caused the second bootstrap stage to explode into over a thousand misleading errors. This was not a pre-existing issue, it was instead from human error (my error) during the initial implementation where I accidentally put the wrong variable. Once that was fixed, the remaining failures were much more helpful than the bright flash of red and āTypecheck failed with 1224 error(s)ā message! Where this leaves v1.4 With the first step toward ābetter typesā done, aliases are no longer just syntax. That gives v1.4 a solid base for whatever comes next in the type system without having to fake around raw names. During this whole dev session, I did discover that a whole lot more of the source code was left using legacy work-arounds: int instead of bool , name_start; name_length and @char instead of string . In all fairness, some of these arenāt exactly the easiest to refactor. However, I will probably hold off on refactoring the codebase until either right before v2.0 , or right after. Just know itās on my radar ;)
Devlog: Fixing Flowerās Compiler Process So It Stops Fighting the Host This wasnāt really about language design at all buttttt it is much more embarrassing , AND more important: Flowerās compiler process itself was too fragile. The immediate issue showed up on Linux, specifically NixOS (thanks shipwrights <3). The build flow was assuming too much: a previously existing bin/Flower could be reused safely bash would exist at the expected path clang would always be available the checked-in compiler binary would be runnable on whatever machine the repo landed on That worked well enough on my machine until it didnāt. On NixOS ā and by extension probably any other machine without the prexisting binaries I had ā it broke: make targets were inconsistent, the shell script failed on interpreter assumptions, and the compiler binary itself could be the wrong format for the host. What changed The fix was to separate āthe compiler source existsā from āthe current compiler binary is usable on this machine.ā The build process now starts by compiling a fresh host-native bootstrap compiler from bin/Flower.c , instead of trusting whatever happens to already exist in bin/Flower . That means the flow is now: bin/Flower.c -> host-native bootstrap compiler -> new Flower compiler -> self-check instead of: maybe existing bin/Flower -> hopefully works -> maybe bootstrap Ok well thatās kinda a lie; it still relies on hopes and dreams to bootstrap sometimes. BUT itās MUCH safer! And now everyone gets to experience crippling bootstrap anxiety, instead of being met with a failure before the actual compiler gets to.. well, do its thign! I also cleaned up the surrounding tooling: switched the bootstrap script to portable sh restored a clearer build / bootstrap / rebuild / test / clean structure made the compiler use CC and CFLAGS from the environment instead of hardcoding clang What this actually improves Flower is still not universally cross-platform yet. The compiler driver still has POSIX-shaped assumptions in places, and the emitted C can still depend on host APIs depending on what the program uses. Iām not yet at the point of wanting to make it completely universal, especially given how Iām only one person and with v2.0 coming up soon itād ā in my humblest of opinions ā be a waste of time. I am honestly grateful for people reviewing my code and otherwise viewing it catching onto details I have overlooked. My goal is to not make a ājust-barely working on my machineā project; I enjoy sharing development with others, and it hurts knowing people canāt appreciate code, whether it be mine or othersā, due to something as simple as hard-coded sh flags.
Devlog: Formalizing Flowerās Null Foundation Flower already had some of the pieces for null , but they were a bit scattered. The goal here was to make it explicit, consistent, and safe before moving on to nullable syntax like ?T or full union-based nullability later in v1.4 . Another shorter devlog, but still important and distinct enough for me to think āHmm devlog time? Yes, devlog time!ā What changed The main work was in typechecking. I added to the compilerās idea of what null is, how it is represented internally, and what kinds of values are actually allowed to accept it. Rather than letting null-related behavior stay implicit across a few checks, null now follows a clearer rule set: null has one centralized internal type representation pointer-like values can explicitly accept null null comparisons and assignments now go through the same semantic path Why this matters This isnāt all that important on its own, but it matters a lot for where Flower is going next. If null is not defined well, then later features like: ?T better unions smarter narrowing more expressive type flow all become more error-prone (or so I assume given my track record) than I want need them to be. Validation I also expanded the example coverage so null : it now has dedicated behavior checks around assignment, passing values around, and comparison behavior.
Devlog: Adding Pointer-First Nullable Types to Flower I worked on giving Flower its first real nullable type surface without being overambitious and pretending the compiler is ready for full optional-everything semantics yet. The new syntax now works like this: ptr: ?@int = null text: ?@char = null That means there is now an explicit way to say āthis pointer-like value may be absent,ā instead of relying entirely on raw pointer habits from C (If you couldnāt tell by now, I despise C). What changed The main work was split across lexer, parser, and typecheck. I added: ? as a type marker in type positions is_nullable tracking in TypeInfo type rules for nullable pointer/reference values explicit compatibility for: assigning null into nullable pointer-like types comparing nullable values against null casting between @T and ?@T I also kept the scope intentionally narrow: this implementation is pointer-first nullable support , not full nullable scalars. So ?@int makes sense right now, but ?int is still deferred until I make a better semantic union / optional representation for plain values. Why this matters It would have been easy to overreach here and claim ānullable types are done,ā but that would have been a big phat lie. Pointer-like nullability lowers naturally enough with the current backend and current compiler model. Scalar nullability, however, does not. Once you let int or bool become nullable, you need a more real representation for āhas value / no value,ā and that belongs in the later union work, not here. Result explicit absence compiler-owned semantics better future unions stronger type meaning without hidden magic The next real step after this is not more patching around null ā I consider that done for now ā but instead giving Flower the deeper machinery needed for nullable non-pointer values and semantic unions later in v1.4 so it doesnāt come back to bite me in my butt.
v1.4.4 Devlog: Giving Flower Real Semantic Union Types I made it so that semantic unions are now in Flowerās parser and type system ā but not yet its codegen. The goal was to support types like: value: int | string next: @Node | null type Result = int | string Whatās new The parser now understands | inside type positions and builds semantic union type information instead of relying on those old plain aliases or backend-shaped hacks. On the typecheck side, unions are now carried through normal type copying and alias resolution. That means named aliases like: type MaybeName = string | null make sense after resolution, instead of collapsing into nonsense. The typechecker also now accepts union-compatible usage in the places that matter for a foundation: variable initialization assignment parameter passing return checking alias resolution So if a value matches one union member, it is accepted. This is sorta implicit behavior, but I think it gets a pass due to its somewhat explicit nature? What it does not do yet This version was intentionally strict about using unions as values. You cannot yet directly: index a semantic union access a field on a semantic union use arithmetic / comparison operators on one print one directly Instead, Flower now requires an explicit cast before using a union value that way. That may sound harsh, but it is the right restriction.. for now. There is not any narrowing yet, so pretending unions were fully usable would just make the language lie and spit out 2,000 errors. Where this leaves v1.4 Flower now has: transparent type aliases null as a real type-system concept pointer-first nullable types semantic union type representation The next step is the part that will make unions actually usable rather than merely legal: narrowing with is better explicit extraction with as eventually making ?T truly become T | null instead of remaining pointer-first for now No fun screenshot this time :p just frontend work for now⦠Ivy, signing off <3
Devlog: is Checks v1.4.5 added is checks, mostly so code like this can work: if maybe_ptr is @int: real_ptr: @int = maybe_ptr end The idea is (fairly) simple: if the condition proves maybe_ptr is an @int , the inside of the branch should be allowed to treat it like one. Flower did not know how to do that before. It knew what a variable was declared as, but it did not really learn anything from control flow yet. Now it can, at least for the pointer/nullable-ish cases I care about first. This touched the parser, AST, typechecker, narrowing logic, and codegen. So, naturally, the āsmall featureā went everywhere. Iād actually consider this one of the bigger refactors so far, mostly because it added a new TypeAtom structure. Before this, types were still a bit too attached to the places they appeared, and all fell under the TypeInfo . That worked for simpler declarations, but is checks needed type syntax to have something the compiler could pass around to use for comparisons, validations, and narrowing. The parser had to recognize the new expression shape. The AST had to store the left side and the tested type. The typechecker had to make sure the test was allowed and not totally garbage. Then the narrowing logic had to say, āinside this branch, this variable has the proven type of x and therefore we wonāt flag you for being an idiot.ā That last part was where the bug goblin lived. Iām calling them a goblin because they were sneaky (and I also think itās quite a funny and cute name). For a while, Flower had applied narrowing from the if body instead of the if condition, which meant the compiler saw this: if maybe_ptr is @int: real_ptr: @int = maybe_ptr end and somehow still failed on the assignment inside the branch. Very helpful. Thank you, compiler. EVen though itās obviously 100% my fault, I made the compiler, but oh well!! Once I changed the narrowing step to inspect the actual condition expression, it started behaving like it should. The typechecker could see maybe_ptr is @int , attach that narrowed type to the branch scope, and allow maybe_ptr to be used as @int inside the guarded block. For now this explicitness is how I want it. There may come a time in the near future where I decide some implicity is ok, but weāll see ;) is checks are the first real step towards control-flow-aware typing in Flower. Not full union support yet, but definitely the beginning of that road soon to come. Right now it mostly helps with nullable and pointer-like cases. Later, the same idea can support richer unions, better narrowing, and more type-driven control flow without making the programmer manually restate everything the compiler should already know. Also, it bootstrapped cleanly twice ā which.. is obviously the bare minimum, but still!!
Devlog: Semantic Unions Become Actual Values (Part I) In v1.4.6 , I made semantic unions actual runtime values instead of just parsed/typechecked shapes. Before this, Flower could understand: type Value = int | string as a type. It could point at it and say, āyes, that is a union,ā but that was mostly theoretical. The goal was to make this work-work for realsies: type Value = int | string value: Value = 7 if value is int: n: int = value as int end value = "Ivy" if value is string: s: string = value as string end That meant Flower needed more than TypeInfo.is_union = true . It needed a full path from syntax, to type proof, to lowered storage, to runtime extraction. Otherwise unions would just be fancy typechecker thingy-ma-bobbies, which is not very useful when the backend still emits C. What changed Instead of treating a union as a vague āone of these types, probably,ā Flower now lowers it into a tagged structure. Conceptually, this: type Value = int | string becomes something like: struct Value { int tag ; union { int as_int ; flower_string as_string ; } data ; }; Not the final sacred form forever, but that is the shape of it: a tag saying which variant is active, plus storage for the possible members. Since Flower emits C right now, the lowering is C-shaped. I am not fully sure how I want this to look in ASM yet, but I do know it would be way more technical, and uglier. This required a few things to play nicely with one another: if value is int creates a union proof the guarded branch stores narrowing information value as int is only allowed after proof assignments pack values into the right tagged member explicit casts extract the right member from storage Otherwise the compiler is just writing checks its own backend cannot cash. The part that makes it ACTUALLY semantic For pointer narrowing, if value is T mostly refines how the compiler treats an existing value. For semantic unions, the check also becomes a runtime tag test. So this: if value is int: means: check the active tag of value , then inside this branch, treat it as the int variant. Then this becomes valid: n: int = value as int because the branch already proved the active variant. Without that proof, value as int should not be casually allowed. Flower is supposed to be explicit, not psychic, and I am not confident enough yet to implement a proper intuitive implicit checker without summoning something cursed. Assignment and extraction This: value: Value = 7 now packs 7 into the int member and sets the tag to the int variant. Then this: value = "Ivy" does the same thing, but for the string member. So a semantic union is not just some bytes, but rather a tagged runtime object where Flower knows which member is active. Then explicit casts like: value as string can lower into extracting the string member, but only when the typechecker has accepted that the operation is safe in that control-flow path. Why this checkpoint matters Flower can now store variant values, prove which variant is active, and require explicit extraction instead of relying on random magic I threw together. The flower has grown another concerning little organ.
Devlog: Letting Semantic Unions Work In Functions After getting semantic unions working in local declarations, the next problem was fairly obvious (and in my roadmap hehe). This did not work before: func make_value(): int | string return 7 end func accept_value(value: int | string): bool return value is int end Which was annoying, because int | string was already a real union type at this point. Flower could use it in locals, it could pack assigned values, it could check variants. But if I returned 7 from a function declared as int | string , or passed 7 into a parameter expecting int | string , the compiler did not know how to carry that union-lowering information across the boundary. This has been one of the easier changes Iāve made in a long while. It compiled properly first try (if you ignore a tiny misspell I made which I fixed really quickly), and there were no prior hidden bugs that surfaced. This.. is too suspicious. What changed The compiler now carries semantic union info through: function parameters function returns imported alias calls If a function expects: int | string and I call: accept_value(7) typecheck records that 7 needs to be packed as the int member of that union. Same for returns: func make_value(): int | string return 7 end That matters because codegen cannot guess later due to the separation of responsibilities Iāve laid out. By the time Flower is emitting C, it needs to know which tag to set and which member to write. Lowering it properly Codegen already knew how to pack union values for declarations and assignments. The missing part was doing the same thing for call arguments and return statements. So now a value can be packed into a tagged union when it is: stored locally passed into a function returned from a function Alias calls got handled too, so things like: remote.accept(11) remote.make_string() do not become their own weird little cursed island. Why this mattered Without this, semantic unions only worked as long as I never organized my code. They worked in local tests, but not in helper functions, imported providers, or normal inputs and outputs. Now union values can actually move around the program instead of being trapped in the one scope where they were declared ā and for me, forgotten! Very exciting, the union can leave the house. They grow up so fast āāĢ“Ģ ā āĢ“Ģā
Devlog: Adding Obvious Branch-Local Inference to Flower Before this, narrowing mostly worked in the obvious ātrue branchā cases: if maybe != null: real: @int = maybe end and: if value is string: s: string = value as string end But the else branch was still kind of standing there empty-headed, even when the meaning was extremely obvious. Like, if this happens: if maybe == null: return false else: real: @int = maybe end then inside the else , maybe is clearly not null. So now it doesnāt!! What changed Flower now does branch-local narrowing in else for small, explicit cases. That means these now work: if maybe == null: return false else: real: @int = maybe end and: if value is int: return false else: s: string = value as string end It is only applying inference when the condition says something directly and the opposite branch has one obvious meaning. Nullable narrowing For nullable pointer-like values, Flower now understands both sides of simple null checks: if x != null narrows x to non-null in the if body if x == null narrows x to non-null in the else body the opposite side can narrow to null when that is the only meaning left Semantic union narrowing The same idea applies to semantic unions, but a bit more āheld back.ā Essentially, if Flower sees: if value is int: then the if branch narrows to int , like before. Now, if the union only has one other possible member, the else branch can narrow too. So for: int | string the else after if value is int can be treated as string . This is not full control-flow wizardry, since it doesnāt reason across deep boolean chains, early-returns, or giant branches yet. It is deliberately small and local, because I do not want Flower āhelpingā so much that I need a detective board to figure out what type something is.
Devlog: Teaching Flower to Understand Guard Clauses gave Flower branch-local inference. Last update, I added support for branch-local inference, so the compiler could understand things like: if maybe == null: return false else: real: @int = maybe end and: if value is int: return false else: s: string = value as string end That was an improvement, but it still meant narrowing stopped at the end of the branch. That meant stuff like returninging in some conditions still did not really work as naturally as it should: if maybe == null: return false end real: @int = maybe or: if value is string: return false end n: int = value as int In v1.4.9 I fixed that. What changed Now narrowing propagates past very obvious guard clauses. If one branch definitely returns and the other falls through, the compiler now carries the interpretation forward after the if . This means that the compiler can now understand: after if x == null: return ... , x is non-null after if x is string: return ... , a two-member semantic union can narrow to its remaining member I kept this intentionally conservative for now. The compiler is not doing full control-flow analysis yet. It is only recognizing the simplest and most explicit early-exit shape. How it works The main addition was a small semantic check for ādoes this branch definitely return?ā Right now that means: direct return if where both branches definitely return Once the compiler knows one side exits and the other survives, it applies the branchās narrowing to the following statements. Yea.. thatās it lol.
Devlog: Making ?T Actually Mean T | null Before v1.4.10 , ?T was treated as its own nullable system and not really integrated with the rest of the semantic unions. This was unideal, because it created a separation of logic which was cumbersome to maintain. The idea was to make the following be the default: ?int == int | null ?string == string | null ?@int == @int | null Prior to the refactor, nullable types were still mostly pointer-oriented. That worked when ?T basically meant āmaybe this pointer is null,ā but it did not really fit anymore once semantic unions became actual runtime values. If Flower has T | null , then ?T should use that instead of being its own special thing. This is a more pragmatic choice, as it keeps the compiler easier to manage and update later on. What changed Typecheck now lowers ?T into the same semantic-union machinery used by normal unions. That means nullable values now go through the same general path as union values: null checks use union-aware narrowing narrowed nullable values can be extracted with as codegen emits tagged union storage assignments pack into the right union member So this now works as an actual nullable flow: maybe: ?@int = raw if maybe == null: return false end real: @int = maybe as @int The annoying part is that Flower has to track two things at once: the type the programmer is allowed to see after narrowing, and the actual union shape that remains underneath it. After the guard, maybe behaves like an @int . But codegen still has to remember it came from @int | null , because apparently the compiler cannot simply āvibeā its way through storage layout. Tragic! The bugs that annoyed the heck out of me Most of the work was not surface syntax. The syntax was just standing nearby looking innocent. The actual bugs were in the places where Flower knew āthis is non-null now,ā but then forgot how to lower, such as: narrowed nullable values falling back to raw C casts like (int*)(maybe) false branches of == null / != null narrowing to the wrong side (this was my fault lol) null getting packed into the wrong union member That last one was the rude one. For ?@int , generated C could end up doing something like: . tag = 1 , . m0 = NULL instead of packing into the actual null member. So the value looked almost right, but the tag/member pairing was wrong. Then later null checks would fail, because the compiler had technically put null somewhere. Just not the correct somewhere. Very helpful. The fix was separating two questions I had accidentally merged: is this type compatible with this union? which exact union member should this value occupy? Those look related, but they are not the same question. Flower was using the first answer for the second problem, and then acting surprised when everything became soup. Where this leaves Better Types ?T now lowers through the same path as T | null , which means null checks, narrowing, extraction, and storage all line up with the semantic union model. This should make later work cleaner, such as nullable inference, nicer union ergonomics, maybe pattern-like narrowing eventually. Not easy. I am not saying easy near a compiler. That is how they hear you. You do not want them to hear you ..
Devlog: Direct Semantic Union Parameters Now instead of having to do this workaround: type Value = int | string func accept(value: Value): bool You can just pass semantic unions directly: func accept(value: int | string): bool That was it. All I had to do was remove a stale type_error clause in register_params and allow binding variables. Then I updated the two relevant accept functions in /examples.
Devlog: Letting Union Narrowing Follow Field Access Before v1.4.13 , union narrowing only really worked when the thing being narrowed had a variable name due to almost every similarity check relying on name_start and name_length . This was dumb, because semantic unions already knew how to test tags and extract members. Codegen was not the issue, but rather the annoying part was that the typechecker could remember this: if value is int: n: int = value as int end but not this: if box.value is int: n: int = box.value as int end So I still had to do a little temp-variable ritual: tmp: Value = box.value if tmp is int: n: int = tmp as int end Which was gross. Not necessarily catastrophic, just gross and annoying. I wanted needed convenience What changed The compiler was remembering narrowings by variable name, not by expression shape, so box.value looked obvious in source (to me, at least), but to the typechecker it was basically some random expression and not something it could reliably recognize again later. A variable name already had a stable identity, whereas field access chain did not. So the change was to let narrowable expressions represent more than just AST_VAR_REF . For now, that only means stable dot-access chains. The typechecker can record a narrowing for an expression like: box.value and then recognize the same expression later when a cast shows up. So this works directly now: if box.value is int: n: int = box.value as int end Same for the other union members, like string . The detour My first example accidentally wandered into a different feature: if maybe_box.value != null: That exposed a real nullable-field-guard gap, but that is not what this was supposed to be about. Very rude of the test case to have ambition hmph >:( Where this leaves it Semantic union narrowing now persists past field access ā at least for stable dot-access chains ā and the temp-local is no longer needed. Butttt now I gotta work on nullable-field-guards, ugh (hehe)
Devlog: Finishing Nullable Field Narrowing At this point, Flower could already narrow semantic unions through field access in the is / as case, and nullable field checks were supposed to be the obvious follow-through: if maybe_box.value != null: label: string = maybe_box.value as string end Instead, I had forgotten to remove a LOT of stale code, and thus part of it was still behaving like only plain local variables could ever be narrowed. There was also a second, smaller mismatch hiding, where null in type position was not lining up with the compilerās actual internal null representation. ?string and string | null werenāt leading to a congruent output and at times were wobblier than they should be. So the fix was mostly cleanup, but the meaningful kind: make null in type syntax lower the same way the compiler expects remove the stale var-only branches in nullable narrowing let stable field paths like maybe_box.value and holder.box.value narrow properly The funny part is that this felt bigger initially than it actually was once fixed. Nothing fundamentally new had to be invented, I just had to stop the old code from interfering with the newer code, which once I figured out how to do so it was quite quick. I spent an embarrassingly long time figuring it outā¦
Devlog: Syncing Flowerās Docs Back to Reality Just a doc cleanup lol. No code change or compiler updates. Probably did more than needed for now but oh well! The mismatch was REALLY bad. The old docs preserve old assumptions, and someone reading them could walk away with a version of Flower that no longer really exists (or, in some cases, doesnāt exist yet or never ever existed)! What changed I updated the docs that had drifted the most from reality (relatable): README.md now reflects the current type-system shape ROADMAP.md treats v1.4 as accomplished the v1.4.0 milestone doc now includes more of the outcome, not just the original plan contributor docs no longer have stale semantics structure.md is more accurate to what Flower currently is, and what still needs a fuller rewrite later Yea, thatās it.
Devlog: v1.5.1 ā v1.5.5 Following all of the changes Flower has undergone, I felt it was time for some much-needed documentation. On paper this was supposed to be fairly quick, simple, and not require much brain power. Unfortunately for me I got a bit too over-zealous, and included things I thought should work, but in reality hadnāt. For example, in a lot of the code snippets Iād have something like: for i in range 0..10: print(i) end Printing non-string values was not yet supported in Flower. To fix this, I took a small detour back to v1.4 and implemented support for it ā mostly in a single codegen case: if ast.data._print.value_type.base == TOKEN_FLOAT or ast.data._print.value_type.base == TOKEN_DOUBLE: fprintf(out, "printf(\"%%f\", ") gen_expr(ast.data._print.value, out, src) fprintf(out, ");\n") end Afterwards I added more smoke-tests in examples/io/print.flo . Every few runs, however, Iād get a segfault. This was especially odd because it wasnāt simply an error but rather a silent memory bug. Eventually I found out where it was originating ā thanks, ASan! Turns out after the new type system changes, I had forgotten to initialize some values to null / 0 in for loop handlers and a few other places. I just added typeInfo.data = null / 0 where applicable and it fixed the issue! What is v1.5, and why is this devlog so long? To answer the latter first.. I lowkey just forgot to post a devlog for the first two docs I made. Thatās it. For the former question, v1.5 is supposed to be explicitly a documentation pass. First thing I worked on was structure. I cleaned up the docs layout, moved things toward a more consistent lowercase docs/ tree ā I had been trying for so long to do that and I just finally got it to work ā and wrote down the documentation process itself so new pages arenāt just floating about. The point was to try and make the docs feel like a book instead of a folder full of unrelated notes. I wrote and checked the language pages for types, functions, and control flow by reading the compiler itself, not by trusting my (poor) memory. That meant checking parser rules, typecheck behavior, codegen boundaries, and example files before writing anything solid. Types especially needed this, given how Flower now has enough real type machinery that the docs can quickly go from being coherent to completely incorrect: nullable sugar, semantic unions, explicit casts after narrowing, alias behavior, current member limits, and the difference between what the language wants to become and what the compiler supports currently. Functions and control flow had a similar issue. I had to document prop , return rules, direct call forms, logical conditions, range-based for , and the rough edges like break and continue not yet being enforced cleanly as loop-only. That kind of thing is small until someone learns the language from the docs and hits the edge head-first (been there, done that). What Now? Iām just going to keep writing docs. Maybe do one devlog for every new doc, or a batch of docs, who knows! I certainly donāt :p
Hey, itās been a while! Iāve been finding it difficult to stay motivated for this project, especially with how the new payout system works and just my in-general inability to keep commitment despite having a lot of passion. That said, I am going back to working on this diligently, and I think to start Iām going to cut down on the documentation by making perhaps one or two changes, and then going right back to the compiler work. Documentation writing has not been the most fun for me, especially with how long it takes and how itās so difficult to not only write language reference that works, but also keeping the same whimsy Flower should have. Thank you to everyone whoās been following this journey, and I canāt wait to see yāall later!!! With Love, - Ivy <3
Integer Types, Parser Fixes, and Segfaults! Phew ā this one was biiiiiggg. Flower is pretty much just a glorified C transpiler, which is NOT what I want for it! In order to move on, the data has to be handled explicitly by the FloC. So essentially, I implemented i8 , u8 , i16 , u16 , i32 , u32 , i64 , and u64 . For now, int canonically refers to an i32 value. A New Era? With these new literals, the old hoist-sized representation had to go. The decimal source text is preserved, meaning values such as 18446744073709551615 remain after parsing without causing any overflow. Types are picked up from declarations, assignments, function arguments, return values, field writes, array-element writes, * breath in * and binary expressions! Oof, that was a mouthful. That, of course, resulted in proper errors for things like: 256 assigned to u8 ā1 assigned to an unsigned type values beyond u64 unconstrained literals outside the default i32 range I Hate Memory During printing, every width is handled. Integer conditions retain existing zero / nonzero behavior, and literal types print their values rather than a character. Halfway through, I ran into sudden segfaults and memory leaks. I was taken aback, because I didnāt even change anything parser related yet. Turns out, I forgot an assignment in a declaration, which apparently the parser wasnāt able to handle (whoops!). Anyways, I fixed it by propagating errors through the compilation process, so the compiler doesnāt try to typecheck or code gen if the parser reports back errors, and instead will print them out. And thatās it! Not thatās it, but thatās all Iām going to explain for now. More specifics available on the GitHub, of course. Speaking of GitHub thank you so much to S1monr3dst0ne07 on GitHub for fixing some memory leaks in the previous version of Flower ā I forgot to prune allocations before returning from a function :p Love yāall!! <3 P.S.: So glad I gave up on documentation, I was genuinely dreading workong on the project and thatās why Iāve been ianctive for a long time :c
Integers, Integers, Integers Hello!! Been a while :) Lately I have been working on v1.6. I call it the āUsefullnessā update ā rhymes with Grug ā because it adds a ton of long awaited features and various convenience implementations Flower DESPERATELY needs. For example, currently the progress has to do with v1.6.1, or Fixed-Width Integers . When it comes to systems programming and in-general efficiency, having various integer sizes is important as it provides an additional layer of manual control over memory and sizes. I know I would have to add them eventualy, so why not put them at the start of the Usefulness update?? Iām sure theyāll come in handy later on. What Actually Changed? Well, for starters, thereās now fixed-width integers (yay)! Theyāre built in types, so you declare them as you would with any other atom / primitive: type Byte = u8 type Choice = Byte | u16 type OptionalByte = ?Byte struct Packet { pair: Byte[2], size: Choice, owner: OptionalByte } A whole bunch of commits and integer-specific changes regarding indices, arity, unions, nullables, etc etc etc have been made, and they all wonāt fit here so instead, take a look at the current branch ! Whatās In Store? Plenty more features, you can assure yourself! Thereās maybe 6 or 7 ā I swear ā or so commits left for this specific addition, and after that a lot more features laid out in the roadmap for 1.6! As always, thanks for sticking around and watching the fiasco that is this project become more and more estranged with every hour. Love yāall!! Ivy <3
Ships:
Flower is a self-hosted programming language for writing simple, explicit systems code without the abstraction bloat and OOP-heavy direction a lot of modern languages have. The compiler is written in Flower itself, currently targets C, and follows a straightforward pipeline: lexing, parsing, module loading, typechecking, and code generation. Over the past few months, Flower grew from a small lexer/parser/codegen experiment in C into a way bigger language project than I couldvāe imagined. This wasnāt my first attempt at a language, but it has been my favorite! I implemented compiler-enforced module semantics, stronger type-aware codegen, real boolean support, real string support, and a small standard library foundation. Strings now have equality, .length, indexing, and explicit casts to and from @char , while modules support exported prop declarations, aliases as namespaces, and private-by-default top-level declarations. The hardest part was bootstrap stability. I ran into idempotency failures, parser edge cases, compiler corruption scares, and plenty of my own bad logic. A lot of the challenge was getting new features to work not just once, but consistently enough for the compiler to rebuild itself cleanly. One bootstrap it succeeds, and then the next Iām scrambling to figure out why the new binary executable has a corrupted parser despite just working (Still havenāt fixed that yet! It.. was really confusing and Iāve got no clue why it happened lol). Iām proud that I kept pushing through that and ended up with something much more fun to use than where I started ā I mean, I donāt even have to write that much C anymore!! If people want to test Flower, the important thing to know is that it is self-hosted and still experimental, but it does work. The repo includes a bootstrap path, a test suite, and example programs covering types, control flow, memory, imports, strings, and bools. The current release is focused on making the core language feel real and usable before moving on to a larger standard library and a future non-C backend, so donāt be surprised if a C file is shoved in your face!
The compiler is written in Flower itself and currently targets C, so this release was mostly geared towards making the type system have actual Flower semantics instead of a thin little blanket over whatever the backend happened to be doing. The big additions in v1.4 were: transparent type aliases real null nullable types as ?T == T | null semantic unions like int | string explicit narrowing with is explicit extraction with as That support now works across locals, parameters, return types, struct fields, and stable field-expression chains. The work had to touch parser logic, typecheck, narrowing, lowering, codegen, bootstrap, and then all the weird regressions those changes politely dragged into the room. It was.. a process for sure What Iām most proud of is that v1.4 pushed Flower toward a clearer identity that wasnāt defined by C as much anymore. This release also brought the docs back in line with the compiler, which was LONGGGGG overdue. If you want to test it, the main things to look at are the Better Types examples and the self-hosting flow. The compiler should bootstrap cleanly, the test suite should pass, and the examples now cover aliases, nullable values, semantic unions, inference, and struct/field narrowing behavior. For those who will be testing it, DO NOTE that I develop exclusively on my MacBook which is a UNIX system! I do not have the ability to properly develop and provide releases for Linux-specificalities or non-POSIX systems. Iām extremely sorry for this, but alternatively watch the provided video to see Flower in action :) If youāre not able to test it, watch this short (crappy) video instead: https://youtube.com/shorts/DyPtIru6cjY?feature=share...
|
1793505052.2145452
|
1793591452.2145452
|
|
30527
|
Bulldog by @CheezzyBoii | Stardance
|
CheezzyBoii
|
2
|
3.0
|
1
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-16T20:12:10Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "My simple slackbot named bulldog acctualy working this time please take a look", "repo": "https://github.com/CheezzyBoii/Bulldog", "demo": "https://hackclub.enterprise.slack.com/archives/C0BFQ5WMUGN"}, {"ship_num": 2, "ts": "2026-07-07T02:52:57Z", "hours": 1.0, "multiplier": 1.46, "payout": 1, "blessing": "neutral", "text": "Nice slack bot with the nice name Bulldog damn he is tuff.", "repo": "https://github.com/CheezzyBoii/Bulldog", "demo": "https://hackclub.enterprise.slack.com/archives/C0BFQ5WMUGN"}]...
|
[{"post_id": 29692, "ts": "202 [{"post_id": 29692, "ts": "2026-07-16T19:25:25Z", "hours": 0.6619, "text": "Addes /bulldog-yes-no it uses the api https://yesno.wtf to get a yes or no gif for the user"}, {"post_id": 24319, "ts": "2026-07-07T20:31:34Z", "hours": 1.5517, "text": "I worked on bulldog for 1 hour and 31 minutes adding a new slash command /bulldog-image which returns a random dog image. I thought that the read me needed to be updated to be actually useful and some other stuff."}, {"post_id": 23882, "ts": "2026-07-07T02:32:47Z", "hours": 1.0364, "text": "Just make the initial commit for my slack bot project"}]...
|
Title: Bulldog by @CheezzyBoii | Stardance
Devlog Title: Bulldog by @CheezzyBoii | Stardance
Devlogs:
Just make the initial commit for my slack bot project
I worked on bulldog for 1 hour and 31 minutes adding a new slash command /bulldog-image which returns a random dog image. I thought that the read me needed to be updated to be actually useful and some other stuff.
Addes /bulldog-yes-no it uses the api https://yesno.wtf to get a yes or no gif for the user
Ships:
Nice slack bot with the nice name Bulldog damn he is tuff.
My simple slackbot named bulldog acctualy working this time please take a look...
|
1793505047.4331152
|
1793591447.4331152
|
|
30517
|
my APOD site by @SpacerCoder | Stardance
|
SpacerCoder
|
1
|
1.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-05T10:56:57Z", "hours": 1.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a website where you can select any date, without getting an error, and then get the nasa image/video of the day from that time. The challenging part was routing the API call properly, according to the date. I am most proud of how clean the UI is, and how smooth the operation is. It works perfectly as intended! To test this project, click on Try project, and go ahead and select any date and see the description for that image/video!", "repo": "https://github.com/SwiftProGrammer178611/myAPODsite", "demo": "https://swiftprogrammer178611.github.io/myAPODsite/"}]...
|
[{"post_id": 22298, "ts": "202 [{"post_id": 22298, "ts": "2026-07-04T18:06:01Z", "hours": 1.0211, "text": "Finished adding my own little spin. You can pick a date, and see what the picture of the day was from that date from the API form NASA"}, {"post_id": 21978, "ts": "2026-07-04T06:15:17Z", "hours": 0.4544, "text": "setup my APOD site after some errors with deleting files I didnāt need to š
"}]...
|
Title: my APOD site by @SpacerCoder | Stardance
D Title: my APOD site by @SpacerCoder | Stardance
Devlogs:
setup my APOD site after some errors with deleting files I didnāt need to š
Finished adding my own little spin. You can pick a date, and see what the picture of the day was from that date from the API form NASA
Ships:
I made a website where you can select any date, without getting an error, and then get the nasa image/video of the day from that time. The challenging part was routing the API call properly, according to the date. I am most proud of how clean the UI is, and how smooth the operation is. It works perfectly as intended! To test this project, click on Try project, and go ahead and select any date and see the description for that image/video!...
|
1793505042.095842
|
1793591442.095842
|
|
7750
|
Updato by @NellowTCS | Stardance
|
NellowTCS
|
1
|
5.0
|
78
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-06T04:27:18Z", "hours": 5.0, "multiplier": 14.89, "payout": 78, "blessing": "neutral", "text": "Updato is a decentralized update system for web apps. A GitHub Action publishes builds to a CDN branch, a Cloudflare Worker handles version checks, and a client library hot-swaps files in the browser with no reload. Itās on npm as @nellowtcs /updato. It works end to end. Push code, Action builds it, Worker picks it up, client swaps files live. No server, no database. Also thereās a live demo, a docs site, and a real npm package now. It became a real project somewhere along the way. CSS hot-swapping was a whole thing. Ended up using CSSStyleSheet.replaceSync with adoptedStyleSheets to make it work without flashing or breaking CSP. Also npm told me my package name was too similar to āupathā which is just not true but whatever, scoped it and moved on. The live demo ( https://nellowtcs.me/updato/ ) is a clock app that checks for updates from the Worker. You can also install it with āā npm i @nellowtcs/updato ā and the docs are at https://nellowtcs.me/updato/docs .", "repo": "https://github.com/NellowTCS/updato", "demo": "https://nellowtcs.me/updato/"}]...
|
[{"post_id": 3282, "ts": "2026 [{"post_id": 3282, "ts": "2026-06-06T04:21:10Z", "hours": 0.6542, "text": "devlog: shipped updato is published. itās on npm. it has a version number and everything. the publish switched the build from vite to tsdown. vite was fine for dev but tsdown gives you dual esm/cjs output with proper .mjs/.cjs extensions and matching declaration files out of the box. the package exports map has real conditional exports now ā separate import and require entries with their own types. itās the kind of package.json that doesnāt make people file issues. scoped it to @nellowtcs/updato because apparently updato was too close to upath for npmās similarity check. it is not similar. at all. but scoped names are better practice anyway so whatever, npm wins this round. the release workflow strips private , scripts , and devDependencies from package.json before publish. originally did that with an inline node script, swapped it to a one-liner jq pipe because why run a whole runtime to delete three keys. 1.0.0 ā 1.0.1 released 1.0.0. immediately released 1.0.1 because of the name conflict. so it goes. the important thing is npm i @nellowtcs/updato works and the types resolve and the imports are correct. tested it, itās real. what actually shipped all of it: github action that publishes builds to a cdn branch cloudflare worker that serves version checks from KV client library on npm with hot-swap, two update modes, optional metrics live demo at nellowtcs.me/updato docs site at nellowtcs.me/updato/docs ci pipeline for all of it a readme that actually explains what this thing does whatās left one item on the todo list: custom domain for the worker. thatās a āmaybeā and itās been a āmaybeā for a while. it can stay a maybe. closing this started as a dumb idea about pushing updates without a server. it is now a real system with five directories and a package on npm and documentation with a sidebar. i donāt know when it became a real project but it did and now itās done. first release. final (nah, probably not) devlog."}, {"post_id": 3255, "ts": "2026-06-06T03:05:19Z", "hours": 1.6772, "text": "devlog: docs, workflows, and the finish line this is the āmake it realā commit. everything that was on the todo list under ābefore you can call this a real projectā happened in one sitting. docs site built a full docs site using docmd. lives in Docs/ with its own package. seven pages covering everything: home/landing page, quickstart guide, core concepts explainer, and individual reference pages for the client library, github action, worker, hot-swap internals, manifest format, and download metrics. the client library page has full config tables, event references, api docs for every public method, and the UpdateNotification component. the action page documents every input and shows what the cdn branch looks like after a deploy. the worker page covers both endpoints, version comparison logic, caching, and rate limiting. the hot-swap page explains how each asset type gets replaced: scripts via dom replacement with data-hot-file tagging for subsequent updates, css via CSSStyleSheet.replaceSync and adoptedStyleSheets (which is CSP-safe), and images via base64 data uris. used the āskyā theme with system dark mode toggle. search, sitemap plugin, code highlighting, all enabled. github pages deployment new workflow at .github/workflows/static.yml . builds the client library, builds the demo, builds the docs, then assembles them into a single pages-root/ directory. demo goes under /demo/ , docs go at the root. deploys to gh-pages with peaceiris/actions-gh-pages. npm publish workflow .github/workflows/release-npm.yml . triggers on github release publish or manual dispatch with a dry-run option. builds the client library, strips private , scripts , and devDependencies from package.json, copies in the readme and license, then publishes with --provenance . also removed \"private\": true from Build/package.json so npm will actually accept it. security audit workflow daily cron job plus on-push when lockfiles change. runs npm audit --audit-level=high across every package (root, Build, Worker, Action, Demo, Docs). all the audit steps have || true so the workflow reports issues without failing the build, which felt like the right balance for now. separate test workflow split the test job out of ci.yml into its own .github/workflows/test.yml . same matrix across node 20 and 22, runs jest in all three packages. keeps the ci workflow focused on lint and build. todo status checked off docs. whatās left: update the readme with better examples, maybe attach the worker to a custom domain, and publish to npm. the npm workflow is ready, just need to actually pull the trigger."}, {"post_id": 3067, "ts": "2026-06-05T23:24:18Z", "hours": 1.5717, "text": "devlog: the three commits i forgot to write about got in a flow state and forgot to devlog. hereās the catch-up. multi-branch support + notification ui the whole system was hardcoded to a branch called cdn . now you can pass a branch parameter everywhere. the worker accepts it as a query param (defaults to cdn ), the client sends it with check requests, and download urls use the right branch. manifest cache keys in kv include the branch name so different environments donāt collide. the idea is you could have cdn-staging and cdn-production in the same repo and point different app builds at different ones. added branch validation in the worker too since someoneās going to try passing something weird eventually. also built an UpdateNotification class in update-ui.ts . itās a drop-in banner component that handles the whole flow. you pick top or bottom, set it dismissable or not, and call notification.show(result) when thereās an update. clicking the button downloads and applies. if the download fails it resets. styling is all inline so thereās no css file to import. updated both examples to use it. the example-app.html went from a hand-rolled banner with window.__pendingUpdate to just notification.show(result) . much cleaner. module scripts + download metrics the action now scans html files for <script type=\"module\"> tags and includes a modules array in the manifest. the client passes this through to hot-swap so module scripts get replaced with type=\"module\" set on the new element. the regex for finding them is a little fragile but it works for standard vite/webpack output. also switched the action bundler from @vercel/ncc to esbuild . ncc was fine but esbuild is faster and i was already using it elsewhere. added an opt-in DownloadMetrics class that records timing data per file download (start, end, duration, size, url) in localStorage. pass it into the config and it starts tracking. you can export as json or clear it. useful for debugging slow updates but not the kind of thing you want on by default. tests + ci wrote jest tests for all three packages. action tests mock @actions/core , @actions/github , and @actions/exec . covers input parsing, repo context, package.json version reading, recursive file listing, module script detection, and clone url construction. had to export a bunch of internal functions to make them testable. client tests use jsdom with mocked fetch. covers hot-swap (regular scripts, module scripts, stylesheets, images, unknown types), the metrics class, and the main updato class (version tracking, cache management, update checking, downloads, event callbacks). worker tests cover validation helpers, the full fetch handler (missing params, invalid params, successful checks, unknown endpoints, OPTIONS, method rejection), manifest validation with every field failure case, and the rate limiter with fake timers. ci workflow at .github/workflows/ci.yml . runs on push and pr to main, matrix across node 20 and 22. lints, runs all tests, builds all three packages. todo status checked off: multi-branch, notification ui, module types, metrics, tests, ci. whatās left is docs, a demo, and release automation. the core functionality is done."}, {"post_id": 2861, "ts": "2026-06-05T18:37:02Z", "hours": 0.8061, "text": "devlog: the ājust rename itā update (and a bunch of other stuff) the name thing changed name: Updato to name: Updato Action in action.yml. thatās it. thatās the fix. spent hours filing a support ticket, got a polite ānoā from github, and the solution was adding one word. sometimes software development is humbling. hot-swap got its own file ripped the hot-swap logic out of updato.ts and gave it a proper home in hot-swap.ts . while i was in there i figured i might as well make it actually good. it now supports images too. png, jpg, gif, svg, webp, ico, bmp, avif. it finds matching <img> , <source> , and favicon <link> elements by basename and swaps their src/href to a base64 data uri. so if your update is just a new logo, no reload needed. also switched the element matching from substring ( src*=\"${file}\" ) to basename comparison, which is way less fragile. before, a file called app.js couldāve accidentally matched webapp.js . now it actually compares the filename part properly. the css swap switched from btoa() to encodeURIComponent() which handles unicode better. small thing but the kind of thing that wouldāve been a weird bug later. everything returns a typed HotSwapResult now instead of just a boolean. so the caller knows what got swapped, what type it was, and which file it was for. manifest validation added a real validator in Worker/src/manifest.ts . before, the worker was just casting response.json() as Manifest and hoping for the best with a couple of if-checks. now thereās a validateManifest() function that checks every field properly and returns typed errors. each error tells you which field failed and why. this runs both when fetching fresh manifests from github and when reading cached ones from kv. if a cached manifest is corrupted it just falls through and re-fetches. rate limiting new file: Worker/src/rate-limit.ts . uses cloudflare kv to track requests per ip. 60 requests per 60 second window, which is generous enough for normal usage but should keep anyone from hammering it. uses CF-Connecting-IP for the real client ip, falls back to X-Forwarded-For . returns a proper 429 with a Retry-After header when you hit the limit. the kv entries auto-expire so they donāt pile up forever. I half wanted to make the 429 return silly messages, but I gotta be serious apparently sometimes :/ had to add a kv namespace binding in wrangler.toml for this. the worker was fully stateless before, now it has a little bit of state. felt like a big architectural decision for whatās basically a counter but whatever, itās the right call. kv caching for manifests while i was adding kv for rate limiting i figured i might as well use it for manifest caching too. previously every /check request was hitting githubās raw content cdn directly. now it caches the manifest in kv with a configurable ttl (defaults to 300 seconds). means fewer github api calls and faster responses for repeat checks. worker got lint + prettier too copied the eslint + prettier setup from Build into Worker. also added projectService and tsconfigRootDir to both eslint configs so typescript-eslint can actually find the tsconfigs. this was one of those āwhy is eslint yelling at meā rabbit holes. todo cleanup checked off rate limiting and manifest validation. removed the already-completed items that were cluttering the list. itās getting shorter."}, {"post_id": 2619, "ts": "2026-06-05T07:31:58Z", "hours": 0.3933, "text": "devlog: hot-swap and cleanup two things happened here and theyāre very different vibes. hot-swap so previously applyUpdate() was just⦠reload the page. which works, obviously, but itās not exactly elegant. if youāre updating a css file thereās no reason to nuke the entire page state. now it actually tries to be smart about it. when you call applyUpdate() , it looks at each fileās extension and attempts to swap it in-place: for .js files, it finds the matching <script> tag by src and replaces it with a new one containing the updated content for .css files, it finds the matching <link> stylesheet and swaps it with a base64 data url version of the new css if none of the files can be hot-swapped (like if thereās no matching dom element, or itās a file type it doesnāt know about), it falls back to the classic window.location.reload() . so nothing breaks, it just tries the nice path first. the base64 css thing is a little cursed honestly. but it works and avoids needing to host the file anywhere. the browser just reads it inline. i might revisit this later if it causes issues with large stylesheets but for now itās fine. eslint + prettier added eslint and prettier to the Build package because the code was starting to look inconsistent and it was bothering me. set up a flat config with typescript-eslint, browser globals, the usual. named the prettier script make-pretty because i thought it was funny. and idk, itās how i do it ig prettier immediately reformatted a bunch of stuff in updato.ts . removed some unnecessary quote wrapping on \"Accept\" , collapsed a few multi-line expressions that didnāt need to be multi-line, cleaned up trailing commas. nothing behavioral, just formatting. also committed the lockfile. shouldāve done that earlier but here we are. todo progress checked off hot-swap support and the linting setup. removed the version bump script todo since that was already done in the last round. the list is getting shorter. slowly."}, {"post_id": 2606, "ts": "2026-06-05T06:58:58Z", "hours": 0.3131, "text": "the one big devlog so updato exists now. figured i should write down what actually happened before i forget why i made half these decisions. what even is this updato is a decentralized update system for browser apps. the whole idea is: you push code, your app knows thereās a new version, and it updates itself. no app store, no server infrastructure you have to maintain. just github and a cloudflare worker. itās three pieces: a github action that takes your build output and pushes it to a cdn branch on your repo. every version gets its own folder, plus thereās always a latest/ copy. it writes a manifest.json with metadata about whatās current. a cloudflare worker that acts as the middleman. your app asks it āhey is there an update?ā and it goes and reads your manifest off github, compares versions, and tells the client yes or no. stateless, basically free to run. a js client library that you drop into your app. it talks to the worker, downloads new files if thereās an update, caches them in localStorage, and reloads when youāre ready. two modes because i couldnāt pick one thereās commit mode and version mode. commit mode means every push is a new version and the āversionā is just the commit sha. version mode uses semver from your package.json. commit mode is nice for apps where you just want continuous deployment. version mode is for when you want to be more intentional about it. honestly i went back and forth on whether to support both. decided it was easy enough to keep and the action just reads a flag. the action lives in Action/ . typescript, compiled with ncc. it clones your cdn branch into a temp directory (or inits a fresh one if the branch doesnāt exist yet), copies your dist folder into latest/ and versions/{version}/ , writes the manifest, commits, and pushes. the commit messages are kinda nice actually, they show what version replaced what: deploy: abc123 (was def456) . one thing iām quietly proud of is that it handles the ābranch doesnāt exist yetā case gracefully. first run just works. the worker lives in Worker/ . pretty small. two endpoints: /check and /manifest . /check takes a repo and your current version, fetches the manifest from github, does the comparison, and returns whether thereās an update. wrote my own semver parser because i didnāt want to pull in a dependency for whatās basically three number comparisons. itās probably fine. it validates the repo format with a regex so you canāt pass in weird stuff. set up wrangler.toml with a production and staging env. the client lives in Build/ . this is the part that actually runs in peopleās apps. itās a class called Updato (creative naming, i know). you init it with your repo, mode, and current version. then you can check for updates, download them, and apply them. downloads get cached in localStorage with version tags so stale cache gets cleaned up automatically. built with vite, outputs both esm and umd so you can import it or just drop a script tag. tooling i added after wrote a bump-version.js script that bumps the version across all four package.jsons (root + the three workspace packages), commits, tags, and pushes. one command to do a release, basically. also a little print-cdn-commit.js that tells you what the latest cdn branch commit is, which is useful for debugging. thereās a TODO.md with a bunch of stuff i want to do eventually. hot-swap support, rate limiting in the worker, tests, linting, npm publishing. the usual āiāll get to itā list. current status it works. the action runs, the worker deploys, the client checks and downloads. trying to publish the action to the github marketplace but the name āUpdatoā is apparently reserved by a ghost account that doesnāt exist. so thatās cool. working on that."}]...
|
Title: Updato by @NellowTCS | Stardance
Devlogs:
Title: Updato by @NellowTCS | Stardance
Devlogs:
the one big devlog so updato exists now. figured i should write down what actually happened before i forget why i made half these decisions. what even is this updato is a decentralized update system for browser apps. the whole idea is: you push code, your app knows thereās a new version, and it updates itself. no app store, no server infrastructure you have to maintain. just github and a cloudflare worker. itās three pieces: a github action that takes your build output and pushes it to a cdn branch on your repo. every version gets its own folder, plus thereās always a latest/ copy. it writes a manifest.json with metadata about whatās current. a cloudflare worker that acts as the middleman. your app asks it āhey is there an update?ā and it goes and reads your manifest off github, compares versions, and tells the client yes or no. stateless, basically free to run. a js client library that you drop into your app. it talks to the worker, downloads new files if thereās an update, caches them in localStorage, and reloads when youāre ready. two modes because i couldnāt pick one thereās commit mode and version mode. commit mode means every push is a new version and the āversionā is just the commit sha. version mode uses semver from your package.json. commit mode is nice for apps where you just want continuous deployment. version mode is for when you want to be more intentional about it. honestly i went back and forth on whether to support both. decided it was easy enough to keep and the action just reads a flag. the action lives in Action/ . typescript, compiled with ncc. it clones your cdn branch into a temp directory (or inits a fresh one if the branch doesnāt exist yet), copies your dist folder into latest/ and versions/{version}/ , writes the manifest, commits, and pushes. the commit messages are kinda nice actually, they show what version replaced what: deploy: abc123 (was def456) . one thing iām quietly proud of is that it handles the ābranch doesnāt exist yetā case gracefully. first run just works. the worker lives in Worker/ . pretty small. two endpoints: /check and /manifest . /check takes a repo and your current version, fetches the manifest from github, does the comparison, and returns whether thereās an update. wrote my own semver parser because i didnāt want to pull in a dependency for whatās basically three number comparisons. itās probably fine. it validates the repo format with a regex so you canāt pass in weird stuff. set up wrangler.toml with a production and staging env. the client lives in Build/ . this is the part that actually runs in peopleās apps. itās a class called Updato (creative naming, i know). you init it with your repo, mode, and current version. then you can check for updates, download them, and apply them. downloads get cached in localStorage with version tags so stale cache gets cleaned up automatically. built with vite, outputs both esm and umd so you can import it or just drop a script tag. tooling i added after wrote a bump-version.js script that bumps the version across all four package.jsons (root + the three workspace packages), commits, tags, and pushes. one command to do a release, basically. also a little print-cdn-commit.js that tells you what the latest cdn branch commit is, which is useful for debugging. thereās a TODO.md with a bunch of stuff i want to do eventually. hot-swap support, rate limiting in the worker, tests, linting, npm publishing. the usual āiāll get to itā list. current status it works. the action runs, the worker deploys, the client checks and downloads. trying to publish the action to the github marketplace but the name āUpdatoā is apparently reserved by a ghost account that doesnāt exist. so thatās cool. working on that.
devlog: hot-swap and cleanup two things happened here and theyāre very different vibes. hot-swap so previously applyUpdate() was just⦠reload the page. which works, obviously, but itās not exactly elegant. if youāre updating a css file thereās no reason to nuke the entire page state. now it actually tries to be smart about it. when you call applyUpdate() , it looks at each fileās extension and attempts to swap it in-place: for .js files, it finds the matching <script> tag by src and replaces it with a new one containing the updated content for .css files, it finds the matching <link> stylesheet and swaps it with a base64 data url version of the new css if none of the files can be hot-swapped (like if thereās no matching dom element, or itās a file type it doesnāt know about), it falls back to the classic window.location.reload() . so nothing breaks, it just tries the nice path first. the base64 css thing is a little cursed honestly. but it works and avoids needing to host the file anywhere. the browser just reads it inline. i might revisit this later if it causes issues with large stylesheets but for now itās fine. eslint + prettier added eslint and prettier to the Build package because the code was starting to look inconsistent and it was bothering me. set up a flat config with typescript-eslint, browser globals, the usual. named the prettier script make-pretty because i thought it was funny. and idk, itās how i do it ig prettier immediately reformatted a bunch of stuff in updato.ts . removed some unnecessary quote wrapping on "Accept" , collapsed a few multi-line expressions that didnāt need to be multi-line, cleaned up trailing commas. nothing behavioral, just formatting. also committed the lockfile. shouldāve done that earlier but here we are. todo progress checked off hot-swap support and the linting setup. removed the version bump script todo since that was already done in the last round. the list is getting shorter. slowly.
devlog: the ājust rename itā update (and a bunch of other stuff) the name thing changed name: Updato to name: Updato Action in action.yml. thatās it. thatās the fix. spent hours filing a support ticket, got a polite ānoā from github, and the solution was adding one word. sometimes software development is humbling. hot-swap got its own file ripped the hot-swap logic out of updato.ts and gave it a proper home in hot-swap.ts . while i was in there i figured i might as well make it actually good. it now supports images too. png, jpg, gif, svg, webp, ico, bmp, avif. it finds matching <img> , <source> , and favicon <link> elements by basename and swaps their src/href to a base64 data uri. so if your update is just a new logo, no reload needed. also switched the element matching from substring ( src*="${file}" ) to basename comparison, which is way less fragile. before, a file called app.js couldāve accidentally matched webapp.js . now it actually compares the filename part properly. the css swap switched from btoa() to encodeURIComponent() which handles unicode better. small thing but the kind of thing that wouldāve been a weird bug later. everything returns a typed HotSwapResult now instead of just a boolean. so the caller knows what got swapped, what type it was, and which file it was for. manifest validation added a real validator in Worker/src/manifest.ts . before, the worker was just casting response.json() as Manifest and hoping for the best with a couple of if-checks. now thereās a validateManifest() function that checks every field properly and returns typed errors. each error tells you which field failed and why. this runs both when fetching fresh manifests from github and when reading cached ones from kv. if a cached manifest is corrupted it just falls through and re-fetches. rate limiting new file: Worker/src/rate-limit.ts . uses cloudflare kv to track requests per ip. 60 requests per 60 second window, which is generous enough for normal usage but should keep anyone from hammering it. uses CF-Connecting-IP for the real client ip, falls back to X-Forwarded-For . returns a proper 429 with a Retry-After header when you hit the limit. the kv entries auto-expire so they donāt pile up forever. I half wanted to make the 429 return silly messages, but I gotta be serious apparently sometimes :/ had to add a kv namespace binding in wrangler.toml for this. the worker was fully stateless before, now it has a little bit of state. felt like a big architectural decision for whatās basically a counter but whatever, itās the right call. kv caching for manifests while i was adding kv for rate limiting i figured i might as well use it for manifest caching too. previously every /check request was hitting githubās raw content cdn directly. now it caches the manifest in kv with a configurable ttl (defaults to 300 seconds). means fewer github api calls and faster responses for repeat checks. worker got lint + prettier too copied the eslint + prettier setup from Build into Worker. also added projectService and tsconfigRootDir to both eslint configs so typescript-eslint can actually find the tsconfigs. this was one of those āwhy is eslint yelling at meā rabbit holes. todo cleanup checked off rate limiting and manifest validation. removed the already-completed items that were cluttering the list. itās getting shorter.
devlog: the three commits i forgot to write about got in a flow state and forgot to devlog. hereās the catch-up. multi-branch support + notification ui the whole system was hardcoded to a branch called cdn . now you can pass a branch parameter everywhere. the worker accepts it as a query param (defaults to cdn ), the client sends it with check requests, and download urls use the right branch. manifest cache keys in kv include the branch name so different environments donāt collide. the idea is you could have cdn-staging and cdn-production in the same repo and point different app builds at different ones. added branch validation in the worker too since someoneās going to try passing something weird eventually. also built an UpdateNotification class in update-ui.ts . itās a drop-in banner component that handles the whole flow. you pick top or bottom, set it dismissable or not, and call notification.show(result) when thereās an update. clicking the button downloads and applies. if the download fails it resets. styling is all inline so thereās no css file to import. updated both examples to use it. the example-app.html went from a hand-rolled banner with window.__pendingUpdate to just notification.show(result) . much cleaner. module scripts + download metrics the action now scans html files for <script type="module"> tags and includes a modules array in the manifest. the client passes this through to hot-swap so module scripts get replaced with type="module" set on the new element. the regex for finding them is a little fragile but it works for standard vite/webpack output. also switched the action bundler from @vercel/ncc to esbuild . ncc was fine but esbuild is faster and i was already using it elsewhere. added an opt-in DownloadMetrics class that records timing data per file download (start, end, duration, size, url) in localStorage. pass it into the config and it starts tracking. you can export as json or clear it. useful for debugging slow updates but not the kind of thing you want on by default. tests + ci wrote jest tests for all three packages. action tests mock @actions/core , @actions/github , and @actions/exec . covers input parsing, repo context, package.json version reading, recursive file listing, module script detection, and clone url construction. had to export a bunch of internal functions to make them testable. client tests use jsdom with mocked fetch. covers hot-swap (regular scripts, module scripts, stylesheets, images, unknown types), the metrics class, and the main updato class (version tracking, cache management, update checking, downloads, event callbacks). worker tests cover validation helpers, the full fetch handler (missing params, invalid params, successful checks, unknown endpoints, OPTIONS, method rejection), manifest validation with every field failure case, and the rate limiter with fake timers. ci workflow at .github/workflows/ci.yml . runs on push and pr to main, matrix across node 20 and 22. lints, runs all tests, builds all three packages. todo status checked off: multi-branch, notification ui, module types, metrics, tests, ci. whatās left is docs, a demo, and release automation. the core functionality is done.
devlog: docs, workflows, and the finish line this is the āmake it realā commit. everything that was on the todo list under ābefore you can call this a real projectā happened in one sitting. docs site built a full docs site using docmd. lives in Docs/ with its own package. seven pages covering everything: home/landing page, quickstart guide, core concepts explainer, and individual reference pages for the client library, github action, worker, hot-swap internals, manifest format, and download metrics. the client library page has full config tables, event references, api docs for every public method, and the UpdateNotification component. the action page documents every input and shows what the cdn branch looks like after a deploy. the worker page covers both endpoints, version comparison logic, caching, and rate limiting. the hot-swap page explains how each asset type gets replaced: scripts via dom replacement with data-hot-file tagging for subsequent updates, css via CSSStyleSheet.replaceSync and adoptedStyleSheets (which is CSP-safe), and images via base64 data uris. used the āskyā theme with system dark mode toggle. search, sitemap plugin, code highlighting, all enabled. github pages deployment new workflow at .github/workflows/static.yml . builds the client library, builds the demo, builds the docs, then assembles them into a single pages-root/ directory. demo goes under /demo/ , docs go at the root. deploys to gh-pages with peaceiris/actions-gh-pages. npm publish workflow .github/workflows/release-npm.yml . triggers on github release publish or manual dispatch with a dry-run option. builds the client library, strips private , scripts , and devDependencies from package.json, copies in the readme and license, then publishes with --provenance . also removed "private": true from Build/package.json so npm will actually accept it. security audit workflow daily cron job plus on-push when lockfiles change. runs npm audit --audit-level=high across every package (root, Build, Worker, Action, Demo, Docs). all the audit steps have || true so the workflow reports issues without failing the build, which felt like the right balance for now. separate test workflow split the test job out of ci.yml into its own .github/workflows/test.yml . same matrix across node 20 and 22, runs jest in all three packages. keeps the ci workflow focused on lint and build. todo status checked off docs. whatās left: update the readme with better examples, maybe attach the worker to a custom domain, and publish to npm. the npm workflow is ready, just need to actually pull the trigger.
devlog: shipped updato is published. itās on npm. it has a version number and everything. the publish switched the build from vite to tsdown. vite was fine for dev but tsdown gives you dual esm/cjs output with proper .mjs/.cjs extensions and matching declaration files out of the box. the package exports map has real conditional exports now ā separate import and require entries with their own types. itās the kind of package.json that doesnāt make people file issues. scoped it to @nellowtcs/updato because apparently updato was too close to upath for npmās similarity check. it is not similar. at all. but scoped names are better practice anyway so whatever, npm wins this round. the release workflow strips private , scripts , and devDependencies from package.json before publish. originally did that with an inline node script, swapped it to a one-liner jq pipe because why run a whole runtime to delete three keys. 1.0.0 ā 1.0.1 released 1.0.0. immediately released 1.0.1 because of the name conflict. so it goes. the important thing is npm i @nellowtcs/updato works and the types resolve and the imports are correct. tested it, itās real. what actually shipped all of it: github action that publishes builds to a cdn branch cloudflare worker that serves version checks from KV client library on npm with hot-swap, two update modes, optional metrics live demo at nellowtcs.me/updato docs site at nellowtcs.me/updato/docs ci pipeline for all of it a readme that actually explains what this thing does whatās left one item on the todo list: custom domain for the worker. thatās a āmaybeā and itās been a āmaybeā for a while. it can stay a maybe. closing this started as a dumb idea about pushing updates without a server. it is now a real system with five directories and a package on npm and documentation with a sidebar. i donāt know when it became a real project but it did and now itās done. first release. final (nah, probably not) devlog.
Ships:
Updato is a decentralized update system for web apps. A GitHub Action publishes builds to a CDN branch, a Cloudflare Worker handles version checks, and a client library hot-swaps files in the browser with no reload. Itās on npm as @nellowtcs /updato. It works end to end. Push code, Action builds it, Worker picks it up, client swaps files live. No server, no database. Also thereās a live demo, a docs site, and a real npm package now. It became a real project somewhere along the way. CSS hot-swapping was a whole thing. Ended up using CSSStyleSheet.replaceSync with adoptedStyleSheets to make it work without flashing or breaking CSP. Also npm told me my package name was too similar to āupathā which is just not true but whatever, scoped it and moved on. The live demo ( https://nellowtcs.me/updato/ ) is a clock app that checks for updates from the Worker. You can also install it with āā npm i @nellowtcs/updato ā and the docs are at https://nellowtcs.me/updato/docs ....
|
1793505037.7576659
|
1793591437.7576659
|
|
39241
|
My own site! by @ArtemD | Stardance
|
ArtemD
|
2
|
3.0
|
0
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-27T23:23:49Z", "hours": 1.0, "multiplier": 2.35, "payout": 0, "blessing": "neutral", "text": "I improved my website but forgot to ship it.. I mean, later is better than never. This website includes interactive buttons, hyperlinks, a picture, and text with varying styles and fonts.", "repo": "https://github.com/avemro/my-personal-website", "demo": "https://avemro.github.io/my-personal-website/"}, {"ship_num": 2, "ts": "2026-07-26T02:00:17Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made my own, personal website. It started on 7.24.2026, when Jenin hosted a Hackatime + Personal Site Workshop. He walked me and everyone else in the workshop through the basics of making a website and we even built our own website! He told everyone to ship it that day but I decided not to, because I had an issue of the image not loading, and I just wanted to improve the website, to make it better. The next day I took all the knowledge I had and started building the website. I firstly changed the theme from orange and white to black and white to make the website look professional. Then, I fixed the issue of the image not loading by changing the scr method I used to src, which took me a long time to figure out, but was honestly a funny reason for the bug. Further, I extended the navigation bar, added a shadow to the image, changed the websiteās main font to Georgia, added an answer for the question āwhy should you join Hack Clubā, which I made, added a text box with a shadow to it, and a button which has a cool lift up animation when you hover over it, for which I have to credit another website called ā https://www.w3schools.com/css/ ā. Honestly, the most challenging part of building the whole thing was the button. I did use a website I already gave credit to for making the button, but it wasnāt as simple as just pasting in code. After I, again, pasted the code, I tried to load the button to my main html file, but it just would work. I tried using a button method and putting a class=ābuttonā into it, but that did not seem to work. I then figured out to used div (by looking at how I constructed the navigation bar), but the button came out too wide. I tried to fix that by changing the width in the css file I believe, but then it got stuck to the left corner. And after many attempts of getting that button working, I finally gave up and just searched my problem online. And the solution was just writing 3 lines of code, which was about 10 times less than the lines of code I wrote trying to fix the issue myself. Another challenge I faced is making the shadows for the image and text box. Long story short, I basically did the same thing as with the button (try to solve the problem -> break my brain -> give up -> search up the solution -> be shocked of writing just a couple of lines of code), I additionally want to give credit to the same website I mentioned earlier for providing the methods needed to make the shadow. Interestingly, after I fixed the two issues, I began being able to fix other problems I had on the website myself, which made me just a little bit proud of myself. Speaking of being proud, I feel very, I mean extremely proud when I open the website and look at it. I just canāt believe I made that. In addition to feeling proud, I should mention that the hyperlinks named āCallā, āTextā, and āMessageā Hack Club do not work on desktops. I made those buttons throughout the workshop with Jenin, and he said that these buttons will function only on phones.", "repo": "https://github.com/avemro/my-personal-website", "demo": "https://avemro.github.io/my-personal-website/"}]...
|
[{"post_id": 41716, "ts": "202 [{"post_id": 41716, "ts": "2026-08-06T03:02:00Z", "hours": 1.4333, "text": "I fixed the website to follow all of the criteria. Here is specifically what Iāve implemented since the last devlog: All of the buttons and images (except links) now lift up when you hover over them using the scale() function Made the āJoin Hack Clubā button move and rotate slightly when you hover over it, which looks very interesting honestly Changed the āJoin Hack Clubā buttonās settings to have sharp edges and a grey shadow, which is also sharp Created a dark-brown shadow for the āEXPERIENCEā heading Removed the āCall Hack Clubā, āText Hack Clubā and āMessage Hack Clubā buttons and implemented a working āEmail Hack Clubās Supportā button (I found the email on the official Hack Club website) Here is what Iām planning to do/have done/have in mind for the next version of my website: Build the āAbout meā, āHack Clubā and some other buttons which redirect to other pages. The āHack Clubā buttons will have the āJoin Stardanceā, āPrograms of Hack Clubā, āJoin Stardanceā, āHack Clubās clubsā and āEmail Hack Clubās supportā hyperlinks inside that page. I am already drawing a blueprint for the pages and how will they look like. Craft a settings menu with options like āMusicā (On/Off), āDark/Whiteā websiteās theme and maybe other options that will come across my mind Notes: I am very happy about my website. I tried to be creative, and Iām sure I was this time. Additionally, I will look for errors and fix any that come on my path."}, {"post_id": 34920, "ts": "2026-07-26T00:43:58Z", "hours": 1.615, "text": "I improved my website by a lot. I changed the theme of the website from orange-yellow to black-white I made four sections in the navigation bar I added more hyperlinks I made a shadow for the F1 Ferrari car, and changed the image itself (The reason it would not load last time is because I used the scr function instead of the correct src one, and scr did not exist) I changed the description of the image to a more professional one, changing itself and its style I added a header and text which explains why should you join Hack Club, and used a text box, a new concept I made a āJoin Hack Clubā button that looks cool when you hover over it. Credits to https://www.w3schools.com/css/ I literally love my website now. It looks modern, professional, neat, well structured, and many more adjectives.."}, {"post_id": 34216, "ts": "2026-07-24T18:49:42Z", "hours": 0.7319, "text": "I made a very simple website with the help Jenin - in the āHackatime + Personal Siteā workshop. But the image I have doesnāt seem to load, and I overall think the website is too raw, so Iāll keep working on it. Hereās what I have on the website right now: Navigation bar Title Paragraphs Clickable hyperlinks Image Description for the image"}]...
|
Title: My own site! by @ArtemD | Stardance
Devlog Title: My own site! by @ArtemD | Stardance
Devlogs:
I made a very simple website with the help Jenin - in the āHackatime + Personal Siteā workshop. But the image I have doesnāt seem to load, and I overall think the website is too raw, so Iāll keep working on it. Hereās what I have on the website right now: Navigation bar Title Paragraphs Clickable hyperlinks Image Description for the image
I improved my website by a lot. I changed the theme of the website from orange-yellow to black-white I made four sections in the navigation bar I added more hyperlinks I made a shadow for the F1 Ferrari car, and changed the image itself (The reason it would not load last time is because I used the scr function instead of the correct src one, and scr did not exist) I changed the description of the image to a more professional one, changing itself and its style I added a header and text which explains why should you join Hack Club, and used a text box, a new concept I made a āJoin Hack Clubā button that looks cool when you hover over it. Credits to https://www.w3schools.com/css/ I literally love my website now. It looks modern, professional, neat, well structured, and many more adjectives..
I fixed the website to follow all of the criteria. Here is specifically what Iāve implemented since the last devlog: All of the buttons and images (except links) now lift up when you hover over them using the scale() function Made the āJoin Hack Clubā button move and rotate slightly when you hover over it, which looks very interesting honestly Changed the āJoin Hack Clubā buttonās settings to have sharp edges and a grey shadow, which is also sharp Created a dark-brown shadow for the āEXPERIENCEā heading Removed the āCall Hack Clubā, āText Hack Clubā and āMessage Hack Clubā buttons and implemented a working āEmail Hack Clubās Supportā button (I found the email on the official Hack Club website) Here is what Iām planning to do/have done/have in mind for the next version of my website: Build the āAbout meā, āHack Clubā and some other buttons which redirect to other pages. The āHack Clubā buttons will have the āJoin Stardanceā, āPrograms of Hack Clubā, āJoin Stardanceā, āHack Clubās clubsā and āEmail Hack Clubās supportā hyperlinks inside that page. I am already drawing a blueprint for the pages and how will they look like. Craft a settings menu with options like āMusicā (On/Off), āDark/Whiteā websiteās theme and maybe other options that will come across my mind Notes: I am very happy about my website. I tried to be creative, and Iām sure I was this time. Additionally, I will look for errors and fix any that come on my path.
Ships:
I made my own, personal website. It started on 7.24.2026, when Jenin hosted a Hackatime + Personal Site Workshop. He walked me and everyone else in the workshop through the basics of making a website and we even built our own website! He told everyone to ship it that day but I decided not to, because I had an issue of the image not loading, and I just wanted to improve the website, to make it better. The next day I took all the knowledge I had and started building the website. I firstly changed the theme from orange and white to black and white to make the website look professional. Then, I fixed the issue of the image not loading by changing the scr method I used to src, which took me a long time to figure out, but was honestly a funny reason for the bug. Further, I extended the navigation bar, added a shadow to the image, changed the websiteās main font to Georgia, added an answer for the question āwhy should you join Hack Clubā, which I made, added a text box with a shadow to it, and a button which has a cool lift up animation when you hover over it, for which I have to credit another website called ā https://www.w3schools.com/css/ ā. Honestly, the most challenging part of building the whole thing was the button. I did use a website I already gave credit to for making the button, but it wasnāt as simple as just pasting in code. After I, again, pasted the code, I tried to load the button to my main html file, but it just would work. I tried using a button method and putting a class=ābuttonā into it, but that did not seem to work. I then figured out to used div (by looking at how I constructed the navigation bar), but the button came out too wide. I tried to fix that by changing the width in the css file I believe, but then it got stuck to the left corner. And after many attempts of getting that button working, I finally gave up and just searched my problem online. And the solution was just writing 3 lines of code, which was about 10 times less than the lines of code I wrote trying to fix the issue myself. Another challenge I faced is making the shadows for the image and text box. Long story short, I basically did the same thing as with the button (try to solve the problem -> break my brain -> give up -> search up the solution -> be shocked of writing just a couple of lines of code), I additionally want to give credit to the same website I mentioned earlier for providing the methods needed to make the shadow. Interestingly, after I fixed the two issues, I began being able to fix other problems I had on the website myself, which made me just a little bit proud of myself. Speaking of being proud, I feel very, I mean extremely proud when I open the website and look at it. I just canāt believe I made that. In addition to feeling proud, I should mention that the hyperlinks named āCallā, āTextā, and āMessageā Hack Club do not work on desktops. I made those buttons throughout the workshop with Jenin, and he said that these buttons will function only on phones.
I improved my website but forgot to ship it.. I mean, later is better than never. This website includes interactive buttons, hyperlinks, a picture, and text with varying styles and fonts....
|
1793505026.8341112
|
1793591426.8341112
|
|
38297
|
pear-agent by @aomona | Stardance
|
aomona
|
1
|
12.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-22T12:48:44Z", "hours": 12.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I built PEAR Agent, a framework for creating agents that plan tasks, wait for human approval, execute them, and replan when something changes. The most challenging part was designing a system that could support different use cases while keeping the workflow predictable and safe. I am proud that the original idea has become a working, documented framework that is now ready for beta testing. To test it, visit the GitHub repository, follow the setup instructions in the documentation, and run one of the example applications. It is still in beta, so there may be some small bugs or rough edges.", "repo": "https://github.com/aomona/pear-agent", "demo": "https://pear-agent.aomona.me/"}]...
|
[{"post_id": 32935, "ts": "202 [{"post_id": 32935, "ts": "2026-07-22T12:37:31Z", "hours": 12.0619, "text": "Most of the features I wanted for PEAR Agent are now complete. It is ready for a beta release, and I have also finished the main documentation. From here, I will focus on fixing small bugs and improving the overall polish."}]...
|
Title: pear-agent by @aomona | Stardance
Devlogs: Title: pear-agent by @aomona | Stardance
Devlogs:
Most of the features I wanted for PEAR Agent are now complete. It is ready for a beta release, and I have also finished the main documentation. From here, I will focus on fixing small bugs and improving the overall polish.
Ships:
I built PEAR Agent, a framework for creating agents that plan tasks, wait for human approval, execute them, and replan when something changes. The most challenging part was designing a system that could support different use cases while keeping the workflow predictable and safe. I am proud that the original idea has become a working, documented framework that is now ready for beta testing. To test it, visit the GitHub repository, follow the setup instructions in the documentation, and run one of the example applications. It is still in beta, so there may be some small bugs or rough edges....
|
1793505017.0492835
|
1793591417.0492835
|
|
5038
|
AI Slack bot by @YoussefTech | Stardance
|
YoussefTech
|
1
|
1.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-03T15:16:02Z", "hours": 1.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made an AI assistant slack bot that you can use for free, it uses the HackClub AI API. To test it out, go to any channel on the HackClub slack workspace and type /asb-ask to prompt the AI, it will take a sec to respond, just give it some time š. Available commands: /asb-ping - Check if the bot is working and the latency /asb-joke - Fetch a random joke from the Official Joke API /asb-calc [expression] - Calculate a mathematical expression /asb-ask [question] - Ask the AI a question /asb-whoami - Info about the bot and its developer /asb-quote - Random quote", "repo": "https://github.com/yousseftechdev/AISlackBot", "demo": "https://hackclub.slack.com/archives/C0B8W2LQYD8/p1780861946621539"}]...
|
[{"post_id": 1481, "ts": "2026 [{"post_id": 1481, "ts": "2026-06-03T15:06:54Z", "hours": 0.3664, "text": "Added /asb-whoami command that prints info about the bot and its developer Added /asb-quote command to print a random quote Updated README.md"}, {"post_id": 1395, "ts": "2026-06-03T12:32:18Z", "hours": 0.3936, "text": "Well adding the AI part was easy, I used the HackClub AI API, I picked a free model because I donāt want every user of the bot to input their own API key, though that might be a cool idea for later updates, I placed a system instruction in the beginning of the prompt explaining to the AI model that itās a slack bot so it doesnāt try to use tables or fancy formatting: SYSTEM INSTRUCTION: You are a slack bot, so follow slack formatting rules and markdown conventions when responding, no tables. The bot is now up and running and Iām trying to find extra features to add to increase the time on this project"}, {"post_id": 1382, "ts": "2026-06-03T11:44:19Z", "hours": 0.5392, "text": "Just finished the guide for the āMake a Slack Botā mission, I liked it, but i feel like it was too easy, the guide said 1.5h but it only took me 20 minutes for the code and 10 minutes to make it live 24/7 on the Nest container"}]...
|
Title: AI Slack bot by @YoussefTech | Stardance
D Title: AI Slack bot by @YoussefTech | Stardance
Devlogs:
Just finished the guide for the āMake a Slack Botā mission, I liked it, but i feel like it was too easy, the guide said 1.5h but it only took me 20 minutes for the code and 10 minutes to make it live 24/7 on the Nest container
Well adding the AI part was easy, I used the HackClub AI API, I picked a free model because I donāt want every user of the bot to input their own API key, though that might be a cool idea for later updates, I placed a system instruction in the beginning of the prompt explaining to the AI model that itās a slack bot so it doesnāt try to use tables or fancy formatting: SYSTEM INSTRUCTION: You are a slack bot, so follow slack formatting rules and markdown conventions when responding, no tables. The bot is now up and running and Iām trying to find extra features to add to increase the time on this project
Added /asb-whoami command that prints info about the bot and its developer Added /asb-quote command to print a random quote Updated README.md
Ships:
I made an AI assistant slack bot that you can use for free, it uses the HackClub AI API. To test it out, go to any channel on the HackClub slack workspace and type /asb-ask to prompt the AI, it will take a sec to respond, just give it some time š. Available commands: /asb-ping - Check if the bot is working and the latency /asb-joke - Fetch a random joke from the Official Joke API /asb-calc [expression] - Calculate a mathematical expression /asb-ask [question] - Ask the AI a question /asb-whoami - Info about the bot and its developer /asb-quote - Random quote...
|
1793505012.1705194
|
1793591412.1705194
|
|
19371
|
Planetarium by @The_Craw | Stardance
|
The_Craw
|
1
|
2.44
|
29
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-16T10:24:58Z", "hours": 2.0, "multiplier": 12.05, "payout": 29, "blessing": "neutral", "text": "A custom-made leaderboard, made with my own unofficial stardance API system. Tracks projects over time, for followers, time used, and devlogs. This project is confirmed to have been used by the Fraud Squad to catch users who have faked their time.", "repo": "https://github.com/Jonah-Crawford/Planetarium", "demo": "https://planetarium.ultimatecraw.xyz/"}]...
|
[{"post_id": 16815, "ts": "202 [{"post_id": 16815, "ts": "2026-06-27T09:33:43Z", "hours": 0.4414, "text": "Simple additions like adding a āsuper starā column to track exceptional projects have been added. The webpage is still quite slow though š
"}, {"post_id": 9866, "ts": "2026-06-16T10:12:57Z", "hours": 1.335, "text": "Final devlog, shipping as the basic leaderboard is done!"}, {"post_id": 9828, "ts": "2026-06-16T08:42:16Z", "hours": 0.6761, "text": "Iām not going to lie, ChatGPT did the CSS because I donāt know how to. This is why it looks vibecoded, which makes it stinky. I apologise."}, {"post_id": 9495, "ts": "2026-06-15T20:56:36Z", "hours": 0.3767, "text": "Did someone say new leaderboard? Thatās right, Crawās Stardance Leaderboard now works with Crawās Stardance API! This leaderboard updates every 6 hours, rather than every week, and can show history data! Want to see the fastest growing projects? Easy peasy with Planetarium."}]...
|
Title: Planetarium by @The_Craw | Stardance
Devlo Title: Planetarium by @The_Craw | Stardance
Devlogs:
Did someone say new leaderboard? Thatās right, Crawās Stardance Leaderboard now works with Crawās Stardance API! This leaderboard updates every 6 hours, rather than every week, and can show history data! Want to see the fastest growing projects? Easy peasy with Planetarium.
Iām not going to lie, ChatGPT did the CSS because I donāt know how to. This is why it looks vibecoded, which makes it stinky. I apologise.
Final devlog, shipping as the basic leaderboard is done!
Simple additions like adding a āsuper starā column to track exceptional projects have been added. The webpage is still quite slow though š
Ships:
A custom-made leaderboard, made with my own unofficial stardance API system. Tracks projects over time, for followers, time used, and devlogs. This project is confirmed to have been used by the Fraud Squad to catch users who have faked their time....
|
1793505006.3930395
|
1793591406.3930395
|
|
36016
|
My very own WebOS by @RajanKC | Stardance
|
RajanKC
|
2
|
17.0
|
72
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-07T17:15:25Z", "hours": 14.0, "multiplier": 5.0, "payout": 72, "blessing": "neutral", "text": "OS-Web is a lightweight, open-source web operating system built with HTML, CSS, and JavaScript. It brings a desktop-style experience to your browser with apps, a taskbar, and a simple interface that you can explore, customize, and improve.", "repo": "https://github.com/RajanKCKC/OSWeb", "demo": "https://rajankckc.github.io/OSWeb/"}, {"ship_num": 2, "ts": "2026-07-20T16:04:47Z", "hours": 3.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Shipped WebOS. Built a basic browser desktop clone with HTML, CSS, and JS. It has a taskbar, a welcome window, windows you can drag around with working close buttons, and a simple notes app that opens when clicked.", "repo": "https://github.com/RajanKCKC/OSWeb", "demo": "https://rajankckc.github.io/OSWeb/"}]...
|
[{"post_id": 42760, "ts": "202 [{"post_id": 42760, "ts": "2026-08-07T17:14:29Z", "hours": 1.3003, "text": "Add Password Strength Meter app with UI, functionality, and integrate into main interface"}, {"post_id": 42077, "ts": "2026-08-06T17:12:25Z", "hours": 1.4725, "text": "Add Github User Finder app with UI, functionality, and integrate into main interface"}, {"post_id": 41382, "ts": "2026-08-05T15:43:36Z", "hours": 0.6836, "text": "Add QR Code Generator app with UI, functionality, and integrate into main interface"}, {"post_id": 40757, "ts": "2026-08-04T14:28:26Z", "hours": 1.1311, "text": "Add Tic Tac Toe app with UI, functionality, and integrate into main interface"}, {"post_id": 40211, "ts": "2026-08-03T16:49:51Z", "hours": 1.1114, "text": "Add ToDo app with UI, functionality, and integrate into main interface"}, {"post_id": 39521, "ts": "2026-08-02T15:07:58Z", "hours": 0.6947, "text": "Add Quiz app with UI, functionality, and integrate into main interface"}, {"post_id": 38986, "ts": "2026-08-01T16:44:01Z", "hours": 0.6003, "text": "Add Map app with UI, functionality, and integrate into main interface"}, {"post_id": 38296, "ts": "2026-07-31T16:45:57Z", "hours": 0.5333, "text": "Add Notes app with UI and integrate into main interface"}, {"post_id": 37658, "ts": "2026-07-30T15:28:48Z", "hours": 1.0669, "text": "Add Calendar app with UI, functionality, and integrate into main interface"}, {"post_id": 37116, "ts": "2026-07-29T16:30:18Z", "hours": 1.4522, "text": "Add Calculator, Paint app, and Welcome page with associated styles and functionality"}, {"post_id": 36450, "ts": "2026-07-28T16:05:34Z", "hours": 0.7019, "text": "Add Paint app with UI elements and window controls"}, {"post_id": 35564, "ts": "2026-07-27T02:56:29Z", "hours": 0.4669, "text": "Add welcome page and style adjustments for improved layout"}, {"post_id": 35318, "ts": "2026-07-26T17:14:11Z", "hours": 0.4792, "text": "Add Google app functionality with UI elements and window controls"}, {"post_id": 34668, "ts": "2026-07-25T16:03:57Z", "hours": 0.5169, "text": "Fix minimize button IDs for Notes and Solitaire, and implement taskbar item management"}, {"post_id": 34124, "ts": "2026-07-24T16:48:43Z", "hours": 0.3206, "text": "Add minimize functionality to Notes, Minecraft, and Solitaire windows"}, {"post_id": 33446, "ts": "2026-07-23T12:27:23Z", "hours": 0.9111, "text": "Implement maximize functionality for app windows and update styles"}, {"post_id": 33062, "ts": "2026-07-22T17:11:41Z", "hours": 0.3669, "text": "Add Solitaire app functionality with UI elements and window controls"}, {"post_id": 32436, "ts": "2026-07-21T16:45:42Z", "hours": 0.5339, "text": "Add Minecraft app icon and window functionality with styles"}, {"post_id": 31856, "ts": "2026-07-20T15:59:49Z", "hours": 0.7336, "text": "Update README, enhance UI, and improve functionality"}, {"post_id": 31326, "ts": "2026-07-19T16:58:18Z", "hours": 1.2972, "text": "Add Notes app functionality with UI elements and styles"}, {"post_id": 30614, "ts": "2026-07-18T10:26:52Z", "hours": 0.7039, "text": "Added Draggable windows and Window Control buttons"}, {"post_id": 30144, "ts": "2026-07-17T14:14:23Z", "hours": 0.3836, "text": "Added Task bar and window"}, {"post_id": 29931, "ts": "2026-07-17T03:17:13Z", "hours": 0.3103, "text": "Added Welcome screen"}]...
|
Title: My very own WebOS by @RajanKC | Stardance
Title: My very own WebOS by @RajanKC | Stardance
Devlogs:
Added Welcome screen
Added Task bar and window
Added Draggable windows and Window Control buttons
Add Notes app functionality with UI elements and styles
Update README, enhance UI, and improve functionality
Add Minecraft app icon and window functionality with styles
Add Solitaire app functionality with UI elements and window controls
Implement maximize functionality for app windows and update styles
Add minimize functionality to Notes, Minecraft, and Solitaire windows
Fix minimize button IDs for Notes and Solitaire, and implement taskbar item management
Add Google app functionality with UI elements and window controls
Add welcome page and style adjustments for improved layout
Add Paint app with UI elements and window controls
Add Calculator, Paint app, and Welcome page with associated styles and functionality
Add Calendar app with UI, functionality, and integrate into main interface
Add Notes app with UI and integrate into main interface
Add Map app with UI, functionality, and integrate into main interface
Add Quiz app with UI, functionality, and integrate into main interface
Add ToDo app with UI, functionality, and integrate into main interface
Add Tic Tac Toe app with UI, functionality, and integrate into main interface
Add QR Code Generator app with UI, functionality, and integrate into main interface
Add Github User Finder app with UI, functionality, and integrate into main interface
Add Password Strength Meter app with UI, functionality, and integrate into main interface
Ships:
Shipped WebOS. Built a basic browser desktop clone with HTML, CSS, and JS. It has a taskbar, a welcome window, windows you can drag around with working close buttons, and a simple notes app that opens when clicked.
OS-Web is a lightweight, open-source web operating system built with HTML, CSS, and JavaScript. It brings a desktop-style experience to your browser with apps, a taskbar, and a simple interface that you can explore, customize, and improve....
|
1793505002.1735518
|
1793591402.1735518
|
|
9826
|
Anything AI by @THEbluefirestudios | Stardance
|
THEbluefirestudios
|
1
|
5.0
|
46
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-11T13:39:14Z", "hours": 5.0, "multiplier": 9.67, "payout": 46, "blessing": "neutral", "text": "An LLM wrapper that uses multiple open source AIs to make something that is as good as big AI like Claude, and ChatGPT", "repo": "https://github.com/THEbluefirestudios/anything-ai", "demo": "https://github.com/THEbluefirestudios/anything-ai/releases"}]...
|
[{"post_id": 6166, "ts": "2026 [{"post_id": 6166, "ts": "2026-06-10T11:30:10Z", "hours": 1.5317, "text": "Damn manā¦. so much for adding chat history and long term memoryā¦. Today I spent 1 and a half hours adding them, the memory is stored in Anything AI\\memory and chats are stored in Anything AI\\chats . I also switched the sorter AI to deepseek-ai/DeepSeek-R1-Distill-Llama-70B coz llama was hallucinating a LOT, ill be releasing another beta soonā¦.."}, {"post_id": 5522, "ts": "2026-06-09T10:24:06Z", "hours": 1.0064, "text": "Iām regretting making a TUI instead of a GUI. I made it so because i wanted to save time and focus on the important stuff, and cause i was lazy, but it turned out to be a mistake. Today I spent nearly an hour trying to fix terminal formatting issues like shown in the attached screenshot (sorry for low resolution) , it got so bad that I just ended making my own input() function instead. Truly an experience, anyways, Anything has entered beta! The full proper official ship will come soon!"}, {"post_id": 4827, "ts": "2026-06-08T10:42:23Z", "hours": 0.6256, "text": "Now I have created the logo for Anything AI, so it will be definitely out soon! I hope this project gets high ratings! Lapse: https://lapse.hackclub.com/timelapse/kOucepr-Hpub"}, {"post_id": 4808, "ts": "2026-06-08T09:52:08Z", "hours": 0.4364, "text": "YESS, attach file works! It currently supports .txt, .csv, .docx, .pptx, .xlsx and code files like .py, .kt, .java, .cpp and, obviously image files, the ones supported by PIL :). Anything AI will be finished soon!"}, {"post_id": 4792, "ts": "2026-06-08T09:00:53Z", "hours": 0.6258, "text": "Today Iām working on adding more modalities to my AI, more specifically, giving it the ability to read text, documents and code files alongside the already implemented image file. To do this Iām migrating from pick_image_file() to just pick_file() As of now, the pick_file() function is done and i need to add functions for parsing the returned filepath to data the AI can read. I also ran out of free credits on Hugging Face so i created an extra account. :("}, {"post_id": 4139, "ts": "2026-06-07T10:35:45Z", "hours": 0.3117, "text": "OK, so terminal commands work! I also fixed the jank bug that caused issues with displaying text after addingf an image to a prompt. Things seem to be going well! Iām gonna make myself a bowl of maggi now >. <"}, {"post_id": 4122, "ts": "2026-06-07T09:55:20Z", "hours": 0.3342, "text": "Ok so, I know this is a project I started before Stardance on May 25 2026 and have worked for hours on this, and its almost ship ready, Iāve added everything I want like multimodal input, file generation, etc. As of now, Iām giving it the ability to run terminal commands and do some bugfixing before shipping it as an .exe"}]...
|
Title: Anything AI by @THEbluefirestudios | Starda Title: Anything AI by @THEbluefirestudios | Stardance
Devlogs:
Ok so, I know this is a project I started before Stardance on May 25 2026 and have worked for hours on this, and its almost ship ready, Iāve added everything I want like multimodal input, file generation, etc. As of now, Iām giving it the ability to run terminal commands and do some bugfixing before shipping it as an .exe
OK, so terminal commands work! I also fixed the jank bug that caused issues with displaying text after addingf an image to a prompt. Things seem to be going well! Iām gonna make myself a bowl of maggi now >. <
Today Iām working on adding more modalities to my AI, more specifically, giving it the ability to read text, documents and code files alongside the already implemented image file. To do this Iām migrating from pick_image_file() to just pick_file() As of now, the pick_file() function is done and i need to add functions for parsing the returned filepath to data the AI can read. I also ran out of free credits on Hugging Face so i created an extra account. :(
YESS, attach file works! It currently supports .txt, .csv, .docx, .pptx, .xlsx and code files like .py, .kt, .java, .cpp and, obviously image files, the ones supported by PIL :). Anything AI will be finished soon!
Now I have created the logo for Anything AI, so it will be definitely out soon! I hope this project gets high ratings! Lapse: https://lapse.hackclub.com/timelapse/kOucepr-Hpub
Iām regretting making a TUI instead of a GUI. I made it so because i wanted to save time and focus on the important stuff, and cause i was lazy, but it turned out to be a mistake. Today I spent nearly an hour trying to fix terminal formatting issues like shown in the attached screenshot (sorry for low resolution) , it got so bad that I just ended making my own input() function instead. Truly an experience, anyways, Anything has entered beta! The full proper official ship will come soon!
Damn manā¦. so much for adding chat history and long term memoryā¦. Today I spent 1 and a half hours adding them, the memory is stored in Anything AI\memory and chats are stored in Anything AI\chats . I also switched the sorter AI to deepseek-ai/DeepSeek-R1-Distill-Llama-70B coz llama was hallucinating a LOT, ill be releasing another beta soonā¦..
Ships:
An LLM wrapper that uses multiple open source AIs to make something that is as good as big AI like Claude, and ChatGPT...
|
1793504991.4957092
|
1793591391.4957092
|
|
31183
|
Wrapped by @advayc | Stardance
|
advayc
|
1
|
2.81
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-08T22:23:13Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "i built spotify wrapped but for your imsg data. by running a curl command in your terminal, itll open a website for you to view your imessage data from either the past year or in total. the most challenging part was honestly uiux of the website, as well as making sure it works properly without golang, installed. i think im post proud of the system to scrape the data from the files on your mac computer. to test it out have to be on macos and might need golang installed.", "repo": "https://github.com/advayc/wrapped", "demo": "https://github.com/advayc/wrapped/releases/tag/v1.0.0"}]...
|
[{"post_id": 35650, "ts": "202 [{"post_id": 35650, "ts": "2026-07-27T07:10:44Z", "hours": 0.8139, "text": "make executable"}, {"post_id": 25007, "ts": "2026-07-08T22:20:23Z", "hours": 1.0931, "text": "UIUX polish and rewrite the readme, git commits are lowk all over the place though"}, {"post_id": 23332, "ts": "2026-07-06T06:53:20Z", "hours": 0.4006, "text": "bug fixes, running opencode agent to fix an issue with msg data scraping (getting the wrong number)"}, {"post_id": 23325, "ts": "2026-07-06T06:26:27Z", "hours": 1.0044, "text": "built it out fully inspired off a seperate script i saw online in python. but i figured it would be cool if i could build it out in go, how it works: run one curl command in your terminal it uses go run under the hood, so nothing is saved the script reads your ~/Library/Messages/chat.db + Address Book contacts to resolve names pick a timeframe via then it analyzes everything, the total messages, reply times, streaks, double texts, etc builds a self-contained HTML slideshow using scraped data"}]...
|
Title: Wrapped by @advayc | Stardance
Devlogs:
bu Title: Wrapped by @advayc | Stardance
Devlogs:
built it out fully inspired off a seperate script i saw online in python. but i figured it would be cool if i could build it out in go, how it works: run one curl command in your terminal it uses go run under the hood, so nothing is saved the script reads your ~/Library/Messages/chat.db + Address Book contacts to resolve names pick a timeframe via then it analyzes everything, the total messages, reply times, streaks, double texts, etc builds a self-contained HTML slideshow using scraped data
bug fixes, running opencode agent to fix an issue with msg data scraping (getting the wrong number)
UIUX polish and rewrite the readme, git commits are lowk all over the place though
make executable
Ships:
i built spotify wrapped but for your imsg data. by running a curl command in your terminal, itll open a website for you to view your imessage data from either the past year or in total. the most challenging part was honestly uiux of the website, as well as making sure it works properly without golang, installed. i think im post proud of the system to scrape the data from the files on your mac computer. to test it out have to be on macos and might need golang installed....
|
1793504982.8326254
|
1793591382.8326254
|
|
57434
|
My first slack bot! by @skyskysun | Stardance
|
skyskysun
|
1
|
0.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-06T01:35:30Z", "hours": 0.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made first slack bot. Pretty easy, as i have not added any fun commands and just sticked with the basic bots, as I am working on the hackpad most of the time and got no time for the slack bot.", "repo": "https://github.com/RealSkyskysun/skybot1slack", "demo": "https://app.slack.com/client/E09V59WQY1E/C0P5NE354"}]...
|
[{"post_id": 61364, "ts": "202 [{"post_id": 61364, "ts": "2026-09-04T07:33:07Z", "hours": 0.3117, "text": "Setting up the basic slackbot, just started stardance, hope everything goes well"}]...
|
Title: My first slack bot! by @skyskysun | Stardan Title: My first slack bot! by @skyskysun | Stardance
Devlogs:
Setting up the basic slackbot, just started stardance, hope everything goes well
Ships:
I made first slack bot. Pretty easy, as i have not added any fun commands and just sticked with the basic bots, as I am working on the hackpad most of the time and got no time for the slack bot....
|
1793504977.5122292
|
1793591377.5122292
|
|
31577
|
PickleWatch by @karthikeya | Stardance
|
karthikeya
|
3
|
34.53
|
308
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-30T23:17:55Z", "hours": 0.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I have improved the sound detection system and revamped the whole UI. Please take a look and try out the app yourself. Whatās New? Bug Fixes, More advanced sound detection eliminating background noise and focusing more on upbeats that sound like racket hits. Working towards integrating it with the Apple Watch.", "repo": "https://github.com/Coder-13-11/PickleWatch", "demo": "https://pickle-watch.vercel.app"}, {"ship_num": 2, "ts": "2026-09-10T03:58:34Z", "hours": 27.0, "multiplier": 16.51, "payout": 246, "blessing": "neutral", "text": "I updated it to now RallyLab. I did this because initially i had an app to find open pickleball courts near me in Tampa. It worked, but I realized you really only use a court finder once. You check it, drive there, and thatās it. So Iāve been rebuilding it into RallyLab. The idea is simple: put your phone on the bench and let it listen to your match. Instead of recording the match, the new app -RallyLab- just detects racket hits and the words you say like serves etc to detect who got the point. The audio gets processed 128 samples at a time and immediately overwritten, so there is no recording or audio file. I am going to spend more time on this and make it a full on product people can use.", "repo": "https://github.com/Coder-13-11/PickleWatch", "demo": "https://pickle-watch.vercel.app"}, {"ship_num": 3, "ts": "2026-07-10T15:13:48Z", "hours": 7.0, "multiplier": 8.97, "payout": 62, "blessing": "neutral", "text": "PickleWatch, an App for Pickleball Athletes So basically the problem is thereās like 8 pickleball courts around Tampa and you never know which ones are actually free or if theyāre packed until you drive there and itās a whole thing. So I made an app that tells you before you leave your house. Itās a website (kinda like an app, you can add it to your home screen) that shows all 8 courts and how busy each one probably is right now. Itās not just guessing randomly either ā I made it learn the normal pattern for each court (like Northlakes gets crazy busy around 6pm on weekdays but High 5 is more of a lunchtime thing) and then it mixes that with actual people checking in. Like if you show up and tap āIām hereā and say how busy it is, that updates everyoneās app in real time for like 90 minutes and then it fades away. The real time part is honestly the coolest part, I used this thing called Supabase which is like a free database that can push updates instantly. I tested it by opening two browser windows side by side and checking in on one and watching it show up on the other one immediately, no refreshing or anything. Other stuff it does: Rally button ā pick a time and it makes a message you can send to your group chat on WhatsApp asking who wants to play Polls ā like if people canāt decide where to play you make a poll and everyone votes and you can see it update live Friends ā add your friends and itāll show you when they check in somewhere, plus little avatar bubbles showing whoās at a court right now No login or password or anything, you just type your name once and thatās it. Didnāt want to deal with accounts for something this small. Everythingās free too ā Supabase has a free plan and Iām hosting it on Vercel which is also free, so itās not costing me anything to run.", "repo": "https://github.com/Coder-13-11/PickleWatch", "demo": "https://pickle-watch.vercel.app"}]...
|
[{"post_id": 85215, "ts": "202 [{"post_id": 85215, "ts": "2026-10-30T23:47:25Z", "hours": 0.5253, "text": "I made significant updates to RallyLab! I improved the appās audio detection quality by planning to integrate advanced noise-reduction and machine-learning models. I also started designing new community features, including user profiles, match scheduling, and leaderboards, to make the app more engaging. Additionally, I revamped the UI for better accessibility and mobile optimization. Excited to bring these changes to life!"}, {"post_id": 79042, "ts": "2026-10-12T14:04:26Z", "hours": 0.45, "text": "Update: fixed bugs and improved the sound detection algorithm so it accurately captures the hits, I am still wondering on how to make this really accurate so any suggestions would be helpful."}, {"post_id": 65180, "ts": "2026-09-10T03:56:43Z", "hours": 15.4464, "text": "š¢ Quick Update on Picklewatch š¢. I updated it to now RallyLab. I did this because initially i had an app to find open pickleball courts near me in Tampa. It worked, but I realized you really only use a court finder once. You check it, drive there, and thatās it. So Iāve been rebuilding it into RallyLab. The idea is simple: put your phone on the bench and let it listen to your match. Instead of recording the match, the new app -RallyLab- just detects racket hits and the words you say like serves etc to detect who got the point. The audio gets processed 128 samples at a time and immediately overwritten, so there is no recording or audio file. The hit detector is working pretty well now. I tested it with simulated gym noise, talking, shoe squeaks, and another court playing nearby, and 9/11 conditions got an F1 of at least 0.93. I also added badminton, tennis, pickleball, squash, and table tennis, along with their different scoring rules. There are also 393 tests passing. The biggest thing Iām working on now is automatic score tracking. I originally planned to have players tap who won each rally, but nobody is going to do that during a game. Since players already say the score out loud, Iām using that instead. Speech recognition by itself is only around 73% accurate, but because there are only a few legal scores that can follow each score, an HMM + Viterbi decoder can bring that up to around 96ā100%. I said its almost ready but I am trying to make it realible for an athlete to trust. Then I found a weird problem. The serverās score is always said first, so the microphone can know the score is 5-3 but canāt know which team is serving. That leaves two possibilities at exactly 50/50. Iām working on speaker ID now, but Iām using it as a probability instead of a hard rule so one mistake doesnāt ruin everything. Next is getting the score system into the UI, finishing speaker ID, figuring out the iOS audio situation, and testing it in a real gym. So far all my testing has been simulated. If it canāt handle six courts playing at once, then I have a much bigger problem. Maybe in the future, once i get the grant from hackclub to buy a licence for playstore, the app might fucntion more efficiently than a web app."}, {"post_id": 44219, "ts": "2026-08-09T20:42:41Z", "hours": 5.1753, "text": "Revamped the UI, check it out!"}, {"post_id": 32595, "ts": "2026-07-21T21:27:26Z", "hours": 6.0836, "text": "Fixed and Patched Bugs in PickleWatch!"}, {"post_id": 25968, "ts": "2026-07-10T14:41:36Z", "hours": 7.2303, "text": "Love Pickleball?? Check this out! I just made an app that tracks nearby pickleball courts and estimates how many people are on them, so the user can save time and play more efficiently when they get there. I have also created a feature for polls and for adding your crew to the friends list, so you can decide when to play the sport at your convenience. Please take a look at my screenshots below"}]...
|
Title: PickleWatch by @karthikeya | Stardance
Dev Title: PickleWatch by @karthikeya | Stardance
Devlogs:
Love Pickleball?? Check this out! I just made an app that tracks nearby pickleball courts and estimates how many people are on them, so the user can save time and play more efficiently when they get there. I have also created a feature for polls and for adding your crew to the friends list, so you can decide when to play the sport at your convenience. Please take a look at my screenshots below
Fixed and Patched Bugs in PickleWatch!
Revamped the UI, check it out!
š¢ Quick Update on Picklewatch š¢. I updated it to now RallyLab. I did this because initially i had an app to find open pickleball courts near me in Tampa. It worked, but I realized you really only use a court finder once. You check it, drive there, and thatās it. So Iāve been rebuilding it into RallyLab. The idea is simple: put your phone on the bench and let it listen to your match. Instead of recording the match, the new app -RallyLab- just detects racket hits and the words you say like serves etc to detect who got the point. The audio gets processed 128 samples at a time and immediately overwritten, so there is no recording or audio file. The hit detector is working pretty well now. I tested it with simulated gym noise, talking, shoe squeaks, and another court playing nearby, and 9/11 conditions got an F1 of at least 0.93. I also added badminton, tennis, pickleball, squash, and table tennis, along with their different scoring rules. There are also 393 tests passing. The biggest thing Iām working on now is automatic score tracking. I originally planned to have players tap who won each rally, but nobody is going to do that during a game. Since players already say the score out loud, Iām using that instead. Speech recognition by itself is only around 73% accurate, but because there are only a few legal scores that can follow each score, an HMM + Viterbi decoder can bring that up to around 96ā100%. I said its almost ready but I am trying to make it realible for an athlete to trust. Then I found a weird problem. The serverās score is always said first, so the microphone can know the score is 5-3 but canāt know which team is serving. That leaves two possibilities at exactly 50/50. Iām working on speaker ID now, but Iām using it as a probability instead of a hard rule so one mistake doesnāt ruin everything. Next is getting the score system into the UI, finishing speaker ID, figuring out the iOS audio situation, and testing it in a real gym. So far all my testing has been simulated. If it canāt handle six courts playing at once, then I have a much bigger problem. Maybe in the future, once i get the grant from hackclub to buy a licence for playstore, the app might fucntion more efficiently than a web app.
Update: fixed bugs and improved the sound detection algorithm so it accurately captures the hits, I am still wondering on how to make this really accurate so any suggestions would be helpful.
I made significant updates to RallyLab! I improved the appās audio detection quality by planning to integrate advanced noise-reduction and machine-learning models. I also started designing new community features, including user profiles, match scheduling, and leaderboards, to make the app more engaging. Additionally, I revamped the UI for better accessibility and mobile optimization. Excited to bring these changes to life!
Ships:
PickleWatch, an App for Pickleball Athletes So basically the problem is thereās like 8 pickleball courts around Tampa and you never know which ones are actually free or if theyāre packed until you drive there and itās a whole thing. So I made an app that tells you before you leave your house. Itās a website (kinda like an app, you can add it to your home screen) that shows all 8 courts and how busy each one probably is right now. Itās not just guessing randomly either ā I made it learn the normal pattern for each court (like Northlakes gets crazy busy around 6pm on weekdays but High 5 is more of a lunchtime thing) and then it mixes that with actual people checking in. Like if you show up and tap āIām hereā and say how busy it is, that updates everyoneās app in real time for like 90 minutes and then it fades away. The real time part is honestly the coolest part, I used this thing called Supabase which is like a free database that can push updates instantly. I tested it by opening two browser windows side by side and checking in on one and watching it show up on the other one immediately, no refreshing or anything. Other stuff it does: Rally button ā pick a time and it makes a message you can send to your group chat on WhatsApp asking who wants to play Polls ā like if people canāt decide where to play you make a poll and everyone votes and you can see it update live Friends ā add your friends and itāll show you when they check in somewhere, plus little avatar bubbles showing whoās at a court right now No login or password or anything, you just type your name once and thatās it. Didnāt want to deal with accounts for something this small. Everythingās free too ā Supabase has a free plan and Iām hosting it on Vercel which is also free, so itās not costing me anything to run.
I updated it to now RallyLab. I did this because initially i had an app to find open pickleball courts near me in Tampa. It worked, but I realized you really only use a court finder once. You check it, drive there, and thatās it. So Iāve been rebuilding it into RallyLab. The idea is simple: put your phone on the bench and let it listen to your match. Instead of recording the match, the new app -RallyLab- just detects racket hits and the words you say like serves etc to detect who got the point. The audio gets processed 128 samples at a time and immediately overwritten, so there is no recording or audio file. I am going to spend more time on this and make it a full on product people can use.
I have improved the sound detection system and revamped the whole UI. Please take a look and try out the app yourself. Whatās New? Bug Fixes, More advanced sound detection eliminating background noise and focusing more on upbeats that sound like racket hits. Working towards integrating it with the Apple Watch....
|
1793504974.401264
|
1793591374.401264
|
|
31086
|
BlackOS by @khabibullayev | Stardance
|
khabibullayev
|
1
|
1.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-06T07:18:51Z", "hours": 1.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "What did you make? I built BlackOS, a conceptual web-based operating system. It features an interactive boot screen, a functional login system, and a desktop environment with draggable windows. What was challenging? Managing the virtual file system (VFS) and ensuring the window management logic stayed smooth while keeping the interface responsive. What are you proud of? Iām proud of the custom boot animation and the modular architecture, which makes it easy to add new built-in apps like the terminal and calculator. What should people know so they can test your project? The system is open to everyoneāno password required. You can drag windows around, use the terminal to browse the VFS, and explore the settings.", "repo": "https://github.com/nullPulse-cmoke/BlackOS", "demo": "https://quiet-beignet-5838c1.netlify.app/"}]...
|
[{"post_id": 23326, "ts": "202 [{"post_id": 23326, "ts": "2026-07-06T06:36:17Z", "hours": 0.5208, "text": "Working on the desktop environment for BlackOS. Currently implementing the Finder and terminal logic, as well as setting up the authorization system and VFS. Next up is refining the UI to match the macOS aesthetic."}]...
|
Title: BlackOS by @khabibullayev | Stardance
Devl Title: BlackOS by @khabibullayev | Stardance
Devlogs:
Working on the desktop environment for BlackOS. Currently implementing the Finder and terminal logic, as well as setting up the authorization system and VFS. Next up is refining the UI to match the macOS aesthetic.
Ships:
What did you make? I built BlackOS, a conceptual web-based operating system. It features an interactive boot screen, a functional login system, and a desktop environment with draggable windows. What was challenging? Managing the virtual file system (VFS) and ensuring the window management logic stayed smooth while keeping the interface responsive. What are you proud of? Iām proud of the custom boot animation and the modular architecture, which makes it easy to add new built-in apps like the terminal and calculator. What should people know so they can test your project? The system is open to everyoneāno password required. You can drag windows around, use the terminal to browse the VFS, and explore the settings....
|
1793504972.1711187
|
1793591372.1711187
|
|
36848
|
Jahysite by @jahyue | Stardance
|
jahyue
|
1
|
2.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-21T12:09:14Z", "hours": 2.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I was able to make my own site! its a matrixy terminal theme which really took some time to accomplish but im very proud of what ive done its very minimal and i dont have much projects but itll grow over time", "repo": "https://github.com/jahyue/jahysite", "demo": "https://jahyue.github.io/jahysite/"}]...
|
[{"post_id": 31479, "ts": "202 [{"post_id": 31479, "ts": "2026-07-19T21:38:10Z", "hours": 1.595, "text": "I just finished the site i gave it a bit more of a matrix andd terminal theme and i really like the look i gave it"}, {"post_id": 30912, "ts": "2026-07-18T21:48:56Z", "hours": 0.2606, "text": "I was able to make a barebones website with a very very very very short intro about me with some socials and showing off my projects all i need now is some better design and some stuff"}]...
|
Title: Jahysite by @jahyue | Stardance
Devlogs:
I Title: Jahysite by @jahyue | Stardance
Devlogs:
I was able to make a barebones website with a very very very very short intro about me with some socials and showing off my projects all i need now is some better design and some stuff
I just finished the site i gave it a bit more of a matrix andd terminal theme and i really like the look i gave it
Ships:
I was able to make my own site! its a matrixy terminal theme which really took some time to accomplish but im very proud of what ive done its very minimal and i dont have much projects but itll grow over time...
|
1793504967.3680437
|
1793591367.3680437
|
|
23619
|
Wallipheus by @Wally | Stardance
|
Wally
|
1
|
2.32
|
4
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-25T12:54:55Z", "hours": 2.0, "multiplier": 2.28, "payout": 4, "blessing": "neutral", "text": "Made a Slack app for my personal channel, it can welcome new members, set a reminder, give cat fun facts, greet people, and has a daily reminder with a message that can be changed with a command, the ReadMe contains all the command names and what they do", "repo": "https://github.com/wally-ben/wallipheus", "demo": "https://hackclub.enterprise.slack.com/archives/C0AECK065AP"}]...
|
[{"post_id": 15801, "ts": "202 [{"post_id": 15801, "ts": "2026-06-25T18:01:03Z", "hours": 0.3242, "text": "Cleaned up the ReadMe file and fixed a problem where the Cat Command wasnāt working"}, {"post_id": 15558, "ts": "2026-06-25T09:17:07Z", "hours": 0.4958, "text": "Added a daily reminder at 9 am with a message that can be changed using /wallipheus-daily"}, {"post_id": 15362, "ts": "2026-06-24T23:45:44Z", "hours": 0.4456, "text": "Added a reminder command, it currently only takes in the amount of minutes and a message but I plan on adding the option to have a daily reminder"}, {"post_id": 15151, "ts": "2026-06-24T16:47:18Z", "hours": 0.2503, "text": "Added a Welcome message for #the-wally-cave, and started working on a reminder system"}, {"post_id": 15102, "ts": "2026-06-24T15:18:28Z", "hours": 0.7103, "text": "Followed the guide and made a Slack app with 3 commands, wallipheus-greet, wallipheus-ping, and wallipheus-cat. Will be adding more commands that use other APIs."}]...
|
Title: Wallipheus by @Wally | Stardance
Devlogs:
Title: Wallipheus by @Wally | Stardance
Devlogs:
Followed the guide and made a Slack app with 3 commands, wallipheus-greet, wallipheus-ping, and wallipheus-cat. Will be adding more commands that use other APIs.
Added a Welcome message for #the-wally-cave, and started working on a reminder system
Added a reminder command, it currently only takes in the amount of minutes and a message but I plan on adding the option to have a daily reminder
Added a daily reminder at 9 am with a message that can be changed using /wallipheus-daily
Cleaned up the ReadMe file and fixed a problem where the Cat Command wasnāt working
Ships:
Made a Slack app for my personal channel, it can welcome new members, set a reminder, give cat fun facts, greet people, and has a daily reminder with a message that can be changed with a command, the ReadMe contains all the command names and what they do...
|
1793504964.2587874
|
1793591364.2587874
|
|
35763
|
Future Oracle by @jacksonkyronox | Stardance
|
jacksonkyronox
|
1
|
0.0
|
1
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-17T13:02:04Z", "hours": 0.0, "multiplier": 1.56, "payout": 1, "blessing": "neutral", "text": "Hey there ! I , Gauransh , made a web app that has hardly anything to do with our daily life and making things easy . However , considering the fact that most of the people on this platform are teenagers just like me , I can guarantee that they pursue clarity in future , than anything else . But facts are facts . You canāt see the future . Neither can I ! But my project can tell people what their life āmayā look like if they keep working hard , and that too , in just the right direction . You enter some info about you , press enter , and suddenly you are in a room with a window from where you can see the Shibuya crossing . A small table , a cup of coffee , your laptop on , and Copilot is debugging your code . Now that may not have anything useful , but it provides something . And yes , that is clarity . That does clarify what your future will look like if you are honest enough with what you should do , and know how you can be one step forward after each day towards your goals !! I hope you all like it . Love you all !! Gauransh Sharma .", "repo": "https://github.com/jacksonkyronox-sudo/Inspo-Possibilities-.-", "demo": "https://inspo-possibilities.vercel.app/"}]...
|
[{"post_id": 29547, "ts": "202 [{"post_id": 29547, "ts": "2026-07-16T15:35:35Z", "hours": 0.3836, "text": "Hey everyone! Gauranth this side ā this is my first project here, and itās built around something most teens do more than theyād admit. You know that moment right before sleep when youāre not tired yet? Or when the dayās chaos settles and youāre just⦠satisfied with what you got done? I spend that time closing my eyes and picturing what my future looks like if I keep taking small steps toward my goals. Turns out my friends do this too. Maybe you do. So I built something for that exact moment. You enter a few details about where youāre headed, and it hands you back a glimpse of that possible future ā a small nudge to keep the momentum going. It runs on an API key under the hood, nothing fancy, just enough to make the magic work. This is my first project here, so reviews genuinely matter to me. Tear it apart if you need to ā I want to make it better. Love you guys!"}]...
|
Title: Future Oracle by @jacksonkyronox | Stardanc Title: Future Oracle by @jacksonkyronox | Stardance
Devlogs:
Hey everyone! Gauranth this side ā this is my first project here, and itās built around something most teens do more than theyād admit. You know that moment right before sleep when youāre not tired yet? Or when the dayās chaos settles and youāre just⦠satisfied with what you got done? I spend that time closing my eyes and picturing what my future looks like if I keep taking small steps toward my goals. Turns out my friends do this too. Maybe you do. So I built something for that exact moment. You enter a few details about where youāre headed, and it hands you back a glimpse of that possible future ā a small nudge to keep the momentum going. It runs on an API key under the hood, nothing fancy, just enough to make the magic work. This is my first project here, so reviews genuinely matter to me. Tear it apart if you need to ā I want to make it better. Love you guys!
Ships:
Hey there ! I , Gauransh , made a web app that has hardly anything to do with our daily life and making things easy . However , considering the fact that most of the people on this platform are teenagers just like me , I can guarantee that they pursue clarity in future , than anything else . But facts are facts . You canāt see the future . Neither can I ! But my project can tell people what their life āmayā look like if they keep working hard , and that too , in just the right direction . You enter some info about you , press enter , and suddenly you are in a room with a window from where you can see the Shibuya crossing . A small table , a cup of coffee , your laptop on , and Copilot is debugging your code . Now that may not have anything useful , but it provides something . And yes , that is clarity . That does clarify what your future will look like if you are honest enough with what you should do , and know how you can be one step forward after each day towards your goals !! I hope you all like it . Love you all !! Gauransh Sharma ....
|
1793504955.3850305
|
1793591355.3850305
|
|
37175
|
My first slack bot! by @Ayon | Stardance
|
Ayon
|
1
|
1.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-19T13:18:58Z", "hours": 1.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made an assistant bot that can tell current weather, give weather forecast, random quote. The challenging part was formatting. So, I used ChatGPT to suggest formatting of the responses. Deployed on HackClub Nest. Now it is working just fine.", "repo": "https://github.com/amiayon8/myassistant-slack", "demo": "https://hackclub.slack.com/archives/C0BJAR0QEV8"}]...
|
[{"post_id": 31168, "ts": "202 [{"post_id": 31168, "ts": "2026-07-19T10:39:51Z", "hours": 0.4331, "text": "Done random quotes and ping! Now my bot is ready to ship"}, {"post_id": 31149, "ts": "2026-07-19T10:03:13Z", "hours": 0.6186, "text": "Done current weather and weather forecast commands. Working well. Not yet deployed as my Nest Request isnāt approved yet"}]...
|
Title: My first slack bot! by @Ayon | Stardance
D Title: My first slack bot! by @Ayon | Stardance
Devlogs:
Done current weather and weather forecast commands. Working well. Not yet deployed as my Nest Request isnāt approved yet
Done random quotes and ping! Now my bot is ready to ship
Ships:
I made an assistant bot that can tell current weather, give weather forecast, random quote. The challenging part was formatting. So, I used ChatGPT to suggest formatting of the responses. Deployed on HackClub Nest. Now it is working just fine....
|
1793504945.9203224
|
1793591345.9203224
|
|
39413
|
octoPy by @sircheetodust | Stardance
|
sircheetodust
|
1
|
6.0
|
69
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-29T00:01:36Z", "hours": 6.0, "multiplier": 11.27, "payout": 69, "blessing": "neutral", "text": "This is OctoPy A chip-8 emulator fully written in python that I made while waiting for one of my other projects to finish rating(IT DOESNT EVEN HAVE ONE, ITS BEEN A WEEK, SOMEONE HALP). This project was my first emulator so I am proud to present it. It features a CPU with all of the chip-8s instructions programmed into it. It also has a pygame GUI interface, where you can choose ROMS, test the emulator, and even use your own ROMs(make sure they are for the chip8, this isnt a SCHIP or XOChip). This project had its own fair share of issues, such as the FX0A opcode just freezing the emulator entirely, or when games tried to play sound, your eardrums explode. I fixed all of these and finally finished this project. Please leave feedback!", "repo": "https://github.com/thecheetoman/octoPy", "demo": "https://github.com/thecheetoman/octoPy/releases/tag/v1.0"}]...
|
[{"post_id": 36733, "ts": "202 [{"post_id": 36733, "ts": "2026-07-28T23:57:31Z", "hours": 0.4281, "text": "Readme is useful i wrote the readme and created a gh release"}, {"post_id": 36666, "ts": "2026-07-28T21:27:44Z", "hours": 2.3717, "text": "i am going to eat a tire I might be only compiling this windows. pygbag is not cooperating at all. After this imma work on readme and get ready to ship. Here is a screenshot of the farthest I got it working."}, {"post_id": 36214, "ts": "2026-07-28T04:36:48Z", "hours": 0.9808, "text": "Emulator accuracy improvements Today I ran multiple test ROMS through my emulator. It passed most of the quirks and flags tests. It had issues with they FX0A instruction though. My previous CPU handled this in a way that the code will stop execution forever, not good. So I fixed that(took way too long) and ran the tests again. I can now say I have made my own emulator!"}, {"post_id": 35543, "ts": "2026-07-27T01:38:33Z", "hours": 0.8592, "text": "Dev log #3 Today i finished a boot UI. from here you can choose a game rom and play it. You can also hit esc and return to the menu. I also included test roms just in case someone wants to test the emulator. Emulator doesnt pass some of the tests though so i gotta work on that =("}, {"post_id": 34943, "ts": "2026-07-26T01:58:28Z", "hours": 0.6817, "text": "Got the emulator working I finally got the emulator working. Here is a quick clip of me playing pong, forgive my nonexistent skills at pong"}, {"post_id": 34380, "ts": "2026-07-25T01:29:25Z", "hours": 0.9022, "text": "Dev log #1 This is a short project that I hope to finish in a few days⦠Today I researched how the Chip-8 works, got some test ROMS, and wrote my CPU. Next I hope to make a GUI that i can even export to web. Im not sure what image to put here so here is js a pic of code"}]...
|
Title: octoPy by @sircheetodust | Stardance
Devlo Title: octoPy by @sircheetodust | Stardance
Devlogs:
Dev log #1 This is a short project that I hope to finish in a few days⦠Today I researched how the Chip-8 works, got some test ROMS, and wrote my CPU. Next I hope to make a GUI that i can even export to web. Im not sure what image to put here so here is js a pic of code
Got the emulator working I finally got the emulator working. Here is a quick clip of me playing pong, forgive my nonexistent skills at pong
Dev log #3 Today i finished a boot UI. from here you can choose a game rom and play it. You can also hit esc and return to the menu. I also included test roms just in case someone wants to test the emulator. Emulator doesnt pass some of the tests though so i gotta work on that =(
Emulator accuracy improvements Today I ran multiple test ROMS through my emulator. It passed most of the quirks and flags tests. It had issues with they FX0A instruction though. My previous CPU handled this in a way that the code will stop execution forever, not good. So I fixed that(took way too long) and ran the tests again. I can now say I have made my own emulator!
i am going to eat a tire I might be only compiling this windows. pygbag is not cooperating at all. After this imma work on readme and get ready to ship. Here is a screenshot of the farthest I got it working.
Readme is useful i wrote the readme and created a gh release
Ships:
This is OctoPy A chip-8 emulator fully written in python that I made while waiting for one of my other projects to finish rating(IT DOESNT EVEN HAVE ONE, ITS BEEN A WEEK, SOMEONE HALP). This project was my first emulator so I am proud to present it. It features a CPU with all of the chip-8s instructions programmed into it. It also has a pygame GUI interface, where you can choose ROMS, test the emulator, and even use your own ROMs(make sure they are for the chip8, this isnt a SCHIP or XOChip). This project had its own fair share of issues, such as the FX0A opcode just freezing the emulator entirely, or when games tried to play sound, your eardrums explode. I fixed all of these and finally finished this project. Please leave feedback!...
|
1793504937.9795487
|
1793591337.9795487
|
|
57417
|
Portfolio Website by @aarav_shrivastava | Stardanc Portfolio Website by @aarav_shrivastava | Stardance...
|
aarav_shrivastava
|
1
|
12.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-04T12:23:01Z", "hours": 12.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "A personal portfolio website designed to showcase my background, education, projects, interests, and ways to connect with me. This website is my personal space on the web where I can introduce myself and document the things I build and learn. To test it just click āTry Projectā button below.", "repo": "https://github.com/aaravshrivastava4129/Portfolio-Website", "demo": "https://aaravshrivastava4129.github.io/Portfolio-Website/"}]...
|
[{"post_id": 61458, "ts": "202 [{"post_id": 61458, "ts": "2026-09-04T11:57:58Z", "hours": 3.6606, "text": "Portfolio Website All sections are completed. Soon it will be shipped."}, {"post_id": 60988, "ts": "2026-09-03T17:53:25Z", "hours": 4.3367, "text": "Portfolio Website Finally home, about me, projects and connect with me sections are completed. Next, I will add my education section. Currently āView Projectā button does nothing, I will make it working later and will add more projects"}, {"post_id": 60749, "ts": "2026-09-03T10:03:04Z", "hours": 0.4414, "text": "Portfolio Website About section is now completed and I have used Doraemon picture for now later I will add mine. Now I will make projects section."}, {"post_id": 60371, "ts": "2026-09-02T17:45:40Z", "hours": 3.8631, "text": "Portfolio Website I have successfully completed home section of my portfolio website and the about section is also 80% completed."}]...
|
Title: Portfolio Website by @aarav_shrivastava | S Title: Portfolio Website by @aarav_shrivastava | Stardance
Devlogs:
Portfolio Website I have successfully completed home section of my portfolio website and the about section is also 80% completed.
Portfolio Website About section is now completed and I have used Doraemon picture for now later I will add mine. Now I will make projects section.
Portfolio Website Finally home, about me, projects and connect with me sections are completed. Next, I will add my education section. Currently āView Projectā button does nothing, I will make it working later and will add more projects
Portfolio Website All sections are completed. Soon it will be shipped.
Ships:
A personal portfolio website designed to showcase my background, education, projects, interests, and ways to connect with me. This website is my personal space on the web where I can introduce myself and document the things I build and learn. To test it just click āTry Projectā button below....
|
1793504933.7538633
|
1793591333.7538633
|
|
33097
|
AmethystOS by @Alexutzu | Stardance
|
Alexutzu
|
1
|
24.77
|
108
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-10T12:41:59Z", "hours": 14.0, "multiplier": 7.65, "payout": 108, "blessing": "neutral", "text": "What did you make? AmethystOS ā a tiny x86-64 operating system written in pure NASM assembly, booting through real mode ā protected mode ā 64-bit long mode with zero bootloader dependencies (works on both legacy BIOS and UEFI). It has a hand-rolled text-mode shell (history, arrow-key editing, a calculator, ACPI-powered real shutdown, a PS/2 mouse cursor, sysinfo/date/time/draw), and ā newest ā a full USB stack: UHCI/OHCI/EHCI/xHCI controller detection plus real device enumeration down to fetching each deviceās actual vendor/product name strings live over the wire. What was challenging? Getting the boot chain right with nothing to lean on: A20 gate, GDT setup, the jump into 32-bit protected mode, then PAE paging and EFER.LME into 64-bit long mode ā all before thereās a print function to debug with. Later, building a hybrid BIOS+UEFI image meant maintaining two completely different boot paths in one ISO. The USB3/xHCI work resurfaced that same āno debuggerā pain: three silent bugs (a clobbered PCI write, an event-type mixup, an untracked ring cycle-state bit) that each looked like dead hardware until traced by hand. What are you proud of? That every layer ā boot chain, shell, ACPI shutdown, USB3 device enumeration ā is hand-written with no OS framework, no bootloader, no libc. Including the small detail that USB vendor/product names shown by the usb command arenāt hardcoded: theyāre decoded live from each deviceās real USB string descriptor. How people can test it: Easiest: try the demo website first ā a React reimplementation of the shell that runs in-browser, no VM setup needed. Note to Shipwrecks: development is ongoing, so by the time this is reviewed, the project may have changed ā lightly or heavily ā for the better. Treat this ship as a snapshot, not the final state.", "repo": "https://github.com/alexutzusoft/amethyst-os", "demo": "https://alexutzu.pro/amethyst/"}]...
|
[{"post_id": 26550, "ts": "202 [{"post_id": 26550, "ts": "2026-07-11T13:08:02Z", "hours": 10.775, "text": "Mass storage groundwork. āAdded ls / dir commands with FAT read support over USB mass storageā pulled the xHCI bring-up out of commands_usb.asmās cmd_usb into a shared xhci_controller_init (caps parse, halt/reset, scratchpad, DCBAA, command+event ring, run ā CF on failure) so the new commands_fs.asm could drive the same controller for bulk-only mass storage: Enable Slot ā Address Device ā GET_DESCRIPTOR ā bulk CBW/CSW SCSI READ(10), one 512-byte sector at a time, feeding a FAT12/16/32 root-directory listing. ā Filesystem support broadened fast, one commit per format. āAdded exFAT supportā added MBR partition-type detection plus a GPT path (header at LBA 1, 4 entries/sector, first entry that parses as a valid VBR wins) alongside āEXFAT ā OEM-ID detection. āAdded NTFS supportā added MFT-cluster/record-size parsing and an AML-free walk of root record 5ās INDEX_ROOT/INDEX_ALLOCATION B-tree entries. āAdded cat commandā threaded an fs_action/fs_cat_found flag through all three listing walkers (FAT, exFAT, NTFS) so the same traversal either prints every entry or stops at the first name match and streams that fileās clusters instead. ā Write support, one format at a time. āAdded FAT32 write supportā added fs_write_sector (SCSI WRITE(10)) and echo-to-file: create-or-overwrite a root-directory entry, allocating a fresh cluster chain via the FAT. āAdded FAT16 write supportā reused the same path, adding a fs_is_fat16 mount-time branch (FAT12 vs FAT16 disambiguated by the classic <4085-cluster rule; FAT12ās packed 12-bit entries stayed explicitly unsupported). āAdded exFAT write supportā extended fs_build_target_name to track a display-cased name (fs_target_disp) alongside the raw match name, and added its own root-entry alloc/overwrite path capped at 15-char names. āAdded NTFS write supportā was the big one (~1500 lines) and the slowest by far ā about 8 hours to get right: update-sequence fixup read/write (fs_write_fixup, inverse of the existing fixup-apply), MFT record allocation via $MFTās $BITMAP, resident $DATA overwrite-in-place, and ā for new files ā a full FILE record build plus INDEX_ROOT insertion into record 5, gated to root-only files with no INDEX_ALLOCATION. The attached screenshot is an NTFS volume end to end: ls listing System Volume Information and test.txt , an echo ... > file.txt walking through the debug trace (search ā create path ā alloc ref ā build record ā indx-alloc insert ā ok), and cat file.txt reading the freshly written content back."}, {"post_id": 25917, "ts": "2026-07-10T12:32:29Z", "hours": 2.5372, "text": "Demo website. āAdded demo websiteā added a React 19 + TypeScript + Vite frontend under frontend/ that reimplements the shell in-browser rather than just describing it: a simulated 1MB memory buffer seeded with a fake IVT/BDA/boot sector/RSDP, a virtual 0xB8000 VGA text buffer, and a boot sequence (blank POST screen ā āHello, Amethyst!ā ā prompt) mirroring entry.asm. Reuses the real ASCII art strings from data_commands.asm and tracks cursor/attribute/scrollback state parallel to the kernelās own globals. ā USB enumeration. āAdded usb command with USB 1.1/2.0/3.x device enumerationā is the big one (~1200 lines, mostly new commands_usb.asm): brute-force PCI scan for class 0x0C/subclass 0x03 controllers, printing bus:dev.func, controller type (UHCI/OHCI/EHCI/xHCI), and vendor:device IDs. EHCI drives a real async QH/qTD control transfer to fetch each deviceās descriptor. xHCI goes further ā full register setup, command ring + polled event ring, per-port reset/speed detection, then a genuine Enable Slot ā Address Device ā GET_DESCRIPTOR(Device) sequence per port. Getting this working surfaced and fixed three bugs in one commit: pci_write32 clobbering its own value through a scratch register pci_config_addr also used; xhci_wait_event returning any event regardless of type, mistaking a stray Port Status Change Event for a command completion; and an untracked Cycle State bit that silently dropped every second transfer on the reused control-transfer ring. ā Vendor/product names, without hardcoding. āAdded iManufacturer string fetch for USB vendor namesā factored the existing iProduct fetch into a shared xhci_print_string_desc helper, called once for iManufacturer and once for iProduct ā decoding the real UTF-16LE string descriptor live over a control transfer, no lookup table. Also cleaned up the register-dump and completion-code debug prints left over from chasing the bugs above, so cmd_usbās output is just the device/vendor/name lines."}, {"post_id": 25544, "ts": "2026-07-09T21:18:12Z", "hours": 2.4944, "text": "Previously in devlog #1: Boot chain transitioned from 16-bit real mode to 64-bit long mode; shell got core commands (echo, run, clear, mem, peek/poke, cpuid, uptime); ACPI power-off enabled true hardware shutdown; UI/UX gained text input, PS/2 mouse cursor, scrolling, and draw/sysinfo; infrastructure achieved hybrid BIOS+UEFI boot. ā Codebase organization. The second āOrganized src/ā commit dismantled the monolithic kernel.asm by extracting components into modular topic files (%included under defs.inc.asm, entry.asm, interrupts.asm, input.asm, display.asm, data_strings.asm, data_commands.asm, and command handlers divided by category). ā Shell features. āAdded command historyā implemented a 16-slot ring buffer for commands up to 128 bytes each. Arrow Up recalls older lines while caching the current unsaved prompt; Arrow Down moves back forward, restoring the saved prompt at position 0, with cursor positioning aligned to the end of the text. Shift+arrow keys are bypassed to maintain viewport scrollback. ā Calculator. āAdded calc commandā introduced signed decimal parsing (parse_dec_arg) and printing to support signed 64-bit integer binary operations (+, -, *, /, %). It also implements an integer square root (isqrt64) working as a prefix or postfix (calc sqrt N or calc N sqrt) with error-checking for division-by-zero and negative parameters. ā Infra & Licensing. āUpdated LICENSEā adopted the custom TreeSoft Open Source License. āAdded release workflowā standardized output file names to lowercase kebab-case (amethyst-os.iso/.img) and introduced a GitHub Actions pipeline that builds both ISO and raw USB images on ubuntu-latest, calculates SHA256 checksums, and publishes nightly prereleases via the GitHub CLI. ā"}, {"post_id": 25381, "ts": "2026-07-09T17:12:11Z", "hours": 9.2583, "text": "Boot chain. Started as a 16-bit MBR sector that set VGA mode 3 and printed āHello, Amethyst!ā via BIOS teletype. Added protected mode (A20 gate, GDT, CR0.PE, far jump to [BITS 32], direct 0xB8000 VGA writes replacing BIOS calls), then long mode (PAE paging, identity-mapped first 1GB, EFER.LME). Later split the monolithic boot.asm into stage1.asm (realāprotectedālong mode handoff) + kernel.asm (%included, everything from protected mode on) ā that was āCleaned codebaseā; āOrganized src/ā was purely a file move (src/boot/kernel.asm ā src/kernel/kernel.asm), no logic change. ā Shell core. echo came first, then run ā decodes a hex-byte string into a scratch buffer and calls into it directly, no sandboxing, on purpose. āAdded more commandsā was one big commit landing nine at once: clear, help, reboot, halt, mem, peek, poke, cpuid, uptime, shutdown. ā ACPI. āImproved shutdownā was misleadingly named ā itās where real ACPI support landed: RSDP scanning, RSDT/XSDT parsing with checksum validation, a brute-force table scan fallback, _S5 AML decoding, and the acpi command to probe/display it all. This is what makes shutdown actually power off real hardware instead of just halting. ā UI/UX. color added named presets (red/green/blue/yellow/white) plus raw hex attribute bytes, with input validation and a usage message. Arrow-key navigation added cursor movement, word-jump (Ctrl+arrow), selection, insert/delete-at-cursor, and full input-line redraw logic ā the single largest diff in the history (~343 lines). Then PS/2 mouse cursor support, scrolling, and scrollback. ā Later additions. date/time, sysinfo (cpu/ram/gpu/general, using the BIOS memory map stage1 captures in real mode), draw. āDoubled stage1 budget; Fixed bugsā doubled KERNEL_SECTORS 16ā32 (and the matching -boot-load-size/times padding) to make room for growth, and in the same commit reworked help to print aligned two-column output with per-command descriptions (command_descriptions table) and tightened colorās argument validation. ā Infra. Hybrid BIOS+UEFI boot support: uefi.asm linked as a PE32+ EFI app, packed into a FAT ESP image, combined with the BIOS MBR into one hybrid ISO, plus a raw .img for USB writes and three separate QEMU run scripts for each boot path."}]...
|
Title: AmethystOS by @Alexutzu | Stardance
Devlog Title: AmethystOS by @Alexutzu | Stardance
Devlogs:
Boot chain. Started as a 16-bit MBR sector that set VGA mode 3 and printed āHello, Amethyst!ā via BIOS teletype. Added protected mode (A20 gate, GDT, CR0.PE, far jump to [BITS 32], direct 0xB8000 VGA writes replacing BIOS calls), then long mode (PAE paging, identity-mapped first 1GB, EFER.LME). Later split the monolithic boot.asm into stage1.asm (realāprotectedālong mode handoff) + kernel.asm (%included, everything from protected mode on) ā that was āCleaned codebaseā; āOrganized src/ā was purely a file move (src/boot/kernel.asm ā src/kernel/kernel.asm), no logic change. ā Shell core. echo came first, then run ā decodes a hex-byte string into a scratch buffer and calls into it directly, no sandboxing, on purpose. āAdded more commandsā was one big commit landing nine at once: clear, help, reboot, halt, mem, peek, poke, cpuid, uptime, shutdown. ā ACPI. āImproved shutdownā was misleadingly named ā itās where real ACPI support landed: RSDP scanning, RSDT/XSDT parsing with checksum validation, a brute-force table scan fallback, _S5 AML decoding, and the acpi command to probe/display it all. This is what makes shutdown actually power off real hardware instead of just halting. ā UI/UX. color added named presets (red/green/blue/yellow/white) plus raw hex attribute bytes, with input validation and a usage message. Arrow-key navigation added cursor movement, word-jump (Ctrl+arrow), selection, insert/delete-at-cursor, and full input-line redraw logic ā the single largest diff in the history (~343 lines). Then PS/2 mouse cursor support, scrolling, and scrollback. ā Later additions. date/time, sysinfo (cpu/ram/gpu/general, using the BIOS memory map stage1 captures in real mode), draw. āDoubled stage1 budget; Fixed bugsā doubled KERNEL_SECTORS 16ā32 (and the matching -boot-load-size/times padding) to make room for growth, and in the same commit reworked help to print aligned two-column output with per-command descriptions (command_descriptions table) and tightened colorās argument validation. ā Infra. Hybrid BIOS+UEFI boot support: uefi.asm linked as a PE32+ EFI app, packed into a FAT ESP image, combined with the BIOS MBR into one hybrid ISO, plus a raw .img for USB writes and three separate QEMU run scripts for each boot path.
Previously in devlog #1: Boot chain transitioned from 16-bit real mode to 64-bit long mode; shell got core commands (echo, run, clear, mem, peek/poke, cpuid, uptime); ACPI power-off enabled true hardware shutdown; UI/UX gained text input, PS/2 mouse cursor, scrolling, and draw/sysinfo; infrastructure achieved hybrid BIOS+UEFI boot. ā Codebase organization. The second āOrganized src/ā commit dismantled the monolithic kernel.asm by extracting components into modular topic files (%included under defs.inc.asm, entry.asm, interrupts.asm, input.asm, display.asm, data_strings.asm, data_commands.asm, and command handlers divided by category). ā Shell features. āAdded command historyā implemented a 16-slot ring buffer for commands up to 128 bytes each. Arrow Up recalls older lines while caching the current unsaved prompt; Arrow Down moves back forward, restoring the saved prompt at position 0, with cursor positioning aligned to the end of the text. Shift+arrow keys are bypassed to maintain viewport scrollback. ā Calculator. āAdded calc commandā introduced signed decimal parsing (parse_dec_arg) and printing to support signed 64-bit integer binary operations (+, -, *, /, %). It also implements an integer square root (isqrt64) working as a prefix or postfix (calc sqrt N or calc N sqrt) with error-checking for division-by-zero and negative parameters. ā Infra & Licensing. āUpdated LICENSEā adopted the custom TreeSoft Open Source License. āAdded release workflowā standardized output file names to lowercase kebab-case (amethyst-os.iso/.img) and introduced a GitHub Actions pipeline that builds both ISO and raw USB images on ubuntu-latest, calculates SHA256 checksums, and publishes nightly prereleases via the GitHub CLI. ā
Demo website. āAdded demo websiteā added a React 19 + TypeScript + Vite frontend under frontend/ that reimplements the shell in-browser rather than just describing it: a simulated 1MB memory buffer seeded with a fake IVT/BDA/boot sector/RSDP, a virtual 0xB8000 VGA text buffer, and a boot sequence (blank POST screen ā āHello, Amethyst!ā ā prompt) mirroring entry.asm. Reuses the real ASCII art strings from data_commands.asm and tracks cursor/attribute/scrollback state parallel to the kernelās own globals. ā USB enumeration. āAdded usb command with USB 1.1/2.0/3.x device enumerationā is the big one (~1200 lines, mostly new commands_usb.asm): brute-force PCI scan for class 0x0C/subclass 0x03 controllers, printing bus:dev.func, controller type (UHCI/OHCI/EHCI/xHCI), and vendor:device IDs. EHCI drives a real async QH/qTD control transfer to fetch each deviceās descriptor. xHCI goes further ā full register setup, command ring + polled event ring, per-port reset/speed detection, then a genuine Enable Slot ā Address Device ā GET_DESCRIPTOR(Device) sequence per port. Getting this working surfaced and fixed three bugs in one commit: pci_write32 clobbering its own value through a scratch register pci_config_addr also used; xhci_wait_event returning any event regardless of type, mistaking a stray Port Status Change Event for a command completion; and an untracked Cycle State bit that silently dropped every second transfer on the reused control-transfer ring. ā Vendor/product names, without hardcoding. āAdded iManufacturer string fetch for USB vendor namesā factored the existing iProduct fetch into a shared xhci_print_string_desc helper, called once for iManufacturer and once for iProduct ā decoding the real UTF-16LE string descriptor live over a control transfer, no lookup table. Also cleaned up the register-dump and completion-code debug prints left over from chasing the bugs above, so cmd_usbās output is just the device/vendor/name lines.
Mass storage groundwork. āAdded ls / dir commands with FAT read support over USB mass storageā pulled the xHCI bring-up out of commands_usb.asmās cmd_usb into a shared xhci_controller_init (caps parse, halt/reset, scratchpad, DCBAA, command+event ring, run ā CF on failure) so the new commands_fs.asm could drive the same controller for bulk-only mass storage: Enable Slot ā Address Device ā GET_DESCRIPTOR ā bulk CBW/CSW SCSI READ(10), one 512-byte sector at a time, feeding a FAT12/16/32 root-directory listing. ā Filesystem support broadened fast, one commit per format. āAdded exFAT supportā added MBR partition-type detection plus a GPT path (header at LBA 1, 4 entries/sector, first entry that parses as a valid VBR wins) alongside āEXFAT ā OEM-ID detection. āAdded NTFS supportā added MFT-cluster/record-size parsing and an AML-free walk of root record 5ās INDEX_ROOT/INDEX_ALLOCATION B-tree entries. āAdded cat commandā threaded an fs_action/fs_cat_found flag through all three listing walkers (FAT, exFAT, NTFS) so the same traversal either prints every entry or stops at the first name match and streams that fileās clusters instead. ā Write support, one format at a time. āAdded FAT32 write supportā added fs_write_sector (SCSI WRITE(10)) and echo-to-file: create-or-overwrite a root-directory entry, allocating a fresh cluster chain via the FAT. āAdded FAT16 write supportā reused the same path, adding a fs_is_fat16 mount-time branch (FAT12 vs FAT16 disambiguated by the classic <4085-cluster rule; FAT12ās packed 12-bit entries stayed explicitly unsupported). āAdded exFAT write supportā extended fs_build_target_name to track a display-cased name (fs_target_disp) alongside the raw match name, and added its own root-entry alloc/overwrite path capped at 15-char names. āAdded NTFS write supportā was the big one (~1500 lines) and the slowest by far ā about 8 hours to get right: update-sequence fixup read/write (fs_write_fixup, inverse of the existing fixup-apply), MFT record allocation via $MFTās $BITMAP, resident $DATA overwrite-in-place, and ā for new files ā a full FILE record build plus INDEX_ROOT insertion into record 5, gated to root-only files with no INDEX_ALLOCATION. The attached screenshot is an NTFS volume end to end: ls listing System Volume Information and test.txt , an echo ... > file.txt walking through the debug trace (search ā create path ā alloc ref ā build record ā indx-alloc insert ā ok), and cat file.txt reading the freshly written content back.
Ships:
What did you make? AmethystOS ā a tiny x86-64 operating system written in pure NASM assembly, booting through real mode ā protected mode ā 64-bit long mode with zero bootloader dependencies (works on both legacy BIOS and UEFI). It has a hand-rolled text-mode shell (history, arrow-key editing, a calculator, ACPI-powered real shutdown, a PS/2 mouse cursor, sysinfo/date/time/draw), and ā newest ā a full USB stack: UHCI/OHCI/EHCI/xHCI controller detection plus real device enumeration down to fetching each deviceās actual vendor/product name strings live over the wire. What was challenging? Getting the boot chain right with nothing to lean on: A20 gate, GDT setup, the jump into 32-bit protected mode, then PAE paging and EFER.LME into 64-bit long mode ā all before thereās a print function to debug with. Later, building a hybrid BIOS+UEFI image meant maintaining two completely different boot paths in one ISO. The USB3/xHCI work resurfaced that same āno debuggerā pain: three silent bugs (a clobbered PCI write, an event-type mixup, an untracked ring cycle-state bit) that each looked like dead hardware until traced by hand. What are you proud of? That every layer ā boot chain, shell, ACPI shutdown, USB3 device enumeration ā is hand-written with no OS framework, no bootloader, no libc. Including the small detail that USB vendor/product names shown by the usb command arenāt hardcoded: theyāre decoded live from each deviceās real USB string descriptor. How people can test it: Easiest: try the demo website first ā a React reimplementation of the shell that runs in-browser, no VM setup needed. Note to Shipwrecks: development is ongoing, so by the time this is reviewed, the project may have changed ā lightly or heavily ā for the better. Treat this ship as a snapshot, not the final state....
|
1793504925.8686779
|
1793591325.8686779
|
|
32323
|
Bloomington Streets Alliance by @wingedmolotov | S Bloomington Streets Alliance by @wingedmolotov | Stardance...
|
wingedmolotov
|
1
|
21.45
|
50
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-12T04:25:47Z", "hours": 11.0, "multiplier": 4.52, "payout": 50, "blessing": "neutral", "text": "A hub for a local alternative transportation action group. My goal was to include a short bio of the group, a guide to advocacy, and helpful links, but keep the main focus on actionable items. Proud of adding interactive animations and using flexbox for the first time, challenge was figuring out spacing.", "repo": "https://github.com/WingedMolotov/Bloomington-Streets-Alliance", "demo": "https://wingedmolotov.org/Bloomington-Streets-Alliance/"}]...
|
[{"post_id": 29922, "ts": "202 [{"post_id": 29922, "ts": "2026-07-17T03:03:16Z", "hours": 4.6853, "text": "Devlog #4 Hello all! Yesterday and today: Get Involved page Create mobile-friendly stacked version using @media filters Collapse initiatives row into a card slider in the mobile version. I was able to reuse some code from the home page (this involved a lot of troubleshooting to handle transitioning between desktop and mobile) Advocating page Create mobile-friendly stacked version using @media filters Switch from using <details> and <summary> to custom JavaScript-based smooth accordion About page Create mobile-friendly stacked version using @media filters (by far the easiest page to make responsive Other minor changes as necessary Including creating a second @media filter for even smaller screens for the footer Also⦠New initiative - Budget page Mostly reusing template from the 102nd Street page, with some tweaks as needed"}, {"post_id": 28693, "ts": "2026-07-15T03:12:50Z", "hours": 3.4625, "text": "Devlog #3 Hello all! Today: Resources page Create mobile-friendly version using @media filters, stacking everything vertically Use order: -1 to have images and text alternate positions in desktop version but have images appear above text in mobile version Create custom smooth dropdown (similar to HTML <detail> / <summary> , utilizing JS requestAnimationFrame() 102nd St (initiative) page Create mobile-friendly version using @media filters (vertical stacking) Clean up information bubbles using CSS Grid and overflow scrolling Other minor tweaks as needed"}, {"post_id": 28071, "ts": "2026-07-14T03:07:48Z", "hours": 0.425, "text": "Devlog #2 Hello all! Short devlog to round off the day. I made the main content of the homepage responsive by figuring out a good breakpoint (compressing until it looked bad), and then turning what were previously row flexboxes into columns. Some small tweaks to dimensions were added as necessary. I also experimented with max: in CSS, setting some margins and paddings using it to make sure a minimum threshold existed. I plan to repeat this process for other pages."}, {"post_id": 28001, "ts": "2026-07-13T23:35:39Z", "hours": 1.8753, "text": "Hello all! I realize I should probably be more in-depth with these devlogs, so consider this devlog #1. 1 - Responsive footer When the width of the page gets too narrow, I notice that the links in the footer overlap with the copyright notice. I determined that this was because the links were positioned and centered absolutely. To fix this, I squashed the page until just before this happened and made that my breakpoint for use in a @media filter. In the filter for smaller screens, I simply changed the footer from being a horizontal flexbox to a vertical one, and removed the absolute positioning and centering. I copied these changes to all of my websiteās pages. (see image below) 2 - Responsive top navigation Similarly, I noticed that a narrow viewport caused the links at the top to become compressed and even extend past the yellow containing box. Tox fix this, I first squashed the page to find my @media breakpoint. Next, I used fa-solid fa-bars and fa-solid fa-rectangle-xmark in order to create a hamburger menu that would appear on the right, replacing the four links on the top. I used JavaScript event listeners to make the menu appear and disappear at the press of these icons. Creating this hamburger menu itself was fairly simple, as it only involved converting the <ul> that the links were in from a horizontal flexbox to a vertical one. Then, I added the gold background, changed the :hover underline to white, and used position: fixed to align it with the right-hand side. Originally, this navigation panel would simply appear when the hamburger button was pressed. I felt that this lacked an element of interactivity and was visually jarring. After trying unsucessfully to use CSS animations to achieve a smooth sliding effect, I asked ChatGPT for help. With that, I refactored my code to, instead of using display: none to hide the menu, use transform: translateX(100%) . This simplified my JavaScript and allowed me to use a trigger class and CSS transitions to smoothly animate the menu in and out. I then copied this to the other pages, using a new universal JavaScript file - dynamic top.js - to streamline the process somewhat. Using this, I was also able to easily make a change that applies overflow: hidden to the document body when the menu is active. dynamic_top.js const burger = document.getElementById('burger'); const toprow = document.querySelector('#toprow ul'); const close = document.getElementById('close'); burger.addEventListener('click', () => { toprow.classList.add('open'); body.style.overflow = 'hidden'; }); close.addEventListener('click', () => { toprow.classList.remove('open'); body.style.overflow = 'auto'; }); The results are in the second and third images. #3 - Small tweaks Add min-height: 225px to the card carousel on the hero section so it doesnāt get too squished Change the size and spacing of the indicator dots at the bottom of the card carousel to be in fixed units so it doesnāt get too small Next step - making the main content of each of the six pages responsive, starting with the home page. Thanks!"}, {"post_id": 27001, "ts": "2026-07-12T04:23:51Z", "hours": 0.3222, "text": "Fix spacing, link to custom bike map"}, {"post_id": 26983, "ts": "2026-07-12T03:35:04Z", "hours": 1.2358, "text": "finalize resources pg"}, {"post_id": 25706, "ts": "2026-07-10T04:16:22Z", "hours": 2.1311, "text": "initiative page and cards"}, {"post_id": 25534, "ts": "2026-07-09T21:04:47Z", "hours": 3.9158, "text": "created advocacy guide, expanded resources"}, {"post_id": 24524, "ts": "2026-07-08T03:54:21Z", "hours": 1.9747, "text": "created about and resources pages"}, {"post_id": 24415, "ts": "2026-07-07T23:20:59Z", "hours": 1.0206, "text": "added clickthrough action alert cards (placeholder) and set up newsletter thru buttondown"}, {"post_id": 24373, "ts": "2026-07-07T21:54:14Z", "hours": 0.535, "text": "Setting up a form for an email newsletter!"}]...
|
Title: Bloomington Streets Alliance by @wingedmolo Title: Bloomington Streets Alliance by @wingedmolotov | Stardance
Devlogs:
Setting up a form for an email newsletter!
added clickthrough action alert cards (placeholder) and set up newsletter thru buttondown
created about and resources pages
created advocacy guide, expanded resources
initiative page and cards
finalize resources pg
Fix spacing, link to custom bike map
Hello all! I realize I should probably be more in-depth with these devlogs, so consider this devlog #1. 1 - Responsive footer When the width of the page gets too narrow, I notice that the links in the footer overlap with the copyright notice. I determined that this was because the links were positioned and centered absolutely. To fix this, I squashed the page until just before this happened and made that my breakpoint for use in a @media filter. In the filter for smaller screens, I simply changed the footer from being a horizontal flexbox to a vertical one, and removed the absolute positioning and centering. I copied these changes to all of my websiteās pages. (see image below) 2 - Responsive top navigation Similarly, I noticed that a narrow viewport caused the links at the top to become compressed and even extend past the yellow containing box. Tox fix this, I first squashed the page to find my @media breakpoint. Next, I used fa-solid fa-bars and fa-solid fa-rectangle-xmark in order to create a hamburger menu that would appear on the right, replacing the four links on the top. I used JavaScript event listeners to make the menu appear and disappear at the press of these icons. Creating this hamburger menu itself was fairly simple, as it only involved converting the <ul> that the links were in from a horizontal flexbox to a vertical one. Then, I added the gold background, changed the :hover underline to white, and used position: fixed to align it with the right-hand side. Originally, this navigation panel would simply appear when the hamburger button was pressed. I felt that this lacked an element of interactivity and was visually jarring. After trying unsucessfully to use CSS animations to achieve a smooth sliding effect, I asked ChatGPT for help. With that, I refactored my code to, instead of using display: none to hide the menu, use transform: translateX(100%) . This simplified my JavaScript and allowed me to use a trigger class and CSS transitions to smoothly animate the menu in and out. I then copied this to the other pages, using a new universal JavaScript file - dynamic top.js - to streamline the process somewhat. Using this, I was also able to easily make a change that applies overflow: hidden to the document body when the menu is active. dynamic_top.js const burger = document.getElementById('burger'); const toprow = document.querySelector('#toprow ul'); const close = document.getElementById('close'); burger.addEventListener('click', () => { toprow.classList.add('open'); body.style.overflow = 'hidden'; }); close.addEventListener('click', () => { toprow.classList.remove('open'); body.style.overflow = 'auto'; }); The results are in the second and third images. #3 - Small tweaks Add min-height: 225px to the card carousel on the hero section so it doesnāt get too squished Change the size and spacing of the indicator dots at the bottom of the card carousel to be in fixed units so it doesnāt get too small Next step - making the main content of each of the six pages responsive, starting with the home page. Thanks!
Devlog #2 Hello all! Short devlog to round off the day. I made the main content of the homepage responsive by figuring out a good breakpoint (compressing until it looked bad), and then turning what were previously row flexboxes into columns. Some small tweaks to dimensions were added as necessary. I also experimented with max: in CSS, setting some margins and paddings using it to make sure a minimum threshold existed. I plan to repeat this process for other pages.
Devlog #3 Hello all! Today: Resources page Create mobile-friendly version using @media filters, stacking everything vertically Use order: -1 to have images and text alternate positions in desktop version but have images appear above text in mobile version Create custom smooth dropdown (similar to HTML <detail> / <summary> , utilizing JS requestAnimationFrame() 102nd St (initiative) page Create mobile-friendly version using @media filters (vertical stacking) Clean up information bubbles using CSS Grid and overflow scrolling Other minor tweaks as needed
Devlog #4 Hello all! Yesterday and today: Get Involved page Create mobile-friendly stacked version using @media filters Collapse initiatives row into a card slider in the mobile version. I was able to reuse some code from the home page (this involved a lot of troubleshooting to handle transitioning between desktop and mobile) Advocating page Create mobile-friendly stacked version using @media filters Switch from using <details> and <summary> to custom JavaScript-based smooth accordion About page Create mobile-friendly stacked version using @media filters (by far the easiest page to make responsive Other minor changes as necessary Including creating a second @media filter for even smaller screens for the footer Also⦠New initiative - Budget page Mostly reusing template from the 102nd Street page, with some tweaks as needed
Ships:
A hub for a local alternative transportation action group. My goal was to include a short bio of the group, a guide to advocacy, and helpful links, but keep the main focus on actionable items. Proud of adding interactive animations and using flexbox for the first time, challenge was figuring out spacing....
|
1793504917.2688708
|
1793591317.2688708
|
|
21779
|
BatFlash by @aahil | Stardance
|
aahil
|
1
|
1.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-19T14:10:45Z", "hours": 1.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Heyo! I made a Batman batarang that lights up and fits in a case!", "repo": "https://github.com/aahvl/BatFlash", "demo": ""}]...
|
[{"post_id": 11384, "ts": "202 [{"post_id": 11384, "ts": "2026-06-18T17:02:44Z", "hours": 1.1061, "text": "Made the PCB and the Case for it."}]...
|
Title: BatFlash by @aahil | Stardance
Devlogs:
Ma Title: BatFlash by @aahil | Stardance
Devlogs:
Made the PCB and the Case for it.
Ships:
Heyo! I made a Batman batarang that lights up and fits in a case!...
|
1793504910.7624404
|
1793591310.7624404
|
|
17809
|
ZENOS by @yashasvib | Stardance
|
yashasvib
|
1
|
1.96
|
5
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-13T18:18:38Z", "hours": 1.0, "multiplier": 4.97, "payout": 5, "blessing": "neutral", "text": "WHAT DID I MAKE ? I built ZENOS, a futuristic desktop-style web interface with a live clock ,date and time display, draggable widgets, a calculator and a notepad , al designed with a glassmorphism aesthetic CHALLENGES: getting the draggable working smoothly and trying to arrange things so that my IDOL was not covered . turning a simple webpage into interactive desktop experience that feels just right is cool . GUYSS!!!! open the web ,drag the widget around , use them and watch live clock and time updates . THANK YOU !!!!!", "repo": "https://github.com/yashasvi-2012-star/realOS", "demo": "https://zenos-os.vercel.app/"}]...
|
[{"post_id": 8759, "ts": "2026 [{"post_id": 8759, "ts": "2026-06-14T15:52:03Z", "hours": 0.3661, "text": "last one wasssss not the last update guys this one is -vGUYSS!!! I FIXED THE BUGSS AND ADDED SOME NEW FEATURES AS WELL AS UPDATED . i added a better drawing pad with adjustable size and all and even a live sportify playlist where you can just play any song you like !!! . GO CHECK IT OUT NOW !!!"}, {"post_id": 8280, "ts": "2026-06-13T19:27:58Z", "hours": 0.2694, "text": "SECOND UPDATE !!!- ZENOS is getting more exciting now! Iāve added a movable live clock that shows real-time updates, making the desktop feel more interactive and alive. And Iām soon going to add a movable drawing pad where users can write or sketch freely, making the system even more creative and fun to use( AND i will be adding A REAL SPORTIFY PLAYLIST ICON . i am currently working on it !!! IT MEAN U CAN PATSE YOUR OWN PLAYLIST (embed link ) IN AND SEE !!!(before as mentioned in devlog1 i decided to add just a icon but i changed my mind and added real working sportify window ))"}, {"post_id": 8264, "ts": "2026-06-13T19:08:09Z", "hours": 0.3289, "text": "FIRST UPDATE - (SRRY GUYSS I COULD NOT POST BEFORE THIS !!! )IT IS clean, minimal desktop-style operating system UI called ZENOS. It has a top bar showing date and time, a central wallpaper with an analog clock, a calculator on the left, a notepad on the right, and a small music card. modern simple and kpop-ed design . i hope i get feedbacks !!!"}, {"post_id": 8212, "ts": "2026-06-13T17:39:30Z", "hours": 0.9428, "text": "maybee LAST UPDATE - HEYYYY!!! THIS IS MY FIRST OS INSPIRED BY MY FAVROITE ARTIST JENIEEEEEEE!!!! okay to be fair i was excited will making this an this is probabaly not my best work but i tried hard ON THIS .i added draggable calculator , draggable notepad, (maybe add draggable sportify window ), draggable clock and draggable drawing pad"}]...
|
Title: ZENOS by @yashasvib | Stardance
Devlogs:
m Title: ZENOS by @yashasvib | Stardance
Devlogs:
maybee LAST UPDATE - HEYYYY!!! THIS IS MY FIRST OS INSPIRED BY MY FAVROITE ARTIST JENIEEEEEEE!!!! okay to be fair i was excited will making this an this is probabaly not my best work but i tried hard ON THIS .i added draggable calculator , draggable notepad, (maybe add draggable sportify window ), draggable clock and draggable drawing pad
FIRST UPDATE - (SRRY GUYSS I COULD NOT POST BEFORE THIS !!! )IT IS clean, minimal desktop-style operating system UI called ZENOS. It has a top bar showing date and time, a central wallpaper with an analog clock, a calculator on the left, a notepad on the right, and a small music card. modern simple and kpop-ed design . i hope i get feedbacks !!!
SECOND UPDATE !!!- ZENOS is getting more exciting now! Iāve added a movable live clock that shows real-time updates, making the desktop feel more interactive and alive. And Iām soon going to add a movable drawing pad where users can write or sketch freely, making the system even more creative and fun to use( AND i will be adding A REAL SPORTIFY PLAYLIST ICON . i am currently working on it !!! IT MEAN U CAN PATSE YOUR OWN PLAYLIST (embed link ) IN AND SEE !!!(before as mentioned in devlog1 i decided to add just a icon but i changed my mind and added real working sportify window ))
last one wasssss not the last update guys this one is -vGUYSS!!! I FIXED THE BUGSS AND ADDED SOME NEW FEATURES AS WELL AS UPDATED . i added a better drawing pad with adjustable size and all and even a live sportify playlist where you can just play any song you like !!! . GO CHECK IT OUT NOW !!!
Ships:
WHAT DID I MAKE ? I built ZENOS, a futuristic desktop-style web interface with a live clock ,date and time display, draggable widgets, a calculator and a notepad , al designed with a glassmorphism aesthetic CHALLENGES: getting the draggable working smoothly and trying to arrange things so that my IDOL was not covered . turning a simple webpage into interactive desktop experience that feels just right is cool . GUYSS!!!! open the web ,drag the widget around , use them and watch live clock and time updates . THANK YOU !!!!!...
|
1793504904.632996
|
1793591304.632996
|
|
57404
|
Tiger OS by @Rayan123-4 | Stardance
|
Rayan123-4
|
3
|
75.0
|
447
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-25T03:15:51Z", "hours": 18.0, "multiplier": 18.42, "payout": 332, "blessing": "neutral", "text": "What did I make I made TigerOS, a web based operating system that it completely run on the web. Itās themed around tigers as you can see, and has many interesting features such a as a, weather API, a tiger habitat and population graph, a classic calculator, a tiger earth three.js simulator and many more amazing experiences to explore through. It is made using JavaScript, HTML, and CSS. What was chalenging The most challenging part of making this project for me was the JavaScript. I am quite new to JavaScript and coding things like the earth using three.js was very new to be and it took some time and learning. Also I the styling wasnāt nessisary hard, however I would say that I am not the best at it, so it took also some time to get it too look nice. What am I most proud of I am most proud of making advanced features to my webOS such as a, tiger habitat and population graph and a 3d earth and stars using three.js. I am proud of learning more about JavaScript syntax and how to properly debugg and fix stuff when I have a problem. What should people know about my project It runs completely on the web, so no installing or any local host is needed. Just click on the link either in my project description or in the README.md. I would suggest reading though my README and other devlogs, I know that they are a bit long, so you donāt need to read all of them just skim through and get the jist of what I have done. Thank you for taking the time to read through, It would be really helpful for me if your left good reviews and ratings, that would help me further improve on my coding journey.", "repo": "https://github.com/rayan123-4/My-WebOS-Stardance", "demo": "https://stardancetigeros.site/"}, {"ship_num": 2, "ts": "2026-09-27T23:41:52Z", "hours": 50.0, "multiplier": 2.32, "payout": 115, "blessing": "neutral", "text": "I made TigerOS, a tiger themed WebOS made for the WebOS Stardance mission. I made it using HTML, CSS, and Javascript. It has many features such as, a real time weather app, a working calculator app, a snake game app, a paint canvas app, sounds, special effects, and the list goes on. The most challenging part of making this, was getting everything to work smoothly how I want it with no errors. Probably the hardest thing that I made was the weather API app, since I had never worked with an API before it was very challenging, but I learnt a lot. I am very proud of how it came out, and that all my apps and features work to how I want it. I didnāt think I would make it this far to have so many cool stuff, but I am very happy with my final product. I suggest that anyone wanting to try out my site, they should test out all of the apps and the features. I also encourage you to find the hidden secret feature. However, it should be pretty obvious to find. Test out all of the weather apps, and even try to beat my high score of 25 on the tiger snake game. Please take some time to explore TigerOS and leave a thoughtful review, as any feedback would really help me to improve. Thanks Stardance, for setting up this oportunity for me and everyone else.", "repo": "https://github.com/rayan123-4/My-WebOS-Stardance", "demo": "https://stardancetigeros.site/"}, {"ship_num": 3, "ts": "2026-09-04T21:53:15Z", "hours": 7.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made my first WebOS. It was very difficult and challenging to make, but the jams guide made it much more easier to get started with and finish. The site currently has 2 apps, but there will be more to come in the future.", "repo": "https://github.com/rayan123-4/My-WebOS-Stardance", "demo": "https://stardancetigeros.site/"}]...
|
[{"post_id": 82515, "ts": "202 [{"post_id": 82515, "ts": "2026-10-25T03:07:17Z", "hours": 0.7139, "text": "Devlog 52: Just tiding up my code with comments and editing the README.md Just tiding up my code, adding comments and making sure it all looks nice for the ship. I have learn a lot from making this project and I am happy with how it turned out. This will be my final devlog, and so please give me good ratings and feedback, so that I can learn and improve."}, {"post_id": 82137, "ts": "2026-10-24T02:07:18Z", "hours": 0.8194, "text": "Devlog 51: Adding stars, realistic tilt, and better quality textures to the 3D earth. I added 2000 stars to the earth window and even made a realistic tilt for the earth, like how it is in real life. I think that the stars made a big impact on the overall feel of the window, and makes it look much better. I also added a 8k quality texture onto the earth model instead of a 2k quality texture, so that the earth would be more clearer to see."}, {"post_id": 81962, "ts": "2026-10-23T06:09:26Z", "hours": 2.1297, "text": "Devlog 50: Adding new 3D Tiger Earth window. I added a new window made with three.js, that is a 3D globe of the world that is, movable, rotatable, and zoom in able. I also added a feature where you can stop the rotation, so that its easier to view (And find the hidden Tiger). First I made the 3D circle and of the globe and then added the texture and animations. What did I learn and what was difficult. This is my first time making a project like a 3D thing, so I was a bit new to this. Now I have learnt much more about how to make 3D projects like this and I hope I can make many more simulation projects like this in the future."}, {"post_id": 81186, "ts": "2026-10-20T07:19:14Z", "hours": 2.155, "text": "Devlog 49: Adding tiger population chart window and UI polishing. I added a new window that shows the tiger population in the countries Russia, Nepal, and India. The data points are the milestones of there tiger conservation across 2010 to 2016 to 2022. The chart is a line graph and the 3 line variables are the countries. The chart looks very good and I am happy with how it turned out. I also polished more of my webOS using nice fonts such as āFira Sansā, āBoldā, and āItalicā. I styled it and made sure across my webOS there was a orange, black, and white theme, like the tigers colors. What did I learn and what was difficult The most difficult part of it was debugging everything when I found errors. I learnt the functions for making a graph in JavaScript and how to get data and put it into a graph using code, while still making it look nice. This helps me a lot especially for more projects I might do in the future using data and statistics."}, {"post_id": 79494, "ts": "2026-10-14T09:29:47Z", "hours": 1.8556, "text": "Devlog 48: Updating the CSS styling and improving the interface visibility. I edited the CSS stying adding more things such as box-shadow and different color border. I made sure the web os looked good and wasnāt too heavily colored, that might make the text less easy to read. I also fixed the minimize button in the link window since it was off centered, because of the small size of it compared to the normal window sized ones. Difficulty: For me to be honest, this was difficult not because of like syntax and stuff, but because Iām not very good at styling. I tried to like make it pop and look extra good, and I think I have done well."}, {"post_id": 77180, "ts": "2026-10-05T23:23:31Z", "hours": 1.5567, "text": "Devlog 47: Add text on icon hover, that displays window name. I made it so that when you hover over the icons in the icon bar, it will show the name of the window that the icon is connected to. This makes it easier for users to know what icon goes to which window, without guesses based on the icon image. What did I learn and what was difficult. At first I thought that making this would only need a bit of HTML and CSS, and normally it would. However I came upon a problem and CSS wasnāt fixing it, nor was the HTML, so I had to adapt and use Javascript to fix my error. Eventually it worked out in the end, and not much Javascipt was actually needed. This helped me to learn how to fix errors outside of the box, and too try different ways to fix them. This helped me learn more about problem solving and debugging, which will help me in future projects."}, {"post_id": 76578, "ts": "2026-10-04T01:22:56Z", "hours": 0.6781, "text": "Devlog 46: Edited some of the CSS styling on the windows and top bar. I edited the CSS styling on things like the, text, the windows, and the top bar. I used functions such as, text-shadow and box-shadow, to make text and windows stand out and look much nicer. I also edited the border color and size of many things to make them either pop or, look better in between colors. Things like animations scale and filter, also helped make it look much more appealing. What did I learn and how difficult was it I learnt more about CSS styling and how to make project look extra nice. I was playing around with the CSS learning new mechanics and functions, to help make different things and parts of project look more nicer and clean. This was fairly easy and I didnāt have any trouble with doing so."}, {"post_id": 76381, "ts": "2026-10-03T11:06:48Z", "hours": 1.8306, "text": "Devlog 45: Added a lot of in depth comments to my Javascript file. And adding a download button to the paint window. I went through my Javascript code and worked on improving my comments and adding more, where they were needed. I focused on being very descriptive with my comments, explaining what things do and how. I also added some hover animations to the paint board buttons. Download button added I added a download button to my paint window. I made it so when the user clicks the button, the browser download trigger is activated and the image is downloaded. I did this in Javascript using toDataURL(). Diffuculty Making the comments was fairly easy, as I just went to important parts with no comments and added explanations about them. Also the Javascript for the download button wasnāt too hard, and I think I am learning more and more about Javascript, which is helping make it easier and easier."}, {"post_id": 75997, "ts": "2026-10-01T23:50:08Z", "hours": 0.9978, "text": "Devlog 44: Fixed a z-index error, adjusted the colors and styling I found a z-index error in the Javascript file, where the images when opened, wouldnāt go to the highest z-index, so I just added z-index 99 when window open. I also mainly adjusted the colors, experimenting in CSS, to get the best design and the best text to background ratio in CSS. Difficulty Not too bad, because I didnāt have to go through hidden Javascript syntax errors and stuff, so it was mostly stuff I could just look around for a bit until I find the missing parenthesis or something."}, {"post_id": 75845, "ts": "2026-10-01T10:11:49Z", "hours": 0.7925, "text": "Devlog 43: Fix camera animation Fixing the camera animation, making it so the user cannot spam open the window, making the animation run for however many times the user tapped the icon. Difficulty It wasnāt too hard to do, just needed to make some simple if statement to check if the window had been opened. Edited Also adjusted some styling in the map window making the text hover change in css."}, {"post_id": 75429, "ts": "2026-09-30T02:17:24Z", "hours": 0.7275, "text": "Devlog 42: Minimizer button Added a minimizer button to all of the windows. I made it so that when users press the button, the hover filter glow will show on the corrisponding icon, to let users know the window is open. Difficulty This was fairly simple to do, and I just had to make some code for it in the same place near the close button in the Javascript."}, {"post_id": 75148, "ts": "2026-09-29T09:16:19Z", "hours": 1.8561, "text": "Devlog 41: Styling the windows, making it look nice Fixed some of the styling on the windows, specifically on the manual window and the welcome window, since my rating said they looked like a power point. Trying to make my website look much cleaner and have a better design."}, {"post_id": 75046, "ts": "2026-09-29T00:06:01Z", "hours": 1.8983, "text": "Devlog 40: Camera Animation Added Added a camera flash animation when you open the gallery app. It was quiet hard to make flash show after the camera image, but it works well."}, {"post_id": 74671, "ts": "2026-09-27T23:27:05Z", "hours": 0.6822, "text": "Devlog 39: May be Last Devlog This is going to probably be my final devlog until I ship. I have enjoyed making this project and I hope that I can maybe make it better in the future. This video shows all of my windows and stuff."}, {"post_id": 74374, "ts": "2026-09-27T08:22:51Z", "hours": 0.7228, "text": "Devlog 38: Finishing touches Adding finishing touches to my WebOS such as fixing code to work better. Making it so if you tap a window that is behind another window, it gets moved to the front. And some other fixes."}, {"post_id": 74260, "ts": "2026-09-27T02:46:44Z", "hours": 1.2206, "text": "Devlog 37: Icon hover response Finsished making the icons hover display to stay on the icon image, if the corrisponding window is still open. Once the window is closed the style goes back to normal, but still if you hover it will have the style."}, {"post_id": 73487, "ts": "2026-09-25T07:05:36Z", "hours": 0.6139, "text": "Devlog 36: Adding a link window Creating a link window that has multiple links. The window is closable and it uses the same functions as the other windows except that you cannot drag it."}, {"post_id": 73053, "ts": "2026-09-24T08:54:47Z", "hours": 1.0725, "text": "Devlog 35: Fixed many usability errors that I had such as Making boundaries for dragging the window. Making the scroll app bar optimize for different window sizes. Fixing a bug where you can play all roar sounds at once and they overlap. And a few random glitched that I found while trying to fix these."}, {"post_id": 72578, "ts": "2026-09-23T08:39:47Z", "hours": 0.3111, "text": "Devlog 34: Adding information to manual window Just adding some more information to my Manual, for the new things that I have made. This is where users can find information about different features in my website. I wrote it all myself."}, {"post_id": 72139, "ts": "2026-09-22T09:13:19Z", "hours": 1.8511, "text": "Devlog 33: Adding undo button to paint window Added the undo button and made it so that it will undo lines, fill, and clear. This means that if you accidently fill your work or clear it you can press undo and it will bring it back :). Works for multiple times, because it saves it in a array. I am very happy with how it came out, because it was quite challenging to make."}, {"post_id": 72113, "ts": "2026-09-22T06:08:49Z", "hours": 1.085, "text": "Devlog 32: Adding the paint window My Tiger Masterpiece! Finally finished making the paint board window. I also fixed a few bugs that I had with the drag header, and it not working. Im going to add the title to this soon and also I will add an undo button incase you accedently delete your Tiger mona lisa."}, {"post_id": 71686, "ts": "2026-09-21T09:48:24Z", "hours": 2.8558, "text": "Devlog 31: Making the drawing window function Making drawing window. Donāt mind why it looks weird right now, I will fix it later. Also I spent a lot of time trying to fix some hidden error I didnāt know where it was and I was totally confused, so I went back a commit and put my working code back and it fixed. I think I am going to wrap up my project soon, so that I donāt create more project breaking errors."}, {"post_id": 71121, "ts": "2026-09-20T10:10:32Z", "hours": 0.9147, "text": "Devlog 30: Finally made the calculator window Idk how I managed to make it, but maybe the tutorial I was watching before was just not it. However, this one is: ( https://youtu.be/KM8PIiqq97c?si=RgpvGnOKA7ZbfZoQ ). Anyone wanting to make a good calculator, check out that tutorial because he saved me! Thanks KennyYipCoding on youtube. Also surprisingly simple."}, {"post_id": 71089, "ts": "2026-09-20T08:57:41Z", "hours": 4.3286, "text": "Devlog 29: Struggling on the calculator window 4 hours down the drain. I worked for 4 hours trying to get a simple thing like a calculator to work. Some how it kept not working even when I followed a tutorial correctly. I will try again tomorrow maybe with a different tutorial, but honestly idk what happend. Also part of it was me trying to code in python and that turned out a disaster, but then I went to JavaScript and still didnāt work??. I know it might seem weird and also stardance if your reading this you can like delete the 4 hours or whatever from my thing Incase idk if this is fraud or something."}, {"post_id": 70477, "ts": "2026-09-19T08:14:43Z", "hours": 1.3042, "text": "Devlog 28: Added achievement alert Added some nice animations to stuff and added a achievement/alert for the snake game, when you hit a specific score."}, {"post_id": 70364, "ts": "2026-09-19T01:39:36Z", "hours": 2.1081, "text": "Devlog 27: Designing the snake game window Design on the Tiger Snake Game app is finished. I added the instructions in the manual app, but the game is pretty simple to play. I added a skin feature in case the stripes moving are a bit hard on some peoples eyes. I added the high score tracker which saves your high score even if you close the tab. And just fixed the lay out made it look nice."}, {"post_id": 70309, "ts": "2026-09-18T22:15:48Z", "hours": 3.1364, "text": "Devlog 26: Finished adding the tiger snake game Finished making my Tiger snake game. I watched a very good and easy tutorial, link: ( https://youtu.be/Je0B3nHhKmM?si=DQiSr36gDDSM3Psj ) I still need to design it more to make it look more like a real Tiger snake, like the logo if you can see all the way down there. I think also I could make some Instructions and a highscore button, so that will be for next time."}, {"post_id": 69938, "ts": "2026-09-18T03:03:26Z", "hours": 0.63, "text": "Devlog 25: Secret button editing Just added the hover glow to the secret button so you can be more sure your on something special. So far I think my project is close to the end and I just need to do now fixing up to make perfect . And maybe even an extra feature. This is what the front of my page looks like (there more apps and features, the app side bar is scrollable, as you can see from my other devlogs)."}, {"post_id": 69069, "ts": "2026-09-16T10:01:51Z", "hours": 1.5325, "text": "Devlog 24: Added the secret button Finished Adding the Secret feature! I cannot show you yet because itās secret, but you could try and find it on my site (Itās not that hard its pretty obvious to find the secret). Also I added a ding when you find the secret and as you can see the alert in the image at the bottom, so you will know if you found it."}, {"post_id": 68559, "ts": "2026-09-15T10:07:36Z", "hours": 2.4817, "text": "Devlog 23: Making the weather window look nice Made the weather app have a default weather image now, but when the user inputs city it will change to the correct one. Also as you can see I made the handle a starling, and also in the bottom right corner there is 3 of them. The handle starling is for all of the windows and is how you drag, by holding it. That is for something I am making right now, however I am not finsihed yet. Just trying to make my website look as good as possible right now, while keeping the simple theme. (edit: I actually just realized that this devlog is exactly 1 second longer than the previous one)."}, {"post_id": 67978, "ts": "2026-09-14T09:38:41Z", "hours": 2.4814, "text": "Devlog 22: Designing the manual window, welcome window, and other windows Finished designing the manual app. It looks not too bad. Also I edit the welcome window bit, but I still have some work to do, to make it stand out. This took a while as I was playing around with the CSS also fixing other windows and stuff."}, {"post_id": 67070, "ts": "2026-09-13T03:43:12Z", "hours": 0.9197, "text": "Devlog 21: Adding content to manual window Just added some information into the Manual app. Im not finished yet, I still need to make it look nicer. I will add some images and stuff to it next."}, {"post_id": 66369, "ts": "2026-09-12T05:10:30Z", "hours": 2.5203, "text": "Devlog 20: Added icon side bar, making new window, and fixing roar sound errors Finished making the side bar with the icons. The side bar is scrollable, because I had too many icons and so that keeps them stored there better. I also started making the manual window, but I havenāt added any content yet. I also fixed some errors such as, the roar sound button would keep playing, even when the window was closed, so I thought it might be better if it stopped the sound when the sound window is closed. I also fixed some other errors and stuff, but everything looks good now."}, {"post_id": 65841, "ts": "2026-09-11T07:50:12Z", "hours": 0.9428, "text": "Devlog 19: Real working weather window added Finally finished the weather window. It was very hard to do for me. Iām not done yet I still need to edit it to make the design look more good. The api works, and it runs smoothly. Need to change a few things also like the app icon side bar. Used a bit of AI to learn how to set up the api, since I was using a different one than the tutorial, it was much harder, but still uses same main core code. Overall I am happy with how It turned out. Thereās still a lot to improve on, however I learn a lot from this."}, {"post_id": 65744, "ts": "2026-09-11T03:05:00Z", "hours": 0.3494, "text": "Devlog 18: Adding fun fact window app icon Adding fun fact window app icon, and fixing some other stuff finished up the window. This is for the old weather window that I gave up on, that is now gonna be a weather fun fact window. I will still have both windows, its just one will be for a fun fact and one for a working API weather app."}, {"post_id": 65297, "ts": "2026-09-10T10:38:52Z", "hours": 0.8128, "text": "Devlog 17: Trying to make Working Weather window again Trying again to make a real working weather window. Im still gonna keep the other one as like a cool fact, but this one is gonna work. I have found a good tutorial and I am really trying to make this work."}, {"post_id": 65212, "ts": "2026-09-10T05:52:50Z", "hours": 1.5169, "text": "Devlog 16: Scratch the weather API idea Slight change in idea. No more weather api. Its a static window that shows the hottest day in Madhya Pradesh, home to the highest population of tigers in an Indian state. Looks pretty nice though."}, {"post_id": 65078, "ts": "2026-09-09T23:01:26Z", "hours": 1.1167, "text": "Devlog 15: Started trying to make weather window Just started making a new weather window. Iām 15 minutes through the tutorial and now I need to add the api. I have never used an API before so this might be hard."}, {"post_id": 64670, "ts": "2026-09-09T08:08:11Z", "hours": 2.3972, "text": "Devlog 14: Adding comments to js and making new window Finally finished sorting out my code so its easier to move and navigate around, using comments and stuff. I also made this Tiger information window, that shows some interesting information and facts about tigers. The window is scrollable and there is more information below this. Took me a while to do all of this and find information and stuff, but it looks like it turned out not too bad."}, {"post_id": 64472, "ts": "2026-09-08T21:55:55Z", "hours": 0.9753, "text": "Devlog 13: Adding comments to my CSS Just sorting out my CSS so its easier to read. Adding comments and making specific parts for different windows and features so that they are easy to find."}, {"post_id": 64030, "ts": "2026-09-08T04:39:41Z", "hours": 1.3342, "text": "Devlog 12: Added start up animation Made an animation on site startup. The text comes in from the left and then the tiger drops down. It wasnāt too hard, but I did find some struggle. I used Canva to make the design for the banner here and in my README are the credits to all of the photos and resources I have used from other people."}, {"post_id": 63439, "ts": "2026-09-07T09:04:16Z", "hours": 2.1725, "text": "Devlog 11: Added dark/light mode switcher feature Just made a dark/light mode switcher in the settings window. Also if you close the tab it will stay the way you left it (This is the same for the background switcher as well). I also fixed many of the errors that I had, such as it not saving."}, {"post_id": 62754, "ts": "2026-09-06T08:40:59Z", "hours": 0.5739, "text": "Devlog 10: Making an images and audio file, and fixing a few errors Just fixing an few errors and tidying things up. I had a few errors in my code so I just fixed that and then made my images and audio files more neater."}, {"post_id": 62556, "ts": "2026-09-06T00:26:52Z", "hours": 2.5967, "text": "Devlog 9: Added a settings window with a background changer Finally finished the settings window. Its a background changer and it took so long to make and even longer to layout. The background changer works perfectly and looks good in both backgrounds. Was a bit hard though."}, {"post_id": 62022, "ts": "2026-09-05T07:17:22Z", "hours": 1.5619, "text": "Devlog 8: Added a new tiger map window Added Tiger species habitat map. It shows where different Tiger species live and a bit more info. (Image from Wildlife foundation in Thailand (WFFT))."}, {"post_id": 61964, "ts": "2026-09-05T04:49:42Z", "hours": 0.9481, "text": "Devlog 7: Added multiple sound effects Added some different Tiger species sounds to the window, so you can see the slight differences and similarities. First Devlog after first ship."}, {"post_id": 61803, "ts": "2026-09-04T21:49:12Z", "hours": 0.4042, "text": "Devlog 6: Readme added Readme Added now ready to ship (There is more to the Readme than the image shows). The README includes information about my website and how I made it."}, {"post_id": 61420, "ts": "2026-09-04T10:10:11Z", "hours": 1.6531, "text": "Devlog 5: New window added - roar sound effect Added a working Tiger roar sound effect button to a new window. When you press the button is makes a roar sound effect."}, {"post_id": 61318, "ts": "2026-09-04T05:17:55Z", "hours": 2.0894, "text": "Devlog 4: Adding tiger gallery window Added a new photo gallery window to my site. There is also now a close button that closes the window, and I finished the tutorial this is just what I made instead of the tutorials other window, but it uses the same properties."}, {"post_id": 60735, "ts": "2026-09-03T09:19:54Z", "hours": 2.0831, "text": "Devlog 3: Adding drag and open buttons Added the drag buttons to the window, also added the open button as you can see in the top left corner. I made this In JavaScript using event listeners .On part 4 of the guide."}, {"post_id": 60545, "ts": "2026-09-02T23:07:05Z", "hours": 0.3536, "text": "Devlog 2: Adding the working date/time Adding a working date/time at the top right corner. It updates live according to where you live. Still on the tutorial."}, {"post_id": 60127, "ts": "2026-09-02T09:31:06Z", "hours": 0.4903, "text": "Devlog 1: The start of my WebOS Making my first WebOS. Finished part one of the tutorial. hereās what it looks like right now."}]...
|
Title: Tiger OS by @Rayan123-4 | Stardance
Devlog Title: Tiger OS by @Rayan123-4 | Stardance
Devlogs:
Devlog 1: The start of my WebOS Making my first WebOS. Finished part one of the tutorial. hereās what it looks like right now.
Devlog 2: Adding the working date/time Adding a working date/time at the top right corner. It updates live according to where you live. Still on the tutorial.
Devlog 3: Adding drag and open buttons Added the drag buttons to the window, also added the open button as you can see in the top left corner. I made this In JavaScript using event listeners .On part 4 of the guide.
Devlog 4: Adding tiger gallery window Added a new photo gallery window to my site. There is also now a close button that closes the window, and I finished the tutorial this is just what I made instead of the tutorials other window, but it uses the same properties.
Devlog 5: New window added - roar sound effect Added a working Tiger roar sound effect button to a new window. When you press the button is makes a roar sound effect.
Devlog 6: Readme added Readme Added now ready to ship (There is more to the Readme than the image shows). The README includes information about my website and how I made it.
Devlog 7: Added multiple sound effects Added some different Tiger species sounds to the window, so you can see the slight differences and similarities. First Devlog after first ship.
Devlog 8: Added a new tiger map window Added Tiger species habitat map. It shows where different Tiger species live and a bit more info. (Image from Wildlife foundation in Thailand (WFFT)).
Devlog 9: Added a settings window with a background changer Finally finished the settings window. Its a background changer and it took so long to make and even longer to layout. The background changer works perfectly and looks good in both backgrounds. Was a bit hard though.
Devlog 10: Making an images and audio file, and fixing a few errors Just fixing an few errors and tidying things up. I had a few errors in my code so I just fixed that and then made my images and audio files more neater.
Devlog 11: Added dark/light mode switcher feature Just made a dark/light mode switcher in the settings window. Also if you close the tab it will stay the way you left it (This is the same for the background switcher as well). I also fixed many of the errors that I had, such as it not saving.
Devlog 12: Added start up animation Made an animation on site startup. The text comes in from the left and then the tiger drops down. It wasnāt too hard, but I did find some struggle. I used Canva to make the design for the banner here and in my README are the credits to all of the photos and resources I have used from other people.
Devlog 13: Adding comments to my CSS Just sorting out my CSS so its easier to read. Adding comments and making specific parts for different windows and features so that they are easy to find.
Devlog 14: Adding comments to js and making new window Finally finished sorting out my code so its easier to move and navigate around, using comments and stuff. I also made this Tiger information window, that shows some interesting information and facts about tigers. The window is scrollable and there is more information below this. Took me a while to do all of this and find information and stuff, but it looks like it turned out not too bad.
Devlog 15: Started trying to make weather window Just started making a new weather window. Iām 15 minutes through the tutorial and now I need to add the api. I have never used an API before so this might be hard.
Devlog 16: Scratch the weather API idea Slight change in idea. No more weather api. Its a static window that shows the hottest day in Madhya Pradesh, home to the highest population of tigers in an Indian state. Looks pretty nice though.
Devlog 17: Trying to make Working Weather window again Trying again to make a real working weather window. Im still gonna keep the other one as like a cool fact, but this one is gonna work. I have found a good tutorial and I am really trying to make this work.
Devlog 18: Adding fun fact window app icon Adding fun fact window app icon, and fixing some other stuff finished up the window. This is for the old weather window that I gave up on, that is now gonna be a weather fun fact window. I will still have both windows, its just one will be for a fun fact and one for a working API weather app.
Devlog 19: Real working weather window added Finally finished the weather window. It was very hard to do for me. Iām not done yet I still need to edit it to make the design look more good. The api works, and it runs smoothly. Need to change a few things also like the app icon side bar. Used a bit of AI to learn how to set up the api, since I was using a different one than the tutorial, it was much harder, but still uses same main core code. Overall I am happy with how It turned out. Thereās still a lot to improve on, however I learn a lot from this.
Devlog 20: Added icon side bar, making new window, and fixing roar sound errors Finished making the side bar with the icons. The side bar is scrollable, because I had too many icons and so that keeps them stored there better. I also started making the manual window, but I havenāt added any content yet. I also fixed some errors such as, the roar sound button would keep playing, even when the window was closed, so I thought it might be better if it stopped the sound when the sound window is closed. I also fixed some other errors and stuff, but everything looks good now.
Devlog 21: Adding content to manual window Just added some information into the Manual app. Im not finished yet, I still need to make it look nicer. I will add some images and stuff to it next.
Devlog 22: Designing the manual window, welcome window, and other windows Finished designing the manual app. It looks not too bad. Also I edit the welcome window bit, but I still have some work to do, to make it stand out. This took a while as I was playing around with the CSS also fixing other windows and stuff.
Devlog 23: Making the weather window look nice Made the weather app have a default weather image now, but when the user inputs city it will change to the correct one. Also as you can see I made the handle a starling, and also in the bottom right corner there is 3 of them. The handle starling is for all of the windows and is how you drag, by holding it. That is for something I am making right now, however I am not finsihed yet. Just trying to make my website look as good as possible right now, while keeping the simple theme. (edit: I actually just realized that this devlog is exactly 1 second longer than the previous one).
Devlog 24: Added the secret button Finished Adding the Secret feature! I cannot show you yet because itās secret, but you could try and find it on my site (Itās not that hard its pretty obvious to find the secret). Also I added a ding when you find the secret and as you can see the alert in the image at the bottom, so you will know if you found it.
Devlog 25: Secret button editing Just added the hover glow to the secret button so you can be more sure your on something special. So far I think my project is close to the end and I just need to do now fixing up to make perfect . And maybe even an extra feature. This is what the front of my page looks like (there more apps and features, the app side bar is scrollable, as you can see from my other devlogs).
Devlog 26: Finished adding the tiger snake game Finished making my Tiger snake game. I watched a very good and easy tutorial, link: ( https://youtu.be/Je0B3nHhKmM?si=DQiSr36gDDSM3Psj ) I still need to design it more to make it look more like a real Tiger snake, like the logo if you can see all the way down there. I think also I could make some Instructions and a highscore button, so that will be for next time.
Devlog 27: Designing the snake game window Design on the Tiger Snake Game app is finished. I added the instructions in the manual app, but the game is pretty simple to play. I added a skin feature in case the stripes moving are a bit hard on some peoples eyes. I added the high score tracker which saves your high score even if you close the tab. And just fixed the lay out made it look nice.
Devlog 28: Added achievement alert Added some nice animations to stuff and added a achievement/alert for the snake game, when you hit a specific score.
Devlog 29: Struggling on the calculator window 4 hours down the drain. I worked for 4 hours trying to get a simple thing like a calculator to work. Some how it kept not working even when I followed a tutorial correctly. I will try again tomorrow maybe with a different tutorial, but honestly idk what happend. Also part of it was me trying to code in python and that turned out a disaster, but then I went to JavaScript and still didnāt work??. I know it might seem weird and also stardance if your reading this you can like delete the 4 hours or whatever from my thing Incase idk if this is fraud or something.
Devlog 30: Finally made the calculator window Idk how I managed to make it, but maybe the tutorial I was watching before was just not it. However, this one is: ( https://youtu.be/KM8PIiqq97c?si=RgpvGnOKA7ZbfZoQ ). Anyone wanting to make a good calculator, check out that tutorial because he saved me! Thanks KennyYipCoding on youtube. Also surprisingly simple.
Devlog 31: Making the drawing window function Making drawing window. Donāt mind why it looks weird right now, I will fix it later. Also I spent a lot of time trying to fix some hidden error I didnāt know where it was and I was totally confused, so I went back a commit and put my working code back and it fixed. I think I am going to wrap up my project soon, so that I donāt create more project breaking errors.
Devlog 32: Adding the paint window My Tiger Masterpiece! Finally finished making the paint board window. I also fixed a few bugs that I had with the drag header, and it not working. Im going to add the title to this soon and also I will add an undo button incase you accedently delete your Tiger mona lisa.
Devlog 33: Adding undo button to paint window Added the undo button and made it so that it will undo lines, fill, and clear. This means that if you accidently fill your work or clear it you can press undo and it will bring it back :). Works for multiple times, because it saves it in a array. I am very happy with how it came out, because it was quite challenging to make.
Devlog 34: Adding information to manual window Just adding some more information to my Manual, for the new things that I have made. This is where users can find information about different features in my website. I wrote it all myself.
Devlog 35: Fixed many usability errors that I had such as Making boundaries for dragging the window. Making the scroll app bar optimize for different window sizes. Fixing a bug where you can play all roar sounds at once and they overlap. And a few random glitched that I found while trying to fix these.
Devlog 36: Adding a link window Creating a link window that has multiple links. The window is closable and it uses the same functions as the other windows except that you cannot drag it.
Devlog 37: Icon hover response Finsished making the icons hover display to stay on the icon image, if the corrisponding window is still open. Once the window is closed the style goes back to normal, but still if you hover it will have the style.
Devlog 38: Finishing touches Adding finishing touches to my WebOS such as fixing code to work better. Making it so if you tap a window that is behind another window, it gets moved to the front. And some other fixes.
Devlog 39: May be Last Devlog This is going to probably be my final devlog until I ship. I have enjoyed making this project and I hope that I can maybe make it better in the future. This video shows all of my windows and stuff.
Devlog 40: Camera Animation Added Added a camera flash animation when you open the gallery app. It was quiet hard to make flash show after the camera image, but it works well.
Devlog 41: Styling the windows, making it look nice Fixed some of the styling on the windows, specifically on the manual window and the welcome window, since my rating said they looked like a power point. Trying to make my website look much cleaner and have a better design.
Devlog 42: Minimizer button Added a minimizer button to all of the windows. I made it so that when users press the button, the hover filter glow will show on the corrisponding icon, to let users know the window is open. Difficulty This was fairly simple to do, and I just had to make some code for it in the same place near the close button in the Javascript.
Devlog 43: Fix camera animation Fixing the camera animation, making it so the user cannot spam open the window, making the animation run for however many times the user tapped the icon. Difficulty It wasnāt too hard to do, just needed to make some simple if statement to check if the window had been opened. Edited Also adjusted some styling in the map window making the text hover change in css.
Devlog 44: Fixed a z-index error, adjusted the colors and styling I found a z-index error in the Javascript file, where the images when opened, wouldnāt go to the highest z-index, so I just added z-index 99 when window open. I also mainly adjusted the colors, experimenting in CSS, to get the best design and the best text to background ratio in CSS. Difficulty Not too bad, because I didnāt have to go through hidden Javascript syntax errors and stuff, so it was mostly stuff I could just look around for a bit until I find the missing parenthesis or something.
Devlog 45: Added a lot of in depth comments to my Javascript file. And adding a download button to the paint window. I went through my Javascript code and worked on improving my comments and adding more, where they were needed. I focused on being very descriptive with my comments, explaining what things do and how. I also added some hover animations to the paint board buttons. Download button added I added a download button to my paint window. I made it so when the user clicks the button, the browser download trigger is activated and the image is downloaded. I did this in Javascript using toDataURL(). Diffuculty Making the comments was fairly easy, as I just went to important parts with no comments and added explanations about them. Also the Javascript for the download button wasnāt too hard, and I think I am learning more and more about Javascript, which is helping make it easier and easier.
Devlog 46: Edited some of the CSS styling on the windows and top bar. I edited the CSS styling on things like the, text, the windows, and the top bar. I used functions such as, text-shadow and box-shadow, to make text and windows stand out and look much nicer. I also edited the border color and size of many things to make them either pop or, look better in between colors. Things like animations scale and filter, also helped make it look much more appealing. What did I learn and how difficult was it I learnt more about CSS styling and how to make project look extra nice. I was playing around with the CSS learning new mechanics and functions, to help make different things and parts of project look more nicer and clean. This was fairly easy and I didnāt have any trouble with doing so.
Devlog 47: Add text on icon hover, that displays window name. I made it so that when you hover over the icons in the icon bar, it will show the name of the window that the icon is connected to. This makes it easier for users to know what icon goes to which window, without guesses based on the icon image. What did I learn and what was difficult. At first I thought that making this would only need a bit of HTML and CSS, and normally it would. However I came upon a problem and CSS wasnāt fixing it, nor was the HTML, so I had to adapt and use Javascript to fix my error. Eventually it worked out in the end, and not much Javascipt was actually needed. This helped me to learn how to fix errors outside of the box, and too try different ways to fix them. This helped me learn more about problem solving and debugging, which will help me in future projects.
Devlog 48: Updating the CSS styling and improving the interface visibility. I edited the CSS stying adding more things such as box-shadow and different color border. I made sure the web os looked good and wasnāt too heavily colored, that might make the text less easy to read. I also fixed the minimize button in the link window since it was off centered, because of the small size of it compared to the normal window sized ones. Difficulty: For me to be honest, this was difficult not because of like syntax and stuff, but because Iām not very good at styling. I tried to like make it pop and look extra good, and I think I have done well.
Devlog 49: Adding tiger population chart window and UI polishing. I added a new window that shows the tiger population in the countries Russia, Nepal, and India. The data points are the milestones of there tiger conservation across 2010 to 2016 to 2022. The chart is a line graph and the 3 line variables are the countries. The chart looks very good and I am happy with how it turned out. I also polished more of my webOS using nice fonts such as āFira Sansā, āBoldā, and āItalicā. I styled it and made sure across my webOS there was a orange, black, and white theme, like the tigers colors. What did I learn and what was difficult The most difficult part of it was debugging everything when I found errors. I learnt the functions for making a graph in JavaScript and how to get data and put it into a graph using code, while still making it look nice. This helps me a lot especially for more projects I might do in the future using data and statistics.
Devlog 50: Adding new 3D Tiger Earth window. I added a new window made with three.js, that is a 3D globe of the world that is, movable, rotatable, and zoom in able. I also added a feature where you can stop the rotation, so that its easier to view (And find the hidden Tiger). First I made the 3D circle and of the globe and then added the texture and animations. What did I learn and what was difficult. This is my first time making a project like a 3D thing, so I was a bit new to this. Now I have learnt much more about how to make 3D projects like this and I hope I can make many more simulation projects like this in the future.
Devlog 51: Adding stars, realistic tilt, and better quality textures to the 3D earth. I added 2000 stars to the earth window and even made a realistic tilt for the earth, like how it is in real life. I think that the stars made a big impact on the overall feel of the window, and makes it look much better. I also added a 8k quality texture onto the earth model instead of a 2k quality texture, so that the earth would be more clearer to see.
Devlog 52: Just tiding up my code with comments and editing the README.md Just tiding up my code, adding comments and making sure it all looks nice for the ship. I have learn a lot from making this project and I am happy with how it turned out. This will be my final devlog, and so please give me good ratings and feedback, so that I can learn and improve.
Ships:
I made my first WebOS. It was very difficult and challenging to make, but the jams guide made it much more easier to get started with and finish. The site currently has 2 apps, but there will be more to come in the future.
I made TigerOS, a tiger themed WebOS made for the WebOS Stardance mission. I made it using HTML, CSS, and Javascript. It has many features such as, a real time weather app, a working calculator app, a snake game app, a paint canvas app, sounds, special effects, and the list goes on. The most challenging part of making this, was getting everything to work smoothly how I want it with no errors. Probably the hardest thing that I made was the weather API app, since I had never worked with an API before it was very challenging, but I learnt a lot. I am very proud of how it came out, and that all my apps and features work to how I want it. I didnāt think I would make it this far to have so many cool stuff, but I am very happy with my final product. I suggest that anyone wanting to try out my site, they should test out all of the apps and the features. I also encourage you to find the hidden secret feature. However, it should be pretty obvious to find. Test out all of the weather apps, and even try to beat my high score of 25 on the tiger snake game. Please take some time to explore TigerOS and leave a thoughtful review, as any feedback would really help me to improve. Thanks Stardance, for setting up this oportunity for me and everyone else.
What did I make I made TigerOS, a web based operating system that it completely run on the web. Itās themed around tigers as you can see, and has many interesting features such a as a, weather API, a tiger habitat and population graph, a classic calculator, a tiger earth three.js simulator and many more amazing experiences to explore through. It is made using JavaScript, HTML, and CSS. What was chalenging The most challenging part of making this project for me was the JavaScript. I am quite new to JavaScript and coding things like the earth using three.js was very new to be and it took some time and learning. Also I the styling wasnāt nessisary hard, however I would say that I am not the best at it, so it took also some time to get it too look nice. What am I most proud of I am most proud of making advanced features to my webOS such as a, tiger habitat and population graph and a 3d earth and stars using three.js. I am proud of learning more about JavaScript syntax and how to properly debugg and fix stuff when I have a problem. What should people know about my project It runs completely on the web, so no installing or any local host is needed. Just click on the link either in my project description or in the README.md. I would suggest reading though my README and other devlogs, I know that they are a bit long, so you donāt need to read all of them just skim through and get the jist of what I have done. Thank you for taking the time to read through, It would be really helpful for me if your left good reviews and ratings, that would help me further improve on my coding journey....
|
1793504896.336247
|
1793591296.336247
|
|
21532
|
Real OS from scratch solo ( I named it NovaOS ) by Real OS from scratch solo ( I named it NovaOS ) by @tonyx | Stardance...
|
tonyx
|
1
|
0.36
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-19T14:29:13Z", "hours": 0.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "NovaOS is an experimental operating system built from scratch, designed to deeply explore how a full OS works. It includes a custom kernel, hardware drivers, a graphical interface system, a network stack, a file system, and a set of system applications. The project covers the entire stack, from low-level boot processes to the user environment, and is actively evolving with a modular architecture aimed at building a complete, structured, and extensible operating system.", "repo": "https://github.com/Juste1dev/NovaOS", "demo": "https://github.com/Juste1dev/NovaOS/releases/tag/TheOS"}]...
|
[{"post_id": 12498, "ts": "202 [{"post_id": 12498, "ts": "2026-06-20T12:32:43Z", "hours": 0.3558, "text": "Working on the users sessions updating and optimizing"}, {"post_id": 11919, "ts": "2026-06-19T13:07:58Z", "hours": 0.3125, "text": "Working On the web browser adding more tabs and shortcuts"}]...
|
Title: Real OS from scratch solo ( I named it Nova Title: Real OS from scratch solo ( I named it NovaOS ) by @tonyx | Stardance
Devlogs:
Working On the web browser adding more tabs and shortcuts
Working on the users sessions updating and optimizing
Ships:
NovaOS is an experimental operating system built from scratch, designed to deeply explore how a full OS works. It includes a custom kernel, hardware drivers, a graphical interface system, a network stack, a file system, and a set of system applications. The project covers the entire stack, from low-level boot processes to the user environment, and is actively evolving with a modular architecture aimed at building a complete, structured, and extensible operating system....
|
1793504892.2217488
|
1793591292.2217488
|
|
52830
|
j by @adityaeshan84 | Stardance
|
adityaeshan84
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: j by @adityaeshan84 | Stardance
|
1792727287.7558832
|
1793591287.7558832
|