diff --git a/apps/site/package.json b/apps/site/package.json index 4c8fba9dde..3cbe7ef240 100644 --- a/apps/site/package.json +++ b/apps/site/package.json @@ -35,6 +35,7 @@ "react-intersection-observer": "^10.0.3", "react-github-btn": "^1.4.0", "react-tweet": "catalog:", + "recharts": "catalog:", "remark-directive": "catalog:", "shiki": "3.22.0", "tailwind-merge": "catalog:", diff --git a/apps/site/public/illustrations/query-insights/features_1.svg b/apps/site/public/illustrations/query-insights/features_1.svg new file mode 100644 index 0000000000..de4f17f3bc --- /dev/null +++ b/apps/site/public/illustrations/query-insights/features_1.svg @@ -0,0 +1,161 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/apps/site/public/illustrations/query-insights/features_1_light.svg b/apps/site/public/illustrations/query-insights/features_1_light.svg new file mode 100644 index 0000000000..29a7f527ca --- /dev/null +++ b/apps/site/public/illustrations/query-insights/features_1_light.svg @@ -0,0 +1,161 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/apps/site/public/illustrations/query-insights/features_1_mobile_light.svg b/apps/site/public/illustrations/query-insights/features_1_mobile_light.svg new file mode 100644 index 0000000000..64f436bab3 --- /dev/null +++ b/apps/site/public/illustrations/query-insights/features_1_mobile_light.svg @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/site/public/illustrations/query-insights/features_2.svg b/apps/site/public/illustrations/query-insights/features_2.svg new file mode 100644 index 0000000000..e8c0c017da --- /dev/null +++ b/apps/site/public/illustrations/query-insights/features_2.svg @@ -0,0 +1,291 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/apps/site/public/illustrations/query-insights/features_2_light.svg b/apps/site/public/illustrations/query-insights/features_2_light.svg new file mode 100644 index 0000000000..ddba3e0dd2 --- /dev/null +++ b/apps/site/public/illustrations/query-insights/features_2_light.svg @@ -0,0 +1,291 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/apps/site/public/illustrations/query-insights/features_2_mobile_light.svg b/apps/site/public/illustrations/query-insights/features_2_mobile_light.svg new file mode 100644 index 0000000000..a2ac569080 --- /dev/null +++ b/apps/site/public/illustrations/query-insights/features_2_mobile_light.svg @@ -0,0 +1,120 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/apps/site/public/illustrations/query-insights/features_3.svg b/apps/site/public/illustrations/query-insights/features_3.svg new file mode 100644 index 0000000000..fdb4d366f8 --- /dev/null +++ b/apps/site/public/illustrations/query-insights/features_3.svg @@ -0,0 +1,320 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/apps/site/public/illustrations/query-insights/features_3_light.svg b/apps/site/public/illustrations/query-insights/features_3_light.svg new file mode 100644 index 0000000000..2a111b63dd --- /dev/null +++ b/apps/site/public/illustrations/query-insights/features_3_light.svg @@ -0,0 +1,320 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/apps/site/public/illustrations/query-insights/features_3_mobile_light.svg b/apps/site/public/illustrations/query-insights/features_3_mobile_light.svg new file mode 100644 index 0000000000..56bc59a8c5 --- /dev/null +++ b/apps/site/public/illustrations/query-insights/features_3_mobile_light.svg @@ -0,0 +1,154 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/apps/site/public/illustrations/query-insights/features_mobile_1.svg b/apps/site/public/illustrations/query-insights/features_mobile_1.svg new file mode 100644 index 0000000000..4d8662298c --- /dev/null +++ b/apps/site/public/illustrations/query-insights/features_mobile_1.svg @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/site/public/illustrations/query-insights/features_mobile_2.svg b/apps/site/public/illustrations/query-insights/features_mobile_2.svg new file mode 100644 index 0000000000..748ec51e58 --- /dev/null +++ b/apps/site/public/illustrations/query-insights/features_mobile_2.svg @@ -0,0 +1,120 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/apps/site/public/illustrations/query-insights/features_mobile_3.svg b/apps/site/public/illustrations/query-insights/features_mobile_3.svg new file mode 100644 index 0000000000..1907a7c1c0 --- /dev/null +++ b/apps/site/public/illustrations/query-insights/features_mobile_3.svg @@ -0,0 +1,154 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/apps/site/src/app/query-insights/page.tsx b/apps/site/src/app/query-insights/page.tsx new file mode 100644 index 0000000000..9d47562df4 --- /dev/null +++ b/apps/site/src/app/query-insights/page.tsx @@ -0,0 +1,259 @@ +import React from "react"; + +import { CardSection } from "@/components/homepage/card-section/card-section"; +import { Metadata } from "next"; +import { Badge, Button, Card } from "@prisma/eclipse"; +import { + QueryInsightsBars, + QueryInsightsLine, + QueryInsightsTable, +} from "../../components/query-insights"; + +export async function generateMetadata(): Promise { + return { + title: "Prisma Query Insights", + description: + "Understand why your database queries are slow, see their real impact in production, and generate a structured AI prompt to improve them.", + openGraph: { + title: "Prisma Query Insights", + description: + "Understand why your database queries are slow, see their real impact in production, and generate a structured AI prompt to improve them.", + url: "https://www.prisma.io/query-insights", + type: "website", + siteName: "Prisma", + images: [ + { + url: "/og-images/og-query-insights.png", + width: 1200, + height: 630, + alt: "Prisma Query Insights", + }, + ], + }, + twitter: { + card: "summary_large_image", + site: "@prisma", + creator: "@prisma", + }, + }; +} + +export default async function Page({ + searchParams, +}: { + searchParams: { [key: string]: string | string[] | undefined }; +}) { + return ( +
+
+
+
+
+
+ Query insights + +
+

+ AI-powered insights +
built into Prisma Postgres +

+
+

+ Understand why your database queries are slow, see their real impact + in production, and generate a structured AI prompt to improve them. +

+
+ + +
+ + Query Insights is included with + Prisma Postgres at no additional cost. + +
+
+
+
+
+ +
+
+ Average Latency +
+
+ + 15 + + + Milliseconds + +
+ +
+
+ +
+
+ Average Latency +
+
+ + 15 + + + Milliseconds + +
+ +
+
+
+
+ +
+
+
+
+
+ +

+ Actionable query visibility +

+

+ Query Insights groups your queries, tracks execution time + and read volume, and shows you which query shapes are + driving performance issues, in one single overview page. +

+
+ ), + }, + { + imageUrl: "/illustrations/query-insights/features_2", + imageAlt: "Query insights features", + mobileImageUrl: + "/illustrations/query-insights/features_2_mobile", + mobileImageAlt: "Query insights features", + logos: null, + useDefaultLogos: false, + visualPosition: "right" as const, + visualType: "image" as const, + content: ( +
+

+ From application query to SQL impact +

+

+ See which code-level query is causing slow responses or + increased load. Prisma ORM queries get exclusive + attribution. All other SQL queries are visible too. +

+
+ ), + }, + { + imageUrl: "/illustrations/query-insights/features_3", + imageAlt: "Query insights features", + mobileImageUrl: + "/illustrations/query-insights/features_3_mobile", + mobileImageAlt: "Query insights features", + logos: null, + useDefaultLogos: false, + visualPosition: "left" as const, + visualType: "image" as const, + content: ( +
+ +

+ Generate an AI prompt to fix it +

+

+ Query Insights generates an optimization prompt for each + query group, covering likely causes like missing indexes + or excessive reads. Works with any AI coding assistant. +

+
+ ), + }, + ]} + /> +
+
+ {/* + + COMMENTED VIDEO SECTION UNTIL WE HAVE A VIDEO + +
+
+

+ See how it works +

+

+ See the full workflow: a slow endpoint, the query + behind it, and the prompt that helps fix it. +

+
+ +
+
+
+ */} +
+
+
+
+

+ Built in and free +

+

+ Already built into Prisma Postgres. No setup, no extra cost. + Open the Queries tab and start analyzing. +

+
+
+ + +
+
+
+
+
+ ); +} diff --git a/apps/site/src/components/query-insights.tsx b/apps/site/src/components/query-insights.tsx new file mode 100644 index 0000000000..859784f90a --- /dev/null +++ b/apps/site/src/components/query-insights.tsx @@ -0,0 +1,239 @@ +"use client"; + +import { + ChartContainer, + ChartTooltip, + ChartTooltipContent, +} from "@prisma/eclipse"; +import { Line, LineChart, XAxis, YAxis, CartesianGrid } from "recharts"; +import { CodeBlock, Pre } from "@prisma/eclipse"; +import { cn } from "@/lib/cn"; +import Image from "next/image"; +import { Bar, BarChart } from "recharts"; + +const Table = ({ children }: { children?: React.ReactNode }) => ( +
{children ?? null}
+); + +const TableHeader = ({ children }: { children?: React.ReactNode }) => ( +
{children ?? null}
+); + +const TableRow = ({ + children, + className, +}: { + children?: React.ReactNode; + className?: string; +}) => ( +
+ {children ?? null} +
+); + +const TableHead = ({ children }: { children?: React.ReactNode }) => ( +
+ {children} +
+); + +const TableCell = ({ children }: { children?: React.ReactNode }) => ( +
{children ?? null}
+); + +const TableBody = ({ children }: { children?: React.ReactNode }) => ( +
{children ?? null}
+); + +export const QueryInsightsTable = () => ( + + + + Latency + + Executions + Reads + Last seen + + + + + 15ms + +
+            SELECT p.id, p.title, p.content, p.published, p.authorId,
+            p.createdAt, u.id as author_id, u.name, u.email FROM Post p INNER
+            JOIN User u ON p.authorId = u.id WHERE p.published = true ORDER BY
+            p.createdAt DESC LIMIT 10;
+          
+
+ 7 + 10 + 12:32:31 +
+ + 22ms + + + {`post.findMany({ where: { published: true }, include: { author: true }, orderBy: { createdAt: 'desc' }, take: 10 })`} + + + 18 + 13 + 12:32:31 + +
+
+); + +export const ContentBox = ({ + children, + reverse, + image, +}: { + children: React.ReactNode; + reverse?: boolean; + image?: { + src: string; + mobile?: string; + alt?: string; + width?: number; + height?: number; + }; +}) => { + return ( +
+
+ {children} +
+ {image && ( + <> + {image.alt + {image.mobile && ( + {image.alt + )} + + )} +
+ ); +}; + +const chartData = [ + { date: "January", connections: 186 }, + { date: "February", connections: 305 }, + { date: "March", connections: 237 }, + { date: "April", connections: 73 }, + { date: "May", connections: 209 }, + { date: "June", connections: 214 }, + { date: "July", connections: 50 }, + { date: "August", connections: 0 }, + { date: "September", connections: 150 }, + { date: "October", connections: 100 }, + { date: "November", connections: 75 }, + { date: "December", connections: 230 }, +]; + +const chartConfig = { + connections: { + label: "Connections", + color: "#8b5cf6", + }, +}; + +export function QueryInsightsLine() { + return ( + + + + + } + wrapperStyle={{ + backgroundColor: "rgba(255, 255, 255, 0.6)", + border: "1px solid rgba(255, 255, 255, 0.1)", + borderRadius: "8px", + padding: "8px 12px", + }} + /> + + + ); +} + +const chartDataBars = [ + { month: "January", queries: 186 }, + { month: "February", queries: 305 }, + { month: "March", queries: 237 }, + { month: "April", queries: 73 }, + { month: "May", queries: 209 }, + { month: "June", queries: 214 }, + { month: "July", queries: 50 }, + { month: "August", queries: 0 }, + { month: "September", queries: 150 }, + { month: "October", queries: 100 }, + { month: "November", queries: 75 }, + { month: "December", queries: 230 }, +]; + +const chartConfigBars = { + queries: { + label: "Queries", + color: "#2563eb", + }, +}; + +export function QueryInsightsBars() { + return ( + + + + + } + cursor={{ fill: "transparent" }} + wrapperStyle={{ + backgroundColor: "rgba(255, 255, 255, 0.6)", + border: "1px solid rgba(255, 255, 255, 0.1)", + borderRadius: "8px", + padding: "8px 12px", + }} + /> + + + ); +} diff --git a/packages/ui/src/components/logo-parade.tsx b/packages/ui/src/components/logo-parade.tsx index ddc07f53f2..e1b2755340 100644 --- a/packages/ui/src/components/logo-parade.tsx +++ b/packages/ui/src/components/logo-parade.tsx @@ -1,5 +1,49 @@ -"use client"; -import { useState } from "react"; +import { cn } from "../lib/cn"; +const LogoParadeItem = ({ + logo, + clickable = true, + className, + homepage, + noFilter, + noLinks, +}: any) => { + const LogoParadeWrapper = ({ href, children }: any) => { + const wrapperClass = cn( + "inline-flex self-center p-0 animate-[fadein_0.5s_cubic-bezier(0.455,0.03,0.515,0.955)_forwards]", + !clickable && "cursor-default pointer-events-none", + ); + + return !Boolean(noLinks) && Boolean(href) && clickable ? ( + + {children} + + ) : ( +
{children}
+ ); + }; + return ( +
+ + {`logo`} + +
+ ); +}; const logoParade = [ { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 62a4c31e3b..7741ffa3c0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -657,6 +657,9 @@ importers: react-tweet: specifier: 'catalog:' version: 3.3.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + recharts: + specifier: 'catalog:' + version: 3.7.0(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react-is@19.2.4)(react@19.2.4)(redux@5.0.1) remark-directive: specifier: 'catalog:' version: 4.0.0