Project

General

Profile

Actions

Manual ICO Web

ICO Web — Project Migration Document

Note: This project was originally scaffolded using Vite (create-vite with the React/TypeScript template).


1. Stack & Prerequisites

Tech Stack

Category Technology Version
Language TypeScript ^5.6.3
Framework React ^18.3.1
Build Tool Vite ^6.3.5
Styling Tailwind CSS ^3.4.11
State Management Redux Toolkit ^2.2.7
Routing React Router DOM ^6.26.2
HTTP Client Axios ^1.7.7
Form React Hook Form ^7.53.0
Form Validation Zod ^3.23.8
i18n i18next ^25.7.4
Testing Jest ^29.7.0
Linting ESLint ^8.56.0
Container Docker (multi-stage)
Web Server Nginx Alpine

Prerequisites to Install

Tool Version
Node.js LTS (v20/v22)
Yarn Berry (v2+)
Docker 20+
Git 2.x

Verify Installations

node -v       # v20.x or v22.x
yarn -v       # 4.x (Berry)
docker -v     # Docker version 20+
git --version # git version 2.x

3. Package Manager

This project uses Yarn Berry (v2+) with classic node_modules linker.

Configuration

File: .yarnrc.yml

nodeLinker: node-modules

Common Commands

# Install all dependencies
yarn install

# Add a new dependency
yarn add <package-name>

# Add a dev dependency
yarn add -D <package-name>

# Remove a dependency
yarn remove <package-name>

Scripts (from package.json)

yarn dev                    # Start Vite dev server (http://localhost:5173)
yarn build                  # TypeScript check + production build → /dist
yarn test                   # Run Jest tests

4. Project Architecture

4.1 Routing (React Router DOM v6)

Entry: src/app/AppRoutes.tsx

All routes are defined in a single file using <Routes> and <Route>. The app wraps routes in a <HelmetLayout> for SEO.

Route groups:

Group Path Pattern Pages
Landing / Landing page, investment campaign
Auth /login, /reset-* Login, reset password, Google Authenticator
Sign Up (Thai) /signup/* Type select → corporate/individual → basicinfo → suite test → OTP → ID card → verification
Sign Up (Foreign) /foreign/* Fullname → CRS → basicinfo → suite test → doc upload → OTP
Re-KYC /rekyc/* Re-KYC flow, FATCA, suite test, ID card
Portfolio /portfolio Portfolio management
Marketplace /marketplace Marketplace + TOTP confirmation
Order & Trade /order-trade Order trade + high net worth verification
Subscription /subscription Subscription page
Asset Details /asset-details/* ICO details, white paper, filing
Fraction Exchange /fraction-exchange Fraction exchange
Static Pages /contact-us, etc. Contact, policy, complaint, about us, terms
Error * 404 page

4.2 State Management (Redux Toolkit)

Store: src/redux/store.tsx

Redux Store
└── redux/
   ├── store
   └── slice/


4.3 API Layer (Axios)

File: src/api/axios.tsx

The project creates multiple Axios instances, all with baseURL: window.origin (same-origin proxy):

Instance Purpose Auth
default export Basic API calls Cookies only
axiosCheckToken Authenticated calls with refresh Auto-refresh
axiosMultipart File uploads (multipart/form-data) Cookies
axiosNoAuth Public API calls None

Token refresh flow:

  1. Request interceptor checks if refresh token is expired → redirect to login if so
  2. If access token is expired, calls POST /api/v1/authen/customers/refresh
  3. Queues failed requests in failedQueue while refresh is in-flight
  4. On success, retries all queued requests with new token
  5. In dev mode (isDev()), token checks are skipped entirely

Helper: getCustomAxios() returns axiosCheckToken if access token exists, otherwise axiosNoAuth.


4.4 Form Handling

Library Purpose
React Hook Form Form state, validation, submission
Zod Schema-based validation
@hookform/resolvers Connects Zod schemas to RHF

4.5 Internationalization (i18n)

File: src/i18n/config.ts

Setting Value
Library i18next + react-i18next
Languages en (English), th (Thai)
Fallback en
Detection localStorage → navigator → htmlTag
Storage key i18nextLng (localStorage)
Translation files public/locales/{lng}/{ns}.json
Namespaces common, footer, navbar, landing, signup, portfolio
Default ns common

4.6 Styling

Tool Config File Notes
Tailwind CSS tailwind.config.js Custom font: Anuphan, custom colors/screens
CSS src/index.css Global styles
PostCSS postcss.config.js Tailwind + Autoprefixer plugins
tailwind-merge via src/lib/utils.ts cn() helper for conditional classes

4.7 Key Libraries

Library Purpose
crypto-js Encryption/decryption (with pepper keys)
jwt-decode Decode JWT tokens (expiry check)
js-cookie Cookie management (access/refresh token)
dayjs Date/time formatting (with UTC/timezone)
lodash Utility functions
react-toastify Toast notifications
react-helmet-async SEO meta tags
apexcharts Interactive charts
chart.js Canvas-based charts
echarts-for-react ECharts wrapper
@tanstack/react-table Headless table
swiper Carousel/slider
leaflet Map component
filepond File upload widget
react-webcam Webcam capture (ID card/liveness)

5. Environment Variables

5.1 Variable List

All variables use the VITE_ prefix (required by Vite to expose to client-side code):

Variable Required Description
VITE_BASE_URL Yes Backend API base URL
VITE_REKOGNITOR_URL Yes AWS Rekognition / face liveness service URL
VITE_STATIC_URL Yes Static file server URL (images, documents)
VITE_BUCKET_URL Yes S3 bucket URL for uploads/downloads
VITE_PEPER Yes Encryption pepper (used with crypto-js)
VITE_BACK_REGISTER Yes Backend registration endpoint pepper
VITE_CID_PEPER Yes CID (citizen ID) encryption pepper
VITE_ENVIRONMENT Yes Environment name: dev, uat, production

5.2 Environment Variable Injection (CI/CD Pipeline)

Workflow process:

  1. Build Phase: The React app is built using Vite. During this build use config paceholder VITE_* (e.g., the string "VITE_BASE_URL" instead of a real URL).
  2. Docker Phase: The Dockerfile packages the built static files and an entrypoint.sh script into an Nginx image.
  3. Environment Fetching: Before the application spins up in the target AWS environment, the real environment values are fetched from an .env file securely stored in an AWS S3 bucket.
  4. Runtime Injection: When the Docker container starts, it executes entrypoint.sh. This shell script uses sed to find all the JS bundles that contain the text placeholders and replaces them with the real environment values fetched from S3.

This pattern allows the same Docker image to be promoted across Dev, UAT, and Prod environments just by fetching a different .env file from S3

5.3 Config File

File: src/config/config.ts

This file maps environment variables to exported constants used throughout the app:

Constant Source / Env Var
BASE_URL VITE_BASE_URL
BASE_REKOGNITOR_URL VITE_REKOGNITOR_URL
BASE_STATIC_URL VITE_STATIC_URL
BASE_BUCKET_URL VITE_BUCKET_URL
PEPER VITE_PEPER
PEPER_BACK_REGISTER VITE_BACK_REGISTER
PEPER_CID VITE_CID_PEPER
ENVIRONMENT VITE_ENVIRONMENT

Updated by prin methirattanasophon about 1 month ago · 1 revisions