create-react-adam 0.5.1 → 0.6.1

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/README.md CHANGED
@@ -19,6 +19,7 @@ Running without flags opens an interactive wizard where you pick features
19
19
  │ ◼ Utility functions (classNames, Storage, useUrlState, safeTimeout)
20
20
  │ ◼ Lighthouse CI workflow (a11y/SEO/performance budgets)
21
21
  │ ◼ ESLint rule: prefer WebP images
22
+ │ ◼ PWA (installable app + offline support via vite-plugin-pwa)
22
23
 
23
24
  ```
24
25
 
@@ -42,8 +43,9 @@ Running without flags opens an interactive wizard where you pick features
42
43
  - `--with-utils` / `--no-utils` - Include or skip utility functions
43
44
  - `--with-lighthouse` / `--no-lighthouse` - Include or skip the Lighthouse CI workflow
44
45
  - `--with-webp-lint` / `--no-webp-lint` - Include or skip the prefer-webp-images ESLint rule
46
+ - `--with-pwa` / `--no-pwa` - Include or skip PWA support (installable, works offline)
45
47
 
46
- Any feature answered by a flag is removed from the wizard; if all four are
48
+ Any feature answered by a flag is removed from the wizard; if all five are
47
49
  answered, the wizard is skipped entirely.
48
50
 
49
51
  ## What's Included
@@ -67,7 +69,7 @@ Every generated project starts with:
67
69
  idle prefetcher warms the rest after first paint (documented in the
68
70
  generated README, easy to remove)
69
71
  - **SEO-ready `index.html`** - meta description, Open Graph and Twitter card
70
- tags, theme-color, plus a `public/robots.txt`
72
+ tags, theme-color, an SVG favicon, plus a `public/robots.txt`
71
73
  - **Accessible shell** - skip-to-content link, `<main>` landmark, visible
72
74
  `:focus-visible` styles, and per-route document titles
73
75
 
@@ -102,6 +104,22 @@ When you include E2E testing (via wizard or `--with-e2e` flag), you get:
102
104
  - Pre-configured test setup with example tests
103
105
  - HTML reports and Allure integration
104
106
 
107
+ ### Optional PWA Support
108
+
109
+ When you include PWA support (via wizard or `--with-pwa` flag), the app
110
+ becomes an installable Progressive Web App:
111
+
112
+ - **vite-plugin-pwa** configured in `vite.config.ts`, with comments explaining
113
+ every option
114
+ - Production builds generate a precaching service worker (`dist/sw.js`) and a
115
+ web app manifest (`dist/manifest.webmanifest`); the registration script is
116
+ injected into `index.html` automatically
117
+ - The app shell (JS, CSS, HTML, SVG, fonts) works offline after the first
118
+ visit, and client-side routes fall back to the cached `index.html`
119
+ - `registerType: "autoUpdate"` means new deployments replace the old service
120
+ worker automatically — no "refresh to update" prompt
121
+ - Dev mode is unchanged: the service worker only exists in production builds
122
+
105
123
  ### Git Integration
106
124
 
107
125
  After scaffolding (when not already inside a git repository), the CLI:
@@ -202,6 +220,7 @@ Runs basic troubleshooting checks:
202
220
  ```
203
221
  my-app/
204
222
  ├── public/
223
+ │ ├── favicon.svg # App icon (also used by the PWA manifest)
205
224
  │ ├── fonts/ # Self-hosted Inter (variable woff2)
206
225
  │ └── robots.txt
207
226
  ├── src/
package/bin/index.js CHANGED
@@ -32,6 +32,11 @@ const FEATURES = [
32
32
  id: 'webpLint',
33
33
  flag: 'webp-lint',
34
34
  label: 'ESLint rule: prefer WebP images'
35
+ },
36
+ {
37
+ id: 'pwa',
38
+ flag: 'pwa',
39
+ label: 'PWA (installable app + offline support via vite-plugin-pwa)'
35
40
  }
36
41
  ];
37
42
 
@@ -97,6 +102,8 @@ function printUsage() {
97
102
  console.log(' --no-lighthouse Skip Lighthouse CI workflow');
98
103
  console.log(' --with-webp-lint Include the prefer-webp-images ESLint rule');
99
104
  console.log(' --no-webp-lint Skip the prefer-webp-images ESLint rule');
105
+ console.log(' --with-pwa Include PWA support (installable, works offline)');
106
+ console.log(' --no-pwa Skip PWA support');
100
107
  }
101
108
 
