cztomsik / graffiti

HTML/CSS engine for node.js and deno.
http://tomsik.cz/graffiti
MIT License
939 stars 18 forks source link

Use-cases #143

Open cztomsik opened 4 years ago

cztomsik commented 4 years ago

I'd like to know what you want to build with this project.

It will help me with some future design decisions and it's also going to be very useful when writing documentation (better examples).

knoopx commented 4 years ago

Hey @cztomsik, I would like to build an RPI touchscreen client for octoprint/klipper. I'm also very interested in your hackable tv project

cztomsik commented 4 years ago

hey, thanks for the feedback and good luck with the project - I think it's actually very cool idea. Feel free to reach me on discord if you're stuck with something :)

egasimus commented 4 years ago

All I want is to be able to put semantic graphics on screen easily, cheaply and flexibly. The current platform fragmentation is insane: browsers are everywhere and generally pleasant to develop for but are terrible resource hogs and a source of security vulnerabilities; while native toolkits are either too low-level or tend to have too many assumptions for me to work comfortably with. A non-browser-based, DOM-like thing would be a game-changer.

cztomsik commented 4 years ago

@egasimus thanks for your response, I'm glad it's not just me :-)

@egasimus @knoopx I still need to finish few things before release but I want to write some tutorials soon, is there anything you'd like to see in particular?

egasimus commented 4 years ago

@cztomsik Idk, but if you already have some topics in mind I could try and lend a hand with writing some tutorials?

cztomsik commented 4 years ago

@egasimus I need to polish public API (window creation & context isolation) a bit first but then it would be really helpful.

Some ideas:

I could even provide some PoCs of those so you wouldn't need to start from scratch. But it would be best to discuss it on discord. (join link is on the homepage)

egasimus commented 4 years ago

Discord is... suboptimal. In general, I prefer asynchronous conversations (like this one), but as far as modern collaboration tools go, why not give Riot a shot? :-)

I have some neat ideas about audio library management in particular so I might go with that. Terminal multiplexing, desktop panels, and a discoverable systemd GUI are some other interesting problem spaces - a little more niche but fun and useful nonetheless.

Feature-wise, if Graffiti supports a canvas-like component, or some sort of OpenGL/Vulkan rendering surface (does it? guess I should start reading the source huh), I'd build a trading chart visualizer. Or a music sequencer. Or an image editor of course. Actually for those first two I might be able to dig out some code based on canvas and/or SVG (and at least one demo with pure Rust+GLSL) that I could look into porting/rewriting for Graffiti.

So yeah, what about people interested in porting their existing apps? Maybe if you had some sort of medium-sized React app that doesn't work in Graffiti out of the box but could be ported with a modicum of effort, I could do a writeup of the steps to get it running, maybe even do a comparative benchmark to measure exactly how much faster than a browser this is.

Sounds like fun, I'm really glad to be discussing this :-)

cztomsik commented 4 years ago

@egasimus np, we can stay here or you can mail me

audio-project sounds very interesting but

Currently, the biggest limitation is the absence of global styles (only inline styles are supported). I'd like to avoid adding it because it would take months to make it work similarly - I'd rather like to add support for some utility-first CSS framework, like tailwind or tachyons - that could be done easily with plain react (custom h function would just concatenate & cache the inline style)

// this does not exists yet, but it's simple to do, actually
/* @jsx h */
import { h } from 'inline-tachyons'

<div cx="btn p-5">Btn with padding 5</div>

And I also think, CSS is fundamentally broken - it's so easy to get into collisions and what's worse, css rules are applied in the definition order (order of classes in className does not matter) and I'd like to avoid repeating the same mistakes.

Unfortunately, I was always working on intranet webapps so I don't have much to show/port except what I've already mentioned. Maybe one old (angular1) application for making invoices.

egasimus commented 4 years ago

I think there being no audio API is a feature rather than a shortcoming. In my opinion, it's crucial to confine the scope to just the GUI engine, rather than reimplement the whole browser. As a potential Graffiti app developer, I'd benefit from having to bring my own audio code - or better yet, delegate all that to a daemon via some form of IPC. A diversity of implementations is better than a diversity of hacky workarounds atop a default implementation.

