diff --git a/apps/blog/content/blog/announcing-prisma-orm-7-0-0/index.mdx b/apps/blog/content/blog/announcing-prisma-orm-7-0-0/index.mdx index 46b7c03f30..d639d43d28 100644 --- a/apps/blog/content/blog/announcing-prisma-orm-7-0-0/index.mdx +++ b/apps/blog/content/blog/announcing-prisma-orm-7-0-0/index.mdx @@ -26,7 +26,7 @@ With the ORM roadmap and Prisma Postgres launched, we had a solid foundation for When we [launched 6.0.0](https://www.prisma.io/blog/prisma-6-better-performance-more-flexibility-and-type-safe-sql?utm_content=launch-blog&via=prisma7), we promised better performance, more flexibility, and better type-safety. We knew there was work to be done, and to get there, we needed to make some drastic changes. -We announced we were [migrating the Prisma Client away from Rust](https://www.prisma.io/blog/series/prisma-orm-the-complete-rust-to-typescript-migration-journey?utm_source=blog&utm_content=launch-blog&via=prisma7) and rebuilding it in TypeScript. This might have seemed like a strange move to some, as Rust’s main premise is that it is fast and performant. But that is only half the story in our case. +We announced we were [migrating the Prisma Client away from Rust](https://www.prisma.io/blog/series/rust-to-typescript-migration-journey?utm_source=blog&utm_content=launch-blog&via=prisma7) and rebuilding it in TypeScript. This might have seemed like a strange move to some, as Rust’s main premise is that it is fast and performant. But that is only half the story in our case. A side effect of the client being built in Rust is that we were limiting who can contribute to the ORM. If you didn’t have strong Rust experience, it was far more difficult to make any meaningful contributions. On the technical side, the communication layer between Rust and the JavaScript runtime is much slower than doing things in plain JavaScript, plus it creates additional dependencies on the runtime. Our friends at Deno shared this sentiment: diff --git a/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-auth-mngp1ps7kip4/index.mdx b/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-auth-mngp1ps7kip4/index.mdx index 0af5763c0b..169544d6ee 100644 --- a/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-auth-mngp1ps7kip4/index.mdx +++ b/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-auth-mngp1ps7kip4/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Secure a TypeScript and PostgreSQL backend with Prisma, passwo metaImagePath: "/backend-prisma-typescript-orm-with-postgresql-auth-mngp1ps7kip4/imgs/meta-9eae0d75afddb1fce65c68320479268f4cdcffd3-1692x852.png" heroImagePath: "/backend-prisma-typescript-orm-with-postgresql-auth-mngp1ps7kip4/imgs/hero-9f73d35216a42b2bb796a971053669fbc90e36ee-846x426.svg" heroImageAlt: "Backend with TypeScript, PostgreSQL & Prisma: Authentication & Authz" -series: - title: "Building a modern backend with TypeScript, PostgreSQL and Prisma" +series: backend-prisma-typescript-orm-with-postgresql seriesIndex: 3 --- diff --git a/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-data-modeling-tsjs1ps7kip1/index.mdx b/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-data-modeling-tsjs1ps7kip1/index.mdx index 268cd8bc62..ac1a42c5d0 100644 --- a/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-data-modeling-tsjs1ps7kip1/index.mdx +++ b/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-data-modeling-tsjs1ps7kip1/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how to model data, perform CRUD operations, and query ag metaImagePath: "/backend-prisma-typescript-orm-with-postgresql-data-modeling-tsjs1ps7kip1/imgs/hero-df67ee11927bde800c1ba033b94e182ab3565110-1692x852.png" heroImagePath: "/backend-prisma-typescript-orm-with-postgresql-data-modeling-tsjs1ps7kip1/imgs/hero-df67ee11927bde800c1ba033b94e182ab3565110-1692x852.png" heroImageAlt: "Backend with TypeScript PostgreSQL & Prisma: Data Modeling & CRUD" -series: - title: "Building a modern backend with TypeScript, PostgreSQL and Prisma" +series: backend-prisma-typescript-orm-with-postgresql seriesIndex: 1 --- diff --git a/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-deployment-bbba1ps7kip5/index.mdx b/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-deployment-bbba1ps7kip5/index.mdx index 7535a533ca..b445e4e6c6 100644 --- a/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-deployment-bbba1ps7kip5/index.mdx +++ b/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-deployment-bbba1ps7kip5/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Set up CI/CD for a TypeScript, PostgreSQL, and Prisma backend metaImagePath: "/backend-prisma-typescript-orm-with-postgresql-deployment-bbba1ps7kip5/imgs/hero-d3aa9c3e0b081fe4d675e11574d1bbcf8ea9de46-1692x852.png" heroImagePath: "/backend-prisma-typescript-orm-with-postgresql-deployment-bbba1ps7kip5/imgs/hero-d3aa9c3e0b081fe4d675e11574d1bbcf8ea9de46-1692x852.png" heroImageAlt: "Backend with TypeScript, PostgreSQL & Prisma: CI & Deployment" -series: - title: "Building a modern backend with TypeScript, PostgreSQL and Prisma" +series: backend-prisma-typescript-orm-with-postgresql seriesIndex: 4 --- diff --git a/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-rest-api-validation-dcba1ps7kip3/index.mdx b/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-rest-api-validation-dcba1ps7kip3/index.mdx index c220183e42..9bf9f69f2d 100644 --- a/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-rest-api-validation-dcba1ps7kip3/index.mdx +++ b/apps/blog/content/blog/backend-prisma-typescript-orm-with-postgresql-rest-api-validation-dcba1ps7kip3/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Build a REST API with TypeScript, PostgreSQL, Prisma, and Hapi metaImagePath: "/backend-prisma-typescript-orm-with-postgresql-rest-api-validation-dcba1ps7kip3/imgs/hero-21fe21324bb4e62111c88b37b71091676e29f616-1692x852.png" heroImagePath: "/backend-prisma-typescript-orm-with-postgresql-rest-api-validation-dcba1ps7kip3/imgs/hero-21fe21324bb4e62111c88b37b71091676e29f616-1692x852.png" heroImageAlt: "Backend with TypeScript, PostgreSQL & Prisma: REST, Validation & Tests" -series: - title: "Building a modern backend with TypeScript, PostgreSQL and Prisma" +series: backend-prisma-typescript-orm-with-postgresql seriesIndex: 2 --- diff --git a/apps/blog/content/blog/data-migrations-in-prisma-next/index.mdx b/apps/blog/content/blog/data-migrations-in-prisma-next/index.mdx index 1f24d05430..ded520660c 100644 --- a/apps/blog/content/blog/data-migrations-in-prisma-next/index.mdx +++ b/apps/blog/content/blog/data-migrations-in-prisma-next/index.mdx @@ -13,6 +13,8 @@ metaImagePath: "/data-migrations-in-prisma-next/imgs/meta.png" tags: - "orm" - "education" +series: prisma-next +seriesIndex: 5 --- Sooner or later, you need a migration to change data as well as schema. In Prisma Next, that happens inside your migration in TypeScript, with the same query builder you use in your app. diff --git a/apps/blog/content/blog/e2e-type-safety-graphql-react-1-I2GxIfxkSZ/index.mdx b/apps/blog/content/blog/e2e-type-safety-graphql-react-1-I2GxIfxkSZ/index.mdx index 74dc41fea3..b4e00a981e 100644 --- a/apps/blog/content/blog/e2e-type-safety-graphql-react-1-I2GxIfxkSZ/index.mdx +++ b/apps/blog/content/blog/e2e-type-safety-graphql-react-1-I2GxIfxkSZ/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how to build a fully type-safe application with GraphQL, metaImagePath: "/e2e-type-safety-graphql-react-1-I2GxIfxkSZ/imgs/meta-dc0f147b1428391e4b3d0374523d45639d1318a6-1269x715.png" heroImagePath: "/e2e-type-safety-graphql-react-1-I2GxIfxkSZ/imgs/hero-2f58c7e9701e7f9a0250db211bdf5284da11d2d8-844x474.svg" heroImageAlt: "hero image prisma" -series: - title: "Build a Fully Type-Safe Application with GraphQL, Prisma & React" +series: e2e-type-safety-graphql-react seriesIndex: 1 tags: - "education" diff --git a/apps/blog/content/blog/e2e-type-safety-graphql-react-2-j9mEyHY0Ej/index.mdx b/apps/blog/content/blog/e2e-type-safety-graphql-react-2-j9mEyHY0Ej/index.mdx index 54ba552972..021c529471 100644 --- a/apps/blog/content/blog/e2e-type-safety-graphql-react-2-j9mEyHY0Ej/index.mdx +++ b/apps/blog/content/blog/e2e-type-safety-graphql-react-2-j9mEyHY0Ej/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how to build a fully type-safe application with GraphQL, metaImagePath: "/e2e-type-safety-graphql-react-2-j9mEyHY0Ej/imgs/meta-06962f83ac8be93c511d0ef6cbc29e2cff49e387-1269x715.png" heroImagePath: "/e2e-type-safety-graphql-react-2-j9mEyHY0Ej/imgs/hero-838c88ca3817165045cc051d8845880e5a313baf-844x474.svg" heroImageAlt: "hero image prisma" -series: - title: "Build a Fully Type-Safe Application with GraphQL, Prisma & React" +series: e2e-type-safety-graphql-react seriesIndex: 2 tags: - "education" diff --git a/apps/blog/content/blog/e2e-type-safety-graphql-react-3-fbV2ZVIGWg/index.mdx b/apps/blog/content/blog/e2e-type-safety-graphql-react-3-fbV2ZVIGWg/index.mdx index b85f2d7b9e..6f364d2324 100644 --- a/apps/blog/content/blog/e2e-type-safety-graphql-react-3-fbV2ZVIGWg/index.mdx +++ b/apps/blog/content/blog/e2e-type-safety-graphql-react-3-fbV2ZVIGWg/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how to build a fully type-safe application with GraphQL, metaImagePath: "/e2e-type-safety-graphql-react-3-fbV2ZVIGWg/imgs/meta-c8b654f7165277e7cf2cfde5311381d601463251-1269x715.png" heroImagePath: "/e2e-type-safety-graphql-react-3-fbV2ZVIGWg/imgs/hero-78bb7b87f2bf7e691114b2768df5ddfe12e00934-844x474.svg" heroImageAlt: "hero image prisma" -series: - title: "Build a Fully Type-Safe Application with GraphQL, Prisma & React" +series: e2e-type-safety-graphql-react seriesIndex: 3 tags: - "education" diff --git a/apps/blog/content/blog/e2e-type-safety-graphql-react-4-JaHA8GbkER/index.mdx b/apps/blog/content/blog/e2e-type-safety-graphql-react-4-JaHA8GbkER/index.mdx index 54c87cff14..b8ccea27ec 100644 --- a/apps/blog/content/blog/e2e-type-safety-graphql-react-4-JaHA8GbkER/index.mdx +++ b/apps/blog/content/blog/e2e-type-safety-graphql-react-4-JaHA8GbkER/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how to build a fully type-safe application with GraphQL, metaImagePath: "/e2e-type-safety-graphql-react-4-JaHA8GbkER/imgs/meta-42c1cab53d152b8e3e634d75bc70b9d624431cf7-1269x715.png" heroImagePath: "/e2e-type-safety-graphql-react-4-JaHA8GbkER/imgs/hero-b277fdcfbb2267b2f5a9b5d2bd7f06e053febf0f-844x474.svg" heroImageAlt: "hero image prisma" -series: - title: "Build a Fully Type-Safe Application with GraphQL, Prisma & React" +series: e2e-type-safety-graphql-react seriesIndex: 4 tags: - "education" diff --git a/apps/blog/content/blog/from-rust-to-typescript-a-new-chapter-for-prisma-orm/index.mdx b/apps/blog/content/blog/from-rust-to-typescript-a-new-chapter-for-prisma-orm/index.mdx index 5cdd9578e3..b489c2a096 100644 --- a/apps/blog/content/blog/from-rust-to-typescript-a-new-chapter-for-prisma-orm/index.mdx +++ b/apps/blog/content/blog/from-rust-to-typescript-a-new-chapter-for-prisma-orm/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Why is Prisma ORM switching from Rust to TypeScript? Read the metaImagePath: "/from-rust-to-typescript-a-new-chapter-for-prisma-orm/imgs/meta-ded124ddfa8412b0d678ab94a9804127188fde00-1266x711.png" heroImagePath: "/from-rust-to-typescript-a-new-chapter-for-prisma-orm/imgs/hero-0f2a3395d4395fe407ce7fb6b603bb7c5ff3e460-844x474.svg" heroImageAlt: "Prisma ORM Architecture Shift: Why We Moved from Rust to TypeScript" -series: - title: "Prisma ORM: The Complete Rust-to-TypeScript Migration Journey" +series: rust-to-typescript-migration-journey seriesIndex: 1 --- @@ -24,7 +23,7 @@ Prisma ORM's core engine has undergone a major shift from the **Rust based query - **Performance:** Get **up to 3.4x faster queries** (by removing cross-language serialization) and a **90% smaller bundle size** (from ~14MB to 1.6 MB). - **Better support for different runtimes:** Enables better support for deployement environments and runtimes like Cloudflare Workers, Deno, Bun, Vercel Edge and more. -To implement these benefits now, see the [official usage guide for the new Rust-Free ORM](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/no-rust-engine). You can also follow the entire development and release history in our **[Prisma ORM: The Complete Rust-to-TypeScript Migration Journey](https://www.prisma.io/blog/series/prisma-orm-the-complete-rust-to-typescript-migration-journey)** blog series. +To implement these benefits now, see the [official usage guide for the new Rust-Free ORM](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/no-rust-engine). You can also follow the entire development and release history in our **[Prisma ORM: The Complete Rust-to-TypeScript Migration Journey](https://www.prisma.io/blog/series/rust-to-typescript-migration-journey)** blog series. ## Prisma’s doing what now?! diff --git a/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-2-fwpc6ds155/index.mdx b/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-2-fwpc6ds155/index.mdx index 13618bd665..7ffd894f53 100644 --- a/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-2-fwpc6ds155/index.mdx +++ b/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-2-fwpc6ds155/index.mdx @@ -10,8 +10,7 @@ metaDescription: "Learn how to build a fullstack app using TypeScript, PostgreSQ metaImagePath: "/fullstack-nextjs-graphql-prisma-2-fwpc6ds155/imgs/hero-3c25e8ccea9b86c6d7a625f95cd6b42f76c8c5e7-1269x714.png" heroImagePath: "/fullstack-nextjs-graphql-prisma-2-fwpc6ds155/imgs/hero-3c25e8ccea9b86c6d7a625f95cd6b42f76c8c5e7-1269x714.png" heroImageAlt: "Fullstack App With TypeScript, PostgreSQL, Next.js, Prisma & GraphQL: GraphQL API" -series: - title: "Building a fullstack app using TypeScript, PostgreSQL, Next.js, GraphQL and Prisma" +series: fullstack-nextjs-graphql-prisma seriesIndex: 2 tags: diff --git a/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-3-clxbrcqppv/index.mdx b/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-3-clxbrcqppv/index.mdx index eeb9e078c4..99ed0327e6 100644 --- a/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-3-clxbrcqppv/index.mdx +++ b/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-3-clxbrcqppv/index.mdx @@ -10,8 +10,7 @@ metaDescription: "Learn how to build a fullstack app using TypeScript, PostgreSQ metaImagePath: "/fullstack-nextjs-graphql-prisma-3-clxbrcqppv/imgs/meta-91075c8f117cdbd825ecc504f44bf57d5916e0af-1269x714.png" heroImagePath: "/fullstack-nextjs-graphql-prisma-3-clxbrcqppv/imgs/hero-6e7a91ceafb378a17154ba9cb238ed0953434c64-844x474.svg" heroImageAlt: "Fullstack App With TypeScript, PostgreSQL, Next.js, Prisma & GraphQL: Authentication" -series: - title: "Building a fullstack app using TypeScript, PostgreSQL, Next.js, GraphQL and Prisma" +series: fullstack-nextjs-graphql-prisma seriesIndex: 3 tags: - "education" diff --git a/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-4-1k1kc83x3v/index.mdx b/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-4-1k1kc83x3v/index.mdx index ccbce97803..c8a6e12a66 100644 --- a/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-4-1k1kc83x3v/index.mdx +++ b/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-4-1k1kc83x3v/index.mdx @@ -10,8 +10,7 @@ metaDescription: "Learn how to build a fullstack app using TypeScript, PostgreSQ metaImagePath: "/fullstack-nextjs-graphql-prisma-4-1k1kc83x3v/imgs/meta-020d4caf40065aad2ab5d59cff56d2bec9470bd9-1269x714.png" heroImagePath: "/fullstack-nextjs-graphql-prisma-4-1k1kc83x3v/imgs/hero-0672449d4925722e1d058122cf3ef071ca3235e4-844x474.svg" heroImageAlt: "Fullstack App With TypeScript, PostgreSQL, Next.js, Prisma & GraphQL: Image upload" -series: - title: "Building a fullstack app using TypeScript, PostgreSQL, Next.js, GraphQL and Prisma" +series: fullstack-nextjs-graphql-prisma seriesIndex: 4 tags: - "education" diff --git a/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-5-m2fna60h7c/index.mdx b/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-5-m2fna60h7c/index.mdx index 72e69c14ba..6f0d9ab140 100644 --- a/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-5-m2fna60h7c/index.mdx +++ b/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-5-m2fna60h7c/index.mdx @@ -10,8 +10,7 @@ metaDescription: "Learn how to build a fullstack app using TypeScript, PostgreSQ metaImagePath: "/fullstack-nextjs-graphql-prisma-5-m2fna60h7c/imgs/meta-6b91985fb8bb4d0d06e95090aab1d8b0ede0696b-1269x714.png" heroImagePath: "/fullstack-nextjs-graphql-prisma-5-m2fna60h7c/imgs/hero-487ed996090048a8225eec985d2ea001c5e1486b-844x474.svg" heroImageAlt: "Fullstack App With TypeScript, PostgreSQL, Next.js, Prisma & GraphQL: Deployment" -series: - title: "Building a fullstack app using TypeScript, PostgreSQL, Next.js, GraphQL and Prisma" +series: fullstack-nextjs-graphql-prisma seriesIndex: 5 tags: - "education" diff --git a/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-oklidw1rhw/index.mdx b/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-oklidw1rhw/index.mdx index 63eedb1fc1..955b34b5c8 100644 --- a/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-oklidw1rhw/index.mdx +++ b/apps/blog/content/blog/fullstack-nextjs-graphql-prisma-oklidw1rhw/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Build a fullstack app using TypeScript, PostgreSQL, Next.js, G metaImagePath: "/fullstack-nextjs-graphql-prisma-oklidw1rhw/imgs/meta-1ec6d4e3035143375360a59242258c3c93609907-1269x714.png" heroImagePath: "/fullstack-nextjs-graphql-prisma-oklidw1rhw/imgs/hero-cf0efe94442ee755fc47d4c085a10f2b453c74a6-844x475.svg" heroImageAlt: "Fullstack App With TypeScript, PostgreSQL, Next.js, Prisma & GraphQL: Data Modeling" -series: - title: "Building a fullstack app using TypeScript, PostgreSQL, Next.js, GraphQL and Prisma" +series: fullstack-nextjs-graphql-prisma seriesIndex: 1 tags: - "education" diff --git a/apps/blog/content/blog/fullstack-remix-prisma-mongodb-1-7d0bftxbmb6r/index.mdx b/apps/blog/content/blog/fullstack-remix-prisma-mongodb-1-7d0bftxbmb6r/index.mdx index cee459f00b..7bde7d6f15 100644 --- a/apps/blog/content/blog/fullstack-remix-prisma-mongodb-1-7d0bftxbmb6r/index.mdx +++ b/apps/blog/content/blog/fullstack-remix-prisma-mongodb-1-7d0bftxbmb6r/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how to build and deploy a fullstack application using Re metaImagePath: "/fullstack-remix-prisma-mongodb-1-7d0bftxbmb6r/imgs/meta-f24cae902752ee69692b9010216f2d207af37321-1920x1080.png" heroImagePath: "/fullstack-remix-prisma-mongodb-1-7d0bftxbmb6r/imgs/hero-23f25185781fa115971071b951ef70832386640b-844x474.svg" heroImageAlt: "Build A Fullstack App with Remix, Prisma & MongoDB: Project Setup" -series: - title: "Build A Fullstack App with Remix, Prisma & MongoDB" +series: fullstack-remix-prisma-mongodb seriesIndex: 1 tags: - "education" diff --git a/apps/blog/content/blog/fullstack-remix-prisma-mongodb-2-ZTmOy58p4re8/index.mdx b/apps/blog/content/blog/fullstack-remix-prisma-mongodb-2-ZTmOy58p4re8/index.mdx index dfa1d1ad6b..86973fba36 100644 --- a/apps/blog/content/blog/fullstack-remix-prisma-mongodb-2-ZTmOy58p4re8/index.mdx +++ b/apps/blog/content/blog/fullstack-remix-prisma-mongodb-2-ZTmOy58p4re8/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how to build and deploy a fullstack application using Re metaImagePath: "/fullstack-remix-prisma-mongodb-2-ZTmOy58p4re8/imgs/meta-4b70ee51aee99eaddac2a48baa614189c5fa74c2-1920x1080.png" heroImagePath: "/fullstack-remix-prisma-mongodb-2-ZTmOy58p4re8/imgs/hero-29016ded5a59403f81349c8247116f8f084a0ae2-844x474.svg" heroImageAlt: "Build A Fullstack App with Remix, Prisma & MongoDB: Authentication" -series: - title: "Build A Fullstack App with Remix, Prisma & MongoDB" +series: fullstack-remix-prisma-mongodb seriesIndex: 2 tags: diff --git a/apps/blog/content/blog/fullstack-remix-prisma-mongodb-3-By5pmN5Nzo1v/index.mdx b/apps/blog/content/blog/fullstack-remix-prisma-mongodb-3-By5pmN5Nzo1v/index.mdx index a860656291..b29daf565f 100644 --- a/apps/blog/content/blog/fullstack-remix-prisma-mongodb-3-By5pmN5Nzo1v/index.mdx +++ b/apps/blog/content/blog/fullstack-remix-prisma-mongodb-3-By5pmN5Nzo1v/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how to build and deploy a fullstack application using Re metaImagePath: "/fullstack-remix-prisma-mongodb-3-By5pmN5Nzo1v/imgs/meta-ec93dfa6d5929320447e9fa9610b276088e86dd8-1920x1080.png" heroImagePath: "/fullstack-remix-prisma-mongodb-3-By5pmN5Nzo1v/imgs/hero-45f6a2c1b0de348ea063b18dba5fb66f7dbb7594-844x474.svg" heroImageAlt: "Build A Fullstack App with Remix, Prisma & MongoDB: CRUD, Filtering & Sorting" -series: - title: "Build A Fullstack App with Remix, Prisma & MongoDB" +series: fullstack-remix-prisma-mongodb seriesIndex: 3 tags: - "education" diff --git a/apps/blog/content/blog/fullstack-remix-prisma-mongodb-4-l3mwep4zlim2/index.mdx b/apps/blog/content/blog/fullstack-remix-prisma-mongodb-4-l3mwep4zlim2/index.mdx index 8b448055f4..6422127d10 100644 --- a/apps/blog/content/blog/fullstack-remix-prisma-mongodb-4-l3mwep4zlim2/index.mdx +++ b/apps/blog/content/blog/fullstack-remix-prisma-mongodb-4-l3mwep4zlim2/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how to build and deploy a fullstack application using Re metaImagePath: "/fullstack-remix-prisma-mongodb-4-l3mwep4zlim2/imgs/meta-fa4a72549e81768cec73ac357b0dacc1a4985cb6-1920x1080.png" heroImagePath: "/fullstack-remix-prisma-mongodb-4-l3mwep4zlim2/imgs/hero-a48a8ff2b7f60d0db82366f887ef868ba1ffe6ff-844x474.svg" heroImageAlt: "Build A Fullstack App with Remix, Prisma & MongoDB: Referential Integrity & Image Uploads" -series: - title: "Build A Fullstack App with Remix, Prisma & MongoDB" +series: fullstack-remix-prisma-mongodb seriesIndex: 4 tags: - "education" diff --git a/apps/blog/content/blog/fullstack-remix-prisma-mongodb-5-gOhQsnfUPXSx/index.mdx b/apps/blog/content/blog/fullstack-remix-prisma-mongodb-5-gOhQsnfUPXSx/index.mdx index 779adf24e8..0581515ee4 100644 --- a/apps/blog/content/blog/fullstack-remix-prisma-mongodb-5-gOhQsnfUPXSx/index.mdx +++ b/apps/blog/content/blog/fullstack-remix-prisma-mongodb-5-gOhQsnfUPXSx/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how to build and deploy a fullstack application using Re metaImagePath: "/fullstack-remix-prisma-mongodb-5-gOhQsnfUPXSx/imgs/meta-0c44161122fc6096b266ce2463146d441aef52f4-1920x1080.png" heroImagePath: "/fullstack-remix-prisma-mongodb-5-gOhQsnfUPXSx/imgs/hero-a00a8da49b238e170ebeea1caa4d9a67fec1db3d-844x474.svg" heroImageAlt: "Build A Fullstack App with Remix, Prisma & MongoDB: Deployment" -series: - title: "Build A Fullstack App with Remix, Prisma & MongoDB" +series: fullstack-remix-prisma-mongodb seriesIndex: 5 tags: - "education" diff --git a/apps/blog/content/blog/improving-query-performance-using-indexes-1-zuLNZwBkuL/index.mdx b/apps/blog/content/blog/improving-query-performance-using-indexes-1-zuLNZwBkuL/index.mdx index e9894d6846..4704d8c581 100644 --- a/apps/blog/content/blog/improving-query-performance-using-indexes-1-zuLNZwBkuL/index.mdx +++ b/apps/blog/content/blog/improving-query-performance-using-indexes-1-zuLNZwBkuL/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn the fundamentals of database indexes: what they are, the metaImagePath: "/improving-query-performance-using-indexes-1-zuLNZwBkuL/imgs/meta-c92a4afeb9d9b1df6f8104fced300d5e49233bd0-1269x714.png" heroImagePath: "/improving-query-performance-using-indexes-1-zuLNZwBkuL/imgs/hero-1c62649f62f41f22d8a54c882cd24da906c51479-844x474.svg" heroImageAlt: "Improving Query Performance with Indexes using Prisma: Introduction" -series: - title: "Improving query performance with indexes using Prisma" +series: improving-query-performance-using-indexes seriesIndex: 1 tags: - "education" diff --git a/apps/blog/content/blog/improving-query-performance-using-indexes-2-MyoiJNMFTsfq/index.mdx b/apps/blog/content/blog/improving-query-performance-using-indexes-2-MyoiJNMFTsfq/index.mdx index 11d4f5463a..cfeaa05b68 100644 --- a/apps/blog/content/blog/improving-query-performance-using-indexes-2-MyoiJNMFTsfq/index.mdx +++ b/apps/blog/content/blog/improving-query-performance-using-indexes-2-MyoiJNMFTsfq/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how you can optimize a slow database query in your appli metaImagePath: "/improving-query-performance-using-indexes-2-MyoiJNMFTsfq/imgs/meta-f47ff182b4ce89e7dd52fb5ba19e0850dd24a8fa-1692x952.png" heroImagePath: "/improving-query-performance-using-indexes-2-MyoiJNMFTsfq/imgs/hero-21765b1aeb13badff0117580a169a45609788d7e-844x474.svg" heroImageAlt: "Improving Query Performance with Indexes using Prisma: B-Tree Index" -series: - title: "Improving query performance with indexes using Prisma" +series: improving-query-performance-using-indexes seriesIndex: 2 tags: - "education" diff --git a/apps/blog/content/blog/improving-query-performance-using-indexes-3-kduk351qv1/index.mdx b/apps/blog/content/blog/improving-query-performance-using-indexes-3-kduk351qv1/index.mdx index fa06e1b5ec..f19f79c33e 100644 --- a/apps/blog/content/blog/improving-query-performance-using-indexes-3-kduk351qv1/index.mdx +++ b/apps/blog/content/blog/improving-query-performance-using-indexes-3-kduk351qv1/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how you can optimize a slow database query in your appli metaImagePath: "/improving-query-performance-using-indexes-3-kduk351qv1/imgs/meta-a2babe32fc26290c3dee9a6d0cb09decc68fae6a-1269x714.png" heroImagePath: "/improving-query-performance-using-indexes-3-kduk351qv1/imgs/hero-f7add11b063d3376bf02a64092431ac5397e82ba-844x474.svg" heroImageAlt: "Improving Query Performance with Indexes using Prisma: Hash Indexes" -series: - title: "Improving query performance with indexes using Prisma" +series: improving-query-performance-using-indexes seriesIndex: 3 tags: - "education" diff --git a/apps/blog/content/blog/introducing-graphql-nexus-code-first-graphql-server-development-ll6s1yy5cxl5/index.mdx b/apps/blog/content/blog/introducing-graphql-nexus-code-first-graphql-server-development-ll6s1yy5cxl5/index.mdx index a1a336b5cc..125c54457a 100644 --- a/apps/blog/content/blog/introducing-graphql-nexus-code-first-graphql-server-development-ll6s1yy5cxl5/index.mdx +++ b/apps/blog/content/blog/introducing-graphql-nexus-code-first-graphql-server-development-ll6s1yy5cxl5/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Meet GraphQL Nexus, a code-first library for building GraphQL metaImagePath: "/introducing-graphql-nexus-code-first-graphql-server-development-ll6s1yy5cxl5/imgs/hero-5fcd43415f21b9a4fc240fa2c5869f6b6fe2abe0-1200x630.png" heroImagePath: "/introducing-graphql-nexus-code-first-graphql-server-development-ll6s1yy5cxl5/imgs/hero-5fcd43415f21b9a4fc240fa2c5869f6b6fe2abe0-1200x630.png" heroImageAlt: "Introducing GraphQL Nexus" -series: - title: "What is Nexus and how to use it to build GraphQL servers?" +series: graphql-nexus seriesIndex: 2 --- diff --git a/apps/blog/content/blog/nestjs-prisma-authentication-7D056s1s0k3l/index.mdx b/apps/blog/content/blog/nestjs-prisma-authentication-7D056s1s0k3l/index.mdx index fed0b50665..35f39611ce 100644 --- a/apps/blog/content/blog/nestjs-prisma-authentication-7D056s1s0k3l/index.mdx +++ b/apps/blog/content/blog/nestjs-prisma-authentication-7D056s1s0k3l/index.mdx @@ -9,8 +9,7 @@ metaDescription: "In this tutorial, you will learn how to implement JWT authenti metaImagePath: "/nestjs-prisma-authentication-7D056s1s0k3l/imgs/meta-425dd76be3dd7fa36e7051613296031be0344159-1920x1080.png" heroImagePath: "/nestjs-prisma-authentication-7D056s1s0k3l/imgs/hero-7c1df9404c5bc6f5047c3e3ba1972005f90ea2bb-843x474.svg" heroImageAlt: "Building a REST API with NestJS and Prisma: Authentication" -series: - title: "Building a REST API with NestJS, PostgreSQL, Swagger and Prisma" +series: nestjs-prisma-rest-api seriesIndex: 5 tags: - "education" @@ -132,7 +131,7 @@ median ├── tsconfig.build.json └── tsconfig.json ``` -> **Note**: You might notice that this folder comes with a `test` directory as well. Testing won't be covered in this tutorial. However, if you want to learn about how best practices for testing your applications with Prisma, be sure to check out this tutorial series: [The Ultimate Guide to Testing with Prisma](https://www.prisma.io/blog/series/ultimate-guide-to-testing-eTzz0U4wwV) +> **Note**: You might notice that this folder comes with a `test` directory as well. Testing won't be covered in this tutorial. However, if you want to learn about how best practices for testing your applications with Prisma, be sure to check out this tutorial series: [The Ultimate Guide to Testing with Prisma](https://www.prisma.io/blog/series/testing-with-prisma) The notable files and directories in this repository are: @@ -866,4 +865,3 @@ You can find the finished code for this tutorial in the [`end-authentication`](h - diff --git a/apps/blog/content/blog/nestjs-prisma-error-handling-7D056s1kOop2/index.mdx b/apps/blog/content/blog/nestjs-prisma-error-handling-7D056s1kOop2/index.mdx index 4c26051de6..77e6006b6b 100644 --- a/apps/blog/content/blog/nestjs-prisma-error-handling-7D056s1kOop2/index.mdx +++ b/apps/blog/content/blog/nestjs-prisma-error-handling-7D056s1kOop2/index.mdx @@ -9,8 +9,7 @@ metaDescription: "In this tutorial, you will implement error handling in a NestJ metaImagePath: "/nestjs-prisma-error-handling-7D056s1kOop2/imgs/meta-61137d012c97c0dc9c0a72557fe3a277a11700a4-1272x716.png" heroImagePath: "/nestjs-prisma-error-handling-7D056s1kOop2/imgs/hero-c86e8991069ead629ccc386f69880911bbb014c8-844x474.svg" heroImageAlt: "Building a REST API with NestJS and Prisma: Error Handling" -series: - title: "Building a REST API with NestJS, PostgreSQL, Swagger and Prisma" +series: nestjs-prisma-rest-api seriesIndex: 3 tags: - "education" diff --git a/apps/blog/content/blog/nestjs-prisma-relational-data-7D056s1kOabc/index.mdx b/apps/blog/content/blog/nestjs-prisma-relational-data-7D056s1kOabc/index.mdx index aa5759e23f..7d3c81e7a9 100644 --- a/apps/blog/content/blog/nestjs-prisma-relational-data-7D056s1kOabc/index.mdx +++ b/apps/blog/content/blog/nestjs-prisma-relational-data-7D056s1kOabc/index.mdx @@ -9,8 +9,7 @@ metaDescription: "In this tutorial, you will learn how to handle relational data metaImagePath: "/nestjs-prisma-relational-data-7D056s1kOabc/imgs/hero-2d5ec1b2f38575e64a7ae28b6915e68d77e197f2-1920x1080.png" heroImagePath: "/nestjs-prisma-relational-data-7D056s1kOabc/imgs/hero-2d5ec1b2f38575e64a7ae28b6915e68d77e197f2-1920x1080.png" heroImageAlt: "Building a REST API with NestJS and Prisma: Handling Relational Data" -series: - title: "Building a REST API with NestJS, PostgreSQL, Swagger and Prisma" +series: nestjs-prisma-rest-api seriesIndex: 4 tags: - "education" @@ -130,7 +129,7 @@ median ├── tsconfig.build.json └── tsconfig.json ``` -> **Note**: You might notice that this folder comes with a `test` directory as well. Testing won't be covered in this tutorial. However, if you want to learn about how best practices for testing your applications with Prisma, be sure to check out this tutorial series: [The Ultimate Guide to Testing with Prisma](https://www.prisma.io/blog/series/ultimate-guide-to-testing-eTzz0U4wwV) +> **Note**: You might notice that this folder comes with a `test` directory as well. Testing won't be covered in this tutorial. However, if you want to learn about how best practices for testing your applications with Prisma, be sure to check out this tutorial series: [The Ultimate Guide to Testing with Prisma](https://www.prisma.io/blog/series/testing-with-prisma) The notable files and directories in this repository are: @@ -898,4 +897,3 @@ In this chapter, you learned how to model relational data in a NestJS applicatio You can find the finished code for this tutorial in the [`end-relational-data`](https://github.com/prisma/blog-backend-rest-api-nestjs-prisma/tree/end-relational-data) branch of the [GitHub repository](https://github.com/prisma/blog-backend-rest-api-nestjs-prisma). Please feel free to raise an issue in the repository or submit a PR if you notice a problem. You can also reach out to me directly on [Twitter](https://twitter.com/tasinishmam). - diff --git a/apps/blog/content/blog/nestjs-prisma-rest-api-7D056s1BmOL0/index.mdx b/apps/blog/content/blog/nestjs-prisma-rest-api-7D056s1BmOL0/index.mdx index 45e92382b7..f96cbcd59f 100644 --- a/apps/blog/content/blog/nestjs-prisma-rest-api-7D056s1BmOL0/index.mdx +++ b/apps/blog/content/blog/nestjs-prisma-rest-api-7D056s1BmOL0/index.mdx @@ -8,8 +8,7 @@ metaTitle: "Build a REST API with NestJS, Prisma, PostgreSQL and Swagger" metaDescription: "Learn how to build a backend REST API with NestJS, Prisma, PostgreSQL and Swagger. In this article, you will learn how to set up the project, build the API and document it with Swagger." heroImagePath: "/nestjs-prisma-rest-api-7D056s1BmOL0/imgs/hero-4bb8a42e7fe028072f5e7d90b2eff2435ad6dabb-844x474.svg" heroImageAlt: "Building a REST API with NestJS and Prisma" -series: - title: "Building a REST API with NestJS, PostgreSQL, Swagger and Prisma" +series: nestjs-prisma-rest-api seriesIndex: 1 tags: - "education" diff --git a/apps/blog/content/blog/nestjs-prisma-validation-7D056s1kOla1/index.mdx b/apps/blog/content/blog/nestjs-prisma-validation-7D056s1kOla1/index.mdx index 311af8d088..4ca70084f9 100644 --- a/apps/blog/content/blog/nestjs-prisma-validation-7D056s1kOla1/index.mdx +++ b/apps/blog/content/blog/nestjs-prisma-validation-7D056s1kOla1/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how to build a backend REST API with NestJS, Prisma, Pos metaImagePath: "/nestjs-prisma-validation-7D056s1kOla1/imgs/meta-c114050a8b7a4eacbd9270a105ff912a0e91eec5-1272x716.png" heroImagePath: "/nestjs-prisma-validation-7D056s1kOla1/imgs/hero-adc0af7eb5b3f3e751cd795ba7e184ce98a3ed81-844x474.svg" heroImageAlt: "Building a REST API with NestJS and Prisma: Input Validation & Transformation" -series: - title: "Building a REST API with NestJS, PostgreSQL, Swagger and Prisma" +series: nestjs-prisma-rest-api seriesIndex: 2 tags: - "education" diff --git a/apps/blog/content/blog/prisma-6-9-0-release/index.mdx b/apps/blog/content/blog/prisma-6-9-0-release/index.mdx index 60c90b912f..da604d558d 100644 --- a/apps/blog/content/blog/prisma-6-9-0-release/index.mdx +++ b/apps/blog/content/blog/prisma-6-9-0-release/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Explore Prisma 6.9.0: Connect any tool to Prisma Postgres (Dri metaImagePath: "/prisma-6-9-0-release/imgs/meta-e89ea5cb6384d5ad92e1611a0ad373aa368018b0-1266x711.png" heroImagePath: "/prisma-6-9-0-release/imgs/hero-b471bc0c613d1100e7f62c052743300a08093d24-844x474.svg" heroImageAlt: "Prisma 6.9.0 release graphic showing key updates: connect to Prisma Postgres with any ORM, manage databases in VS Code, preview Prisma ORM without Rust engine, and more." -series: - title: "Prisma ORM: The Complete Rust-to-TypeScript Migration Journey" +series: rust-to-typescript-migration-journey seriesIndex: 4 --- @@ -24,7 +23,7 @@ Prisma ORM's core engine has undergone a major shift from the **Rust based query - **Performance:** Get **up to 3.4x faster queries** (by removing cross-language serialization) and a **90% smaller bundle size** (from ~14MB to 1.6 MB). - **Better support for different runtimes:** Enables better support for deployement environments and runtimes like Cloudflare Workers, Deno, Bun, Vercel Edge and more. -To implement these benefits now, see the [official usage guide for the new Rust-Free ORM](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/no-rust-engine). You can also follow the entire development and release history in our **[Prisma ORM: The Complete Rust-to-TypeScript Migration Journey](https://www.prisma.io/blog/series/prisma-orm-the-complete-rust-to-typescript-migration-journey)** blog series**.** +To implement these benefits now, see the [official usage guide for the new Rust-Free ORM](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/no-rust-engine). You can also follow the entire development and release history in our **[Prisma ORM: The Complete Rust-to-TypeScript Migration Journey](https://www.prisma.io/blog/series/rust-to-typescript-migration-journey)** blog series**.** ## Prisma ORM without Rust engines for PostgreSQL & SQLite (Preview) diff --git a/apps/blog/content/blog/prisma-next-call-for-extension-authors/index.mdx b/apps/blog/content/blog/prisma-next-call-for-extension-authors/index.mdx index 6bb67d6059..3601d83f1e 100644 --- a/apps/blog/content/blog/prisma-next-call-for-extension-authors/index.mdx +++ b/apps/blog/content/blog/prisma-next-call-for-extension-authors/index.mdx @@ -14,6 +14,8 @@ tags: - "orm" - "announcement" - "education" +series: prisma-next +seriesIndex: 6 --- If you've ever wanted to integrate your tool, your database, or your library with Prisma, or you tried in Prisma 6 or 7 and gave up, this post is for you. Read the [Prisma Next Early Access announcement](https://www.prisma.io/blog/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app) for the full launch story. diff --git a/apps/blog/content/blog/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/index.mdx b/apps/blog/content/blog/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/index.mdx index 312b7734ac..80bdfc5672 100644 --- a/apps/blog/content/blog/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/index.mdx +++ b/apps/blog/content/blog/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app/index.mdx @@ -14,6 +14,8 @@ tags: - "orm" - "announcement" - "ai" +series: prisma-next +seriesIndex: 8 --- import { diff --git a/apps/blog/content/blog/prisma-next-roadmap-april-milestone/index.mdx b/apps/blog/content/blog/prisma-next-roadmap-april-milestone/index.mdx index 87364c1f0e..f60518e7ea 100644 --- a/apps/blog/content/blog/prisma-next-roadmap-april-milestone/index.mdx +++ b/apps/blog/content/blog/prisma-next-roadmap-april-milestone/index.mdx @@ -11,6 +11,8 @@ metaImagePath: "/prisma-next-roadmap-april-milestone/imgs/meta.png" tags: - "orm" - "announcement" +series: prisma-next +seriesIndex: 7 --- In March we published the [Prisma Next roadmap](https://pris.ly/AgH6EUa). April was the month we'd open Prisma Next up to external contributors. May was the month we'd put it into users' hands. diff --git a/apps/blog/content/blog/prisma-next-roadmap/index.mdx b/apps/blog/content/blog/prisma-next-roadmap/index.mdx index c9c009babd..078e1d04fe 100644 --- a/apps/blog/content/blog/prisma-next-roadmap/index.mdx +++ b/apps/blog/content/blog/prisma-next-roadmap/index.mdx @@ -11,6 +11,8 @@ metaImagePath: "/prisma-next-roadmap/imgs/meta.png" tags: - "orm" - "announcement" +series: prisma-next +seriesIndex: 2 --- On March 4th we [introduced Prisma Next](https://www.prisma.io/blog/the-next-evolution-of-prisma-orm), the future of Prisma ORM. We made the repo public so you can follow progress. We shared some of what we've built so far and what's in the works, including: diff --git a/apps/blog/content/blog/prisma-orm-without-rust-latest-performance-benchmarks/index.mdx b/apps/blog/content/blog/prisma-orm-without-rust-latest-performance-benchmarks/index.mdx index f7422f8c94..b14f388b5f 100644 --- a/apps/blog/content/blog/prisma-orm-without-rust-latest-performance-benchmarks/index.mdx +++ b/apps/blog/content/blog/prisma-orm-without-rust-latest-performance-benchmarks/index.mdx @@ -8,8 +8,7 @@ metaTitle: "Prisma ORM without Rust: Latest Performance Benchmarks" metaDescription: "See the latest benchmarks for Prisma ORM's Rust-free architecture, including faster queries, smaller bundles, and what the TypeScript/WASM Query Compiler changes." metaImagePath: "/prisma-orm-without-rust-latest-performance-benchmarks/imgs/meta-8d83e1420faca85afbc7a1cf78f660374577d3f3-1266x711.png" heroImagePath: "/prisma-orm-without-rust-latest-performance-benchmarks/imgs/hero-be74183d9d749c0b17c850334f376711d8a44d22-844x474.svg" -series: - title: "Prisma ORM: The Complete Rust-to-TypeScript Migration Journey" +series: rust-to-typescript-migration-journey seriesIndex: 5 tags: - "orm" @@ -27,7 +26,7 @@ Prisma ORM's core engine has undergone a major shift from the **Rust based query - **Performance:** Get **up to 3.4x faster queries** (by removing cross-language serialization) and a **90% smaller bundle size** (from ~14MB to 1.6 MB). - **Better support for different runtimes:** Enables better support for deployement environments and runtimes like Cloudflare Workers, Deno, Bun, Vercel Edge and more. -To implement these benefits now, see the [official usage guide for the new Rust-Free ORM](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/no-rust-engine). You can also follow the entire development and release history in our **[Prisma ORM: The Complete Rust-to-TypeScript Migration Journey](https://www.prisma.io/blog/series/prisma-orm-the-complete-rust-to-typescript-migration-journey)** blog series**.** +To implement these benefits now, see the [official usage guide for the new Rust-Free ORM](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/no-rust-engine). You can also follow the entire development and release history in our **[Prisma ORM: The Complete Rust-to-TypeScript Migration Journey](https://www.prisma.io/blog/series/rust-to-typescript-migration-journey)** blog series**.** ## Prisma ORM without Rust engines is in Preview diff --git a/apps/blog/content/blog/rethinking-database-migrations/index.mdx b/apps/blog/content/blog/rethinking-database-migrations/index.mdx index a3052f7c41..0823e6d6c7 100644 --- a/apps/blog/content/blog/rethinking-database-migrations/index.mdx +++ b/apps/blog/content/blog/rethinking-database-migrations/index.mdx @@ -12,6 +12,8 @@ heroImagePath: "/rethinking-database-migrations/imgs/hero.svg" heroImageAlt: "Rethinking Database Migrations" tags: - "orm" +series: prisma-next +seriesIndex: 3 --- Database migrations are brittle and they break when you're most vulnerable; when you're deploying to production. Prisma Next migrations make them explicit, verifiable and safe to retry. Here's how. diff --git a/apps/blog/content/blog/rust-free-prisma-orm-is-ready-for-production/index.mdx b/apps/blog/content/blog/rust-free-prisma-orm-is-ready-for-production/index.mdx index ef1a705799..5988533df5 100644 --- a/apps/blog/content/blog/rust-free-prisma-orm-is-ready-for-production/index.mdx +++ b/apps/blog/content/blog/rust-free-prisma-orm-is-ready-for-production/index.mdx @@ -9,8 +9,7 @@ metaDescription: "The future of Prisma ORM is here: The Rust-free version of Pri metaImagePath: "/rust-free-prisma-orm-is-ready-for-production/imgs/meta-9c1f5eb2a51fc9c54ed069779bcc76e5eb0af5d4-1266x711.png" heroImagePath: "/rust-free-prisma-orm-is-ready-for-production/imgs/hero-a6f1588362b51200aac9693f9c331101d6b397d1-844x474.svg" heroImageAlt: "Visual for 6.16.0" -series: - title: "Prisma ORM: The Complete Rust-to-TypeScript Migration Journey" +series: rust-to-typescript-migration-journey seriesIndex: 6 tags: - "orm" diff --git a/apps/blog/content/blog/rust-to-typescript-update-boosting-prisma-orm-performance/index.mdx b/apps/blog/content/blog/rust-to-typescript-update-boosting-prisma-orm-performance/index.mdx index 136a4fa591..c0e906e86f 100644 --- a/apps/blog/content/blog/rust-to-typescript-update-boosting-prisma-orm-performance/index.mdx +++ b/apps/blog/content/blog/rust-to-typescript-update-boosting-prisma-orm-performance/index.mdx @@ -9,8 +9,7 @@ metaTitle: "Rust to TypeScript Update: Boosting Prisma ORM Performance" metaDescription: "A blog post showing how the new Query Compiler project, where the Prisma query engine is being re-written from Rust to TypeScript, is improving performance." metaImagePath: "/rust-to-typescript-update-boosting-prisma-orm-performance/imgs/meta-a0def58926eae703ce0eccf28d5df589a2c5bc05-1266x711.png" heroImagePath: "/rust-to-typescript-update-boosting-prisma-orm-performance/imgs/hero-508e044038cf37bd9138323288a3d8b5be57ca63-844x474.svg" -series: - title: "Prisma ORM: The Complete Rust-to-TypeScript Migration Journey" +series: rust-to-typescript-migration-journey seriesIndex: 2 --- @@ -24,7 +23,7 @@ Prisma ORM's core engine has undergone a major shift from the **Rust based query - **Performance:** Get **up to 3.4x faster queries** (by removing cross-language serialization) and a **90% smaller bundle size** (from ~14MB to 1.6 MB). - **Better support for different runtimes:** Enables better support for deployement environments and runtimes like Cloudflare Workers, Deno, Bun, Vercel Edge and more. -To implement these benefits now, see the [official usage guide for the new Rust-Free ORM](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/no-rust-engine). You can also follow the entire development and release history in our **[Prisma ORM: The Complete Rust-to-TypeScript Migration Journey](https://www.prisma.io/blog/series/prisma-orm-the-complete-rust-to-typescript-migration-journey)** blog series**.** +To implement these benefits now, see the [official usage guide for the new Rust-Free ORM](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/no-rust-engine). You can also follow the entire development and release history in our **[Prisma ORM: The Complete Rust-to-TypeScript Migration Journey](https://www.prisma.io/blog/series/rust-to-typescript-migration-journey)** blog series**.** ## Breaking performance barriers diff --git a/apps/blog/content/blog/testing-series-1-8eRB5p0Y8o/index.mdx b/apps/blog/content/blog/testing-series-1-8eRB5p0Y8o/index.mdx index 9771172104..146798dca5 100644 --- a/apps/blog/content/blog/testing-series-1-8eRB5p0Y8o/index.mdx +++ b/apps/blog/content/blog/testing-series-1-8eRB5p0Y8o/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn about mocking and spying, why they are useful, and how t metaImagePath: "/testing-series-1-8eRB5p0Y8o/imgs/meta-4fe84c71772f90f758778c5a9f5e6db96af0efd2-1266x712.png" heroImagePath: "/testing-series-1-8eRB5p0Y8o/imgs/hero-c96c41c8c5f42d2c52751fac51563dbc8f01b52c-844x474.svg" heroImageAlt: "The Ultimate Guide to Testing with Prisma: Mocking Prisma Client" -series: - title: "The Ultimate Guide to Testing with Prisma" +series: testing-with-prisma seriesIndex: 1 tags: - "education" diff --git a/apps/blog/content/blog/testing-series-2-xPhjjmIEsM/index.mdx b/apps/blog/content/blog/testing-series-2-xPhjjmIEsM/index.mdx index 3ae8ee1462..e06664185f 100644 --- a/apps/blog/content/blog/testing-series-2-xPhjjmIEsM/index.mdx +++ b/apps/blog/content/blog/testing-series-2-xPhjjmIEsM/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn about what unit testing is and how to approach it in an metaImagePath: "/testing-series-2-xPhjjmIEsM/imgs/meta-5b092626852ebeccdc7962534c6e45d87869900d-1266x712.png" heroImagePath: "/testing-series-2-xPhjjmIEsM/imgs/hero-c9711528e68bdd2e62b432a8fad0f7e6f4859ede-844x474.svg" heroImageAlt: "The Ultimate Guide to Testing with Prisma: Unit Testing" -series: - title: "The Ultimate Guide to Testing with Prisma" +series: testing-with-prisma seriesIndex: 2 tags: - "education" diff --git a/apps/blog/content/blog/testing-series-3-aBUyF8nxAn/index.mdx b/apps/blog/content/blog/testing-series-3-aBUyF8nxAn/index.mdx index 27dff617d6..0af07175ab 100644 --- a/apps/blog/content/blog/testing-series-3-aBUyF8nxAn/index.mdx +++ b/apps/blog/content/blog/testing-series-3-aBUyF8nxAn/index.mdx @@ -8,8 +8,7 @@ metaTitle: "The Ultimate Guide to Testing with Prisma: Integration Testing" metaDescription: "Learn about how to plan, set up and write integration tests for your API." heroImagePath: "/testing-series-3-aBUyF8nxAn/imgs/hero-d60da664991c33bbb498244fe0303813fad6a657-844x474.svg" heroImageAlt: "The Ultimate Guide to Testing with Prisma: Integration Testing" -series: - title: "The Ultimate Guide to Testing with Prisma" +series: testing-with-prisma seriesIndex: 3 tags: - "education" diff --git a/apps/blog/content/blog/testing-series-4-OVXtDis201/index.mdx b/apps/blog/content/blog/testing-series-4-OVXtDis201/index.mdx index 90de188366..4775d67b99 100644 --- a/apps/blog/content/blog/testing-series-4-OVXtDis201/index.mdx +++ b/apps/blog/content/blog/testing-series-4-OVXtDis201/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn all about end-to-end testing, how to set up a testing en metaImagePath: "/testing-series-4-OVXtDis201/imgs/meta-b984941339322c22e27db8dae8010454522fba88-1266x712.png" heroImagePath: "/testing-series-4-OVXtDis201/imgs/hero-205e6248fbc41a4e2b56b77d5a68ccc8e67742db-844x474.svg" heroImageAlt: "The Ultimate Guide to Testing with Prisma: End-To-End Testing" -series: - title: "The Ultimate Guide to Testing with Prisma" +series: testing-with-prisma seriesIndex: 4 tags: - "education" diff --git a/apps/blog/content/blog/testing-series-5-xWogenROXm/index.mdx b/apps/blog/content/blog/testing-series-5-xWogenROXm/index.mdx index 89036b4a12..b8e60ed5d1 100644 --- a/apps/blog/content/blog/testing-series-5-xWogenROXm/index.mdx +++ b/apps/blog/content/blog/testing-series-5-xWogenROXm/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how to set up a CI pipeline to automatically run tests a metaImagePath: "/testing-series-5-xWogenROXm/imgs/meta-1688da94cebe335c8252420b638b7dfa43b135f2-1267x712.png" heroImagePath: "/testing-series-5-xWogenROXm/imgs/hero-1f810a93209524174c2aefb95145a831d4c0fd34-844x474.svg" heroImageAlt: "The Ultimate Guide to Testing with Prisma: CI Pipelines" -series: - title: "The Ultimate Guide to Testing with Prisma" +series: testing-with-prisma seriesIndex: 5 tags: - "education" diff --git a/apps/blog/content/blog/the-next-evolution-of-prisma-orm/index.mdx b/apps/blog/content/blog/the-next-evolution-of-prisma-orm/index.mdx index 32a03e856f..e18302f8da 100644 --- a/apps/blog/content/blog/the-next-evolution-of-prisma-orm/index.mdx +++ b/apps/blog/content/blog/the-next-evolution-of-prisma-orm/index.mdx @@ -12,6 +12,8 @@ heroImagePath: "/the-next-evolution-of-prisma-orm/imgs/hero-61773d2cc286213d32b6 heroImageAlt: "The Next Evolution of Prisma ORM" tags: - "orm" +series: prisma-next +seriesIndex: 1 --- Today, we're excited to share what we've been working on the last few months: Prisma Next, a new foundation for Prisma ORM written fully in TypeScript. diff --git a/apps/blog/content/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3/index.mdx b/apps/blog/content/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3/index.mdx index c15126c5b5..5a5f35d095 100644 --- a/apps/blog/content/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3/index.mdx +++ b/apps/blog/content/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Explore the limitations of schema-first GraphQL server develop metaImagePath: "/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3/imgs/meta-72943771e4be50e26d645130d640c20a4deb48ee-1200x630.png" heroImagePath: "/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3/imgs/hero-91c07e1fd19a7c0ebdd6e970c354bb8d7630a23c-870x457.png" heroImageAlt: "The Problems of \"Schema-First\" GraphQL Server Development" -series: - title: "What is Nexus and how to use it to build GraphQL servers?" +series: graphql-nexus seriesIndex: 1 --- diff --git a/apps/blog/content/blog/try-the-new-rust-free-version-of-prisma-orm-early-access/index.mdx b/apps/blog/content/blog/try-the-new-rust-free-version-of-prisma-orm-early-access/index.mdx index 158c68f77b..102325bd2e 100644 --- a/apps/blog/content/blog/try-the-new-rust-free-version-of-prisma-orm-early-access/index.mdx +++ b/apps/blog/content/blog/try-the-new-rust-free-version-of-prisma-orm-early-access/index.mdx @@ -8,8 +8,7 @@ metaTitle: "Try the New \"Rust-free\" Version of Prisma ORM (Early Access)" metaDescription: "Try the early-access Rust-free version of Prisma ORM and learn how the new TypeScript/WASM architecture improves performance, deployments, and runtime compatibility." metaImagePath: "/try-the-new-rust-free-version-of-prisma-orm-early-access/imgs/meta-ff0b26daee0a92c1135e8397f9af50c91aec798c-1266x711.png" heroImagePath: "/try-the-new-rust-free-version-of-prisma-orm-early-access/imgs/hero-72705c07c42651a759db9aab07ea8a062c671a46-844x474.svg" -series: - title: "Prisma ORM: The Complete Rust-to-TypeScript Migration Journey" +series: rust-to-typescript-migration-journey seriesIndex: 3 tags: - "orm" @@ -26,7 +25,7 @@ Prisma ORM's core engine has undergone a major shift from the **Rust based query - **Performance:** Get **up to 3.4x faster queries** (by removing cross-language serialization) and a **90% smaller bundle size** (from ~14MB to 1.6 MB). - **Better support for different runtimes:** Enables better support for deployement environments and runtimes like Cloudflare Workers, Deno, Bun, Vercel Edge and more. -To implement these benefits now, see the [official usage guide for the new Rust-Free ORM](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/no-rust-engine). You can also follow the entire development and release history in our **[Prisma ORM: The Complete Rust-to-TypeScript Migration Journey](https://www.prisma.io/blog/series/prisma-orm-the-complete-rust-to-typescript-migration-journey)** blog series**.** +To implement these benefits now, see the [official usage guide for the new Rust-Free ORM](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/no-rust-engine). You can also follow the entire development and release history in our **[Prisma ORM: The Complete Rust-to-TypeScript Migration Journey](https://www.prisma.io/blog/series/rust-to-typescript-migration-journey)** blog series**.** ## A brief history of Prisma ORM diff --git a/apps/blog/content/blog/typescript-migrations-in-prisma-next/index.mdx b/apps/blog/content/blog/typescript-migrations-in-prisma-next/index.mdx index 7603a6df07..e7aba5e0a7 100644 --- a/apps/blog/content/blog/typescript-migrations-in-prisma-next/index.mdx +++ b/apps/blog/content/blog/typescript-migrations-in-prisma-next/index.mdx @@ -13,6 +13,8 @@ heroImageAlt: "TypeScript Migrations In Prisma Next" tags: - "orm" - "education" +series: prisma-next +seriesIndex: 4 --- Migrations shouldn't be the scariest part of your deploy. In Prisma Next, migrations are TypeScript files you can read, edit, and re-run with confidence. Every step is verified before it runs and again after. Every failure points directly at the operation that caused it. diff --git a/apps/blog/content/blog/using-graphql-nexus-with-a-database-pmyl3660ncst/index.mdx b/apps/blog/content/blog/using-graphql-nexus-with-a-database-pmyl3660ncst/index.mdx index 257e1efa40..7842a16321 100644 --- a/apps/blog/content/blog/using-graphql-nexus-with-a-database-pmyl3660ncst/index.mdx +++ b/apps/blog/content/blog/using-graphql-nexus-with-a-database-pmyl3660ncst/index.mdx @@ -9,8 +9,7 @@ metaDescription: "Learn how to connect GraphQL Nexus to a database with Prisma C metaImagePath: "/using-graphql-nexus-with-a-database-pmyl3660ncst/imgs/hero-d5d2d2a170d84629937a237d833679a49653a117-1200x630.png" heroImagePath: "/using-graphql-nexus-with-a-database-pmyl3660ncst/imgs/hero-d5d2d2a170d84629937a237d833679a49653a117-1200x630.png" heroImageAlt: "Using GraphQL Nexus with a Database" -series: - title: "What is Nexus and how to use it to build GraphQL servers?" +series: graphql-nexus seriesIndex: 3 --- diff --git a/apps/blog/content/blog/wnip-q2-2022-pmn7rulcj8x/index.mdx b/apps/blog/content/blog/wnip-q2-2022-pmn7rulcj8x/index.mdx index ed556a9196..ade82fb5b6 100644 --- a/apps/blog/content/blog/wnip-q2-2022-pmn7rulcj8x/index.mdx +++ b/apps/blog/content/blog/wnip-q2-2022-pmn7rulcj8x/index.mdx @@ -740,7 +740,7 @@ In this quarter, we published several articles on our blog: - [Building a REST API with NestJS and Prisma](https://www.prisma.io/blog/nestjs-prisma-rest-api-7D056s1BmOL0) - [Prisma Support for CockroachDB Is Production Ready 🪳](https://www.prisma.io/blog/cockroach-ga-5JrD9XVWQDYL) - [How Prisma helps Amplication evolutionize backend development](https://www.prisma.io/blog/amplication-customer-story-nmlkBNlLlxnN) -- [Build A Fullstack App with Remix, Prisma & MongoDB (series)](https://www.prisma.io/blog/series/fullstack-remix-prisma-mongodb-MaTVLuwpaICD) +- [Build A Fullstack App with Remix, Prisma & MongoDB (series)](https://www.prisma.io/blog/series/fullstack-remix-prisma-mongodb) We also published several technical articles on the [Data Guide](https://www.prisma.io/dataguide) that you might find useful: diff --git a/apps/blog/content/blog/wnip-q4-2022-f66prwkjx72s/index.mdx b/apps/blog/content/blog/wnip-q4-2022-f66prwkjx72s/index.mdx index 136e8cc1e1..bc248cc7a3 100644 --- a/apps/blog/content/blog/wnip-q4-2022-f66prwkjx72s/index.mdx +++ b/apps/blog/content/blog/wnip-q4-2022-f66prwkjx72s/index.mdx @@ -503,9 +503,9 @@ We published several articles on our blog this quarter: - [How TypeScript 4.9 `satisfies` Your Prisma Workflows](https://www.prisma.io/blog/satisfies-operator-ur8ys8ccq7zb) - [Database Metrics with Prisma, Prometheus & Grafana](https://www.prisma.io/blog/metrics-tutorial-prisma-pmoldgq10kz) - [Monitor Your Server with Tracing Using OpenTelemetry & Prisma](https://www.prisma.io/blog/tracing-tutorial-prisma-pmkddgq1lm2) -- [Improving query performance with indexes using Prisma](https://www.prisma.io/blog/series/improving-query-performance-using-indexes-2gozGfdxjevI)(series) +- [Improving query performance with indexes using Prisma](https://www.prisma.io/blog/series/improving-query-performance-using-indexes)(series) - [Prisma Support for Tracing and Metrics Is Now in Preview](https://www.prisma.io/blog/tracing-launch-announcement-pmk4rlpc0ll) -- [Build a Fully Type-Safe Application with GraphQL, Prisma & React](https://www.prisma.io/blog/series/e2e-typesafety-graphql-react-yiw81oBkun) (series) +- [Build a Fully Type-Safe Application with GraphQL, Prisma & React](https://www.prisma.io/blog/series/e2e-type-safety-graphql-react) (series) We also published several technical articles on the [Data Guide](https://www.prisma.io/dataguide) that you might find useful: diff --git a/apps/blog/source.config.ts b/apps/blog/source.config.ts index b84944d9d8..b73fa829f8 100644 --- a/apps/blog/source.config.ts +++ b/apps/blog/source.config.ts @@ -1,11 +1,11 @@ import remarkDirective from "remark-directive"; -import { remarkDirectiveAdmonition, remarkMdxFiles, remarkMdxMermaid } from "fumadocs-core/mdx-plugins"; -import { remarkImage } from "fumadocs-core/mdx-plugins"; import { - defineCollections, - defineConfig, - frontmatterSchema, -} from "fumadocs-mdx/config"; + remarkDirectiveAdmonition, + remarkMdxFiles, + remarkMdxMermaid, +} from "fumadocs-core/mdx-plugins"; +import { remarkImage } from "fumadocs-core/mdx-plugins"; +import { defineCollections, defineConfig, frontmatterSchema } from "fumadocs-mdx/config"; import lastModified from "fumadocs-mdx/plugins/last-modified"; import { z } from "zod"; import convert from "npm-to-yarn"; @@ -19,12 +19,10 @@ export const blogPosts = defineCollections({ date: z.coerce.date(), heroImagePath: z.string().optional(), metaImagePath: z.string().optional(), - series: z - .object({ - title: z.string(), - }) - .optional(), + series: z.string().optional(), seriesIndex: z.number().int().positive().optional(), + prev: z.string().optional(), + next: z.string().optional(), tags: z .array( z.enum([ @@ -64,26 +62,20 @@ export default defineConfig({ // Custom package managers to add --bun flag for bunx commands packageManagers: [ { - command: (cmd: string) => - convert(cmd.replace(/^npm init -y$/, "npm init"), "npm"), + command: (cmd: string) => convert(cmd.replace(/^npm init -y$/, "npm init"), "npm"), name: "npm", }, { - command: (cmd: string) => - convert(cmd.replace(/^npm init -y$/, "npm init"), "pnpm"), + command: (cmd: string) => convert(cmd.replace(/^npm init -y$/, "npm init"), "pnpm"), name: "pnpm", }, { - command: (cmd: string) => - convert(cmd.replace(/^npm init -y$/, "npm init"), "yarn"), + command: (cmd: string) => convert(cmd.replace(/^npm init -y$/, "npm init"), "yarn"), name: "yarn", }, { command: (cmd: string) => { - const converted = convert( - cmd.replace(/^npm init -y$/, "npm init"), - "bun", - ); + const converted = convert(cmd.replace(/^npm init -y$/, "npm init"), "bun"); if (!converted) return undefined; return converted.replace(/^bun x /, "bunx --bun "); }, diff --git a/apps/blog/src/app/(blog)/[slug]/page.tsx b/apps/blog/src/app/(blog)/[slug]/page.tsx index 955d6a2fd0..8b1b46b0a1 100644 --- a/apps/blog/src/app/(blog)/[slug]/page.tsx +++ b/apps/blog/src/app/(blog)/[slug]/page.tsx @@ -10,11 +10,11 @@ import { JsonLd } from "@prisma-docs/ui/components/json-ld"; import { FooterNewsletterForm } from "@prisma-docs/ui/components/newsletter"; import { BlogShare } from "@/components/BlogShare"; import { AuthorAvatarGroup } from "@/components/AuthorAvatarGroup"; -import { - getBaseUrl, - withBlogBasePath, - withBlogBasePathForImageSrc, -} from "@/lib/url"; +import { SeriesBanner } from "@/components/SeriesBanner"; +import { SeriesMarker } from "@/components/SeriesMarker"; +import { SeriesNavigation } from "@/components/SeriesNavigation"; +import { getSeriesContext } from "@/lib/series"; +import { getBaseUrl, withBlogBasePath, withBlogBasePathForImageSrc } from "@/lib/url"; import Link from "next/link"; import type { Metadata } from "next"; import { cn } from "@prisma-docs/ui/lib/cn"; @@ -75,25 +75,17 @@ function toIsoDate(value: unknown): string | undefined { return date.toISOString(); } -function getBlogPostingJsonLd( - page: ReturnType, -): BlogPostingSchema | null { +function getBlogPostingJsonLd(page: ReturnType): BlogPostingSchema | null { if (!page) return null; const title = (page.data.metaTitle ?? page.data.title)?.trim(); - const description = ( - page.data.metaDescription ?? - page.data.description ?? - "" - ).trim(); + const description = (page.data.metaDescription ?? page.data.description ?? "").trim(); if (!title || !description) return null; const canonicalPath = withBlogBasePath(page.url); const canonicalUrl = toAbsoluteUrl(canonicalPath); const imagePath = page.data.metaImagePath ?? page.data.heroImagePath; - const imageUrl = imagePath - ? toAbsoluteUrl(withBlogBasePathForImageSrc(imagePath)) - : undefined; + const imageUrl = imagePath ? toAbsoluteUrl(withBlogBasePathForImageSrc(imagePath)) : undefined; const authorNames = Array.isArray(page.data.authors) ? page.data.authors @@ -104,8 +96,7 @@ function getBlogPostingJsonLd( const datePublished = toIsoDate(page.data.date); const dateModified = - toIsoDate((page.data as { lastModified?: unknown }).lastModified) ?? - datePublished; + toIsoDate((page.data as { lastModified?: unknown }).lastModified) ?? datePublished; const jsonLd: BlogPostingSchema = { "@context": "https://schema.org", @@ -163,15 +154,14 @@ function extractText(node: React.ReactNode): string { return ""; } -export default async function Page(props: { - params: Promise<{ slug: string }>; -}) { +export default async function Page(props: { params: Promise<{ slug: string }> }) { const params = await props.params; const page = blog.getPage([params.slug]); if (!page) notFound(); const MDX = page.data.body; const blogPostingJsonLd = getBlogPostingJsonLd(page); + const seriesContext = getSeriesContext(page); const newsletterApiUrl = withBlogBasePath("/api/newsletter"); return ( @@ -182,10 +172,7 @@ export default async function Page(props: {
{/* Title + meta */}
- + ← Back to Blog

@@ -223,6 +210,7 @@ export default async function Page(props: { ))}

)} + {seriesContext ? : null} {/* Body */} @@ -263,6 +251,12 @@ export default async function Page(props: { /> + {seriesContext ? ( + <> + + + + ) : null} {/* Share Container */} diff --git a/apps/blog/src/app/(blog)/page.tsx b/apps/blog/src/app/(blog)/page.tsx index 08acd3ab9f..7928ba6fbc 100644 --- a/apps/blog/src/app/(blog)/page.tsx +++ b/apps/blog/src/app/(blog)/page.tsx @@ -1,5 +1,7 @@ import { blog, getPageImage } from "@/lib/source"; +import { getSeriesMetadata, seriesRegistry } from "@/lib/series-registry"; import { type BlogCardItem } from "@/components/BlogGrid"; +import { FeaturedSeriesShelf, type SeriesShelfItem } from "@/components/SeriesShelf"; import { BLOG_HOME_DESCRIPTION, BLOG_HOME_TITLE } from "@/lib/blog-metadata"; import type { Metadata } from "next"; import { withBlogBasePath, withBlogBasePathForImageSrc } from "@/lib/url"; @@ -91,19 +93,42 @@ export default async function BlogHome() { authors, imageSrc: withBlogBasePathForImageSrc(post.data.heroImagePath ?? ""), imageAlt: (data.heroImageAlt as string) ?? (data.title as string), - seriesTitle: data.series?.title ?? null, + seriesTitle: typeof data.series === "string" ? getSeriesMetadata(data.series).title : null, tags: data.tags, }; }); const uniqueTags = [ ...new Set( - items - .flatMap((item) => item.tags ?? []) - .filter((tag): tag is string => Boolean(tag)), + items.flatMap((item) => item.tags ?? []).filter((tag): tag is string => Boolean(tag)), ), ]; + const seriesCounts = new Map(); + for (const post of posts) { + const seriesKey = (post.data as { series?: string }).series; + if (typeof seriesKey === "string") { + seriesCounts.set(seriesKey, (seriesCounts.get(seriesKey) ?? 0) + 1); + } + } + + const seriesItems: SeriesShelfItem[] = Object.keys(seriesRegistry) + .map((key) => { + const meta = getSeriesMetadata(key); + return { + key, + title: meta.title, + description: meta.description, + featured: meta.featured ?? false, + count: seriesCounts.get(key) ?? 0, + }; + }) + .filter((item) => item.count > 0) + .sort((a, b) => { + if (a.featured !== b.featured) return a.featured ? -1 : 1; + return b.count - a.count; + }); + return (

@@ -116,7 +141,11 @@ export default async function BlogHome() { * since all post data is already present in the RSC payload. */} }> - + } + />

); diff --git a/apps/blog/src/app/(blog)/series/[key]/page.tsx b/apps/blog/src/app/(blog)/series/[key]/page.tsx new file mode 100644 index 0000000000..39a5e03155 --- /dev/null +++ b/apps/blog/src/app/(blog)/series/[key]/page.tsx @@ -0,0 +1,122 @@ +import { notFound } from "next/navigation"; +import Link from "next/link"; +import type { Metadata } from "next"; + +import { blog } from "@/lib/source"; +import { getSeriesPosts } from "@/lib/series"; +import { getSeriesMetadata, isKnownSeriesKey, seriesRegistry } from "@/lib/series-registry"; +import { withBlogBasePath, withBlogBasePathForImageSrc } from "@/lib/url"; +import { BlogGrid, type BlogCardItem } from "@/components/BlogGrid"; +import { BLOG_HOME_TITLE } from "@/lib/blog-metadata"; + +export const revalidate = false; + +interface SeriesPageParams { + key: string; +} + +function buildCardItems(seriesKey: string): BlogCardItem[] { + const posts = getSeriesPosts(seriesKey); + return posts.map((post) => { + const data = post.data as { + title?: string; + date?: Date | string; + metaDescription?: string; + authors?: string[]; + heroImagePath?: string; + heroImageAlt?: string; + tags?: string[]; + }; + + let dateISO = ""; + if (data.date) { + const dateObj = new Date(data.date); + if (!Number.isNaN(dateObj.getTime())) { + dateISO = dateObj.toISOString(); + } + } + + const authors = Array.isArray(data.authors) + ? data.authors.filter((a): a is string => typeof a === "string") + : []; + + return { + url: withBlogBasePath(post.url), + title: data.title ?? "", + date: dateISO, + excerpt: data.metaDescription, + author: authors[0] ?? null, + authors, + imageSrc: withBlogBasePathForImageSrc(data.heroImagePath ?? ""), + imageAlt: data.heroImageAlt ?? data.title ?? "", + tags: data.tags, + }; + }); +} + +export default async function SeriesPage(props: { params: Promise }) { + const { key } = await props.params; + if (!isKnownSeriesKey(key)) notFound(); + + const meta = getSeriesMetadata(key); + const items = buildCardItems(key); + + return ( +
+ + ← Back to Blog + + +
+
+ Series · {items.length} {items.length === 1 ? "part" : "parts"} +
+

+ {meta.title} +

+ {meta.description ? ( +

{meta.description}

+ ) : null} +
+ + +
+ ); +} + +export function generateStaticParams(): SeriesPageParams[] { + return Object.keys(seriesRegistry).map((key) => ({ key })); +} + +export async function generateMetadata({ + params, +}: { + params: Promise; +}): Promise { + const { key } = await params; + if (!isKnownSeriesKey(key)) return {}; + + const meta = getSeriesMetadata(key); + const title = `${meta.title} — ${BLOG_HOME_TITLE}`; + const description = meta.description; + + return { + title, + description, + alternates: { canonical: withBlogBasePath(`/series/${key}`) }, + openGraph: { + type: "website", + title, + description, + url: withBlogBasePath(`/series/${key}`), + }, + twitter: { + card: "summary_large_image", + title, + description, + }, + }; +} + +// Reference `blog` so the route is recompiled when content changes. +void blog; diff --git a/apps/blog/src/app/(blog)/series/page.tsx b/apps/blog/src/app/(blog)/series/page.tsx new file mode 100644 index 0000000000..c282a9d92e --- /dev/null +++ b/apps/blog/src/app/(blog)/series/page.tsx @@ -0,0 +1,77 @@ +import type { Metadata } from "next"; +import Link from "next/link"; + +import { blog } from "@/lib/source"; +import { getSeriesMetadata, seriesRegistry } from "@/lib/series-registry"; +import { withBlogBasePath } from "@/lib/url"; +import { SeriesIndexGrid, type SeriesShelfItem } from "@/components/SeriesShelf"; +import { BLOG_HOME_TITLE } from "@/lib/blog-metadata"; + +export const revalidate = false; + +const PAGE_TITLE = "Series"; +const PAGE_DESCRIPTION = "Multi-part series from the Prisma blog. Explore a topic end to end."; + +export async function generateMetadata(): Promise { + const title = `${PAGE_TITLE} — ${BLOG_HOME_TITLE}`; + return { + title, + description: PAGE_DESCRIPTION, + alternates: { canonical: withBlogBasePath("/series") }, + openGraph: { + type: "website", + title, + description: PAGE_DESCRIPTION, + url: withBlogBasePath("/series"), + }, + twitter: { + card: "summary_large_image", + title, + description: PAGE_DESCRIPTION, + }, + }; +} + +export default function SeriesIndexPage() { + const seriesCounts = new Map(); + for (const post of blog.getPages()) { + const seriesKey = (post.data as { series?: string }).series; + if (typeof seriesKey === "string") { + seriesCounts.set(seriesKey, (seriesCounts.get(seriesKey) ?? 0) + 1); + } + } + + const items: SeriesShelfItem[] = Object.keys(seriesRegistry) + .map((key) => { + const meta = getSeriesMetadata(key); + return { + key, + title: meta.title, + description: meta.description, + featured: meta.featured ?? false, + count: seriesCounts.get(key) ?? 0, + }; + }) + .filter((item) => item.count > 0) + .sort((a, b) => { + if (a.featured !== b.featured) return a.featured ? -1 : 1; + return b.count - a.count; + }); + + return ( +
+ + ← Back to Blog + +
+
+ {items.length} {items.length === 1 ? "series" : "series"} +
+

