Railsdesigner iconRailsdesignerSep 24, 2026 ~6 min source read

Lazy loading, optimistic UI and more in Rails with Attractive.js

A summary of how Attractive.js 1.0.0 (pre-release) can power a Rails message board with no Stimulus or Turbo Streams: one partial drives initial render, optimistic previews, client/server validation, lazy loading, keyboard shortcuts, and a compact JSON actions protocol.

Lazy loading, optimistic UI and more in Rails with Attractive.js

Share this story

Send the public story page.

Useful takeaways from this story.

A single Rails partial powers initial rendering, optimistic previews, and lazy-loaded items via Attractive’s template-driven actions.

Lazy loading uses an in-view trigger to fetch batches and the server returns multiple actions to append data, update the loader, and set the next offset.

# What this is

This article explains how Attractive.js 1.0.0 (pre-release) can be used with Rails to build interactive HTML without writing custom JavaScript. The author built a simple message board that avoids Stimulus and Turbo Streams and relies on Attractive's extensions and a small JSON actions protocol.

# One partial, three uses

The app uses a single partial for a message item. That partial renders the initial page, is used as a cached for optimistic previews, and is cloned for lazy-loaded batches. Template fields are annotated with attract-field so Attract knows where to put server data when rendering the template client-side.

# Attract extension and the JSON actions protocol

Attract intercepts form submissions and issues fetch requests instead of traditional page reloads. The server responds with JSON containing an actions array. Each action describes a DOM mutation, for example:

  • append: clone a named template and append to a target
  • prepend: clone and insert before children of a target
  • replace: swap a target element with rendered template
  • before/after: insert relative to a target element
  • remove: delete element(s)
  • setStore and other state-related actions (via bundled Reactive store)

The same actions drive optimistic updates, lazy loading, and simple UI behaviors such as removing flash messages after a delay.

# Optimistic UI flow

When a user submits a new message, a cached template renders immediately as an optimistic preview while the server processes the request. The server then returns actions like updating a Reactive store value and resetting the form. In the demo, the create request purposely sleeps for a second so the optimistic preview is visible before the server response arrives.

# Client and server validation

# Lazy loading messages

# Keyboard shortcuts and small utilities

Attractive's keyboard extension wires keyboard shortcuts scoped to elements. Examples in the demo include meta+k to focus the filter, Escape to clear it, and meta+Enter to submit. The library also supports small action one-liners (js: prefix) and custom action registration for behaviors too small to warrant a full module.

# Hotwire

Attractive can be used alongside Hotwire or as a replacement depending on needs. It deliberately provides actions out of the box and an extensible interface so you can opt into only the pieces you need. The author mentions thinking about adding SSE support to broadcast actions to multiple clients in the future.

# Practical takeaway

If you want minimal JavaScript with declarative HTML-driven interactions in a Rails app, Attractive.js offers a compact pattern: templates + an actions JSON protocol + a small set of bundled extensions (attract, validate, keyboard, reactive). That covers optimistic updates, server-driven DOM changes, lazy loading, and keyboard shortcuts without Stimulus or Turbo Streams.

More context around this story.

Ractor-ready Rails, ordered cache fetches, and more!
Rubyonrails iconRubyonrailsSep 4, 2026

Ractor-ready Rails, ordered cache fetches, and more!

Originally appeared on Ruby on Rails: Compress the complexity of modern web apps . Hi, it’s Vipul . Let’s explore this week’s changes in the Rails codebase. Agents on Rails: Claude Fable 5.1 and GLM 5.3 Flash Claude Fable 5.1 matched Opus 5 at the top of the Agents on Rails leaderboard with 58 of 63 successful runs, wh

JSON schema cache, herb:check, and more!
Rubyonrails iconRubyonrailsSep 18, 2026

JSON schema cache, herb:check, and more!

Originally appeared on Ruby on Rails: Compress the complexity of modern web apps . A week of things that should just work: schema cache that loads in JSON, PostgreSQL names that resolve to one table, Active Storage that boots even when libvips is missing or too old, and Live responses that finally carry the default hea

Loading more related stories...

Keep reading in the app

Open the app view to save this story, compare related coverage, and continue from the same source.

Open in app