remove with-fauna example (#80440)

This commit is contained in:
Dominik Ferber
2025-06-12 11:03:15 +02:00
committed by GitHub
parent f8875169c5
commit 301e79db45
23 changed files with 0 additions and 447 deletions
-1
View File
@@ -1 +0,0 @@
FAUNA_CLIENT_SECRET=
-40
View File
@@ -1,40 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# 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
-41
View File
@@ -1,41 +0,0 @@
# Fauna Guestbook Starter
This Guestbook Application example shows you how to use [Fauna](https://docs.fauna.com/) in your Next.js project.
## Deploy your own
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-fauna&project-name=fauna-nextjs-guestbook&repository-name=fauna-nextjs-guestbook&demo-title=Next.js%20Fauna%20Guestbook%20App&demo-description=A%20simple%20guestbook%20application%20built%20with%20Next.js%20and%20Fauna&integration-ids=oac_Erlbqm8Teb1y4WhioE3r2utY)
## How to use
Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example:
```bash
npx create-next-app --example with-fauna with-fauna-app
```
```bash
yarn create next-app --example with-fauna with-fauna-app
```
```bash
pnpm create next-app --example with-fauna with-fauna-app
```
### Setting Up Your Fauna Database
Head over to [Fauna Dashboard](https://dashboard.fauna.com/) and create a new database. You can name it whatever you want, but for this example, we'll use `nextjs-guestbook`. Next, create a new collection called `Entry` in your new database.
Finally create a new database access key to connect to your database.
Watch [this video](https://www.youtube.com/watch?v=8YJcG2fUPyE&t=43s&ab_channel=FaunaInc.) to learn how to connect to your database.
### Run locally
Install packages, set up if needed, then run the development server:
```bash
npm install
npm run dev
```
Your app should be up and running on [http://localhost:3000](http://localhost:3000)!
-22
View File
@@ -1,22 +0,0 @@
"use server";
import { revalidatePath } from "next/cache";
import { createEntry } from "@/lib/fauna";
export async function createEntryAction(prevState: any, formData: FormData) {
const name = formData.get("name") as string;
const message = formData.get("message") as string;
try {
await createEntry(name, message);
revalidatePath("/");
return {
successMessage: "Thank you for signing the guest book",
errorMessage: null,
};
} catch (error) {
return {
successMessage: null,
errorMessage: "Something went wrong. Please try again",
};
}
}
-3
View File
@@ -1,3 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@@ -1,50 +0,0 @@
import cn from "classnames";
import formatDate from "date-fns/format";
import EntryForm from "@/components/EntryForm";
import { EntryType } from "./page";
const EntryItem = ({ entry }: { entry: EntryType }) => (
<div className="flex flex-col space-y-2">
<div className="prose dark:prose-dark w-full">{entry.message}</div>
<div className="flex items-center space-x-3">
<p className="text-sm text-gray-500">{entry.name}</p>
<span className="text-gray-200 dark:text-gray-800">/</span>
<p className="text-sm text-gray-400 dark:text-gray-600">
{formatDate(
new Date(entry.createdAt.isoString),
"d MMM yyyy 'at' h:mm bb",
)}
</p>
</div>
</div>
);
export default async function GuestbookPage({
entries,
}: {
entries: EntryType[];
}) {
return (
<main className="max-w-4xl mx-auto p-4">
<div
className={cn(
"border border-blue-200 rounded p-6",
"my-4 w-full dark:border-gray-800 bg-blue-50",
"dark:bg-blue-opaque",
)}
>
<h5 className={cn("text-lg md:text-xl font-bold", "text-gray-900")}>
Sign the Guestbook
</h5>
<p className="my-1 text-gray-800">
Share a message for a future visitor.
</p>
<EntryForm />
</div>
<div className="mt-4 space-y-8 px-2">
{entries?.map((entry) => <EntryItem key={entry.id} entry={entry} />)}
</div>
</main>
);
}
-21
View File
@@ -1,21 +0,0 @@
import "./globals.css";
export const metadata: {
title: string;
description: string;
} = {
title: "Next.js + Fauna example",
description: "Generated by Next.js",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
-16
View File
@@ -1,16 +0,0 @@
import { getAllEntries } from "@/lib/fauna";
import GuestbookPage from "./guestbook-page";
export type EntryType = {
id: string;
name: string;
message: string;
createdAt: {
isoString: string;
};
};
export default async function Page() {
const entries = (await getAllEntries()) as EntryType[];
return <GuestbookPage entries={entries} />;
}
@@ -1,67 +0,0 @@
"use client";
import cn from "classnames";
import { createEntryAction } from "@/actions/entry";
// @ts-ignore
import { useActionState } from "react";
// @ts-ignore
import { useFormStatus } from "react-dom";
import LoadingSpinner from "@/components/LoadingSpinner";
import SuccessMessage from "@/components/SuccessMessage";
import ErrorMessage from "@/components/ErrorMessage";
const inputClasses = cn(
"block py-2 bg-white dark:bg-gray-800",
"rounded-md border-gray-300 focus:ring-blue-500",
"focus:border-blue-500 text-gray-900 dark:text-gray-100",
);
const initialState = {
successMessage: null,
errorMessage: null,
};
export default function EntryForm() {
// useActionState is available with React 19 (Next.js App Router)
const [state, formAction] = useActionState(createEntryAction, initialState);
const { pending } = useFormStatus();
return (
<>
<form className="relative flex my-4" action={formAction}>
<input
required
className={cn(inputClasses, "w-1/3 mr-2 px-4")}
aria-label="Your name"
placeholder="Your name..."
name="name"
/>
<input
required
className={cn(inputClasses, "pl-4 pr-32 flex-grow")}
aria-label="Your message"
placeholder="Your message..."
name="message"
/>
<button
className={cn(
"flex items-center justify-center",
"absolute right-1 top-1 px-4 font-bold h-8",
"bg-gray-100 dark:bg-gray-700 text-gray-900",
"dark:text-gray-100 rounded w-28",
)}
type="submit"
disabled={pending}
>
{pending ? <LoadingSpinner /> : "Sign"}
</button>
</form>
{state?.successMessage ? (
<SuccessMessage>{state.successMessage}</SuccessMessage>
) : null}
{state?.errorMessage ? (
<ErrorMessage>{state.errorMessage}</ErrorMessage>
) : null}
</>
);
}
@@ -1,23 +0,0 @@
export default function ErrorMessage({
children,
}: {
children: React.ReactNode;
}) {
return (
<p className="flex items-center text-sm font-bold text-red-800 dark:text-red-400">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
className="mr-2 h-4 w-4"
>
<path
fillRule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z"
clipRule="evenodd"
/>
</svg>
{children}
</p>
);
}
@@ -1,24 +0,0 @@
export default function LoadingSpinner() {
return (
<svg
className="animate-spin h-5 w-5 text-gray-900 dark:text-gray-100"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
/>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
);
}
@@ -1,23 +0,0 @@
export default function SuccessMessage({
children,
}: {
children: React.ReactNode;
}) {
return (
<p className="flex items-center text-sm font-bold text-green-700 dark:text-green-400">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
className="mr-2 h-4 w-4"
>
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
{children}
</p>
);
}
-10
View File
@@ -1,10 +0,0 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/actions/*": ["actions/*"],
"@/components/*": ["components/*"],
"@/lib/*": ["lib/*"]
}
}
}
-31
View File
@@ -1,31 +0,0 @@
import "server-only";
import { Client, fql, QuerySuccess, QueryValueObject } from "fauna";
const client = new Client({
secret: process.env.FAUNA_CLIENT_SECRET,
});
export const getAllEntries = async () => {
try {
const dbresponse: QuerySuccess<QueryValueObject> = await client.query(fql`
Entry.all()
`);
return dbresponse.data.data;
} catch (error: any) {
throw new Error(error.message);
}
};
export const createEntry = async (name: string, message: string) => {
try {
const dbresponse = await client.query(fql`
Entry.create({
name: ${name},
message: ${message},
createdAt: Time.now(),
})`);
return dbresponse.data;
} catch (error: any) {
throw new Error(error.message);
}
};
-3
View File
@@ -1,3 +0,0 @@
const nextConfig = {};
module.exports = nextConfig;
-25
View File
@@ -1,25 +0,0 @@
{
"private": true,
"scripts": {
"dev": "next",
"build": "yarn setup && next build",
"start": "next start",
"setup": "node ./scripts/setup.js"
},
"dependencies": {
"classnames": "2.3.1",
"date-fns": "2.28.0",
"fauna": "^1.2.0",
"next": "canary",
"react": "rc",
"react-dom": "rc",
"server-only": "^0.0.1"
},
"devDependencies": {
"autoprefixer": "^10.4.16",
"postcss": "^8.4.31",
"request": "^2.88.2",
"stream-to-promise": "3.0.0",
"tailwindcss": "^3.3.3"
}
}
-6
View File
@@ -1,6 +0,0 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

-12
View File
@@ -1,12 +0,0 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./app/**/*.{js,ts,jsx,tsx,mdx}",
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {},
},
plugins: [],
};
-28
View File
@@ -1,28 +0,0 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
@@ -78,7 +78,6 @@
"with-emotion-swc": true,
"with-eslint": true,
"with-facebook-pixel": true,
"with-fauna": true,
"with-fela": true,
"with-fingerprintjs-pro": true,
"with-firebase": true,