diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000000..f6bb6efa14 --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,13 @@ +[production] +> 0.5% +last 2 Chrome versions +last 2 Firefox versions +last 2 Safari versions +last 2 Edge versions +Firefox ESR +not dead + +[development] +last 1 Chrome version +last 1 Firefox version +last 1 Safari version diff --git a/apps/blog/.browserslistrc b/apps/blog/.browserslistrc new file mode 100644 index 0000000000..f6bb6efa14 --- /dev/null +++ b/apps/blog/.browserslistrc @@ -0,0 +1,13 @@ +[production] +> 0.5% +last 2 Chrome versions +last 2 Firefox versions +last 2 Safari versions +last 2 Edge versions +Firefox ESR +not dead + +[development] +last 1 Chrome version +last 1 Firefox version +last 1 Safari version diff --git a/apps/blog/content/blog/about-mcp-servers-and-how-we-built-one-for-prisma/index.mdx b/apps/blog/content/blog/about-mcp-servers-and-how-we-built-one-for-prisma/index.mdx index 0c5674c2b1..0c63570311 100644 --- a/apps/blog/content/blog/about-mcp-servers-and-how-we-built-one-for-prisma/index.mdx +++ b/apps/blog/content/blog/about-mcp-servers-and-how-we-built-one-for-prisma/index.mdx @@ -5,6 +5,7 @@ date: "2025-05-07" authors: - "Nikolas Burk" metaTitle: "About MCP Servers & How We Built One for Prisma" +metaDescription: "Learn what MCP servers are and how Prisma built its MCP server, from tool access concepts to remote server architecture and practical implementation details." metaImagePath: "/about-mcp-servers-and-how-we-built-one-for-prisma/imgs/meta-c7ef9462464563ecc68ddf667e18dbef71f9f4fd-1266x711.png" heroImagePath: "/about-mcp-servers-and-how-we-built-one-for-prisma/imgs/hero-af7a5b40501028b64219b2144f7b5c03723c4d99-844x474.svg" tags: diff --git a/apps/blog/content/blog/all-you-need-to-know-about-apollo-client-2-7e27e36d62fd/index.mdx b/apps/blog/content/blog/all-you-need-to-know-about-apollo-client-2-7e27e36d62fd/index.mdx index 0830b00d1c..f156abfae3 100644 --- a/apps/blog/content/blog/all-you-need-to-know-about-apollo-client-2-7e27e36d62fd/index.mdx +++ b/apps/blog/content/blog/all-you-need-to-know-about-apollo-client-2-7e27e36d62fd/index.mdx @@ -5,6 +5,7 @@ date: "2017-11-07" authors: - "Nikolas Burk" metaTitle: "All you need to know about Apollo Client 2 | Prisma" +metaDescription: "Learn about Apollo Client 2.0, including Apollo Link, local state management, cache updates, and the biggest changes from earlier Apollo Client releases." metaImagePath: "/all-you-need-to-know-about-apollo-client-2-7e27e36d62fd/imgs/hero-ebd9548e6d9cfb33c4e35eac48e11a80532a8d30-1440x960.jpg" heroImagePath: "/all-you-need-to-know-about-apollo-client-2-7e27e36d62fd/imgs/hero-ebd9548e6d9cfb33c4e35eac48e11a80532a8d30-1440x960.jpg" heroImageAlt: "All you need to know about Apollo Client 2" diff --git a/apps/blog/content/blog/announcing-prisma-2-n0v98rzc8br1/index.mdx b/apps/blog/content/blog/announcing-prisma-2-n0v98rzc8br1/index.mdx index f9182b0235..22f97c00a4 100644 --- a/apps/blog/content/blog/announcing-prisma-2-n0v98rzc8br1/index.mdx +++ b/apps/blog/content/blog/announcing-prisma-2-n0v98rzc8br1/index.mdx @@ -5,6 +5,7 @@ date: "2020-06-09" authors: - "Nikolas Burk" metaTitle: "Announcing Prisma 2: Confidence and productivity for your database" +metaDescription: "Prisma 2 introduced a type-safe database client and declarative migrations to make working with databases in Node.js and TypeScript faster and more reliable." metaImagePath: "/announcing-prisma-2-n0v98rzc8br1/imgs/hero-11436ec45c7ccbc812212d1d6d7c8794d9514f2f-1692x852.jpg" heroImagePath: "/announcing-prisma-2-n0v98rzc8br1/imgs/hero-11436ec45c7ccbc812212d1d6d7c8794d9514f2f-1692x852.jpg" heroImageAlt: " Ombre Prisma" @@ -689,4 +690,3 @@ This year, we are going remote and are inviting everyone to join us for amazing
{/* */} - diff --git a/apps/blog/content/blog/announcing-prisma-2-zq1s745db8i5/index.mdx b/apps/blog/content/blog/announcing-prisma-2-zq1s745db8i5/index.mdx index 61e6047ef9..fb309216b6 100644 --- a/apps/blog/content/blog/announcing-prisma-2-zq1s745db8i5/index.mdx +++ b/apps/blog/content/blog/announcing-prisma-2-zq1s745db8i5/index.mdx @@ -5,6 +5,7 @@ date: "2019-06-18" authors: - "Nikolas Burk" metaTitle: "Type-safe Database Access & Declarative Migrations | Prisma 2 Preview" +metaDescription: "Prisma 2 Preview introduced a type-safe database client and declarative migrations to modernize database workflows for application developers." metaImagePath: "/announcing-prisma-2-zq1s745db8i5/imgs/hero-34a26858c7de3cad0d84a376d12b58b82ee10da0-1200x630.png" heroImagePath: "/announcing-prisma-2-zq1s745db8i5/imgs/hero-34a26858c7de3cad0d84a376d12b58b82ee10da0-1200x630.png" heroImageAlt: "Prisma 2 Preview: Type-safe Database Access & Declarative Migrations" @@ -459,4 +460,3 @@ The Prisma 2 Preview is not the only exciting thing happening this week. We are - [GraphQL Conf](https://www.graphqlconf.org/) (**Late bird tickets still available**) We are especially looking forward to welcoming the Prisma community at Prisma Day for a day of inspiring talks and great conversations. See you all tomorrow! 🙌 - diff --git a/apps/blog/content/blog/announcing-prisma-6-19-0/index.mdx b/apps/blog/content/blog/announcing-prisma-6-19-0/index.mdx index 1177210de7..1edc3fb145 100644 --- a/apps/blog/content/blog/announcing-prisma-6-19-0/index.mdx +++ b/apps/blog/content/blog/announcing-prisma-6-19-0/index.mdx @@ -92,6 +92,8 @@ With this release, we’re very close to the next major release of Prisma, v7. T For a full reference of the options that can be used in Prisma Config, see the [docs](https://www.prisma.io/docs/orm/reference/prisma-config-reference). +If you want to go deeper on the Postgres side of this release, explore [Prisma Postgres](https://www.prisma.io/postgres), review [pricing](https://www.prisma.io/pricing), and check the [connection pooling docs](https://www.prisma.io/docs/postgres/database/connection-pooling). + Be sure to follow us on social media to stay up to date with all the latest release of Prisma ORM and Prisma Postgres - [X/Twitter](https://x.com/prisma) diff --git a/apps/blog/content/blog/announcing-prisma-day-50cg22nn40qk/index.mdx b/apps/blog/content/blog/announcing-prisma-day-50cg22nn40qk/index.mdx index d63370801e..03490a6e1f 100644 --- a/apps/blog/content/blog/announcing-prisma-day-50cg22nn40qk/index.mdx +++ b/apps/blog/content/blog/announcing-prisma-day-50cg22nn40qk/index.mdx @@ -5,6 +5,7 @@ date: "2019-04-11" authors: - "Etel Sverdlov" metaTitle: "Prisma Day 2019 - community conference on modern app development" +metaDescription: "Prisma Day 2019 brought the Prisma community together in Berlin for talks on modern app development, databases, and Prisma in production." metaImagePath: "/announcing-prisma-day-50cg22nn40qk/imgs/meta-eeacc461f1965ed958af330fc9dc93f635920b43-1200x630.png" heroImagePath: "/announcing-prisma-day-50cg22nn40qk/imgs/hero-d719c9276cc4c57665d4a32cc5fdae5b5bfcad50-1200x630.png" heroImageAlt: "Announcing Prisma Day the future of data" 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 6c6aad0457..46b7c03f30 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 @@ -104,6 +104,12 @@ All of this is possible because Prisma Postgres is just standard Postgres, but b There’s a lot in this release that we would love to talk about, but then this post would be much longer. We're already grateful you read this far! We’ve spent countless hours working through our backlog of issues and feature requests to address some of the top requested ones, like [mapped enums](https://github.com/prisma/prisma/issues/273?utm_source=blog&utm_content=launch-blog&via=prisma7), updating the minimum version of Node and TypeScript required for projects, as well as a brand new version of Prisma Studio via `npx prisma studio`. You can find **everything** that’s in this release in our changelog, and we have a migrations guide available as well. +## Where to go next + +- [Explore Prisma ORM](https://www.prisma.io/orm) to see what shipped in Prisma 7 in one place. +- [Follow the Prisma 7 upgrade guide](https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-7) if you're planning a production upgrade. +- [Try Prisma Postgres](https://www.prisma.io/postgres), review [pricing](https://www.prisma.io/pricing), or [set up Prisma's MCP tooling](https://www.prisma.io/mcp) if you want a faster way to provision databases for new projects and AI-assisted workflows. + ## Thank you This is not just another version release for us. It's the foundation of what comes next for Prisma ORM and Prisma Postgres. We want the tools we've built to provide the best possible experience, so developers can focus on building and shipping amazing applications. So thank you to our incredible community and a special thank you to everyone who has provided feedback during our pre-release process. And to everyone giving Prisma 7 a shot now: please tell us what you think! diff --git a/apps/blog/content/blog/announcing-prisma-orm-7-2-0/index.mdx b/apps/blog/content/blog/announcing-prisma-orm-7-2-0/index.mdx index 1d62d04ce1..27b79dfe2a 100644 --- a/apps/blog/content/blog/announcing-prisma-orm-7-2-0/index.mdx +++ b/apps/blog/content/blog/announcing-prisma-orm-7-2-0/index.mdx @@ -118,6 +118,12 @@ If you’ve been using the `@db.Money` type in your Prisma schema, you might hav This issue was reported back in July, and we’re thrilled that it’s been fixed in 7.2.0. +## Where to go next + +- [Explore Prisma ORM](https://www.prisma.io/orm) for the latest Prisma 7 releases and capabilities. +- [Review the Prisma 7 upgrade guide](https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-7) before rolling 7.2.0 out more broadly. +- [Refresh your Prisma Client generation setup](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/generating-prisma-client) if you're adopting the newer Prisma config workflow. + ## Parting Thoughts As we mentioned in a previous post, we’re aware of a performance regression that appears in some specific cases. We’re actively working on a fix and plan to release it as soon as possible. We’ll share more updates once the fix has been merged and released. @@ -129,4 +135,3 @@ Be sure to follow us on social media to stay up to date with the latest releases - [YouTube](https://www.youtube.com/@PrismaData) - [LinkedIn](https://www.linkedin.com/company/prisma-io/) - [Discord](https://pris.ly/discord) - diff --git a/apps/blog/content/blog/announcing-prisma-postgres-for-ai-coding-agents/index.mdx b/apps/blog/content/blog/announcing-prisma-postgres-for-ai-coding-agents/index.mdx index de83130cc7..e6d3d3db93 100644 --- a/apps/blog/content/blog/announcing-prisma-postgres-for-ai-coding-agents/index.mdx +++ b/apps/blog/content/blog/announcing-prisma-postgres-for-ai-coding-agents/index.mdx @@ -5,6 +5,7 @@ date: "2025-02-06" authors: - "Søren Bramer Schmidt" metaTitle: "Announcing: Instant Prisma Postgres for AI Coding Agents" +metaDescription: "Prisma Postgres gives AI coding agents instant database provisioning so developers can build, test, and iterate on AI-powered apps much faster." metaImagePath: "/announcing-prisma-postgres-for-ai-coding-agents/imgs/meta-24be732ef3e8f019820d370b8a5f74ab14170fdc-1266x711.png" heroImagePath: "/announcing-prisma-postgres-for-ai-coding-agents/imgs/hero-6ad1b7b4a851a45e91418d443573f0c38accc78d-844x474.svg" tags: diff --git a/apps/blog/content/blog/announcing-typedsql-make-your-raw-sql-queries-type-safe-with-prisma-orm/index.mdx b/apps/blog/content/blog/announcing-typedsql-make-your-raw-sql-queries-type-safe-with-prisma-orm/index.mdx index 98644c01da..a7f5ea4552 100644 --- a/apps/blog/content/blog/announcing-typedsql-make-your-raw-sql-queries-type-safe-with-prisma-orm/index.mdx +++ b/apps/blog/content/blog/announcing-typedsql-make-your-raw-sql-queries-type-safe-with-prisma-orm/index.mdx @@ -254,4 +254,6 @@ We see TypedSQL as the evolution of SQL query builders, giving developers even m
[Try TypedSQL](https://pris.ly/typedsql-example) +If you want to go deeper, explore [TypedSQL](https://www.prisma.io/typedsql), read the [TypedSQL docs](https://www.prisma.io/docs/orm/prisma-client/using-raw-sql/typedsql), or see how it fits into the broader [Prisma ORM](https://www.prisma.io/orm) workflow. + We’d love for you to try out TypedSQL and let us know what you think of it on [X](https://pris.ly/x) and on [Discord](https://pris.ly/discord)! 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 3a45e544c9..0af5763c0b 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 @@ -5,6 +5,7 @@ date: "2020-09-10" authors: - "Daniel Norman" metaTitle: "TypeScript, PostgreSQL, Prisma Backend | Authentication, Authorization" +metaDescription: "Secure a TypeScript and PostgreSQL backend with Prisma, passwordless authentication, JWTs, and authorization rules using Hapi." 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" @@ -1096,4 +1097,3 @@ You can find the full source code on [GitHub](https://github.com/2color/real-wor While Prisma aims to make working with relational databases easy, it's useful to understand the underlying database and authentication principles. If you have questions, feel free to reach out on [Twitter](https://twitter.com/daniel2color). - 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 1f5deab3a7..268cd8bc62 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 @@ -5,6 +5,7 @@ date: "2020-07-30" authors: - "Daniel Norman" metaTitle: "TypeScript, PostgreSQL, Prisma | Data Modeling, CRUD, Aggregates" +metaDescription: "Learn how to model data, perform CRUD operations, and query aggregates in a TypeScript and PostgreSQL backend built with Prisma." 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" 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 dab4075a39..7535a533ca 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 @@ -5,6 +5,7 @@ date: "2020-09-17" authors: - "Daniel Norman" metaTitle: "TypeScript, PostgreSQL, Prisma | Continuous Integration & Deployment" +metaDescription: "Set up CI/CD for a TypeScript, PostgreSQL, and Prisma backend with GitHub Actions, automated tests, and Heroku deployment." 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" @@ -365,4 +366,3 @@ You can find the full source code for the backend on [GitHub](https://github.com While Prisma aims to make working with relational databases easy, it's useful to understand the underlying database and [Heroku specific details](https://devcenter.heroku.com/articles/deploying-nodejs). If you have questions, feel free to reach out on [Twitter](https://twitter.com/daniel2color). - 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 62e18f8891..c220183e42 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 @@ -5,6 +5,7 @@ date: "2020-08-20" authors: - "Daniel Norman" metaTitle: "TypeScript, PostgreSQL, Prisma Backend | REST API, Validation, Testing" +metaDescription: "Build a REST API with TypeScript, PostgreSQL, Prisma, and Hapi, then add validation and tests for CRUD endpoints." 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" @@ -1135,4 +1136,3 @@ In the next parts of the series, you'll learn more about: - Integration with external APIs: Using a transactional email API to send emails. - Authorization: Provide different levels of access to different resources. - Deployment - diff --git a/apps/blog/content/blog/build-an-app-with-svelte-and-typescript-PZDY3t93qAtd/index.mdx b/apps/blog/content/blog/build-an-app-with-svelte-and-typescript-PZDY3t93qAtd/index.mdx index 67e7983c8f..1ed4efe7e2 100644 --- a/apps/blog/content/blog/build-an-app-with-svelte-and-typescript-PZDY3t93qAtd/index.mdx +++ b/apps/blog/content/blog/build-an-app-with-svelte-and-typescript-PZDY3t93qAtd/index.mdx @@ -5,6 +5,7 @@ date: "2020-12-17" authors: - "Ryan Chenkie" metaTitle: "How to build an App With Svelte and TypeScript | Prisma" +metaDescription: "Learn how to build a Svelte app with TypeScript and improve developer ergonomics with stronger typing across your frontend codebase." metaImagePath: "/build-an-app-with-svelte-and-typescript-PZDY3t93qAtd/imgs/meta-711f2d3f2094907c22c0ef2dd88e69992f950026-2400x1256.png" heroImagePath: "/build-an-app-with-svelte-and-typescript-PZDY3t93qAtd/imgs/hero-0e8c20420d860a393f68694b8bab707306822df3-1692x852.png" heroImageAlt: "Build an App With Svelte and TypeScript" diff --git a/apps/blog/content/blog/connections-edges-nodes-in-relay-758d358aa4c7/index.mdx b/apps/blog/content/blog/connections-edges-nodes-in-relay-758d358aa4c7/index.mdx index 125dba10c4..9aba9c2ebe 100644 --- a/apps/blog/content/blog/connections-edges-nodes-in-relay-758d358aa4c7/index.mdx +++ b/apps/blog/content/blog/connections-edges-nodes-in-relay-758d358aa4c7/index.mdx @@ -6,6 +6,7 @@ authors: - "Johannes Schickling" - "Søren Bramer Schmidt" metaTitle: "Learn more about Connections, Edges & Nodes in Relay | Prisma" +metaDescription: "Learn how Relay uses connections, edges, and nodes to model relationships and pagination on top of GraphQL schemas." metaImagePath: "/connections-edges-nodes-in-relay-758d358aa4c7/imgs/meta-cc730c78d87244cb877764a6a4a850b2c9223871-1200x775.png" heroImagePath: "/connections-edges-nodes-in-relay-758d358aa4c7/imgs/hero-a86c8de527177e03b9e08b9f1f1522dc1debbc6d-559x361.png" --- diff --git a/apps/blog/content/blog/database-access-in-react-server-components-r2xgk9aztgdf/index.mdx b/apps/blog/content/blog/database-access-in-react-server-components-r2xgk9aztgdf/index.mdx index c97d10d03e..dacd7d1050 100644 --- a/apps/blog/content/blog/database-access-in-react-server-components-r2xgk9aztgdf/index.mdx +++ b/apps/blog/content/blog/database-access-in-react-server-components-r2xgk9aztgdf/index.mdx @@ -5,6 +5,7 @@ date: "2021-02-24" authors: - "Mahmoud Abdelwahab" metaTitle: "Send Database Queries in a React App Using Server Components" +metaDescription: "Learn how to query your database directly from React Server Components with Prisma, and why type-safe database access fits the server-rendered React model." metaImagePath: "/database-access-in-react-server-components-r2xgk9aztgdf/imgs/meta-8befd7df92cc32135332ef9c28b41e076e2c8998-1251x630.png" heroImagePath: "/database-access-in-react-server-components-r2xgk9aztgdf/imgs/hero-f388984fa1fe34f5d79d884f6f599c22a4107fa1-846x426.png" heroImageAlt: "Database Access in React Server Components" @@ -490,4 +491,3 @@ We also end up having a faster user experience since less JavaScript is shipped Finally, React's virtual DOM now spans the entire application instead of just the client. There are still many questions to be answered, and there are [drawbacks](https://github.com/josephsavona/rfcs/blob/server-components/text/0000-server-components.md#drawbacks), but it's exciting to see how the future of building Web apps using React might look like. - diff --git a/apps/blog/content/blog/datamodel-v11-lrzqy1f56c90/index.mdx b/apps/blog/content/blog/datamodel-v11-lrzqy1f56c90/index.mdx index 2d65047687..4fdacd5128 100644 --- a/apps/blog/content/blog/datamodel-v11-lrzqy1f56c90/index.mdx +++ b/apps/blog/content/blog/datamodel-v11-lrzqy1f56c90/index.mdx @@ -5,6 +5,7 @@ date: "2019-04-17" authors: - "Nikolas Burk" metaTitle: "New Datamodel Syntax: Improved Schema Control & Simpler Migrations" +metaDescription: "Prisma's new datamodel syntax gave developers more control over database schemas while simplifying migrations and reducing opinionated defaults." metaImagePath: "/datamodel-v11-lrzqy1f56c90/imgs/hero-99f1530d6ebe62110fd2839ba4f0185795ee5db4-1200x630.png" heroImagePath: "/datamodel-v11-lrzqy1f56c90/imgs/hero-99f1530d6ebe62110fd2839ba4f0185795ee5db4-1200x630.png" heroImageAlt: "New Datamodel Syntax: More Schema Control & Simpler Migration" diff --git a/apps/blog/content/blog/documenting-apis-mjjpZ7E7NkVP/index.mdx b/apps/blog/content/blog/documenting-apis-mjjpZ7E7NkVP/index.mdx index 3eaf6823d0..107e2ab09e 100644 --- a/apps/blog/content/blog/documenting-apis-mjjpZ7E7NkVP/index.mdx +++ b/apps/blog/content/blog/documenting-apis-mjjpZ7E7NkVP/index.mdx @@ -5,6 +5,7 @@ date: "2021-05-06" authors: - "Alex Ruheni" metaTitle: "Learn 5 Tools for Documenting Web APIs" +metaDescription: "Explore five tools and approaches for documenting web APIs so teams can ship clearer, more usable developer experiences." metaImagePath: "/documenting-apis-mjjpZ7E7NkVP/imgs/hero-2982f7850de70f0c52daa613dae904b463342823-1692x852.png" heroImagePath: "/documenting-apis-mjjpZ7E7NkVP/imgs/hero-2982f7850de70f0c52daa613dae904b463342823-1692x852.png" heroImageAlt: "5 Tools for Documenting Your Web API" diff --git a/apps/blog/content/blog/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d/index.mdx b/apps/blog/content/blog/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d/index.mdx index c63e4480c4..a990c7da52 100644 --- a/apps/blog/content/blog/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d/index.mdx +++ b/apps/blog/content/blog/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d/index.mdx @@ -5,6 +5,7 @@ date: "2017-11-22" authors: - "Nikolas Burk" metaTitle: "Enabling CORS for Express-GraphQL & Apollo Server | Prisma" +metaDescription: "Learn how to enable CORS in Express-GraphQL and Apollo Server so browser clients can safely call your GraphQL API across origins." metaImagePath: "/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d/imgs/hero-88be8d72c611e06bf0170f1e0416f589d50262dd-720x481.jpg" heroImagePath: "/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d/imgs/hero-88be8d72c611e06bf0170f1e0416f589d50262dd-720x481.jpg" heroImageAlt: "Enabling CORS for Express-GraphQL & Apollo Server" 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 2d7b697ad8..5cdd9578e3 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 @@ -197,3 +197,5 @@ Yes. If you encounter compatibility issues, you can temporarily revert to the le However, the Rust binary-free engine is now the default moving forward and is recommended for all new projects. Migration steps and fallback guidance are available in the [Rust-free Prisma ORM production release blog](https://www.prisma.io/blog/rust-free-prisma-orm-is-ready-for-production?utm_source=chatgpt.com). + +If you're planning to adopt the new architecture, explore [Prisma ORM](https://www.prisma.io/orm), review the [Rust-free Prisma Client docs](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/no-rust-engine), and use [Prisma Postgres](https://www.prisma.io/postgres) if you want the database workflow shown throughout this migration series. diff --git a/apps/blog/content/blog/full-stack-typesafety-with-angular-nest-nx-and-prisma-CcMK7fbQfTWc/index.mdx b/apps/blog/content/blog/full-stack-typesafety-with-angular-nest-nx-and-prisma-CcMK7fbQfTWc/index.mdx index 1789674e56..5f43cb3172 100644 --- a/apps/blog/content/blog/full-stack-typesafety-with-angular-nest-nx-and-prisma-CcMK7fbQfTWc/index.mdx +++ b/apps/blog/content/blog/full-stack-typesafety-with-angular-nest-nx-and-prisma-CcMK7fbQfTWc/index.mdx @@ -5,6 +5,7 @@ date: "2021-01-19" authors: - "Ryan Chenkie" metaTitle: "Applying Full Stack Type Safety with Angular, Nest, Nx & Prisma" +metaDescription: "Learn how Angular, NestJS, Nx, and Prisma can deliver full-stack type safety from the frontend to the database in a TypeScript app." metaImagePath: "/full-stack-typesafety-with-angular-nest-nx-and-prisma-CcMK7fbQfTWc/imgs/meta-6edf92a2f15ffb62ed50e0da3deed2b2908d0156-2398x1208.png" heroImagePath: "/full-stack-typesafety-with-angular-nest-nx-and-prisma-CcMK7fbQfTWc/imgs/hero-2e21e72be724fc37acc24f269c8b6a0628ad5a18-870x438.jpg" heroImageAlt: "Full Stack Type Safety with Angular, Nest, Nx, and Prisma" 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 6c5984fb26..72e69c14ba 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 @@ -19,6 +19,8 @@ tags: This article is the final part of the course where you build a fullstack app with Next.js, GraphQL, TypeScript, Prisma, and PostgreSQL. In this article, you will learn how to deploy your app to Vercel. +> **Update (May 2026):** This deployment chapter still works as a conceptual guide, but the Prisma Data Proxy steps are now historical. For new projects, prefer [Prisma Accelerate](https://www.prisma.io/accelerate) for connection pooling and caching, use the current [serverless deployment docs](https://www.prisma.io/docs/orm/prisma-client/deployment/serverless/deploy-to-vercel), and consider [Prisma Postgres](https://www.prisma.io/postgres) if you want a managed Postgres database with Prisma ORM. + ## Table of Contents - [Introduction](#introduction) @@ -36,7 +38,7 @@ This article is the final part of the course where you build a fullstack app wit In this course you will learn how to build "awesome-links", a fullstack app where users can browse through a list of curated links and bookmark their favorite ones. -In [part 4](/fullstack-nextjs-graphql-prisma-4-1k1kc83x3v), you added support for image uploads using AWS S3. In this part, you will set up the Prisma Data Proxy to handle database connections in a serverless environment and then deploy the app to Vercel. +In [part 4](/fullstack-nextjs-graphql-prisma-4-1k1kc83x3v), you added support for image uploads using AWS S3. In this part, you will walk through the original deployment flow for the series and see why connection pooling matters in serverless environments. ## Prerequisites @@ -154,10 +156,11 @@ You: - Built a GraphQL API using GraphQL Yoga and Pothos - Added authentication using Auth0 - Added image upload using AWS S3. -- Used the Prisma Data Proxy to handle database connection pooling +- Learned why serverless deployments need connection pooling and how Prisma approached that problem at the time - Deployed your Next.js application to Vercel +For a modern production setup, use [Prisma Accelerate](https://www.prisma.io/accelerate) together with the latest [Prisma Client deployment docs](https://www.prisma.io/docs/orm/prisma-client/deployment/serverless/deploy-to-vercel). + You can find the complete source code for the app on [GitHub](https://github.com/prisma/awesome-links). Feel free to raise issues or contribute to the repository if you find any bugs or want to make improvements. Feel free to reach out on [Twitter](https://twitter.com/thisismahmoud_) if you have any questions. - diff --git a/apps/blog/content/blog/getting-started-with-relay-modern-46f8de6bd6ec/index.mdx b/apps/blog/content/blog/getting-started-with-relay-modern-46f8de6bd6ec/index.mdx index 17bbc62c1d..7bb008ee38 100644 --- a/apps/blog/content/blog/getting-started-with-relay-modern-46f8de6bd6ec/index.mdx +++ b/apps/blog/content/blog/getting-started-with-relay-modern-46f8de6bd6ec/index.mdx @@ -5,6 +5,7 @@ date: "2017-06-18" authors: - "Nikolas Burk" metaTitle: "Getting Started with Relay Modern | Prisma" +metaDescription: "Follow a step-by-step tutorial for building an Instagram-style app with Relay Modern, GraphQL, and Create React App." metaImagePath: "/getting-started-with-relay-modern-46f8de6bd6ec/imgs/hero-703a89ee445ad7c79ca9de6acc53c27a8e49204f-900x482.png" heroImagePath: "/getting-started-with-relay-modern-46f8de6bd6ec/imgs/hero-703a89ee445ad7c79ca9de6acc53c27a8e49204f-900x482.png" heroImageAlt: "Getting Started with Relay Modern" diff --git a/apps/blog/content/blog/graphql-directive-permissions-authorization-made-easy-54c076b5368e/index.mdx b/apps/blog/content/blog/graphql-directive-permissions-authorization-made-easy-54c076b5368e/index.mdx index e6ecdde40c..fe0cdb4746 100644 --- a/apps/blog/content/blog/graphql-directive-permissions-authorization-made-easy-54c076b5368e/index.mdx +++ b/apps/blog/content/blog/graphql-directive-permissions-authorization-made-easy-54c076b5368e/index.mdx @@ -5,6 +5,7 @@ date: "2018-03-01" authors: - "Dennis Walsh" metaTitle: "GraphQL Directive Permissions — Authorization Made Easy | Prisma" +metaDescription: "Learn how GraphQL directive permissions provide a declarative way to implement authorization rules and protect data in GraphQL servers." metaImagePath: "/graphql-directive-permissions-authorization-made-easy-54c076b5368e/imgs/hero-210b2d6ae4e602480f1fee9860018b83891660ee-900x482.png" heroImagePath: "/graphql-directive-permissions-authorization-made-easy-54c076b5368e/imgs/hero-210b2d6ae4e602480f1fee9860018b83891660ee-900x482.png" heroImageAlt: "GraphQL Directive Permissions — Authorization Made Easy" diff --git a/apps/blog/content/blog/graphql-eu-18-eiw8bishe2di/index.mdx b/apps/blog/content/blog/graphql-eu-18-eiw8bishe2di/index.mdx index d090e205db..bd504bfda5 100644 --- a/apps/blog/content/blog/graphql-eu-18-eiw8bishe2di/index.mdx +++ b/apps/blog/content/blog/graphql-eu-18-eiw8bishe2di/index.mdx @@ -5,6 +5,7 @@ date: "2018-06-04" authors: - "Nikolas Burk" metaTitle: "GraphQL Europe 2018: the community comes together in Berlin" +metaDescription: "GraphQL Europe 2018 brought the community together in Berlin with talks, workshops, and discussions on the future of GraphQL." metaImagePath: "/graphql-eu-18-eiw8bishe2di/imgs/hero-aa07614217b24348635532e5f06f7be6230c9077-1200x630.png" heroImagePath: "/graphql-eu-18-eiw8bishe2di/imgs/hero-aa07614217b24348635532e5f06f7be6230c9077-1200x630.png" heroImageAlt: "GraphQL Europe 2018: The GraphQL community comes together in Berlin" diff --git a/apps/blog/content/blog/graphql-middleware-zie3iphithxy/index.mdx b/apps/blog/content/blog/graphql-middleware-zie3iphithxy/index.mdx index 945ae081d9..33d1f179a8 100644 --- a/apps/blog/content/blog/graphql-middleware-zie3iphithxy/index.mdx +++ b/apps/blog/content/blog/graphql-middleware-zie3iphithxy/index.mdx @@ -5,6 +5,7 @@ date: "2018-08-07" authors: - "Nikolas Burk" metaTitle: "GraphQL Middleware is Open Source - Library to Simplify Your Resolvers" +metaDescription: "GraphQL Middleware lets you run reusable logic around resolvers for cleaner authorization, logging, error handling, and code organization." metaImagePath: "/graphql-middleware-zie3iphithxy/imgs/hero-00450644ec19cc8a354555367848ee135f88561c-1200x630.png" heroImagePath: "/graphql-middleware-zie3iphithxy/imgs/hero-00450644ec19cc8a354555367848ee135f88561c-1200x630.png" heroImageAlt: "Open Sourcing GraphQL Middleware - Library to Simplify Your Resolvers" diff --git a/apps/blog/content/blog/graphql-schema-stitching-explained-schema-delegation-4c6caf468405/index.mdx b/apps/blog/content/blog/graphql-schema-stitching-explained-schema-delegation-4c6caf468405/index.mdx index 17340fb467..80bac854f4 100644 --- a/apps/blog/content/blog/graphql-schema-stitching-explained-schema-delegation-4c6caf468405/index.mdx +++ b/apps/blog/content/blog/graphql-schema-stitching-explained-schema-delegation-4c6caf468405/index.mdx @@ -5,6 +5,7 @@ date: "2017-12-12" authors: - "Nikolas Burk" metaTitle: "GraphQL Schema Stitching explained: Schema Delegation | Prisma" +metaDescription: "Understand GraphQL schema delegation and how schema stitching combines multiple services into a unified GraphQL API." metaImagePath: "/graphql-schema-stitching-explained-schema-delegation-4c6caf468405/imgs/hero-b01f755cd26e943970fb26c0395027a491baa9a0-720x480.jpg" heroImagePath: "/graphql-schema-stitching-explained-schema-delegation-4c6caf468405/imgs/hero-b01f755cd26e943970fb26c0395027a491baa9a0-720x480.jpg" heroImageAlt: "GraphQL Schema Stitching explained" diff --git a/apps/blog/content/blog/graphql-sdl-schema-definition-language-6755bcb9ce51/index.mdx b/apps/blog/content/blog/graphql-sdl-schema-definition-language-6755bcb9ce51/index.mdx index d19031dbc4..a054b490b4 100644 --- a/apps/blog/content/blog/graphql-sdl-schema-definition-language-6755bcb9ce51/index.mdx +++ b/apps/blog/content/blog/graphql-sdl-schema-definition-language-6755bcb9ce51/index.mdx @@ -5,6 +5,7 @@ date: "2017-05-01" authors: - "Nikolas Burk" metaTitle: "Learn more about the GraphQL SDL — Schema Definition Language" +metaDescription: "Learn the GraphQL Schema Definition Language (SDL) and how it is used to define types, fields, arguments, and relationships in GraphQL schemas." metaImagePath: "/graphql-sdl-schema-definition-language-6755bcb9ce51/imgs/hero-5d02853f87e521b189e585083a6fa90709310007-900x482.png" heroImagePath: "/graphql-sdl-schema-definition-language-6755bcb9ce51/imgs/hero-5d02853f87e521b189e585083a6fa90709310007-900x482.png" heroImageAlt: "GraphQL SDL " diff --git a/apps/blog/content/blog/graphql-server-basics-demystifying-the-info-argument-in-graphql-resolvers-6f26249f613a/index.mdx b/apps/blog/content/blog/graphql-server-basics-demystifying-the-info-argument-in-graphql-resolvers-6f26249f613a/index.mdx index 72fc3c0299..31103c5491 100644 --- a/apps/blog/content/blog/graphql-server-basics-demystifying-the-info-argument-in-graphql-resolvers-6f26249f613a/index.mdx +++ b/apps/blog/content/blog/graphql-server-basics-demystifying-the-info-argument-in-graphql-resolvers-6f26249f613a/index.mdx @@ -5,6 +5,7 @@ date: "2018-02-06" authors: - "Nikolas Burk" metaTitle: "GraphQL Server Basics: Demystifying the `info` Argument in Resolvers" +metaDescription: "Learn what the `info` argument in GraphQL resolvers contains and how it helps with selection sets, execution context, and server internals." metaImagePath: "/graphql-server-basics-demystifying-the-info-argument-in-graphql-resolvers-6f26249f613a/imgs/hero-53626cca942e63310e547d4bc3575d78fad23c84-720x479.png" heroImagePath: "/graphql-server-basics-demystifying-the-info-argument-in-graphql-resolvers-6f26249f613a/imgs/hero-53626cca942e63310e547d4bc3575d78fad23c84-720x479.png" heroImageAlt: "GraphQL Basics" diff --git a/apps/blog/content/blog/graphql-server-basics-the-network-layer-51d97d21861/index.mdx b/apps/blog/content/blog/graphql-server-basics-the-network-layer-51d97d21861/index.mdx index 1f8f668a5a..1572476287 100644 --- a/apps/blog/content/blog/graphql-server-basics-the-network-layer-51d97d21861/index.mdx +++ b/apps/blog/content/blog/graphql-server-basics-the-network-layer-51d97d21861/index.mdx @@ -5,6 +5,7 @@ date: "2017-11-28" authors: - "Nikolas Burk" metaTitle: "GraphQL Server Basics: The Network Layer | Prisma" +metaDescription: "Learn how the network layer controls request handling, transport, and execution flow in GraphQL server implementations." metaImagePath: "/graphql-server-basics-the-network-layer-51d97d21861/imgs/hero-244004bc5e6c3eb9d27aacabfb68d51510ea275e-900x429.png" heroImagePath: "/graphql-server-basics-the-network-layer-51d97d21861/imgs/hero-244004bc5e6c3eb9d27aacabfb68d51510ea275e-900x429.png" heroImageAlt: "GraphQL Server Basics" diff --git a/apps/blog/content/blog/graphql-server-basics-the-schema-ac5e2950214e/index.mdx b/apps/blog/content/blog/graphql-server-basics-the-schema-ac5e2950214e/index.mdx index 064c02b77c..ab87676663 100644 --- a/apps/blog/content/blog/graphql-server-basics-the-schema-ac5e2950214e/index.mdx +++ b/apps/blog/content/blog/graphql-server-basics-the-schema-ac5e2950214e/index.mdx @@ -5,6 +5,7 @@ date: "2017-11-14" authors: - "Nikolas Burk" metaTitle: "GraphQL Server Basics: GraphQL Schemas, TypeDefs & Resolvers | Prisma" +metaDescription: "Learn the basics of GraphQL schemas, type definitions, and resolvers, and how they fit together in GraphQL server development." metaImagePath: "/graphql-server-basics-the-schema-ac5e2950214e/imgs/hero-4b7f2edb1e23c9afd77908b058e6904ada648cc2-900x519.png" heroImagePath: "/graphql-server-basics-the-schema-ac5e2950214e/imgs/hero-4b7f2edb1e23c9afd77908b058e6904ada648cc2-900x519.png" heroImageAlt: "GraphQL Server Basics" diff --git a/apps/blog/content/blog/graphql-vs-firebase-496498546142/index.mdx b/apps/blog/content/blog/graphql-vs-firebase-496498546142/index.mdx index 61b4e5bd5c..27d4795f56 100644 --- a/apps/blog/content/blog/graphql-vs-firebase-496498546142/index.mdx +++ b/apps/blog/content/blog/graphql-vs-firebase-496498546142/index.mdx @@ -5,6 +5,7 @@ date: "2017-05-05" authors: - "Nikolas Burk" metaTitle: "Comparing GraphQL and Firebase | Prisma" +metaDescription: "Compare GraphQL and Firebase across data modeling, realtime features, backend flexibility, and tradeoffs for modern app development." metaImagePath: "/graphql-vs-firebase-496498546142/imgs/hero-c257f8c747d9610f835954d2fe2601bda2b0bff3-720x385.png" heroImagePath: "/graphql-vs-firebase-496498546142/imgs/hero-c257f8c747d9610f835954d2fe2601bda2b0bff3-720x385.png" heroImageAlt: "GraphQL vs Firebase" diff --git a/apps/blog/content/blog/helping-rapha-access-data-across-platforms-n3jfhtyu6rgn/index.mdx b/apps/blog/content/blog/helping-rapha-access-data-across-platforms-n3jfhtyu6rgn/index.mdx index 7a391f940c..847697cf9e 100644 --- a/apps/blog/content/blog/helping-rapha-access-data-across-platforms-n3jfhtyu6rgn/index.mdx +++ b/apps/blog/content/blog/helping-rapha-access-data-across-platforms-n3jfhtyu6rgn/index.mdx @@ -5,6 +5,7 @@ date: "2021-01-27" authors: - "Justin Ellingwood" metaTitle: "Learn how Prisma Helps Rapha Manage Their Mobile Application Data" +metaDescription: "Learn how Rapha uses Prisma to manage mobile application data and deliver consistent APIs across platforms and backend systems." metaImagePath: "/helping-rapha-access-data-across-platforms-n3jfhtyu6rgn/imgs/hero-b0f3d722a514f161e410fc12ccf0e00e562b5ecb-1692x852.jpg" heroImagePath: "/helping-rapha-access-data-across-platforms-n3jfhtyu6rgn/imgs/hero-b0f3d722a514f161e410fc12ccf0e00e562b5ecb-1692x852.jpg" heroImageAlt: "How Prisma Helps Rapha Manage Their Mobile Application Data" diff --git a/apps/blog/content/blog/how-do-graphql-remote-schemas-work-7118237c89d7/index.mdx b/apps/blog/content/blog/how-do-graphql-remote-schemas-work-7118237c89d7/index.mdx index f32eaee1e8..84519b4c77 100644 --- a/apps/blog/content/blog/how-do-graphql-remote-schemas-work-7118237c89d7/index.mdx +++ b/apps/blog/content/blog/how-do-graphql-remote-schemas-work-7118237c89d7/index.mdx @@ -5,6 +5,7 @@ date: "2017-12-06" authors: - "Nikolas Burk" metaTitle: "Learn how GraphQL remote schemas work? | Prisma" +metaDescription: "Learn how GraphQL remote schemas work and how schema stitching can combine data from multiple GraphQL services." metaImagePath: "/how-do-graphql-remote-schemas-work-7118237c89d7/imgs/hero-da5c4b73a3fd5b55d0301343f2b5698eedc64f9e-900x545.jpg" heroImagePath: "/how-do-graphql-remote-schemas-work-7118237c89d7/imgs/hero-da5c4b73a3fd5b55d0301343f2b5698eedc64f9e-900x545.jpg" heroImageAlt: "How do GraphQL remote schemas work?" diff --git a/apps/blog/content/blog/how-prisma-supports-transactions-x45s1d5l0ww1/index.mdx b/apps/blog/content/blog/how-prisma-supports-transactions-x45s1d5l0ww1/index.mdx index 04c0e68f64..912a7d88ae 100644 --- a/apps/blog/content/blog/how-prisma-supports-transactions-x45s1d5l0ww1/index.mdx +++ b/apps/blog/content/blog/how-prisma-supports-transactions-x45s1d5l0ww1/index.mdx @@ -6,6 +6,7 @@ authors: - "Nikolas Burk" - "Søren Bramer Schmidt" metaTitle: "Learn How Prisma Supports Database Transactions | Prisma" +metaDescription: "Learn how Prisma supports database transactions, the tradeoffs of different transaction patterns, and how Prisma's transaction capabilities have evolved." metaImagePath: "/how-prisma-supports-transactions-x45s1d5l0ww1/imgs/hero-644cfd40037273136103e964bfde80be554c43a7-1692x852.png" heroImagePath: "/how-prisma-supports-transactions-x45s1d5l0ww1/imgs/hero-644cfd40037273136103e964bfde80be554c43a7-1692x852.png" heroImageAlt: "How Prisma Supports Database Transactions" @@ -175,4 +176,3 @@ While we believe that the vast majority of use cases for database transactions c > **Update (July 1st, 2022)**: Since this article has been published, we have released [interactive transactions](https://www.prisma.io/docs/concepts/components/prisma-client/transactions#interactive-transactions-in-preview) which enables developers to use flexible, long-running transactions in Prisma Client. - diff --git a/apps/blog/content/blog/how-to-build-a-real-time-chat-with-graphql-subscriptions-and-apollo-d4004369b0d4/index.mdx b/apps/blog/content/blog/how-to-build-a-real-time-chat-with-graphql-subscriptions-and-apollo-d4004369b0d4/index.mdx index 60d1ac9c1d..f95ebd35a3 100644 --- a/apps/blog/content/blog/how-to-build-a-real-time-chat-with-graphql-subscriptions-and-apollo-d4004369b0d4/index.mdx +++ b/apps/blog/content/blog/how-to-build-a-real-time-chat-with-graphql-subscriptions-and-apollo-d4004369b0d4/index.mdx @@ -5,6 +5,7 @@ date: "2017-03-17" authors: - "Nikolas Burk" metaTitle: "Building a Real-Time Chat with GraphQL Subscriptions and Apollo" +metaDescription: "Build a real-time chat app with GraphQL subscriptions, Apollo, and live location updates on a shared map." metaImagePath: "/how-to-build-a-real-time-chat-with-graphql-subscriptions-and-apollo-d4004369b0d4/imgs/hero-c189aafe68785bbb4ff4f8c3e303c7f1ced92ea9-720x385.png" heroImagePath: "/how-to-build-a-real-time-chat-with-graphql-subscriptions-and-apollo-d4004369b0d4/imgs/hero-c189aafe68785bbb4ff4f8c3e303c7f1ced92ea9-720x385.png" heroImageAlt: "How to build a Real-Time Chat with GraphQL Subscriptions and Apollo" diff --git a/apps/blog/content/blog/how-to-use-create-react-app-with-graphql-apollo-62e574617cff/index.mdx b/apps/blog/content/blog/how-to-use-create-react-app-with-graphql-apollo-62e574617cff/index.mdx index 74b244f79f..c999fa84b0 100644 --- a/apps/blog/content/blog/how-to-use-create-react-app-with-graphql-apollo-62e574617cff/index.mdx +++ b/apps/blog/content/blog/how-to-use-create-react-app-with-graphql-apollo-62e574617cff/index.mdx @@ -5,6 +5,7 @@ date: "2017-03-27" authors: - "Nikolas Burk" metaTitle: "Using `create-react-app` with GraphQL & Apollo | Prisma" +metaDescription: "Learn how to build an Instagram-style app with Create React App, GraphQL, and Apollo." metaImagePath: "/how-to-use-create-react-app-with-graphql-apollo-62e574617cff/imgs/hero-d817c94b8e0c665d3296db3d2983002133e7a548-900x619.png" heroImagePath: "/how-to-use-create-react-app-with-graphql-apollo-62e574617cff/imgs/hero-d817c94b8e0c665d3296db3d2983002133e7a548-900x619.png" heroImageAlt: "GraphQL & Apollo" diff --git a/apps/blog/content/blog/how-to-wrap-a-rest-api-with-graphql-8bf3fb17547d/index.mdx b/apps/blog/content/blog/how-to-wrap-a-rest-api-with-graphql-8bf3fb17547d/index.mdx index fbb7c06e15..8d406e1907 100644 --- a/apps/blog/content/blog/how-to-wrap-a-rest-api-with-graphql-8bf3fb17547d/index.mdx +++ b/apps/blog/content/blog/how-to-wrap-a-rest-api-with-graphql-8bf3fb17547d/index.mdx @@ -5,6 +5,7 @@ date: "2018-02-22" authors: - "Nikolas Burk" metaTitle: "Wrap a REST API with GraphQL - A 3-step tutorial | Prisma" +metaDescription: "Learn how to wrap a REST API with GraphQL in three steps and expose a more flexible query interface for clients." metaImagePath: "/how-to-wrap-a-rest-api-with-graphql-8bf3fb17547d/imgs/hero-bf82758030919645523931bf645440e96386e06f-720x385.png" heroImagePath: "/how-to-wrap-a-rest-api-with-graphql-8bf3fb17547d/imgs/hero-bf82758030919645523931bf645440e96386e06f-720x385.png" heroImageAlt: "How to wrap a REST API with GraphQL - A 3-step tutorial" diff --git a/apps/blog/content/blog/improving-performance-with-apollo-query-batching-66455ea9d8b/index.mdx b/apps/blog/content/blog/improving-performance-with-apollo-query-batching-66455ea9d8b/index.mdx index ea082bf3c2..ef364afa13 100644 --- a/apps/blog/content/blog/improving-performance-with-apollo-query-batching-66455ea9d8b/index.mdx +++ b/apps/blog/content/blog/improving-performance-with-apollo-query-batching-66455ea9d8b/index.mdx @@ -6,6 +6,7 @@ authors: - "Søren Bramer Schmidt" - "Johannes Schickling" metaTitle: "How to Improve Performance with Apollo Query Batching | Prisma" +metaDescription: "Learn how Apollo query batching reduces network overhead and improves performance in complex GraphQL applications." metaImagePath: "/improving-performance-with-apollo-query-batching-66455ea9d8b/imgs/hero-f2e13f2e7910c8249ff5843c46423850eac4455d-1080x231.png" heroImagePath: "/improving-performance-with-apollo-query-batching-66455ea9d8b/imgs/hero-f2e13f2e7910c8249ff5843c46423850eac4455d-1080x231.png" heroImageAlt: "Improving Performance with Apollo Query Batching" diff --git a/apps/blog/content/blog/improving-prismas-release-process-yaey8deiwaex/index.mdx b/apps/blog/content/blog/improving-prismas-release-process-yaey8deiwaex/index.mdx index 09cc5ab817..67fda7b949 100644 --- a/apps/blog/content/blog/improving-prismas-release-process-yaey8deiwaex/index.mdx +++ b/apps/blog/content/blog/improving-prismas-release-process-yaey8deiwaex/index.mdx @@ -5,6 +5,7 @@ date: "2018-05-29" authors: - "Nikolas Burk" metaTitle: "Improving the Release Process | Prisma" +metaDescription: "Learn how Prisma's release process uses dedicated beta periods to improve quality while keeping new features shipping quickly." metaImagePath: "/improving-prismas-release-process-yaey8deiwaex/imgs/hero-d8dabd6ac06854c11615741cb43bbae8569cdd4e-1200x630.png" heroImagePath: "/improving-prismas-release-process-yaey8deiwaex/imgs/hero-d8dabd6ac06854c11615741cb43bbae8569cdd4e-1200x630.png" heroImageAlt: "New Release Process for Prisma" 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 442868d757..a1a336b5cc 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 @@ -5,6 +5,7 @@ date: "2019-02-07" authors: - "Tim Griesser" metaTitle: "GraphQL Nexus: Code-First GraphQL Server Development | Prisma" +metaDescription: "Meet GraphQL Nexus, a code-first library for building GraphQL servers with type-safe schemas and a better developer workflow." 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" diff --git a/apps/blog/content/blog/labelbox-simnycbotiok/index.mdx b/apps/blog/content/blog/labelbox-simnycbotiok/index.mdx index d3e263d58e..67faf2a95e 100644 --- a/apps/blog/content/blog/labelbox-simnycbotiok/index.mdx +++ b/apps/blog/content/blog/labelbox-simnycbotiok/index.mdx @@ -5,6 +5,7 @@ date: "2019-01-08" authors: - "Etel Sverdlov" metaTitle: "How Labelbox Supports Vast Machine Learning Needs | Prisma" +metaDescription: "Learn how Labelbox uses Prisma to support large-scale machine learning data workflows and manage millions of records more effectively." metaImagePath: "/labelbox-simnycbotiok/imgs/hero-4074c886a7303d113bad6cb6e96549dd817b8869-1200x630.png" heroImagePath: "/labelbox-simnycbotiok/imgs/hero-4074c886a7303d113bad6cb6e96549dd817b8869-1200x630.png" heroImageAlt: "Labelbox " diff --git a/apps/blog/content/blog/learn-typescript-a-pocketguide-tutorial-q329XmXQHUjz/index.mdx b/apps/blog/content/blog/learn-typescript-a-pocketguide-tutorial-q329XmXQHUjz/index.mdx index f03495734b..a8be0c3a0d 100644 --- a/apps/blog/content/blog/learn-typescript-a-pocketguide-tutorial-q329XmXQHUjz/index.mdx +++ b/apps/blog/content/blog/learn-typescript-a-pocketguide-tutorial-q329XmXQHUjz/index.mdx @@ -5,6 +5,7 @@ date: "2020-11-17" authors: - "Ryan Chenkie" metaTitle: "Learn TypeScript: A Pocketguide Tutorial | Prisma" +metaDescription: "Learn TypeScript's core features in a practical pocket guide covering types, interfaces, functions, and developer productivity." metaImagePath: "/learn-typescript-a-pocketguide-tutorial-q329XmXQHUjz/imgs/meta-ea7367ba686030645338459b4feaf9733da97717-1692x852.png" heroImagePath: "/learn-typescript-a-pocketguide-tutorial-q329XmXQHUjz/imgs/hero-ed0603d756c104c189e556f5a0a65cc59adde9b3-870x438.png" heroImageAlt: "Learn TypeScript: A Pocketguide Tutorial" 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 05ac3b76a6..fed0b50665 100644 --- a/apps/blog/content/blog/nestjs-prisma-authentication-7D056s1s0k3l/index.mdx +++ b/apps/blog/content/blog/nestjs-prisma-authentication-7D056s1s0k3l/index.mdx @@ -23,6 +23,8 @@ tags: Welcome to the fifth tutorial in this series about building a REST API with NestJS, Prisma and PostgreSQL! In this tutorial, you will learn how to implement JWT authentication in your NestJS REST API. +> **Update (May 2026):** This tutorial is still useful for the authentication flow, but if you're starting fresh you should pair it with the current [NestJS + Prisma guide](https://www.prisma.io/docs/guides/frameworks/nestjs), [Prisma ORM](https://www.prisma.io/orm), and [Prisma Postgres](https://www.prisma.io/postgres) or your existing PostgreSQL database. + ## Table Of Contents - [Introduction](#introduction) @@ -858,9 +860,9 @@ You can now login with the correct password and get a JWT in the response. In this chapter, you learned how to implement JWT authentication in your NestJS REST API. You also learned about salting passwords and integrating authentication with Swagger. -You can find the finished code for this tutorial in the [`end-authentication`](https://github.com/prisma/blog-backend-rest-api-nestjs-prisma/tree/end-authentication) 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). - +To keep the series moving, review the [Prisma getting started guide](https://www.prisma.io/docs/getting-started), explore [Prisma Migrate](https://www.prisma.io/docs/orm/prisma-migrate/getting-started) for schema changes, or use [Prisma Postgres](https://www.prisma.io/postgres) as the database for your next NestJS API. +You can find the finished code for this tutorial in the [`end-authentication`](https://github.com/prisma/blog-backend-rest-api-nestjs-prisma/tree/end-authentication) 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-error-handling-7D056s1kOop2/index.mdx b/apps/blog/content/blog/nestjs-prisma-error-handling-7D056s1kOop2/index.mdx index 6c70e1679a..4c26051de6 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 @@ -408,5 +408,6 @@ Congratulations! You took an existing NestJS application in this tutorial and le In this chapter you learned how to handle Prisma errors. But the techniques themselves are not limited to Prisma. You can use them to handle any type of error in your application. -You can find the finished code for this tutorial in the [`end-error-handling-part-3`](https://github.com/prisma/blog-backend-rest-api-nestjs-prisma/tree/end-error-handling-part-3) 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). +If you're continuing the series, the [Prisma getting started guide](https://www.prisma.io/docs/getting-started), [Prisma Migrate docs](https://www.prisma.io/docs/orm/prisma-migrate/getting-started), and [Prisma Postgres](https://www.prisma.io/postgres) are the best next resources for taking the app from tutorial to production-ready workflow. +You can find the finished code for this tutorial in the [`end-error-handling-part-3`](https://github.com/prisma/blog-backend-rest-api-nestjs-prisma/tree/end-error-handling-part-3) 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 9e65c2cad5..45e92382b7 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 @@ -21,6 +21,8 @@ tags: NestJS is one of the prominent Node.js frameworks, and it has recently gained a lot of developer love and traction. This article will teach you how to build a backend REST API with NestJS, Prisma, PostgreSQL and Swagger. +> **Update (May 2026):** If you're building this stack today, pair [Prisma ORM](https://www.prisma.io/orm) with [Prisma Postgres](https://www.prisma.io/postgres) or your existing PostgreSQL database, and keep the latest [NestJS + Prisma docs](https://www.prisma.io/docs/guides/frameworks/nestjs) open alongside this tutorial. + ## Table Of Contents - [Introduction](#introduction) @@ -151,7 +153,7 @@ This command will watch your files, automatically recompiling and reloading the You will be using PostgreSQL as the database for your NestJS application. This tutorial will show you how to install and run PostgreSQL on your machine through a Docker container. -> **Note**: If you don't want to use Docker, you can [set up a PostgreSQL instance natively](https://www.prisma.io/dataguide/postgresql/setting-up-a-local-postgresql-database) or get a [hosted PostgreSQL database on Heroku](https://dev.to/prisma/how-to-setup-a-free-postgresql-database-on-heroku-1dc1). +> **Note**: If you don't want to use Docker, you can [set up PostgreSQL locally](https://www.prisma.io/dataguide/postgresql/setting-up-a-local-postgresql-database) or start with [Prisma Postgres](https://www.prisma.io/postgres) for a managed Postgres database that works well with Prisma ORM. First, create a `docker-compose.yml` file in the main folder of your project: @@ -1001,7 +1003,6 @@ Congratulations! You've built a rudimentary REST API using NestJS. Throughout th One of the main takeaways from this tutorial is how easy it is to build a REST API with NestJS and Prisma. This is an incredibly productive stack for rapidly building well structured, type-safe and maintainable backend applications. +If you want to keep building from here, start with the [Prisma getting started guide](https://www.prisma.io/docs/getting-started), learn more about [Prisma Migrate](https://www.prisma.io/docs/orm/prisma-migrate/getting-started), or create a [Prisma Postgres](https://www.prisma.io/postgres) database for your next NestJS project. You can find the source code for this project on [GitHub](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-validation-7D056s1kOla1/index.mdx b/apps/blog/content/blog/nestjs-prisma-validation-7D056s1kOla1/index.mdx index 62e6eea0b4..311af8d088 100644 --- a/apps/blog/content/blog/nestjs-prisma-validation-7D056s1kOla1/index.mdx +++ b/apps/blog/content/blog/nestjs-prisma-validation-7D056s1kOla1/index.mdx @@ -397,8 +397,9 @@ Congratulations! In this tutorial, you took an existing REST API and: You might have noticed that NestJS heavily relies on decorators. This is a very intentional design choice. NestJS aims to improve code readability and modularity by heavily leveraging decorators for various kinds of [cross-cutting concerns](https://en.wikipedia.org/wiki/Cross-cutting_concern). As a result, controllers and service methods do not need to be bloated with boilerplate code for doing things like validation, caching, logging, etc. -You can find the finished code for this tutorial in the [end-validation branch](https://github.com/prisma/blog-backend-rest-api-nestjs-prisma/tree/end-validation) 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). +If you want to extend the project further, the [Prisma getting started guide](https://www.prisma.io/docs/getting-started) and [Prisma Migrate docs](https://www.prisma.io/docs/orm/prisma-migrate/getting-started) are good next steps, and [Prisma Postgres](https://www.prisma.io/postgres) is an easy way to stand up the database layer for follow-on work. +You can find the finished code for this tutorial in the [end-validation branch](https://github.com/prisma/blog-backend-rest-api-nestjs-prisma/tree/end-validation) 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/new-tooling-to-improve-your-graphql-workflows-7240c81e1ba3/index.mdx b/apps/blog/content/blog/new-tooling-to-improve-your-graphql-workflows-7240c81e1ba3/index.mdx index 240f13d728..db0804bc16 100644 --- a/apps/blog/content/blog/new-tooling-to-improve-your-graphql-workflows-7240c81e1ba3/index.mdx +++ b/apps/blog/content/blog/new-tooling-to-improve-your-graphql-workflows-7240c81e1ba3/index.mdx @@ -5,6 +5,7 @@ date: "2017-08-01" authors: - "Nikolas Burk" metaTitle: "New Tooling to Improve Your GraphQL Workflows | Prisma" +metaDescription: "Explore new GraphQL tooling like GraphQL Config and related libraries that improve project setup, tooling integration, and workflows." metaImagePath: "/new-tooling-to-improve-your-graphql-workflows-7240c81e1ba3/imgs/hero-a61300c6ae647f6e566843a176ed58109da8e65c-900x509.png" heroImagePath: "/new-tooling-to-improve-your-graphql-workflows-7240c81e1ba3/imgs/hero-a61300c6ae647f6e566843a176ed58109da8e65c-900x509.png" heroImageAlt: "New Tooling to Improve Your GraphQL Workflows" diff --git a/apps/blog/content/blog/optimizing-postgres-for-global-apps/index.mdx b/apps/blog/content/blog/optimizing-postgres-for-global-apps/index.mdx index ec6f96c048..6c0d5b4aba 100644 --- a/apps/blog/content/blog/optimizing-postgres-for-global-apps/index.mdx +++ b/apps/blog/content/blog/optimizing-postgres-for-global-apps/index.mdx @@ -5,6 +5,7 @@ date: "2025-06-19" authors: - "Tyler Benfield" metaTitle: "Optimizing Postgres for Global Apps" +metaDescription: "Learn why the Postgres wire protocol struggles in serverless and multi-region apps, and what patterns can improve performance for globally deployed systems." metaImagePath: "/optimizing-postgres-for-global-apps/imgs/meta-2d60d46aec9dc44a8e90072330ce14346817df5b-1266x711.png" heroImagePath: "/optimizing-postgres-for-global-apps/imgs/hero-8633a2e3d0da7dccae76ab2597e841ac444cbe7a-844x474.svg" tags: diff --git a/apps/blog/content/blog/organize-your-prisma-schema-with-multi-file-support/index.mdx b/apps/blog/content/blog/organize-your-prisma-schema-with-multi-file-support/index.mdx index a52f04ce42..d2b3c0392c 100644 --- a/apps/blog/content/blog/organize-your-prisma-schema-with-multi-file-support/index.mdx +++ b/apps/blog/content/blog/organize-your-prisma-schema-with-multi-file-support/index.mdx @@ -90,3 +90,9 @@ If you’d like to see how this feature looks in the real world, check out our [ ### We Want Your Feedback! We'd love to hear your thoughts on this new feature. Please share your feedback and any issues you may encounter by commenting on our dedicated [GitHub discussion](https://github.com/prisma/prisma/discussions/24413). + +## Where to go next + +- [Read the multi-file Prisma schema docs](https://www.prisma.io/docs/orm/prisma-schema/overview/location#multi-file-prisma-schema) for the current GA workflow and caveats. +- [Explore Prisma ORM](https://www.prisma.io/orm) if you're evaluating the broader developer workflow around schema design and generated types. +- [Pair it with Prisma Postgres](https://www.prisma.io/postgres) if you want a managed Postgres setup that works naturally with larger Prisma projects. diff --git a/apps/blog/content/blog/orm-6-10-0-new-features-for-prisma-postgres-remote-mcp-and-more/index.mdx b/apps/blog/content/blog/orm-6-10-0-new-features-for-prisma-postgres-remote-mcp-and-more/index.mdx index 3ca3b6e07d..8341858a51 100644 --- a/apps/blog/content/blog/orm-6-10-0-new-features-for-prisma-postgres-remote-mcp-and-more/index.mdx +++ b/apps/blog/content/blog/orm-6-10-0-new-features-for-prisma-postgres-remote-mcp-and-more/index.mdx @@ -160,4 +160,6 @@ We improved the `prisma migrate dev` command by optimizing the interactions with This week we released major improvement, both for Prisma Postgres and for Prisma ORM: Better local development, more elaborate UI workflows in VS Code, manual backups for Prisma Postgres, a remote MCP server to enable Prisma Postgres workflows in AI tools, a Rust-free preview of Prisma ORM for MySQL, PlanetScale and MSSQL, and more. +If you want to use those workflows in your own stack, start with [Prisma Postgres](https://www.prisma.io/postgres), try [Prisma Studio](https://www.prisma.io/studio), or connect your AI tooling through [Prisma's MCP page](https://www.prisma.io/mcp). + If you're using any of these features, we want to know what you think! Join the discussion on [Discord](https://pris.ly/discord), and ping us on [X](https://pris.ly/x). diff --git a/apps/blog/content/blog/orm-6-13-0-ci-cd-workflows-and-pgvector-for-prisma-postgres/index.mdx b/apps/blog/content/blog/orm-6-13-0-ci-cd-workflows-and-pgvector-for-prisma-postgres/index.mdx index 53c5d4d340..133caafece 100644 --- a/apps/blog/content/blog/orm-6-13-0-ci-cd-workflows-and-pgvector-for-prisma-postgres/index.mdx +++ b/apps/blog/content/blog/orm-6-13-0-ci-cd-workflows-and-pgvector-for-prisma-postgres/index.mdx @@ -258,4 +258,6 @@ The [Prisma Console](https://console.prisma.io/) got a visual refresh! Navigatio We’ve released a bunch of new features this week! Prisma Config and multi-schema support are now GA, and SQL view support is almost there. On the Prisma Postgres side, we're excited about `pgvector` support and the new Management API—great for CI/CD and preview databases. +If you're evaluating these workflows for a team, explore [Prisma Postgres](https://www.prisma.io/postgres), review [pricing](https://www.prisma.io/pricing), and check the [Management API docs](https://www.prisma.io/docs/postgres/introduction/management-api) for the CI/CD and preview-database setup. + Trying these out? We’d love your feedback! Join the conversation on [Discord](https://pris.ly/discord) or ping us on [X](https://pris.ly/x). diff --git a/apps/blog/content/blog/performance-benchmarks-comparing-query-latency-across-typescript-orms-and-databases/index.mdx b/apps/blog/content/blog/performance-benchmarks-comparing-query-latency-across-typescript-orms-and-databases/index.mdx index 2f8d851e4d..b854c3f939 100644 --- a/apps/blog/content/blog/performance-benchmarks-comparing-query-latency-across-typescript-orms-and-databases/index.mdx +++ b/apps/blog/content/blog/performance-benchmarks-comparing-query-latency-across-typescript-orms-and-databases/index.mdx @@ -235,3 +235,4 @@ Optimize captures all queries that are sent to your DB via Prisma ORM and gives You can find the results of our benchmark run on https://benchmarks.prisma.io. Check them out and let us know what you think on [X](https://pris.ly/x) and [Discord](https://pris.ly/discord). We're especially keen on hearing on how we can make this benchmark even more helpful to you and welcome suggestions for improvement! +If you want to act on the performance guidance from this article, explore [Prisma ORM](https://www.prisma.io/orm), review [Query Insights](https://www.prisma.io/query-insights), and see how [Prisma Postgres](https://www.prisma.io/postgres) can help with the database side of the performance story. diff --git a/apps/blog/content/blog/performance-engineering-aeduv0rei0jk/index.mdx b/apps/blog/content/blog/performance-engineering-aeduv0rei0jk/index.mdx index 508c3ba937..6e13607a80 100644 --- a/apps/blog/content/blog/performance-engineering-aeduv0rei0jk/index.mdx +++ b/apps/blog/content/blog/performance-engineering-aeduv0rei0jk/index.mdx @@ -5,6 +5,7 @@ date: "2018-08-21" authors: - "Nikolas Burk" metaTitle: "How We Constantly Improve the Performance of Prisma" +metaDescription: "See how Prisma's engineering team approaches performance with tooling, benchmarking, and practices for fast, predictable database workflows." metaImagePath: "/performance-engineering-aeduv0rei0jk/imgs/hero-e43f947aa769d0709b8e4af281e447028c0ec23e-1200x630.png" heroImagePath: "/performance-engineering-aeduv0rei0jk/imgs/hero-e43f947aa769d0709b8e4af281e447028c0ec23e-1200x630.png" heroImageAlt: "How We're Constantly Improving the Performance of Prisma" diff --git a/apps/blog/content/blog/prisma-2-beta-b7bcl0gd8d8e/index.mdx b/apps/blog/content/blog/prisma-2-beta-b7bcl0gd8d8e/index.mdx index 3928cc6bba..4c824416de 100644 --- a/apps/blog/content/blog/prisma-2-beta-b7bcl0gd8d8e/index.mdx +++ b/apps/blog/content/blog/prisma-2-beta-b7bcl0gd8d8e/index.mdx @@ -5,6 +5,7 @@ date: "2020-03-31" authors: - "Nikolas Burk" metaTitle: "Prisma 2.0 | Now in Beta: Type-safe Database Access with Prisma Client" +metaDescription: "Prisma 2 Beta introduced type-safe database access with Prisma Client, updated docs, and a clearer path toward production readiness." metaImagePath: "/prisma-2-beta-b7bcl0gd8d8e/imgs/meta-ef78167b288b460b14a81e0364434fc5c0caa204-1688x886.png" heroImagePath: "/prisma-2-beta-b7bcl0gd8d8e/imgs/hero-28cf1f43bc68b6f46097c6f654a0e77dfbf643ca-870x457.png" heroImageAlt: "Prisma 2.0 is now in beta" diff --git a/apps/blog/content/blog/prisma-6-8-0-release/index.mdx b/apps/blog/content/blog/prisma-6-8-0-release/index.mdx index 650bf07ebb..20e011e889 100644 --- a/apps/blog/content/blog/prisma-6-8-0-release/index.mdx +++ b/apps/blog/content/blog/prisma-6-8-0-release/index.mdx @@ -121,6 +121,8 @@ You can now deploy your Prisma Postgres instance in Singapore and bring your app We’re working to build a more powerful developer experience with Prisma 6.8.0 and beyond. From local-first database development and real-time documentation lookups to edge-ready Deno deployments, it's all designed to keep you coding, *not configuring*. +If you want to try the workflows from this release yourself, start with [Prisma Postgres](https://www.prisma.io/postgres), review [pricing](https://www.prisma.io/pricing), or learn how [Prisma's MCP tooling](https://www.prisma.io/mcp) can help with database setup inside AI-powered tools. + But we’re not stopping here and working to build more integrations and better tooling. Want to stay ahead of the curve? [Follow us on X](https://pris.ly/x?utm_source=website) for updates, tips, and previews of what's next. Got ideas, feedback, or just want to see what others are building? [Join our Discord community](https://pris.ly/discord?utm_source=website) to chat with fellow developers, ask questions, and be part of shaping the future of Prisma. 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 61987b0644..60c90b912f 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 @@ -172,4 +172,6 @@ More regions are on the way! Keep an [eye on X](https://pris.ly/x?utm_source=web Prisma 6.9.0 introduces several improvements: persistent local Prisma Postgres database instances, connecting to Prisma Postgres from any ORM or tool, a UI in VS Code, and a Rust-free preview of Prisma ORM for PostgreSQL and SQLite. +If you want to build on these workflows, explore [Prisma Postgres](https://www.prisma.io/postgres), try [Prisma Studio](https://www.prisma.io/studio), or learn how [Prisma's MCP tooling](https://www.prisma.io/mcp) fits into AI-assisted database workflows. + If you're using any of these features, we want your feedback. It helps us prioritize what to build next. Join the discussion on [Discord](https://pris.ly/discord), and get product updates on [X](https://pris.ly/x). diff --git a/apps/blog/content/blog/prisma-6-better-performance-more-flexibility-and-type-safe-sql/index.mdx b/apps/blog/content/blog/prisma-6-better-performance-more-flexibility-and-type-safe-sql/index.mdx index ec36e3f869..91c25d71b1 100644 --- a/apps/blog/content/blog/prisma-6-better-performance-more-flexibility-and-type-safe-sql/index.mdx +++ b/apps/blog/content/blog/prisma-6-better-performance-more-flexibility-and-type-safe-sql/index.mdx @@ -213,8 +213,9 @@ It is only thanks to _you_—our amazing community—that we have been able to c Thank you all so much for the ongoing support, your feedback and input that helps us make Prisma better every day. +If you want to dig deeper into the pieces from this release, explore [Prisma ORM](https://www.prisma.io/orm), learn more about [TypedSQL](https://www.prisma.io/typedsql), spin up [Prisma Postgres](https://www.prisma.io/postgres), or compare [pricing](https://www.prisma.io/pricing) for the database workflows we highlighted above. + If you have anything to share, be it a help request, an excited compliment, or constructive feedback, you can always reach us on our [Discord](https://pris.ly/discord) and on [X](https://pris.ly/x). > ✨ We're always trying to improve! If you've recently used Prisma ORM, we'd appreciate hearing your thoughts about your experience via this [2min survey](https://pris.ly/orm/survey/release-5-22). - diff --git a/apps/blog/content/blog/prisma-and-graphql-mfl5y2r7t49c/index.mdx b/apps/blog/content/blog/prisma-and-graphql-mfl5y2r7t49c/index.mdx index 8bfad0e161..53904dcdb9 100644 --- a/apps/blog/content/blog/prisma-and-graphql-mfl5y2r7t49c/index.mdx +++ b/apps/blog/content/blog/prisma-and-graphql-mfl5y2r7t49c/index.mdx @@ -6,6 +6,7 @@ authors: - "Nikolas Burk" - "Tim Suchanek" metaTitle: "How Prisma and GraphQL fit together | Prisma" +metaDescription: "Learn how Prisma and GraphQL fit together, where Prisma goes beyond GraphQL use cases, and how Prisma simplifies database workflows across APIs." metaImagePath: "/prisma-and-graphql-mfl5y2r7t49c/imgs/meta-fa8e2859efa37829166cc290e4913124ad4a99a0-1200x630.png" heroImagePath: "/prisma-and-graphql-mfl5y2r7t49c/imgs/hero-a170d7e275c2b415bc159d86a7a0eacf7b92acef-870x457.png" heroImageAlt: "How Prisma and GraphQL fit together" @@ -154,4 +155,3 @@ We are speccing all upcoming features in public (via GitHub issues and an [RFC]( **If you have any questions or comments, [please share them on Spectrum](https://spectrum.chat/prisma/general/how-prisma-and-graphql-fit-together~8c05c8f2-84c7-4ced-8f16-74d9798c71fa).** > [**We are hiring!**](https://www.prisma.io/careers) As you will find, one item on the roadmap is a full rewrite of the Prisma core in Rust. If you are a Rust engineer or just generally interested in highly technical challenges and open-source development, definitely check out our [jobs page](https://www.prisma.io/careers). - diff --git a/apps/blog/content/blog/prisma-client-preview-ahph4o1umail/index.mdx b/apps/blog/content/blog/prisma-client-preview-ahph4o1umail/index.mdx index 439ad20e96..b2ba58fe69 100644 --- a/apps/blog/content/blog/prisma-client-preview-ahph4o1umail/index.mdx +++ b/apps/blog/content/blog/prisma-client-preview-ahph4o1umail/index.mdx @@ -5,6 +5,7 @@ date: "2018-09-11" authors: - "Nikolas Burk" metaTitle: "Prisma Client in Preview: Simplified & Type-safe Database Access" +metaDescription: "Prisma Client introduced type-safe, auto-generated database access for application code and marked an important step toward Prisma's modern developer workflow." metaImagePath: "/prisma-client-preview-ahph4o1umail/imgs/hero-5f01c71f75711647bda65187ba3679acd63a63da-1200x630.png" heroImagePath: "/prisma-client-preview-ahph4o1umail/imgs/hero-5f01c71f75711647bda65187ba3679acd63a63da-1200x630.png" heroImageAlt: "Prisma Client (Preview): Simplified & Type-safe Database Access" @@ -238,4 +239,3 @@ To learn more about the Prisma client, check out the new [examples](https://gith
[Get started](https://v1.prisma.io/docs/1.34/get-started/01-setting-up-prisma-new-database-JAVASCRIPT-a002/) - diff --git a/apps/blog/content/blog/prisma-data-proxy-xb16ba0p21/index.mdx b/apps/blog/content/blog/prisma-data-proxy-xb16ba0p21/index.mdx index 1b967cf90f..3a2b185c6b 100644 --- a/apps/blog/content/blog/prisma-data-proxy-xb16ba0p21/index.mdx +++ b/apps/blog/content/blog/prisma-data-proxy-xb16ba0p21/index.mdx @@ -17,7 +17,7 @@ tags: Databases connection management in serverless functions is a major issue for many developers. The Prisma Data Proxy (Early Access) solves this problem by managing a connection pool. -> **Data Proxy will be discontinued on December 31, 2023.** For a seamless transition, we recommend exploring [Prisma Accelerate](https://www.prisma.io/data-platform/accelerate), which offers connection pooling, global caching and enables usage of Prisma Client in edge functions. +> **Update (May 2026):** Prisma Data Proxy has been discontinued. If you need connection pooling for serverless Prisma ORM apps today, start with [Prisma Accelerate](https://www.prisma.io/accelerate) and the current [deployment docs](https://www.prisma.io/docs/orm/prisma-client/deployment/serverless/deploy-to-vercel). If you're starting a new project and want a managed Postgres database plus Prisma ORM, take a look at [Prisma Postgres](https://www.prisma.io/postgres). ## Contents @@ -108,15 +108,11 @@ To learn how the Data Proxy works, check out [Daniel Norman's](https://twitter.c The Data Proxy also enables entirely new use cases, such as accessing a database from limited function environments such as [Cloudflare Workers](https://workers.cloudflare.com/). Follow the [guide](https://www.prisma.io/docs/guides/deployment/deployment-guides/deploying-to-cloudflare-workers) in our docs to learn more or watch the [demo](https://youtu.be/Ufe_tI_jJs8?t=380) from our recent "What's new in Prisma"-livestream. -## Let us know what you think +## Modern alternatives -You can try out the Prisma Data Proxy today by enabling it on the [Prisma Data Platform](https://cloud.prisma.io). - -
-
-[Try the Prisma Data Proxy](https://cloud.prisma.io) - - -We are hosting our first [Serverless Data Conference](https://www.prisma.io/serverless) on **November 18th** with fantastic speakers from companies like Vercel, Netlify, MongoDB and Cloudflare. Join us to learn more about the Data Proxy and other awesome features that are planned for the [Prisma Data Platform](https://cloud.prisma.io). +This article remains a useful explanation of why serverless workloads need connection pooling, but the product recommendation has changed. +- Use [Prisma Accelerate](https://www.prisma.io/accelerate) if you want managed connection pooling and caching for Prisma ORM. +- Use [Prisma Postgres](https://www.prisma.io/postgres) if you want a managed Postgres database that works well with Prisma ORM. +- Use the current [Prisma Client deployment docs](https://www.prisma.io/docs/orm/prisma-client/deployment/serverless/deploy-to-vercel) for up-to-date serverless deployment guidance. diff --git a/apps/blog/content/blog/prisma-insider-program/index.mdx b/apps/blog/content/blog/prisma-insider-program/index.mdx index 0aed5b11e5..4d7dec994b 100644 --- a/apps/blog/content/blog/prisma-insider-program/index.mdx +++ b/apps/blog/content/blog/prisma-insider-program/index.mdx @@ -1,5 +1,6 @@ --- title: "Join the Prisma Insider Program and Shape the Future of our Products" +metaDescription: "Join the Prisma Insider Program for early access to Prisma features, direct feedback opportunities, and a closer role in product development." slug: "prisma-insider-program" date: "2024-05-29" authors: diff --git a/apps/blog/content/blog/prisma-orm-6-6-0-esm-support-d1-migrations-and-prisma-mcp-server/index.mdx b/apps/blog/content/blog/prisma-orm-6-6-0-esm-support-d1-migrations-and-prisma-mcp-server/index.mdx index 276a4cfdfa..54c1fce414 100644 --- a/apps/blog/content/blog/prisma-orm-6-6-0-esm-support-d1-migrations-and-prisma-mcp-server/index.mdx +++ b/apps/blog/content/blog/prisma-orm-6-6-0-esm-support-d1-migrations-and-prisma-mcp-server/index.mdx @@ -148,4 +148,6 @@ npx prisma init --vibe "Cat meme generator" This is just the beginning, we have a lot more exciting things coming to Prisma ORM in the next weeks and months — check out our [3-months roadmap](https://github.com/prisma/prisma/issues/26592) to get a glimpse of what's next or catch up on the most recent developments in our [changelog](https://www.prisma.io/changelog) (such as the [performance improvements gained from our move from Rust to TypeScript](https://www.prisma.io/blog/rust-to-typescript-update-boosting-prisma-orm-performance)). +If you want to try the new workflows from this release, explore [Prisma ORM](https://www.prisma.io/orm), configure [Prisma's MCP tooling](https://www.prisma.io/mcp), or spin up [Prisma Postgres](https://www.prisma.io/postgres) for the database side of the experience. + Let us know on [X](https://pris.ly/x?utm_source=blog&utm_medium=conclusion) and our [Discord](https://pris.ly/discord?utm_source=blog&utm_medium=conclusion) what you think of this release — and follow us to stay in the loop with all the exciting things coming your way! 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 ef7d6527a4..f7422f8c94 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 @@ -5,6 +5,7 @@ date: "2025-07-24" authors: - "Nikolas Burk" 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: @@ -123,6 +124,8 @@ In the Rust-based version of Prisma ORM, you’ll find an engine binary file in The Rust-free version of Prisma ORM is approaching General Availability and we’re excited that you can now try it out for any major database supported by Prisma ORM. +If you want to test the new setup in your own stack, explore [Prisma ORM](https://www.prisma.io/orm), review the [Rust-free Prisma Client docs](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/no-rust-engine), or pair it with [Prisma Postgres](https://www.prisma.io/postgres) for the database layer. + Follow the instructions above or try one of our [ready-to-run example projects](https://github.com/prisma/prisma-examples/tree/latest/generator-prisma-client) (which also use the new, ESM-first `prisma-client` generator), for example: - [Next.js + Turborepo + Node.js](https://github.com/prisma/prisma-examples/tree/latest/generator-prisma-client/nextjs-starter-webpack-turborepo) @@ -132,4 +135,3 @@ Follow the instructions above or try one of our [ready-to-run example projects]( - [Deno Deploy](https://github.com/prisma/prisma-examples/tree/latest/generator-prisma-client/deno-deploy) Share your feedback [on Discord](https://pris.ly/discord) or ping us [on X](https://pris.ly/x). - diff --git a/apps/blog/content/blog/prisma-raises-4-5m-to-build-the-graphql-data-layer-for-all-databases-663484df0f60/index.mdx b/apps/blog/content/blog/prisma-raises-4-5m-to-build-the-graphql-data-layer-for-all-databases-663484df0f60/index.mdx index be5aff774a..e9cfb0c190 100644 --- a/apps/blog/content/blog/prisma-raises-4-5m-to-build-the-graphql-data-layer-for-all-databases-663484df0f60/index.mdx +++ b/apps/blog/content/blog/prisma-raises-4-5m-to-build-the-graphql-data-layer-for-all-databases-663484df0f60/index.mdx @@ -6,6 +6,7 @@ authors: - "Søren Bramer Schmidt" - "Johannes Schickling" metaTitle: "Prisma raises $4.5M to build a GraphQL access layer for all databases" +metaDescription: "Prisma raised $4.5M to build a GraphQL data layer for databases and shared the vision behind the company's next phase of product development." metaImagePath: "/prisma-raises-4-5m-to-build-the-graphql-data-layer-for-all-databases-663484df0f60/imgs/hero-73c2e03277f2cceb9f6cc435356d4a7ab822ed5b-1200x630.png" heroImagePath: "/prisma-raises-4-5m-to-build-the-graphql-data-layer-for-all-databases-663484df0f60/imgs/hero-73c2e03277f2cceb9f6cc435356d4a7ab822ed5b-1200x630.png" heroImageAlt: "Prisma raises $4.5M to build the GraphQL data layer for all databases" diff --git a/apps/blog/content/blog/prisma-raises-series-a-saks1zr7kip6/index.mdx b/apps/blog/content/blog/prisma-raises-series-a-saks1zr7kip6/index.mdx index dd5ee20a49..1f40dc167e 100644 --- a/apps/blog/content/blog/prisma-raises-series-a-saks1zr7kip6/index.mdx +++ b/apps/blog/content/blog/prisma-raises-series-a-saks1zr7kip6/index.mdx @@ -5,6 +5,7 @@ date: "2020-06-26" authors: - "Søren Bramer Schmidt" metaTitle: "Prisma Raises $12M Series A to Build Next Generation of Database Tools" +metaDescription: "Prisma raised $12M in Series A funding to keep building the next generation of database tools for application developers." metaImagePath: "/prisma-raises-series-a-saks1zr7kip6/imgs/meta-c3234082c86092e77a0b0a840c32a3c9a44f3754-1252x630.png" heroImageAlt: "Building construction" --- @@ -181,4 +182,3 @@ To try Prisma, you can follow the Quickstart or set up Prisma with your own data
{/* */} - diff --git a/apps/blog/content/blog/prisma-sql-server-support-preview-a4anl2gd8d3a/index.mdx b/apps/blog/content/blog/prisma-sql-server-support-preview-a4anl2gd8d3a/index.mdx index 6b60034c6a..d3c107db6e 100644 --- a/apps/blog/content/blog/prisma-sql-server-support-preview-a4anl2gd8d3a/index.mdx +++ b/apps/blog/content/blog/prisma-sql-server-support-preview-a4anl2gd8d3a/index.mdx @@ -5,6 +5,7 @@ date: "2020-10-28" authors: - "Daniel Norman" metaTitle: "Preview Support for Microsoft SQL Server | Prisma 2.10" +metaDescription: "Prisma 2.10 added preview support for Microsoft SQL Server, expanding Prisma's database coverage for teams building with SQL Server." metaImagePath: "/prisma-sql-server-support-preview-a4anl2gd8d3a/imgs/hero-a14944906d95712a04317e2c17e35cef35fac770-846x426.png" heroImagePath: "/prisma-sql-server-support-preview-a4anl2gd8d3a/imgs/hero-a14944906d95712a04317e2c17e35cef35fac770-846x426.png" heroImageAlt: "Prisma 2.10 Adds Preview Support for Microsoft SQL Server" @@ -93,4 +94,3 @@ We built this for you and are eager to hear your feedback!
[Get started with Prisma and SQL Server](https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-sqlserver) - diff --git a/apps/blog/content/blog/prisma-startup-program/index.mdx b/apps/blog/content/blog/prisma-startup-program/index.mdx index c2df5056b5..7a966e797f 100644 --- a/apps/blog/content/blog/prisma-startup-program/index.mdx +++ b/apps/blog/content/blog/prisma-startup-program/index.mdx @@ -5,6 +5,7 @@ date: "2025-02-07" authors: - "Shane Neubauer" metaTitle: "Helping Founders Scale Faster and Build Smarter" +metaDescription: "The Prisma Startups Program gives early-stage teams credits, guidance, and support to build faster with Prisma Postgres and scalable database workflows." metaImagePath: "/prisma-startup-program/imgs/meta-63addacd981bca37aca44f2cb8e46109fb7f00ce-1266x711.png" heroImagePath: "/prisma-startup-program/imgs/hero-8e11313115c9b81a2482973c2046e817f6a0b101-844x474.svg" heroImageAlt: "Announcing the Prisma Startup Program" diff --git a/apps/blog/content/blog/prisma-studio-3rtf78dg99fe/index.mdx b/apps/blog/content/blog/prisma-studio-3rtf78dg99fe/index.mdx index a20b1a4198..dd13ecc091 100644 --- a/apps/blog/content/blog/prisma-studio-3rtf78dg99fe/index.mdx +++ b/apps/blog/content/blog/prisma-studio-3rtf78dg99fe/index.mdx @@ -5,6 +5,7 @@ date: "2020-11-03" authors: - "Hervé Labas" metaTitle: "A Visual Interface for Your Database | Prisma Studio" +metaDescription: "Prisma Studio is a visual database browser for viewing and editing application data, with filtering, pagination, and relation-aware workflows for Prisma projects." metaImagePath: "/prisma-studio-3rtf78dg99fe/imgs/meta-6c7061054a1005d0cdfebd5dd8e353b56091beb9-1692x852.png" heroImagePath: "/prisma-studio-3rtf78dg99fe/imgs/hero-cdf9e7b1b90248dde0b35f13b0f30afdf859edeb-870x439.svg" heroImageAlt: "Prisma Studio - A Visual Interface for Your Database" @@ -159,4 +160,3 @@ npx prisma studio While Studio is currently focused to the most common tasks you may want to perform on your data, we're just getting started. We're eager to understand how Studio fits into your development workflow and how we can help you stay productive and confident while building data-powered applications. Feel free to join us on our [Slack](https://slack.prisma.io) in the [`#prisma-studio`](https://app.slack.com/client/T0MQBS8JG/C01ACF1DJ1M) channel for help and feedback, or [raise an issue on Github](https://github.com/prisma/studio/issues/new) if you run into problems. - diff --git a/apps/blog/content/blog/read-replicas-prisma-client-extension-f66prwk56wow/index.mdx b/apps/blog/content/blog/read-replicas-prisma-client-extension-f66prwk56wow/index.mdx index 11a3e9941b..91940e0797 100644 --- a/apps/blog/content/blog/read-replicas-prisma-client-extension-f66prwk56wow/index.mdx +++ b/apps/blog/content/blog/read-replicas-prisma-client-extension-f66prwk56wow/index.mdx @@ -108,7 +108,7 @@ To create a read replica, navigate to the [Neon dashboard](https://bit.ly/prisma @@ -122,7 +122,7 @@ Next, retrieve the connection string for the read replica you just created: diff --git a/apps/blog/content/blog/relay-moderns-connection-directive-1ecd8322f5c8/index.mdx b/apps/blog/content/blog/relay-moderns-connection-directive-1ecd8322f5c8/index.mdx index bd2269de12..a67654c483 100644 --- a/apps/blog/content/blog/relay-moderns-connection-directive-1ecd8322f5c8/index.mdx +++ b/apps/blog/content/blog/relay-moderns-connection-directive-1ecd8322f5c8/index.mdx @@ -5,6 +5,7 @@ date: "2017-06-02" authors: - "Nikolas Burk" metaTitle: "Relay Modern’s @connection directive | Prisma" +metaDescription: "Learn how Relay Modern's @connection directive works and how it helps manage pagination and cache behavior in client apps." metaImagePath: "/relay-moderns-connection-directive-1ecd8322f5c8/imgs/hero-d77cd8556b1e37826824d5a4feb83f16ea5b35b7-720x385.png" heroImagePath: "/relay-moderns-connection-directive-1ecd8322f5c8/imgs/hero-d77cd8556b1e37826824d5a4feb83f16ea5b35b7-720x385.png" heroImageAlt: "Relay Modern" diff --git a/apps/blog/content/blog/relay-vs-apollo-comparing-graphql-clients-for-react-apps-b40af58c1534/index.mdx b/apps/blog/content/blog/relay-vs-apollo-comparing-graphql-clients-for-react-apps-b40af58c1534/index.mdx index 9278d87356..052535cb0c 100644 --- a/apps/blog/content/blog/relay-vs-apollo-comparing-graphql-clients-for-react-apps-b40af58c1534/index.mdx +++ b/apps/blog/content/blog/relay-vs-apollo-comparing-graphql-clients-for-react-apps-b40af58c1534/index.mdx @@ -5,6 +5,7 @@ date: "2017-04-01" authors: - "Nikolas Burk" metaTitle: "Relay vs Apollo - Comparison of GraphQL clients for React apps" +metaDescription: "Compare Relay and Apollo for React GraphQL apps, including their tradeoffs in caching, tooling, and developer experience." metaImagePath: "/relay-vs-apollo-comparing-graphql-clients-for-react-apps-b40af58c1534/imgs/hero-bec4b18f6f63be54e12c792608ca39e7793a9216-900x482.png" heroImagePath: "/relay-vs-apollo-comparing-graphql-clients-for-react-apps-b40af58c1534/imgs/hero-bec4b18f6f63be54e12c792608ca39e7793a9216-900x482.png" heroImageAlt: "Relay vs Apollo " 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 1af3e9cdd1..ef1a705799 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 @@ -131,5 +131,6 @@ Our focus on robustness and stability from the last weeks paid off! This week wa Additionally, you can now create OAuth apps yourself, so you can offer Prisma Postgres to your own users. We're excited to see what you're going to build with it! -Let us know your thoughts, questions and feedback [on X](https://pris.ly/x) and join the conversation [on Discord](https://pris.ly/discord). +If you're ready to put these changes to work, explore [Prisma ORM](https://www.prisma.io/orm), review the [Prisma Client generation docs](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/generating-prisma-client), and try [Prisma Postgres](https://www.prisma.io/postgres) for the database workflows highlighted in this release. +Let us know your thoughts, questions and feedback [on X](https://pris.ly/x) and join the conversation [on Discord](https://pris.ly/discord). diff --git a/apps/blog/content/blog/state-of-prisma-2-december-rcrwcqyu655e/index.mdx b/apps/blog/content/blog/state-of-prisma-2-december-rcrwcqyu655e/index.mdx index c866b50559..dc2c23162d 100644 --- a/apps/blog/content/blog/state-of-prisma-2-december-rcrwcqyu655e/index.mdx +++ b/apps/blog/content/blog/state-of-prisma-2-december-rcrwcqyu655e/index.mdx @@ -5,6 +5,7 @@ date: "2019-12-06" authors: - "Nikolas Burk" metaTitle: "Update on the State of Prisma 2 (December 2019)" +metaDescription: "Get the December 2019 Prisma 2 roadmap update, including timeline changes and expected production-ready releases." metaImagePath: "/state-of-prisma-2-december-rcrwcqyu655e/imgs/hero-9f370997d51d3a43686ee7fc9e492dc1d54d197c-1200x630.png" heroImagePath: "/state-of-prisma-2-december-rcrwcqyu655e/imgs/hero-9f370997d51d3a43686ee7fc9e492dc1d54d197c-1200x630.png" heroImageAlt: "State of Prisma 2 (December 2019)" diff --git a/apps/blog/content/blog/studio-for-prisma-postgres-view-and-edit-your-data-online/index.mdx b/apps/blog/content/blog/studio-for-prisma-postgres-view-and-edit-your-data-online/index.mdx index 46d72fb26a..b4ba6de2b1 100644 --- a/apps/blog/content/blog/studio-for-prisma-postgres-view-and-edit-your-data-online/index.mdx +++ b/apps/blog/content/blog/studio-for-prisma-postgres-view-and-edit-your-data-online/index.mdx @@ -49,6 +49,8 @@ Simply navigate to the new **Studio** tab in the sidebar of your project environ If you’re not using Prisma Postgres, don’t sweat — Prisma Studio is coming to Console for other databases soon! +If you want to keep exploring, visit [Prisma Studio](https://www.prisma.io/studio), learn how to get started in the [Studio docs](https://www.prisma.io/docs/studio/getting-started), create a new [Prisma Postgres](https://www.prisma.io/postgres) database to try the online workflow yourself, or review [pricing](https://www.prisma.io/pricing) before rolling it out more broadly. + In the meantime, let us know on [X](https://pris.ly/x) and [Discord](https://pris.ly/discord) what you think of Studio for Prisma Postgres and if there is anything else that you’d like to be able to do with it? We look forward to hearing from you! diff --git a/apps/blog/content/blog/the-guild-takes-over-oss-libraries-vvluy2i4uevs/index.mdx b/apps/blog/content/blog/the-guild-takes-over-oss-libraries-vvluy2i4uevs/index.mdx index ec32e7075a..02c881774e 100644 --- a/apps/blog/content/blog/the-guild-takes-over-oss-libraries-vvluy2i4uevs/index.mdx +++ b/apps/blog/content/blog/the-guild-takes-over-oss-libraries-vvluy2i4uevs/index.mdx @@ -5,6 +5,7 @@ date: "2019-08-14" authors: - "Uri Goldshtein" metaTitle: "Prisma Hands The Guild the Maintenance of the GraphQL CLI" +metaDescription: "The Guild took over development of GraphQL CLI and related libraries, helping ensure their continued growth and maintenance." metaImagePath: "/the-guild-takes-over-oss-libraries-vvluy2i4uevs/imgs/hero-9955207df52f4ccd9dd7985866c84af54806940a-1200x630.png" heroImagePath: "/the-guild-takes-over-oss-libraries-vvluy2i4uevs/imgs/hero-9955207df52f4ccd9dd7985866c84af54806940a-1200x630.png" heroImageAlt: "The Guild Takes over Development of the GraphQL CLI & Other Libraries" 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 5ecd5c7d72..f09b1a6466 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 @@ -435,6 +435,8 @@ Prisma Next is an open look at where we’re headed. We’re publishing a [Prisma 7 roadmap alongside this post](https://pris.ly/p7-roadmap) so you can see what’s ahead. In parallel, we’ll keep iterating on Prisma Next in the open. When it’s ready for general use, Prisma Next becomes **Prisma 8**. +If you're shipping today while following this work, start with [Prisma ORM](https://www.prisma.io/orm), use [Prisma Postgres](https://www.prisma.io/postgres) for the database layer, and keep an eye on [Prisma's MCP tooling](https://www.prisma.io/mcp) if agent-assisted development is already part of your workflow. + ## We’re working in the open Today we’re publishing the Prisma Next repo so you can follow the work as it happens. Even though it's early and not yet production-ready, we’re sharing it now so the community can see where we’re headed and help shape the design. 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 ebcfe77f4d..c15126c5b5 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 @@ -5,6 +5,7 @@ date: "2019-01-31" authors: - "Nikolas Burk" metaTitle: "The Problems of \"Schema-First\" GraphQL Server Development | Prisma" +metaDescription: "Explore the limitations of schema-first GraphQL server development and the case for code-first alternatives like GraphQL Nexus." 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" diff --git a/apps/blog/content/blog/top-5-reasons-to-use-graphql-b60cfa683511/index.mdx b/apps/blog/content/blog/top-5-reasons-to-use-graphql-b60cfa683511/index.mdx index de8984d012..0ecc829706 100644 --- a/apps/blog/content/blog/top-5-reasons-to-use-graphql-b60cfa683511/index.mdx +++ b/apps/blog/content/blog/top-5-reasons-to-use-graphql-b60cfa683511/index.mdx @@ -5,6 +5,7 @@ date: "2018-03-20" authors: - "Nikolas Burk" metaTitle: "5 Top Reasons Why and How to Use GraphQL | Prisma" +metaDescription: "Learn five reasons to use GraphQL and how it can improve flexibility, developer experience, and API efficiency." metaImagePath: "/top-5-reasons-to-use-graphql-b60cfa683511/imgs/hero-646eacc9490ba67cda9493f1e1c959da2090a2ee-1350x900.png" heroImagePath: "/top-5-reasons-to-use-graphql-b60cfa683511/imgs/hero-646eacc9490ba67cda9493f1e1c959da2090a2ee-1350x900.png" heroImageAlt: "Reasons to use GraphQL | Top 5 Reasons Why and How to use GraphQL" 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 03aeae76da..158c68f77b 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 @@ -5,6 +5,7 @@ date: "2025-04-30" authors: - "Nikolas Burk" 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: diff --git a/apps/blog/content/blog/tutorial-building-a-realtime-graphql-server-with-subscriptions-2758cfc6d427/index.mdx b/apps/blog/content/blog/tutorial-building-a-realtime-graphql-server-with-subscriptions-2758cfc6d427/index.mdx index aabde46010..d2cd15f868 100644 --- a/apps/blog/content/blog/tutorial-building-a-realtime-graphql-server-with-subscriptions-2758cfc6d427/index.mdx +++ b/apps/blog/content/blog/tutorial-building-a-realtime-graphql-server-with-subscriptions-2758cfc6d427/index.mdx @@ -5,6 +5,7 @@ date: "2018-04-26" authors: - "Nikolas Burk" metaTitle: "Build a Realtime GraphQL Server with Subscriptions | Prisma" +metaDescription: "Learn how to build a realtime GraphQL server with subscriptions so clients can receive live event updates." metaImagePath: "/tutorial-building-a-realtime-graphql-server-with-subscriptions-2758cfc6d427/imgs/hero-781be5bd42b889008892c3564dc6bc915c33581f-2000x1050.png" heroImagePath: "/tutorial-building-a-realtime-graphql-server-with-subscriptions-2758cfc6d427/imgs/hero-781be5bd42b889008892c3564dc6bc915c33581f-2000x1050.png" heroImageAlt: "Tutorial: Building a Realtime GraphQL Server with Subscriptions" diff --git a/apps/blog/content/blog/tutorial-render-props-in-react-apollo-2-1-199e9e2bd01e/index.mdx b/apps/blog/content/blog/tutorial-render-props-in-react-apollo-2-1-199e9e2bd01e/index.mdx index 6a463b098c..6558681b7d 100644 --- a/apps/blog/content/blog/tutorial-render-props-in-react-apollo-2-1-199e9e2bd01e/index.mdx +++ b/apps/blog/content/blog/tutorial-render-props-in-react-apollo-2-1-199e9e2bd01e/index.mdx @@ -5,6 +5,7 @@ date: "2018-03-27" authors: - "Nikolas Burk" metaTitle: "How to Render Props in React Apollo 2.1 | Prisma" +metaDescription: "Learn how to use the React Apollo 2.1 render props API in a full-stack GraphQL tutorial." metaImagePath: "/tutorial-render-props-in-react-apollo-2-1-199e9e2bd01e/imgs/meta-e2111dc3b582d8715d9835a48db4976a57f2b859-1200x630.png" heroImagePath: "/tutorial-render-props-in-react-apollo-2-1-199e9e2bd01e/imgs/hero-f130ef1313ac6bbb52267050f3cbc5bc83839911-870x457.svg" heroImageAlt: "Tutorial: Render Props in React Apollo 2.1" diff --git a/apps/blog/content/blog/tutorial-using-create-react-native-app-with-graphql-apollo-e630aee3ae1e/index.mdx b/apps/blog/content/blog/tutorial-using-create-react-native-app-with-graphql-apollo-e630aee3ae1e/index.mdx index 3aa0090184..45efb4465e 100644 --- a/apps/blog/content/blog/tutorial-using-create-react-native-app-with-graphql-apollo-e630aee3ae1e/index.mdx +++ b/apps/blog/content/blog/tutorial-using-create-react-native-app-with-graphql-apollo-e630aee3ae1e/index.mdx @@ -5,6 +5,7 @@ date: "2017-03-28" authors: - "Nikolas Burk" metaTitle: "Using `create-react-native-app` with GraphQL & Apollo | Prisma" +metaDescription: "Learn how to build an Instagram-style React Native app with Create React Native App, GraphQL, and Apollo." metaImagePath: "/tutorial-using-create-react-native-app-with-graphql-apollo-e630aee3ae1e/imgs/hero-a83dd1e60398f33faecaec5abe5adc37027f5811-400x711.png" heroImagePath: "/tutorial-using-create-react-native-app-with-graphql-apollo-e630aee3ae1e/imgs/hero-a83dd1e60398f33faecaec5abe5adc37027f5811-400x711.png" heroImageAlt: "GraphQL & Apollo" 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 935011c7ee..257e1efa40 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 @@ -5,6 +5,7 @@ date: "2019-02-12" authors: - "Nikolas Burk" metaTitle: "How to Use GraphQL Nexus with a Database | Prisma" +metaDescription: "Learn how to connect GraphQL Nexus to a database with Prisma Client and the Nexus Prisma plugin." 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" diff --git a/apps/blog/content/blog/watch-prisma-day-talks-z11sg6ipb3i1/index.mdx b/apps/blog/content/blog/watch-prisma-day-talks-z11sg6ipb3i1/index.mdx index cb7ee6ae02..117d205ecb 100644 --- a/apps/blog/content/blog/watch-prisma-day-talks-z11sg6ipb3i1/index.mdx +++ b/apps/blog/content/blog/watch-prisma-day-talks-z11sg6ipb3i1/index.mdx @@ -5,6 +5,7 @@ date: "2019-07-11" authors: - "Etel Sverdlov" metaTitle: "Watch recordings of the talks from Prisma Day 2019 | Prisma" +metaDescription: "Watch the Prisma Day 2019 talks and explore videos and photos from Prisma's conference on databases and modern app development." metaImagePath: "/watch-prisma-day-talks-z11sg6ipb3i1/imgs/meta-fea8ecef646b6bf26d0612835a9125136d5d1b90-1200x630.png" heroImagePath: "/watch-prisma-day-talks-z11sg6ipb3i1/imgs/hero-e1f0832d806403801afbd482ec812d046bfcf8a5-870x457.png" heroImageAlt: "Prisma Day videos available" diff --git a/apps/blog/content/blog/why-prisma-orm-checks-types-faster-than-drizzle/index.mdx b/apps/blog/content/blog/why-prisma-orm-checks-types-faster-than-drizzle/index.mdx index 442e5cd28f..6b41db510d 100644 --- a/apps/blog/content/blog/why-prisma-orm-checks-types-faster-than-drizzle/index.mdx +++ b/apps/blog/content/blog/why-prisma-orm-checks-types-faster-than-drizzle/index.mdx @@ -349,5 +349,7 @@ Note that Drizzle's 1.0.0 beta significantly reduces schema instantiations to ~5 You can explore all the benchmark files in our [open-source repo](https://github.com/prisma/type-benchmarks/blob/main/benchmark.md). If you are building a large, complex app where developer velocity and CI performance matter, Prisma ORM’s approach scales further and faster. Most importantly, type performance is developer experience. The faster your editor responds, the quicker your feedback loop and the happier your developers. + +If you want to see how that workflow looks in practice, explore [Prisma ORM](https://www.prisma.io/orm), review how [Prisma Client generation works](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/generating-prisma-client), and compare it with [TypedSQL](https://www.prisma.io/typedsql) for the cases where you need lower-level control. > We used Drizzle ORM versions `0.44.4` (stable) and `1.0.0-beta.1-2acab7f` and compared them against Prisma ORM `6.15.0`. diff --git a/apps/blog/next.config.mjs b/apps/blog/next.config.mjs index 04befc1642..873525e9a3 100644 --- a/apps/blog/next.config.mjs +++ b/apps/blog/next.config.mjs @@ -192,6 +192,10 @@ const securityHeaders = [ key: "Referrer-Policy", value: "strict-origin-when-cross-origin", }, + { + key: "Strict-Transport-Security", + value: "max-age=63072000; includeSubDomains; preload", + }, ]; const allowedDevOrigins = (process.env.ALLOWED_DEV_ORIGINS ?? "localhost,127.0.0.1,192.168.1.48") diff --git a/apps/blog/src/app/(blog)/[slug]/page.tsx b/apps/blog/src/app/(blog)/[slug]/page.tsx index fbcf806972..068b22171a 100644 --- a/apps/blog/src/app/(blog)/[slug]/page.tsx +++ b/apps/blog/src/app/(blog)/[slug]/page.tsx @@ -9,7 +9,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 { + getBaseUrl, + withBlogBasePath, + withBlogBasePathForImageSrc, +} from "@/lib/url"; import Link from "next/link"; import type { Metadata } from "next"; @@ -48,6 +52,10 @@ interface BlogPostingSchema { publisher: { "@type": "Organization"; name: string; + logo: { + "@type": "ImageObject"; + url: string; + }; }; } @@ -65,17 +73,25 @@ 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 @@ -86,7 +102,8 @@ function getBlogPostingJsonLd(page: ReturnType): BlogPostin 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", @@ -98,6 +115,10 @@ function getBlogPostingJsonLd(page: ReturnType): BlogPostin publisher: { "@type": "Organization", name: "Prisma", + logo: { + "@type": "ImageObject", + url: "https://www.prisma.io/logo.png", + } }, }; @@ -131,7 +152,9 @@ function getBlogPostingJsonLd(page: ReturnType): BlogPostin return jsonLd; } -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]); @@ -148,7 +171,10 @@ export default async function Page(props: { params: Promise<{ slug: string }> })
{/* Title + meta */}
- + ← Back to Blog

@@ -175,9 +201,9 @@ export default async function Page(props: { params: Promise<{ slug: string }> }) className=" transition-colors border capitalize - border-stroke-neutral-strong + border-stroke-neutral-strong bg-transparent - text-foreground-neutral-weak + text-foreground-neutral-weak hover:bg-background-ppg/50 hover:border-stroke-ppg/50 hover:text-foreground-ppg" diff --git a/apps/blog/src/app/(blog)/page.tsx b/apps/blog/src/app/(blog)/page.tsx index 64796dba59..2b1179b444 100644 --- a/apps/blog/src/app/(blog)/page.tsx +++ b/apps/blog/src/app/(blog)/page.tsx @@ -1,81 +1,27 @@ import { blog, getPageImage } from "@/lib/source"; -import { BlogGrid, type BlogCardItem } from "@/components/BlogGrid"; -import { CategoryTagFilter } from "@/components/CategoryTagFilter"; +import { type BlogCardItem } from "@/components/BlogGrid"; import { BLOG_HOME_DESCRIPTION, BLOG_HOME_TITLE } from "@/lib/blog-metadata"; import type { Metadata } from "next"; import { withBlogBasePath, withBlogBasePathForImageSrc } from "@/lib/url"; -import { - Pagination, - PaginationContent, - PaginationEllipsis, - PaginationItem, - PaginationLink, - PaginationNext, - PaginationPrevious, -} from "@prisma/eclipse"; -import { LargeSearchToggle } from "@/components/search-toggle"; - -const SHOW_ALL = "show-all"; -const PAGE_SIZE = 12; - -type BlogHomeSearchParams = { - page?: string | string[]; - tag?: string | string[]; -}; - -function getFirstQueryValue(value?: string | string[]): string | undefined { - if (Array.isArray(value)) { - return value[0]; - } - - return value; -} - -function parsePage(value: string | undefined): number { - const parsed = Number.parseInt(value ?? "1", 10); - return Number.isNaN(parsed) || parsed < 1 ? 1 : parsed; -} - -function buildBlogHref(tag: string, page: number): string { - const params = new URLSearchParams(); - - if (tag !== SHOW_ALL) { - params.set("tag", tag); - } - - if (page > 1) { - params.set("page", String(page)); - } - - const query = params.toString(); - const basePath = withBlogBasePath("/"); - return query ? `${basePath}?${query}` : basePath; -} - -function getPaginationSequence(totalPages: number, currentPage: number) { - if (totalPages <= 7) { - return Array.from({ length: totalPages }, (_, index) => index + 1); - } - - const pages: Array = [1]; - const start = Math.max(2, currentPage - 1); - const end = Math.min(totalPages - 1, currentPage + 1); - - if (start > 2) { - pages.push("ellipsis"); - } - - for (let page = start; page <= end; page += 1) { - pages.push(page); - } - - if (end < totalPages - 1) { - pages.push("ellipsis"); - } - - pages.push(totalPages); - return pages; -} +import { Suspense } from "react"; +import { BlogHomeClient } from "@/components/BlogHomeClient"; + +/** + * Opt into full static rendering for this route. + * + * Previously, the page accepted `searchParams` as a Server Component prop which + * forced Next.js into dynamic rendering and emitted: + * Cache-Control: private, no-cache, no-store + * + * By removing `searchParams` from this component and delegating URL-based + * filtering/pagination to the `BlogHomeClient` client component (which reads + * `useSearchParams()` after hydration), the page is now statically rendered and + * receives proper public cache headers from Next.js / Vercel's edge network. + * + * All post data is passed as props so the RSC payload ships the full dataset — + * no extra network round-trip is needed during client hydration. + */ +export const revalidate = false; export async function generateMetadata(): Promise { return { @@ -100,12 +46,7 @@ export async function generateMetadata(): Promise { }; } -export default async function BlogHome({ - searchParams, -}: { - searchParams?: Promise | BlogHomeSearchParams; -}) { - const resolvedSearchParams = (await Promise.resolve(searchParams)) ?? {}; +export default async function BlogHome() { const posts = blog.getPages().sort((a, b) => { const aTime = a.data.date instanceof Date @@ -127,7 +68,6 @@ export default async function BlogHome({ const items: BlogCardItem[] = posts.map((post) => { const data = post.data as any; - // Safely convert date to ISO string with validation let dateISO = ""; if (data.date) { try { @@ -135,8 +75,7 @@ export default async function BlogHome({ if (!isNaN(dateObj.getTime())) { dateISO = dateObj.toISOString(); } - } catch (error) { - // If date conversion fails, fall back to empty string + } catch { dateISO = ""; } } @@ -156,90 +95,26 @@ export default async function BlogHome({ 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 validTags = new Set(uniqueTags); - const tagFromQuery = getFirstQueryValue(resolvedSearchParams.tag); - const currentCategory = tagFromQuery && validTags.has(tagFromQuery) ? tagFromQuery : SHOW_ALL; - const filteredItems = - currentCategory === SHOW_ALL - ? items - : items.filter((item) => item.tags?.includes(currentCategory)); - - const totalPages = Math.max(1, Math.ceil(filteredItems.length / PAGE_SIZE)); - const pageFromQuery = parsePage(getFirstQueryValue(resolvedSearchParams.page)); - const currentPage = Math.max(1, Math.min(pageFromQuery, 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); - - const paginationSequence = getPaginationSequence(totalPages, currentPage); return (

Blog

-
-
- - -
- - - -
- {totalPages > 1 ? ( - - - - - - {paginationSequence.map((entry, index) => ( - - {entry === "ellipsis" ? ( - - ) : ( - - {entry} - - )} - - ))} - - - - - - ) : null} -
-
+ {/* + * Suspense is required here because BlogHomeClient uses useSearchParams(). + * During static pre-rendering Next.js renders the fallback; after hydration + * the client component takes over and applies URL-driven filtering instantly + * since all post data is already present in the RSC payload. + */} + }> + +
); } diff --git a/apps/blog/src/app/layout.tsx b/apps/blog/src/app/layout.tsx index 0a59c6dc1c..5bb1f91448 100644 --- a/apps/blog/src/app/layout.tsx +++ b/apps/blog/src/app/layout.tsx @@ -1,4 +1,5 @@ import { Provider } from "@/components/provider"; +import { createBlogStructuredData } from "@/lib/structured-data"; import { getBaseUrl } from "@/lib/url"; import "./global.css"; import { Inter, Barlow } from "next/font/google"; @@ -6,6 +7,7 @@ import type { Metadata } from "next"; import Script from "next/script"; import { BLOG_HOME_DESCRIPTION, BLOG_HOME_TITLE } from "@/lib/blog-metadata"; import { FontAwesomeScript as EclipseFA } from "@prisma/eclipse"; +import { JsonLd } from "@prisma-docs/ui/components/json-ld"; const inter = Inter({ subsets: ["latin"], @@ -24,11 +26,30 @@ export const metadata: Metadata = { description: BLOG_HOME_DESCRIPTION, }; +const blogStructuredData = createBlogStructuredData(); + export default function Layout({ children }: LayoutProps<"/">) { return ( - + - - // [!code ++] - - -``` - -Finally, add a server-side check to redirect authenticated users away from this page. If a user is already signed in, they should be redirected to the dashboard instead. - -```html title="src/pages/sign-up/index.astro" ---- -export const prerender = false; - -if (Astro.locals.user?.id) return Astro.redirect("/dashboard"); // [!code ++] ---- - - - - - - Sign Up - - -
-

Sign Up

-
- - - - -
-

Already have an account? Sign in here.

-
- - - -``` - -### 7.2. Sign in page - -This page allows existing users to authenticate. Start with the basic HTML structure in `src/pages/sign-in/index.astro`. - -```html title="src/pages/sign-in/index.astro" ---- -export const prerender = false; ---- - - - - - - Sign In - - -
-

Sign In

-
- - -``` - -Add a form with input fields for email and password. This form will collect the user's credentials. - -```html title="src/pages/sign-in/index.astro" ---- -export const prerender = false; ---- - - - - - - Sign In - - -
-

Sign In

-
- // [!code ++] // [!code ++] - // [!code ++] - // [!code ++] -
- // [!code ++] -

Don't have an account? Sign up here.

- // [!code ++] -
- - -``` - -Now add a script to handle form submission. Import the `authClient` and add an event listener that prevents default submission, extracts the form data, and calls the Better Auth sign-in method. - -```html title="src/pages/sign-in/index.astro" ---- -export const prerender = false; ---- - - - - - - Sign In - - -
-

Sign In

-
- - - -
-

Don't have an account? Sign up here.

-
- - // [!code ++] - - -``` - -Finally, add a server-side check to redirect authenticated users away from this page. If a user is already signed in, they should be redirected to the dashboard instead. - -```html title="src/pages/sign-in/index.astro" ---- -export const prerender = false; - -if (Astro.locals.user?.id) return Astro.redirect("/dashboard"); // [!code ++] ---- - - - - - - Sign In - - -
-

Sign In

-
- - - -
-

Don't have an account? Sign up here.

-
- - - -``` - -### 7.3. Dashboard page - -This is the protected page for authenticated users. Start with the basic HTML structure in `src/pages/dashboard/index.astro`. - -```html title="src/pages/dashboard/index.astro" ---- -export const prerender = false; ---- - - - - - - Dashboard - - -
-

Dashboard

-
- - -``` - -Add a server-side check to protect this route. If the user is not authenticated, redirect them to the sign-in page. - -```html title="src/pages/dashboard/index.astro" ---- -export const prerender = false; - -if (!Astro.locals.user?.id) return Astro.redirect("/sign-in"); // [!code ++] ---- - - - - - - Dashboard - - -
-

Dashboard

-
- - -``` - -Now display the authenticated user's information. The `Astro.locals.user` object contains the user data that was set by the middleware. - -```html title="src/pages/dashboard/index.astro" ---- -export const prerender = false; - -if (!Astro.locals.user?.id) return Astro.redirect("/sign-in"); ---- - - - - - - Dashboard - - -
-

Dashboard

-
{JSON.stringify(Astro.locals.user, null, 2)}
- {/* [!code ++] */} -
- - -``` - -Finally, add a sign-out button. Import the `authClient` and add a button that calls the sign-out method, allowing the user to log out and be redirected to the sign-in page. - -```html title="src/pages/dashboard/index.astro" ---- -export const prerender = false; - -if (!Astro.locals.user?.id) return Astro.redirect("/sign-in"); ---- - - - - - - Dashboard - - -
-

Dashboard

-
{JSON.stringify(Astro.locals.user, null, 2)}
- {/* [!code ++] */} -
- - // [!code ++] - - -``` - -### 7.4. Home page - -Finally, update the home page to provide simple navigation. Replace the contents of `src/pages/index.astro` with the following: - -```html title="src/pages/index.astro" ---- -export const prerender = false; ---- - - - - - - Better Auth + Astro + Prisma - - -
-

Better Auth + Astro + Prisma

- { Astro.locals.user ? ( -
-

Welcome back, {Astro.locals.user.name}!

- Go to Dashboard -
- ) : ( - - ) } -
- - -``` - -## 8. Test it out - -Your application is now fully configured. - -1. Start the development server to test it: - -```npm -npm run dev -``` - -2. Navigate to `http://localhost:4321` in your browser. You should see the home page with "Sign Up" and "Sign In" links. - -3. Click on **Sign Up**, create a new account, and you should be redirected to the dashboard. You can then sign out and sign back in. - -4. To view the user data directly in your database, you can use Prisma Studio. - -```npm -npx prisma studio -``` - -5. This will open a new tab in your browser where you can see the `User`, `Session`, and `Account` tables and their contents. - -:::success - -Congratulations! You now have a fully functional authentication system built with Better Auth, Prisma, and Astro. - -::: - -## Next steps - -- Add support for social login or magic links -- Implement password reset and email verification -- Add user profile and account management pages -- Deploy to Vercel or Netlify and secure your environment variables -- Extend your Prisma schema with custom application models - -## Further reading - -- [Better Auth documentation](https://www.better-auth.com/docs) -- [Prisma documentation](/v6/orm/overview/introduction/what-is-prisma) -- [Astro documentation](https://astro.build/docs) diff --git a/apps/docs/content/docs.v6/guides/betterauth-nextjs.mdx b/apps/docs/content/docs.v6/guides/betterauth-nextjs.mdx deleted file mode 100644 index a69685d7a5..0000000000 --- a/apps/docs/content/docs.v6/guides/betterauth-nextjs.mdx +++ /dev/null @@ -1,996 +0,0 @@ ---- -title: Better Auth (with Next.js) -description: Learn how to use Prisma ORM in a Next.js app with Better Auth -image: /img/guides/prisma-betterauth-nextjs-cover.png -url: /v6/guides/betterauth-nextjs -metaTitle: How to use Prisma ORM and Prisma Postgres with Better Auth and Next.js -metaDescription: Learn how to use Prisma ORM in a Next.js app with Better Auth ---- - -## Introduction - -[Better Auth](https://better-auth.com/) is a modern, open-source authentication solution for web applications. It's built with TypeScript and provides a simple and extensible auth experience with support for multiple database adapters, including Prisma. - -In this guide, you'll wire Better Auth into a brand-new [Next.js](https://nextjs.org/) app and persist users in a [Prisma Postgres](https://prisma.io/postgres) database. You can find a complete example of this guide on [GitHub](https://github.com/prisma/prisma-examples/tree/latest/orm/betterauth-nextjs). - -## Prerequisites - -- [Node.js 20+](https://nodejs.org) -- Basic familiarity with Next.js App Router and Prisma - -## 1. Set up your project - -Create a new Next.js application: - -```npm -npx create-next-app@latest betterauth-nextjs-prisma -``` - -It will prompt you to customize your setup. Choose the defaults: - -:::info - -- _Would you like to use TypeScript?_ `Yes` -- _Would you like to use ESLint?_ `Yes` -- _Would you like to use Tailwind CSS?_ `Yes` -- _Would you like your code inside a `src/` directory?_ `Yes` -- _Would you like to use App Router?_ `Yes` -- _Would you like to use Turbopack?_ `Yes` -- _Would you like to customize the import alias (`@/_`by default)?*`No` - -::: - -Navigate to the project directory: - -```bash -cd betterauth-nextjs-prisma -``` - -These selections will create a modern Next.js project with TypeScript for type safety, ESLint for code quality, and Tailwind CSS for styling. Using the `src/` directory and the App Router are common conventions for new Next.js applications. - -## 2. Set up Prisma - -Next, you'll add Prisma to your project to manage your database. - -### 2.1. Install Prisma and dependencies - -Install the necessary Prisma packages. The dependencies differ slightly depending on whether you use Prisma Postgres with Accelerate or another database. - -```npm -npm install prisma tsx @types/pg --save-dev -``` - -```npm -npm install @prisma/client @prisma/adapter-pg dotenv pg -``` - -:::info - -If you are using a different database provider (MySQL, SQL Server, SQLite), install the corresponding driver adapter package instead of `@prisma/adapter-pg`. For more information, see [Database drivers](/v6/orm/overview/databases/database-drivers). - -::: - -Once installed, initialize Prisma in your project: - -```npm -npx prisma init --db --output ../src/generated/prisma -``` - -:::info -You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database like "My Better Auth Project" -::: - -This will create: - -- A `prisma` directory with a `schema.prisma` file -- A Prisma Postgres database -- A `.env` file containing the `DATABASE_URL` at the project root -- An `output` directory for the generated Prisma Client as `better-auth/generated/prisma` - -### 2.2. Configure Prisma - -Create a `prisma.config.ts` file in the root of your project with the following content: - -```typescript title="prisma.config.ts" -import "dotenv/config"; -import { defineConfig, env } from "prisma/config"; - -export default defineConfig({ - schema: "prisma/schema.prisma", - migrations: { - path: "prisma/migrations", - }, - datasource: { - url: env("DATABASE_URL"), - }, -}); -``` - -:::note - -The `dotenv` package should already be installed as it's a Next.js dependency. If not, install it using: - -```npm -npm install dotenv -``` - -::: - -### 2.3. Generate the Prisma client - -Run the following command to create the database tables and generate the Prisma Client: - -```npm -npx prisma generate -``` - -### 2.4. Set up a global Prisma client - -In the `src` directory, create a `lib` folder and a `prisma.ts` file inside it. This file will be used to create and export your Prisma Client instance. - -```bash -mkdir -p src/lib -touch src/lib/prisma.ts -``` - -Set up the Prisma client like this: - -```tsx title="src/lib/prisma.ts" -import { PrismaClient } from "@/generated/prisma/client"; -import { PrismaPg } from "@prisma/adapter-pg"; - -const adapter = new PrismaPg({ - connectionString: process.env.DATABASE_URL!, -}); - -const globalForPrisma = global as unknown as { - prisma: PrismaClient; -}; - -const prisma = - globalForPrisma.prisma || - new PrismaClient({ - adapter, - }); - -if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; - -export default prisma; -``` - -:::warning -We recommend using a connection pooler (like [Prisma Accelerate](https://www.prisma.io/accelerate)) to manage database connections efficiently. - -If you choose not to use one, **avoid** instantiating `PrismaClient` globally in long-lived environments. Instead, create and dispose of the client per request to prevent exhausting your database connections. -::: - -## 3. Set up Better Auth - -Now it's time to integrate Better Auth for authentication. - -### 3.1. Install and configure Better Auth - -First, install the Better Auth core package: - -```npm -npm install better-auth -``` - -Next, generate a secure secret that Better Auth will use to sign authentication tokens. This ensures your tokens cannot be messed with. - -```npm -npx @better-auth/cli@latest secret -``` - -Copy the generated secret and add it, along with your application's URL, to your `.env` file: - -```bash title=".env" -# Better Auth -BETTER_AUTH_SECRET=your-generated-secret # [!code ++] -BETTER_AUTH_URL=http://localhost:3000 # [!code ++] - -# Prisma -DATABASE_URL="your-database-url" -``` - -Now, create a configuration file for Better Auth. In the `src/lib` directory, create an `auth.ts` file: - -```bash -touch src/lib/auth.ts -``` - -In this file, you'll configure Better Auth to use the Prisma adapter, which allows it to persist user and session data in your database. You will also enable email and password authentication. - -```ts title="src/lib/auth.ts" -import { betterAuth } from "better-auth"; -import { prismaAdapter } from "better-auth/adapters/prisma"; -import prisma from "@/lib/prisma"; - -export const auth = betterAuth({ - database: prismaAdapter(prisma, { - provider: "postgresql", - }), -}); -``` - -Better Auth also supports other sign-in methods like social logins (Google, GitHub, etc.), which you can explore in their [documentation](https://www.better-auth.com/docs/authentication/email-password). - -```ts title="src/lib/auth.ts" -import { betterAuth } from "better-auth"; -import { prismaAdapter } from "better-auth/adapters/prisma"; -import prisma from "@/lib/prisma"; - -export const auth = betterAuth({ - database: prismaAdapter(prisma, { - provider: "postgresql", - }), - emailAndPassword: { - // [!code ++] - enabled: true, // [!code ++] - }, // [!code ++] -}); -``` - -:::info -If your application runs on a port other than `3000`, you must add it to the `trustedOrigins` in your `auth.ts` configuration to avoid CORS errors during authentication requests. - -```ts title="src/lib/auth.ts" -import { betterAuth } from "better-auth"; -import { prismaAdapter } from "better-auth/adapters/prisma"; -import prisma from "@/lib/prisma"; - -export const auth = betterAuth({ - database: prismaAdapter(prisma, { - provider: "postgresql", - }), - emailAndPassword: { - enabled: true, - }, - trustedOrigins: ["http://localhost:3001"], // [!code ++] -}); -``` - -::: - -### 3.2. Add Better Auth models to your schema - -Better Auth provides a CLI command to automatically add the necessary authentication models (`User`, `Session`, `Account`, and `Verification`) to your `schema.prisma` file. - -Run the following command: - -```npm -npx @better-auth/cli generate -``` - -:::note -It will ask for confirmation to overwrite your existing Prisma schema. Select `y`. -::: - -This will add the following models: - -```prisma -model User { - id String @id - name String - email String - emailVerified Boolean - image String? - createdAt DateTime - updatedAt DateTime - sessions Session[] - accounts Account[] - - @@unique([email]) - @@map("user") -} - -model Session { - id String @id - expiresAt DateTime - token String - createdAt DateTime - updatedAt DateTime - ipAddress String? - userAgent String? - userId String - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@unique([token]) - @@map("session") -} - -model Account { - id String @id - accountId String - providerId String - userId String - user User @relation(fields: [userId], references: [id], onDelete: Cascade) - accessToken String? - refreshToken String? - idToken String? - accessTokenExpiresAt DateTime? - refreshTokenExpiresAt DateTime? - scope String? - password String? - createdAt DateTime - updatedAt DateTime - - @@map("account") -} - -model Verification { - id String @id - identifier String - value String - expiresAt DateTime - createdAt DateTime? - updatedAt DateTime? - - @@map("verification") -} -``` - -### 3.3. Migrate the database - -With the new models in your schema, you need to update your database. Run a migration to create the corresponding tables: - -```npm -npx prisma migrate dev --name add-auth-models -``` - -```npm -npx prisma generate -``` - -## 4. Set up the API routes - -Better Auth needs an API endpoint to handle authentication requests like sign-in, sign-up, and sign-out. You'll create a catch-all API route in Next.js to handle all requests sent to `/api/auth/[...all]`. - -In the `src/app/api` directory, create an `auth/[...all]` folder structure and a `route.ts` file inside it: - -```bash -mkdir -p "src/app/api/auth/[...all]" -touch "src/app/api/auth/[...all]/route.ts" -``` - -Add the following code to the newly created `route.ts` file. This code uses a helper from Better Auth to create Next.js-compatible `GET` and `POST` request handlers. - -```ts -import { auth } from "@/lib/auth"; -import { toNextJsHandler } from "better-auth/next-js"; - -export const { POST, GET } = toNextJsHandler(auth); -``` - -Next, you'll need a client-side utility to interact with these endpoints from your React components. In the `src/lib` directory, create an `auth-client.ts` file: - -```bash -touch src/lib/auth-client.ts -``` - -Add the following code, which creates the React hooks and functions you'll use in your UI: - -```ts -import { createAuthClient } from "better-auth/react"; - -export const { signIn, signUp, signOut, useSession } = createAuthClient(); -``` - -## 5. Set up your pages - -Now, let's build the user interface for authentication. In the `src/app` directory, create the following folder structure: - -- `sign-up/page.tsx` -- `sign-in/page.tsx` -- `dashboard/page.tsx` - -```bash -mkdir -p src/app/{sign-up,sign-in,dashboard} -touch src/app/{sign-up,sign-in,dashboard}/page.tsx -``` - -### 5.1. Sign up page - -First, create the basic `SignUpPage` component in `src/app/sign-up/page.tsx`. This sets up the main container and a title for your page. - -```tsx title="src/app/sign-up/page.tsx" -"use client"; - -export default function SignUpPage() { - return ( -
-

Sign Up

-
- ); -} -``` - -Next, import the necessary hooks from React and Next.js to manage state and navigation. Initialize the router and a state variable to hold any potential error messages. - -```tsx title="src/app/sign-up/page.tsx" -"use client"; - -import { useState } from "react"; // [!code ++] -import { useRouter } from "next/navigation"; // [!code ++] - -export default function SignUpPage() { - const router = useRouter(); // [!code ++] - const [error, setError] = useState(null); // [!code ++] - - return ( -
-

Sign Up

-
- ); -} -``` - -Now, import the `signUp` function from your Better Auth client and add the `handleSubmit` function. This function is triggered on form submission and calls the `signUp.email` method provided by Better Auth, passing the user's name, email, and password. - -```tsx title="src/app/sign-up/page.tsx" -"use client"; - -import { useState } from "react"; -import { useRouter } from "next/navigation"; -//add-next-lin -import { signUp } from "@/lib/auth-client"; - -export default function SignUpPage() { - const router = useRouter(); - const [error, setError] = useState(null); - - async function handleSubmit(e: React.FormEvent) { - // [!code ++] - e.preventDefault(); // [!code ++] - setError(null); // [!code ++] - - const formData = new FormData(e.currentTarget); // [!code ++] - - const res = await signUp.email({ - // [!code ++] - name: formData.get("name") as string, // [!code ++] - email: formData.get("email") as string, // [!code ++] - password: formData.get("password") as string, // [!code ++] - }); // [!code ++] - - if (res.error) { - // [!code ++] - setError(res.error.message || "Something went wrong."); // [!code ++] - } else { - // [!code ++] - router.push("/dashboard"); // [!code ++] - } // [!code ++] - } // [!code ++] - - return ( -
-

Sign Up

-
- ); -} -``` - -To inform the user of any issues, add an element that conditionally renders when the `error` state is not null. - -```tsx title="src/app/sign-up/page.tsx" -"use client"; - -import { useState } from "react"; -import { useRouter } from "next/navigation"; -import { signUp } from "@/lib/auth-client"; - -export default function SignUpPage() { - const router = useRouter(); - const [error, setError] = useState(null); - - async function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - setError(null); - - const formData = new FormData(e.currentTarget); - - const res = await signUp.email({ - name: formData.get("name") as string, - email: formData.get("email") as string, - password: formData.get("password") as string, - }); - - if (res.error) { - setError(res.error.message || "Something went wrong."); - } else { - router.push("/dashboard"); - } - } - - return ( -
-

Sign Up

- {error &&

{error}

} // [!code ++] -
- ); -} -``` - -Finally, add the HTML form with input fields for the user's name, email, and password, and a submit button. - -```tsx title="src/app/sign-up/page.tsx" -"use client"; - -import { useState } from "react"; -import { useRouter } from "next/navigation"; -import { signUp } from "@/lib/auth-client"; - -export default function SignUpPage() { - const router = useRouter(); - const [error, setError] = useState(null); - - async function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - setError(null); - - const formData = new FormData(e.currentTarget); - - const res = await signUp.email({ - name: formData.get("name") as string, - email: formData.get("email") as string, - password: formData.get("password") as string, - }); - - if (res.error) { - setError(res.error.message || "Something went wrong."); - } else { - router.push("/dashboard"); - } - } - - return ( -
-

Sign Up

- {error &&

{error}

} -
- {" "} - // [!code ++] - {" "} - // [!code ++] - {" "} - // [!code ++] - {" "} - // [!code ++] - {" "} - // [!code ++] -
{" "} - // [!code ++] -
- ); -} -``` - -### 5.2. Sign in page - -For the sign-in page, start with the basic structure in `src/app/sign-in/page.tsx`. - -```tsx title="src/app/sign-in/page.tsx" -"use client"; - -export default function SignInPage() { - return ( -
-

Sign In

-
- ); -} -``` - -Now, add the state and router hooks, similar to the sign-up page. - -```tsx title="src/app/sign-in/page.tsx" -"use client"; - -import { useState } from "react"; // [!code ++] -import { useRouter } from "next/navigation"; // [!code ++] - -export default function SignInPage() { - const router = useRouter(); // [!code ++] - const [error, setError] = useState(null); // [!code ++] - - return ( -
-

Sign In

-
- ); -} -``` - -Add the `handleSubmit` function, this time importing and using the `signIn.email` method from Better Auth. - -```tsx title="src/app/sign-in/page.tsx" -"use client"; - -import { useState } from "react"; -import { useRouter } from "next/navigation"; -import { signIn } from "@/lib/auth-client"; -{ - /* [!code ++] */ -} - -export default function SignInPage() { - const router = useRouter(); - const [error, setError] = useState(null); - - async function handleSubmit(e: React.FormEvent) { - // [!code ++] - e.preventDefault(); // [!code ++] - setError(null); // [!code ++] - - const formData = new FormData(e.currentTarget); // [!code ++] - - const res = await signIn.email({ - // [!code ++] - email: formData.get("email") as string, // [!code ++] - password: formData.get("password") as string, // [!code ++] - }); // [!code ++] - - if (res.error) { - // [!code ++] - setError(res.error.message || "Something went wrong."); // [!code ++] - } else { - // [!code ++] - router.push("/dashboard"); // [!code ++] - } // [!code ++] - } // [!code ++] - - return ( -
-

Sign In

-
- ); -} -``` - -Add the conditional error message display. - -```tsx title="src/app/sign-in/page.tsx" -"use client"; - -import { useState } from "react"; -import { useRouter } from "next/navigation"; -import { signIn } from "@/lib/auth-client"; - -export default function SignInPage() { - const router = useRouter(); - const [error, setError] = useState(null); - - async function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - setError(null); - - const formData = new FormData(e.currentTarget); - - const res = await signIn.email({ - email: formData.get("email") as string, - password: formData.get("password") as string, - }); - - if (res.error) { - setError(res.error.message || "Something went wrong."); - } else { - router.push("/dashboard"); - } - } - - return ( -
-

Sign In

- {error &&

{error}

} // [!code ++] -
- ); -} -``` - -Finally, add the form fields for email and password and a sign-in button. - -```tsx title="src/app/sign-in/page.tsx" -"use client"; - -import { useState } from "react"; -import { useRouter } from "next/navigation"; -import { signIn } from "@/lib/auth-client"; - -export default function SignInPage() { - const router = useRouter(); - const [error, setError] = useState(null); - - async function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - setError(null); - - const formData = new FormData(e.currentTarget); - - const res = await signIn.email({ - email: formData.get("email") as string, - password: formData.get("password") as string, - }); - - if (res.error) { - setError(res.error.message || "Something went wrong."); - } else { - router.push("/dashboard"); - } - } - - return ( -
-

Sign In

- {error &&

{error}

} -
- {" "} - // [!code ++] - {" "} - // [!code ++] - {" "} - // [!code ++] - {" "} - // [!code ++] -
{" "} - // [!code ++] -
- ); -} -``` - -### 5.3. Dashboard page - -This is the protected page for authenticated users. Start with the basic component in `src/app/dashboard/page.tsx`. - -```tsx title="src/app/dashboard/page.tsx" -"use client"; - -export default function DashboardPage() { - return ( -
-

Dashboard

-
- ); -} -``` - -Import the `useSession` hook from your Better Auth client. This hook is the key to managing authentication state on the client side. It provides the session data and a pending status. - -```tsx title="src/app/dashboard/page.tsx" -"use client"; - -import { useRouter } from "next/navigation"; // [!code ++] -import { useSession } from "@/lib/auth-client"; // [!code ++] - -export default function DashboardPage() { - const router = useRouter(); // [!code ++] - const { data: session, isPending } = useSession(); // [!code ++] - - return ( -
-

Dashboard

-
- ); -} -``` - -To protect this route, use a `useEffect` hook. This effect checks if the session has loaded (`!isPending`) and if there is no authenticated user (`!session?.user`). If both are true, it redirects the user to the sign-in page. - -```tsx title="src/app/dashboard/page.tsx" -"use client"; - -import { useRouter } from "next/navigation"; -import { useSession } from "@/lib/auth-client"; -import { useEffect } from "react"; -{ - /* [!code ++] */ -} - -export default function DashboardPage() { - const router = useRouter(); - const { data: session, isPending } = useSession(); - - useEffect(() => { - // [!code ++] - if (!isPending && !session?.user) { - // [!code ++] - router.push("/sign-in"); // [!code ++] - } // [!code ++] - }, [isPending, session, router]); // [!code ++] - - return ( -
-

Dashboard

-
- ); -} -``` - -To provide a better user experience, add loading and redirecting states while the session is being verified. - -```tsx title="src/app/dashboard/page.tsx" -"use client"; - -import { useRouter } from "next/navigation"; -import { useSession } from "@/lib/auth-client"; -import { useEffect } from "react"; - -export default function DashboardPage() { - const router = useRouter(); - const { data: session, isPending } = useSession(); - - useEffect(() => { - if (!isPending && !session?.user) { - router.push("/sign-in"); - } - }, [isPending, session, router]); - - if (isPending) return

Loading...

; // [!code ++] - if (!session?.user) return

Redirecting...

; // [!code ++] - - return ( -
-

Dashboard

-
- ); -} -``` - -Finally, if the user is authenticated, display their name and email from the `session` object. Also, import the `signOut` function and add a button that calls it, allowing the user to log out. - -```tsx title="src/app/dashboard/page.tsx" -"use client"; - -import { useRouter } from "next/navigation"; -import { useSession, signOut } from "@/lib/auth-client"; -import { useEffect } from "react"; - -export default function DashboardPage() { - const router = useRouter(); - const { data: session, isPending } = useSession(); - - useEffect(() => { - if (!isPending && !session?.user) { - router.push("/sign-in"); - } - }, [isPending, session, router]); - - if (isPending) return

Loading...

; - if (!session?.user) return

Redirecting...

; - - const { user } = session; // [!code ++] - - return ( -
-

Dashboard

-

Welcome, {user.name || "User"}!

-

Email: {user.email}

- {" "} - // [!code ++] -
- ); -} -``` - -### 5.4. Home page - -Finally, update the home page to provide simple navigation to the sign-in and sign-up pages. Replace the contents of `src/app/page.tsx` with the following: - -```tsx title="src/app/page.tsx" -"use client"; - -import { useRouter } from "next/navigation"; - -export default function Home() { - const router = useRouter(); - - return ( -
-
- - -
-
- ); -} -``` - -## 6. Test it out - -Your application is now fully configured. - -1. Start the development server to test it: - -```npm -npm run dev -``` - -2. Navigate to `http://localhost:3000` in your browser. You should see the home page with "Sign Up" and "Sign In" buttons. - -3. Click on **Sign Up**, create a new account, and you should be redirected to the dashboard. You can then sign out and sign back in. - -4. To view the user data directly in your database, you can use Prisma Studio. - -```npm -npx prisma studio -``` - -5. This will open a new tab in your browser where you can see the `User`, `Session`, and `Account` tables and their contents. - -:::success - -Congratulations! You now have a fully functional authentication system built with Better Auth, Prisma, and Next.js. - -::: - -## Next steps - -- Add support for social login or magic links -- Implement password reset and email verification -- Add user profile and account management pages -- Deploy to Vercel and secure your environment variables -- Extend your Prisma schema with custom application models - -## Further reading - -- [Better Auth documentation](https://www.better-auth.com/docs) -- [Prisma documentation](/v6/orm/overview/introduction/what-is-prisma) -- [Next.js App Router](https://nextjs.org/docs/app) diff --git a/apps/docs/content/docs.v6/guides/bun.mdx b/apps/docs/content/docs.v6/guides/bun.mdx deleted file mode 100644 index d28a2371f6..0000000000 --- a/apps/docs/content/docs.v6/guides/bun.mdx +++ /dev/null @@ -1,329 +0,0 @@ ---- -title: Bun -description: Learn how to use Prisma ORM in a Bun application with Prisma Postgres -image: /img/guides/prisma-bun-cover-image.png -url: /v6/guides/bun -metaTitle: How to use Prisma ORM and Prisma Postgres with Bun -metaDescription: Learn how to use Prisma ORM in a Bun application with Prisma Postgres ---- - -## Introduction - -[Bun](https://bun.sh) is a fast JavaScript runtime that includes a bundler, test runner, and package manager. In this guide, you will set up a Bun project with Prisma ORM and a Prisma Postgres database. You will create a simple HTTP server and build a Bun executable for deployment. - -## Prerequisites - -- [Bun](https://bun.sh/docs/installation) installed in your system -- A [Prisma Postgres database](/v6/postgres) (created during setup) -- Basic knowledge of JavaScript/TypeScript - -## 1. Setting up your Bun project - -First, create a directory for your project and navigate to it: - -```bash -mkdir bun-prisma -cd bun-prisma -``` - -Then, initialise a new Bun project: - -```bash -bun init -y -``` - -This creates a basic Bun project that includes a `package.json` file and an `index.ts` file. - -## 2. Installing and configuring Prisma - -### 2.1. Install dependencies - -Install the required Prisma packages and other dependencies: - -```bash -bun add -d prisma @types/pg -bun add @prisma/client @prisma/adapter-pg pg -``` - -:::info - -If you are using a different database provider (MySQL, SQL Server, SQLite), install the corresponding driver adapter package instead of `@prisma/adapter-pg`. For more information, see [Database drivers](/v6/orm/overview/databases/database-drivers). - -::: - -### 2.2. Initialize Prisma ORM with Prisma Postgres - -Initialize Prisma ORM with Prisma Postgres in your project: - -```bash -bunx --bun prisma init --db -``` - -:::note - -The `--bun` flag is required to ensure Prisma runs with the Bun runtime. Without it, Prisma falls back to Node.js due to the `#!/usr/bin/env node` shebang in the CLI. - -::: - -:::info - -You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database like "My Bun Project" - -::: - -This command creates: - -- A `prisma/` directory with your `schema.prisma` file -- A new Prisma Postgres database -- A `prisma.config.ts` file -- A `.env` file with your `DATABASE_URL` - -### 2.3. Configure environment variables for direct connection - -We're going to use a direct connection string for connecting to Prisma Postgres. To get your [direct connection string](/v6/postgres/database/direct-connections#how-to-connect-to-prisma-postgres-via-direct-tcp): - -1. Navigate to your recently created Prisma Postgres project dashboard (e.g. "My Bun Project") -2. Click the **API Keys** tab in the project's sidebar -3. Click the **Create API key** button -4. Provide a name for the API key and click **Create** -5. Copy the connection string starting with `postgres://` - -Update your `.env` file to replace the `DATABASE_URL` with the new connection string: - -```bash title=".env" -DATABASE_URL="your_database_url_here" # [!code --] -DATABASE_URL="your_direct_connection_string_here" # [!code ++] -``` - -### 2.4. Update your Prisma schema - -Open `prisma/schema.prisma` and update it to include your data model: - -```prisma title="prisma/schema.prisma" -generator client { - provider = "prisma-client" - output = "../generated/prisma" -} - -datasource db { - provider = "postgresql" -} - -model User { // [!code ++] - id Int @id @default(autoincrement()) // [!code ++] - email String @unique // [!code ++] - name String? // [!code ++] -} // [!code ++] -``` - -## 3. Generate Prisma Client and run migrations - -Generate the Prisma client and apply your schema to the database: - -```bash -bunx --bun prisma migrate dev --name init -bunx --bun prisma generate -``` - -This command: - -- Creates the database tables based on your schema -- Generates the Prisma client in the `generated/prisma` directory - -## 4. Setting up database configuration and creating a seed script - -### 4.1. Create a database utility file - -Create a `db.ts` file in your project root to configure `PrismaClient`: - -```typescript title="db.ts" -import { PrismaClient } from "./generated/prisma/client"; -import { PrismaPg } from "@prisma/adapter-pg"; - -const adapter = new PrismaPg({ - connectionString: process.env.DATABASE_URL!, -}); - -export const prisma = new PrismaClient({ - adapter, -}); -``` - -### 4.2. Create a seed script - -Create a seed script in the `prisma` folder to populate your database with sample data: - -```typescript title="prisma/seed.ts" -import { PrismaClient } from "../generated/prisma/client"; -import { PrismaPg } from "@prisma/adapter-pg"; - -const adapter = new PrismaPg({ - connectionString: process.env.DATABASE_URL!, -}); - -const prisma = new PrismaClient({ - adapter, -}); - -async function main() { - // Create multiple users - await prisma.user.createMany({ - data: [ - { email: "alice@example.com", name: "Alice" }, - { email: "bob@example.com", name: "Bob" }, - { email: "charlie@example.com", name: "Charlie" }, - { email: "diana@example.com", name: "Diana" }, - { email: "eve@example.com", name: "Eve" }, - { email: "frank@example.com", name: "Frank" }, - { email: "grace@example.com", name: "Grace" }, - { email: "henry@example.com", name: "Henry" }, - { email: "isabella@example.com", name: "Isabella" }, - { email: "jack@example.com", name: "Jack" }, - ], - skipDuplicates: true, // prevents errors if you run the seed multiple times - }); - - console.log("Seed data inserted!"); -} - -main() - .catch((e) => { - console.error(e); - process.exit(1); - }) - .finally(async () => { - await prisma.$disconnect(); - }); -``` - -### 3.3. Add the seed script to Prisma Config - -Add the following content to the file: - -```typescript title="prisma.config.ts" -import { defineConfig, env } from "prisma/config"; - -export default defineConfig({ - schema: "prisma/schema.prisma", - migrations: { - path: "prisma/migrations", - seed: `bun run prisma/seed.ts`, // [!code ++] - }, - datasource: { - url: env("DATABASE_URL"), - }, -}); -``` - -:::note - -Unlike Node.js, Bun automatically loads `.env` files, so the `import 'dotenv/config'` line is not needed. If you see this import in your generated `prisma.config.ts`, you can safely remove it. - -::: - -Run the seed script to populate your database: - -```bash -bunx --bun prisma db seed -``` - -## 5. Creating your Bun server - -Replace the `index.ts` file contents with the following code to build a simple HTTP server that uses Prisma ORM to fetch and display users: - -```typescript title="index.ts" -import { prisma } from "./db"; - -const server = Bun.serve({ - port: 3000, - async fetch(req) { - const { pathname } = new URL(req.url); - - // Skip favicon route - if (pathname === "/favicon.ico") { - return new Response(null, { status: 204 }); // or serve an icon if you have one - } - - // Return all users - const users = await prisma.user.findMany(); - - // Count all users - const count = await prisma.user.count(); - - // Format the response with JSON - return new Response( - JSON.stringify({ - users: users, - totalUsers: count, - }), - { headers: { "Content-Type": "application/json" } }, - ); - }, -}); - -console.log(`Listening on http://localhost:${server.port}`); -``` - -## 6. Running your application - -Start your Bun server: - -```bash -bun run index.ts -``` - -You should see `Listening on http://localhost:3000` in the console. When you visit `http://localhost:3000` in your browser, you'll see a JSON response with all the users in your database and the total count. - -## 7. Building and running a Bun executable - -Bun can compile your [TypeScript application into a single executable file](https://bun.com/docs/bundler/executables), which is useful for deployment and distribution. - -### 7.1. Build the executable - -Build your application into an executable: - -```bash -bun build --compile index.ts -``` - -This creates an executable file named `index` (or `index.exe` on Windows) in your project directory. - -### 7.2. Run the executable - -Run the compiled executable: - -```bash -./index -``` - -You should see the same `Listening on http://localhost:3000` message, and your application will work exactly the same as before. The executable includes all dependencies and can be deployed to any compatible system without requiring Bun or Node.js to be installed. - -:::note - -Bun executables are useful for: - -- **Deployment**: Ship a single file instead of managing dependencies -- **Distribution**: Share your application without requiring users to install Bun -- **Performance**: Faster startup times compared to running TypeScript files -- **Security**: Your source code is compiled and not easily readable - -::: - -## Next steps - -You can explore [this example](https://pris.ly/bun_ppg_example) to see a sample application built with Bun and Prisma. - -Now that you have a Bun application connected to a Prisma Postgres database, you can continue by: - -- Extending your Prisma schema with additional models and relationships -- Implementing authentication and authorization -- Adding input validation and error handling -- Exploring Bun's built-in testing tools -- Deploying your executable to production servers - -### More info - -- [Bun Documentation](https://bun.sh/docs) -- [Prisma Config File](/v6/orm/reference/prisma-config-reference) -- [Prisma Client without the Rust engine](/v6/orm/prisma-client/setup-and-configuration/no-rust-engine) -- [Prisma Postgres](/v6/postgres) diff --git a/apps/docs/content/docs.v6/guides/clerk-astro.mdx b/apps/docs/content/docs.v6/guides/clerk-astro.mdx deleted file mode 100644 index db86762c85..0000000000 --- a/apps/docs/content/docs.v6/guides/clerk-astro.mdx +++ /dev/null @@ -1,518 +0,0 @@ ---- -title: Clerk (with Astro) -description: Learn how to use Prisma ORM in an Astro app with Clerk Auth -image: /img/guides/prisma-clerk-astro-cover.png -url: /v6/guides/clerk-astro -metaTitle: How to use Prisma ORM and Prisma Postgres with Clerk Auth and Astro -metaDescription: Learn how to use Prisma ORM in an Astro app with Clerk Auth ---- - -## Introduction - -[Clerk](https://clerk.com/) is a drop-in auth provider that handles sign-up, sign-in, user management, and webhooks so you don't have to. - -In this guide you'll wire Clerk into a brand-new [Astro](https://astro.build/) app and persist users in a [Prisma Postgres](https://prisma.io/postgres) database. You can find a complete example of this guide on [GitHub](https://github.com/prisma/prisma-examples/tree/latest/orm/clerk-astro). - -## Prerequisites - -- [Node.js 20+](https://nodejs.org) -- [Clerk account](https://clerk.com) -- [ngrok account](https://ngrok.com) - -## 1. Set up your project - -Create a new Astro project: - -```npm -npm create astro@latest -``` - -It will prompt you to customize your setup. Choose the defaults: - -:::info - -- _How would you like to start your new project?_ `Empty` -- _Install dependencies?_ `Yes` -- _Initialize a new git repository?_ `Yes` - -::: - -Navigate into the newly created project directory: - -```bash -cd -``` - -## 2. Set up Clerk - -### 2.1. Create a new Clerk application - -[Sign in](https://dashboard.clerk.com/sign-in) to Clerk and navigate to the home page. From there, press the `Create Application` button to create a new application. Enter a title, select your sign-in options, and click `Create Application`. - -:::info - -For this guide, the Google, Github, and Email sign in options will be used. - -::: - -Install the Clerk Astro SDK and Node adapter: - -```npm -npm install @clerk/astro @astrojs/node -``` - -In the Clerk Dashboard, navigate to the **API keys** page. In the **Quick Copy** section, copy your Clerk Publishable and Secret Keys. Paste your keys into `.env` in the root of your project: - -```bash title=".env" -PUBLIC_CLERK_PUBLISHABLE_KEY= -CLERK_SECRET_KEY= -``` - -### 2.2. Configure Astro with Clerk - -Astro needs to be configured for server-side rendering (SSR) with the Node adapter to work with Clerk. Update your `astro.config.mjs` file to include the Clerk integration and enable SSR: - -```javascript title="astro.config.mjs" -import { defineConfig } from "astro/config"; -import node from "@astrojs/node"; // [!code ++] -import clerk from "@clerk/astro"; // [!code ++] - -export default defineConfig({ - integrations: [clerk()], // [!code ++] - adapter: node({ mode: "standalone" }), // [!code ++] - output: "server", // [!code ++] -}); -``` - -### 2.3. Set up Clerk middleware - -The `clerkMiddleware` helper enables authentication across your entire application. Create a `middleware.ts` file in the `src` directory: - -```typescript title="src/middleware.ts" -import { clerkMiddleware } from "@clerk/astro/server"; - -export const onRequest = clerkMiddleware(); -``` - -### 2.4. Add Clerk UI to your page - -Update your `src/pages/index.astro` file to import the Clerk authentication components: - -```html title="src/pages/index.astro" ---- -import { // [!code ++] -SignedIn, // [!code ++] -SignedOut, // [!code ++] -UserButton, // [!code ++] -SignInButton, // [!code ++] -} from "@clerk/astro/components"; // [!code ++] ---- - - - - - - - - Astro - - - -``` - -Now add a header with conditional rendering to show sign-in buttons for unauthenticated users and a user button for authenticated users: - -```html title="src/pages/index.astro" ---- -import { -SignedIn, -SignedOut, -UserButton, -SignInButton, -} from "@clerk/astro/components"; ---- - - - - - - - - Astro - - -
- // [!code ++] - // [!code ++] // [!code ++] // [!code - ++] // [!code ++] // [!code ++] // [!code ++] -
- // [!code ++] - - -``` - -## 3. Install and configure Prisma - -### 3.1. Install dependencies - -To get started with Prisma, you'll need to install a few dependencies: - -```npm -npm install prisma tsx @types/pg --save-dev -``` - -```npm -npm install @prisma/client @prisma/adapter-pg dotenv pg -``` - -:::info - -If you are using a different database provider (MySQL, SQL Server, SQLite), install the corresponding driver adapter package instead of `@prisma/adapter-pg`. For more information, see [Database drivers](/v6/orm/overview/databases/database-drivers). - -::: - -Once installed, initialize Prisma in your project: - -```npm -npx prisma init --db -``` - -:::info -You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for the database like "My Clerk Astro Project" -::: - -This will create: - -- A `prisma/` directory with a `schema.prisma` file -- A `prisma.config.ts` file with your Prisma configuration -- A `.env` file with a `DATABASE_URL` already set - -### 3.2. Define your Prisma Schema - -Add a `User` model that will store authenticated user information from Clerk. The `clerkId` field uniquely links each database user to their Clerk account: - -```prisma title="prisma/schema.prisma" -generator client { - provider = "prisma-client" - output = "../src/generated/prisma" -} - -datasource db { - provider = "postgresql" -} - -model User { // [!code ++] - id Int @id @default(autoincrement()) // [!code ++] - clerkId String @unique // [!code ++] - email String @unique // [!code ++] - name String? // [!code ++] -} // [!code ++] -``` - -Run the following command to create the database tables: - -```npm -npx prisma migrate dev --name init -``` - -After the migration is complete, generate the Prisma Client: - -```npm -npx prisma generate -``` - -This generates the Prisma Client in the `src/generated/prisma` directory. - -### 3.3. Create TypeScript environment definitions - -Create an `env.d.ts` file in your `src` directory to provide TypeScript definitions for your environment variables: - -```bash -touch src/env.d.ts -``` - -Add type definitions for all the environment variables your application uses: - -```typescript title="src/env.d.ts" -interface ImportMetaEnv { - readonly DATABASE_URL: string; - readonly CLERK_WEBHOOK_SIGNING_SECRET: string; - readonly CLERK_SECRET_KEY: string; - readonly PUBLIC_CLERK_PUBLISHABLE_KEY: string; -} - -interface ImportMeta { - readonly env: ImportMetaEnv; -} -``` - -### 3.4. Create a reusable Prisma Client - -In the `src` directory, create a `lib` directory and a `prisma.ts` file inside it: - -```bash -mkdir src/lib -touch src/lib/prisma.ts -``` - -Initialize the Prisma Client with the PostgreSQL adapter: - -```typescript title="src/lib/prisma.ts" -import { PrismaClient } from "../generated/prisma/client"; -import { PrismaPg } from "@prisma/adapter-pg"; - -const adapter = new PrismaPg({ - connectionString: import.meta.env.DATABASE_URL, -}); - -const prisma = new PrismaClient({ - adapter, -}); - -export default prisma; -``` - -## 4. Wire Clerk to the database - -### 4.1. Create a Clerk webhook endpoint - -Webhooks allow Clerk to notify your application when events occur, such as when a user signs up. You'll create an API route to handle these webhooks and sync user data to your database. - -Create the directory structure and file for the webhook endpoint: - -```bash -mkdir -p src/pages/api/webhooks -touch src/pages/api/webhooks/clerk.ts -``` - -Import the necessary dependencies: - -```typescript title="src/pages/api/webhooks/clerk.ts" -import { verifyWebhook } from "@clerk/astro/webhooks"; -import type { APIRoute } from "astro"; -import prisma from "../../../lib/prisma"; -``` - -Create the `POST` handler that Clerk will call. The `verifyWebhook` function validates that the request actually comes from Clerk using the signing secret: - -```typescript title="src/pages/api/webhooks/clerk.ts" -import { verifyWebhook } from "@clerk/astro/webhooks"; -import type { APIRoute } from "astro"; -import prisma from "../../../lib/prisma"; - -export const POST: APIRoute = async ({ request }) => { - // [!code ++] - try { - // [!code ++] - const evt = await verifyWebhook(request, { - // [!code ++] - signingSecret: import.meta.env.CLERK_WEBHOOK_SIGNING_SECRET, // [!code ++] - }); // [!code ++] - const { id } = evt.data; // [!code ++] - const eventType = evt.type; // [!code ++] - console.log(`Received webhook with ID ${id} and event type of ${eventType}`); // [!code ++] - } catch (err) { - // [!code ++] - console.error("Error verifying webhook:", err); // [!code ++] - return new Response("Error verifying webhook", { status: 400 }); // [!code ++] - } // [!code ++] -}; // [!code ++] -``` - -When a new user is created, they need to be stored in the database. - -You'll do that by checking if the event type is `user.created` and then using Prisma's `upsert` method to create a new user if they don't exist: - -```typescript title="src/pages/api/webhooks/clerk.ts" -import { verifyWebhook } from "@clerk/astro/webhooks"; -import type { APIRoute } from "astro"; -import prisma from "../../../lib/prisma"; - -export const POST: APIRoute = async ({ request }) => { - try { - const evt = await verifyWebhook(request, { - signingSecret: import.meta.env.CLERK_WEBHOOK_SIGNING_SECRET, - }); - const { id } = evt.data; - const eventType = evt.type; - console.log(`Received webhook with ID ${id} and event type of ${eventType}`); - - if (eventType === "user.created") { - // [!code ++] - const { id, email_addresses, first_name, last_name } = evt.data; // [!code ++] - await prisma.user.upsert({ - // [!code ++] - where: { clerkId: id }, // [!code ++] - update: {}, // [!code ++] - create: { - // [!code ++] - clerkId: id, // [!code ++] - email: email_addresses[0].email_address, // [!code ++] - name: `${first_name} ${last_name}`, // [!code ++] - }, // [!code ++] - }); // [!code ++] - } // [!code ++] - } catch (err) { - console.error("Error verifying webhook:", err); - return new Response("Error verifying webhook", { status: 400 }); - } -}; -``` - -Finally, return a response to Clerk to confirm the webhook was received: - -```typescript title="src/pages/api/webhooks/clerk.ts" -import { verifyWebhook } from "@clerk/astro/webhooks"; -import type { APIRoute } from "astro"; -import prisma from "../../../lib/prisma"; - -export const POST: APIRoute = async ({ request }) => { - try { - const evt = await verifyWebhook(request, { - signingSecret: import.meta.env.CLERK_WEBHOOK_SIGNING_SECRET, - }); - const { id } = evt.data; - const eventType = evt.type; - console.log(`Received webhook with ID ${id} and event type of ${eventType}`); - - if (eventType === "user.created") { - const { id, email_addresses, first_name, last_name } = evt.data; - await prisma.user.upsert({ - where: { clerkId: id }, - update: {}, - create: { - clerkId: id, - email: email_addresses[0].email_address, - name: `${first_name} ${last_name}`, - }, - }); - } - - return new Response("Webhook received", { status: 200 }); // [!code ++] - } catch (err) { - console.error("Error verifying webhook:", err); - return new Response("Error verifying webhook", { status: 400 }); - } -}; -``` - -### 4.2. Expose your local app for webhooks - -You'll need to expose your local app for webhooks with [ngrok](https://ngrok.com/). This will allow Clerk to reach your `/api/webhooks/clerk` route to push events like `user.created`. - -Start your development server: - -```npm -npm run dev -``` - -In a separate terminal window, install ngrok globally and expose your local app: - -```npm -npm install --global ngrok -ngrok http 4321 -``` - -Copy the ngrok `Forwarding URL` (e.g., `https://a65a60261342.ngrok-free.app`). This will be used to configure the webhook URL in Clerk. - -### 4.3. Configure Astro to allow ngrok connections - -Astro needs to be configured to accept connections from the ngrok domain. Update your `astro.config.mjs` to include the ngrok host in the allowed hosts list: - -```javascript title="astro.config.mjs" -import { defineConfig } from "astro/config"; -import node from "@astrojs/node"; -import clerk from "@clerk/astro"; - -export default defineConfig({ - integrations: [clerk()], - adapter: node({ mode: "standalone" }), - output: "server", - server: { - // [!code ++] - allowedHosts: ["localhost", ".ngrok-free.app"], // [!code ++] - }, // [!code ++] -}); -``` - -:::note - -Replace `` with the subdomain from your ngrok URL. For example, if your ngrok URL is `https://a65a60261342.ngrok-free.app`, use `a65a60261342.ngrok-free.app`. - -::: - -### 4.4. Register the webhook in Clerk - -Navigate to the **_Webhooks_** section of your Clerk application located near the bottom of the **_Configure_** tab under **_Developers_**. - -Click **_Add Endpoint_** and paste the ngrok URL into the **_Endpoint URL_** field and add `/api/webhooks/clerk` to the end. It should look similar to this: - -```text -https://a65a60261342.ngrok-free.app/api/webhooks/clerk -``` - -Subscribe to the **user.created** event by checking the box next to it under **_Message Filtering_**. - -Click **_Create_** to save the webhook endpoint. - -Copy the **_Signing Secret_** and add it to your `.env` file: - -```bash title=".env" -# Prisma -DATABASE_URL= - -# Clerk -PUBLIC_CLERK_PUBLISHABLE_KEY= -CLERK_SECRET_KEY= -CLERK_WEBHOOK_SIGNING_SECRET= # [!code ++] -``` - -Restart your dev server to pick up the new environment variable: - -```npm -npm run dev -``` - -### 4.5. Test the integration - -Navigate to `http://localhost:4321` in your browser and sign in using any of the sign-up options you configured in Clerk. - -Open Prisma Studio to verify that the user was created in your database: - -```npm -npx prisma studio -``` - -You should see a new user record with the Clerk ID, email, and name from your sign-up. - -:::note - -If you don't see a user record, there are a few things to check: - -- Delete your user from the Users tab in Clerk and try signing up again. -- Check your ngrok URL and ensure it's correct _(it will change every time you restart ngrok)_. -- Verify your Clerk webhook is pointing to the correct ngrok URL. -- Make sure you've added `/api/webhooks/clerk` to the end of the webhook URL. -- Ensure you've subscribed to the **user.created** event in Clerk. -- Confirm you've added the ngrok host to `allowedHosts` in `astro.config.mjs` and removed `https://`. -- Check the terminal running `npm run dev` for any error messages. - -::: - -You've successfully built an Astro application with Clerk authentication and Prisma, creating a foundation for a secure and scalable full-stack application that handles user management and data persistence with ease. - -## Next steps - -Now that you have a working Astro app with Clerk authentication and Prisma connected to a Prisma Postgres database, you can: - -- Add user profile management and update functionality -- Build protected API routes that require authentication -- Extend your schema with additional models related to users -- Deploy to your preferred hosting platform and set your production webhook URL in Clerk -- Enable query caching with [Prisma Postgres](/v6/postgres/database/caching) for better performance - -### More info - -- [Prisma Documentation](/v6/orm/overview/introduction/what-is-prisma) -- [Astro Documentation](https://docs.astro.build) -- [Clerk Documentation](https://clerk.com/docs) diff --git a/apps/docs/content/docs.v6/guides/clerk-nextjs.mdx b/apps/docs/content/docs.v6/guides/clerk-nextjs.mdx deleted file mode 100644 index 2cf142ca10..0000000000 --- a/apps/docs/content/docs.v6/guides/clerk-nextjs.mdx +++ /dev/null @@ -1,834 +0,0 @@ ---- -title: Clerk (with Next.js) -description: Learn how to use Prisma ORM in a Next.js app with Clerk Auth -image: /img/guides/prisma-clerk-nextjs-cover.png -url: /v6/guides/clerk-nextjs -metaTitle: How to use Prisma ORM and Prisma Postgres with Clerk Auth and Next.js -metaDescription: Learn how to use Prisma ORM in a Next.js app with Clerk Auth ---- - -## Introduction - -[Clerk](https://clerk.com/) is a drop-in auth provider that handles sign-up, sign-in, user management, and webhooks so you don't have to. - -In this guide you'll wire Clerk into a brand-new [Next.js](https://nextjs.org/) app, persist users in a [Prisma Postgres](https://prisma.io/postgres) database, and expose a tiny posts API. You can find a complete example of this guide on [GitHub](https://github.com/prisma/prisma-examples/tree/latest/orm/clerk-nextjs). - -## Prerequisites - -- [Node.js 20+](https://nodejs.org) -- [Clerk account](https://clerk.com) -- [ngrok account](https://ngrok.com) - -## 1. Set up your project - -Create the app: - -```npm -npx create-next-app@latest clerk-nextjs-prisma -``` - -It will prompt you to customize your setup. Choose the defaults: - -:::info - -- _Would you like to use TypeScript?_ `Yes` -- _Would you like to use ESLint?_ `Yes` -- _Would you like to use Tailwind CSS?_ `Yes` -- _Would you like your code inside a `src/` directory?_ `No` -- _Would you like to use App Router?_ (recommended) `Yes` -- _Would you like to use Turbopack for `next dev`?_ `Yes` -- _Would you like to customize the import alias (`@/_`by default)?*`No` - -::: - -Navigate to the project directory: - -```bash -cd clerk-nextjs-prisma -``` - -## 2. Set up Clerk - -### 2.1. Create a new Clerk application - -[Sign in](https://dashboard.clerk.com/sign-in) to Clerk and navigate to the home page. From there, press the `Create Application` button to create a new application. Enter a title, select your sign-in options, and click `Create Application`. - -:::info - -For this guide, the Google, Github, and Email sign in options will be used. - -::: - -Install the Clerk Next.js SDK: - -```npm -npm install @clerk/nextjs -``` - -Copy your Clerk keys and paste them into **.env** in the root of your project: - -```bash title=".env" -# Clerk # [!code ++] -NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY= # [!code ++] -CLERK_SECRET_KEY= # [!code ++] -``` - -### 2.2. Protect routes with Clerk middleware - -The `clerkMiddleware` helper enables authentication and is where you'll configure your protected routes. - -Create a `middleware.ts` file in the root directory of your project: - -```tsx title="middleware.ts" showLineNumbers -import { clerkMiddleware } from "@clerk/nextjs/server"; // [!code ++] - -export default clerkMiddleware(); // [!code ++] - -export const config = { - // [!code ++] - matcher: [ - // [!code ++] - "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)", // [!code ++] - "/(api|trpc)(.*)", // [!code ++] - ], // [!code ++] -}; // [!code ++] -``` - -### 2.3. Add Clerk UI to your layout - -Next, you'll need to wrap your app in the `ClerkProvider` component to make authentication globally available. - -In your `layout.tsx` file, add the `ClerkProvider` component: - -```tsx title="app/layout.tsx" showLineNumbers -import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; -import "./globals.css"; -import { ClerkProvider } from "@clerk/nextjs"; {/* [!code ++] */} - -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], -}); - -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], -}); - -export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", -}; - -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { - return ( - {/* [!code ++] */} - - - {children} - - - {/* [!code ++] */} - ); -} -``` - -Create a `Navbar` component which will be used to display the Sign In and Sign Up buttons as well as the User Button once a user is signed in: - -```tsx title="app/layout.tsx" showLineNumbers -import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; -import "./globals.css"; -import { - ClerkProvider, - UserButton, // [!code ++] - SignInButton, // [!code ++] - SignUpButton, // [!code ++] - SignedOut, // [!code ++] - SignedIn, // [!code ++] -} from "@clerk/nextjs"; - -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], -}); - -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], -}); - -export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", -}; - -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { - return ( - - - - {/* [!code ++] */} - {children} - - - - ); -} - -const Navbar = () => { - // [!code ++] - return ( - // [!code ++] -
- {" "} - // [!code ++] - - {" "} - // [!code ++] - // [!code ++] - // [!code ++] - {" "} - // [!code ++] - - {" "} - // [!code ++] - // [!code ++] - {" "} - // [!code ++] -
// [!code ++] - ); // [!code ++] -}; // [!code ++] -``` - -## 3. Install and configure Prisma - -### 3.1. Install dependencies - -To get started with Prisma, you'll need to install a few dependencies: - -```npm -npm install prisma tsx @types/pg --save-dev -``` - -```npm -npm install @prisma/client @prisma/adapter-pg dotenv pg -``` - -:::info - -If you are using a different database provider (MySQL, SQL Server, SQLite), install the corresponding driver adapter package instead of `@prisma/adapter-pg`. For more information, see [Database drivers](/v6/orm/overview/databases/database-drivers). - -::: - -Once installed, initialize Prisma in your project: - -```npm -npx prisma init --db --output ../app/generated/prisma -``` - -:::info -You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for the database like "My Clerk NextJS Project" -::: -This will create: - -- A `prisma/` directory with a `schema.prisma` file -- A `DATABASE_URL` in `.env` - -### 3.2. Define your Prisma Schema - -In the `prisma/schema.prisma` file, add the following models: - -```prisma title="prisma/schema.prisma" showLineNumbers -generator client { - provider = "prisma-client" - output = "../app/generated/prisma" -} - -datasource db { - provider = "postgresql" -} - -model User { // [!code ++] - id Int @id @default(autoincrement()) // [!code ++] - clerkId String @unique // [!code ++] - email String @unique // [!code ++] - name String? // [!code ++] - posts Post[] // [!code ++] -} // [!code ++] - -model Post { // [!code ++] - id Int @id @default(autoincrement()) // [!code ++] - title String // [!code ++] - content String? // [!code ++] - published Boolean @default(false) // [!code ++] - authorId Int // [!code ++] - author User @relation(fields: [authorId], references: [id]) // [!code ++] - createdAt DateTime @default(now()) // [!code ++] -} // [!code ++] -``` - -This will create two models: `User` and `Post`, with a one-to-many relationship between them. - -Create a `prisma.config.ts` file to configure Prisma: - -```typescript title="prisma.config.ts" showLineNumbers -import "dotenv/config"; // [!code ++] -import { defineConfig, env } from "prisma/config"; // [!code ++] - -export default defineConfig({ - // [!code ++] - schema: "prisma/schema.prisma", // [!code ++] - migrations: { - // [!code ++] - path: "prisma/migrations", // [!code ++] - }, // [!code ++] - datasource: { - // [!code ++] - url: env("DATABASE_URL"), // [!code ++] - }, // [!code ++] -}); // [!code ++] -``` - -:::note - -You'll need to install the `dotenv` package: - -```npm -npm install dotenv -``` - -::: - -Now, run the following command to create the database tables and generate the Prisma Client: - -```npm -npx prisma migrate dev --name init -``` - -```npm -npx prisma generate -``` - -:::warning - -It is recommended that you add `/app/generated/prisma` to your `.gitignore` file. - -::: - -### 3.3. Create a reusable Prisma Client - -In the root directory, create a `lib` directory and a `prisma.ts` file inside it: - -```tsx title="lib/prisma.ts" showLineNumbers -import { PrismaClient } from "../app/generated/prisma/client"; // [!code ++] -import { PrismaPg } from "@prisma/adapter-pg"; // [!code ++] - -const adapter = new PrismaPg({ - // [!code ++] - connectionString: process.env.DATABASE_URL!, // [!code ++] -}); // [!code ++] - -const globalForPrisma = global as unknown as { - // [!code ++] - prisma: PrismaClient; // [!code ++] -}; // [!code ++] - -const prisma = // [!code ++] - globalForPrisma.prisma || // [!code ++] - new PrismaClient({ - // [!code ++] - adapter, // [!code ++] - }); // [!code ++] - -if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; // [!code ++] - -export default prisma; // [!code ++] -``` - -## 4. Wire Clerk to the database - -### 4.1. Create a Clerk webhook endpoint - -Create a new API route at `app/api/webhooks/clerk/route.ts`: - -Import the necessary dependencies: - -```tsx title="app/api/webhooks/clerk/route.ts" showLineNumbers -import { verifyWebhook } from "@clerk/nextjs/webhooks"; // [!code ++] -import { NextRequest } from "next/server"; // [!code ++] -import prisma from "@/lib/prisma"; // [!code ++] -``` - -Create the `POST` method that Clerk will call and verify the webhook: - -```tsx title="app/api/webhooks/clerk/route.ts" showLineNumbers -import { verifyWebhook } from "@clerk/nextjs/webhooks"; -import { NextRequest } from "next/server"; -import prisma from "@/lib/prisma"; - -export async function POST(req: NextRequest) { - // [!code ++] - try { - // [!code ++] - const evt = await verifyWebhook(req); // [!code ++] - const { id } = evt.data; // [!code ++] - const eventType = evt.type; // [!code ++] - console.log(`Received webhook with ID ${id} and event type of ${eventType}`); // [!code ++] - } catch (err) { - // [!code ++] - console.error("Error verifying webhook:", err); // [!code ++] - return new Response("Error verifying webhook", { status: 400 }); // [!code ++] - } // [!code ++] -} // [!code ++] -``` - -When a new user is created, they need to be stored in the database. - -You'll do that by checking if the event type is `user.created` and then using Prisma's `upsert` method to create a new user if they don't exist: - -```tsx title="app/api/webhooks/clerk/route.ts" showLineNumbers -import { verifyWebhook } from "@clerk/nextjs/webhooks"; -import { NextRequest } from "next/server"; -import prisma from "@/lib/prisma"; - -export async function POST(req: NextRequest) { - try { - const evt = await verifyWebhook(req); - const { id } = evt.data; - const eventType = evt.type; - console.log(`Received webhook with ID ${id} and event type of ${eventType}`); - - if (eventType === "user.created") { - // [!code ++] - const { id, email_addresses, first_name, last_name } = evt.data; // [!code ++] - await prisma.user.upsert({ - // [!code ++] - where: { clerkId: id }, // [!code ++] - update: {}, // [!code ++] - create: { - // [!code ++] - clerkId: id, // [!code ++] - email: email_addresses[0].email_address, // [!code ++] - name: `${first_name} ${last_name}`, // [!code ++] - }, // [!code ++] - }); // [!code ++] - } // [!code ++] - } catch (err) { - console.error("Error verifying webhook:", err); - return new Response("Error verifying webhook", { status: 400 }); - } -} -``` - -Finally, return a response to Clerk to confirm the webhook was received: - -```tsx title="app/api/webhooks/clerk/route.ts" showLineNumbers -import { verifyWebhook } from "@clerk/nextjs/webhooks"; -import { NextRequest } from "next/server"; -import prisma from "@/lib/prisma"; - -export async function POST(req: NextRequest) { - try { - const evt = await verifyWebhook(req); - const { id } = evt.data; - const eventType = evt.type; - console.log(`Received webhook with ID ${id} and event type of ${eventType}`); - - if (eventType === "user.created") { - const { id, email_addresses, first_name, last_name } = evt.data; - await prisma.user.upsert({ - where: { clerkId: id }, - update: {}, - create: { - clerkId: id, - email: email_addresses[0].email_address, - name: `${first_name} ${last_name}`, - }, - }); - } - - return new Response("Webhook received", { status: 200 }); - { - /* [!code ++] */ - } - } catch (err) { - console.error("Error verifying webhook:", err); - return new Response("Error verifying webhook", { status: 400 }); - } -} -``` - -### 4.2. Expose your local app for webhooks - -You'll need to expose your local app for webhooks with [ngrok](https://ngrok.com/). This will allow Clerk to reach your `/api/webhooks/clerk` route to push events like `user.created`. - -Install ngrok and expose your local app: - -```npm -npm install --global ngrok -ngrok http 3000 -``` - -Copy the ngrok `Forwarding URL`. This will be used to set the webhook URL in Clerk. - -Navigate to the **_Webhooks_** section of your Clerk application located near the bottom of the **_Configure_** tab under **_Developers_**. - -Click **_Add Endpoint_** and paste the ngrok URL into the **_Endpoint URL_** field and add `/api/webhooks/clerk` to the end of the URL. It should look similar to this: - -```text -https://a60b-99-42-62-240.ngrok-free.app/api/webhooks/clerk -``` - -Copy the **_Signing Secret_** and add it to your `.env` file: - -```bash title=".env" -# Prisma -DATABASE_URL= - -# Clerk -NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY= -CLERK_SECRET_KEY= -CLERK_WEBHOOK_SIGNING_SECRET= # [!code ++] -``` - -On the home page, press Sign Up and create an account using any of the sign-up options - -Open Prisma Studio and you should see a user record. - -```npm -npx prisma studio -``` - -:::note - -If you don't see a user record, there are a few things to check: - -- Delete your user from the Users tab in Clerk and try again. -- Check your ngrok URL and ensure it's correct _(it will change everytime you restart ngrok)_. -- Check your Clerk webhook is pointing to the correct ngrok URL. -- Make sure you've added `/api/webhooks/clerk` to the end of the URL. - -::: - -## 5. Build a posts API - -To create posts under a user, you'll need to create a new API route at `app/api/posts/route.ts`: - -Start by importing the necessary dependencies: - -```tsx title="app/api/posts/route.ts" showLineNumbers -import { auth } from "@clerk/nextjs/server"; // [!code ++] -import prisma from "@/lib/prisma"; // [!code ++] -``` - -Get the `clerkId` of the authenticated user. If there's no user, return a `401` Unauthorized response: - -```tsx title="app/api/posts/route.ts" showLineNumbers -import { auth } from "@clerk/nextjs/server"; -import prisma from "@/lib/prisma"; - -export async function POST(req: Request) { - // [!code ++] - const { userId: clerkId } = await auth(); // [!code ++] - if (!clerkId) return new Response("Unauthorized", { status: 401 }); // [!code ++] -} // [!code ++] -``` - -Match the Clerk user to a user in the database. If none is found, return a `404` Not Found response: - -```tsx title="app/api/posts/route.ts" showLineNumbers -import { auth } from "@clerk/nextjs/server"; -import prisma from "@/lib/prisma"; - -export async function POST(req: Request) { - const { userId: clerkId } = await auth(); - if (!clerkId) return new Response("Unauthorized", { status: 401 }); - - const user = await prisma.user.findUnique({ - // [!code ++] - where: { clerkId }, // [!code ++] - }); // [!code ++] - - if (!user) return new Response("User not found", { status: 404 }); // [!code ++] -} -``` - -Destructure the title and content from the incoming request and create a post. Once done, return a `201` Created response: - -```tsx title="app/api/posts/route.ts" showLineNumbers -import { auth } from "@clerk/nextjs/server"; -import prisma from "@/lib/prisma"; - -export async function POST(req: Request) { - const { userId: clerkId } = await auth(); - if (!clerkId) return new Response("Unauthorized", { status: 401 }); - - const { title, content } = await req.json(); - { - /* [!code ++] */ - } - - const user = await prisma.user.findUnique({ - where: { clerkId }, - }); - - if (!user) return new Response("User not found", { status: 404 }); - - const post = await prisma.post.create({ - // [!code ++] - data: { - // [!code ++] - title, // [!code ++] - content, // [!code ++] - authorId: user.id, // [!code ++] - }, // [!code ++] - }); // [!code ++] - - return new Response(JSON.stringify(post), { status: 201 }); - { - /* [!code ++] */ - } -} -``` - -## 6. Add a Post creation UI - -In `/app`, create a `/components` directory and a `PostInputs.tsx` file inside it: - -```tsx title="app/components/PostInputs.tsx" showLineNumbers -"use client"; -{ - /* [!code ++] */ -} - -import { useState } from "react"; -{ - /* [!code ++] */ -} - -export default function PostInputs() { - // [!code ++] - const [title, setTitle] = useState(""); // [!code ++] - const [content, setContent] = useState(""); // [!code ++] -} // [!code ++] -``` - -This component uses `"use client"` to ensure the component is rendered on the client. The title and content are stored in their own `useState` hooks. - -Create a function that will be called when a form is submitted: - -```tsx title="app/components/PostInputs.tsx" showLineNumbers -"use client"; - -import { useState } from "react"; - -export default function PostInputs() { - const [title, setTitle] = useState(""); - const [content, setContent] = useState(""); - - async function createPost(e: React.FormEvent) { - // [!code ++] - e.preventDefault(); // [!code ++] - if (!title || !content) return; // [!code ++] - - await fetch("/api/posts", { - // [!code ++] - method: "POST", // [!code ++] - headers: { "Content-Type": "application/json" }, // [!code ++] - body: JSON.stringify({ title, content }), // [!code ++] - }); // [!code ++] - - setTitle(""); // [!code ++] - setContent(""); // [!code ++] - location.reload(); // [!code ++] - } // [!code ++] -} -``` - -You'll be using a form to create a post and call the `POST` route you created earlier: - -```tsx title="app/components/PostInputs.tsx" showLineNumbers -"use client"; - -import { useState } from "react"; - -export default function PostInputs() { - const [title, setTitle] = useState(""); - const [content, setContent] = useState(""); - - async function createPost(e: React.FormEvent) { - e.preventDefault(); - if (!title || !content) return; - - await fetch("/api/posts", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ title, content }), - }); - - setTitle(""); - setContent(""); - location.reload(); - } - - return ( - // [!code ++] -
- {" "} - // [!code ++] - setTitle(e.target.value)} // [!code ++] - className="w-full p-2 border border-zinc-800 rounded" // [!code ++] - />{" "} - // [!code ++] -