DEV Community

Cover image for Introducing the new Community Dashboard on TailView.work
Harsh patel
Harsh patel

Posted on

Introducing the new Community Dashboard on TailView.work

We just shipped a brand‑new Community Dashboard on TailView.work—purpose‑built for Rails developers who want a fast, modern, and accessible social surface without pulling in a front‑end megaframework. It’s powered by Tailwind CSS, Hotwire (Turbo + Stimulus), and real‑time updates via ActionCable.

TL;DR

  • Built with Rails 7+, Tailwind, Turbo, Stimulus, and ActionCable
  • Real‑time feed: new posts appear instantly without page refresh
  • Clean, focused UI with native <dialog> and <details> for accessibility
  • Thoughtful UX: keyboard‑first, high‑contrast states, reduced JS complexity
  • Production‑ready patterns you can copy into your app

Why this dashboard?

Rails teams told us they needed:

  • A real‑time, low‑friction place to share what they’re shipping
  • Zero‑build, no‑webpack front‑end they can actually maintain
  • An interface that feels modern but stays accessible and fast

So we designed a dashboard that feels native to Rails: no client‑side routing, no hydration ceremony—just HTML over the wire and subtle animation where it helps.

What’s new

  • Real‑time feed
    • New discussions prepend instantly via Turbo Streams
    • Lightweight “highlight on arrival” animation for context
  • Smart filtering & topics
    • Filter by latest activity, most appreciated, most discussed, or relevance
    • Topic browsing with native <details> for predictable keyboard behavior
  • Composer that doesn’t fight you
    • Native <dialog> for the modal, so ESC, focus trapping, and backdrop “just work”
    • Clear copy and labels; field states and errors are visible and friendly
  • Presence panel
    • See who’s currently active—live, with gentle motion and minimal noise

UI/UX decisions that matter

  • Use the platform: native <dialog> and <details> replace heavy JS and improve accessibility out of the box.
  • Motion with meaning: we highlight just‑arrived items and keep transitions short and subtle.
  • High‑signal affordances: “Share”, “New discussion”, and filters are prominent; destructive actions are de‑emphasized.
  • Mobile‑sane by default: chips for topics, condensed headers, and large tap targets.

The stack (and why)

  • Tailwind CSS: utility‑first, consistent spacing/typography, tokens you can reason about.
  • Turbo Streams: real‑time, server‑rendered HTML—no client state to sync.
  • Stimulus: sprinkle‑sized behavior; controllers are tiny and composable.
  • ActionCable: stable, framework‑native websockets.

A few patterns you can reuse

Render and stream updates (server → clients):

# app/services/community/feed_broadcaster.rb
Turbo::StreamsChannel.broadcast_prepend_to(
  "community_feed",
  target: "community_discussions",
  partial: "community/discussion",
  locals: { discussion: discussion, highlight: true }
)
Enter fullscreen mode Exit fullscreen mode

Turbo Streams subscription in your view:

<%= turbo_stream_from "community_feed" %>
<ul id="community_discussions">
  <%= render partial: "community/discussion", collection: @discussions %>
</ul>
Enter fullscreen mode Exit fullscreen mode

A tiny Stimulus controller for “copy share link”:

// app/javascript/controllers/share_link_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["tooltip"]
  static values = { url: String, timeout: Number }

  copy(e) {
    e.preventDefault()
    navigator.clipboard?.writeText(this.urlValue)
      .then(() => this.show())
      .catch(() => this.fallback())
  }

  fallback() {
    const ta = document.createElement("textarea")
    ta.value = this.urlValue
    ta.style.position = "fixed"; ta.style.left = "-9999px"
    document.body.appendChild(ta); ta.select()
    document.execCommand("copy"); document.body.removeChild(ta)
    this.show()
  }

  show() {
    this.tooltipTarget.classList.remove("opacity-0")
    this.tooltipTarget.classList.add("opacity-100")
    clearTimeout(this.t); this.t = setTimeout(() => {
      this.tooltipTarget.classList.add("opacity-0")
      this.tooltipTarget.classList.remove("opacity-100")
    }, this.timeoutValue || 2000)
  }
}
Enter fullscreen mode Exit fullscreen mode

Composer with a native dialog:

<dialog data-controller="community-composer-modal"
        data-community-composer-modal-target="dialog"
        class="fixed inset-0 m-auto h-fit w-full max-w-3xl rounded-3xl bg-white p-0 shadow-2xl backdrop:bg-gray-900/70">
  <%= render "community/composer", communities: @communities, topic: @topic %>
</dialog>
Enter fullscreen mode Exit fullscreen mode

Try it, copy it, ship it

The Community Dashboard is live on TailView.work. If you’re building Rails apps with Tailwind and Hotwire, you can lift the patterns directly: streams for real‑time UI, native HTML for modals/accordions, and Stimulus for tiny, testable interactions.

Questions or suggestions? Start a discussion on the new dashboard and show us what you’re shipping.

Top comments (0)