Show HN: Repaint – a WebGL based website builder (repaint.com)
It has panning, zooming, and dragging elements around. The settings closely follow html/css. We think an open canvas is a big improvement over other website builders. Everything is easier: styling, consistency, responsiveness…
But making it work was hard! We thought HN would appreciate the tech behind it: - A custom WebGL rendering engine (w/text, shadows, blurs, gradients, & opacity groups) - A partial implementation of the css spec - A custom text editor & text shaper - A transformer to turn designs into publishable html/css
Repaint is a design tool for html/css. But internally, it doesn’t actually use html/css itself. All your designs live in a single <canvas> element.
We wanted users to be able to see all their content on one screen. We target +60fps, so frames only have 16ms to render. The browser’s layout engine couldn’t handle simple actions, like zooming, with many thousands of nodes on the screen. To fix that, we wrote a rendering engine in WebGL.
Since we use custom rendering, we had to create a lot of built-in browser behavior ourselves.
Users modify a large dom-like data-structure in our editor. Each node in the document has a set of css-like styles. We created a layout engine that turns this document into a list of positions and sizes. We feed these values into the rendering engine. Our layout engine lets us display proper html layouts without using the browser's layout engine. We support both flex and block layouts. We already support multiple layout units and properties (px, %, mins, maxes, etc.).
We also can’t use the browser’s built-in text editor, so we made one ourselves. We implemented all the common text editor features regarding selection and content editing (clicking, selection, hotkeys, inline styling, etc.). The state consists of content and selection. The inputs are keystrokes, clicks, and style changes. The updated state is used to render text, selection boxes, and the cursor.
When you publish a website, we turn our internal document into an html document. We've intentionally structured our document to feel similar to a dom tree. Each node has a 1:1 mapping with an html element. Nodes have a list of breakpoints which represent media-queries. We apply the styles by turning them into selectors. All of the html pages are saved and stored on our fileserver for hosting.
We made a playground for HN, so you can try it yourself. Now that the tech works, we’d love feedback and ideas for improving the product experience.
And we’d love to meet more builders interested in the space. If that’s you, feel free to say hello in the comments! Or you can reach Ben from his website.
Playground: https://app.repaint.com/playground
Demo Vid: https://www.loom.com/share/03ee81317c224189bfa202d3eacfa3c3?...
Main Website: https://repaint.com/
Contact: https://benshumaker.xyz/
166 comments
[ 5.8 ms ] story [ 413 ms ] threadWe think our ux foundation is stronger. Many high-frequency actions are faster: moving between pages, copying content between them, multi-select editing. Especially if you're used to Figma. A lot of designers feel like Webflow is notoriously cumbersome to use.
But we also want to keep it very close to html/css. We think it's the only way too push power really far. Webflow did that. Framer's diverged quite a bit. We imagine it might go beyond a website builder to be a generally good "design tool for code"
When you explained how you had just reimplemented the CSS spec I was mindblown.
You guys rock. Repaint is amazing.
Your budget is only 8.33ms if you target 120hz too btw :) And realistically less because you don't get all of it.
I'm on S20 FE
Frankly, we've been very focused on making Repaint a great design tool to build websites and haven't thought about hosting that much.
Would you want to self host? Or maybe edit the code output?
As presented only makes sense for competing with Wix for power users.
But to the point, if my output is locked to the tool, I'm not going to use it. If I can get at least an uglified version of the source that I can host on my own Nginx, then it's a possibility, but not having at least that is a total deal breaker for me.
If you're talking about wanting to use this tool as a starting point for actual applications, then I would see why you'd need to export JS/React code.
Btw, your pricing is broken :)
Edit/addition: Congrats on your product! Always great to see a high-quality, pure software project get funded and realized. If I ever do YC (non-ivy so probably not in the cards) I'd probably do something like this.
Maybe one day :)
Repaint might be in some sense the bridge, though!
- No way to set defaults for new frames etc ( that I know of )
- Some things rely on mouse input (setting width modes etc) which breaks flow
- Generally not for power users
- No decent code export
- No stylesheets for retheming components /showing variation (I know there's a Variant workflow for it but it's not simple to restyle an entire hierarchy)
Would love to see you tackle those if you're not already. Great to see you following CSS more closely, makes so much sense.
But if you aren't allowing us to extract the code / self host then I'll be passing on it. Digital feudalism
Also congratulations on building a canvas engine library! Nothing is easy when it comes to canvas. Creating one for the WebGL canvas is magnitudes of more difficulty compared to 2D (which is what my library maps to).
I'd love to hear your horror stories when it came to coding up the text layout functionality and text editor - that is, in my view, the hardest part of the job: I may have invented a few new swear words while tackling that work.
I'd also be interested in your plans for accessibility. Not just making the tool accessible, but how such a tool may push designers to consider accessibility as a first class requirement for the end user in the projects they build with the tool.
Best wishes and great fortune!
Haven't planned accessibility help yet. But I think simple warnings could go far. When I break guidelines, it's usually by accident.
Every time I have to interact with font metrics data directly, I pour one out for IBM’s greatest and most tragic PC desktop OS.
https://faultlore.com/blah/text-hates-you
- import existing html/css. This would allow me to use it for non-greenfield projects, and allow for back-and-forth workflows.
- mark nodes with my own semantic ids that are included in the html export. I would use these to post process exported html to create dynamic templates/components/views. I don't want to be tied to a specific framework.
And congrats. I’ve dabbled a little in trying to use WebGL in places where DOM would the typical choice, and quickly ran away. :)
Here's the link: https://app.repaint.com/playground
Not sure what audience you have in mind.
The rendered pages have noticeable aliasing when zooming out in the playground. Is there a reason why the WebGL context isn't configured with anti-aliasing enabled?
Supersampling is easy to implement, just set the canvas size to a multiple of the viewport size and scale it down with CSS. It will help with all forms of aliasing, however it gets very slow very quickly. Shader aliasing is better solved analytically whenever possible.
One trick that you can use when aliasing is difficult to solve is to use supersampling but only when the scene is static. Google Maps WebGL does this. While you are dragging the map it is aliased. As soon as you stop dragging and the map becomes stationary, it renders 16 frames with subpixel offsets and blends them together to produce one supersampled frame (this is better than resizing the canvas because it can be interrupted in the middle if the user starts dragging again). This doesn't work for dynamic games but it might be suitable for your application with a lot of static content.
Now that I think about it, it may not work as well for your app as Google Maps. The thing about Google Maps is that when you zoom or pan the map the whole screen moves. In your app when you drag something, everything else remains static. The static items on screen will flicker between aliased and smooth whenever you drag something else. That will be distracting.
Ill definately be building something with this. Il give more detailed feedback after use - but from vid:
Have you used SPLINE at all and looked at their events menu system for anims in Spline (which BTW you should take a look at how to integrate and work with the Spline folks as their app would be an indeal way to make interactive 3d UI/X on this as well...
But also - (il test this,) but UI scaling for the windows to get them out of way given canvas, the ability to s=zoom a single element/page on the canvas?>
And the ability to float menu panels to a second screen? (I have a USb monitor on laptop, move all the menu panels to that usb monitor and have the canvas full screen laptop)
-Excited to try this out later today.
https://old.reddit.com/r/Spline3D/top/
I've never of a web app that lets you pull panels to a second screen. Sounds neat though. Is there a good reference?
This issue with this strategy is usually over reliance on 3rd party code that assumes that globalThis.window is the only window, and event handlers don’t end up working or something.
If you are using good libraries that really understand the DOM (React itself handles this well) or you write things yourself, it’s a bit of bother to add “target window” as a parameter to various functions that were previously using the global but quite doable.
I built an electron app that has one “root” window that is hidden that I use to spawn child windows without needing to load an entire new web page & instance of the JS bundle into each window. I used Tldraw and had to do some patch-package to fix global window assumptions in a few places.
Here’s my code: https://github.com/justjake/tlshot/blob/main/src/renderer/ed...
The video felt a little sped up. Not sure whether that's your natural talking cadence, or the video was 1.5x, but slightly slower would be great.
Also, at first the video focusses on the nerdy interesting things like fast pan & zoom, vs the things less-technically-inclined users would care about.
It's easy to go all out with a desktop design and discover it's not practical for a mobile view, nor is it easy to find ways to scale it down and have it make sense both aesthetically and technically for a smaller screen. On the other hand, it's not so difficult to start with limitations that can then scale out into something else as screen real estate allows.
Are these potential issues mitigated by how the tools allow you to layout and design things in Repaint?
Another thing, what are your plans around accessibility and semantics? How is the SEO for these sites? I noticed "Welcome to the Playground" in the playground is a p tag with an id. Almost everything is divs and p tags. Not to detract from what is clearly incredible software so far; you're all doing an awesome job. I'd be extremely happy with myself if I accomplished this.
edit: I ran a lighthouse test on the preview and I see the SEO and accessibility are higher than I expected. The performance score is excellent. The others aren't great, but they likely beat a lot stuff out there. I mean, visit any recipe website and weep for the modern internet.
edit edit: I'm realizing you could probably generate some decent document structure/semantics by having the user indicate the intent of some root items, like headers, subtitles, and sections. That's plenty to get some great meta and intent, right? You've got the hierarchy of the page, you can infer some info from properties of the containers and text, etc. There's a ton of potential to get excellent results here without too much knowledge or input from the users.
My totally unasked for suggestions:
We plan on giving the users control over what tag each element uses for SEO purposes (h1, section, etc.).
We have some SEO related settings that can be set (descriptions, title, etc.) and plan to add more.
This actually sounds like fun to implement. I suppose it should be opt-in, because some users genuinely won't care. And I imagine doing as much as possible by default would be ideal too, because this can turn into a huge chore which might make your product seem less efficient and convenient by no fault of its own.
This makes editing your content and navigating your project easier.
I was curious what your plans are for code output in the future, have you considered some kind of React integration? If this tool had Storybook-style codebase integration I would 100% pay for a subscription. For example, being able to export the website design as a React project with organized components, allow me to modify the component code to customize behavior, and continue to iterate on the design and apply changes to my codebase?
I think an important thing for me would be to have the ability to continue to modify the design after exporting and be able to apply the design changes without having to lose my code changes.
Obviously just my personal preference so take that with a grain of salt, but I know with that feature this would completely replace Figma in my workflow and would definitely be worth paying for.
Congratulations on your launch!
You're right about the exporting though. We're not sure exactly how to synchronize a code editor & Repaint editor for two way updates.
HTML/CSS support should just be another MIME type among many. Java Applets, Flash/Shockwave, PDF, Markdown, VRML-97, Quake .map, or whatever. Most sites would use one of the many stock renderer & runtimes. Some would implement their own, like your CSS reimplementation, as needed.
In other words, just skip the need for HTML shims.
Lastly, your efforts bring us that much closer to bringing us full circle. Next step: implement Wayland (and/or X11 if you're nostalgic).
https://ishoudinireadyyet.com/
https://github.com/w3c/css-houdini-drafts/blob/master/css-la...
I need to integrate a "site builder" for a landing page service. I cant use things like the other options out there because they require actually going to the site. It makes it useless where i want a fully self contained "builder" for a number (bunch) of different landing page domains.
I literally almost built this myself twice, and just never got around to it.