Deploying React Projects Located in Subdirectories to GitHub Pages Using GitHub Actions (CI/CD)
Published: 2024-04-11 06:58:37



Hello developers!

Let's suppose that you have multiple React projects within the same GitHub repository, and you're looking to deploy them all to GitHub Pages while automating the deployment process for each commit, you've come to the right place!

Today, I'd like to share some of the challenges I encountered while setting up a CI/CD pipeline via GitHub Actions for recent react projects I've been working on. Specifically, I'll be focusing on a scenario where I have a GitHub repository named [`react-challenges`](https://github.com/DEVLOKER/react-challenges), which contains multiple React projects, each residing in a subdirectory (`accordion`, `guess-word`, `landing-page`, `tic-tac-toe`, and `tree`).


![react projects subdirectories](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ond4jj9ub89d4hosmxfh.jpg)


**Are you ready? Let's dive in!**

### 1. Customize `vite.config.ts`

First you have to know that all those react projects are created using [Vite](https://vitejs.dev), and for each of them, you need change the `vite.config.ts` file by adding the following configuration:

```typescript
build: {
    outDir: "build",
},
base: "",
```


![vite.config.ts after changes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8r4itgx5dobynynancw3.jpg)

> 
**Note**: The default build folder for a Vite project is `dist`, however in my projects I used `build` folder. So, If you prefer to use the default, make sure to adjust the paths accordingly in the YAML file (step 2).

### 2. Create `deploy.yml`

Create a deployment file named `deploy.yml` inside the `.github/workflows` directory and paste the following code:

```yaml
name: Deploy static content to Pages

on:
  push:
    branches: ["main"]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: "pages"
  cancel-in-progress: true

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Set up Node
        uses: actions/setup-node@v4
        with:
          node-version: 20

      # landing-page project
      - name: Build landing-page
        run: |
          cd landing-page
          npm install && npm run build
          cd ..
          mkdir -p deploy/landing-page
          cp -r landing-page/build/* deploy/landing-page/
      # tic-tac-toe project
      - name: Build tic-tac-toe
        run: |
          cd tic-tac-toe
          npm install && npm run build
          cd ..
          mkdir -p deploy/tic-tac-toe
          cp -r tic-tac-toe/build/* deploy/tic-tac-toe/
      # guess-word project
      - name: Build guess-word
        run: |
          cd guess-word
          npm install && npm run build
          cd ..
          mkdir -p deploy/guess-word
          cp -r guess-word/build/* deploy/guess-word/
      # accordion project
      - name: Build accordion
        run: |
          cd accordion
          npm install && npm run build
          cd ..
          mkdir -p deploy/accordion
          cp -r accordion/build/* deploy/accordion/
      # tree project
      - name: Build tree
        run: |
          cd tree
          npm install && npm run build
          cd ..
          mkdir -p deploy/tree
          cp -r tree/build/* deploy/tree/

      - name: Setup Pages
        uses: actions/configure-pages@v4
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: "./deploy"
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4
```

What this YAML file do? after building the projects, will copy the `build` output of each project to a root folder named `./deploy`, while the root folder will be served at the following link: `https://{username}.github.io/react-challenges/`.
And each project will be accessible by adding its subdirectory name to the end of the root link: `https://{username}.github.io/react-challenges/{react-sub-directory}`.

In my case:
- [https://DEVLOKER.github.io/react-challenges/guess-word](https://DEVLOKER.github.io/react-challenges/guess-word)
- [https://DEVLOKER.github.io/react-challenges/tic-tac-toe](https://DEVLOKER.github.io/react-challenges/tic-tac-toe)
- [https://DEVLOKER.github.io/react-challenges/landing-page](https://DEVLOKER.github.io/react-challenges/landing-page)
- [https://DEVLOKER.github.io/react-challenges/accordion](https://DEVLOKER.github.io/react-challenges/accordion)
- [https://devloker.github.io/react-challenges/tree](https://devloker.github.io/react-challenges/tree)

### 3. GitHub Repository Settings

Ensure that the build and deployment source are set to `GitHub Actions` from `Settings/Pages/Build and deployment`. 

![Enable GitHub Actions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pxmsp2m73sanduh11xrt.jpg)

Also, grant read and write permissions for Workflow permissions by checking `Read and write permissions` from `Settings/Actions/General/Workflow permissions`.

![Enable Read and write permissions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/273isv44xce04fjryxqr.jpg)

Finally, with these configurations in place, your deployment process should end successfully!


![Deployment successfully](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/95o3ktq3k3b22z31dclt.jpg)

**Thats all!** 
I really hope this post was beneficial to you and saved you some research/debug time. If you find any thing incorrect or lacking in explanation, please leave a comment and I will edit accordingly.

Feel free to fork the [Github repository](https://github.com/DEVLOKER/react-challenges)

Check out the deployed GitHub Pages for each project:

- [Guess-Word](https://DEVLOKER.github.io/react-challenges/guess-word)
- [Tic-Tac-Toe](https://DEVLOKER.github.io/react-challenges/tic-tac-toe)
- [Landing Page](https://DEVLOKER.github.io/react-challenges/landing-page)
- [Accordion](https://DEVLOKER.github.io/react-challenges/accordion)
- [Tree](https://devloker.github.io/react-challenges/tree)

Happy coding and deploying!