Brian Lovin
/
Hacker News

Show HN: Puck – Open-source visual editor for React

github.com

Hey hackers, OP here!

I've been dipping in and out of this problem space for the last few years with many of my clients.

Puck sits somewhere between an old-school WYSIWYG-powered CMS and headless one, allowing content teams to author content using real React components.

Traditional CMS solutions were flexible but often resulted in page that completely broke the brand guidelines. Headless CMS solutions are a fantastic way of controlling brand by restricting UI changes to developers, but makes layout changes restrictive and slow as developers often need to get involved.

Puck provides a visual editor for React that can sit on top of your existing headless CMS (or act as standalone). We've been dog-fooding it on a few pages at https://measured.co and on https://wellpaid.io. So far, so good

The API is built for React, which allows FE devs to quickly integrate their existing component and add some form fields for author input, or connect it to a headless CMS of choice.

It's open-source under MIT, and pairs nicely with Next.js (check out the demo application). Next in the pipeline: support for multi-column layouts, richer demos, new plugins.

Looking forward to hearing your comments!

Daily Digest email

Get the top HN stories in your inbox every day.

simonw

Wow, I've seen so many of these kinds of things over the years but this one is really special: extremely intuitive design, really powerful and flexible, and MIT licensed too. Super impressed.

chrisvxd

This comment made my day. Thank you

Exuma

Awesome. I've literally been tasked with building something exactly like this, and it's a pain in the ass nothing exists like this for Vue so I have to do it from scratch.

I plan to make it more like builder.io/demo however where CSS can be arbitrary, that way basic landing pages can be built.

Do you have any tips of things you wish you did differently, or what was more painful than you expected, as well as anything that might help in this?

chrisvxd

It's such a common problem, I'm amazed there aren't more solutions out there.

A sound data model really helps things out. I'd go API-first.