102
109
  async function resolveFeatures(flags) {
@@ -339,6 +346,22 @@ async function main() {
339
346
  }
340
347
  await rm(noWebpConfigPath);
341
348
 
349
+ // Resolve the vite config variant: the template's vite.config.ts is the
350
+ // PWA version (vite-plugin-pwa + web app manifest); vite.config.no-pwa.ts
351
+ // is the plain version used when the PWA feature is skipped. When PWA is
352
+ // off, also drop the now-unused vite-plugin-pwa devDependency so it never
353
+ // gets installed.
354
+ const noPwaConfigPath = join(projectPath, 'vite.config.no-pwa.ts');
355
+ if (!features.pwa) {
356
+ await copyFile(noPwaConfigPath, join(projectPath, 'vite.config.ts'));
357
+
358
+ const pkgPath = join(projectPath, 'package.json');
359
+ const pkg = JSON.parse(await readFile(pkgPath, 'utf-8'));
360
+ delete pkg.devDependencies['vite-plugin-pwa'];
361
+ await writeFile(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`, 'utf-8');
362
+ }
363
+ await rm(noPwaConfigPath);
364
+
342
365
  // README.md uses {{PROJECT_NAME}} because Prettier's markdown formatter
343
366
  // rewrites __PROJECT_NAME__ (underscore emphasis) to **PROJECT_NAME**.
344
367
  const replacements = {
@@ -350,6 +373,9 @@ async function main() {
350
373
  'package.json',
351
374
  'index.html',
352
375
  'README.md',
376
+ // vite.config.ts only has placeholders in its PWA variant (the web app
377
+ // manifest name); replacing is a harmless no-op otherwise.
378
+ 'vite.config.ts',
353
379
  join('src', 'pages', 'Home', 'index.tsx'),
354
380
  join('src', 'pages', 'About', 'index.tsx'),
355
381
  join('src', 'pages', 'NotFound', 'index.tsx')
@@ -395,6 +421,13 @@ async function main() {
395
421
  console.log(' Generates and opens Allure report.\n');
396
422
  }
397
423
 
424
+ if (features.pwa) {
425
+ console.log(
426
+ 'PWA support is on: production builds generate a service worker and web' +
427
+ '\napp manifest (configured in vite.config.ts); dev mode is unaffected.\n'
428
+ );
429
+ }
430
+
398
431
  console.log('We suggest that you begin by typing:\n');
399
432
  console.log(` cd ${projectName}`);
400
433
  console.log(' npm run dev\n');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-react-adam",
3
- "version": "0.5.1",
3
+ "version": "0.6.1",
4
4
  "description": "Create opinionated React apps with TypeScript, Vite, Wouter, and Tailwind CSS",
5
5
  "type": "module",
6
6
  "bin": {
@@ -122,10 +122,33 @@ location makes it smooth.
122
122
  - **Fonts**: Inter is self-hosted from `public/fonts/` (variable `woff2`,
123
123
  `font-display: swap`, preloaded in `index.html`). No third-party requests.
124
124
  - **SEO**: `index.html` ships meta description, Open Graph, and Twitter card
125
- tags — update them as your app takes shape. `public/robots.txt` is included.
125
+ tags — update them as your app takes shape. `public/robots.txt` and an SVG
126
+ favicon (`public/favicon.svg`) are included.
126
127
  - **Accessibility**: a skip-to-content link, `<main>` landmark, and visible
127
128
  `:focus-visible` styles are wired into `App.tsx` / `app.css`.
128
129
 
130
+ ## PWA (if included)
131
+
132
+ This app is a Progressive Web App: browsers offer an "Install" option, and
133
+ the app keeps working offline after the first visit.
134
+
135
+ - Everything is configured in `vite.config.ts` via
136
+ [vite-plugin-pwa](https://vite-pwa-org.netlify.app) — the web app manifest
137
+ (name, colors, icon) lives there too. Update it alongside the matching
138
+ values in `index.html` (`theme-color`) and `public/favicon.svg`.
139
+ - `npm run build` generates the service worker (`dist/sw.js`) and manifest
140
+ (`dist/manifest.webmanifest`) and injects the registration script into
141
+ `index.html` — no client code to maintain.
142
+ - The service worker precaches the app shell (JS, CSS, HTML, SVG, fonts) and
143
+ answers client-side routes with the cached `index.html` when offline.
144
+ - Updates are automatic (`registerType: "autoUpdate"`): a new deployment
145
+ replaces the old service worker on the user's next visit.
146
+ - Dev mode is unaffected — the service worker only exists in production
147
+ builds. Test it locally with `npm run build && npm run preview`.
148
+
149
+ To remove PWA support later: delete the `VitePWA(...)` block and its import
150
+ from `vite.config.ts`, then run `npm uninstall vite-plugin-pwa`.
151
+
129
152
  ## ESLint: prefer-webp-images (if included)
130
153
 
131
154
  A local rule in `eslint-rules/prefer-webp-images.js` errors on references to
@@ -15,6 +15,7 @@
15
15
  />
16
16
  <meta property="og:type" content="website" />
17
17
  <meta name="twitter:card" content="summary" />
18
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
18
19
  <link
19
20
  rel="preload"
20
21
  href="/fonts/InterVariable.woff2"
@@ -45,8 +45,9 @@
45
45
  "prettier-plugin-tailwindcss": "0.8.0",
46
46
  "tailwindcss": "4.3.2",
47
47
  "typescript": "6.0.3",
48
- "typescript-eslint": "8.63.0",
49
- "vite": "8.1.4"
48
+ "typescript-eslint": "8.64.0",
49
+ "vite": "8.1.4",
50
+ "vite-plugin-pwa": "1.3.0"
50
51
  },
51
52
  "overrides": {
52
53
  "eslint-plugin-jsx-a11y": {
@@ -0,0 +1,9 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
2
+ <rect width="512" height="512" rx="96" fill="#2563eb" />
3
+ <g fill="none" stroke="#ffffff" stroke-width="20">
4
+ <ellipse cx="256" cy="256" rx="176" ry="72" />
5
+ <ellipse cx="256" cy="256" rx="176" ry="72" transform="rotate(60 256 256)" />
6
+ <ellipse cx="256" cy="256" rx="176" ry="72" transform="rotate(120 256 256)" />
7
+ </g>
8
+ <circle cx="256" cy="256" r="28" fill="#ffffff" />
9
+ </svg>
@@ -0,0 +1,7 @@
1
+ import tailwindcss from "@tailwindcss/vite";
2
+ import react from "@vitejs/plugin-react";
3
+ import { defineConfig } from "vite";
4
+
5
+ export default defineConfig({
6
+ plugins: [react(), tailwindcss()],
7
+ });
@@ -1,7 +1,56 @@
1
1
  import tailwindcss from "@tailwindcss/vite";
2
2
  import react from "@vitejs/plugin-react";
3
3
  import { defineConfig } from "vite";
4
+ import { VitePWA } from "vite-plugin-pwa";
4
5
 
6
+ // PWA support (optional create-react-adam feature). vite-plugin-pwa makes
7
+ // the app installable and offline-capable: `npm run build` generates a
8
+ // service worker (dist/sw.js) that precaches the app shell, emits a web app
9
+ // manifest (dist/manifest.webmanifest), and injects the registration script
10
+ // into index.html. `npm run dev` is unaffected — the service worker only
11
+ // exists in production builds; test it locally with
12
+ // `npm run build && npm run preview`. Docs: https://vite-pwa-org.netlify.app
5
13
  export default defineConfig({
6
- plugins: [react(), tailwindcss()],
14
+ plugins: [
15
+ react(),
16
+ tailwindcss(),
17
+ VitePWA({
18
+ // New deployments take over automatically on the user's next visit —
19
+ // no "refresh to update" prompt, no stale app shell.
20
+ registerType: "autoUpdate",
21
+ workbox: {
22
+ // Precache all built JS/CSS/HTML plus SVGs and the self-hosted
23
+ // fonts, so the entire app shell works offline after the first
24
+ // visit. Add extensions here if you ship other static assets
25
+ // (e.g. png, webp) that should be available offline.
26
+ globPatterns: ["**/*.{js,css,html,svg,woff2}"],
27
+ // SPA fallback: deep links like /about are client-side routes, so
28
+ // the service worker answers them with the cached index.html when
29
+ // offline instead of failing with a network error.
30
+ navigateFallback: "index.html",
31
+ },
32
+ // The install metadata browsers read for "Install app" / "Add to
33
+ // Home Screen": the installed app's name, icon, and window colors.
34
+ manifest: {
35
+ name: "__PROJECT_NAME__",
36
+ short_name: "__PROJECT_NAME__",
37
+ description: "A React app built with create-react-adam",
38
+ // Keep in sync with the theme-color <meta> tag in index.html.
39
+ theme_color: "#2563eb",
40
+ // Splash-screen background while the app loads; matches
41
+ // --color-brand-background in src/app.css.
42
+ background_color: "#f8fafc",
43
+ display: "standalone",
44
+ icons: [
45
+ {
46
+ // SVG icons scale to any size; swap in 192x192 and 512x512
47
+ // PNGs here if you need to support older devices.
48
+ src: "/favicon.svg",
49
+ sizes: "any",
50
+ type: "image/svg+xml",
51
+ },
52
+ ],
53
+ },
54
+ }),
55
+ ],
7
56
  });