0 ? dataset[0].bench.unit : "",
+ },
+ beginAtZero: true,
+ },
+ },
+ plugins: {
+ tooltip: {
+ callbacks: {
+ afterTitle: (items) => {
+ const index = items[0].dataIndex;
+ const data = dataset[index];
+ return "\n" + data.commit.message + "\n\n" + data.commit.timestamp + " committed by @" +
+ data.commit.author.username + "\n";
+ },
+ label: (item) => {
+ let label = item.formattedValue;
+ const { range, unit } = dataset[item.datasetIndex].bench;
+ label += " " + unit;
+ if (range) {
+ label += " (" + range + ")";
+ }
+ return label;
+ },
+ afterLabel: (item) => {
+ const { extra } = dataset[item.datasetIndex].bench;
+ return extra ? "\n" + extra : "";
+ },
+ },
+ },
+ },
+ onClick: (_mouseEvent, activeElems) => {
+ if (activeElems.length === 0) {
+ return;
+ }
+ // XXX: Undocumented. How can we know the index?
+ const index = activeElems[0].index;
+ const url = dataset[index].commit.url;
+ window.open(url, "_blank");
+ },
+ }}
+ />
+ );
+};
+
+export default function BenchmarkResultCharts(): JSX.Element {
+ const [data, setData] = useState<{ entries: { Benchmark: [] } }>();
+
+ useEffect(() => {
+ if (!data) {
+ (async () => {
+ setData(
+ JSON.parse(
+ (await (await fetch(
+ "https://raw.githubusercontent.com/discordeno/discordeno/benchies/benchmarksResult/data.js",
+ )).text()).slice(24),
+ ),
+ );
+ })();
+ }
+ }, []);
+
+ function collectBenchesPerTestCase(entries) {
+ const dataMap = new Map();
+ for (const entry of entries) {
+ const { commit, date, tool, benches } = entry;
+ for (const bench of benches) {
+ const result = { commit, date, tool, bench };
+ const arr = dataMap.get(bench.name);
+ if (arr === undefined) {
+ dataMap.set(bench.name, [result]);
+ } else {
+ arr.push(result);
+ }
+ }
+ }
+ return dataMap;
+ }
+
+ return (
+
+ {data
+ ? Array.from(
+ collectBenchesPerTestCase(data.entries.Benchmark),
+ ([key, value]) => ({ benchName: key, benches: value }),
+ ).map((
+ bench,
+ index,
+ ) => (
+
+ ))
+ : <>>}
+
+ );
+}
diff --git a/site/src/components/BenchmarkResultCharts.jsx b/site/src/components/BenchmarkResultCharts.jsx
deleted file mode 100644
index ef040f82a..000000000
--- a/site/src/components/BenchmarkResultCharts.jsx
+++ /dev/null
@@ -1,147 +0,0 @@
-import { useColorMode } from "@docusaurus/theme-common";
-import React, { useEffect, useState } from "react";
-import { Line } from "react-chartjs-2";
-// Colors from https://github.com/github/linguist/blob/master/lib/linguist/languages.yml
-const toolColors = {
- cargo: "#dea584",
- go: "#00add8",
- benchmarkjs: "#f1e05a",
- benchmarkluau: "#000080",
- pytest: "#3572a5",
- googlecpp: "#f34b7d",
- catch2: "#f34b7d",
- julia: "#a270ba",
- benchmarkdotnet: "#178600",
- customBiggerIsBetter: "#38ff38",
- customSmallerIsBetter: "#ff3838",
- _: "#333333",
-};
-
-const BenchmarkResultChart = ({ name, dataset, theme }) => {
- const color = toolColors[dataset.length > 0 ? dataset[0].tool : "_"];
- const data = {
- labels: dataset.map((d) => d.commit.id.slice(0, 7)),
- datasets: [
- {
- label: name,
- data: dataset.map((d) => d.bench.value),
- borderColor: color,
- backgroundColor: color + "60", // Add alpha for #rrggbbaa
- },
- ],
- };
- const options = {
- scales: {
- xAxes: [
- {
- scaleLabel: {
- display: true,
- labelString: "commit",
- },
- },
- ],
- yAxes: [
- {
- scaleLabel: {
- display: true,
- labelString: dataset.length > 0 ? dataset[0].bench.unit : "",
- },
- ticks: {
- beginAtZero: true,
- },
- },
- ],
- legend: {
- labels: {
- // This more specific font property overrides the global property
- defaultFontColor: theme === "light" ? "#000000" : "#FFFFFF",
- },
- },
- },
- tooltips: {
- callbacks: {
- afterTitle: (items) => {
- const { index } = items[0];
- const data = dataset[index];
- return "\n" + data.commit.message + "\n\n" + data.commit.timestamp + " committed by @" +
- data.commit.committer.username + "\n";
- },
- label: (item) => {
- let label = item.value;
- const { range, unit } = dataset[item.index].bench;
- label += " " + unit;
- if (range) {
- label += " (" + range + ")";
- }
- return label;
- },
- afterLabel: (item) => {
- const { extra } = dataset[item.index].bench;
- return extra ? "\n" + extra : "";
- },
- },
- },
- onClick: (_mouseEvent, activeElems) => {
- if (activeElems.length === 0) {
- return;
- }
- // XXX: Undocumented. How can we know the index?
- const index = activeElems[0]._index;
- const url = dataset[index].commit.url;
- window.open(url, "_blank");
- },
- };
- // console.log(theme);
- return ;
-};
-
-export default function BenchmarkResultCharts() {
- const { colorMode } = useColorMode();
- const [data, setData] = useState();
-
- useEffect(async () => {
- if (!data) {
- setData(
- JSON.parse(
- (await (await fetch(
- "https://raw.githubusercontent.com/discordeno/discordeno/benchies/benchmarksResult/data.js",
- )).text()).slice(24),
- ),
- );
- }
- }, []);
-
- function collectBenchesPerTestCase(entries) {
- const dataMap = new Map();
- for (const entry of entries) {
- const { commit, date, tool, benches } = entry;
- for (const bench of benches) {
- const result = { commit, date, tool, bench };
- const arr = dataMap.get(bench.name);
- if (arr === undefined) {
- dataMap.set(bench.name, [result]);
- } else {
- arr.push(result);
- }
- }
- }
- return dataMap;
- }
-
- return (data
- ? Array.from(
- collectBenchesPerTestCase(data.entries.Benchmark),
- ([key, value]) => ({ benchName: key, benches: value }),
- ).map((
- bench,
- index,
- ) => (
-
- ))
- : <>>);
-}
diff --git a/site/src/components/architecture/BaseFlowChart.tsx b/site/src/components/architecture/BaseFlowChart.tsx
new file mode 100644
index 000000000..bc1117bb2
--- /dev/null
+++ b/site/src/components/architecture/BaseFlowChart.tsx
@@ -0,0 +1,93 @@
+import React, { useEffect, useState } from "react";
+import ReactFlow, { Background, Controls, Edge, Handle, Node, Position, useEdgesState, useNodesState } from "reactflow";
+import "reactflow/dist/style.css";
+
+export const multiplier = 225;
+export const height = 40;
+export const widthMultiplier = 0.75;
+
+export const defaultNodeOptions = {
+ targetPosition: Position.Left,
+ sourcePosition: Position.Right,
+ draggable: false,
+ style: { width: `${multiplier * 0.75}px`, height: `${height}px` },
+};
+
+export const defaultGroupOptions = {
+ draggable: false,
+};
+
+export default function BaseFlowChart(
+ { initialNodes = [], initialEdges = [] }: { initialNodes: Node[]; initialEdges: Edge[] },
+) {
+ function getWindowDimensions() {
+ const { innerWidth: width, innerHeight: height } = window;
+ return {
+ width,
+ height,
+ };
+ }
+
+ const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());
+
+ useEffect(() => {
+ function handleResize() {
+ setWindowDimensions(getWindowDimensions());
+ }
+
+ window.addEventListener("resize", handleResize);
+ return () => window.removeEventListener("resize", handleResize);
+ }, []);
+
+ const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
+ const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
+
+ return (
+ <>
+ = 997
+ ? `${
+ (100 *
+ ((windowDimensions.width - 300 -
+ (windowDimensions.width >= 1620 ? (windowDimensions.width - 1620) * 0.5 : 0)) /
+ windowDimensions.width) - 2) * widthMultiplier
+ }vw`
+ : "95vw",
+ height: "25vh",
+ }}
+ >
+
(
+
+
+
+
+ ),
+ baseLineNodeText: (n) => (
+
+
{n.data.label}
+
+ ),
+ }}
+ fitView
+ >
+
+
+
+
+ >
+ );
+}
diff --git a/site/src/components/architecture/FlowChart.tsx b/site/src/components/architecture/FlowChart.tsx
new file mode 100644
index 000000000..d89ade8eb
--- /dev/null
+++ b/site/src/components/architecture/FlowChart.tsx
@@ -0,0 +1,103 @@
+import React from "react";
+import { Edge, Node } from "reactflow";
+import "reactflow/dist/style.css";
+import BaseFlowChart, { defaultNodeOptions, multiplier } from "./BaseFlowChart";
+
+const initialNodes: Node[] = [
+ {
+ id: "discordGateway",
+ type: "input",
+ position: { x: 0 * multiplier, y: 0 },
+ data: { label: "Discord Gateway" },
+ ...defaultNodeOptions,
+ },
+ { id: "gateway", position: { x: 1 * multiplier, y: 0 }, data: { label: "Gateway" }, ...defaultNodeOptions },
+ { id: "baseLineNode-1", type: "baseLineNode", position: { x: 0.85 * multiplier, y: 170 }, data: {} },
+ { id: "baseLineNode-2", type: "baseLineNode", position: { x: 0.85 * multiplier, y: -130 }, data: {} },
+ { id: "baseLineNode-3", type: "baseLineNode", position: { x: 2.85 * multiplier, y: 170 }, data: {} },
+ { id: "baseLineNode-4", type: "baseLineNode", position: { x: 2.85 * multiplier, y: -130 }, data: {} },
+ { id: "baseLineNode-5", type: "baseLineNode", position: { x: 3.85 * multiplier, y: 170 }, data: {} },
+ { id: "baseLineNode-6", type: "baseLineNode", position: { x: 3.85 * multiplier, y: -130 }, data: {} },
+ { id: "baseLineNode-7", type: "baseLineNode", position: { x: 4.85 * multiplier, y: 170 }, data: {} },
+ { id: "baseLineNode-8", type: "baseLineNode", position: { x: 4.85 * multiplier, y: -130 }, data: {} },
+ {
+ id: "baseLineNodeText-1",
+ type: "baseLineNodeText",
+ position: { x: 0 * multiplier, y: -130 },
+ data: { label: "Discord" },
+ },
+ {
+ id: "baseLineNodeText-2",
+ type: "baseLineNodeText",
+ position: { x: 1.5 * multiplier, y: -130 },
+ data: { label: "Event In" },
+ },
+ {
+ id: "baseLineNodeText-3",
+ type: "baseLineNodeText",
+ position: { x: 3 * multiplier, y: -130 },
+ data: { label: "Event Processing" },
+ },
+ {
+ id: "baseLineNodeText-4",
+ type: "baseLineNodeText",
+ position: { x: 4 * multiplier, y: -130 },
+ data: { label: "Event out" },
+ },
+ {
+ id: "baseLineNodeText-6",
+ type: "baseLineNodeText",
+ position: { x: 5 * multiplier, y: -130 },
+ data: { label: "Discord" },
+ },
+ { id: "bot", position: { x: 2 * multiplier, y: 0 }, data: { label: "Bot" }, ...defaultNodeOptions },
+ { id: "yourCode", position: { x: 3 * multiplier, y: 0 }, data: { label: "Your Code" }, ...defaultNodeOptions },
+ { id: "rest", position: { x: 4 * multiplier, y: 0 }, data: { label: "Rest" }, ...defaultNodeOptions },
+ {
+ id: "discordApiGateway",
+ type: "output",
+ position: { x: 5 * multiplier, y: 0 },
+ data: { label: "Discord Api" },
+ ...defaultNodeOptions,
+ },
+];
+
+const initialEdges: Edge[] = [
+ { id: "d-g", source: "discordGateway", target: "gateway" },
+ { id: "g-b", source: "gateway", target: "bot" },
+ { id: "b-y", source: "bot", target: "yourCode" },
+ { id: "y-r", source: "yourCode", target: "rest" },
+ { id: "r-d", source: "rest", target: "discordApiGateway" },
+ {
+ id: "baseLine-1",
+ source: "baseLineNode-1",
+ target: "baseLineNode-2",
+ style: { stroke: "blue", strokeDasharray: 20 },
+ animated: false,
+ },
+ {
+ id: "baseLine-2",
+ source: "baseLineNode-3",
+ target: "baseLineNode-4",
+ style: { stroke: "blue", strokeDasharray: 20 },
+ animated: false,
+ },
+ {
+ id: "baseLine-3",
+ source: "baseLineNode-5",
+ target: "baseLineNode-6",
+ style: { stroke: "blue", strokeDasharray: 20 },
+ animated: false,
+ },
+ {
+ id: "baseLine-4",
+ source: "baseLineNode-7",
+ target: "baseLineNode-8",
+ style: { stroke: "blue", strokeDasharray: 20 },
+ animated: false,
+ },
+];
+
+export default function FlowChart() {
+ return ;
+}
diff --git a/site/src/components/architecture/FlowChart2.tsx b/site/src/components/architecture/FlowChart2.tsx
new file mode 100644
index 000000000..6f10ee87d
--- /dev/null
+++ b/site/src/components/architecture/FlowChart2.tsx
@@ -0,0 +1,198 @@
+import React from "react";
+import { Edge, Node, Position } from "reactflow";
+import "reactflow/dist/style.css";
+import BaseFlowChart, { defaultGroupOptions, defaultNodeOptions, multiplier } from "./BaseFlowChart";
+
+const initialNodes: Node[] = [
+ {
+ id: "discordGateway",
+ type: "input",
+ position: { x: 0 * multiplier, y: 0 },
+ data: { label: "Discord Gateway" },
+ ...defaultNodeOptions,
+ },
+ { id: "baseLineNode-1", type: "baseLineNode", position: { x: 0.85 * multiplier, y: 170 }, data: {} },
+ { id: "baseLineNode-2", type: "baseLineNode", position: { x: 0.85 * multiplier, y: -130 }, data: {} },
+ { id: "baseLineNode-3", type: "baseLineNode", position: { x: 3.75 * multiplier, y: 170 }, data: {} },
+ { id: "baseLineNode-4", type: "baseLineNode", position: { x: 3.75 * multiplier, y: -130 }, data: {} },
+ {
+ id: "baseLineNodeText-1",
+ type: "baseLineNodeText",
+ position: { x: 0 * multiplier, y: -130 },
+ data: { label: "Discord" },
+ },
+ {
+ id: "baseLineNodeText-2",
+ type: "baseLineNodeText",
+ position: { x: 2 * multiplier, y: -130 },
+ data: { label: "Gateway" },
+ },
+ {
+ id: "baseLineNodeText-3",
+ type: "baseLineNodeText",
+ position: { x: 4 * multiplier, y: -130 },
+ data: { label: "Bot" },
+ },
+ {
+ id: "gatewayManager",
+ type: "input",
+ position: { x: 2.0625 * multiplier, y: -80 },
+ data: { label: "Gateway Manager" },
+ ...defaultNodeOptions,
+ targetPosition: Position.Top,
+ sourcePosition: Position.Bottom,
+ },
+ {
+ id: "shard-1",
+ type: "output",
+ position: { x: 1.25 * multiplier, y: -20 },
+ data: { label: "Shard-1" },
+ style: { width: `${multiplier * 2}px`, height: "80px" },
+ ...defaultGroupOptions,
+ },
+ {
+ id: "shard-1-socket",
+ position: { x: 0.125 * multiplier, y: 20 },
+ data: { label: "webSocket" },
+ ...defaultNodeOptions,
+ parentNode: "shard-1",
+ extent: "parent",
+ },
+ {
+ id: "shard-1-handleMessage",
+ position: { x: 1.125 * multiplier, y: 20 },
+ data: { label: "HandleMessage" },
+ ...defaultNodeOptions,
+ parentNode: "shard-1",
+ extent: "parent",
+ },
+ {
+ id: "shard-2",
+ type: "output",
+ position: { x: 1.375 * multiplier, y: 0 },
+ data: { label: "Shard-2" },
+ style: { width: `${multiplier * 2}px`, height: "80px" },
+ ...defaultGroupOptions,
+ },
+ {
+ id: "shard-2-socket",
+ position: { x: 0.125 * multiplier, y: 20 },
+ data: { label: "webSocket" },
+ ...defaultNodeOptions,
+ parentNode: "shard-2",
+ extent: "parent",
+ },
+ {
+ id: "shard-2-handleMessage",
+ position: { x: 1.125 * multiplier, y: 20 },
+ data: { label: "HandleMessage" },
+ ...defaultNodeOptions,
+ parentNode: "shard-2",
+ extent: "parent",
+ },
+ {
+ id: "shard-3",
+ type: "output",
+ position: { x: 1.5 * multiplier, y: 20 },
+ data: { label: "Shard-3" },
+ style: { width: `${multiplier * 2}px`, height: "80px" },
+ ...defaultGroupOptions,
+ },
+ {
+ id: "shard-3-socket",
+ position: { x: 0.125 * multiplier, y: 20 },
+ data: { label: "webSocket" },
+ ...defaultNodeOptions,
+ parentNode: "shard-3",
+ extent: "parent",
+ },
+ {
+ id: "shard-3-handleMessage",
+ position: { x: 1.125 * multiplier, y: 20 },
+ data: { label: "HandleMessage" },
+ ...defaultNodeOptions,
+ parentNode: "shard-3",
+ extent: "parent",
+ },
+ {
+ id: "shard-n",
+ type: "output",
+ position: { x: 1.625 * multiplier, y: 40 },
+ data: { label: "Shard-N" },
+ style: { width: `${multiplier * 2}px`, height: "80px" },
+ ...defaultGroupOptions,
+ },
+ {
+ id: "shard-n-socket",
+ position: { x: 0.125 * multiplier, y: 20 },
+ data: { label: "webSocket" },
+ ...defaultNodeOptions,
+ parentNode: "shard-n",
+ extent: "parent",
+ },
+ {
+ id: "shard-n-handleMessage",
+ position: { x: 1.125 * multiplier, y: 20 },
+ data: { label: "HandleMessage" },
+ ...defaultNodeOptions,
+ parentNode: "shard-n",
+ extent: "parent",
+ },
+ { id: "bot", type: "output", position: { x: 4 * multiplier, y: 0 }, data: { label: "Bot" }, ...defaultNodeOptions },
+];
+
+const initialEdges: Edge[] = [
+ { id: "d-g", source: "discordGateway", target: "gateway" },
+ { id: "g-b", source: "gateway", target: "bot" },
+ { id: "b-y", source: "bot", target: "yourCode" },
+ { id: "y-r", source: "yourCode", target: "rest" },
+ { id: "r-d", source: "rest", target: "discordApiGateway" },
+ {
+ id: "baseLine-1",
+ source: "baseLineNode-1",
+ target: "baseLineNode-2",
+ style: { stroke: "blue", strokeDasharray: 20 },
+ animated: false,
+ },
+ {
+ id: "baseLine-2",
+ source: "baseLineNode-3",
+ target: "baseLineNode-4",
+ style: { stroke: "blue", strokeDasharray: 20 },
+ animated: false,
+ },
+ {
+ id: "baseLine-3",
+ source: "baseLineNode-5",
+ target: "baseLineNode-6",
+ style: { stroke: "blue", strokeDasharray: 20 },
+ animated: false,
+ },
+ {
+ id: "baseLine-4",
+ source: "baseLineNode-7",
+ target: "baseLineNode-8",
+ style: { stroke: "blue", strokeDasharray: 20 },
+ animated: false,
+ },
+ { id: "d-shard-1", source: "discordGateway", target: "shard-1-socket", zIndex: 100 },
+ { id: "d-shard-2", source: "discordGateway", target: "shard-2-socket", zIndex: 100 },
+ { id: "d-shard-3", source: "discordGateway", target: "shard-3-socket", zIndex: 100 },
+ { id: "d-shard-n", source: "discordGateway", target: "shard-n-socket", zIndex: 100 },
+ { id: "shard-1-socket-handleMessage", source: "shard-1-socket", target: "shard-1-handleMessage", zIndex: 100 },
+ { id: "shard-2-socket-handleMessage", source: "shard-2-socket", target: "shard-2-handleMessage", zIndex: 100 },
+ { id: "shard-3-socket-handleMessage", source: "shard-3-socket", target: "shard-3-handleMessage", zIndex: 100 },
+ { id: "shard-n-socket-handleMessage", source: "shard-n-socket", target: "shard-n-handleMessage", zIndex: 100 },
+ { id: "shard-1-handleMessage-bot", source: "shard-1-handleMessage", target: "bot", zIndex: 100 },
+ { id: "shard-2-handleMessage-bot", source: "shard-2-handleMessage", target: "bot", zIndex: 100 },
+ { id: "shard-3-handleMessage-bot", source: "shard-3-handleMessage", target: "bot", zIndex: 100 },
+ { id: "shard-n-handleMessage-bot", source: "shard-n-handleMessage", target: "bot", zIndex: 100 },
+ { id: "gatewayManager-shard-1", source: "gatewayManager", target: "shard-1", zIndex: 10 },
+ { id: "gatewayManager-shard-2", source: "gatewayManager", target: "shard-2", zIndex: 100 },
+ { id: "gatewayManager-shard-3", source: "gatewayManager", target: "shard-3", zIndex: 100 },
+ { id: "gatewayManager-shard-n", source: "gatewayManager", target: "shard-n", zIndex: 100 },
+];
+
+export default function FlowChart2() {
+ return ;
+}
diff --git a/site/src/components/architecture/FlowChart3.tsx b/site/src/components/architecture/FlowChart3.tsx
new file mode 100644
index 000000000..6131215e4
--- /dev/null
+++ b/site/src/components/architecture/FlowChart3.tsx
@@ -0,0 +1,669 @@
+import React, { useEffect, useState } from "react";
+import ReactFlow, {
+ Background,
+ Controls,
+ Edge,
+ Handle,
+ Node,
+ NodeMouseHandler,
+ Position,
+ useEdgesState,
+ useNodesState,
+} from "reactflow";
+import "reactflow/dist/style.css";
+import { defaultNodeOptions, height, multiplier, widthMultiplier } from "./BaseFlowChart";
+
+const handlers: {
+ [index: string]: {
+ transformers: string[];
+ event: string;
+ };
+} = {
+ handleChannelCreate: { transformers: ["transformers.channel"], event: "events.channelCreate" },
+ handleChannelDelete: {
+ transformers: ["transformers.channel", "transformers.snowflake"],
+ event: "events.channelDelete",
+ },
+ handleChannelPinsUpdate: {
+ transformers: ["transformers.snowflake", "transformers.snowflake"],
+ event: "events.channelPinsUpdate",
+ },
+ handleChannelUpdate: { transformers: ["transformers.channel"], event: "events.channelUpdate" },
+ handleStageInstanceCreate: {
+ transformers: ["transformers.snowflake", "transformers.snowflake", "transformers.snowflake"],
+ event: "events.stageInstanceCreate",
+ },
+ handleStageInstanceDelete: {
+ transformers: ["transformers.snowflake", "transformers.snowflake", "transformers.snowflake"],
+ event: "events.stageInstanceDelete",
+ },
+ handleStageInstanceUpdate: {
+ transformers: ["transformers.snowflake", "transformers.snowflake", "transformers.snowflake"],
+ event: "events.stageInstanceUpdate",
+ },
+ handleThreadCreate: { transformers: ["transformers.channel"], event: "events.threadCreate" },
+ handleThreadDelete: { transformers: ["transformers.channel"], event: "events.threadDelete" },
+ handleThreadListSync: {
+ transformers: [
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.channel",
+ "transformers.snowflake",
+ "transformers.snowflake",
+ ],
+ event: undefined,
+ },
+ handleThreadMembersUpdate: {
+ transformers: [
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.threadMember",
+ "transformers.snowflake",
+ ],
+ event: "events.threadMembersUpdate",
+ },
+ handleThreadMemberUpdate: {
+ transformers: ["transformers.snowflake", "transformers.snowflake"],
+ event: "events.threadMemberUpdate",
+ },
+ handleThreadUpdate: { transformers: ["transformers.channel"], event: "events.threadUpdate" },
+ handleGuildEmojisUpdate: {
+ transformers: ["transformers.snowflake", "transformers.snowflake"],
+ event: "events.guildEmojisUpdate",
+ },
+ handleAutoModerationActionExecution: {
+ transformers: ["transformers.automodActionExecution"],
+ event: "events.automodActionExecution",
+ },
+ handleAutoModerationRuleCreate: { transformers: ["transformers.automodRule"], event: "events.automodRuleCreate" },
+ handleAutoModerationRuleDelete: { transformers: ["transformers.automodRule"], event: "events.automodRuleDelete" },
+ handleAutoModerationRuleUpdate: { transformers: ["transformers.automodRule"], event: "events.automodRuleUpdate" },
+ handleGuildBanAdd: {
+ transformers: ["transformers.user", "transformers.snowflake"],
+ event: "events.guildBanAdd",
+ },
+ handleGuildBanRemove: {
+ transformers: ["transformers.user", "transformers.snowflake"],
+ event: "events.guildBanRemove",
+ },
+ handleGuildCreate: { transformers: ["transformers.guild"], event: "events.guildCreate" },
+ handleGuildDelete: { transformers: ["transformers.snowflake"], event: "events.guildDelete" },
+ handleGuildIntegrationsUpdate: { transformers: ["transformers.snowflake"], event: "events.integrationUpdate" },
+ handleGuildUpdate: { transformers: ["transformers.guild"], event: "events.guildUpdate" },
+ handleGuildScheduledEventCreate: {
+ transformers: ["transformers.scheduledEvent"],
+ event: "events.scheduledEventCreate",
+ },
+ handleGuildScheduledEventDelete: {
+ transformers: ["transformers.scheduledEvent"],
+ event: "events.scheduledEventDelete",
+ },
+ handleGuildScheduledEventUpdate: {
+ transformers: ["transformers.scheduledEvent"],
+ event: "events.scheduledEventUpdate",
+ },
+ handleGuildScheduledEventUserAdd: {
+ transformers: ["transformers.snowflake", "transformers.snowflake", "transformers.snowflake"],
+ event: "events.scheduledEventUserAdd",
+ },
+ handleGuildScheduledEventUserRemove: {
+ transformers: ["transformers.snowflake", "transformers.snowflake", "transformers.snowflake"],
+ event: "events.scheduledEventUserRemove",
+ },
+ handleIntegrationCreate: { transformers: ["transformers.integration"], event: "events.integrationCreate" },
+ handleIntegrationDelete: {
+ transformers: ["transformers.snowflake", "transformers.snowflake", "transformers.snowflake"],
+ event: "events.integrationDelete",
+ },
+ handleIntegrationUpdate: { transformers: ["transformers.integration"], event: "events.integrationUpdate" },
+ handleInteractionCreate: {
+ transformers: ["transformers.snowflake", "transformers.interaction"],
+ event: "events.interactionCreate",
+ },
+ handleInviteCreate: { transformers: ["transformers.invite"], event: "events.inviteCreate" },
+ handleInviteDelete: {
+ transformers: ["transformers.snowflake", "transformers.snowflake"],
+ event: "events.inviteDelete",
+ },
+ handleGuildMembersChunk: {
+ transformers: [
+ "transformers.snowflake",
+ "transformers.member",
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.user",
+ "transformers.activity",
+ ],
+ event: undefined,
+ },
+ handleGuildMemberAdd: {
+ transformers: ["transformers.snowflake", "transformers.user", "transformers.member"],
+ event: "events.guildMemberAdd",
+ },
+ handleGuildMemberRemove: {
+ transformers: ["transformers.snowflake", "transformers.user"],
+ event: "events.guildMemberRemove",
+ },
+ handleGuildMemberUpdate: {
+ transformers: ["transformers.user", "transformers.member", "transformers.snowflake"],
+ event: "events.guildMemberUpdate",
+ },
+ handleMessageCreate: { transformers: ["transformers.message"], event: "events.messageCreate" },
+ handleMessageDelete: {
+ transformers: ["transformers.snowflake", "transformers.snowflake", "transformers.snowflake"],
+ event: "events.messageDelete",
+ },
+ handleMessageDeleteBulk: {
+ transformers: [
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.snowflake",
+ ],
+ event: "events.messageDeleteBulk",
+ },
+ handleMessageReactionAdd: {
+ transformers: [
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.member",
+ "transformers.user",
+ "transformers.emoji",
+ ],
+ event: "events.reactionAdd",
+ },
+ handleMessageReactionRemove: {
+ transformers: [
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.emoji",
+ ],
+ event: "events.reactionRemove",
+ },
+ handleMessageReactionRemoveAll: {
+ transformers: ["transformers.snowflake", "transformers.snowflake", "transformers.snowflake"],
+ event: "events.reactionRemoveAll",
+ },
+ handleMessageReactionRemoveEmoji: {
+ transformers: [
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.emoji",
+ ],
+ event: "events.reactionRemoveEmoji",
+ },
+ handleMessageUpdate: { transformers: ["transformers.message"], event: "events.messageUpdate" },
+ handlePresenceUpdate: { transformers: ["transformers.presence"], event: "events.presenceUpdate" },
+ handleReady: {
+ transformers: [
+ "transformers.user",
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.snowflake",
+ ],
+ event: "events.ready",
+ },
+ handleTypingStart: {
+ transformers: [
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.snowflake",
+ "transformers.member",
+ ],
+ event: "events.typingStart",
+ },
+ handleUserUpdate: { transformers: ["transformers.user"], event: "events.botUpdate" },
+ handleGuildRoleCreate: {
+ transformers: ["transformers.role", "transformers.snowflake"],
+ event: "events.roleCreate",
+ },
+ handleGuildRoleDelete: {
+ transformers: ["transformers.snowflake", "transformers.snowflake"],
+ event: "events.roleDelete",
+ },
+ handleGuildRoleUpdate: {
+ transformers: ["transformers.role", "transformers.snowflake"],
+ event: "events.roleUpdate",
+ },
+ handleVoiceServerUpdate: { transformers: ["transformers.snowflake"], event: "events.voiceServerUpdate" },
+ handleVoiceStateUpdate: {
+ transformers: ["transformers.snowflake", "transformers.voiceState"],
+ event: "events.voiceStateUpdate",
+ },
+ handleWebhooksUpdate: {
+ transformers: ["transformers.snowflake", "transformers.snowflake"],
+ event: "events.webhooksUpdate",
+ },
+};
+
+export default function FlowChart({ handlerFilter = (handler: string) => true }) {
+ function getWindowDimensions() {
+ const { innerWidth: width, innerHeight: height } = window;
+ return {
+ width,
+ height,
+ };
+ }
+
+ const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());
+
+ useEffect(() => {
+ function handleResize() {
+ setWindowDimensions(getWindowDimensions());
+ }
+
+ window.addEventListener("resize", handleResize);
+ return () => window.removeEventListener("resize", handleResize);
+ }, []);
+
+ const transformers = [];
+
+ const events = [];
+
+ const initialNodes: Node[] = [
+ {
+ id: "baseNode-gateway",
+ type: "input",
+ position: { x: 0 * multiplier, y: 0 },
+ data: { label: "gateway" },
+ ...defaultNodeOptions,
+ },
+ {
+ id: "baseNode-yourCode",
+ type: "output",
+ position: { x: 5 * multiplier, y: 0 },
+ data: { label: "Your Code" },
+ ...defaultNodeOptions,
+ },
+ { id: "baseLineNode-1", type: "baseLineNode", position: { x: 0.85 * multiplier, y: 170 }, data: {} },
+ { id: "baseLineNode-2", type: "baseLineNode", position: { x: 0.85 * multiplier, y: -130 }, data: {} },
+ { id: "baseLineNode-3", type: "baseLineNode", position: { x: 4.85 * multiplier, y: 170 }, data: {} },
+ { id: "baseLineNode-4", type: "baseLineNode", position: { x: 4.85 * multiplier, y: -130 }, data: {} },
+ {
+ id: "baseLineNodeText-1",
+ type: "baseLineNodeText",
+ position: { x: 0 * multiplier, y: -130 },
+ data: { label: "Gateway" },
+ },
+ {
+ id: "baseLineNodeText-2",
+ type: "baseLineNodeText",
+ position: { x: 1 * multiplier, y: -130 },
+ data: { label: "Bot" },
+ },
+ {
+ id: "baseLineNodeText-3",
+ type: "baseLineNodeText",
+ position: { x: 5 * multiplier, y: -130 },
+ data: { label: "Your Code" },
+ },
+ {
+ id: "baseNode-handleDiscordPayload",
+ position: { x: 1 * multiplier, y: 0 },
+ data: { label: "Handle discord payload" },
+ ...defaultNodeOptions,
+ },
+ ];
+
+ const initialEdges: Edge[] = [
+ { id: "baseEdge-1", source: "baseNode-gateway", target: "baseNode-handleDiscordPayload" },
+ { id: "baseEdge-3", source: "baseNode-g-1", target: "baseNode-g-2" },
+ { id: "baseEdge-4", source: "baseNode-g-2", target: "baseNode-handleDiscordPayload" },
+ {
+ id: "baseLine-1",
+ source: "baseLineNode-1",
+ target: "baseLineNode-2",
+ style: { stroke: "blue", strokeDasharray: 20 },
+ },
+ {
+ id: "baseLine-2",
+ source: "baseLineNode-3",
+ target: "baseLineNode-4",
+ style: { stroke: "blue", strokeDasharray: 20 },
+ },
+ ];
+
+ //@ts-ignore
+ for (const [index, handler] of Object.keys(handlers).filter(handlerFilter).entries()) {
+ initialNodes.push({
+ id: handler,
+ position: {
+ x: 2 * multiplier,
+ y: index * (height + 10) - Object.keys(handlers).filter(handlerFilter).length * ((height + 10) / 2) +
+ height / 2,
+ },
+ data: { label: handler.slice(6) },
+ ...defaultNodeOptions,
+ });
+ initialEdges.push({
+ id: `handleDiscordPayload-${handler}`,
+ source: "baseNode-handleDiscordPayload",
+ target: handler,
+ });
+ if (!events.find((e) => e === handlers[handler].event) && handlers[handler].event) {
+ events.push(handlers[handler].event);
+ initialEdges.push({
+ id: `${handlers[handler].event}-yourCode`,
+ source: handlers[handler].event,
+ target: "baseNode-yourCode",
+ });
+ }
+ for (const transformer of handlers[handler].transformers) {
+ if (!transformers.find((t) => t === transformer) && transformer) transformers.push(transformer);
+ if (!initialEdges.find((edge) => edge.id === `${handler}-${transformer}`) && transformer) {
+ initialEdges.push({ id: `${handler}-${transformer}`, source: handler, target: transformer });
+ }
+ if (
+ !initialEdges.find((edge) => edge.id === `${transformer}-${handlers[handler].event}`) && handlers[handler].event
+ ) {
+ initialEdges.push({
+ id: `${transformer}-${handlers[handler].event}`,
+ source: transformer,
+ target: handlers[handler].event,
+ });
+ }
+ }
+ }
+
+ //@ts-ignore
+ for (const [index, transformer] of transformers.entries()) {
+ initialNodes.push({
+ id: transformer,
+ position: {
+ x: 3 * multiplier,
+ y: index * (height + 10) - transformers.length * ((height + 10) / 2) + height / 2,
+ },
+ data: { label: transformer.slice(13) },
+ ...defaultNodeOptions,
+ });
+ }
+
+ //@ts-ignore
+ for (const [index, event] of events.entries()) {
+ initialNodes.push({
+ id: event,
+ position: { x: 4 * multiplier, y: index * (height + 10) - events.length * ((height + 10) / 2) + height / 2 },
+ data: { label: event.slice(7) },
+ ...defaultNodeOptions,
+ });
+ }
+
+ initialNodes.unshift(
+ {
+ id: "handlers",
+ type: "group",
+ position: {
+ x: 1.925 * multiplier,
+ y: -Object.keys(handlers).filter(handlerFilter).length * ((height + 10) / 2) - 45,
+ },
+ data: { label: "" },
+ style: {
+ height: `${Object.keys(handlers).filter(handlerFilter).length * (height + 10) + 75}px`,
+ width: `${multiplier * 0.9}px`,
+ borderColor: "rgba(0,0,0,0.25)",
+ },
+ draggable: false,
+ },
+ {
+ id: "baseLineNodeText-4",
+ type: "baseLineNodeText",
+ position: {
+ x: 2 * multiplier,
+ y: -Object.keys(handlers).filter(handlerFilter).length * ((height + 10) / 2) - ((height + 10) / 2),
+ },
+ data: { label: "Handlers" },
+ draggable: false,
+ },
+ {
+ id: "transformers",
+ type: "group",
+ position: { x: 2.925 * multiplier, y: -transformers.length * ((height + 10) / 2) - 45 },
+ data: { label: "" },
+ style: {
+ height: `${transformers.length * (height + 10) + 75}px`,
+ width: `${multiplier * 0.9}px`,
+ borderColor: "rgba(0,0,0,0.25)",
+ },
+ draggable: false,
+ },
+ {
+ id: "baseLineNodeText-5",
+ type: "baseLineNodeText",
+ position: { x: 3 * multiplier, y: -transformers.length * ((height + 10) / 2) - ((height + 10) / 2) },
+ data: { label: "Transformers" },
+ draggable: false,
+ },
+ {
+ id: "events",
+ type: "group",
+ position: { x: 3.925 * multiplier, y: -events.length * ((height + 10) / 2) - 45 },
+ data: { label: "" },
+ style: {
+ height: `${events.length * (height + 10) + 75}px`,
+ width: `${multiplier * 0.9}px`,
+ borderColor: "rgba(0,0,0,0.25)",
+ },
+ draggable: false,
+ },
+ {
+ id: "baseLineNodeText-6",
+ type: "baseLineNodeText",
+ position: { x: 4 * multiplier, y: -events.length * ((height + 10) / 2) - ((height + 10) / 2) },
+ data: { label: "Event" },
+ draggable: false,
+ },
+ );
+
+ const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
+ const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
+ const [handlerIndex, setHandlerIndex] = useState(0);
+ const [userClick, setUserClick] = useState(false);
+
+ const nodeMouseHandler: NodeMouseHandler = (_, node, userTrigger = true) => {
+ if (userTrigger) setUserClick(true);
+ if (node.id.split("-")[0] === "baseNode") {
+ edges.forEach((e) => {
+ if (e.id.startsWith("baseLine")) return;
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ });
+ setEdges([...edges]);
+ return;
+ }
+ if (Object.keys(handlers).find((h) => handlers[h].event === node.id)) {
+ const handlerName = Object.keys(handlers).find((h) => handlers[h].event === node.id);
+ const handler = handlers[handlerName];
+ edges.forEach((e) => {
+ if (e.id.startsWith("baseLine")) return;
+ if (e.id.split("-")[0] === "baseEdge") {
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ return;
+ }
+ if (e.id.split("-")[0] === "handleDiscordPayload" && e.id.split("-")[1] === handlerName) {
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ return;
+ }
+ if (e.id.split("-")[0] === handlerName && handler.transformers.includes(e.id.split("-")[1])) {
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ return;
+ }
+ if (handler.transformers.includes(e.id.split("-")[0]) && e.id.split("-")[1] === handler.event) {
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ return;
+ }
+ if (e.id.split("-")[0] === handler.event && e.id.split("-")[1] === "yourCode") {
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ return;
+ }
+ e.animated = false;
+ e.style = { opacity: 0.3 };
+ });
+ setEdges([...edges]);
+ return;
+ }
+ if (Object.keys(handlers).find((h) => handlers[h].transformers.includes(node.id))) {
+ edges.forEach((e) => {
+ if (e.id.startsWith("baseLine")) return;
+ if (e.id.split("-")[0] === "baseEdge") {
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ return;
+ }
+ if (
+ e.id.split("-")[0] === "handleDiscordPayload" &&
+ Object.keys(handlers).filter((h) => handlers[h].transformers.includes(node.id)).includes(e.id.split("-")[1])
+ ) {
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ return;
+ }
+ if (
+ Object.keys(handlers).filter((h) => handlers[h].transformers.includes(node.id)).includes(
+ e.id.split("-")[0],
+ ) && e.id.split("-")[1] === node.id
+ ) {
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ return;
+ }
+ if (e.id.split("-")[0] === node.id) {
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ return;
+ }
+ e.animated = false;
+ e.style = { opacity: 0.3 };
+ });
+ setEdges([...edges]);
+ return;
+ }
+ if (handlers[node.id]) {
+ const handler = handlers[node.id];
+ edges.forEach((e) => {
+ if (e.id.startsWith("baseLine")) return;
+ if (e.id.split("-")[0] === "baseEdge") {
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ return;
+ }
+ if (e.id.split("-")[0] === "handleDiscordPayload" && e.id.split("-")[1] === node.id) {
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ return;
+ }
+ if (e.id.split("-")[0] === node.id && handler.transformers.includes(e.id.split("-")[1])) {
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ return;
+ }
+ if (handler.transformers.includes(e.id.split("-")[0]) && e.id.split("-")[1] === handler.event) {
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ return;
+ }
+ if (e.id.split("-")[0] === handler.event) {
+ e.animated = true;
+ e.style = { stroke: "blue" };
+ return;
+ }
+ e.animated = false;
+ e.style = { opacity: 0.3 };
+ });
+ setEdges([...edges]);
+ return;
+ }
+ edges.forEach((e) => {
+ if (e.id.startsWith("baseLine")) return;
+ e.animated = false;
+ e.style = {};
+ });
+ setEdges([...edges]);
+ };
+
+ useEffect(() => {
+ const interval = setInterval(() => {
+ const randomIndex = Math.round((Object.keys(handlers).filter(handlerFilter).length - 1) * Math.random());
+ if (!userClick) {
+ nodeMouseHandler(undefined, { id: Object.keys(handlers).filter(handlerFilter)[randomIndex] }, false);
+ }
+ setHandlerIndex(randomIndex);
+ }, 1000);
+ return () => clearInterval(interval);
+ }, [userClick]);
+
+ useEffect(() => {
+ if (userClick) {
+ const timeout = setTimeout(() => {
+ setUserClick(false);
+ }, 10000);
+ return () => clearTimeout(timeout);
+ }
+ }, [userClick]);
+
+ return (
+ <>
+ = 997
+ ? `${
+ (100 *
+ ((windowDimensions.width - 300 -
+ (windowDimensions.width >= 1620 ? (windowDimensions.width - 1620) * 0.5 : 0)) /
+ windowDimensions.width) - 2) * widthMultiplier
+ }vw`
+ : "95vw",
+ height: "50vh",
+ }}
+ >
+
{
+ //@ts-ignore
+ if (e.target.className === "react-flow__pane") nodeMouseHandler(e, { id: " - ", data: { label: " - " } });
+ }}
+ nodeTypes={{
+ baseLineNode: () => (
+
+
+
+
+ ),
+ baseLineNodeText: (n) => (
+
+
{n.data.label}
+
+ ),
+ }}
+ fitView
+ >
+
+
+
+
+ >
+ );
+}
diff --git a/site/src/pages/index.tsx b/site/src/pages/index.tsx
index 0fa82d657..21d3bc09e 100644
--- a/site/src/pages/index.tsx
+++ b/site/src/pages/index.tsx
@@ -1,10 +1,10 @@
-import React from "react";
-import clsx from "clsx";
-import Layout from "@theme/Layout";
import Link from "@docusaurus/Link";
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
-import styles from "./index.module.css";
+import Layout from "@theme/Layout";
+import clsx from "clsx";
+import React from "react";
import HomepageFeatures from "../components/HomepageFeatures";
+import styles from "./index.module.css";
function HomepageHeader() {
const { siteConfig } = useDocusaurusContext();
diff --git a/site/docs/amethyst/AmethystCollection.md b/site/tutorial/amethyst/AmethystCollection.md
similarity index 100%
rename from site/docs/amethyst/AmethystCollection.md
rename to site/tutorial/amethyst/AmethystCollection.md
diff --git a/site/docs/amethyst/AmethystEmbed.md b/site/tutorial/amethyst/AmethystEmbed.md
similarity index 100%
rename from site/docs/amethyst/AmethystEmbed.md
rename to site/tutorial/amethyst/AmethystEmbed.md
diff --git a/site/docs/amethyst/_category_.json b/site/tutorial/amethyst/_category_.json
similarity index 100%
rename from site/docs/amethyst/_category_.json
rename to site/tutorial/amethyst/_category_.json
diff --git a/site/docs/amethyst/client.md b/site/tutorial/amethyst/client.md
similarity index 100%
rename from site/docs/amethyst/client.md
rename to site/tutorial/amethyst/client.md
diff --git a/site/docs/amethyst/exampleBot.md b/site/tutorial/amethyst/exampleBot.md
similarity index 100%
rename from site/docs/amethyst/exampleBot.md
rename to site/tutorial/amethyst/exampleBot.md
diff --git a/site/docs/amethyst/intro.md b/site/tutorial/amethyst/intro.md
similarity index 100%
rename from site/docs/amethyst/intro.md
rename to site/tutorial/amethyst/intro.md
diff --git a/site/docs/big-bot-guide/_category_.json b/site/tutorial/big-bot-guide/_category_.json
similarity index 100%
rename from site/docs/big-bot-guide/_category_.json
rename to site/tutorial/big-bot-guide/_category_.json
diff --git a/site/docs/big-bot-guide/cache.md b/site/tutorial/big-bot-guide/cache.md
similarity index 100%
rename from site/docs/big-bot-guide/cache.md
rename to site/tutorial/big-bot-guide/cache.md
diff --git a/site/docs/big-bot-guide/events.md b/site/tutorial/big-bot-guide/events.md
similarity index 100%
rename from site/docs/big-bot-guide/events.md
rename to site/tutorial/big-bot-guide/events.md
diff --git a/site/docs/big-bot-guide/gateway.md b/site/tutorial/big-bot-guide/gateway.md
similarity index 99%
rename from site/docs/big-bot-guide/gateway.md
rename to site/tutorial/big-bot-guide/gateway.md
index b2497f00f..7f79dd954 100644
--- a/site/docs/big-bot-guide/gateway.md
+++ b/site/tutorial/big-bot-guide/gateway.md
@@ -127,14 +127,14 @@ const gateway = createGatewayManager({
});
```
-**Basic Keys**
+#### Basic Keys
- `EVENT_HANDLER_SECRET_KEY` is from your configs that will be used to make sure requests sent to your event handler
process are indeed from you.
- `DISCORD_TOKEN` if you can't figure this out, this guide isn't for you. Please find another.
- `INTENTS` pass in a number or a string of intents. Autocomplete/type-safety is provided for strings :)
-**Powerful Keys**
+#### Powerful Keys
If your bot is going to be run on one process, you can re-use the data that discord gave you to connect.
diff --git a/site/docs/big-bot-guide/rest.md b/site/tutorial/big-bot-guide/rest.md
similarity index 100%
rename from site/docs/big-bot-guide/rest.md
rename to site/tutorial/big-bot-guide/rest.md
diff --git a/site/docs/big-bot-guide/step-by-step.md b/site/tutorial/big-bot-guide/step-by-step.md
similarity index 100%
rename from site/docs/big-bot-guide/step-by-step.md
rename to site/tutorial/big-bot-guide/step-by-step.md
diff --git a/site/docs/nodejs/CommandHandler/_category_.json b/site/tutorial/nodejs/CommandHandler/_category_.json
similarity index 100%
rename from site/docs/nodejs/CommandHandler/_category_.json
rename to site/tutorial/nodejs/CommandHandler/_category_.json
diff --git a/site/docs/nodejs/CommandHandler/command-manager.md b/site/tutorial/nodejs/CommandHandler/command-manager.md
similarity index 100%
rename from site/docs/nodejs/CommandHandler/command-manager.md
rename to site/tutorial/nodejs/CommandHandler/command-manager.md
diff --git a/site/docs/nodejs/CommandHandler/create-command.md b/site/tutorial/nodejs/CommandHandler/create-command.md
similarity index 100%
rename from site/docs/nodejs/CommandHandler/create-command.md
rename to site/tutorial/nodejs/CommandHandler/create-command.md
diff --git a/site/docs/nodejs/CommandHandler/getting-started.md b/site/tutorial/nodejs/CommandHandler/getting-started.md
similarity index 100%
rename from site/docs/nodejs/CommandHandler/getting-started.md
rename to site/tutorial/nodejs/CommandHandler/getting-started.md
diff --git a/site/docs/nodejs/EventHandler/_category_.json b/site/tutorial/nodejs/EventHandler/_category_.json
similarity index 100%
rename from site/docs/nodejs/EventHandler/_category_.json
rename to site/tutorial/nodejs/EventHandler/_category_.json
diff --git a/site/docs/nodejs/EventHandler/event-manager.md b/site/tutorial/nodejs/EventHandler/event-manager.md
similarity index 100%
rename from site/docs/nodejs/EventHandler/event-manager.md
rename to site/tutorial/nodejs/EventHandler/event-manager.md
diff --git a/site/docs/nodejs/EventHandler/getting-started.md b/site/tutorial/nodejs/EventHandler/getting-started.md
similarity index 100%
rename from site/docs/nodejs/EventHandler/getting-started.md
rename to site/tutorial/nodejs/EventHandler/getting-started.md
diff --git a/site/docs/nodejs/EventHandler/handle-event.md b/site/tutorial/nodejs/EventHandler/handle-event.md
similarity index 100%
rename from site/docs/nodejs/EventHandler/handle-event.md
rename to site/tutorial/nodejs/EventHandler/handle-event.md
diff --git a/site/docs/nodejs/Structures/_category_.json b/site/tutorial/nodejs/Structures/_category_.json
similarity index 100%
rename from site/docs/nodejs/Structures/_category_.json
rename to site/tutorial/nodejs/Structures/_category_.json
diff --git a/site/docs/nodejs/Structures/collectors.md b/site/tutorial/nodejs/Structures/collectors.md
similarity index 100%
rename from site/docs/nodejs/Structures/collectors.md
rename to site/tutorial/nodejs/Structures/collectors.md
diff --git a/site/docs/nodejs/Structures/components.md b/site/tutorial/nodejs/Structures/components.md
similarity index 100%
rename from site/docs/nodejs/Structures/components.md
rename to site/tutorial/nodejs/Structures/components.md
diff --git a/site/docs/nodejs/Structures/create-structure.md b/site/tutorial/nodejs/Structures/create-structure.md
similarity index 100%
rename from site/docs/nodejs/Structures/create-structure.md
rename to site/tutorial/nodejs/Structures/create-structure.md
diff --git a/site/docs/nodejs/Structures/embeds.md b/site/tutorial/nodejs/Structures/embeds.md
similarity index 100%
rename from site/docs/nodejs/Structures/embeds.md
rename to site/tutorial/nodejs/Structures/embeds.md
diff --git a/site/docs/nodejs/Structures/getting-started.md b/site/tutorial/nodejs/Structures/getting-started.md
similarity index 100%
rename from site/docs/nodejs/Structures/getting-started.md
rename to site/tutorial/nodejs/Structures/getting-started.md
diff --git a/site/docs/nodejs/_category_.json b/site/tutorial/nodejs/_category_.json
similarity index 100%
rename from site/docs/nodejs/_category_.json
rename to site/tutorial/nodejs/_category_.json
diff --git a/site/docs/nodejs/create-application.md b/site/tutorial/nodejs/create-application.md
similarity index 100%
rename from site/docs/nodejs/create-application.md
rename to site/tutorial/nodejs/create-application.md
diff --git a/site/docs/nodejs/design.md b/site/tutorial/nodejs/design.md
similarity index 100%
rename from site/docs/nodejs/design.md
rename to site/tutorial/nodejs/design.md
diff --git a/site/docs/nodejs/getting-started.md b/site/tutorial/nodejs/getting-started.md
similarity index 100%
rename from site/docs/nodejs/getting-started.md
rename to site/tutorial/nodejs/getting-started.md
diff --git a/site/docs/nodejs/initial-setup.md b/site/tutorial/nodejs/initial-setup.md
similarity index 100%
rename from site/docs/nodejs/initial-setup.md
rename to site/tutorial/nodejs/initial-setup.md
diff --git a/site/docs/nodejs/installion.md b/site/tutorial/nodejs/installion.md
similarity index 100%
rename from site/docs/nodejs/installion.md
rename to site/tutorial/nodejs/installion.md
diff --git a/site/docs/nodejs/slash-command.md b/site/tutorial/nodejs/slash-command.md
similarity index 100%
rename from site/docs/nodejs/slash-command.md
rename to site/tutorial/nodejs/slash-command.md
diff --git a/site/tutorialSidebars.js b/site/tutorialSidebars.js
new file mode 100644
index 000000000..3fa56fd10
--- /dev/null
+++ b/site/tutorialSidebars.js
@@ -0,0 +1,30 @@
+/**
+ * Creating a sidebar enables you to:
+ - create an ordered group of docs
+ - render a sidebar for each doc of that group
+ - provide next/previous navigation
+
+ The sidebars can be generated from the filesystem, or explicitly defined here.
+
+ Create as many sidebars as you want.
+ */
+
+// @ts-check
+
+/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
+const sidebars = {
+ // By default, Docusaurus generates a sidebar from the docs folder structure
+ tutorial: [{ type: "autogenerated", dirName: "." }],
+ // But you can create a sidebar manually
+ /*
+ tutorialSidebar: [
+ {
+ type: 'category',
+ label: 'Tutorial',
+ items: ['hello'],
+ },
+ ],
+ */
+};
+
+module.exports = sidebars;