diff --git a/packages/typegpu-cli/src/options.ts b/packages/typegpu-cli/src/options.ts index f6250de5f4..ef2584dd72 100644 --- a/packages/typegpu-cli/src/options.ts +++ b/packages/typegpu-cli/src/options.ts @@ -10,6 +10,7 @@ export const PROJECT_TEMPLATES = [ { value: 'vite-bare', label: 'Vite (Bare)' }, { value: 'vite-complex', label: 'Vite (Complex - Domain Warping)' }, { value: 'vite-react', label: 'Vite + React (Bare)' }, + { value: 'nextjs-bare', label: 'Next.js (Bare)' }, { value: 'expo-bare', label: 'Expo RN (Bare)' }, ] as const; diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/AGENTS.md b/packages/typegpu-cli/templates/template-nextjs-bare/AGENTS.md new file mode 100644 index 0000000000..8bd0e39085 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/AGENTS.md @@ -0,0 +1,5 @@ + +# This is NOT the Next.js you know + +This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices. + diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/CLAUDE.md b/packages/typegpu-cli/templates/template-nextjs-bare/CLAUDE.md new file mode 100644 index 0000000000..43c994c2d3 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/_gitignore b/packages/typegpu-cli/templates/template-nextjs-bare/_gitignore new file mode 100644 index 0000000000..166e81b14a --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/_gitignore @@ -0,0 +1,43 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build +/dist + +# misc +.DS_Store +*.pem +.agents + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/_nvmrc b/packages/typegpu-cli/templates/template-nextjs-bare/_nvmrc new file mode 100644 index 0000000000..a45fd52cc5 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/_nvmrc @@ -0,0 +1 @@ +24 diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/_oxfmtrc.json b/packages/typegpu-cli/templates/template-nextjs-bare/_oxfmtrc.json new file mode 100644 index 0000000000..acf53a0834 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/_oxfmtrc.json @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "ignorePatterns": [".agents/**", "AGENTS.md", "CLAUDE.md"] +} diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/_package.json b/packages/typegpu-cli/templates/template-nextjs-bare/_package.json new file mode 100644 index 0000000000..d2681ac679 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/_package.json @@ -0,0 +1,41 @@ +{ + "name": "typegpu-nextjs-bare-project", + "version": "0.0.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "check": "oxlint && oxfmt --check", + "fix": "oxlint --fix && oxfmt", + "types": "tsc --p ./tsconfig.json --noEmit" + }, + "dependencies": { + "@typegpu/react": "^0.11.2", + "next": "16.2.7", + "react": "19.2.4", + "react-dom": "19.2.4", + "typegpu": "^0.11.9" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "@webgpu/types": "^0.1.70", + "eslint-plugin-typegpu": "^0.11.1", + "oxfmt": "^0.49.0", + "oxlint": "^1.64.0", + "tailwindcss": "^4", + "typescript": "npm:tsover@6.0.1", + "unplugin-typegpu": "^0.11.6" + }, + "overrides": { + "typescript": "npm:tsover@6.0.1" + }, + "pnpm": { + "overrides": { + "typescript": "npm:tsover@6.0.1" + } + } +} diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/_vscode/extensions.json b/packages/typegpu-cli/templates/template-nextjs-bare/_vscode/extensions.json new file mode 100644 index 0000000000..99e2f7ddf7 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/_vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["oxc.oxc-vscode"] +} diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/_vscode/settings.json b/packages/typegpu-cli/templates/template-nextjs-bare/_vscode/settings.json new file mode 100644 index 0000000000..1056eac024 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/_vscode/settings.json @@ -0,0 +1,18 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib", + "typescript.preferences.importModuleSpecifier": "relative", + "typescript.enablePromptUseWorkspaceTsdk": true, + + "oxc.configPath": "oxlint.config.ts", + "oxc.fmt.configPath": ".oxfmtrc.json", + "oxc.lint.run": "onType", + "editor.defaultFormatter": "oxc.oxc-vscode", + "editor.formatOnSave": true, + "editor.formatOnSaveMode": "file", + + "editor.codeActionsOnSave": { + "source.organizeImports": "never", + "source.format.oxc": "always", + "source.fixAll.oxc": "always" + } +} diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/_zed/settings.json b/packages/typegpu-cli/templates/template-nextjs-bare/_zed/settings.json new file mode 100644 index 0000000000..ee27702340 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/_zed/settings.json @@ -0,0 +1,58 @@ +// Folder-specific settings +// +// For a full list of overridable settings, and general information on folder-specific settings, +// see the documentation: https://zed.dev/docs/configuring-zed#settings-files +{ + "lsp": { + "vtsls": { + "settings": { + "typescript": { + "tsdk": "node_modules/typescript/lib" + } + } + }, + "oxlint": { + "initialization_options": { + "settings": { + "configPath": "./oxlint.config.ts", + "run": "onType", + "fixKind": "safe_fix" + } + } + }, + "oxfmt": { + "initialization_options": { + "settings": { + "fmt.configPath": ".oxfmtrc.json" + } + } + } + }, + "languages": { + "TypeScript": { + "format_on_save": "on", + "prettier": { "allowed": false }, + "formatter": [{ "language_server": { "name": "oxfmt" } }] + }, + "TSX": { + "format_on_save": "on", + "prettier": { "allowed": false }, + "formatter": [{ "language_server": { "name": "oxfmt" } }] + }, + "JavaScript": { + "format_on_save": "on", + "prettier": { "allowed": false }, + "formatter": [{ "language_server": { "name": "oxfmt" } }] + }, + "JSON": { + "format_on_save": "on", + "prettier": { "allowed": false }, + "formatter": [{ "language_server": { "name": "oxfmt" } }] + }, + "JSONC": { + "format_on_save": "on", + "prettier": { "allowed": false }, + "formatter": [{ "language_server": { "name": "oxfmt" } }] + } + } +} diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/app/Shader.tsx b/packages/typegpu-cli/templates/template-nextjs-bare/app/Shader.tsx new file mode 100644 index 0000000000..d256615280 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/app/Shader.tsx @@ -0,0 +1,29 @@ +'use client'; + +import React, { useMemo } from 'react'; +import { useConfigureContext, useFrame, useRoot } from '@typegpu/react'; +import { common, d } from 'typegpu'; + +export default function Shader({ className }: { className?: string }) { + const { ref, ctxRef } = useConfigureContext({ autoResize: true, alphaMode: 'premultiplied' }); + + const root = useRoot(); + const renderPipeline = useMemo( + () => + root.createRenderPipeline({ + vertex: common.fullScreenTriangle, + fragment: ({ uv }) => { + 'use gpu'; + return d.vec4f(0.55, uv, 1); + }, + }), + [root], + ); + + useFrame(() => { + if (!ctxRef.current) return; + renderPipeline.withColorAttachment({ view: ctxRef.current }).draw(3); + }); + + return ; +} diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/app/favicon.ico b/packages/typegpu-cli/templates/template-nextjs-bare/app/favicon.ico new file mode 100644 index 0000000000..2901de79c8 Binary files /dev/null and b/packages/typegpu-cli/templates/template-nextjs-bare/app/favicon.ico differ diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/app/globals.css b/packages/typegpu-cli/templates/template-nextjs-bare/app/globals.css new file mode 100644 index 0000000000..f232fefb0e --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/app/globals.css @@ -0,0 +1,64 @@ +@import 'tailwindcss'; + +:root { + --text: #6b6375; + --text-h: #08060d; + --bg: #fff; + --border: #e5e4e7; + --social-bg: rgba(244, 243, 236, 0.5); + --shadow: rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px; +} + +@theme inline { + --color-bg: var(--bg); + --color-text: var(--text); + --color-text-h: var(--text-h); + --color-border: var(--border); + --color-social: var(--social-bg); + --font-sans: var(--font-geist-sans); + --font-mono: var(--font-geist-mono); +} + +@media (prefers-color-scheme: dark) { + :root { + --text: #9ca3af; + --text-h: #f3f4f6; + --bg: #16171d; + --border: #2e303a; + --social-bg: rgba(47, 48, 58, 0.5); + --shadow: rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px; + } + + .button-icon { + filter: invert(1) brightness(2); + } +} + +body { + margin: 0; + background: var(--bg); + color: var(--text); +} + +.ticks { + position: relative; + width: 100%; +} + +.ticks::before, +.ticks::after { + content: ''; + position: absolute; + top: -4.5px; + border: 5px solid transparent; +} + +.ticks::before { + left: 0; + border-left-color: var(--border); +} + +.ticks::after { + right: 0; + border-right-color: var(--border); +} diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/app/layout.tsx b/packages/typegpu-cli/templates/template-nextjs-bare/app/layout.tsx new file mode 100644 index 0000000000..ad42aadbce --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/app/layout.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import type { Metadata } from 'next'; + +// oxlint-disable-next-line import/no-unassigned-import +import './globals.css'; + +export const metadata: Metadata = { + title: 'typegpu-nextjs-bare-project', + description: 'TypeGPU + Next.js', +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + {children} + + ); +} diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/app/page.tsx b/packages/typegpu-cli/templates/template-nextjs-bare/app/page.tsx new file mode 100644 index 0000000000..2a72f31174 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/app/page.tsx @@ -0,0 +1,136 @@ +import React from 'react'; +import { ClientOnly } from '@typegpu/react'; + +import Shader from './Shader.tsx'; +import typegpuLogoDark from '../public/typegpu-logo-dark.svg'; +import typegpuLogoLight from '../public/typegpu-logo-light.svg'; +import nextLogo from '../public/next.svg'; + +export default function Page() { + return ( +
+
+ Loading...

