B
B
Breezy
Search…
Philosophy

Inspired by Turbolinks

Breezy is inspired by Turbolinks. When you click on a link like this: <a href='/posts' data-bz-visit={true} />, Breezy fetches the next page's full content in JSON and swaps it with the current page JSON before handing it to your next React page component.

Pages not models

Breezy comes with a simple and denormalized Redux state. Each node in the store is a copy of your recently visited page in JSON. This concept is very similar to Turbolink's page cache, but Breezy exposes the pages to your Redux reducers to allow you to make optimistic updates.
For example, we can optimistically edit the header on the current and all previous pages using a reducer.
1
const applicationPagesReducer = (state = {}, action) => {
2
switch(action.type) {
3
4
case UPDATE_USER_HEADERS: {
5
const nextPages = { ...state }
6
const { email } = action.payload
7
8
for (const key in nextPages) {
9
if (nextPages[key].email) {
10
nextPages[key].email = email
11
}
12
}
13
14
return nextPages
15
}
16
17
default:
18
return state
19
}
20
}
Copied!

No APIs

There are no APIs to build. Instead, Breezy leans on Rail's ability to render different mime types on the same route.
In a Breezy application, you write your page's content in JSON using PropsTemplate, inject that state in HTML, and write your markup in JSX.
Here's how that looks:
1
MyRailsApp/
2
app/
3
views/
4
dashboard/
5
index.html.erb <- where index.json.props gets rendered as initial state
6
index.js <- Gets packaged with application.js
7
index.json.props <- will also respond to `.json` requests
Copied!
The routes remain simple:
1
resources :posts
Copied!
When a user clicks on a link enabled with Breezy's UJS:
1
<a href='/posts' data-bz-visit={true} />
Copied!
Breezy will specify the request's mime type as JSON, causing Rails to render index.json.props, and respond with the full page's JSON for your next page component to consume.

Make updates easy

Any part of your page can be easily updated in as little as a single line of code.
For example, here's how to refresh a chart with a button without any APIs:
1
<a href='/posts?bzq=data.dashboard.key_metrics_chart' data-bz-remote={true} />
Copied!
PropsTemplate powers this interaction. Any template you build with PropsTemplate is queryable using a param that you pass to the root node in your layout/application.json.props:
1
json.data(search: params[:bzq]) do
2
json.side_bar do
3
# gets skipped
4
end
5
json.dashboard do
6
json.key_metrics_chart do
7
#gets rendered
8
end
9
end
10
end
Copied!
When the server receives a request, it will query your template and fetch ONLY the data.dashboard.key_metrics_chart node without executing other nodes in your template.
Finally, Breezy on the client-side will receive the node, immutably graft it into your Redux state in the same exact path and hand it over to your component to render.
The syntax of bzq is a keypath, here's another example using an array:
1
<a href='/posts?bzq=data.post_list.0.title' data-bz-remote={true} />
Copied!
Read more about this in the querying guide

Embrace UJS

You may have noticed that we've been using data-bz-remote or data-bz-visit in the examples.
1
<a href='/posts?bzq=data.dashboard.key_metrics_chart' data-bz-visit={true} />
Copied!
Breezy embraces Unobtrusive Javascript. Any link or form with a data-bz attribute receives superpowers inspired by Rails data attributes.
For more advanced use cases, an action creator is passed to all your connected components when using the included React helpers
For example:
1
this.props.visit('/posts?bzq=data.dashboard.key_metrics_chart')
2
.then....
Copied!
Last modified 3mo ago