{PAGE_TITLE}

+

{PAGE_DESCRIPTION}

+
+ + +
+ ); +} diff --git a/apps/blog/src/components/BlogHomeClient.tsx b/apps/blog/src/components/BlogHomeClient.tsx index 11e1cfcaf4..3faecddbab 100644 --- a/apps/blog/src/components/BlogHomeClient.tsx +++ b/apps/blog/src/components/BlogHomeClient.tsx @@ -14,6 +14,7 @@ import { } from "@prisma/eclipse"; import { LargeSearchToggle } from "@/components/search-toggle"; import { withBlogBasePath } from "@/lib/url"; +import type { ReactNode } from "react"; const SHOW_ALL = "show-all"; const PAGE_SIZE = 12; @@ -67,15 +68,15 @@ function getPaginationSequence(totalPages: number, currentPage: number) { interface BlogHomeClientProps { items: BlogCardItem[]; uniqueTags: string[]; + seriesShelf?: ReactNode; } -export function BlogHomeClient({ items, uniqueTags }: BlogHomeClientProps) { +export function BlogHomeClient({ items, uniqueTags, seriesShelf }: BlogHomeClientProps) { const searchParams = useSearchParams(); const tagFromQuery = searchParams.get("tag") ?? undefined; const validTags = new Set(uniqueTags); - const currentCategory = - tagFromQuery && validTags.has(tagFromQuery) ? tagFromQuery : SHOW_ALL; + const currentCategory = tagFromQuery && validTags.has(tagFromQuery) ? tagFromQuery : SHOW_ALL; const filteredItems = currentCategory === SHOW_ALL @@ -83,25 +84,19 @@ export function BlogHomeClient({ items, uniqueTags }: BlogHomeClientProps) { : items.filter((item) => item.tags?.includes(currentCategory)); const totalPages = Math.max(1, Math.ceil(filteredItems.length / PAGE_SIZE)); - const currentPage = Math.max( - 1, - Math.min(parsePage(searchParams.get("page")), totalPages), - ); + const currentPage = Math.max(1, Math.min(parsePage(searchParams.get("page")), totalPages)); const shouldShowFeatured = currentCategory === SHOW_ALL && currentPage === 1; const featuredPost = shouldShowFeatured ? filteredItems[0] : undefined; const postsToRender = shouldShowFeatured ? filteredItems.slice(1, PAGE_SIZE) - : filteredItems.slice( - (currentPage - 1) * PAGE_SIZE, - currentPage * PAGE_SIZE, - ); + : filteredItems.slice((currentPage - 1) * PAGE_SIZE, currentPage * PAGE_SIZE); const paginationSequence = getPaginationSequence(totalPages, currentPage); return (
-
+
+ {seriesShelf} + @@ -150,10 +144,7 @@ export function BlogHomeClient({ items, uniqueTags }: BlogHomeClientProps) { ))} diff --git a/apps/blog/src/components/SeriesBanner.tsx b/apps/blog/src/components/SeriesBanner.tsx new file mode 100644 index 0000000000..e1d1f8dfa4 --- /dev/null +++ b/apps/blog/src/components/SeriesBanner.tsx @@ -0,0 +1,77 @@ +import Link from "next/link"; +import type { SeriesContext } from "@/lib/series"; + +export function SeriesBanner({ series }: { series: SeriesContext }) { + const seriesUrl = `/series/${series.key}`; + return ( + + ); +} diff --git a/apps/blog/src/components/SeriesMarker.tsx b/apps/blog/src/components/SeriesMarker.tsx new file mode 100644 index 0000000000..7100e5698c --- /dev/null +++ b/apps/blog/src/components/SeriesMarker.tsx @@ -0,0 +1,28 @@ +import Link from "next/link"; +import type { SeriesContext } from "@/lib/series"; + +export function SeriesMarker({ series }: { series: SeriesContext }) { + const seriesUrl = `/series/${series.key}`; + return ( +
+ + + Part{" "} + + {series.index} of {series.total} + {" "} + in the{" "} + + {series.title} + {" "} + series. + + + View full series → + +
+ ); +} diff --git a/apps/blog/src/components/SeriesNavigation.tsx b/apps/blog/src/components/SeriesNavigation.tsx new file mode 100644 index 0000000000..36bf1de2b7 --- /dev/null +++ b/apps/blog/src/components/SeriesNavigation.tsx @@ -0,0 +1,39 @@ +import Link from "next/link"; +import type { SeriesContext } from "@/lib/series"; + +export function SeriesNavigation({ series }: { series: SeriesContext }) { + if (!series.prev && !series.next) return null; + + return ( + + ); +} diff --git a/apps/blog/src/components/SeriesShelf.tsx b/apps/blog/src/components/SeriesShelf.tsx new file mode 100644 index 0000000000..69a3c50312 --- /dev/null +++ b/apps/blog/src/components/SeriesShelf.tsx @@ -0,0 +1,154 @@ +import Link from "next/link"; +import { cn } from "@prisma-docs/ui/lib/cn"; + +export type SeriesShelfItem = { + key: string; + title: string; + description?: string; + count: number; + featured?: boolean; +}; + +// Total chips shown in the home shelf (featured + popular non-featured). +const CHIP_LIMIT = 2; + +function SeriesCard({ item, variant }: { item: SeriesShelfItem; variant: "compact" | "full" }) { + const featured = item.featured; + return ( + +
+ {featured ? Featured : null} + + {item.count} {item.count === 1 ? "part" : "parts"} + +
+
+ {item.title} +
+ {item.description && variant === "full" ? ( +

{item.description}

+ ) : null} + + ); +} + +function SeriesChip({ item }: { item: SeriesShelfItem }) { + const featured = item.featured; + return ( + + {featured ? ( + + ) : null} + {item.title} + {item.count} + + ); +} + +function FeaturedHighlight({ item }: { item: SeriesShelfItem }) { + return ( + +
+ Featured series + + · + + + {item.count} {item.count === 1 ? "part" : "parts"} + +
+
+ {item.title} +
+ {item.description ? ( +

{item.description}

+ ) : null} +
Explore the series →
+ + ); +} + +/** + * Home page series surface: a small chip row plus a prominent highlight + * card for the single most important series. Built to sit between the + * tag filter row and the post grid. + */ +export function FeaturedSeriesShelf({ series }: { series: SeriesShelfItem[] }) { + if (series.length === 0) return null; + + const featured = series.filter((s) => s.featured); + const nonFeatured = series.filter((s) => !s.featured); + + const chips: SeriesShelfItem[] = [...featured, ...nonFeatured].slice(0, CHIP_LIMIT); + + const highlight = featured[0] ?? null; + + return ( +
+
+ + Series + +
    + {chips.map((item) => ( +
  • + +
  • + ))} +
+ + View all series → + +
+ {highlight ? : null} +
+ ); +} + +/** + * Full index of every series, used on /blog/series. Featured items render + * first with a brand-accented border. + */ +export function SeriesIndexGrid({ series }: { series: SeriesShelfItem[] }) { + if (series.length === 0) return null; + return ( +
    + {series.map((item) => ( +
  • + +
  • + ))} +
+ ); +} diff --git a/apps/blog/src/lib/format.ts b/apps/blog/src/lib/format.ts index 20bb8e4248..7012f305c3 100644 --- a/apps/blog/src/lib/format.ts +++ b/apps/blog/src/lib/format.ts @@ -10,8 +10,12 @@ export const formatDate = (iso: string) => { }); }; +const TAG_ACRONYMS: Record = { + orm: "ORM", + ai: "AI", +}; + export const formatTag = (tag: string) => { - return tag === "orm" - ? "ORM" - : tag.replace(/-/g, " ").replace(/\b\w/g, (char) => char.toUpperCase()); + if (Object.prototype.hasOwnProperty.call(TAG_ACRONYMS, tag)) return TAG_ACRONYMS[tag]; + return tag.replace(/-/g, " ").replace(/\b\w/g, (char) => char.toUpperCase()); }; diff --git a/apps/blog/src/lib/series-registry.ts b/apps/blog/src/lib/series-registry.ts new file mode 100644 index 0000000000..e91b0b17ff --- /dev/null +++ b/apps/blog/src/lib/series-registry.ts @@ -0,0 +1,94 @@ +/** + * Single source of truth for blog series metadata. + * + * To add a new series: + * 1. Add a key/value entry below. + * 2. In each post in the series, set `series: ` and `seriesIndex: N` + * in the frontmatter. + * + * Set `featured: true` to surface the series on the blog home shelf and + * style its card with the brand accent. Keep this list short — featured + * cards take prime real estate. + */ +export const seriesRegistry = { + "prisma-next": { + title: "Prisma Next", + description: + "Follow the journey of Prisma Next, the next evolution of Prisma ORM. From the announcement and roadmap to TypeScript migrations, the extension API, and Early Access.", + featured: true, + }, + "rust-to-typescript-migration-journey": { + title: "Prisma ORM: The Complete Rust-to-TypeScript Migration Journey", + description: + "How Prisma ORM moved off the Rust query engine to a leaner TypeScript/WASM core, covering the rewrite, benchmarks, and the road to a Rust-free production release.", + }, + "improving-query-performance-using-indexes": { + title: "Improving query performance with indexes using Prisma", + description: + "A practical series on using database indexes with Prisma, from the fundamentals to specific index types and how to apply them to real queries.", + }, + "fullstack-nextjs-graphql-prisma": { + title: "Building a fullstack app using TypeScript, PostgreSQL, Next.js, GraphQL and Prisma", + description: + "Build a production-ready fullstack app step by step with Next.js, GraphQL, PostgreSQL and Prisma.", + }, + "fullstack-remix-prisma-mongodb": { + title: "Build A Fullstack App with Remix, Prisma & MongoDB", + description: + "A multi-part walkthrough of building a fullstack application with Remix, Prisma, and MongoDB.", + }, + "e2e-type-safety-graphql-react": { + title: "Build a Fully Type-Safe Application with GraphQL, Prisma & React", + description: + "Achieve end-to-end type safety across the stack using GraphQL, Prisma, and React.", + }, + "backend-prisma-typescript-orm-with-postgresql": { + title: "Building a modern backend with TypeScript, PostgreSQL and Prisma", + description: + "Build a modern backend from data modeling and validation all the way to deployment using TypeScript, PostgreSQL, and Prisma.", + }, + "nestjs-prisma-rest-api": { + title: "Building a REST API with NestJS, PostgreSQL, Swagger and Prisma", + description: + "Build a complete REST API with NestJS and Prisma, covering validation, relational data, error handling, and authentication.", + }, + "testing-with-prisma": { + title: "The Ultimate Guide to Testing with Prisma", + description: + "An end-to-end testing playbook for Prisma apps: unit, integration, and end-to-end tests, plus mocking patterns and CI workflows.", + }, + "graphql-nexus": { + title: "Code-first GraphQL server development with Nexus", + description: + "Build code-first GraphQL servers with Nexus, from the problems of schema-first to using Nexus with a database.", + }, +} as const satisfies Record; + +export type SeriesKey = keyof typeof seriesRegistry; + +export type SeriesMetadata = { + title: string; + description?: string; + featured?: boolean; +}; + +function hasSeriesKey(key: string): key is SeriesKey { + return Object.prototype.hasOwnProperty.call(seriesRegistry, key); +} + +/** + * Resolves series metadata for a given key. Falls back to a synthetic entry + * using the key as the title if it isn't in the registry, so missing keys + * never break the page — they just look unstyled until added to the registry. + */ +export function getSeriesMetadata(key: string): SeriesMetadata { + if (hasSeriesKey(key)) { + const entry = seriesRegistry[key] as SeriesMetadata; + return entry; + } + return { title: key }; +} + +export function isKnownSeriesKey(key: string): key is SeriesKey { + return hasSeriesKey(key); +} diff --git a/apps/blog/src/lib/series.ts b/apps/blog/src/lib/series.ts new file mode 100644 index 0000000000..312cb6e853 --- /dev/null +++ b/apps/blog/src/lib/series.ts @@ -0,0 +1,114 @@ +import { blog } from "./source"; +import { getSeriesMetadata } from "./series-registry"; + +type BlogPage = ReturnType[number]; + +export type SeriesPostRef = { + url: string; + title: string; + slug: string; + seriesIndex?: number; +}; + +export type SeriesContext = { + key: string; + title: string; + description?: string; + posts: SeriesPostRef[]; + index: number; + total: number; + prev: SeriesPostRef | null; + next: SeriesPostRef | null; +}; + +function getSlug(page: BlogPage): string { + return page.slugs[0] ?? ""; +} + +function toRef(page: BlogPage): SeriesPostRef { + const data = page.data as { title?: string; seriesIndex?: number }; + return { + url: page.url, + title: data.title ?? "", + slug: getSlug(page), + seriesIndex: data.seriesIndex, + }; +} + +function findBySlug(slug: string): BlogPage | undefined { + return blog.getPages().find((p) => getSlug(p) === slug); +} + +/** + * Returns all posts that belong to a given series key, ordered by + * `seriesIndex` (asc). Posts without an index sort after indexed ones, by date. + */ +export function getSeriesPosts(seriesKey: string): BlogPage[] { + return blog + .getPages() + .filter((p) => (p.data as { series?: string }).series === seriesKey) + .sort((a, b) => { + const ai = (a.data as { seriesIndex?: number }).seriesIndex; + const bi = (b.data as { seriesIndex?: number }).seriesIndex; + if (ai != null && bi != null) return ai - bi; + if (ai != null) return -1; + if (bi != null) return 1; + const ad = new Date((a.data as { date?: Date }).date ?? 0).getTime(); + const bd = new Date((b.data as { date?: Date }).date ?? 0).getTime(); + return ad - bd; + }); +} + +/** + * Resolves the series context for a given post. + * + * Title/description come from the registry (keyed by `series` in frontmatter). + * Prev/next are derived from `seriesIndex` order within the series unless the + * post sets explicit `prev`/`next` slugs in frontmatter (those win). + */ +export function getSeriesContext(page: BlogPage): SeriesContext | null { + const data = page.data as { + series?: string; + prev?: string; + next?: string; + }; + const key = data.series; + if (!key) return null; + + const posts = getSeriesPosts(key); + if (posts.length === 0) return null; + + const meta = getSeriesMetadata(key); + + const currentSlug = getSlug(page); + const currentIndex = posts.findIndex((p) => getSlug(p) === currentSlug); + + const explicitPrev = data.prev ? findBySlug(data.prev) : undefined; + const explicitNext = data.next ? findBySlug(data.next) : undefined; + const explicitPrevInSeries = + explicitPrev && (explicitPrev.data as { series?: string }).series === key + ? explicitPrev + : undefined; + const explicitNextInSeries = + explicitNext && (explicitNext.data as { series?: string }).series === key + ? explicitNext + : undefined; + + const positionalPrev = currentIndex > 0 ? posts[currentIndex - 1] : undefined; + const positionalNext = + currentIndex >= 0 && currentIndex < posts.length - 1 ? posts[currentIndex + 1] : undefined; + + const prevPage = explicitPrevInSeries ?? positionalPrev; + const nextPage = explicitNextInSeries ?? positionalNext; + + return { + key, + title: meta.title, + description: meta.description, + posts: posts.map(toRef), + index: currentIndex >= 0 ? currentIndex + 1 : 0, + total: posts.length, + prev: prevPage ? toRef(prevPage) : null, + next: nextPage ? toRef(nextPage) : null, + }; +}