authorgravatar for mahdibenmassoud98@gmail.comMahdi Ben Messaoud <mahdibenmassoud98@gmail.com> 2026-08-15 14:29:36+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-15 12:29:36+00:00
log04f23098e13410a325fd2b997cbf7144e872470e
tree4914e1b2e9bcc96637085e2b2f870f96dfb87ed4
parent61b2e744df378b7a8d534494114cf59b26cbe6ca
signature Signed by PGP key B5690EEEBB952194

fix(marketing): detect Mac chip on homepage download button (#4197)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com> Co-authored-by: codex <codex@users.noreply.github.com>

3 files changed, 56 insertions(+), 1 deletions(-)

apps/marketing/src/lib/macArch.test.ts created+20
...@@ -0,0 +1,20 @@
1import { describe, expect, it } from "vite-plus/test";
2
3import { macArchFromGpuRenderer } from "./macArch";
4
5describe("macArchFromGpuRenderer", () => {
6 it("detects explicit Apple Silicon renderers", () => {
7 expect(macArchFromGpuRenderer("Apple M4 Pro")).toBe("arm64");
8 });
9
10 it("prefers an Intel GPU marker even when the renderer also mentions Apple", () => {
11 expect(macArchFromGpuRenderer("ANGLE Metal Renderer: Apple, Intel Iris Plus Graphics")).toBe(
12 "x64",
13 );
14 });
15
16 it("uses x64 for ambiguous Safari and unavailable renderer values", () => {
17 expect(macArchFromGpuRenderer("Apple GPU")).toBe("x64");
18 expect(macArchFromGpuRenderer("")).toBe("x64");
19 });
20});
apps/marketing/src/lib/macArch.ts created+16
...@@ -0,0 +1,16 @@
1const INTEL_GPU_PATTERN = /intel|amd|radeon|nvidia|geforce/i;
2const APPLE_SILICON_GPU_PATTERN = /\bapple\s+m\d/i;
3
4export function macArchFromGpuRenderer(renderer: string): "arm64" | "x64" {
5 if (INTEL_GPU_PATTERN.test(renderer)) {
6 return "x64";
7 }
8 if (APPLE_SILICON_GPU_PATTERN.test(renderer)) {
9 return "arm64";
10 }
11
12 // Generic "Apple GPU" renderers are ambiguous on Safari. x64 is the safe
13 // fallback because Apple Silicon can run it through Rosetta, while Intel
14 // Macs cannot run an arm64 build.
15 return "x64";
16}
apps/marketing/src/pages/index.astro+20-1
...@@ -391,14 +391,33 @@ const mobileEndorsementRows = [...@@ -391,14 +391,33 @@ const mobileEndorsementRows = [
391391
392<script>392<script>
393 import { fetchLatestRelease, RELEASES_URL, type ReleaseAsset } from "../lib/releases";393 import { fetchLatestRelease, RELEASES_URL, type ReleaseAsset } from "../lib/releases";
394 import { macArchFromGpuRenderer } from "../lib/macArch";
394395
395 type Platform = { os: "mac" | "win" | "linux"; label: string; arch?: string };396 type Platform = { os: "mac" | "win" | "linux"; label: string; arch?: string };
396397
398 // navigator.userAgent reports "Intel Mac OS X" on both Intel and Apple Silicon
399 // Macs, so probe the GPU renderer instead: Apple Silicon exposes an "Apple" GPU.
400 function detectMacArch(): "arm64" | "x64" {
401 try {
402 const canvas = document.createElement("canvas");
403 const gl = (canvas.getContext("webgl") ||
404 canvas.getContext("experimental-webgl")) as WebGLRenderingContext | null;
405 const debugInfo = gl?.getExtension("WEBGL_debug_renderer_info");
406 if (gl && debugInfo) {
407 const renderer = String(gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) ?? "");
408 return macArchFromGpuRenderer(renderer);
409 }
410 } catch {
411 // fall through to the default below
412 }
413 return macArchFromGpuRenderer("");
414 }
415
397 function detectPlatform(): Platform | null {416 function detectPlatform(): Platform | null {
398 const ua = navigator.userAgent;417 const ua = navigator.userAgent;
399 if (/Win/i.test(ua)) return { os: "win", label: "Download for Windows" };418 if (/Win/i.test(ua)) return { os: "win", label: "Download for Windows" };
400 if (/Mac/i.test(ua)) {419 if (/Mac/i.test(ua)) {
401 return { os: "mac", label: "Download for macOS", arch: "arm64" };420 return { os: "mac", label: "Download for macOS", arch: detectMacArch() };
402 }421 }
403 if (/Linux/i.test(ua)) return { os: "linux", label: "Download for Linux" };422 if (/Linux/i.test(ua)) return { os: "linux", label: "Download for Linux" };
404 return null;423 return null;