|
66426
|
raspberry pi weather display by @pcsef40 | Stardan raspberry pi weather display by @pcsef40 | Stardance...
|
pcsef40
|
0
|
1.28
|
0
|
[]
|
[{"post_id": 74995, "ts": "202 [{"post_id": 74995, "ts": "2026-09-28T20:04:50Z", "hours": 1.285, "text": "some cable management… as you can see i dont have much to work with"}]...
|
Title: raspberry pi weather display by @pcsef40 | Title: raspberry pi weather display by @pcsef40 | Stardance
Devlogs:
some cable management… as you can see i dont have much to work with...
|
1793098349.0572212
|
1793703149.0572212
|
|
1983
|
rasterminal by @PavolUlicny | Stardance
|
PavolUlicny
|
1
|
470.39
|
8580
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-08T16:24:17Z", "hours": 449.0, "multiplier": 19.99, "payout": 8580, "blessing": "neutral", "text": "rasterminal rasterminal is a 3D model viewer in the terminal Why i decided to build it The original idea didn’t really have any big inspiration, I’ve just always been fascinated by the inner workings of 3D and how that all works. I’ve been wanting to build a project involving 3D for a while and I didn’t want to make just another program that uses libraries and GPU drivers to do all the work. So I came up with the idea: a software rasterizer that renders in the terminal! There are lots of TUIs and lots of boring old software rasterizer projects, so I just combined the two into something unique. And over time, I realized I could make it an actually useful tool, with no real competition: a 3D model viewer in the terminal. Sure, there are some similar projects on GitHub (like taigrr’s trophy), but none are actually usable with heavier models or support pixel graphics. What I learned I learned a lot. I really mean a lot. Anything from math and rendering to how terminals work and how to control them using escape sequences. I don’t want to sit here and name everything I learned over the period of the last 5 months, but I can confidently say that this project really taught me how much work goes into everyday software and how to actually develop and maintain a project professionally. The future of rasterminal The whole project is very far from done. You can see that from the latest release version: v0.1.0-alpha.2. I’ve got a lot of work to do and I’ve roughly got the major landmarks mapped out. Main things I definitely want to change/add at some point before v1 are: Add animation support (currently can only render still meshes) Complete the renderer (complete support for basically every feature of every format that makes sense to support) Add optional GPU acceleration (after I’m satisfied with everything else) Hardware / OS support Supports every major OS (Windows, Linux, MacOS, and any other POSIX-based OS, so practically everything), and every CPU that I could think of (any architecture, 32 or 64bit). You would have to actually try a to find a platform that it doesn’t support (most of the unsupported hardware are big-endian systems, which are basically phased out completely). This is one of the main goals of the project, so (almost) any modern machine with a terminal can run it. Special thanks Special thanks to anyone who followed, liked, helped, or otherwise supported the project in any way. I wouldn’t have had the motivation to push it this far if it wasn’t for you guys.", "repo": "https://github.com/PavolUlicny/rasterminal", "demo": "https://github.com/PavolUlicny/rasterminal/releases/tag/v0.1.0-alpha.2"}]...
|
[{"post_id": 70278, "ts": "202 [{"post_id": 70278, "ts": "2026-09-18T21:10:51Z", "hours": 6.11, "text": "Code quality and CI improvements Finally did the long overdue main loop refactor. The main loop is now way shorter, more readable and more testable. I just split off some of the main loop’s work into it’s own modules, which made them way better looking and also, since they are now standalone modules, actually testable. A big win for repo structure. In the process, I also replaced the input handling’s long if chain that made each character do it’s job with a switch statement. It’s more readable and theoretically faster, although since I compile it with -O3, it probably made no difference or an unnoticeable one at best. I also finally fixed the super long CI times. Until now, CI used to take ~50 minutes (depending on how fast the GitHub runner was) because of cppcheck. Everything else finished in under 10 minutes, but cppcheck stalled it for an hour. It was stalling in mesh_assimp.cpp (the assimp wrapper) for most of it’s runtime. I always thought it was because assimp is a very large library. So I experimented with it a little. I included everything I include in the wrapper into a test file with a little code and ran cppcheck on that. It finished in less than 10 seconds. Eventually, I found out it was somehow taking that long because the main loader function was too long and handled too much by itself. So i just refactored it into 3 separate functions, without changing the behavior at all. Somehow, I still don’t get why, it reduced the whole cppcheck run to 9 minutes. a more than 5x improvement, just because I split a function into more functions. I’m not complaining, but it’s definitely weird. CI is now way faster and adding new things is gonna be way smoother now."}, {"post_id": 68728, "ts": "2026-09-15T17:06:41Z", "hours": 6.6975, "text": "Miscellaneous fixes and improvements Fixed two races in platform code (one MacOS, one Windows) Removed build flags that disabled some compiler security hardening at the cost of a little performance Fixed the test framework to not freak out on NaN in near assertions Improved thread launching and handling in loaders and renderer So overall just boring fixes and improvements, nothing special."}, {"post_id": 66825, "ts": "2026-09-12T18:42:57Z", "hours": 8.5847, "text": "Refactored the platform layer The whole platform layer was just one file until now. Since I did a lot of work on it recently, it grew to over 2400 lines of code. It was super confusing and disorienting. So I decided to refactor it (split it) into 8 files, based on what they handle: console.h - saving/restoring terminal state control.h - termination signal handling file.h - file operations (64bit) input_reader.h - handling input (not parsing, that is it’s own file) shared_memory.h - shared memory handling for the kitty protocol terminal_io.h - writes output to the terminal terminal_query.h - querying the terminal for things like graphics capability, etc. timing.h - frame timing and sleeps"}, {"post_id": 64252, "ts": "2026-09-08T14:55:07Z", "hours": 2.3467, "text": "Last pre-release checks and cleanup I’m finally ready to release v0.1.0-alpha.2. Only notable thing I changed here is that I changed the default thread count: It now defaults to hardware concurrency everywhere. Other than that, I of course did final documentation checks and fixes and now I’m just waiting for CI to pass so I can tag it and let the release workflow do the last step. So this is hopefully the last devlog before my ship!"}, {"post_id": 63837, "ts": "2026-09-07T20:19:19Z", "hours": 10.4164, "text": "Did some polish and cleanup of the platform layer Did final polish and cleanup of the platform layer since I want to actually finally cut a release relatively soon and I just did a lot of work there. Fixed things like useless tests, outdated or wrong comments and some platform specific quirks. Probably actually gonna cut a release soon (this time for real). Also added early rejections for BVH and CSM files, since they contain no model geometry (they can’t currently be displayed at all) and documented the change. The code is basically done (hopefully, I really don’t want to find another big gap that’s gonna take a week to close), I just want to correct anything wrong in the README, changelog, manpage or help menu and maybe make them look a little better before cutting a release and shipping."}, {"post_id": 62122, "ts": "2026-09-05T11:43:50Z", "hours": 9.5678, "text": "Working on SIGSTOP and SIGCONT handling SIGSTOP and SIGCONT are POSIX signals for stopping and resuming a running process. I’m working on adding handling for these, so you can safely pause and unpause rasterminal at any time. This is a lot of work, since until now, we just set up the terminal on program start and cleaned up when the program exited. There’s a lot of quirks and weird scenarios that I have to handle, for example if another signal gets sent while cleaning up the terminal for SIGSTOP. I’m trying to catch as many edge cases by just doing random things while using the program and also with the help of AI to come up with potentially uncaught scenarios."}, {"post_id": 59763, "ts": "2026-09-01T18:10:34Z", "hours": 4.3639, "text": "Added handling for SIGINT, SIGTERM, SIGQUIT and SIGHUP I don’t really have much to say here, I just added the full per-spec handling for all these. Only remaining POSIX-only gap is now SIGSTOP/SIGCONT (stop/resume process). I’m also starting school now, so I’ll be working on this less."}, {"post_id": 58964, "ts": "2026-08-31T15:12:04Z", "hours": 3.8394, "text": "Fully fixed and merged the first POSIX cleanup item Well, would you look at that! That took significantly less time than the Windows fix. It is partly because it was a smaller fix and only part whole POSIX fix, while the Windows one was the whole thing and also the foundation had already been laid out from the Windows work and I just integrated the POSIX path into that, but it is also very much because Microsoft is a horrible, terrible company that can’t make good software. I mean, look at GitHub, they have been going downhill ever since they got acquired by Microsoft. Now that I got that out of my system, here’s what was fixed: If the program cannot enable raw mode at startup, it safely fails instead of continuing and corrupting the terminal state If the cleanup gets interrupted, it retries cleanup so it doesn’t leave the terminal state corrupted after one failed attempt Onto the next POSIX fix: handling SIGQUIT and SIGHUP."}, {"post_id": 58269, "ts": "2026-08-30T17:14:59Z", "hours": 8.6936, "text": "Merged the full Windows console restoration branch My nightmare is over. I hopefully won’t have to deal with Windows for a while now. Summary of what is now fixed/handled on Windows: Ctrl+C, Ctrl+Break and Q exits fully recover the terminal’s state Ctrl+C and Ctrl+Break don’t leak mouse escape sequences into the next prompt if you terminate while actively dragging a model A bunch of other minor Windows or cmd.exe specific quirks Only thing that isn’t handled (didn’t find a good way to handle it) is task manager “end process”. It kills the program without cleaning up and sometimes freezes the shell."}, {"post_id": 56881, "ts": "2026-08-28T21:26:16Z", "hours": 9.6883, "text": "I HATE WINDOWS Windows just doesn’t work. It doesn’t work. Nothing works on Windows. Everything breaks. I don’t get it. THE UNIT TESTS PASS ON WINDOWS CI BUT WHEN I ACTUALLY RUN THE TESTS ON WINDOWS IT FAILS????? HOW IS THAT EVEN POSSIBLE. The release is now definitely getting delayed by at least a week because I keep running into more and more and more and more and more and more and more and more and more issues. I hate Windows. Microslop is the only company that could mess up a basic terminal emulator. And I also have to reboot my PC every time I fix something and push it and then reboot to get back to linux. this is torture. At one point I tried to do it on a Windows VM on linux but that was too slow so I just gave up."}, {"post_id": 55585, "ts": "2026-08-27T15:06:53Z", "hours": 8.8714, "text": "Found a bunch of terminal cleanup gaps Most of them are Windows or cmd.exe specific (nothing ever works on Windows), but some are present on POSIX too. The Windows specific ones are: cmd.exe for some unknown reason doesn’t turn off the raw input sequences, so arrow keys don’t work like they should, even though I explicitly turn it off (????????) (I hate Windows, they always have to do something unexplainable for no reason just so your code doesn’t work as it should) when you terminate the program with ctrl+c or ctrl+break while actively dragging the model around, it sometimes leaks mouse escape sequences into the next prompt bunch of other weird small stuff that nobody cares about And the few on POSIX are mostly ctrl+z suspend/resume behaviour not recovering the terminal and the same thing with ctrl+\\ (SIGQUIT). I’m still working on fixing these. Most of the windows ones are already fixed, but I haven’t even started with the linux/POSIX ones. I have postponed the planned release to when I fix these + any other issues I find."}, {"post_id": 54695, "ts": "2026-08-25T19:14:01Z", "hours": 10.7308, "text": "Cutting a release The repo is in a pretty complete and polished state, so I’ll cut a release here. This will also probably be the last release before I ship, so I’m making sure that nothing is broken and everything works on every platform. I’ve still got a lot of work to do though, even after the end of stardance, like animations, glTF PBR, format completeness for every format, GPU acceleration, etc."}, {"post_id": 53861, "ts": "2026-08-24T15:48:08Z", "hours": 10.9639, "text": "Merged the full assimp integration into main I really don’t have much to say here, I’ve already put all the info about the branch into the past devlogs. All the formats work and the wrapper is very sturdy. I’ve found more bugs in assimp itself than my code (devlog on that soon). So, rasterminal can now load basically any 3D model you throw at it. Some of the formats assimp supports are so niche, I’ve never even heard of them."}, {"post_id": 53278, "ts": "2026-08-23T18:46:58Z", "hours": 13.1411, "text": "Fuzzing my assimp wrapper I’m trying a bunch of hand-crafted models from all the formats that I can load and trying to find things that dont load or render properly. Also had AI write me a simple fuzzer in python and I’m just letting it run for a few hours. Also auditing the assimp loader paths against my wrapper to find any format specific behaviour that should be handled. I’ve already found a bunch of things and I’m still finding more. Assimp has a lot of weird quirks and issues that I keep running into. Honestly kinda regretting the decision to integrate it, but since I’m already so deep in, I’ll just keep going."}, {"post_id": 52574, "ts": "2026-08-22T19:13:37Z", "hours": 11.0969, "text": "Still working on the assimp intgration Currently trying various models from all the different model formats that assimp loads. So far found a segfault, some weird behavior and integration mistakes that I made. Also found a small bug in assimp itself, for which I’ve submitted the PR with the fix to their GitHub repo. For anyone interested, here’s the PR: https://github.com/assimp/assimp/pull/6799"}, {"post_id": 51884, "ts": "2026-08-21T19:41:32Z", "hours": 6.9825, "text": "Working on assimp integration Yop, I’m adding the Open Asset Import Library as a fallback for any model formats that aren’t natively supported with their own dedicated loader (only ones with dedicated loaders are glTF2, PLY, STL and OBJ). I’m still keeping the dedicated loaders, because they are more feature-complete, to-spec and wayyy faster (especially the glTF one). I added it because I feel like for a 3D model viewer, support for many formats, even niche and obscure ones, is pretty important, even though nobody might use them. This roughly doubled compile time and almost quadrupled binary size, which also made CI take way longer (of course). It somehow made the MacOS runners take 50 minutes to compile (from the previous 3 minutes), but I fixed that by bounding the number of processes CMake can spawn to the number of threads on the runner (previously was using -j which spawns as many as it wants and it was spawning about 230 of them). I’m still testing how it handles various model formats and trying to find any reachable segfaults."}, {"post_id": 51275, "ts": "2026-08-20T20:14:42Z", "hours": 6.7119, "text": "Cleanup and restructuring changes After I just merged three big feature branches (kitty and sixel graphics protocols and the high-res performance branch), I needed to do some overdue cleanup and refactoring. And so I did: Collapsed the super long changelog entries into way more readable and legible points Restructured the src directory into multiple subdirectories because it had like 50 files already Sadly completely removed the Make build system, so now you can only build with CMake (CMake is very much evil and even more evil but it’s the only one of the two that supports windows and I was tired of managing two build systems) Removed the –graphics-scale flag, so now everything renders at native resolution And some small docs and comment cleanup"}, {"post_id": 50683, "ts": "2026-08-20T00:07:13Z", "hours": 12.3297, "text": "Finally merging the performance branch It’s finally time to merge the performance branch. I basically redesigned the whole renderer and rasterizer around high resolution workloads, where it would still choose the old high-poly paths where they were faster. Even snuck in some SSE2 SIMD code (picture), although I will probably be switching to a dispatch SIMD library like Google’s Highway. Not entirely sure it will be Highway or even if I will do that yet, that depends on the code complexity and before/after benchmarks."}, {"post_id": 49184, "ts": "2026-08-17T20:28:00Z", "hours": 14.5689, "text": "Still optimizing… Spent the first ~7 hours trying to find microoptimizations and each one was either a wash or worse somehow. The compiler works in mysterious ways. At some point, I just gave up and let Claude have a go at the optimizing. Surprisingly it actually came up with a lot of interesting optimization techniques and solutions that I definitely couldn’t have come up with on my own. But it found so much, that the whole diff adds 5k lines of code. So now I’ll be cleaning up, testing, and maybe further optimizing that diff…"}, {"post_id": 48227, "ts": "2026-08-16T15:09:59Z", "hours": 3.5944, "text": "My reported bug in libtermkey has been fixed in the newest version Just got an email from one of the maintainers that the crash bug i reported a month ago was fixed in the new release. libtermkey is a terminal input parsing library that I considered using and found a crash bug in. The bug was already fixed in neovim’s fork of the library, so i just pointed the maintainers at that fix. For anybody interested, here’s the issue link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1142891"}, {"post_id": 48078, "ts": "2026-08-16T11:20:07Z", "hours": 11.47, "text": "Working on improving performance With the addition of the high-res protocols, the target resolutions quickly went from hundreds or thousands of pixels to millions. So I now desperately need to improve performance. So far it’s looking promising: A whole model covering the camera 6 moving at 4k went from about 8 fps to 20-30 fps. Not ideal yet, but I think we’re on the right track. Super dense meshes (more than 2 million polygons) improved 2-3x Meshes with transparent parts improved about 2x While these wins may seem really big (they kinda are), the jump in resolutions still means they are barely usable interactively. I do want to add gpu acceleration later (with the cpu path as a fallback), but until then I want to make it as fast as I possibly can."}, {"post_id": 47112, "ts": "2026-08-14T19:18:15Z", "hours": 9.0333, "text": "Fully merged sixel Fully merged the sixel protocol implementation. Works on all platforms everywhere that supports it. So now both high-res terminal protocols done. Moving onto other minor things and especially performance."}, {"post_id": 46486, "ts": "2026-08-13T18:38:49Z", "hours": 10.6753, "text": "Working on adding full Sixel support Working on adding support for the other mainstream terminal pixel protocol of the main two - Sixel. Already did fully implemented the kitty protocol last time, so once I’m done with this one, I’ll be done with terminal protocols (at least for the near future, hopefully). There are some other ones like the iterm2 protocol, but that one’s pretty rare and I won’t add it unless I really don’t have anything better to do. It’s basically done, just need to polish it and test it on a bunch of terminals and operating systems to make sure everything works before merging."}, {"post_id": 44676, "ts": "2026-08-10T16:23:20Z", "hours": 4.0767, "text": "Fully merged and done with Kitty Finally completed the kitty protocol implementation. It is kinda slow, since the resolution is so much bigger, so I will try to optimize the high-res performance even more. So now the next two big milestones are: Add Sixel on top of kitty, that’ll be a lot of work Optimize the rasterizer even more I was thinking of maybe adding gpu rendering as an option for super large meshes or high-res scenarios, but idk. I’ll definetly keep the pure cpu renderer for computers without gpus, but I’m not sure about a gpu implementation. It would be hard to do, less portable and it might not even work that well."}, {"post_id": 44513, "ts": "2026-08-10T09:59:08Z", "hours": 6.8483, "text": "Found a bug in Ghostty’s kitty protocol handling Ghostty is a modern and fast terminal emulator that i personally use. While testing the kitty protocol feature in rasterminal, I found a Ghostty bug that lagged my whole computer after a few minutes. I tested it in Kitty (terminal emulator) and there it worked fine. I looked at Ghostty’s code vs Kitty’s, found the bug and reported it to the Ghostty maintainers. Mitchell himself (the creator) fixed it in like 2 hours. Honestly I’m kinda sad I didn’t get to become a contributor and fix the bug, but since it was a small fix and I already described it in the issue, I get why Mitchell just fixed it in main. Here’s the full issue: https://github.com/ghostty-org/ghostty/discussions/13719"}, {"post_id": 43513, "ts": "2026-08-08T20:35:37Z", "hours": 7.6361, "text": "Working on adding support for the Kitty protocol Some modern terminals like Kitty and Ghostty have support for the Kitty protocol. It’s a feature that allows you to display high resolution content like images and videos in the terminal without it looking super pixelated. There’s also the Sixel protocol, which is basically the same thing but a little worse and more widely supported (even Windows terminal has it). I’ll add Sixel after i merge Kitty to main. It is very clearly a worthwhile feature and I have been planning to add it from the start of the project. Today I finally decided that it’s time. Most of the work is already done on the branch and i’m just polishing out the bugs and issues before I merge. In the photos, you can see the comparison between using just the block characters and using Kitty. It is a night and day difference. Although the performance isn’t great at that high of a resolution, but I’m still working on optimizing that."}, {"post_id": 42752, "ts": "2026-08-07T17:00:51Z", "hours": 3.5125, "text": "Minor comment cleanup Just did some comment cleanup: Deleted redundant comments and why comments Removed separator comments Compressed or rewrote some really long comments (without removing the info they give)"}, {"post_id": 42161, "ts": "2026-08-06T19:24:06Z", "hours": 8.2153, "text": "Added issue templates + contributing documentation Added templates and a config for submitting GitHub issues, for both bug reports and feature requests. Also added a CONTRIBUTING.md for clear instructions on how to make, structure and audit code contributions. (tests, linters, formatting, etc.) I tried to make some optimizations to the renderer by auditing the compiler generated assembly and looking for inefficiencies, but everything i tried turned out to actually hurt performance. And GitHub actions decided to have a major outage right when i pushed the commits, so that’s awesome"}, {"post_id": 39599, "ts": "2026-08-02T18:05:04Z", "hours": 7.4436, "text": "Completely redesigned and rewrote the HUD The HUD used to be just a single line at the bottom of the screen aligned to the left. It looked pretty bad, but it did tell the user everything they needed to know. [picture 1] First, I added model name sanitization, so models with control bytes like newline ( \\n ), line feed or other symbols like emojis can’t break the whole program when trying to display them in the HUD. Then, I completely redesigned the whole HUD to look better and be more robust, while still telling the user everything they need to know. I went with this design [picture 2]: On the left, you only have the model name. In the middle, first you have the current shading mode (highlighted in cyan), then the lighting mode in plain white and then the background color in gray. All three middle indicators are separated with a dot and are different colors, so nobody can confuse them. On the right, there’s 3 boolean indicators: spin (if the model spin is on), backface cull (if it’s currently culling backfaces) and texture (if it’s showing the texture, isn’t there at all on models without a texture). They are gray if inactive and cyan if active. The last thing on the right is just the fps number. There can also be optional indicators: Wireframe color (in the middle, after the shading mode) which only shows up in wireframe mode. [picture 3] First person speed multiplier (on the right, between the bools and the fps number) which shows up only in first person mode. [picture 4] I also made each “island” cleanly disappear when the terminal’s width is too low instead of just slowly getting cut off letter by letter. I think this design looks better, less cluttered and is pretty easy to understand at a glance. I would very much appreciate a star on GitHub!"}, {"post_id": 38478, "ts": "2026-07-31T21:36:35Z", "hours": 7.7572, "text": "Did a smaller fix and added a pretty big feature First, let’s talk about the small fix: I Fixed a super long model name showing up in the HUD in it’s full length, often blocking out other HUD elements. Previously, the HUD would display a model name of any length. Now there’s a hard cap of 24 chars, with any name longer than that truncated (middle style truncation) to fit into that limit. And now the big feature: Added a first person noclip-style camera mode. It’s accessed with the –first-person flag and let’s you explore the model as a floating camera (not bound like the default orbit camera). It was honestly easier to implement than I thought it would be. With it, I added two new keybinds special to the first person mode - E and V for going up and down. They don’t do nothing in orbit mode. Also added a second –first-person-speed flag for controlling the initial movement speed. It is also controllable during runtime with scrolling or +/- (I didn’t know what to bind these to in this mode since you can’t zoom like in orbit mode and this was the only place where they fit). In the photos, you can see some angles taken in the first person mode that weren’t possible in the default orbit mode."}, {"post_id": 37806, "ts": "2026-07-30T19:08:29Z", "hours": 2.7436, "text": "Finally committed and pushed the input rework Tested it on both linux and windows and everything seems to work. No inputs interpreted as other inputs, all edge cases handled, just works. Finally can move onto other things."}, {"post_id": 37656, "ts": "2026-07-30T15:25:21Z", "hours": 9.285, "text": "Still working on the input parsing system It is very hard and I keep finding bugs and reasons to redesign it. I’m in pain. I do think I’m getting closer to the final robust design."}, {"post_id": 36697, "ts": "2026-07-28T22:28:53Z", "hours": 9.9361, "text": "Working on completely rewriting the current input parsing handling The current input handling is subpar at best; it interprets a lot of random keys as escape, which currently quits the program (This will also be changed to Q and Ctrl+C only. Kind of a no-brainer since this is the more standard choice for TUIs - for example btop - and it also means I don’t have to deal with the headache of distinguishing function keys and others from escape) and has a lot of other quirky behavior that needs fixing. I’ll also try to improve robustness against malformed input like a leaky SSH session. There are a lot of various edge cases and situations where you have no way to distinguish real input from malformed input. This is all a very major pain in the ass. And I thought figuring out the raw mode output would be the hard part. And after all this, I’ll end up with way less attention than strictly slower, less robust competitors, just because they already have an audience from other projects. I bet nobody will even read this. I’m basically talking to myself right now. Or maybe, just to spite me, the algorithm will push this more than my other devlogs."}, {"post_id": 35924, "ts": "2026-07-27T17:55:43Z", "hours": 8.7953, "text": "So, i found two memory bugs in a widely used terminal input library I was researching terminal input libraries to use for this project because my current approach was so buggy that it wasn’t worth fixing. Both of them are memory bugs in the libtermkey library. There are forks of the lib with this fixed, but since many projects still rely on this lib, i submitted them anyways. I’ve also confirmed that the bug is present on my machine on Ubuntu 24.04 LTS on Neovim, because it links the vulnerable shared library. I didn’t mark them as CVEs (hopefully that isn’t a problem). If anyone want’s to look at the bug reports, they are at https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1142891 and https://bugs.launchpad.net/ubuntu/+source/libtermkey/+bug/2161916"}, {"post_id": 33607, "ts": "2026-07-23T17:38:48Z", "hours": 4.5575, "text": "Added more CLI flags for startup customizability Added flags to set the camera pitch, yaw and zoom on startup. Now every runtime-settable variable can be set during startup through the CLI. The R button now resets the state to the CLI set state, not to factory defaults."}, {"post_id": 32607, "ts": "2026-07-21T21:48:11Z", "hours": 4.4442, "text": "Added –spin-speed and –spin-direction flags Added CLI flags for the spin speed and direction. The speed is in deg/s and the directions is simply left or right. Here’s what 1000 deg/s looks like spinning to the right:"}, {"post_id": 30923, "ts": "2026-07-18T22:17:24Z", "hours": 8.6892, "text": "Did a bunch of small code quality and usability improvements Fixed a Windows bug that crashed the program on model sizes bigger than 2GB, improved the orbit usability (fixed mouse drag behavior when models are turned upside down), and did a few cleanups and fixes in the CLI parsing. I’m planning on adding a few CLI flags that I think can be very useful for some people, specifically better spin settings, starting camera angle/zoom control and a few more."}, {"post_id": 29772, "ts": "2026-07-16T21:27:23Z", "hours": 0.7175, "text": "Finally merged color-fallback, I can move onto other things The branch is finally merged. I’ve accumulated a bunch of usability and code quirks and issues that i can finally get to now that the branch is merged. So now I’ll be reworking all the CLI flags, camera and other components. And we also passed the 700 commit mark with this merge!"}, {"post_id": 29484, "ts": "2026-07-16T13:40:29Z", "hours": 4.9444, "text": "Changed the 24bit to 256 color palette conversion logic Until now, the conversion picked the closest color possible mathematically. But from testing on a bunch of different models, I’ve realized that it doesn’t actually look very close to the human eye. So I swapped it out for a different method, called CIELAB distance. Now it still doesn’t look perfect, but as a fallback for older terminals it’s close enough."}, {"post_id": 28408, "ts": "2026-07-14T17:26:16Z", "hours": 9.2258, "text": "Working on a –color compatibility flag The color terminal compatibility thing I was working on has landed in the branch, now I’m adding a –color flag to override the automatic capability detection for situations like ssh, where we almost always degrade to the 256 color pallete for maximum compatibility. So now you’re gonna be able to use the right color mode even if the automatic detection is wrong for your situation."}, {"post_id": 27302, "ts": "2026-07-12T19:23:17Z", "hours": 10.3522, "text": "Working on terminal color capability detection I am adding automatic terminal capability detection, meaning that rasterminal will get the terminal type and either refuse to render on super old or “dumb” terminals, degrade on some terminals and render normally on modern ones."}, {"post_id": 24314, "ts": "2026-07-07T20:18:01Z", "hours": 5.1908, "text": "Working on adding 256 color support Some older terminals can’t display full 24bit RGB colors and use a 256 color palette instead. I’m adding a fallback so the older terminals can still use rasterminal. It still calculates the full old RGB colors, but then just maps them to the nearest 256 color with LUTs. On a side note, I switched my terminal emulator from Kitty to Ghostty."}, {"post_id": 23070, "ts": "2026-07-05T20:10:12Z", "hours": 10.4403, "text": "Working on portability Did a bunch of small fixes and improvements in the last ~week. Right now I’m on vacation for the next couple of days, so I won’t be active. I am currently working on broader terminal and platform support, so older systems and terminals will be able to run cleanly with some fallbacks or will fail loud with a clear message about what isn’t supported."}, {"post_id": 19371, "ts": "2026-06-30T17:34:50Z", "hours": 5.1925, "text": "Completely removed the shadow map Before, rasterminal built a shadow map on model load and displayed it during runtime. I now completely removed it, because it was slower during load, slower during runtime, sometimes looked broken on curved surfaces and added essentially no value. Here, the first picture is with the shadow map and the second is without."}, {"post_id": 18685, "ts": "2026-06-29T21:27:29Z", "hours": 13.4722, "text": "Wasted 7 hours of my life Did a bunch of smaller cleanups and fixes, and then I tried to template the unlit and lit paths in the rasterize_flat function, which turned out to be a performance regression. Awesome."}, {"post_id": 17021, "ts": "2026-06-27T17:00:39Z", "hours": 5.7733, "text": "Added a release workflow, manpage and changelog I added a github release workflow that works alongside the changelog and released the first pre-release version: v0.1.0-alpha.1 Also added a manpage and an install target to make and cmake that installs the binary, docs and manpage into the path."}, {"post_id": 16313, "ts": "2026-06-26T15:28:43Z", "hours": 5.1883, "text": "Pararelized the wireframe shading mode I did a bunch of small things alongside it, but the main feature for this devlog is the pararelization of the wireframe shading mode. It was previously fully single threaded, but it wasn’t that hard to pararelize, i just had to make the function it used to write into the framebuffer (draw_line) CAS atomic, to avoid race conditions. Now wireframe is the fastest shading mode in basically all scenarios. Below, you can see a performance benchmark (built into rasterminal using a flag) with wireframe mode on a super dense mesh and how the wireframe mode looks like (you can also cycle the colors)."}, {"post_id": 15932, "ts": "2026-06-25T21:35:36Z", "hours": 1.9053, "text": "Split the tests into sub-directories The test suite is now very long (20k LOC across 47 files), so i decided to split it into sub-directories instead of just having 47 files in one flat dir. It’s cleaner, more maintainable and looks better."}, {"post_id": 15741, "ts": "2026-06-25T16:48:43Z", "hours": 4.9903, "text": "Completely removed gouraud shading mode Gouraud was previously the main shading mode, but now I’ve just completely removed it. It was by far the slowest, while not adding any actual value to the project. Blinn-phong lighting is faster AND it supports more features (normal maps, etc.), so there was just no point in keeping gouraud. Now that I’ve removed it, the project has less code to maintain and a faster default shading mode with more features."}, {"post_id": 15551, "ts": "2026-06-25T08:50:38Z", "hours": 3.7597, "text": "Added proper OBJ bump map support OBJ bump maps are textures for simulating bumps and wrinkles on models. Blender used to author bump maps as normal maps for some reason, so I made it automatically detect if it’s a normal map disguised as a bump map and handle it well, since there are a lot of old Blender OBJ models in the wild. But it also handles bump maps as bump maps normally, so it’s basically the best of both worlds."}, {"post_id": 15117, "ts": "2026-06-24T15:43:58Z", "hours": 6.87, "text": "Added texture transform into the TEXCOORD branch and merged it into main Not that hard, just read it, pass it to the rasterizer and then display it. I did have a very sneaky bug in the loader that made the whole feature render wrong, where I just had to negate one value to fully fix it, but now everything fully works. Below you can see the Khronos test asset for texture transforms. (tick means fully working, clearcoat is not yet implemented so it doesn’t show as working)"}, {"post_id": 13839, "ts": "2026-06-22T17:59:12Z", "hours": 5.2097, "text": "Added TEXCOORD_1 support glTF sometimes authors a second TEXCOORD set (first one is TEXCOORD_0, 0 indexed numbering). The official spec only requires support for the first two TEXCOORD sets, even though there can theoretically be any number of them in a model. That said, major model exporters don’t author any more than the two sets, so to avoid extra work, I only added support for 0 and 1. (not merged into main yet, I want to polish it a little and maybe add KHR_texture_transform support on top of it first)"}, {"post_id": 12798, "ts": "2026-06-20T22:37:18Z", "hours": 7.6314, "text": "Optimized the transparent cleanup path in the renderer After rendering the model in the transparent path, we have to resolve the transparent pixels, which basically just pastes in the pixels behind it and sometimes tints it based on how dark and what color the transparent material is (tinted glass will make the things behind it darker, normal glass will be mostly completely untinted). Before, the resolve function looped over every single pixel in the frame, even non-transparent and background ones. This is obviously wasteful. So I made it find the smallest box, in which all the transparent pixels of the whole frame fit and just looped over that. It recovered the overhead of the transparent resolve on models with smaller transparent parts, but it also made fully transparent or mostly transparent models slightly slower (it still basically loops over almost the whole screen on these types of models, so keeping track of the smallest bounding box while also still doing the same work as before made it a little slower). But the performance benefits for the average model outweighed the losses on rare fully transparent models. In the image, you can see the benchmark results versus the baseline."}, {"post_id": 12171, "ts": "2026-06-19T21:42:34Z", "hours": 6.6653, "text": "Made the shading mode branches compile time instead of runtime in the renderer with templates Did the same template if constexpr (compile time if branches) thing that we already do for opaque/transparent models with the shading mode (was a runtime per triangle if branch before), which improved performance. It basically just makes a new copy of the function for each shading mode x each transparency mode, so 4x2 which is 8 slightly different functions and uses the correct one on each call. That increases binary size and icache pressure, but drops per triangle or per pixel if branches that hurt performance, so it’s an overall performance win. Benchmarked across a ton of different resolutions, models, shading modes, etc. (the benchmark by itself took like 2 hours to run)"}, {"post_id": 10115, "ts": "2026-06-16T18:24:38Z", "hours": 4.0297, "text": "Added support for wrap modes for textures Only in glTF and OBJ models (the only ones that support it) and verified with the Khronos group sample assets model. Also added PLY texture support."}, {"post_id": 9453, "ts": "2026-06-15T20:20:25Z", "hours": 4.6839, "text": "Working on adding supersampling anti-aliasing Still a work in progress and I might not merge it into main, because it’s a lot of work for not that much benefit. I have to catch a lot of bad_allocs and things like that for super large SSAA sizes, which is really annoying and can affect performance. SSAA works by rendering at a higher resolution and then downscaling for better edges (makes edges smooth and fade-in instead of jagged) Picture with 2x SSAA and without SSAA:"}, {"post_id": 8652, "ts": "2026-06-14T11:36:32Z", "hours": 5.2058, "text": "Adapted the arg parsing and CLI behaviour to the GNU standard Now, rasterminal’s CLI behaves under the GNU CLI standards, so on par with most linux tools."}, {"post_id": 8162, "ts": "2026-06-13T16:37:29Z", "hours": 2.8394, "text": "Added deduplicating vertices to the stl loader. After two unsuccessful and unmerged branches, I finally did something useful on main. I used to deduplicate the vertices in stl_reader and then reduplicate them in the loader. But now, we just dedup in stl_reader and use those. That also allowed me to enable ambient occlusion, which was disabled for stl before. And now crease smoothing fully works too. And it’s faster (runtime wise, load time is slower because of ambient occlusion and crease smoothing that weren’t there before). So an all-round very positive change, and also an end to my non-merging dry spell."}, {"post_id": 7990, "ts": "2026-06-13T10:20:35Z", "hours": 2.4908, "text": "Replaced tinyobjloader with rapidobj for way faster obj parsing But after actually replacing it and integrating it into the source code, i realized it’s not worth it, because rapidobj just has too many downsides and isn’t very actively supported anymore. For example, it doesn’t support multiple mtl files, which is against the spec. So if i want to keep it spec compliant, I need to find a workaround for it, which just isn’t worth the speed increase of rapidobj, even if it’s like 4x faster (from my testing on a large obj) The graph is from this article: https://aras-p.info/blog/2022/05/14/comparing-obj-parse-libraries/"}, {"post_id": 7643, "ts": "2026-06-12T19:26:54Z", "hours": 8.7975, "text": "I tried to rewrite the STL loader from scratch for more performance But it’s taking super long and I’m way too bored with it, so I think I’ll just abandon the branch and work on something else."}, {"post_id": 6791, "ts": "2026-06-11T11:35:25Z", "hours": 3.6575, "text": "Added full native 32 bit support for all platforms Didn’t have to redesign any of the source code (thankfully), just some warning suppressing and fixing some static casts. Also added a CI job that’ll flag future 32 bit compatibility regressions."}, {"post_id": 5755, "ts": "2026-06-09T17:34:17Z", "hours": 4.1133, "text": "Transparency is fully done and merged. Did some polish, cleanup and optimization on the transparency branch and successfully merged into main."}, {"post_id": 4897, "ts": "2026-06-08T13:53:56Z", "hours": 3.2906, "text": "Transparency is basically done, with caveats. Transparency works correctly, but transmission , which is completely different, is simplified to transparency. So for spec-complete gltf, I would need to implement the whole transmission pipeline, which I’m way too lazy to do right now. So for now, we just simplify it to transparency and call it a day."}, {"post_id": 4320, "ts": "2026-06-07T16:09:10Z", "hours": 6.2586, "text": "Working on adding transparency support. For that, I have to completely rework the rendering loop and the rasterizers, so basically the whole core of the project. It’s going very badly. And since performance is a big factor here, I’m going for a template approach so the transparency overhead doesn’t affect non-transparent meshes."}, {"post_id": 3846, "ts": "2026-06-06T22:11:48Z", "hours": 3.5269, "text": "I did a hot-loop performance cleanup run, because the hot loops were getting slower with new features, and I found a big optimization opportunity in clip-near call sites: clip_near slices off the part of a triangle that pokes behind the camera’s near plane, but almost every triangle is fully in front of it with nothing to clip. The pipeline still called it for all of them, and in the compiled binary that common case just copied all three vertices to memory and back, millions of times a frame. The fix was to check inline whether the triangle is fully in front and skip the call entirely if so. Result on a 2.77M-triangle model: median frame time dropped from 21.1 ms to 19.2 ms, about 8.7% faster."}, {"post_id": 3572, "ts": "2026-06-06T15:51:49Z", "hours": 2.4386, "text": "Because of all the libraries I added, the binary size increased significantly. I don’t use most of the vendored code, so I added build flags to ignore unused code in the final binary. Other than that, I added some other performance flags and also a CMakePresets.txt. It took longer than it should’ve, because I tested and benchmarked a bunch of other configs and flags. I put off PGO for now."}, {"post_id": 2939, "ts": "2026-06-05T20:55:20Z", "hours": 3.9267, "text": "I wired in Webp image format support by vendoring in google’s libwebp decoding library. It wasn’t that hard to wire into the source code, the hard part was the vendoring, dealing with licenses and professional vendoring practices. Only thing that remains to add for full gltf extension support is avif image support, but I’ll do that later."}, {"post_id": 2739, "ts": "2026-06-05T14:38:57Z", "hours": 1.3417, "text": "I just added unlit material support, which means materials that are supposed to stay intentionally unaffected by lighting render correctly. Pretty straightforward change, just read it at load time and then check if that material is unlit during the lighting pass and skip it."}, {"post_id": 2631, "ts": "2026-06-05T08:21:00Z", "hours": 3.3225, "text": "Reworked the whole readme with better instructions, screenshots and a gif. The gif was super annoying to polish, because i used asciinema which records all the setup escape sequences so there were gaps at the start and end that i had to manually read and remove. And I also had to perfectly close it exactly when it did one full rotation and that took like an hour to perfect. At least now I don’t have to touch the readme for a while."}, {"post_id": 2311, "ts": "2026-06-04T18:46:14Z", "hours": 3.1892, "text": "Well, I tried to refactor the main rendering loop for like the third time, because it’s horrifyingly indented, but it has defeated me once again. At this point, I’m confident that it’s impossible to do without a noticeable drop in performance, or g++ is just ragebaiting me. I installed a rainbow indentation neovim plugin just to show the absurdity of this."}, {"post_id": 386, "ts": "2026-06-01T18:58:14Z", "hours": 0.6783, "text": "I just implemented KTX2 and Basis texture support, which are special compressed texture formats. So now any models with these textures are viewable in rasterminal."}, {"post_id": 359, "ts": "2026-06-01T17:59:06Z", "hours": 4.5428, "text": "Hey everyone, I want to introduce my project! rasterminal is a full software 3D rasterizer and model viewer that runs entirely in your terminal. The whole rendering pipeline is implemented from scratch. I only rely on third-party libraries for load-time things like 3D model parsing, image parsing, and decompression. It doesn’t touch the GPU at all, running purely on the CPU. That makes it completely safe for SSH usage, though it does come with a performance cost. I use multithreading to recover some of what’s lost, and the result is still significantly faster than any other terminal 3D viewer I’ve come across. Right now I’m focused on broader 3D format feature support and transparent material rendering. If you want to try it out, I’d love to hear what you think, feedback and issues are very welcome over on GitHub. https://github.com/PavolUlicny/rasterminal Thanks for any support! 🙏"}]...
|
Title: rasterminal by @PavolUlicny | Stardance
De Title: rasterminal by @PavolUlicny | Stardance
Devlogs:
Hey everyone, I want to introduce my project! rasterminal is a full software 3D rasterizer and model viewer that runs entirely in your terminal. The whole rendering pipeline is implemented from scratch. I only rely on third-party libraries for load-time things like 3D model parsing, image parsing, and decompression. It doesn’t touch the GPU at all, running purely on the CPU. That makes it completely safe for SSH usage, though it does come with a performance cost. I use multithreading to recover some of what’s lost, and the result is still significantly faster than any other terminal 3D viewer I’ve come across. Right now I’m focused on broader 3D format feature support and transparent material rendering. If you want to try it out, I’d love to hear what you think, feedback and issues are very welcome over on GitHub. https://github.com/PavolUlicny/rasterminal Thanks for any support! 🙏
I just implemented KTX2 and Basis texture support, which are special compressed texture formats. So now any models with these textures are viewable in rasterminal.
Well, I tried to refactor the main rendering loop for like the third time, because it’s horrifyingly indented, but it has defeated me once again. At this point, I’m confident that it’s impossible to do without a noticeable drop in performance, or g++ is just ragebaiting me. I installed a rainbow indentation neovim plugin just to show the absurdity of this.
Reworked the whole readme with better instructions, screenshots and a gif. The gif was super annoying to polish, because i used asciinema which records all the setup escape sequences so there were gaps at the start and end that i had to manually read and remove. And I also had to perfectly close it exactly when it did one full rotation and that took like an hour to perfect. At least now I don’t have to touch the readme for a while.
I just added unlit material support, which means materials that are supposed to stay intentionally unaffected by lighting render correctly. Pretty straightforward change, just read it at load time and then check if that material is unlit during the lighting pass and skip it.
I wired in Webp image format support by vendoring in google’s libwebp decoding library. It wasn’t that hard to wire into the source code, the hard part was the vendoring, dealing with licenses and professional vendoring practices. Only thing that remains to add for full gltf extension support is avif image support, but I’ll do that later.
Because of all the libraries I added, the binary size increased significantly. I don’t use most of the vendored code, so I added build flags to ignore unused code in the final binary. Other than that, I added some other performance flags and also a CMakePresets.txt. It took longer than it should’ve, because I tested and benchmarked a bunch of other configs and flags. I put off PGO for now.
I did a hot-loop performance cleanup run, because the hot loops were getting slower with new features, and I found a big optimization opportunity in clip-near call sites: clip_near slices off the part of a triangle that pokes behind the camera’s near plane, but almost every triangle is fully in front of it with nothing to clip. The pipeline still called it for all of them, and in the compiled binary that common case just copied all three vertices to memory and back, millions of times a frame. The fix was to check inline whether the triangle is fully in front and skip the call entirely if so. Result on a 2.77M-triangle model: median frame time dropped from 21.1 ms to 19.2 ms, about 8.7% faster.
Working on adding transparency support. For that, I have to completely rework the rendering loop and the rasterizers, so basically the whole core of the project. It’s going very badly. And since performance is a big factor here, I’m going for a template approach so the transparency overhead doesn’t affect non-transparent meshes.
Transparency is basically done, with caveats. Transparency works correctly, but transmission , which is completely different, is simplified to transparency. So for spec-complete gltf, I would need to implement the whole transmission pipeline, which I’m way too lazy to do right now. So for now, we just simplify it to transparency and call it a day.
Transparency is fully done and merged. Did some polish, cleanup and optimization on the transparency branch and successfully merged into main.
Added full native 32 bit support for all platforms Didn’t have to redesign any of the source code (thankfully), just some warning suppressing and fixing some static casts. Also added a CI job that’ll flag future 32 bit compatibility regressions.
I tried to rewrite the STL loader from scratch for more performance But it’s taking super long and I’m way too bored with it, so I think I’ll just abandon the branch and work on something else.
Replaced tinyobjloader with rapidobj for way faster obj parsing But after actually replacing it and integrating it into the source code, i realized it’s not worth it, because rapidobj just has too many downsides and isn’t very actively supported anymore. For example, it doesn’t support multiple mtl files, which is against the spec. So if i want to keep it spec compliant, I need to find a workaround for it, which just isn’t worth the speed increase of rapidobj, even if it’s like 4x faster (from my testing on a large obj) The graph is from this article: https://aras-p.info/blog/2022/05/14/comparing-obj-parse-libraries/
Added deduplicating vertices to the stl loader. After two unsuccessful and unmerged branches, I finally did something useful on main. I used to deduplicate the vertices in stl_reader and then reduplicate them in the loader. But now, we just dedup in stl_reader and use those. That also allowed me to enable ambient occlusion, which was disabled for stl before. And now crease smoothing fully works too. And it’s faster (runtime wise, load time is slower because of ambient occlusion and crease smoothing that weren’t there before). So an all-round very positive change, and also an end to my non-merging dry spell.
Adapted the arg parsing and CLI behaviour to the GNU standard Now, rasterminal’s CLI behaves under the GNU CLI standards, so on par with most linux tools.
Working on adding supersampling anti-aliasing Still a work in progress and I might not merge it into main, because it’s a lot of work for not that much benefit. I have to catch a lot of bad_allocs and things like that for super large SSAA sizes, which is really annoying and can affect performance. SSAA works by rendering at a higher resolution and then downscaling for better edges (makes edges smooth and fade-in instead of jagged) Picture with 2x SSAA and without SSAA:
Added support for wrap modes for textures Only in glTF and OBJ models (the only ones that support it) and verified with the Khronos group sample assets model. Also added PLY texture support.
Made the shading mode branches compile time instead of runtime in the renderer with templates Did the same template if constexpr (compile time if branches) thing that we already do for opaque/transparent models with the shading mode (was a runtime per triangle if branch before), which improved performance. It basically just makes a new copy of the function for each shading mode x each transparency mode, so 4x2 which is 8 slightly different functions and uses the correct one on each call. That increases binary size and icache pressure, but drops per triangle or per pixel if branches that hurt performance, so it’s an overall performance win. Benchmarked across a ton of different resolutions, models, shading modes, etc. (the benchmark by itself took like 2 hours to run)
Optimized the transparent cleanup path in the renderer After rendering the model in the transparent path, we have to resolve the transparent pixels, which basically just pastes in the pixels behind it and sometimes tints it based on how dark and what color the transparent material is (tinted glass will make the things behind it darker, normal glass will be mostly completely untinted). Before, the resolve function looped over every single pixel in the frame, even non-transparent and background ones. This is obviously wasteful. So I made it find the smallest box, in which all the transparent pixels of the whole frame fit and just looped over that. It recovered the overhead of the transparent resolve on models with smaller transparent parts, but it also made fully transparent or mostly transparent models slightly slower (it still basically loops over almost the whole screen on these types of models, so keeping track of the smallest bounding box while also still doing the same work as before made it a little slower). But the performance benefits for the average model outweighed the losses on rare fully transparent models. In the image, you can see the benchmark results versus the baseline.
Added TEXCOORD_1 support glTF sometimes authors a second TEXCOORD set (first one is TEXCOORD_0, 0 indexed numbering). The official spec only requires support for the first two TEXCOORD sets, even though there can theoretically be any number of them in a model. That said, major model exporters don’t author any more than the two sets, so to avoid extra work, I only added support for 0 and 1. (not merged into main yet, I want to polish it a little and maybe add KHR_texture_transform support on top of it first)
Added texture transform into the TEXCOORD branch and merged it into main Not that hard, just read it, pass it to the rasterizer and then display it. I did have a very sneaky bug in the loader that made the whole feature render wrong, where I just had to negate one value to fully fix it, but now everything fully works. Below you can see the Khronos test asset for texture transforms. (tick means fully working, clearcoat is not yet implemented so it doesn’t show as working)
Added proper OBJ bump map support OBJ bump maps are textures for simulating bumps and wrinkles on models. Blender used to author bump maps as normal maps for some reason, so I made it automatically detect if it’s a normal map disguised as a bump map and handle it well, since there are a lot of old Blender OBJ models in the wild. But it also handles bump maps as bump maps normally, so it’s basically the best of both worlds.
Completely removed gouraud shading mode Gouraud was previously the main shading mode, but now I’ve just completely removed it. It was by far the slowest, while not adding any actual value to the project. Blinn-phong lighting is faster AND it supports more features (normal maps, etc.), so there was just no point in keeping gouraud. Now that I’ve removed it, the project has less code to maintain and a faster default shading mode with more features.
Split the tests into sub-directories The test suite is now very long (20k LOC across 47 files), so i decided to split it into sub-directories instead of just having 47 files in one flat dir. It’s cleaner, more maintainable and looks better.
Pararelized the wireframe shading mode I did a bunch of small things alongside it, but the main feature for this devlog is the pararelization of the wireframe shading mode. It was previously fully single threaded, but it wasn’t that hard to pararelize, i just had to make the function it used to write into the framebuffer (draw_line) CAS atomic, to avoid race conditions. Now wireframe is the fastest shading mode in basically all scenarios. Below, you can see a performance benchmark (built into rasterminal using a flag) with wireframe mode on a super dense mesh and how the wireframe mode looks like (you can also cycle the colors).
Added a release workflow, manpage and changelog I added a github release workflow that works alongside the changelog and released the first pre-release version: v0.1.0-alpha.1 Also added a manpage and an install target to make and cmake that installs the binary, docs and manpage into the path.
Wasted 7 hours of my life Did a bunch of smaller cleanups and fixes, and then I tried to template the unlit and lit paths in the rasterize_flat function, which turned out to be a performance regression. Awesome.
Completely removed the shadow map Before, rasterminal built a shadow map on model load and displayed it during runtime. I now completely removed it, because it was slower during load, slower during runtime, sometimes looked broken on curved surfaces and added essentially no value. Here, the first picture is with the shadow map and the second is without.
Working on portability Did a bunch of small fixes and improvements in the last ~week. Right now I’m on vacation for the next couple of days, so I won’t be active. I am currently working on broader terminal and platform support, so older systems and terminals will be able to run cleanly with some fallbacks or will fail loud with a clear message about what isn’t supported.
Working on adding 256 color support Some older terminals can’t display full 24bit RGB colors and use a 256 color palette instead. I’m adding a fallback so the older terminals can still use rasterminal. It still calculates the full old RGB colors, but then just maps them to the nearest 256 color with LUTs. On a side note, I switched my terminal emulator from Kitty to Ghostty.
Working on terminal color capability detection I am adding automatic terminal capability detection, meaning that rasterminal will get the terminal type and either refuse to render on super old or “dumb” terminals, degrade on some terminals and render normally on modern ones.
Working on a –color compatibility flag The color terminal compatibility thing I was working on has landed in the branch, now I’m adding a –color flag to override the automatic capability detection for situations like ssh, where we almost always degrade to the 256 color pallete for maximum compatibility. So now you’re gonna be able to use the right color mode even if the automatic detection is wrong for your situation.
Changed the 24bit to 256 color palette conversion logic Until now, the conversion picked the closest color possible mathematically. But from testing on a bunch of different models, I’ve realized that it doesn’t actually look very close to the human eye. So I swapped it out for a different method, called CIELAB distance. Now it still doesn’t look perfect, but as a fallback for older terminals it’s close enough.
Finally merged color-fallback, I can move onto other things The branch is finally merged. I’ve accumulated a bunch of usability and code quirks and issues that i can finally get to now that the branch is merged. So now I’ll be reworking all the CLI flags, camera and other components. And we also passed the 700 commit mark with this merge!
Did a bunch of small code quality and usability improvements Fixed a Windows bug that crashed the program on model sizes bigger than 2GB, improved the orbit usability (fixed mouse drag behavior when models are turned upside down), and did a few cleanups and fixes in the CLI parsing. I’m planning on adding a few CLI flags that I think can be very useful for some people, specifically better spin settings, starting camera angle/zoom control and a few more.
Added –spin-speed and –spin-direction flags Added CLI flags for the spin speed and direction. The speed is in deg/s and the directions is simply left or right. Here’s what 1000 deg/s looks like spinning to the right:
Added more CLI flags for startup customizability Added flags to set the camera pitch, yaw and zoom on startup. Now every runtime-settable variable can be set during startup through the CLI. The R button now resets the state to the CLI set state, not to factory defaults.
So, i found two memory bugs in a widely used terminal input library I was researching terminal input libraries to use for this project because my current approach was so buggy that it wasn’t worth fixing. Both of them are memory bugs in the libtermkey library. There are forks of the lib with this fixed, but since many projects still rely on this lib, i submitted them anyways. I’ve also confirmed that the bug is present on my machine on Ubuntu 24.04 LTS on Neovim, because it links the vulnerable shared library. I didn’t mark them as CVEs (hopefully that isn’t a problem). If anyone want’s to look at the bug reports, they are at https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1142891 and https://bugs.launchpad.net/ubuntu/+source/libtermkey/+bug/2161916
Working on completely rewriting the current input parsing handling The current input handling is subpar at best; it interprets a lot of random keys as escape, which currently quits the program (This will also be changed to Q and Ctrl+C only. Kind of a no-brainer since this is the more standard choice for TUIs - for example btop - and it also means I don’t have to deal with the headache of distinguishing function keys and others from escape) and has a lot of other quirky behavior that needs fixing. I’ll also try to improve robustness against malformed input like a leaky SSH session. There are a lot of various edge cases and situations where you have no way to distinguish real input from malformed input. This is all a very major pain in the ass. And I thought figuring out the raw mode output would be the hard part. And after all this, I’ll end up with way less attention than strictly slower, less robust competitors, just because they already have an audience from other projects. I bet nobody will even read this. I’m basically talking to myself right now. Or maybe, just to spite me, the algorithm will push this more than my other devlogs.
Still working on the input parsing system It is very hard and I keep finding bugs and reasons to redesign it. I’m in pain. I do think I’m getting closer to the final robust design.
Finally committed and pushed the input rework Tested it on both linux and windows and everything seems to work. No inputs interpreted as other inputs, all edge cases handled, just works. Finally can move onto other things.
Did a smaller fix and added a pretty big feature First, let’s talk about the small fix: I Fixed a super long model name showing up in the HUD in it’s full length, often blocking out other HUD elements. Previously, the HUD would display a model name of any length. Now there’s a hard cap of 24 chars, with any name longer than that truncated (middle style truncation) to fit into that limit. And now the big feature: Added a first person noclip-style camera mode. It’s accessed with the –first-person flag and let’s you explore the model as a floating camera (not bound like the default orbit camera). It was honestly easier to implement than I thought it would be. With it, I added two new keybinds special to the first person mode - E and V for going up and down. They don’t do nothing in orbit mode. Also added a second –first-person-speed flag for controlling the initial movement speed. It is also controllable during runtime with scrolling or +/- (I didn’t know what to bind these to in this mode since you can’t zoom like in orbit mode and this was the only place where they fit). In the photos, you can see some angles taken in the first person mode that weren’t possible in the default orbit mode.
Completely redesigned and rewrote the HUD The HUD used to be just a single line at the bottom of the screen aligned to the left. It looked pretty bad, but it did tell the user everything they needed to know. [picture 1] First, I added model name sanitization, so models with control bytes like newline ( \n ), line feed or other symbols like emojis can’t break the whole program when trying to display them in the HUD. Then, I completely redesigned the whole HUD to look better and be more robust, while still telling the user everything they need to know. I went with this design [picture 2]: On the left, you only have the model name. In the middle, first you have the current shading mode (highlighted in cyan), then the lighting mode in plain white and then the background color in gray. All three middle indicators are separated with a dot and are different colors, so nobody can confuse them. On the right, there’s 3 boolean indicators: spin (if the model spin is on), backface cull (if it’s currently culling backfaces) and texture (if it’s showing the texture, isn’t there at all on models without a texture). They are gray if inactive and cyan if active. The last thing on the right is just the fps number. There can also be optional indicators: Wireframe color (in the middle, after the shading mode) which only shows up in wireframe mode. [picture 3] First person speed multiplier (on the right, between the bools and the fps number) which shows up only in first person mode. [picture 4] I also made each “island” cleanly disappear when the terminal’s width is too low instead of just slowly getting cut off letter by letter. I think this design looks better, less cluttered and is pretty easy to understand at a glance. I would very much appreciate a star on GitHub!
Added issue templates + contributing documentation Added templates and a config for submitting GitHub issues, for both bug reports and feature requests. Also added a CONTRIBUTING.md for clear instructions on how to make, structure and audit code contributions. (tests, linters, formatting, etc.) I tried to make some optimizations to the renderer by auditing the compiler generated assembly and looking for inefficiencies, but everything i tried turned out to actually hurt performance. And GitHub actions decided to have a major outage right when i pushed the commits, so that’s awesome
Minor comment cleanup Just did some comment cleanup: Deleted redundant comments and why comments Removed separator comments Compressed or rewrote some really long comments (without removing the info they give)
Working on adding support for the Kitty protocol Some modern terminals like Kitty and Ghostty have support for the Kitty protocol. It’s a feature that allows you to display high resolution content like images and videos in the terminal without it looking super pixelated. There’s also the Sixel protocol, which is basically the same thing but a little worse and more widely supported (even Windows terminal has it). I’ll add Sixel after i merge Kitty to main. It is very clearly a worthwhile feature and I have been planning to add it from the start of the project. Today I finally decided that it’s time. Most of the work is already done on the branch and i’m just polishing out the bugs and issues before I merge. In the photos, you can see the comparison between using just the block characters and using Kitty. It is a night and day difference. Although the performance isn’t great at that high of a resolution, but I’m still working on optimizing that.
Found a bug in Ghostty’s kitty protocol handling Ghostty is a modern and fast terminal emulator that i personally use. While testing the kitty protocol feature in rasterminal, I found a Ghostty bug that lagged my whole computer after a few minutes. I tested it in Kitty (terminal emulator) and there it worked fine. I looked at Ghostty’s code vs Kitty’s, found the bug and reported it to the Ghostty maintainers. Mitchell himself (the creator) fixed it in like 2 hours. Honestly I’m kinda sad I didn’t get to become a contributor and fix the bug, but since it was a small fix and I already described it in the issue, I get why Mitchell just fixed it in main. Here’s the full issue: https://github.com/ghostty-org/ghostty/discussions/13719
Fully merged and done with Kitty Finally completed the kitty protocol implementation. It is kinda slow, since the resolution is so much bigger, so I will try to optimize the high-res performance even more. So now the next two big milestones are: Add Sixel on top of kitty, that’ll be a lot of work Optimize the rasterizer even more I was thinking of maybe adding gpu rendering as an option for super large meshes or high-res scenarios, but idk. I’ll definetly keep the pure cpu renderer for computers without gpus, but I’m not sure about a gpu implementation. It would be hard to do, less portable and it might not even work that well.
Working on adding full Sixel support Working on adding support for the other mainstream terminal pixel protocol of the main two - Sixel. Already did fully implemented the kitty protocol last time, so once I’m done with this one, I’ll be done with terminal protocols (at least for the near future, hopefully). There are some other ones like the iterm2 protocol, but that one’s pretty rare and I won’t add it unless I really don’t have anything better to do. It’s basically done, just need to polish it and test it on a bunch of terminals and operating systems to make sure everything works before merging.
Fully merged sixel Fully merged the sixel protocol implementation. Works on all platforms everywhere that supports it. So now both high-res terminal protocols done. Moving onto other minor things and especially performance.
Working on improving performance With the addition of the high-res protocols, the target resolutions quickly went from hundreds or thousands of pixels to millions. So I now desperately need to improve performance. So far it’s looking promising: A whole model covering the camera 6 moving at 4k went from about 8 fps to 20-30 fps. Not ideal yet, but I think we’re on the right track. Super dense meshes (more than 2 million polygons) improved 2-3x Meshes with transparent parts improved about 2x While these wins may seem really big (they kinda are), the jump in resolutions still means they are barely usable interactively. I do want to add gpu acceleration later (with the cpu path as a fallback), but until then I want to make it as fast as I possibly can.
My reported bug in libtermkey has been fixed in the newest version Just got an email from one of the maintainers that the crash bug i reported a month ago was fixed in the new release. libtermkey is a terminal input parsing library that I considered using and found a crash bug in. The bug was already fixed in neovim’s fork of the library, so i just pointed the maintainers at that fix. For anybody interested, here’s the issue link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1142891
Still optimizing… Spent the first ~7 hours trying to find microoptimizations and each one was either a wash or worse somehow. The compiler works in mysterious ways. At some point, I just gave up and let Claude have a go at the optimizing. Surprisingly it actually came up with a lot of interesting optimization techniques and solutions that I definitely couldn’t have come up with on my own. But it found so much, that the whole diff adds 5k lines of code. So now I’ll be cleaning up, testing, and maybe further optimizing that diff…
Finally merging the performance branch It’s finally time to merge the performance branch. I basically redesigned the whole renderer and rasterizer around high resolution workloads, where it would still choose the old high-poly paths where they were faster. Even snuck in some SSE2 SIMD code (picture), although I will probably be switching to a dispatch SIMD library like Google’s Highway. Not entirely sure it will be Highway or even if I will do that yet, that depends on the code complexity and before/after benchmarks.
Cleanup and restructuring changes After I just merged three big feature branches (kitty and sixel graphics protocols and the high-res performance branch), I needed to do some overdue cleanup and refactoring. And so I did: Collapsed the super long changelog entries into way more readable and legible points Restructured the src directory into multiple subdirectories because it had like 50 files already Sadly completely removed the Make build system, so now you can only build with CMake (CMake is very much evil and even more evil but it’s the only one of the two that supports windows and I was tired of managing two build systems) Removed the –graphics-scale flag, so now everything renders at native resolution And some small docs and comment cleanup
Working on assimp integration Yop, I’m adding the Open Asset Import Library as a fallback for any model formats that aren’t natively supported with their own dedicated loader (only ones with dedicated loaders are glTF2, PLY, STL and OBJ). I’m still keeping the dedicated loaders, because they are more feature-complete, to-spec and wayyy faster (especially the glTF one). I added it because I feel like for a 3D model viewer, support for many formats, even niche and obscure ones, is pretty important, even though nobody might use them. This roughly doubled compile time and almost quadrupled binary size, which also made CI take way longer (of course). It somehow made the MacOS runners take 50 minutes to compile (from the previous 3 minutes), but I fixed that by bounding the number of processes CMake can spawn to the number of threads on the runner (previously was using -j which spawns as many as it wants and it was spawning about 230 of them). I’m still testing how it handles various model formats and trying to find any reachable segfaults.
Still working on the assimp intgration Currently trying various models from all the different model formats that assimp loads. So far found a segfault, some weird behavior and integration mistakes that I made. Also found a small bug in assimp itself, for which I’ve submitted the PR with the fix to their GitHub repo. For anyone interested, here’s the PR: https://github.com/assimp/assimp/pull/6799
Fuzzing my assimp wrapper I’m trying a bunch of hand-crafted models from all the formats that I can load and trying to find things that dont load or render properly. Also had AI write me a simple fuzzer in python and I’m just letting it run for a few hours. Also auditing the assimp loader paths against my wrapper to find any format specific behaviour that should be handled. I’ve already found a bunch of things and I’m still finding more. Assimp has a lot of weird quirks and issues that I keep running into. Honestly kinda regretting the decision to integrate it, but since I’m already so deep in, I’ll just keep going.
Merged the full assimp integration into main I really don’t have much to say here, I’ve already put all the info about the branch into the past devlogs. All the formats work and the wrapper is very sturdy. I’ve found more bugs in assimp itself than my code (devlog on that soon). So, rasterminal can now load basically any 3D model you throw at it. Some of the formats assimp supports are so niche, I’ve never even heard of them.
Cutting a release The repo is in a pretty complete and polished state, so I’ll cut a release here. This will also probably be the last release before I ship, so I’m making sure that nothing is broken and everything works on every platform. I’ve still got a lot of work to do though, even after the end of stardance, like animations, glTF PBR, format completeness for every format, GPU acceleration, etc.
Found a bunch of terminal cleanup gaps Most of them are Windows or cmd.exe specific (nothing ever works on Windows), but some are present on POSIX too. The Windows specific ones are: cmd.exe for some unknown reason doesn’t turn off the raw input sequences, so arrow keys don’t work like they should, even though I explicitly turn it off (????????) (I hate Windows, they always have to do something unexplainable for no reason just so your code doesn’t work as it should) when you terminate the program with ctrl+c or ctrl+break while actively dragging the model around, it sometimes leaks mouse escape sequences into the next prompt bunch of other weird small stuff that nobody cares about And the few on POSIX are mostly ctrl+z suspend/resume behaviour not recovering the terminal and the same thing with ctrl+\ (SIGQUIT). I’m still working on fixing these. Most of the windows ones are already fixed, but I haven’t even started with the linux/POSIX ones. I have postponed the planned release to when I fix these + any other issues I find.
I HATE WINDOWS Windows just doesn’t work. It doesn’t work. Nothing works on Windows. Everything breaks. I don’t get it. THE UNIT TESTS PASS ON WINDOWS CI BUT WHEN I ACTUALLY RUN THE TESTS ON WINDOWS IT FAILS????? HOW IS THAT EVEN POSSIBLE. The release is now definitely getting delayed by at least a week because I keep running into more and more and more and more and more and more and more and more and more issues. I hate Windows. Microslop is the only company that could mess up a basic terminal emulator. And I also have to reboot my PC every time I fix something and push it and then reboot to get back to linux. this is torture. At one point I tried to do it on a Windows VM on linux but that was too slow so I just gave up.
Merged the full Windows console restoration branch My nightmare is over. I hopefully won’t have to deal with Windows for a while now. Summary of what is now fixed/handled on Windows: Ctrl+C, Ctrl+Break and Q exits fully recover the terminal’s state Ctrl+C and Ctrl+Break don’t leak mouse escape sequences into the next prompt if you terminate while actively dragging a model A bunch of other minor Windows or cmd.exe specific quirks Only thing that isn’t handled (didn’t find a good way to handle it) is task manager “end process”. It kills the program without cleaning up and sometimes freezes the shell.
Fully fixed and merged the first POSIX cleanup item Well, would you look at that! That took significantly less time than the Windows fix. It is partly because it was a smaller fix and only part whole POSIX fix, while the Windows one was the whole thing and also the foundation had already been laid out from the Windows work and I just integrated the POSIX path into that, but it is also very much because Microsoft is a horrible, terrible company that can’t make good software. I mean, look at GitHub, they have been going downhill ever since they got acquired by Microsoft. Now that I got that out of my system, here’s what was fixed: If the program cannot enable raw mode at startup, it safely fails instead of continuing and corrupting the terminal state If the cleanup gets interrupted, it retries cleanup so it doesn’t leave the terminal state corrupted after one failed attempt Onto the next POSIX fix: handling SIGQUIT and SIGHUP.
Added handling for SIGINT, SIGTERM, SIGQUIT and SIGHUP I don’t really have much to say here, I just added the full per-spec handling for all these. Only remaining POSIX-only gap is now SIGSTOP/SIGCONT (stop/resume process). I’m also starting school now, so I’ll be working on this less.
Working on SIGSTOP and SIGCONT handling SIGSTOP and SIGCONT are POSIX signals for stopping and resuming a running process. I’m working on adding handling for these, so you can safely pause and unpause rasterminal at any time. This is a lot of work, since until now, we just set up the terminal on program start and cleaned up when the program exited. There’s a lot of quirks and weird scenarios that I have to handle, for example if another signal gets sent while cleaning up the terminal for SIGSTOP. I’m trying to catch as many edge cases by just doing random things while using the program and also with the help of AI to come up with potentially uncaught scenarios.
Did some polish and cleanup of the platform layer Did final polish and cleanup of the platform layer since I want to actually finally cut a release relatively soon and I just did a lot of work there. Fixed things like useless tests, outdated or wrong comments and some platform specific quirks. Probably actually gonna cut a release soon (this time for real). Also added early rejections for BVH and CSM files, since they contain no model geometry (they can’t currently be displayed at all) and documented the change. The code is basically done (hopefully, I really don’t want to find another big gap that’s gonna take a week to close), I just want to correct anything wrong in the README, changelog, manpage or help menu and maybe make them look a little better before cutting a release and shipping.
Last pre-release checks and cleanup I’m finally ready to release v0.1.0-alpha.2. Only notable thing I changed here is that I changed the default thread count: It now defaults to hardware concurrency everywhere. Other than that, I of course did final documentation checks and fixes and now I’m just waiting for CI to pass so I can tag it and let the release workflow do the last step. So this is hopefully the last devlog before my ship!
Refactored the platform layer The whole platform layer was just one file until now. Since I did a lot of work on it recently, it grew to over 2400 lines of code. It was super confusing and disorienting. So I decided to refactor it (split it) into 8 files, based on what they handle: console.h - saving/restoring terminal state control.h - termination signal handling file.h - file operations (64bit) input_reader.h - handling input (not parsing, that is it’s own file) shared_memory.h - shared memory handling for the kitty protocol terminal_io.h - writes output to the terminal terminal_query.h - querying the terminal for things like graphics capability, etc. timing.h - frame timing and sleeps
Miscellaneous fixes and improvements Fixed two races in platform code (one MacOS, one Windows) Removed build flags that disabled some compiler security hardening at the cost of a little performance Fixed the test framework to not freak out on NaN in near assertions Improved thread launching and handling in loaders and renderer So overall just boring fixes and improvements, nothing special.
Code quality and CI improvements Finally did the long overdue main loop refactor. The main loop is now way shorter, more readable and more testable. I just split off some of the main loop’s work into it’s own modules, which made them way better looking and also, since they are now standalone modules, actually testable. A big win for repo structure. In the process, I also replaced the input handling’s long if chain that made each character do it’s job with a switch statement. It’s more readable and theoretically faster, although since I compile it with -O3, it probably made no difference or an unnoticeable one at best. I also finally fixed the super long CI times. Until now, CI used to take ~50 minutes (depending on how fast the GitHub runner was) because of cppcheck. Everything else finished in under 10 minutes, but cppcheck stalled it for an hour. It was stalling in mesh_assimp.cpp (the assimp wrapper) for most of it’s runtime. I always thought it was because assimp is a very large library. So I experimented with it a little. I included everything I include in the wrapper into a test file with a little code and ran cppcheck on that. It finished in less than 10 seconds. Eventually, I found out it was somehow taking that long because the main loader function was too long and handled too much by itself. So i just refactored it into 3 separate functions, without changing the behavior at all. Somehow, I still don’t get why, it reduced the whole cppcheck run to 9 minutes. a more than 5x improvement, just because I split a function into more functions. I’m not complaining, but it’s definitely weird. CI is now way faster and adding new things is gonna be way smoother now.
Ships:
rasterminal rasterminal is a 3D model viewer in the terminal Why i decided to build it The original idea didn’t really have any big inspiration, I’ve just always been fascinated by the inner workings of 3D and how that all works. I’ve been wanting to build a project involving 3D for a while and I didn’t want to make just another program that uses libraries and GPU drivers to do all the work. So I came up with the idea: a software rasterizer that renders in the terminal! There are lots of TUIs and lots of boring old software rasterizer projects, so I just combined the two into something unique. And over time, I realized I could make it an actually useful tool, with no real competition: a 3D model viewer in the terminal. Sure, there are some similar projects on GitHub (like taigrr’s trophy), but none are actually usable with heavier models or support pixel graphics. What I learned I learned a lot. I really mean a lot. Anything from math and rendering to how terminals work and how to control them using escape sequences. I don’t want to sit here and name everything I learned over the period of the last 5 months, but I can confidently say that this project really taught me how much work goes into everyday software and how to actually develop and maintain a project professionally. The future of rasterminal The whole project is very far from done. You can see that from the latest release version: v0.1.0-alpha.2. I’ve got a lot of work to do and I’ve roughly got the major landmarks mapped out. Main things I definitely want to change/add at some point before v1 are: Add animation support (currently can only render still meshes) Complete the renderer (complete support for basically every feature of every format that makes sense to support) Add optional GPU acceleration (after I’m satisfied with everything else) Hardware / OS support Supports every major OS (Windows, Linux, MacOS, and any other POSIX-based OS, so practically everything), and every CPU that I could think of (any architecture, 32 or 64bit). You would have to actually try a to find a platform that it doesn’t support (most of the unsupported hardware are big-endian systems, which are basically phased out completely). This is one of the main goals of the project, so (almost) any modern machine with a terminal can run it. Special thanks Special thanks to anyone who followed, liked, helped, or otherwise supported the project in any way. I wouldn’t have had the motivation to push it this far if it wasn’t for you guys....
|
1793274652.2442877
|
1793361052.2442877
|
|
7168
|
rat by @ttyChud | Stardance
|
ttyChud
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: rat by @ttyChud | Stardance
|
1792925610.2864182
|
1793789610.2864182
|
|
29793
|
raven by @kuruni | Stardance
|
kuruni
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: raven by @kuruni | Stardance
|
1793170422.4606702
|
1793775222.4606702
|
|
10358
|
rawFilm by @not-willem | Stardance
|
not-willem
|
0
|
2.69
|
0
|
[]
|
[{"post_id": 5368, "ts": "2026 [{"post_id": 5368, "ts": "2026-06-09T03:33:52Z", "hours": 1.8556, "text": "rawFilm a program to restore old films to look like they’ve been taken by a modern day digital camera currently ive made a command line interface and worked a little bit on the actual video fixing. Ive made background flicker fixing and i would show some examples but the video im using as a test is really long and i cant be bothered to get a smaller video haha anyway im gonna add in some video jitter fixes and denoising to remove the film grain and then MAYBE colorizing as an option but i assume it would be slow also i forgot to add but i HAVE implemented a FFmpeg thing to convert the video to an image sequence and then use pillow to edit it."}, {"post_id": 4059, "ts": "2026-06-07T07:32:06Z", "hours": 0.8306, "text": "Started coding a command line interface. Gotta actually make the program do its job but heres the plan: use Pillow to take the images, find the general brightness of the image and then tone up or down the rest of the images to have the same levels of brightness as the middle frame or a different frame if you choose then maybe a bit later I’ll add some line detection if its a cartoon to extract the lines and colors if a video is like REALLY bad but yeah :D it’ll be cool"}]...
|
Title: rawFilm by @not-willem | Stardance
Devlogs Title: rawFilm by @not-willem | Stardance
Devlogs:
Started coding a command line interface. Gotta actually make the program do its job but heres the plan: use Pillow to take the images, find the general brightness of the image and then tone up or down the rest of the images to have the same levels of brightness as the middle frame or a different frame if you choose then maybe a bit later I’ll add some line detection if its a cartoon to extract the lines and colors if a video is like REALLY bad but yeah :D it’ll be cool
rawFilm a program to restore old films to look like they’ve been taken by a modern day digital camera currently ive made a command line interface and worked a little bit on the actual video fixing. Ive made background flicker fixing and i would show some examples but the video im using as a test is really long and i cant be bothered to get a smaller video haha anyway im gonna add in some video jitter fixes and denoising to remove the film grain and then MAYBE colorizing as an option but i assume it would be slow also i forgot to add but i HAVE implemented a FFmpeg thing to convert the video to an image sequence and then use pillow to edit it....
|
1793253226.0361938
|
1793858026.0361938
|
|
29890
|
raycast engine by @kan411 | Stardance
|
kan411
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: raycast engine by @kan411 | Stardance
|
1792932794.4612145
|
1793796794.4612145
|
|
182
|
rayjam by @logabe | Stardance
|
logabe
|
0
|
0.55
|
0
|
[]
|
[{"post_id": 17, "ts": "2026-0 [{"post_id": 17, "ts": "2026-05-31T07:58:22Z", "hours": 0.5472, "text": "Hello Stardance! Here’s a very quick devlog so I can test this out before I go to bed haha. I threw together a music player program in C w/ Raylib. You drag in the file you want to play and it will loop it until you close the program or drag in another one. Happy hacking!!"}]...
|
Title: rayjam by @logabe | Stardance
Devlogs:
Hel Title: rayjam by @logabe | Stardance
Devlogs:
Hello Stardance! Here’s a very quick devlog so I can test this out before I go to bed haha. I threw together a music player program in C w/ Raylib. You drag in the file you want to play and it will loop it until you close the program or drag in another one. Happy hacking!!...
|
1792795725.6119006
|
1793400525.6119006
|
|
37974
|
raytracer by @saltn | Stardance
|
saltn
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: raytracer by @saltn | Stardance
|
1793231749.2484589
|
1793836549.2484589
|
|
46470
|
rbpt by @unfreeinfreedom | Stardance
|
unfreeinfreedom
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: rbpt by @unfreeinfreedom | Stardance
|
1793386309.3600936
|
1793991109.3600936
|
|
61003
|
rc car by @AgentK | Stardance
|
AgentK
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: rc car by @AgentK | Stardance
|
1793037152.7167134
|
1793641952.7167134
|
|
45735
|
rc car by @AryaD | Stardance
|
AryaD
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: rc car by @AryaD | Stardance
|
1793350486.9820633
|
1793955286.9820633
|
|
35473
|
rc car by @KobeL | Stardance
|
KobeL
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: rc car by @KobeL | Stardance
|
1792806513.2475684
|
1793411313.2475684
|
|
52180
|
rc car by @Nova-Tech | Stardance
|
Nova-Tech
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: rc car by @Nova-Tech | Stardance
|
1793425958.1387982
|
1794030758.1387982
|
|
51806
|
rc car by @chrif | Stardance
|
chrif
|
0
|
22.69
|
0
|
[]
|
[{"post_id": 71330, "ts": "202 [{"post_id": 71330, "ts": "2026-09-20T17:11:35Z", "hours": 5.9003, "text": "i finished the schematics in kicad, then made the case/shell and made it link with the chassis using magnets then i made the github for the project and set everything up including the readme and exporting the bodies for 3d printing then i made the zine and with that the project is pretty much done (note: i might come back to it or reuse it for other projects and add stuff like cameras or path finding or ai detection or a bionic hand or something)"}, {"post_id": 69309, "ts": "2026-09-16T19:34:44Z", "hours": 2.1169, "text": "i finished the cad and steering and now we need to do the schematics, the programming, and the case"}, {"post_id": 66121, "ts": "2026-09-11T18:48:44Z", "hours": 7.065, "text": "dude omg i made an error on the last devlog by putting the motor next to the two wheel gears without a differential so i thought “ oh easy i just need to add a differential and that’s it” it was not that easy. you can tell by the amount of time that i spent a lot of time trying to figure this out but i finally got it to work after endless mistakes and fusion 360 hickups and glitches and inconvenieces but im pretty sure it should work this time i just need to add the steering and we’re pretty much done with cad"}, {"post_id": 59257, "ts": "2026-08-31T23:02:10Z", "hours": 1.2, "text": "today i fixed the problems with the axles not aligning and then i finished designing the gearboxes and honestly it was easer than i though, before starting the project i thought it was going to be a way bigger prolem than it actually was now i only have the steering left and that will be all the cad work done for now i hope to tackle a more challenging project in the future"}, {"post_id": 58330, "ts": "2026-08-30T18:28:13Z", "hours": 2.2022, "text": "i added the ball bearings that let the wheels turn and then i started working on the gearbox while fixing some design mistakes along the way, looking for how to get a 3d model of a bevel gear was a problem but that got solved quickly although putting them in place on the assembly was tough but when i went to add the axles that connect to the back wheels i noticed a fatal mistake i made is that i forgot that the wheels have to be on the same height yet i put the front wheels too high up or the back wheels too low down either way its going to be a hassle fixing it i wish i noticed it earlier"}, {"post_id": 55253, "ts": "2026-08-26T22:21:37Z", "hours": 2.5922, "text": "i added the spinning axles on the front and made space for the ball bearings since i couldnt find a model for them anywhere and shaped the axle to fing the standart rc car wheels (the yellow ones that are in every beginers kit) and made mounting holes for all the components now all thats left cad-wise is to make the gearbox and the rear axles and then i have to make the schematics and then the programming"}, {"post_id": 51757, "ts": "2026-08-21T16:18:35Z", "hours": 1.6169, "text": "today i planned out the whole project and what i want the final product to look like and then a 3d model to place the components and see how the dimensions will fit together as well as picking the components needed for the bare minimum prototype"}]...
|
Title: rc car by @chrif | Stardance
Devlogs:
toda Title: rc car by @chrif | Stardance
Devlogs:
today i planned out the whole project and what i want the final product to look like and then a 3d model to place the components and see how the dimensions will fit together as well as picking the components needed for the bare minimum prototype
i added the spinning axles on the front and made space for the ball bearings since i couldnt find a model for them anywhere and shaped the axle to fing the standart rc car wheels (the yellow ones that are in every beginers kit) and made mounting holes for all the components now all thats left cad-wise is to make the gearbox and the rear axles and then i have to make the schematics and then the programming
i added the ball bearings that let the wheels turn and then i started working on the gearbox while fixing some design mistakes along the way, looking for how to get a 3d model of a bevel gear was a problem but that got solved quickly although putting them in place on the assembly was tough but when i went to add the axles that connect to the back wheels i noticed a fatal mistake i made is that i forgot that the wheels have to be on the same height yet i put the front wheels too high up or the back wheels too low down either way its going to be a hassle fixing it i wish i noticed it earlier
today i fixed the problems with the axles not aligning and then i finished designing the gearboxes and honestly it was easer than i though, before starting the project i thought it was going to be a way bigger prolem than it actually was now i only have the steering left and that will be all the cad work done for now i hope to tackle a more challenging project in the future
dude omg i made an error on the last devlog by putting the motor next to the two wheel gears without a differential so i thought “ oh easy i just need to add a differential and that’s it” it was not that easy. you can tell by the amount of time that i spent a lot of time trying to figure this out but i finally got it to work after endless mistakes and fusion 360 hickups and glitches and inconvenieces but im pretty sure it should work this time i just need to add the steering and we’re pretty much done with cad
i finished the cad and steering and now we need to do the schematics, the programming, and the case
i finished the schematics in kicad, then made the case/shell and made it link with the chassis using magnets then i made the github for the project and set everything up including the readme and exporting the bodies for 3d printing then i made the zine and with that the project is pretty much done (note: i might come back to it or reuse it for other projects and add stuff like cameras or path finding or ai detection or a bionic hand or something)...
|
1793408155.921622
|
1794012955.921622
|
|
12044
|
rc car by @demircimustafacan08 | Stardance
|
demircimustafacan08
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: rc car by @demircimustafacan08 | Stardance
|
1793317886.9483917
|
1793922686.9483917
|
|
31878
|
rc car by @harjassinghghedu | Stardance
|
harjassinghghedu
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: rc car by @harjassinghghedu | Stardance
|
1793314318.7828465
|
1793919118.7828465
|
|
35627
|
rc car by @hemantradhakrishnan | Stardance
|
hemantradhakrishnan
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: rc car by @hemantradhakrishnan | Stardance
|
1793181357.5817738
|
1793786157.5817738
|
|
7541
|
rc car by @jonathanwillner | Stardance
|
jonathanwillner
|
0
|
24.0
|
0
|
[]
|
[{"post_id": 3227, "ts": "2026 [{"post_id": 3227, "ts": "2026-06-06T01:48:55Z", "hours": 24.0, "text": "e"}]...
|
Title: rc car by @jonathanwillner | Stardance
Dev Title: rc car by @jonathanwillner | Stardance
Devlogs:
e...
|
1792954161.0555346
|
1793818161.0555346
|
|
45727
|
rc car that anybody can controll anywhere from the rc car that anybody can controll anywhere from the world by @IlliaMarkov | Stardance...
|
IlliaMarkov
|
0
|
4.97
|
0
|
[]
|
[{"post_id": 62493, "ts": "202 [{"post_id": 62493, "ts": "2026-09-05T21:38:06Z", "hours": 0.8833, "text": "THE WEBSITE IS LIVE FOR TESTING! You can drive my rc yes you cab drive it here are the links for both controll and additinal veiw: THE RC CAR CONTROLL: https://disk-patch-survival-tap.trycloudflare.com/ TOP VEIW: https://danny-digital-axis-before.trycloudflare.com/ GITHUB: https://github.com/IlliaMarkovCode/webcontrol_V4 I have added a que system so if you see the sorry screan just wait for a bit and then it will let you leave when the other person leave. When you leaving the website use A BIG YELLOW BUTTON TO LEAVE the websute my brake and not let the other person join before the time of runns out. Have fun with the car but if there are any isseus leave a comment I will try to fix them before I ship but again have fun."}, {"post_id": 56992, "ts": "2026-08-29T01:50:41Z", "hours": 0.3833, "text": "Big changes for my website controlled rc car, I mostly solved all the issue is had before, added buttons so people can control thought the phone, added a little arm so people can pick and place stuff with it really fun, and most importantly a webcam to to the robot so people can see the view and put it on a website it’s really coming together. also I modified one of the model of wheel to make it fit my car and when to my local libry to print it not sure if I am gonna use them yet but they look pro ig, but I really like it :D Code(it used flask now and also I added stl file for the wheels): https://github.com/IlliaMarkovCode/webcontrol_V3"}, {"post_id": 56240, "ts": "2026-08-27T22:23:21Z", "hours": 0.5264, "text": "WEBSITE CAN RUN PUBLICLY!! Now my RC car can be controller by basically anybody thought website(running though Cloudflare tunnel service)but I am not releasing into the public just yet. I am not even sure if my website is safe. It still need a lot of improvements. It need vison, some sort of line system and mobile support I still have a lot of work to be done, but I am getting closer and closer. Code: https://github.com/IlliaMarkovCode/webcontrol_V2"}, {"post_id": 55189, "ts": "2026-08-26T18:16:05Z", "hours": 0.6, "text": "GOT THE WEBSITE WORKING!! Sadly for now it only running locally so I can host it only network but, it fixed all the issue with delays and inputs(had to ask claude for this one), and I made the robot smaller and now it turn no problem, I am still waiting for a smaller power bank to arrive so I can but on the robot byt we are getting there. Code: https://github.com/IlliaMarkovCode/webcontrol_V1"}, {"post_id": 54626, "ts": "2026-08-25T17:27:40Z", "hours": 1.2503, "text": "I got two prototype working, the fist one I tired was without the front wheels just to see how it works, it worked okey but because I used pynput libery it had an issue where it would have a gap in between driving so I added a timeout so where there was gap in input it would just skip it but it added another issue where it would have a delay when I actually when I release the key to stop, and then later I added front wheel but I had trouble running, I thinks it’s because how far away they are from the turning point so I am gonna move it closer together YEYEYE Code: https://github.com/IlliaMarkovCode/motor_test_V2_and_V3"}, {"post_id": 54169, "ts": "2026-08-25T01:05:05Z", "hours": 0.8833, "text": "Firstly I had to buy some electrical components with was probaly the most terios part. If you live in London ON I would strongly recommend Electrical & Electronic Supply Inc it has basically everything you need for a Arduino or the raspberry pi I got all the part no problem and it costed around $50 for all I needed and soldering iron. I did quite a bit of testing with the motors I got and one of them to spin with a simple code and then with a proper code I got all 4 spinning in order. Code: https://github.com/IlliaMarkovCode/motor_test_V1_and_V2"}, {"post_id": 54108, "ts": "2026-08-24T22:14:37Z", "hours": 0.4442, "text": "This project has already been moslty fnished, but I discoved about the hackclub just about now I still wanna share the project that I have been working on over this summer. I am gonna split it in to multiple devlog tring to show how my progres went on my rc car. I have quite a bit I can share and maybe so of you might be try it yourself so IDK enjoy."}]...
|
Title: rc car that anybody can controll anywhere f Title: rc car that anybody can controll anywhere from the world by @IlliaMarkov | Stardance
Devlogs:
This project has already been moslty fnished, but I discoved about the hackclub just about now I still wanna share the project that I have been working on over this summer. I am gonna split it in to multiple devlog tring to show how my progres went on my rc car. I have quite a bit I can share and maybe so of you might be try it yourself so IDK enjoy.
Firstly I had to buy some electrical components with was probaly the most terios part. If you live in London ON I would strongly recommend Electrical & Electronic Supply Inc it has basically everything you need for a Arduino or the raspberry pi I got all the part no problem and it costed around $50 for all I needed and soldering iron. I did quite a bit of testing with the motors I got and one of them to spin with a simple code and then with a proper code I got all 4 spinning in order. Code: https://github.com/IlliaMarkovCode/motor_test_V1_and_V2
I got two prototype working, the fist one I tired was without the front wheels just to see how it works, it worked okey but because I used pynput libery it had an issue where it would have a gap in between driving so I added a timeout so where there was gap in input it would just skip it but it added another issue where it would have a delay when I actually when I release the key to stop, and then later I added front wheel but I had trouble running, I thinks it’s because how far away they are from the turning point so I am gonna move it closer together YEYEYE Code: https://github.com/IlliaMarkovCode/motor_test_V2_and_V3
GOT THE WEBSITE WORKING!! Sadly for now it only running locally so I can host it only network but, it fixed all the issue with delays and inputs(had to ask claude for this one), and I made the robot smaller and now it turn no problem, I am still waiting for a smaller power bank to arrive so I can but on the robot byt we are getting there. Code: https://github.com/IlliaMarkovCode/webcontrol_V1
WEBSITE CAN RUN PUBLICLY!! Now my RC car can be controller by basically anybody thought website(running though Cloudflare tunnel service)but I am not releasing into the public just yet. I am not even sure if my website is safe. It still need a lot of improvements. It need vison, some sort of line system and mobile support I still have a lot of work to be done, but I am getting closer and closer. Code: https://github.com/IlliaMarkovCode/webcontrol_V2
Big changes for my website controlled rc car, I mostly solved all the issue is had before, added buttons so people can control thought the phone, added a little arm so people can pick and place stuff with it really fun, and most importantly a webcam to to the robot so people can see the view and put it on a website it’s really coming together. also I modified one of the model of wheel to make it fit my car and when to my local libry to print it not sure if I am gonna use them yet but they look pro ig, but I really like it :D Code(it used flask now and also I added stl file for the wheels): https://github.com/IlliaMarkovCode/webcontrol_V3
THE WEBSITE IS LIVE FOR TESTING! You can drive my rc yes you cab drive it here are the links for both controll and additinal veiw: THE RC CAR CONTROLL: https://disk-patch-survival-tap.trycloudflare.com/ TOP VEIW: https://danny-digital-axis-before.trycloudflare.com/ GITHUB: https://github.com/IlliaMarkovCode/webcontrol_V4 I have added a que system so if you see the sorry screan just wait for a bit and then it will let you leave when the other person leave. When you leaving the website use A BIG YELLOW BUTTON TO LEAVE the websute my brake and not let the other person join before the time of runns out. Have fun with the car but if there are any isseus leave a comment I will try to fix them before I ship but again have fun....
|
1793350448.5805016
|
1793955248.5805016
|
|
18162
|
rc plane by @berzs | Stardance
|
berzs
|
0
|
1.64
|
0
|
[]
|
[{"post_id": 15583, "ts": "202 [{"post_id": 15583, "ts": "2026-06-25T10:47:10Z", "hours": 0.5472, "text": "I spent the day wiring up the electronics for the esp now protocol. Sadly it has much more latency than i thought it would have. But theres no stopping. I will assemble the plane but have doubts about its capabilities."}, {"post_id": 13074, "ts": "2026-06-21T11:56:50Z", "hours": 0.8028, "text": "built this prototype in cad. i will make it out of foam then build the electornics for it. this smalll prototype will use esp now protocol for the controlling. Designed it using a couple of rule of thumbs. will do a testflight and adjust accordingly"}, {"post_id": 8304, "ts": "2026-06-13T20:09:00Z", "hours": 0.2936, "text": "making a smaller prototype, will build it next week made the motor mount and the fuselage"}]...
|
Title: rc plane by @berzs | Stardance
Devlogs:
ma Title: rc plane by @berzs | Stardance
Devlogs:
making a smaller prototype, will build it next week made the motor mount and the fuselage
built this prototype in cad. i will make it out of foam then build the electornics for it. this smalll prototype will use esp now protocol for the controlling. Designed it using a couple of rule of thumbs. will do a testflight and adjust accordingly
I spent the day wiring up the electronics for the esp now protocol. Sadly it has much more latency than i thought it would have. But theres no stopping. I will assemble the plane but have doubts about its capabilities....
|
1793350319.545056
|
1793955119.545056
|
|
20863
|
reFlow by @Aki | Stardance
|
Aki
|
1
|
5.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-26T11:45:46Z", "hours": 5.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Honestly a fun project to start with, was QUITE confusing (why math) at the beginning but turned quite fun at the end. Ngl, the hardest part was actually setting up directories and making stuff point at other stuff in the correct way rather than making the actual code (yes im dumb okay) and that took MOST of my time and wasn’t even logged (21h GONE) cuz i forgot to download the desktop application and the only time logged was in the AI debug sesh and inspos and rules in Chrome…. sadness.", "repo": "https://github.com/extension1/reFlow", "demo": "https://reflow-337435966196.asia-southeast1.run.app/"}]...
|
[{"post_id": 12254, "ts": "202 [{"post_id": 12254, "ts": "2026-06-20T00:42:01Z", "hours": 1.8578, "text": "reFlow Devlog 4 — pain & suffering++ long one, buckle up. also never posted devlog 3, so some of that’s folded in here. hour 13 (retroactive): hardware hijacking wanted the tunnel to interrogate your PC. hooked into the WebGL debug renderer extension for real GPU model strings (had to regex out ANGLE’s prefix junk), navigator.hardwareConcurrency for core count, performance.memory for live JS heap, and the Battery API for charge state. built a perf tracker timing the physics loop per frame — if it blows the 16ms budget, System Stress flips to CRITICAL with specific diagnoses like “Low Core Alert” instead of just “it’s lagging.” hour 17: the great physics divorce the entire physics engine was crammed inside Three.js’s render loop in WindTunnel.tsx. worked at 10k particles, died at 30k+ — browser froze, laptop got loud. ripped every physics function into a standalone physics.ts — pure math, zero Three.js imports, just numbers in and out. took two hours of replacing Vector3.set() calls with raw tuples and hand-rolled rotation matrices. hour 18: web workers enter the chat moved the whole particle loop off the main thread into a Web Worker via Vite’s one-line worker syntax. main thread sends position/velocity/color arrays, worker crunches 40k particles, sends them back. UI never freezes. used Transferable objects so arrays move by ownership transfer instead of getting copied every frame. added a main-thread fallback if workers fail to load. hour 19: the wake was lying to me old turbulence was just Math.sin() — predictable, periodic, fake. replaced with hash-based pseudo-random noise for organic chaos, added von Kármán vortex shedding behind bluff bodies (alternating vortex pairs, like lampposts oscillating in wind), and a no-slip boundary layer so particles slow down near surfaces instead of just bouncing. hour 20: the car was ugly and the flat plate was a brick car was a 2D extruded polygon that looked like a cheese wedge. rebuilt with bezier/quadratic curves for a real windshield, roofline, and spoiler lip, plus wheel arch cutouts. flat plate was basically a cutting board (BoxGeometry(0.3, 5.8, 5.8)) — thinned to 0.08 with beveled edges so it actually reads as a plate. hour 21: torus goes brrr torus was hardcoded. added live sliders for major radius (1.5–6.0) and minor radius (0.3–2.5) that rebuild the geometry AND feed the physics engine in real time. thin ring = ethereal vortex shedding, chonky donut = half-blocked tunnel. added an R/r ratio readout because it sounds smart. hour 22: the sidebar was eating my screen between left controls, right diagnostics, a bottom chart/AI panel, and a header full of badges, the 3D canvas shrank to a postage stamp. added collapsible panels — chevron toggles collapse the sidebars to thin strips and the canvas reclaims ~80% of the screen. sometimes the best feature is removing stuff. hour 23: the absolute madman feature (GLB loader) end of devlog 3 I said “maybe a glTF loader, we’ll see.” we saw. you can now upload any .glb/.gltf, and the app auto-scales/centers it, then voxelizes it — shoots rays through a 48×48×48 grid, counts intersections, and marks solid vs. air. physics engine uses that voxel grid for collisions. not physically perfect, but you can drop in a Stanford bunny and watch particles flow around its ears. file count went from 2 source files to 5. physics.ts alone is 731 lines of math. wrote more linear algebra this week than my whole school career. up next: markdown rendering for AI reports, and fixing the README’s leftover “YOUR_USERNAME” placeholders before anyone notices."}, {"post_id": 11360, "ts": "2026-06-18T16:00:42Z", "hours": 0.81, "text": "reFlow Devlog #2 - moar suffering!!!! round two. we are back. the wind tunnel is no longer just a 3d playground; it’s a quantum control deck. here is how i spent the last few hours losing sleep over perspective cameras, slice projection math, and custom state toggle controls. hour 7: the flatland incursion (toggling 2d slice mode) why turn a 3d tunnel back to 2d? because aerodynamics is all about cross-sections. how to constrain a 3d particle swarm to 2d without a total refactor: when “is2D” is true, we hijack the particle spawner. instead of spreading particles across x-axis depth, we force positions[idx] = (Math.random() - 0.5) * 0.1, wrapping the flow into a super thin sheet at x = 0. we also restricted the smoke line emitters to a vertical slice. the result looks like a clean laser-cut sheet of wind passing through the wing. (not really, but it’s the thought that counts) hour 8: camera capture and control hijacking particles are in 2d, but the camera still rotates in 3d. rotating it breaks the illusion (just a flat sheet of dots). solution: camera hijacking. when 2d mode triggers, we fly the camera to (38, 0, 0) looking down the x-axis at the wing. we disable OrbitControls rotation (controls.enableRotate = false) and force camera.up.set(0, 1, 0). debugging this was a nightmare—OrbitControls flips the camera if target/up vectors aren’t updated first. now, swapping dimensions is smooth. hour 9: freezing time (the pause engine) sometimes wind moves too fast to see gradients. we need a freeze-frame. added “isPaused” state. first try: skip the animate loop. but that froze the rendering, stopping camera rotation. second try: keep the rendering loop active, but bypass particle position updates. now you can pause, orbit in 3d, and inspect smoke streams and vectors suspended in amber. sci-fi vibes. hour 10: tuning the storm (particle customizability) default 6,000 particles is cool, but my GPU was barely breaking a sweat. expanded particle count up to 20,000 (step 1000) and added a size slider (0.1 to 1.5). adjusting particle size from tiny dust specks to fat plasma spheres is satisfying. setting count to 20,000 makes the wind tunnel look like a dense gas nebula. the cpu is sweating, but performance is smooth thanks to typed buffer array updates. hour 11: cyberpunk telemetry deck (hud overhaul) with new toggleable states (2d/3d and pause/play), the dashboard needed a facelift. built a cyber-cyan “Switch 2D” button with custom ambient glow shadows (shadow-[0_0_15px_rgba(125,249,255,0.15)]) and a yellow pause button changing to play icon. added a footer telemetry status pill showing “2D Slice | [Active Object]” vs “3D Space | [Active Object]”. makes the app feel like a high-budget engineering interface. hour 12: collision math strikes back (local normals) particles clipped through spherical and box obstacles due to lazy velocity mirroring. introduced a robust getNormalLocal(type, x, y, z) helper. when a particle collides with a sphere, we calculate the exact radial normal: (x/r, y/r, z/r). for box geometry, the helper evaluates which face was breached (min === dx logic) and returns an axis normal. now particles bounce and slide off physical bodies with realistic deflection vectors. no more ghosting. next up: actually making the visuals work (someone send help)"}, {"post_id": 10728, "ts": "2026-06-17T16:39:49Z", "hours": 2.4094, "text": "reFlow Devlog 1 - building a 3d wind tunnel without losing my mind (?) enjoy my suffering. hour 1: the “it’s not that hard” phase decided on: react, three.js, and tailwind css. getting three.js to render took half an hour because i forgot lights. stared at a pitch black void wondering why my life is like this. finally got a grey cube spinning. les go spinny coob hour 2: wikipedia math is scary goal: make an airfoil (wing shape). searched “naca airfoil math formula” and got hit with an abomination of an equation: yt = 5 * t * (0.2969 * sqrt(x) - 0.1260 * x - 0.3516 * x^2 + 0.2843 * x^3 - 0.1015 * x^4). wouldn’t have signed up if i knew math was involved. translated it into a javascript loop generating a THREE.Shape. my eyes watered staring at parentheses. messed up the loop direction 3 times and made twisted metal instead of a wing. had to scale it up cuz default was microscopic. after 4 tries, it looks like a wing. LETS GOOO hour 3: the wind has to blow made a particle system with 6,000 points. spawn at front, move back, respawn. easy, but particles must bend around the wing. wrote a collision loop. first draft: particles got stuck, formed a massive blue blob. second draft: calculated slope. particles flew off at 90-degree angles. coded a simplified double-flow vector calc. not real CFD (my laptop would explode running Navier-Stokes), but it looks real. hour 4: adding cool dashboards app needed to look like a telemetry deck. added: sidebar with sliders for viscosity, inlet speed, angle of attack. custom html5 canvas real-time graph. draws lift (cyan) and drag (orange) lines. legit math at home guys. pressure heatmap. flat vertical plane in center. slow air hitting nose = high pressure (RED). fast air over top = low pressure (NEON GREEN). tilting the wing shifts the red spot. ASMR for the eyes wooooo hour 5: stall warning and ai pilot added stall physics! over 15deg tilt, lift cuts by 70% and drag multiplies. added a flashing CRITICAL STALL WARNING banner. integrated Gemini API for aero reports then realized this comp requires no auth, so api keys are prolly an issue. wrote a local backup expert system. no API key = runs generateLocalReport() with rule-based templates. 100% plug-and-play. hour 6: single-file challenge wanted app super portable. one .html file. vite/tailwind output to .js and .css. wrote bundle.js to inline them which ended up giving “ReferenceError: require is not defined in ES module scope.” bruh. renamed it to bundle.cjs and that worked yay btw throwing html into google AI studio gets a free hosted site?? the more you know i guess lots of math still broken lol. coolest project i’ve built though. going to sleep for a week."}]...
|
Title: reFlow by @Aki | Stardance
Devlogs:
reFlow Title: reFlow by @Aki | Stardance
Devlogs:
reFlow Devlog 1 - building a 3d wind tunnel without losing my mind (?) enjoy my suffering. hour 1: the “it’s not that hard” phase decided on: react, three.js, and tailwind css. getting three.js to render took half an hour because i forgot lights. stared at a pitch black void wondering why my life is like this. finally got a grey cube spinning. les go spinny coob hour 2: wikipedia math is scary goal: make an airfoil (wing shape). searched “naca airfoil math formula” and got hit with an abomination of an equation: yt = 5 * t * (0.2969 * sqrt(x) - 0.1260 * x - 0.3516 * x^2 + 0.2843 * x^3 - 0.1015 * x^4). wouldn’t have signed up if i knew math was involved. translated it into a javascript loop generating a THREE.Shape. my eyes watered staring at parentheses. messed up the loop direction 3 times and made twisted metal instead of a wing. had to scale it up cuz default was microscopic. after 4 tries, it looks like a wing. LETS GOOO hour 3: the wind has to blow made a particle system with 6,000 points. spawn at front, move back, respawn. easy, but particles must bend around the wing. wrote a collision loop. first draft: particles got stuck, formed a massive blue blob. second draft: calculated slope. particles flew off at 90-degree angles. coded a simplified double-flow vector calc. not real CFD (my laptop would explode running Navier-Stokes), but it looks real. hour 4: adding cool dashboards app needed to look like a telemetry deck. added: sidebar with sliders for viscosity, inlet speed, angle of attack. custom html5 canvas real-time graph. draws lift (cyan) and drag (orange) lines. legit math at home guys. pressure heatmap. flat vertical plane in center. slow air hitting nose = high pressure (RED). fast air over top = low pressure (NEON GREEN). tilting the wing shifts the red spot. ASMR for the eyes wooooo hour 5: stall warning and ai pilot added stall physics! over 15deg tilt, lift cuts by 70% and drag multiplies. added a flashing CRITICAL STALL WARNING banner. integrated Gemini API for aero reports then realized this comp requires no auth, so api keys are prolly an issue. wrote a local backup expert system. no API key = runs generateLocalReport() with rule-based templates. 100% plug-and-play. hour 6: single-file challenge wanted app super portable. one .html file. vite/tailwind output to .js and .css. wrote bundle.js to inline them which ended up giving “ReferenceError: require is not defined in ES module scope.” bruh. renamed it to bundle.cjs and that worked yay btw throwing html into google AI studio gets a free hosted site?? the more you know i guess lots of math still broken lol. coolest project i’ve built though. going to sleep for a week.
reFlow Devlog #2 - moar suffering!!!! round two. we are back. the wind tunnel is no longer just a 3d playground; it’s a quantum control deck. here is how i spent the last few hours losing sleep over perspective cameras, slice projection math, and custom state toggle controls. hour 7: the flatland incursion (toggling 2d slice mode) why turn a 3d tunnel back to 2d? because aerodynamics is all about cross-sections. how to constrain a 3d particle swarm to 2d without a total refactor: when “is2D” is true, we hijack the particle spawner. instead of spreading particles across x-axis depth, we force positions[idx] = (Math.random() - 0.5) * 0.1, wrapping the flow into a super thin sheet at x = 0. we also restricted the smoke line emitters to a vertical slice. the result looks like a clean laser-cut sheet of wind passing through the wing. (not really, but it’s the thought that counts) hour 8: camera capture and control hijacking particles are in 2d, but the camera still rotates in 3d. rotating it breaks the illusion (just a flat sheet of dots). solution: camera hijacking. when 2d mode triggers, we fly the camera to (38, 0, 0) looking down the x-axis at the wing. we disable OrbitControls rotation (controls.enableRotate = false) and force camera.up.set(0, 1, 0). debugging this was a nightmare—OrbitControls flips the camera if target/up vectors aren’t updated first. now, swapping dimensions is smooth. hour 9: freezing time (the pause engine) sometimes wind moves too fast to see gradients. we need a freeze-frame. added “isPaused” state. first try: skip the animate loop. but that froze the rendering, stopping camera rotation. second try: keep the rendering loop active, but bypass particle position updates. now you can pause, orbit in 3d, and inspect smoke streams and vectors suspended in amber. sci-fi vibes. hour 10: tuning the storm (particle customizability) default 6,000 particles is cool, but my GPU was barely breaking a sweat. expanded particle count up to 20,000 (step 1000) and added a size slider (0.1 to 1.5). adjusting particle size from tiny dust specks to fat plasma spheres is satisfying. setting count to 20,000 makes the wind tunnel look like a dense gas nebula. the cpu is sweating, but performance is smooth thanks to typed buffer array updates. hour 11: cyberpunk telemetry deck (hud overhaul) with new toggleable states (2d/3d and pause/play), the dashboard needed a facelift. built a cyber-cyan “Switch 2D” button with custom ambient glow shadows (shadow-[0_0_15px_rgba(125,249,255,0.15)]) and a yellow pause button changing to play icon. added a footer telemetry status pill showing “2D Slice | [Active Object]” vs “3D Space | [Active Object]”. makes the app feel like a high-budget engineering interface. hour 12: collision math strikes back (local normals) particles clipped through spherical and box obstacles due to lazy velocity mirroring. introduced a robust getNormalLocal(type, x, y, z) helper. when a particle collides with a sphere, we calculate the exact radial normal: (x/r, y/r, z/r). for box geometry, the helper evaluates which face was breached (min === dx logic) and returns an axis normal. now particles bounce and slide off physical bodies with realistic deflection vectors. no more ghosting. next up: actually making the visuals work (someone send help)
reFlow Devlog 4 — pain & suffering++ long one, buckle up. also never posted devlog 3, so some of that’s folded in here. hour 13 (retroactive): hardware hijacking wanted the tunnel to interrogate your PC. hooked into the WebGL debug renderer extension for real GPU model strings (had to regex out ANGLE’s prefix junk), navigator.hardwareConcurrency for core count, performance.memory for live JS heap, and the Battery API for charge state. built a perf tracker timing the physics loop per frame — if it blows the 16ms budget, System Stress flips to CRITICAL with specific diagnoses like “Low Core Alert” instead of just “it’s lagging.” hour 17: the great physics divorce the entire physics engine was crammed inside Three.js’s render loop in WindTunnel.tsx. worked at 10k particles, died at 30k+ — browser froze, laptop got loud. ripped every physics function into a standalone physics.ts — pure math, zero Three.js imports, just numbers in and out. took two hours of replacing Vector3.set() calls with raw tuples and hand-rolled rotation matrices. hour 18: web workers enter the chat moved the whole particle loop off the main thread into a Web Worker via Vite’s one-line worker syntax. main thread sends position/velocity/color arrays, worker crunches 40k particles, sends them back. UI never freezes. used Transferable objects so arrays move by ownership transfer instead of getting copied every frame. added a main-thread fallback if workers fail to load. hour 19: the wake was lying to me old turbulence was just Math.sin() — predictable, periodic, fake. replaced with hash-based pseudo-random noise for organic chaos, added von Kármán vortex shedding behind bluff bodies (alternating vortex pairs, like lampposts oscillating in wind), and a no-slip boundary layer so particles slow down near surfaces instead of just bouncing. hour 20: the car was ugly and the flat plate was a brick car was a 2D extruded polygon that looked like a cheese wedge. rebuilt with bezier/quadratic curves for a real windshield, roofline, and spoiler lip, plus wheel arch cutouts. flat plate was basically a cutting board (BoxGeometry(0.3, 5.8, 5.8)) — thinned to 0.08 with beveled edges so it actually reads as a plate. hour 21: torus goes brrr torus was hardcoded. added live sliders for major radius (1.5–6.0) and minor radius (0.3–2.5) that rebuild the geometry AND feed the physics engine in real time. thin ring = ethereal vortex shedding, chonky donut = half-blocked tunnel. added an R/r ratio readout because it sounds smart. hour 22: the sidebar was eating my screen between left controls, right diagnostics, a bottom chart/AI panel, and a header full of badges, the 3D canvas shrank to a postage stamp. added collapsible panels — chevron toggles collapse the sidebars to thin strips and the canvas reclaims ~80% of the screen. sometimes the best feature is removing stuff. hour 23: the absolute madman feature (GLB loader) end of devlog 3 I said “maybe a glTF loader, we’ll see.” we saw. you can now upload any .glb/.gltf, and the app auto-scales/centers it, then voxelizes it — shoots rays through a 48×48×48 grid, counts intersections, and marks solid vs. air. physics engine uses that voxel grid for collisions. not physically perfect, but you can drop in a Stanford bunny and watch particles flow around its ears. file count went from 2 source files to 5. physics.ts alone is 731 lines of math. wrote more linear algebra this week than my whole school career. up next: markdown rendering for AI reports, and fixing the README’s leftover “YOUR_USERNAME” placeholders before anyone notices.
Ships:
Honestly a fun project to start with, was QUITE confusing (why math) at the beginning but turned quite fun at the end. Ngl, the hardest part was actually setting up directories and making stuff point at other stuff in the correct way rather than making the actual code (yes im dumb okay) and that took MOST of my time and wasn’t even logged (21h GONE) cuz i forgot to download the desktop application and the only time logged was in the AI debug sesh and inspos and rules in Chrome…. sadness....
|
1793260430.990943
|
1793346830.990943
|
|
10129
|
reMDer by @Keyboard1000n17 | Stardance
|
Keyboard1000n17
|
0
|
197.03
|
0
|
[]
|
[{"post_id": 71282, "ts": "202 [{"post_id": 71282, "ts": "2026-09-20T16:00:28Z", "hours": 25.7911, "text": "last devlog this is my last devlog the project isn’t complete and i won’t be shipping it. you see, i was banned for 2 months for misconduct on slack (i will not provide details here but i deserved it, it was corny anyway), and as part of that ban, i can’t participate in any events, including stardance. in this time however, i’ve done a lot. there’s now spinners for images, proper tables, and so many more improvements. keep your eyes peeled for a release on the github ! 👀 also it doesn’t matter that this devlog is 15 hours over the limit, its not like i can do anything about it. also if one of you regulars in #stardance see this, can you please ask amber if i can have my sticky streak rewards? i really want the stickers and plushie Changelog ( 446103b ) Render details elements properly again ( f527e5d ) Better logs, align images in row when a paragraph contains only images ( 3df2f59 ) Make task list function use TextChunk over ANSI escapes ( 2367089 ) Add proper tables ( 47c2b42 ) Add aligning components ( 00785d7 ) Move from Chalk/ANSI escapes to OpenTUI StyledText for styles ( 429e4b6 ) Load images lazily with spinner while loading ( a993197 ) Use OpenTUI ImageRenderable for images in renderer ( aa96067 ) Improve types and error handling, work on image bug ( b54ad43 ) Revert “Add footnote plugin (usage WIP) (errors on run)”"}, {"post_id": 64726, "ts": "2026-09-09T11:11:17Z", "hours": 6.0719, "text": "scroll one line at a time, render div and details elements not very big news here, but now you can: scroll just one line at a time instead of a whole renderable/element at once render div and details properly! now you can click on a details element to open and close it! this didn’t even take too long more technical, but i switched to mostly using the opentui renderable api which uses classes like TextRenderable or BoxRenderable that return a Renderable instance instead of functions like Text and Box which return a ProxiedVNode<T> . this is mostly because there’s a bunch of things a Renderable has that a ProxiedVNode doesn’t anyways im currently working on adding footnotes, so see you in a few days Changelog ( 64f6ed8 ) Add footnote plugin (usage WIP) (errors on run) ( ddd5c46 ) Add indicators to details elements and opening on click/space/enter ( 344806a ) Add support for rendering div and details elements ( d3b4a1d ) Fix small layout issues ( 5eb11b9 ) Scroll only one line at a time and convert (mostly) to Renderable API"}, {"post_id": 62808, "ts": "2026-09-06T10:22:48Z", "hours": 10.2442, "text": "table of contents feature is done! took only 10 hours, but im done with the table of contents thing! you can press shift+j to go down to the next heading, and i forgot to add shift+k 😭 anyway this took a while since i couldn’t figure out how to position the box properly and how to style it. this was fucking ass icl. i usually have much more to talk about but this wasn’t the most fun so here’s the commits: Changelog ( 5ccec11 ) Remove unnecessary focusing ToC ( 927cae9 ) Add tab cycling ( ae72d3d ) Scroll ToC menu to selected index instead of blindly 1 down ( 249d61a ) Implement scrolling ToC on pressing J ( a2ae0f2 ) Get table of contents feature working ( a6c7744 ) Add scrolling to next heading on pressing J ( 49f8fec ) Add “? - Help” hint to end of bottom bar"}, {"post_id": 60445, "ts": "2026-09-02T19:38:19Z", "hours": 10.6467, "text": "figlet headings, small headings, bottom bar, help menu and keybinds we’ve got a lot of new stuff! firstly we’ve got a bottom bar! all it does for now is show reMDer with a green bg and the file name next to it, but i’ll add more later! next we’ve got figlet headings! at the start i was thinking about using figlet for headings but i gave up on that. but now, i’m back to using it! this took a good chunk of the overflowing hours here but they look really cool too! passing a --no-render-headings or -H flag will make the headings render as normal text with colors instead of figlet fonts now! there’s now a tiny help menu in the corner! it only shows two keybinds right now–oh and speaking of keybinds… keybindings are now in ! for now you can press q to quit, ? to toggle the help menu, and C (shift+c) to open the console in debug mode and that’s about it next steps? here’s what i’m gonna do next: add support for horizontal rules add a table of contents feature like that of the leaf markdown viewer add some stuff to the bottom bar add an option to put the bottom bar at the top instead add support for a config file using YAML Changelog ( 9557586 ) Add help menu ( a4149e2 ) Add keybinds: q to quit, C to toggle console ( 4b18153 ) Finish figlet fonts support ( d23466d ) Start trying figlet again for ASCII art ( 33d52ea ) Start working on ASCII art for h2 headings ( b0e1668 ) Add option to not print big headings ( c58369c ) Start with bottom bar"}, {"post_id": 56522, "ts": "2026-08-28T10:01:31Z", "hours": 7.42, "text": "code blocks, alerts, emojis and task lists! we’ve got loads of new cool stuff that get rendered now! first, github alerts/callouts now render nicely! they look like this: > [!TAG] > content where TAG can be NOTE , IMPORTANT , TIP , WARNING or CAUTION . they also have these cool icons next to them, but the catch is you need a nerd font for it. i’ll add an option to not need it and only use ascii characters next, we have highlighted code blocks! the renderer can highlight hundreds of languages using shiki ! you might not even have heard of some of the languages that it can highlight! imo its really nice looking and i love it! the bulk of this time came from adding support for task list items because i couldn’t figure out how to do it. eventually after some tinkering i’ve got it to work! it looks kinda cool too tbh i also got emoji support using an extension. it automatically converts :emoji: to the corresponding emoji if its in the unicode specification. finally, i added a simple height option that just sets the height of the renderer. it allows you to set the height of the renderer manually and that’s about it lmao Changelog ( b4f69ad ) Add height option ( beea3a6 ) Add task list items support ( 4c42c84 ) Add emoji support ( 564a761 ) Upgrade markdown-it, fix breaking changes ( 963d910 ) Add alerts support ( 5e266e8 ) Add icons in code blocks ( 0bf0af7 ) Add code block support"}, {"post_id": 54062, "ts": "2026-08-24T20:36:45Z", "hours": 4.4367, "text": "holy fuck, you can pipe into stdin and tables render properly! while this is quite out of schedule (i usually post every 2-3 days), today brings some peak stuff! the peakest part is at the end firstly, i have in fact fixed tables! the issue was i was pushing the accumulated cells array to the rows array in the wrong loop. i was doing this in the loop that iterates over the cells in a row, so it was causing it to repeatedly push the same strings over and over. the fix was putting it in the loop just outside, that is, the loop that iterates over the rows in the table token! i’ve also improved the image handling! now Image classes have the buffer property renamed to content , and has a new property called properties , which is always {} . with this, it has all the properties of ProcessedToken , so my lsp won’t complain that some property doesn’t exist on Image speaking of ProcessedToken , its now an interface instead of a type. there’s also a new TableToken interface that extends ProcessedToken , with an alignment property. this makes it a bit easier to handle tables since the content property is narrowed. also, it seems like opentui’s tables don’t support alignment, so i might have to make a custom table function. i also upgraded opentui from 0.5.7 to 0.5.8! i have no idea what changed, but whatever i’ve also stopped using chalk to color my errors since the opentui console doesn’t support ansi now the peakest part is you can pipe markdown into the program . this is pretty peak and you must agree since there’s a lot of stuff you can do with this. for example, you could render arbitrary markdown without having to create a file first! it has a limitation though: if you’re on windows, you can’t use the interactive mode, and the rendered content is forced to print to stdout. this is because of a bug with bun. if you’re piping into the program, it’ll get the input by calling await Bun.stdin.text() , but this stops sending keypresses to opentui because of a bug in the bun runtime, so you can’t scroll down. i solved this issue (or rather, chatgpt solved this issue) by opening a read stream on /dev/tty . the issue with this is that /dev/tty doesn’t exist on windows since its not unix-like. my idea was to just, not let you do interactive mode on windows if you’re piping content to it. again, this is a bug with bun, and i’ll remove this limitation once one of the two is merged. that’s right, there’s two! here’s one for reference: https://github.com/oven-sh/bun/pull/32153 shit that was long Changelog ( dd07e14 ) Upgrade packages ( 77e6d34 ) Add support for piping into renderer.ts from stdin ( 1995f45 ) Improve image and ANSI handling, stop using chalk in errors ( 22cfacd ) Improve table handling, switch some types to interfaces pls like"}, {"post_id": 53181, "ts": "2026-08-23T16:52:59Z", "hours": 9.7842, "text": "better types. debug mode and stdout! from my last devlog: next up: code blocks (~2-4 hours) fixes to table rendering (<30 mins) fix image handling (it doesn’t handle relative paths correctly) (<1hr?) of these, i’ve done none! what i have done though is add flags and types! i spent a while dealing with type errors because i decided to specify types instead of just putting any on ProcessedToken.content . i also added a debug flag, but literally all it does is show the console i also fixed the width thing, so the content is only as wide as the space you give it so cooll!! the main part of this is that i added a --print-to-stdout flag that just prints the formatted markdown to stdout! you can just scroll in your terminal instead of having a whole ass tui its kinda borked and incomplete though, so i’ll fix it up! it does print some garbage at the beginning so that’s not great anyways, i’d better do what i said i’ll do last devlog! i went off track for this lmao Changelog ( b1c0489 ) Implement half-baked print to stdout option ( aa3c029 ) Add debug flag, fix logic errors ( aa33e84 ) Specify types for ProcessedToken.content instead of any"}, {"post_id": 51600, "ts": "2026-08-21T11:25:29Z", "hours": 8.0094, "text": "(back to) opentui! if you’ve read my last devlog, you might remember that i was considering the jsvision library. however, i came back to opentui because its still much simpler. also, i found that there are libs to adapt ansi! or at least chatgpt did at first i was doing ghostty-opentui , but i realized after some time that it was literally a whole terminal. then i got chatgpt to find me this package called ansi-sequence-parser ( https://www.npmjs.com/package/ansi-sequence-parser ) and its perfect! so now im using that to render the bold and italics! tbh i could just eliminate the middle stage ( stylize.ts ), but i put a lot of work into it and i’m extremely vulnerable to the sunken cost fallacy, so i’m doing this bloat lmao. also, i got ordered lists, bullet lists, and blockquotes working! they look so cool! as for the menu, its not doing very fine, but that’s because i’ve not worked on it! i’ll get to it, don’t worry! next up: code blocks (~2-4 hours) fixes to table rendering (<30 mins) fix image handling (it doesn’t handle relative paths correctly) (<1hr?) Changelog ( 8b44667 ) Add blockquotes and 1 row bottom margin to second-level renderables ( 3e5182f ) Add oredered list handling ( d997aff ) Switch back to OpenTUI, get things working"}, {"post_id": 49847, "ts": "2026-08-18T19:57:55Z", "hours": 8.505, "text": "generational fuck up well i’ve messed up big time, sunken cost fallacy is real and it got me you see, i was using opentui earlier, but i decided to change because i realized that it doesn’t support ansi escape sequences. i landed on neo-neo-blessed , and it seemed cool, until i realized the list selection thing got fucked up because it didn’t handle scrolling list options with heights greater than 1 row properly which is a deal breaker. i also spent a lot of time patching its types, in fact that’s what most of this time went to i think i’ll use jsvision. it seems interesting and i’ve got nothing to lose. the only issue is it has one maintainer and 9 stars, but gpt found it, and it seems cool. also they have demos of the unmodified lib running in the browser which i wanted to do, so this will be fun Changelog ( 33e1c91 ) Start using neo-neo-blessed and do a generational fuck up"}, {"post_id": 47449, "ts": "2026-08-15T11:47:19Z", "hours": 9.8211, "text": "TUI! i’ve got news: the TUI renders! for this tui, im using opentui! right now, the tui only shows an interactive list of files, and its supposed to render the file content if you select one, but that’s not happening right now. i’ve been working on the function to make opentui render the markdown. while opentui does have its own thing for markdown rendering ( ), i’m gonna render my own markdown. im currently trying to get tables working! Changelog ( c8ab716 ) Work further on rendering, start with rendering tables ( dc8b0be ) Start using OpenTUI for rendering TUI ( 86347cf ) Render unknown HTML correctly (without showing tags)"}, {"post_id": 44744, "ts": "2026-08-10T18:22:19Z", "hours": 2.7394, "text": "it works holy shit it works, the problem was that i was running a function but i wasn’t putting it in a console.log . the test function for reference returned a string. also, unknown tags are handled somewhat properly. i need to actually fix that, but once i do, im gonna start on the tui!! its been 96+ hours now what a crazy thing, i expected this to take 10-20 hours and now look at this… anyways, i’ll go fix the unknown tag thing! after that i’ll start working on the tui Changelog ( c1461c3 ) Get unknown HTML tags rendering"}, {"post_id": 43978, "ts": "2026-08-09T13:44:03Z", "hours": 10.3797, "text": "headings! unknown tag handling (that doesn’t work)! well we’ve got some nice stuff now! here’s a list of everything, including problems!: just whitespace? no more! : tokens that are just whitespace get omitted typescript lsp doesn’t complain : oh my god finally that was so annoying what’s this tag? : if it doesn’t have a handler, it falls back to the default, that is, it turns into a string! this doesn’t work properly though, i have to fix this ching chong ruby tags : now ruby tags are supported! is that a highlighter? : mark elements are now supported, which just put a yellow bg on some text is this a block element or not? : now the renderer can tell by looking at a token’s block property proper heading rendering?!?!? : chatgpt wrote the entirety of this part because you cannot bother me to make an efficient function that wraps giant text art letters based on width where’s the inline code? : that’s right, it doesn’t work and gets completely omitted! Changelog ( 456161f ) Trim content, add boolean property ( 07da8a6 ) Add handlers type to make the LSP shut up, trim strings in test file ( b4d251c ) Add handling for unknown tags ( d903b48 ) Add support for dfn , samp , ruby tags ( 813d934 ) Fix code to stop TypeScript ( vtsls lsp) warnings"}, {"post_id": 40582, "ts": "2026-08-04T07:04:35Z", "hours": 9.9967, "text": "typescript! i’ve moved to typescript, cleaned up some code, finished that image function from last devlog, and upgraded packages! finished the image function : now it works perfectly! upgraded packages : shiki was upgraded! its the code coloring package btw added a test : i can’t keep pressing the arrow keys in bun repl i have to do this moved to typescript : this is the main thing. devs on discord kept telling me to use and i said i’d do it soon. i wasn’t planning on it at this time, but i did because i got fed up with a stupid bug where i was accidentally setting token types to a boolean instead of a string. that prompted me to just do it™ and now i’m fixing a bunch of bugs! still not sure why the language server is just complaining about cases that can’t happen, but that’s what typescript is for i guess Changelog ( 688afd8 ) Start moving to TypeScript ( ac99373 ) Switch to map for aliases, add test, clean up code ( c62c57b ) Upgrade packages, clean up code ( f98e65c ) Finish revamping image function"}, {"post_id": 38811, "ts": "2026-08-01T11:37:47Z", "hours": 10.2436, "text": "WIP WORK // INCOMPLETE // this was a lot of work, and i’m still not done with html in the stylizer! here’s a list of changes with explanations: add more aliases to the aliases array in the html parsing section: this makes it so that html tokens and markdown tokens have the same types convert the array of allowed html tags into a set : sets have a .has() function that lets us find an element in O(1) time complexity which is much faster compared to Array.prototype.includes() which has an O(n) time complexity properly implement disallowed tags: these tags show as plain text because they are disallowed and shouldn’t be processed in markdown put non-block tokens as children of an inline token: non-block tokens only got parsed in the part where inline tokens were processed set attributes: the objects returned by the stylize function now have a properties key better error handling: now, where it used to just throw an error about being undefined or whatever, it will catch it, and throw a more useful error with better debug info [BUGFIX] make sure that arrays don’t get nested: this was a bug where arrays would get nested for some reason [BUGFIX] set token.level and token.nesting properly when processing html: this is necessary because the while loop depends on the nesting to know when to stop accumulating tokens and process them [WIP] html handling: any tokens having the substring _open in their .type property are handled all together, with a handlers object made up of functions. this handling is recursive token with types that don’t match the substring _open get handled through other branches of the if statement ( else if(...) {..} ) [WIP] bullet list handling: i did not realize that there were more markdown-it tokens that i had not added handling for in the stylize function. i also need to do this for some more token types too [WIP] revamp image handling: instead of just a complicated function, i added a class called Image that has a function to render the image. its nearly complete but it has some errors that i committed because i need to commit often lmao chatpgt usage now here i used chatgpt a lot for debugging. here’s exactly what i used it for: why tokens weren’t being processed: this is the problem the array nesting bugfix fixed fixing infinite recursion: i accidentally did that lmfao replacing top-level non-block tokens with an inline token that contains those top-level non-block tokens as children figuring how to set the level property of the tokens questions about syntax and mutation of global vars Changelog ( 5e931f7 ) Revamp image function (WIP) ( 0ce066f ) Improve error handling and fix token.level assignment ( 0f28b75 ) Process details element in stylizer ( 0e154f3 ) Start improving stylizer (WIP) why such long devlogs? you may have noticed i’ve been going more and more time without devlogging. that’s because i like devlogging when there’s a big new thing, not for every small little thing. my plan for this devlog was to announce that i was done with processing html in the stylize function, but that hasn’t happened yet because well, there were a latta bugs here and there, and i had to fix those too. as for the length of the devlog text, i like writing about my progress here because its the only place where it makes sense to talk about it in-depth"}, {"post_id": 35679, "ts": "2026-07-27T08:45:19Z", "hours": 7.8072, "text": "HTML parsing is now complete its been nearly 2 weeks and i have great news: html parsing is complete what this means is that html blocks get processed into token streams like the one’s markdown-it makes. now, i must clarify that these html blocks were already in a token stream but they were distinctly html, having the type html_block , and if i didn’t convert those html blocks into markdown-it’s _open / _close tokens, i’d have to parse it in the file that styles the tokens, and many html tags do the exact same thing as their markdown counterparts so i could reuse some functions. i must also clarify that i have NOT done anything for stylizing html in the stylize.js file, which deals with processing text formatting and image processing next up: stylizing html! Changelog ( c5a5ce0 ) Finish HTML parsing ( 841ba42 ) Start work on HTML parsing"}, {"post_id": 29515, "ts": "2026-07-16T14:30:25Z", "hours": 1.24, "text": "improvements and fixes to inline rendering this is way earlier than my normal schedule, but that’s because i’ve got something to show . basically, inline rendering was bugged , and not only did i fix it , i also made it so that it works better ! that’s all you need to know, do NOT read the rest of this if you don’t want to be bored to death, its a really lengthy explanation of this the initial bug was that inline rendering wouldn’t work at all. i figured out the problem was that i wasn’t pushing \"inline\" to the state array somewhere. i realized that it wasn’t working when called in the table rendering function, and that was because i wasn’t pushing \"inline\" to the state array. the reason for this is because the renderInline function slices the state array at the index after the \"inline\" string, so if its something like [\"paragraph\", \"inline\", \"bold\", \"italic\"] , the function slices at index 2 because \"inline\" is at index 1, and we get [\"bold\", \"italic\"] . the problem is, if \"inline\" doesn’t exist, running indexOf(\"inline\") returns -1, so it slices at -1 + 1 , which is 0, so its just the whole array. but anything before “inline” isn’t a valid style, and since the function for that is undefined, it goes kaboom and throws an error saying that it’s not a function. also gpt found 5 other bugs but they’re kinda irrelevant the fix was making it so that the renderInline function itself pushed \"inline' to the state array instead of depending on it being already there. this also removed the need for making sure that the inline string was already there. i might do this with the rest of the functions too actually :goonology: also removed unnecessary state.pop() occurrences since the pop method is destructive and can mess up everything as for the improvement, you might see in the first screenshot that there’s a bunch of text tokens together. yk, they could be squished together into one token… oh right, that’s what i did! i changed the renderInline function to make a variable where the text accumulates until there’s no more text or if there’s an image, on which it gets pushed to the contents array now the most important thing is that there’s only one more thing left to do: html rendering . this is the last thing before i get to actually rendering stuff on the screen! this is exciting! Changelog ( 9de477d ) Fix, improve inline rendering please like this took more than an hour to write"}, {"post_id": 29168, "ts": "2026-07-15T21:42:41Z", "hours": 4.2522, "text": "THAT WAS SO LONG WHAT ON EARTH in short, tables now work and the inline rendering function is fixed! this took a while because i genuinely had no idea what i was doing. now the long stuff: tables go brr i got distracted while writing this and realized everything’s actually borked, but tables do somewhat work! its still borked tho– also i realized that my whole code is borked, but… inline rendering includes links now! still have no idea how i missed that other i just changed image function so that it returns an object with a prototype function instead of unnecessarily repeating the function as a property of all the image objects, so if there’s 10 pictures in a file, there will only be one function to render each as opposed to 10 instances of that function Changelog ( d8feb46 ) Add table support, fix inline rendering oh fuck, my code is COMPLETELY borked"}, {"post_id": 27805, "ts": "2026-07-13T17:59:20Z", "hours": 2.5478, "text": "PEAK CODE gng TS IS PEAK!!!! i added a function that renders code AND ITS PEAK JUST SEE THE SS now some of this time came from trying to figure out why my code was joining the contents of a function, and it was because i forgot to add the argument that gave the coloring function (chalk library) the text to color. hey, at least i found a way to read the contents of functions time to go steal code from closed-source packages leaving that aside, my next step is thematic breaks. this shouldn’t be too hard, in fact, i’ll do it rn since it’s that easy. rn its 8:49 PM GMT+0300, i’ll tell in the next paragraph when i finish it. [8:54 PM] just did it, it only took like 2 mins, the other 3 were because i found a bug that never removed codeBlock from the stack after it was added. that’s about it, and this devlog was quite short. well, comparatively, to my other devlogs, after all there’s people posting 4 word devlogs. you should follow this project tho Changelog ( a17bd2b ) Add thematic break support ( e28f1b1 ) Add code block styling"}, {"post_id": 26701, "ts": "2026-07-11T17:20:33Z", "hours": 4.4769, "text": "when the FUCK did this become 4 hours so uhh i spent like all of this time debugging and improving my code. first thing is, i replaced these “microfunctions”, as i call them, with an object that had keys whose values were arrow functions. these arrow functions did the exact same thing and took up less space and was even more readable! second, i spent some time on a stupid bug where the main function in stylize.js would hang. i thought it was an issue with the image function, but after half an hour or so, when i added console.log(done) right before the return, i realized it had to do with the main function that was calling the image function, and sure enough, the second i looked at it, i realized the problem: it was a while loop and i forgot to add a line that incremented the index, so it just kept doing the same thing forever until i killed the process oh well, more hours for me third, i improved (or rather cleaned) my image function. it returns promises and doesn’t use terminal-image directly. instead, i made it so that it would return an object with a bunch of keys, one of which is a function that takes the whole object as an input. this function actually renders the image, since i plan to write the function to display it in a way that deals with image rendering after rendering text, and while the images get rendered, a spinner takes their place temporarily, but the images replace those spinners once they are processed fourth thing is, i made it so that the main function calls the renderInline function instead of the paragraph function. in fact, this paragraph function is completely useless, so i went ahead and removed it too. lastly, i upgraded a bunch of packages: upgraded typescript from version 5 to 5.9.3 upgraded got from version 15.0.7 to 15.1.0 upgraded markdown-it from version 14.2.0 to 14.3.0 upgraded shiki from version 4.3.0 to 4.3.1 if you wonder what these packages are typescript is, well, the typescript language, not sure why i have it, might be a dependency for another package. got is some package that does pretty much the same thing as the default fetch() but it can give me a buffer, which i need for images markdown-it is the markdown parser shiki is for coloring code. fancy, right? Changelog ( 9118913 ) Improve code ( 5b9c953 ) Remove test file ( ab3af08 ) Test image URL parsing on GitHub aight this took me 2 hours to write and i started coding again in the middle of writing this"}, {"post_id": 21475, "ts": "2026-07-03T13:24:58Z", "hours": 5.595, "text": "oof! that was a lot of work, but now we’re REALLY getting somewhere!!! first thing, headings actually work now, and if there’s a link in the heading, it gets displayed right below the heading! tbf i did rip the heading thing straight out of the original index.js file when i was trying to make a markdown parser using regex secondly, and the more important thing, image rendering now works . pretty big milestone. i achieved this through the terminal-image npm package. however, this took a while because i couldn’t figure out why it wouldn’t render. the problem was tmux–it was stripping the codes it didn’t recognise so i implemented another system to detect if the terminal had color and/or image support to decide whether to use ansi blocks or actual images. now, it works! ts so peak fr tl;dr headings work (i ripped them out of my original implementation in index.js ) images work (took me a while because it didn’t work properly in tmux we getting somewhere with this one 🔥 Changelog ( 9941b1b ) Finish image rendering ( 007b3f4 ) Work on image rendering ( 609be18 ) Make heading work"}, {"post_id": 18690, "ts": "2026-06-29T21:31:37Z", "hours": 6.2242, "text": "holy this shit is so long heyo! this is a long one, so i’ll go over this commit by commit ( 0ad2cb2 ) Start paragraph parsing here, i did these: i made a global string state to maintain the nesting while styling. managing this was quite tedious and useless i added a helper function to get the style of a token called getStyle() . i’ll explain the use for it below. i continued working on the heading() and paragraph() functions as well as the stylize() function ( eb218d2 ) Add markdown extensions as for this one, i added a bunch of packages, mostly extensions for markdown-it . these are: markdown-it-footnote markdown-it-github-alerts markdown-it-sanitizer markdown-it-table markdown-it-task-lists shiki (for code highlighting) terminal-image i removed a few of these later because they were either not really working properly or just weren’t necessary. besides these, i also configured the plugin to use the plugins, enable the autolink extension and also replace all HTML line breaks ( <br> ) with double newlines ( \\n\\n ) ( 5ecef2c ) Start working on image rendering and colors/styles now here is where i found a gem in my dependency tree. you see, i was searching for a package to handle color rendering since i sure as hell wasn’t gonna deal with the hex codes shiki , the code-highlighting plugin, was giving me for the colors of the tokens. so i saw a package called chalk and it sounded familiar. turns out, shiki had chalk as a dependency, so it was already installed! for that reason, i added a chalk import in this commit. i also started working on an image function to render images, and named it renderImage() . also added a great error message if two requirements weren’t met: throw new Error ( \" WRONG TOKEN IDIOT DEV \" ); but that was all i really did in that function ( 0dc393d ) Remove unnecessary object processing and dependencies this is where i removed markdown-it-footnote and markdown-it-table because i realized there just wasn’t a point in those since they weren’t letting me test my function, they were erroring out for some reason and i found out markdown-it-table already had support for markdown tables. i also removed the mapping function in the parser stage that i made to give myself only a few fields. it was pretty useless since i kept randomly finding that i’d need some new property. ( 8a5200c ) Continue work on inline parsing, add terminal-link latest commit, this is where i did a lot of work: i removed terminal-image as a dependency since i found that bun already provided a class for it ( Bun.Image ) and it also had webp support unlike terminal-image , so no point in another package when a built-in one works better i made the getStyles() function better i added a bunch of micro-functions like bold() , italic() , etc. i also renamed renderImage() to image() i combined two if statements into one in this image() function because why 2 if statements when 1 i did a lot of work in the renderInline() function. now it uses computed function names that call those micro-functions. i also changed that global string state to a global array, made things much easier. i worked on the heading() and paragraph() functions further that’s about it gng, also its 12:28 am for me rn this is why we devlog more often gng ✌️"}, {"post_id": 17162, "ts": "2026-06-27T21:04:18Z", "hours": 2.7842, "text": "toiling away… toiling away at this code… today was a bunch of stuff i added a renderInline() function to render stuff inline. i still need to add images and links, but i’d need a lib for links, and maybe for the images too i worked more on the main function. right now, im trying to get paragraphs actually rendered, which will take a while. i also added a heading() function that will render headings, emphasis on will because its not being called yet it took me a lot of thinking to get here so that part wasn’t too fun (a person who thinks all the time, has nothing to think about 🔥) changelog ( e24a192 ) Work more on the stylizer ( 1a02163 ) Start actual work on stylizer"}, {"post_id": 16483, "ts": "2026-06-26T20:35:10Z", "hours": 1.5342, "text": "revamp! i revamped the parse-input.js file! now, it has two functions: giveFields(obj) this is a function called by the second function. since markdown-it (the parser im using now!) has a lot of fields that i don’t need. so this function returns a mapped array with the fields type , tag , nesting , content , and children . as for this children field, the children field is an array of objects, where the objects are just like the parent object, with lots of unnecessary fields. for those, i used recursion! (it’s my first time using recursion ) parse(input) : this is the function that i’ll be using to get the tokens i need to style! what it does is pretty simple: initialize a new instance of the MarkdownIt constructor (? i’m not too sure if it’s a constructor) get markdown-it ’s tokens using their parsing function make a constant whose content is an array of objects returned by the first function ( giveFields() if your memory is that terrible). again its a mapped array that gives only select fields from the markdown-it tokens return that constant in other news, i wrote 2 more test markdown files. one tests the behaviour of headings and the other tests the behaviour of inline stuff like bold and italic text! Changelog ( 88bad121 ) Revamp parse-input.js ( 3eda61e5 ) Add more stuff to inlines.md"}, {"post_id": 15772, "ts": "2026-06-25T17:18:25Z", "hours": 2.5692, "text": "FUCK fuck this rewrite, i’m abandoning this shithole of a parser i’m trying to make, i’ll just go use an already existing parser, its just not worth it it’s too much hassle to make an in-house parser, so here’s my plan: i install a markdown parser that returns a tree of text, not html, and as a dependency in the styling part, i’ll go ahead and read the tree of text that the parser returns it gets passed to the renderer hopefully this will move much faster now!"}, {"post_id": 11542, "ts": "2026-06-18T20:48:29Z", "hours": 2.0211, "text": "rewrite i started a rewrite! what i was doing earlier was honestly too messy to actually use. my earlier way was making a bunch of regexes and using those to match the remaining text. my new method is still using regexes, but i split the whole thing into two parts: block parser and inline parser. block parser the block parser splits the markdown doc on newlines and checks what it starts with or ends with. when it finds that some line is not a paragraph, it pushes a token to the tokens array indicating that it is the start of a block. when it detects that the block has ended, it pushes a token to the tokens array indicating the end of the block. this is currently only implemented for headings, more are coming. it took this long because me dumb inline parser the inline parser loops through the existing tokens array made by the block parser and looks for characters that indicate the start of an inline token like bold, italic and so on. like the block parser, it will push start and end tokens to the tokens array the implementation of the inline parser has not started yet new character i added a backslash to the giant block letters i made for headings! Changelog (bac8c5a) Start parser rewrite (664713e) Add backslash in heading"}, {"post_id": 10859, "ts": "2026-06-17T20:14:25Z", "hours": 7.0403, "text": "help me what on god’s green earth is this so after dealing with a shit ton of regex and doing pretty much nothing with it besides some stuff that would improve performance, i have decided that regex is not the way. instead, i’ll just set a bunch of flags with empty content and make a separate function that processes everything. i think the styling function will handle tokens because that’s its job, to style the tokens. at least i have something to follow now. (i did not implement any of this yet) Changelog fc8de72 : Fix some regexes fe6eeef : Change some regexes f67c3b5 : Change matching system in parser 8a80409 : Add some HTML support in lexical parser 0727d82 : Finish lexical parser (almost) b7bc45b : Make lexical parser work"}, {"post_id": 7594, "ts": "2026-06-12T18:16:30Z", "hours": 6.0661, "text": "i got bombed by my own regex anyways, so i started making a lexical parser and uhh its not going all sunshine and rainbows. the blockquote regex doesn’t really work right and also i checked the gfm spec since i want to adhere to it and uhh fuck i might be cooked. i thought ts was going to be a 20h project help meeeeeee also yes it took me 6 hours for 74 lines of code sob this is just great"}, {"post_id": 6452, "ts": "2026-06-10T21:06:48Z", "hours": 1.475, "text": "HEADINGS NOW RENDER! headings now render! as you can see in the screenshot, it now renders the headings as big boys also, me very happy. this took a while because i lowk didn’t know what to really do. i didn’t think about how i would do it, i was only thinking about doing it anyways gn gng"}, {"post_id": 5881, "ts": "2026-06-09T20:48:17Z", "hours": 6.8622, "text": "took only this long to make a bunch of letters you see, i had to make a bunch of custom glyphs to render headings in the terminal. making that for pretty much all the characters on your keyboard isn’t quite easy but hey its done now. the thing is, this is only for level one headings. once i finish the actual parser, i’ll add glyphs for the rest of the headings. in the meantime, i’ll have to do the rest. i did not expect to have spent this long on the project already yk"}, {"post_id": 4481, "ts": "2026-06-07T20:14:04Z", "hours": 0.4414, "text": "a terminal markdown reader that has actual headings? never could have thought of it huh well this is what i’m doing. literally a markdown reader that prints text the way you might have written it. anyways so this is gonna use bun since bun is ultra fast. also this might be a 10-20h proj, shouldn’t be too hard. well i like more hours, so i might also add stuff like: browsing all the markdown files in a directory (and subdirectories) editing (very unlikely!) well i don’t really know what else to put so ig that’s it? anyways i have actually done some work, that is, my file currently ouputs some text. literally the raw original text. what’d you expect from 24m of coding"}]...
|
Title: reMDer by @Keyboard1000n17 | Stardance
Dev Title: reMDer by @Keyboard1000n17 | Stardance
Devlogs:
a terminal markdown reader that has actual headings? never could have thought of it huh well this is what i’m doing. literally a markdown reader that prints text the way you might have written it. anyways so this is gonna use bun since bun is ultra fast. also this might be a 10-20h proj, shouldn’t be too hard. well i like more hours, so i might also add stuff like: browsing all the markdown files in a directory (and subdirectories) editing (very unlikely!) well i don’t really know what else to put so ig that’s it? anyways i have actually done some work, that is, my file currently ouputs some text. literally the raw original text. what’d you expect from 24m of coding
took only this long to make a bunch of letters you see, i had to make a bunch of custom glyphs to render headings in the terminal. making that for pretty much all the characters on your keyboard isn’t quite easy but hey its done now. the thing is, this is only for level one headings. once i finish the actual parser, i’ll add glyphs for the rest of the headings. in the meantime, i’ll have to do the rest. i did not expect to have spent this long on the project already yk
HEADINGS NOW RENDER! headings now render! as you can see in the screenshot, it now renders the headings as big boys also, me very happy. this took a while because i lowk didn’t know what to really do. i didn’t think about how i would do it, i was only thinking about doing it anyways gn gng
i got bombed by my own regex anyways, so i started making a lexical parser and uhh its not going all sunshine and rainbows. the blockquote regex doesn’t really work right and also i checked the gfm spec since i want to adhere to it and uhh fuck i might be cooked. i thought ts was going to be a 20h project help meeeeeee also yes it took me 6 hours for 74 lines of code sob this is just great
help me what on god’s green earth is this so after dealing with a shit ton of regex and doing pretty much nothing with it besides some stuff that would improve performance, i have decided that regex is not the way. instead, i’ll just set a bunch of flags with empty content and make a separate function that processes everything. i think the styling function will handle tokens because that’s its job, to style the tokens. at least i have something to follow now. (i did not implement any of this yet) Changelog fc8de72 : Fix some regexes fe6eeef : Change some regexes f67c3b5 : Change matching system in parser 8a80409 : Add some HTML support in lexical parser 0727d82 : Finish lexical parser (almost) b7bc45b : Make lexical parser work
rewrite i started a rewrite! what i was doing earlier was honestly too messy to actually use. my earlier way was making a bunch of regexes and using those to match the remaining text. my new method is still using regexes, but i split the whole thing into two parts: block parser and inline parser. block parser the block parser splits the markdown doc on newlines and checks what it starts with or ends with. when it finds that some line is not a paragraph, it pushes a token to the tokens array indicating that it is the start of a block. when it detects that the block has ended, it pushes a token to the tokens array indicating the end of the block. this is currently only implemented for headings, more are coming. it took this long because me dumb inline parser the inline parser loops through the existing tokens array made by the block parser and looks for characters that indicate the start of an inline token like bold, italic and so on. like the block parser, it will push start and end tokens to the tokens array the implementation of the inline parser has not started yet new character i added a backslash to the giant block letters i made for headings! Changelog (bac8c5a) Start parser rewrite (664713e) Add backslash in heading
FUCK fuck this rewrite, i’m abandoning this shithole of a parser i’m trying to make, i’ll just go use an already existing parser, its just not worth it it’s too much hassle to make an in-house parser, so here’s my plan: i install a markdown parser that returns a tree of text, not html, and as a dependency in the styling part, i’ll go ahead and read the tree of text that the parser returns it gets passed to the renderer hopefully this will move much faster now!
revamp! i revamped the parse-input.js file! now, it has two functions: giveFields(obj) this is a function called by the second function. since markdown-it (the parser im using now!) has a lot of fields that i don’t need. so this function returns a mapped array with the fields type , tag , nesting , content , and children . as for this children field, the children field is an array of objects, where the objects are just like the parent object, with lots of unnecessary fields. for those, i used recursion! (it’s my first time using recursion ) parse(input) : this is the function that i’ll be using to get the tokens i need to style! what it does is pretty simple: initialize a new instance of the MarkdownIt constructor (? i’m not too sure if it’s a constructor) get markdown-it ’s tokens using their parsing function make a constant whose content is an array of objects returned by the first function ( giveFields() if your memory is that terrible). again its a mapped array that gives only select fields from the markdown-it tokens return that constant in other news, i wrote 2 more test markdown files. one tests the behaviour of headings and the other tests the behaviour of inline stuff like bold and italic text! Changelog ( 88bad121 ) Revamp parse-input.js ( 3eda61e5 ) Add more stuff to inlines.md
toiling away… toiling away at this code… today was a bunch of stuff i added a renderInline() function to render stuff inline. i still need to add images and links, but i’d need a lib for links, and maybe for the images too i worked more on the main function. right now, im trying to get paragraphs actually rendered, which will take a while. i also added a heading() function that will render headings, emphasis on will because its not being called yet it took me a lot of thinking to get here so that part wasn’t too fun (a person who thinks all the time, has nothing to think about 🔥) changelog ( e24a192 ) Work more on the stylizer ( 1a02163 ) Start actual work on stylizer
holy this shit is so long heyo! this is a long one, so i’ll go over this commit by commit ( 0ad2cb2 ) Start paragraph parsing here, i did these: i made a global string state to maintain the nesting while styling. managing this was quite tedious and useless i added a helper function to get the style of a token called getStyle() . i’ll explain the use for it below. i continued working on the heading() and paragraph() functions as well as the stylize() function ( eb218d2 ) Add markdown extensions as for this one, i added a bunch of packages, mostly extensions for markdown-it . these are: markdown-it-footnote markdown-it-github-alerts markdown-it-sanitizer markdown-it-table markdown-it-task-lists shiki (for code highlighting) terminal-image i removed a few of these later because they were either not really working properly or just weren’t necessary. besides these, i also configured the plugin to use the plugins, enable the autolink extension and also replace all HTML line breaks ( <br> ) with double newlines ( \n\n ) ( 5ecef2c ) Start working on image rendering and colors/styles now here is where i found a gem in my dependency tree. you see, i was searching for a package to handle color rendering since i sure as hell wasn’t gonna deal with the hex codes shiki , the code-highlighting plugin, was giving me for the colors of the tokens. so i saw a package called chalk and it sounded familiar. turns out, shiki had chalk as a dependency, so it was already installed! for that reason, i added a chalk import in this commit. i also started working on an image function to render images, and named it renderImage() . also added a great error message if two requirements weren’t met: throw new Error ( " WRONG TOKEN IDIOT DEV " ); but that was all i really did in that function ( 0dc393d ) Remove unnecessary object processing and dependencies this is where i removed markdown-it-footnote and markdown-it-table because i realized there just wasn’t a point in those since they weren’t letting me test my function, they were erroring out for some reason and i found out markdown-it-table already had support for markdown tables. i also removed the mapping function in the parser stage that i made to give myself only a few fields. it was pretty useless since i kept randomly finding that i’d need some new property. ( 8a5200c ) Continue work on inline parsing, add terminal-link latest commit, this is where i did a lot of work: i removed terminal-image as a dependency since i found that bun already provided a class for it ( Bun.Image ) and it also had webp support unlike terminal-image , so no point in another package when a built-in one works better i made the getStyles() function better i added a bunch of micro-functions like bold() , italic() , etc. i also renamed renderImage() to image() i combined two if statements into one in this image() function because why 2 if statements when 1 i did a lot of work in the renderInline() function. now it uses computed function names that call those micro-functions. i also changed that global string state to a global array, made things much easier. i worked on the heading() and paragraph() functions further that’s about it gng, also its 12:28 am for me rn this is why we devlog more often gng ✌️
oof! that was a lot of work, but now we’re REALLY getting somewhere!!! first thing, headings actually work now, and if there’s a link in the heading, it gets displayed right below the heading! tbf i did rip the heading thing straight out of the original index.js file when i was trying to make a markdown parser using regex secondly, and the more important thing, image rendering now works . pretty big milestone. i achieved this through the terminal-image npm package. however, this took a while because i couldn’t figure out why it wouldn’t render. the problem was tmux–it was stripping the codes it didn’t recognise so i implemented another system to detect if the terminal had color and/or image support to decide whether to use ansi blocks or actual images. now, it works! ts so peak fr tl;dr headings work (i ripped them out of my original implementation in index.js ) images work (took me a while because it didn’t work properly in tmux we getting somewhere with this one 🔥 Changelog ( 9941b1b ) Finish image rendering ( 007b3f4 ) Work on image rendering ( 609be18 ) Make heading work
when the FUCK did this become 4 hours so uhh i spent like all of this time debugging and improving my code. first thing is, i replaced these “microfunctions”, as i call them, with an object that had keys whose values were arrow functions. these arrow functions did the exact same thing and took up less space and was even more readable! second, i spent some time on a stupid bug where the main function in stylize.js would hang. i thought it was an issue with the image function, but after half an hour or so, when i added console.log(done) right before the return, i realized it had to do with the main function that was calling the image function, and sure enough, the second i looked at it, i realized the problem: it was a while loop and i forgot to add a line that incremented the index, so it just kept doing the same thing forever until i killed the process oh well, more hours for me third, i improved (or rather cleaned) my image function. it returns promises and doesn’t use terminal-image directly. instead, i made it so that it would return an object with a bunch of keys, one of which is a function that takes the whole object as an input. this function actually renders the image, since i plan to write the function to display it in a way that deals with image rendering after rendering text, and while the images get rendered, a spinner takes their place temporarily, but the images replace those spinners once they are processed fourth thing is, i made it so that the main function calls the renderInline function instead of the paragraph function. in fact, this paragraph function is completely useless, so i went ahead and removed it too. lastly, i upgraded a bunch of packages: upgraded typescript from version 5 to 5.9.3 upgraded got from version 15.0.7 to 15.1.0 upgraded markdown-it from version 14.2.0 to 14.3.0 upgraded shiki from version 4.3.0 to 4.3.1 if you wonder what these packages are typescript is, well, the typescript language, not sure why i have it, might be a dependency for another package. got is some package that does pretty much the same thing as the default fetch() but it can give me a buffer, which i need for images markdown-it is the markdown parser shiki is for coloring code. fancy, right? Changelog ( 9118913 ) Improve code ( 5b9c953 ) Remove test file ( ab3af08 ) Test image URL parsing on GitHub aight this took me 2 hours to write and i started coding again in the middle of writing this
PEAK CODE gng TS IS PEAK!!!! i added a function that renders code AND ITS PEAK JUST SEE THE SS now some of this time came from trying to figure out why my code was joining the contents of a function, and it was because i forgot to add the argument that gave the coloring function (chalk library) the text to color. hey, at least i found a way to read the contents of functions time to go steal code from closed-source packages leaving that aside, my next step is thematic breaks. this shouldn’t be too hard, in fact, i’ll do it rn since it’s that easy. rn its 8:49 PM GMT+0300, i’ll tell in the next paragraph when i finish it. [8:54 PM] just did it, it only took like 2 mins, the other 3 were because i found a bug that never removed codeBlock from the stack after it was added. that’s about it, and this devlog was quite short. well, comparatively, to my other devlogs, after all there’s people posting 4 word devlogs. you should follow this project tho Changelog ( a17bd2b ) Add thematic break support ( e28f1b1 ) Add code block styling
THAT WAS SO LONG WHAT ON EARTH in short, tables now work and the inline rendering function is fixed! this took a while because i genuinely had no idea what i was doing. now the long stuff: tables go brr i got distracted while writing this and realized everything’s actually borked, but tables do somewhat work! its still borked tho– also i realized that my whole code is borked, but… inline rendering includes links now! still have no idea how i missed that other i just changed image function so that it returns an object with a prototype function instead of unnecessarily repeating the function as a property of all the image objects, so if there’s 10 pictures in a file, there will only be one function to render each as opposed to 10 instances of that function Changelog ( d8feb46 ) Add table support, fix inline rendering oh fuck, my code is COMPLETELY borked
improvements and fixes to inline rendering this is way earlier than my normal schedule, but that’s because i’ve got something to show . basically, inline rendering was bugged , and not only did i fix it , i also made it so that it works better ! that’s all you need to know, do NOT read the rest of this if you don’t want to be bored to death, its a really lengthy explanation of this the initial bug was that inline rendering wouldn’t work at all. i figured out the problem was that i wasn’t pushing "inline" to the state array somewhere. i realized that it wasn’t working when called in the table rendering function, and that was because i wasn’t pushing "inline" to the state array. the reason for this is because the renderInline function slices the state array at the index after the "inline" string, so if its something like ["paragraph", "inline", "bold", "italic"] , the function slices at index 2 because "inline" is at index 1, and we get ["bold", "italic"] . the problem is, if "inline" doesn’t exist, running indexOf("inline") returns -1, so it slices at -1 + 1 , which is 0, so its just the whole array. but anything before “inline” isn’t a valid style, and since the function for that is undefined, it goes kaboom and throws an error saying that it’s not a function. also gpt found 5 other bugs but they’re kinda irrelevant the fix was making it so that the renderInline function itself pushed "inline' to the state array instead of depending on it being already there. this also removed the need for making sure that the inline string was already there. i might do this with the rest of the functions too actually :goonology: also removed unnecessary state.pop() occurrences since the pop method is destructive and can mess up everything as for the improvement, you might see in the first screenshot that there’s a bunch of text tokens together. yk, they could be squished together into one token… oh right, that’s what i did! i changed the renderInline function to make a variable where the text accumulates until there’s no more text or if there’s an image, on which it gets pushed to the contents array now the most important thing is that there’s only one more thing left to do: html rendering . this is the last thing before i get to actually rendering stuff on the screen! this is exciting! Changelog ( 9de477d ) Fix, improve inline rendering please like this took more than an hour to write
HTML parsing is now complete its been nearly 2 weeks and i have great news: html parsing is complete what this means is that html blocks get processed into token streams like the one’s markdown-it makes. now, i must clarify that these html blocks were already in a token stream but they were distinctly html, having the type html_block , and if i didn’t convert those html blocks into markdown-it’s _open / _close tokens, i’d have to parse it in the file that styles the tokens, and many html tags do the exact same thing as their markdown counterparts so i could reuse some functions. i must also clarify that i have NOT done anything for stylizing html in the stylize.js file, which deals with processing text formatting and image processing next up: stylizing html! Changelog ( c5a5ce0 ) Finish HTML parsing ( 841ba42 ) Start work on HTML parsing
WIP WORK // INCOMPLETE // this was a lot of work, and i’m still not done with html in the stylizer! here’s a list of changes with explanations: add more aliases to the aliases array in the html parsing section: this makes it so that html tokens and markdown tokens have the same types convert the array of allowed html tags into a set : sets have a .has() function that lets us find an element in O(1) time complexity which is much faster compared to Array.prototype.includes() which has an O(n) time complexity properly implement disallowed tags: these tags show as plain text because they are disallowed and shouldn’t be processed in markdown put non-block tokens as children of an inline token: non-block tokens only got parsed in the part where inline tokens were processed set attributes: the objects returned by the stylize function now have a properties key better error handling: now, where it used to just throw an error about being undefined or whatever, it will catch it, and throw a more useful error with better debug info [BUGFIX] make sure that arrays don’t get nested: this was a bug where arrays would get nested for some reason [BUGFIX] set token.level and token.nesting properly when processing html: this is necessary because the while loop depends on the nesting to know when to stop accumulating tokens and process them [WIP] html handling: any tokens having the substring _open in their .type property are handled all together, with a handlers object made up of functions. this handling is recursive token with types that don’t match the substring _open get handled through other branches of the if statement ( else if(...) {..} ) [WIP] bullet list handling: i did not realize that there were more markdown-it tokens that i had not added handling for in the stylize function. i also need to do this for some more token types too [WIP] revamp image handling: instead of just a complicated function, i added a class called Image that has a function to render the image. its nearly complete but it has some errors that i committed because i need to commit often lmao chatpgt usage now here i used chatgpt a lot for debugging. here’s exactly what i used it for: why tokens weren’t being processed: this is the problem the array nesting bugfix fixed fixing infinite recursion: i accidentally did that lmfao replacing top-level non-block tokens with an inline token that contains those top-level non-block tokens as children figuring how to set the level property of the tokens questions about syntax and mutation of global vars Changelog ( 5e931f7 ) Revamp image function (WIP) ( 0ce066f ) Improve error handling and fix token.level assignment ( 0f28b75 ) Process details element in stylizer ( 0e154f3 ) Start improving stylizer (WIP) why such long devlogs? you may have noticed i’ve been going more and more time without devlogging. that’s because i like devlogging when there’s a big new thing, not for every small little thing. my plan for this devlog was to announce that i was done with processing html in the stylize function, but that hasn’t happened yet because well, there were a latta bugs here and there, and i had to fix those too. as for the length of the devlog text, i like writing about my progress here because its the only place where it makes sense to talk about it in-depth
typescript! i’ve moved to typescript, cleaned up some code, finished that image function from last devlog, and upgraded packages! finished the image function : now it works perfectly! upgraded packages : shiki was upgraded! its the code coloring package btw added a test : i can’t keep pressing the arrow keys in bun repl i have to do this moved to typescript : this is the main thing. devs on discord kept telling me to use and i said i’d do it soon. i wasn’t planning on it at this time, but i did because i got fed up with a stupid bug where i was accidentally setting token types to a boolean instead of a string. that prompted me to just do it™ and now i’m fixing a bunch of bugs! still not sure why the language server is just complaining about cases that can’t happen, but that’s what typescript is for i guess Changelog ( 688afd8 ) Start moving to TypeScript ( ac99373 ) Switch to map for aliases, add test, clean up code ( c62c57b ) Upgrade packages, clean up code ( f98e65c ) Finish revamping image function
headings! unknown tag handling (that doesn’t work)! well we’ve got some nice stuff now! here’s a list of everything, including problems!: just whitespace? no more! : tokens that are just whitespace get omitted typescript lsp doesn’t complain : oh my god finally that was so annoying what’s this tag? : if it doesn’t have a handler, it falls back to the default, that is, it turns into a string! this doesn’t work properly though, i have to fix this ching chong ruby tags : now ruby tags are supported! is that a highlighter? : mark elements are now supported, which just put a yellow bg on some text is this a block element or not? : now the renderer can tell by looking at a token’s block property proper heading rendering?!?!? : chatgpt wrote the entirety of this part because you cannot bother me to make an efficient function that wraps giant text art letters based on width where’s the inline code? : that’s right, it doesn’t work and gets completely omitted! Changelog ( 456161f ) Trim content, add boolean property ( 07da8a6 ) Add handlers type to make the LSP shut up, trim strings in test file ( b4d251c ) Add handling for unknown tags ( d903b48 ) Add support for dfn , samp , ruby tags ( 813d934 ) Fix code to stop TypeScript ( vtsls lsp) warnings
it works holy shit it works, the problem was that i was running a function but i wasn’t putting it in a console.log . the test function for reference returned a string. also, unknown tags are handled somewhat properly. i need to actually fix that, but once i do, im gonna start on the tui!! its been 96+ hours now what a crazy thing, i expected this to take 10-20 hours and now look at this… anyways, i’ll go fix the unknown tag thing! after that i’ll start working on the tui Changelog ( c1461c3 ) Get unknown HTML tags rendering
TUI! i’ve got news: the TUI renders! for this tui, im using opentui! right now, the tui only shows an interactive list of files, and its supposed to render the file content if you select one, but that’s not happening right now. i’ve been working on the function to make opentui render the markdown. while opentui does have its own thing for markdown rendering ( ), i’m gonna render my own markdown. im currently trying to get tables working! Changelog ( c8ab716 ) Work further on rendering, start with rendering tables ( dc8b0be ) Start using OpenTUI for rendering TUI ( 86347cf ) Render unknown HTML correctly (without showing tags)
generational fuck up well i’ve messed up big time, sunken cost fallacy is real and it got me you see, i was using opentui earlier, but i decided to change because i realized that it doesn’t support ansi escape sequences. i landed on neo-neo-blessed , and it seemed cool, until i realized the list selection thing got fucked up because it didn’t handle scrolling list options with heights greater than 1 row properly which is a deal breaker. i also spent a lot of time patching its types, in fact that’s what most of this time went to i think i’ll use jsvision. it seems interesting and i’ve got nothing to lose. the only issue is it has one maintainer and 9 stars, but gpt found it, and it seems cool. also they have demos of the unmodified lib running in the browser which i wanted to do, so this will be fun Changelog ( 33e1c91 ) Start using neo-neo-blessed and do a generational fuck up
(back to) opentui! if you’ve read my last devlog, you might remember that i was considering the jsvision library. however, i came back to opentui because its still much simpler. also, i found that there are libs to adapt ansi! or at least chatgpt did at first i was doing ghostty-opentui , but i realized after some time that it was literally a whole terminal. then i got chatgpt to find me this package called ansi-sequence-parser ( https://www.npmjs.com/package/ansi-sequence-parser ) and its perfect! so now im using that to render the bold and italics! tbh i could just eliminate the middle stage ( stylize.ts ), but i put a lot of work into it and i’m extremely vulnerable to the sunken cost fallacy, so i’m doing this bloat lmao. also, i got ordered lists, bullet lists, and blockquotes working! they look so cool! as for the menu, its not doing very fine, but that’s because i’ve not worked on it! i’ll get to it, don’t worry! next up: code blocks (~2-4 hours) fixes to table rendering (<30 mins) fix image handling (it doesn’t handle relative paths correctly) (<1hr?) Changelog ( 8b44667 ) Add blockquotes and 1 row bottom margin to second-level renderables ( 3e5182f ) Add oredered list handling ( d997aff ) Switch back to OpenTUI, get things working
better types. debug mode and stdout! from my last devlog: next up: code blocks (~2-4 hours) fixes to table rendering (<30 mins) fix image handling (it doesn’t handle relative paths correctly) (<1hr?) of these, i’ve done none! what i have done though is add flags and types! i spent a while dealing with type errors because i decided to specify types instead of just putting any on ProcessedToken.content . i also added a debug flag, but literally all it does is show the console i also fixed the width thing, so the content is only as wide as the space you give it so cooll!! the main part of this is that i added a --print-to-stdout flag that just prints the formatted markdown to stdout! you can just scroll in your terminal instead of having a whole ass tui its kinda borked and incomplete though, so i’ll fix it up! it does print some garbage at the beginning so that’s not great anyways, i’d better do what i said i’ll do last devlog! i went off track for this lmao Changelog ( b1c0489 ) Implement half-baked print to stdout option ( aa3c029 ) Add debug flag, fix logic errors ( aa33e84 ) Specify types for ProcessedToken.content instead of any
holy fuck, you can pipe into stdin and tables render properly! while this is quite out of schedule (i usually post every 2-3 days), today brings some peak stuff! the peakest part is at the end firstly, i have in fact fixed tables! the issue was i was pushing the accumulated cells array to the rows array in the wrong loop. i was doing this in the loop that iterates over the cells in a row, so it was causing it to repeatedly push the same strings over and over. the fix was putting it in the loop just outside, that is, the loop that iterates over the rows in the table token! i’ve also improved the image handling! now Image classes have the buffer property renamed to content , and has a new property called properties , which is always {} . with this, it has all the properties of ProcessedToken , so my lsp won’t complain that some property doesn’t exist on Image speaking of ProcessedToken , its now an interface instead of a type. there’s also a new TableToken interface that extends ProcessedToken , with an alignment property. this makes it a bit easier to handle tables since the content property is narrowed. also, it seems like opentui’s tables don’t support alignment, so i might have to make a custom table function. i also upgraded opentui from 0.5.7 to 0.5.8! i have no idea what changed, but whatever i’ve also stopped using chalk to color my errors since the opentui console doesn’t support ansi now the peakest part is you can pipe markdown into the program . this is pretty peak and you must agree since there’s a lot of stuff you can do with this. for example, you could render arbitrary markdown without having to create a file first! it has a limitation though: if you’re on windows, you can’t use the interactive mode, and the rendered content is forced to print to stdout. this is because of a bug with bun. if you’re piping into the program, it’ll get the input by calling await Bun.stdin.text() , but this stops sending keypresses to opentui because of a bug in the bun runtime, so you can’t scroll down. i solved this issue (or rather, chatgpt solved this issue) by opening a read stream on /dev/tty . the issue with this is that /dev/tty doesn’t exist on windows since its not unix-like. my idea was to just, not let you do interactive mode on windows if you’re piping content to it. again, this is a bug with bun, and i’ll remove this limitation once one of the two is merged. that’s right, there’s two! here’s one for reference: https://github.com/oven-sh/bun/pull/32153 shit that was long Changelog ( dd07e14 ) Upgrade packages ( 77e6d34 ) Add support for piping into renderer.ts from stdin ( 1995f45 ) Improve image and ANSI handling, stop using chalk in errors ( 22cfacd ) Improve table handling, switch some types to interfaces pls like
code blocks, alerts, emojis and task lists! we’ve got loads of new cool stuff that get rendered now! first, github alerts/callouts now render nicely! they look like this: > [!TAG] > content where TAG can be NOTE , IMPORTANT , TIP , WARNING or CAUTION . they also have these cool icons next to them, but the catch is you need a nerd font for it. i’ll add an option to not need it and only use ascii characters next, we have highlighted code blocks! the renderer can highlight hundreds of languages using shiki ! you might not even have heard of some of the languages that it can highlight! imo its really nice looking and i love it! the bulk of this time came from adding support for task list items because i couldn’t figure out how to do it. eventually after some tinkering i’ve got it to work! it looks kinda cool too tbh i also got emoji support using an extension. it automatically converts :emoji: to the corresponding emoji if its in the unicode specification. finally, i added a simple height option that just sets the height of the renderer. it allows you to set the height of the renderer manually and that’s about it lmao Changelog ( b4f69ad ) Add height option ( beea3a6 ) Add task list items support ( 4c42c84 ) Add emoji support ( 564a761 ) Upgrade markdown-it, fix breaking changes ( 963d910 ) Add alerts support ( 5e266e8 ) Add icons in code blocks ( 0bf0af7 ) Add code block support
figlet headings, small headings, bottom bar, help menu and keybinds we’ve got a lot of new stuff! firstly we’ve got a bottom bar! all it does for now is show reMDer with a green bg and the file name next to it, but i’ll add more later! next we’ve got figlet headings! at the start i was thinking about using figlet for headings but i gave up on that. but now, i’m back to using it! this took a good chunk of the overflowing hours here but they look really cool too! passing a --no-render-headings or -H flag will make the headings render as normal text with colors instead of figlet fonts now! there’s now a tiny help menu in the corner! it only shows two keybinds right now–oh and speaking of keybinds… keybindings are now in ! for now you can press q to quit, ? to toggle the help menu, and C (shift+c) to open the console in debug mode and that’s about it next steps? here’s what i’m gonna do next: add support for horizontal rules add a table of contents feature like that of the leaf markdown viewer add some stuff to the bottom bar add an option to put the bottom bar at the top instead add support for a config file using YAML Changelog ( 9557586 ) Add help menu ( a4149e2 ) Add keybinds: q to quit, C to toggle console ( 4b18153 ) Finish figlet fonts support ( d23466d ) Start trying figlet again for ASCII art ( 33d52ea ) Start working on ASCII art for h2 headings ( b0e1668 ) Add option to not print big headings ( c58369c ) Start with bottom bar
table of contents feature is done! took only 10 hours, but im done with the table of contents thing! you can press shift+j to go down to the next heading, and i forgot to add shift+k 😭 anyway this took a while since i couldn’t figure out how to position the box properly and how to style it. this was fucking ass icl. i usually have much more to talk about but this wasn’t the most fun so here’s the commits: Changelog ( 5ccec11 ) Remove unnecessary focusing ToC ( 927cae9 ) Add tab cycling ( ae72d3d ) Scroll ToC menu to selected index instead of blindly 1 down ( 249d61a ) Implement scrolling ToC on pressing J ( a2ae0f2 ) Get table of contents feature working ( a6c7744 ) Add scrolling to next heading on pressing J ( 49f8fec ) Add “? - Help” hint to end of bottom bar
scroll one line at a time, render div and details elements not very big news here, but now you can: scroll just one line at a time instead of a whole renderable/element at once render div and details properly! now you can click on a details element to open and close it! this didn’t even take too long more technical, but i switched to mostly using the opentui renderable api which uses classes like TextRenderable or BoxRenderable that return a Renderable instance instead of functions like Text and Box which return a ProxiedVNode<T> . this is mostly because there’s a bunch of things a Renderable has that a ProxiedVNode doesn’t anyways im currently working on adding footnotes, so see you in a few days Changelog ( 64f6ed8 ) Add footnote plugin (usage WIP) (errors on run) ( ddd5c46 ) Add indicators to details elements and opening on click/space/enter ( 344806a ) Add support for rendering div and details elements ( d3b4a1d ) Fix small layout issues ( 5eb11b9 ) Scroll only one line at a time and convert (mostly) to Renderable API
last devlog this is my last devlog the project isn’t complete and i won’t be shipping it. you see, i was banned for 2 months for misconduct on slack (i will not provide details here but i deserved it, it was corny anyway), and as part of that ban, i can’t participate in any events, including stardance. in this time however, i’ve done a lot. there’s now spinners for images, proper tables, and so many more improvements. keep your eyes peeled for a release on the github ! 👀 also it doesn’t matter that this devlog is 15 hours over the limit, its not like i can do anything about it. also if one of you regulars in #stardance see this, can you please ask amber if i can have my sticky streak rewards? i really want the stickers and plushie Changelog ( 446103b ) Render details elements properly again ( f527e5d ) Better logs, align images in row when a paragraph contains only images ( 3df2f59 ) Make task list function use TextChunk over ANSI escapes ( 2367089 ) Add proper tables ( 47c2b42 ) Add aligning components ( 00785d7 ) Move from Chalk/ANSI escapes to OpenTUI StyledText for styles ( 429e4b6 ) Load images lazily with spinner while loading ( a993197 ) Use OpenTUI ImageRenderable for images in renderer ( aa96067 ) Improve types and error handling, work on image bug ( b54ad43 ) Revert “Add footnote plugin (usage WIP) (errors on run)”...
|
1792803099.7726493
|
1793407899.7726493
|
|
31917
|
reaction time game by @alton | Stardance
|
alton
|
1
|
0.0
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-11T14:06:46Z", "hours": 0.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I made a reaction game tester, the challenging part of this project was the coding, I am new to coding so i used Ai to assist me, I am proud of this project because it works and I managed to make something fun to play around with and my friends enjoy playing with it aswell.", "repo": "https://github.com/altonguvs-arch/reaction-time-game-", "demo": ""}]...
|
[{"post_id": 26539, "ts": "202 [{"post_id": 26539, "ts": "2026-07-11T12:39:39Z", "hours": 0.3331, "text": "I just finished assembling all the hardware today, this is me testing it and it works perfectly but as you can see I’m terrible at this game ( but my high score off camera was 6 in a row so). Now I just need to make a housing for it to hide all the wires and turn it into a mini arcade game."}, {"post_id": 26257, "ts": "2026-07-10T22:54:26Z", "hours": 0.2828, "text": "I added in an active buzzer, so that when you land on the wrong led it double beeps, so that’s the new feature"}]...
|
Title: reaction time game by @alton | Stardance
D Title: reaction time game by @alton | Stardance
Devlogs:
I added in an active buzzer, so that when you land on the wrong led it double beeps, so that’s the new feature
I just finished assembling all the hardware today, this is me testing it and it works perfectly but as you can see I’m terrible at this game ( but my high score off camera was 6 in a row so). Now I just need to make a housing for it to hide all the wires and turn it into a mini arcade game.
Ships:
I made a reaction game tester, the challenging part of this project was the coding, I am new to coding so i used Ai to assist me, I am proud of this project because it works and I managed to make something fun to play around with and my friends enjoy playing with it aswell....
|
1793292473.7970874
|
1793378873.7970874
|
|
1112
|
reaction wheel by @berzs | Stardance
|
berzs
|
0
|
0.39
|
0
|
[]
|
[{"post_id": 353, "ts": "2026- [{"post_id": 353, "ts": "2026-06-01T17:43:47Z", "hours": 0.3875, "text": "created the first prototype which is a triangle and uses only one motor, later this will go up to 3 and become a cube. Put together all the components on the bredboard asqwell but dont know how should i log that. This prototype uses a brushed coreless dc motor. drv883x h-bridge. An mpu 6050 imu and an esp 8266"}]...
|
Title: reaction wheel by @berzs | Stardance
Devlo Title: reaction wheel by @berzs | Stardance
Devlogs:
created the first prototype which is a triangle and uses only one motor, later this will go up to 3 and become a cube. Put together all the components on the bredboard asqwell but dont know how should i log that. This prototype uses a brushed coreless dc motor. drv883x h-bridge. An mpu 6050 imu and an esp 8266...
|
1793231736.6911483
|
1793836536.6911483
|
|
42191
|
reader by @archa | Stardance
|
archa
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: reader by @archa | Stardance
|
1793166508.6843324
|
1793771308.6843324
|
|
18112
|
readingflow by @roy | Stardance
|
roy
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: readingflow by @roy | Stardance
|
1792947168.7182622
|
1793811168.7182622
|
|
24244
|
readthisshit.fyi by @futuraura | Stardance
|
futuraura
|
0
|
36.1
|
0
|
[]
|
[{"post_id": 33765, "ts": "202 [{"post_id": 33765, "ts": "2026-07-23T23:02:09Z", "hours": 0.4733, "text": "Why you should think twice about separating the frontend from the backend"}, {"post_id": 33718, "ts": "2026-07-23T20:56:21Z", "hours": 8.2783, "text": "Devlog 6 :^"}, {"post_id": 30743, "ts": "2026-07-18T15:58:33Z", "hours": 9.9694, "text": "Devlog number 3 or 4 :3"}, {"post_id": 25566, "ts": "2026-07-09T21:57:13Z", "hours": 4.725, "text": "So, today I’ve finally finished the language switcher and have done some refactoring on how the modals work, etc, etc. Nothing too interesting basically. I am planning on working with the backend next and also I’ll have to come up with some way of displaying search results. For now tho I’ll keep on working with the basics"}, {"post_id": 24879, "ts": "2026-07-08T18:45:19Z", "hours": 4.2442, "text": "I’ve almost completed all of the pages. I’ll have to probably rewrite the language stuff, cause I am planning on supporting wayy more than just english. Anyway, I yet have to finish the contribution page and refactor the other pages to use a separate vue modal since it’s just more efficient."}, {"post_id": 16155, "ts": "2026-06-26T08:14:20Z", "hours": 7.2911, "text": "HELL YEAH! FINALLY THE MODALS ARE DONE!!! IT TOOK ME 8 HOURS TO CENTER A DIV, Just kidding though 😂 Yet and still the pop up window when you click on a link finally works and looks somewhat fine.. I will have to rework the design later on.. (Also, here’s another screenshot of the cards on the home page xD"}, {"post_id": 13956, "ts": "2026-06-22T22:11:09Z", "hours": 1.1142, "text": "There has been so much time unlogged, but I’ve made the figma designs, homepage and currently am building a simple backend for placeholder generation and to map out the API structure. I’ve added screenshots from figma of what the website should theoretically look like… Anyway, I’ll get back to writing the placeholder backend. See you guys in 10 hours. I will also have to make a tablet and mobile design… But for now I wanna ship atleast the sh***y pc version."}]...
|
Title: readthisshit.fyi by @futuraura | Stardance
Title: readthisshit.fyi by @futuraura | Stardance
Devlogs:
There has been so much time unlogged, but I’ve made the figma designs, homepage and currently am building a simple backend for placeholder generation and to map out the API structure. I’ve added screenshots from figma of what the website should theoretically look like… Anyway, I’ll get back to writing the placeholder backend. See you guys in 10 hours. I will also have to make a tablet and mobile design… But for now I wanna ship atleast the sh***y pc version.
HELL YEAH! FINALLY THE MODALS ARE DONE!!! IT TOOK ME 8 HOURS TO CENTER A DIV, Just kidding though 😂 Yet and still the pop up window when you click on a link finally works and looks somewhat fine.. I will have to rework the design later on.. (Also, here’s another screenshot of the cards on the home page xD
I’ve almost completed all of the pages. I’ll have to probably rewrite the language stuff, cause I am planning on supporting wayy more than just english. Anyway, I yet have to finish the contribution page and refactor the other pages to use a separate vue modal since it’s just more efficient.
So, today I’ve finally finished the language switcher and have done some refactoring on how the modals work, etc, etc. Nothing too interesting basically. I am planning on working with the backend next and also I’ll have to come up with some way of displaying search results. For now tho I’ll keep on working with the basics
Devlog number 3 or 4 :3
Devlog 6 :^
Why you should think twice about separating the frontend from the backend...
|
1793224331.6366413
|
1793829131.6366413
|
|
25726
|
real life jarvis by @dummy | Stardance
|
dummy
|
1
|
12.29
|
0
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-06-29T09:48:46Z", "hours": 11.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "I built a self-hosted real-life JARVIS using Proxmox, Home Assistant, Hermes Agent, View Assist, and an old Echo Show. The system can listen for a wake word, understand speech, respond with a voice, control smart-home devices, and show information on a dedicated screen without needing a phone or computer.", "repo": "https://github.com/getthreadcontext/homey", "demo": "https://github.com/getthreadcontext/homey/blob/main/Guides/how_to_deploy.md"}]...
|
[{"post_id": 18294, "ts": "202 [{"post_id": 18294, "ts": "2026-06-29T12:15:47Z", "hours": 1.2947, "text": "I properly configured the repository so it works as a HACS integration. I also removed the text-to-speech and speech-to-text parts from the integration. In the future, I plan to move the TTS and STT features into a separate service so they can be developed, updated, and used independently."}, {"post_id": 18216, "ts": "2026-06-29T09:00:44Z", "hours": 3.0658, "text": "worte the last guide and fix bugs added better error loging"}, {"post_id": 17075, "ts": "2026-06-27T18:39:09Z", "hours": 1.2231, "text": "I set up a working voice device for JARVIS. I can now talk to JARVIS directly without needing to use my phone or computer. I also created configuration files that should work for everyone and wrote a guide explaining how to set up the voice device and connect it to Home Assistant and Hermes Agent."}, {"post_id": 16507, "ts": "2026-06-26T21:13:49Z", "hours": 1.5731, "text": "I fixed the text-to-speech and speech-to-text providers in the Home Assistant Hermes integration.The Hermes conversation agent, TTS provider, and STT provider are now all working inside Home Assistant."}, {"post_id": 16225, "ts": "2026-06-26T11:12:13Z", "hours": 1.5672, "text": "I created a HACS integration for connecting Hermes Agent to Home Assistant. The integration adds: A Hermes conversation agent and tts/sst form Hermes. The conversation agent is working, but the TTS and STT are currently broken."}, {"post_id": 16170, "ts": "2026-06-26T08:45:00Z", "hours": 1.5303, "text": "The tts and stt API plugin for Hermes fully work now. The next step is to create a Home Assistant add-on that connects Home Assistant’s AI and voice features to Hermes Agent. This will allow Home Assistant to use Hermes as part of the JARVIS voice-assistant system."}, {"post_id": 16107, "ts": "2026-06-26T06:08:15Z", "hours": 0.9978, "text": "Today, I started working on a plugin for Hermes Agent that exposes its stt and tts through an API .The goal is to use this API later to connect Hermes Agent to Home Assistant and other parts of the JARVIS project. I have not managed to get the plugin working yet, so I will continue working on it today and try to fix it."}, {"post_id": 15639, "ts": "2026-06-25T13:09:22Z", "hours": 1.1489, "text": "Dev Log 001. I started building the foundation of my real-life JARVIS project. I chose an old laptop with an AMD Ryzen 7 5700U and 16 GB of RAM as the main server. I installed Proxmox VE so I can run multiple virtual machines and services on the same computer. After setting up Proxmox, I installed Home Assistant OS using the Proxmox community installation script. I then completed the Home Assistant setup and installed HACS so I can easily add community integrations and custom features later. I also wrote the first setup guides for the project. These guides explain which hardware I am using, why I chose Proxmox, how to install Proxmox VE, how to open the Proxmox web interface, and how to install Home Assistant OS and HACS."}]...
|
Title: real life jarvis by @dummy | Stardance
Dev Title: real life jarvis by @dummy | Stardance
Devlogs:
Dev Log 001. I started building the foundation of my real-life JARVIS project. I chose an old laptop with an AMD Ryzen 7 5700U and 16 GB of RAM as the main server. I installed Proxmox VE so I can run multiple virtual machines and services on the same computer. After setting up Proxmox, I installed Home Assistant OS using the Proxmox community installation script. I then completed the Home Assistant setup and installed HACS so I can easily add community integrations and custom features later. I also wrote the first setup guides for the project. These guides explain which hardware I am using, why I chose Proxmox, how to install Proxmox VE, how to open the Proxmox web interface, and how to install Home Assistant OS and HACS.
Today, I started working on a plugin for Hermes Agent that exposes its stt and tts through an API .The goal is to use this API later to connect Hermes Agent to Home Assistant and other parts of the JARVIS project. I have not managed to get the plugin working yet, so I will continue working on it today and try to fix it.
The tts and stt API plugin for Hermes fully work now. The next step is to create a Home Assistant add-on that connects Home Assistant’s AI and voice features to Hermes Agent. This will allow Home Assistant to use Hermes as part of the JARVIS voice-assistant system.
I created a HACS integration for connecting Hermes Agent to Home Assistant. The integration adds: A Hermes conversation agent and tts/sst form Hermes. The conversation agent is working, but the TTS and STT are currently broken.
I fixed the text-to-speech and speech-to-text providers in the Home Assistant Hermes integration.The Hermes conversation agent, TTS provider, and STT provider are now all working inside Home Assistant.
I set up a working voice device for JARVIS. I can now talk to JARVIS directly without needing to use my phone or computer. I also created configuration files that should work for everyone and wrote a guide explaining how to set up the voice device and connect it to Home Assistant and Hermes Agent.
worte the last guide and fix bugs added better error loging
I properly configured the repository so it works as a HACS integration. I also removed the text-to-speech and speech-to-text parts from the integration. In the future, I plan to move the TTS and STT features into a separate service so they can be developed, updated, and used independently.
Ships:
I built a self-hosted real-life JARVIS using Proxmox, Home Assistant, Hermes Agent, View Assist, and an old Echo Show. The system can listen for a wake word, understand speech, respond with a voice, control smart-home devices, and show information on a dedicated screen without needing a phone or computer....
|
1793253369.2859936
|
1793339769.2859936
|
|
24433
|
real time telescope organizer by @hyokang | Starda real time telescope organizer by @hyokang | Stardance...
|
hyokang
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: real time telescope organizer by @hyokang | Title: real time telescope organizer by @hyokang | Stardance...
|
1793260254.757125
|
1793865054.757125
|
|
68312
|
realistic F1 inspired game by @pmandal7355 | Stard realistic F1 inspired game by @pmandal7355 | Stardance...
|
pmandal7355
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: realistic F1 inspired game by @pmandal7355 Title: realistic F1 inspired game by @pmandal7355 | Stardance...
|
1793119952.6469693
|
1793724752.6469693
|
|
54761
|
realistic shooter by @Sium | Stardance
|
Sium
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: realistic shooter by @Sium | Stardance
|
1792803220.0506632
|
1793408020.0506632
|
|
42453
|
really bad cyberdeck by @phamezz_t | Stardance
|
phamezz_t
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: really bad cyberdeck by @phamezz_t | Starda Title: really bad cyberdeck by @phamezz_t | Stardance...
|
1793177504.4917946
|
1793782304.4917946
|
|
65447
|
receipt by @Alan-Betty | Stardance
|
Alan-Betty
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: receipt by @Alan-Betty | Stardance
|
1793087491.148771
|
1793692291.148771
|
|
65220
|
receipt by @furgenramen | Stardance
|
furgenramen
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: receipt by @furgenramen | Stardance
|
1793084122.3587897
|
1793688922.3587897
|
|
65177
|
receipt-stardance by @kaxokaze | Stardance
|
kaxokaze
|
0
|
1.08
|
0
|
[]
|
[{"post_id": 73704, "ts": "202 [{"post_id": 73704, "ts": "2026-09-25T18:55:47Z", "hours": 1.0825, "text": "issssSPIDERMANNN issssSPIDERMANNN. checkout now:"}]...
|
Title: receipt-stardance by @kaxokaze | Stardance
Title: receipt-stardance by @kaxokaze | Stardance
Devlogs:
issssSPIDERMANNN issssSPIDERMANNN. checkout now:...
|
1793084039.816749
|
1793688839.816749
|
|
8783
|
recognizer by @cyberft | Stardance
|
cyberft
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: recognizer by @cyberft | Stardance
|
1793170265.6136892
|
1793775065.6136892
|
|
10206
|
recycle helper by @maruitus | Stardance
|
maruitus
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: recycle helper by @maruitus | Stardance
|
1793400759.319259
|
1794005559.319259
|
|
4238
|
red bull tracker by @neset | Stardance
|
neset
|
1
|
22.29
|
336
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-06T20:00:22Z", "hours": 22.0, "multiplier": 15.51, "payout": 336, "blessing": "neutral", "text": "this is a caffeine drink tracker allowing you to add and track your caffeine intake across multiple days. i wrote it using svelte and postgresql. this was one of my first projects that i wrote with svelte, so i learned quite a bit about it. i also did custom art and design for each of the drinks in figma.", "repo": "https://github.com/nesetkab/redbull", "demo": "https://redbull.nesetk.com"}]...
|
[{"post_id": 77666, "ts": "202 [{"post_id": 77666, "ts": "2026-10-07T19:35:28Z", "hours": 0.2911, "text": "bug fixes"}, {"post_id": 77399, "ts": "2026-10-06T19:58:44Z", "hours": 2.0128, "text": "ready to ship! added an intro explaining what this is added cookies so u can track ur own data made my data global for everyone to see minor bug fixes todo: add more drinks"}, {"post_id": 19639, "ts": "2026-07-01T00:46:56Z", "hours": 1.6789, "text": "more progress on ui, adding more drinks, polishing drink picker. currently on amtrack so very bad wifi"}, {"post_id": 18904, "ts": "2026-06-30T02:59:09Z", "hours": 2.9706, "text": "im highkey across the country but wtv working on makign picker ux way better look at this yummy anim"}, {"post_id": 16070, "ts": "2026-06-26T03:45:21Z", "hours": 1.8869, "text": "working on looks! statistics looks much better still a lot to do to finish it up, but i’m almost there"}, {"post_id": 15365, "ts": "2026-06-24T23:49:42Z", "hours": 0.5797, "text": "wowzers statistics tooltips need to fix the labels hitting each other $state() might be the best thing in the world"}, {"post_id": 15160, "ts": "2026-06-24T17:02:58Z", "hours": 0.585, "text": "statistics are a lot more prettyyyyy fixed mobile handling for statistics todo: add more drinks drink chooser ui ship!"}, {"post_id": 13894, "ts": "2026-06-22T19:36:41Z", "hours": 2.8711, "text": "LOTS done. changed how data is stored to allow for more drinks to be added added “caffeine” attribute in order to track my caffeine intake (addiction) added statistics in order to track how many redbulls im actually drinking began adding other drinks to do: finalize the UX of how drinks are chosen add more drinks! finish statistics to be more functional and look more pretty ship!"}, {"post_id": 12791, "ts": "2026-06-20T22:21:44Z", "hours": 1.43, "text": "new redbull designs that are more accurate to the real thing! fixed some ux bugs todo: make ui look better add monster? i love monster data analysis ship!"}, {"post_id": 12279, "ts": "2026-06-20T01:40:43Z", "hours": 0.5042, "text": "havent finished the data part yet but i want to make a dev log because look at how BEAUTIFUL the new icons look <3333"}, {"post_id": 12267, "ts": "2026-06-20T01:01:09Z", "hours": 1.1347, "text": "multi-submit works* improved ux a LOT, i really like these tilted incrementers i want to change it so that SF is a toggle rather than a diff redbull, to decrease scrolling (better ux) submitter is VERY chopped rn (that’s why there’s the asterisk) multi submit repeatedly adds the redbull into a list which works but is kind of chopped. also, SF toggle doesn’t rly work. once i restructure the picker, im going to design icons for plus, minus, and SF, improve ui/ux a bit more, and then add data statistics. after that, i think it’ll be good to ship !!!"}, {"post_id": 11668, "ts": "2026-06-19T00:38:31Z", "hours": 0.5356, "text": "added data sorting by day into the tracker! groups by today, yesterday, and then weekly. plan is to add day sorting within those weeks next. also, need to add a way to submit multiple of the same redbull without repeatedly submitting. also, adding statistics would be nice."}, {"post_id": 11048, "ts": "2026-06-18T02:29:21Z", "hours": 0.6739, "text": "today count works now. i wanna go eep but ill work on data analysis tmr"}, {"post_id": 11000, "ts": "2026-06-18T00:52:01Z", "hours": 1.2214, "text": "deleting works now. the beginnings of a viewer exists"}, {"post_id": 10916, "ts": "2026-06-17T21:50:28Z", "hours": 0.4422, "text": "finally added all of the red bull flavors, including the sugarfree ones"}, {"post_id": 10709, "ts": "2026-06-17T15:59:38Z", "hours": 3.16, "text": "i’m now able to choose a redbull and add it! red bulls are stored in a psql database which keeps track of the red bull name, whether its sugarfree or not, and the date it was submitted. todo: add more redbulls! make a more visual data viewer graphs to see my statistics host this so other ppl can see my stats"}]...
|
Title: red bull tracker by @neset | Stardance
Dev Title: red bull tracker by @neset | Stardance
Devlogs:
i’m now able to choose a redbull and add it! red bulls are stored in a psql database which keeps track of the red bull name, whether its sugarfree or not, and the date it was submitted. todo: add more redbulls! make a more visual data viewer graphs to see my statistics host this so other ppl can see my stats
finally added all of the red bull flavors, including the sugarfree ones
deleting works now. the beginnings of a viewer exists
today count works now. i wanna go eep but ill work on data analysis tmr
added data sorting by day into the tracker! groups by today, yesterday, and then weekly. plan is to add day sorting within those weeks next. also, need to add a way to submit multiple of the same redbull without repeatedly submitting. also, adding statistics would be nice.
multi-submit works* improved ux a LOT, i really like these tilted incrementers i want to change it so that SF is a toggle rather than a diff redbull, to decrease scrolling (better ux) submitter is VERY chopped rn (that’s why there’s the asterisk) multi submit repeatedly adds the redbull into a list which works but is kind of chopped. also, SF toggle doesn’t rly work. once i restructure the picker, im going to design icons for plus, minus, and SF, improve ui/ux a bit more, and then add data statistics. after that, i think it’ll be good to ship !!!
havent finished the data part yet but i want to make a dev log because look at how BEAUTIFUL the new icons look <3333
new redbull designs that are more accurate to the real thing! fixed some ux bugs todo: make ui look better add monster? i love monster data analysis ship!
LOTS done. changed how data is stored to allow for more drinks to be added added “caffeine” attribute in order to track my caffeine intake (addiction) added statistics in order to track how many redbulls im actually drinking began adding other drinks to do: finalize the UX of how drinks are chosen add more drinks! finish statistics to be more functional and look more pretty ship!
statistics are a lot more prettyyyyy fixed mobile handling for statistics todo: add more drinks drink chooser ui ship!
wowzers statistics tooltips need to fix the labels hitting each other $state() might be the best thing in the world
working on looks! statistics looks much better still a lot to do to finish it up, but i’m almost there
im highkey across the country but wtv working on makign picker ux way better look at this yummy anim
more progress on ui, adding more drinks, polishing drink picker. currently on amtrack so very bad wifi
ready to ship! added an intro explaining what this is added cookies so u can track ur own data made my data global for everyone to see minor bug fixes todo: add more drinks
bug fixes
Ships:
this is a caffeine drink tracker allowing you to add and track your caffeine intake across multiple days. i wrote it using svelte and postgresql. this was one of my first projects that i wrote with svelte, so i learned quite a bit about it. i also did custom art and design for each of the drinks in figma....
|
1793342898.9960113
|
1793429298.9960113
|
|
68098
|
red0x-OS by @Red0x | Stardance
|
Red0x
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: red0x-OS by @Red0x | Stardance
|
1793116462.2733052
|
1793721262.2733052
|
|
294
|
redaptcha by @redac1ed | Stardance
|
redac1ed
|
0
|
0.53
|
0
|
[]
|
[{"post_id": 857, "ts": "2026- [{"post_id": 857, "ts": "2026-06-02T15:49:32Z", "hours": 0.5281, "text": "Heya! This is the starting of this captcha that I am making in Rust! Changes: added a frontend to test the captcha added a backend to make the prototype Commits: cbad970 Now, I am going to lock in to make a plan for the backend."}]...
|
Title: redaptcha by @redac1ed | Stardance
Devlogs Title: redaptcha by @redac1ed | Stardance
Devlogs:
Heya! This is the starting of this captcha that I am making in Rust! Changes: added a frontend to test the captcha added a backend to make the prototype Commits: cbad970 Now, I am going to lock in to make a plan for the backend....
|
1793188412.0639882
|
1793793212.0639882
|
|
809
|
redditstockscraper by @opmasterajar | Stardance
|
opmasterajar
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: redditstockscraper by @opmasterajar | Stard Title: redditstockscraper by @opmasterajar | Stardance...
|
1793231664.7709026
|
1793836464.7709026
|
|
64648
|
redhalOS by @gober | Stardance
|
gober
|
0
|
6.0
|
0
|
[]
|
[{"post_id": 74843, "ts": "202 [{"post_id": 74843, "ts": "2026-09-28T12:47:15Z", "hours": 2.2208, "text": "I followed the tutorial some more to finally get the window to be draggable and closable! (Yes, I seriously spent 2 hours trying to figure it out, because I MISMATCHED NAMES AGAIN!! ) Also I polished up the welcome window so it doesn’t look stupid"}, {"post_id": 73312, "ts": "2026-09-24T20:40:52Z", "hours": 1.3206, "text": "Okay, so I gave it a wallpaper (hey this looks familiar…), and I made the top bar from the tutorial, but in TRANSLUCENT RED!!! I broke my brain trying to get the time to work, and then I found out it was stupidly simple and I plugged in the variables wrong (I thought I was supposed to put another script tag where the time and date is printed 😭)"}, {"post_id": 73107, "ts": "2026-09-24T12:31:05Z", "hours": 1.0275, "text": "Added a font and turned the page into a little window!"}, {"post_id": 72823, "ts": "2026-09-23T20:09:58Z", "hours": 0.3272, "text": "Spent a bit of time making a little favicon on Figma, sadly my time wasnt logged ;-;"}, {"post_id": 72667, "ts": "2026-09-23T13:48:02Z", "hours": 1.1069, "text": "Getting started! This is the base of the WebOS, the 1 hour is probably fake"}]...
|
Title: redhalOS by @gober | Stardance
Devlogs:
Ge Title: redhalOS by @gober | Stardance
Devlogs:
Getting started! This is the base of the WebOS, the 1 hour is probably fake
Spent a bit of time making a little favicon on Figma, sadly my time wasnt logged ;-;
Added a font and turned the page into a little window!
Okay, so I gave it a wallpaper (hey this looks familiar…), and I made the top bar from the tutorial, but in TRANSLUCENT RED!!! I broke my brain trying to get the time to work, and then I found out it was stupidly simple and I plugged in the variables wrong (I thought I was supposed to put another script tag where the time and date is printed 😭)
I followed the tutorial some more to finally get the window to be draggable and closable! (Yes, I seriously spent 2 hours trying to figure it out, because I MISMATCHED NAMES AGAIN!! ) Also I polished up the welcome window so it doesn’t look stupid...
|
1793065855.4502535
|
1793670655.4502535
|
|
23868
|
redline by @pinetree182 | Stardance
|
pinetree182
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: redline by @pinetree182 | Stardance
|
1792914652.236727
|
1793778652.236727
|
|
66657
|
redo hruss.com by @hruss | Stardance
|
hruss
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: redo hruss.com by @hruss | Stardance
|
1793101804.6665542
|
1793706604.6665542
|
|
71009
|
redoo by @bareerakhalid | Stardance
|
bareerakhalid
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: redoo by @bareerakhalid | Stardance
|
1792748847.3255894
|
1793353647.3255894
|
|
42605
|
reel steel by @amitesh_senthil | Stardance
|
amitesh_senthil
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: reel steel by @amitesh_senthil | Stardance
|
1793184510.208586
|
1793789310.208586
|
|
9351
|
reelr by @faizaaaaaaan | Stardance
|
faizaaaaaaan
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: reelr by @faizaaaaaaan | Stardance
|
1793339345.7153387
|
1793944145.7153387
|
|
34778
|
ref os by @samarth_hota | Stardance
|
samarth_hota
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: ref os by @samarth_hota | Stardance
|
1792918297.4166925
|
1793782297.4166925
|
|
15644
|
reflection system for the rust programming languag reflection system for the rust programming language by @jsumme205 | Stardance...
|
jsumme205
|
0
|
0.0
|
0
|
[]
|
[]
|
Title: reflection system for the rust programming Title: reflection system for the rust programming language by @jsumme205 | Stardance...
|
1793368109.6540546
|
1793972909.6540546
|
|
68810
|
reflexclock by @akshat_singh1738 | Stardance
|
akshat_singh1738
|
0
|
0.7
|
0
|
[]
|
[{"post_id": 81266, "ts": "202 [{"post_id": 81266, "ts": "2026-10-20T15:24:40Z", "hours": 0.7008, "text": "devlog 1: worked on the pcb design for my relfex test based alarm . So the idea for my alarm is that you need to take a quick reflex test to stop it and this wakes you up fully! Today i worked on learning kicad and how pcb design works and then designed the pcb with the help of the guide!"}]...
|
Title: reflexclock by @akshat_singh1738 | Stardanc Title: reflexclock by @akshat_singh1738 | Stardance
Devlogs:
devlog 1: worked on the pcb design for my relfex test based alarm . So the idea for my alarm is that you need to take a quick reflex test to stop it and this wakes you up fully! Today i worked on learning kicad and how pcb design works and then designed the pcb with the help of the guide!...
|
1793126955.6026976
|
1793731755.6026976
|