+ } + > + +
+
+ +
+ +
+ {/* TypeGPU */} +
+ + + TypeGPU + + +

Type-safe WebGPU

+ + +
+ + {/* Next.js */} +
+

+ + + +

+ +

The React framework

+ + +
+
+ +
+ +
+
+ ); +} diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/babel.config.js b/packages/typegpu-cli/templates/template-nextjs-bare/babel.config.js new file mode 100644 index 0000000000..ef07c2dc32 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/babel.config.js @@ -0,0 +1,7 @@ +module.exports = (api) => { + api.cache(true); + return { + presets: ['next/babel'], + plugins: ['unplugin-typegpu/babel'], + }; +}; diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/next.config.ts b/packages/typegpu-cli/templates/template-nextjs-bare/next.config.ts new file mode 100644 index 0000000000..9c1882429e --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/next.config.ts @@ -0,0 +1,8 @@ +import type { NextConfig } from 'next'; + +const nextConfig: NextConfig = { + output: 'export', + distDir: './dist', +}; + +export default nextConfig; diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/oxlint.config.ts b/packages/typegpu-cli/templates/template-nextjs-bare/oxlint.config.ts new file mode 100644 index 0000000000..b18160f3d2 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/oxlint.config.ts @@ -0,0 +1,21 @@ +import { defineConfig } from 'oxlint'; +import typegpu from 'eslint-plugin-typegpu'; + +export default defineConfig({ + plugins: ['typescript', 'import', 'unicorn', 'oxc', 'react', 'nextjs'], + jsPlugins: ['eslint-plugin-typegpu'], + categories: { + correctness: 'warn', + suspicious: 'warn', + }, + rules: { + ...typegpu.configs.recommended.rules, + 'typescript/no-non-null-assertion': 'error', + 'typescript/no-explicit-any': 'error', + 'typescript/no-unsafe-type-assertion': 'off', + 'import/no-named-as-default': 'off', + }, + env: { + builtin: true, + }, +}); diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/pnpm-workspace.yaml b/packages/typegpu-cli/templates/template-nextjs-bare/pnpm-workspace.yaml new file mode 100644 index 0000000000..581a9d5b59 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +ignoredBuiltDependencies: + - sharp + - unrs-resolver diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/postcss.config.mjs b/packages/typegpu-cli/templates/template-nextjs-bare/postcss.config.mjs new file mode 100644 index 0000000000..297374d80b --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + '@tailwindcss/postcss': {}, + }, +}; + +export default config; diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/public/icons.svg b/packages/typegpu-cli/templates/template-nextjs-bare/public/icons.svg new file mode 100644 index 0000000000..36acdb9f18 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/public/icons.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/public/next.svg b/packages/typegpu-cli/templates/template-nextjs-bare/public/next.svg new file mode 100644 index 0000000000..5174b28c56 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/public/typegpu-logo-dark.svg b/packages/typegpu-cli/templates/template-nextjs-bare/public/typegpu-logo-dark.svg new file mode 100644 index 0000000000..65c9a02c31 --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/public/typegpu-logo-dark.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/public/typegpu-logo-light.svg b/packages/typegpu-cli/templates/template-nextjs-bare/public/typegpu-logo-light.svg new file mode 100644 index 0000000000..a1b63335fc --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/public/typegpu-logo-light.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/typegpu-cli/templates/template-nextjs-bare/tsconfig.json b/packages/typegpu-cli/templates/template-nextjs-bare/tsconfig.json new file mode 100644 index 0000000000..5a416dd8af --- /dev/null +++ b/packages/typegpu-cli/templates/template-nextjs-bare/tsconfig.json @@ -0,0 +1,37 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "module": "ESNext", + "esModuleInterop": true, + "skipLibCheck": true, + "moduleResolution": "bundler", + "moduleDetection": "force", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "allowJs": true, + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "types": ["@webgpu/types", "@types/react", "@types/react-dom", "@types/node"] + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts", + "**/*.mts", + "dist/types/**/*.ts", + "dist/dev/types/**/*.ts" + ], + "exclude": ["node_modules"] +}