Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .github/workflows/doc-site.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: "Build Documentation Site"
on:
push:
branches:
- main
- doc-site
paths:
- doc-site/**

env:
region: us-west-2
s3_sync_path: /docs/modules/frontend-react
BUILD_DOMAIN: ${{ secrets.ZERO_DOC_SITE_DOMAIN_NAME }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup node.js
uses: actions/setup-node@v1
with:
node-version: 14.x
- name: Install Dependencies
working-directory: doc-site
run: npm install
- name: Build website
working-directory: doc-site
run: |
npm run build
ls -la
- name: Upload build artifact to Github
uses: actions/upload-artifact@v2
with:
name: build-artifact
path: doc-site/build

deploy:
name: Deploy
runs-on: ubuntu-latest
needs: build

steps:
# Once github action supports nested composite actions (anything `uses` is a composite action)
# Therefore we cannot reuse the code as a separate composite action until it supports it,
# current the deploy logic is in this file twice because of it
## https://github.com/actions/runner/issues/862
- uses: actions/checkout@v2
- name: Configure AWS credentials for S3 sync
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.ZERO_DOC_SITE_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.ZERO_DOC_SITE_AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.region }}
- name: Download build artifact from Github
uses: actions/download-artifact@v1
with:
name: build-artifact
path: build/
- name: Sync with S3
shell: bash
run: |
cd build
aws s3 sync . "s3://${{ secrets.ZERO_DOC_SITE_BUCKET_NAME }}${{ env.s3_sync_path }}" --delete
- name: Invalidate Cloudfront
shell: bash
run: |
export DIST_ID=$(aws cloudfront list-distributions --query "DistributionList.Items[?Aliases.Items[?@=='${{ secrets.ZERO_DOC_SITE_BUCKET_NAME }}']].Id | [0]" | tr -d '"')
aws cloudfront create-invalidation --distribution-id ${DIST_ID} --paths "${{ env.s3_sync_path }}*"
24 changes: 24 additions & 0 deletions doc-site/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Dependencies
/node_modules

# Production
/build

# Generated files
.docusaurus
.cache-loader

# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

# This is downloaded during build time
# to sync with zero core styles
src/css/zero-downloaded-global-custom.css
33 changes: 33 additions & 0 deletions doc-site/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Website

This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.

## Installation

```console
yarn install
```

## Local Development

```console
yarn start
```

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

## Build

```console
yarn build
```

This command generates static content into the `build` directory and can be served using any static contents hosting service.

## Deployment

```console
GIT_USER=<Your GitHub username> USE_SSH=true yarn deploy
```

If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
3 changes: 3 additions & 0 deletions doc-site/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
};
34 changes: 34 additions & 0 deletions doc-site/docs/about/module-life-cycle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: Module Life cycle
sidebar_label: Module Life cycle
sidebar_position: 4
---


## Prerequisites
The CI/CD pipeline of the module requires S3 bucket and cloudfront distribution to be created under the same project name. And Injects the CI-user's credentials from into the CI secrets on init phase. These are created from the zero-aws-eks-stack repository.

## Scaffold
Based on Parameters in Project definition(`zero-project.yml`), module will be scaffolded and templated out during Zero create

Options that alter the templated repository
- `userAuth`: Determines whether user auth provider is included in your repository
- `CIVendor`: Scaffolds one of CircleCI / Github actions deployment pipeline
- `billingEnabled`: Includes billing page to load products and api calls to communicated with backend service, and API key in `config.json`


## Module Initialize phase
_Run once only during `zero apply`_
- Sets up CI pipeline with `env-vars` and secrets containing CI-user's AWS Credentials
- Github Actions will rerun the initial commit since it was first ran without the credentials (during `zero create`)

## On-going
### Pull request
- Unit test
### Push to master branch
- Unit test
- Build static site
- (stage) Sync build to S3 bucket
- (stage) Invalidate Cloudfront Cache
- (prod) Sync build to S3 bucket
- (prod) Invalidate Cloudfront Cache
44 changes: 44 additions & 0 deletions doc-site/docs/about/module-parameters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
title: Module Parameters
sidebar_label: Module Parameters
sidebar_position: 2
---

## Parameters

| Parameter | Label | Env-var(apply) | Default |
|--|---|---|---|
| useExistingAwsProfile | Use credentials from an existing AWS profile? | n/a | null |
| profilePicker | n/a | n/a | null |
| accessKeyId | AWS AccessKeyId | AWS_ACCESS_KEY_ID | null |
| secretAccessKey | AWS SecretAccessKey | AWS_SECRET_ACCESS_KEY | null |
| githubAccessToken | Github API Key to setup your repository and optionally CI/CD | GITHUB_ACCESS_TOKEN | null |
| region | Select AWS Region | n/a | null |
| productionHostRoot | Production Root Host Name (e.g. mydomain.com) - this must be the root of the chosen domain, not a subdomain. | n/a | null |
| productionFrontendSubdomain | Production Frontend Host Name (e.g. app.) | n/a | app. |
| productionBackendSubdomain | Production Backend Host Name (e.g. api.) | n/a | api. |
| stagingHostRoot | Staging Root Host Name (e.g. mydomain-staging.com) - this must be the root of the chosen domain, not a subdomain. | n/a | null |
| stagingFrontendSubdomain | Staging Frontend Host Name (e.g. app.) | n/a | app. |
| stagingBackendSubdomain | Staging Backend Host Name (e.g. api.) | n/a | api. |
| randomSeed | Random seed that will be shared between projects to come up with deterministic resource names | n/a | null |
| userAuth | Enable user management using Kratos and authentication using the Oathkeeper access proxy? | n/a | true |
| CIVendor | Using either circleCI or github Actions to build / test your repository | n/a | circleci |
| circleciApiKey | Circle CI API Key to setup your CI/CD for repositories | CIRCLECI_API_KEY | null |
| billingEnabled | Provides a subscription example using stripe in backend and frontend repository | n/a | null |
| stagingStripePublicApiKey | Staging Stripe public api key, used for frontend repository (Recommended: using sandbox key while setting up) | n/a | null |
| stagingStripeSecretApiKey | Staging Stripe secret api key, used for backend repository (Recommended: using sandbox key while setting up) | n/a | null |
| productionStripePublicApiKey | Production Stripe public api key, used for frontend repository (Recommended: using sandbox key while setting up) | n/a | null |
| productionStripeSecretApiKey | Production Stripe secret api key, used for backend repository (Recommended: using sandbox key while setting up) | n/a | null |

:::info
Content generated by
```shell
## requires binary: `yq`
which yqq >/dev/null || echo "Please install yq"
cat <<EOF
| Parameter | Label | Env-var(apply) | Default |
|--|---|---|---|
EOF
cat zero-module.yml | yq -r '.parameters[] | "| " + .field + " | " + (.label//"n/a") + " | " + (.envVarName //"n/a") + " | " + ((.default)|tostring //"n/a") + " | "'
```
:::
23 changes: 23 additions & 0 deletions doc-site/docs/about/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: Overview
sidebar_label: Overview
sidebar_position: 1
---


This is a [Zero] module which sets up a
React web-app bundled statically served through CloudFront and S3 from the [zero-aws-eks-stack][zero-infra].

The `/templates` folder is meant to be filled in via [Zero][zero] and results in Simple React application. It also contains a simple CircleCI pipeline which defines how to build and deploy the service.

This repository is business-logic agnostic; mainly showcasing some universal best practices:

- Creating an optimized build of your frontend application.
- Out of the box CI/CD flow CircleCi.
- testing
- building your web-app as a static distribution in /dist folder.
- syncs the built bundle to AWS S3.
- invalidates Cloudfront cached version.

[zero]: https://github.com/commitdev/zero
[zero-infra]: https://github.com/commitdev/zero-aws-eks-stack
31 changes: 31 additions & 0 deletions doc-site/docs/components/billing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
title: Billing using Stripe
sidebar_label: Stripe
sidebar_position: 3
---

## Billing example
If you have enabled Billing from Zero, a subscription and checkout example using [Stripe](https://stripe.com), coupled with the backend repository to provide an end-to-end checkout example for you to customize. We also setup a webhook and an endpoint in the backend to receive webhook when events occur.

### Requirements
This billing example requires the following backend API endpoints:
```
GET /billing/products
POST /billing/success
POST /billing/cancel
POST /billing/checkout
```

### Setup
The following example content has been set up in Stripe:
- 1 product
- 3 prices(subscriptions) [annual, monthly, daily]
- 1 webhook [`charge.failed`, `charge.succeeded`, `customer.created`, `subscription_schedule.created`]
See link for available webhooks: https://stripe.com/docs/api/webhook_endpoints/create?lang=curl#create_webhook_endpoint-enabled_events

this is setup using the script [scripts/stripe-example-setup.sh][backend-stripe-setup-script]

### Deployment
The deployment requires the publishable key in the build, per environment you will have to provide `stripePublishableKey` in `config/<env>.json` [`production`/`staging`/`development`], then when CI builds it will create a bundle with the Stripe publishable API key

[backend-stripe-setup-script]: https://github.com/commitdev/zero-deployable-backend/blob/main/templates/scripts/stripe-example-setup.sh
32 changes: 32 additions & 0 deletions doc-site/docs/components/user-auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: User Auth
sidebar_label: User Auth
sidebar_position: 1
---

## Authentication
If you enabled `user_auth` from Project definition. An authentication setup would be templated out along side your frontend application.
With examples of:
- Authenticated and Unauthenticated navigation bar
- Auth-provider implemented with user status checking
- Home page with 2 blocks of data from backend, one requiring authentication
- Signup/Login/Password reset forms secured with CSRF token
- Example of backend API calls authenticated via https only cookie using signed JWT tokens

## Concept
This example is built with backend components [ORY Oathkeepr][oathkeeper] as an access identity proxy and [ORY Kratos][kratos] as user-management system.

### Forms
Forms on the frontend are secured with [CSRF tokens][csrf], they are a nonce that ensure the request cannot be repeatedly executed. Each form request(signup/login/password reset) are initiated and identifiable.

### API calls to the backend
API calls to the backend are authenticated via the Oathkeeper proxy, they are made to the backend with `credentials: include`
```javascript
fetch(uri,{ credentials : "include" });
```
This will pass along `same-origin`'s cookie along with the request, and through Oathkeeper Proxy will inspect the Cookie against Kratos for authenticity and expiry, and upon unauthenticated request it will return `401 Unauthorized` and request **will not** make it to the backend service.


[kratos]: https://github.com/ory/kratos
[oathkeeper]: https://github.com/ory/oathkeeper
[csrf]:https://owasp.org/www-community/attacks/csrf
43 changes: 43 additions & 0 deletions doc-site/docusaurus.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/** @type {import('@docusaurus/types').DocusaurusConfig} */
const { downloadCommonCustomCss, themeConfig, stylesheets, misc } = require('@commitdev/zero-doc-site-common-elements');

const siteUrl = process.env.BUILD_DOMAIN ? `https://${process.env.BUILD_DOMAIN}` : 'https://staging.getzero.dev';
const baseUrl = '/docs/modules/frontend-react/';
const repositoryName = 'zero-deployable-react-frontend';

let customCss;
try {
customCss = require.resolve(downloadCommonCustomCss());
} catch (e) {
console.error("Failing back to local css, if you see this warning means your module theme is likely outdated")
customCss = require.resolve('./src/css/fallback.css');
}

module.exports = {
title: 'Zero Frontend - React Documentation',
tagline: 'Opinionated infrastructure to take you from idea to production on day one',
...misc(), //includes onBrokenLinks, onBrokenMarkdownLinks, favicon, organizationName
url: siteUrl,
baseUrl: baseUrl,
projectName: repositoryName,
themeConfig: themeConfig({ siteUrl, repositoryName }),
presets: [
[
'@docusaurus/preset-classic',
{
docs :{
sidebarPath: require.resolve('./sidebars.js'),
path: 'docs',
routeBasePath: '/',
editUrl: `https://github.com/commitdev/${repositoryName}/blob/main/doc-site/`,
},
theme: {
customCss,
},
debug: true,
},
],
],
stylesheets: stylesheets(),

};
Loading