This project is automatically deployed to GitHub Pages whenever changes are
pushed to the main branch via a GitHub Action.
This is a blog built with Astro. One of the main benefits for using Astro is the islands architecture. Most of the site is static. Only those areas that need some interactivity (islands) are given that with a small bundle of JavaScript.
The end result is a much lighter page with the interactivity benefits.
The first page lists the articles. These are written in markdown or mdx. The
articles can be found in src/pages/blog. Each folder in the blog folder is
an article. It starts with the index.mdx file. Other related content like
images, videos or even components that are specific to that article can be
placed inside the folder.
There is a separate drafts folder next to the blog folder. There all the draft articles are kept. This because it's a bit tricky to get astro to only read "published" articles. Having them in a separate drafts folder means less smart solutions that need to be built and maintained (for now)
There is a search feature. An index can either be manually created or is created on deploy. Users can search per keyword which searches the title of the article which is based on the folder name of the article.
There is a tools page that allows the user to see the listed tools. They can be subfiltered by category.
The blog is deployed on GitHub Pages.
Deployment is handled automatically via GitHub Actions. The workflow is defined
in .github/workflows/deploy.yml.
When you push changes to the main branch:
- The Deploy workflow is triggered.
- It installs dependencies and builds the project (
npm run buildandnpm run build:pwa). - It runs tests (
npm test). - It deploys the contents of the
docsoutput directory to GitHub Pages using thepeaceiris/actions-gh-pagesaction.
The project is configured to build to the docs directory in astro.config.ts:
output: "static",
outDir: "./docs",This aligns with the deployment workflow which publishes the docs directory.
To test the site locally:
npm run dev # Start development server
npm run build # Build the site
npm run preview # Preview the built siteThe build script also runs the populateSearchData script to ensure the
search index is up to date.
This blog is implemented as a fully-featured Progressive Web App (PWA) that meets all modern PWA standards. Users can install the app on their devices and access content offline.
- App Installation: Users can install the blog as an app on their devices through browser prompts
- Standalone Mode: The installed app runs in standalone mode without browser UI
- App Icons: Comprehensive icon set for all platforms (iOS, Android, Windows)
- Splash Screen: Custom splash screen with gray background (#808080) and app branding
- Service Worker: Automatically caches visited pages and static assets
- Offline Fallback: Custom offline page when uncached content is accessed
- Cache Strategy: Stale-while-revalidate caching for optimal performance
- Blog Post Caching: Last 3 visited articles are cached for offline reading
- Asset Caching: Images, fonts, and static assets cached for 1 month
- Fast Loading: Critical resources are precached for instant loading
- Background Updates: Content updates automatically in the background
- Update Notifications: Non-intrusive notifications when new content is available
The web app manifest is generated via the VitePWA integration in
astro.config.ts (values sourced from src/config.ts) and includes:
{
"name": "Giwan Blog",
"short_name": "G1",
"theme_color": "#272822",
"background_color": "#808080",
"display": "standalone",
"start_url": "/",
"scope": "/"
}PWA functionality is configured in astro.config.ts using VitePWA:
VitePWA({
scope: "/",
registerType: "autoUpdate",
workbox: {
navigateFallback: "/offline.html",
runtimeCaching: [
// Blog posts - stale while revalidate
{
urlPattern: /\/blog\/.*/,
handler: "StaleWhileRevalidate",
options: {
cacheName: "blog-posts",
expiration: {
maxEntries: 50,
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
},
},
},
],
},
});- Replace icon files in
public/icons/directory - Ensure all required sizes are included (16x16 to 1024x1024)
- Include maskable icons for Android adaptive icons
- Update the icon list in
src/config.ts(PWA_ICONS) if filenames change - Test installation on different platforms
- Edit
src/config.tsto modify site or PWA metadata - Adjust the VitePWA configuration in
astro.config.tsif additional settings are required - Test changes with Lighthouse PWA audit
- Verify installation behavior after changes
- Modify
workbox.runtimeCachinginastro.config.ts - Adjust cache expiration times and entry limits
- Test offline functionality after changes
- Monitor cache storage usage
# Build the site with PWA features
npm run build
# Serve the built site locally
npm run preview
# Test PWA features at http://localhost:4321- Install prompt appears in supported browsers
- App installs correctly on desktop and mobile
- Standalone mode works without browser UI
- Offline pages load from cache
- Offline fallback displays for uncached content
- Service worker updates work correctly
- Icons and splash screen display properly
Run Lighthouse PWA audit to verify compliance:
- Open Chrome DevTools
- Go to Lighthouse tab
- Select "Progressive Web App" category
- Run audit and aim for 100/100 score
- Chrome: Full PWA support including installation
- Safari: iOS PWA features and home screen installation
- Edge: Windows PWA installation and features
- Firefox: Basic PWA functionality
Problem: Install prompt doesn't appear
- Solution: Ensure HTTPS is enabled and manifest is valid
- Check: Verify all required manifest fields are present
- Test: Use Chrome DevTools Application tab to inspect manifest
Problem: App doesn't install on iOS
- Solution: Verify Apple-specific meta tags in BaseHead component
- Check: Ensure
apple-mobile-web-app-capablemeta tag is present - Test: Use Safari on iOS device or simulator
Problem: Pages don't load offline
- Solution: Check if pages were visited while online first
- Check: Inspect service worker cache in DevTools
- Debug: Look for service worker errors in console
Problem: Offline fallback not showing
- Solution: Verify
/offline.htmlexists and is accessible - Check: Ensure
navigateFallbackis configured in workbox - Test: Disable network in DevTools and navigate to uncached page
Problem: Content doesn't update
- Solution: Check if service worker is updating properly
- Check: Look for update notifications or force refresh
- Debug: Clear cache and reload, or unregister service worker
Problem: Cache storage full
- Solution: Reduce cache limits in workbox configuration
- Check: Monitor cache usage in DevTools Application tab
- Fix: Implement cache cleanup strategies
Problem: Service worker fails to register
- Solution: Check console for registration errors
- Check: Verify service worker file is accessible
- Debug: Ensure HTTPS is enabled (required for service workers)
Problem: Service worker not updating
- Solution: Check
registerTypeconfiguration in VitePWA - Check: Verify build process generates new service worker
- Fix: Clear browser cache and hard refresh
Problem: Slow loading after PWA installation
- Solution: Review caching strategies and precache critical resources
- Check: Use Lighthouse performance audit
- Optimize: Reduce bundle sizes and optimize images
- Chrome DevTools: Application tab for PWA inspection
- Lighthouse: PWA audit and performance testing
- Workbox: Service worker debugging and cache inspection
- PWA Builder: Microsoft's PWA validation tool
- Clear all caches: DevTools > Application > Storage > Clear storage
- Unregister service worker: DevTools > Application > Service Workers > Unregister
- Hard refresh: Ctrl+Shift+R (Cmd+Shift+R on Mac)
- Incognito testing: Test PWA features in private browsing mode
The project uses a modern styling approach based on Tailwind CSS and HSL variables:
The design system is built on Tailwind CSS, integrated through the Astro
Tailwind integration. Configuration is in tailwind.config.js.
Instead of hardcoded hex values, the project uses HSL variables defined in
src/styles/global.css. This allows for seamless theme switching and consistent
semantic colors (e.g., primary, background, muted).
:root {
--background: 0 0% 100%;
--primary: 240 5.9% 10%;
/* ... */
}These variables are mapped in Tailwind to allow usage like bg-background or
text-primary.
Astro components can include scoped styles directly within the component file
using the <style> tag. These are automatically scoped to prevent global
conflicts.
This approach ensures a consistent newspaper-style aesthetic while maintaining developer flexibility and high performance.