Styling — Dark Theme
Website Rebuild with Ruby on Rails
Chapter 5 · Styling — Dark Theme
Three siblings, three positions on asset bundling: Next.js bundles by mandatory framework design, Django ships nothing at all, Laravel pre-wires an optional bundler (Vite) without being one itself. Rails 7+ reaches a fourth position that isn't just another point on the same spectrum — it's a deliberate attempt to avoid needing a JavaScript bundler in the first place.
Propshaft: Fingerprinting, Not Bundling
Rails 7.1+ defaults to Propshaft as its asset pipeline — a genuinely minimal one. Propshaft doesn't compile Sass, doesn't transpile anything, and doesn't bundle multiple files into one. It does exactly one job: it fingerprints static asset files with a content-based digest for cache-busting, and serves them. Any real compilation this site's own assets might need is delegated to separate, opt-in tools — not baked into the default pipeline the way Next.js's bundler is baked into that framework.
app/assets/stylesheets/application.css holds this site's own dark theme — plain CSS, no preprocessing needed for it, so Propshaft's own "just fingerprint and serve" behavior is already the entire pipeline this chapter requires.
Importmap: No Bundler for JavaScript, Deliberately
javascript_importmap_tags renders a browser-native <script type="importmap"> block, mapping bare module names to real file URLs — resolved directly by the browser's own native ES module support, with no bundling step running anywhere, in development or production. app/javascript/application.js holds this site's own copy-to-clipboard script, the same small enhancement used throughout every other course on the site, needing nothing more than what the browser already provides.
jsbundling-rails) rather than a default assumption. That's a genuinely different starting philosophy, not a fourth data point on the same spectrum.
Four Positions on Asset Bundling
| Next.js | Django | Laravel | Rails | |
|---|---|---|---|---|
| Default JS pipeline | A bundler, mandatory | None | Vite, pre-wired but a real bundler | Importmap — no bundler at all |
| Node/npm required? | Always | Never (nothing built in) | Yes, for npm run build | Not for the default case |
| CSS handling | Bundled with the build | Served as-is via collectstatic | Bundled via Vite | Fingerprinted and served by Propshaft, no processing |
bin/rails assets:precompile runs Propshaft's own fingerprinting during deploy, with no separate JavaScript build pipeline to coordinate.
Hands-On Exercises
Explain what Propshaft actually does — and, just as importantly, what it deliberately doesn't do — compared to a real bundler like the one built into Next.js.
📄 View solutionExplain how Importmap resolves a JavaScript module without a bundler, and why this is described in this chapter as a philosophical position rather than just a fourth entry on the same spectrum as Next.js, Django, and Laravel.
📄 View solutionExplain why this course's own dark theme CSS needs nothing more than Propshaft's default fingerprint-and-serve behavior, with no preprocessing step involved.
📄 View solutionChapter 5 Quick Reference
- Propshaft — Rails 7.1+'s default asset pipeline: fingerprint and serve, no compilation or bundling
stylesheet_link_tag "application"— renders the fingerprinted CSS link tag- Importmap — browser-native ES module resolution, no bundler required for the default case
javascript_importmap_tags— renders the native<script type="importmap">block- A genuine fourth philosophy — not "bundle by default," "nothing built in," or "bundler pre-wired," but "avoid needing a bundler at all"
- Next chapter: The Database: ActiveRecord ORM