Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
Yangshun Tay edited this pageSep 19, 2025 ·27 revisions

Getting Started

Install Yarn

InstallYarn as the package manager. All npm commands should be usingyarn and notnpm. After installing Yarn, runyarn once at the root of the repository.

yarn

Set up the.env file

Make a copy ofapps/portal/.env.example toapps/portal/.env. This is the environment config that is used by the TIH Portal Next.js app.

cp apps/portal/.env.example apps/portal/.env
  • DATABASE_URL: You will need to have a PostgreSQL database already running and add in the password. You can useSupabase to spin up a managed PostgreSQL database quickly if you don't want to bother with setting up local databases.
  • GITHUB_CLIENT_SECRET: Ping @yangshun for the value.

Run the app locally

At the root of the repository:

  • yarn dev: Runs justapp/portal. Most of the time you'll only need this. Openhttp://localhost:3000 to access the app.
  • yarn dev:ui: Runs justapp/storybook. Runs the local Storybook environment.

Tech Stack

AreaChoiceWhat is it
MonorepoTurborepoHigh-performance build system that allows you to break a repo into multiple smaller packages
LanguageTypeScriptStatically typed JavaScript
ViewReactMost popular UI library
App FrameworkNext.jsReact meta framework that has multiple ways of rendering
StylingTailwind CSSRapidly build modern websites without ever leaving your HTML
Data FetchingReact QueryA pretty sophisticated data fetching library
AuthNextAuth.jsAuthentication for Next.js, supports many OAuth options
Type SafetytRPCEnd-to-end typesafe APIs made easy
ORMPrismaNext-generation Node.js and TypeScript ORM
DatabasePostgreSQLPopular open source relational database

Development

Source Control

  • main is release branch and should remain stable at all times.
  • Create feature branches for your in-progress features and using the format<username>/my-feature (doesn't have to be your GitHub username, just use something identifiable and be consistent about it).
  • Before merging/pushing tomain, ensure that runningyarn ci in the root directory doesn't show any errors.
  • We use a variation ofConventional Commits specification for commit messages:
  • Use[feat] my commit message instead offeat: my commit message.
  • Prefix the commit message with the project. E.g.[resumes][feat] foobar,[offers][fix] foobar,[questions][refactor] foobar.
  • Rebase and squash commits into a single commit before merging intomain. We don't wantmain to contain any merge commits. A linear Git history is much easier to look at.
  • Delete your branch after merging intomain.

Code Editor

Directory Structure

The repository is structured as aTurborepo monorepo:

.├── package.json# Global dependencies. You shouldn't need to modify this.├── apps│   ├── portal# TIH portal│   ├── storybook# Storybook to view and try UI components│   └── website# Existing website on Docusaurus. Ignore└── packages    ├── eslint-config-tih# ESLint configuration    ├── tsconfig# TypeScript configuration    └── ui# UI components

You should spend most of the time building within/apps/portal. New dependencies should be installed within/apps/portal/package.json.

Front End

Next.js

  • For most imports, use~/ which is an alias for theapps/portal/src instead of relative paths.
  • We're using the newnewNextLinkBehavior: true flag, so there's no need for<a> within<Link>.
  • SSR pages as much as possible (viagetServerSideProps()), rather than fetching data on the client side for better SEO.
  • Work within your designated directories:
    • Resumes:src/components/resumes andsrc/pages/resumes
    • Offers:src/components/offers andsrc/pages/offers
    • Questions:src/components/questions andsrc/pages/questions

React

  • Props should beReadonly.
  • Props should be sorted alphabetically.
  • Props should be destructured in the component function declaration.

Styling

  • Use components as much as possible, rather than Tailwind classes.
  • Color guidelines:
    • Use semantic colors where available:
      • Useprimary instead ofpurple/indigo (e.g.text-primary-500 overtext-indigo-500. This is so that we can change all the colors anytime by changing the Tailwind config.
      • Other available colors:
        • danger (red)
        • success (green)
        • warning (yellow)
        • info (blue)
    • Useslate instead ofgray as that's our preferred shade of gray.

Data Fetching

React Query is a client side state management library to help you manage remote state (data fetched from the server). With React Query (and tRPC), you can do data fetching in a declarative and typesafe manner.

Form Library

  • Form library TBD. Possiblyreact-hook-form.
  • Don't add state for forms unless necessary (e.g. front end validation).

Back End

Data Model: Prisma

We usePrisma, which is an ORM for JavaScript/TypeScript applications. Make sure you have thePrisma VS Code extension installed, which gives you autocompletion and formatting of the.prisma files.

  • Model
    • Namespace/Prefix your models per project (e.g.ResumesSomething,OffersSomething,QuestionsSomething).
    • enum values should be written using UPPER_SNAKE_CASE.
  • Fields
    • Use camelCase for fields inschema.prisma. If you see some snake_case fields inAccount, that's because of the requirements of NextAuth.js, and they are exceptions.
    • Usecuid() for ids, don't useautoincrement(). We don't want to reveal how many rows there are in a table.
    • Look around and see the existing schema fields and try to be consistent about field naming, even across projects.

Prisma Studio

In case you want to have an admin view of your database, runyarn prisma studio which will run an admin web app onhttp://localhost:5555.

Server API calls: tRPC

We're usingtRPC v9. Check that you're looking at the right version of the docs because v10 is quite different.

  • userIds for creator fields should always come from the session, not from a parameter.
  • Prisma doesn’t have ACL (access control list), so we need to manually implement permissions in tRPC routing code.
  • Handle errors properly. Refer toerror docs.

Database

Set up your own local PostgreSQL database and update theDATABASE_URL field within the.env file.

Setting up

Runningprisma migrate dev inapps/portal updates the database specified in.env with the latest changes. You will need to run the command if it's your first time setting up the database and every timeschema.prisma changes.

Changing schema

  1. After you changeschema.prisma, runprisma migrate dev inapps/portal. Prisma will generate migration files for you and make the changes to your local database.
  2. Ping @yangshun for now to productionize any changes.

Auth

We're usingNextAuth.js which has integrations with many auth providers for Next.js and is super handy. Most of the time you won't need to mess with authentication since it's already done. But if you need to, here'sNextAuth.js' official demo site and thesource code on GitHub.

Google Analytics

Setting Up

  1. Configure your product's Google Analytics 4 (GA4) measurement ID in your product config.
  2. Note that GA logging is disabled during development by default. If you want to test the logging during development, comment out theprocess.env.NODE_ENV === 'development' checks inGoogleAnalytics.tsx.

Logging Events

import{useGoogleAnalytics}from'~/components/global/GoogleAnalytics';functionMyComponent(){const{ event}=useGoogleAnalytics();return<div><buttononClick={()=>{// Reference: https://developers.google.com/analytics/devguides/collection/gtagjs/eventsevent({// Prefix with your action strings with your product name// because eventually we'll combine all the events into measurement ID.action:'offers.button_click',category:'engagement',label:'Click Me',});}}>      Click Me</button></div>}

[8]ページ先頭

©2009-2025 Movatter.jp