Show HN: An open-source, local-first Webflow for your own app (github.com)
I posted the repo a few months ago [1] when it was just 2 weeks old. Since then, we’ve made some big changes/improvements. I wanted to share some of the updates we’ve made and add more technical details. Here are the three big ones:
• Inserting new elements - Draw elements in the live page like a design tool and write them back to code. • Component detection - Detect when an element is a re-used component and find its usages. • DOM tree representation - A layers panel similar to the Chrome devtool or Figma.
Technical details [2]:
Visual editing - Onlook is technically a browser that points to your localhost running the app. It can manipulate the DOM like a Chrome Devtool, and all these changes are injected into the page through a CSS stylesheet or DOM manipulation. The changes are non-persistent until written to code.
Write to code - To translate the changes to code, we inject an attribute into the DOM elements at build-time that points back to the code like a source map. The attribute gives us the location of the code block, and the component scope [3]. We then find the code, parse it into an AST, inject the styles, and write it back.
Framework support - This technique is framework agnostic as we can swap in a different compiler for another framework [4]. It can work for any codebase as we’re just using open standards that don’t require any custom code. The code generated is written directly into your codebase, locally, so you can always take the output without being locked-in to the tool.
Actions - All the changes made are stored as actions. This allows them to be serialized, stored, and reproduced. We did it this way so eventually, we can introduce online collaboration or let an agent generate actions. To do this, we’d just need to serve the locally running page and resolve incoming actions.
What’s next?
It’s still a bit bare-bones but the support and suggestions from the HN and open-source communities have helped us a lot with our direction. Now that we’ve built the core engine, we can start doing some cooler visual builder features, fulfilling the “Webflow” part of our mission such as [5]:
• Detecting CSS variables in the page and letting you use them as “design tokens” in the UI. • Duplicating a page and A/B testing designs before committing to code. • Creating new components directly in the canvas. • Creating a front-end project from scratch using Onlook.
Some things we’re considering, but aren’t sure about yet:
• Offer hosting directly from the app. • Collaboration such as real-time edits, comments, and share page as a prototype.
I’d love to hear your thoughts/feedback. This project continues to be a blast to work on and the community response has been awesome. Thank you to everyone who has tried out and contributed to the repo :)
_________
[1] https://news.ycombinator.com/item?id=40904862
[2] https://github.com/onlook-dev/onlook/wiki/Architecture
[3] The attribute looks something like this:
data-onlook-id="eJxNjUEKwzAMBP+ic6gOKT3k2i+kDzC2aEwcKVgyDQT/vU5pS067sMvMDl6WVZjYYIC7y2GMlgg6IA6je8LAJaUOVmdTO+BDKSvOkWwSfEme1+Q8oXASmVGthCgYaBFFps3wT1csEX3jX0y3hldz2T6C/VAd4SWVhWG4dpAiUyt9/R7Pc/+b+1ut9Q33rUM5"
And decodes to this: {"component":"Dashboard","endTag":{"end":{"column":10,"line":620},"start":{"column":5,"line":620}},"path":"/Users/kietho/workplace/onlook/studio/demos/next/components...
52 comments
[ 3.1 ms ] story [ 164 ms ] threadKiet and I started working together in January to try to solve the design / dev handoff, and we think that this is a great first step to getting more people into code. People have mentioned that Onlook is a great complement to building frontends with Cursor, so if you’re just learning to code with Cursor, try running your projects locally with Onlook.
One thing I’d like to do is open-source our design system and make it easier for designers to contribute. If you have any suggestions or examples of projects that have done this well, let me know!
I’m hopeful that with the help of so many great contributors, we can make an editor experience that doesn’t compromise on the design / code experience!
I'm also curious how they determine where in source the code needs to change, because you could have (a) external stylesheets, (b) a stylesheet in the html head, (c) tailwind classes, (d) some css-in-js variant, or even (e) direct style application of dom elements in your javascript.
It does edit html. Inserting html elements in this case.
> I'm also curious how they determine where in source the code needs to change
Right now we're editing inline-tailwind because it's the easiest option. It only edits the existing tailwind styles so there could be some interaction with existing styles that have higher-priotity.
The plan later is to have users configure how they want their styles written. We have full code access to be able to edit css stylesheets or inject our own.
Chrome inspector does so much more like clip support and media queries that I didn't even know about. It also writes directly to inline styles so propagating those changes as code is definitely possible. I was thinking if there's a way we can leverage the great work the Chrome devtool have already put in.
I don't want to step on your toes by linking my own project, but essentially my idea is: the editor creates an object representation of the html/css which can then be transpiled into any framework the user wants (so long as there is an existing transpiler for it). Then the output could be hosted on npm or some other remote repository for the application repo to install.
Not at all, it's in good spirit! Happy to talk through any technical details from my side :)
> though if you try to listen for those changes with a mutation observer, it won't fire
It doesn't have to fire an immediate mutation imo. When you click on an element to edit, you could inject a data-attribute into it (not sure if the Chrome Devtool let you do this but an extension might). At write-time, you can query the elements that were marked, get the delta and write it to code.
You might've thought of this longer than I have so I think that might be a naive solution.
> can then be transpiled into any framework the user wants
You might be interested in Mitosis https://github.com/BuilderIO/mitosis
That was a pattern we initially went with but it adds some complexity:
The React compiler gives absolute paths, which we can adjust to relative paths by passing in the current process' running location into our plugin. This makes the plugin API more complex. We'd also have to track the project's relative path at runtime and concat it back.
We decided the extra characters were worth it to eliminate the extra complexity. I do realize that the character number scales with the path + complexity of the project.
> JS had access to gzip (or zlib)
I haven't looked at this but will give it a try. We're doing some compression here but there's also a performance hit for compressing too much at build time.
I do think we can save space by using a different format than JSON. Even just a raw string. Something like: 'path/to/file:startTag:start:line:col:...'
If I were to ask: why use Onlook over Devlink what would your answer be?
However, you're still locking into a WebFlow project. You can export a DevLink component out and then migrate it back in. You also have to instrument the weblink component.
With Onlook, there's no new environment. Your code is just running in localhost in your project. No import export and no extra code just to develop a new component.
We had to focus on React for various reasons [2] but I'd really like to support Svelte again
[1] https://github.com/onlook-dev/chrome-extension/tree/main/plu...
[2] https://news.ycombinator.com/item?id=40904862
The video needs work; the main risk perceived will be to have bad design applied and not be caught. The video is basically a demo of that scenario.
For monetization we'd like to keep the editor free for people to use and may monetize through add-on services like hosting. The way I like to think about it is that we may monetize on convenience points but keep things open-source so if you wanted to do things custom, then you can if you'd like.
On the video – thanks for the note there! We can certainly show it to do something more detailed as well than just a background color change. The good thing is that any designs done with Onlook still go through the usual code review process for any project, so hopefully people won't accept non-compliant design changes. In the event that they do, it'll be easier to fix things with Onlook.
On the lines of keeping things compliant with design systems, I'm excited about our ability to surface design tokens from a codebase, so users can always be sure they are selecting the right colors in the right scopes. That's something we still have yet to tackle, but have an open issue for:
https://github.com/onlook-dev/onlook/issues/49
Thought theoretically, you could write a parser to add the necessary information to the HTML tags at "build time"
Onlook has less abstraction between code and the visual editor. It works with your existing React codebase with no migration. Everything is written into code in real-time so you wouldn't import or export the code from Onlook. You can use it anytime and stop anytime like an IDE.
Does this make sense? I'd love to hear Oleg's thoughts on this as well :)
It is achieved by using data as a source of truth, not the code. Web tooling is very fragmented. People have too many opinions on how to write components and that makes it nearly impossible to have components written by hand and then synced back into the UI without enforcing a huge amount of constraints. You will end up writing code in such a way that the UI can handle.
[1] https://github.com/onlook-dev/onlook/issues/247
I'm a product designer turned web dev, and I work extensively with Nextjs, Tailwind, and Shadcn/ui.
I love the idea of being able to visually edit my webapp and port them back to code seamlessly. I was hoping you could help me understand the following
- How does Onlook compare with Webflow's devlink and Webstudio? Honestly Devlink seems dead to me, Webstudio seems promising but doesn't look like they prioritize react nor tailwind
- Can I use onlook in a Nextjs project with Tailwind? Will the visual edit reflects in Tailwind classes' updates?
- Will there be issues with "use client" or "use server" components as I read there were with Devlink?
- I'm building out of a turbo monorepo, how will this work? Do I just cd apps/my-nextjs-app and run npx onlook?
- How does this work with Shadcn/ui? If I update a component in the visual editor, I'm assuming it will change the tailwind className from app/components/ui?