refactor(website,guide): cloudflare workers support (#11204)
0
.husky/commit-msg
Executable file → Normal file
0
.husky/pre-commit
Executable file → Normal file
2
apps/guide/.gitignore
vendored
@@ -16,7 +16,9 @@ pids
|
|||||||
.env*.local
|
.env*.local
|
||||||
|
|
||||||
# Dist
|
# Dist
|
||||||
|
.open-next
|
||||||
.next
|
.next
|
||||||
|
.wrangler
|
||||||
.source
|
.source
|
||||||
|
|
||||||
# Miscellaneous
|
# Miscellaneous
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
title: Introduction
|
title: Introduction
|
||||||
---
|
---
|
||||||
|
|
||||||
import { GithubInfo } from 'fumadocs-ui/components/github-info';
|
import { GithubInfo } from '@/components/GitHubInfo';
|
||||||
|
|
||||||
<GithubInfo owner="discordjs" repo="discord.js" />
|
<GithubInfo owner="discordjs" repo="discord.js" />
|
||||||
|
|
||||||
|
|||||||
@@ -23,14 +23,6 @@ export default withMDX({
|
|||||||
fullUrl: true,
|
fullUrl: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
experimental: {
|
|
||||||
ppr: true,
|
|
||||||
useCache: true,
|
|
||||||
dynamicOnHover: true,
|
|
||||||
},
|
|
||||||
eslint: {
|
|
||||||
ignoreDuringBuilds: true,
|
|
||||||
},
|
|
||||||
reactCompiler: true,
|
reactCompiler: true,
|
||||||
typescript: {
|
typescript: {
|
||||||
ignoreBuildErrors: true,
|
ignoreBuildErrors: true,
|
||||||
|
|||||||
3
apps/guide/open-next.config.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { defineCloudflareConfig } from '@opennextjs/cloudflare';
|
||||||
|
|
||||||
|
export default defineCloudflareConfig();
|
||||||
@@ -5,11 +5,15 @@
|
|||||||
"description": "Imagine a bot... the most popular way to build discord bots",
|
"description": "Imagine a bot... the most popular way to build discord bots",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts",
|
||||||
"build:check": "tsc --noEmit",
|
"build:check": "tsc --noEmit",
|
||||||
"build:local": "cross-env NEXT_PUBLIC_LOCAL_DEV=true pnpm run build:prod",
|
"build:local": "cross-env NEXT_PUBLIC_LOCAL_DEV=true pnpm run build:prod",
|
||||||
"build:prod": "pnpm run build:next",
|
"build:prod": "pnpm run build:next",
|
||||||
"build:next": "next build",
|
"build:next": "next build",
|
||||||
|
"build": "next build --webpack",
|
||||||
"preview": "next start",
|
"preview": "next start",
|
||||||
|
"preview:cf": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
|
||||||
|
"deploy:cf": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
|
||||||
"dev": "next dev -p 3001 --turbopack",
|
"dev": "next dev -p 3001 --turbopack",
|
||||||
"lint": "pnpm run build:check && prettier --check . && cross-env TIMING=1 eslint --format=pretty src ",
|
"lint": "pnpm run build:check && prettier --check . && cross-env TIMING=1 eslint --format=pretty src ",
|
||||||
"format": "pnpm run build:check && prettier --write . && cross-env TIMING=1 eslint --fix --format=pretty src ",
|
"format": "pnpm run build:check && prettier --write . && cross-env TIMING=1 eslint --fix --format=pretty src ",
|
||||||
@@ -44,30 +48,32 @@
|
|||||||
"homepage": "https://discord.js.org",
|
"homepage": "https://discord.js.org",
|
||||||
"funding": "https://github.com/discordjs/discord.js?sponsor",
|
"funding": "https://github.com/discordjs/discord.js?sponsor",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@opennextjs/cloudflare": "^1.11.0",
|
||||||
"@react-icons/all-files": "^4.1.0",
|
"@react-icons/all-files": "^4.1.0",
|
||||||
"@vercel/analytics": "^1.5.0",
|
"@vercel/analytics": "^1.5.0",
|
||||||
"cmdk": "^1.1.1",
|
"cmdk": "^1.1.1",
|
||||||
"cva": "1.0.0-beta.3",
|
"cva": "1.0.0-beta.3",
|
||||||
"fumadocs-core": "^15.8.4",
|
"fumadocs-core": "^16.0.2",
|
||||||
"fumadocs-mdx": "^12.0.3",
|
"fumadocs-mdx": "^13.0.0",
|
||||||
"fumadocs-twoslash": "^3.1.8",
|
"fumadocs-twoslash": "^3.1.9",
|
||||||
"fumadocs-ui": "^15.8.4",
|
"fumadocs-ui": "^16.0.2",
|
||||||
"geist": "^1.5.1",
|
"geist": "^1.5.1",
|
||||||
"immer": "^10.1.3",
|
"immer": "^10.1.3",
|
||||||
"jotai": "^2.15.0",
|
"jotai": "^2.15.0",
|
||||||
"jotai-immer": "^0.4.1",
|
"jotai-immer": "^0.4.1",
|
||||||
"lucide-react": "^0.545.0",
|
"lucide-react": "^0.548.0",
|
||||||
"mermaid": "^11.12.0",
|
"mermaid": "^11.12.0",
|
||||||
"motion": "^12.23.22",
|
"motion": "^12.23.24",
|
||||||
"next": "15.6.0-canary.45",
|
"next": "^16.0.0",
|
||||||
"next-mdx-remote-client": "^2.1.6",
|
"next-mdx-remote-client": "^2.1.7",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"nuqs": "^2.7.1",
|
"nuqs": "^2.7.2",
|
||||||
"react": "^19.2.0",
|
"react": "^19.2.0",
|
||||||
"react-aria": "^3.44.0",
|
"react-aria": "^3.44.0",
|
||||||
"react-aria-components": "^1.13.0",
|
"react-aria-components": "^1.13.0",
|
||||||
"react-dom": "^19.2.0",
|
"react-dom": "^19.2.0",
|
||||||
"react-error-boundary": "^6.0.0",
|
"react-error-boundary": "^6.0.0",
|
||||||
|
"safe-mdx": "^1.3.8",
|
||||||
"sharp": "^0.34.4",
|
"sharp": "^0.34.4",
|
||||||
"tailwind-merge": "^3.3.1",
|
"tailwind-merge": "^3.3.1",
|
||||||
"tw-animate-css": "^1.4.0",
|
"tw-animate-css": "^1.4.0",
|
||||||
@@ -75,15 +81,15 @@
|
|||||||
"usehooks-ts": "^3.1.1"
|
"usehooks-ts": "^3.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@next/env": "^15.5.4",
|
"@next/env": "^16.0.0",
|
||||||
"@shikijs/rehype": "^3.13.0",
|
"@shikijs/rehype": "^3.13.0",
|
||||||
"@tailwindcss/postcss": "^4.1.14",
|
"@tailwindcss/postcss": "^4.1.16",
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@tailwindcss/vite": "^4.1.14",
|
"@tailwindcss/vite": "^4.1.16",
|
||||||
"@types/mdx": "^2.0.13",
|
"@types/mdx": "^2.0.13",
|
||||||
"@types/node": "^22.18.8",
|
"@types/node": "^24.9.1",
|
||||||
"@types/react": "^19.2.0",
|
"@types/react": "^19.2.2",
|
||||||
"@types/react-dom": "^19.2.0",
|
"@types/react-dom": "^19.2.2",
|
||||||
"autoprefixer": "^10.4.21",
|
"autoprefixer": "^10.4.21",
|
||||||
"babel-plugin-react-compiler": "19.1.0-rc.3",
|
"babel-plugin-react-compiler": "19.1.0-rc.3",
|
||||||
"cpy-cli": "^6.0.0",
|
"cpy-cli": "^6.0.0",
|
||||||
@@ -94,15 +100,16 @@
|
|||||||
"git-describe": "^4.1.1",
|
"git-describe": "^4.1.1",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"prettier-plugin-tailwindcss": "^0.6.14",
|
"prettier-plugin-tailwindcss": "^0.7.1",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"remark-rehype": "^11.1.2",
|
"remark-rehype": "^11.1.2",
|
||||||
"shiki": "^3.13.0",
|
"shiki": "^3.13.0",
|
||||||
"tailwindcss": "^4.1.14",
|
"tailwindcss": "^4.1.16",
|
||||||
"tailwindcss-react-aria-components": "^2.0.1",
|
"tailwindcss-react-aria-components": "^2.0.1",
|
||||||
"turbo": "^2.5.8",
|
"turbo": "^2.5.8",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"vercel": "^48.2.1"
|
"vercel": "^48.2.1",
|
||||||
|
"wrangler": "^4.45.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22.12.0"
|
"node": ">=22.12.0"
|
||||||
|
|||||||
2
apps/guide/public/_headers
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/_next/static/*
|
||||||
|
Cache-Control: public,max-age=31536000,immutable
|
||||||
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 8.9 KiB |
@@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<browserconfig>
|
|
||||||
<msapplication>
|
|
||||||
<tile>
|
|
||||||
<square70x70logo src="/mstile-70x70.png"/>
|
|
||||||
<square150x150logo src="/mstile-150x150.png"/>
|
|
||||||
<square310x310logo src="/mstile-310x310.png"/>
|
|
||||||
<wide310x150logo src="/mstile-310x150.png"/>
|
|
||||||
<TileColor>#090a16</TileColor>
|
|
||||||
</tile>
|
|
||||||
</msapplication>
|
|
||||||
</browserconfig>
|
|
||||||
|
Before Width: | Height: | Size: 561 B |
|
Before Width: | Height: | Size: 1.1 KiB |
BIN
apps/guide/public/favicon-96x96.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
3
apps/guide/public/favicon.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="180" height="180" viewBox="0 0 180 180"><image width="180" height="180" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALQAAAC0CAMAAAAKE/YAAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAKjUExURQkKFveUVAgIFAQFEv/bXFz/nVxs/////7dc//9cXAYHEwUIFbld/wcJFRESHsHBxAsLF//dXV3/n11t//v7++vr7FBRWgsNGf/bW2NkbP39/To6RP7+/viVVP/fXQwOH/9fXFts/1r/nvtbWzucZ/yXVZs7Pw8OGQ0WHIqLkBYOGREOI/9bXBMQGGVq//T09Px0WFxq/6lf/6xX8CIXHRMRKRYUGT4iXZlfO0S7d1tcZLVb/PqWVRYZI7RtQiEhLBwdKGMoMDMcIeTk5ZFKzLlFSP5nWrJd/zc9kLJZ+JuGP0ZSwRQXNrqgSFtp+O5WVyEVN6iorTQeUCgpNG86n2lCL/CPUvx8WPmNVX5m/9DR01IsdyoZQ0xNVndAr1fvlVNh5q5e/29o/2tsc5+gpJKSmIpGw+zLVhsSL/3HWlv4nRgcQvuEVi4vObe3u9nZ2/n5+a+wtMnJzKVT6PbUWVgvgTU2QPaSVDtGoFx5+Mfncp5h/4pk/7freUFMtHR0e4CBh0cnaVhNLNWBSyMpYTQoIf7TWykwcT4xJEtYzxUuKvXfYYP3jZ9R30YeJ1ZWX8NIS0M7JoBDuPDw8WI0jnlnNpaDP09c2/27WFdp7/mhVR8lU1g4Ksd3R1zRvSdjR5Vi/3X8lC93Umb+mVDei9/jaaLxgU4qcr29wUdIUVlZYXUvNCJUPos1OptP2VMiKzeHWt/AU2s4mVyK6/uuV96ETVDNgOzhZeNSVKxARGUpMKyURJNZOmZZMEBBSsGmSqdlPoNRNlzuqs2xTly6zF3prh5JOZTzh14mLs1LTbadR0ZFp2Fg6LlgRVyj21zetWZb4TxIqkO3dVlY1FyV41yx0a+IRFVQw5ygUDhzd1S2cFye3aikT0SPk6bVb2RPxmBZ2kyJzQcAAApJSURBVHja7Zr5WxNJGoDb4grdKWgI2CAwkZE1QARcSQxyCAuMgrrcoNwi54AIiAfe4on3gfd934o66jiOt6Nz7xy7O3sff8pWJaHTHTpJR9Myz7P1/uRjqlJvf/3VV1+noSgCgUAgEAgEAoFAIBAIBAKBQCAQCAQCgUAgEAgEAoFA+NVCe0lD0wBCJ/MgY8PZOApCy1Cn3+YeXG24JKljn3ZmBSBzB/OY3Y9+N8yj3azDK6PiDdlDX6FBQ7sN8SzjGfGAK5EhUnQnDeZU9azfU8rRkgvBif4ThvH/KF46xLrsRxP3PiwsNI8qfLh34vXseMoD3gGBfs7o7mpKzZLShhPH+/NISxu++uzhBH8xhXtvZuugwtLYOzA8i3ZbGhquf21vbPX+bOhdtV1LI+0rtRxwSxqyQ3ullS3au1motLSfX2hcFnBDGhpuFvo7o/CmASou7ReyqJOWLQ2zP5rg74Kvh1jFpf38ApfRMqVh9l7/SRjnwb4eDxWX9lvcCWRJQ8P3kzEzZswYP97fsfyEifHKS/stygRypBNSosZgls+bN2/hXCxvdbeXn3CTVV56XLNOjnR5hUV6mOXYfa418uP5WZP8C4c8E+nIcVYipayTrgGX0jB7o8g5Kr3i/snpKSnPp5+8j+wRczE4f66zHpEOibuWaia8Ma64KmlkWtsShJee5D9j8vcJ/Pexj4XOUVH3U05kx7MInWHziZSNy9P5zx4neKZ6dNei5s4CZDPHNoXaJ8g6e2mkPHde+vQE6UBHVTzfTPFNEsOwhvLpFRbtqOnvUKnF0mMFZQ3QutpAuzSp4kONpSf5j5+xcN6YMQJppny50PlFPGPXQ00tPzkGXVbUyWxIKSCNe+3S4nHiAz3Vy9blobxYaFYUSOuepwuyIyVhpBljeFGBsmaAoRSSpujMReJQF+t46ck4yGPE0tAgyI6ojdlSZpA9sbGi3HMN0whpil7WJZLuKrXmB/P4N7ydTZoZENS79BQH5QFuLtcpKU3BdSGi/LhmzQ8mRVJamNLLyx2mgCdbUwlpkFklCnUc5VxauA1PMJQyuJKmYJz4LA9wKv0iPYrPj1GUpq+KDpmuTOhM+uDHZo4cuXfv2LHyUZO2y48ca4fKS0elH7v3y9Rh6Sdh3sNs2fKLbrSkqYAeUf9xlearR9SxY/eOfLxlS9DveekNS3hp76DWfcxoSYNm0SPMHi9rpI9gX4udTXqg1Vtg/czAjJb0etFODLdKz/rAJsdLQ8OrIIG19zebmdGRZtaJGpBw2ok0RR0SSXu/2pDAjIY03ThOvrQoqfFHSz7f53ltGdJuRXrqM3Go0Xb8fMNUBo5uTqd6OZVmnohDbY72s4ObWebXUD0cSFNTvwnyHqEddufQPh3zHqXZYqH04FXn6UEx++6MtPYOCmrF2vA9ScOsxeITETiXpqgnrd5S4OQ2eOaXdde9R4ToSbEqC7qSZg8u8ZbWXvLKM8ntWlpcPPgub9YHYRiksuPTf4qkqYSDrUEOtL3vHBp4d22XDwEZV0TFY731/jKHdly8uHLlmktf7tx59u+xdttgw52gsDBp7aDWWQMsUFaa3iPqTJNqrSNAzNmz58/7fIgJnhZrf6kDf1356Q7vMHtz/B87Lv779nagpDTICrT7DQEOSwd/6GNlpDQFY8892HlpzcqLFnVLJqFEurjm0s7zwT4P3igoDXVxIZJPW1jax4k0egrcfu6Cz/nzZ3d+eWnNmpUokXAmncX3Bs+oPxerlDRkGwfFbwQiaJnSaATSftCO08c6zPYvNKX9dqwy0nTAOlu5iwxdXNzcGABlS6MxIOP0z/XBtoFC2m9zHpeGgNY9LeY3YWRXXEQWJ3gVKkcaD4t9E3PBR1K7/jT0kLQXNEOxGZ2pTTm2D4qXUeK3iTKl0UBu++0H7RLawRfeuoaIpMf1xJlpbuoJzOkWFLr1AbQ5+F40dFcaJ3fG6Wn1I7WDYzhPSDt6jxingxSkAzprayMyAHRXGid37I2Ykdr1b4By0j0ZyFm3pycnKSk0sDEDuC1tzpIbP9trv3WoZUiHPqXRaR43OJze5t+o3ZXGe/LGNHFuv3VWy5Bu0lEUZztkIotR4EXSPtPk1VwQe84u2KeVku6+RlP0VUF/GtIIhNLtr0/9K0DucjcuCG7Qyx/+plR65JQCim0SvbxFoTZLt7889cUfPlmhma2Vuxw4XW85EF+f+uIfn6yQP9FN6cUZEGZV2R/mIOb1qT//aYXmtwg3pCku5uUPlitFE323GaEy0osCICjNEfenXhToswj7IjRr5UuD40cFEw/PAUpId1eFs5S99Fj0RN6n8R1G85Mbpct42Nc2cb7npSOTuopT8TPhiIdbmuLWCqTz3FhaO1vz7tI9g6FS5HRdaVo/tlRnObeh6LePRRkQGLfZ1vbdCsTHttLSbGeEFJ2lmRmcF9/VgQhBfiSlApyaNueCTcKlueNOTfSCq33bnKYALQUQ/iUhThDb00BIM26q84Tx6hAsDTYdnd3hWAXMmS+Y+ZYlzyUQsHocv0ZrrAfjcJXuEC2tF1aHwxrN4U2cI22wtUCwEfuUMQb6krK6NtQwscuaF+eEdjXV4o5PK9iGaB8KnDrw3dcczTNKWwOjIKV9o7cCzwtTxpqlLclqVZkedxtsVmlpJocaa6DNE4TLt+A4sHfS+G7bpJUS4vKieeNozXcdHpZmi0qqy3KT09QqlSqtrA1YLsPc4OlFzpptRv469X3DTpqCtce1wM5p+Gqjo6N9ExdUrqrzdEqzd/PT1NjYTItJa9maALAdawXOaH1blebyFiQmJmosVpqja7fOYW3eAHBopgZ/goTPTJmpyu/3dHYAU77Khjq5rr9Ir9Vq52zqQ3sw2gJaPnHBf/myxVYnN0yZsmrVmdWVlcheoyk43Le1w6hF5yXLoZk/zcfjK1evQsL4O1v00NMprd+vVgm103pz99f958eCRDMLFlRWrl59ZtWUhqW2y+y1zZjZMMUi/90fZ3+bl9f37V9+tIyfyQ9JNgGPVw5QkiyyVqkRWAbT0DDTsro6t43/Y5uSW+IJ2H1mQ0ODdYL9Z3c5BeodeyBN5Qq1MFygJlclG3VLG1CiSBv3q10tnX+AFd6coro0tUzn3BqgzGFY1OJCIe2ueC9B/dJetUxnSCkDrGlx7lxmv/8hW9IiJ9gtijkjh7a6fLXjfD6gBxIH9dJbKrWLjXC3TTlnp/dbvesyJ7U0hEUHbjmJtjot18QBSkkgW1OXrB6hoFYnl9U4LJZs0dLcfLWUt1qdn1ttVFbZrK011fWqBAqoXOfvKivhnNxhAI0m1LjgoaIyn7+rzmQEkHoPAK5m6f5byWlmh7Tk3tyy/iJXL6hQG27EHdeu5HzLqZTfe2v/AVMR936ULQrathLT5erq6n5TSZGepYGsSTSnLyox9aN5l/tNNUYtpAH1XkEK6CHM8iTmVlNOD8+DFIFAIBAIBAKBQCAQCAQCgUAgEAgEAoFAIBAIBAKBQPg/5H/D3r7K3BZFuAAAAFd6VFh0UmF3IHByb2ZpbGUgdHlwZSBpcHRjAAB4nOPyDAhxVigoyk/LzEnlUgADIwsuYwsTIxNLkxQDEyBEgDTDZAMjs1Qgy9jUyMTMxBzEB8uASKBKLgDqFxF08kI1lQAAAABJRU5ErkJggg=="></image><style>@media (prefers-color-scheme: light) { :root { filter: none; } }
|
||||||
|
@media (prefers-color-scheme: dark) { :root { filter: none; } }
|
||||||
|
</style></svg>
|
||||||
|
After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
@@ -1,32 +0,0 @@
|
|||||||
<?xml version="1.0" standalone="no"?>
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
|
||||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
|
||||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="400.000000pt" height="400.000000pt" viewBox="0 0 400.000000 400.000000"
|
|
||||||
preserveAspectRatio="xMidYMid meet">
|
|
||||||
<metadata>
|
|
||||||
Created by potrace 1.14, written by Peter Selinger 2001-2017
|
|
||||||
</metadata>
|
|
||||||
<g transform="translate(0.000000,400.000000) scale(0.100000,-0.100000)"
|
|
||||||
fill="#000000" stroke="none">
|
|
||||||
<path d="M0 2000 l0 -2000 2000 0 2000 0 0 2000 0 2000 -2000 0 -2000 0 0
|
|
||||||
-2000z m1305 795 c219 -47 373 -197 421 -411 24 -109 16 -315 -16 -399 l-23
|
|
||||||
-61 -59 -11 c-110 -21 -182 -92 -203 -202 -11 -56 -11 -56 -68 -79 -76 -30
|
|
||||||
-201 -42 -464 -42 l-223 0 0 610 0 610 283 0 c210 0 300 -4 352 -15z m890
|
|
||||||
-585 c0 -543 -2 -601 -18 -659 -56 -198 -190 -334 -365 -370 -176 -37 -349 5
|
|
||||||
-471 115 -48 44 -111 134 -111 161 0 6 19 14 43 18 23 4 73 18 110 32 l68 24
|
|
||||||
50 -45 c56 -50 98 -66 175 -66 100 0 207 81 234 178 6 23 10 251 10 625 l0
|
|
||||||
588 138 -3 137 -3 0 -595z m930 570 c93 -29 197 -84 252 -134 l44 -41 -61 -75
|
|
||||||
c-34 -41 -67 -81 -74 -88 -10 -10 -25 -4 -78 32 -95 63 -154 81 -268 81 -79 0
|
|
||||||
-103 -4 -142 -23 -62 -31 -90 -71 -96 -137 -8 -94 28 -137 168 -202 157 -73
|
|
||||||
172 -80 240 -108 236 -97 341 -215 356 -400 16 -193 -82 -363 -258 -449 -91
|
|
||||||
-45 -187 -66 -303 -66 -191 0 -390 74 -524 195 l-40 37 80 93 80 94 73 -53
|
|
||||||
c168 -121 353 -155 491 -92 72 33 108 82 113 155 9 122 -37 162 -323 286 -258
|
|
||||||
111 -350 179 -407 300 -69 148 -37 343 75 463 61 65 195 133 300 152 79 14
|
|
||||||
222 4 302 -20z m-1367 -977 c45 -34 65 -69 70 -125 4 -61 -19 -106 -77 -145
|
|
||||||
-90 -60 -226 3 -238 111 -3 24 -3 56 1 70 8 34 54 86 91 102 40 19 120 12 153
|
|
||||||
-13z"/>
|
|
||||||
<path d="M967 2543 c-4 -3 -7 -159 -7 -346 l0 -339 128 4 c101 3 136 8 172 24
|
|
||||||
106 48 162 145 168 292 10 214 -69 334 -238 361 -73 12 -213 15 -223 4z"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.8 KiB |
@@ -3,14 +3,16 @@
|
|||||||
"short_name": "discord.js",
|
"short_name": "discord.js",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-192x192.png",
|
"src": "/web-app-manifest-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png",
|
||||||
|
"purpose": "maskable"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-384x384.png",
|
"src": "/web-app-manifest-512x512.png",
|
||||||
"sizes": "384x384",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png",
|
||||||
|
"purpose": "maskable"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"theme_color": "#1a1b1e",
|
"theme_color": "#1a1b1e",
|
||||||
|
|||||||
BIN
apps/guide/public/web-app-manifest-192x192.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
apps/guide/public/web-app-manifest-512x512.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
@@ -1,6 +1,6 @@
|
|||||||
import { Analytics } from '@vercel/analytics/react';
|
import { Analytics } from '@vercel/analytics/react';
|
||||||
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
||||||
import { RootProvider } from 'fumadocs-ui/provider';
|
import { RootProvider } from 'fumadocs-ui/provider/next';
|
||||||
import { GeistMono } from 'geist/font/mono';
|
import { GeistMono } from 'geist/font/mono';
|
||||||
import { GeistSans } from 'geist/font/sans';
|
import { GeistSans } from 'geist/font/sans';
|
||||||
import type { Metadata, Viewport } from 'next';
|
import type { Metadata, Viewport } from 'next';
|
||||||
@@ -29,33 +29,16 @@ export const metadata: Metadata = {
|
|||||||
icons: {
|
icons: {
|
||||||
other: [
|
other: [
|
||||||
{
|
{
|
||||||
url: '/favicon-32x32.png',
|
url: '/favicon-96x96.png',
|
||||||
sizes: '32x32',
|
sizes: '96x96',
|
||||||
type: 'image/png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: '/favicon-16x16.png',
|
|
||||||
sizes: '16x16',
|
|
||||||
type: 'image/png',
|
type: 'image/png',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
apple: [
|
apple: ['/apple-touch-icon.png'],
|
||||||
'/apple-touch-icon.png',
|
|
||||||
{
|
|
||||||
url: '/safari-pinned-tab.svg',
|
|
||||||
rel: 'mask-icon',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
|
|
||||||
manifest: '/site.webmanifest',
|
manifest: '/site.webmanifest',
|
||||||
|
|
||||||
appleWebApp: {
|
|
||||||
title: 'discord.js',
|
|
||||||
},
|
|
||||||
|
|
||||||
applicationName: 'discord.js',
|
|
||||||
|
|
||||||
openGraph: {
|
openGraph: {
|
||||||
siteName: 'discord.js',
|
siteName: 'discord.js',
|
||||||
type: 'website',
|
type: 'website',
|
||||||
@@ -67,10 +50,6 @@ export const metadata: Metadata = {
|
|||||||
card: 'summary_large_image',
|
card: 'summary_large_image',
|
||||||
creator: '@iCrawlToGo',
|
creator: '@iCrawlToGo',
|
||||||
},
|
},
|
||||||
|
|
||||||
other: {
|
|
||||||
'msapplication-TileColor': '#1a1a1e',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async function RootLayout({ children }: PropsWithChildren) {
|
export default async function RootLayout({ children }: PropsWithChildren) {
|
||||||
|
|||||||
@@ -9,12 +9,25 @@ export function generateStaticParams() {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function loadGoogleFont(font: string, text: string) {
|
||||||
|
const url = `https://fonts.googleapis.com/css2?family=${font}&text=${encodeURIComponent(text)}`;
|
||||||
|
const css = await (await fetch(url)).text();
|
||||||
|
// eslint-disable-next-line prefer-named-capture-group
|
||||||
|
const resource = /src: url\((.+)\) format\('(opentype|truetype)'\)/.exec(css);
|
||||||
|
|
||||||
|
if (resource) {
|
||||||
|
const response = await fetch(resource[1]!);
|
||||||
|
if (response.status === 200) {
|
||||||
|
return response.arrayBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('failed to load font data');
|
||||||
|
}
|
||||||
|
|
||||||
export async function GET(_req: Request, { params }: { params: Promise<{ slug: string[] }> }) {
|
export async function GET(_req: Request, { params }: { params: Promise<{ slug: string[] }> }) {
|
||||||
const { slug } = await params;
|
const { slug } = await params;
|
||||||
const page = source.getPage(slug.slice(0, -1));
|
const page = source.getPage(slug.slice(0, -1));
|
||||||
// const fontData = await fetch(new URL('../../assets/Geist-Regular.ttf', import.meta.url), {
|
|
||||||
// next: { revalidate: 604_800 },
|
|
||||||
// }).then(async (res) => res.arrayBuffer());
|
|
||||||
|
|
||||||
if (!page) {
|
if (!page) {
|
||||||
notFound();
|
notFound();
|
||||||
@@ -24,13 +37,13 @@ export async function GET(_req: Request, { params }: { params: Promise<{ slug: s
|
|||||||
title: page.data.title,
|
title: page.data.title,
|
||||||
description: page.data.description,
|
description: page.data.description,
|
||||||
site: 'discord.js Guide',
|
site: 'discord.js Guide',
|
||||||
// fonts: [
|
fonts: [
|
||||||
// {
|
{
|
||||||
// name: 'Geist',
|
name: 'Geist',
|
||||||
// data: fontData,
|
data: await loadGoogleFont('Geist:wght@400', page.data.title),
|
||||||
// weight: 900,
|
weight: 400,
|
||||||
// style: 'normal',
|
style: 'normal',
|
||||||
// },
|
},
|
||||||
// ],
|
],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
109
apps/guide/src/components/GitHubInfo.tsx
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
// https://github.com/fuma-nama/fumadocs/blob/dev/packages/ui/src/components/github-info.tsx
|
||||||
|
// https://github.com/fuma-nama/fumadocs/blob/dev/LICENSE
|
||||||
|
|
||||||
|
import { Star } from 'lucide-react';
|
||||||
|
import { type AnchorHTMLAttributes } from 'react';
|
||||||
|
import { twMerge as cn } from 'tailwind-merge';
|
||||||
|
|
||||||
|
async function getRepoStarsAndForks(
|
||||||
|
owner: string,
|
||||||
|
repo: string,
|
||||||
|
token?: string,
|
||||||
|
): Promise<{
|
||||||
|
forks: number;
|
||||||
|
stars: number;
|
||||||
|
}> {
|
||||||
|
const endpoint = `https://api.github.com/repos/${owner}/${repo}`;
|
||||||
|
const headers = new Headers({
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'User-Agent': 'discordjs-guide',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (token) headers.set('Authorization', `Bearer ${token}`);
|
||||||
|
|
||||||
|
const response = await fetch(endpoint, {
|
||||||
|
headers,
|
||||||
|
next: {
|
||||||
|
revalidate: 60,
|
||||||
|
},
|
||||||
|
} as RequestInit);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const message = await response.text();
|
||||||
|
|
||||||
|
throw new Error(`Failed to fetch repository data: ${message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return {
|
||||||
|
stars: data.stargazers_count,
|
||||||
|
forks: data.forks_count,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GithubInfo({
|
||||||
|
repo,
|
||||||
|
owner,
|
||||||
|
token,
|
||||||
|
...props
|
||||||
|
}: AnchorHTMLAttributes<HTMLAnchorElement> & {
|
||||||
|
readonly owner: string;
|
||||||
|
readonly repo: string;
|
||||||
|
readonly token?: string;
|
||||||
|
}) {
|
||||||
|
const { stars } = await getRepoStarsAndForks(owner, repo, token);
|
||||||
|
const humanizedStars = humanizeNumber(stars);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={`https://github.com/${owner}/${repo}`}
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
target="_blank"
|
||||||
|
{...props}
|
||||||
|
className={cn(
|
||||||
|
'text-fd-foreground/80 hover:text-fd-accent-foreground hover:bg-fd-accent flex flex-col gap-1.5 rounded-lg p-2 text-sm transition-colors lg:flex-row lg:items-center',
|
||||||
|
props.className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<p className="flex items-center gap-2 truncate">
|
||||||
|
<svg className="size-3.5" fill="currentColor" viewBox="0 0 24 24">
|
||||||
|
<title>GitHub</title>
|
||||||
|
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
|
||||||
|
</svg>
|
||||||
|
{owner}/{repo}
|
||||||
|
</p>
|
||||||
|
<p className="text-fd-muted-foreground flex items-center gap-1 text-xs">
|
||||||
|
<Star className="size-3" />
|
||||||
|
{humanizedStars}
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a number to a human-readable string with K suffix for thousands
|
||||||
|
*
|
||||||
|
* @example 1500 -> "1.5K", 1000000 -> "1000000"
|
||||||
|
*/
|
||||||
|
function humanizeNumber(num: number): string {
|
||||||
|
if (num < 1_000) {
|
||||||
|
return num.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num < 100_000) {
|
||||||
|
// For numbers between 1,000 and 99,999, show with one decimal (e.g., 1.5K)
|
||||||
|
const value = (num / 1_000).toFixed(1);
|
||||||
|
// Remove trailing .0 if present
|
||||||
|
const formattedValue = value.endsWith('.0') ? value.slice(0, -2) : value;
|
||||||
|
|
||||||
|
return `${formattedValue}K`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num < 1_000_000) {
|
||||||
|
// For numbers between 10,000 and 999,999, show as whole K (e.g., 10K, 999K)
|
||||||
|
return `${Math.floor(num / 1_000)}K`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For 1,000,000 and above, just return the number
|
||||||
|
return num.toString();
|
||||||
|
}
|
||||||
19
apps/guide/wrangler.jsonc
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"$schema": "node_modules/wrangler/config-schema.json",
|
||||||
|
"main": ".open-next/worker.js",
|
||||||
|
"name": "discordjs-guide",
|
||||||
|
"keep_names": false,
|
||||||
|
"compatibility_date": "2025-10-04",
|
||||||
|
"compatibility_flags": ["nodejs_compat"],
|
||||||
|
"assets": {
|
||||||
|
"directory": ".open-next/assets",
|
||||||
|
"binding": "ASSETS",
|
||||||
|
},
|
||||||
|
"observability": {
|
||||||
|
"logs": {
|
||||||
|
"enabled": true,
|
||||||
|
"head_sampling_rate": 1,
|
||||||
|
"invocation_logs": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
3
apps/website/.gitignore
vendored
@@ -16,8 +16,11 @@ pids
|
|||||||
.env*.local
|
.env*.local
|
||||||
|
|
||||||
# Dist
|
# Dist
|
||||||
|
.open-next
|
||||||
.next
|
.next
|
||||||
|
.wrangler
|
||||||
public/searchIndex
|
public/searchIndex
|
||||||
|
public/readme
|
||||||
src/assets/readme
|
src/assets/readme
|
||||||
src/styles/unocss.css
|
src/styles/unocss.css
|
||||||
|
|
||||||
|
|||||||
@@ -19,13 +19,6 @@ export default {
|
|||||||
fullUrl: true,
|
fullUrl: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
experimental: {
|
|
||||||
ppr: true,
|
|
||||||
dynamicOnHover: true,
|
|
||||||
},
|
|
||||||
eslint: {
|
|
||||||
ignoreDuringBuilds: true,
|
|
||||||
},
|
|
||||||
reactCompiler: true,
|
reactCompiler: true,
|
||||||
typescript: {
|
typescript: {
|
||||||
ignoreBuildErrors: true,
|
ignoreBuildErrors: true,
|
||||||
|
|||||||
3
apps/website/open-next.config.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { defineCloudflareConfig } from '@opennextjs/cloudflare';
|
||||||
|
|
||||||
|
export default defineCloudflareConfig();
|
||||||
@@ -5,14 +5,18 @@
|
|||||||
"description": "Imagine a bot... the most popular way to build discord bots",
|
"description": "Imagine a bot... the most popular way to build discord bots",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts",
|
||||||
"build:copy_readme": "cpy \"../../packages/(discord.js|brokers|builders|collection|core|formatters|next|proxy|rest|structures|util|voice|ws)/README.md\" \"src/assets/readme\" --rename='home-{{basename}}'",
|
"build:copy_readme": "cpy \"../../packages/(discord.js|brokers|builders|collection|core|formatters|next|proxy|rest|structures|util|voice|ws)/README.md\" \"src/assets/readme\" --rename='home-{{basename}}'",
|
||||||
"build:check": "tsc --noEmit",
|
"build:check": "tsc --noEmit",
|
||||||
"build:local": "cross-env NEXT_PUBLIC_LOCAL_DEV=true pnpm run build:prod",
|
"build:local": "cross-env NEXT_PUBLIC_LOCAL_DEV=true pnpm run build:prod",
|
||||||
"build:prod": "pnpm run build:copy_readme && pnpm run build:next",
|
"build:prod": "pnpm run build:copy_readme && pnpm run build:next",
|
||||||
"build:next": "next build",
|
"build:next": "next build",
|
||||||
|
"build": "pnpm run build:copy_readme && next build --webpack",
|
||||||
"build:search_indices": "pnpm node scripts/generateAllIndices.js",
|
"build:search_indices": "pnpm node scripts/generateAllIndices.js",
|
||||||
"build:analyze": "turbo run docs --filter='@discordjs/*' --concurrency=4 && cross-env ANALYZE=true NEXT_PUBLIC_LOCAL_DEV=true pnpm run build:prod",
|
"build:analyze": "turbo run docs --filter='@discordjs/*' --concurrency=4 && cross-env ANALYZE=true NEXT_PUBLIC_LOCAL_DEV=true pnpm run build:prod",
|
||||||
"preview": "next start",
|
"preview": "next start",
|
||||||
|
"preview:cf": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
|
||||||
|
"deploy:cf": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
|
||||||
"dev": "next dev --turbopack",
|
"dev": "next dev --turbopack",
|
||||||
"lint": "pnpm run build:check && prettier --check . && cross-env TIMING=1 eslint --format=pretty src ",
|
"lint": "pnpm run build:check && prettier --check . && cross-env TIMING=1 eslint --format=pretty src ",
|
||||||
"format": "pnpm run build:check && prettier --write . && cross-env TIMING=1 eslint --fix --format=pretty src ",
|
"format": "pnpm run build:check && prettier --write . && cross-env TIMING=1 eslint --fix --format=pretty src ",
|
||||||
@@ -47,11 +51,12 @@
|
|||||||
"homepage": "https://discord.js.org",
|
"homepage": "https://discord.js.org",
|
||||||
"funding": "https://github.com/discordjs/discord.js?sponsor",
|
"funding": "https://github.com/discordjs/discord.js?sponsor",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@opennextjs/cloudflare": "^1.11.0",
|
||||||
"@radix-ui/react-collapsible": "^1.1.12",
|
"@radix-ui/react-collapsible": "^1.1.12",
|
||||||
"@react-icons/all-files": "^4.1.0",
|
"@react-icons/all-files": "^4.1.0",
|
||||||
"@tanstack/react-query": "^5.90.2",
|
"@tanstack/react-query": "^5.90.5",
|
||||||
"@vercel/analytics": "^1.5.0",
|
"@vercel/analytics": "^1.5.0",
|
||||||
"@vercel/edge-config": "^1.4.0",
|
"@vercel/edge-config": "^1.4.3",
|
||||||
"@vercel/postgres": "^0.10.0",
|
"@vercel/postgres": "^0.10.0",
|
||||||
"cloudflare": "^5.2.0",
|
"cloudflare": "^5.2.0",
|
||||||
"cmdk": "^1.1.1",
|
"cmdk": "^1.1.1",
|
||||||
@@ -60,13 +65,13 @@
|
|||||||
"immer": "^10.1.3",
|
"immer": "^10.1.3",
|
||||||
"jotai": "^2.15.0",
|
"jotai": "^2.15.0",
|
||||||
"jotai-immer": "^0.4.1",
|
"jotai-immer": "^0.4.1",
|
||||||
"lucide-react": "^0.545.0",
|
"lucide-react": "^0.548.0",
|
||||||
"meilisearch": "^0.50.0",
|
"meilisearch": "^0.53.0",
|
||||||
"motion": "^12.23.22",
|
"motion": "^12.23.24",
|
||||||
"next": "15.6.0-canary.45",
|
"next": "^16.0.0",
|
||||||
"next-mdx-remote-client": "^2.1.6",
|
"next-mdx-remote-client": "^2.1.7",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"nuqs": "^2.7.1",
|
"nuqs": "^2.7.2",
|
||||||
"overlayscrollbars": "^2.12.0",
|
"overlayscrollbars": "^2.12.0",
|
||||||
"overlayscrollbars-react": "^0.5.6",
|
"overlayscrollbars-react": "^0.5.6",
|
||||||
"react": "^19.2.0",
|
"react": "^19.2.0",
|
||||||
@@ -74,20 +79,21 @@
|
|||||||
"react-aria-components": "^1.13.0",
|
"react-aria-components": "^1.13.0",
|
||||||
"react-dom": "^19.2.0",
|
"react-dom": "^19.2.0",
|
||||||
"react-error-boundary": "^6.0.0",
|
"react-error-boundary": "^6.0.0",
|
||||||
|
"safe-mdx": "^1.3.8",
|
||||||
"sharp": "^0.34.4",
|
"sharp": "^0.34.4",
|
||||||
"tailwind-merge": "^3.3.1",
|
"tailwind-merge": "^3.3.1",
|
||||||
"tw-animate-css": "^1.4.0",
|
"tw-animate-css": "^1.4.0",
|
||||||
"usehooks-ts": "^3.1.1"
|
"usehooks-ts": "^3.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@next/env": "^15.5.4",
|
"@next/env": "^16.0.0",
|
||||||
"@shikijs/rehype": "^3.13.0",
|
"@shikijs/rehype": "^3.13.0",
|
||||||
"@tailwindcss/postcss": "^4.1.14",
|
"@tailwindcss/postcss": "^4.1.16",
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@tailwindcss/vite": "^4.1.14",
|
"@tailwindcss/vite": "^4.1.16",
|
||||||
"@types/node": "^22.18.8",
|
"@types/node": "^24.9.1",
|
||||||
"@types/react": "^19.2.0",
|
"@types/react": "^19.2.2",
|
||||||
"@types/react-dom": "^19.2.0",
|
"@types/react-dom": "^19.2.2",
|
||||||
"autoprefixer": "^10.4.21",
|
"autoprefixer": "^10.4.21",
|
||||||
"babel-plugin-react-compiler": "19.1.0-rc.3",
|
"babel-plugin-react-compiler": "19.1.0-rc.3",
|
||||||
"cpy-cli": "^6.0.0",
|
"cpy-cli": "^6.0.0",
|
||||||
@@ -98,15 +104,16 @@
|
|||||||
"git-describe": "^4.1.1",
|
"git-describe": "^4.1.1",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"prettier-plugin-tailwindcss": "^0.6.14",
|
"prettier-plugin-tailwindcss": "^0.7.1",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"remark-rehype": "^11.1.2",
|
"remark-rehype": "^11.1.2",
|
||||||
"shiki": "^3.13.0",
|
"shiki": "^3.13.0",
|
||||||
"tailwindcss": "^4.1.14",
|
"tailwindcss": "^4.1.16",
|
||||||
"tailwindcss-react-aria-components": "^2.0.1",
|
"tailwindcss-react-aria-components": "^2.0.1",
|
||||||
"turbo": "^2.5.8",
|
"turbo": "^2.5.8",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"vercel": "^48.2.1"
|
"vercel": "^48.2.1",
|
||||||
|
"wrangler": "^4.45.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22.12.0"
|
"node": ">=22.12.0"
|
||||||
|
|||||||
2
apps/website/public/_headers
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/_next/static/*
|
||||||
|
Cache-Control: public,max-age=31536000,immutable
|
||||||
BIN
apps/website/public/web-app-manifest-192x192.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
apps/website/public/web-app-manifest-512x512.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
@@ -3,8 +3,6 @@
|
|||||||
import { ImageResponse } from 'next/og';
|
import { ImageResponse } from 'next/og';
|
||||||
import { resolveKind } from '@/util/resolveNodeKind';
|
import { resolveKind } from '@/util/resolveNodeKind';
|
||||||
|
|
||||||
export const runtime = 'edge';
|
|
||||||
|
|
||||||
export const size = {
|
export const size = {
|
||||||
width: 1_200,
|
width: 1_200,
|
||||||
height: 630,
|
height: 630,
|
||||||
@@ -12,6 +10,22 @@ export const size = {
|
|||||||
|
|
||||||
export const contentType = 'image/png';
|
export const contentType = 'image/png';
|
||||||
|
|
||||||
|
async function loadGoogleFont(font: string, text: string) {
|
||||||
|
const url = `https://fonts.googleapis.com/css2?family=${font}&text=${encodeURIComponent(text)}`;
|
||||||
|
const css = await (await fetch(url)).text();
|
||||||
|
// eslint-disable-next-line prefer-named-capture-group
|
||||||
|
const resource = /src: url\((.+)\) format\('(opentype|truetype)'\)/.exec(css);
|
||||||
|
|
||||||
|
if (resource) {
|
||||||
|
const response = await fetch(resource[1]!);
|
||||||
|
if (response.status === 200) {
|
||||||
|
return response.arrayBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('failed to load font data');
|
||||||
|
}
|
||||||
|
|
||||||
export default async function Image({
|
export default async function Image({
|
||||||
params,
|
params,
|
||||||
}: {
|
}: {
|
||||||
@@ -19,14 +33,6 @@ export default async function Image({
|
|||||||
}) {
|
}) {
|
||||||
const { item, packageName, version } = await params;
|
const { item, packageName, version } = await params;
|
||||||
|
|
||||||
const [fontDataBold, fontDataBlack] = await Promise.all([
|
|
||||||
fetch(new URL('../../../../../../assets/Geist-Bold.ttf', import.meta.url), {
|
|
||||||
next: { revalidate: 604_800 },
|
|
||||||
}).then(async (res) => res.arrayBuffer()),
|
|
||||||
fetch(new URL('../../../../../../assets/Geist-Black.ttf', import.meta.url), {
|
|
||||||
next: { revalidate: 604_800 },
|
|
||||||
}).then(async (res) => res.arrayBuffer()),
|
|
||||||
]);
|
|
||||||
const normalizeItem = item.split(encodeURIComponent(':')).join('.').toLowerCase();
|
const normalizeItem = item.split(encodeURIComponent(':')).join('.').toLowerCase();
|
||||||
|
|
||||||
const isMain = version === 'main';
|
const isMain = version === 'main';
|
||||||
@@ -107,13 +113,13 @@ export default async function Image({
|
|||||||
fonts: [
|
fonts: [
|
||||||
{
|
{
|
||||||
name: 'Geist',
|
name: 'Geist',
|
||||||
data: fontDataBold,
|
data: await loadGoogleFont('Geist:wght@700', node.displayName),
|
||||||
weight: 700,
|
weight: 700,
|
||||||
style: 'normal',
|
style: 'normal',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Geist',
|
name: 'Geist',
|
||||||
data: fontDataBlack,
|
data: await loadGoogleFont('Geist:wght@900', node.displayName),
|
||||||
weight: 900,
|
weight: 900,
|
||||||
style: 'normal',
|
style: 'normal',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
import { readFile } from 'node:fs/promises';
|
|
||||||
import { join } from 'node:path';
|
|
||||||
import rehypeShikiFromHighlighter from '@shikijs/rehype/core';
|
|
||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { notFound } from 'next/navigation';
|
import { notFound } from 'next/navigation';
|
||||||
import { MDXRemote } from 'next-mdx-remote-client/rsc';
|
import { SafeMdxRenderer } from 'safe-mdx';
|
||||||
import remarkGfm from 'remark-gfm';
|
import { mdxParse } from 'safe-mdx/parse';
|
||||||
import { DocItem } from '@/components/DocItem';
|
import { DocItem } from '@/components/DocItem';
|
||||||
import { PACKAGES_WITH_ENTRY_POINTS } from '@/util/constants';
|
import { SyntaxHighlighter } from '@/components/SyntaxHighlighter';
|
||||||
|
// import { PACKAGES_WITH_ENTRY_POINTS } from '@/util/constants';
|
||||||
import { fetchNode } from '@/util/fetchNode';
|
import { fetchNode } from '@/util/fetchNode';
|
||||||
import { parseDocsPathParams } from '@/util/parseDocsPathParams';
|
import { parseDocsPathParams } from '@/util/parseDocsPathParams';
|
||||||
import { getSingletonHighlighter } from '@/util/shiki.bundle';
|
|
||||||
|
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
params,
|
params,
|
||||||
@@ -52,48 +49,38 @@ export default async function Page({
|
|||||||
const { entryPoints: parsedEntrypoints, foundItem } = parseDocsPathParams(item);
|
const { entryPoints: parsedEntrypoints, foundItem } = parseDocsPathParams(item);
|
||||||
|
|
||||||
if (!foundItem) {
|
if (!foundItem) {
|
||||||
const hasEntryPoint = PACKAGES_WITH_ENTRY_POINTS.includes(packageName);
|
// const hasEntryPoint = PACKAGES_WITH_ENTRY_POINTS.includes(packageName);
|
||||||
|
|
||||||
if (hasEntryPoint) {
|
// if (hasEntryPoint) {
|
||||||
return <>Placeholder</>;
|
// return <>Placeholder</>;
|
||||||
}
|
// }
|
||||||
|
|
||||||
let fileContent: string;
|
let fileContent: string;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fileContent = await readFile(join(process.cwd(), `src/assets/readme/${packageName}/home-README.md`), 'utf8');
|
fileContent = await fetch(`${process.env.CF_R2_README_BUCKET_URL}/${packageName}/home-README.md`).then(
|
||||||
} catch (error: any) {
|
async (res) => res.text(),
|
||||||
if ('code' in error && error.code === 'ENOENT') {
|
);
|
||||||
notFound();
|
} catch {
|
||||||
}
|
notFound();
|
||||||
|
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mdast = mdxParse(fileContent);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="prose prose-neutral dark:prose-invert prose-a:[&>img]:inline-block prose-a:[&>img]:m-0 prose-a:[&>img[height='44']]:h-11 prose-p:my-2 prose-pre:py-3 prose-pre:rounded-sm prose-pre:px-0 prose-pre:border prose-pre:border-[#d4d4d4] dark:prose-pre:border-[#404040] prose-code:font-normal prose-a:text-[#5865F2] prose-a:no-underline prose-a:hover:text-[#3d48c3] dark:prose-a:hover:text-[#7782fa] mx-auto max-w-screen-xl px-6 py-6 break-words [&_code_span:last-of-type:empty]:hidden [&_div[align='center']_p_a+a]:ml-2">
|
<div className="prose prose-neutral dark:prose-invert prose-a:[&>img]:inline-block prose-a:[&>img]:m-0 prose-a:[&>img[height='44']]:h-11 prose-p:my-2 prose-pre:py-3 prose-pre:rounded-sm prose-pre:px-0 prose-pre:border prose-pre:border-[#d4d4d4] dark:prose-pre:border-[#404040] prose-code:font-normal prose-a:text-[#5865F2] prose-a:no-underline prose-a:hover:text-[#3d48c3] dark:prose-a:hover:text-[#7782fa] mx-auto max-w-screen-xl px-6 py-6 break-words [&_code_span:last-of-type:empty]:hidden [&_div[align='center']_p_a+a]:ml-2">
|
||||||
<MDXRemote
|
<SafeMdxRenderer
|
||||||
options={{
|
markdown={fileContent}
|
||||||
mdxOptions: {
|
mdast={mdast}
|
||||||
remarkPlugins: [remarkGfm],
|
renderNode={(node) => {
|
||||||
rehypePlugins: [
|
if (node.type === 'code') {
|
||||||
[
|
const language = node.lang ?? 'text';
|
||||||
rehypeShikiFromHighlighter,
|
|
||||||
await getSingletonHighlighter({
|
return <SyntaxHighlighter code={node.value} lang={language} />;
|
||||||
langs: ['typescript', 'javascript', 'shellscript'],
|
}
|
||||||
themes: ['github-light', 'github-dark-dimmed'],
|
|
||||||
}),
|
return undefined;
|
||||||
{
|
|
||||||
themes: {
|
|
||||||
light: 'github-light',
|
|
||||||
dark: 'github-dark-dimmed',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
source={fileContent}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
import { ImageResponse } from 'next/og';
|
import { ImageResponse } from 'next/og';
|
||||||
|
|
||||||
export const runtime = 'edge';
|
|
||||||
|
|
||||||
export const size = {
|
export const size = {
|
||||||
width: 1_200,
|
width: 1_200,
|
||||||
height: 630,
|
height: 630,
|
||||||
@@ -11,11 +9,23 @@ export const size = {
|
|||||||
|
|
||||||
export const contentType = 'image/png';
|
export const contentType = 'image/png';
|
||||||
|
|
||||||
export default async function Image() {
|
async function loadGoogleFont(font: string, text: string) {
|
||||||
const fontData = await fetch(new URL('../assets/Geist-Black.ttf', import.meta.url), { cache: 'force-cache' }).then(
|
const url = `https://fonts.googleapis.com/css2?family=${font}&text=${encodeURIComponent(text)}`;
|
||||||
async (res) => res.arrayBuffer(),
|
const css = await (await fetch(url)).text();
|
||||||
);
|
// eslint-disable-next-line prefer-named-capture-group
|
||||||
|
const resource = /src: url\((.+)\) format\('(opentype|truetype)'\)/.exec(css);
|
||||||
|
|
||||||
|
if (resource) {
|
||||||
|
const response = await fetch(resource[1]!);
|
||||||
|
if (response.status === 200) {
|
||||||
|
return response.arrayBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('failed to load font data');
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function Image() {
|
||||||
return new ImageResponse(
|
return new ImageResponse(
|
||||||
(
|
(
|
||||||
<div tw="flex bg-[#121214] h-full w-full">
|
<div tw="flex bg-[#121214] h-full w-full">
|
||||||
@@ -39,7 +49,7 @@ export default async function Image() {
|
|||||||
fonts: [
|
fonts: [
|
||||||
{
|
{
|
||||||
name: 'Geist',
|
name: 'Geist',
|
||||||
data: fontData,
|
data: await loadGoogleFont('Geist:wght@900', 'The most popular way to build Discord bots.'),
|
||||||
weight: 900,
|
weight: 900,
|
||||||
style: 'normal',
|
style: 'normal',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -43,12 +43,12 @@ export function CmdK({ dependencies }: { readonly dependencies: string[] }) {
|
|||||||
value={item.id}
|
value={item.id}
|
||||||
>
|
>
|
||||||
{resolveKind(item.kind)}
|
{resolveKind(item.kind)}
|
||||||
<div className="flex flex-grow flex-col">
|
<div className="flex grow flex-col">
|
||||||
<span className="font-semibold wrap-anywhere">{item.name}</span>
|
<span className="font-semibold wrap-anywhere">{item.name}</span>
|
||||||
<span className={cx('truncate text-sm', isMobile ? 'max-w-[30ch]' : 'max-w-[40ch]')}>{item.summary}</span>
|
<span className={cx('truncate text-sm', isMobile ? 'max-w-[30ch]' : 'max-w-[40ch]')}>{item.summary}</span>
|
||||||
<span className={cx('truncate text-xs', isMobile ? 'max-w-[30ch]' : 'max-w-[40ch]')}>{item.path}</span>
|
<span className={cx('truncate text-xs', isMobile ? 'max-w-[30ch]' : 'max-w-[40ch]')}>{item.path}</span>
|
||||||
</div>
|
</div>
|
||||||
<ArrowRight aria-hidden className="flex-shrink-0" />
|
<ArrowRight aria-hidden className="shrink-0" />
|
||||||
</Command.Item>
|
</Command.Item>
|
||||||
)) ?? [];
|
)) ?? [];
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import Cloudflare from 'cloudflare';
|
// import Cloudflare from 'cloudflare';
|
||||||
import { ENV } from './env';
|
import { ENV } from './env';
|
||||||
|
|
||||||
const client = new Cloudflare({
|
// const client = new Cloudflare({
|
||||||
apiToken: process.env.CF_D1_DOCS_API_KEY,
|
// apiToken: process.env.CF_D1_DOCS_API_KEY,
|
||||||
});
|
// });
|
||||||
|
|
||||||
export async function fetchVersions(packageName: string) {
|
export async function fetchVersions(packageName: string) {
|
||||||
if (ENV.IS_LOCAL_DEV) {
|
if (ENV.IS_LOCAL_DEV) {
|
||||||
@@ -11,13 +11,32 @@ export async function fetchVersions(packageName: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { result } = await client.d1.database.query(process.env.CF_D1_DOCS_ID!, {
|
// const { result } = await client.d1.database.query(process.env.CF_D1_DOCS_ID!, {
|
||||||
account_id: process.env.CF_ACCOUNT_ID!,
|
// account_id: process.env.CF_ACCOUNT_ID!,
|
||||||
sql: `select version from documentation where name = ? order by version desc;`,
|
// sql: `select version from documentation where name = ? order by version desc;`,
|
||||||
params: [packageName],
|
// params: [packageName],
|
||||||
});
|
// });
|
||||||
|
|
||||||
return (result[0]?.results as { version: string }[] | undefined) ?? [];
|
// return (result[0]?.results as { version: string }[] | undefined) ?? [];
|
||||||
|
|
||||||
|
const response = await fetch(
|
||||||
|
`https://api.cloudflare.com/client/v4/accounts/${process.env.CF_ACCOUNT_ID}/d1/database/${process.env.CF_D1_DOCS_ID}/query`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${process.env.CF_D1_DOCS_API_KEY}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
sql: `select version from documentation where name = ? order by version desc;`,
|
||||||
|
params: [packageName],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
return data.result[0]?.results;
|
||||||
} catch {
|
} catch {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|||||||
19
apps/website/wrangler.jsonc
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"$schema": "node_modules/wrangler/config-schema.json",
|
||||||
|
"main": ".open-next/worker.js",
|
||||||
|
"name": "discordjs-website",
|
||||||
|
"keep_names": false,
|
||||||
|
"compatibility_date": "2025-10-04",
|
||||||
|
"compatibility_flags": ["nodejs_compat"],
|
||||||
|
"assets": {
|
||||||
|
"directory": ".open-next/assets",
|
||||||
|
"binding": "ASSETS",
|
||||||
|
},
|
||||||
|
"observability": {
|
||||||
|
"logs": {
|
||||||
|
"enabled": true,
|
||||||
|
"head_sampling_rate": 1,
|
||||||
|
"invocation_logs": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
0
packages/api-extractor/bin/api-extractor
Executable file → Normal file
0
packages/docgen/bin/index.js
Executable file → Normal file
0
packages/scripts/bin/generateSplitDocumentation.js
Executable file → Normal file
0
packages/scripts/bin/sortLabels.js
Executable file → Normal file
6302
pnpm-lock.yaml
generated
@@ -14,8 +14,10 @@ onlyBuiltDependencies:
|
|||||||
- bufferutil
|
- bufferutil
|
||||||
- esbuild
|
- esbuild
|
||||||
- protobufjs
|
- protobufjs
|
||||||
|
- rclone.js
|
||||||
- sharp
|
- sharp
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
|
- workerd
|
||||||
- zlib-sync
|
- zlib-sync
|
||||||
|
|
||||||
patchedDependencies:
|
patchedDependencies:
|
||||||
|
|||||||