Skip to content

Commit

Permalink
init: add pdp project examples (#5854)
Browse files Browse the repository at this point in the history
* init: add pdp project examples

* feat: update pulse resend example

* feat: make the READMEs more refined

* feat: enhance accelerate docs

* feat: change accelerate starter readme

* feat: refine README

* Update README.md

Co-authored-by: Jon Harrell <[email protected]>

* Update README.md

Co-authored-by: Jon Harrell <[email protected]>

* enhance: add standards

* Update prisma-data-platform/pulse/starter/index.ts

Co-authored-by: Jon Harrell <[email protected]>

* Update prisma-data-platform/accelerate/nextjs/app/page.tsx

Co-authored-by: Jon Harrell <[email protected]>

* Update prisma-data-platform/pulse/email-with-resend/README.md

Co-authored-by: Nikolas <[email protected]>

* Update prisma-data-platform/pulse/email-with-resend/README.md

Co-authored-by: Nikolas <[email protected]>

* Update prisma-data-platform/pulse/email-with-resend/README.md

Co-authored-by: Nikolas <[email protected]>

* Update prisma-data-platform/pulse/email-with-resend/README.md

Co-authored-by: Nikolas <[email protected]>

* Update prisma-data-platform/pulse/email-with-resend/README.md

Co-authored-by: Nikolas <[email protected]>

* Update prisma-data-platform/pulse/email-with-resend/README.md

Co-authored-by: Nikolas <[email protected]>

* Update prisma-data-platform/pulse/email-with-resend/README.md

Co-authored-by: Nikolas <[email protected]>

* update pulse readmes

* rename nexts project for accelerate

* update accelerate starter readme

* update accelerate starter readme

* delete migration history in accelerate example

* finalize accelerate readme

* updater pulse/starter readme

* update main README

* removed prisma-data-platform folder and mentions in readme, move pulse and acclerate to top level folders

* i think i fixed the tables in the read me, that was awful

* removed tailing slash

* i cant spell

* changed directories to be just the product name to future proof

* small updates in READMEs

* Update accelerate/nextjs-starter/lib/utils/helpers.ts

Co-authored-by: Jon Harrell <[email protected]>

* Update accelerate/nextjs-starter/lib/utils/query.ts

Co-authored-by: Jon Harrell <[email protected]>

* Update accelerate/nextjs-starter/lib/utils/query.ts

Co-authored-by: Jon Harrell <[email protected]>

* Update pulse/email-with-resend/.gitignore

Co-authored-by: Jon Harrell <[email protected]>

* Update pulse/email-with-resend/script.ts

Co-authored-by: Jon Harrell <[email protected]>

* feat: add licenses

* add licenses

* feat: add accelerate migrations

* docs: improve documentation

---------

Co-authored-by: Jon Harrell <[email protected]>
Co-authored-by: Nikolas <[email protected]>
Co-authored-by: Marc Hess <[email protected]>
  • Loading branch information
4 people authored May 15, 2024
1 parent 707c0aa commit 43ea69c
Show file tree
Hide file tree
Showing 49 changed files with 1,315 additions and 29 deletions.
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.mdx
*.md
77 changes: 48 additions & 29 deletions README.md

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions accelerate/nextjs-starter/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
37 changes: 37 additions & 0 deletions accelerate/nextjs-starter/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

.env

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
21 changes: 21 additions & 0 deletions accelerate/nextjs-starter/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License Copyright (c) 2024 ankur

Permission is hereby granted, free of
charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to the
following conditions:

The above copyright notice and this permission notice
(including the next paragraph) shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
86 changes: 86 additions & 0 deletions accelerate/nextjs-starter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Prisma Accelerate Example: Next.js Starter

This project showcases how to use Prisma ORM with Prisma Accelerate in a Next.js application. It [demonstrates](./app/api/route.ts#L15-46) every available [caching strategy in Accelerate](https://www.prisma.io/docs/data-platform/accelerate/concepts#cache-strategies).

## Prerequisites

To successfully run the project, you will need the following:

- The **connection string** of a publicly accessible database
- Your **Accelerate connection string** (containing your **Accelerate API key**) which you can get by enabling Accelerate in a project in your [Prisma Data Platform](https://pris.ly/pdp) account (learn more in the [docs](https://www.prisma.io/docs/platform/concepts/environments#api-keys))

## Getting started

### 1. Clone the repository

Clone the repository, navigate into it and install dependencies:

```
git clone [email protected]:prisma/prisma-examples.git --depth=1
cd prisma-examples/accelerate/nextjs-starter
npm install
```

### 2. Configure environment variables

Create a `.env` in the root of the project directory:

```bash
touch .env
```

Now, open the `.env` file and set the `DATABASE_URL` and `DIRECT_URL` environment variables with the values of your connection string and your Accelerate connection string:

```bash
# .env

# Accelerate connection string (used for queries by Prisma Client)
DATABASE_URL="__YOUR_ACCELERATE_CONNECTION_STRING__"

# Database connection string (used for migrations by Prisma Migrate)
DIRECT_URL="__YOUR_DATABASE_CONNECTION_STRING__"

NEXT_PUBLIC_URL="http://localhost:3000"
```

Note that `__YOUR_DATABASE_CONNECTION_STRING__` and `__YOUR_ACCELERATE_CONNECTION_STRING__` are placeholder values that you need to replace with the values of your database and Accelerate connection strings. Notice that the Accelerate connection string has the following structure: `prisma://accelerate.prisma-data.net/?api_key=__YOUR_ACCELERATE_API_KEY__`.

### 3. Run a migration to create the `Quotes` table and seed the database

The Prisma schema file contains a single `Quotes` model. You can map this model to the database and create the corresponding `Quotes` table using the following command:

```
npx prisma migrate dev --name init
```

You now have an empty `Quotes` table in your database. Next, run the [seed script](./prisma/seed.ts) to create some sample records in the table:

```
npx prisma db seed
```

### 4. Generate Prisma Client for Accelerate

When using Accelerate, Prisma Client doesn't need a query engine. That's why you should generate it as follows:

```
npx prisma generate --no-engine
```

### 5. Start the app

You can run the app with the following command:

```
npm run dev
```

You can see the performancen and other stats (e.g. cache/hit) for the different Accelerate cache strategies at the bottom of the UI:

![Demo](./demo.gif)

## Resources

- [Accelerate Speed Test](https://accelerate-speed-test.vercel.app/)
- [Accelerate documentation](https://www.prisma.io/docs/accelerate)
- [Prisma Discord](https://pris.ly/discord)
65 changes: 65 additions & 0 deletions accelerate/nextjs-starter/app/api/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { addQuote, getQuotes } from "@/lib/utils/query";
import { z } from "zod";

export const runtime = "edge";

// disabling caching
export const fetchCache = "force-no-store";
export const revalidate = 0;

export async function GET(request: Request) {
const url = new URL(request.url);
const searchParams = new URLSearchParams(url.search);

const parser = z.enum(["TTL", "SWR", "BOTH", "NONE"]);
const parsedOutput = await parser.safeParseAsync(searchParams.get("cache"));

if (!parsedOutput.success) {
return new Response(JSON.stringify("Invalid search parameter."), {
status: 400,
});
}

let map = new Map();

// When TTL is selected
map.set("TTL", {
ttl: 30,
});

// When SWR is selected
map.set("SWR", {
swr: 30,
});

// When TTL + SWR is selected
map.set("BOTH", {
ttl: 30,
swr: 60,
});

// This ensures no caching is performed and only the Accelerate connection pool is used
map.set("NONE", undefined);

const data = await getQuotes(map.get(parsedOutput.data));

return new Response(JSON.stringify(data), {
headers: { "Content-Type": "application/json" },
status: 200,
});
}

export async function POST(request: Request) {
const response = await fetch("https://api.quotable.io/random", {
cache: "no-cache",
});

const data = await response.json();

await addQuote(data.content);

return new Response(JSON.stringify({ quote: data.content }), {
headers: { "Content-Type": "application/json" },
status: 201,
});
}
Binary file added accelerate/nextjs-starter/app/favicon.ico
Binary file not shown.
27 changes: 27 additions & 0 deletions accelerate/nextjs-starter/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
}

@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
}
}

body {
color: rgb(var(--foreground-rgb));
background: linear-gradient(
to bottom,
transparent,
rgb(var(--background-end-rgb))
)
rgb(var(--background-start-rgb));
}
22 changes: 22 additions & 0 deletions accelerate/nextjs-starter/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import "./globals.css";
import type { Metadata } from "next";
import { Inter } from "next/font/google";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
title: "Accelerated Quotes",
description: "Accelerate starter",
};

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
);
}
28 changes: 28 additions & 0 deletions accelerate/nextjs-starter/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { AddQuote } from '@/components/Quote/AddQuote'
import { QuotesLoading } from '@/components/Quote/QuotesLoading'
import { Quotes } from '@/components/Quote/Quotes'
import { Suspense } from 'react'