On the flip side, I think first-class support for hot module reloading is quite important - the more instant feedback when building a GUI, the better! I've seen HMR being done even in C++ with JUCE. I've done a few experiments with hot module reloading in Node; the most self-contained one so far is dothot, which does not attempt to do dependency tracking at all; it relies on calling require() within the bodies of functions instead of at the top of the module. This has the intention of shepherding people into a more functional style. I think I also have some similar code somewhere that implements dependency tracking as well.

For me, the important takeway here is that most HMR implementations target a frontend loaded over the network in a browser, and optimize for that use case (Webpack has "web" in its name, heh). This makes them leaky abstractions. I'd much rather see just the delivery method abstracted away, so that if I'm building a Graffiti app which is local-first, and only incidentally accessible remotely via browser, I would have an iteration speed of e.g. 100ms vs of 1s (90% of which due to traversing the network stack to localhost, tree-shaking, minification, all of which are irrelevant in that case). Yes, hardly anyone would say something about 100ms vs 1s feedback loop when coding a GUI, but I think it still makes a difference.

I totally get you about always working on intranet webapps, I'm the same :-) Luckily I also have a big stash of unfinished side projects which I'll be more than happy to dust off once I've found a way around #152. Maybe once I have picked up some speed with Graffiti I could even record some live coding videos, been on my mind for a while.

One last thing, have you seen Arcan? I see it as having some common ground with Graffiti, in terms of "indie project that attempts to get rid of all the accumulated cruft in the GUI stack". It has a bit more of a "kitchen sink" approach and "Unix greybeard" mentality I guess - which I totally admire, but I'm more comfortable with Rust, Node and the DOM as opposed to C, Lua and imperative drawing, which is one reason I find Graffiti so relevant.

cztomsik commented 4 years ago

I think there being no audio API ...

Agreed.

On the flip side, I think first-class support for hot module reloading ...

Yes, something very simple is already there - you can see it in hackable-tv I've been trying different modules/approaches but it always had some issues here and there. It's probably not easy to make it work with all of the different transpilers and their plugins/configurations. It is definitely something I want to fix but I'm also thinking about providing some cli bin so you could gft run --watch myfile.js and it would simply forget everything except global object (and window) and node_modules and it would run the file again (no module.hot, no need to override require or anything like that, if you want to keep something, just put it to global). That way I think it might be possible to support React Fast Refresh too.

