Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ worker
# production
/build
stats.html
**/pwa-assets

# misc
.DS_Store
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ bun install
bun dev
```

## PWA Setup

PWA icons and splash screens are automatically generated using [pwa-asset-generator](https://github.com/elegantapp/pwa-asset-generator), which also updates the HTML metadata tags accordingly. Asset generation settings can be configured in the generate-pwa-assets script in package.json.

## Contributing

Join the `#dev-connect-web` channel on our [Discord](https://discord.comma.ai).
Expand Down
12 changes: 9 additions & 3 deletions check-bundle-size.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
cd $DIR

gzip -r -9 dist
BUNDLE_SIZE=$(du -sk dist | cut -f1)
echo "Bundle size is $BUNDLE_SIZE K"

# Calculate bundle size excluding PWA assets
BUNDLE_SIZE=$(find dist -type f \
! -name "apple-splash-*" \
! -name "apple-icon-*" \
-print0 | xargs -0 du -ck | grep total$ | cut -f1)

echo "Bundle size (excluding specified assets) is $BUNDLE_SIZE K"

if [ $BUNDLE_SIZE -lt 200 ]; then
echo "Bundle sizer lower than expected, let's lower the limit!"
echo "Bundle size lower than expected, let's lower the limit!"
exit 1
fi

Expand Down
81 changes: 53 additions & 28 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,38 +1,63 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no" />
<meta name="theme-color" content="#1B1B1F" />
<meta name="description" content="manage your openpilot experience" />
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
<meta name="theme-color" content="#1B1B1F">
<meta name="description" content="manage your openpilot experience">
<title>connect</title>
<link rel="manifest" href="/manifest.json">
<link href="/images/favicon-16x16.png" rel="icon" type="image/png" sizes="16x16">
<link href="/images/favicon-32x32.png" rel="icon" type="image/png" sizes="32x32">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],400,0..1,0&amp;display=block">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:[email protected]&amp;family=JetBrains+Mono:wght@400;500&amp;display=swap">

<link rel="manifest" href="/manifest.json" />
<link
href="/images/favicon-16x16.png"
rel="icon"
type="image/png"
sizes="16x16"
/>
<link
href="/images/favicon-32x32.png"
rel="icon"
type="image/png"
sizes="32x32"
/>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],400,0..1,0&display=block"
/>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inter:[email protected]&family=JetBrains+Mono:wght@400;500&display=swap"
/>
<!-- DON'T CHANGE MANUALLY. The below are auto-generated PWA assets (scripts defined in package.json). -->
<meta name="mobile-web-app-capable" content="yes">
<link rel="apple-touch-icon" href="pwa-assets/apple-icon-180.png">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2048-2732.jpg" media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2732-2048.jpg" media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1668-2388.jpg" media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2388-1668.jpg" media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1536-2048.jpg" media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2048-1536.jpg" media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1488-2266.jpg" media="(device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2266-1488.jpg" media="(device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1640-2360.jpg" media="(device-width: 820px) and (device-height: 1180px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2360-1640.jpg" media="(device-width: 820px) and (device-height: 1180px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1668-2224.jpg" media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2224-1668.jpg" media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1620-2160.jpg" media="(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2160-1620.jpg" media="(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1320-2868.jpg" media="(device-width: 440px) and (device-height: 956px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2868-1320.jpg" media="(device-width: 440px) and (device-height: 956px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1206-2622.jpg" media="(device-width: 402px) and (device-height: 874px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2622-1206.jpg" media="(device-width: 402px) and (device-height: 874px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1290-2796.jpg" media="(device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2796-1290.jpg" media="(device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1179-2556.jpg" media="(device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2556-1179.jpg" media="(device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1284-2778.jpg" media="(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2778-1284.jpg" media="(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1170-2532.jpg" media="(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2532-1170.jpg" media="(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1125-2436.jpg" media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2436-1125.jpg" media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1242-2688.jpg" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2688-1242.jpg" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-828-1792.jpg" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1792-828.jpg" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1242-2208.jpg" media="(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-2208-1242.jpg" media="(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-750-1334.jpg" media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1334-750.jpg" media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-640-1136.jpg" media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
<link rel="apple-touch-startup-image" href="pwa-assets/apple-splash-1136-640.jpg" media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
</head>
<body data-theme="dark" class="overflow-x-hidden bg-background text-on-background">
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>

<script src="/src/index.tsx" type="module"></script>
</body>
</html>
</html>
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
"url": "https://github.com/commaai/connect-beta.git"
},
"scripts": {
"build": "vite build",
"build": "npm run pwa-setup && vite build",
"dev": "vite",
"generate-pwa-assets": "npx pwa-asset-generator ./public/images/icon-vector.svg ./pwa-assets -m ./public/manifest.json -i ./index.html --sizes \"72x72,96x96,128x128,144x144,152x152,192x192,384x384,512x512\" --quality 75 --padding \"10%\" --platform android,ios --opaque false",
Copy link
Contributor

Choose a reason for hiding this comment

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

let's document these in the README?

"move-pwa-assets": "rm -rf ./public/pwa-assets && mv ./pwa-assets ./public/",
"pwa-setup": "npm run generate-pwa-assets && npm run move-pwa-assets",
Copy link
Author

@knownotunknown knownotunknown Nov 4, 2024

Choose a reason for hiding this comment

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

  1. "generate-pwa-assets":

    • Takes our vector icon from public/images/icon-vector.svg
    • Generates various sizes of icons required for PWA (72px to 512px)
    • Updates manifest.json and index.html with the new icons
    • Applies settings:
      • 75% image quality for bundle size optimization
      • 10% padding around icons
      • Compatible with both Android and iOS
      • Transparent background allowed
  2. "move-pwa-assets":

    • Cleans up old assets to avoid duplicates
    • Moves generated assets to the public directory
  3. "pwa-setup":

    • Runs both commands in sequence to generate and organize PWA assets

"serve": "vite prefix",
"lint": "eslint --cache --cache-location node_modules/.eslintcache",
"prepare": "husky",
Expand Down
33 changes: 18 additions & 15 deletions public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,38 @@
"name": "comma connect",
"icons": [
{
"src": "/images/icon-vector.svg",
"type": "image/svg+xml",
"sizes": "512x512"
"src": "pwa-assets/manifest-icon-192.maskable.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/images/icon-192.png",
"src": "pwa-assets/manifest-icon-192.maskable.png",
"sizes": "192x192",
"type": "image/png",
"sizes": "192x192"
"purpose": "maskable"
},
{
"src": "/images/icon-256.png",
"src": "pwa-assets/manifest-icon-512.maskable.png",
"sizes": "512x512",
"type": "image/png",
"sizes": "256x256"
"purpose": "any"
},
{
"src": "/images/icon-384.png",
"src": "pwa-assets/manifest-icon-512.maskable.png",
"sizes": "512x512",
"type": "image/png",
"sizes": "384x384"
"purpose": "maskable"
},
{
"src": "/images/icon-512.png",
"src": "/images/icon-256.png",
"type": "image/png",
"sizes": "512x512"
"sizes": "256x256"
},
{
"src": "/images/icon-maskable.png",
"sizes": "512x512",
"src": "/images/icon-384.png",
"type": "image/png",
"purpose": "maskable"
"sizes": "384x384"
}
],
"id": "/",
Expand All @@ -41,4 +44,4 @@
"scope": "/",
"theme_color": "#1B1B1F",
"description": "manage your openpilot experience"
}
}