docs(examples): add whitelabel example (#1947)

* chore: adds whitelabel example

* chore: updates readme

* chore: updates icon/logo/favicon assets
This commit is contained in:
Jessica Chowdhury
2023-01-26 14:24:23 +00:00
committed by GitHub
parent 3d854f7724
commit fb41d245e6
13 changed files with 470 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
MONGODB_URI=mongodb://localhost/whitelabel-example-cms
PAYLOAD_SECRET=ENTER-STRING-HERE

166
examples/whitelabel/.gitignore vendored Normal file
View File

@@ -0,0 +1,166 @@
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
### Node Patch ###
# Serverless Webpack directories
.webpack/
# Optional stylelint cache
# SvelteKit build / generate output
.svelte-kit
### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
.ionide
# Support for Project snippet scope
.vscode/*.code-snippets
# Ignore code-workspaces
*.code-workspace
# End of https://www.toptal.com/developers/gitignore/api/node,visualstudiocode

View File

@@ -0,0 +1 @@
legacy-peer-deps=true

View File

@@ -0,0 +1,65 @@
# Whitelabeled Example for PayloadCMS
This example demonstrates how to rebrand the admin panel by modifying the favicon, icon, logo, ogImage and title suffix.
To use this example, you'll need the following software:
- Yarn or NPM
- NodeJS version 10+
- A Mongo Database - IMPORTANT: you need to either have MongoDB running locally, or have signed up for a free MongoDB Atlas server in order to test this repo locally.
## Running locally
[- Step 1. Copy example](#step-1-copy-example)
[- Step 2. Set up the environment variables](#step-2-set-up-the-environment-variables)
[- Step 3. Start the development server](#step-3-add-dependencies-and-start-the-development-server)
### Step 1. Copy example
Copy the example by running the following command at your terminal:
```bash
npx degit github:payloadcms/payload/examples/whitelabel
```
### Step 2. Set up the environment variables
Copy the `.env.example` file in this directory to `.env`:
```bash
cp .env.example .env
```
Typically, the only line that you'll need to change within your new .env for local development is the `MONGO_URI` value. If you have MongoDB running locally, then you can use the example connection string, but if you are using Mongo Atlas or similar, you'll want to fill this value in with your own connection string.
### Step 3. Add dependencies and start the development server
```bash
yarn
yarn dev
```
Your CMS should now be up and running on [http://localhost:3000/admin](http://localhost:3000/admin).
## Rebranding walkthrough
Start by navigating to the `payload.config.ts` file and then take a look at the admin property.
The following sub-properties have already been configured:
`favicon`: Image that will be displayed as the tab icon.
`ogImage`: Image that will appear in the preview when you share links to your admin panel online and through social media.
`titleSuffix`: Text that appends the meta/page title displayed in the browser tab — *must be a string*.
`graphics.Logo`: Image component to be displayed as the logo on the Sign Up / Login view.
`graphics.Icon`: Image component displayed above the Nav in the admin panel, often a condensed version of a full logo.
👉 Check out this blog post for a more in-depth walkthrough: [White-label the Admin UI](https://payloadcms.com/blog/white-label-admin-ui)
## Questions
If you have any issues or questions, reach out to us on [Discord](https://discord.com/invite/r6sCXqVk3v) or start a [GitHub discussion](https://github.com/payloadcms/payload/discussions).

View File

@@ -0,0 +1,15 @@
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="216" height="218" viewBox="0 0 216 218">
<g transform="translate(0,218) scale(0.1,-0.1)"
fill="#000000" stroke="none">
<path d="M0 1095 l0 -1085 1075 0 1075 0 0 1085 0 1085 -1075 0 -1075 0 0
-1085z m1217 538 c-15 -158 -29 -434 -24 -439 3 -3 95 31 204 76 109 46 206
85 215 87 13 4 23 -14 48 -97 17 -56 29 -105 25 -108 -4 -4 -105 -32 -226 -62
-121 -30 -219 -59 -218 -65 1 -5 68 -95 150 -199 l149 -188 -84 -64 c-47 -35
-89 -64 -93 -64 -4 0 -64 97 -133 215 -69 118 -127 215 -130 215 -3 0 -61 -95
-130 -210 -84 -142 -129 -209 -138 -205 -25 9 -161 110 -161 119 -1 5 69 96
154 202 96 120 151 196 143 199 -7 2 -94 25 -193 50 -99 26 -196 51 -216 56
l-37 9 30 98 c16 53 33 100 37 105 4 4 104 -33 222 -82 118 -49 216 -87 218
-85 4 4 -17 397 -25 462 l-5 42 112 0 112 0 -6 -67z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 KiB

View File

@@ -0,0 +1,4 @@
{
"ext": "ts",
"exec": "ts-node src/server.ts"
}

View File

@@ -0,0 +1,30 @@
{
"name": "whitelabel-example-cms",
"version": "1.0.0",
"main": "dist/server.js",
"license": "MIT",
"scripts": {
"dev": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts nodemon",
"build:payload": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload build",
"build:server": "tsc",
"build": "yarn copyfiles && yarn build:payload && yarn build:server",
"serve": "cross-env PAYLOAD_CONFIG_PATH=dist/payload.config.js NODE_ENV=production node dist/server.js",
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png}\" dist/",
"generate:types": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:types",
"generate:graphQLSchema": "PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:graphQLSchema"
},
"dependencies": {
"payload": "^1.5.9",
"dotenv": "^8.2.0",
"express": "^4.17.1"
},
"devDependencies": {
"payload": "^1.5.9",
"@types/express": "^4.17.9",
"cross-env": "^7.0.3",
"nodemon": "^2.0.6",
"ts-node": "^9.1.1",
"copyfiles": "^2.4.1",
"typescript": "^4.8.4"
}
}

View File

@@ -0,0 +1,45 @@
import React from 'react';
const css = `
html[data-theme="dark"] .text {
fill: #0C0C0C;
}
html[data-theme="dark"] .bg {
fill: white;
}
.graphic-icon {
width: 50px;
height: 50px;
}
`;
export const Icon = () => {
return (
<svg
className="graphic-icon"
width="430"
height="435"
viewBox="0 0 430 435"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<style>
{css}
</style>
<rect
className="bg"
width="430"
height="434"
transform="translate(0 0.154785)"
fill="#0C0C0C"
/>
<path
className="text"
d="M79.1562 185.75V193.297H95.1406V246.5H79.1562V254H120.406V246.5H104.047V193.297H120.406V185.75H79.1562ZM200.216 233.469H191.544C191.262 235.531 190.778 237.453 190.091 239.234C189.403 240.984 188.481 242.5 187.325 243.781C186.169 245.094 184.747 246.109 183.059 246.828C181.403 247.547 179.434 247.906 177.153 247.906C175.059 247.906 173.231 247.578 171.669 246.922C170.106 246.234 168.747 245.297 167.591 244.109C166.434 242.953 165.481 241.609 164.731 240.078C163.981 238.547 163.372 236.906 162.903 235.156C162.434 233.438 162.091 231.688 161.872 229.906C161.684 228.094 161.591 226.344 161.591 224.656V215.047C161.591 213.359 161.684 211.625 161.872 209.844C162.091 208.031 162.434 206.266 162.903 204.547C163.372 202.828 163.981 201.203 164.731 199.672C165.512 198.141 166.481 196.797 167.637 195.641C168.762 194.484 170.106 193.578 171.669 192.922C173.262 192.234 175.091 191.891 177.153 191.891C179.434 191.891 181.403 192.281 183.059 193.062C184.747 193.812 186.169 194.859 187.325 196.203C188.481 197.547 189.403 199.109 190.091 200.891C190.778 202.672 191.262 204.594 191.544 206.656H200.216C199.841 203.406 199.059 200.438 197.872 197.75C196.716 195.062 195.169 192.75 193.231 190.812C191.294 188.906 188.981 187.438 186.294 186.406C183.606 185.344 180.559 184.812 177.153 184.812C174.309 184.812 171.747 185.219 169.466 186.031C167.184 186.812 165.153 187.906 163.372 189.312C161.559 190.719 159.997 192.391 158.684 194.328C157.403 196.234 156.341 198.312 155.497 200.562C154.622 202.812 153.966 205.172 153.528 207.641C153.122 210.109 152.903 212.609 152.872 215.141V224.656C152.903 227.188 153.122 229.688 153.528 232.156C153.966 234.625 154.622 236.984 155.497 239.234C156.341 241.484 157.403 243.562 158.684 245.469C159.997 247.375 161.559 249.031 163.372 250.438C165.153 251.844 167.184 252.953 169.466 253.766C171.778 254.547 174.341 254.938 177.153 254.938C180.434 254.938 183.403 254.422 186.059 253.391C188.747 252.328 191.075 250.844 193.044 248.938C194.981 247.062 196.559 244.812 197.778 242.188C198.997 239.531 199.809 236.625 200.216 233.469ZM277.259 223.812V216.031C277.228 213.594 277.009 211.125 276.603 208.625C276.228 206.125 275.634 203.719 274.822 201.406C273.978 199.094 272.916 196.938 271.634 194.938C270.384 192.906 268.884 191.141 267.134 189.641C265.384 188.141 263.369 186.969 261.087 186.125C258.806 185.25 256.259 184.812 253.447 184.812C250.634 184.812 248.087 185.25 245.806 186.125C243.556 186.969 241.556 188.141 239.806 189.641C238.056 191.172 236.541 192.953 235.259 194.984C234.009 196.984 232.978 199.141 232.166 201.453C231.322 203.766 230.697 206.172 230.291 208.672C229.916 211.141 229.712 213.594 229.681 216.031V223.812C229.712 226.25 229.931 228.703 230.337 231.172C230.744 233.641 231.369 236.031 232.212 238.344C233.025 240.656 234.072 242.828 235.353 244.859C236.634 246.859 238.15 248.609 239.9 250.109C241.65 251.609 243.65 252.797 245.9 253.672C248.181 254.516 250.728 254.938 253.541 254.938C256.353 254.938 258.884 254.516 261.134 253.672C263.416 252.797 265.431 251.609 267.181 250.109C268.931 248.609 270.431 246.859 271.681 244.859C272.962 242.859 274.009 240.703 274.822 238.391C275.634 236.078 276.228 233.688 276.603 231.219C277.009 228.719 277.228 226.25 277.259 223.812ZM268.681 215.938V223.812C268.65 225.438 268.541 227.141 268.353 228.922C268.197 230.703 267.9 232.453 267.462 234.172C266.994 235.922 266.384 237.594 265.634 239.188C264.916 240.75 264.009 242.125 262.916 243.312C261.791 244.531 260.447 245.5 258.884 246.219C257.353 246.938 255.572 247.297 253.541 247.297C251.509 247.297 249.728 246.938 248.197 246.219C246.666 245.5 245.337 244.531 244.212 243.312C243.087 242.125 242.15 240.734 241.4 239.141C240.65 237.547 240.041 235.875 239.572 234.125C239.103 232.406 238.759 230.656 238.541 228.875C238.353 227.094 238.244 225.406 238.212 223.812V215.938C238.244 214.344 238.353 212.672 238.541 210.922C238.759 209.141 239.103 207.375 239.572 205.625C240.009 203.906 240.603 202.266 241.353 200.703C242.103 199.109 243.041 197.703 244.166 196.484C245.291 195.297 246.619 194.344 248.15 193.625C249.681 192.906 251.447 192.547 253.447 192.547C255.478 192.547 257.259 192.906 258.791 193.625C260.322 194.312 261.65 195.25 262.775 196.438C263.9 197.656 264.837 199.062 265.587 200.656C266.337 202.219 266.947 203.859 267.416 205.578C267.853 207.328 268.166 209.094 268.353 210.875C268.541 212.625 268.65 214.312 268.681 215.938ZM352.475 254V185.75H343.709L343.569 236.656L317.084 185.75H308.272V254H317.038L317.178 203L343.663 254H352.475Z"
fill="white"
/>
</svg>
);
};

View File

@@ -0,0 +1,53 @@
import React from 'react';
const css = `
html[data-theme="dark"] path {
fill: white;
}
.graphic-logo {
width: 150px;
height: auto;
}`;
export const Logo = () => {
return (
<svg
className="graphic-logo"
xmlns="http://www.w3.org/2000/svg"
fill="#0F0F0F"
viewBox="0 0 518 563"
>
<style type="text/css">
{css}
</style>
<g
transform="translate(0,563) scale(0.1,-0.1)"
fill="#000000"
stroke="none"
>
<path d="M440 3060 l0 -2170 2150 0 2150 0 0 2170 0 2170 -2150 0 -2150 0 0
-2170z m1855 301 c52 -24 88 -63 117 -126 19 -42 23 -71 26 -182 4 -151 -8
-213 -58 -281 -55 -77 -140 -107 -230 -83 -66 18 -105 53 -141 128 -31 61 -33
74 -37 189 -5 145 16 233 69 298 60 72 169 97 254 57z m766 8 c74 -25 126 -85
144 -166 l7 -33 -45 0 c-41 0 -45 2 -50 29 -15 75 -102 125 -177 102 -84 -25
-126 -130 -118 -295 5 -109 36 -189 88 -226 39 -28 129 -31 178 -6 26 14 31
23 37 69 4 29 5 66 3 82 -3 30 -4 30 -70 33 l-68 3 0 34 0 35 110 0 110 0 0
-129 0 -130 -32 -24 c-54 -40 -97 -58 -154 -64 -189 -20 -311 148 -290 399 12
141 66 241 151 279 46 21 126 24 176 8z m774 -8 c105 -49 151 -165 143 -368
-4 -104 -7 -117 -39 -180 -41 -82 -91 -121 -164 -129 -145 -17 -241 78 -266
264 -19 144 13 296 79 366 60 63 167 84 247 47z m-2505 -296 l0 -305 165 0
165 0 0 -35 0 -35 -210 0 -210 0 0 340 0 340 45 0 45 0 0 -305z"
/>
<path d="M2140 3286 c-80 -44 -114 -265 -64 -418 44 -135 193 -147 254 -22 22
44 24 63 24 184 1 122 -2 140 -23 183 -13 26 -36 56 -51 67 -33 23 -102 26
-140 6z"
/>
<path d="M3667 3280 c-14 -11 -36 -41 -49 -68 -20 -42 -23 -61 -23 -177 0
-120 2 -134 27 -187 30 -65 64 -88 129 -88 35 0 48 6 79 38 52 52 63 98 58
257 -3 117 -6 134 -28 173 -14 24 -37 50 -52 58 -40 21 -110 18 -141 -6z"
/>
</g>
</svg>
);
};

View File

@@ -0,0 +1,31 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { buildConfig } from 'payload/config';
import path from 'path';
import { Icon } from './graphics/Icon';
import { Logo } from './graphics/Logo';
export default buildConfig({
serverURL: 'http://localhost:3000',
admin: {
// Add your own logo and icon here
components: {
graphics: {
Icon,
Logo,
},
},
// Add your own meta data here
meta: {
favicon: '/assets/favicon.svg',
ogImage: '/assets/ogImage.png',
titleSuffix: '- Your App Name',
},
},
typescript: {
outputFile: path.resolve(__dirname, 'payload-types.ts'),
},
graphQL: {
schemaOutputFile: path.resolve(__dirname, 'generated-schema.graphql'),
},
});

View File

@@ -0,0 +1,30 @@
/* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable @typescript-eslint/no-var-requires */
import express from 'express';
import payload from 'payload';
import path from 'path';
require('dotenv').config();
const app = express();
// Redirect root to Admin panel
app.get('/', (_, res) => {
res.redirect('/admin');
});
app.use('/assets', express.static(path.resolve(__dirname, '../assets')));
// Initialize Payload
payload.init({
secret: process.env.PAYLOAD_SECRET,
mongoURL: process.env.MONGODB_URI,
express: app,
onInit: () => {
payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`);
},
});
// Add your own express routes here
app.listen(3000);

View File

@@ -0,0 +1,28 @@
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"strict": false,
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "./dist",
"rootDir": "./src",
"jsx": "react"
},
"include": [
"src"
],
"exclude": [
"node_modules",
"dist",
"build",
],
"ts-node": {
"transpileOnly": true
}
}