I'd much rather see just the delivery method abstracted away, so that if I'm building a Graffiti app which is local-first, and only incidentally accessible remotely via browser, I would have an iteration speed of e.g. 100ms vs of 1s (90% of which due to traversing the network stack to

100% agree, that's why that naive hmr.ts is there and why I was trying different modules (https://github.com/sidorares/hot-module-replacement worked the best but not so good with typescript and export * from ... and import { ... } from '.'). There are many gotchas.

But feel free to try it with your dothot (I'm not sure I was trying it)

Luckily I also have a big stash of unfinished side projects

This is great!

One last thing, have you seen Arcan? I see it as having some common ground with Graffiti, in terms of "indie project that attempts to get rid of all the accumulated cruft in the GUI stack". It has a bit more of a "kitchen sink" approach and "Unix greybeard" mentality I guess - which I totally admire, but I'm more comfortable with Rust, Node and the DOM as opposed to C, Lua and imperative drawing, which is one reason I find Graffiti so relevant.

Never heard about it but I'll have a look, thanks :)

nanfang2000 commented 4 years ago

I would like to run the React based GUI app on a cheap embedded device without the heavy of electron or chrome/webkit. my target device: 64MB storage and 64MB RAM on a 600Mhz ARM9 is that possible? Looking forward to your project to be light replacement of electron

cztomsik commented 4 years ago

64M storage should be fine but RAM might be tight depending on how big the screen is (framebuffer can take a lot) and how much mem pressure your js script is going to make. You will also need GPU with OpenGL 2.1 or GLES2 (at least for now)

I got it running (~59-60fps) on raspi zero w but that's 512M. There's also $5 version without bluetooth if you need real lowcost. Stay tuned, new version is around the corner (with support for CSS-in-JS frameworks)

nanfang2000 commented 4 years ago

Thank you @cztomsik ! I have a Allwinner ARM A7 SBC that has 128MB DDR, with GLES2, which I believe is easier to fit. Waiting forward to your project, well done!

jelemux commented 4 years ago

I'd like to build webapps that also run on desktop with Rust compiled to WASM and maybe vue.js client-side and preferably something like Rocket server-side. Would this be possible with graffiti?

One idea for a project that I have in mind would be an creator/editor for application letters and curriculum vitae that then generates and outputs a PDF with different styles and layouts.

cztomsik commented 4 years ago

Graffiti will always be just a subset of DOM/CSS so you'd need to only use what's supported but otherwise it should work. Currently, it's limited to inline styles only but it will eventually (life is sometimes hard & unexpected) support most of the CSS (probably excluding sibling selectors and some pseudo elements).

PDF would be possible but it's currently out-of-scope (everything is rendered directly to OpenGL)

If you need PDF, electron is still the best choice.

egasimus commented 4 years ago

@cztomsik What subset of HTML5 DOM API support is to be expected? Is there a foundational design document of some sort that determines the scope you are currently aiming to achieve?

Can I embed a video? Render SVG? Do I have Canvas? I know that at least some of those browser features are implemented in pure JS in Node-land so that could become part of the core Graffiti as the Rust equivalents mature (and someone does the assumedly non-negligible integration work?)

Can someone bolt a HTTP lib on to Graffiti, write a URL bar in HTML5 and make a browser? It runs WebRender under the hood, right - so can I just write in <MyComponent> tags that have no default behavior and define everything with JS (I'm presuming whatever engine you're embedding can handle anything sane I throw at it, I presume) and CSS (again, what subset, and what defines the subset, if it's based on WebRender?)

Never got beyond some hello world examples in a crazy Nix environment. But figured out that Nix the package manager (which you can get on any distro) has this crazy double #! trick where you can use Graffitti to write a GUI app in a single. fucking. file. (if it fits ofc, I'm emphasizing the lightness of boilerplate as compared to any GUI project even a Web/Electron app nowadays)

cztomsik commented 4 years ago

Never got beyond some hello world examples in a crazy Nix environment.

Wow, that looks really great!

What subset of HTML5 DOM API support is to be expected? Is there a foundational design document of some sort that determines the scope you are currently aiming to achieve?

no feature matrix for now, sorry... it's a moving target but the scope is:

Can I embed a video? Render SVG? Do I have Canvas? I know that at least some of those browser features are implemented in pure JS in Node-land so that could become part of the core Graffiti as the Rust equivalents mature (and someone does the assumedly non-negligible integration work?)

I'd like to do that eventually but it's rather going to be separate plugin

Can someone bolt a HTTP lib on to Graffiti, write a URL bar in HTML5 and make a browser? It runs WebRender under the hood, right - so can I just write in <MyComponent> tags that have no default behavior and define everything with JS (I'm presuming whatever engine you're embedding can handle anything sane I throw at it, I presume) and CSS (again, what subset, and what defines the subset, if it's based on WebRender?)

JoCat commented 3 years ago

Hello, I saw a mention in the GUI thread for Deno, I decided to take a look. I would like to create a lightweight client for the Minecraft game with simple customization using a web technology stack. I'm currently focused on Electron, but looking for better alternatives. At the moment I am using Vue. And in principle it would be nice to have access to basic stuff. 😅

cztomsik commented 3 years ago

This is from-scratch HTML/CSS engine so no canvas (yet), but there's WebView (macos-only for now) so you could do that. You might also have a look at tauri - but that's a bit different approach. Graffiti is just nodejs/deno module so it's one import and you have it. Eventually I want canvas but I need to work too so no promises :)

JoCat commented 3 years ago

ouch, I didn't put it right, I'm writing a launcher that launches the client in a separate process, in my case canvas is not required, at least for now))

cztomsik commented 3 years ago

oh, ok then that might be good fit for graffiti, you essentially just need to create index.html and one main.js file where you create window (like with electron) but it's still broken at least until weekend, sorry.

the previous version should work fine but api was different and now we have much better support for standards - it's already passing fraction of WPT

JoCat commented 3 years ago

Yes, I tried to run graffiti, but I ran into the same error as here #157 Well, I'm in no hurry anyway, so there is time)