mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
Add Progressive Web App (PWA) support
Add PWA setup with vite-plugin-pwa, assets generator, and templates Include CLI flag and interactive prompt option for PWA installation
This commit is contained in:
5
.changeset/heavy-carpets-jump.md
Normal file
5
.changeset/heavy-carpets-jump.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"create-better-t-stack": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add Progressive Web App (PWA) support
|
||||||
@@ -28,6 +28,9 @@ export const dependencyVersionMap = {
|
|||||||
|
|
||||||
"@prisma/client": "^5.7.1",
|
"@prisma/client": "^5.7.1",
|
||||||
prisma: "^5.7.1",
|
prisma: "^5.7.1",
|
||||||
|
|
||||||
|
"vite-plugin-pwa": "^0.21.2",
|
||||||
|
"@vite-pwa/assets-generator": "^0.2.6",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type AvailableDependencies = keyof typeof dependencyVersionMap;
|
export type AvailableDependencies = keyof typeof dependencyVersionMap;
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import fs from "fs-extra";
|
import fs from "fs-extra";
|
||||||
|
import { PKG_ROOT } from "../constants";
|
||||||
import type { ProjectAddons } from "../types";
|
import type { ProjectAddons } from "../types";
|
||||||
|
import { addPackageDependency } from "../utils/add-package-deps";
|
||||||
|
|
||||||
export async function setupAddons(projectDir: string, addons: ProjectAddons[]) {
|
export async function setupAddons(projectDir: string, addons: ProjectAddons[]) {
|
||||||
if (addons.includes("docker")) {
|
if (addons.includes("docker")) {
|
||||||
await setupDocker(projectDir);
|
await setupDocker(projectDir);
|
||||||
}
|
}
|
||||||
|
if (addons.includes("pwa")) {
|
||||||
|
await setupPwa(projectDir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setupDocker(projectDir: string) {
|
async function setupDocker(projectDir: string) {
|
||||||
@@ -89,3 +94,30 @@ node_modules
|
|||||||
dockerignoreContent,
|
dockerignoreContent,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function setupPwa(projectDir: string) {
|
||||||
|
const pwaTemplateDir = path.join(PKG_ROOT, "template/with-pwa");
|
||||||
|
if (await fs.pathExists(pwaTemplateDir)) {
|
||||||
|
await fs.copy(pwaTemplateDir, projectDir, { overwrite: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const clientPackageDir = path.join(projectDir, "packages/client");
|
||||||
|
|
||||||
|
addPackageDependency({
|
||||||
|
dependencies: ["vite-plugin-pwa"],
|
||||||
|
devDependencies: ["@vite-pwa/assets-generator"],
|
||||||
|
projectDir: clientPackageDir,
|
||||||
|
});
|
||||||
|
|
||||||
|
const clientPackageJsonPath = path.join(clientPackageDir, "package.json");
|
||||||
|
if (await fs.pathExists(clientPackageJsonPath)) {
|
||||||
|
const packageJson = await fs.readJson(clientPackageJsonPath);
|
||||||
|
|
||||||
|
packageJson.scripts = {
|
||||||
|
...packageJson.scripts,
|
||||||
|
"generate-pwa-assets": "pwa-assets-generator",
|
||||||
|
};
|
||||||
|
|
||||||
|
await fs.writeJson(clientPackageJsonPath, packageJson, { spaces: 2 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -135,15 +135,6 @@ cd packages/server && ${packageManagerRunCmd} db:local
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auth) {
|
|
||||||
setup += `
|
|
||||||
3. Generate the authentication schema:
|
|
||||||
\`\`\`bash
|
|
||||||
cd packages/server && ${packageManagerRunCmd} auth:generate
|
|
||||||
\`\`\`
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
setup += `
|
setup += `
|
||||||
${auth ? "4" : "3"}. ${
|
${auth ? "4" : "3"}. ${
|
||||||
orm === "prisma"
|
orm === "prisma"
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ async function main() {
|
|||||||
.option("--auth", "Include authentication")
|
.option("--auth", "Include authentication")
|
||||||
.option("--no-auth", "Exclude authentication")
|
.option("--no-auth", "Exclude authentication")
|
||||||
.option("--docker", "Include Docker setup")
|
.option("--docker", "Include Docker setup")
|
||||||
|
.option("--pwa", "Include Progressive Web App support")
|
||||||
.option("--no-addons", "Skip all additional addons")
|
.option("--no-addons", "Skip all additional addons")
|
||||||
.option("--git", "Include git setup")
|
.option("--git", "Include git setup")
|
||||||
.option("--no-git", "Skip git initialization")
|
.option("--no-git", "Skip git initialization")
|
||||||
@@ -64,17 +65,20 @@ async function main() {
|
|||||||
...(options.prisma && { orm: "prisma" }),
|
...(options.prisma && { orm: "prisma" }),
|
||||||
...("auth" in options && { auth: options.auth }),
|
...("auth" in options && { auth: options.auth }),
|
||||||
...(options.npm && { packageManager: "npm" }),
|
...(options.npm && { packageManager: "npm" }),
|
||||||
...(options.pnpm && { packageManager: "pnpm" }),
|
...(options.pnpm && { packageManager: " pnpm" }),
|
||||||
...(options.yarn && { packageManager: "yarn" }),
|
...(options.yarn && { packageManager: "yarn" }),
|
||||||
...(options.bun && { packageManager: "bun" }),
|
...(options.bun && { packageManager: "bun" }),
|
||||||
...("git" in options && { git: options.git }),
|
...("git" in options && { git: options.git }),
|
||||||
...("install" in options && { noInstall: !options.install }),
|
...("install" in options && { noInstall: !options.install }),
|
||||||
...("turso" in options && { turso: options.turso }),
|
...("turso" in options && { turso: options.turso }),
|
||||||
...((options.docker || options.addons === false) && {
|
...((options.docker || options.pwa || options.addons === false) && {
|
||||||
addons:
|
addons:
|
||||||
options.addons === false
|
options.addons === false
|
||||||
? []
|
? []
|
||||||
: ([...(options.docker ? ["docker"] : [])] as ProjectAddons[]),
|
: ([
|
||||||
|
...(options.docker ? ["docker"] : []),
|
||||||
|
...(options.pwa ? ["pwa"] : []),
|
||||||
|
] as ProjectAddons[]),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,11 @@ export async function getAddonsChoice(
|
|||||||
label: "Docker setup",
|
label: "Docker setup",
|
||||||
hint: "Containerize your application",
|
hint: "Containerize your application",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: "pwa",
|
||||||
|
label: "PWA (Progressive Web App)",
|
||||||
|
hint: "Make your app installable and work offline",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
required: false,
|
required: false,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export type ProjectDatabase = "sqlite" | "postgres" | "none";
|
export type ProjectDatabase = "sqlite" | "postgres" | "none";
|
||||||
export type ProjectOrm = "drizzle" | "prisma" | "none";
|
export type ProjectOrm = "drizzle" | "prisma" | "none";
|
||||||
export type PackageManager = "npm" | "pnpm" | "yarn" | "bun";
|
export type PackageManager = "npm" | "pnpm" | "yarn" | "bun";
|
||||||
export type ProjectAddons = "docker";
|
export type ProjectAddons = "docker" | "pwa";
|
||||||
|
|
||||||
export interface ProjectConfig {
|
export interface ProjectConfig {
|
||||||
projectName: string;
|
projectName: string;
|
||||||
|
|||||||
@@ -19,3 +19,5 @@ dist/
|
|||||||
|
|
||||||
*.env*
|
*.env*
|
||||||
!.env.example
|
!.env.example
|
||||||
|
|
||||||
|
dev-dist
|
||||||
|
|||||||
BIN
apps/cli/template/with-pwa/packages/client/public/logo.png
Normal file
BIN
apps/cli/template/with-pwa/packages/client/public/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,12 @@
|
|||||||
|
import {
|
||||||
|
defineConfig,
|
||||||
|
minimal2023Preset as preset,
|
||||||
|
} from "@vite-pwa/assets-generator/config";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
headLinkOptions: {
|
||||||
|
preset: "2023",
|
||||||
|
},
|
||||||
|
preset,
|
||||||
|
images: ["public/logo.png"],
|
||||||
|
});
|
||||||
35
apps/cli/template/with-pwa/packages/client/vite.config.ts
Normal file
35
apps/cli/template/with-pwa/packages/client/vite.config.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
|
import { TanStackRouterVite } from "@tanstack/router-plugin/vite";
|
||||||
|
import react from "@vitejs/plugin-react";
|
||||||
|
import path from "path";
|
||||||
|
import { defineConfig } from "vite";
|
||||||
|
import { VitePWA } from "vite-plugin-pwa";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [
|
||||||
|
tailwindcss(),
|
||||||
|
TanStackRouterVite({}),
|
||||||
|
react(),
|
||||||
|
VitePWA({
|
||||||
|
registerType: "autoUpdate",
|
||||||
|
manifest: {
|
||||||
|
name: "My App",
|
||||||
|
short_name: "My App ",
|
||||||
|
description: "My App",
|
||||||
|
theme_color: "#0c0c0c",
|
||||||
|
},
|
||||||
|
pwaAssets: {
|
||||||
|
disabled: false,
|
||||||
|
config: true,
|
||||||
|
},
|
||||||
|
devOptions: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"@": path.resolve(__dirname, "./src"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user