add cms
This commit is contained in:
3
api/.env.local.example
Normal file
3
api/.env.local.example
Normal file
@@ -0,0 +1,3 @@
|
||||
PAYLOAD_SECRET=jawliejfilwajefSEANlawefawfewag349jwgo3gj4w
|
||||
MONGODB_URI=mongodb://127.0.0.1:27017/next-payload-3
|
||||
# POSTGRES_URI=postgresql://postgres:password123@127.0.0.1:5432/next-payload-3
|
||||
3
api/.eslintrc.json
Normal file
3
api/.eslintrc.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "next/core-web-vitals"
|
||||
}
|
||||
43
api/.gitignore
vendored
Normal file
43
api/.gitignore
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
.yarn/install-state.gz
|
||||
|
||||
/.idea/*
|
||||
!/.idea/runConfigurations
|
||||
|
||||
# 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
|
||||
|
||||
.env
|
||||
|
||||
/media
|
||||
6
api/.prettierrc.json
Normal file
6
api/.prettierrc.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 100,
|
||||
"semi": false
|
||||
}
|
||||
3
api/.vscode/extensions.json
vendored
Normal file
3
api/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint"]
|
||||
}
|
||||
12
api/.vscode/launch.json
vendored
Normal file
12
api/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"command": "pnpm run dev",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev (pnpm)",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
],
|
||||
"version": "0.2.0"
|
||||
}
|
||||
41
api/.vscode/settings.json
vendored
Normal file
41
api/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"npm.packageManager": "pnpm",
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
}
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
}
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
}
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"editor.formatOnSaveMode": "file",
|
||||
"eslint.rules.customizations": [{ "rule": "*", "severity": "warn" }],
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"[javascript][typescript][typescriptreact]": {
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
}
|
||||
}
|
||||
}
|
||||
13
api/CHANGELOG.md
Normal file
13
api/CHANGELOG.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# alpha.42
|
||||
|
||||
**We're now pre-compiling CSS for faster startup times**
|
||||
|
||||
We are beginning to optimize the compilation and dev startup performance of Payload 3.0, and the first thing we've done is pre-compiled all SCSS that is required by the Payload admin UI.
|
||||
|
||||
If you started before `alpha.42` and update to this version, you'll see that no styles are loaded. To fix this, take a look at the `/src/app/(payload)/layout.tsx` file within this repo, and note that this file has a new CSS import within it to load all CSS required by the Payload admin panel.
|
||||
|
||||
Simply add this import to your `(payload)/layout.tsx` file, and you'll be back in business.
|
||||
|
||||
**We now load all required Payload static files from your Next.js `public` folder**
|
||||
|
||||
In addition to pre-compiling SCSS, we are also shipping static files through the Next.js `/public` folder which will cut down on compilation time as well. Make sure you copy the `public/payload` folder into your repo as well as add the CSS import above.
|
||||
87
api/README.md
Normal file
87
api/README.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# Payload 3.0 Beta Demo
|
||||
|
||||
This repo showcases a demo of the Payload 3.0 Beta running completely within Next.js.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> It's extremely important to note that as of now, this demo contains BETA software and you are 100% guaranteed to run into bugs / weird stuff.
|
||||
>
|
||||
> We're actively working toward a stable release as fast as we possibly can.
|
||||
|
||||
### Highlights
|
||||
|
||||
1. Payload is now Next.js-native
|
||||
1. Turbopack works out of the box (this will get faster over time, expect more here)
|
||||
1. The Payload admin UI is built with React Server Components and automatically eliminates server-side code from your admin bundle, completely alleviating the need to use Webpack aliases to remove hooks, access control, etc.
|
||||
1. Payload is now fully-ESM across the board
|
||||
1. GraphQL is now initialized only when you hit the GraphQL endpoint, and does not affect overhead of REST API routes
|
||||
1. All UI components have been abstracted into a separate `@payloadcms/ui` package, which will be fully documented and exposed for your re-use once we hit stable 3.0 or before
|
||||
1. You can run your own Next.js site alongside of Payload in the same app
|
||||
1. You can now deploy Payload to Vercel and Netlify, and there will be official support for Vercel Blob Storage and Netlify Blobs coming soon (so no S3 needed for files)
|
||||
1. Server-side HMR works out of the box, with no need for `nodemon` or similar. When the Payload config changes, your app will automatically re-initialize Payload seamlessly in the background
|
||||
1. All custom React components can be server components by default, and you can decide if you want them to be server components or client components
|
||||
1. Sharp has been abstracted to be an optional dependency
|
||||
1. Payload now relies on the Web Request / Response APIs rather than the Node Request / Response
|
||||
1. Express can still be used with Next.js' Custom Server functionality
|
||||
1. Payload itself has slimmed down significantly and can now be fully portable, run anywhere. You can leverage the Payload Local API completely outside of Next.js if you want.
|
||||
1. The data layer, including the shape of the database Payload used and the API responses in 2.0, has not been affected whatsoever
|
||||
|
||||
### Work to come
|
||||
|
||||
We are making this available to our community so that we can gather your feedback and test the new approach that Payload is taking. Don't expect it to be fully functional yet. There are some things that we are aware of that are not yet completed, but we're going to keep blazing through the remaining items as fast as we can to reach stable 3.0 as quickly and efficiently as possible. Here are a few of the items that we are still working on (not a full list):
|
||||
|
||||
1. Documentation
|
||||
1. Vercel Blob Storage and Netlify Blobs adapter
|
||||
1. Lots of bugs for sure
|
||||
1. 100% of tests passing
|
||||
1. Compiler speed improvements (turbo is beta still, it is slower than it should be. it will get faster)
|
||||
1. Overall speed improvements
|
||||
1. An install script to be able to install Payload easily into any existing Next.js app
|
||||
1. A full list of breaking changes for 2.0 -> 3.0, including an in-depth migration guide
|
||||
|
||||
### Existing Next.js project
|
||||
|
||||
You can install Payload into your existing Next.js project using this command:
|
||||
|
||||
```
|
||||
npx create-payload-app@beta
|
||||
```
|
||||
|
||||
Contents from `src/app` will have to be moved into a new directory `src/app/(app)` so that Payload's root layout and routes can remain isolated from the rest of your app.
|
||||
|
||||
### Using this repo
|
||||
|
||||
To try out this repo yourself, follow the steps below:
|
||||
|
||||
1. Clone the repo to your computer (`git clone git@github.com:payloadcms/payload-3.0-demo.git`)
|
||||
2. `cd` into the new folder by running `cd ./payload-3.0-demo`
|
||||
3. Copy the `.env.local.example` by running `cp .env.local.example .env.local` in the repo, then fill out the values including the connection string to your DB
|
||||
4. Install dependencies with whatever package manager you use (`pnpm i`, `npm install`, `yarn`, etc.). `pnpm` is highly recommended. The usage of yarn v1 is discouraged.
|
||||
5. Start your database. For local postgresql use `.\start-database.sh` to start it in docker container.
|
||||
6. Fire it up (`pnpm dev`, `npm run dev`, `yarn dev`, etc.)
|
||||
7. Visit https://localhost:3000 and log in with the user created within the config's `onInit` method
|
||||
|
||||
### Follow along with breaking changes
|
||||
|
||||
There is a possibility that we will make breaking changes before releasing the full stable version of Payload 3.0.
|
||||
|
||||
**To follow along with breaking changes in advance of the full, stable release,** you can keep an eye on the [CHANGELOG.md](https://github.com/payloadcms/payload-3.0-demo/blob/main/CHANGELOG.md).
|
||||
|
||||
### Technical details
|
||||
|
||||
**The app folder**
|
||||
|
||||
You'll see that Payload requires a few files to be present in your `/app` folder. There are files for the admin UI as well as files for all route handlers. We've consolidated all admin views into a single `page.tsx` and consolidated most of the REST endpoints into a single `route.ts` file for simplicity, but also for development performance. With this pattern, you only have to compile the admin UI / REST API / GraphQL API a single time - and from there, it will be lightning-fast.
|
||||
|
||||
**The `next.config.js` `withPayload` function**
|
||||
|
||||
You'll see in the Next.js config that we have a `withPayload` function installed. This function is required for Payload to operate, and it ensures compatibility with packages that Payload needs such as `drizzle-kit`, `sharp`, `pino`, and `mongodb`.
|
||||
|
||||
**Using a TypeScript alias to point to your Payload config**
|
||||
|
||||
In the `tsconfig.json` within this repo, you'll see that we have `paths` set up to point `@payload-config` to the Payload config, which is located in the root. You can put your config wherever you want. By default, the `page.tsx` files and `route.ts` files within the `/app` folder use this alias. In the future, we might make it optional to use `paths` - and by default, we might just hard-code relative path imports to the config. We would like to hear your feedback on this part. What do you prefer? Use `paths` or just use relative imports?
|
||||
|
||||
---
|
||||
|
||||
### Find a bug?
|
||||
|
||||
Open an issue on this repo at `https://github.com/payloadcms/payload-3.0-demo` with as much detail as you can provide and we will tackle them as fast as we can. Let's get stable!
|
||||
11
api/next.config.mjs
Normal file
11
api/next.config.mjs
Normal file
@@ -0,0 +1,11 @@
|
||||
import { withPayload } from '@payloadcms/next/withPayload'
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
// Your Next.js config here
|
||||
experimental: {
|
||||
reactCompiler: false
|
||||
}
|
||||
}
|
||||
|
||||
export default withPayload(nextConfig)
|
||||
57
api/package.json
Normal file
57
api/package.json
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"name": "next-latest-starter",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
|
||||
"devturbo": "cross-env NODE_OPTIONS=--no-deprecation next dev --turbo",
|
||||
"devsafe": "rm -rf .next && cross-env NODE_OPTIONS=--no-deprecation next dev",
|
||||
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
|
||||
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start",
|
||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||
"ci": "payload migrate && pnpm build",
|
||||
"generate:types": "payload generate:types",
|
||||
"generate:schema": "payload-graphql generate:schema",
|
||||
"standalone-script": "node ./src/scripts/standalone-script.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.20.2 || >=20.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@payloadcms/db-mongodb": "3.0.0-beta.52",
|
||||
"@payloadcms/db-postgres": "3.0.0-beta.52",
|
||||
"@payloadcms/next": "3.0.0-beta.52",
|
||||
"@payloadcms/richtext-lexical": "3.0.0-beta.52",
|
||||
"@payloadcms/richtext-slate": "3.0.0-beta.52",
|
||||
"@payloadcms/ui": "3.0.0-beta.52",
|
||||
"babel-plugin-react-compiler": "^0.0.0-experimental-592953e-20240517",
|
||||
"cross-env": "^7.0.3",
|
||||
"graphql": "^16.8.2",
|
||||
"next": "15.0.0-rc.0",
|
||||
"payload": "3.0.0-beta.52",
|
||||
"react": "19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "19.0.0-rc-f994737d14-20240522",
|
||||
"sharp": "0.32.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@payloadcms/graphql": "3.0.0-beta.52",
|
||||
"@types/node": "^20.14.5",
|
||||
"@types/react": "npm:types-react@19.0.0-beta.2",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-next": "15.0.0-rc.0",
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"@types/react": "npm:types-react@19.0.0-beta.2",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2"
|
||||
}
|
||||
},
|
||||
"overrides": {
|
||||
"@types/react": "npm:types-react@19.0.0-beta.2",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2"
|
||||
}
|
||||
}
|
||||
122
api/payload-types.ts
Normal file
122
api/payload-types.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* This file was automatically generated by Payload.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
export interface Config {
|
||||
collections: {
|
||||
users: User;
|
||||
pages: Page;
|
||||
media: Media;
|
||||
'payload-preferences': PayloadPreference;
|
||||
'payload-migrations': PayloadMigration;
|
||||
};
|
||||
globals: {};
|
||||
locale: null;
|
||||
user: User & {
|
||||
collection: 'users';
|
||||
};
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
email: string;
|
||||
resetPasswordToken?: string | null;
|
||||
resetPasswordExpiration?: string | null;
|
||||
salt?: string | null;
|
||||
hash?: string | null;
|
||||
loginAttempts?: number | null;
|
||||
lockUntil?: string | null;
|
||||
password?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "pages".
|
||||
*/
|
||||
export interface Page {
|
||||
id: string;
|
||||
title?: string | null;
|
||||
content?: {
|
||||
root: {
|
||||
type: string;
|
||||
children: {
|
||||
type: string;
|
||||
version: number;
|
||||
[k: string]: unknown;
|
||||
}[];
|
||||
direction: ('ltr' | 'rtl') | null;
|
||||
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
|
||||
indent: number;
|
||||
version: number;
|
||||
};
|
||||
[k: string]: unknown;
|
||||
} | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "media".
|
||||
*/
|
||||
export interface Media {
|
||||
id: string;
|
||||
text?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
url?: string | null;
|
||||
thumbnailURL?: string | null;
|
||||
filename?: string | null;
|
||||
mimeType?: string | null;
|
||||
filesize?: number | null;
|
||||
width?: number | null;
|
||||
height?: number | null;
|
||||
focalX?: number | null;
|
||||
focalY?: number | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-preferences".
|
||||
*/
|
||||
export interface PayloadPreference {
|
||||
id: string;
|
||||
user: {
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
};
|
||||
key?: string | null;
|
||||
value?:
|
||||
| {
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| unknown[]
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-migrations".
|
||||
*/
|
||||
export interface PayloadMigration {
|
||||
id: string;
|
||||
name?: string | null;
|
||||
batch?: number | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
|
||||
declare module 'payload' {
|
||||
export interface GeneratedTypes extends Config {}
|
||||
}
|
||||
122
api/payload.config.ts
Normal file
122
api/payload.config.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import path from 'path'
|
||||
// import { postgresAdapter } from '@payloadcms/db-postgres'
|
||||
import { en } from 'payload/i18n/en'
|
||||
import {
|
||||
AlignFeature,
|
||||
BlockquoteFeature,
|
||||
BlocksFeature,
|
||||
BoldFeature,
|
||||
ChecklistFeature,
|
||||
HeadingFeature,
|
||||
IndentFeature,
|
||||
InlineCodeFeature,
|
||||
ItalicFeature,
|
||||
lexicalEditor,
|
||||
LinkFeature,
|
||||
OrderedListFeature,
|
||||
ParagraphFeature,
|
||||
RelationshipFeature,
|
||||
UnorderedListFeature,
|
||||
UploadFeature,
|
||||
} from '@payloadcms/richtext-lexical'
|
||||
//import { slateEditor } from '@payloadcms/richtext-slate'
|
||||
import { mongooseAdapter } from '@payloadcms/db-mongodb'
|
||||
import { buildConfig } from 'payload'
|
||||
import sharp from 'sharp'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
export default buildConfig({
|
||||
//editor: slateEditor({}),
|
||||
editor: lexicalEditor(),
|
||||
collections: [
|
||||
{
|
||||
slug: 'users',
|
||||
auth: true,
|
||||
access: {
|
||||
delete: () => false,
|
||||
update: () => false,
|
||||
},
|
||||
fields: [],
|
||||
},
|
||||
{
|
||||
slug: 'pages',
|
||||
admin: {
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'content',
|
||||
type: 'richText',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
slug: 'media',
|
||||
upload: true,
|
||||
fields: [
|
||||
{
|
||||
name: 'text',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
secret: process.env.PAYLOAD_SECRET || '',
|
||||
typescript: {
|
||||
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
||||
},
|
||||
// db: postgresAdapter({
|
||||
// pool: {
|
||||
// connectionString: process.env.POSTGRES_URI || ''
|
||||
// }
|
||||
// }),
|
||||
db: mongooseAdapter({
|
||||
url: process.env.MONGODB_URI || '',
|
||||
}),
|
||||
|
||||
/**
|
||||
* Payload can now accept specific translations from 'payload/i18n/en'
|
||||
* This is completely optional and will default to English if not provided
|
||||
*/
|
||||
i18n: {
|
||||
supportedLanguages: { en },
|
||||
},
|
||||
|
||||
admin: {
|
||||
autoLogin: {
|
||||
email: 'dev@payloadcms.com',
|
||||
password: 'test',
|
||||
prefillOnly: true,
|
||||
},
|
||||
},
|
||||
async onInit(payload) {
|
||||
const existingUsers = await payload.find({
|
||||
collection: 'users',
|
||||
limit: 1,
|
||||
})
|
||||
|
||||
if (existingUsers.docs.length === 0) {
|
||||
await payload.create({
|
||||
collection: 'users',
|
||||
data: {
|
||||
email: 'dev@payloadcms.com',
|
||||
password: 'test',
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
// Sharp is now an optional dependency -
|
||||
// if you want to resize images, crop, set focal point, etc.
|
||||
// make sure to install it and pass it to the config.
|
||||
|
||||
// This is temporary - we may make an adapter pattern
|
||||
// for this before reaching 3.0 stable
|
||||
sharp,
|
||||
})
|
||||
7750
api/pnpm-lock.yaml
generated
Normal file
7750
api/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
BIN
api/public/blur.png
Normal file
BIN
api/public/blur.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 170 KiB |
3
api/public/crosshair.svg
Normal file
3
api/public/crosshair.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 0H9V9H0V10H9V19H10V10H19V9H10V0Z" fill="white" fill-opacity="0.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 184 B |
BIN
api/public/gradient.webp
Normal file
BIN
api/public/gradient.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
2236
api/schema.graphql
Normal file
2236
api/schema.graphql
Normal file
File diff suppressed because it is too large
Load Diff
191
api/src/app/(app)/globals.scss
Normal file
191
api/src/app/(app)/globals.scss
Normal file
@@ -0,0 +1,191 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #ffffff;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
main {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding-block: 80px;
|
||||
border-inline-width: 1px;
|
||||
border-inline-style: solid;
|
||||
border-image: linear-gradient(180deg, #ffffff00, #ffffff00, #ffffff1a, #ffffff00) 1;
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
padding-block: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
article {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
padding: 60px 80px;
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
padding: 40px 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2.6px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #ffffff;
|
||||
font-size: 4rem;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
letter-spacing: -0.02rem;
|
||||
margin: 0;
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
font-weight: 300;
|
||||
line-height: 28px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #ffffff;
|
||||
text-decoration: underline;
|
||||
transition: color 0.2s ease-out;
|
||||
|
||||
&:hover {
|
||||
color: #ffffff80;
|
||||
}
|
||||
}
|
||||
|
||||
.codeBlock {
|
||||
position: relative;
|
||||
background-color: #00000066;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
padding: 60px 80px;
|
||||
overflow-x: auto;
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
padding: 40px 40px;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: calc(50% - 50vw);
|
||||
width: 100vw;
|
||||
height: 1px;
|
||||
background: linear-gradient(90deg, #ffffff00, #ffffff1a, #ffffff1a, #ffffff00);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: url('/crosshair.svg');
|
||||
display: block;
|
||||
height: 19px;
|
||||
width: 19px;
|
||||
position: absolute;
|
||||
top: -9px;
|
||||
left: -10px;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 14px;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: calc(50% - 50vw);
|
||||
width: 100vw;
|
||||
height: 1px;
|
||||
background: linear-gradient(90deg, #ffffff00, #ffffff1a, #ffffff1a, #ffffff00);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: url('/crosshair.svg');
|
||||
display: block;
|
||||
height: 19px;
|
||||
width: 19px;
|
||||
position: absolute;
|
||||
bottom: -9px;
|
||||
right: -10px;
|
||||
}
|
||||
}
|
||||
|
||||
.background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
|
||||
div.blur {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url('/blur.png');
|
||||
background-repeat: repeat;
|
||||
background-size: 400px 400px;
|
||||
background-blend-mode: soft-light, normal;
|
||||
backdrop-filter: blur(60px);
|
||||
}
|
||||
|
||||
div.gradient {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: url('/gradient.webp');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
z-index: -2;
|
||||
}
|
||||
}
|
||||
19
api/src/app/(app)/layout.tsx
Normal file
19
api/src/app/(app)/layout.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import React from 'react'
|
||||
import './globals.scss'
|
||||
import { Inter } from 'next/font/google'
|
||||
|
||||
const inter = Inter({
|
||||
subsets: ['latin'],
|
||||
display: 'swap',
|
||||
})
|
||||
|
||||
/* Our app sits here to not cause any conflicts with payload's root layout */
|
||||
const Layout: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
return (
|
||||
<html className={inter.className}>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
|
||||
export default Layout
|
||||
52
api/src/app/(app)/page.tsx
Normal file
52
api/src/app/(app)/page.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import { Badge } from '@/components/Badge'
|
||||
import { Background } from '@/components/Background'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
|
||||
const Page = () => {
|
||||
return (
|
||||
<>
|
||||
<main>
|
||||
<article>
|
||||
<Badge />
|
||||
<h1>Payload 3.0</h1>
|
||||
<p>
|
||||
This BETA is rapidly evolving, you can report any bugs against{' '}
|
||||
<Link href="https://github.com/payloadcms/payload-3.0-demo/issues" target="_blank">
|
||||
the repo
|
||||
</Link>{' '}
|
||||
or in the{' '}
|
||||
<Link
|
||||
href="https://discord.com/channels/967097582721572934/1215659716538273832"
|
||||
target="_blank"
|
||||
>
|
||||
dedicated channel in Discord
|
||||
</Link>
|
||||
. Payload is running at <Link href="/admin">/admin</Link>. An example of a custom route
|
||||
running the Local API can be found at <Link href="/my-route">/my-route</Link>.
|
||||
</p>
|
||||
<p>You can use the Local API in your server components like this:</p>
|
||||
</article>
|
||||
<div className="codeBlock">
|
||||
<pre>
|
||||
<code>
|
||||
{`import { getPayloadHMR } from '@payloadcms/next/utilities'
|
||||
import configPromise from '@payload-config'
|
||||
const payload = await getPayloadHMR({ config: configPromise })
|
||||
|
||||
const data = await payload.find({
|
||||
collection: 'posts',
|
||||
})
|
||||
|
||||
return <Posts data={data} />
|
||||
`}
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
</main>
|
||||
<Background />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Page
|
||||
22
api/src/app/(payload)/admin/[[...segments]]/not-found.tsx
Normal file
22
api/src/app/(payload)/admin/[[...segments]]/not-found.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
import type { Metadata } from 'next'
|
||||
|
||||
import config from '@payload-config'
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import { NotFoundPage, generatePageMetadata } from '@payloadcms/next/views'
|
||||
|
||||
type Args = {
|
||||
params: {
|
||||
segments: string[]
|
||||
}
|
||||
searchParams: {
|
||||
[key: string]: string | string[]
|
||||
}
|
||||
}
|
||||
|
||||
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
|
||||
generatePageMetadata({ config, params, searchParams })
|
||||
|
||||
const NotFound = ({ params, searchParams }: Args) => NotFoundPage({ config, params, searchParams })
|
||||
|
||||
export default NotFound
|
||||
22
api/src/app/(payload)/admin/[[...segments]]/page.tsx
Normal file
22
api/src/app/(payload)/admin/[[...segments]]/page.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
import type { Metadata } from 'next'
|
||||
|
||||
import config from '@payload-config'
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import { RootPage, generatePageMetadata } from '@payloadcms/next/views'
|
||||
|
||||
type Args = {
|
||||
params: {
|
||||
segments: string[]
|
||||
}
|
||||
searchParams: {
|
||||
[key: string]: string | string[]
|
||||
}
|
||||
}
|
||||
|
||||
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
|
||||
generatePageMetadata({ config, params, searchParams })
|
||||
|
||||
const Page = ({ params, searchParams }: Args) => RootPage({ config, params, searchParams })
|
||||
|
||||
export default Page
|
||||
10
api/src/app/(payload)/api/[...slug]/route.ts
Normal file
10
api/src/app/(payload)/api/[...slug]/route.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY it because it could be re-written at any time. */
|
||||
import config from '@payload-config'
|
||||
import { REST_DELETE, REST_GET, REST_OPTIONS, REST_PATCH, REST_POST } from '@payloadcms/next/routes'
|
||||
|
||||
export const GET = REST_GET(config)
|
||||
export const POST = REST_POST(config)
|
||||
export const DELETE = REST_DELETE(config)
|
||||
export const PATCH = REST_PATCH(config)
|
||||
export const OPTIONS = REST_OPTIONS(config)
|
||||
6
api/src/app/(payload)/api/graphql-playground/route.ts
Normal file
6
api/src/app/(payload)/api/graphql-playground/route.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY it because it could be re-written at any time. */
|
||||
import config from '@payload-config'
|
||||
import { GRAPHQL_PLAYGROUND_GET } from '@payloadcms/next/routes'
|
||||
|
||||
export const GET = GRAPHQL_PLAYGROUND_GET(config)
|
||||
6
api/src/app/(payload)/api/graphql/route.ts
Normal file
6
api/src/app/(payload)/api/graphql/route.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY it because it could be re-written at any time. */
|
||||
import config from '@payload-config'
|
||||
import { GRAPHQL_POST } from '@payloadcms/next/routes'
|
||||
|
||||
export const POST = GRAPHQL_POST(config)
|
||||
0
api/src/app/(payload)/custom.scss
Normal file
0
api/src/app/(payload)/custom.scss
Normal file
16
api/src/app/(payload)/layout.tsx
Normal file
16
api/src/app/(payload)/layout.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
import configPromise from '@payload-config'
|
||||
import '@payloadcms/next/css'
|
||||
import { RootLayout } from '@payloadcms/next/layouts'
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import React from 'react'
|
||||
|
||||
import './custom.scss'
|
||||
|
||||
type Args = {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
const Layout = ({ children }: Args) => <RootLayout config={configPromise}>{children}</RootLayout>
|
||||
|
||||
export default Layout
|
||||
14
api/src/app/my-route/route.ts
Normal file
14
api/src/app/my-route/route.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { getPayloadHMR } from '@payloadcms/next/utilities'
|
||||
import configPromise from '@payload-config'
|
||||
|
||||
export const GET = async () => {
|
||||
const payload = await getPayloadHMR({
|
||||
config: configPromise,
|
||||
})
|
||||
|
||||
const data = await payload.find({
|
||||
collection: 'users',
|
||||
})
|
||||
|
||||
return Response.json(data)
|
||||
}
|
||||
8
api/src/components/Background.tsx
Normal file
8
api/src/components/Background.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
export const Background = () => {
|
||||
return (
|
||||
<div className="background">
|
||||
<div className="blur" />
|
||||
<div className="gradient" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
20
api/src/components/Badge.tsx
Normal file
20
api/src/components/Badge.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
export const Badge = () => {
|
||||
return (
|
||||
<span className="badge">
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.35899 1.59033L16.956 6.233V15.0452L11.2355 18.4097V9.59751L3.62941 4.96095L9.35899 1.59033Z"
|
||||
fill="#ffffff"
|
||||
/>
|
||||
<path d="M8.77667 17.9211V11.0447L3.04407 14.4153L8.77667 17.9211Z" fill="#ffffff" />
|
||||
</svg>
|
||||
Beta
|
||||
</span>
|
||||
)
|
||||
}
|
||||
11
api/src/components/Example.tsx
Normal file
11
api/src/components/Example.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import React from 'react'
|
||||
import { getPayloadHMR } from '@payloadcms/next/utilities'
|
||||
import configPromise from '@payload-config'
|
||||
|
||||
const Example: React.FC = async () => {
|
||||
const payload = await getPayloadHMR({ config: configPromise })
|
||||
const url = payload.getAdminURL()
|
||||
return <div>The admin panel is running at: {url}</div>
|
||||
}
|
||||
|
||||
export default Example
|
||||
21
api/src/scripts/standalone-script.js
Normal file
21
api/src/scripts/standalone-script.js
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* This is an example of a standalone script that loads in the Payload config
|
||||
* and uses the Payload Local API to query the database.
|
||||
*/
|
||||
|
||||
import { getPayload } from 'payload'
|
||||
import { importConfig } from 'payload/node'
|
||||
|
||||
async function run() {
|
||||
const awaitedConfig = await importConfig('../../payload.config.ts')
|
||||
const payload = await getPayload({ config: awaitedConfig })
|
||||
|
||||
const pages = await payload.find({
|
||||
collection: 'pages',
|
||||
})
|
||||
|
||||
console.log(pages)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
run().catch(console.error)
|
||||
28
api/start-database.sh
Normal file
28
api/start-database.sh
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
DB_CONTAINER_NAME="next-payload-3"
|
||||
|
||||
if ! [ -x "$(command -v docker)" ]; then
|
||||
echo "Docker is not installed. Please install docker and try again.\nDocker install guide: https://docs.docker.com/engine/install/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$(docker ps -q -f name=$DB_CONTAINER_NAME)" ]; then
|
||||
docker start $DB_CONTAINER_NAME
|
||||
echo "Database container started"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
set -a
|
||||
source .env
|
||||
|
||||
DB_PASSWORD=$(echo $DATABASE_URL | awk -F':' '{print $3}' | awk -F'@' '{print $1}')
|
||||
|
||||
if [ "$DB_PASSWORD" = "password" ]; then
|
||||
echo "You are using the default database password"
|
||||
fi
|
||||
|
||||
docker run --name $DB_CONTAINER_NAME -e POSTGRES_PASSWORD=$DB_PASSWORD -e POSTGRES_HOST_AUTH_METHOD=trust -e POSTGRES_DB=next-payload-3 -d -p 5432:5432 docker.io/postgres
|
||||
|
||||
echo "Database container was successfully created"
|
||||
|
||||
44
api/tsconfig.json
Normal file
44
api/tsconfig.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
],
|
||||
"@payload-config": [
|
||||
"./payload.config.ts"
|
||||
]
|
||||
},
|
||||
"target": "ES2017"
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user