HN user

mariusandra

860 karma
Posts69
Comments95
View on HN
cases.frameos.net 1y ago

FrameOS Case Maker for eInk Displays

mariusandra
2pts0
frameos.net 1y ago

FrameOS 2024 Recap

mariusandra
1pts0
www.youtube.com 1y ago

DIY 12.48" e-Paper display with FrameOS – Full Build [video]

mariusandra
2pts0
github.com 1y ago

Gpt.sh

mariusandra
3pts0
frameos.net 1y ago

FrameOS NimConf 2024

mariusandra
2pts0
innovationhypercube.com 2y ago

Innovation Hypercube

mariusandra
2pts0
frameos.net 2y ago

Show HN: FrameOS – operating system for single function smart frames

mariusandra
474pts112
frameos.net 2y ago

FrameOS Nim Rewrite

mariusandra
6pts0
github.com 2y ago

FrameOS – Control Raspberry Pi-powered picture frames

mariusandra
1pts0
posthog.com 3y ago

HogQL: Direct SQL Access for PostHog

mariusandra
4pts0
medium.com 3y ago

Some people create work. Some people solve work

mariusandra
2pts0
medium.com 3y ago

Some people create work. Some people solve work

mariusandra
3pts0
www.youtube.com 4y ago

Kea 3 introduction and getting started

mariusandra
1pts0
keajs.org 4y ago

Kea 3.0 – State Management via Logic Builders

mariusandra
39pts18
keajs.org 4y ago

Kea v3.0 Pre-Release

mariusandra
4pts0
posthog.com 4y ago

Automating a Software Company with GitHub Actions

mariusandra
247pts70
kea.js.org 5y ago

It's time for a data-first front end revolution

mariusandra
2pts0
kea.js.org 5y ago

It's time for a data-first front end revolution

mariusandra
1pts0
kea.js.org 5y ago

Keep your state in Kea and your views in React

mariusandra
1pts0
pigeon-maps.js.org 5y ago

Pigeon Maps – ReactJS maps without external dependencies

mariusandra
2pts0
kea.js.org 5y ago

Kea – Production Ready React State Management

mariusandra
1pts0
kea.js.org 5y ago

TypeScript Support in Kea (The Long Road)

mariusandra
2pts0
www.youtube.com 5y ago

Kea-typegen – autogenerate TypeScript types for Kea (React state management)

mariusandra
1pts0
github.com 6y ago

Asking: How does Kea compare to other state management frameworks?

mariusandra
1pts0
kea.js.org 6y ago

What Is Kea?

mariusandra
1pts0
kea.js.org 6y ago

Kea 2.0 – Production Ready State Management for React

mariusandra
1pts0
kea.js.org 6y ago

Kea 2.0 Relased – Production Ready State Management for React

mariusandra
2pts0
news.ycombinator.com 6y ago

Show HN: Insights – Visual PostgreSQL Explorer for Startups

mariusandra
4pts0
github.com 6y ago

Insights – Open-Source Self-Hosted Business Intelligence Platform

mariusandra
91pts14
github.com 6y ago

Insights – Free Self-Hosted Business Intelligence Platform

mariusandra
4pts0
PostHog FOSS 13 days ago

um... we've had this posthog-foss repo for years now. No idea why it made front page. This is not news.

Source: I was there

To clarify: PostHog has been MIT licensed since day 1, with the exception of the `ee/` folder. This `posthog-foss` repo is a mirror of the main `posthog` repo with the `ee/` folder removed. We've had it for ages.

The math didn't add up for us (I work at PostHog). At the rate we were scaling, we would have needed an entire call center's worth of highly trained Kubernetes support engineers to debug everyone's "my pods just died" / "Kafka just stopped" / "what is Zookeeper" problems.

This stack isn't straightforward to manage, and we couldn't crack the code of doing it at scale for other people without even having access to their systems. There was no malicious intent.

Read more here: https://posthog.com/blog/sunsetting-helm-support-posthog

Re-reading, my tone in the first sentence sounds rather hostile. I apologise for that. I have no ill intent, the joke was likely funnier in my head.

FrameOS is also targeting 60+FPS LCD and other screens, which will be hard for ESP to run. Thus it's for the raspberry. I'd love to scale it down though, and deliberately chose Nim so that it would at least be theoretically possible.

I also need to get doom running on it...

Yes, MP4, sorry for the typo :).

I believe in such places the cost of service and maintenance is many multiples the cost of the initial installation. A $20 "720p hdmi stick" from aliexpress vs a $300 mac mini is a no brainer. 100 mac minis will work reliably and predictably for years to come, whereas 100 random $20-$50 sticks sounds like something that needs constant supervision and maintenance.

