diff --git a/.github/workflows/config/.linkspector.yml b/.github/workflows/config/.linkspector.yml deleted file mode 100644 index 0d06293a36..0000000000 --- a/.github/workflows/config/.linkspector.yml +++ /dev/null @@ -1,19 +0,0 @@ -dirs: - - content -useGitIgnore: true -ignorePatterns: - - pattern: "^/.*" # local links are not checked - - pattern: "^http://localhost.*" # Localhost links are not checked - - pattern: "^https://packagecontrol.*" # Package control links are not checked (it was 500ing at time of writing) - - pattern: "^https://(www|dash).cloudflare.com.*" # Cloudflare links return 403 at time of writing - -fileExtensions: - - mdx - - md -modifiedFilesOnly: false -aliveStatusCodes: - - 200 - - 201 - - 204 - - 304 - - 403 diff --git a/.github/workflows/linkspector.yml b/.github/workflows/linkspector.yml deleted file mode 100644 index e428cf19b6..0000000000 --- a/.github/workflows/linkspector.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Linkspector -on: [pull_request] -jobs: - check-links: - name: runner / linkspector - runs-on: ubuntu-22.04 - permissions: - contents: write - steps: - - uses: actions/checkout@v4 - - name: Run linkspector - uses: umbrelladocs/action-linkspector@v1.3.7 - with: - github_token: ${{ secrets.github_token }} - reporter: github-pr-check - fail_on_error: true - filter_mode: nofilter - config_file: .github/workflows/config/.linkspector.yml \ No newline at end of file diff --git a/.github/workflows/lychee.yml b/.github/workflows/lychee.yml index 72cf3fa499..6bae422c2b 100644 --- a/.github/workflows/lychee.yml +++ b/.github/workflows/lychee.yml @@ -34,6 +34,7 @@ jobs: --exclude 'http://localhost.*' --exclude 'https://localhost.*' --exclude 'https://cockroachlabs.com' + --exclude 'https://www.gnu.org' --exclude '^/.*' './**/*.md' './**/*.mdx' workingDirectory: "content" @@ -60,6 +61,7 @@ jobs: --exclude 'http://localhost.*' --exclude 'https://localhost.*' --exclude 'https://cockroachlabs.com' + --exclude 'https://www.gnu.org' --exclude '^/.*' './**/*.md' './**/*.mdx' workingDirectory: "content" @@ -97,7 +99,7 @@ jobs: fi - name: 📝 Comment Broken Links - if: ${{ always() && github.event.pull_request.head.repo.fork == false }} + if: ${{ always() && github.event.pull_request.head.repo.fork == false && (steps.lychee.outputs.exit_code != 0 || (steps.lychee-retry.conclusion != 'skipped' && steps.lychee-retry.outputs.exit_code != 0)) }} uses: peter-evans/create-or-update-comment@v4 with: issue-number: ${{ github.event.pull_request.number }} diff --git a/content/100-getting-started/index.mdx b/content/100-getting-started/index.mdx index b03a3857a7..110d5db0e6 100644 --- a/content/100-getting-started/index.mdx +++ b/content/100-getting-started/index.mdx @@ -3,7 +3,6 @@ title: 'Get Started' metaTitle: 'Get started with Prisma' metaDescription: 'Build data-driven applications with ease using Prisma ORM, add connection pooling or global caching with Prisma Accelerate.' hide_title: true -tocDepth: 1 sidebar_position: 0 sidebar_class_name: firstTitle pagination_next: 'getting-started/quickstart-sqlite' @@ -18,82 +17,60 @@ import { Grid, LinkCard, List, + Plus, + Plug, SignalStream, PrismaPostgres, SquareLogo, + QuickstartLinkCard } from '@site/src/components/GettingStarted'; +Getting started - - -Get started - -Welcome 👋 - -Explore our products that make it easy to build and scale data-driven applications: - -[**Prisma ORM**](/orm/overview/introduction/what-is-prisma) is a next-generation Node.js and TypeScript ORM that unlocks a new level of developer experience when working with databases thanks to its intuitive data model, automated migrations, type-safety & auto-completion. - -[**Prisma Postgres**](/postgres) is a managed PostgreSQL service that gives you an _always-on_ database with _pay-as-you-go_ pricing. - -[**Prisma Optimize**](/optimize/) helps you analyze queries, generate insights, and provides recommendations to make your database queries faster. + -[**Prisma Accelerate**](/accelerate) is a global database cache with scalable connection pooling to make your queries fast. + - +[**Prisma ORM**](/orm/overview/introduction/what-is-prisma) is an open-source ORM that provides fast, type-safe access to Postgres, MySQL, SQLite, and more databases, and runs smoothly across Node.js, Bun, and Deno. +```terminal +npx prisma init --db +``` + + -## Prisma ORM + -Add Prisma ORM to your application in a few minutes to start modeling your data, run schema migrations and query your database. +[**Prisma Postgres**](/postgres) is a fully managed PostgreSQL database that scales to zero, integrates with Prisma ORM and Prisma Studio, and includes a generous free tier. -### The easiest way to get started with Prisma +```terminal +npx create-db +``` + + + -_Explore all Prisma products at once._ +
- +> -### Explore quickly with a SQLite database +The fastest way to set up **Prisma ORM** with a ready-to-use **Prisma Postgres** database. -_These options don't require you to have your own database running._ + - - - - +
+
-### Choose an option to get started with your own database +### Already have your own database? -_Select one of these options if you want to connect Prisma ORM to your own database._ +The fastest way to set Prisma ORM up with a ready-to-use database. - - -

- Set up Prisma ORM from scratch with your favorite database and - learn basic workflows like data modeling, querying, and migrations. -

- - + + - -
- -

- Get started with Prisma ORM and your existing database by - introspecting your database schema and learn how to query your database. -

