quiver-cli 0.1.0
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 +188 -0
- package/bin/quiver-cli.mjs +2 -0
- package/dist/cli.js +3074 -0
- package/package.json +55 -0
- package/template/.agents/AGENTS.md +25 -0
- package/template/.agents/commands/cp.md +116 -0
- package/template/.agents/commands/next-setup.md +1064 -0
- package/template/.agents/commands/tf-readme.md +38 -0
- package/template/.agents/config.json +60 -0
- package/template/.agents/skills/agent-browser/SKILL.md +55 -0
- package/template/.agents/skills/apps/skybridge/SKILL.md +46 -0
- package/template/.agents/skills/apps/skybridge/references/architecture.md +175 -0
- package/template/.agents/skills/apps/skybridge/references/copy-template.md +24 -0
- package/template/.agents/skills/apps/skybridge/references/csp.md +33 -0
- package/template/.agents/skills/apps/skybridge/references/deploy.md +33 -0
- package/template/.agents/skills/apps/skybridge/references/discover.md +84 -0
- package/template/.agents/skills/apps/skybridge/references/download-file.md +77 -0
- package/template/.agents/skills/apps/skybridge/references/fetch-and-render-data.md +151 -0
- package/template/.agents/skills/apps/skybridge/references/oauth.md +115 -0
- package/template/.agents/skills/apps/skybridge/references/open-external-links.md +71 -0
- package/template/.agents/skills/apps/skybridge/references/prompt-llm.md +20 -0
- package/template/.agents/skills/apps/skybridge/references/publish.md +19 -0
- package/template/.agents/skills/apps/skybridge/references/run-locally.md +51 -0
- package/template/.agents/skills/apps/skybridge/references/state-and-context.md +151 -0
- package/template/.agents/skills/apps/skybridge/references/ui-guidelines.md +205 -0
- package/template/.agents/skills/code/cleanup/SKILL.md +26 -0
- package/template/.agents/skills/code/vercel-react-best-practices/AGENTS.md +3810 -0
- package/template/.agents/skills/code/vercel-react-best-practices/README.md +123 -0
- package/template/.agents/skills/code/vercel-react-best-practices/SKILL.md +149 -0
- package/template/.agents/skills/code/vercel-react-best-practices/metadata.json +15 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/_sections.md +46 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/_template.md +28 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/advanced-effect-event-deps.md +56 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-api-routes.md +38 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-defer-await.md +82 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-dependencies.md +51 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-parallel.md +28 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-analyzable-paths.md +63 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-barrel-imports.md +60 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-preload.md +50 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-early-exit.md +50 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-flatmap-filter.md +60 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-index-maps.md +37 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-request-idle-callback.md +105 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-activity.md +26 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-resource-hints.md +85 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-script-defer-async.md +68 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-memo.md +44 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-no-inline-components.md +82 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-cache-react.md +76 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-hoist-static-io.md +149 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-no-shared-module-state.md +50 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-serialization.md +38 -0
- package/template/.agents/skills/data/prisma-cli/SKILL.md +247 -0
- package/template/.agents/skills/data/prisma-cli/references/db-execute.md +78 -0
- package/template/.agents/skills/data/prisma-cli/references/db-pull.md +185 -0
- package/template/.agents/skills/data/prisma-cli/references/db-push.md +148 -0
- package/template/.agents/skills/data/prisma-cli/references/db-seed.md +188 -0
- package/template/.agents/skills/data/prisma-cli/references/debug.md +46 -0
- package/template/.agents/skills/data/prisma-cli/references/dev.md +157 -0
- package/template/.agents/skills/data/prisma-cli/references/format.md +48 -0
- package/template/.agents/skills/data/prisma-cli/references/generate.md +173 -0
- package/template/.agents/skills/data/prisma-cli/references/init.md +136 -0
- package/template/.agents/skills/data/prisma-cli/references/mcp.md +38 -0
- package/template/.agents/skills/data/prisma-cli/references/migrate-deploy.md +127 -0
- package/template/.agents/skills/data/prisma-cli/references/migrate-dev.md +145 -0
- package/template/.agents/skills/data/prisma-cli/references/migrate-diff.md +89 -0
- package/template/.agents/skills/data/prisma-cli/references/migrate-reset.md +78 -0
- package/template/.agents/skills/data/prisma-cli/references/migrate-resolve.md +57 -0
- package/template/.agents/skills/data/prisma-cli/references/migrate-status.md +65 -0
- package/template/.agents/skills/data/prisma-cli/references/studio.md +137 -0
- package/template/.agents/skills/data/prisma-cli/references/validate.md +53 -0
- package/template/.agents/skills/data/prisma-client-api/SKILL.md +216 -0
- package/template/.agents/skills/data/prisma-client-api/references/client-methods.md +223 -0
- package/template/.agents/skills/data/prisma-client-api/references/constructor.md +208 -0
- package/template/.agents/skills/data/prisma-client-api/references/filters.md +256 -0
- package/template/.agents/skills/data/prisma-client-api/references/model-queries.md +281 -0
- package/template/.agents/skills/data/prisma-client-api/references/query-options.md +276 -0
- package/template/.agents/skills/data/prisma-client-api/references/raw-queries.md +194 -0
- package/template/.agents/skills/data/prisma-client-api/references/relations.md +308 -0
- package/template/.agents/skills/data/prisma-client-api/references/transactions.md +184 -0
- package/template/.agents/skills/design/impeccable/SKILL.md +176 -0
- package/template/.agents/skills/design/impeccable/reference/adapt.md +311 -0
- package/template/.agents/skills/design/impeccable/reference/animate.md +201 -0
- package/template/.agents/skills/design/impeccable/reference/audit.md +133 -0
- package/template/.agents/skills/design/impeccable/reference/bolder.md +113 -0
- package/template/.agents/skills/design/impeccable/reference/brand.md +108 -0
- package/template/.agents/skills/design/impeccable/reference/clarify.md +288 -0
- package/template/.agents/skills/design/impeccable/reference/codex.md +105 -0
- package/template/.agents/skills/design/impeccable/reference/colorize.md +257 -0
- package/template/.agents/skills/design/impeccable/reference/craft.md +123 -0
- package/template/.agents/skills/design/impeccable/reference/critique.md +767 -0
- package/template/.agents/skills/design/impeccable/reference/delight.md +302 -0
- package/template/.agents/skills/design/impeccable/reference/distill.md +111 -0
- package/template/.agents/skills/design/impeccable/reference/document.md +429 -0
- package/template/.agents/skills/design/impeccable/reference/extract.md +69 -0
- package/template/.agents/skills/design/impeccable/reference/harden.md +347 -0
- package/template/.agents/skills/design/impeccable/reference/init.md +172 -0
- package/template/.agents/skills/design/impeccable/reference/interaction-design.md +189 -0
- package/template/.agents/skills/design/impeccable/reference/layout.md +161 -0
- package/template/.agents/skills/design/impeccable/reference/live.md +718 -0
- package/template/.agents/skills/design/impeccable/reference/onboard.md +234 -0
- package/template/.agents/skills/design/impeccable/reference/optimize.md +258 -0
- package/template/.agents/skills/design/impeccable/reference/overdrive.md +130 -0
- package/template/.agents/skills/design/impeccable/reference/polish.md +241 -0
- package/template/.agents/skills/design/impeccable/reference/product.md +60 -0
- package/template/.agents/skills/design/impeccable/reference/quieter.md +99 -0
- package/template/.agents/skills/design/impeccable/reference/shape.md +165 -0
- package/template/.agents/skills/design/impeccable/reference/typeset.md +279 -0
- package/template/.agents/skills/design/impeccable/scripts/cleanup-deprecated.mjs +284 -0
- package/template/.agents/skills/design/impeccable/scripts/command-metadata.json +94 -0
- package/template/.agents/skills/design/impeccable/scripts/context-signals.mjs +225 -0
- package/template/.agents/skills/design/impeccable/scripts/context.mjs +270 -0
- package/template/.agents/skills/design/impeccable/scripts/critique-storage.mjs +242 -0
- package/template/.agents/skills/design/impeccable/scripts/design-parser.mjs +835 -0
- package/template/.agents/skills/design/impeccable/scripts/detect-csp.mjs +198 -0
- package/template/.agents/skills/design/impeccable/scripts/detect.mjs +21 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/browser/injected/index.mjs +1733 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/cli/main.mjs +244 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/detect-antipatterns-browser.js +4551 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/detect-antipatterns.mjs +43 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/browser/detect-url.mjs +252 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/regex/detect-text.mjs +535 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +986 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/detect-html.mjs +208 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs +189 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/findings.mjs +12 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/node/file-system.mjs +198 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/profile/profiler.mjs +166 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/registry/antipatterns.mjs +419 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/rules/checks.mjs +2316 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/color.mjs +124 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/constants.mjs +101 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/page.mjs +7 -0
- package/template/.agents/skills/design/impeccable/scripts/impeccable-paths.mjs +126 -0
- package/template/.agents/skills/design/impeccable/scripts/is-generated.mjs +69 -0
- package/template/.agents/skills/design/impeccable/scripts/live-accept.mjs +812 -0
- package/template/.agents/skills/design/impeccable/scripts/live-browser-session.js +123 -0
- package/template/.agents/skills/design/impeccable/scripts/live-browser.js +10316 -0
- package/template/.agents/skills/design/impeccable/scripts/live-commit-manual-edits.mjs +1241 -0
- package/template/.agents/skills/design/impeccable/scripts/live-complete.mjs +75 -0
- package/template/.agents/skills/design/impeccable/scripts/live-completion.mjs +19 -0
- package/template/.agents/skills/design/impeccable/scripts/live-copy-edit-agent.mjs +683 -0
- package/template/.agents/skills/design/impeccable/scripts/live-discard-manual-edits.mjs +51 -0
- package/template/.agents/skills/design/impeccable/scripts/live-event-validation.mjs +136 -0
- package/template/.agents/skills/design/impeccable/scripts/live-inject.mjs +557 -0
- package/template/.agents/skills/design/impeccable/scripts/live-insert-ui.mjs +458 -0
- package/template/.agents/skills/design/impeccable/scripts/live-insert.mjs +272 -0
- package/template/.agents/skills/design/impeccable/scripts/live-manual-edit-evidence.mjs +363 -0
- package/template/.agents/skills/design/impeccable/scripts/live-manual-edits-buffer.mjs +152 -0
- package/template/.agents/skills/design/impeccable/scripts/live-poll.mjs +379 -0
- package/template/.agents/skills/design/impeccable/scripts/live-resume.mjs +94 -0
- package/template/.agents/skills/design/impeccable/scripts/live-server.mjs +2322 -0
- package/template/.agents/skills/design/impeccable/scripts/live-session-store.mjs +289 -0
- package/template/.agents/skills/design/impeccable/scripts/live-status.mjs +61 -0
- package/template/.agents/skills/design/impeccable/scripts/live-svelte-component.mjs +826 -0
- package/template/.agents/skills/design/impeccable/scripts/live-sveltekit-adapter.mjs +274 -0
- package/template/.agents/skills/design/impeccable/scripts/live-ui-core.mjs +179 -0
- package/template/.agents/skills/design/impeccable/scripts/live-wrap.mjs +894 -0
- package/template/.agents/skills/design/impeccable/scripts/live.mjs +246 -0
- package/template/.agents/skills/design/impeccable/scripts/modern-screenshot.umd.js +14 -0
- package/template/.agents/skills/design/impeccable/scripts/palette.mjs +633 -0
- package/template/.agents/skills/design/impeccable/scripts/pin.mjs +214 -0
- package/template/.agents/skills/design/shadcn/SKILL.md +242 -0
- package/template/.agents/skills/design/shadcn/agents/openai.yml +5 -0
- package/template/.agents/skills/design/shadcn/assets/shadcn-small.png +0 -0
- package/template/.agents/skills/design/shadcn/assets/shadcn.png +0 -0
- package/template/.agents/skills/design/shadcn/cli.md +257 -0
- package/template/.agents/skills/design/shadcn/customization.md +202 -0
- package/template/.agents/skills/design/shadcn/evals/evals.json +47 -0
- package/template/.agents/skills/design/shadcn/mcp.md +94 -0
- package/template/.agents/skills/design/shadcn/rules/base-vs-radix.md +306 -0
- package/template/.agents/skills/design/shadcn/rules/composition.md +195 -0
- package/template/.agents/skills/design/shadcn/rules/forms.md +192 -0
- package/template/.agents/skills/design/shadcn/rules/icons.md +101 -0
- package/template/.agents/skills/design/shadcn/rules/styling.md +162 -0
- package/template/.agents/skills/find-skills/SKILL.md +142 -0
- package/template/.agents/skills/integrations/langfuse/SKILL.md +142 -0
- package/template/.agents/skills/integrations/langfuse/references/cli.md +52 -0
- package/template/.agents/skills/integrations/langfuse/references/error-analysis.md +100 -0
- package/template/.agents/skills/integrations/langfuse/references/instrumentation.md +134 -0
- package/template/.agents/skills/integrations/langfuse/references/judge-calibration.md +288 -0
- package/template/.agents/skills/integrations/langfuse/references/prompt-migration.md +234 -0
- package/template/.agents/skills/integrations/langfuse/references/sdk-upgrade.md +175 -0
- package/template/.agents/skills/integrations/langfuse/references/skill-feedback.md +52 -0
- package/template/.agents/skills/integrations/langfuse/references/user-feedback.md +88 -0
- package/template/.agents/skills/integrations/posthog/SKILL.md +102 -0
- package/template/.agents/skills/integrations/posthog/references/error-tracking-alerts.md +63 -0
- package/template/.agents/skills/integrations/posthog/references/error-tracking-assigning-issues.md +77 -0
- package/template/.agents/skills/integrations/posthog/references/error-tracking-fingerprints.md +57 -0
- package/template/.agents/skills/integrations/posthog/references/error-tracking-monitoring.md +140 -0
- package/template/.agents/skills/integrations/posthog/references/error-tracking-nextjs.md +490 -0
- package/template/.agents/skills/integrations/posthog/references/error-tracking-source-maps.md +45 -0
- package/template/.agents/skills/integrations/posthog/references/feature-flags-best-practices.md +139 -0
- package/template/.agents/skills/integrations/posthog/references/feature-flags-react.md +302 -0
- package/template/.agents/skills/integrations/posthog/references/identify-users.md +202 -0
- package/template/.agents/skills/integrations/posthog/references/integration-example.md +706 -0
- package/template/.agents/skills/integrations/posthog/references/integration-nextjs.md +385 -0
- package/template/.agents/skills/integrations/posthog/references/integration-step-1-begin.md +43 -0
- package/template/.agents/skills/integrations/posthog/references/integration-step-2-edit.md +37 -0
- package/template/.agents/skills/integrations/posthog/references/integration-step-3-revise.md +22 -0
- package/template/.agents/skills/integrations/posthog/references/integration-step-4-conclude.md +38 -0
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-anthropic.md +200 -0
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-basics.md +62 -0
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-costs.md +197 -0
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-manual-capture.md +397 -0
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-traces.md +98 -0
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-vercel-ai.md +120 -0
- package/template/.agents/skills/repo/repo-ci/SKILL.md +265 -0
- package/template/.agents/skills/repo/repo-init-next-js/SKILL.md +129 -0
- package/template/.agents/skills/repo/repo-init-next-js/references/file-contents.md +800 -0
- package/template/.agents/skills/repo/repo-init-next-js/scripts/setup.sh +47 -0
- package/template/.agents/skills/repo/repo-init-node/SKILL.md +196 -0
- package/template/.agents/skills/skill-creator/LICENSE.txt +202 -0
- package/template/.agents/skills/skill-creator/SKILL.md +485 -0
- package/template/.agents/skills/skill-creator/agents/analyzer.md +274 -0
- package/template/.agents/skills/skill-creator/agents/comparator.md +202 -0
- package/template/.agents/skills/skill-creator/agents/grader.md +223 -0
- package/template/.agents/skills/skill-creator/assets/eval_review.html +146 -0
- package/template/.agents/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/template/.agents/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/template/.agents/skills/skill-creator/references/schemas.md +430 -0
- package/template/.agents/skills/skill-creator/scripts/__init__.py +0 -0
- package/template/.agents/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/template/.agents/skills/skill-creator/scripts/generate_report.py +326 -0
- package/template/.agents/skills/skill-creator/scripts/improve_description.py +247 -0
- package/template/.agents/skills/skill-creator/scripts/package_skill.py +136 -0
- package/template/.agents/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/template/.agents/skills/skill-creator/scripts/run_eval.py +310 -0
- package/template/.agents/skills/skill-creator/scripts/run_loop.py +328 -0
- package/template/.agents/skills/skill-creator/scripts/utils.py +47 -0
- package/template/.agents/upstreams.json +80 -0
|
@@ -0,0 +1,1064 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Scaffold a new Next.js project with tRPC, Prisma, PostgreSQL, Clerk auth, shadcn/ui, ESLint, Prettier, and knip
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Next.js Full-Stack Project Setup
|
|
6
|
+
|
|
7
|
+
Bootstrap a Next.js App Router project with: Prisma + PostgreSQL (Docker), tRPC + React Query, optional Clerk auth, next-themes, sonner toasts, Tailwind v4 with shadcn/ui, Prettier, ESLint flat config, and knip.
|
|
8
|
+
|
|
9
|
+
## Prerequisites
|
|
10
|
+
|
|
11
|
+
- A Next.js project already created via `pnpm create next-app` (with App Router, TypeScript, Tailwind CSS, `src/` directory)
|
|
12
|
+
- pnpm as package manager
|
|
13
|
+
- Docker installed (for PostgreSQL)
|
|
14
|
+
|
|
15
|
+
## Workflow
|
|
16
|
+
|
|
17
|
+
### 0. Ask the User
|
|
18
|
+
|
|
19
|
+
Before creating any files, ask the user for:
|
|
20
|
+
|
|
21
|
+
1. **Project name** — used in `README.md`, `package.json`, `AGENTS.md`.
|
|
22
|
+
2. **Project description** — used in `AGENTS.md`, `README.md`, `package.json`.
|
|
23
|
+
3. **Node.js version** — default `24`. Used in `.nvmrc`.
|
|
24
|
+
4. **PostgreSQL version** — default `18`. Used in `docker-compose.yml`.
|
|
25
|
+
5. **shadcn/ui preset code** — optional. A preset code from [shadcn.com/themes](https://ui.shadcn.com/themes) (e.g. `a1Dg5eFl`). If empty, use `--defaults`.
|
|
26
|
+
6. **With Clerk auth?** — default: yes. If no, skip all Clerk-related files and packages.
|
|
27
|
+
7. If the user chose Clerk, also ask for:
|
|
28
|
+
- **Clerk Publishable Key** (`NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY`)
|
|
29
|
+
- **Clerk Secret Key** (`CLERK_SECRET_KEY`)
|
|
30
|
+
|
|
31
|
+
### 1. Create folder structure
|
|
32
|
+
|
|
33
|
+
Create these directories (skip any that already exist):
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
src/server/routers/
|
|
37
|
+
src/lib/trpc/
|
|
38
|
+
src/providers/
|
|
39
|
+
src/components/ui/
|
|
40
|
+
src/app/api/trpc/[trpc]/
|
|
41
|
+
prisma/
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
If using Clerk, also create:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
src/app/main/
|
|
48
|
+
src/app/sign-in/[[...sign-in]]/
|
|
49
|
+
src/app/sign-up/[[...sign-up]]/
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Clean public folder
|
|
53
|
+
|
|
54
|
+
Remove Next.js boilerplate assets:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
rm -rf public/*.svg public/*.ico
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 3. Create all template files
|
|
61
|
+
|
|
62
|
+
Create every file listed in the **Template Files** section below at its specified path. Replace `{{PROJECT_NAME}}`, `{{DESCRIPTION}}`, `{{NODE_VERSION}}`, and `{{PG_VERSION}}` with the user's answers from Step 0.
|
|
63
|
+
|
|
64
|
+
**Important — existing files:** Before overwriting any file that already exists from `create-next-app` (e.g. `layout.tsx`, `page.tsx`, `next.config.ts`, `tsconfig.json`, `README.md`, `package.json`, `.gitignore`), you **must read it first** using the Read tool. Split file creation into two batches:
|
|
65
|
+
|
|
66
|
+
1. First batch: all **new** files (files that don't exist yet).
|
|
67
|
+
2. Second batch: read all existing files, then overwrite them.
|
|
68
|
+
|
|
69
|
+
**If the user chose no Clerk**, skip these files and use the alternative templates marked with "(without Clerk)":
|
|
70
|
+
|
|
71
|
+
- `src/providers/clerk-provider.tsx` — skip entirely
|
|
72
|
+
- `src/proxy.ts` — skip entirely
|
|
73
|
+
- `src/app/main/` — skip entirely
|
|
74
|
+
- `src/app/sign-in/` and `src/app/sign-up/` — skip entirely
|
|
75
|
+
- `src/providers/index.tsx` — use the "without Clerk" variant
|
|
76
|
+
- `src/server/trpc.ts` — use the "without Clerk" variant
|
|
77
|
+
- `.env.example` — use the "without Clerk" variant
|
|
78
|
+
- `src/app/page.tsx` — use the "without Clerk" variant
|
|
79
|
+
|
|
80
|
+
### 4. Install dependencies
|
|
81
|
+
|
|
82
|
+
Run these commands:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pnpm add \
|
|
86
|
+
@prisma/client @prisma/adapter-pg pg \
|
|
87
|
+
@trpc/client @trpc/server @trpc/react-query \
|
|
88
|
+
@tanstack/react-query \
|
|
89
|
+
superjson \
|
|
90
|
+
next-themes sonner \
|
|
91
|
+
clsx tailwind-merge \
|
|
92
|
+
lucide-react \
|
|
93
|
+
tw-animate-css \
|
|
94
|
+
dotenv
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
If using Clerk:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
pnpm add @clerk/nextjs
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Dev dependencies:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
pnpm add -D \
|
|
107
|
+
prisma \
|
|
108
|
+
babel-plugin-react-compiler \
|
|
109
|
+
@ianvs/prettier-plugin-sort-imports \
|
|
110
|
+
prettier-plugin-tailwindcss \
|
|
111
|
+
prettier \
|
|
112
|
+
knip
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 5. Initialize shadcn/ui
|
|
116
|
+
|
|
117
|
+
If the user provided a preset code:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
pnpm dlx shadcn@latest init --preset {{PRESET_CODE}}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
If no preset code:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
pnpm dlx shadcn@latest init --defaults
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Then add base components:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
pnpm dlx shadcn@latest add sonner button card avatar
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
This generates `globals.css`, `components.json`, `lib/utils.ts`, and `postcss.config.mjs` automatically.
|
|
136
|
+
|
|
137
|
+
### 6. Extend package.json
|
|
138
|
+
|
|
139
|
+
Read the existing `package.json` and merge the following. Do NOT overwrite the entire file — only add/update the `scripts` and `knip` fields:
|
|
140
|
+
|
|
141
|
+
**Scripts to add/overwrite:**
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"scripts": {
|
|
146
|
+
"dev": "npx prisma generate && next dev",
|
|
147
|
+
"build": "npx prisma generate && npx prisma migrate deploy && next build",
|
|
148
|
+
"start": "next start",
|
|
149
|
+
"postinstall": "npx prisma generate",
|
|
150
|
+
"lint": "eslint .",
|
|
151
|
+
"format": "prettier --write .",
|
|
152
|
+
"format:check": "prettier --check .",
|
|
153
|
+
"tsc": "tsc --noEmit",
|
|
154
|
+
"db": "docker compose up -d",
|
|
155
|
+
"db:push": "npx prisma db push",
|
|
156
|
+
"db:migrate": "npx prisma migrate dev",
|
|
157
|
+
"db:studio": "npx prisma studio",
|
|
158
|
+
"cleanup": "knip"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**knip config to add:**
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"knip": {
|
|
168
|
+
"entry": ["src/app/**/*.{ts,tsx}", "src/server/**/*.ts"],
|
|
169
|
+
"project": ["src/**/*.{ts,tsx}"],
|
|
170
|
+
"ignore": ["src/components/ui/**"]
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### 7. Set up environment
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
cp .env.example .env
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
If using Clerk, replace the empty key values in `.env` with the credentials the user provided in Step 0.
|
|
182
|
+
|
|
183
|
+
### 8. Push database schema
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
docker compose up -d
|
|
187
|
+
npx prisma generate
|
|
188
|
+
npx prisma db push
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 9. Verify
|
|
192
|
+
|
|
193
|
+
Run `pnpm dev` and confirm the app starts without errors.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Template Files
|
|
198
|
+
|
|
199
|
+
All files to create. Replace `{{PROJECT_NAME}}`, `{{DESCRIPTION}}`, `{{NODE_VERSION}}`, and `{{PG_VERSION}}` with the user's answers.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
### `AGENTS.md`
|
|
204
|
+
|
|
205
|
+
```markdown
|
|
206
|
+
# AGENTS.md
|
|
207
|
+
|
|
208
|
+
## Project
|
|
209
|
+
|
|
210
|
+
{{DESCRIPTION}}
|
|
211
|
+
|
|
212
|
+
## Tech Stack
|
|
213
|
+
|
|
214
|
+
- **Framework:** Next.js 16 with App Router and React 19
|
|
215
|
+
- **Auth:** Clerk (if enabled)
|
|
216
|
+
- **API:** tRPC with React Query
|
|
217
|
+
- **Database:** PostgreSQL with Prisma ORM
|
|
218
|
+
- **Styling:** Tailwind CSS v4 with shadcn/ui components (Radix-based)
|
|
219
|
+
|
|
220
|
+
## Commands
|
|
221
|
+
|
|
222
|
+
- `pnpm dev` — start development server
|
|
223
|
+
- `pnpm build` — build for production
|
|
224
|
+
- `pnpm lint` — run ESLint
|
|
225
|
+
- `pnpm format` — format with Prettier
|
|
226
|
+
- `pnpm format:check` — check formatting
|
|
227
|
+
- `pnpm tsc` — typecheck
|
|
228
|
+
- `pnpm db` — start PostgreSQL via Docker
|
|
229
|
+
- `pnpm db:push` — push schema changes to database
|
|
230
|
+
- `pnpm db:migrate` — create and run migrations
|
|
231
|
+
- `pnpm db:studio` — open Prisma Studio
|
|
232
|
+
- `pnpm cleanup` — detect dead code with knip
|
|
233
|
+
|
|
234
|
+
## Project Structure
|
|
235
|
+
|
|
236
|
+
\`\`\`
|
|
237
|
+
src/
|
|
238
|
+
├── app/ # Next.js App Router pages
|
|
239
|
+
├── server/
|
|
240
|
+
│ ├── trpc.ts # tRPC context & procedures
|
|
241
|
+
│ └── routers/ # tRPC routers
|
|
242
|
+
├── lib/
|
|
243
|
+
│ ├── prisma.ts # Prisma client singleton
|
|
244
|
+
│ └── trpc/client.ts # tRPC React client
|
|
245
|
+
├── components/
|
|
246
|
+
│ └── ui/ # shadcn/ui base components
|
|
247
|
+
└── providers/ # React context providers
|
|
248
|
+
\`\`\`
|
|
249
|
+
|
|
250
|
+
## Naming Conventions
|
|
251
|
+
|
|
252
|
+
- File names: kebab-case everywhere
|
|
253
|
+
- Components & types: PascalCase
|
|
254
|
+
- Functions & procedures: camelCase
|
|
255
|
+
- Constants: UPPER_SNAKE_CASE
|
|
256
|
+
- Hooks: `use-<name>.ts`
|
|
257
|
+
|
|
258
|
+
## Imports
|
|
259
|
+
|
|
260
|
+
- Use `@/` path alias, not relative paths
|
|
261
|
+
- No barrel files
|
|
262
|
+
|
|
263
|
+
## Code Style
|
|
264
|
+
|
|
265
|
+
- Prettier with import sorting via `@ianvs/prettier-plugin-sort-imports`
|
|
266
|
+
- Tailwind class sorting via `prettier-plugin-tailwindcss`
|
|
267
|
+
- TypeScript strict mode enabled
|
|
268
|
+
- Avoid `any`; prefer `unknown` + narrowing
|
|
269
|
+
|
|
270
|
+
## Commit Convention
|
|
271
|
+
|
|
272
|
+
\`\`\`
|
|
273
|
+
<type>(<scope>): <subject>
|
|
274
|
+
\`\`\`
|
|
275
|
+
|
|
276
|
+
Types: `feat`, `fix`, `refactor`, `docs`, `style`, `perf`, `test`, `chore`, `ci`
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
### `prisma/schema.prisma`
|
|
282
|
+
|
|
283
|
+
```prisma
|
|
284
|
+
generator client {
|
|
285
|
+
provider = "prisma-client-js"
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
datasource db {
|
|
289
|
+
provider = "postgresql"
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
### `prisma.config.ts`
|
|
296
|
+
|
|
297
|
+
```ts
|
|
298
|
+
import "dotenv/config";
|
|
299
|
+
|
|
300
|
+
import path from "node:path";
|
|
301
|
+
import { fileURLToPath } from "node:url";
|
|
302
|
+
import { defineConfig } from "prisma/config";
|
|
303
|
+
|
|
304
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
305
|
+
|
|
306
|
+
export default defineConfig({
|
|
307
|
+
schema: path.join(__dirname, "prisma", "schema.prisma"),
|
|
308
|
+
datasource: {
|
|
309
|
+
url: process.env.DATABASE_URL!,
|
|
310
|
+
shadowDatabaseUrl: process.env.SHADOW_DATABASE_URL,
|
|
311
|
+
},
|
|
312
|
+
});
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
### `src/lib/prisma.ts`
|
|
318
|
+
|
|
319
|
+
```ts
|
|
320
|
+
import { PrismaPg } from "@prisma/adapter-pg";
|
|
321
|
+
import { PrismaClient } from "@prisma/client";
|
|
322
|
+
|
|
323
|
+
const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });
|
|
324
|
+
|
|
325
|
+
const prisma =
|
|
326
|
+
globalThis.prisma ||
|
|
327
|
+
new PrismaClient({
|
|
328
|
+
adapter,
|
|
329
|
+
log: process.env.NODE_ENV === "development" ? ["error", "warn"] : ["error"],
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
if (process.env.NODE_ENV !== "production") {
|
|
333
|
+
globalThis.prisma = prisma;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export default prisma;
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
### `src/server/trpc.ts` (with Clerk)
|
|
342
|
+
|
|
343
|
+
```ts
|
|
344
|
+
import { auth } from "@clerk/nextjs/server";
|
|
345
|
+
import { initTRPC, TRPCError } from "@trpc/server";
|
|
346
|
+
import superjson from "superjson";
|
|
347
|
+
|
|
348
|
+
export interface Context {
|
|
349
|
+
userId: string | null;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export async function createContext(): Promise<Context> {
|
|
353
|
+
const { userId } = await auth();
|
|
354
|
+
return { userId: userId ?? null };
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const t = initTRPC.context<Context>().create({
|
|
358
|
+
transformer: superjson,
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
const enforceUserAuthenticated = t.middleware(({ ctx, next }) => {
|
|
362
|
+
if (!ctx.userId) {
|
|
363
|
+
throw new TRPCError({ code: "UNAUTHORIZED" });
|
|
364
|
+
}
|
|
365
|
+
return next({ ctx: { userId: ctx.userId! } });
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
export const router = t.router;
|
|
369
|
+
export const mergeRouters = t.mergeRouters;
|
|
370
|
+
export const publicProcedure = t.procedure;
|
|
371
|
+
export const protectedProcedure = t.procedure.use(enforceUserAuthenticated);
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
### `src/server/trpc.ts` (without Clerk)
|
|
377
|
+
|
|
378
|
+
```ts
|
|
379
|
+
import { initTRPC } from "@trpc/server";
|
|
380
|
+
import superjson from "superjson";
|
|
381
|
+
|
|
382
|
+
export interface Context {
|
|
383
|
+
userId: string | null;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export async function createContext(): Promise<Context> {
|
|
387
|
+
// TODO: implement your own auth logic here
|
|
388
|
+
return { userId: null };
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const t = initTRPC.context<Context>().create({
|
|
392
|
+
transformer: superjson,
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
export const router = t.router;
|
|
396
|
+
export const mergeRouters = t.mergeRouters;
|
|
397
|
+
export const publicProcedure = t.procedure;
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
### `src/server/routers/_app.ts`
|
|
403
|
+
|
|
404
|
+
```ts
|
|
405
|
+
import { router } from "@/server/trpc";
|
|
406
|
+
|
|
407
|
+
export const appRouter = router({});
|
|
408
|
+
|
|
409
|
+
export type AppRouter = typeof appRouter;
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
### `src/lib/trpc/client.ts`
|
|
415
|
+
|
|
416
|
+
```ts
|
|
417
|
+
import type { AppRouter } from "@/server/routers/_app";
|
|
418
|
+
import { createTRPCReact } from "@trpc/react-query";
|
|
419
|
+
|
|
420
|
+
export const trpc = createTRPCReact<AppRouter>();
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
### `src/app/api/trpc/[trpc]/route.ts`
|
|
426
|
+
|
|
427
|
+
```ts
|
|
428
|
+
import { appRouter } from "@/server/routers/_app";
|
|
429
|
+
import { createContext } from "@/server/trpc";
|
|
430
|
+
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
|
|
431
|
+
|
|
432
|
+
const handler = (req: Request) =>
|
|
433
|
+
fetchRequestHandler({
|
|
434
|
+
endpoint: "/api/trpc",
|
|
435
|
+
req,
|
|
436
|
+
router: appRouter,
|
|
437
|
+
createContext,
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
export { handler as GET, handler as POST };
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
### `src/providers/trpc-provider.tsx`
|
|
446
|
+
|
|
447
|
+
```tsx
|
|
448
|
+
"use client";
|
|
449
|
+
|
|
450
|
+
import { useState } from "react";
|
|
451
|
+
import { trpc } from "@/lib/trpc/client";
|
|
452
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
453
|
+
import { httpBatchLink, loggerLink } from "@trpc/client";
|
|
454
|
+
import superjson from "superjson";
|
|
455
|
+
|
|
456
|
+
export function TRPCProvider({ children }: { children: React.ReactNode }) {
|
|
457
|
+
const [queryClient] = useState(() => new QueryClient());
|
|
458
|
+
const [trpcClient] = useState(() =>
|
|
459
|
+
trpc.createClient({
|
|
460
|
+
links: [
|
|
461
|
+
loggerLink({ enabled: () => process.env.NODE_ENV === "development" }),
|
|
462
|
+
httpBatchLink({
|
|
463
|
+
url: `${process.env.NEXT_PUBLIC_BASE_URL}/api/trpc`,
|
|
464
|
+
transformer: superjson,
|
|
465
|
+
}),
|
|
466
|
+
],
|
|
467
|
+
}),
|
|
468
|
+
);
|
|
469
|
+
|
|
470
|
+
return (
|
|
471
|
+
<trpc.Provider client={trpcClient} queryClient={queryClient}>
|
|
472
|
+
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
473
|
+
</trpc.Provider>
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
### `src/providers/theme-provider.tsx`
|
|
481
|
+
|
|
482
|
+
```tsx
|
|
483
|
+
"use client";
|
|
484
|
+
|
|
485
|
+
import { ThemeProvider as NextThemesProvider } from "next-themes";
|
|
486
|
+
|
|
487
|
+
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
|
488
|
+
return (
|
|
489
|
+
<NextThemesProvider
|
|
490
|
+
attribute='class'
|
|
491
|
+
defaultTheme='system'
|
|
492
|
+
enableSystem
|
|
493
|
+
disableTransitionOnChange
|
|
494
|
+
>
|
|
495
|
+
{children}
|
|
496
|
+
</NextThemesProvider>
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
### `src/providers/clerk-provider.tsx` (only with Clerk)
|
|
504
|
+
|
|
505
|
+
```tsx
|
|
506
|
+
"use client";
|
|
507
|
+
|
|
508
|
+
import { ClerkProvider as ClerkProviderBase } from "@clerk/nextjs";
|
|
509
|
+
|
|
510
|
+
export function ClerkProvider({ children }: { children: React.ReactNode }) {
|
|
511
|
+
return (
|
|
512
|
+
<ClerkProviderBase signInFallbackRedirectUrl='/main'>
|
|
513
|
+
{children}
|
|
514
|
+
</ClerkProviderBase>
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
---
|
|
520
|
+
|
|
521
|
+
### `src/providers/index.tsx` (with Clerk)
|
|
522
|
+
|
|
523
|
+
```tsx
|
|
524
|
+
"use client";
|
|
525
|
+
|
|
526
|
+
import { ClerkProvider } from "./clerk-provider";
|
|
527
|
+
import { ThemeProvider } from "./theme-provider";
|
|
528
|
+
import { TRPCProvider } from "./trpc-provider";
|
|
529
|
+
|
|
530
|
+
export function Providers({ children }: { children: React.ReactNode }) {
|
|
531
|
+
return (
|
|
532
|
+
<ClerkProvider>
|
|
533
|
+
<ThemeProvider>
|
|
534
|
+
<TRPCProvider>{children}</TRPCProvider>
|
|
535
|
+
</ThemeProvider>
|
|
536
|
+
</ClerkProvider>
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
543
|
+
### `src/providers/index.tsx` (without Clerk)
|
|
544
|
+
|
|
545
|
+
```tsx
|
|
546
|
+
"use client";
|
|
547
|
+
|
|
548
|
+
import { ThemeProvider } from "./theme-provider";
|
|
549
|
+
import { TRPCProvider } from "./trpc-provider";
|
|
550
|
+
|
|
551
|
+
export function Providers({ children }: { children: React.ReactNode }) {
|
|
552
|
+
return (
|
|
553
|
+
<ThemeProvider>
|
|
554
|
+
<TRPCProvider>{children}</TRPCProvider>
|
|
555
|
+
</ThemeProvider>
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
---
|
|
561
|
+
|
|
562
|
+
### `src/app/layout.tsx`
|
|
563
|
+
|
|
564
|
+
Replace the existing layout with:
|
|
565
|
+
|
|
566
|
+
```tsx
|
|
567
|
+
import type { Metadata } from "next";
|
|
568
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
569
|
+
import { Providers } from "@/providers";
|
|
570
|
+
|
|
571
|
+
import { Toaster } from "@/components/ui/sonner";
|
|
572
|
+
|
|
573
|
+
import "./globals.css";
|
|
574
|
+
|
|
575
|
+
const geistSans = Geist({
|
|
576
|
+
variable: "--font-geist-sans",
|
|
577
|
+
subsets: ["latin"],
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
const geistMono = Geist_Mono({
|
|
581
|
+
variable: "--font-geist-mono",
|
|
582
|
+
subsets: ["latin"],
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
export const metadata: Metadata = {
|
|
586
|
+
title: "{{PROJECT_NAME}}",
|
|
587
|
+
description: "{{DESCRIPTION}}",
|
|
588
|
+
};
|
|
589
|
+
|
|
590
|
+
export default function RootLayout({
|
|
591
|
+
children,
|
|
592
|
+
}: Readonly<{
|
|
593
|
+
children: React.ReactNode;
|
|
594
|
+
}>) {
|
|
595
|
+
return (
|
|
596
|
+
<html lang='en' suppressHydrationWarning>
|
|
597
|
+
<body
|
|
598
|
+
className={`${geistSans.variable} ${geistMono.variable} bg-background text-foreground antialiased`}
|
|
599
|
+
>
|
|
600
|
+
<Providers>
|
|
601
|
+
{children}
|
|
602
|
+
<Toaster position='top-center' richColors />
|
|
603
|
+
</Providers>
|
|
604
|
+
</body>
|
|
605
|
+
</html>
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
---
|
|
611
|
+
|
|
612
|
+
### `src/app/page.tsx` (with Clerk)
|
|
613
|
+
|
|
614
|
+
```tsx
|
|
615
|
+
import Link from "next/link";
|
|
616
|
+
import prisma from "@/lib/prisma";
|
|
617
|
+
import { Prisma } from "@prisma/client";
|
|
618
|
+
|
|
619
|
+
import { Button } from "@/components/ui/button";
|
|
620
|
+
|
|
621
|
+
export default async function HomePage() {
|
|
622
|
+
let dbConnected = false;
|
|
623
|
+
try {
|
|
624
|
+
await prisma.$queryRaw(Prisma.sql`SELECT 1`);
|
|
625
|
+
dbConnected = true;
|
|
626
|
+
} catch {
|
|
627
|
+
dbConnected = false;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
return (
|
|
631
|
+
<main className='flex min-h-screen flex-col items-center justify-center gap-6'>
|
|
632
|
+
<h1 className='text-4xl font-bold'>{{ PROJECT_NAME }}</h1>
|
|
633
|
+
<div className='flex items-center gap-2'>
|
|
634
|
+
<span
|
|
635
|
+
className={`inline-block h-3 w-3 rounded-full ${dbConnected ? "bg-green-500" : "bg-red-500"}`}
|
|
636
|
+
/>
|
|
637
|
+
<span className='text-muted-foreground text-sm'>
|
|
638
|
+
Database {dbConnected ? "connected" : "disconnected"}
|
|
639
|
+
</span>
|
|
640
|
+
</div>
|
|
641
|
+
<div className='flex gap-4'>
|
|
642
|
+
<Button asChild>
|
|
643
|
+
<Link href='/sign-in'>Sign In</Link>
|
|
644
|
+
</Button>
|
|
645
|
+
<Button asChild variant='outline'>
|
|
646
|
+
<Link href='/sign-up'>Sign Up</Link>
|
|
647
|
+
</Button>
|
|
648
|
+
</div>
|
|
649
|
+
</main>
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
---
|
|
655
|
+
|
|
656
|
+
### `src/app/page.tsx` (without Clerk)
|
|
657
|
+
|
|
658
|
+
```tsx
|
|
659
|
+
import prisma from "@/lib/prisma";
|
|
660
|
+
import { Prisma } from "@prisma/client";
|
|
661
|
+
|
|
662
|
+
export default async function HomePage() {
|
|
663
|
+
let dbConnected = false;
|
|
664
|
+
try {
|
|
665
|
+
await prisma.$queryRaw(Prisma.sql`SELECT 1`);
|
|
666
|
+
dbConnected = true;
|
|
667
|
+
} catch {
|
|
668
|
+
dbConnected = false;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
return (
|
|
672
|
+
<main className='flex min-h-screen flex-col items-center justify-center gap-6'>
|
|
673
|
+
<h1 className='text-4xl font-bold'>{{ PROJECT_NAME }}</h1>
|
|
674
|
+
<div className='flex items-center gap-2'>
|
|
675
|
+
<span
|
|
676
|
+
className={`inline-block h-3 w-3 rounded-full ${dbConnected ? "bg-green-500" : "bg-red-500"}`}
|
|
677
|
+
/>
|
|
678
|
+
<span className='text-muted-foreground text-sm'>
|
|
679
|
+
Database {dbConnected ? "connected" : "disconnected"}
|
|
680
|
+
</span>
|
|
681
|
+
</div>
|
|
682
|
+
</main>
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
---
|
|
688
|
+
|
|
689
|
+
### `src/app/sign-in/[[...sign-in]]/page.tsx` (only with Clerk)
|
|
690
|
+
|
|
691
|
+
```tsx
|
|
692
|
+
import { SignIn } from "@clerk/nextjs";
|
|
693
|
+
|
|
694
|
+
export const dynamic = "force-dynamic";
|
|
695
|
+
|
|
696
|
+
export default function SignInPage() {
|
|
697
|
+
return (
|
|
698
|
+
<div className='flex min-h-screen items-center justify-center'>
|
|
699
|
+
<SignIn />
|
|
700
|
+
</div>
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
---
|
|
706
|
+
|
|
707
|
+
### `src/app/sign-up/[[...sign-up]]/page.tsx` (only with Clerk)
|
|
708
|
+
|
|
709
|
+
```tsx
|
|
710
|
+
import { SignUp } from "@clerk/nextjs";
|
|
711
|
+
|
|
712
|
+
export const dynamic = "force-dynamic";
|
|
713
|
+
|
|
714
|
+
export default function SignUpPage() {
|
|
715
|
+
return (
|
|
716
|
+
<div className='flex min-h-screen items-center justify-center'>
|
|
717
|
+
<SignUp />
|
|
718
|
+
</div>
|
|
719
|
+
);
|
|
720
|
+
}
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
---
|
|
724
|
+
|
|
725
|
+
### `src/app/main/page.tsx` (only with Clerk)
|
|
726
|
+
|
|
727
|
+
```tsx
|
|
728
|
+
import { redirect } from "next/navigation";
|
|
729
|
+
import { SignOutButton } from "@clerk/nextjs";
|
|
730
|
+
import { auth, currentUser } from "@clerk/nextjs/server";
|
|
731
|
+
|
|
732
|
+
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
|
733
|
+
import { Button } from "@/components/ui/button";
|
|
734
|
+
import {
|
|
735
|
+
Card,
|
|
736
|
+
CardContent,
|
|
737
|
+
CardFooter,
|
|
738
|
+
CardHeader,
|
|
739
|
+
CardTitle,
|
|
740
|
+
} from "@/components/ui/card";
|
|
741
|
+
|
|
742
|
+
export default async function MainPage() {
|
|
743
|
+
const { userId } = await auth();
|
|
744
|
+
if (!userId) redirect("/sign-in");
|
|
745
|
+
|
|
746
|
+
const user = await currentUser();
|
|
747
|
+
if (!user) redirect("/sign-in");
|
|
748
|
+
|
|
749
|
+
const initials =
|
|
750
|
+
[user.firstName?.[0], user.lastName?.[0]]
|
|
751
|
+
.filter(Boolean)
|
|
752
|
+
.join("")
|
|
753
|
+
.toUpperCase() || "?";
|
|
754
|
+
|
|
755
|
+
return (
|
|
756
|
+
<main className='flex min-h-screen items-center justify-center'>
|
|
757
|
+
<Card className='w-full max-w-sm'>
|
|
758
|
+
<CardHeader className='flex flex-col items-center gap-4'>
|
|
759
|
+
<Avatar className='h-20 w-20'>
|
|
760
|
+
<AvatarImage src={user.imageUrl} alt={user.fullName ?? "User"} />
|
|
761
|
+
<AvatarFallback>{initials}</AvatarFallback>
|
|
762
|
+
</Avatar>
|
|
763
|
+
<CardTitle className='text-center'>
|
|
764
|
+
{user.fullName ?? "User"}
|
|
765
|
+
</CardTitle>
|
|
766
|
+
</CardHeader>
|
|
767
|
+
<CardContent className='text-muted-foreground space-y-1 text-center text-sm'>
|
|
768
|
+
{user.primaryEmailAddress && (
|
|
769
|
+
<p>{user.primaryEmailAddress.emailAddress}</p>
|
|
770
|
+
)}
|
|
771
|
+
</CardContent>
|
|
772
|
+
<CardFooter className='justify-center'>
|
|
773
|
+
<SignOutButton redirectUrl='/'>
|
|
774
|
+
<Button variant='outline'>Sign Out</Button>
|
|
775
|
+
</SignOutButton>
|
|
776
|
+
</CardFooter>
|
|
777
|
+
</Card>
|
|
778
|
+
</main>
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
---
|
|
784
|
+
|
|
785
|
+
### `src/proxy.ts` (only with Clerk)
|
|
786
|
+
|
|
787
|
+
Clerk middleware for Next.js 16+ (replaces the old `middleware.ts`).
|
|
788
|
+
|
|
789
|
+
```ts
|
|
790
|
+
import { clerkMiddleware } from "@clerk/nextjs/server";
|
|
791
|
+
|
|
792
|
+
export default clerkMiddleware();
|
|
793
|
+
|
|
794
|
+
export const config = {
|
|
795
|
+
matcher: [
|
|
796
|
+
"/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
|
|
797
|
+
"/(api|trpc)(.*)",
|
|
798
|
+
],
|
|
799
|
+
};
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
---
|
|
803
|
+
|
|
804
|
+
### `.env.example` (with Clerk)
|
|
805
|
+
|
|
806
|
+
```
|
|
807
|
+
NEXT_PUBLIC_BASE_URL=http://localhost:3000
|
|
808
|
+
|
|
809
|
+
# Database (used by Prisma)
|
|
810
|
+
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/myapp?schema=public"
|
|
811
|
+
SHADOW_DATABASE_URL="postgresql://postgres:postgres@localhost:5433/myapp_shadow?schema=public"
|
|
812
|
+
|
|
813
|
+
# Clerk Authentication (get from https://dashboard.clerk.com)
|
|
814
|
+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=
|
|
815
|
+
CLERK_SECRET_KEY=
|
|
816
|
+
NEXT_PUBLIC_CLERK_SIGN_IN_URL="/sign-in"
|
|
817
|
+
NEXT_PUBLIC_CLERK_SIGN_UP_URL="/sign-up"
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
---
|
|
821
|
+
|
|
822
|
+
### `.env.example` (without Clerk)
|
|
823
|
+
|
|
824
|
+
```
|
|
825
|
+
NEXT_PUBLIC_BASE_URL=http://localhost:3000
|
|
826
|
+
|
|
827
|
+
# Database (used by Prisma)
|
|
828
|
+
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/myapp?schema=public"
|
|
829
|
+
SHADOW_DATABASE_URL="postgresql://postgres:postgres@localhost:5433/myapp_shadow?schema=public"
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
---
|
|
833
|
+
|
|
834
|
+
### `docker-compose.yml`
|
|
835
|
+
|
|
836
|
+
```yaml
|
|
837
|
+
services:
|
|
838
|
+
postgres:
|
|
839
|
+
image: postgres:{{PG_VERSION}}-alpine
|
|
840
|
+
restart: unless-stopped
|
|
841
|
+
ports:
|
|
842
|
+
- "5432:5432"
|
|
843
|
+
environment:
|
|
844
|
+
POSTGRES_USER: postgres
|
|
845
|
+
POSTGRES_PASSWORD: postgres
|
|
846
|
+
POSTGRES_DB: myapp
|
|
847
|
+
volumes:
|
|
848
|
+
- postgres_data:/var/lib/postgresql/data
|
|
849
|
+
|
|
850
|
+
postgres-shadow:
|
|
851
|
+
image: postgres:{{PG_VERSION}}-alpine
|
|
852
|
+
restart: unless-stopped
|
|
853
|
+
ports:
|
|
854
|
+
- "5433:5432"
|
|
855
|
+
environment:
|
|
856
|
+
POSTGRES_USER: postgres
|
|
857
|
+
POSTGRES_PASSWORD: postgres
|
|
858
|
+
POSTGRES_DB: myapp_shadow
|
|
859
|
+
volumes:
|
|
860
|
+
- postgres_shadow_data:/var/lib/postgresql/data
|
|
861
|
+
|
|
862
|
+
volumes:
|
|
863
|
+
postgres_data:
|
|
864
|
+
postgres_shadow_data:
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
---
|
|
868
|
+
|
|
869
|
+
### `.prettierrc`
|
|
870
|
+
|
|
871
|
+
```json
|
|
872
|
+
{
|
|
873
|
+
"tabWidth": 2,
|
|
874
|
+
"semi": true,
|
|
875
|
+
"jsxSingleQuote": true,
|
|
876
|
+
"quoteProps": "as-needed",
|
|
877
|
+
"bracketSameLine": false,
|
|
878
|
+
"arrowParens": "always",
|
|
879
|
+
"embeddedLanguageFormatting": "auto",
|
|
880
|
+
"importOrder": [
|
|
881
|
+
"^(react/(.*)$)|^(react$)",
|
|
882
|
+
"^(next/(.*)$)|^(next$)",
|
|
883
|
+
"<THIRD_PARTY_MODULES>",
|
|
884
|
+
"",
|
|
885
|
+
"^types$",
|
|
886
|
+
"^@/config/(.*)$",
|
|
887
|
+
"^@/actions/(.*)$",
|
|
888
|
+
"^@/stores/(.*)$",
|
|
889
|
+
"^@/types/(.*)$",
|
|
890
|
+
"^@/components/ui/(.*)$",
|
|
891
|
+
"^@/components/(.*)$",
|
|
892
|
+
"^@/styles/(.*)$",
|
|
893
|
+
"^@/app/(.*)$",
|
|
894
|
+
"",
|
|
895
|
+
"^[./]"
|
|
896
|
+
],
|
|
897
|
+
"importOrderSeparation": false,
|
|
898
|
+
"importOrderSortSpecifiers": true,
|
|
899
|
+
"importOrderBuiltinModulesToTop": true,
|
|
900
|
+
"importOrderParserPlugins": ["typescript", "jsx", "decorators-legacy"],
|
|
901
|
+
"importOrderMergeDuplicateImports": true,
|
|
902
|
+
"importOrderCombineTypeAndValueImports": true,
|
|
903
|
+
"plugins": [
|
|
904
|
+
"@ianvs/prettier-plugin-sort-imports",
|
|
905
|
+
"prettier-plugin-tailwindcss"
|
|
906
|
+
]
|
|
907
|
+
}
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
---
|
|
911
|
+
|
|
912
|
+
### `eslint.config.mjs`
|
|
913
|
+
|
|
914
|
+
```js
|
|
915
|
+
import { dirname } from "path";
|
|
916
|
+
import { fileURLToPath } from "url";
|
|
917
|
+
import { FlatCompat } from "@eslint/eslintrc";
|
|
918
|
+
|
|
919
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
920
|
+
const __dirname = dirname(__filename);
|
|
921
|
+
|
|
922
|
+
const compat = new FlatCompat({
|
|
923
|
+
baseDirectory: __dirname,
|
|
924
|
+
});
|
|
925
|
+
|
|
926
|
+
const eslintConfig = [
|
|
927
|
+
...compat.extends("next/core-web-vitals", "next/typescript"),
|
|
928
|
+
{
|
|
929
|
+
ignores: [".next/", "out/", "build/", "next-env.d.ts"],
|
|
930
|
+
},
|
|
931
|
+
];
|
|
932
|
+
|
|
933
|
+
export default eslintConfig;
|
|
934
|
+
```
|
|
935
|
+
|
|
936
|
+
---
|
|
937
|
+
|
|
938
|
+
### `next.config.ts`
|
|
939
|
+
|
|
940
|
+
```ts
|
|
941
|
+
import type { NextConfig } from "next";
|
|
942
|
+
|
|
943
|
+
const nextConfig: NextConfig = {
|
|
944
|
+
reactCompiler: true,
|
|
945
|
+
};
|
|
946
|
+
|
|
947
|
+
export default nextConfig;
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
---
|
|
951
|
+
|
|
952
|
+
### `tsconfig.json`
|
|
953
|
+
|
|
954
|
+
Replace the default with:
|
|
955
|
+
|
|
956
|
+
```json
|
|
957
|
+
{
|
|
958
|
+
"compilerOptions": {
|
|
959
|
+
"target": "ES2017",
|
|
960
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
961
|
+
"allowJs": true,
|
|
962
|
+
"skipLibCheck": true,
|
|
963
|
+
"strict": true,
|
|
964
|
+
"noEmit": true,
|
|
965
|
+
"esModuleInterop": true,
|
|
966
|
+
"module": "esnext",
|
|
967
|
+
"moduleResolution": "bundler",
|
|
968
|
+
"resolveJsonModule": true,
|
|
969
|
+
"isolatedModules": true,
|
|
970
|
+
"jsx": "react-jsx",
|
|
971
|
+
"incremental": true,
|
|
972
|
+
"plugins": [
|
|
973
|
+
{
|
|
974
|
+
"name": "next"
|
|
975
|
+
}
|
|
976
|
+
],
|
|
977
|
+
"paths": {
|
|
978
|
+
"@/*": ["./src/*"]
|
|
979
|
+
}
|
|
980
|
+
},
|
|
981
|
+
"include": [
|
|
982
|
+
"next-env.d.ts",
|
|
983
|
+
"**/*.ts",
|
|
984
|
+
"**/*.tsx",
|
|
985
|
+
".next/types/**/*.ts",
|
|
986
|
+
".next/dev/types/**/*.ts",
|
|
987
|
+
"**/*.mts"
|
|
988
|
+
],
|
|
989
|
+
"exclude": ["node_modules"]
|
|
990
|
+
}
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
---
|
|
994
|
+
|
|
995
|
+
### `.nvmrc`
|
|
996
|
+
|
|
997
|
+
```
|
|
998
|
+
{{NODE_VERSION}}
|
|
999
|
+
```
|
|
1000
|
+
|
|
1001
|
+
---
|
|
1002
|
+
|
|
1003
|
+
### `.gitignore`
|
|
1004
|
+
|
|
1005
|
+
```
|
|
1006
|
+
# dependencies
|
|
1007
|
+
node_modules/
|
|
1008
|
+
|
|
1009
|
+
# next.js
|
|
1010
|
+
.next/
|
|
1011
|
+
out/
|
|
1012
|
+
build/
|
|
1013
|
+
|
|
1014
|
+
# environment
|
|
1015
|
+
.env
|
|
1016
|
+
.env.*
|
|
1017
|
+
!.env.example
|
|
1018
|
+
|
|
1019
|
+
# vercel
|
|
1020
|
+
.vercel
|
|
1021
|
+
|
|
1022
|
+
# typescript
|
|
1023
|
+
*.tsbuildinfo
|
|
1024
|
+
next-env.d.ts
|
|
1025
|
+
|
|
1026
|
+
# misc
|
|
1027
|
+
.DS_Store
|
|
1028
|
+
*.pem
|
|
1029
|
+
```
|
|
1030
|
+
|
|
1031
|
+
---
|
|
1032
|
+
|
|
1033
|
+
### `README.md`
|
|
1034
|
+
|
|
1035
|
+
```markdown
|
|
1036
|
+
# {{PROJECT_NAME}}
|
|
1037
|
+
|
|
1038
|
+
{{DESCRIPTION}}
|
|
1039
|
+
|
|
1040
|
+
## Getting Started
|
|
1041
|
+
|
|
1042
|
+
1. Install dependencies: `pnpm install`
|
|
1043
|
+
2. Copy environment file: `cp .env.example .env`
|
|
1044
|
+
3. Start the database: `pnpm db`
|
|
1045
|
+
4. Push the schema: `pnpm db:push`
|
|
1046
|
+
5. Run the dev server: `pnpm dev`
|
|
1047
|
+
6. Open [http://localhost:3000](http://localhost:3000)
|
|
1048
|
+
|
|
1049
|
+
## Scripts
|
|
1050
|
+
|
|
1051
|
+
| Command | Description |
|
|
1052
|
+
| ------------------- | -------------------------------- |
|
|
1053
|
+
| `pnpm dev` | Start development server |
|
|
1054
|
+
| `pnpm build` | Production build |
|
|
1055
|
+
| `pnpm lint` | Run ESLint |
|
|
1056
|
+
| `pnpm format` | Format with Prettier |
|
|
1057
|
+
| `pnpm format:check` | Check formatting |
|
|
1058
|
+
| `pnpm tsc` | TypeScript typecheck |
|
|
1059
|
+
| `pnpm db` | Start PostgreSQL via Docker |
|
|
1060
|
+
| `pnpm db:push` | Push schema changes to database |
|
|
1061
|
+
| `pnpm db:migrate` | Create and run Prisma migrations |
|
|
1062
|
+
| `pnpm db:studio` | Open Prisma Studio |
|
|
1063
|
+
| `pnpm cleanup` | Detect dead code with knip |
|
|
1064
|
+
```
|