@donotdev/cli 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dependencies-matrix.json +234 -114
- package/dist/bin/commands/build.js +9 -3
- package/dist/bin/commands/bump.js +119 -100
- package/dist/bin/commands/cacheout.js +9 -3
- package/dist/bin/commands/create-app.js +60 -34
- package/dist/bin/commands/create-project.js +61 -34
- package/dist/bin/commands/deploy.js +22 -14
- package/dist/bin/commands/dev.js +9 -3
- package/dist/bin/commands/emu.js +9 -3
- package/dist/bin/commands/format.js +9 -3
- package/dist/bin/commands/lint.js +9 -3
- package/dist/bin/commands/make-admin.d.ts +11 -0
- package/dist/bin/commands/make-admin.d.ts.map +1 -0
- package/dist/bin/commands/make-admin.js +12 -0
- package/dist/bin/commands/make-admin.js.map +1 -0
- package/dist/bin/commands/preview.js +9 -3
- package/dist/bin/commands/sync-secrets.js +9 -3
- package/dist/index.js +72 -44
- package/package.json +1 -1
- package/templates/app-demo/index.html.example +4 -0
- package/templates/app-demo/src/App.tsx.example +28 -10
- package/templates/app-demo/src/config/app.ts.example +56 -0
- package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +5 -5
- package/templates/app-next/src/app/ClientLayout.tsx.example +5 -4
- package/templates/app-next/src/app/layout.tsx.example +17 -25
- package/templates/app-next/src/globals.css.example +10 -7
- package/templates/app-next/src/locales/dndev_en.json.example +68 -0
- package/templates/app-next/src/pages/locales/example_en.json.example +5 -0
- package/templates/app-vite/index.html.example +3 -0
- package/templates/app-vite/src/App.tsx.example +1 -1
- package/templates/app-vite/src/globals.css.example +14 -6
- package/templates/app-vite/src/locales/dndev_en.json.example +68 -0
- package/templates/functions-firebase/README.md.example +25 -0
- package/templates/functions-firebase/tsconfig.json.example +3 -13
- package/templates/functions-vercel/tsconfig.json.example +1 -13
- package/templates/root-consumer/firebase.json.example +1 -1
- package/templates/root-consumer/guides/AGENT_START_HERE.md.example +229 -7
- package/templates/root-consumer/guides/COMPONENTS_ADV.md.example +456 -0
- package/templates/root-consumer/guides/COMPONENTS_ATOMIC.md.example +43 -1
- package/templates/root-consumer/guides/COMPONENTS_UI.md.example +6 -0
- package/templates/root-consumer/guides/INDEX.md.example +3 -0
- package/templates/root-consumer/guides/SETUP_APP_CONFIG.md.example +5 -2
- package/templates/root-consumer/guides/SETUP_BILLING.md.example +44 -4
- package/templates/root-consumer/guides/SETUP_CRUD.md.example +1244 -0
- package/templates/root-consumer/guides/SETUP_FUNCTIONS.md.example +52 -0
- package/templates/root-consumer/guides/SETUP_I18N.md.example +145 -6
- package/templates/root-consumer/guides/SETUP_LAYOUTS.md.example +18 -0
- package/templates/root-consumer/guides/SETUP_PAGES.md.example +25 -0
- package/templates/root-consumer/guides/SETUP_PWA.md.example +213 -0
- package/templates/root-consumer/guides/USE_ROUTING.md.example +503 -0
- package/templates/root-consumer/vercel.json.example +315 -20
- package/templates/app-demo/src/Routes.tsx.example +0 -20
- package/templates/app-vite/src/Routes.tsx.example +0 -16
- package/templates/app-vite/src/pages/locales/README.md.example +0 -1
|
@@ -4,6 +4,31 @@
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## ⚠️ CRITICAL: Import Rules for Functions
|
|
8
|
+
|
|
9
|
+
**Functions run on Node.js - you MUST use `/server` imports or your function will crash on deploy.**
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
// ✅ CORRECT - Functions MUST use /server imports
|
|
13
|
+
import { getFirebaseAdminAuth } from '@donotdev/firebase/server';
|
|
14
|
+
import { getFirebaseAdminFirestore } from '@donotdev/firebase/server';
|
|
15
|
+
import { handleError } from '@donotdev/core/server';
|
|
16
|
+
|
|
17
|
+
// ❌ WRONG - This will crash on deploy (pulls in React/client code)
|
|
18
|
+
import { getAuth } from '@donotdev/firebase';
|
|
19
|
+
import { getFirestore } from '@donotdev/firebase';
|
|
20
|
+
import { handleError } from '@donotdev/core';
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Why?** Functions run in Node.js, not the browser. Client imports (`@donotdev/firebase`) include React and browser-only code that will crash your function.
|
|
24
|
+
|
|
25
|
+
**Rule:** Always use `/server` suffix for:
|
|
26
|
+
- `@donotdev/firebase/server` (not `@donotdev/firebase`)
|
|
27
|
+
- `@donotdev/core/server` (not `@donotdev/core`)
|
|
28
|
+
- `@donotdev/utils/server` (not `@donotdev/utils`)
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
7
32
|
## Standard Use
|
|
8
33
|
|
|
9
34
|
**Structure:**
|
|
@@ -59,4 +84,31 @@ export const createCheckoutSession = generic(stripeBackConfig);
|
|
|
59
84
|
|
|
60
85
|
---
|
|
61
86
|
|
|
87
|
+
## Advanced: Custom Functions with Firebase
|
|
88
|
+
|
|
89
|
+
**When writing custom functions that access Firestore/Auth, use `/server` imports:**
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { onCall } from 'firebase-functions/v2/https';
|
|
93
|
+
import { FUNCTION_CONFIG } from '@donotdev/functions/firebase';
|
|
94
|
+
// ✅ MUST use /server imports in functions
|
|
95
|
+
import { getFirebaseAdminFirestore } from '@donotdev/firebase/server';
|
|
96
|
+
import { getFirebaseAdminAuth } from '@donotdev/firebase/server';
|
|
97
|
+
import { handleError } from '@donotdev/core/server';
|
|
98
|
+
|
|
99
|
+
export const myCustomFunction = onCall(FUNCTION_CONFIG, async (request) => {
|
|
100
|
+
const firestore = getFirebaseAdminFirestore();
|
|
101
|
+
const auth = getFirebaseAdminAuth();
|
|
102
|
+
|
|
103
|
+
// Your custom logic here
|
|
104
|
+
const doc = await firestore.collection('users').doc(request.auth.uid).get();
|
|
105
|
+
|
|
106
|
+
return { data: doc.data() };
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Remember:** All Firebase imports in functions MUST use `@donotdev/firebase/server`, never `@donotdev/firebase`.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
62
114
|
**Add functions, get backend. Framework handles the rest.**
|
|
@@ -4,15 +4,81 @@
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## Translation File Locations (CRITICAL)
|
|
8
|
+
|
|
9
|
+
**Two paths - choose based on when translations are needed:**
|
|
10
|
+
|
|
11
|
+
1. **Eager (`src/locales/`)**: Always loaded - use for common UI, navigation, app-wide content
|
|
12
|
+
2. **Lazy (`src/pages/locales/`)**: Loaded when page loads - use for page-specific content
|
|
13
|
+
|
|
14
|
+
**✅ RULE OF THUMB:**
|
|
15
|
+
- **Eager**: Navigation, buttons, common messages (used everywhere)
|
|
16
|
+
- **Lazy**: Page content, feature content, large text blocks (used on specific pages)
|
|
17
|
+
|
|
18
|
+
**Framework auto-discovers both paths. No configuration needed.**
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
7
22
|
## Standard Use
|
|
8
23
|
|
|
9
|
-
**
|
|
24
|
+
**CRITICAL: Two Translation Paths - Choose Based on When Translations Are Needed**
|
|
25
|
+
|
|
26
|
+
### Eager Translations (Always Loaded)
|
|
27
|
+
**Path:** `src/locales/<namespace>_<2-char-ISO>.json`
|
|
28
|
+
|
|
29
|
+
**Use for:**
|
|
30
|
+
- Common UI elements (buttons, labels, navigation)
|
|
31
|
+
- Critical app-wide translations (app name, common messages)
|
|
32
|
+
- Translations needed on every page
|
|
33
|
+
|
|
34
|
+
**Example:**
|
|
35
|
+
```
|
|
36
|
+
src/
|
|
37
|
+
locales/
|
|
38
|
+
common_en.json # ✅ Eager - always available
|
|
39
|
+
common_fr.json
|
|
40
|
+
navigation_en.json # ✅ Eager - used in header/sidebar
|
|
41
|
+
navigation_fr.json
|
|
42
|
+
```
|
|
10
43
|
|
|
44
|
+
### Lazy Translations (Loaded When Page Loads)
|
|
45
|
+
**Path:** `src/pages/locales/<namespace>_<2-char-ISO>.json`
|
|
46
|
+
|
|
47
|
+
**Use for:**
|
|
48
|
+
- Page-specific content (page titles, descriptions, page content)
|
|
49
|
+
- Feature-specific translations (dashboard, blog, admin)
|
|
50
|
+
- Translations only needed when that page/feature is accessed
|
|
51
|
+
|
|
52
|
+
**Example:**
|
|
53
|
+
```
|
|
54
|
+
src/
|
|
55
|
+
pages/
|
|
56
|
+
HomePage.tsx
|
|
57
|
+
locales/
|
|
58
|
+
home_en.json # ✅ Lazy - loaded when HomePage loads
|
|
59
|
+
home_fr.json
|
|
60
|
+
dashboard/
|
|
61
|
+
DashboardPage.tsx
|
|
62
|
+
locales/
|
|
63
|
+
dashboard_en.json # ✅ Lazy - loaded when DashboardPage loads
|
|
64
|
+
dashboard_fr.json
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**✅ DECISION GUIDE:**
|
|
68
|
+
- **Eager (`src/locales/`)**: Navigation, common buttons, app-wide messages
|
|
69
|
+
- **Lazy (`src/pages/locales/`)**: Page content, feature-specific content, large text blocks
|
|
70
|
+
|
|
71
|
+
**Usage:**
|
|
11
72
|
```tsx
|
|
12
73
|
import { useTranslation } from '@donotdev/core';
|
|
13
74
|
|
|
14
|
-
|
|
15
|
-
t('
|
|
75
|
+
// Eager namespace (common, navigation, etc.)
|
|
76
|
+
const { t } = useTranslation('common');
|
|
77
|
+
t('app.title');
|
|
78
|
+
|
|
79
|
+
// Lazy namespace (page-specific)
|
|
80
|
+
const { t } = useTranslation('home');
|
|
81
|
+
t('hero.title');
|
|
16
82
|
```
|
|
17
83
|
|
|
18
84
|
**LanguageSelector:** Included in layout presets. Import from `@donotdev/core` if needed elsewhere.
|
|
@@ -21,14 +87,87 @@ t('title');
|
|
|
21
87
|
|
|
22
88
|
## Advanced: Array Translations
|
|
23
89
|
|
|
90
|
+
### Low-level: translateArray
|
|
91
|
+
|
|
24
92
|
```tsx
|
|
25
93
|
import { translateArray, translateObjectArray, maybeTranslate } from '@donotdev/core';
|
|
26
94
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
95
|
+
// Get array of strings (filters missing translations automatically)
|
|
96
|
+
const benefits = translateArray(t, 'benefits', 10); // Up to 10 items (benefits.0-9), safe if only 4 exist
|
|
97
|
+
const features = translateArray(t, 'features.list', 5); // Nested keys work
|
|
98
|
+
|
|
99
|
+
// Get array of objects
|
|
100
|
+
const cases = translateObjectArray(t, 'cases', 10, ['useCase', 'bestFit']);
|
|
101
|
+
|
|
102
|
+
// Auto-detect if value is a translation key or literal string
|
|
103
|
+
maybeTranslate(t, 'products.earlyBird.name');
|
|
30
104
|
```
|
|
31
105
|
|
|
106
|
+
### High-level: tList (Recommended for Cards)
|
|
107
|
+
|
|
108
|
+
`tList` wraps `translateArray` and returns a `List` component ready for `Card` content:
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
import { tList } from '@donotdev/ui';
|
|
112
|
+
|
|
113
|
+
// With default icon (CheckCircle)
|
|
114
|
+
<Card content={tList(t, 'features.items', 4)} />
|
|
115
|
+
|
|
116
|
+
// With custom icon
|
|
117
|
+
<Card content={tList(t, 'features.items', 4, Star)} />
|
|
118
|
+
|
|
119
|
+
// Without icon (for emoji-prefixed labels like "🚀 Kick-off")
|
|
120
|
+
<Card content={tList(t, 'features.items', 4, null)} />
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**JSON structure:**
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"features": {
|
|
127
|
+
"items": [
|
|
128
|
+
"Feature 1",
|
|
129
|
+
"Feature 2",
|
|
130
|
+
"Feature 3"
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Advanced: Rich Text (Trans)
|
|
139
|
+
|
|
140
|
+
For inline styling in translations, use `Trans` instead of `t()`. Use when translations contain HTML-like tags for styling.
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
import { Trans } from '@donotdev/core';
|
|
144
|
+
|
|
145
|
+
// Translation: "<accent>MVP</accent> in 2 weeks"
|
|
146
|
+
<HeroSection title={<Trans ns={NAMESPACE} i18nKey="hero.title" />} />
|
|
147
|
+
|
|
148
|
+
// Translation: "I need <accent>Clarity</accent>"
|
|
149
|
+
<Card title={<Trans ns={NAMESPACE} i18nKey="products.transformation.title" />} />
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**JSON with tags:**
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"hero": {
|
|
156
|
+
"title": "Idea to <accent>MVP</accent> in 2 weeks"
|
|
157
|
+
},
|
|
158
|
+
"products": {
|
|
159
|
+
"transformation": {
|
|
160
|
+
"title": "I need <accent>Clarity</accent>",
|
|
161
|
+
"subtitle": "...for a <accent>critical</accent> application"
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Supported tags:** `<accent>` `<primary>` `<muted>` `<success>` `<warning>` `<error>` `<bold>` `<code>`
|
|
168
|
+
|
|
169
|
+
**Note:** `Trans` accepts `ns` prop (string) for namespace. Use `t()` for plain strings, `Trans` for rich text with styling tags.
|
|
170
|
+
|
|
32
171
|
---
|
|
33
172
|
|
|
34
173
|
## Advanced: I18N Components
|
|
@@ -18,6 +18,24 @@ export const appConfig: AppConfig = {
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
+
## Preset Capabilities
|
|
22
|
+
|
|
23
|
+
**The `docs` preset AUTOMATICALLY generates sidebar navigation from your `src/pages` files. You do not need to configure a sidebar manually.**
|
|
24
|
+
|
|
25
|
+
All presets automatically include these components when applicable:
|
|
26
|
+
|
|
27
|
+
* **LanguageSelector** - Automatically shown if more than 1 language is configured
|
|
28
|
+
* **ThemeToggle** - Automatically shown if more than 1 theme is available
|
|
29
|
+
* **AuthMenu** - Automatically shown if auth is configured in `.env` (Firebase keys present)
|
|
30
|
+
* **Navigation Menu** - Automatically generated from `src/pages/*Page.tsx` files for sidebars
|
|
31
|
+
* **GoTo Component** - Command palette (Cmd+K) for quick navigation - always available
|
|
32
|
+
* **Footer** - Automatic footer with copyright and legal links
|
|
33
|
+
* **LegalLinks + Copyright** - Automatically included in footer from `config/legal.ts`
|
|
34
|
+
|
|
35
|
+
**You don't need to add these manually - the framework handles them based on your configuration.**
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
21
39
|
## Advanced: Slot Overrides
|
|
22
40
|
|
|
23
41
|
**Customize zones:**
|
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## File Routing Rule
|
|
8
|
+
|
|
9
|
+
**CRITICAL: Only files ending in `Page.tsx` inside `src/pages` become routes.**
|
|
10
|
+
|
|
11
|
+
Files must be named `*Page.tsx` (e.g., `HomePage.tsx`, `AboutPage.tsx`, `BlogPostPage.tsx`). Files without the `Page.tsx` suffix are ignored by the routing system.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
7
15
|
## Standard Use
|
|
8
16
|
|
|
9
17
|
**Pattern:** `src/pages/**/*Page.tsx` → routes
|
|
@@ -103,8 +111,25 @@ import { useNavigate, Link } from '@donotdev/ui';
|
|
|
103
111
|
const navigate = useNavigate();
|
|
104
112
|
navigate('/about');
|
|
105
113
|
<Link path="/about">About</Link>
|
|
114
|
+
|
|
115
|
+
// Card with navigation (supports middle-click)
|
|
116
|
+
import { Card } from '@donotdev/components';
|
|
117
|
+
import { Link } from '@donotdev/ui';
|
|
118
|
+
|
|
119
|
+
<Link
|
|
120
|
+
path="/about"
|
|
121
|
+
style={{ display: 'block', textDecoration: 'none', height: '100%' }}
|
|
122
|
+
aria-label="Learn more about About"
|
|
123
|
+
>
|
|
124
|
+
<Card title="About" subtitle="Learn more" />
|
|
125
|
+
</Link>
|
|
106
126
|
```
|
|
107
127
|
|
|
128
|
+
**Navigation patterns:**
|
|
129
|
+
- **Link component:** Use for text links, buttons, or wrapping other components
|
|
130
|
+
- **Card navigation:** Wrap Card in Link for clickable cards with middle-click support
|
|
131
|
+
- **onClick only:** Use `onClick={() => navigate()}` for actions that don't need middle-click
|
|
132
|
+
|
|
108
133
|
**Pre-configured:** Navigation menu auto-generated, sitemap auto-built (if `generateSitemap: true`).
|
|
109
134
|
|
|
110
135
|
---
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# PWA Setup
|
|
2
|
+
|
|
3
|
+
**For AI Agents:** Enable PWA in config, add required app metadata. Framework handles service worker, manifest, and caching.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
### 1. Add Required App Metadata
|
|
10
|
+
|
|
11
|
+
PWA requires `name`, `shortName`, and `description` in your app config:
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
// src/config/app.ts
|
|
15
|
+
import type { AppConfig } from '@donotdev/core';
|
|
16
|
+
|
|
17
|
+
export const appConfig: AppConfig = {
|
|
18
|
+
app: {
|
|
19
|
+
name: 'My App', // Full app name (required for PWA)
|
|
20
|
+
shortName: 'App', // Short name for home screen (required for PWA)
|
|
21
|
+
description: 'My app description', // App description (required for PWA)
|
|
22
|
+
url: 'https://myapp.com',
|
|
23
|
+
},
|
|
24
|
+
// ... rest of config
|
|
25
|
+
};
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 2. Enable PWA in Build Config
|
|
29
|
+
|
|
30
|
+
**For Vite apps:**
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
// vite.config.ts
|
|
34
|
+
import { defineViteConfig } from '@donotdev/core/vite';
|
|
35
|
+
import { appConfig } from './src/config/app';
|
|
36
|
+
|
|
37
|
+
export default defineViteConfig({
|
|
38
|
+
appConfig,
|
|
39
|
+
pwa: {
|
|
40
|
+
enabled: true, // Enable PWA in production builds
|
|
41
|
+
devEnabled: false, // Enable PWA in development (optional)
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**For Next.js apps:**
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
// next.config.ts
|
|
50
|
+
import { defineNextConfig } from '@donotdev/core/next';
|
|
51
|
+
import { appConfig } from './src/config/app';
|
|
52
|
+
|
|
53
|
+
export default defineNextConfig({
|
|
54
|
+
appConfig,
|
|
55
|
+
pwa: {
|
|
56
|
+
enabled: true, // Enable PWA in production builds
|
|
57
|
+
devEnabled: false, // Enable PWA in development (optional)
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Done.** Framework automatically:
|
|
63
|
+
- Generates `manifest.json` from app metadata
|
|
64
|
+
- Creates service worker with Workbox
|
|
65
|
+
- Discovers and precaches app icons
|
|
66
|
+
- Sets up offline caching strategies
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## What Gets Auto-Generated
|
|
71
|
+
|
|
72
|
+
### Manifest (`manifest.json`)
|
|
73
|
+
- **Name & description:** From `appConfig.app.name`, `shortName`, `description`
|
|
74
|
+
- **Icons:** Auto-discovered from `public/` folder (favicon, apple-touch-icon, etc.)
|
|
75
|
+
- **Theme colors:** Defaults to white background, black theme (customizable)
|
|
76
|
+
- **Display mode:** `standalone` (app-like experience)
|
|
77
|
+
|
|
78
|
+
### Service Worker (`sw.js`)
|
|
79
|
+
- **Precaching:** All JS, CSS, HTML, icons, and fonts
|
|
80
|
+
- **Runtime caching:** Smart defaults for API calls and images
|
|
81
|
+
- **Offline support:** Navigation fallback to `/`
|
|
82
|
+
- **Update strategy:** Prompts user to update when new version available
|
|
83
|
+
|
|
84
|
+
### Icons
|
|
85
|
+
Framework discovers icons from:
|
|
86
|
+
- `public/favicon.svg` or `public/favicon.ico`
|
|
87
|
+
- `public/apple-touch-icon.png`
|
|
88
|
+
- Any icons generated by AssetPlugin
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Optional Configuration
|
|
93
|
+
|
|
94
|
+
### Custom Manifest Values
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// vite.config.ts or next.config.ts
|
|
98
|
+
export default defineViteConfig({
|
|
99
|
+
appConfig,
|
|
100
|
+
pwa: {
|
|
101
|
+
enabled: true,
|
|
102
|
+
manifest: {
|
|
103
|
+
// Override any manifest values
|
|
104
|
+
theme_color: '#667eea',
|
|
105
|
+
background_color: '#ffffff',
|
|
106
|
+
display: 'standalone',
|
|
107
|
+
orientation: 'portrait',
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Custom Workbox Configuration
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
pwa: {
|
|
117
|
+
enabled: true,
|
|
118
|
+
workbox: {
|
|
119
|
+
// Maximum file size to cache (default: 5MB)
|
|
120
|
+
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
|
|
121
|
+
|
|
122
|
+
// Custom precache patterns
|
|
123
|
+
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}'],
|
|
124
|
+
globIgnores: ['**/node_modules/**'],
|
|
125
|
+
|
|
126
|
+
// Runtime caching strategies
|
|
127
|
+
runtimeCaching: [
|
|
128
|
+
{
|
|
129
|
+
urlPattern: /^https:\/\/api\.example\.com\/.*/i,
|
|
130
|
+
handler: 'NetworkFirst',
|
|
131
|
+
options: {
|
|
132
|
+
cacheName: 'api-cache',
|
|
133
|
+
expiration: {
|
|
134
|
+
maxEntries: 50,
|
|
135
|
+
maxAgeSeconds: 60 * 60, // 1 hour
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Development Mode
|
|
145
|
+
|
|
146
|
+
Enable PWA in development for testing:
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
pwa: {
|
|
150
|
+
enabled: true,
|
|
151
|
+
devEnabled: true, // Enable service worker in dev mode
|
|
152
|
+
debug: true, // Enable debug logging
|
|
153
|
+
},
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Note:** Service workers require HTTPS (or localhost). Use `server: { https: true }` in Vite config for local HTTPS.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Testing PWA
|
|
161
|
+
|
|
162
|
+
1. **Build for production:**
|
|
163
|
+
```bash
|
|
164
|
+
bun run build
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
2. **Serve production build:**
|
|
168
|
+
```bash
|
|
169
|
+
bun run preview # Vite
|
|
170
|
+
# or
|
|
171
|
+
bun run start # Next.js
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
3. **Test in browser:**
|
|
175
|
+
- Open DevTools → Application → Service Workers
|
|
176
|
+
- Check "Offline" checkbox to test offline mode
|
|
177
|
+
- Verify manifest in Application → Manifest
|
|
178
|
+
- Test "Add to Home Screen" prompt
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Requirements Checklist
|
|
183
|
+
|
|
184
|
+
- [ ] `appConfig.app.name` defined
|
|
185
|
+
- [ ] `appConfig.app.shortName` defined
|
|
186
|
+
- [ ] `appConfig.app.description` defined
|
|
187
|
+
- [ ] `pwa.enabled: true` in build config
|
|
188
|
+
- [ ] Icons in `public/` folder (auto-discovered)
|
|
189
|
+
- [ ] HTTPS in production (required for service workers)
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Troubleshooting
|
|
194
|
+
|
|
195
|
+
**PWA not working:**
|
|
196
|
+
- Check browser console for service worker errors
|
|
197
|
+
- Verify HTTPS (required except localhost)
|
|
198
|
+
- Check manifest.json exists in build output
|
|
199
|
+
- Verify app metadata is complete
|
|
200
|
+
|
|
201
|
+
**Icons not showing:**
|
|
202
|
+
- Ensure icons exist in `public/` folder
|
|
203
|
+
- Check icon formats (SVG, PNG, ICO supported)
|
|
204
|
+
- Verify AssetPlugin discovered icons (check build logs)
|
|
205
|
+
|
|
206
|
+
**Service worker not registering:**
|
|
207
|
+
- Check browser console for registration errors
|
|
208
|
+
- Verify HTTPS (service workers require secure context)
|
|
209
|
+
- Clear browser cache and hard refresh
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
**Zero config. Override when needed.**
|