- + + +
+
+ + {/* ### Using Prisma Postgres with other tools? + +You can also use Prisma Postgres with different tools or ORMs. Pick one of the options below to see how to connect. + + + + +
+
*/} + +### Add Prisma to your favorite framework? + +Working with **Next.js**, **Remix**, or another framework? You can easily add Prisma to your setup in just a few steps and start using it right away. + + - -
-
- -## Prisma Accelerate - -Make your database queries faster by scaling your database connections and caching database results at the edge with Prisma Accelerate. - - - - - -
- - -## Prisma Optimize - -Make your database queries faster by using the insights and recommendations generated by Prisma Optimize. - - - - - + + + + + + diff --git a/content/800-guides/010-data-migration.mdx b/content/800-guides/010-data-migration.mdx index 24b98c97b6..9f8893c69c 100644 --- a/content/800-guides/010-data-migration.mdx +++ b/content/800-guides/010-data-migration.mdx @@ -61,7 +61,36 @@ model Post { } ``` -### 1.2. Create a development branch +### 1.2. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=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 + +You'll need to install the `dotenv` package to load environment variables. If you haven't already, install it using your package manager: + +```bash +npm install dotenv +``` + +::: + +### 1.3. Create a development branch Create a new branch for your changes: diff --git a/content/800-guides/020-implementing-schema-changes.mdx b/content/800-guides/020-implementing-schema-changes.mdx index a5d8342766..83a4f30211 100644 --- a/content/800-guides/020-implementing-schema-changes.mdx +++ b/content/800-guides/020-implementing-schema-changes.mdx @@ -47,6 +47,35 @@ Source-controlling the `schema.prisma` file is not enough - you must include you - Customized migrations contain information that cannot be represented in the Prisma schema - The `prisma migrate deploy` command only runs migration files +### 1.3. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=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 + +You'll need to install the `dotenv` package to load environment variables. If you haven't already, install it using your package manager: + +```bash +npm install dotenv +``` + +::: + ## 2. Incorporate team changes ### 2.1. Pull latest changes diff --git a/content/800-guides/030-migrate-from-typeorm.mdx b/content/800-guides/030-migrate-from-typeorm.mdx index 210e5bd1be..4b852ac2b9 100644 --- a/content/800-guides/030-migrate-from-typeorm.mdx +++ b/content/800-guides/030-migrate-from-typeorm.mdx @@ -51,6 +51,35 @@ Update the `DATABASE_URL` in the `.env` file with your database connection strin DATABASE_URL="postgresql://USER:PASSWORD@HOST:PORT/DATABASE" ``` +### 2.3. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=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 + +You'll need to install the `dotenv` package to load environment variables. If you haven't already, install it using your package manager: + +```bash +npm install dotenv +``` + +::: + ## 3. Migrate the database schema ### 3.1. Introspect your database diff --git a/content/800-guides/040-migrate-from-sequelize.mdx b/content/800-guides/040-migrate-from-sequelize.mdx index 4abf2e8fac..bc98456af4 100644 --- a/content/800-guides/040-migrate-from-sequelize.mdx +++ b/content/800-guides/040-migrate-from-sequelize.mdx @@ -78,6 +78,35 @@ Update the `DATABASE_URL` in the `.env` file with your database connection strin DATABASE_URL="postgresql://USER:PASSWORD@HOST:PORT/DATABASE" ``` +### 1.3. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=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 + +You'll need to install the `dotenv` package to load environment variables. If you haven't already, install it using your package manager: + +```bash +npm install dotenv +``` + +::: + ## 2. Migrate the database schema ### 2.1. Introspect your database diff --git a/content/800-guides/050-migrate-from-mongoose.mdx b/content/800-guides/050-migrate-from-mongoose.mdx index 3143c942f0..e9a4b2b306 100644 --- a/content/800-guides/050-migrate-from-mongoose.mdx +++ b/content/800-guides/050-migrate-from-mongoose.mdx @@ -78,6 +78,35 @@ Update the `DATABASE_URL` in the `.env` file with your MongoDB connection string DATABASE_URL="mongodb://USER:PASSWORD@HOST:PORT/DATABASE" ``` +### 1.3. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=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 + +You'll need to install the `dotenv` package to load environment variables. If you haven't already, install it using your package manager: + +```bash +npm install dotenv +``` + +::: + ## 2. Migrate the database schema ### 2.1. Introspect your database diff --git a/content/800-guides/060-migrate-from-drizzle.mdx b/content/800-guides/060-migrate-from-drizzle.mdx index 53b6e57d18..0fe8942aca 100644 --- a/content/800-guides/060-migrate-from-drizzle.mdx +++ b/content/800-guides/060-migrate-from-drizzle.mdx @@ -150,7 +150,36 @@ datasource db { Once that's done, you can configure your [database connection URL](/orm/reference/connection-urls) in the `.env` file. Drizzle and Prisma ORM use the same format for connection URLs, so your existing connection URL should work fine. -### 2.3. Introspect your database using Prisma ORM +### 2.3. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=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 + +You'll need to install the `dotenv` package to load environment variables. If you haven't already, install it using your package manager: + +```bash +npm install dotenv +``` + +::: + +### 2.4. Introspect your database using Prisma ORM With your connection URL in place, you can [introspect](/orm/prisma-schema/introspection) your database to generate your Prisma models: @@ -170,7 +199,7 @@ model todo { The generated Prisma model represents a database table. Prisma models are the foundation for your programmatic Prisma Client API which allows you to send queries to your database. -### 2.4. Create a baseline migration +### 2.5. Create a baseline migration To continue using Prisma Migrate to evolve your database schema, you will need to [baseline your database](/orm/prisma-migrate/getting-started). @@ -202,7 +231,7 @@ The command will mark `0_init` as applied by adding it to the `_prisma_migration You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. -### 2.5. Adjust the Prisma schema (optional) +### 2.6. Adjust the Prisma schema (optional) Models that are generated via introspection currently _exactly_ map to your database tables. In this section, you'll learn how you can adjust the naming of the Prisma models to adhere to [Prisma ORM's naming conventions](/orm/reference/prisma-schema-reference#naming-conventions). diff --git a/content/800-guides/070-cloudflare-d1.mdx b/content/800-guides/070-cloudflare-d1.mdx index 7264a75355..9dbb973915 100644 --- a/content/800-guides/070-cloudflare-d1.mdx +++ b/content/800-guides/070-cloudflare-d1.mdx @@ -179,7 +179,7 @@ CLOUDFLARE_D1_TOKEN="F8Cg..." Ensure that you have a `prisma.config.ts` file set up in the root of your project with a [driver adapter](/orm/reference/prisma-config-reference#adapter) defined. -```ts +```typescript file=prisma.config.ts import type { PrismaConfig } from 'prisma'; import { PrismaD1 } from '@prisma/adapter-d1'; @@ -191,6 +191,12 @@ export default { adapter: true, }, schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + }, + datasource: { + url: process.env.DATABASE_URL!, + }, async adapter() { return new PrismaD1({ CLOUDFLARE_D1_TOKEN: process.env.CLOUDFLARE_D1_TOKEN!, diff --git a/content/800-guides/080-turborepo.mdx b/content/800-guides/080-turborepo.mdx index 6580182f7b..f0dd46e806 100644 --- a/content/800-guides/080-turborepo.mdx +++ b/content/800-guides/080-turborepo.mdx @@ -94,7 +94,7 @@ Next, install the required dependencies to use Prisma ORM. Use your preferred pa ```terminal npm install prisma --save-dev -npm install @prisma/client +npm install @prisma/client dotenv ``` @@ -103,7 +103,7 @@ npm install @prisma/client ```terminal yarn add prisma --dev -yarn add @prisma/client +yarn add @prisma/client dotenv ``` @@ -112,7 +112,7 @@ yarn add @prisma/client ```terminal pnpm add prisma --save-dev -pnpm add @prisma/client +pnpm add @prisma/client dotenv ``` @@ -222,6 +222,23 @@ model Post { //add-end ``` +The `prisma.config.ts` file created in the `packages/database` directory should look like this: + +```typescript file=packages/database/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'), + }, +}); +``` + :::warning It is recommended to add `../generated/prisma` to the `.gitignore` file because it contains platform-specific binaries that can cause compatibility issues across different environments. @@ -335,7 +352,7 @@ Navigate to the project root and run the following command to automatically migr -Generate your `prisma.schema` +Generate your `schema.prisma` To generate the types from Prisma schema, from the project root run: diff --git a/content/800-guides/090-nextjs.mdx b/content/800-guides/090-nextjs.mdx index 445d252b3e..1b55438503 100644 --- a/content/800-guides/090-nextjs.mdx +++ b/content/800-guides/090-nextjs.mdx @@ -139,17 +139,17 @@ This creates two models: `User` and `Post`, with a one-to-many relationship betw To get access to the variables in the `.env` file, they can either be loaded by your runtime, or by using `dotenv`. Include an import for `dotenv` at the top of the `prisma.config.ts` -```ts +```typescript file=prisma.config.ts //add-start import 'dotenv/config' //add-end import { defineConfig, env } from 'prisma/config'; + export default defineConfig({ schema: 'prisma/schema.prisma', migrations: { path: 'prisma/migrations' }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -218,9 +218,10 @@ main(); Now, tell Prisma how to run this script by updating your `prisma.config.ts`: -```ts file=prisma.config.ts +```typescript file=prisma.config.ts import 'dotenv/config' import { defineConfig, env } from 'prisma/config'; + export default defineConfig({ schema: 'prisma/schema.prisma', migrations: { @@ -229,7 +230,6 @@ export default defineConfig({ seed: `tsx prisma/seed.ts`, //add-end }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, diff --git a/content/800-guides/100-nuxt.mdx b/content/800-guides/100-nuxt.mdx index c35659aa03..11aa72da40 100644 --- a/content/800-guides/100-nuxt.mdx +++ b/content/800-guides/100-nuxt.mdx @@ -62,7 +62,36 @@ To follow this guide, ensure you have the following: }); ``` -## 2. Setup Prisma ORM by running the development server locally +## 2. Configure Prisma + +Before running the development server, create a `prisma.config.ts` file in the root of your project to manage environment variables and configuration: + +```typescript file=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 + +You'll need to install the `dotenv` package to load environment variables: + +```bash +npm install dotenv +``` + +::: + +## 3. Setup Prisma ORM by running the development server locally After configuring your Nuxt project with the Prisma module, the next step is to set up Prisma ORM. This process begins by starting the development server, which automatically configures Prisma with a [SQLite database](/orm/overview/databases/sqlite). @@ -121,7 +150,7 @@ Once the setup flow has terminated, it: 5. Installed and generated [Prisma Client](https://da-2255.docs-51g.pages.dev/orm/reference/prisma-client-reference) which enables you to query your DB. 6. Installed [Prisma Studio](/orm/tools/prisma-studio). -When the Prisma setup is complete, the development server should start on `https://localhost:3000`. +When the Prisma setup is complete, the development server should start on `https://localhost:3000`. Next, stop the server, as we need to make some code changes. diff --git a/content/800-guides/130-docker.mdx b/content/800-guides/130-docker.mdx index b6d6e1684d..c8c24a5838 100644 --- a/content/800-guides/130-docker.mdx +++ b/content/800-guides/130-docker.mdx @@ -126,6 +126,33 @@ In the `schema.prisma` file, we specify a [custom `output` path](/orm/prisma-cli ::: +Now, create a `prisma.config.ts` file in the root of your project: + +```typescript file=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 + +You'll need to install the `dotenv` package to load environment variables: + +```bash +npm install dotenv +``` + +::: + ### 1.4. Create an Express.js server With the Prisma schema in place, let's create an Express.js server to interact with the database. Start by creating an `index.js` file: diff --git a/content/800-guides/140-use-prisma-in-pnpm-workspaces.mdx b/content/800-guides/140-use-prisma-in-pnpm-workspaces.mdx index 388b68f1c8..45757bd01a 100644 --- a/content/800-guides/140-use-prisma-in-pnpm-workspaces.mdx +++ b/content/800-guides/140-use-prisma-in-pnpm-workspaces.mdx @@ -161,6 +161,35 @@ model User { //add-end ``` +Now, create a `prisma.config.ts` file in the `database` package to configure Prisma: + +```typescript file=database/prisma.config.ts +// add-start +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'), + }, +}); +// add-end +``` + +:::note + +You'll need to install the `dotenv` package to load environment variables from the `.env` file: + +```terminal +pnpm add dotenv +``` + +::: + Next, add helper scripts to your `package.json` to simplify Prisma commands: ```json file=database/package.json diff --git a/content/800-guides/150-multiple-databases.mdx b/content/800-guides/150-multiple-databases.mdx index f3dd98f223..f304134f9c 100644 --- a/content/800-guides/150-multiple-databases.mdx +++ b/content/800-guides/150-multiple-databases.mdx @@ -146,6 +146,35 @@ model User { //add-end ``` +Create a `prisma.config.ts` file for the user database: + +```typescript file=prisma-user-database/prisma.config.ts +//add-start +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma-user-database/schema.prisma', + migrations: { + path: 'prisma-user-database/migrations', + }, + datasource: { + url: env('PPG_USER_DATABASE_URL'), + }, +}); +//add-end +``` + +:::note + +You'll need to install the `dotenv` package if you haven't already: + +```terminal +npm install dotenv +``` + +::: + Your user database schema is now ready. ### 2.2. Create a Prisma Postgres instance for post data @@ -197,12 +226,31 @@ datasource db { //add-start model Post { id Int @id @default(autoincrement()) - title String + title String content String? } //add-end ``` +Create a `prisma.config.ts` file for the post database: + +```typescript file=prisma-post-database/prisma.config.ts +//add-start +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma-post-database/schema.prisma', + migrations: { + path: 'prisma-post-database/migrations', + }, + datasource: { + url: env('PPG_POST_DATABASE_URL'), + }, +}); +//add-end +``` + Your post database schema is now set. ### 2.3. Add helper scripts and migrate the schemas diff --git a/content/800-guides/160-tanstack-start.mdx b/content/800-guides/160-tanstack-start.mdx index 971908e4d4..a288dbd61b 100644 --- a/content/800-guides/160-tanstack-start.mdx +++ b/content/800-guides/160-tanstack-start.mdx @@ -390,7 +390,6 @@ export default defineConfig({ migrations: { path: 'prisma/migrations', }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -468,7 +467,6 @@ export default defineConfig({ seed: `tsx prisma/seed.ts`, //add-end }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, diff --git a/content/800-guides/170-react-router-7.mdx b/content/800-guides/170-react-router-7.mdx index 6cd1474854..c953dd4990 100644 --- a/content/800-guides/170-react-router-7.mdx +++ b/content/800-guides/170-react-router-7.mdx @@ -129,7 +129,6 @@ export default defineConfig({ migrations: { path: 'prisma/migrations', }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -209,7 +208,6 @@ export default defineConfig({ seed: `tsx prisma/seed.ts`, //add-end }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, diff --git a/content/800-guides/180-solid-start.mdx b/content/800-guides/180-solid-start.mdx index 705eaf4a58..85e99aeff7 100644 --- a/content/800-guides/180-solid-start.mdx +++ b/content/800-guides/180-solid-start.mdx @@ -149,7 +149,6 @@ export default defineConfig({ migrations: { path: 'prisma/migrations', }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -230,7 +229,6 @@ export default defineConfig({ seed: `tsx prisma/seed.ts`, //add-end }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, diff --git a/content/800-guides/190-data-dog.mdx b/content/800-guides/190-data-dog.mdx index 41d7894df3..fcba863180 100644 --- a/content/800-guides/190-data-dog.mdx +++ b/content/800-guides/190-data-dog.mdx @@ -182,6 +182,35 @@ model Post { //add-end ``` +Create a `prisma.config.ts` file to configure Prisma: + +```typescript file=prisma.config.ts +//add-start +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'), + }, +}); +//add-end +``` + +:::note + +You'll need to install the `dotenv` package if you haven't already: + +```terminal +npm install dotenv +``` + +::: + ### 2.3. Generate the Prisma Client and run migrations Generate the Prisma Client and apply your schema to your database: diff --git a/content/800-guides/190-sveltekit.mdx b/content/800-guides/190-sveltekit.mdx index 9031029e71..7625b273aa 100644 --- a/content/800-guides/190-sveltekit.mdx +++ b/content/800-guides/190-sveltekit.mdx @@ -143,7 +143,6 @@ export default defineConfig({ migrations: { path: 'prisma/migrations', }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -223,7 +222,6 @@ export default defineConfig({ seed: `tsx prisma/seed.ts`, //add-end }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, diff --git a/content/800-guides/200-clerk-nextjs.mdx b/content/800-guides/200-clerk-nextjs.mdx index 4d4409fa5d..e1fcfd2810 100644 --- a/content/800-guides/200-clerk-nextjs.mdx +++ b/content/800-guides/200-clerk-nextjs.mdx @@ -286,6 +286,35 @@ model Post { 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 file=prisma.config.ts showLineNumbers +//add-start +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'), + }, +}); +//add-end +``` + +:::note + +You'll need to install the `dotenv` package: + +```terminal +npm install dotenv +``` + +::: + Now, run the following command to create the database tables and generate the Prisma Client: ```terminal diff --git a/content/800-guides/210-shopify.mdx b/content/800-guides/210-shopify.mdx index b8a9eca491..81c9e4afa9 100644 --- a/content/800-guides/210-shopify.mdx +++ b/content/800-guides/210-shopify.mdx @@ -85,6 +85,35 @@ model Session { } ``` +Create a `prisma.config.ts` file to configure Prisma: + +```typescript file=prisma.config.ts +//add-start +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'), + }, +}); +//add-end +``` + +:::note + +Since Shopify apps typically have dotenv pre-installed, you should already have access to it. If not, install it with: + +```terminal +npm install dotenv +``` + +::: + To enable your app to store notes for each product, let's add a new `ProductNote` model to your Prisma schema. This model will allow you to save and organize notes linked to individual products in your database through the `productGid` field. diff --git a/content/800-guides/220-astro.mdx b/content/800-guides/220-astro.mdx index ccd930ce0b..ad28d9a98c 100644 --- a/content/800-guides/220-astro.mdx +++ b/content/800-guides/220-astro.mdx @@ -130,7 +130,6 @@ export default defineConfig({ migrations: { path: 'prisma/migrations', }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, @@ -223,7 +222,6 @@ export default defineConfig({ path: 'prisma/migrations', seed: `tsx prisma/seed.ts`, }, - engine: 'classic', datasource: { url: env('DATABASE_URL'), }, diff --git a/content/800-guides/230-betterauth-nextjs.mdx b/content/800-guides/230-betterauth-nextjs.mdx index 5a048fb22c..7caaccb31d 100644 --- a/content/800-guides/230-betterauth-nextjs.mdx +++ b/content/800-guides/230-betterauth-nextjs.mdx @@ -1,8 +1,8 @@ --- -title: 'How to use Prisma ORM with Better-Auth and Next.js' -metaTitle: 'How to use Prisma ORM and Prisma Postgres with Better-Auth and Next.js' -description: 'Learn how to use Prisma ORM in a Next.js app with Better-Auth' -sidebar_label: 'Better-Auth (with Next.js)' +title: 'How to use Prisma ORM with Better Auth and Next.js' +metaTitle: 'How to use Prisma ORM and Prisma Postgres with Better Auth and Next.js' +description: 'Learn how to use Prisma ORM in a Next.js app with Better Auth' +sidebar_label: 'Better Auth (with Next.js)' image: '/img/guides/prisma-betterauth-nextjs-cover.png' completion_time: '25 min' community_section: true @@ -10,9 +10,9 @@ community_section: true ## Introduction -[Better-Auth](https://better-auth.com/) is a modern, open-source authentication solution for web applications. It's built with TypeScript, React, and Prisma to provide a simple and extensible auth experience. +[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). +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 @@ -78,17 +78,46 @@ Once installed, initialize Prisma in your project: 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" +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`. +- 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 the Prisma client generator +### 2.2. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=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: + +```bash +npm install dotenv +``` + +::: + +### 2.3. Generate the Prisma client Run the following command to create the database tables and generate the Prisma Client: @@ -96,9 +125,9 @@ Run the following command to create the database tables and generate the Prisma npx prisma generate ``` -### 2.3. Set up a global Prisma client +### 2.4. Set up a global Prisma client -Create a `/lib` directory and a `prisma.ts` file inside it. This file will be used to create and export your Prisma Client instance. +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. ```terminal mkdir -p src/lib @@ -149,19 +178,19 @@ We recommend using a connection pooler (like [Prisma Accelerate](https://www.pri 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 +## 3. Set up Better Auth -Now it's time to integrate Better-Auth for authentication. +Now it's time to integrate Better Auth for authentication. -### 3.1. Install and configure Better-Auth +### 3.1. Install and configure Better Auth -First, install the Better-Auth core package: +First, install the Better Auth core package: ```terminal 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. +Next, generate a secure secret that Better Auth will use to sign authentication tokens. This ensures your tokens cannot be messed with. ```terminal npx @better-auth/cli@latest secret @@ -170,7 +199,7 @@ npx @better-auth/cli@latest secret Copy the generated secret and add it, along with your application's URL, to your `.env` file: ```dotenv file=.env showLineNumbers -# Better-Auth +# Better Auth //add-start BETTER_AUTH_SECRET=your-generated-secret BETTER_AUTH_URL=http://localhost:3000 @@ -180,13 +209,13 @@ BETTER_AUTH_URL=http://localhost:3000 DATABASE_URL="your-database-url" ``` -Now, create a configuration file for Better-Auth at `src/lib/auth.ts`: +Now, create a configuration file for Better Auth. In the `src/lib` directory, create an `auth.ts` file: ```terminal 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. +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 file=src/lib/auth.ts import { betterAuth } from 'better-auth' @@ -200,7 +229,7 @@ export const auth = betterAuth({ }) ``` -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). +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 file=src/lib/auth.ts import { betterAuth } from 'better-auth' @@ -240,9 +269,9 @@ export const auth = betterAuth({ ``` ::: -### 3.2. Add Better-Auth models to your schema +### 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. +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: @@ -325,20 +354,18 @@ With the new models in your schema, you need to update your database. Run a migr npx prisma migrate dev --name add-auth-models ``` -
- ## 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]`. +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]`. -First, create the necessary directory and file: +In the `src/app/api` directory, create an `auth/[...all]` folder structure and a `route.ts` file inside it: ```terminal 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. +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"; @@ -347,7 +374,7 @@ 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. Create a new file `src/lib/auth-client.ts`: +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: ```terminal touch src/lib/auth-client.ts @@ -363,7 +390,11 @@ export const { signIn, signUp, signOut, useSession } = createAuthClient() ## 5. Set up your pages -Now, let's build the user interface for authentication. Create the pages for signing up, signing in, and a protected dashboard: +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` ```terminal mkdir -p src/app/{sign-up,sign-in,dashboard} @@ -410,7 +441,7 @@ export default function SignUpPage() { } ``` -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. +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 file=src/app/sign-up/page.tsx "use client"; @@ -611,7 +642,7 @@ export default function SignInPage() { } ``` -Add the `handleSubmit` function, this time importing and using the `signIn.email` method from Better-Auth. +Add the `handleSubmit` function, this time importing and using the `signIn.email` method from Better Auth. ```tsx file=src/app/sign-in/page.tsx "use client"; @@ -778,7 +809,7 @@ export default function DashboardPage() { } ``` -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. +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 file=src/app/dashboard/page.tsx "use client"; @@ -816,7 +847,7 @@ export default function DashboardPage() { const router = useRouter(); const { data: session, isPending } = useSession(); - //add-start: redirect if not signed in + //add-start useEffect(() => { if (!isPending && !session?.user) { router.push("/sign-in"); @@ -851,7 +882,7 @@ export default function DashboardPage() { } }, [isPending, session, router]); - //add-start: loading and redirect states + //add-start if (isPending) return

