Loading...
Loading...
Weekly AI insights —
Real strategies, no fluff. Unsubscribe anytime.
Founder & CEO, Agentik {OS}
The App Store takes 30% and days of review. PWAs skip all of it. With AI agents handling service workers and caching, the web-native gap is effectively zero.

The App Store is a 30% tax on your revenue, a multi-day review process for every release, and a gatekeeping authority that can reject your app for using the wrong tint color on a navigation bar.
That is a significant overhead for most applications. And for many categories of application, it is an overhead that provides nothing in return.
Progressive Web Apps eliminate all of it. A PWA loads from a URL, installs to the home screen without an app store, works offline, sends push notifications, and updates silently in the background. The user experience is indistinguishable from a native app for the majority of application categories.
The objection I have heard for years: "PWAs are too hard to build correctly." That was legitimate in 2019. With AI agents handling service workers, cache strategies, and the Web App Manifest, it is not legitimate anymore.
A Progressive Web App is a web application that meets a specific set of criteria:
That is the minimum. A well-built PWA goes further:
AI agents can generate all of this correctly. The complexity that made PWAs "too hard" was primarily in service worker logic, which is complex but well-documented and pattern-heavy.
A service worker is a JavaScript file that runs in the background, separate from the main browser thread. It intercepts network requests and decides what to do with each one.
This is where PWA complexity has historically lived. Getting cache strategies right is genuinely tricky. The wrong strategy for the wrong resource type creates maddening bugs. Too aggressive: stale content that never updates. Too conservative: offline mode that does not work.
AI agents select the right strategy for each resource type:
// Service worker with strategy-per-resource-type
// Generated by AI agent with correct cache strategies
import { registerRoute, NavigationRoute } from 'workbox-routing';
import {
CacheFirst,
NetworkFirst,
StaleWhileRevalidate,
} from 'workbox-strategies';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
import { ExpirationPlugin } from 'workbox-expiration';
import { precacheAndRoute } from 'workbox-precaching';
declare const self: ServiceWorkerGlobalScope;
// Precache build artifacts (versioned by webpack/Vite hash)
precacheAndRoute(self.__WB_MANIFEST);
// Static assets: Cache-First (versioned, safe to cache forever)
registerRoute(
({ request }) => request.destination === 'image' ||
request.destination === 'font',
new CacheFirst({
cacheName: 'static-assets',
plugins: [
new CacheableResponsePlugin({ statuses: [200] }),
new ExpirationPlugin({
maxEntries: 100,
maxAgeSeconds: 365 * 24 * 60 * 60, // 1 year
}),
],
})
);
// API responses: Network-First with cache fallback
// Fresh when connected, stale when not
registerRoute(
({ url }) => url.pathname.startsWith('/api/'),
new NetworkFirst({
cacheName: 'api-responses',
plugins: [
new CacheableResponsePlugin({ statuses: [200] }),
new ExpirationPlugin({
maxEntries: 50,
maxAgeSeconds: 5 * 60, // 5 minutes
}),
],
networkTimeoutSeconds: 3,
})
);
// HTML pages: Stale-While-Revalidate
// Instant loads from cache, background refresh
registerRoute(
new NavigationRoute(
new StaleWhileRevalidate({
cacheName: 'pages',
plugins: [
new ExpirationPlugin({ maxEntries: 20 }),
],
})
)
);The strategy selection is not arbitrary:
Cache-First for static assets because they are versioned by content hash. A change in the file produces a new URL. Serving the cached version is always correct.
Network-First for API responses because freshness matters. The fallback to cache keeps the app functional when offline, but fresh data wins when available.
Stale-While-Revalidate for HTML because HTML changes infrequently. Serving the cached version instantly while revalidating in the background gives users instant loads and eventually fresh content.
The Web App Manifest is a JSON file that tells browsers how to install your PWA. Icons, name, theme color, display mode, orientation.
{
"name": "Your Application",
"short_name": "YourApp",
"description": "A description for app stores and install prompts",
"start_url": "/dashboard",
"scope": "/",
"display": "standalone",
"orientation": "portrait-primary",
"theme_color": "#1a1a1a",
"background_color": "#1a1a1a",
"icons": [
{ "src": "/icons/icon-72.png", "sizes": "72x72", "type": "image/png" },
{ "src": "/icons/icon-96.png", "sizes": "96x96", "type": "image/png" },
{ "src": "/icons/icon-128.png", "sizes": "128x128", "type": "image/png" },
{ "src": "/icons/icon-144.png", "sizes": "144x144", "type": "image/png" },
{ "src": "/icons/icon-152.png", "sizes": "152x152", "type": "image/png" },
{ "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "maskable" },
{ "src": "/icons/icon-384.png", "sizes": "384x384", "type": "image/png" },
{ "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" }
],
"shortcuts": [
{
"name": "New Project",
"url": "/projects/new",
"icons": [{ "src": "/icons/shortcut-new.png", "sizes": "96x96" }]
}
],
"screenshots": [
{
"src": "/screenshots/desktop.png",
"sizes": "1280x720",
"type": "image/png",
"form_factor": "wide"
}
]
}The maskable purpose for the 192px icon deserves explanation. Android uses adaptive icons that apply a mask shape (circle, squircle, etc.) to icons. Without a maskable icon, the system applies the mask to your entire square icon, potentially clipping important content. A maskable icon has safe padding that ensures the important content stays within the masked area.
AI agents generate the complete manifest and icon set from your brand assets, including maskable variants.
"Add to Home Screen" converts at under 1% when shown immediately on first visit. Users have not experienced the value yet. They have no reason to install.
The right moment to prompt installation is after the user has demonstrated that they find the application valuable.
// Engagement-based install prompting
class InstallPromptManager {
private deferredPrompt: BeforeInstallPromptEvent | null = null;
private sessionData = {
visitCount: 0,
actionsCompleted: 0,
minutesEngaged: 0,
};
constructor() {
// Capture the browser's install prompt
window.addEventListener('beforeinstallprompt', (event) => {
event.preventDefault(); // Prevent automatic prompt
this.deferredPrompt = event as BeforeInstallPromptEvent;
});
// Track session data from localStorage
this.sessionData = this.loadSessionData();
}
trackAction(actionType: string) {
this.sessionData.actionsCompleted++;
this.saveSessionData();
this.checkInstallConditions(actionType);
}
private checkInstallConditions(triggerAction: string) {
// Do not prompt if already installed
if (window.matchMedia('(display-mode: standalone)').matches) return;
// Do not prompt without the event
if (!this.deferredPrompt) return;
const conditions = [
// Third visit or later
this.sessionData.visitCount >= 3,
// Has completed meaningful actions
this.sessionData.actionsCompleted >= 5,
// Has spent meaningful time
this.sessionData.minutesEngaged >= 10,
];
const shouldPrompt = conditions.filter(Boolean).length >= 2;
if (shouldPrompt) {
// Contextual prompt message based on what user just did
const message = this.getContextualMessage(triggerAction);
this.showInstallPrompt(message);
}
}
private getContextualMessage(action: string): string {
const messages: Record<string, string> = {
'save_item': 'Install to access your saved items offline',
'complete_project': 'Install for faster access to your projects',
'view_dashboard': 'Install for one-tap access to your dashboard',
};
return messages[action] ?? 'Install for faster access and offline use';
}
async showInstallPrompt(message: string) {
if (!this.deferredPrompt) return;
// Show custom UI with contextual message
const userChoice = await showCustomInstallBanner(message);
if (userChoice === 'install') {
this.deferredPrompt.prompt();
const { outcome } = await this.deferredPrompt.userChoice;
trackAnalytics('pwa_install_prompt', { outcome, message });
}
this.deferredPrompt = null;
}
}Contextual install prompts that appear after meaningful actions convert at 5-15x the rate of immediate prompts on first visit.
Push notifications are mobile apps' strongest re-engagement mechanism. PWAs have had push notifications for years, but the implementation complexity kept many teams from bothering.
AI agents implement the complete push notification stack:
// Push notification subscription
async function subscribeToPushNotifications(): Promise<PushSubscription | null> {
if (!('serviceWorker' in navigator) || !('PushManager' in window)) {
return null;
}
const permission = await Notification.requestPermission();
if (permission !== 'granted') return null;
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY!),
});
// Store subscription on server
await savePushSubscription(subscription);
return subscription;
}
// Service worker: handle push events
self.addEventListener('push', (event: PushEvent) => {
if (!event.data) return;
const notification = event.data.json();
event.waitUntil(
self.registration.showNotification(notification.title, {
body: notification.body,
icon: '/icons/icon-192.png',
badge: '/icons/badge-72.png',
data: { url: notification.url },
actions: notification.actions ?? [],
tag: notification.tag, // Prevents duplicate notifications
})
);
});
// Handle notification click: open the specific URL
self.addEventListener('notificationclick', (event: NotificationClickEvent) => {
event.notification.close();
const url = event.notification.data?.url ?? '/';
event.waitUntil(
clients.openWindow(url)
);
});AI features normally require network connectivity. But smaller AI models can run directly in the browser via WebAssembly.
WebLLM and ONNX Runtime Web allow loading quantized models into the browser for local inference:
For these use cases, offline AI eliminates latency and API costs simultaneously. A spelling correction model that runs locally responds in under 10ms. The same check via an API call takes 200-500ms.
AI agents configure the client-side model pipeline with progressive loading (model downloads in background while user uses the app), WebAssembly backend for optimal performance, and graceful degradation to server-side AI when the local model is unavailable.
Pair PWAs with mobile-specific patterns when you genuinely need native hardware access, and with accessibility standards to ensure your PWA serves all users on any device.
Q: What is a Progressive Web App (PWA)?
A PWA is a web application that provides native app-like experiences through modern web capabilities: offline support, push notifications, home screen installation, and fast performance. PWAs work across all devices from a single codebase, eliminating the need for separate iOS and Android development.
Q: How do AI agents build PWAs?
AI agents generate service worker configurations, implement caching strategies, create offline fallback pages, set up push notification systems, and configure web app manifests. They ensure PWAs meet all installability criteria and performance benchmarks automatically.
Q: Should I build a PWA or a native mobile app?
Choose a PWA for content-heavy applications, e-commerce, and services where broad reach matters more than deep device integration. Choose native for apps requiring advanced camera, sensor, or OS-level features. PWAs built with AI are dramatically faster and cheaper to develop than native apps.
Full-stack developer and AI architect with years of experience shipping production applications across SaaS, mobile, and enterprise. Gareth built Agentik {OS} to prove that one person with the right AI system can outperform an entire traditional development team. He has personally architected and shipped 7+ production applications using AI-first workflows.

AI Performance Optimization: LCP From 4.2s to 1.1s
An AI agent analyzed, identified, and fixed seven performance bottlenecks in one hour. Manual optimization would have taken a week. Here's the process.

Mobile Dev with AI: Ship iOS and Android Faster
AI agents accelerate React Native and Expo development from component generation to App Store deployment. Cross-platform, done right.

Accessible Apps with AI: WCAG Compliance by Default
Retrofitting accessibility is expensive. Building it in from the start is nearly free. AI agents make 'from the start' the default for every component.
Stop reading about AI and start building with it. Book a free discovery call and see how AI agents can accelerate your business.