// Disable caching. If 'force-dynamic' is not used, stale data can be returned from Prisma Client.
// Learn more here: https://www.prisma.io/docs/orm/more/help-and-troubleshooting/help-articles/nextjs-prisma-client-dynamic.
export const dynamic = 'force-dynamic'

export default async function Home() {
return (
<main className="flex min-h-screen flex-col items-center justify-start p-8 md:p-24">
<h1 className="text-3xl text-slate-800 dark:text-white">
Accelerated Quotes
</h1>
<br />
<p className="text-xl text-slate-800 dark:text-slate-200">
Retrieves the most recently added quote with and without caching enabled
</p>
<br />
<AddQuote />
<br />
<Suspense fallback={<QuotesLoading />}>
<Quotes />
</Suspense>
</main>
)
}
46 changes: 46 additions & 0 deletions accelerate/nextjs-starter/components/Quote/AddQuote.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"use client";

import { HOST, delay } from "@/lib/utils/helpers";
import { useRouter } from "next/navigation";

import toast, { Toaster } from "react-hot-toast";

export const AddQuote = () => {
const router = useRouter();

const addQuote = async () => {
try {
const response = await fetch(`${HOST}/api`, {
method: "POST",
});
const data = await response.json();
const toastId = toast.success(`New quote added - "${data.quote}"`);
await delay(2000);
toast.remove(toastId);
router.refresh();
} catch (error) {
toast.error("Something went wrong");
}
};

return (
<>
<Toaster position="top-center" reverseOrder={false} />
<button
type="button"
onClick={addQuote}
className="focus:outline-none text-white bg-green-700 hover:bg-green-800 focus:ring-4 focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 mr-2 mb-2 dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800"
>
Add new quote and refresh page
</button>

<button
type="button"
onClick={() => router.refresh()}
className="focus:outline-none text-white bg-green-700 hover:bg-green-800 focus:ring-4 focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 mr-2 mb-2 dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800"
>
Refresh
</button>
</>
);
};
Loading

0 comments on commit 43ea69c

Please sign in to comment.