Loading...

; if (!session?.user) @@ -890,7 +921,7 @@ export default function DashboardPage() { if (!session?.user) return

Redirecting...

; - //add-start: destructure user from session + //add-start const { user } = session; //add-end @@ -899,7 +930,7 @@ export default function DashboardPage() {

Dashboard

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

Email: {user.email}

- {/* add-start: sign out button */} + {/* add-start */} + +

Already have an account? Sign in here.

+ //add-end + + + +``` + +Now add a script to handle form submission. Import the `authClient` and add an event listener to the form that prevents the default submission behavior, extracts the form data, and calls the Better Auth sign-up method. + +```html file=src/pages/sign-up/index.astro +--- +export const prerender = false; +--- + + + + + + Sign Up + + +
+

Sign Up

+
+ + + + +
+

Already have an account? Sign in here.

+
+ //add-start + + //add-end + + +``` + +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 file=src/pages/sign-up/index.astro +--- +export const prerender = false; + +//add-start +if (Astro.locals.user?.id) return Astro.redirect("/dashboard"); +//add-end +--- + + + + + + 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 file=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 file=src/pages/sign-in/index.astro +--- +export const prerender = false; +--- + + + + + + Sign In + + +
+

Sign In

+ //add-start +
+ + + +
+

Don't have an account? Sign up here.

+ //add-end +
+ + +``` + +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 file=src/pages/sign-in/index.astro +--- +export const prerender = false; +--- + + + + + + Sign In + + +
+

Sign In

+
+ + + +
+

Don't have an account? Sign up here.

+
+ //add-start + + //add-end + + +``` + +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 file=src/pages/sign-in/index.astro +--- +export const prerender = false; + +//add-start +if (Astro.locals.user?.id) return Astro.redirect("/dashboard"); +//add-end +--- + + + + + + 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 file=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 file=src/pages/dashboard/index.astro +--- +export const prerender = false; + +//add-start +if (!Astro.locals.user?.id) return Astro.redirect("/sign-in"); +//add-end +--- + + + + + + 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 file=src/pages/dashboard/index.astro +--- +export const prerender = false; + +if (!Astro.locals.user?.id) return Astro.redirect("/sign-in"); +--- + + + + + + Dashboard + + +
+

Dashboard

+ //add-next-line +
{JSON.stringify(Astro.locals.user, null, 2)}
+
+ + +``` + +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 file=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)}
+ //add-next-line + +
+ //add-start + + //add-end + + +``` + +### 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 file=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: + +```terminal +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. + +```terminal +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](/orm/overview/introduction) +- [Astro documentation](https://astro.build/docs) diff --git a/content/800-guides/999-making-guides.mdx b/content/800-guides/999-making-guides.mdx index b8d2a04f8f..8186c8145c 100644 --- a/content/800-guides/999-making-guides.mdx +++ b/content/800-guides/999-making-guides.mdx @@ -344,14 +344,47 @@ model Post { This creates two models: `User` and `Post`, with a one-to-many relationship between them. -### 2.3. Configure the Prisma Client generator +### 2.3. Configure Prisma + +Create a `prisma.config.ts` file in the root of your project with the following content: + +```typescript file=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 + +You'll need to install the `dotenv` package to load environment variables: + +```bash +npm install dotenv +``` + +::: + +:::warning +***DEV NOTE:*** If your guide includes database seeding, you'll update this config file later to add the `seed` field in the migrations section. See the seeding section below for an example. +::: + +### 2.4. Generate Prisma Client and run migrations Now, run the following command to create the database tables and generate the Prisma Client: ```terminal npx prisma migrate dev --name init ``` -### 2.4. Seed the database +### 2.5. Seed the database Add some seed data to populate the database with sample users and posts. @@ -404,16 +437,24 @@ export async function main() { main(); ``` -Now, tell Prisma how to run this script by updating your `package.json`: +Create a `prisma.config.ts` file to configure Prisma with seeding: -```json file=package.json -... rest of the file +```typescript file=prisma.config.ts //add-start -"prisma": { - "seed": "tsx prisma/seed.ts" -} +import 'dotenv/config' +import { defineConfig, env } from 'prisma/config'; + +export default defineConfig({ + schema: 'prisma/schema.prisma', + migrations: { + path: 'prisma/migrations', + seed: `tsx prisma/seed.ts`, + }, + datasource: { + url: env('DATABASE_URL'), + }, +}); //add-end -... rest of the file ``` Run the seed script: diff --git a/content/900-ai/prompts/astro.mdx b/content/900-ai/prompts/astro.mdx index 2fb3fe5caa..473c95d336 100644 --- a/content/900-ai/prompts/astro.mdx +++ b/content/900-ai/prompts/astro.mdx @@ -260,3 +260,29 @@ When asked about Prisma + Astro implementation, you MUST: Remember: There are NO EXCEPTIONS to these rules. ```` + +## Running the application + +Get your application running locally in three quick steps: + +**1. Generate the Prisma Client:** + +```terminal +npx prisma generate --no-engine +``` + +**2. View your database in Prisma Studio:** + +```terminal +npm run db:studio +``` + +Prisma Studio opens at `localhost:5555` where you can inspect your `User` table and see the test user stored in your database. + +**3. Start your Next.js development server:** + +```terminal +npm run dev +``` + +Visit `http://localhost:3000` to see your Next.js application live, displaying your first user fetched directly from your Prisma Postgres database! \ No newline at end of file diff --git a/content/900-ai/prompts/nextjs.mdx b/content/900-ai/prompts/nextjs.mdx index 329da64442..a2a01ec1aa 100644 --- a/content/900-ai/prompts/nextjs.mdx +++ b/content/900-ai/prompts/nextjs.mdx @@ -15,6 +15,22 @@ Include this prompt in your AI assistant to guide consistent code generation for - **Zed**: Use `/file` followed by your prompt's path. - **Windsurf**: Use `@Files` and choose your prompt file from the list. +## Video Tutorial + +Watch this step-by-step walkthrough showing this prompt in action: + +
+ +
+ ## Prompt ````md diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 5bc27295e3..6807372575 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -4,6 +4,7 @@ import { themes as prismThemes } from "prism-react-renderer"; import type { Config, RouteConfig } from "@docusaurus/types"; import type * as Preset from "@docusaurus/preset-classic"; +import type { PluginOptions } from "@signalwire/docusaurus-plugin-llms-txt/public"; const DOCUSAURUS_BASE_URL = process.env.DOCUSAURUS_BASE_URL ?? "/"; @@ -91,6 +92,21 @@ const config: Config = { enableInDevelopment: false, }, ], + [ + "@signalwire/docusaurus-plugin-llms-txt", + { + // Enable with defaults + generate: { + enableMarkdownFiles: true, + enableLlmsFullTxt: false, + }, + include: { + includeBlog: false, + includePages: false, + includeDocs: true, + }, + } satisfies PluginOptions, + ], async function pluginLlmsTxt(context) { return { name: "llms-txt-plugin", @@ -297,7 +313,7 @@ const config: Config = { to: "/postgres/database/prisma-studio", label: "Studio", sub: "Explore and manipulate your data", - icon: "fa-regular fa-table" + icon: "fa-regular fa-table", }, { type: "docSidebar", @@ -305,7 +321,7 @@ const config: Config = { className: "teal", label: "Optimize", sub: "AI-driven query analysis", - icon: "fa-regular fa-magnifying-glass-chart" + icon: "fa-regular fa-magnifying-glass-chart", }, { type: "docSidebar", @@ -313,7 +329,7 @@ const config: Config = { className: "teal", label: "Accelerate", sub: "Make your database global", - icon: "fa-regular fa-bolt" + icon: "fa-regular fa-bolt", }, { type: "docSidebar", @@ -321,7 +337,7 @@ const config: Config = { sidebarId: "aiSidebar", label: "Prisma + AI", sub: "Build faster with Prisma + AI", - icon: "fa-regular fa-robot" + icon: "fa-regular fa-robot", }, ], }, diff --git a/functions/_middleware.ts b/functions/_middleware.ts new file mode 100644 index 0000000000..cfd258bc87 --- /dev/null +++ b/functions/_middleware.ts @@ -0,0 +1,113 @@ +interface Env { + ASSETS: { + fetch: typeof fetch; + }; +} + +const AI_CRAWLER_PATTERNS = [ + 'GPTBot', + 'OAI-SearchBot', + 'ChatGPT-User', + 'ChatGPT-User 2.0', + 'anthropic-ai', + 'OpenAI', + 'ClaudeBot', + 'claude-web', + 'Claude/', + 'Claude-User', + 'anthropic', + 'PerplexityBot', + 'Perplexity-User', + 'Google-Extended', + 'BingBot', + 'Amazonbot', + 'Applebot', + 'Applebot-Extended', + 'FacebookBot', + 'meta-externalagent', + 'LinkedInBot', + 'Bytespider', + 'AI2Bot', + 'CCBot', + 'Diffbot', + 'DuckAssistBot', + 'DuckDuckGo', + 'DeepSeekBot', + 'cohere-ai', + 'omgili', + 'TimpiBot', + 'YouBot', + 'MistralAI-User', + 'ImagesiftBot', + 'Scrapy', + + 'chatgpt', + 'openai', + 'gpt', + 'claude', + 'anthropic', + 'cursor', + 'windsurf', + 'perplexity', + 'copilot', + 'ai-agent', + 'llm-agent', +]; + +function isAICrawler(request: Request): boolean { + // if (!userAgent) return false; + + const userAgent = request.headers.get('user-agent') || ''; + const accept = request.headers.get('accept') || ''; + + const hasHtml = accept.includes('text/html'); + + const prefersNonHtml = + !hasHtml && + (accept.includes('application/json') || + accept.includes('text/plain') || + accept.includes('application/xml')); + + const hasAiUserAgent = AI_CRAWLER_PATTERNS.some((pattern) => userAgent.toLowerCase().includes(pattern.toLowerCase())); + + return prefersNonHtml || hasAiUserAgent + + // const normalizedUA = userAgent.toLowerCase(); + // return AI_CRAWLER_PATTERNS.some((pattern) => normalizedUA.includes(pattern.toLowerCase())); +} + +export const onRequest: PagesFunction = async (context) => { + const { request, next } = context; + + if (isAICrawler(request)) { + const url = new URL(request.url); + const urlPath = url.pathname; + + const markdownPath = `${urlPath}.md`; + + const markdownRequest = new Request(new URL(markdownPath, url.origin), { + method: request.method, + headers: request.headers, + }); + + const response = await context.env.ASSETS.fetch(markdownRequest); + + if (response.ok) { + // Check what content type we actually got + const actualContentType = response.headers.get('content-type'); + console.log(`Fetched ${markdownPath}, got content-type: ${actualContentType}`); + + return new Response(response.body, { + status: 200, + headers: { + 'Content-Type': 'text/markdown; charset=utf-8', + 'Cache-Control': 'public, max-age=3600', + }, + }); + } + + return next(); + } + + return next(); +}; diff --git a/functions/types.d.ts b/functions/types.d.ts new file mode 100644 index 0000000000..86ad944860 --- /dev/null +++ b/functions/types.d.ts @@ -0,0 +1,12 @@ +// TypeScript definitions for Cloudflare Pages Functions +interface EventContext { + request: Request; + env: Env; + params: Record; + data: Record; + next: () => Promise; + waitUntil: (promise: Promise) => void; + passThroughOnException: () => void; +} + +type PagesFunction = (context: EventContext) => Response | Promise; diff --git a/package-lock.json b/package-lock.json index b57e49bc85..128d01fdb5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@react-aria/overlays": "^3.29.1", "@react-aria/tooltip": "^3.8.7", "@react-aria/utils": "^3.24.1", + "@signalwire/docusaurus-plugin-llms-txt": "^2.0.0-alpha.2", "clsx": "^2.1.1", "copy-text-to-clipboard": "^3.1.0", "docusaurus-plugin-sass": "^0.2.6", @@ -6511,6 +6512,44 @@ "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", "license": "BSD-3-Clause" }, + "node_modules/@signalwire/docusaurus-plugin-llms-txt": { + "version": "2.0.0-alpha.2", + "resolved": "https://registry.npmjs.org/@signalwire/docusaurus-plugin-llms-txt/-/docusaurus-plugin-llms-txt-2.0.0-alpha.2.tgz", + "integrity": "sha512-jLATcj60UE4/iYtrB4xbBqki9/+WSf2t/BQ2hcszzTnm1Rafl+kW7ykh1TXQSeq97nQaL6zTDzsJYrIdcFig1A==", + "license": "MIT", + "dependencies": { + "fs-extra": "^11.0.0", + "hast-util-select": "^6.0.4", + "hast-util-to-html": "^9.0.5", + "hast-util-to-string": "^3.0.1", + "p-map": "^7.0.2", + "rehype-parse": "^9", + "rehype-remark": "^10", + "remark-gfm": "^4", + "remark-stringify": "^11", + "string-width": "^5.0.0", + "unified": "^11", + "unist-util-visit": "^5" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@docusaurus/core": "^3.0.0" + } + }, + "node_modules/@signalwire/docusaurus-plugin-llms-txt/node_modules/p-map": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -11667,6 +11706,20 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-embedded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-3.0.0.tgz", + "integrity": "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-from-dom": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz", @@ -11749,6 +11802,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-is-body-ok-link": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-3.0.1.tgz", + "integrity": "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-is-element": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", @@ -11762,6 +11828,23 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-minify-whitespace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hast-util-minify-whitespace/-/hast-util-minify-whitespace-1.0.1.tgz", + "integrity": "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-parse-selector": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", @@ -11775,6 +11858,23 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-phrasing": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-3.0.1.tgz", + "integrity": "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-is-body-ok-link": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-raw": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", @@ -11855,6 +11955,29 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-jsx-runtime": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", @@ -11882,6 +12005,32 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-mdast": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/hast-util-to-mdast/-/hast-util-to-mdast-10.1.2.tgz", + "integrity": "sha512-FiCRI7NmOvM4y+f5w32jPRzcxDIz+PUqDwEqn1A+1q2cdp3B8Gx7aVrXORdOKjMNDQsD1ogOr896+0jJHW1EFQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-phrasing": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "hast-util-to-text": "^4.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-minify-whitespace": "^6.0.0", + "trim-trailing-lines": "^2.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-parse5": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", @@ -11924,6 +12073,22 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-whitespace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", @@ -18919,6 +19084,35 @@ "regjsparser": "bin/parser" } }, + "node_modules/rehype-minify-whitespace": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/rehype-minify-whitespace/-/rehype-minify-whitespace-6.0.2.tgz", + "integrity": "sha512-Zk0pyQ06A3Lyxhe9vGtOtzz3Z0+qZ5+7icZ/PL/2x1SHPbKao5oB/g/rlc6BCTajqBb33JcOe71Ye1oFsuYbnw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-minify-whitespace": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-html": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-raw": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", @@ -18949,6 +19143,23 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-remark": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-remark/-/rehype-remark-10.0.1.tgz", + "integrity": "sha512-EmDndlb5NVwXGfUa4c9GPK+lXeItTilLhE6ADSaQuHr4JUlKw9MidzGzx4HpqZrNCt6vnHmEifXQiiA+CEnjYQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "hast-util-to-mdast": "^10.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -20702,6 +20913,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/trim-trailing-lines": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-2.1.0.tgz", + "integrity": "sha512-5UR5Biq4VlVOtzqkm2AZlgvSlDJtME46uV0br0gENbwN4l5+mMKT4b9gJKqWtuL2zAIqajGJGuvbCbcAJUZqBg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/trough": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", @@ -20922,6 +21143,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-is": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", diff --git a/package.json b/package.json index f9989b6807..93af9e443b 100644 --- a/package.json +++ b/package.json @@ -24,9 +24,10 @@ "@react-aria/overlays": "^3.29.1", "@react-aria/tooltip": "^3.8.7", "@react-aria/utils": "^3.24.1", + "@signalwire/docusaurus-plugin-llms-txt": "^2.0.0-alpha.2", "clsx": "^2.1.1", - "docusaurus-plugin-sass": "^0.2.6", "copy-text-to-clipboard": "^3.1.0", + "docusaurus-plugin-sass": "^0.2.6", "posthog-docusaurus": "^2.0.4", "prism-react-renderer": "^2.4.1", "react": "^19.1.1", diff --git a/sidebars.ts b/sidebars.ts index e38be5d27a..1240220659 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -447,6 +447,7 @@ const sidebars: SidebarsConfig = { "guides/clerk-nextjs", "guides/shopify", "guides/permit-io-access-control", + "guides/betterauth-astro", "guides/betterauth-nextjs", "guides/ai-sdk-nextjs", "guides/authjs-nextjs", diff --git a/src/components/GettingStarted/index.tsx b/src/components/GettingStarted/index.tsx index 92a0986c82..cfcab301c7 100644 --- a/src/components/GettingStarted/index.tsx +++ b/src/components/GettingStarted/index.tsx @@ -67,6 +67,36 @@ export const SignalStream = ({ color, height, width }: any) => ( ); +export const Plus = ({ color, height, width }: any) => ( + + + +); + +export const Plug = ({ color, height, width }: any) => ( + + + +); + export const PrismaPostgres = ({ color, height, width }: any) => ( { ); }; +export const QuickstartLinkCard = ({ icon, title, desc, link, highlight, children }: any) => { + const linkCardRef = useRef(null); + return ( + +
+ {icon && } +

{title}

+
+ {children ??

{desc}

} + + ); +}; + export const Tab = ({ children, ...props }) => (
{children} diff --git a/src/css/gettingStarted.module.scss b/src/css/gettingStarted.module.scss index 14fdb997a2..9d78a93d81 100644 --- a/src/css/gettingStarted.module.scss +++ b/src/css/gettingStarted.module.scss @@ -16,8 +16,14 @@ } .borderBox { padding: 24px 24px 32px 24px; + margin-top: 16px; + display: flex; + flex-direction: column; + justify-content: space-between; border-radius: 8px; - background: var(--main-bgd-color); + border: 1px solid var(--border-color); + background: var(--surface-brand-grey-strong); + width: fit-content; a { text-decoration: underline; } @@ -26,7 +32,8 @@ text-align: left; letter-spacing: 0em; line-height: 20px; - font-size: 14px; + font-size: 16px; + margin: 0; :first-child { margin-top: 0; } @@ -34,6 +41,23 @@ margin-bottom: 0; } } + > p { + margin-bottom: 16px; + &:last-child { + margin-bottom: 0; + } + } + pre[class*="language-"] { + background: #121521 !important; + border: 0.7px solid #2d3748; + code span { + font-size: 16px; + color: #e2e8f0 !important; + &::before { + color: #4a5568; + } + } + } } .boxTitle { @@ -45,31 +69,6 @@ letter-spacing: -0.8px; } -.grid { - gap: 16px; - display: grid; - margin-top: 24px; - grid-template-columns: none; - @media (min-width: 600px) { - grid-template-columns: 1fr 1fr; - } - a { - border-color: var(--ifm-btn-border-color); - background: transparent; - color: var(--main-font-color); - &:hover { - border-color: var(--ifm-btn-border-color-active); - background: transparent; - } - } -} - -.separator { - height: 100%; - width: 1px; - border-left: 1px solid var(--ifm-btn-border-color); -} - .linkCardWrapper { border: 1px solid var(--border-color); padding: 20px 24px; @@ -86,15 +85,16 @@ color: inherit; } &.linkCardHighlight { - background: rgba(22, 163, 148, 0.12); - border-color: rgb(22, 163, 148); - &:hover { - // background: #B7F4EE; - border-color: #154f47; - } + border-radius: 8px; + border: 1px solid var(--surface-brand-default); + background: var(--surface-brand-light); } .title { display: inline-flex; + h2 { + font-family: Barlow; + border-bottom: 1px solid var(--main-font-color); + } h6 { font-size: 18px; display: inline-block; @@ -117,22 +117,6 @@ } } -.tab { - padding: 15px; - background-color: var(--main-bgd-color); - border: 1px solid var(--indigo-600); - border-radius: 0px 8px 8px 8px; - font-family: Inter; - font-size: 14px; - font-weight: 400; - line-height: 20px; - letter-spacing: 0em; - text-align: left; - p { - margin-top: 0; - } -} - .squareWrapper { width: 90px; height: 90px; @@ -165,10 +149,14 @@ .list { display: grid; - gap: 16px; margin-top: 16px; - max-width: fit-content; + width: fit-content; grid-template-columns: repeat(2, auto); + gap: 16px; + width: fit-content; + display: flex; + justify-content: flex-start; + &:not(.framedList) { @media (min-width: 1400px) { grid-template-columns: repeat(7, auto); diff --git a/src/data/indexData.ts b/src/data/indexData.ts index 29bc26ad8d..3081a6a7ab 100644 --- a/src/data/indexData.ts +++ b/src/data/indexData.ts @@ -125,9 +125,9 @@ export const get_help = [ export const tabs = [ { icon: "fa-solid fa-chart-pyramid", - label: "Use Prisma Postgres", + label: "Use Prisma's managed Postgres", description: - "Get started with your favorite framework and Prisma Postgres. With Prisma Postgres you get an instant, fully hosted high-performance database that includes built-in caching, scales to zero, and integrates deeply with Prisma ORM and Prisma Studio—all backed by a generous free tier.", + "Get started with your favorite framework and Prisma Postgres. With Prisma Postgres you get an instant, fully hosted high-performance database that scales to zero and integrates deeply with Prisma ORM and Prisma Studio—all backed by a generous free tier.", list: [ { url: "/guides/nextjs", diff --git a/src/pages/index.tsx b/src/pages/index.tsx index e242c4ec34..55f2b82ea3 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -54,7 +54,7 @@ function HomepageHowDoISection() { const hiddenCards = how_do_i.slice(3); const location = useLocation(); - + return (
@@ -72,7 +72,7 @@ function HomepageHowDoISection() { {e.tags.map((tag: any) => )}
} {e.time &&
- + {e.time} min. read
}
} @@ -89,7 +89,7 @@ function HomepageHowDoISection() { {e.tags.map((tag: any) => )} } {e.time &&
- + {e.time} min. read
} } @@ -100,7 +100,7 @@ function HomepageHowDoISection() { className={clsx(styles.seeMore, seeMore && styles.clicked)} onClick={() => { setSeeMore(!seeMore) - howRef.current.scrollIntoView({behavior: "smooth", offset: 80}); + howRef.current.scrollIntoView({ behavior: "smooth", offset: 80 }); }} > See {seeMore ? `less` : `more`} @@ -110,7 +110,7 @@ function HomepageHowDoISection() { ); } -const CommunityIcon = ({icon, link, label}: any) => { +const CommunityIcon = ({ icon, link, label }: any) => { const [visibleTooltip, setVisibleTooltip] = useState(false); const iconRef = useRef(null); @@ -161,41 +161,41 @@ function HomepageCommunitySection() { ); } -const TabBox = ({icon, label, description, list, link}: any) => { +const TabBox = ({ icon, label, description, list, link }: any) => { const location = useLocation(); return (
- {icon && } + {icon && } {label}
-

+

- {list && list.length && list.map((l: any, idx: number) => + {list && list.length && list.map((l: any, idx: number) => )}
- + {link.label} - +
) } function HomepageHeroSection() { - const { colorMode } = useColorMode(); + const { colorMode } = useColorMode(); return (
@@ -216,7 +216,7 @@ function HomepageHeroSection() { label="Start with an AI prompt →" color="teal" /> */}
- {tabs && tabs.map((tab: any, idx: number) => + {tabs && tabs.map((tab: any, idx: number) => )}
@@ -241,9 +241,9 @@ function HomepageGetHelpSection() {

{e.title}

-

+

- {e.links.map((link: any) => + {e.links.map((link: any) => {link.label} @@ -272,7 +272,7 @@ export default function Home(): JSX.Element { - + diff --git a/static/_redirects b/static/_redirects index e2c2eb925f..dd1525cb19 100644 --- a/static/_redirects +++ b/static/_redirects @@ -636,5 +636,12 @@ /postgres/database/tooling /docs/postgres/integrations/viewing-data /postgres/integrations/tooling /docs/postgres/integrations/viewing-data +/getting-started#-prisma-orm /docs/getting-started +/getting-started#explore-quickly-with-a-sqlite-database /docs/getting-started/quickstart-sqlite +/getting-started#choose-an-option-to-get-started-with-your-own-database /docs/getting-started/quickstart-sqlite +/getting-started#-prisma-accelerate /docs/postgres/database/caching +/getting-started#-prisma-optimize /docs/postgres/query-optimization + + ### NO REDIRECTS BELOW THIS LINE. ADD REDIRECTS ABOVE THIS SECTION ### diff --git a/static/img/guides/prisma-betterauth-astro-cover.png b/static/img/guides/prisma-betterauth-astro-cover.png new file mode 100644 index 0000000000..5ac0879424 Binary files /dev/null and b/static/img/guides/prisma-betterauth-astro-cover.png differ diff --git a/static/img/technologies/astro.svg b/static/img/technologies/astro.svg new file mode 100644 index 0000000000..e52118199d --- /dev/null +++ b/static/img/technologies/astro.svg @@ -0,0 +1,4 @@ + + + + diff --git a/static/img/technologies/astrodark.svg b/static/img/technologies/astrodark.svg new file mode 100644 index 0000000000..52b76d5509 --- /dev/null +++ b/static/img/technologies/astrodark.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/static/img/technologies/drizzle.svg b/static/img/technologies/drizzle.svg new file mode 100644 index 0000000000..fdacf2c789 --- /dev/null +++ b/static/img/technologies/drizzle.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/static/img/technologies/kysely.svg b/static/img/technologies/kysely.svg new file mode 100644 index 0000000000..5ca04a32b0 --- /dev/null +++ b/static/img/technologies/kysely.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/static/img/technologies/remix.svg b/static/img/technologies/remix.svg new file mode 100644 index 0000000000..25faf57061 --- /dev/null +++ b/static/img/technologies/remix.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/static/img/technologies/sequelize.svg b/static/img/technologies/sequelize.svg new file mode 100644 index 0000000000..728f77161e --- /dev/null +++ b/static/img/technologies/sequelize.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/img/technologies/typeorm.svg b/static/img/technologies/typeorm.svg new file mode 100644 index 0000000000..e91fbd55c8 --- /dev/null +++ b/static/img/technologies/typeorm.svg @@ -0,0 +1,4 @@ + + + +