{"id":30570494,"url":"https://github.com/skyzerozx/ng-ssr-twa-adaptive","last_synced_at":"2026-05-15T22:40:10.328Z","repository":{"id":309106116,"uuid":"1035181618","full_name":"SkyZeroZx/ng-ssr-twa-adaptive","owner":"SkyZeroZx","description":null,"archived":false,"fork":false,"pushed_at":"2025-08-17T21:36:48.000Z","size":750,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-17T23:19:51.971Z","etag":null,"topics":["angular","pwa","ssr","twa"],"latest_commit_sha":null,"homepage":"https://ng-ssr-twa-adaptive.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SkyZeroZx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-09T20:37:56.000Z","updated_at":"2025-08-17T21:36:52.000Z","dependencies_parsed_at":"2025-08-09T22:34:08.494Z","dependency_job_id":null,"html_url":"https://github.com/SkyZeroZx/ng-ssr-twa-adaptive","commit_stats":null,"previous_names":["skyzerozx/ng-ssr-twa-adaptive"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/SkyZeroZx/ng-ssr-twa-adaptive","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SkyZeroZx%2Fng-ssr-twa-adaptive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SkyZeroZx%2Fng-ssr-twa-adaptive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SkyZeroZx%2Fng-ssr-twa-adaptive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SkyZeroZx%2Fng-ssr-twa-adaptive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SkyZeroZx","download_url":"https://codeload.github.com/SkyZeroZx/ng-ssr-twa-adaptive/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SkyZeroZx%2Fng-ssr-twa-adaptive/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272547867,"owners_count":24953460,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-28T02:00:10.768Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","pwa","ssr","twa"],"created_at":"2025-08-28T20:04:27.184Z","updated_at":"2026-05-15T22:40:10.321Z","avatar_url":"https://github.com/SkyZeroZx.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Angular SSR PWA con Trusted Web Activity (TWA)\n\n## Descripción\n\nEste repositorio es una guía práctica para implementar una **Progressive Web Application (PWA)** con **Server-Side Rendering (SSR)** utilizando **Angular** y su posterior empaquetado como **Trusted Web Activity (TWA)** para Android. El proyecto incluye una arquitectura adaptativa que optimiza el rendimiento tanto en web como en dispositivos móviles.\n\n## Tabla de Contenidos\n\n- [Requisitos](#requisitos)\n- [Arquitectura del Proyecto](#arquitectura-del-proyecto)\n- [Estructura del Proyecto](#estructura-del-proyecto)\n- [Características](#características)\n- [Configuración](#configuración)\n- [Desarrollo](#desarrollo)\n- [TWA](#generar-twa)\n\n## Requisitos\n\n- Node.js 20+\n- Angular CLI v20+\n- Bubblewrap\n- Android Studio (para TWA)\n- Chrome DevTools\n\n## Arquitectura del Proyecto\n\nLa arquitectura del proyecto está diseñada para ser modular, escalable y optimizada para múltiples plataformas:\n\n```mermaid\nflowchart TD\n    subgraph Platforms [\"🖥️ Plataformas de Distribución\"]\n        WebBrowser[\"🌐 Web Browser\"]\n        MobilePWA[\"📱 Mobile PWA\"]\n        AndroidTWA[\"🤖 Android TWA\"]\n    end\n\n    subgraph AngularApp [\"⚡ Angular SSR Application\"]\n        ClientHydration[\"🔄 Client Hydration\"]\n        ServerRendering[\"🖥️ Server Rendering\"]\n    end\n\n    subgraph API [\"🌐 DummyJSON API\"]\n        Products[\"📦 Products\"]\n    end\n\n    subgraph PWAFeatures [\"📱 PWA Features\"]\n        ServiceWorker[\"⚙️ Service Worker\"]\n        WebManifest[\"📋 Web App Manifest\"]\n        OfflineSupport[\"📴 Offline Support\"]\n        PushNotifications[\"🔔 Push Notifications\"]\n        InstallPrompts[\"⬇️ Install Prompts\"]\n    end\n\n    Platforms --\u003e AngularApp\n    AngularApp --\u003e API\n    AngularApp --\u003e PWAFeatures\n    ClientHydration \u003c--\u003e ServerRendering\n```\n\n### Componentes\n\n- **Angular SSR**:\n\n  - Renderizado del lado del servidor para mejorar SEO y tiempo de carga inicial\n  - Hidratación para una experiencia fluida\n  - Consumo optimizado de DummyJSON API con SSR\n\n- **DummyJSON API Integration**:\n\n  - API externa que proporciona datos fake para desarrollo y testing\n  - Endpoints para productos, usuarios, posts, comentarios, todos, etc.\n  - No requiere configuración de backend local\n\n- **PWA Core**:\n\n  - Service Worker para caché inteligente y funcionalidad offline\n  - Web App Manifest para instalación nativa\n  - Estrategias de caché adaptativas para API responses\n\n- **Trusted Web Activity (TWA)**:\n\n  - Empaquetado como aplicación Android nativa\n  - Integración completa con el ecosistema Android\n  - Experiencia de aplicación nativa sin browser chrome\n\n- **Adaptive Design**:\n  - Responsive design optimizado para múltiples dispositivos\n  - Detección de capacidades del dispositivo\n  - Carga condicional de recursos\n\n## Estructura del Proyecto\n\n```\nng-ssr-twa-adaptive/\n├── src/\n│   ├── app/                   # Aplicación Angular principal\n│   │   ├── core/              # Constantes core , resolvers , guards\n│   │   ├── shared/            # Componentes y módulos compartidos\n│   │   ├── layout/            # Layout base por plataforma\n│   │   └── pages/             # Páginas principales\n│   │   └── services/          # Servicios de la aplicación\n│   ├── public/\n│   │   └── manifest.webmanifest # Web App Manifest\n│   ├── environments/          # Configuraciones de entorno\n├── android/                   # Proyecto TWA para Android\n```\n\n## Características\n\n### 🚀 Performance\n\n- **Server-Side Rendering** para carga inicial optimizada\n- **Code Splitting** automático por rutas\n- **Lazy Loading** de módulos\n- **Tree Shaking** para bundle size mínimo\n\n### 📱 Progressive Web App\n\n- **Service Worker** con estrategias de caché\n- **Offline functionality** completa\n- **Push notifications** nativas\n- **App install prompts** inteligentes\n\n### 🤖 Android Integration\n\n- **Trusted Web Activity** para experiencia nativa\n- **Play Store distribution** ready\n\n### 🎨 Adaptive UI/UX\n\n- **Responsive design** mobile-first\n- **Touch-friendly** interactions\n\n## Configuración\n\n### Configuración de Entornos\n\nConfigura los archivos en `src/environments/`:\n\n```typescript\nexport const environment = {\n  API: \"https://dummyjson.com\",\n  WEB_URL: \"http://localhost:4200\",\n  twaConfig: {\n    production: false,\n  },\n  httpCache: {\n    /**\n     * maxAge of cache in milliseconds\n     */\n    maxAge: 60_0000,\n    /**\n     * max cacheCount for different parameters\n     * maximum allowed unique caches (different parameters)\n     */\n    maxCacheCount: 100,\n  },\n};\n```\n\n### Web App Manifest\n\nEl archivo `src/manifest.json` está configurado para optimizar la instalación PWA:\n\n```json\n{\n  \"name\": \"Angular SSR TWA App\",\n  \"short_name\": \"NgSSRTWA\",\n  \"theme_color\": \"#1976d2\",\n  \"background_color\": \"#fafafa\",\n  \"display\": \"standalone\",\n  \"start_url\": \"/\",\n  \"icons\": [...]\n}\n```\n\n## Desarrollo\n\n### Servidor de Desarrollo\n\nPara iniciar el servidor de desarrollo:\n\n```bash\nng serve\n```\n\n## Generar Build\nPara generar la build productiva con el siguiente comando:\n\n```bash\nng build --configuration production\n```\n\n## Trusted Web Activity (TWA) - Context-Aware Architecture\n\n### El Problema Resuelto\n\nTradicionalmente, desarrollar para múltiples plataformas requería:\n\n- **3 codebases separados**: Web, PWA, y aplicación nativa\n- **3 equipos de desarrollo**: Frontend, Mobile Web, Android\n- **Fragmentación de features**: Inconsistencias entre experiencias\n\n### La Solución: Context-Aware SSR\n\nEste proyecto implementa una **arquitectura context-aware revolucionaria** que detecta la plataforma de origen **desde el servidor** y renderiza la experiencia optimizada específica, manteniendo un único codebase Angular.\n\n```mermaid\nflowchart TD\n    subgraph Request [\"📱 Incoming Request\"]\n        UserAgent[\"User-Agent\"]\n        Referer[\"Referer Header\"]\n        Cookies[\"Context Cookies\"]\n    end\n\n    subgraph Server [\"🖥️ Angular SSR Server\"]\n        Detection[\"🔍 Platform Detection\u003cbr/\u003eContextServerService\"]\n        Strategy[\"⚡ Context Strategy\u003cbr/\u003eprovideContextService\"]\n        Render[\"🎨 Adaptive SSR\u003cbr/\u003ePlatform-specific UI\"]\n    end\n\n    subgraph Response [\"📦 Optimized Response\"]\n        HTMLBundle[\"📄 Context-specific HTML\"]\n        JSBundle[\"⚡ Minimal JS Bundle\"]\n        Resources[\"🎨 Platform Assets\"]\n    end\n\n    subgraph Client [\"💻 Client Hydration\"]\n        Hydration[\"🔄 Perfect Hydration\u003cbr/\u003eZero Layout Shift\"]\n        Enhancement[\"✨ Progressive Enhancement\"]\n    end\n\n    Request --\u003e Detection\n    Detection --\u003e Strategy\n    Strategy --\u003e Render\n    Render --\u003e Response\n    Response --\u003e Hydration\n    Hydration --\u003e Enhancement\n```\n\n#### 🧠 **Zero Hydration Mismatch**\n\n- Server renderiza **exactamente** la misma UI que el cliente espera\n- Eliminación completa de layout shifts\n- Hydratación perfecta sin re-renders\n\n### Context Detection Logic\n\nEl sistema detecta automáticamente el contexto de ejecución mediante múltiples estrategias:\n\n#### **🔍 Server-Side Detection**\n\n- **Referer Analysis**: `android-app://` indica TWA origin\n- **User-Agent Parsing**: Patrones específicos de PWA/TWA\n- **Cookie Persistence**: Mantiene contexto entre navegaciones\n\n#### **📱 Client-Side Enhancement**\n\n- **Document.referrer**: Validación client-side\n- **navigator.userAgent**: Detección de user agent\n- **Navigator API**: Hardware-specific optimizations\n\n### Digital Asset Links \u0026 Security\n\n```json\n// .well-known/assetlinks.json - Validación de propiedad\n[\n  {\n    \"relation\": [\"delegate_permission/common.handle_all_urls\"],\n    \"target\": {\n      \"namespace\": \"android_app\",\n      \"package_name\": \"com.yourapp.twa\",\n      \"sha256_cert_fingerprints\": [\"YOUR_CERT_FINGERPRINT\"]\n    }\n  }\n]\n```\n\n### Analytics \u0026 Monitoring Diferenciado\n\n```typescript\n// Tracking context-aware para insights únicos\nexport class AnalyticsService {\n  trackContextSpecificEvent(event: string, data: any) {\n    const context = this.contextService.getContext();\n\n    gtag(\"event\", event, {\n      ...data,\n      context_type: context,\n    });\n  }\n}\n```\n\n### Casos de Uso Ideales\n\n#### **🛒 E-commerce**\n\n- **Web**: Experiencia completa con comparación de productos\n- **PWA**: Optimizada para compras offline y notificaciones\n- **TWA**: Experiencia nativa con integración de pagos Android\n\n#### **📰 Media \u0026 Content**\n\n- **Web**: Layout expansivo con sidebar y múltiples secciones\n- **PWA**: Lectura offline y sincronización de contenido\n- **TWA**: Experiencia inmersiva sin distracciones del browser\n\n### Ventajas Competitivas\n\n#### **vs. Desarrollo Tradicional Multi-Platform**\n\n- ✅ **menos** código duplicado\n- ✅ **menos** tiempo de desarrollo\n- ✅ **Consistencia** garantizada entre plataformas\n- ✅ **Deployment único** para todas las experiencias\n\n#### **vs. Responsive Design**\n\n- ✅ **Bundle optimization** por contexto\n- ✅ **Native UX** en TWA sin compromisos\n- ✅ **Server-side optimization** específica\n- ✅ **Zero layout shift** guarantee\n\nEsta arquitectura representa la **evolución natural del desarrollo web moderno**, donde una sola aplicación Angular puede ofrecer experiencias nativas optimizadas para web, PWA, y aplicaciones Android, manteniendo la simplicidad del desarrollo y maximizando el performance en cada contexto.\n\n\n## Generar TWA (Trusted Web Activity)\n\n### Prerrequisitos\n\nAntes de generar la TWA, asegúrate de tener instaladas las siguientes herramientas:\n\n```bash\n# Instalar Bubblewrap CLI globalmente\nnpm install -g @bubblewrap/cli\n\n# Verificar instalación\nbubblewrap --version\n```\n\n**Requisitos adicionales:**\n- Android Studio instalado y configurado\n- Java Development Kit (JDK) 8 o superior\n- Android SDK configurado con las herramientas de build\n\n### Proceso de Generación\n\n#### 1. **Validar Web App Manifest**\n\nVerifica que el manifest esté correctamente desplegado y accesible:\n\n```bash\n# Validar manifest en producción\ncurl -I https://ng-ssr-twa-adaptive.vercel.app/manifest.webmanifest\n```\n\n**URL de validación:** https://ng-ssr-twa-adaptive.vercel.app/manifest.webmanifest\n\n#### 2. **Inicializar Proyecto TWA**\n\n```bash\n# Crear el proyecto TWA con el manifest\nbubblewrap init --manifest=https://ng-ssr-twa-adaptive.vercel.app/manifest.webmanifest\n```\n\n#### 3. **Configuración Context-Aware**\n\n**Aspecto Crítico:** Configura la URL de inicio para aprovechar la arquitectura context-aware:\n\n```bash\n# Durante la inicialización, configurar:\nStart URL: /?ctx=twa\n```\n\nEsta configuración permite que:\n- El servidor detecte automáticamente el contexto TWA\n- Se renderice la UI optimizada para experiencia nativa\n- Se apliquen las optimizaciones específicas de Android\n\n#### 4. **Configurar Digital Asset Links**\n\nAsegúrate de que el archivo `.well-known/assetlinks.json` esté correctamente configurado en tu dominio para establecer la relación de confianza entre la app web y la TWA.\n\n#### 5. **Generar APK**\n\n```bash\n# Construir la aplicación Android\nbubblewrap build\n\n# Para builds de release (Google Play)\nbubblewrap build --release\n```\n\n### Configuraciones Avanzadas\n\n#### **Personalización del Context Parameter**\n\nSi modificas el parámetro de contexto en el `ContextService`, actualiza correspondientemente la URL de inicio:\n\n```typescript\n// Si cambias en el service de: 'ctx=twa' a 'ctx=android'\n// Actualiza la Start URL a: /?ctx=android\n```\n\n### Deployment y Testing\n\n#### **Testing Local**\n\n```bash\n# Instalar APK en dispositivo/emulador\nadb install app-release-signed.apk\n\n# Debug con Chrome DevTools\nchrome://inspect/#devices\n```\n\n#### **Validación de Contexto**\n\nVerifica que la detección funcione correctamente:\n1. Abrir la TWA en dispositivo Android\n2. Verificar que se muestre la UI optimizada para contexto nativo\n3. Confirmar que analytics trackee correctamente el contexto 'twa'\n\n### Recursos Adicionales\n\n- **[Google Codelabs - PWA to Play Store](https://developers.google.com/codelabs/pwa-in-play)**\n- **[Bubblewrap Documentation](https://github.com/GoogleChromeLabs/bubblewrap)**\n- **[Digital Asset Links](https://developers.google.com/digital-asset-links)**\n- **[TWA Best Practices](https://web.dev/trusted-web-activity/)**","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskyzerozx%2Fng-ssr-twa-adaptive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskyzerozx%2Fng-ssr-twa-adaptive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskyzerozx%2Fng-ssr-twa-adaptive/lists"}