diff --git a/.changeset/plain-spies-smoke.md b/.changeset/plain-spies-smoke.md new file mode 100644 index 0000000..f90b6ae --- /dev/null +++ b/.changeset/plain-spies-smoke.md @@ -0,0 +1,5 @@ +--- +"create-better-t-stack": minor +--- + +add pwa support in nextjs diff --git a/apps/cli/src/helpers/addons-setup.ts b/apps/cli/src/helpers/addons-setup.ts index ff97c32..c538a1a 100644 --- a/apps/cli/src/helpers/addons-setup.ts +++ b/apps/cli/src/helpers/addons-setup.ts @@ -10,7 +10,9 @@ import type { ProjectConfig } from "../types"; export async function setupAddons(config: ProjectConfig) { const { addons, frontend, projectDir } = config; const hasReactWebFrontend = - frontend.includes("react-router") || frontend.includes("tanstack-router"); + frontend.includes("react-router") || + frontend.includes("tanstack-router") || + frontend.includes("next"); const hasNuxtFrontend = frontend.includes("nuxt"); const hasSvelteFrontend = frontend.includes("svelte"); const hasSolidFrontend = frontend.includes("solid"); diff --git a/apps/cli/src/helpers/template-manager.ts b/apps/cli/src/helpers/template-manager.ts index 8284647..c18d388 100644 --- a/apps/cli/src/helpers/template-manager.ts +++ b/apps/cli/src/helpers/template-manager.ts @@ -557,10 +557,20 @@ export async function setupAddonsTemplate( let addonDestDir = projectDir; if (addon === "pwa") { - addonSrcDir = path.join(PKG_ROOT, "templates/addons/pwa/apps/web"); - addonDestDir = path.join(projectDir, "apps/web"); - - if (!(await fs.pathExists(addonDestDir))) { + const webAppDir = path.join(projectDir, "apps/web"); + if (!(await fs.pathExists(webAppDir))) { + continue; + } + addonDestDir = webAppDir; + if (context.frontend.includes("next")) { + addonSrcDir = path.join(PKG_ROOT, "templates/addons/pwa/apps/web/next"); + } else if ( + context.frontend.some((f) => + ["tanstack-router", "react-router", "solid"].includes(f), + ) + ) { + addonSrcDir = path.join(PKG_ROOT, "templates/addons/pwa/apps/web/vite"); + } else { continue; } } diff --git a/apps/cli/src/index.ts b/apps/cli/src/index.ts index 8707f29..b719eeb 100644 --- a/apps/cli/src/index.ts +++ b/apps/cli/src/index.ts @@ -800,7 +800,10 @@ function processAndValidateFlags( ); const hasCompatibleWebFrontend = effectiveFrontend?.some((f) => { const isPwaCompatible = - f === "tanstack-router" || f === "react-router" || f === "solid"; + f === "tanstack-router" || + f === "react-router" || + f === "solid" || + f === "next"; const isTauriCompatible = f === "tanstack-router" || f === "react-router" || @@ -828,7 +831,7 @@ function processAndValidateFlags( let incompatibleReason = "Selected frontend is not compatible."; if (config.addons.includes("pwa")) { incompatibleReason = - "PWA requires tanstack-router, react-router, or solid."; + "PWA requires tanstack-router, react-router, next, or solid."; } if (config.addons.includes("tauri")) { incompatibleReason = diff --git a/apps/cli/src/prompts/addons.ts b/apps/cli/src/prompts/addons.ts index 0c56608..4fe0abe 100644 --- a/apps/cli/src/prompts/addons.ts +++ b/apps/cli/src/prompts/addons.ts @@ -18,7 +18,8 @@ export async function getAddonsChoice( const hasCompatiblePwaFrontend = frontends?.includes("react-router") || frontends?.includes("tanstack-router") || - frontends?.includes("solid"); + frontends?.includes("solid") || + frontends?.includes("next"); const hasCompatibleTauriFrontend = frontends?.includes("react-router") || diff --git a/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/apple-touch-icon.png b/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/apple-touch-icon.png new file mode 100644 index 0000000..751bd56 Binary files /dev/null and b/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/apple-touch-icon.png differ diff --git a/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/favicon-96x96.png b/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/favicon-96x96.png new file mode 100644 index 0000000..d2662e1 Binary files /dev/null and b/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/favicon-96x96.png differ diff --git a/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/favicon.svg b/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/favicon.svg new file mode 100644 index 0000000..0c15667 --- /dev/null +++ b/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/favicon.svg @@ -0,0 +1,6 @@ + + + $_ + \ No newline at end of file diff --git a/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/site.webmanifest.hbs b/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/site.webmanifest.hbs new file mode 100644 index 0000000..d48f6d9 --- /dev/null +++ b/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/site.webmanifest.hbs @@ -0,0 +1,21 @@ +{ + "name": "{{projectName}}", + "short_name": "{{projectName}}", + "icons": [ + { + "src": "/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/web-app-manifest-192x192.png b/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/web-app-manifest-192x192.png new file mode 100644 index 0000000..7148b79 Binary files /dev/null and b/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/web-app-manifest-192x192.png differ diff --git a/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/web-app-manifest-512x512.png b/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/web-app-manifest-512x512.png new file mode 100644 index 0000000..804ed4b Binary files /dev/null and b/apps/cli/templates/addons/pwa/apps/web/next/public/favicon/web-app-manifest-512x512.png differ diff --git a/apps/cli/templates/addons/pwa/apps/web/next/src/app/manifest.ts.hbs b/apps/cli/templates/addons/pwa/apps/web/next/src/app/manifest.ts.hbs new file mode 100644 index 0000000..a82f11b --- /dev/null +++ b/apps/cli/templates/addons/pwa/apps/web/next/src/app/manifest.ts.hbs @@ -0,0 +1,26 @@ +import type { MetadataRoute } from "next"; + +export default function manifest(): MetadataRoute.Manifest { + return { + name: "{{projectName}}", + short_name: "{{projectName}}", + description: + "my pwa app", + start_url: "/new", + display: "standalone", + background_color: "#ffffff", + theme_color: "#000000", + icons: [ + { + src: "/favicon/web-app-manifest-192x192.png", + sizes: "192x192", + type: "image/png", + }, + { + src: "/favicon/web-app-manifest-512x512.png", + sizes: "512x512", + type: "image/png", + }, + ], + }; +} diff --git a/apps/cli/templates/addons/pwa/apps/web/public/logo.png b/apps/cli/templates/addons/pwa/apps/web/vite/public/logo.png similarity index 100% rename from apps/cli/templates/addons/pwa/apps/web/public/logo.png rename to apps/cli/templates/addons/pwa/apps/web/vite/public/logo.png diff --git a/apps/cli/templates/addons/pwa/apps/web/pwa-assets.config.ts b/apps/cli/templates/addons/pwa/apps/web/vite/pwa-assets.config.ts.hbs similarity index 100% rename from apps/cli/templates/addons/pwa/apps/web/pwa-assets.config.ts rename to apps/cli/templates/addons/pwa/apps/web/vite/pwa-assets.config.ts.hbs diff --git a/apps/cli/templates/frontend/react/next/next.config.ts.hbs b/apps/cli/templates/frontend/react/next/next.config.ts.hbs index 676fa21..cb651cd 100644 --- a/apps/cli/templates/frontend/react/next/next.config.ts.hbs +++ b/apps/cli/templates/frontend/react/next/next.config.ts.hbs @@ -1,7 +1,5 @@ import type { NextConfig } from "next"; -const nextConfig: NextConfig = { - output: "export" -}; +const nextConfig: NextConfig = {}; export default nextConfig;