chore(templates): add generated templates [no-lint] (#6604)
Generate static template variations
This commit is contained in:
33
.github/workflows/main.yml
vendored
33
.github/workflows/main.yml
vendored
@@ -56,7 +56,8 @@ jobs:
|
||||
echo "templates: ${{ steps.filter.outputs.templates }}"
|
||||
|
||||
lint:
|
||||
if: github.event_name == 'pull_request'
|
||||
if: >
|
||||
github.event_name == 'pull_request' && !contains(github.event.pull_request.title, 'no-lint') && !contains(github.event.pull_request.title, 'skip-lint')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -500,6 +501,36 @@ jobs:
|
||||
yarn build
|
||||
yarn generate:types
|
||||
|
||||
generated-templates:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# https://github.com/actions/virtual-environments/issues/1187
|
||||
- name: tune linux network
|
||||
run: sudo ethtool -K eth0 tx off rx off
|
||||
|
||||
- name: Setup Node@${{ env.NODE_VERSION }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: ${{ env.PNPM_VERSION }}
|
||||
run_install: false
|
||||
|
||||
- name: Restore build
|
||||
uses: actions/cache@v4
|
||||
timeout-minutes: 10
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}-${{ github.run_number }}
|
||||
|
||||
- name: Build all generated templates
|
||||
run: pnpm tsx ./scripts/build-generated-templates.ts
|
||||
|
||||
all-green:
|
||||
name: All Green
|
||||
if: always()
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
"reinstall": "pnpm clean:all && pnpm install",
|
||||
"release:alpha": "tsx ./scripts/release.ts --bump prerelease --tag alpha",
|
||||
"release:beta": "tsx ./scripts/release.ts --bump prerelease --tag beta",
|
||||
"script:gen-templates": "tsx ./scripts/generate-template-variations.ts",
|
||||
"script:list-published": "tsx scripts/lib/getPackageRegistryVersions.ts",
|
||||
"script:pack": "tsx scripts/pack-all-to-dest.ts",
|
||||
"pretest": "pnpm build",
|
||||
@@ -107,6 +108,7 @@
|
||||
"changelogen": "^0.5.5",
|
||||
"comment-json": "^4.2.3",
|
||||
"copyfiles": "2.4.1",
|
||||
"create-payload-app": "workspace:*",
|
||||
"cross-env": "7.0.3",
|
||||
"dotenv": "16.4.5",
|
||||
"drizzle-kit": "0.20.14-1f2c838",
|
||||
|
||||
@@ -10,10 +10,24 @@
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./types": {
|
||||
"import": "./src/types.ts",
|
||||
"require": "./src/types.ts"
|
||||
},
|
||||
"./commands": {
|
||||
"import": "./src/lib/init-next.ts",
|
||||
"require": "./src/lib/init-next.ts",
|
||||
"types": "./src/lib/init-next.ts"
|
||||
},
|
||||
"./lib/*": {
|
||||
"import": "./src/lib/*",
|
||||
"require": "./src/lib/*",
|
||||
"types": "./src/lib/*"
|
||||
},
|
||||
"./utils/*": {
|
||||
"import": "./src/utils/*",
|
||||
"require": "./src/utils/*",
|
||||
"types": "./src/utils/*"
|
||||
}
|
||||
},
|
||||
"bin": {
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
import fse from 'fs-extra'
|
||||
import globby from 'globby'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import path from 'path'
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
import type { DbDetails } from '../types.js'
|
||||
import type { DbType, StorageAdapterType } from '../types.js'
|
||||
|
||||
import { warning } from '../utils/log.js'
|
||||
import { dbReplacements } from './packages.js'
|
||||
import { configReplacements, dbReplacements, storageReplacements } from './replacements.js'
|
||||
|
||||
/** Update payload config with necessary imports and adapters */
|
||||
export async function configurePayloadConfig(args: {
|
||||
dbDetails: DbDetails | undefined
|
||||
dbType?: DbType
|
||||
envNames?: {
|
||||
dbUri: string
|
||||
}
|
||||
packageJsonName?: string
|
||||
projectDirOrConfigPath: { payloadConfigPath: string } | { projectDir: string }
|
||||
storageAdapter?: StorageAdapterType
|
||||
sharp?: boolean
|
||||
}): Promise<void> {
|
||||
if (!args.dbDetails) {
|
||||
if (!args.dbType) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -28,7 +31,7 @@ export async function configurePayloadConfig(args: {
|
||||
try {
|
||||
const packageObj = await fse.readJson(packageJsonPath)
|
||||
|
||||
const dbPackage = dbReplacements[args.dbDetails.type]
|
||||
const dbPackage = dbReplacements[args.dbType]
|
||||
|
||||
// Delete all other db adapters
|
||||
Object.values(dbReplacements).forEach((p) => {
|
||||
@@ -40,6 +43,24 @@ export async function configurePayloadConfig(args: {
|
||||
// Set version of db adapter to match payload version
|
||||
packageObj.dependencies[dbPackage.packageName] = packageObj.dependencies['payload']
|
||||
|
||||
if (args.storageAdapter) {
|
||||
const storagePackage = storageReplacements[args.storageAdapter]
|
||||
|
||||
if (storagePackage?.packageName) {
|
||||
// Set version of storage adapter to match payload version
|
||||
packageObj.dependencies[storagePackage.packageName] = packageObj.dependencies['payload']
|
||||
}
|
||||
}
|
||||
|
||||
// Sharp provided by default, only remove if explicitly set to false
|
||||
if (args.sharp === false) {
|
||||
delete packageObj.dependencies['sharp']
|
||||
}
|
||||
|
||||
if (args.packageJsonName) {
|
||||
packageObj.name = args.packageJsonName
|
||||
}
|
||||
|
||||
await fse.writeJson(packageJsonPath, packageObj, { spaces: 2 })
|
||||
} catch (err: unknown) {
|
||||
warning(`Unable to configure Payload in package.json`)
|
||||
@@ -66,35 +87,54 @@ export async function configurePayloadConfig(args: {
|
||||
}
|
||||
|
||||
const configContent = fse.readFileSync(payloadConfigPath, 'utf-8')
|
||||
const configLines = configContent.split('\n')
|
||||
let configLines = configContent.split('\n')
|
||||
|
||||
const dbReplacement = dbReplacements[args.dbDetails.type]
|
||||
// DB Replacement
|
||||
const dbReplacement = dbReplacements[args.dbType]
|
||||
|
||||
let dbConfigStartLineIndex: number | undefined
|
||||
let dbConfigEndLineIndex: number | undefined
|
||||
|
||||
configLines.forEach((l, i) => {
|
||||
if (l.includes('// database-adapter-import')) {
|
||||
configLines[i] = dbReplacement.importReplacement
|
||||
}
|
||||
|
||||
if (l.includes('// database-adapter-config-start')) {
|
||||
dbConfigStartLineIndex = i
|
||||
}
|
||||
if (l.includes('// database-adapter-config-end')) {
|
||||
dbConfigEndLineIndex = i
|
||||
}
|
||||
configLines = replaceInConfigLines({
|
||||
replacement: dbReplacement.configReplacement(args.envNames?.dbUri),
|
||||
startMatch: `// database-adapter-config-start`,
|
||||
endMatch: `// database-adapter-config-end`,
|
||||
lines: configLines,
|
||||
})
|
||||
|
||||
if (!dbConfigStartLineIndex || !dbConfigEndLineIndex) {
|
||||
warning('Unable to update payload.config.ts with database adapter import')
|
||||
} else {
|
||||
// Replaces lines between `// database-adapter-config-start` and `// database-adapter-config-end`
|
||||
configLines.splice(
|
||||
dbConfigStartLineIndex,
|
||||
dbConfigEndLineIndex - dbConfigStartLineIndex + 1,
|
||||
...dbReplacement.configReplacement,
|
||||
)
|
||||
configLines = replaceInConfigLines({
|
||||
replacement: [dbReplacement.importReplacement],
|
||||
startMatch: '// database-adapter-import',
|
||||
lines: configLines,
|
||||
})
|
||||
|
||||
// Storage Adapter Replacement
|
||||
if (args.storageAdapter) {
|
||||
const replacement = storageReplacements[args.storageAdapter]
|
||||
configLines = replaceInConfigLines({
|
||||
replacement: replacement.configReplacement,
|
||||
startMatch: '// storage-adapter-placeholder',
|
||||
lines: configLines,
|
||||
})
|
||||
|
||||
if (replacement?.importReplacement) {
|
||||
configLines = replaceInConfigLines({
|
||||
replacement: [replacement.importReplacement],
|
||||
startMatch: '// storage-adapter-import-placeholder',
|
||||
lines: configLines,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Sharp Replacement (provided by default, only remove if explicitly set to false)
|
||||
if (args.sharp === false) {
|
||||
configLines = replaceInConfigLines({
|
||||
replacement: [],
|
||||
startMatch: 'sharp,',
|
||||
lines: configLines,
|
||||
})
|
||||
configLines = replaceInConfigLines({
|
||||
replacement: [],
|
||||
startMatch: "import sharp from 'sharp'",
|
||||
lines: configLines,
|
||||
})
|
||||
}
|
||||
|
||||
fse.writeFileSync(payloadConfigPath, configLines.join('\n'))
|
||||
@@ -104,3 +144,30 @@ export async function configurePayloadConfig(args: {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function replaceInConfigLines({
|
||||
replacement,
|
||||
startMatch,
|
||||
endMatch,
|
||||
lines,
|
||||
}: {
|
||||
replacement: string[]
|
||||
startMatch: string
|
||||
/** Optional endMatch to replace multiple lines */
|
||||
endMatch?: string
|
||||
lines: string[]
|
||||
}) {
|
||||
if (!replacement) {
|
||||
return lines
|
||||
}
|
||||
|
||||
const startIndex = lines.findIndex((l) => l.includes(startMatch))
|
||||
const endIndex = endMatch ? lines.findIndex((l) => l.includes(endMatch)) : startIndex
|
||||
|
||||
if (startIndex === -1 || endIndex === -1) {
|
||||
return lines
|
||||
}
|
||||
|
||||
lines.splice(startIndex, endIndex - startIndex + 1, ...replacement)
|
||||
return lines
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import fse from 'fs-extra'
|
||||
import path from 'path'
|
||||
import type { CliArgs, DbType, ProjectTemplate } from '../types.js'
|
||||
import { createProject } from './create-project.js'
|
||||
import { dbReplacements } from './packages.js'
|
||||
import { dbReplacements } from './replacements.js'
|
||||
import { getValidTemplates } from './templates.js'
|
||||
import globby from 'globby'
|
||||
import { jest } from '@jest/globals'
|
||||
@@ -125,7 +125,7 @@ describe('createProject', () => {
|
||||
|
||||
expect(content).not.toContain('// database-adapter-config-start')
|
||||
expect(content).not.toContain('// database-adapter-config-end')
|
||||
expect(content).toContain(dbReplacement.configReplacement.join('\n'))
|
||||
expect(content).toContain(dbReplacement.configReplacement().join('\n'))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -90,7 +90,10 @@ export async function createProject(args: {
|
||||
|
||||
await updatePackageJSON({ projectDir, projectName })
|
||||
spinner.message('Configuring Payload...')
|
||||
await configurePayloadConfig({ dbDetails, projectDirOrConfigPath: { projectDir } })
|
||||
await configurePayloadConfig({
|
||||
dbType: dbDetails?.type,
|
||||
projectDirOrConfigPath: { projectDir },
|
||||
})
|
||||
|
||||
// Remove yarn.lock file. This is only desired in Payload Cloud.
|
||||
const lockPath = path.resolve(projectDir, 'yarn.lock')
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import type { DbType } from '../types.js'
|
||||
|
||||
type DbAdapterReplacement = {
|
||||
configReplacement: string[]
|
||||
importReplacement: string
|
||||
packageName: string
|
||||
}
|
||||
|
||||
const mongodbReplacement: DbAdapterReplacement = {
|
||||
importReplacement: "import { mongooseAdapter } from '@payloadcms/db-mongodb'",
|
||||
packageName: '@payloadcms/db-mongodb',
|
||||
// Replacement between `// database-adapter-config-start` and `// database-adapter-config-end`
|
||||
configReplacement: [
|
||||
' db: mongooseAdapter({',
|
||||
" url: process.env.DATABASE_URI || '',",
|
||||
' }),',
|
||||
],
|
||||
}
|
||||
|
||||
const postgresReplacement: DbAdapterReplacement = {
|
||||
configReplacement: [
|
||||
' db: postgresAdapter({',
|
||||
' pool: {',
|
||||
" connectionString: process.env.DATABASE_URI || '',",
|
||||
' },',
|
||||
' }),',
|
||||
],
|
||||
importReplacement: "import { postgresAdapter } from '@payloadcms/db-postgres'",
|
||||
packageName: '@payloadcms/db-postgres',
|
||||
}
|
||||
|
||||
export const dbReplacements: Record<DbType, DbAdapterReplacement> = {
|
||||
mongodb: mongodbReplacement,
|
||||
postgres: postgresReplacement,
|
||||
}
|
||||
96
packages/create-payload-app/src/lib/replacements.ts
Normal file
96
packages/create-payload-app/src/lib/replacements.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import type { DbType, StorageAdapterType } from '../types.js'
|
||||
|
||||
type DbAdapterReplacement = {
|
||||
configReplacement: (envName?: string) => string[]
|
||||
importReplacement: string
|
||||
packageName: string
|
||||
}
|
||||
|
||||
const mongodbReplacement: DbAdapterReplacement = {
|
||||
// Replacement between `// database-adapter-config-start` and `// database-adapter-config-end`
|
||||
configReplacement: (envName = 'DATABASE_URI') => [
|
||||
' db: mongooseAdapter({',
|
||||
` url: process.env.${envName} || '',`,
|
||||
' }),',
|
||||
],
|
||||
importReplacement: "import { mongooseAdapter } from '@payloadcms/db-mongodb'",
|
||||
packageName: '@payloadcms/db-mongodb',
|
||||
}
|
||||
|
||||
const postgresReplacement: DbAdapterReplacement = {
|
||||
configReplacement: (envName = 'DATABASE_URI') => [
|
||||
' db: postgresAdapter({',
|
||||
' pool: {',
|
||||
` connectionString: process.env.${envName} || '',`,
|
||||
' },',
|
||||
' }),',
|
||||
],
|
||||
importReplacement: "import { postgresAdapter } from '@payloadcms/db-postgres'",
|
||||
packageName: '@payloadcms/db-postgres',
|
||||
}
|
||||
|
||||
export const dbReplacements: Record<DbType, DbAdapterReplacement> = {
|
||||
mongodb: mongodbReplacement,
|
||||
postgres: postgresReplacement,
|
||||
}
|
||||
|
||||
type StorageAdapterReplacement = {
|
||||
configReplacement: string[]
|
||||
importReplacement?: string
|
||||
packageName?: string
|
||||
}
|
||||
|
||||
const vercelBlobStorageReplacement: StorageAdapterReplacement = {
|
||||
// Replacement of `// storage-adapter-placeholder`
|
||||
configReplacement: [
|
||||
' vercelBlobStorage({',
|
||||
' collections: {',
|
||||
' [Media.slug]: true,',
|
||||
' },',
|
||||
" token: process.env.BLOB_READ_WRITE_TOKEN || '',",
|
||||
' }),',
|
||||
],
|
||||
importReplacement: "import { vercelBlobStorage } from '@payloadcms/storage-vercel-blob'",
|
||||
packageName: '@payloadcms/storage-vercel-blob',
|
||||
}
|
||||
|
||||
const payloadCloudReplacement: StorageAdapterReplacement = {
|
||||
configReplacement: [' payloadCloudPlugin(),'],
|
||||
importReplacement: "import { payloadCloudPlugin } from '@payloadcms/plugin-cloud'",
|
||||
packageName: '@payloadcms/plugin-cloud',
|
||||
}
|
||||
|
||||
// Removes placeholders
|
||||
const diskReplacement: StorageAdapterReplacement = {
|
||||
configReplacement: [],
|
||||
}
|
||||
|
||||
export const storageReplacements: Record<StorageAdapterType, StorageAdapterReplacement> = {
|
||||
payloadCloud: payloadCloudReplacement,
|
||||
vercelBlobStorage: vercelBlobStorageReplacement,
|
||||
localDisk: diskReplacement,
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic config replacement
|
||||
*/
|
||||
type ConfigReplacement = {
|
||||
configReplacement: {
|
||||
match: string
|
||||
replacement: string
|
||||
}
|
||||
importReplacement: string
|
||||
packageName: string
|
||||
}
|
||||
|
||||
export const configReplacements: Record<string, ConfigReplacement> = {
|
||||
sharp: {
|
||||
// Replacement of `sharp, // Now optional`
|
||||
configReplacement: {
|
||||
match: 'sharp,',
|
||||
replacement: ' // sharp,',
|
||||
},
|
||||
importReplacement: "import sharp from 'sharp'",
|
||||
packageName: 'sharp',
|
||||
},
|
||||
}
|
||||
@@ -95,7 +95,7 @@ export class Main {
|
||||
message: chalk.bold(`Upgrade Payload in this project?`),
|
||||
})
|
||||
|
||||
if (!p.isCancel(shouldUpdate) || shouldUpdate) {
|
||||
if (!p.isCancel(shouldUpdate) && shouldUpdate) {
|
||||
const { message, success: updateSuccess } = await updatePayloadInProject(nextAppDetails)
|
||||
if (updateSuccess) {
|
||||
info(message)
|
||||
@@ -156,7 +156,7 @@ export class Main {
|
||||
}
|
||||
|
||||
await configurePayloadConfig({
|
||||
dbDetails,
|
||||
dbType: dbDetails?.type,
|
||||
projectDirOrConfigPath: {
|
||||
payloadConfigPath: result.payloadConfigPath,
|
||||
},
|
||||
|
||||
@@ -76,3 +76,5 @@ export type NextAppDetails = {
|
||||
}
|
||||
|
||||
export type NextConfigType = 'cjs' | 'esm'
|
||||
|
||||
export type StorageAdapterType = 'payloadCloud' | 'vercelBlobStorage' | 'localDisk'
|
||||
|
||||
@@ -3,6 +3,8 @@ import path from 'path'
|
||||
|
||||
/**
|
||||
* Recursively copy files from src to dest
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function copyRecursiveSync(src: string, dest: string, debug?: boolean) {
|
||||
const exists = fs.existsSync(src)
|
||||
|
||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@@ -95,6 +95,9 @@ importers:
|
||||
copyfiles:
|
||||
specifier: 2.4.1
|
||||
version: 2.4.1
|
||||
create-payload-app:
|
||||
specifier: workspace:*
|
||||
version: link:packages/create-payload-app
|
||||
cross-env:
|
||||
specifier: 7.0.3
|
||||
version: 7.0.3
|
||||
|
||||
36
scripts/build-generated-templates.ts
Normal file
36
scripts/build-generated-templates.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import * as fs from 'node:fs/promises'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import path from 'path'
|
||||
import { execSync } from 'child_process'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
async function main() {
|
||||
// Get all directories in `templates` directory
|
||||
const repoRoot = path.resolve(dirname, '..')
|
||||
const templatesDir = path.resolve(repoRoot, 'templates')
|
||||
|
||||
const rawTemplateDirs = await fs.readdir(templatesDir, { withFileTypes: true })
|
||||
const templateDirnames = rawTemplateDirs
|
||||
.filter(
|
||||
(dirent) =>
|
||||
dirent.isDirectory() && (dirent.name.startsWith('with') || dirent.name == 'blank'),
|
||||
)
|
||||
.map((dirent) => dirent.name)
|
||||
|
||||
console.log(`Found generated templates: ${templateDirnames}`)
|
||||
|
||||
// Build each template
|
||||
for (const template of templateDirnames) {
|
||||
const cmd = `cd ${templatesDir}/${template} && pnpm install --ignore-workspace --no-frozen-lockfile && pnpm build`
|
||||
console.log(`🔧 Building ${template}...`)
|
||||
console.log(` cmd: ${cmd}\n\n`)
|
||||
execSync(cmd, { stdio: 'inherit' })
|
||||
}
|
||||
}
|
||||
196
scripts/generate-template-variations.ts
Normal file
196
scripts/generate-template-variations.ts
Normal file
@@ -0,0 +1,196 @@
|
||||
/**
|
||||
* This script generates variations of the templates into the `templates` directory.
|
||||
*
|
||||
* How to use:
|
||||
*
|
||||
* pnpm run script:gen-templates
|
||||
*
|
||||
* NOTE: You will likely have to commit by using the `--no-verify` flag to avoid the repo linting
|
||||
* There is no way currently to have lint-staged ignore the templates directory.
|
||||
*/
|
||||
|
||||
import type { DbType, StorageAdapterType } from 'packages/create-payload-app/src/types.js'
|
||||
|
||||
import { configurePayloadConfig } from 'create-payload-app/lib/configure-payload-config.js'
|
||||
import { copyRecursiveSync } from 'create-payload-app/utils/copy-recursive-sync.js'
|
||||
import * as fs from 'node:fs/promises'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import path from 'path'
|
||||
import { execSync } from 'child_process'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
type TemplateVariations = {
|
||||
/** package.json name */
|
||||
name: string
|
||||
/** Directory in templates dir */
|
||||
dirname: string
|
||||
db: DbType
|
||||
storage: StorageAdapterType
|
||||
sharp: boolean
|
||||
vercelDeployButtonLink?: string
|
||||
envNames?: {
|
||||
dbUri: string
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
async function main() {
|
||||
const templatesDir = path.resolve(dirname, '../templates')
|
||||
|
||||
// WARNING: This will need to be updated when this merges into main
|
||||
const templateRepoUrlBase = `https://github.com/payloadcms/payload/tree/beta/templates`
|
||||
|
||||
const variations: TemplateVariations[] = [
|
||||
{
|
||||
name: 'payload-vercel-postgres-template',
|
||||
dirname: 'with-vercel-postgres',
|
||||
db: 'postgres',
|
||||
storage: 'vercelBlobStorage',
|
||||
sharp: false,
|
||||
vercelDeployButtonLink:
|
||||
`https://vercel.com/new/clone?repository-url=` +
|
||||
encodeURI(
|
||||
`${templateRepoUrlBase}/${dirname}` +
|
||||
'&project-name=payload-project' +
|
||||
'&env=PAYLOAD_SECRET' +
|
||||
'&build-command=pnpm run ci' +
|
||||
'&stores=[{"type":"postgres"},{"type":"blob"}]', // Postgres and Vercel Blob Storage
|
||||
),
|
||||
envNames: {
|
||||
// This will replace the process.env.DATABASE_URI to process.env.POSTGRES_URL
|
||||
dbUri: 'POSTGRES_URL',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'payload-vercel-mongodb-template',
|
||||
dirname: 'with-vercel-mongodb',
|
||||
db: 'mongodb',
|
||||
storage: 'vercelBlobStorage',
|
||||
sharp: false,
|
||||
vercelDeployButtonLink:
|
||||
`https://vercel.com/new/clone?repository-url=` +
|
||||
encodeURI(
|
||||
`${templateRepoUrlBase}/${dirname}` +
|
||||
'&project-name=payload-project' +
|
||||
'&env=PAYLOAD_SECRET' +
|
||||
'&build-command=pnpm run ci' +
|
||||
'&stores=[{"type":"blob"}]' + // Vercel Blob Storage
|
||||
'&integration-ids=oac_jnzmjqM10gllKmSrG0SGrHOH', // MongoDB Atlas
|
||||
),
|
||||
envNames: {
|
||||
dbUri: 'MONGODB_URI',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'blank',
|
||||
dirname: 'blank',
|
||||
db: 'mongodb',
|
||||
storage: 'localDisk',
|
||||
sharp: true,
|
||||
},
|
||||
{
|
||||
name: 'payload-cloud-mongodb-template',
|
||||
dirname: 'with-payload-cloud',
|
||||
db: 'mongodb',
|
||||
storage: 'payloadCloud',
|
||||
sharp: true,
|
||||
},
|
||||
]
|
||||
|
||||
for (const {
|
||||
name,
|
||||
dirname,
|
||||
db,
|
||||
storage,
|
||||
vercelDeployButtonLink,
|
||||
envNames,
|
||||
sharp,
|
||||
} of variations) {
|
||||
console.log(`Generating ${name}...`)
|
||||
const destDir = path.join(templatesDir, dirname)
|
||||
copyRecursiveSync(path.join(templatesDir, '_template'), destDir)
|
||||
console.log(`Generated ${name} in ${destDir}`)
|
||||
|
||||
// Configure payload config
|
||||
await configurePayloadConfig({
|
||||
dbType: db,
|
||||
packageJsonName: name,
|
||||
projectDirOrConfigPath: { projectDir: destDir },
|
||||
storageAdapter: storage,
|
||||
sharp,
|
||||
envNames,
|
||||
})
|
||||
|
||||
await generateReadme({
|
||||
destDir,
|
||||
data: {
|
||||
name,
|
||||
description: name, // TODO: Add descriptions
|
||||
attributes: { db, storage },
|
||||
...(vercelDeployButtonLink && { vercelDeployButtonLink }),
|
||||
},
|
||||
})
|
||||
|
||||
// Copy in initial migration if db is postgres. This contains user and media.
|
||||
if (db === 'postgres') {
|
||||
const migrationSrcDir = path.join(templatesDir, '_data/migrations')
|
||||
const migrationDestDir = path.join(destDir, 'src/migrations')
|
||||
|
||||
// Make directory if it doesn't exist
|
||||
if ((await fs.stat(migrationDestDir).catch(() => null)) === null) {
|
||||
await fs.mkdir(migrationDestDir, { recursive: true })
|
||||
}
|
||||
console.log(`Copying migrations from ${migrationSrcDir} to ${migrationDestDir}`)
|
||||
copyRecursiveSync(migrationSrcDir, migrationDestDir)
|
||||
}
|
||||
|
||||
// TODO: Email?
|
||||
|
||||
// TODO: Sharp?
|
||||
|
||||
console.log(`Done configuring payload config for ${destDir}/src/payload.config.ts`)
|
||||
}
|
||||
// TODO: Run prettier manually on the generated files, husky blows up
|
||||
console.log('Running prettier on generated files...')
|
||||
execSync(`pnpm prettier --write templates "*.{js,jsx,ts,tsx}"`)
|
||||
|
||||
console.log('Template generation complete!')
|
||||
}
|
||||
|
||||
async function generateReadme({
|
||||
destDir,
|
||||
data: { name, description, attributes, vercelDeployButtonLink },
|
||||
}: {
|
||||
destDir: string
|
||||
data: {
|
||||
name: string
|
||||
description: string
|
||||
attributes: Pick<TemplateVariations, 'db' | 'storage'>
|
||||
vercelDeployButtonLink?: string
|
||||
}
|
||||
}) {
|
||||
let header = `# ${name}\n`
|
||||
if (vercelDeployButtonLink) {
|
||||
header += `\n[](${vercelDeployButtonLink})`
|
||||
}
|
||||
|
||||
const readmeContent = `${header}
|
||||
|
||||
${description}
|
||||
|
||||
## Attributes
|
||||
|
||||
- **Database**: ${attributes.db}
|
||||
- **Storage Adapter**: ${attributes.storage}
|
||||
`
|
||||
|
||||
const readmePath = path.join(destDir, 'README.md')
|
||||
await fs.writeFile(readmePath, readmeContent)
|
||||
console.log(`Generated README.md in ${readmePath}`)
|
||||
}
|
||||
375
templates/_data/migrations/initial.json
Normal file
375
templates/_data/migrations/initial.json
Normal file
@@ -0,0 +1,375 @@
|
||||
{
|
||||
"id": "8146d795-d1a9-49be-857d-4320898b38fb",
|
||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||
"version": "5",
|
||||
"dialect": "pg",
|
||||
"tables": {
|
||||
"users": {
|
||||
"name": "users",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "serial",
|
||||
"primaryKey": true,
|
||||
"notNull": true
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"reset_password_token": {
|
||||
"name": "reset_password_token",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"reset_password_expiration": {
|
||||
"name": "reset_password_expiration",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"salt": {
|
||||
"name": "salt",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"hash": {
|
||||
"name": "hash",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"login_attempts": {
|
||||
"name": "login_attempts",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"lock_until": {
|
||||
"name": "lock_until",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"users_created_at_idx": {
|
||||
"name": "users_created_at_idx",
|
||||
"columns": ["created_at"],
|
||||
"isUnique": false
|
||||
},
|
||||
"users_email_idx": {
|
||||
"name": "users_email_idx",
|
||||
"columns": ["email"],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"media": {
|
||||
"name": "media",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "serial",
|
||||
"primaryKey": true,
|
||||
"notNull": true
|
||||
},
|
||||
"alt": {
|
||||
"name": "alt",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"url": {
|
||||
"name": "url",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"thumbnail_u_r_l": {
|
||||
"name": "thumbnail_u_r_l",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"filename": {
|
||||
"name": "filename",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"mime_type": {
|
||||
"name": "mime_type",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"filesize": {
|
||||
"name": "filesize",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"width": {
|
||||
"name": "width",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"height": {
|
||||
"name": "height",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"focal_x": {
|
||||
"name": "focal_x",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"focal_y": {
|
||||
"name": "focal_y",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"media_created_at_idx": {
|
||||
"name": "media_created_at_idx",
|
||||
"columns": ["created_at"],
|
||||
"isUnique": false
|
||||
},
|
||||
"media_filename_idx": {
|
||||
"name": "media_filename_idx",
|
||||
"columns": ["filename"],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"payload_preferences": {
|
||||
"name": "payload_preferences",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "serial",
|
||||
"primaryKey": true,
|
||||
"notNull": true
|
||||
},
|
||||
"key": {
|
||||
"name": "key",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"value": {
|
||||
"name": "value",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"payload_preferences_key_idx": {
|
||||
"name": "payload_preferences_key_idx",
|
||||
"columns": ["key"],
|
||||
"isUnique": false
|
||||
},
|
||||
"payload_preferences_created_at_idx": {
|
||||
"name": "payload_preferences_created_at_idx",
|
||||
"columns": ["created_at"],
|
||||
"isUnique": false
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"payload_preferences_rels": {
|
||||
"name": "payload_preferences_rels",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "serial",
|
||||
"primaryKey": true,
|
||||
"notNull": true
|
||||
},
|
||||
"order": {
|
||||
"name": "order",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"parent_id": {
|
||||
"name": "parent_id",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"path": {
|
||||
"name": "path",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"users_id": {
|
||||
"name": "users_id",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"payload_preferences_rels_order_idx": {
|
||||
"name": "payload_preferences_rels_order_idx",
|
||||
"columns": ["order"],
|
||||
"isUnique": false
|
||||
},
|
||||
"payload_preferences_rels_parent_idx": {
|
||||
"name": "payload_preferences_rels_parent_idx",
|
||||
"columns": ["parent_id"],
|
||||
"isUnique": false
|
||||
},
|
||||
"payload_preferences_rels_path_idx": {
|
||||
"name": "payload_preferences_rels_path_idx",
|
||||
"columns": ["path"],
|
||||
"isUnique": false
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"payload_preferences_rels_parent_fk": {
|
||||
"name": "payload_preferences_rels_parent_fk",
|
||||
"tableFrom": "payload_preferences_rels",
|
||||
"tableTo": "payload_preferences",
|
||||
"columnsFrom": ["parent_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"payload_preferences_rels_users_fk": {
|
||||
"name": "payload_preferences_rels_users_fk",
|
||||
"tableFrom": "payload_preferences_rels",
|
||||
"tableTo": "users",
|
||||
"columnsFrom": ["users_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"payload_migrations": {
|
||||
"name": "payload_migrations",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "serial",
|
||||
"primaryKey": true,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"batch": {
|
||||
"name": "batch",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp(3) with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"payload_migrations_created_at_idx": {
|
||||
"name": "payload_migrations_created_at_idx",
|
||||
"columns": ["created_at"],
|
||||
"isUnique": false
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
}
|
||||
},
|
||||
"enums": {},
|
||||
"schemas": {},
|
||||
"_meta": {
|
||||
"schemas": {},
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
}
|
||||
}
|
||||
93
templates/_data/migrations/initial.ts
Normal file
93
templates/_data/migrations/initial.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import type { MigrateDownArgs, MigrateUpArgs } from '@payloadcms/db-postgres'
|
||||
|
||||
import { sql } from '@payloadcms/db-postgres'
|
||||
|
||||
export async function up({ payload }: MigrateUpArgs): Promise<void> {
|
||||
await payload.db.drizzle.execute(sql`
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "users" (
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||||
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||||
"email" varchar NOT NULL,
|
||||
"reset_password_token" varchar,
|
||||
"reset_password_expiration" timestamp(3) with time zone,
|
||||
"salt" varchar,
|
||||
"hash" varchar,
|
||||
"login_attempts" numeric,
|
||||
"lock_until" timestamp(3) with time zone
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "media" (
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"alt" varchar NOT NULL,
|
||||
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||||
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||||
"url" varchar,
|
||||
"thumbnail_u_r_l" varchar,
|
||||
"filename" varchar,
|
||||
"mime_type" varchar,
|
||||
"filesize" numeric,
|
||||
"width" numeric,
|
||||
"height" numeric,
|
||||
"focal_x" numeric,
|
||||
"focal_y" numeric
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "payload_preferences" (
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"key" varchar,
|
||||
"value" jsonb,
|
||||
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||||
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "payload_preferences_rels" (
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"order" integer,
|
||||
"parent_id" integer NOT NULL,
|
||||
"path" varchar NOT NULL,
|
||||
"users_id" integer
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "payload_migrations" (
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"name" varchar,
|
||||
"batch" numeric,
|
||||
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||||
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "users_created_at_idx" ON "users" ("created_at");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "users_email_idx" ON "users" ("email");
|
||||
CREATE INDEX IF NOT EXISTS "media_created_at_idx" ON "media" ("created_at");
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "media_filename_idx" ON "media" ("filename");
|
||||
CREATE INDEX IF NOT EXISTS "payload_preferences_key_idx" ON "payload_preferences" ("key");
|
||||
CREATE INDEX IF NOT EXISTS "payload_preferences_created_at_idx" ON "payload_preferences" ("created_at");
|
||||
CREATE INDEX IF NOT EXISTS "payload_preferences_rels_order_idx" ON "payload_preferences_rels" ("order");
|
||||
CREATE INDEX IF NOT EXISTS "payload_preferences_rels_parent_idx" ON "payload_preferences_rels" ("parent_id");
|
||||
CREATE INDEX IF NOT EXISTS "payload_preferences_rels_path_idx" ON "payload_preferences_rels" ("path");
|
||||
CREATE INDEX IF NOT EXISTS "payload_migrations_created_at_idx" ON "payload_migrations" ("created_at");
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "payload_preferences_rels" ADD CONSTRAINT "payload_preferences_rels_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "payload_preferences"("id") ON DELETE cascade ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE "payload_preferences_rels" ADD CONSTRAINT "payload_preferences_rels_users_fk" FOREIGN KEY ("users_id") REFERENCES "users"("id") ON DELETE cascade ON UPDATE no action;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
`)
|
||||
}
|
||||
|
||||
export async function down({ payload }: MigrateDownArgs): Promise<void> {
|
||||
await payload.db.drizzle.execute(sql`
|
||||
|
||||
DROP TABLE "users";
|
||||
DROP TABLE "media";
|
||||
DROP TABLE "payload_preferences";
|
||||
DROP TABLE "payload_preferences_rels";
|
||||
DROP TABLE "payload_migrations";`)
|
||||
}
|
||||
2
templates/_template/.env.example
Normal file
2
templates/_template/.env.example
Normal file
@@ -0,0 +1,2 @@
|
||||
DATABASE_URI=mongodb://127.0.0.1/payload-template-blank-3-0
|
||||
PAYLOAD_SECRET=YOUR_SECRET_HERE
|
||||
8
templates/_template/.eslintrc.cjs
Normal file
8
templates/_template/.eslintrc.cjs
Normal file
@@ -0,0 +1,8 @@
|
||||
/** @type {import('eslint').Linter.Config} */
|
||||
module.exports = {
|
||||
extends: ['next/core-web-vitals'],
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.json'],
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
}
|
||||
43
templates/_template/.gitignore
vendored
Normal file
43
templates/_template/.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
templates/_template/.prettierrc.json
Normal file
6
templates/_template/.prettierrc.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 100,
|
||||
"semi": false
|
||||
}
|
||||
1
templates/_template/.yarnrc
Normal file
1
templates/_template/.yarnrc
Normal file
@@ -0,0 +1 @@
|
||||
--install.ignore-engines true
|
||||
69
templates/_template/Dockerfile
Normal file
69
templates/_template/Dockerfile
Normal file
@@ -0,0 +1,69 @@
|
||||
# From https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
|
||||
|
||||
FROM node:18-alpine AS base
|
||||
|
||||
# Install dependencies only when needed
|
||||
FROM base AS deps
|
||||
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||
RUN apk add --no-cache libc6-compat
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies based on the preferred package manager
|
||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
|
||||
RUN \
|
||||
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
|
||||
elif [ -f package-lock.json ]; then npm ci; \
|
||||
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
|
||||
else echo "Lockfile not found." && exit 1; \
|
||||
fi
|
||||
|
||||
|
||||
# Rebuild the source code only when needed
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
|
||||
# Next.js collects completely anonymous telemetry data about general usage.
|
||||
# Learn more here: https://nextjs.org/telemetry
|
||||
# Uncomment the following line in case you want to disable telemetry during the build.
|
||||
# ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
RUN \
|
||||
if [ -f yarn.lock ]; then yarn run build; \
|
||||
elif [ -f package-lock.json ]; then npm run build; \
|
||||
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
|
||||
else echo "Lockfile not found." && exit 1; \
|
||||
fi
|
||||
|
||||
# Production image, copy all the files and run next
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV production
|
||||
# Uncomment the following line in case you want to disable telemetry during runtime.
|
||||
# ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
|
||||
COPY --from=builder /app/public ./public
|
||||
|
||||
# Set the correct permission for prerender cache
|
||||
RUN mkdir .next
|
||||
RUN chown nextjs:nodejs .next
|
||||
|
||||
# Automatically leverage output traces to reduce image size
|
||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV PORT 3000
|
||||
|
||||
# server.js is created by next build from the standalone output
|
||||
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
|
||||
CMD HOSTNAME="0.0.0.0" node server.js
|
||||
42
templates/_template/README.md
Normal file
42
templates/_template/README.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Payload Blank Template
|
||||
|
||||
A blank template for [Payload](https://github.com/payloadcms/payload) to help you get up and running quickly. This repo may have been created by running `npx create-payload-app@latest` and selecting the "blank" template or by cloning this template on [Payload Cloud](https://payloadcms.com/new/clone/blank).
|
||||
|
||||
See the official [Examples Directory](https://github.com/payloadcms/payload/tree/main/examples) for details on how to use Payload in a variety of different ways.
|
||||
|
||||
## Development
|
||||
|
||||
To spin up the project locally, follow these steps:
|
||||
|
||||
1. First clone the repo
|
||||
1. Then `cd YOUR_PROJECT_REPO && cp .env.example .env`
|
||||
1. Next `yarn && yarn dev` (or `docker-compose up`, see [Docker](#docker))
|
||||
1. Now `open http://localhost:3000/admin` to access the admin panel
|
||||
1. Create your first admin user using the form on the page
|
||||
|
||||
That's it! Changes made in `./src` will be reflected in your app.
|
||||
|
||||
### Docker
|
||||
|
||||
Alternatively, you can use [Docker](https://www.docker.com) to spin up this project locally. To do so, follow these steps:
|
||||
|
||||
1. Follow [steps 1 and 2 from above](#development), the docker-compose file will automatically use the `.env` file in your project root
|
||||
1. Next run `docker-compose up`
|
||||
1. Follow [steps 4 and 5 from above](#development) to login and create your first admin user
|
||||
|
||||
That's it! The Docker instance will help you get up and running quickly while also standardizing the development environment across your teams.
|
||||
|
||||
## Production
|
||||
|
||||
To run Payload in production, you need to build and serve the Admin panel. To do so, follow these steps:
|
||||
|
||||
1. First invoke the `payload build` script by running `yarn build` or `npm run build` in your project root. This creates a `./build` directory with a production-ready admin bundle.
|
||||
1. Then run `yarn serve` or `npm run serve` to run Node in production and serve Payload from the `./build` directory.
|
||||
|
||||
### Deployment
|
||||
|
||||
The easiest way to deploy your project is to use [Payload Cloud](https://payloadcms.com/new/import), a one-click hosting solution to deploy production-ready instances of your Payload apps directly from your GitHub repo. You can also deploy your app manually, check out the [deployment documentation](https://payloadcms.com/docs/production/deployment) for full details.
|
||||
|
||||
## Questions
|
||||
|
||||
If you have any issues or questions, reach out to us on [Discord](https://discord.com/invite/payload) or start a [GitHub discussion](https://github.com/payloadcms/payload/discussions).
|
||||
43
templates/_template/docker-compose.yml
Normal file
43
templates/_template/docker-compose.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
payload:
|
||||
image: node:18-alpine
|
||||
ports:
|
||||
- '3000:3000'
|
||||
volumes:
|
||||
- .:/home/node/app
|
||||
- node_modules:/home/node/app/node_modules
|
||||
working_dir: /home/node/app/
|
||||
command: sh -c "corepack enable && corepack prepare pnpm@latest --activate && pnpm install && pnpm dev"
|
||||
depends_on:
|
||||
- mongo
|
||||
# - postgres
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
# Ensure your DATABASE_URI uses 'mongo' as the hostname ie. mongodb://mongo/my-db-name
|
||||
mongo:
|
||||
image: mongo:latest
|
||||
ports:
|
||||
- '27017:27017'
|
||||
command:
|
||||
- --storageEngine=wiredTiger
|
||||
volumes:
|
||||
- data:/data/db
|
||||
logging:
|
||||
driver: none
|
||||
|
||||
# Uncomment the following to use postgres
|
||||
# postgres:
|
||||
# restart: always
|
||||
# image: postgres:latest
|
||||
# volumes:
|
||||
# - pgdata:/var/lib/postgresql/data
|
||||
# ports:
|
||||
# - "5432:5432"
|
||||
|
||||
volumes:
|
||||
data:
|
||||
# pgdata:
|
||||
node_modules:
|
||||
8
templates/_template/next.config.mjs
Normal file
8
templates/_template/next.config.mjs
Normal file
@@ -0,0 +1,8 @@
|
||||
import { withPayload } from '@payloadcms/next/withPayload'
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
// Your Next.js config here
|
||||
}
|
||||
|
||||
export default withPayload(nextConfig)
|
||||
51
templates/_template/package.json
Normal file
51
templates/_template/package.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "template-blank-3.0",
|
||||
"version": "1.0.0",
|
||||
"description": "A blank template to get started with Payload 3.0",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
|
||||
"dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
|
||||
"devsafe": "rm -rf .next && cross-env NODE_OPTIONS=--no-deprecation next dev",
|
||||
"generate:types": "payload generate:types",
|
||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@payloadcms/db-mongodb": "beta",
|
||||
"@payloadcms/next": "beta",
|
||||
"@payloadcms/plugin-cloud": "beta",
|
||||
"@payloadcms/richtext-lexical": "beta",
|
||||
"cross-env": "^7.0.3",
|
||||
"graphql": "^16.8.1",
|
||||
"next": "15.0.0-rc.0",
|
||||
"payload": "beta",
|
||||
"react": "^19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "^19.0.0-rc-f994737d14-20240522",
|
||||
"sharp": "0.32.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.12.12",
|
||||
"@types/react": "npm:types-react@19.0.0-beta.2",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2",
|
||||
"dotenv": "^16.4.5",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "^14.2.3",
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.20.2 || >=20.6.0"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
templates/_template/src/app/(payload)/api/[...slug]/route.ts
Normal file
10
templates/_template/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)
|
||||
@@ -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)
|
||||
@@ -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
templates/_template/src/app/(payload)/custom.scss
Normal file
0
templates/_template/src/app/(payload)/custom.scss
Normal file
16
templates/_template/src/app/(payload)/layout.tsx
Normal file
16
templates/_template/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
templates/_template/src/app/my-route/route.ts
Normal file
14
templates/_template/src/app/my-route/route.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import configPromise from '@payload-config'
|
||||
import { getPayload } from 'payload'
|
||||
|
||||
export const GET = async () => {
|
||||
const payload = await getPayload({
|
||||
config: configPromise,
|
||||
})
|
||||
|
||||
const data = await payload.find({
|
||||
collection: 'users',
|
||||
})
|
||||
|
||||
return Response.json(data)
|
||||
}
|
||||
16
templates/_template/src/collections/Media.ts
Normal file
16
templates/_template/src/collections/Media.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import type { CollectionConfig } from 'payload/types'
|
||||
|
||||
export const Media: CollectionConfig = {
|
||||
slug: 'media',
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'alt',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
upload: true,
|
||||
}
|
||||
13
templates/_template/src/collections/Users.ts
Normal file
13
templates/_template/src/collections/Users.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { CollectionConfig } from 'payload/types'
|
||||
|
||||
export const Users: CollectionConfig = {
|
||||
slug: 'users',
|
||||
admin: {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
auth: true,
|
||||
fields: [
|
||||
// Email added by default
|
||||
// Add more fields as needed
|
||||
],
|
||||
}
|
||||
34
templates/_template/src/payload.config.ts
Normal file
34
templates/_template/src/payload.config.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
// storage-adapter-import-placeholder
|
||||
import { mongooseAdapter } from '@payloadcms/db-mongodb' // database-adapter-import
|
||||
import { lexicalEditor } from '@payloadcms/richtext-lexical'
|
||||
import path from 'path'
|
||||
import { buildConfig } from 'payload/config'
|
||||
import { fileURLToPath } from 'url'
|
||||
import sharp from 'sharp'
|
||||
|
||||
import { Users } from './collections/Users'
|
||||
import { Media } from './collections/Media'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
export default buildConfig({
|
||||
admin: {
|
||||
user: Users.slug,
|
||||
},
|
||||
collections: [Users, Media],
|
||||
editor: lexicalEditor(),
|
||||
secret: process.env.PAYLOAD_SECRET || '',
|
||||
typescript: {
|
||||
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
||||
},
|
||||
// database-adapter-config-start
|
||||
db: mongooseAdapter({
|
||||
url: process.env.DATABASE_URI || '',
|
||||
}),
|
||||
// database-adapter-config-end
|
||||
sharp,
|
||||
plugins: [
|
||||
// storage-adapter-placeholder
|
||||
],
|
||||
})
|
||||
44
templates/_template/tsconfig.json
Normal file
44
templates/_template/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": [
|
||||
"./src/payload.config.ts"
|
||||
]
|
||||
},
|
||||
"target": "ES2017"
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
16
templates/blank-3.0/src/collections/Media.ts
Normal file
16
templates/blank-3.0/src/collections/Media.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import type { CollectionConfig } from 'payload/types'
|
||||
|
||||
export const Media: CollectionConfig = {
|
||||
slug: 'media',
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'alt',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
upload: true,
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
// storage-adapter-import-placeholder
|
||||
import { mongooseAdapter } from '@payloadcms/db-mongodb' // database-adapter-import
|
||||
// import { payloadCloud } from '@payloadcms/plugin-cloud'
|
||||
import { lexicalEditor } from '@payloadcms/richtext-lexical'
|
||||
import path from 'path'
|
||||
import { buildConfig } from 'payload/config'
|
||||
// import sharp from 'sharp'
|
||||
import { fileURLToPath } from 'url'
|
||||
import sharp from 'sharp'
|
||||
|
||||
import { Users } from './collections/Users'
|
||||
import { Media } from './collections/Media'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
@@ -15,9 +16,8 @@ export default buildConfig({
|
||||
admin: {
|
||||
user: Users.slug,
|
||||
},
|
||||
collections: [Users],
|
||||
editor: lexicalEditor({}),
|
||||
// plugins: [payloadCloud()], // TODO: Re-enable when cloud supports 3.0
|
||||
collections: [Users, Media],
|
||||
editor: lexicalEditor(),
|
||||
secret: process.env.PAYLOAD_SECRET || '',
|
||||
typescript: {
|
||||
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
||||
@@ -27,13 +27,8 @@ export default buildConfig({
|
||||
url: process.env.DATABASE_URI || '',
|
||||
}),
|
||||
// database-adapter-config-end
|
||||
|
||||
// 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,
|
||||
sharp,
|
||||
plugins: [
|
||||
// storage-adapter-placeholder
|
||||
],
|
||||
})
|
||||
|
||||
2
templates/blank/.env.example
Normal file
2
templates/blank/.env.example
Normal file
@@ -0,0 +1,2 @@
|
||||
DATABASE_URI=mongodb://127.0.0.1/payload-template-blank-3-0
|
||||
PAYLOAD_SECRET=YOUR_SECRET_HERE
|
||||
8
templates/blank/.eslintrc.cjs
Normal file
8
templates/blank/.eslintrc.cjs
Normal file
@@ -0,0 +1,8 @@
|
||||
/** @type {import('eslint').Linter.Config} */
|
||||
module.exports = {
|
||||
extends: ['next/core-web-vitals'],
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.json'],
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
}
|
||||
43
templates/blank/.gitignore
vendored
Normal file
43
templates/blank/.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
templates/blank/.prettierrc.json
Normal file
6
templates/blank/.prettierrc.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 100,
|
||||
"semi": false
|
||||
}
|
||||
1
templates/blank/.yarnrc
Normal file
1
templates/blank/.yarnrc
Normal file
@@ -0,0 +1 @@
|
||||
--install.ignore-engines true
|
||||
69
templates/blank/Dockerfile
Normal file
69
templates/blank/Dockerfile
Normal file
@@ -0,0 +1,69 @@
|
||||
# From https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
|
||||
|
||||
FROM node:18-alpine AS base
|
||||
|
||||
# Install dependencies only when needed
|
||||
FROM base AS deps
|
||||
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||
RUN apk add --no-cache libc6-compat
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies based on the preferred package manager
|
||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
|
||||
RUN \
|
||||
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
|
||||
elif [ -f package-lock.json ]; then npm ci; \
|
||||
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
|
||||
else echo "Lockfile not found." && exit 1; \
|
||||
fi
|
||||
|
||||
|
||||
# Rebuild the source code only when needed
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
|
||||
# Next.js collects completely anonymous telemetry data about general usage.
|
||||
# Learn more here: https://nextjs.org/telemetry
|
||||
# Uncomment the following line in case you want to disable telemetry during the build.
|
||||
# ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
RUN \
|
||||
if [ -f yarn.lock ]; then yarn run build; \
|
||||
elif [ -f package-lock.json ]; then npm run build; \
|
||||
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
|
||||
else echo "Lockfile not found." && exit 1; \
|
||||
fi
|
||||
|
||||
# Production image, copy all the files and run next
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV production
|
||||
# Uncomment the following line in case you want to disable telemetry during runtime.
|
||||
# ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
|
||||
COPY --from=builder /app/public ./public
|
||||
|
||||
# Set the correct permission for prerender cache
|
||||
RUN mkdir .next
|
||||
RUN chown nextjs:nodejs .next
|
||||
|
||||
# Automatically leverage output traces to reduce image size
|
||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV PORT 3000
|
||||
|
||||
# server.js is created by next build from the standalone output
|
||||
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
|
||||
CMD HOSTNAME="0.0.0.0" node server.js
|
||||
8
templates/blank/README.md
Normal file
8
templates/blank/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# blank
|
||||
|
||||
blank
|
||||
|
||||
## Attributes
|
||||
|
||||
- **Database**: mongodb
|
||||
- **Storage Adapter**: localDisk
|
||||
43
templates/blank/docker-compose.yml
Normal file
43
templates/blank/docker-compose.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
payload:
|
||||
image: node:18-alpine
|
||||
ports:
|
||||
- '3000:3000'
|
||||
volumes:
|
||||
- .:/home/node/app
|
||||
- node_modules:/home/node/app/node_modules
|
||||
working_dir: /home/node/app/
|
||||
command: sh -c "corepack enable && corepack prepare pnpm@latest --activate && pnpm install && pnpm dev"
|
||||
depends_on:
|
||||
- mongo
|
||||
# - postgres
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
# Ensure your DATABASE_URI uses 'mongo' as the hostname ie. mongodb://mongo/my-db-name
|
||||
mongo:
|
||||
image: mongo:latest
|
||||
ports:
|
||||
- '27017:27017'
|
||||
command:
|
||||
- --storageEngine=wiredTiger
|
||||
volumes:
|
||||
- data:/data/db
|
||||
logging:
|
||||
driver: none
|
||||
|
||||
# Uncomment the following to use postgres
|
||||
# postgres:
|
||||
# restart: always
|
||||
# image: postgres:latest
|
||||
# volumes:
|
||||
# - pgdata:/var/lib/postgresql/data
|
||||
# ports:
|
||||
# - "5432:5432"
|
||||
|
||||
volumes:
|
||||
data:
|
||||
# pgdata:
|
||||
node_modules:
|
||||
8
templates/blank/next.config.mjs
Normal file
8
templates/blank/next.config.mjs
Normal file
@@ -0,0 +1,8 @@
|
||||
import { withPayload } from '@payloadcms/next/withPayload'
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
// Your Next.js config here
|
||||
}
|
||||
|
||||
export default withPayload(nextConfig)
|
||||
51
templates/blank/package.json
Normal file
51
templates/blank/package.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "blank",
|
||||
"version": "1.0.0",
|
||||
"description": "A blank template to get started with Payload 3.0",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
|
||||
"dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
|
||||
"devsafe": "rm -rf .next && cross-env NODE_OPTIONS=--no-deprecation next dev",
|
||||
"generate:types": "payload generate:types",
|
||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@payloadcms/db-mongodb": "beta",
|
||||
"@payloadcms/next": "beta",
|
||||
"@payloadcms/plugin-cloud": "beta",
|
||||
"@payloadcms/richtext-lexical": "beta",
|
||||
"cross-env": "^7.0.3",
|
||||
"graphql": "^16.8.1",
|
||||
"next": "15.0.0-rc.0",
|
||||
"payload": "beta",
|
||||
"react": "^19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "^19.0.0-rc-f994737d14-20240522",
|
||||
"sharp": "0.32.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.12.12",
|
||||
"@types/react": "npm:types-react@19.0.0-beta.2",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2",
|
||||
"dotenv": "^16.4.5",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "^14.2.3",
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.20.2 || >=20.6.0"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
templates/blank/src/app/(payload)/api/[...slug]/route.ts
Normal file
10
templates/blank/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)
|
||||
@@ -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
templates/blank/src/app/(payload)/api/graphql/route.ts
Normal file
6
templates/blank/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
templates/blank/src/app/(payload)/custom.scss
Normal file
0
templates/blank/src/app/(payload)/custom.scss
Normal file
16
templates/blank/src/app/(payload)/layout.tsx
Normal file
16
templates/blank/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
templates/blank/src/app/my-route/route.ts
Normal file
14
templates/blank/src/app/my-route/route.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import configPromise from '@payload-config'
|
||||
import { getPayload } from 'payload'
|
||||
|
||||
export const GET = async () => {
|
||||
const payload = await getPayload({
|
||||
config: configPromise,
|
||||
})
|
||||
|
||||
const data = await payload.find({
|
||||
collection: 'users',
|
||||
})
|
||||
|
||||
return Response.json(data)
|
||||
}
|
||||
16
templates/blank/src/collections/Media.ts
Normal file
16
templates/blank/src/collections/Media.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import type { CollectionConfig } from 'payload/types'
|
||||
|
||||
export const Media: CollectionConfig = {
|
||||
slug: 'media',
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'alt',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
upload: true,
|
||||
}
|
||||
13
templates/blank/src/collections/Users.ts
Normal file
13
templates/blank/src/collections/Users.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { CollectionConfig } from 'payload/types'
|
||||
|
||||
export const Users: CollectionConfig = {
|
||||
slug: 'users',
|
||||
admin: {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
auth: true,
|
||||
fields: [
|
||||
// Email added by default
|
||||
// Add more fields as needed
|
||||
],
|
||||
}
|
||||
30
templates/blank/src/payload.config.ts
Normal file
30
templates/blank/src/payload.config.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
// storage-adapter-import-placeholder
|
||||
import { mongooseAdapter } from '@payloadcms/db-mongodb'
|
||||
import { lexicalEditor } from '@payloadcms/richtext-lexical'
|
||||
import path from 'path'
|
||||
import { buildConfig } from 'payload/config'
|
||||
import { fileURLToPath } from 'url'
|
||||
import sharp from 'sharp'
|
||||
|
||||
import { Users } from './collections/Users'
|
||||
import { Media } from './collections/Media'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
export default buildConfig({
|
||||
admin: {
|
||||
user: Users.slug,
|
||||
},
|
||||
collections: [Users, Media],
|
||||
editor: lexicalEditor(),
|
||||
secret: process.env.PAYLOAD_SECRET || '',
|
||||
typescript: {
|
||||
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
||||
},
|
||||
db: mongooseAdapter({
|
||||
url: process.env.DATABASE_URI || '',
|
||||
}),
|
||||
sharp,
|
||||
plugins: [],
|
||||
})
|
||||
44
templates/blank/tsconfig.json
Normal file
44
templates/blank/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": [
|
||||
"./src/payload.config.ts"
|
||||
]
|
||||
},
|
||||
"target": "ES2017"
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { withPayload } from '@payloadcms/next/withPayload'
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {};
|
||||
const nextConfig = {}
|
||||
|
||||
export default withPayload(nextConfig);
|
||||
export default withPayload(nextConfig)
|
||||
|
||||
5353
templates/vercel-postgres/pnpm-lock.yaml
generated
5353
templates/vercel-postgres/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -3,4 +3,4 @@ module.exports = {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { MigrateDownArgs, MigrateUpArgs} from '@payloadcms/db-postgres';
|
||||
import type { MigrateDownArgs, MigrateUpArgs } from '@payloadcms/db-postgres'
|
||||
|
||||
import { sql } from '@payloadcms/db-postgres'
|
||||
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import type { Config } from "tailwindcss";
|
||||
import type { Config } from 'tailwindcss'
|
||||
|
||||
const config: Config = {
|
||||
content: [
|
||||
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
backgroundImage: {
|
||||
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
|
||||
"gradient-conic":
|
||||
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
|
||||
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
|
||||
'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
export default config;
|
||||
}
|
||||
export default config
|
||||
|
||||
2
templates/with-payload-cloud/.env.example
Normal file
2
templates/with-payload-cloud/.env.example
Normal file
@@ -0,0 +1,2 @@
|
||||
DATABASE_URI=mongodb://127.0.0.1/payload-template-blank-3-0
|
||||
PAYLOAD_SECRET=YOUR_SECRET_HERE
|
||||
8
templates/with-payload-cloud/.eslintrc.cjs
Normal file
8
templates/with-payload-cloud/.eslintrc.cjs
Normal file
@@ -0,0 +1,8 @@
|
||||
/** @type {import('eslint').Linter.Config} */
|
||||
module.exports = {
|
||||
extends: ['next/core-web-vitals'],
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.json'],
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
}
|
||||
43
templates/with-payload-cloud/.gitignore
vendored
Normal file
43
templates/with-payload-cloud/.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
templates/with-payload-cloud/.prettierrc.json
Normal file
6
templates/with-payload-cloud/.prettierrc.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 100,
|
||||
"semi": false
|
||||
}
|
||||
1
templates/with-payload-cloud/.yarnrc
Normal file
1
templates/with-payload-cloud/.yarnrc
Normal file
@@ -0,0 +1 @@
|
||||
--install.ignore-engines true
|
||||
69
templates/with-payload-cloud/Dockerfile
Normal file
69
templates/with-payload-cloud/Dockerfile
Normal file
@@ -0,0 +1,69 @@
|
||||
# From https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
|
||||
|
||||
FROM node:18-alpine AS base
|
||||
|
||||
# Install dependencies only when needed
|
||||
FROM base AS deps
|
||||
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||
RUN apk add --no-cache libc6-compat
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies based on the preferred package manager
|
||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
|
||||
RUN \
|
||||
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
|
||||
elif [ -f package-lock.json ]; then npm ci; \
|
||||
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
|
||||
else echo "Lockfile not found." && exit 1; \
|
||||
fi
|
||||
|
||||
|
||||
# Rebuild the source code only when needed
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
|
||||
# Next.js collects completely anonymous telemetry data about general usage.
|
||||
# Learn more here: https://nextjs.org/telemetry
|
||||
# Uncomment the following line in case you want to disable telemetry during the build.
|
||||
# ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
RUN \
|
||||
if [ -f yarn.lock ]; then yarn run build; \
|
||||
elif [ -f package-lock.json ]; then npm run build; \
|
||||
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
|
||||
else echo "Lockfile not found." && exit 1; \
|
||||
fi
|
||||
|
||||
# Production image, copy all the files and run next
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV production
|
||||
# Uncomment the following line in case you want to disable telemetry during runtime.
|
||||
# ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
|
||||
COPY --from=builder /app/public ./public
|
||||
|
||||
# Set the correct permission for prerender cache
|
||||
RUN mkdir .next
|
||||
RUN chown nextjs:nodejs .next
|
||||
|
||||
# Automatically leverage output traces to reduce image size
|
||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV PORT 3000
|
||||
|
||||
# server.js is created by next build from the standalone output
|
||||
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
|
||||
CMD HOSTNAME="0.0.0.0" node server.js
|
||||
8
templates/with-payload-cloud/README.md
Normal file
8
templates/with-payload-cloud/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# payload-cloud-mongodb-template
|
||||
|
||||
payload-cloud-mongodb-template
|
||||
|
||||
## Attributes
|
||||
|
||||
- **Database**: mongodb
|
||||
- **Storage Adapter**: payloadCloud
|
||||
43
templates/with-payload-cloud/docker-compose.yml
Normal file
43
templates/with-payload-cloud/docker-compose.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
payload:
|
||||
image: node:18-alpine
|
||||
ports:
|
||||
- '3000:3000'
|
||||
volumes:
|
||||
- .:/home/node/app
|
||||
- node_modules:/home/node/app/node_modules
|
||||
working_dir: /home/node/app/
|
||||
command: sh -c "corepack enable && corepack prepare pnpm@latest --activate && pnpm install && pnpm dev"
|
||||
depends_on:
|
||||
- mongo
|
||||
# - postgres
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
# Ensure your DATABASE_URI uses 'mongo' as the hostname ie. mongodb://mongo/my-db-name
|
||||
mongo:
|
||||
image: mongo:latest
|
||||
ports:
|
||||
- '27017:27017'
|
||||
command:
|
||||
- --storageEngine=wiredTiger
|
||||
volumes:
|
||||
- data:/data/db
|
||||
logging:
|
||||
driver: none
|
||||
|
||||
# Uncomment the following to use postgres
|
||||
# postgres:
|
||||
# restart: always
|
||||
# image: postgres:latest
|
||||
# volumes:
|
||||
# - pgdata:/var/lib/postgresql/data
|
||||
# ports:
|
||||
# - "5432:5432"
|
||||
|
||||
volumes:
|
||||
data:
|
||||
# pgdata:
|
||||
node_modules:
|
||||
8
templates/with-payload-cloud/next.config.mjs
Normal file
8
templates/with-payload-cloud/next.config.mjs
Normal file
@@ -0,0 +1,8 @@
|
||||
import { withPayload } from '@payloadcms/next/withPayload'
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
// Your Next.js config here
|
||||
}
|
||||
|
||||
export default withPayload(nextConfig)
|
||||
51
templates/with-payload-cloud/package.json
Normal file
51
templates/with-payload-cloud/package.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "payload-cloud-mongodb-template",
|
||||
"version": "1.0.0",
|
||||
"description": "A blank template to get started with Payload 3.0",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
|
||||
"dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
|
||||
"devsafe": "rm -rf .next && cross-env NODE_OPTIONS=--no-deprecation next dev",
|
||||
"generate:types": "payload generate:types",
|
||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@payloadcms/db-mongodb": "beta",
|
||||
"@payloadcms/next": "beta",
|
||||
"@payloadcms/plugin-cloud": "beta",
|
||||
"@payloadcms/richtext-lexical": "beta",
|
||||
"cross-env": "^7.0.3",
|
||||
"graphql": "^16.8.1",
|
||||
"next": "15.0.0-rc.0",
|
||||
"payload": "beta",
|
||||
"react": "^19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "^19.0.0-rc-f994737d14-20240522",
|
||||
"sharp": "0.32.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.12.12",
|
||||
"@types/react": "npm:types-react@19.0.0-beta.2",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2",
|
||||
"dotenv": "^16.4.5",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "^14.2.3",
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.20.2 || >=20.6.0"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
9812
templates/with-payload-cloud/pnpm-lock.yaml
generated
Normal file
9812
templates/with-payload-cloud/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
16
templates/with-payload-cloud/src/app/(payload)/layout.tsx
Normal file
16
templates/with-payload-cloud/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
templates/with-payload-cloud/src/app/my-route/route.ts
Normal file
14
templates/with-payload-cloud/src/app/my-route/route.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import configPromise from '@payload-config'
|
||||
import { getPayload } from 'payload'
|
||||
|
||||
export const GET = async () => {
|
||||
const payload = await getPayload({
|
||||
config: configPromise,
|
||||
})
|
||||
|
||||
const data = await payload.find({
|
||||
collection: 'users',
|
||||
})
|
||||
|
||||
return Response.json(data)
|
||||
}
|
||||
16
templates/with-payload-cloud/src/collections/Media.ts
Normal file
16
templates/with-payload-cloud/src/collections/Media.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import type { CollectionConfig } from 'payload/types'
|
||||
|
||||
export const Media: CollectionConfig = {
|
||||
slug: 'media',
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'alt',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
upload: true,
|
||||
}
|
||||
13
templates/with-payload-cloud/src/collections/Users.ts
Normal file
13
templates/with-payload-cloud/src/collections/Users.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { CollectionConfig } from 'payload/types'
|
||||
|
||||
export const Users: CollectionConfig = {
|
||||
slug: 'users',
|
||||
admin: {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
auth: true,
|
||||
fields: [
|
||||
// Email added by default
|
||||
// Add more fields as needed
|
||||
],
|
||||
}
|
||||
30
templates/with-payload-cloud/src/payload.config.ts
Normal file
30
templates/with-payload-cloud/src/payload.config.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { payloadCloudPlugin } from '@payloadcms/plugin-cloud'
|
||||
import { mongooseAdapter } from '@payloadcms/db-mongodb'
|
||||
import { lexicalEditor } from '@payloadcms/richtext-lexical'
|
||||
import path from 'path'
|
||||
import { buildConfig } from 'payload/config'
|
||||
import { fileURLToPath } from 'url'
|
||||
import sharp from 'sharp'
|
||||
|
||||
import { Users } from './collections/Users'
|
||||
import { Media } from './collections/Media'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
export default buildConfig({
|
||||
admin: {
|
||||
user: Users.slug,
|
||||
},
|
||||
collections: [Users, Media],
|
||||
editor: lexicalEditor(),
|
||||
secret: process.env.PAYLOAD_SECRET || '',
|
||||
typescript: {
|
||||
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
||||
},
|
||||
db: mongooseAdapter({
|
||||
url: process.env.DATABASE_URI || '',
|
||||
}),
|
||||
sharp,
|
||||
plugins: [payloadCloudPlugin()],
|
||||
})
|
||||
44
templates/with-payload-cloud/tsconfig.json
Normal file
44
templates/with-payload-cloud/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": [
|
||||
"./src/payload.config.ts"
|
||||
]
|
||||
},
|
||||
"target": "ES2017"
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
2
templates/with-vercel-mongodb/.env.example
Normal file
2
templates/with-vercel-mongodb/.env.example
Normal file
@@ -0,0 +1,2 @@
|
||||
DATABASE_URI=mongodb://127.0.0.1/payload-template-blank-3-0
|
||||
PAYLOAD_SECRET=YOUR_SECRET_HERE
|
||||
8
templates/with-vercel-mongodb/.eslintrc.cjs
Normal file
8
templates/with-vercel-mongodb/.eslintrc.cjs
Normal file
@@ -0,0 +1,8 @@
|
||||
/** @type {import('eslint').Linter.Config} */
|
||||
module.exports = {
|
||||
extends: ['next/core-web-vitals'],
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.json'],
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
}
|
||||
43
templates/with-vercel-mongodb/.gitignore
vendored
Normal file
43
templates/with-vercel-mongodb/.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
templates/with-vercel-mongodb/.prettierrc.json
Normal file
6
templates/with-vercel-mongodb/.prettierrc.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 100,
|
||||
"semi": false
|
||||
}
|
||||
1
templates/with-vercel-mongodb/.yarnrc
Normal file
1
templates/with-vercel-mongodb/.yarnrc
Normal file
@@ -0,0 +1 @@
|
||||
--install.ignore-engines true
|
||||
69
templates/with-vercel-mongodb/Dockerfile
Normal file
69
templates/with-vercel-mongodb/Dockerfile
Normal file
@@ -0,0 +1,69 @@
|
||||
# From https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
|
||||
|
||||
FROM node:18-alpine AS base
|
||||
|
||||
# Install dependencies only when needed
|
||||
FROM base AS deps
|
||||
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||
RUN apk add --no-cache libc6-compat
|
||||
WORKDIR /app
|
||||
|
||||
# Install dependencies based on the preferred package manager
|
||||
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
|
||||
RUN \
|
||||
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
|
||||
elif [ -f package-lock.json ]; then npm ci; \
|
||||
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
|
||||
else echo "Lockfile not found." && exit 1; \
|
||||
fi
|
||||
|
||||
|
||||
# Rebuild the source code only when needed
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
|
||||
# Next.js collects completely anonymous telemetry data about general usage.
|
||||
# Learn more here: https://nextjs.org/telemetry
|
||||
# Uncomment the following line in case you want to disable telemetry during the build.
|
||||
# ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
RUN \
|
||||
if [ -f yarn.lock ]; then yarn run build; \
|
||||
elif [ -f package-lock.json ]; then npm run build; \
|
||||
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm run build; \
|
||||
else echo "Lockfile not found." && exit 1; \
|
||||
fi
|
||||
|
||||
# Production image, copy all the files and run next
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV production
|
||||
# Uncomment the following line in case you want to disable telemetry during runtime.
|
||||
# ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
|
||||
COPY --from=builder /app/public ./public
|
||||
|
||||
# Set the correct permission for prerender cache
|
||||
RUN mkdir .next
|
||||
RUN chown nextjs:nodejs .next
|
||||
|
||||
# Automatically leverage output traces to reduce image size
|
||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV PORT 3000
|
||||
|
||||
# server.js is created by next build from the standalone output
|
||||
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
|
||||
CMD HOSTNAME="0.0.0.0" node server.js
|
||||
10
templates/with-vercel-mongodb/README.md
Normal file
10
templates/with-vercel-mongodb/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# payload-vercel-mongodb-template
|
||||
|
||||
[](https://vercel.com/new/clone?repository-url=https://github.com/payloadcms/payload/tree/beta/templates//Users/elliot/dev/core/scripts&project-name=payload-project&env=PAYLOAD_SECRET&build-command=pnpm%20run%20ci&stores=%5B%7B%22type%22:%22blob%22%7D%5D&integration-ids=oac_jnzmjqM10gllKmSrG0SGrHOH)
|
||||
|
||||
payload-vercel-mongodb-template
|
||||
|
||||
## Attributes
|
||||
|
||||
- **Database**: mongodb
|
||||
- **Storage Adapter**: vercelBlobStorage
|
||||
43
templates/with-vercel-mongodb/docker-compose.yml
Normal file
43
templates/with-vercel-mongodb/docker-compose.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
payload:
|
||||
image: node:18-alpine
|
||||
ports:
|
||||
- '3000:3000'
|
||||
volumes:
|
||||
- .:/home/node/app
|
||||
- node_modules:/home/node/app/node_modules
|
||||
working_dir: /home/node/app/
|
||||
command: sh -c "corepack enable && corepack prepare pnpm@latest --activate && pnpm install && pnpm dev"
|
||||
depends_on:
|
||||
- mongo
|
||||
# - postgres
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
# Ensure your DATABASE_URI uses 'mongo' as the hostname ie. mongodb://mongo/my-db-name
|
||||
mongo:
|
||||
image: mongo:latest
|
||||
ports:
|
||||
- '27017:27017'
|
||||
command:
|
||||
- --storageEngine=wiredTiger
|
||||
volumes:
|
||||
- data:/data/db
|
||||
logging:
|
||||
driver: none
|
||||
|
||||
# Uncomment the following to use postgres
|
||||
# postgres:
|
||||
# restart: always
|
||||
# image: postgres:latest
|
||||
# volumes:
|
||||
# - pgdata:/var/lib/postgresql/data
|
||||
# ports:
|
||||
# - "5432:5432"
|
||||
|
||||
volumes:
|
||||
data:
|
||||
# pgdata:
|
||||
node_modules:
|
||||
8
templates/with-vercel-mongodb/next.config.mjs
Normal file
8
templates/with-vercel-mongodb/next.config.mjs
Normal file
@@ -0,0 +1,8 @@
|
||||
import { withPayload } from '@payloadcms/next/withPayload'
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
// Your Next.js config here
|
||||
}
|
||||
|
||||
export default withPayload(nextConfig)
|
||||
51
templates/with-vercel-mongodb/package.json
Normal file
51
templates/with-vercel-mongodb/package.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "payload-vercel-mongodb-template",
|
||||
"version": "1.0.0",
|
||||
"description": "A blank template to get started with Payload 3.0",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
|
||||
"dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
|
||||
"devsafe": "rm -rf .next && cross-env NODE_OPTIONS=--no-deprecation next dev",
|
||||
"generate:types": "payload generate:types",
|
||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@payloadcms/db-mongodb": "beta",
|
||||
"@payloadcms/next": "beta",
|
||||
"@payloadcms/plugin-cloud": "beta",
|
||||
"@payloadcms/richtext-lexical": "beta",
|
||||
"cross-env": "^7.0.3",
|
||||
"graphql": "^16.8.1",
|
||||
"next": "15.0.0-rc.0",
|
||||
"payload": "beta",
|
||||
"react": "^19.0.0-rc-f994737d14-20240522",
|
||||
"react-dom": "^19.0.0-rc-f994737d14-20240522",
|
||||
"@payloadcms/storage-vercel-blob": "beta"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.12.12",
|
||||
"@types/react": "npm:types-react@19.0.0-beta.2",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-beta.2",
|
||||
"dotenv": "^16.4.5",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "^14.2.3",
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.20.2 || >=20.6.0"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user