ワンクリックで
new-lit-pwa
// Scaffold a new Vite + LitElement + IDB PWA app hosted on Netlify with a private GitHub repo. Use when the user wants to create a new personal web app following this stack.
// Scaffold a new Vite + LitElement + IDB PWA app hosted on Netlify with a private GitHub repo. Use when the user wants to create a new personal web app following this stack.
Search jackfranklin/references (personal technical reference docs) for files relevant to the current task. Use when you need a reference guide on a library, API, or tool, or when the user invokes /references-search with search keywords as $ARGUMENTS.
Manage feedback and bug reports for a project using a local SQLite database. Use when the user asks to log, list, view, resolve, or work through feedback items or bugs.
Scaffold a new Deno 2 + Hono + Deno KV + Eta + HTMX app with password auth and PWA support. Use when the user wants to create a new personal web app following this stack.
Reviews code changes for hacky patterns, redundant state, parameter sprawl, and leaky abstractions. Use when the user asks to "review code quality", "check for hacky patterns", "quality review", or wants a quality-focused code review.
Reviews code changes to identify opportunities for reusing existing utilities and helpers. Use when the user asks to "review for reuse", "check for duplicate code", "find existing utilities", or wants a reuse-focused code review.
Reviews code changes for efficiency issues, unnecessary work, missed concurrency, and memory leaks. Use when the user asks to "review for efficiency", "check for performance issues", "find memory leaks", or wants an efficiency-focused code review.
| name | new-lit-pwa |
| description | Scaffold a new Vite + LitElement + IDB PWA app hosted on Netlify with a private GitHub repo. Use when the user wants to create a new personal web app following this stack. |
| disable-model-invocation | true |
| user-invocable | true |
You are scaffolding a new personal PWA app. These apps follow a strict set of conventions:
idb libraryvite-plugin-pwa (installable on phone)gh CLIIf $ARGUMENTS is not empty, parse it as: <app-name> "<Display Name>" "<Short Name>" "<description>" "<theme-color>"
Otherwise, ask the user for:
#1a1a2e)Confirm all values with the user before proceeding.
Create the project at ~/git/<app-name>/.
package.json{
"name": "<app-name>",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"idb": "^8.0.0",
"lit": "^3.0.0"
},
"devDependencies": {
"typescript": "^5.4.0",
"vite": "^5.0.0",
"vite-plugin-pwa": "^0.20.0"
}
}
tsconfig.json{
"compilerOptions": {
"target": "ES2022",
"useDefineForClassFields": false,
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"strict": true,
"experimentalDecorators": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}
vite.config.tsFill in Display Name, Short Name, Description, and theme color from user input.
import { defineConfig } from 'vite';
import { VitePWA } from 'vite-plugin-pwa';
export default defineConfig({
plugins: [
VitePWA({
registerType: 'autoUpdate',
includeAssets: ['icons/*.png'],
manifest: {
name: '<Display Name>',
short_name: '<Short Name>',
description: '<Description>',
theme_color: '<theme-color>',
background_color: '<theme-color>',
display: 'standalone',
orientation: 'portrait',
start_url: '/',
icons: [
{ src: 'icons/icon-192.png', sizes: '192x192', type: 'image/png' },
{ src: 'icons/icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any maskable' },
],
},
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg}'],
runtimeCaching: [],
},
}),
],
});
netlify.toml[build]
command = "npm run build"
publish = "dist"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
index.htmlFill in Display Name, Short Name, and theme color.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="<Short Name>" />
<meta name="theme-color" content="<theme-color>" />
<title><Display Name></title>
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="stylesheet" href="/src/styles/tokens.css" />
<script type="module" src="/src/main.ts"></script>
</head>
<body>
<app-root></app-root>
</body>
</html>
.gitignorenode_modules
dist
.netlify
src/main.tsimport './components/app-root.js';
src/styles/tokens.cssUse the user's theme color as --color-bg and --color-surface. Derive a slightly lighter shade for --color-surface-raised. Use a contrasting accent color. Include the full design token set from the reference app:
--color-bg, --color-surface, --color-surface-raised, --color-accent, --color-accent-dim, --color-text, --color-text-muted, --color-border, --color-success, --color-warning, --color-danger--space-xs (4px) through --space-xl (32px)--radius-sm (6px), --radius-md (12px), --radius-lg (20px)env(safe-area-inset-*) for mobile notch support--tap-target: 44px minimum touch targetsrc/types.tsDefine TypeScript interfaces based on the user's described data model. Each record should have:
id: string (UUID)createdAt: string (ISO date)updatedAt: string (ISO date)src/services/db.tsIDB service using the idb library. Database name: <app-name>. Version 1.
id)getAll<Entity>(), save<Entity>(item), get<Entity>(id), delete<Entity>(id)exportData() — serializes all stores to JSON and triggers a file download via a temporary <a> elementimportData(json) — parses JSON and bulk-writes all recordssrc/components/app-root.tsLitElement root component. Should include:
exportData()connectedCallbackGenerate sensible LitElement components for the data model — at minimum:
Keep components focused. Use @property() for public props, @state() for internal state. Emit custom events (this.dispatchEvent(new CustomEvent(...))) to communicate up to the root.
All components should:
tokens.css via :host { } and standard CSS custom property referencesstatic styles defined with css\...`(imported fromlit`)In public/icons/, create placeholder files named icon-192.png and icon-512.png. Also create placeholder favicon.ico, favicon-16x16.png, favicon-32x32.png, and apple-touch-icon.png in public/.
Tell the user: "You'll need to replace the placeholder icons in public/ with real ones before deploying."
Run npm install in the project directory.
Run these commands in order:
cd ~/git/<app-name>
git init
git add .
git commit -m "Initial scaffold"
gh repo create <app-name> --private --source=. --remote=origin --push
Tell the user:
cd ~/git/<app-name> && npm run dev<app-name>. Build command is npm run build, publish directory is dist.public/ with real PNG files at the correct sizes.src/types.ts and src/services/db.ts if the generated schema needs adjusting.