Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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:",
Expand Down
161 changes: 161 additions & 0 deletions apps/site/public/illustrations/query-insights/features_1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
161 changes: 161 additions & 0 deletions apps/site/public/illustrations/query-insights/features_1_light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
291 changes: 291 additions & 0 deletions apps/site/public/illustrations/query-insights/features_2.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
291 changes: 291 additions & 0 deletions apps/site/public/illustrations/query-insights/features_2_light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
320 changes: 320 additions & 0 deletions apps/site/public/illustrations/query-insights/features_3.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
320 changes: 320 additions & 0 deletions apps/site/public/illustrations/query-insights/features_3_light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
127 changes: 127 additions & 0 deletions apps/site/public/illustrations/query-insights/features_mobile_1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
120 changes: 120 additions & 0 deletions apps/site/public/illustrations/query-insights/features_mobile_2.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
154 changes: 154 additions & 0 deletions apps/site/public/illustrations/query-insights/features_mobile_3.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
259 changes: 259 additions & 0 deletions apps/site/src/app/query-insights/page.tsx
Original file line number Diff line number Diff line change
@@ -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<Metadata> {
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 };
}) {
Comment on lines +41 to +45
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n apps/site/src/app/query-insights/page.tsx

Repository: prisma/web

Length of output: 13741


🏁 Script executed:

# Check Next.js version
cat package.json | grep -A 2 -B 2 "next"

Repository: prisma/web

Length of output: 36


🏁 Script executed:

# Check if there's a root layout that might define metadataBase
find apps/site/src -name "layout.tsx" | head -5

Repository: prisma/web

Length of output: 82


🏁 Script executed:

head -50 package.json

Repository: prisma/web

Length of output: 1113


🏁 Script executed:

cat -n apps/site/src/app/layout.tsx | head -80

Repository: prisma/web

Length of output: 2995


🏁 Script executed:

cat apps/site/package.json | grep -A 2 -B 2 "next"

Repository: prisma/web

Length of output: 671


🌐 Web query:

Next.js 15 searchParams page props async App Router

💡 Result:

In Next.js 15 (App Router), the Page component props changed: params and searchParams are now Promises, so you must await them (or unwrap them with use() in a Client Component). [1][2]

Server Component (recommended)

type SearchParams = Promise<Record<string, string | string[] | undefined>>

export default async function Page(props: { searchParams: SearchParams }) {
  const searchParams = await props.searchParams
  const q = searchParams.q
  return <div>{q}</div>
}

[1]

Client Component option

'use client'
import { use } from 'react'

export default function Page(props: { searchParams: Promise<any> }) {
  const searchParams = use(props.searchParams)
  return <div>{searchParams.q}</div>
}

[1]

If you’re seeing errors about accessing searchParams “synchronously”, it’s because Next 15 still allows some sync access for migration, but it can error (e.g. with certain caching/prerender settings). The fix is to refactor to the async form (and/or run the Next codemod). [2]

Sources:
[1] Next.js “Upgrading: Version 15” (Async Request APIs / searchParams and params examples)
[2] Next.js error doc: “Cannot access Request information synchronously…” (explains Promises + migration guidance)


🏁 Script executed:

grep -r "next" pnpm-lock.yaml 2>/dev/null | grep "version:" | head -3

Repository: prisma/web

Length of output: 1850


🏁 Script executed:

cat -n apps/site/package.json | head -30

Repository: prisma/web

Length of output: 1132


Remove unused searchParams prop typed with incorrect synchronous API.

Line 41–45 declares searchParams with synchronous typing, which conflicts with Next.js 16's async request APIs. Since this prop is never used in the component, remove it entirely to avoid type misalignment and future friction.

Suggested fix
-export default async function Page({
-  searchParams,
-}: {
-  searchParams: { [key: string]: string | string[] | undefined };
-}) {
+export default async function Page() {
   return (
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export default async function Page({
searchParams,
}: {
searchParams: { [key: string]: string | string[] | undefined };
}) {
export default async function Page() {
return (
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/query-insights/page.tsx` around lines 41 - 45, The exported
async component Page currently declares an unused parameter searchParams with a
synchronous type that conflicts with Next.js 16 async request APIs; remove the
searchParams parameter and its type annotation from the Page function signature
(i.e., change export default async function Page({ searchParams }: { ... }) to
export default async function Page()) and ensure there are no remaining
references to searchParams inside the Page function or its helpers (update any
imports/usages if present).

return (
<main className="bg-background-default">
<div className="pt-42! -mt-42! relative">
<div className="opacity-20 absolute top-0 left-0 w-full h-full bg-[linear-gradient(180deg,var(--color-foreground-ppg)_0%,var(--color-background-default)_100%)]" />
<div className="section-hero mt-18! max-w-308 px-4 w-full mx-auto! flex flex-col gap-8 relative pt-12">
<div className="title">
<div className="eyebrow text-center uppercase font-mona-sans stretch-display font-extrabold text-foreground-ppg-weak mb-4!">
<span>Query insights</span>
<i className="fa-solid fa-brain-circuit ml-2! inline-block!"></i>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's find and read the file
fd query-insights/page.tsx

Repository: prisma/web

Length of output: 36


🏁 Script executed:

# Read the file to check the content at the specified lines
cat -n apps/site/src/app/query-insights/page.tsx | sed -n '45,85p'

Repository: prisma/web

Length of output: 2497


🏁 Script executed:

# Check lines around 243 and 251
cat -n apps/site/src/app/query-insights/page.tsx | sed -n '235,260p'

Repository: prisma/web

Length of output: 1110


Hide decorative icons from screen readers with aria-hidden="true".

The <i> elements at lines 54, 73, 77, 243, and 251 are purely decorative—each is paired with adjacent text that conveys the actual meaning. Without aria-hidden="true", screen readers will announce these icons unnecessarily, creating noise for assistive technology users. Since the text alone communicates the intent (e.g., "Start with Prisma Postgres", "Read the docs"), the icons should be explicitly hidden.

-<i className="fa-regular fa-book-open ml-3!" />
+<i className="fa-regular fa-book-open ml-3!" aria-hidden="true" focusable="false" />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/site/src/app/query-insights/page.tsx` at line 54, The decorative <i>
icons in the Query Insights page are being announced by screen readers; update
each decorative icon element in apps/site/src/app/query-insights/page.tsx
(specifically the <i> with className "fa-solid fa-brain-circuit ml-2!
inline-block!" and the other <i> occurrences referenced in the review) to
include aria-hidden="true" so they are ignored by assistive tech; locate the <i>
elements used alongside text (e.g., the brain-circuit icon and the icons near
"Start with Prisma Postgres" / "Read the docs") and add the aria-hidden
attribute to each decorative <i> tag.

</div>
<h1 className="font-mona-sans stretch-display text-6xl text-foreground-neutral text-center">
AI-powered insights
<br /> built into Prisma Postgres
</h1>
</div>
<p className="text-foreground-neutral-weak font-mona-sans max-w-200 w-full mx-auto! text-center">
Understand why your database queries are slow, see their real impact
in production, and generate a structured AI prompt to improve them.
</p>
<div className="btn-group inline-flex gap-4 md:w-fit mx-auto! items-center justify-center flex-col sm:flex-row w-full sm:w-fit">
<Button
variant="ppg"
size="4xl"
className="font-mona-sans font-[650] text-base! w-full sm:w-fit"
href="/postgres"
>
<span>Start with Prisma Postgres</span>
<i className="fa-regular fa-database ml-3!" />
</Button>
<Button variant="default-stronger" size="4xl" href="/docs">
<span>Read the docs</span>
<i className="fa-regular fa-book-open ml-3!" />
</Button>
</div>
<i className="text-xs text-foreground-neutral-weaker text-center mx-auto!">
Query Insights is <span className="underline">included</span> with
Prisma Postgres at no additional cost.
</i>
</div>
</div>
<div className="relative my-12!">
<div className="section-latency max-w-253 px-4 w-full mx-auto! relative">
<div className="grid md:grid-cols-2 gap-2">
<Card className="p-0.25! border-none! bg-[linear-gradient(180deg,var(--color-stroke-neutral-weak)_0%,var(--color-stroke-ppg)_100%)]">
<div className="bg-background-default p-4 rounded-square">
<div className="font-mona-sans text-base text-foreground-neutral-weak uppercase stretch-display font-extrabold mb-2">
Average Latency
</div>
<div className="flex gap-1 items-end leading-[40px] mb-4!">
<span className="font-mona-sans text-[30px] text-foreground-neutral stretch-display font-black">
15
</span>
<span className="mb-1! inline-block text-sm text-foreground-neutral-weak">
Milliseconds
</span>
</div>
<QueryInsightsBars />
</div>
</Card>
<Card className="p-0.25! border-none! bg-[linear-gradient(180deg,var(--color-stroke-neutral-weak)_0%,var(--color-stroke-ppg)_100%)]">
<div className="bg-background-default p-4 rounded-square">
<div className="font-mona-sans text-base text-foreground-neutral-weak uppercase stretch-display font-extrabold mb-2">
Average Latency
</div>
<div className="flex gap-1 items-end leading-[40px] mb-4!">
<span className="font-mona-sans text-[30px] text-foreground-neutral stretch-display font-black">
15
</span>
<span className="mb-1! inline-block text-sm text-foreground-neutral-weak">
Milliseconds
</span>
</div>
<QueryInsightsLine />
</div>
</Card>
</div>
<div className="hidden md:block relative">
<QueryInsightsTable />
</div>
</div>
</div>
<div className="relative my-12!">
<div className="section-features max-w-308 px-4 mx-auto! w-full">
<CardSection
cardSection={[
{
imageUrl: "/illustrations/query-insights/features_1",
imageAlt: "Query insights features",
mobileImageUrl:
"/illustrations/query-insights/features_1_mobile",
mobileImageAlt: "Query insights features",
logos: null,
useDefaultLogos: false,
visualPosition: "left" as const,
visualType: "image" as const,
content: (
<div className="text-center md:text-left content">
<h3 className="m-0! font-sans-display stretch-display text-3xl! md:text-[40px]! text-foreground-neutral">
Actionable query visibility
</h3>
<p className="mb-0 mt-4! text-foreground-neutral-weak text-base!">
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.
</p>
</div>
),
},
{
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: (
<div className="text-center md:text-left content">
<h3 className="m-0! font-mona-sans font-sans-display stretch-display text-3xl! md:text-[40px]! text-foreground-neutral">
From application query to SQL impact
</h3>
<p className="mb-0 mt-4! text-foreground-neutral-weak text-base!">
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.
</p>
</div>
),
},
{
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: (
<div className="text-center md:text-left content">
<Badge
label="Coming soon"
color="success"
className="mb-4!"
/>
<h3 className="m-0! font-mona-sans font-sans-display stretch-display text-3xl! md:text-[40px]! text-foreground-neutral">
Generate an AI prompt to fix it
</h3>
<p className="mb-0 mt-4! text-foreground-neutral-weak text-base!">
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.
</p>
</div>
),
},
]}
/>
</div>
</div>
{/*

COMMENTED VIDEO SECTION UNTIL WE HAVE A VIDEO

<div className="relative my-12! z-1">
<div className="max-w-182 px-4 w-full mx-auto!">
<h4 className="text-[30px]! text-foreground-neutral text-center font-mona-sans my-0! stretch-display font-black!">
See how it works
</h4>
<p className="mb-6! mt-4! text-foreground-neutral-weak text-center text-base! max-w-92 md:max-w-full mx-auto!">
<strong>See the full workflow:</strong> a slow endpoint, the query
behind it, and the prompt that helps fix it.
</p>
<div className="player max-w-171 w-full mx-auto! rounded-square overflow-hidden">
<YouTubePlayer video="/" playOnView />
</div>
</div>
</div>
*/}
<div className="bg-[url('/illustrations/homepage/footer_grid.svg')] bg-contain bg-center before:inset-x-30 before:inset-y-0 before:absolute relative before:content-[''] before:pointer-events-none before:-z-1 rounded-full before:bg-teal-400 before:blur-[100px] relative">
<div className="my-12 p-12">
<div className="flex flex-col mx-auto w-fit items-center justify-center gap-8">
<div className="flex flex-col items-center text-center gap-4">
<h2 className="text-3xl text-foreground-neutral font-sans-display stretch-display">
Built in and free
</h2>
<p className="text-foreground-neutral-weak">
Already built into Prisma Postgres. No setup, no extra cost.
Open the Queries tab and start analyzing.
</p>
</div>
<div className="flex flex-col md:flex-row gap-6">
<Button variant="ppg" size="2xl" href="/postgres">
<span>Start with Prisma Postgres</span>
<i className="fa-regular fa-arrow-right ml-2" />
</Button>
<Button
variant="default-stronger"
size="2xl"
href="/docs/postgres/faq#query-insights"
>
<span>Read the docs</span>
<i className="fa-regular fa-book-open ml-2" />
</Button>
</div>
</div>
</div>
</div>
</main>
);
}
Loading
Loading