Use classic Rails to build rich React Redux applications with NO APIs and NO client-side routing.
Superglue makes React and Redux as productive as Hotwire, Turbo and Stimulus. Its inspired by Turbolinks and designed to feel like a natural extension of Rails. Enjoy the benefits of Redux state management and React components without giving up the productivity of Rails form helpers, UJS, tag helpers, flash, cookie auth, and more.
This project is in its early phases of development. Its interface, behavior, and name are likely to change drastically before a major version release.
Instead of APIs, Superglue leans on Rail's ability to respond to different
mime types
on the same route. In a Superglue application, if you direct your browser to
/dashboard.html
, you would see the HTML version of the content, and if you
went to /dashboard.json
you would see the JSON version of the exact same
content down to the footer.
The end result would be something like this:
Superglue leans on Rails. Features like the flash, cookie auth, and URL helpers continue to be useful. Here's a look at the directory structure of a typical Rails application with Superglue.
app/
|-- controllers/
|-- views/
| |-- dashboard/
| | |-- index.js # The React page component
| | |-- index.json.props # The json for the page component
| | |-- index.html.erb
Powering the JSON responses is PropsTemplate, a digable JSON templating DSL inspired by JBuilder. With PropsTemplate you can specify a path of the node you want, and PropsTemplate will walk the tree to it, skipping the execution of nodes that don't match the keypath.
Superglue comes with batteries that bring all the above concepts together to make building popular SPA features easy, painless, and productive.
A popular ask of SPAs is page-to-page navigation without reloading. This is easily done with Superglue's own UJS attributes inspired by Turbolinks:
<a href='/posts' data-sg-visit />
The above will request for /posts
with an accept
of application/json
, and
when the client receives the response, swap out the current component for the
component the response asks for, and pushState
on history.
Some features rely on updating some parts of the existing page. Imagine implementing type-ahead search. In traditional applications, you may need a new controller, routes, a discussion over versioning, JSON serializer, plenty of new JS code, etc.
With Superglue, this can be done with a simple onChange
const onChange = (e) => (
remote(`/dashboard?qry=${e.target.value}&props_at=data.header.search`)}
)
?> remote
and visit
is a thunk passed to every page component.
With props_at
, the above will make a request to /dashboard?qry=haircut
,
dig your template for the data.header.search
node, return it in the response,
and immutably graft it in the exact same path on the redux store before finally
letting React re-render.
For more on what you can do, check out our documentation.
Server-Side Rendering is supported via Humid. See the documentation for server-side rendering.
Documentation is hosted on Github pages.
Thank you, contributors!
Thanks to jbuilder, scour, turbolinks3, turbograft, turbostreamer