diff --git a/.prettierignore b/.prettierignore
index 1777a72ad3e113461af85e72645241ebb6593623..dfc1be152c1ddcecc864629062bb4c6ce66dd1e8 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -5,3 +5,5 @@ lib/
 dist/
 .docusaurus/
 .source/
+# prttier doesn't support mdx3 we are using
+*.mdx
diff --git a/apps/next/public/og.png b/apps/next/public/og.png
new file mode 100644
index 0000000000000000000000000000000000000000..9f8e0a18bc0a6fb0cad49634261e32311ae304af
Binary files /dev/null and b/apps/next/public/og.png differ
diff --git a/apps/next/src/app/docs/[[...slug]]/page.tsx b/apps/next/src/app/docs/[[...slug]]/page.tsx
index 79e2d9a770b3fc51ca0825526d62b2ed3b01b5c6..c784a3f2ef1cb36793151bac7c21a0d584e6bf74 100644
--- a/apps/next/src/app/docs/[[...slug]]/page.tsx
+++ b/apps/next/src/app/docs/[[...slug]]/page.tsx
@@ -1,4 +1,6 @@
+import { createMetadata, metadataImage } from "@/lib/metadata";
 import { openapi, source } from "@/lib/source";
+import { Popup, PopupContent, PopupTrigger } from "fumadocs-twoslash/ui";
 import defaultMdxComponents from "fumadocs-ui/mdx";
 import {
   DocsBody,
@@ -26,6 +28,9 @@ export default async function Page(props: {
           components={{
             ...defaultMdxComponents,
             APIPage: openapi.APIPage,
+            Popup,
+            PopupContent,
+            PopupTrigger,
           }}
         />
       </DocsBody>
@@ -44,8 +49,13 @@ export async function generateMetadata(props: {
   const page = source.getPage(params.slug);
   if (!page) notFound();
 
-  return {
-    title: page.data.title,
-    description: page.data.description,
-  };
+  return createMetadata(
+    metadataImage.withImage(page.slugs, {
+      title: page.data.title,
+      description: page.data.description,
+      openGraph: {
+        url: `/docs/${page.slugs.join("/")}`,
+      },
+    }),
+  );
 }
diff --git a/apps/next/src/app/docs/layout.tsx b/apps/next/src/app/docs/layout.tsx
index eb0fae89909ba89c8f7bc08a51350f3739293cb8..7d2f6ae7404cc39db3843527e909c0df50d5f921 100644
--- a/apps/next/src/app/docs/layout.tsx
+++ b/apps/next/src/app/docs/layout.tsx
@@ -3,6 +3,7 @@ import { AITrigger } from "@/components/ai-chat";
 import { buttonVariants } from "@/components/ui/button";
 import { source } from "@/lib/source";
 import { cn } from "@/lib/utils";
+import "fumadocs-twoslash/twoslash.css";
 import { DocsLayout } from "fumadocs-ui/layouts/docs";
 import { MessageCircle } from "lucide-react";
 import type { ReactNode } from "react";
diff --git a/apps/next/src/app/og/[...slug]/Geist-Bold.ttf b/apps/next/src/app/og/[...slug]/Geist-Bold.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..5625c00a7e2bb203a2c8d17326804b00cecd3b0f
Binary files /dev/null and b/apps/next/src/app/og/[...slug]/Geist-Bold.ttf differ
diff --git a/apps/next/src/app/og/[...slug]/Geist-Regular.ttf b/apps/next/src/app/og/[...slug]/Geist-Regular.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..a10d58ae29a8c9ea2320d5ae10b98b3ef96ef21e
Binary files /dev/null and b/apps/next/src/app/og/[...slug]/Geist-Regular.ttf differ
diff --git a/apps/next/src/app/og/[...slug]/og.tsx b/apps/next/src/app/og/[...slug]/og.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..79802631f31d735601e9a284f3dc407ddfc2b646
--- /dev/null
+++ b/apps/next/src/app/og/[...slug]/og.tsx
@@ -0,0 +1,180 @@
+import type { ImageResponseOptions } from "next/dist/compiled/@vercel/og/types";
+import { ImageResponse } from "next/og";
+import type { ReactElement, ReactNode } from "react";
+
+interface GenerateProps {
+  title: ReactNode;
+  description?: ReactNode;
+  icon?: ReactNode;
+  primaryColor?: string;
+  primaryTextColor?: string;
+  site?: ReactNode;
+}
+
+export function generateOGImage(
+  options: GenerateProps & ImageResponseOptions,
+): ImageResponse {
+  const {
+    title,
+    description,
+    icon,
+    site,
+    primaryColor,
+    primaryTextColor,
+    ...rest
+  } = options;
+
+  return new ImageResponse(
+    generate({
+      title,
+      description,
+      icon,
+      site,
+      primaryTextColor,
+      primaryColor,
+    }),
+    {
+      width: 1200,
+      height: 630,
+      ...rest,
+    },
+  );
+}
+
+export function generate({
+  primaryColor = "rgba(255,150,255,0.5)",
+  primaryTextColor = "rgb(255,150,255)",
+  ...props
+}: GenerateProps): ReactElement {
+  return (
+    <div
+      style={{
+        display: "flex",
+        flexDirection: "column",
+        width: "100%",
+        height: "100%",
+        color: "white",
+        backgroundColor: "#0c0c0c",
+        backgroundImage: `linear-gradient(to right top, ${primaryColor}, ${primaryColor})`,
+      }}
+    >
+      <div
+        style={{
+          display: "flex",
+          flexDirection: "column",
+          width: "100%",
+          height: "100%",
+          padding: "4rem",
+        }}
+      >
+        <div
+          style={{
+            display: "flex",
+            flexDirection: "row",
+            alignItems: "center",
+            gap: "16px",
+            marginBottom: "12px",
+            color: primaryTextColor,
+          }}
+        >
+          {props.icon}
+          <p
+            style={{
+              fontSize: "56px",
+              fontWeight: 600,
+            }}
+          >
+            {props.site}
+          </p>
+        </div>
+
+        <p
+          style={{
+            fontWeight: 800,
+            fontSize: "82px",
+          }}
+        >
+          {props.title}
+        </p>
+        <p
+          style={{
+            fontSize: "52px",
+            color: "rgba(240,240,240,0.7)",
+          }}
+        >
+          {props.description}
+        </p>
+      </div>
+    </div>
+  );
+}
+
+interface GridPatternProps {
+  width?: number;
+  height?: number;
+  x?: number;
+  y?: number;
+  squares?: [x: number, y: number][];
+  strokeDasharray?: number;
+  className?: string;
+}
+
+export function GridPattern({
+  width = 100,
+  height = 100,
+  x = -1,
+  y = -1,
+  squares,
+  strokeDasharray,
+  ...props
+}: GridPatternProps): ReactElement {
+  return (
+    <svg
+      fill="rgba(156, 163, 175, 0.2)"
+      stroke="rgba(156, 163, 175, 0.2)"
+      style={{
+        position: "absolute",
+        width: "100%",
+        height: "100%",
+        top: 0,
+        maskImage: "radial-gradient(circle at 0% 100%, white, transparent)",
+      }}
+      viewBox="0 0 600 400"
+      {...props}
+    >
+      <defs>
+        <pattern
+          id="og-pattern"
+          width={width}
+          height={height}
+          patternUnits="userSpaceOnUse"
+        >
+          <path
+            d={`M.5 ${height.toString()}V.5H${width.toString()}`}
+            fill="none"
+            strokeWidth={1}
+            strokeDasharray={strokeDasharray}
+          />
+        </pattern>
+      </defs>
+      <rect
+        width="600"
+        height="600"
+        strokeWidth={0}
+        fill="url(#og-pattern)"
+        x={x}
+        y={y}
+      />
+      {squares?.map(([itemX, itemY]) => (
+        <rect
+          strokeWidth="0"
+          key={`${itemX.toString()}-${itemY.toString()}`}
+          width={width - 1}
+          height={height}
+          x={itemX * width + 1}
+          y={itemY * (height + 1)}
+        />
+      ))}
+    </svg>
+  );
+}
diff --git a/apps/next/src/app/og/[...slug]/route.tsx b/apps/next/src/app/og/[...slug]/route.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..4c8aaad31e69d6c6f7096fce5fc6b9d1c1f3a69b
--- /dev/null
+++ b/apps/next/src/app/og/[...slug]/route.tsx
@@ -0,0 +1,84 @@
+import { generateOGImage } from "@/app/og/[...slug]/og";
+import { metadataImage } from "@/lib/metadata";
+import { type ImageResponse } from "next/og";
+import { readFileSync } from "node:fs";
+
+const font = readFileSync("./src/app/og/[...slug]/Geist-Regular.ttf");
+const fontBold = readFileSync("./src/app/og/[...slug]/Geist-Bold.ttf");
+
+export const GET = metadataImage.createAPI((page): ImageResponse => {
+  return generateOGImage({
+    primaryTextColor: "rgb(240,240,240)",
+    primaryColor: "#3178C6",
+    title: page.data.title,
+    icon: (
+      <svg
+        xmlns="http://www.w3.org/2000/svg"
+        height={120}
+        width={120}
+        viewBox="0 0 1920 1920"
+      >
+        <defs>
+          <linearGradient
+            id="linear-gradient"
+            x1="223.68"
+            y1="733.57"
+            x2="1594.48"
+            y2="1521.74"
+            gradientUnits="userSpaceOnUse"
+          >
+            <stop offset="0" stop-color="#f6ddd7" />
+            <stop offset=".25" stop-color="#fcabe6" />
+            <stop offset=".3" stop-color="#f3ade6" />
+            <stop offset=".38" stop-color="#ddb3e8" />
+            <stop offset=".48" stop-color="#b8bcec" />
+            <stop offset=".59" stop-color="#85caf1" />
+            <stop offset=".7" stop-color="#50d8f6" />
+            <stop offset=".76" stop-color="#50d8f6" />
+            <stop offset=".86" stop-color="#b58fe8" />
+          </linearGradient>
+        </defs>
+        <rect
+          id="SquareBG"
+          x="96"
+          y="96"
+          width="1728"
+          height="1728"
+          rx="360.19"
+          ry="360.19"
+          style={{
+            fill: "#000",
+            strokeWidth: 0,
+          }}
+        />
+        <path
+          d="M1227.57,1375.94c-3.92-4.37-7.85-8.74-11.77-13.1-27.64-30.21-41.35-65.1-30.46-111.35-104.67,33.94-205.19,41.62-308.99,17.88-2.72,31.05-3.81,59.43-8.02,87.34-5.15,34.16-13.02,67.9-19.47,101.86-2.25,11.83-4.72,23.74-5.46,35.71-2.2,35.64-1.41,71.63-6.21,106.88-2.47,18.13-14.33,34.99-21.3,50.93h-77.71l.42-.97c4.15-11.29,8.29-22.58,12.44-33.87,0,0-.21.27-.21.27,4.2-4.21,8.39-8.43,12.59-12.64l-.27.27c2.12-2.13,4.24-4.25,6.36-6.38l11.44-1.32c1.11-18.89.94-11.95,1.11-18.89.83-33.72.34-67.53-1.47-101.21-.67-12.36-6.26-24.46-9.6-36.68-2.32.06-4.64.12-6.96.18-12.39,44.7-24.78,89.41-37.17,134.11,0,0,.55-.24.55-.24-8.87,16.08-21.35,47.27-30.22,63.35-11.03,1-42.13-.92-67.88-.77,2.1-21.24,9.98-32.37,23.37-44.39,28.79-25.84,36.54-63.75,36.43-100.05-.15-50.7-6.92-101.37-10.86-152.06,5.59-10.19,8.83-23.19,17.14-30.11,56.24-46.85,102.12-102.83,144.95-161.48,41.46-56.78,83.19-113.45,122.26-171.88,43.03-64.36,87.61-128.6,97.48-208.71,72.88,7.68,142.46,25.43,207.78,60.42,19.96,10.69,45.01,11.89,67.72,17.44,8.42,6.5,20.9,11.26,24.57,19.8,18.5,43.03,36.6,86.42,51.23,130.87,17.99,54.67,22.8,110.74,13.5,168.57-11.14,69.24-41.63,128.83-80.9,185.36-6.53,9.41-8.65,21.88-12.81,32.94,0,0,.15-.18.15-.18-6.82,4.82-14.03,9.18-20.38,14.54-17.18,14.49-21.33,42.61-48.67,46.55-.37-1.49-.55-2.99-.52-4.53-1.44-2.72-2.87-5.43-4.31-8.15-9.96-18.77-19.93-37.53-29.89-56.3ZM517.28,570.6c-10.46-.44-21.29,7.69-31.95,11.86,0,0-9.76,80.82-9.76,121.49s13.91,75.15,16.27,113.41c1.68,27.25,3.01,56.38,13.57,80.73,12.68,29.21,18.19,57.44,16.61,88.5-4.38,86.3,40.37,144.69,108.96,189.16,30.85-33.52,64.34-65,91.99-100.98,55.34-72.02,102.6-149.18,128.62-237.37,5.42-18.37,8.99-37.27,14.28-59.58,2.88-2.94,8.79-8.99,14.7-15.04l-141.94-.4c-2.09-1.89-3.55-3.22-5.64-5.11l-17.96-175.16c-65.91-4.05-131.8-8.74-197.77-11.52ZM665.84,361.83c-23.76-47.96-58.65-85.02-111.51-106.14-.84,14.47-1.52,26.06-2.26,38.88-17.66-12.73-33.28-23.98-53.45-38.52,2.58,25.98,5.08,44.11,6.04,62.33,1.89,36.02-13.58,54.11-49.86,59.15-7.07.98-14.41,0-21.52.83-21.28,2.46-32.65,14.43-35.51,35.63-3.74,27.68,10.41,45.81,33.06,56.83,23.57,11.47,48.7,19.75,77.45,31.13-4.21,14.19-8.49,28.22-12.51,42.32-3.62,12.69-6.95,25.46-10.41,38.2,10.66-4.17,21.48-12.3,31.95-11.86,65.97,2.78,131.86,7.46,197.77,11.52-3.72-76.27-14.91-151.03-49.22-220.28ZM1363.96,1424.58c1.96,2.05,3.91,4.09,5.87,6.14,2.05,2.06,4.1,4.12,6.15,6.17,2.04,1.96,4.07,3.92,6.11,5.88,7.5,4.99,15,9.99,22.49,14.98,3.64-19.55,25.85-47.67,44.43-61.31,7.67-5.63,11.05-16.91,16.99-25.18,3.32-4.62,7.89-8.34,11.9-12.46-1.62-13.04-4.17-26.03-4.67-39.11-1.43-37.53.92-74.57-10.84-112.04-14.13-45-8.64-92.52-6.02-140.17,43.12-8.67,61.47-36.79,63.89-74.64,2.92-45.72-5.65-89.82-34.29-127.23-20.53-26.81-48.34-41.86-82.84-36.43-22.85,3.59-45.04,11.37-67.53,17.28,8.42,6.5,20.9,11.26,24.57,19.8,18.5,43.03,36.6,86.42,51.23,130.87,17.99,54.67,22.8,110.74,13.5,168.57-11.14,69.24-41.63,128.83-80.9,185.36-6.53,9.41-8.65,21.88-12.81,32.94,10.93,13.53,21.85,27.05,32.78,40.58ZM985.74,765.38c-6.29,81.15-44.94,149.41-87.84,215.37-37.77,58.07-75.75,116.3-118.15,170.97-30.45,39.26-68.33,72.77-102.9,108.84.47,26.74.94,53.49,1.41,80.23,5.59-10.19,8.83-23.19,17.14-30.11,56.24-46.85,102.12-102.83,144.95-161.48,41.46-56.78,83.19-113.45,122.26-171.88,43.03-64.36,87.61-128.6,97.48-208.71-24.78-1.08-49.56-2.15-74.34-3.23ZM664.54,1198.77c31.99-35.25,67.97-67.72,95.05-106.41,41.85-59.77,79.26-122.86,115.33-186.36,20.46-36.01,35.34-75.24,37.26-118.13.34-7.72,8.23-15.09,12.63-22.63-3.62.1-7.23.2-10.85.3-4.64-.95-9.28-1.91-13.91-2.86-6.49.04-12.97.07-19.46.11-5.91,6.05-11.83,12.1-14.7,15.04-5.29,22.3-8.87,41.21-14.28,59.58-26.02,88.19-73.28,165.35-128.62,237.37-27.65,35.98-61.14,67.46-91.99,100.98,11.18,7.67,22.36,15.34,33.54,23.02ZM942.72,765.23c2.4,67.42-27.68,124.69-59.91,180.03-31.13,53.43-66.12,104.74-101.63,155.44-20.89,29.83-45.84,56.84-69.42,84.74-11.1,13.13-23.27,25.36-34.96,37.99.02,12.38.03,24.75.05,37.13,34.57-36.07,72.45-69.58,102.9-108.84,42.4-54.66,80.39-112.89,118.15-170.97,42.9-65.96,81.55-134.22,87.84-215.37-14.34-.05-28.68-.1-43.03-.15ZM1405.73,1462.64c5.46,11.19,15.47,22.34,15.54,33.56.25,39.8-2.64,79.65-5.17,119.42-.22,3.52-6.45,6.66-9.89,9.98-2.3,1.72-4.61,3.44-6.91,5.16-1.99,2.12-3.98,4.24-5.97,6.35-2.17,1.91-4.35,3.81-6.52,5.72,3.41,3.84,6.65,10.81,10.25,11,20.21,1.08,40.5.52,61.67.52,17.8-43.47,23.9-85.93,17.32-130.35-1.3-8.8-3.75-19.81.05-26.59,25.92-46.24,19.03-92.21,1.8-138.62-4.01,4.12-8.58,7.84-11.9,12.46-5.94,8.27-9.32,19.55-16.99,25.18-18.58,13.64-40.79,41.76-44.43,61.31.29,1.65.67,3.28,1.15,4.89ZM924.82,765.23c-4.4,7.53-12.29,14.91-12.63,22.63-1.92,42.89-16.8,82.12-37.26,118.13-36.08,63.51-73.48,126.6-115.33,186.36-27.09,38.69-63.06,71.15-95.05,106.41,4.09,8.22,8.17,16.44,12.26,24.66,11.69-12.64,23.86-24.86,34.96-37.99,23.58-27.89,48.53-54.91,69.42-84.74,35.5-50.7,70.5-102.01,101.63-155.44,32.23-55.34,62.31-112.61,59.91-180.03-5.97,0-11.93,0-17.9,0ZM900.05,762.67c4.64.95,9.28,1.91,13.91,2.86-4.64-.95-9.28-1.91-13.91-2.86ZM733.27,759.83c1.79.85,3.59,1.7,5.38,2.55-1.6-1.25-3.4-2.1-5.38-2.55ZM479.39,702.93c1.24,2.91-1.24,5.83,0,8.74-1.24-2.91,1.24-5.83,0-8.74ZM1215.35,1588.66c-8.44,5.86-16.88,11.72-25.32,17.58-1.64,9.45-3.28,18.9-5,28.8h72.24c0-14.59-.97-27.72.34-40.61.87-8.56,2.71-18.87,8.08-24.82,47.78-52.98,66.64-115.78,65.65-185.78-6.82,4.82-14.03,9.18-20.38,14.54-17.18,14.49-21.33,42.61-48.67,46.55.78,53.28-15.32,101.04-46.93,143.74ZM1257.46,1432.24c1.44,2.72,2.87,5.43,4.31,8.15-1.44-2.72-2.87-5.43-4.31-8.15Z"
+          style={{
+            fill: "url(#linear-gradient)",
+            strokeWidth: 0,
+          }}
+        />
+      </svg>
+    ),
+    description: page.data.description,
+    site: "LlamaIndex.TS",
+    fonts: [
+      {
+        name: "Geist",
+        data: font,
+        weight: 400,
+      },
+      {
+        name: "Geist",
+        data: fontBold,
+        weight: 600,
+      },
+    ],
+  });
+});
+
+export function generateStaticParams(): {
+  slug: string[];
+}[] {
+  return metadataImage.generateParams();
+}
diff --git a/apps/next/src/content/docs/llamaindex/index.mdx b/apps/next/src/content/docs/llamaindex/index.mdx
index 663c8b04cceaa17ee6117a9b195257f0a84c944a..8ff94eb80df8bf6c9e9ca81f30709cb1598f2398 100644
--- a/apps/next/src/content/docs/llamaindex/index.mdx
+++ b/apps/next/src/content/docs/llamaindex/index.mdx
@@ -26,12 +26,12 @@ pnpm add llamaindex
   <Card
     title="I'm new to RAG"
     description="Learn more about RAG (Retrieval-augmented generation) using LlamaIndex.TS."
-    href="/docs/llamaindex/starter/what-is-rag"
+    href="/docs/llamaindex/setup/what-is-rag"
   />
   <Card
     title="I want to try LlamaIndex.TS"
     description="Learn how to use LlamaIndex.TS with different JS runtime and frameworks."
-    href="/docs/llamaindex/starter"
+    href="/docs/llamaindex/setup"
   />
   <Card
     title="I want to improve performance when using LlamaIndex.TS"
diff --git a/apps/next/src/content/docs/llamaindex/meta.json b/apps/next/src/content/docs/llamaindex/meta.json
index ca69981f197bfec9dfd346faad9ef7a576c63e6a..d6eb3a2019ebfa8b78068dacba2c37a96f71f021 100644
--- a/apps/next/src/content/docs/llamaindex/meta.json
+++ b/apps/next/src/content/docs/llamaindex/meta.json
@@ -2,5 +2,5 @@
   "title": "LlamaIndex",
   "description": "The Data framework for LLM",
   "root": true,
-  "pages": ["---Guide---", "index", "starter"]
+  "pages": ["---Guide---", "what-is-llamaindex", "index", "setup", "starter"]
 }
diff --git a/apps/next/src/content/docs/llamaindex/setup/cloudflare.mdx b/apps/next/src/content/docs/llamaindex/setup/cloudflare.mdx
new file mode 100644
index 0000000000000000000000000000000000000000..b377a65f18ca7f23381502710eefb544c43d21e9
--- /dev/null
+++ b/apps/next/src/content/docs/llamaindex/setup/cloudflare.mdx
@@ -0,0 +1,48 @@
+---
+title: With Cloudflare Worker
+description: In this guide, you'll learn how to use LlamaIndex with CloudFlare Worker
+---
+
+import {
+  SiNodedotjs,
+  SiDeno,
+  SiBun,
+  SiCloudflareworkers,
+} from "@icons-pack/react-simple-icons";
+
+Before you start, make sure you have try LlamaIndex.TS in Node.js to make sure you understand the basics.
+
+<Card
+  title="Getting Started with LlamaIndex.TS in Node.js"
+  href="/docs/llamaindex/setup/node"
+/>
+
+Also, you need have the basic understanding of <a href='https://developers.cloudflare.com/workers/'><SiCloudflareworkers className="inline mr-2" color="#F38020" />Cloudflare Worker</a>.
+
+## Adding environment variables
+
+```ts
+export default {
+  async fetch(request: Request, env: Env): Promise<Response> {
+    const { setEnvs } = await import("@llamaindex/env");
+    setEnvs(env);
+    const { OpenAIAgent } = await import("@llamaindex/openai");
+    // Start your code here
+    return new Response("Hello, world!");
+  },
+};
+```
+
+Then, you need create `.dev.vars` and add LLM api keys for the local development, such as `OPENAI_API_KEY` for OpenAI API key.
+
+<Callout type="warn">Do not commit the api key to git repository.</Callout>
+
+## Difference between Node.js and Cloudflare Worker
+
+In Cloudflare Worker and similar serverless JS environment, you need to be aware of the following differences:
+
+- Some Node.js modules are not available in Cloudflare Worker, such as `node:fs`, `node:child_process`, `node:cluster`...
+- You are recommend to design your code using network request, such as use `fetch` API to communicate with database, insteadof a long-running process in Node.js.
+- Some of LlamaIndex.TS modules are not available in Cloudflare Worker, for example `SimpleDirectoryReader` (requires `node:fs`), Some multimodal API that relies on [`onnxruntime-node`](https://www.npmjs.com/package/onnxruntime-node)(we might port to HTTP based module in the future).
+- `@llamaindex/core` is designed to work in all JavaScript environment, including Cloudflare Worker. If you find any issue, please report to us.
+- `@llamaindex/env` is a JS environment binding module, which polyfill some Node.js/Modern Web API (for example, we have a memory based `fs` module, and Crypto API polyfill). It is designed to work in all JavaScript environment, including Cloudflare Worker.
diff --git a/apps/next/src/content/docs/llamaindex/setup/getting-started.mdx b/apps/next/src/content/docs/llamaindex/setup/getting-started.mdx
new file mode 100644
index 0000000000000000000000000000000000000000..180a37c01dbc5aed69b4f8bc153f1282a5958149
--- /dev/null
+++ b/apps/next/src/content/docs/llamaindex/setup/getting-started.mdx
@@ -0,0 +1,42 @@
+---
+title: Getting Started
+description: We support multiple JS runtime and frameworks, bundlers.
+---
+import {
+	SiNodedotjs,
+	SiTypescript,
+	SiNextdotjs,
+	SiCloudflareworkers,
+	SiVite
+} from "@icons-pack/react-simple-icons";
+
+<Cards>
+	<Card title={
+		<>
+			<SiNodedotjs className="inline" color="#5FA04E" /> Node.js
+		</>
+	} href="/docs/llamaindex/setup/node" />
+	<Card title={
+		<>
+			<SiTypescript className="inline" color="#3178C6" /> TypeScript
+		</>
+	} href="/docs/llamaindex/setup/typescript.mdx" />
+	<Card title={
+		<>
+			<SiVite className='inline' color='#646CFF' /> Vite
+		</>
+	} href="/docs/llamaindex/setup/vite" />
+	<Card
+		title={
+			<>
+				<SiNextdotjs className='inline' color='#000000' /> Next.js (React Server Component)
+			</>
+		}
+		href="/docs/llamaindex/setup/next"
+	/>
+	<Card title={
+		<>
+			<SiCloudflareworkers className='inline' color='#F38020' /> Cloudflare Workers
+		</>
+	} href="/docs/llamaindex/setup/cloudflare" />
+</Cards>
diff --git a/apps/next/src/content/docs/llamaindex/setup/meta.json b/apps/next/src/content/docs/llamaindex/setup/meta.json
new file mode 100644
index 0000000000000000000000000000000000000000..7d84e670707adb65842e8cb2de3650ccab7708d6
--- /dev/null
+++ b/apps/next/src/content/docs/llamaindex/setup/meta.json
@@ -0,0 +1,13 @@
+{
+  "title": "Setup",
+  "description": "The setup guide",
+  "defaultOpen": true,
+  "pages": [
+    "getting-started",
+    "next",
+    "node",
+    "typescript",
+    "vite",
+    "cloudflare"
+  ]
+}
diff --git a/apps/next/src/content/docs/llamaindex/starter/next.mdx b/apps/next/src/content/docs/llamaindex/setup/next.mdx
similarity index 72%
rename from apps/next/src/content/docs/llamaindex/starter/next.mdx
rename to apps/next/src/content/docs/llamaindex/setup/next.mdx
index 599989182af401134af77e1625860317e14fdbaa..135e1543e46dd0db492ceae4aad57ec5324bcfbb 100644
--- a/apps/next/src/content/docs/llamaindex/starter/next.mdx
+++ b/apps/next/src/content/docs/llamaindex/setup/next.mdx
@@ -7,7 +7,7 @@ Before you start, make sure you have try LlamaIndex.TS in Node.js to make sure y
 
 <Card
   title="Getting Started with LlamaIndex.TS in Node.js"
-  href="/docs/llamaindex/starter/node"
+  href="/docs/llamaindex/setup/node"
 />
 
 ## Differences between Node.js and Next.js
@@ -32,3 +32,10 @@ export default withLlamaIndex(nextConfig);
 ```
 
 If you see any dependency issues, you are welcome to open an issue on the GitHub.
+
+## Edge Runtime
+
+[Vercel Edge Runtime](https://edge-runtime.vercel.app/) is a subset of Node.js APIs. Similar to [Cloudflare Workers](./cloudflare#difference-between-nodejs-and-cloudflare-worker),
+it is a serverless platform that runs your code on the edge.
+
+Not all features of Node.js are supported in Vercel Edge Runtime, so does LlamaIndex.TS, we are working on more compatibility with all JavaScript runtimes.
diff --git a/apps/next/src/content/docs/llamaindex/starter/node.mdx b/apps/next/src/content/docs/llamaindex/setup/node.mdx
similarity index 76%
rename from apps/next/src/content/docs/llamaindex/starter/node.mdx
rename to apps/next/src/content/docs/llamaindex/setup/node.mdx
index 884a015b88bb1225b8c738f41439b782825e5a6b..dd06e41f954452817d97d6c95dcc6315758eb970 100644
--- a/apps/next/src/content/docs/llamaindex/starter/node.mdx
+++ b/apps/next/src/content/docs/llamaindex/setup/node.mdx
@@ -24,11 +24,7 @@ For more information, see the [How to read environment variables from Node.js](h
 
 ## TypeScript support
 
-LlamaIndex.TS is written in TypeScript and provides type definitions.
-We recommend using [tsx](https://www.npmjs.com/package/tsx) to run TypeScript scripts.
-
-```shell
-npx tsx my-script.ts
-# or
-node --import tsx my-script.ts
-```
+<Card
+	title="Getting Started with LlamaIndex.TS in TypeScript"
+	href="/docs/llamaindex/setup/typescript"
+/>
diff --git a/apps/next/src/content/docs/llamaindex/setup/typescript.mdx b/apps/next/src/content/docs/llamaindex/setup/typescript.mdx
new file mode 100644
index 0000000000000000000000000000000000000000..b275cb70735b87c24cbce23068ac36891e228496
--- /dev/null
+++ b/apps/next/src/content/docs/llamaindex/setup/typescript.mdx
@@ -0,0 +1,103 @@
+---
+title: With TypeScript
+description: In this guide, you'll learn how to use LlamaIndex with TypeScript
+---
+import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
+
+LlamaIndex.TS is written in TypeScript and designed to be used in TypeScript projects.
+
+We do lots of work on strong typing to make sure you have a great typing experience with LlamaIndex.TS.
+
+```ts twoslash
+import { PromptTemplate } from '@llamaindex/core/prompts'
+const promptTemplate = new PromptTemplate({
+  template: `Context information from multiple sources is below.
+---------------------
+{context}
+---------------------
+Given the information from multiple sources and not prior knowledge.
+Answer the query in the style of a Shakespeare play"
+Query: {query}
+Answer:`,
+	templateVars: ["context", "query"],
+});
+// @noErrors
+promptTemplate.format({
+	c
+//^|
+})
+```
+
+```ts twoslash
+import { FunctionTool } from '@llamaindex/core/tools'
+import { z } from 'zod'
+
+// ---cut-before---
+const inputSchema = z.object({
+	time: z.string(),
+	city: z.string(),
+})
+
+type Input = z.infer<typeof inputSchema>
+
+FunctionTool.from<Input>((input) => {
+// @noErrors
+	input.t
+//      ^|
+}, {
+	name: 'getWeather',
+	description: 'Get the weather information',
+	parameters: inputSchema,
+})
+```
+
+## Enable TypeScript
+
+
+```json5
+{
+  compilerOptions: {
+    // ⬇️ add this line to your tsconfig.json
+    moduleResolution: "bundler", // or "node16"
+  },
+}
+```
+
+<Accordions>
+	<Accordion
+		title="Why modify tsconfig.json"
+	>
+
+We are shipping both ESM and CJS module, and compatible with Vercel Edge, Cloudflare Workers, and other serverless platforms.
+
+So we are using [conditional exports](https://nodejs.org/api/packages.html#conditional-exports) to support all environments.
+
+This is a kind of modern way of shipping packages, but might cause TypeScript type check to fail because of legacy module resolution.
+
+Imaging you put output file into `/dist/openai.js` but you are importing `llamaindex/openai` in your code, and set `package.json` like this:
+
+```json5
+{
+	"exports": {
+		"./openai": "./dist/openai.js"
+	}
+}
+```
+
+In old module resolution, TypeScript will not be able to find the module because it is not follow the file structure, even you run `node index.js` successfully. (on Node.js >=16)
+
+See more about [moduleResolution](https://www.typescriptlang.org/docs/handbook/modules/theory.html#module-resolution) or
+[TypeScript 5.0 blog](https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#--moduleresolution-bundler7).
+
+
+	</Accordion>
+</Accordions>
+
+
+## Run TypeScript Script in Node.js
+
+We recommend to use [tsx](https://www.npmjs.com/package/tsx) to run TypeScript script in Node.js.
+
+```shell
+node --import tsx ./my-script.ts
+```
diff --git a/apps/next/src/content/docs/llamaindex/setup/vite.mdx b/apps/next/src/content/docs/llamaindex/setup/vite.mdx
new file mode 100644
index 0000000000000000000000000000000000000000..441727707ed6b3de6dac99ab29feeb30467ed639
--- /dev/null
+++ b/apps/next/src/content/docs/llamaindex/setup/vite.mdx
@@ -0,0 +1,23 @@
+---
+title: With Vite
+description: In this guide, you'll learn how to use LlamaIndex with Vite
+---
+
+Before you start, make sure you have try LlamaIndex.TS in Node.js to make sure you understand the basics.
+
+<Card
+  title="Getting Started with LlamaIndex.TS in Node.js"
+  href="/docs/llamaindex/setup/node"
+/>
+
+Also, make sure you have a basic understanding of [Vite](https://vitejs.dev/).
+
+## Why mention Vite?
+
+Vite.js is widely used in building many web applications, like React.js, even for some native app like [Electron](https://www.electronjs.org/).
+
+However, it's not a ready-to-use solution for a Node.js-like application using Vite, as Vite is designed for web applications(run in browser).
+
+There's some plugin/framework based on Vite, like [Waku.gg](https://github.com/dai-shi/waku), or [Electron Vite](https://electron-vite.org/)
+
+For now, we have no clear solution for bundling LlamaIndex.TS with Vite, if you have any idea/solution, please let us know.
diff --git a/apps/next/src/content/docs/llamaindex/starter/getting-started.mdx b/apps/next/src/content/docs/llamaindex/starter/getting-started.mdx
deleted file mode 100644
index ea4d9756b3f58bf0ad01a61b3cc4a38bd02d0369..0000000000000000000000000000000000000000
--- a/apps/next/src/content/docs/llamaindex/starter/getting-started.mdx
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: Getting Started
-description: We support multiple JS runtime and frameworks, bundlers.
----
-
-<Cards>
-  <Card title="Node.js" href="/docs/llamaindex/starter/node" />
-  <Card title="Vite" href="/docs/llamaindex/starter/vite" />
-  <Card
-    title="Next.js (React Server Component)"
-    href="/docs/llamaindex/starter/next"
-  />
-  <Card title="Cloudflare Worker" href="/docs/llamaindex/starter/cloudflare" />
-</Cards>
diff --git a/apps/next/src/content/docs/llamaindex/starter/meta.json b/apps/next/src/content/docs/llamaindex/starter/meta.json
deleted file mode 100644
index aeaf6d7bb1bb83e8d9bcf6645d8d7dc542fd46ce..0000000000000000000000000000000000000000
--- a/apps/next/src/content/docs/llamaindex/starter/meta.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "title": "Starter",
-  "description": "The starter guide",
-  "defaultOpen": true,
-  "pages": ["getting-started", "next", "node"]
-}
diff --git a/apps/next/src/content/docs/llamaindex/what-is-llamaindex.mdx b/apps/next/src/content/docs/llamaindex/what-is-llamaindex.mdx
new file mode 100644
index 0000000000000000000000000000000000000000..b673ccb392b2a4480bfa6d8bd33d5ca9d8f98618
--- /dev/null
+++ b/apps/next/src/content/docs/llamaindex/what-is-llamaindex.mdx
@@ -0,0 +1,24 @@
+---
+title: What is LlamaIndex.TS
+description: LlamaIndex is the leading data framework for building LLM applications
+---
+
+import {
+  SiNodedotjs,
+  SiDeno,
+  SiBun,
+  SiCloudflareworkers,
+} from "@icons-pack/react-simple-icons";
+
+LlamaIndex is a framework for building context-augmented generative AI applications with LLMs including agents and workflows.
+
+The TypeScript implementation is designed for JavaScript server side applications using <SiNodedotjs className="inline" color="#5FA04E" /> Node.js, <SiDeno className="inline" color="#70FFAF" /> Deno, <SiBun className="inline" /> Bun, <SiCloudflareworkers className="inline" color="#F38020" /> Cloudflare Workers, and more.
+
+LlamaIndex.TS provides tools for beginners, advanced users, and everyone in between.
+
+<iframe
+  className="w-full h-[440px]"
+  aria-label="LlamaIndex.TS Starter"
+  aria-description="This is a starter example for LlamaIndex.TS, it shows the basic usage of the library."
+  src="https://stackblitz.com/github/run-llama/LlamaIndexTS/tree/main/examples?file=starter.ts"
+/>
diff --git a/apps/next/src/lib/metadata.ts b/apps/next/src/lib/metadata.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1e6aed81eeb2e35da8f16f384192db56d12535e6
--- /dev/null
+++ b/apps/next/src/lib/metadata.ts
@@ -0,0 +1,30 @@
+import { createMetadataImage } from 'fumadocs-core/server';
+import { source } from '@/lib/source';
+import { Metadata } from 'next';
+
+export const metadataImage = createMetadataImage({
+	source,
+	imageRoute: 'og',
+});
+
+export function createMetadata(override: Metadata): Metadata {
+	return {
+		...override,
+		openGraph: {
+			title: override.title ?? undefined,
+			description: override.description ?? undefined,
+			url: 'https://ts.llamaindex.ai/',
+			images: '/og.png',
+			siteName: 'LlamaIndex.TS',
+			...override.openGraph,
+		},
+		twitter: {
+			card: 'summary_large_image',
+			creator: '@llama_index',
+			title: override.title ?? undefined,
+			description: override.description ?? undefined,
+			images: '/og.png',
+			...override.twitter,
+		},
+	};
+}
\ No newline at end of file
diff --git a/examples/starter.ts b/examples/starter.ts
new file mode 100644
index 0000000000000000000000000000000000000000..371575a9a336e34b8ead5927c70cc6f5c0e7e521
--- /dev/null
+++ b/examples/starter.ts
@@ -0,0 +1,23 @@
+import { SimpleDirectoryReader, VectorStoreIndex } from "llamaindex";
+import { createInterface } from "node:readline/promises";
+
+async function main() {
+  const reader = new SimpleDirectoryReader();
+
+  const documents = await reader.loadData("./data");
+
+  const index = await VectorStoreIndex.fromDocuments(documents);
+  const queryEngine = index.asQueryEngine();
+
+  const rl = createInterface({ input: process.stdin, output: process.stdout });
+
+  while (true) {
+    const query = await rl.question("Query: ");
+    const response = await queryEngine.query({
+      query,
+    });
+    console.log(response.toString());
+  }
+}
+
+main().catch(console.error);
diff --git a/packages/llamaindex/e2e/examples/cloudflare-worker-agent/src/index.ts b/packages/llamaindex/e2e/examples/cloudflare-worker-agent/src/index.ts
index dd4f4d93928d827b67e28c1e1f57e52b759297dc..d4e02bbc09d5e5c10d5ce527c3d9d92efdf15f18 100644
--- a/packages/llamaindex/e2e/examples/cloudflare-worker-agent/src/index.ts
+++ b/packages/llamaindex/e2e/examples/cloudflare-worker-agent/src/index.ts
@@ -9,6 +9,8 @@ export default {
     env: Env,
     ctx: ExecutionContext,
   ): Promise<Response> {
+    const { setEnvs } = await import("@llamaindex/env");
+    setEnvs(env);
     const { OpenAIAgent, OpenAI } = await import("@llamaindex/openai");
     const text = await request.text();
     const agent = new OpenAIAgent({
@@ -29,6 +31,6 @@ export default {
         },
       }),
     );
-    return new Response(response);
+    return new Response("Hello, world!");
   },
 };