That said, a RPi might be enough, depends on the software. That's why FrameOS has HDMI support, to work for such cases. It's still pretty far from being a turnkey solution today, but we could easily get there with some focus at the right time.

I apologize for the confusion, but you do not need to run FrameOS at all. You can just go about your merry day, and either just not use FrameOS, not post this comment, or, if you prefer, not read any of the comments addressing this question before posting yours.

On a serious note, yes, it's planned. The ESP is a very limited chip. If you want to display a BMP from a HTTP source, or a quick calendar, it's great. Try doing HTTPS, image downscaling or any serious processing though. Forget about things like browser screenshots, which you can't even do on 32bit linux anymore. Forget the 60fps mode over HDMI we can now do.

I'll try to get it working regardless, but it's but not a personal priority today over the other items in the todo list. You're free to lend a helping hand of course.

Ha, nice to meet you.

I always say "if it's stupid and it works, it's not stupid". Your approach to get the dithering right sounds brilliant to me :D.

The current inky driver works great, and that fact that it's in Python is what made me develop the original FrameOS software in Python. However now that I rewrote it in Nim, the Python driver is a bit of a crutch. While I could use the C drivers for the Waveshare displays, I'm forced to install a python wrapper on the Pi as a workaround to get the Inky drivers working.

Do you have any idea if there are any C, or even Nim drivers available for the Inky Impression boards? The Python workaround works, but isn't really elegant. If not, I'm considering porting them myself at some point...

I'm also lurking on the Pimoroni discord, and was meaning to ask there about it as well.

Absolutely! Just hook up your display with a HDMI port to a raspberry, and you're good to go.

If you're fine with just displaying an image from an URL, it'll work today. If you want nicer slideshows or rotating images, you'd have to write some code to make it work, but it's all possible today.

A nicer interface tailored specifically for shop windows slideshows is something that could come at a later date.

I have gotten the new Nim-based FrameOS working with two different Waveshare displays. I have two other ones waiting to be tested. Check this folder [1] for the currently enabled drivers.

One of the next items on my todo list [2] is to add back support for all the different waveshare drivers out there. They all follow a similar pattern, so I should be able to generate "best guess" drivers for most of them.

Which display do you have?

[1] https://github.com/FrameOS/frameos/tree/main/frameos/src/dri... [2] https://github.com/FrameOS/frameos/issues/1

I was quite shocked at the amount of tiny and large display options out there. I might even make a YouTube video titled "Home dashboards have gotten cheap and easy" with everything I've learned so far.

Take a $15 Pi Zero W 2, and a screen costing anywhere between $50 to $200. 3d-print a case around them both, and for a third of the price of a new iPad, you'll have a simple and secure single function screen in your house...

I used to have an iPad (3rd gen) on the wall, then it died. I bought the cheapest new one to replace it, but the old Android tablet I had around had better bluetooth reach, so it went on the wall instead.

Old android tablets are notoriously unpatched against all kinds of things. It's easy to be paranoid that some passing foot traffic will infect it with a bluetooth worm, and you'll be none the wiser.

I'm accepting the risk for now, as I do enjoy configuring Home Assistant on it, and looking at the rainmap, but there are times when when a full tablet is overkill. FrameOS is for those cases.

You're technically right (the best kind?), but there's some nuance to the question.

FrameOS is a compiled binary that runs on top of Linux. At present you need to install the "Raspberry Pi OS Lite" (without the desktop environment) on a SD card before you can install FrameOS itself on top of that. So it's "just an application".

However, this is mostly because it's an early project, and this was the fastest way to get going. The next step is to see how much can be removed. Since FrameOS is a statically compiled single binary, it shouldn't need that much more than the Linux kernel? Will FrameOS be a true OS then? Android seems to be considered its own OS despite using the Linux kernel.

Once activated, FrameOS takes over your entire system, has its own `apps/` and `drivers/` folders, and in many ways already behaves like an Operating System. I'm also pondering about getting it running on an ESP32 (will need to add `drivers/wifi/`?). Without any OS below it, will it then be worthy of being called an OS? You all tell me. :shrug:

Thus is it an Operating System? It is to me, but you can choose to disagree.

At my actual job (PostHog), we sometimes call ourselves the "Product OS". This annoys me more, as a suite of webapps definitely isn't an "Operating System" in its traditional sense. I've seen -OS at the end of other things as well that aren't pure Operating Systems. It slightly bothers me, but mostly because I was around when "what OS you're using" was a defining question. Language is evolving, and "operating system" seems to describe more things to different people, than it does to you and me.

Hey, thanks for the feedback!

The editor/controller itself is just a React+Kea app using React Flow for the diagramming part, and Flask for the backend.

