diff --git a/apps/typegpu-docs/astro.config.mjs b/apps/typegpu-docs/astro.config.mjs index 116f22fb6a..ec8e11a173 100644 --- a/apps/typegpu-docs/astro.config.mjs +++ b/apps/typegpu-docs/astro.config.mjs @@ -343,6 +343,10 @@ export default defineConfig({ ]), }), react(), - sitemap(), + sitemap({ + // TODO(#2775): Remove this once the new homepage is live + // Match on the path so this keeps working regardless of deploy host/base. + filter: (page) => new URL(page).pathname.replace(/\/$/, '') !== '/TypeGPU/new', + }), ], }); diff --git a/apps/typegpu-docs/package.json b/apps/typegpu-docs/package.json index 09e7da1f77..a4395c3f56 100644 --- a/apps/typegpu-docs/package.json +++ b/apps/typegpu-docs/package.json @@ -74,6 +74,7 @@ }, "devDependencies": { "@observablehq/plot": "^0.6.17", + "@shikijs/themes": "^4.0.0", "@types/babel__standalone": "^7.1.9", "@types/babel__template": "^7.4.4", "@types/babel__traverse": "^7.20.7", diff --git a/apps/typegpu-docs/public/assets/plum.glb b/apps/typegpu-docs/public/assets/plum.glb new file mode 100644 index 0000000000..397661ca51 Binary files /dev/null and b/apps/typegpu-docs/public/assets/plum.glb differ diff --git a/apps/typegpu-docs/src/assets/externalopen.svg b/apps/typegpu-docs/src/assets/externalopen.svg new file mode 100644 index 0000000000..f7589a04f8 --- /dev/null +++ b/apps/typegpu-docs/src/assets/externalopen.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/typegpu-docs/src/assets/github-icon.svg b/apps/typegpu-docs/src/assets/github-icon.svg index 440f2be1f6..23d6f878a3 100644 --- a/apps/typegpu-docs/src/assets/github-icon.svg +++ b/apps/typegpu-docs/src/assets/github-icon.svg @@ -1,5 +1,5 @@ - \ No newline at end of file + fill="currentColor" /> + diff --git a/apps/typegpu-docs/src/assets/hero/book-opened.svg b/apps/typegpu-docs/src/assets/hero/book-opened.svg new file mode 100644 index 0000000000..644e649951 --- /dev/null +++ b/apps/typegpu-docs/src/assets/hero/book-opened.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/typegpu-docs/src/assets/hero/brackets.svg b/apps/typegpu-docs/src/assets/hero/brackets.svg new file mode 100644 index 0000000000..e7868ca23c --- /dev/null +++ b/apps/typegpu-docs/src/assets/hero/brackets.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/typegpu-docs/src/assets/hero/plus-circle.svg b/apps/typegpu-docs/src/assets/hero/plus-circle.svg new file mode 100644 index 0000000000..eef4d648ac --- /dev/null +++ b/apps/typegpu-docs/src/assets/hero/plus-circle.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/typegpu-docs/src/assets/moon.svg b/apps/typegpu-docs/src/assets/moon.svg new file mode 100644 index 0000000000..a091833730 --- /dev/null +++ b/apps/typegpu-docs/src/assets/moon.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/typegpu-docs/src/assets/sun.svg b/apps/typegpu-docs/src/assets/sun.svg new file mode 100644 index 0000000000..ebdbb6e9a8 --- /dev/null +++ b/apps/typegpu-docs/src/assets/sun.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/apps/typegpu-docs/src/assets/swm-logomark-top-right.svg b/apps/typegpu-docs/src/assets/swm-logomark-top-right.svg new file mode 100644 index 0000000000..71317bf4aa --- /dev/null +++ b/apps/typegpu-docs/src/assets/swm-logomark-top-right.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/typegpu-docs/src/assets/swm-logomark.svg b/apps/typegpu-docs/src/assets/swm-logomark.svg index 2fc7e28cce..f5ee46cc29 100644 --- a/apps/typegpu-docs/src/assets/swm-logomark.svg +++ b/apps/typegpu-docs/src/assets/swm-logomark.svg @@ -2,20 +2,20 @@ + fill="currentColor" /> + fill="currentColor" /> + fill="currentColor" /> + fill="currentColor" /> - \ No newline at end of file + diff --git a/apps/typegpu-docs/src/assets/youtube.svg b/apps/typegpu-docs/src/assets/youtube.svg new file mode 100644 index 0000000000..f4e653d625 --- /dev/null +++ b/apps/typegpu-docs/src/assets/youtube.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/typegpu-docs/src/components/CallToActionButton.astro b/apps/typegpu-docs/src/components/CallToActionButton.astro new file mode 100644 index 0000000000..4d7fecc703 --- /dev/null +++ b/apps/typegpu-docs/src/components/CallToActionButton.astro @@ -0,0 +1,49 @@ +--- +interface Props { + title: string; + href: string; + size: 'lg' | 'base'; + class?: string; +} + +const { + title = 'Get started', + href = '/TypeGPU/getting-started', + size, + class: className, +} = Astro.props; +--- + + + {title} + + + + + diff --git a/apps/typegpu-docs/src/components/CodeButton.astro b/apps/typegpu-docs/src/components/CodeButton.astro new file mode 100644 index 0000000000..8f3f4793e9 --- /dev/null +++ b/apps/typegpu-docs/src/components/CodeButton.astro @@ -0,0 +1,39 @@ +--- +interface Props { + title: string; + message: string; + icon: ((_props: astroHTML.JSX.SVGAttributes) => any) & ImageMetadata; +} + +const { title, message, icon: Icon } = Astro.props as Props; +--- + +
+
+
+
+
+
+ {Icon && } +
+ +

+ {title} +

+ +
{/* Spacing */}
+ +

+ {message} +

+
diff --git a/apps/typegpu-docs/src/components/CodePen.astro b/apps/typegpu-docs/src/components/CodePen.astro new file mode 100644 index 0000000000..aabae38e88 --- /dev/null +++ b/apps/typegpu-docs/src/components/CodePen.astro @@ -0,0 +1,56 @@ +--- +import { Code } from 'astro:components'; +import catppuccinMocha from '@shikijs/themes/catppuccin-mocha'; + +type SupportedLanguages = + | 'typescript' + | 'javascript' + | 'jsx' + | 'tsx' + | 'html' + | 'css' + | 'json' + | 'yaml' + | 'markdown' + | 'bash' + | 'shell'; + +interface Props { + code: string; + language?: SupportedLanguages; +} + +const { code, language = 'typescript' } = Astro.props as Props; + +const formattedCode = code.trim(); +--- + +
+
+ +
+
+ diff --git a/apps/typegpu-docs/src/components/CodeShowcase.astro b/apps/typegpu-docs/src/components/CodeShowcase.astro new file mode 100644 index 0000000000..37b829fe9d --- /dev/null +++ b/apps/typegpu-docs/src/components/CodeShowcase.astro @@ -0,0 +1,229 @@ +--- +import CodeButton from './CodeButton.astro'; +import CodePen from './CodePen.astro'; +import Brackets from '../assets/hero/brackets.svg'; +import PlusCircle from '../assets/hero/plus-circle.svg'; +import BookOpened from '../assets/hero/book-opened.svg'; + +const sectionId = 'interactive-code-section'; +--- + +
+
+
+ +
+
+ +
+
+ +
+
+ +
+ + + d.arrayOf(d.arrayOf(d.f32, height), width); + +// ...then infer types from them +type HeightMap = ReturnType; + +export async function generateHeightMap( + root: TgpuRoot, + opts: { width: number; height: number }, +): Promise & StorageFlag> { + const buffer = root + .createBuffer(HeightMap(opts.width, opts.height)) + .$usage('storage'); + + const rawBuffer = root.unwrap(buffer); // => GPUBuffer + + // Here we can do anything we would usually do with a + // WebGPU buffer, like populating it in a compute shader. + // 'rawBuffer' is the WebGPU resource that is backing the + // typed 'buffer' object, meaning any changes to it will + // be visible in both. + + return buffer; +}`} + language="typescript" + /> + >> & StorageFlag + +function frame() { + requestAnimationFrame(frame); + + // ERROR: Argument of type 'TgpuBuffer>>' is + // not assignable to parameter of type 'TgpuBuffer>>' + plot.array1d(root, terrainBuffer); + + // SUCCESS! + plot.array2d(root, terrainBuffer); +}`} + language="typescript" + /> +
+
+ + + + diff --git a/apps/typegpu-docs/src/components/GradientTitle.astro b/apps/typegpu-docs/src/components/GradientTitle.astro new file mode 100644 index 0000000000..9d89b816be --- /dev/null +++ b/apps/typegpu-docs/src/components/GradientTitle.astro @@ -0,0 +1,36 @@ +--- +interface Props { + title: string; +} + +const { title } = Astro.props; +--- + + + {title} + + + diff --git a/apps/typegpu-docs/src/components/SecondaryButton.astro b/apps/typegpu-docs/src/components/SecondaryButton.astro new file mode 100644 index 0000000000..433326475b --- /dev/null +++ b/apps/typegpu-docs/src/components/SecondaryButton.astro @@ -0,0 +1,54 @@ +--- +interface Props { + title: string; + href: string; + size: 'lg' | 'base'; + arrow?: boolean; + class?: string; +} + +const { title, href, size, class: className, arrow = false } = Astro.props; +--- + + + + {title} + { + arrow && ( + + + + + ) + } + diff --git a/apps/typegpu-docs/src/components/ThemeSwitcher.astro b/apps/typegpu-docs/src/components/ThemeSwitcher.astro new file mode 100644 index 0000000000..4c49d289e3 --- /dev/null +++ b/apps/typegpu-docs/src/components/ThemeSwitcher.astro @@ -0,0 +1,87 @@ +--- +import LightModeIconSvg from '../assets/sun.svg'; +import DarkModeIconSvg from '../assets/moon.svg'; +--- + +
+ + + +
+ + diff --git a/apps/typegpu-docs/src/components/Videos.astro b/apps/typegpu-docs/src/components/Videos.astro new file mode 100644 index 0000000000..3acd452755 --- /dev/null +++ b/apps/typegpu-docs/src/components/Videos.astro @@ -0,0 +1,67 @@ +--- +import YoutubeSvg from '../assets/youtube.svg'; + +const videos = [ + { + title: 'Why Iwo Plaza Created TypeGPU | Syntax.fm', + src: 'https://www.youtube.com/embed/ZxPaKfRlrOE?si=Zjf0Cj8_WWDspLoQ', + className: 'md:col-span-2', + iframeClassName: 'h-[315px] md:h-[500px]', + }, + { + title: 'Live-Coding a Liquid Glass Effect with TypeGPU', + src: 'https://www.youtube.com/embed/5PREvbHirEY?si=N2Cs3xn9IG8_Wh9g', + }, + { + title: 'Iwo Plaza – Write TypeGPU, Use Anywhere (...)', + src: 'https://www.youtube.com/embed/GOjrDiPANYU?si=iTnPp2StLd7HRnU-', + }, + { + title: 'Iwo Plaza – Your GPU is a JavaScript runtime* (TypeGPU deep-dive)', + src: 'https://www.youtube.com/embed/pBRLqJaG4kk?si=-xaSG_MET9-Q1ZfK', + }, + { + title: 'Simplifying Compute Shaders with TypeGPU: GPU Worklets & More', + src: 'https://www.youtube.com/embed/QrHZXiXxu9A?si=CSaZznbx0hf3PlQj', + }, +]; +--- + +
+ { + videos.map((video) => ( +
+ + Watch on YouTube + {video.title} + +