diff --git a/_data/reference_apps.yml b/_data/reference_apps.yml new file mode 100644 index 00000000..c8aaf229 --- /dev/null +++ b/_data/reference_apps.yml @@ -0,0 +1,37 @@ +# Reference Apps — a curated library of exemplary open-source Rails apps. +# +# The bar for inclusion is intentionally high. An app belongs here only if it +# is worth reading to learn how a real, production-quality Rails app is built: +# +# * Open source under a permissive license, with a public repository. +# * Idiomatic, modern Rails — a strong example of the conventions and tools +# the framework encourages today. +# * Actively maintained, or a complete and self-contained reference. +# * Substantial enough to teach something, but readable end to end. +# +# To propose an app, open a pull request adding an entry below. Keep blurbs to +# a single sentence and limit tags to the 2-3 patterns the app best +# demonstrates. Entries render in the order listed here. + +apps: + - name: Campfire + by: 37signals + blurb: A complete, real-time group chat app — a compact masterclass in server-rendered Hotwire and lean, dependency-light Rails. + tags: [Hotwire, Turbo Streams, Action Cable] + repo: https://github.com/basecamp/once-campfire + screenshot: /assets/images/reference-apps/campfire.webp + + - name: Writebook + by: 37signals + blurb: A self-hosted platform for publishing books on the web, showcasing clean model design, Active Storage, and rich text editing. + tags: [Active Storage, Action Text, Auth] + repo: https://github.com/basecamp/writebook + screenshot: /assets/images/reference-apps/writebook.webp + + - name: Fizzy + by: 37signals + blurb: A Kanban board reimagined — drag-and-drop boards built with modern Hotwire patterns and crisp, RESTful controllers. + tags: [Hotwire, Stimulus, RESTful design] + repo: https://github.com/basecamp/fizzy + screenshot: /assets/images/reference-apps/fizzy.webp + diff --git a/_pages/docs.html b/_pages/docs.html index 93765835..748c8375 100644 --- a/_pages/docs.html +++ b/_pages/docs.html @@ -93,7 +93,7 @@

Read the guides

Dive Deeper

-
+
+ +
diff --git a/_pages/reference-apps.html b/_pages/reference-apps.html new file mode 100644 index 00000000..5b91f287 --- /dev/null +++ b/_pages/reference-apps.html @@ -0,0 +1,89 @@ +--- +title: "Reference Apps — Ruby on Rails" +description: "A curated library of exemplary open-source Rails apps, hand-picked to show how real, production-quality Rails applications are built." +permalink: /docs/reference-apps +redirect_from: + - /docs/reference-apps/ +--- + +
+
+
+
+

+ Learn from real,
+ open-source Rails apps. +

+

+ A small, hand-picked library of exemplary open-source apps worth + reading to see how production-quality Rails is built today. +

+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+

About this library

+

+ This is a curated library, and the bar for inclusion is intentionally + high. An app is listed here only if it is open source under a + permissive license, written in idiomatic and modern Rails, and worth + reading end to end to learn how a real, production-quality Rails + application is built. +

+
+
+
+
diff --git a/_sass/modules/_cards.scss b/_sass/modules/_cards.scss index b696a972..18eba94c 100755 --- a/_sass/modules/_cards.scss +++ b/_sass/modules/_cards.scss @@ -363,6 +363,12 @@ margin-left: 60px; margin-right: 60px; + &--docs-dive-deeper { + .card:last-child:nth-child(3n + 1) { + grid-column: 2; + } + } + &.card__fullwidth { // This is handled in the specific fullwidth section above .card { diff --git a/_sass/modules/_reference-apps.scss b/_sass/modules/_reference-apps.scss new file mode 100644 index 00000000..cd2734cb --- /dev/null +++ b/_sass/modules/_reference-apps.scss @@ -0,0 +1,128 @@ +// Reference Apps library — an image-led variant of the docs card grid. +// The default docs cards are fixed-height, centered, and absolutely +// positioned; these cards lead with a screenshot and size to their content. +.reference-apps { + // Breathing room between the heading/subtitle and the grid. Cards stretch + // to equal height per row (default align-items: stretch); the tags are + // pushed to the bottom of each card so rows stay tidy. + .cards__container { + margin-top: 50px; + } + + .card { + height: auto !important; + max-height: none !important; + + a, + .card__body { + position: static; + height: 100%; + } + + // Keep the author eyebrow legible on hover (the base card turns + // .card__label h6 red, which would hide our red-on-transparent text). + a:hover .card__label h6 { + background: transparent; + } + } + + // Image flush to the card edges; overflow:hidden clips it to the + // rounded top corners. Content padding lives on the text wrapper. + .card__body { + align-items: stretch; + height: 100%; + overflow: hidden; + padding: 0; + } + + &__shot { + aspect-ratio: 16 / 9; + background: $color-grey-1; + border-bottom: 1px solid rgba($color-black, 0.08); + display: block; + object-fit: cover; + object-position: top center; + width: 100%; + } + + &__text { + box-sizing: border-box; + display: flex; + flex: 1 1 auto; + flex-direction: column; + padding: 25px; + text-align: left; + width: 100%; + } + + // Author eyebrow — restyle the floating red badge as inline red text. + .card__label { + margin-bottom: 6px; + position: static; + width: auto; + + h6 { + background: transparent; + color: $color-red; + letter-spacing: 0.1em; + padding: 0; + + &:after { + display: none; + } + } + } + + // Neutralize the base card's 30px side margins and vertical padding so + // the headline and blurb align flush with the eyebrow and the wrapper's + // own 25px padding. + .card__headline, + .card__content { + margin-left: 0; + margin-right: 0; + } + + .card__headline { + padding-top: 0; + + h3 { + margin-left: 0; + margin-right: 0; + } + } + + .card__content { + display: flex; + flex: 1 1 auto; + flex-direction: column; + padding-bottom: 0; + + p { + margin-left: 0; + margin-right: 0; + } + } + + // Scoped under .card__content to override the default + // `.cards .card__content ul { list-style-type: disc }` rule. + .card__content ul.reference-apps__tags { + display: flex; + flex-wrap: wrap; + gap: 8px; + list-style: none; + margin-top: auto; // hug the bottom of the card + padding: 18px 0 0; // guaranteed gap above the tags + + li { + background: rgba($color-black, 0.05); + border-radius: 3px; + color: $color-grey-5; + font-size: 12px; + font-weight: 600; + letter-spacing: 0.04em; + line-height: 1; + padding: 6px 10px; + text-transform: uppercase; + } + } +} diff --git a/assets/css/style.scss b/assets/css/style.scss index bd45bd4d..2a0bd6ba 100755 --- a/assets/css/style.scss +++ b/assets/css/style.scss @@ -39,6 +39,7 @@ @import "modules/nav"; @import "modules/notification"; @import "modules/post"; +@import "modules/reference-apps"; @import "modules/text"; @import "modules/trusted"; @import "modules/video"; diff --git a/assets/images/reference-apps/campfire.webp b/assets/images/reference-apps/campfire.webp new file mode 100644 index 00000000..4be22ca4 Binary files /dev/null and b/assets/images/reference-apps/campfire.webp differ diff --git a/assets/images/reference-apps/fizzy.webp b/assets/images/reference-apps/fizzy.webp new file mode 100644 index 00000000..759d9962 Binary files /dev/null and b/assets/images/reference-apps/fizzy.webp differ diff --git a/assets/images/reference-apps/writebook.webp b/assets/images/reference-apps/writebook.webp new file mode 100644 index 00000000..62cd1679 Binary files /dev/null and b/assets/images/reference-apps/writebook.webp differ