For now to test that the app you built works, you must deploy it on a frame. I have a fast RPi 5 for testing, and the feedback loop is typically ~30sec. It's about a minute with a Zero W2, and about 2min with a Zero W. This is not ideal, and I'd like to improve that.

Ideally I'd like to use Nim's JS backend to build a "frame" that can be run directly in the browser for testing.

As for the other questions, the FrameOS system runs at boot, and all the apps are compiled in to that one binary and run as the scene dictates. New frames get rendered when a render event is dispatched, which can happen automatically on an interval, or as requested. Frames send logs back to their controller, but can otherwise operate completely independently.

I'd love it to work on the RP2040, and perhaps even an ESP32, but we're not there yet. Just yesterday I converted FrameOS from being an interpreted python app to a 3MB compiled binary, so we're half of the way there. I'm not sure what changes I must do to get it working (e.g. integrate a wifi driver, remove GC and threads, etc), but it's in the realm of the possible.

There's nothing built in now, but a common technique would be to make the image e.g. ~10px larger in each direction, and then choose a random crop every other second.

It should be really easy to build a FrameOS app that does this. Add one node at the start of the render loop to increase the image accordingly, and one at the end to crop it back down. I was planning to use a similar technique to display smooth scrolling animations/slideshows, but it can definitely be used to prevent burnin.

I'd love for FrameOS to support ESP32. Two days ago FrameOS was a slow and interpreted Python app. Today it's a 3MB statically linked binary. The margins are tight, and I'll likely need to cut out some features (e.g. threading), but theoretically it should be possible to get it to run. However I'm not planning on taking this on any time soon, as there's still a lot of work left to make the Raspberry version great. :)

You're asking very good questions.

I think you can map the example class I wrote to similar concepts - but instead of three+ different function calls to build a logic, you could do one, like `magical(classInstance)` - which would scan the instance and derive internal state machinery much the same way that kea’s `actions` and `reducers` iterate over their argument objects.

That's the magic of Kea: it gives you a framework you can use to get exactly the DSL that makes sense for your app.

This example code you posted:

    kea([
      actions({
        loadUsers: true,
        loadUsersSuccess: (users) => ({ users }),
        loadUsersFailure: (error) => ({ error }),
      }),
    
      reducers({
        users: [
          [],
          {
            loadUsersSuccess: (_, { users }) => users,
          },
        ],
        usersLoading: [
          false,
          {
            loadUsers: () => true,
            loadUsersSuccess: () => false,
            loadUsersFailure: () => false,
          },
        ],
        usersError: [
          null,
          {
            loadUsers: () => null,
            loadUsersFailure: (_, { error }) => error,
          },
        ],
      }),
    
      listeners(({ actions }) => ({
        loadUsers: async () => {
          try {
            const users = await api.get('users')
            actions.loadUsersSuccess(users)
          } catch (error) {
            actions.loadUsersFailure(error.message)
          }
        },
      })),
    ])
    
I'd personally write as this code:
  kea([
    loaders({
      users: { loadUsers: () => api.get('users') }
    })
  ])
and it would do exactly the same thing.

Well, almost, since the `usersError` message won't be saved. To get that you will need to add a reducer.

  kea([
    loaders({
      users: { loadUsers: () => api.get('users') }
    }),
    reducers({
      usersError: (_, { loadUsersFailure: (_, { error }) => error })
    }),
  ])
This is the magic Kea brings to the table, as you can use the core building blocks as frontend state management lego, creating an ever higher language with which to describe your application's logic.

Loading data is such a common pattern, that it makes sense to standardise on a framework level. Who knows what needs your app will have.

But would it be less maintainable? No matter the framework - Redux, Redux Toolkit, Kea, this monstrosity I just cooked up - your team needs to invest in culture and training about the right way to do things.

You're hitting the nail on the head. I've worked with many developers using Kea over the last years, and while people get it quite quickly, you do need to actually read the docs to understand how it all works together. Otherwise you'll bring your old patterns to this new environment, and write bad (hard to maintain) code.

But this is the case no matter the framework, as you argue. If you don't put in the time in to learn the tooling, your output will be highly inefficient.

At work, I've spent quite a bit of time teaching colleagues how to write Kea the right way, and will now contribute most of this knowledge back in the form of screencasts and tutorials on keajs.org. My hope is that these will help future colleagues of mine level up faster, and the same would apply to all other teams using Kea.

I guess the question I’m asking is, why is kea’s current position on the explicit-vs-magic spectrum the right global maximum for developer ergonomics & maintainability? kea advanced over raw Redux already, but why not go even further?

You need to draw lines somewhere, and I believe "base 3" (actions, reducers, selectors) is a good place for that. This is in contrast to "base 2" (get, set), which lures with its simplicity, but lead to abstractions that perform worse when you chunk concepts. That extra unit of reasoning within the core abstraction gives a lot. Think 3*3*3=27 vs 2*2*2*2=16.

