penny
Penny
An e-commerce starter kit by TakeShape.
Check out the store now at https://penny-demo.takeshape.io/.
- Deployed on Netlify: https://penny-ecommerce.netlify.app
- Deployed on Vercel: https://penny-ecommerce.vercel.app
You can clone this repo with git to run the Next.js frontend locally (git clone https://github.com/takeshape/penny
).
To connect it to a GraphQL backend that TakeShape provides, just deploy the pattern in the .takeshape/pattern
directory. The instructions section of this README will teach you how to do that.
Lighthouse Report: mobile
Category
Score
🟢 Performance
98
🟢 Accessibility
100
🟢 Best practices
100
🟢 SEO
100
🟢 PWA
100
Path: /products/basic-tee-6-pack
Report
🟢 Performance
95
🟢 Accessibility
100
🟢 Best practices
100
🟢 SEO
100
🟢 PWA
100
🟢 Performance
96
🟢 Accessibility
100
🟢 Best practices
100
🟢 SEO
100
🟢 PWA
100
The TakeShape project pattern
This starter project composes the following services into a unified GraphQL API:
- Shopify Admin and Storefront for customer data, product info and payment processing
- OpenID for identity management
- ReCAPTCHA for security
- Gorgias for customer support
- Klaviyo for newsletter subscriptions
- REVIEWS.io for product reviews
- Voucherify for customer loyalty rewards
- Ship Engine for shipping management
TakeShape is also providing performance and data services for the storefront:
-
TakeShape’s API Indexing speeds up product queries by
10x and enables lighting fast product search on the frontend -
TakeShape’s ShapeDB hosts some of the custom content used in this
build.
graph TD
A[Frontend Next.js Client] --> |Unified GraphQL API| Mesh{TakeShape's API Mesh}
Mesh --> |User Authentication| OpenID[OpenID connect]
Mesh --> |DDoS prevention| reCAPTCHA
Mesh --> P{Products}
P --> Shopify[Shopify Admin and Storefront]
P --> Recharge[Recharge]
Mesh --> UP{User Profile}
UP --> |Orders, and Customer Data| Shopify
UP --> |Subscripitons, and Customer Data| Recharge
UP --> |Newsletter| Klaviyo
P --> |Product Reviews| REVIEWS.io
UP --> |Reviews Written| REVIEWS.io
UP --> |Shipping info| ShipEngine
UP --> |Loyalty Points| Voucherify
UP --> |Customer Support| Gorgias
The frontend stack
The frontend codebase was built with many features that are important for modern composable e-commerce storefronts,
including:
Frameworks, language and styling
Here are the frameworks, language and styling options we went with for this build:
- Next.js to build the pages and bundle the frontend application
- NextAuth for user authentication against TakeShape and Shopify
- TypeScript for type safety and documentation
- Apollo Client for efficient GraphQL queries against TakeShape
- Jotai for optimized component state management
- Storybook for rapid UI prototyping and review
- Tailwind CSS for beautiful styles.
Continuous Integration
Numerous CI tools have been configured with GitHub Actions. You’ll have a starting point that is easy to test, and easy
to keep error-free and performant.
Unit Tests
- Jest for React component testing.
- ESLint for code style and quality.
- TypeScript ensures a type-safe codebase.
- GraphQL Codegen extend type-safety to all your GraphQL queries.
E2E Tests
- Cypress for frontend end-to-end testing and API service mocking
Performance Tests
- Lighthouse for SEO and browser performance metrics
Set up your lighthouse testing paths in .lighthouse/testPaths.json
. By default your homepage will be tested.
IMPORTANT
If you have branch protections in place on your main
branch you will need to include a repo secret
PROTECTED_PUSH_TOKEN
that is a personal access token with the repo
scopes and which is an admin on the project repo.
If you are not using branch protection rules you can replace ${{ secrets.PROTECTED_PUSH_TOKEN }}
with
${{ secrets.GITHUB_TOKEN }}
in the lighthouse.yml
workflow file.
Snapshots
- Chromatic hosts Storybook stories and provides visual snapshot comparisons
Runtime error reporting
-
Sentry for error reporting and health monitoring
with their Next.js-specific SDK.
TakeShape specific-tools
We also used a few tools from TakeShape’s ecosystem to simplify our workflow and improve the development process:
-
Next-Auth-All-Access — A NextAuth wrapper that
provides JWKS-verifiable access tokens for third-party APIs. -
@takeshape/graphql-validate — GraphQL query validation
against your TakeShape API.
In the next section, you’ll find a screenshot of the finished store’s homepage.
Screenshot
Getting Started
To get started with TakeShape you need to perform these steps:
-
Create a new Github repository for your Project and configure
.env
- Deploy Penny to a new TakeShape Project
- Configure Shopify Admin and Shopify Storefront services
-
Run
npm run dev
to try out Penny with only Shopify enabled - Configure additional services and customize your Penny project!
Create a new Github repository for your Project
- Create a new repository using this repository as a template:
- Clone your new repository
-
Navigate to the project directory in your local terminal and run the
npm install
command to install all
dependencies. - Set up your environment variables.
-
Every project will contain a mix of variables defined in
.env
files and runtime variables defined in a hosting
provider. -
Create your project’s
.env
starter files. Runnpm run prepare-env
. This repo already contains some.env
files
used for the demo, so you will be prompted to overwrite those files. -
Because many variables are required to get a fully functional project you should ensure all your services are
configured before customizing the.env
files. Take a look at the.env
files now to get a sense of what you’ll need
before you run the project, and take note of where the various keys and secrets live along the way. -
.env
contains common variables for all runtimes. You can define publicly available variables here. In most cases
these are prefixed withNEXT_PUBLIC
. This file is checked into your repo. -
.env.local
contains variables to use during local development. This file is not checked into your repo and can
contain all the secrets you need to get your local development environment running, as well as overrides for common
.env
variables. -
.env.test
contains variables and overrides only used when running tests, likejest
orcypress
.
Warning! Never check secrets into your repo!
-
Add secrets needed for Github Actions. You can do this by going to your Github project settings then Secrets /
Actions. You’ll need the following secrets:
-
CHROMATIC_PROJECT_TOKEN
if using Chromatic. -
TS_API_KEY
Use thewebhook
key from earlier. -
TS_AUTH_TOKEN
Can be created in your TakeShape project from the user menu under Access Tokens. -
TS_PROJECT_ID
Can be copied from your TakeShape project dashboard.
Deploy Penny to a new TakeShape Project
- Create a TakeShape project using the pattern in this repo. This button will deploy the project for you:
-
Generate an
anonymous
and awebhook
TakeShape API key. You need these two API keys, and they must have different
permissions scopes. Here’s how to create them:
- Navigate to the Settings tab in your TakeShape project’s dashboard.
- Select the API Keys option in the left sidebar.
- Select the New API Key button at the top-right of the page.
-
Name the first API Key anything you want; just be sure to grant it
anonymous
permissions. -
Save the key in your
.env
file asNEXT_PUBLIC_TAKESHAPE_ANONYMOUS_API_KEY
.
- Get your TakeShape project’s API Endpoint. Here’s how:
-
Navigate to the Home tab of your TakeShape project’s dashboard in the web client. Scroll down to the Useful
Snippets section, and copy the API Endpoint there. -
Save the endpoint in your
.env
file asNEXT_PUBLIC_TAKESHAPE_API_URL
.
-
Commit changes to
.env
NextAuth and OpenID
This project uses NextAuth in combination with the @takeshape/next-auth-all-access
package for user authentication. It
also uses OpenID for identity management. The following instructions will walk you through setting up OpenID as a
service provider in your TakeShape project, and configuring NextAuth with @takeshape/next-auth-all-access
.
Setting up OpenID
-
In the Home tab of your TakeShape project, select OpenID from the list of services. You will be taken to the
OpenID service configuration page. -
Add your store’s URL to the Issuer URL field, and enter the same URL with
/api/auth/all-access/.well-known/openid-configuration
appended to the end of it in the OpenID Configuration
URL.Note: Your store URL should be the public-facing URL of your website, not necessarily your myshopify.com URL.
-
Copy the generated url in the Audience field and save it somewhere secure. You’ll need it for your one of your
project’s environment variables. - Select the Save button at the top-right of the OpenID service page.
-
Update your
.env
file in your Next.js project’s directory with the following variables:
-
Add a
NEXT_PUBLIC_TAKESHAPE_AUTH_AUDIENCE
variable with the generated Audience URL from your OpenID provider. -
Add a
NEXT_PUBLIC_TAKESHAPE_AUTH_ISSUER
variable with the same URL you provided for the Issuer URL field on your
OpenID provider. This should be your store’s URL.
Setting up NextAuth
Use our @takeshape/next-auth-all-access
package to create and sign an access token for your logged-in users.
To generate your keypair, use the following command from the root of your project repo and follow the printed
instructions.
npx @takeshape/next-auth-all-access generate-keys
You will then need to follow these steps:
-
Add the variable
ALLACCESS_PRIVATE_KEY
with your private key to your.env.local
file and to your hosting
provider’s environment. -
Commit the
./keys/jwks.json
file to your repo, push, and build. Your key will need to be web accessible at the URL
you configured in TakeShape before authentication will work.
Shopify Admin and Shopify Storefront
Warning! Connecting this project to a live Shopify store WILL enable real purchases. If you just want to play
around without risking real charges,
set your store’s payments to Test Mode
and use appropriately scoped Shopify API keys. When testing purchases,
always use
Shopify’s accepted fake credit card information.
This project uses Shopify for e-commerce functionality. These instructions assume you’ve already
created a Shopify store. You don’t need to have Shopify Plus to use any of the features
described here.
Follow these instructions to connect your Shopify store’s Admin and Storefront APIs to both your TakeShape project and
the frontend Next.js project.
- Create a Shopify store if you don’t already have one.
-
Navigate to your store’s admin site by visiting
https://your-store.myshopify.com/admin
, substituting “your-store”
with the name of your store. - Configure your Shopify checkout experience.
This project uses Shopify’s checkout experience. That means when a customer is ready to purchase, they are redirected to
a checkout flow that Shopify generates. The only downside is, shopify’s checkout flow will send users to your shopify
store, not your headless store, when they’re done. To force Shopify’s checkout experience to redirect to your headless
storefront, you must use their Liquid templating language. These instructions show
you how:
-
In your store’s admin UI, select the âš™ Settings button. A settings menu will appear. Select Checkout on the
left. -
Scroll down to the Order status page settings. In the Additional Scripts text area, add the following script.
There are two URLs the order can possibly be redirected to. Be sure to add your store’s root URL to the second one,
under the{% else %}
:{% if checkout.attributes.redirect_origin %} <script> window.location = "{{ checkout.attributes.redirect_origin }}/?shopify_checkout_action=success"; </script> {% else %} <script>...