Skip to content
This repository was archived by the owner on Feb 27, 2024. It is now read-only.

Commit d21353a

Browse files
committed
Merge branch 'staging' into develop
2 parents 229aa24 + 4e7845b commit d21353a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+988
-143
lines changed

.env.sample

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ VERCEL_ENV="development"
22
NODE_TLS_REJECT_UNAUTHORIZED="0"
33
LOCAL_WORDPRESS_API_URL="https://nextjswp.test/"
44
PROD_WORDPRESS_API_URL="https://myproductionwordpress.com/"
5-
WORDPRESS_PREVIEW_SECRET=""
6-
WORDPRESS_APPLICATION_USERNAME=""
7-
WORDPRESS_APPLICATION_PASSWORD=""
8-
NEXT_PUBLIC_LOCAL_ALGOLIA_INDEX_NAME=""
9-
NEXT_PUBLIC_ALGOLIA_APPLICATION_ID=""
10-
NEXT_PUBLIC_ALGOLIA_SEARCH_ONLY_KEY=""
5+
WORDPRESS_PREVIEW_SECRET="ANY_RANDOM_STRING_SEE_README"
6+
WORDPRESS_APPLICATION_USERNAME="YOUR_WORDPRESS_USERNAME"
7+
WORDPRESS_APPLICATION_PASSWORD="YOUR_GENERATED_APPLICATION_PASSWORD"
8+
NEXT_PUBLIC_LOCAL_ALGOLIA_INDEX_NAME="YOUR_ALGOLIA_INDEX_NAME"
9+
NEXT_PUBLIC_ALGOLIA_APPLICATION_ID="YOUR_ALGOLIA_APP_ID"
10+
NEXT_PUBLIC_ALGOLIA_SEARCH_ONLY_KEY="YOUR_ALGOLIA_SEARCH_ONLY_KEY"