I get this is going very philosophical/abstract, but we're discussing "magic", so I think we're good :D.

Having seen a lot of different ways to code frontend over the years, I believe a redux-like pattern is the best fit for frontend apps, all* things considered. Compared to "base 2" (get/set) through regular JS primitives, the big difference is that redux forces you to label each write operation with an action type. Every write. This enables a whole class of side effects and observability. These inherent benefits of actions can then be described as magic that comes for free with the abstraction, not as magic that comes from building clever code that hides a complex implementations. As a developer, the former is so much easier to truly and intuitively master, while the latter sounds like a bag of edge cases that you'll keep poking with a stick (see: apollo, based on what I've read on HN lately).

Add to that a global immutable state tree that you can just pass around in a variable (the store), a system of labelled data retrievers from this state tree (selectors), and a way to connect all of these pipes directly to React, an auxiliary system of props and keys to fork data and its operations, a standard library of utils for common operations (routing, forms), commitment to compact syntax, a great way to compose code, and an ever expanding set of learning materials.

The result is what is Kea now. I'm not forcing anyone to use it, but I do think it strikes very close to the global maximum of developer ergonomics and maintainability.

I'm always happy to improve it, and Kea 3.0 was an exercise to push that envelope even further.

lol.

First, it's 2 rewrites. Second, those were all 98% backwards compatible for the users (might need to upgrade plugins), and just refactored the internals.

But sure, let's all write perfect code on day 0, taking into account all the ways libraries you depend on (React) can develop in the future. It's not like "frontend" is a moving target or anything...

/s

Depends what you mean with "readable". It's always easy to make a contrived example, and call that readable because it's shorter. I'm talking about huge apps maintained by multiple remote teams, all working independently.

In this case I would argue that the end goal is "maintainability", not "readability", and Kea, thanks to forcing you to use an abstraction in the first place, leads to better maintainable code.

Piping all "writes" through actions, and all "reads" through selectors gives you complete observability over the entire system at any point in time. The immutable nature of this approach also works wonders in preventing React from wasting time with needless re-renders. Plus the syntax makes it that you can jump into any part of a system consisting of 200+ logic files, and immediately understand how each piece of data came about, and what are the only things that can change it.

Using "simple" and "readable" plain functions that go `this.something = "value"` is the antithesis of a maintainable system. You lose all observability, unless you integrate a lot of "magic", for example making every value secretly use "immer".

There is a lot of non-linear control flow encoded implicitly in calls to `kea`, `actions`, `listeners` in this framework, and for what?

To build large applications that scale well, are easy to reason about, and can be maintained by whoever joins your team.

Well, in PostHog (I'm a colleague of Twixes), we just decided here [1] to go with Kea, as I had more experience with it.

Had Redux Toolkit been around when I started with Redux in 2016, I probably wouldn't have needed to write Kea. However I'm glad I did, as I now do consider Kea to be the better toolkit for the same job. :D. I know you disagree, and that's all fine of course :).

In my mind Kea fills in all the missing parts from React, while Redux Toolkit is still a set of utility functions for state management. You still need to find another set of tools for data loading (I see this has improved), complex data or form management, app routing, scene handling, etc. Redux Toolkit doesn't bother with most of that, and I don't think it should.

Kea however comes with solutions for all of those. The only thing missing from being able to build a complete app is a JS module bundler. Just sit down and start writing your actual app with the least amount of syntax possible to explain things in a redux'y way. Many people have told me that with Kea, the framework basically gets out of the way and disappears.

Now with the Kea 3.0 Logic Builder syntax, Kea is suddenly like lego for state management. I'm curious to see if this picks up or not. I can't unfortunately link Kea from redux.js.org to drive traffic :).

[1] https://github.com/PostHog/posthog/issues/301 -- the magic of working in an open source company is that we can post stuff like this. We're hiring!

OP here, so call me biased, but I tend to disagree. Curious to hear your thought on alternative or better approaches to system design here.

In my experience you need some amount of boilerplate, or what I'd call _architecture_, to have a stable system. Give too much freedom ("just use get/set" or "variables on context"), and not only can no other developer on your team not maintain your code, but no part of your app will work together after a while. You'll end up with multiple incompatible implementations of ad-hoc state machines.

The key to maintainability is to use a framework that forces you to do spend a bit more effort than you'd do when coding YOLO, but which forces everyone on the team to make the same tradeoff. The result: everyone can jump in to any part of the project and with a bit of digging around be fluent in the surroundings.

Kea seems to strike a pretty good balance of making this possible in large projects.