-
-
Notifications
You must be signed in to change notification settings - Fork 14.8k
Home
Install Yarn as the package manager. All npm commands should be using yarn
and not npm
. After installing Yarn, run yarn
once at the root of the repository.
yarn
Make a copy of apps/portal/.env.example
to apps/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 use Supabase 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.
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.
Area | Choice | What is it |
---|---|---|
Monorepo | Turborepo | High-performance build system that allows you to break a repo into multiple smaller packages |
Language | TypeScript | Statically typed JavaScript |
View | React | Most popular UI library |
App Framework | Next.js | React meta framework that has multiple ways of rendering |
Styling | Tailwind CSS | Rapidly build modern websites without ever leaving your HTML |
Data Fetching | React Query | A pretty sophisticated data fetching library |
Auth | NextAuth.js | Authentication for Next.js, supports many OAuth options |
Type Safety | tRPC | End-to-end typesafe APIs made easy |
ORM | Prisma | Next-generation Node.js and TypeScript ORM |
Database | PostgreSQL | Popular open source relational database |
-
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 to
main
, ensure that runningyarn ci
in the root directory doesn't show any errors. - We use a variation of Conventional 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 into
main
. We don't wantmain
to contain any merge commits. A linear Git history is much easier to look at. - Delete your branch after merging into
main
.
- VS Code is the recommended IDE due to it's superb support for TypeScript.
- Install the following extensions for VS Code, or find the equivalents for your IDE:
- Use Workspace settings (in
.vscode/settings.json
(as the source of truth for your VS Code settings for this project.
The repository is structured as a Turborepo 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
.
- For most imports, use
~/
which is an alias for theapps/portal/src
instead of relative paths. - We're using the new
newNextLinkBehavior: true
flag, so there's no need for<a>
within<Link>
. - SSR pages as much as possible (via
getServerSideProps()
), 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
- Resumes:
-
Props
should beReadonly
. -
Props
should be sorted alphabetically. -
Props
should be destructured in the component function declaration.
- Use components as much as possible, rather than Tailwind classes.
- Color guidelines:
- Use semantic colors where available:
- Use
primary
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)
-
- Use
- Use
slate
instead ofgray
as that's our preferred shade of gray.
- Use semantic colors where available:
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 TBD. Possibly react-hook-form.
- Don't add state for forms unless necessary (e.g. front end validation).
We use Prisma, which is an ORM for JavaScript/TypeScript applications. Make sure you have the Prisma 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.
- Namespace/Prefix your models per project (e.g.
- Fields
- Use camelCase for fields in
schema.prisma
. If you see some snake_case fields inAccount
, that's because of the requirements of NextAuth.js, and they are exceptions. - Use
cuid()
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.
- Use camelCase for fields in
In case you want to have an admin view of your database, run yarn prisma studio
which will run an admin web app on http://localhost:5555.
We're using tRPC v9. Check that you're looking at the right version of the docs because v10 is quite different.
-
userId
s 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 to error docs.
Set up your own local PostgreSQL database and update the DATABASE_URL
field within the .env
file.
Running prisma migrate dev
in apps/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 time schema.prisma
changes.
- After you change
schema.prisma
, runprisma migrate dev
inapps/portal
. Prisma will generate migration files for you and make the changes to your local database. - Ping @yangshun for now to productionize any changes.
We're using NextAuth.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's NextAuth.js' official demo site and the source code on GitHub.
- Configure your product's Google Analytics 4 (GA4) measurement ID in your product config.
- Note that GA logging is disabled during development by default. If you want to test the logging during development, comment out the
process.env.NODE_ENV === 'development'
checks inGoogleAnalytics.tsx
.
import { useGoogleAnalytics } from '~/components/global/GoogleAnalytics';
function MyComponent() {
const { event } = useGoogleAnalytics();
return <div>
<button onClick={() => {
// Reference: https://developers.google.com/analytics/devguides/collection/gtagjs/events
event({
// 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>
}