Drag and drop is a PITA. Specifically multi-column layouts, which require nested dropzones and a bunch of "intuitive" UX. A good library can help here, but not do everything (we're using react-beautiful-dnd which is a bit out of date - dnd-kit might have been a better shout). This hasn't landed in our main branch yet, but you can see it under the nested-dropzones branch (https://github.com/measuredco/puck/tree/nested-dropzones).

If you could write React wrappers for your Vue components, you could potentially leverage Puck directly. That would save a lot of time. And even if not, you might be able to fork it or reuse the data model.

Happy to give you more pointers. If you want to DM, I'm @chrisvxd on Twitter/GitHub and here's my LinkedIn: https://linkedin.com/in/chrisvilla/

jcuenod

I just published a dnd library for nested tree structures (https://www.npmjs.com/package/vue-tree-dnd), and I can't believe how much of a PITA dnd is! Working on browser-compatibility took me back to pre-jquery days...

Exuma

Interesting.. do you think it's a good use case for a drag an drop editor compared to other DND out there?

agotterer

If you're open to hosted service, is the best commercial visual + headless CMS I've come across that supports React - https://www.storyblok.com/home.

Exuma

Does it allow embedding in an actual app? Thats the problem I have with these is they all require some weird form of going to their domain. I need the editor (AND the rendered page) to be 100% on my own domain. I wish they had some editor as an open source library and id just pay to have an API key or something

satvikpendem

Are there more details on the data model? I'm actually building something like this but not for React, so it might be useful to reuse the data model as you say.

chrisvxd

The data model is detailed here in the docs: https://github.com/measuredco/puck#data

There's not an awful lot to it.

mattront

Take a look at the Vue Designer [0] (it is our app), an editor that let's you visually build Vue projects, not just using existing components. You can even build components with the editor.

[0] https://vuedesigner.com

showerst

Take a look at grapesjs -- it's a bit janky in places but it's self hosted and overall works pretty well. It can output plain HTML so I think it could be integrated with vue.

Exuma

The problem with that one is I want to completely avoid parsing/rendering HTML. That creates huge headaches when you want to create some kind of "component" but then once the html is rendered, it cant be re-parsed into its original state without adding a bunch of junk to it, like helper classes etc. It's just very brittle for what I want to do

wbarber

Plasmic.app works with vue - why not just use that?

Exuma

This was what I said previously, which I'm assuming plasmic doesnt do:

> Does it allow embedding in an actual app? Thats the problem I have with these is they all require some weird form of going to their domain. I need the editor (AND the rendered page) to be 100% on my own domain. I wish they had some editor as an open source library and id just pay to have an API key or something

2pointsomone

This is just so fantastic, I have been looking for something like this for the open-source edtech app builder Flow (https://github.com/opencurriculum/flow) for the past year! Talked to the WebStudio guy and did so much research, but nothing was just right. This feels JUST. RIGHT.

Thank you for all the hardwork!

2pointsomone

Btw, a very easy big win for you would be to port the side styles/interactions panel of WebStudio into this. And by port I mean extracting the code to make a common open-source library with the correct license and putting it in Puck.

chrisvxd

Great idea - could add this as a core field type so you can use it via the fields API, i.e. `{ type: "css", cssProperties: ["color"] }`

chrisvxd

Oh, awesome. Let me know how you get on!

zoogeny

This looks decent and the idea is sound. I was looking at headless CMS recently and it only vaguely struck me that what is needed is the front-end builder component.

Looking at the comments from the dev in this thread it seems this really only supports vertically stacked layouts right now? At least the demos were responsive but each component seems to assume that it fills the width of the screen. Making responsive components in a columnar layout might be more challenging for this kind of toolset to handle.

Looking at the recipe for next.js app I noticed that the component where the page is rendered appears to be in `[...puckPath]/client.tsx` which is a "use client" component. That makes me wonder about the entire framework and whether or not it actually renders the pages on the client or the server.

If those two things are true then this might have limited application. Finding a way to handle responsive layout for columnar and/or grid based pages will be non-trivial. Finding how to mix server and client components effectively will be non-trivial.

That aside, it seems useful and decently structured. In places where we I've worked where there is a lot of customization desired, having a UI builder that customizes page layout in some data format (json or xml) has been very helpful.

mono_spaced

Scott from Measured here, we're dog-fooding puck on https://measured.co.

There's a WIP branch with support for more sophisticated layouts here: https://github.com/measuredco/puck/tree/nested-dropzones

And I think `use client` is a Next 13 thing. Not sure of the details, but Puck definately does render server-side.

chrisvxd

+1 what Scott said

Multi-column layouts are incoming very soon

And Puck does support either server or client rendering

p2hari

Just love this. And trust me, I have seen many of these kinds , but this is really different in the right sense. So easy to add custom components and get going. Well done. Will definitely try more. Thanks for this.

chrisvxd

Thank you!

talboren

looks awesome, a small screenshot in your readme would have helped understand that it's more of a drag and drop component

talboren

"open source visual editor" doesn't really comply with "The self-hosted drag and drop editor for React."

chrisvxd

Hey, thanks for the feedback! We're still figuring out the wording and will take this on board.

MuffinFlavored

I would've expected some kind of WYSIWYG functionality for "make this API call and map the fields/properties of the response into the components"

Like on the demo where it says https://puck-editor-demo.vercel.app/edit Users Reached 20M+, I thought instead of static text, it would've shown some kind of {{template}} that shows JSON query format like `jq` does to pluck fields from arrays/objects of fetch() response bodies (how React would pass along props/state)

chrisvxd

We don't natively support templating strings, but since it's rendered by React, you can always add that when integrating Puck.

However you can use an adaptor if you need to pull data in via a third party API: https://github.com/measuredco/puck/tree/main/packages/adapto...

MuffinFlavored

I was trying to give feedback on how you might make your product "more attractive"/increase value proposition to the type of person you are aiming to help this with: people who want to make a React UI through a GUI instead of in a text editor.

I know how to pull data in via React/JavaScript "code". If I can do that, I'm technical enough to not need a GUI to help me make a UI... do I?

mono_spaced

Not the OP, but our company Measured is building Puck as an open source project, so I'll try and answer.

Puck is targetted at content/CMS use cases, rather than general UI building. So the ability to establish guardrails in the editor experience is intentional. For best effect, we envisage Puck being used alongside a well-considered library of on-brand composable components. The aim is to enable non-developer editors/authors to freely update and build content, whilst keeping the UI consistent and on-brand.

This is a problem area we've encountered many times in our client work, hence why we wanted to scratch this itch.

Having said that, I do believe the Puck editor GUI _can_ be configured to work with remote data somewhat as you describe, using the adaptor linked above (but there's currently no demo for this feature).

bingemaker

Even if you are technical enough, you might still need a GUI to avoid any surprises. Also the end user of this tool is not tech people, but content managers

nathancahill

How do you keep the saved data props/values (title, description) in sync with the component props in the code? Let's say I change `description` to `subtitle` in the code, what happens to that information?

chrisvxd

I just re-read your comment and realised I didn't answer it first time around.

The best way to handle this is in the render function you pass to Puck, which can continue to support the old prop (`description`) and map into the new prop (`subtitle`), even if it's not provided by the author.

We don't have a system for migrating props in the actual data yet, but it's something we could look into.

chrisvxd

Tracking this here, with proposal: https://github.com/measuredco/puck/issues/41

chrisvxd

We let the user decide how they want to store the data via the `onSave` and `onChange` callback props you provide to the `<Puck>` component. So you would likely save to your own database in the callback.

The data shape is detailed here: https://github.com/measuredco/puck#data

nathancahill

I'm trying to understand if the layout immediately becomes brittle once the data is saved (unless someone goes in to the saved data and patches it by hand when the layout is updated).

chrisvxd

Sorry I got the wrong end of the stick. Please see my other reply to your comment.

satvikpendem

This is exactly what Framer did before pivoting to a website builder, it might be worth looking into them. How will you be different than them?

chrisvxd

Framer is a design tool, but Puck is a content tool. We're focused on allowing content teams to create pages using existing on-brand components. Like a WYSIWYG with guard-rails.

We built it because we couldn't find something that would let our clients' content teams produce content for their sites without 1) either going off-brand or 2) pestering their devs for layout changes.

teddarific

Can you elaborate what you mean by "content" tool? Are your ideal users creating marketing sites, blog posts, or other?

In my experience, most of what content teams work with are some forms of CMS, and the design tools usually deal with layout and creating generic sites that work with the data structure inside the CMS.

chrisvxd

Typically marketing sites and blog posts etc. It could probably be extended to applications, but that’s not what we built it for.

satvikpendem

Framer also has a CMS and you can import React components [1]. They pivoted because there wasn't much traction in that use case.

[1] https://www.framer.com/developers/#overview

danr4

your pivot comments seem irrelevant as he is not selling this as a product, he is using it as a white-label solution for his clients.

jameslk

Nice, this looks pretty good.

It's always been my dream of having something like Retool, but using your own components and completely open source. Retool is a backend layer too, so that's partially what's missing to complete the picture. But if we had that as something like a framework, we'd start getting close to the days of drag-and-drop UIs.

d0100

Can I make my own prop editor?

Ex. instead of an input for the prop `name` I want a picker that fetches data from some API

chrisvxd

You can use adaptors for this. Adaptors let you request a third party API via the `adaptor` field type.

Docs are limited, but there's a reference data shape here: https://github.com/measuredco/puck#adaptor

Example implementation here: https://github.com/measuredco/puck/blob/main/packages/adapto...

Example usage here: https://github.com/measuredco/puck/blob/main/apps/demo/app/c...

You can either use it for a specific prop (i.e. `name`) or spread the result of the API call across your entire component (use the magic `_data` prop).

undefined

[deleted]
Daily Digest email

Get the top HN stories in your inbox every day.

Show HN: Puck – Open-source visual editor for React - Hacker News