RFC: Complete redesign of mruby.org — new visual identity, Jekyll 4, automated data pipeline, and CI-driven deployment#262
RFC: Complete redesign of mruby.org — new visual identity, Jekyll 4, automated data pipeline, and CI-driven deployment#262pusewicz wants to merge 39 commits intomruby:masterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR modernizes mruby.org with a full visual redesign, a new SCSS-based design system, and an automated build/deploy pipeline that generates site data (releases, contributors, mgems, API docs) at build time and deploys via GitHub Actions.
Changes:
- Replaced Bootstrap-era markup/styles with a new SCSS design system and updated layouts/includes.
- Removed committed generated API docs and introduced Rake tasks to regenerate docs + data during builds.
- Added GitHub Actions Pages workflow and updated Ruby/Jekyll-related project plumbing (Gemfile, .ruby-version, README).
Reviewed changes
Copilot reviewed 50 out of 173 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/api/FileTest.html | Removes committed generated YARD API HTML (now generated at build time). |
| docs/api/File/Constants.html | Removes committed generated YARD API HTML (now generated at build time). |
| docs/api/Fiber.html | Removes committed generated YARD API HTML (now generated at build time). |
| docs/api/FalseClass.html | Removes committed generated YARD API HTML (now generated at build time). |
| docs/api/Exception.html | Removes committed generated YARD API HTML (now generated at build time). |
| docs/api/Enumerator/Yielder.html | Removes committed generated YARD API HTML (now generated at build time). |
| docs/api/Enumerator/Generator.html | Removes committed generated YARD API HTML (now generated at build time). |
| docs/api/Enumerator/Chain.html | Removes committed generated YARD API HTML (now generated at build time). |
| docs/api/EOFError.html | Removes committed generated YARD API HTML (now generated at build time). |
| docs/api/Comparable.html | Removes committed generated YARD API HTML (now generated at build time). |
| docs/api/ArgumentError.html | Removes committed generated YARD API HTML (now generated at build time). |
| assets/css/main.scss | Adds the new SCSS entrypoint using @use partials. |
| assets/css/main.css | Removes old committed CSS (now built from SCSS). |
| about/index.html | Rewrites About page markup to match new design system and new content sections. |
| _sass/_variables.scss | Introduces CSS custom properties (colors, spacing, typography) and responsive tokens. |
| _sass/_team.scss | Adds styles for redesigned Team page components. |
| _sass/_reset.scss | Adds a baseline reset and reduced-motion handling for the new UI. |
| _sass/_page-header.scss | Adds a unified page header component with responsive variants. |
| _sass/_navigation.scss | Adds redesigned nav + skip link + mobile menu styles. |
| _sass/_libraries.scss | Adds redesigned Libraries page layout and searchable card styles. |
| _sass/_latest-news.scss | Adds redesigned “Latest News” strip styles. |
| _sass/_inline-code.scss | Adds inline-code styling used across pages. |
| _sass/_footer.scss | Adds redesigned footer styles. |
| _sass/_downloads.scss | Adds redesigned Downloads page layout/styles. |
| _sass/_documentation.scss | Adds redesigned Docs index layout/styles. |
| _sass/_buttons.scss | Adds new button component styles. |
| _sass/_article.scss | Adds new article layout styles including TOC styling. |
| _sass/_about.scss | Adds About page section/layout styles. |
| _layouts/post.html | Replaces legacy post layout with new header/article/TOC + mobile nav JS. |
| _layouts/default.html | Replaces legacy default layout with new includes + mobile nav JS. |
| _includes/navigation.html | Removes old Bootstrap-based navigation include. |
| _includes/nav.html | Adds new accessible navigation with skip link and mobile menu markup. |
| _includes/header.html | Removes old header include that pulled Bootstrap/CDN JS and legacy CSS. |
| _includes/head.html | Adds new head include (fonts, main stylesheet, feeds, meta). |
| _includes/footer.html | Replaces legacy footer markup with new footer component. |
| _includes/_latest_news.html | Removes legacy latest-news include (new section/styles elsewhere). |
| _data/releases.yml | Adds auto-generated releases data consumed by the site. |
| _data/mgems.yml | Updates mgems data set (generated) used by Libraries page. |
| _data/contributors.yml | Adds auto-generated contributors data used by Team page. |
| Rakefile | Adds unified generation tasks + build entrypoint for CI and local builds. |
| README.md | Updates local dev/build/deploy documentation to match the new pipeline. |
| Gemfile | Drops github-pages and declares direct dependencies for Jekyll/plugins + generators. |
| .ruby-version | Pins Ruby version for consistent local/CI builds. |
| .github/workflows/pages.yml | Adds explicit GitHub Actions workflow to build and deploy Pages. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| {% assign first_cat = page.categories | first %} | ||
| {% if first_cat.size > 1 %} | ||
| {% assign display_cat = first_cat | capitalize %} | ||
| {% elsif page.categories %} | ||
| {% assign display_cat = page.categories | capitalize %} |
There was a problem hiding this comment.
first_catcan benilwhenpage.categoriesis empty, which can makefirst_cat.sizethrow during Liquid rendering. Also,page.categories | capitalizeappliescapitalizeto an array (likely producing unintended output). Consider using a nil-safe approach like: only computedisplay_catwhenpage.categoriesis present and non-empty, and thenassign display_cat = page.categories | first | capitalize` (or join categories explicitly if you intend to show more than one).
| {% assign first_cat = page.categories | first %} | |
| {% if first_cat.size > 1 %} | |
| {% assign display_cat = first_cat | capitalize %} | |
| {% elsif page.categories %} | |
| {% assign display_cat = page.categories | capitalize %} | |
| {% assign display_cat = nil %} | |
| {% if page.categories and page.categories.size > 0 %} | |
| {% assign first_cat = page.categories | first %} | |
| {% if first_cat %} | |
| {% assign display_cat = first_cat | capitalize %} | |
| {% endif %} |
| end | ||
|
|
||
| desc 'Serve the Jekyll site locally with live reload' | ||
| task :serve do |
There was a problem hiding this comment.
The PR description/README indicate rake serve runs the gen:* tasks before serving, but the current :serve task does not. This can lead to confusing local behavior (stale/missing _data/*.yml and missing docs/api/). Either make :serve depend on the appropriate gen:* tasks (optionally gating the expensive gen:mrbdoc behind an env flag), or update the documentation to reflect that users must run generation tasks separately.
| task :serve do | |
| task :serve do | |
| Rake::Task['gen:mgemdata'].invoke | |
| Rake::Task['gen:contributors'].invoke | |
| Rake::Task['gen:releasedata'].invoke | |
| Rake::Task['gen:mrbdoc'].invoke unless ENV['SKIP_MRBDOC'] |
| end | ||
|
|
||
| # Copy generated docs into our docs/api/ directory | ||
| dest = File.join(__dir__, 'docs', 'api') |
There was a problem hiding this comment.
Copying into an existing docs/api/ directory without clearing it can leave stale files behind on repeated local builds (files removed upstream won’t be removed locally). Consider removing dest before copying, or replacing the copy step with a “sync” approach so the output directory always exactly matches the newly generated docs.
| dest = File.join(__dir__, 'docs', 'api') | |
| dest = File.join(__dir__, 'docs', 'api') | |
| FileUtils.rm_rf(dest) |
| <script> | ||
| (function () { | ||
| var btn = document.querySelector('.site-nav__hamburger'); | ||
| var links = document.getElementById('site-nav-links'); | ||
| if (!btn || !links) return; | ||
| btn.addEventListener('click', function () { | ||
| var expanded = btn.getAttribute('aria-expanded') === 'true'; | ||
| btn.setAttribute('aria-expanded', String(!expanded)); | ||
| links.classList.toggle('is-open', !expanded); | ||
| }); | ||
| })(); | ||
| </script> |
There was a problem hiding this comment.
This mobile-nav script is duplicated (a very similar block also exists in _layouts/post.html). To reduce drift and make future changes safer, consider moving it into a shared include (or a single asset JS file) and referencing it from both layouts.
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request delivers a comprehensive modernization of the mruby.org website, focusing on a refreshed visual identity and a streamlined technical foundation. The changes aim to improve user experience through a modern design system and enhanced accessibility, while also boosting developer efficiency with an updated build pipeline, automated data generation, and a cleaner repository by removing generated content from version control. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Ignored Files
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This is a massive and impressive undertaking that completely modernizes the mruby.org website. The move to a custom design system, Jekyll 4, and a fully automated data and deployment pipeline are all excellent improvements. The new design is clean and modern, and the technical changes will significantly improve the maintainability and development experience. I've found a few areas for improvement, mostly around code duplication and a configuration detail, but overall this is a fantastic contribution.
Note: Security Review did not run due to the size of the PR.
| @@ -0,0 +1 @@ | |||
| 4.0.1 | |||
There was a problem hiding this comment.
The Ruby version 4.0.1 specified here does not appear to be a valid or existing Ruby version. This will likely cause setup issues for contributors using version managers like rbenv or rvm. It seems this might be a typo. I recommend changing this to a recent stable Ruby version, for example 3.3.0.
3.3.0
| tags = [] | ||
| page = 1 | ||
| loop do | ||
| batch = JSON.parse(`gh api "repos/mruby/mruby/tags?per_page=100&page=#{page}"`) | ||
| break if batch.empty? | ||
| tags.concat(batch) | ||
| break if batch.size < 100 | ||
| page += 1 | ||
| end |
There was a problem hiding this comment.
| (function () { | ||
| // Mobile nav | ||
| var btn = document.querySelector('.site-nav__hamburger'); | ||
| var links = document.getElementById('site-nav-links'); | ||
| if (btn && links) { | ||
| btn.addEventListener('click', function () { | ||
| var expanded = btn.getAttribute('aria-expanded') === 'true'; | ||
| btn.setAttribute('aria-expanded', String(!expanded)); | ||
| links.classList.toggle('is-open', !expanded); | ||
| }); | ||
| } |
There was a problem hiding this comment.
This JavaScript snippet for handling the mobile navigation hamburger menu is also present in _layouts/default.html. To avoid code duplication and improve maintainability, it would be better to extract this script into its own file (e.g., assets/js/nav.js) and include it in the layouts where it's needed.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 67a35bbedd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| on: | ||
| push: | ||
| branches: [master] |
There was a problem hiding this comment.
Run Pages deployment on main branch pushes
The push trigger is restricted to master, so when changes are merged to main (the active default branch in this repo) this workflow will never auto-run and Pages won’t be rebuilt/deployed unless someone manually dispatches it. Update the branch filter to include the branch that actually receives production merges.
Useful? React with 👍 / 👎.
|
I'd talk with the design person, behind the current site. |
|
Who is that person? |
@matz This PR is a ground-up redesign and modernization of mruby.org. Every page has been visually overhauled with a custom design system (no Bootstrap), the build toolchain has been upgraded from Jekyll 3 to Jekyll 4.4.1, the
github-pagesgem has been dropped in favor of direct dependencies, the entire generated API documentation has been removed from the repository and is now produced at build time, and two new automated data pipelines keep release and contributor data current. Deployment has moved to an explicit GitHub Actions workflow, giving us full control over the build environment.I know this comes out of the blue, but as a long fan of the mruby project, and someone who likes nice looking websites, I thought I could help out with mruby's pages.
Visual and Design Changes
Design System
#c0392b) on off-white and near-black neutrals.Pages Redesigned
/)/downloads/)_data/releases.yml; always shows current stable release/docs/)/libraries/)mgems.ymldata/about/)/team/)_data/contributors.ymlResponsive Breakpoints
Three explicit breakpoints: 1024 px (tablet landscape), 768 px (tablet portrait), 480 px (mobile). All layouts collapse gracefully at each breakpoint.
Technical Changes
Jekyll Upgrade: 3 → 4.4.1
Jekyll 4 brings faster incremental builds, improved Sass handling, and drops several long-deprecated Liquid behaviors. See the Jekyll 4 upgrade guide for breaking changes; none of them affected this site's content.
Dependency Cleanup: Dropping
github-pagesThe
github-pagesmeta-gem pins every Jekyll plugin to GitHub's own deployment environment, pulling in roughly 30 transitive dependencies and freezing Jekyll at version 3. By switching to explicit, direct dependencies we:Gemfile.lockby ~30 gems.All plugins previously provided through
github-pagesthat we actually use (jekyll-feed,jekyll-sitemap) are now declared directly.Bundler and Ruby
.ruby-version. This aligns with mruby's own development focus on current Ruby.Build and Deployment
GitHub Actions Workflow
A new workflow at
.github/workflows/pages.ymlreplaces the legacy GitHub Pages automatic build. It:fetch-depth: 0) sogit logis available during generation tasks.bundle exec rake build, which executes allgen:*tasks beforejekyll build._site/artifact using the officialactions/deploy-pagesaction.Unified Rakefile
Rakefileis the single entry point for all build automation:rake buildgen:*tasks, thenjekyll buildrake servegen:*tasks, thenjekyll serverake gen:mgemdata_data/mgems.ymlfrom mrbgems registryrake gen:mrbdocdocs/api/rake gen:releasedata_data/releases.ymlfrom GitHub APIrake gen:contributors_data/contributors.ymlfrom mruby AUTHORS filePreviously, several of these were standalone scripts. They are now unified tasks with consistent error handling and dependency ordering.
API Docs Removed from Git
docs/api/contained approximately 130,000 lines of generated YARD HTML committed directly to the repository. It is now:.gitignore.rake build(and therefore during CI deployment) by thegen:mrbdoctask.This makes the diff of every future commit dramatically smaller and ensures API docs always reflect the current mruby release rather than whatever was last manually committed.
Data Automation
_data/releases.yml— Auto-generatedGenerated by
rake gen:releasedata. Queries the GitHub API for mruby releases and writes structured YAML. The Downloads page consumes this data so it always reflects the latest stable release without manual updates._data/contributors.yml— Auto-generatedGenerated by
rake gen:contributors. Parses theAUTHORSfile from the mruby repository. The Team page now sources its contributor list from this file instead of being manually maintained (beyond_data/team.ymlfor core team members with additional metadata).Accessibility
_includes/nav.htmlfor keyboard users.main,nav,banner,contentinfo) applied throughout layouts.:focus-visibleCSS used instead of removing focus outlines, maintaining keyboard navigability without visual noise for mouse users.prefers-reduced-motionmedia query wraps all CSS transitions and animations.FAQ for Reviewers
Why drop the
github-pagesgem?github-pagespins Jekyll to version 3 and prevents upgrading any plugin it includes. GitHub's own documentation notes that using a custom GitHub Actions workflow is the recommended modern approach and removes the gem requirement entirely. Our newpages.ymlworkflow gives us the same deployment target with full control over versions.What about the API docs — will they still be available at
/docs/api/?Yes. The
gen:mrbdocrake task clones mruby, runs YARD, and writes HTML todocs/api/beforejekyll buildruns. The CI workflow runs this task, sodocs/api/will be present in every deployment. The only change is that the generated files are no longer committed to git.Why Ruby 4.0.1?
Using 4.0.1 ensures our tooling stays aligned with the project's own requirements and lets us use current gem versions without compatibility shims. The
.ruby-versionfile pins this explicitly so all contributors and CI use the same version.Will existing URLs break?
No. All page paths are preserved:
/— home/downloads/— downloads/docs/— documentation index/docs/api/— API reference (generated at build time)/libraries/— mrbgems browser/about/— about page/team/— team page/YYYY/MM/DD/...— unchangedWhat repository settings need to change after merging?
Note
This needs to be changed in order for the GitHub Action to work.
In Settings → Pages, change the source from "Deploy from a branch" to "GitHub Actions". The new workflow handles everything from there. No other settings changes are required.
How do I test locally?
See the section below.
Testing Locally
To skip API doc generation (faster iteration):
bundle exec jekyll serve --livereloadFiles Changed — High-Level Summary
_sass/_layouts/default.html,post.html_includes/header.html,footer.html,navigation.html*.html/*.mdpagesGemfile/Gemfile.lockgithub-pages, added direct deps.ruby-versionRakefile.github/workflows/pages.yml_data/releases.yml_data/contributors.ymldocs/api/.gitignoredocs/api/and build artifactsScreenshots
Home Page
Downloads
Documentation
Libraries
About
Team
Articles
PS. Claude Code was very helpful getting this done quickly.