Development Instructions

Directory Structure

.
├── public                      # Public Assets
├── src
│   ├── app                     # Stores/Hooks
│   ├── features
│       ├── auth                # components/services related to authentication/authorization
│       ├── program             # Program related components/services
│       ├── round               # Round related components/services 
│   ├── api.ts                  # Empty API service (feature APIs will inject endpoints)
│   ├── browserPatches.tsx      # Browser polyfill
│   ├── index.tsx               # Routes
│   ├── index.css               # Global CSS
├── tsconfig.json               # Typescript documentation 
├── craco.json                  # Craco configuration
├── package.json                # Package configuration
└── README.md

The app structure ensures all components and services related to a particular feature are kept in a subdirectory of the features directory.

Observe the directory structure for Authentication feature in features/auth

├── features
│   ├── auth
│   │   ├── ProtectedRoute.tsx
│   │   ├── web3Service.tsx

It contains the ProtectedRoute component and web3Service which extends the base API service defined in src/api.ts by endpoint injection.

Adding a new route

Global routing configuration is held in src/index.tsx. Below is an example of a route definition

<Route path="/program/create" element={<CreateProgram />} /> <Route path="/program/:id" element={<ViewProgram />} />

A protected route i.e a routed which requires a user's wallet connection should be within the parent ProtectedRoute component route

<Route element={<ProtectedRoute />}> <Route path="/program/create" element={<CreateProgram />} /> <Route path="/program/:id" element={<ViewProgram />} /> </Route>

Find more information about routing here.

Creating a new feature

This is as easy as creating a new folder in the features directory that holds all the resources for that particular feature.

The directory structure requires that all components and services which are related to a particular feature be kept in a subdirectory of the features directory.

Observe the directory structure for Authentication feature in features/auth

├── features
│   ├── auth
│   │   ├── ProtectedRoute.tsx
│   │   ├── web3Service.tsx

It contains the ProtectedRoute component and web3Service which extends the base API service defined in src/api.ts by endpoint injection.

Defining a new API

Some features require server-side state management which involves keeping the UI in sync with an external data source e.g REST/GraphQL API service, Smart Contract etc. We use RTK Query which is

a powerful data fetching and caching tool. It is designed to simplify common cases for loading data in a web application, eliminating the need to hand-write data fetching & caching logic yourself

All queries and mutations inject endpoints into the base API src/api.ts

import { createApi, fakeBaseQuery } from "@reduxjs/toolkit/query/react" // initialize an empty api service that we'll inject endpoints into later as needed export const api = createApi({ reducerPath: "api", baseQuery: fakeBaseQuery<string>(), endpoints: () => ({}), })

web3Service.tsx

export const web3Api = api.injectEndpoints({ endpoints: (builder) => ({ getWeb3: builder.query<Web3Instance, void>({ queryFn: async () => { ... }, }), }), overrideExisting: false }) export const { useGetWeb3Query } = web3Api

UI components access data and states thus,

const { data, error, refetch, isSuccess, isFetching, isLoading } = useGetWeb3Query()

Learn more about Redux Toolkit and RTK Query.