Skip to content

Migrate frontend to Vite 5 + Bootstrap 5 + Vue 3#3

Draft
mingtsay wants to merge 223 commits intotwdsco:masterfrom
mingtsay:master
Draft

Migrate frontend to Vite 5 + Bootstrap 5 + Vue 3#3
mingtsay wants to merge 223 commits intotwdsco:masterfrom
mingtsay:master

Conversation

@mingtsay
Copy link

@mingtsay mingtsay commented Feb 25, 2026

Summary

  • Migrate the entire frontend build pipeline from Bootstrap 3 + Vue 2 + jQuery + jekyll-babel to Vite 5 + Bootstrap 5 + Vue 3 + TypeScript, based on tuna/master upstream
  • Upgrade Jekyll 3 (github-pages gem) to Jekyll 4.3 with vite_ruby integration
  • Full English localization of all templates, pages, and Vue components with TWDS branding
  • Add @vitejs/plugin-legacy for SystemJS fallback on older browsers

Changes

Build system:

  • Add Vite 5 build pipeline (_vite.config.mjs, jekyll-vite.rb plugin)
  • Rewrite Gemfile for standalone Jekyll 4.3 + vite_ruby
  • Add package.json with all Node.js dependencies
  • Update build.sh and rebuild-iso.sh to use twds/mirror-web Docker image
  • Update Dockerfiles for Node.js + Vite build
  • Add .nvmrc (Node 22)

Frontend source (_src/):

  • 8 Vue 3 SFC components (DiskBar, IsoModal, MainMirrorList, SearchBox, Sponsors, etc.)
  • TypeScript entrypoints replacing legacy ES6 scripts
  • SCSS styles with Bootstrap 5 variables
  • NJS build targets for NGINX JavaScript

Templates & pages:

  • Convert all _includes/ and _layouts/ to Bootstrap 5 markup
  • Translate all Chinese UI text to English (templates, Vue components, mirror descriptions)
  • Update TWDS sponsors (Gold: Sky Digital, TWDS, YUAN JHEN + personal sponsors via Vue 3 component)
  • Add official mirror badges (blue checkmarks) support
  • Remove help/news system (not used by TWDS)
  • Update _data/options.yml label classes (label-*text-bg-*)

Infrastructure:

  • Fix gen_robot.sh default host and add linuxbrew-bottles exclusion
  • Fix select.rb nil guard for missing help category
  • Migrate genisolist to mirrorz-org/genisolist submodule

Documentation:

  • Rewrite README with TWDS-specific documentation, including prerequisites, local dev, production build, and Docker build instructions

Cleanup:

  • Remove all Bootstrap 3 static assets (~50 files: JS, CSS, fonts)

Test plan

  • npm ci installs successfully
  • bundle install installs successfully
  • bundle exec jekyll build completes without errors
  • Main page mirror list renders correctly (Vue 3 app)
  • Legacy page (/legacy_index.html) works with SystemJS fallback
  • ISO download modal functions properly
  • Sync status page (/status/) displays correctly
  • All UI text is in English (no residual Chinese)
  • Sponsor section and progress bar display correctly
  • Official mirror badges (blue checkmarks) show up
  • Docker build succeeds

🤖 Generated with Claude Code

shankerwangmiao and others added 30 commits April 2, 2024 00:12
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
helpz: sync mirrorz-help-ng@f0407f6c
Signed-off-by: Shengqi Chen <harry-chen@outlook.com>
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
Signed-off-by: Harry Chen <i@harrychen.xyz>
Signed-off-by: Harry Chen <i@harrychen.xyz>
Signed-off-by: Harry Chen <i@harrychen.xyz>
Signed-off-by: Harry Chen <i@harrychen.xyz>
dependabot bot and others added 15 commits January 14, 2026 05:00
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.24.7 to 7.28.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.28.4/packages/babel-runtime)