README.md

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,29 @@ https://nextjs-wordpress-starter-staging.vercel.app/
1313
- [🎓 Overview](#-overview)
1414
- [Why?](#why)
1515
- [How's this all work?](#hows-this-all-work)
16+
- [3rd Party Services](#3rd-party-services)
17+
- [Algolia](#algolia)
18+
- [Chromatic](#chromatic)
19+
- [Vercel](#vercel)
20+
- [WP Engine](#wp-engine)
1621
- [🚀 Frontend Setup (Next.js)](#-frontend-setup-nextjs)
1722
- [Dependencies](#dependencies)
1823
- [Install](#install)
1924
- [🔧 Backend Setup (WordPress)](#-backend-setup-wordpress)
2025
- [Dependencies](#dependencies-1)
2126
- [Install](#install-1)
27+
- [Enable Previews](#enable-previews)
2228
- [💻 Frontend Development](#-frontend-development)
2329
- [Git Workflow](#git-workflow)
2430
- [Deployments](#deployments)
2531
- [Storybook](#storybook)
2632
- [WebDevStudios Specific Info](#webdevstudios-specific-info)
2733
- [WordPress Github](#wordpress-github)
28-
- [WP Engine](#wp-engine)
29-
- [Chromatic](#chromatic)
34+
- [WP Engine](#wp-engine-1)
35+
- [Chromatic](#chromatic-1)
3036
- [1Password](#1password)
3137
- [Migrate DB Pro](#migrate-db-pro)
38+
- [Algolia](#algolia-1)
3239
- [Copy WP Engine Environments](#copy-wp-engine-environments)
3340
- [:octocat: Contributing](#octocat-contributing)
3441

@@ -38,11 +45,11 @@ https://nextjs-wordpress-starter-staging.vercel.app/
3845

3946
### Why?
4047

41-
It's easy to query a WordPress REST-API and map over some blog posts in JavaScript. That's where many examples on the Internet stop and you'd be hard pressed to find anything about supporting advanced features because **_headless WordPress is hard!_**
48+
Querying a REST-API or GraphQL endpoint and looping over blog posts is where many _"how to build a headless WordPress website"_ tutorials stop. You'd be hard pressed to find anything about supporting advanced features and plugins because **_headless WordPress is hard._**
4249

43-
At WebDevStudios we believe that WordPress is so much more than a blog-- and our clients require support for things like: SEO, forms, post previews, search, comments, authentication, custom post types, custom fields, etc...
50+
At WebDevStudios we believe that WordPress is so much more than a blog-- and our clients require support for things like: SEO, forms, previews, search, comments, authentication, custom post types, custom fields, etc...
4451

45-
With this starter, we've figured out "the hard stuff" and placed the sum of our knowledge into something the community (and our future projects) could use as a jumping off point.
52+
With this starter, we've figured out the "hard stuff" and placed the sum of our knowledge into something both the community and our future projects could use as a jumping off point.
4653

4754
### How's this all work?
4855

@@ -52,6 +59,37 @@ The frontend (Next.js) talks to the backend (WordPress) via GraphQL.
5259
<img src="https://dl.dropbox.com/s/9wsal7szatfwt6g/nextjs-wordpress-starter-frontend-backend-graphic.png?dl=0" alt="A graphic showing the relationship between environments">
5360
</details>
5461

62+
### 3rd Party Services
63+
64+
This starter uses a few 3rd party services.
65+
66+
<details>
67+
68+
- [Algolia](https://www.algolia.com/)
69+
- [Chromatic](https://www.chromatic.com/)
70+
- [Vercel](https://vercel.com/)
71+
- [WP Engine](https://wpengine.com)
72+
73+
#### Algolia
74+
75+
We use [WP Search with Algolia](https://wordpress.org/plugins/wp-search-with-algolia/) to push content indicies from WordPress to Algolia. You will need to set up a (free) account and place your API credentials in the frontend `.env` file _and_ in the WordPress plugin settings.
76+
77+
#### Chromatic
78+
79+
Chromatic automates gathering UI feedback, visual testing, and documentation, so developers can iterate faster with less manual work. You will need to update both [`package.json`](https://github.com/WebDevStudios/nextjs-wordpress-starter/blob/staging/package.json#L34) and [`chromatic.yml`](https://github.com/WebDevStudios/nextjs-wordpress-starter/blob/staging/.github/workflows/chromatic.yml) with your Chromatic API key in order to automate builds.
80+
81+
#### Vercel
82+
83+
Vercel is the company behind Next.js and offers a platform _[that was built for deploying](https://vercel.com/solutions/nextjs)_ Next.js apps.
84+
85+
Vercel has a generous free tier and offers support for both serverless functions (required if using incremental static regeneration) and [`next/image`](https://nextjs.org/docs/api-reference/next/image). Something neither Netlify nor Cloudflare support.
86+
87+
#### WP Engine
88+
89+
We're a partner with WP Engine and love their managed WordPress hosting options. That said, while hosting your headless WordPress install on WP Engine is recommended, it is not required.
90+
91+
</details>
92+
5593
---
5694

5795
## 🚀 Frontend Setup (Next.js)
@@ -88,7 +126,7 @@ yarn
88126

89127
**Step 4: Setup ENV Variables**
90128

91-
Copy the sample ENV file, then add your credentials:
129+
ENV variables are like constants in `wp-config.php`. Copy the sample ENV file, then add your credentials:
92130

93131
```bash
94132
cp .env.sample .env
@@ -146,9 +184,22 @@ Before you get started, make sure you have the following dependency installed on
146184

147185
- https://localwp.com/help-docs/getting-started/how-to-import-a-wordpress-site-into-local/
148186

149-
**Step 3: Start the `nextjs-wp` site**
187+
**Step 3: Configure `wp-config.php`**
188+
189+
The follow constants needs to be in `wp-config.php`:
190+
191+
```php
192+
define('HEADLESS_FRONTEND_URL', 'http://localhost:3000/');
193+
define('PREVIEW_SECRET_TOKEN', 'ANY_RANDOM_STRING');
194+
```
195+
196+
**Step 4: Start the `nextjs-wp` site**
197+
198+
**Note:** Make sure your local URL matches the `LOCAL_WORDPRESS_API_URL` in the frontend `.env` file!
150199

151-
**Note:** Make sure your Local URL matches the `LOCAL_WORDPRESS_API_URL` in the frontend `.env` file!
200+
### Enable Previews
201+
202+
To enable previews, you'll need both a `PREVIEW_SECRET_TOKEN` constant in `wp-config.php` and `WORDPRESS_PREVIEW_SECRET` ENV variable in `.env`. The token can be any random string so long as they match.
152203

153204
---
154205

@@ -220,6 +271,10 @@ All of the credentials are in the following vault:
220271

221272
You can use Migrate DB Pro to pull databases and files. Please see 1password for credentials
222273

274+
### Algolia
275+
276+
The login and API credentials are in password.
277+
223278
### Copy WP Engine Environments
224279

225280
WP Engine supports [copying environments](https://wpengine.com/support/copy-site/). This should be done at the end of two week sprints (or as needed).

components/atoms/Code/Code.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import PropTypes from 'prop-types'
2+
import React from 'react'
3+
import styles from './Code.module.css'
4+
import {Prism as SyntaxHighlighter} from 'react-syntax-highlighter'
5+
import {tomorrow} from 'react-syntax-highlighter/dist/cjs/styles/prism'
6+
7+
/**
8+
* Render the Code component.
9+
*
10+
* @author WebDevStudios
11+
* @param {object} props The component attributes as props.
12+
* @param {string} props.className Optional classname.
13+
* @param props.id
14+
* @param props.content
15+
* @param {boolean} props.fullWidth Is this a fullwidth block.
16+
* @return {Element} The Code component.
17+
*/
18+
export default function Code({id, className, content}) {
19+
// Use the className to pass the langauge.
20+
const language = className ? className : 'javascript'
21+
22+
// Replace any `&lt;` and `&gt; encoded HTML.
23+
let code = content.replace(/&lt;/g, '<')
24+
code = code.replace(/&gt;/g, '>')
25+
26+
return (
27+
<>
28+
{!!content && (
29+
<div id={id ? id : null} className={styles.code}>
30+
<SyntaxHighlighter style={tomorrow} language={language}>
31+
{code}
32+
</SyntaxHighlighter>
33+
</div>
34+
)}
35+
</>
36+
)
37+
}
38+
39+
Code.propTypes = {
40+
id: PropTypes.string,
41+
content: PropTypes.string,
42+
className: PropTypes.string
43+
}

components/atoms/Code/Code.module.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.code {
2+
@apply mb-40;
3+
4+
& > pre {
5+
@apply rounded-larger;
6+
}
7+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import {Meta, Story, Canvas} from '@storybook/addon-docs/blocks'
2+
3+
import Separator from '.'
4+
5+
<Meta title="Components/Atoms/Separator" component={Separator} />
6+
7+
# Separator
8+
9+
Use this component to display a page separator with top and bottom margins. Use it anywhere you would use an `<hr>` element.
10+
11+
<Canvas>
12+
<Story name="Component">
13+
<Separator />
14+
</Story>
15+
</Canvas>
16+
17+
## Full Width
18+
19+
The default separator is equal to the container width. To get a full width separator, set the `fullWidth` prop to true.
20+
21+
<Canvas>
22+
<Story name="Full Width">
23+
<Separator fullWidth />
24+
</Story>
25+
</Canvas>
26+
27+
## Controls
28+
29+
Play around with `<Separator />` props in the [Canvas tab of the Controls story](?path=/story/design-system-atoms-separator--controls).
30+
31+
export const Template = (args) => <Separator {...args} />
32+
33+
<Canvas>
34+
<Story
35+
name="Controls"
36+
args={{
37+
fullWidth: false
38+
}}
39+
>
40+
{Template.bind({})}
41+
</Story>
42+
</Canvas>

components/atoms/Code/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export {default} from './Code'

components/atoms/Image/Image.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import Link from 'next/link'
2+
import PropTypes from 'prop-types'
3+
import React from 'react'
4+
import RichText from '@/components/atoms/RichText'
5+
import styles from './Image.module.css'
6+
import cn from 'classnames'
7+
8+
/**
9+
* Render the Image component.
10+
*
11+
* @author WebDevStudios
12+
* @param {string} anchor The anchor/id of the block.
13+
* @param {string} alt The image alt text.
14+
* @param {string} caption The image caption.
15+
* @param {string} className The image class.
16+
* @param {string} id The image ID.
17+
* @param {string} href The URL of the link.
18+
* @param {string} linkTarget Target for the link.
19+
* @param {string} linkClass Class for the link.
20+
* @param {string} rel The rel attribute for the link.
21+
* @param {string} sizeSlug The WP image size.
22+
* @param {string} url The full URL path of the image.
23+
* @return {Element} The Image component.
24+
*/
25+
export default function Image({
26+
alt,
27+
anchor,
28+
caption,
29+
className,
30+
id,
31+
href,
32+
linkTarget,
33+
linkClass,
34+
rel,
35+
url
36+
}) {
37+
return (
38+
<>
39+
{!!url && (
40+
<div id={anchor || null} className={styles.image}>
41+
{href ? (
42+
<Link href={href}>
43+
<a
44+
target={linkTarget || null}
45+
rel={rel || null}
46+
className={linkClass || null}
47+
>
48+
<img
49+
src={url}
50+
alt={alt}
51+
className={cn(className, `image-${id}`)}
52+
/>
53+
</a>
54+
</Link>
55+
) : (
56+
<img
57+
src={url}
58+
alt={alt}
59+
className={cn(className, id && `image-${id}`)}
60+
/>
61+
)}
62+
{!!caption && (
63+
<div className={styles.caption}>
64+
<RichText tag="span">{caption}</RichText>
65+
</div>
66+
)}
67+
</div>
68+
)}
69+
</>
70+
)
71+
}
72+
73+
Image.propTypes = {
74+
alt: PropTypes.string,
75+
anchor: PropTypes.string,
76+
caption: PropTypes.string,
77+
className: PropTypes.string,
78+
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
79+
href: PropTypes.string,
80+
linkClass: PropTypes.string,
81+
linkTarget: PropTypes.string,
82+
rel: PropTypes.string,
83+
sizeSlug: PropTypes.string,
84+
url: PropTypes.string
85+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.image {
2+
@apply mb-20;
3+
4+
& img {
5+
@apply block rounded;
6+
}
7+
8+
& .caption {
9+
@apply text-center font-secondary text-xs pt-12;
10+
}
11+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import {Meta, Story, Canvas} from '@storybook/addon-docs/blocks'
2+
3+
import Image from '.'
4+
5+
<Meta title="Components/Atoms/Image" component={Image} />
6+
7+
# Image
8+
9+
Use this component to display a image.
10+
11+
<Canvas>
12+
<Story name="Component">
13+
<Image
14+
url="https://images.unsplash.com/photo-1611149469739-cf4647d61f07?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1050&q=80"
15+
alt="Image alt text"
16+
caption="This is the image caption"
17+
/>
18+
</Story>
19+
</Canvas>
20+
21+
## Image + Link
22+
23+
Add a link to the image using the `href` prop.
24+
25+
<Canvas>
26+
<Story name="Image + Link">
27+
<Image
28+
url="https://images.unsplash.com/photo-1611149469739-cf4647d61f07?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1050&q=80"
29+
alt="Image alt text"
30+
caption="This is the image caption"
31+
href="https://google.com"
32+
/>
33+
</Story>
34+
</Canvas>
35+
36+
## Controls
37+
38+
Play around with `<Image />` props in the [Canvas tab of the Controls story](?path=/story/components-atoms-image--controls).
39+
40+
export const Template = (args) => <Image {...args} />
41+
42+
<Canvas>
43+
<Story
44+
name="Controls"
45+
args={{
46+
url:
47+
'https://images.unsplash.com/photo-1611149469739-cf4647d61f07?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1050&q=80',
48+
caption: 'Jeffery Smith, 28'
49+
}}
50+
>
51+
{Template.bind({})}
52+
</Story>
53+
</Canvas>

components/atoms/Image/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export {default} from './Image'

0 commit comments

Comments
 (0)