Skip to content

Commit a949975

Browse files
mhessdevclaude
andcommitted
feat(site): add SoftwareApplication schema to /orm, /studio, /mcp pages
Adds Schema.org SoftwareApplication JSON-LD structured data to product pages for rich results eligibility and better AI search extraction. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 1d9c685 commit a949975

4 files changed

Lines changed: 101 additions & 84 deletions

File tree

apps/site/src/app/mcp/page.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { JsonLd } from "@/components/json-ld";
2+
import { createSoftwareApplicationStructuredData } from "@/lib/structured-data";
13
import type { Metadata } from "next";
24

35
import { type McpAgent, McpAgentsSection } from "./_components/mcp-agents-section";
@@ -6,6 +8,13 @@ import { McpCtaSection } from "./_components/mcp-cta-section";
68
import { type McpHeroFeature, McpHeroSection } from "./_components/mcp-hero-section";
79
import { McpVideoSection } from "./_components/mcp-video-section";
810

11+
const mcpStructuredData = createSoftwareApplicationStructuredData({
12+
path: "/mcp",
13+
name: "Prisma MCP Server",
14+
description:
15+
"AI-powered database management via Model Context Protocol. Manage databases with natural language in Claude, Codex, Cursor, Warp, ChatGPT and other AI agents.",
16+
});
17+
918
export const metadata: Metadata = {
1019
title: "Prisma MCP Server — AI-Powered Database Management",
1120
description:
@@ -175,6 +184,7 @@ const capabilities: McpCapability[] = [
175184
export default function McpPage() {
176185
return (
177186
<main className="relative flex-1 w-full -mt-24 flex flex-col overflow-x-hidden bg-[linear-gradient(0deg,var(--color-background-default)_95%,var(--color-background-ppg)_100%)] text-foreground-neutral">
187+
<JsonLd id="mcp-software-application" data={mcpStructuredData} />
178188
<div className="relative z-1 flex flex-col">
179189
<McpHeroSection docsHref={DOCS_MCP} features={heroFeatures} />
180190
<McpVideoSection />

apps/site/src/app/orm/page.tsx

Lines changed: 33 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { JsonLd } from "@/components/json-ld";
2+
import { createSoftwareApplicationStructuredData } from "@/lib/structured-data";
13
import { createPageMetadata } from "@/lib/page-metadata";
24
import { Action, Button, Card, Separator } from "@prisma/eclipse";
35
import { Bento } from "@/components/homepage/bento";
@@ -44,10 +46,7 @@ const CardFooter = () => (
4446
<Separator className="my-6" />
4547
<div className="flex flex-col md:flex-row justify-between w-full gap-8">
4648
{badge_list.map((badge: any) => (
47-
<div
48-
className="flex flex-col md:flex-row gap-2 md:gap-6 md:items-center"
49-
key={badge.title}
50-
>
49+
<div className="flex flex-col md:flex-row gap-2 md:gap-6 md:items-center" key={badge.title}>
5150
<h6 className="font-semibold text-2xs text-foreground-neutral uppercase">
5251
{badge.title}
5352
</h6>
@@ -82,9 +81,9 @@ const twoCol = [
8281
</h2>
8382
</div>
8483
<p className="text-foreground-neutral-weak! text-base">
85-
Database workflows can feel brittle and error-prone. Prisma ORM
86-
increases productivity and confidence when working with databases and
87-
makes workflows like data modeling, migrations and querying easy.
84+
Database workflows can feel brittle and error-prone. Prisma ORM increases productivity and
85+
confidence when working with databases and makes workflows like data modeling, migrations
86+
and querying easy.
8887
</p>
8988
</>
9089
),
@@ -112,8 +111,8 @@ const twoCol = [
112111
Works with your favorite databases and frameworks
113112
</h2>
114113
<p className="text-foreground-neutral-weak! text-base">
115-
Prisma's compatibility with popular tools ensures no stack lock-in,
116-
lower integration costs, and smooth transitions.
114+
Prisma's compatibility with popular tools ensures no stack lock-in, lower integration
115+
costs, and smooth transitions.
117116
</p>
118117
<a href="/stack" className="link-btn orm">
119118
<span>Learn more</span>
@@ -145,15 +144,10 @@ const twoCol_2 = [
145144
</h2>
146145
</div>
147146
<p className="text-foreground-neutral-weak! text-base">
148-
A meaningful comparison of database query latencies across database
149-
providers and ORM libraries in the Node.js & TypeScript ecosystem.
147+
A meaningful comparison of database query latencies across database providers and ORM
148+
libraries in the Node.js & TypeScript ecosystem.
150149
</p>
151-
<Button
152-
variant="orm"
153-
size="xl"
154-
href="https://benchmarks.prisma.io"
155-
className="w-fit"
156-
>
150+
<Button variant="orm" size="xl" href="https://benchmarks.prisma.io" className="w-fit">
157151
<span>Explore Benchmarks</span>
158152
<i className="fa-regular fa-arrow-right ml-2!" />
159153
</Button>
@@ -181,10 +175,9 @@ const twoCol_2 = [
181175
</h2>
182176
</div>
183177
<p className="text-foreground-neutral-weak! text-base">
184-
Prisma Client is a query builder that’s tailored to your schema. We
185-
designed its API to be intuitive, both for SQL veterans and developers
186-
brand new to databases. The auto-completion helps you figure out your
187-
query without the need for documentation.
178+
Prisma Client is a query builder that’s tailored to your schema. We designed its API to be
179+
intuitive, both for SQL veterans and developers brand new to databases. The
180+
auto-completion helps you figure out your query without the need for documentation.
188181
</p>
189182
<a href="/client" className="link-btn orm">
190183
<span>Learn more</span>
@@ -265,6 +258,13 @@ const features = [
265258
},
266259
];
267260

261+
const ormStructuredData = createSoftwareApplicationStructuredData({
262+
path: "/orm",
263+
name: "Prisma ORM",
264+
description:
265+
"Next-generation Node.js and TypeScript ORM for PostgreSQL, MySQL, SQL Server, SQLite, MongoDB, and CockroachDB. Provides type-safety, automated migrations, and an intuitive data model.",
266+
});
267+
268268
export const metadata = createPageMetadata({
269269
title: "Prisma | Next-generation ORM for Node.js & TypeScript",
270270
description:
@@ -276,15 +276,16 @@ export const metadata = createPageMetadata({
276276
export default function ORM() {
277277
return (
278278
<main className="flex-1 w-full z-1 ">
279+
<JsonLd id="orm-software-application" data={ormStructuredData} />
279280
<div className="hero pt-50 -mt-24 flex items-end justify-center px-4 relative">
280281
<div className="absolute inset-0 z-0 bg-[linear-gradient(180deg,var(--color-foreground-orm)_0%,var(--color-background-default)_100%)] opacity-20" />
281282
<div className="content relative z-2 flex flex-col gap-8 py-12">
282283
<h1 className="text-5xl md:text-6xl stretch-display mb-0 text-center mt-0 font-sans-display text-foreground-neutral max-w-224 mx-auto">
283284
Next-generation Node.js and TypeScript ORM
284285
</h1>
285286
<p className="text-center text-foreground-neutral max-w-2xl mx-auto">
286-
Prisma ORM elevates developer experience with intuitive data
287-
modeling, automated migrations, and type-safety.
287+
Prisma ORM elevates developer experience with intuitive data modeling, automated
288+
migrations, and type-safety.
288289
</p>
289290
<div className="flex flex-col md:flex-row gap-4 items-center justify-center">
290291
<Button
@@ -332,30 +333,16 @@ export default function ORM() {
332333
<div className="grid md:grid-cols-2 gap-9">
333334
{twoCol_3.map((stat, index) => (
334335
<div key={stat.title} className="flex flex-col gap-4">
335-
<Action
336-
size="4xl"
337-
color="orm"
338-
className={cn(index === 0 && "p-0", "relative")}
339-
>
336+
<Action size="4xl" color="orm" className={cn(index === 0 && "p-0", "relative")}>
340337
<Image src={stat.icon} alt={stat.title} fill loading="lazy" />
341338
</Action>
342339
<h4 className="text-2xl font-sans-display stretch-display text-foreground-neutral">
343340
{stat.title}
344341
</h4>
345-
<p className="text-foreground-neutral-weak">
346-
{stat.description}
347-
</p>
348-
<Button
349-
variant="default-stronger"
350-
href={stat.btn.url}
351-
size="xl"
352-
className="w-fit"
353-
>
342+
<p className="text-foreground-neutral-weak">{stat.description}</p>
343+
<Button variant="default-stronger" href={stat.btn.url} size="xl" className="w-fit">
354344
<span>
355-
{stat.btn.label}{" "}
356-
{stat.btn.icon && (
357-
<i className={cn("ml-2", stat.btn.icon)} />
358-
)}
345+
{stat.btn.label} {stat.btn.icon && <i className={cn("ml-2", stat.btn.icon)} />}
359346
</span>
360347
</Button>
361348
</div>
@@ -372,8 +359,8 @@ export default function ORM() {
372359
</h3>
373360
<div className="content flex flex-col lg:flex-row gap-3 lg:gap-12 items-center md:items-start lg:items-center">
374361
<p className="max-w-94 w-full text-center md:text-left text-foreground-neutral-weak text-md">
375-
Integrate Prisma into your development ecosystem and focus on your
376-
team’s core competencies
362+
Integrate Prisma into your development ecosystem and focus on your team’s core
363+
competencies
377364
</p>
378365
<Button variant="orm" size="2xl" href="/enterprise">
379366
<span>Explore Enterprise</span>
@@ -418,16 +405,12 @@ export default function ORM() {
418405
Ready to get started?
419406
</h2>
420407
<p className="text-foreground-neutral-weak max-w-121">
421-
Start from scratch, add Prisma ORM to your existing project, or
422-
explore how to build an app using your favorite framework.
408+
Start from scratch, add Prisma ORM to your existing project, or explore how to build
409+
an app using your favorite framework.
423410
</p>
424411
</div>
425412
<div className="flex flex-col md:flex-row gap-6">
426-
<Button
427-
variant="orm"
428-
size="2xl"
429-
href={prismaPostgresQuickstartUrl}
430-
>
413+
<Button variant="orm" size="2xl" href={prismaPostgresQuickstartUrl}>
431414
<span>Try Prisma ORM</span>
432415
<i className="fa-regular fa-arrow-right ml-2" />
433416
</Button>

apps/site/src/app/studio/page.tsx

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { JsonLd } from "@/components/json-ld";
2+
import { createSoftwareApplicationStructuredData } from "@/lib/structured-data";
13
import type { Metadata } from "next";
24
import { Button } from "@prisma/eclipse";
35
import Image from "next/image";
@@ -39,8 +41,7 @@ const featureRows = [
3941
description:
4042
"Access your database anywhere. Work locally for rapid development or use Console for team collaboration. Switch seamlessly between solo and team workflows.",
4143
imageSrc: "/illustrations/studio/laptop.svg",
42-
imageAlt:
43-
"Prisma Studio interface showing local and collaborative workflows",
44+
imageAlt: "Prisma Studio interface showing local and collaborative workflows",
4445
imageWidth: 522,
4546
imageHeight: 295,
4647
},
@@ -50,8 +51,7 @@ const featureRows = [
5051
description:
5152
"Browse your database visually with powerful filters and search. Spot patterns instantly and get insights for debugging or schema changes, no SQL needed.",
5253
imageSrc: "/illustrations/studio/explore.svg",
53-
imageAlt:
54-
"Prisma Studio data exploration interface with highlighted filters",
54+
imageAlt: "Prisma Studio data exploration interface with highlighted filters",
5555
imageWidth: 546,
5656
imageHeight: 275,
5757
},
@@ -87,6 +87,13 @@ const featureRows = [
8787
},
8888
] as const;
8989

90+
const studioStructuredData = createSoftwareApplicationStructuredData({
91+
path: "/studio",
92+
name: "Prisma Studio",
93+
description:
94+
"Visual database browser and editor for Prisma. Explore and manipulate your data with an intuitive interface, locally or in the Prisma Data Platform.",
95+
});
96+
9097
export const metadata: Metadata = {
9198
title: "Prisma Studio — Visual Database Browser & Editor",
9299
description:
@@ -120,6 +127,7 @@ export const metadata: Metadata = {
120127
export default function StudioPage() {
121128
return (
122129
<main className="flex-1 w-full -mt-24 bg-background-default text-foreground-neutral">
130+
<JsonLd id="studio-software-application" data={studioStructuredData} />
123131
{/* Hero Section */}
124132
<section className="relative overflow-hidden bg-[linear-gradient(180deg,var(--color-background-orm)_0%,var(--color-background-default)_72%)] px-4 pt-60 pb-12">
125133
<div className="pointer-events-none absolute inset-x-1/2 top-20 h-[780px] w-[1664px] -translate-x-1/2 rounded-full bg-[repeating-radial-gradient(circle_at_top,rgba(99,102,241,0.28)_0,rgba(99,102,241,0.28)_2px,transparent_2px,transparent_42px)] opacity-45 mask-[linear-gradient(to_bottom,rgba(0,0,0,0.9),transparent_78%)]" />
@@ -140,8 +148,8 @@ export default function StudioPage() {
140148
</div>
141149

142150
<p className="m-0 max-w-[650px] text-lg leading-8 text-foreground-neutral md:text-xl">
143-
The ultimate tool for exploring and editing data in your Prisma
144-
project. Work locally or team up inside the Prisma Console.
151+
The ultimate tool for exploring and editing data in your Prisma project. Work locally
152+
or team up inside the Prisma Console.
145153
</p>
146154

147155
<div className="flex flex-col items-center gap-4 sm:flex-row">
@@ -155,11 +163,7 @@ export default function StudioPage() {
155163
<span>Explore Studio in Prisma Console</span>
156164
<i className="fa-regular fa-arrow-up-right ml-2" />
157165
</Button>
158-
<Button
159-
variant="default-stronger"
160-
size="2xl"
161-
href={STUDIO_DOCS_URL}
162-
>
166+
<Button variant="default-stronger" size="2xl" href={STUDIO_DOCS_URL}>
163167
<span>Try locally</span>
164168
<i className="fa-regular fa-arrow-down ml-2" />
165169
</Button>
@@ -185,10 +189,7 @@ export default function StudioPage() {
185189
>
186190
<div className="flex items-start gap-4">
187191
<div className="flex size-12 items-center justify-center rounded-md bg-background-orm p-3">
188-
<i
189-
className={`${card.icon} text-lg text-foreground-orm`}
190-
aria-hidden="true"
191-
/>
192+
<i className={`${card.icon} text-lg text-foreground-orm`} aria-hidden="true" />
192193
</div>
193194
<div>
194195
<h2 className="m-0 text-xl leading-7 text-foreground-neutral font-sans-display [font-variation-settings:'wght'_800]">
@@ -232,9 +233,8 @@ export default function StudioPage() {
232233
See how Studio works
233234
</h2>
234235
<p className="m-0 mt-4 text-base leading-6 text-foreground-neutral-weak">
235-
Access Prisma Studio on your local machine during development,
236-
or in the Platform Console to collaborate on data with your
237-
team.
236+
Access Prisma Studio on your local machine during development, or in the Platform
237+
Console to collaborate on data with your team.
238238
</p>
239239
</div>
240240

@@ -274,8 +274,7 @@ export default function StudioPage() {
274274
Try it out!
275275
</h2>
276276
<p className="m-0 mt-4 text-base leading-6 text-foreground-neutral-weak">
277-
Take Studio for a spin with a local pre-seeded database and
278-
example project.
277+
Take Studio for a spin with a local pre-seeded database and example project.
279278
</p>
280279
</div>
281280

@@ -332,17 +331,10 @@ function FeatureRow({
332331
<h2 className="m-0 mt-2 text-4xl leading-10 text-foreground-neutral font-sans-display [font-variation-settings:'wght'_900]">
333332
{title}
334333
</h2>
335-
<p className="m-0 mt-4 text-base leading-8 text-foreground-neutral-weak">
336-
{description}
337-
</p>
334+
<p className="m-0 mt-4 text-base leading-8 text-foreground-neutral-weak">{description}</p>
338335
</div>
339336

340-
<StudioFeatureImage
341-
src={imageSrc}
342-
alt={imageAlt}
343-
width={imageWidth}
344-
height={imageHeight}
345-
/>
337+
<StudioFeatureImage src={imageSrc} alt={imageAlt} width={imageWidth} height={imageHeight} />
346338
</div>
347339
);
348340
}

apps/site/src/lib/structured-data.ts

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,7 @@ export function createSiteStructuredData() {
6565
};
6666
}
6767

68-
export function createFaqStructuredData(
69-
pagePath: string,
70-
faqs: FaqEntry[],
71-
name: string,
72-
) {
68+
export function createFaqStructuredData(pagePath: string, faqs: FaqEntry[], name: string) {
7369
return {
7470
"@context": "https://schema.org",
7571
"@type": "FAQPage",
@@ -87,6 +83,42 @@ export function createFaqStructuredData(
8783
};
8884
}
8985

86+
export function createSoftwareApplicationStructuredData({
87+
path,
88+
name,
89+
description,
90+
applicationCategory = "DeveloperApplication",
91+
operatingSystem = "Cross-platform",
92+
}: {
93+
path: string;
94+
name: string;
95+
description: string;
96+
applicationCategory?: string;
97+
operatingSystem?: string;
98+
}) {
99+
const url = absoluteUrl(path);
100+
const baseUrl = getBaseUrl();
101+
102+
return {
103+
"@context": "https://schema.org",
104+
"@type": "SoftwareApplication",
105+
"@id": `${url}#software`,
106+
name,
107+
description,
108+
url,
109+
applicationCategory,
110+
operatingSystem,
111+
offers: {
112+
"@type": "Offer",
113+
price: "0",
114+
priceCurrency: "USD",
115+
},
116+
provider: {
117+
"@id": `${baseUrl}#organization`,
118+
},
119+
};
120+
}
121+
90122
export function createCollectionPageStructuredData({
91123
path,
92124
name,

0 commit comments

Comments
 (0)