---
updated-dependencies:
- dependency-name: "@babel/runtime"
  dependency-version: 7.28.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [@babel/helpers](https://github.com/babel/babel/tree/HEAD/packages/babel-helpers) from 7.24.7 to 7.28.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.28.4/packages/babel-helpers)

---
updated-dependencies:
- dependency-name: "@babel/helpers"
  dependency-version: 7.28.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [rexml](https://github.com/ruby/rexml) from 3.3.6 to 3.4.2.
- [Release notes](https://github.com/ruby/rexml/releases)
- [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md)
- [Commits](ruby/rexml@v3.3.6...v3.4.2)

---
updated-dependencies:
- dependency-name: rexml
  dependency-version: 3.4.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [rack](https://github.com/rack/rack) from 3.0.10 to 3.1.18.
- [Release notes](https://github.com/rack/rack/releases)
- [Changelog](https://github.com/rack/rack/blob/main/CHANGELOG.md)
- [Commits](rack/rack@v3.0.10...v3.1.18)

---
updated-dependencies:
- dependency-name: rack
  dependency-version: 3.1.18
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.7 to 5.4.21.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.21/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.21/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 5.4.21
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [tmp](https://github.com/raszi/node-tmp) to 0.2.5 and updates ancestor dependency [patch-package](https://github.com/ds300/patch-package). These dependencies need to be updated together.


Updates `tmp` from 0.0.33 to 0.2.5
- [Changelog](https://github.com/raszi/node-tmp/blob/master/CHANGELOG.md)
- [Commits](raszi/node-tmp@v0.0.33...v0.2.5)

Updates `patch-package` from 8.0.0 to 8.0.1
- [Release notes](https://github.com/ds300/patch-package/releases)
- [Changelog](https://github.com/ds300/patch-package/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ds300/patch-package/commits)

---
updated-dependencies:
- dependency-name: tmp
  dependency-version: 0.2.5
  dependency-type: indirect
- dependency-name: patch-package
  dependency-version: 8.0.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 2.0.1 to 2.0.2.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](juliangruber/brace-expansion@v2.0.1...v2.0.2)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 2.0.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [webrick](https://github.com/ruby/webrick) from 1.8.1 to 1.8.2.
- [Release notes](https://github.com/ruby/webrick/releases)
- [Commits](ruby/webrick@v1.8.1...v1.8.2)

---
updated-dependencies:
- dependency-name: webrick
  dependency-version: 1.8.2
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
Advance the merge-base to tuna/master HEAD while keeping the TWDS
BS3 tree intact. The Vite + BS5 frontend migration from upstream is
intentionally not adopted at this time.

This allows future tuna merges to only bring in new changes beyond
this point, avoiding repeated conflicts with the 218 upstream commits
since the original fork at 7b0fc27.
Change default HOST from TUNA to mirror.twds.com.tw and exclude
linuxbrew-bottles from robots.txt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace minimal TUNA-referencing README with complete documentation:
configuration overview, submodule prerequisites, Docker build with
correct TWDS URLs, local development guide, and ISO regeneration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the 1300-line local genisolist.ini and genisolist.py with the
upstream mirrorz-org/genisolist submodule, gaining ~58 new distro/app
ISO detection rules and automatic upstream updates.

- Add git submodule geninfo/z-geninfo
- Simplify genisolist.ini to ~100 lines using !include and [%alias%]
- Create distro.ini with TWDS sort order (Arch Linux first)
- Delete local genisolist.py (use submodule version)
- Update rebuild-iso.sh to init submodules and use new script path
- 6 aliases map upstream repo names to TWDS paths
- 3 local overrides for Deepin, Ubuntukylin, CentOS Stream 10+
- Keep TWDS-only sections: Ubuntu netinst, Debian non-free

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mingtsay mingtsay force-pushed the master branch 3 times, most recently from de0859a to 8392b73 Compare February 25, 2026 09:54
Replace the legacy Bootstrap 3 + Vue 2 + jQuery + jekyll-babel stack
with a modern Vite 5 + Bootstrap 5 + Vue 3 + TypeScript build pipeline,
based on tuna/master upstream with TWDS-specific adaptations.

Build system:
- Upgrade Jekyll 3 (github-pages) to Jekyll 4.3 with vite_ruby
- Add Vite 5 build pipeline (_vite.config.mjs, jekyll-vite.rb plugin)
- Add @vitejs/plugin-legacy for SystemJS fallback on older browsers

Frontend:
- Vue 3 SFC components (_src/components/)
- TypeScript entrypoints (_src/entrypoints/)
- SCSS styles with Bootstrap 5 variables (_src/styles/)
- Remove help/news system (not used by TWDS)

Templates & pages:
- Convert all HTML templates to Bootstrap 5 markup
- Full English localization (remove all Chinese text)
- TWDS branding, sponsors, and contact information
- Update label_map classes (label-* → text-bg-*)

Infrastructure:
- Update Dockerfiles for Node.js + Vite build
- Add .nvmrc (Node 22)
- Update .gitignore for Vite artifacts
- Fix select.rb nil guard for missing help category

Cleanup:
- Remove all Bootstrap 3 static assets (JS, CSS, fonts)
- Remove jQuery, Vue 2 CDN, legacy ES6 scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR modernizes the entire frontend build pipeline from a legacy Bootstrap 3 + Vue 2 + jQuery stack to Vite 5 + Bootstrap 5 + Vue 3 + TypeScript, while upgrading Jekyll from 3 to 4.3 with vite_ruby integration. All UI text has been translated to English with TWDS-specific branding, and the project now supports legacy browsers via SystemJS fallback.

Changes:

  • Complete frontend rewrite: Vue 2 → Vue 3 SFC, jQuery → vanilla JS/Vue, Bootstrap 3 → Bootstrap 5, legacy ES6 → TypeScript
  • Build system upgrade: Jekyll 3 → Jekyll 4.3, add Vite 5 pipeline with vite_ruby plugin, remove jekyll-babel
  • English localization of all templates, components, and mirror descriptions with TWDS branding

Reviewed changes

Copilot reviewed 93 out of 131 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
_vite.config.mjs New Vite 5 configuration with Vue 3, TypeScript, legacy plugin, and NJS build support
package.json Node.js dependencies for Vite 5, Bootstrap 5, Vue 3, TypeScript, and polyfills
Gemfile Standalone Jekyll 4.3 setup with vite_ruby integration
_plugins/jekyll-vite.rb Custom Jekyll plugin for Vite integration
_src/entrypoints/*.ts TypeScript entrypoints replacing legacy ES6 scripts
_src/components/*.vue Vue 3 SFC components for mirror list, ISO modal, sponsors, etc.
_src/styles/*.scss Bootstrap 5 SCSS with custom variables
_layouts/index.html Bootstrap 5 markup with Liquid templates for legacy/modern rendering
_includes/*.html Updated templates for Bootstrap 5 classes and Vite script loading
_data/options.yml Updated label classes from Bootstrap 3 (label-*) to Bootstrap 5 (text-bg-*)
status.html Simplified markup with Vue 3 component mounts
404.html Added AI/LLM warning note and TypeScript entrypoint
gen_robot.sh Fixed default host to mirror.twds.com.tw and excluded linuxbrew-bottles
_plugins/select.rb Added nil guard for missing help category
geninfo/z-geninfo Added mirrorz-org/genisolist submodule
README.md Comprehensive TWDS-specific documentation
Dockerfile.build Updated for Node.js 22 and Vite build
.nvmrc Node.js version specification
static/js/*.es6 Removed legacy ES6 scripts
static/css/*.scss Removed legacy SCSS files
static/js/*.min.js Removed legacy vendor libraries
Comments suppressed due to low confidence (1)

status.html:1

  • Corrected spelling of 'jsEntry' to 'jsEntrypoint' for consistency with standard naming conventions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

desc: Linux for single board computers (Images)
- name: ubuntu
desc: 流行的 Linux 發行版 Ubuntu 的安裝檔和官方軟體庫
desc: Popular Linux distribution Ubuntu packages and official repositories
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The English description is generic. Consider adding more specific details about what Ubuntu repositories are mirrored (e.g., 'Ubuntu packages and official repositories including main, universe, restricted, and multiverse').

Suggested change
desc: Popular Linux distribution Ubuntu packages and official repositories
desc: Popular Linux distribution Ubuntu packages and official repositories, including main, universe, restricted, and multiverse components

Copilot uses AI. Check for mistakes.
<script src="{{ site.base }}/static/js/webfont.js?{{ site.data['hash'] }}"></script>
<script src="{{ site.base }}/static/js/thuhidden.js?{{ site.data['hash'] }}"></script>
{% include vite_script.html %}
<link rel="stylesheet" id="style-polyfill-bs3" title="style-polyfill-bs3" href="{% vite_asset_path bs3-polyfill.scss %}" media="screen" integrity="sha256-OnlyforlegacybrowsersAAAAAAAAAAAAAAAAAAAAAA=" />
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The integrity attribute contains a placeholder hash value ('OnlyforlegacybrowsersAAAAAAAAAAAAAAAAAAAAAA='). This will cause the stylesheet to fail integrity checks in modern browsers that support SRI. While the script later removes/reloads it, this could cause a flash of unstyled content or unexpected behavior. Consider using a valid hash or removing the integrity attribute entirely if it's intentionally invalid.

Suggested change
<link rel="stylesheet" id="style-polyfill-bs3" title="style-polyfill-bs3" href="{% vite_asset_path bs3-polyfill.scss %}" media="screen" integrity="sha256-OnlyforlegacybrowsersAAAAAAAAAAAAAAAAAAAAAA=" />
<link rel="stylesheet" id="style-polyfill-bs3" title="style-polyfill-bs3" href="{% vite_asset_path bs3-polyfill.scss %}" media="screen" />

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here should be remove integrity attribute placeholder to make sure that stylesheets will be load successful

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This integrity attribute with a deliberately invalid hash is intentional. It serves as a browser capability detection mechanism:

  • Modern browsers support SRI (Subresource Integrity), so they will reject loading this stylesheet because the hash doesn't match — which is the desired behavior, since modern browsers don't need the BS3 polyfill.
  • Legacy browsers don't support SRI, so they ignore the integrity attribute entirely and load the polyfill stylesheet normally — which is exactly what we want.

The hash value sha256-OnlyforlegacybrowsersAAAAAAAAAAAAAAAAAAAAAA= is self-documenting: it's only meant to be loaded by legacy browsers. Removing it would cause the polyfill to load on all browsers, defeating its purpose.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is quite a dirty method! Is it the upstream practice?


module SelectFilter
def select(input, *selected)
return [] if input.nil?
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider also checking for empty arrays to make the function more robust. The current implementation will still attempt to map over an empty array, which while not an error, could be handled more explicitly: return [] if input.nil? || input.empty?

Suggested change
return [] if input.nil?
return [] if input.nil? || input.empty?

Copilot uses AI. Check for mistakes.
@mingtsay mingtsay marked this pull request as draft February 26, 2026 03:17
@james58899 james58899 removed their request for review February 26, 2026 10:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants