Skip to content

Commit 22c7755

Browse files
committed
chore: update frontend contributing guide
1 parent 6b9e1d4 commit 22c7755

File tree

1 file changed

+74
-56
lines changed

1 file changed

+74
-56
lines changed

docs/contributing/frontend.md

Lines changed: 74 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,25 @@ you.
88

99
## Running the UI
1010

11-
You can run the UI and access the dashboard in two ways:
11+
You can run the UI and access the Coder dashboard in two ways:
1212

1313
- Build the UI pointing to an external Coder server:
1414
`CODER_HOST=https://mycoder.com pnpm dev` inside of the `site` folder. This is
1515
helpful when you are building something in the UI and already have the data on
1616
your deployed server.
1717
- Build the entire Coder server + UI locally: `./scripts/develop.sh` in the root
18-
folder. It is useful when you have to contribute with features that are not
19-
deployed yet or when you have to work on both, frontend and backend.
18+
folder. This is useful for contributing to features that are not deployed yet
19+
or that involve both the frontend and backend.
2020

2121
In both cases, you can access the dashboard on `http://localhost:8080`. If you
22-
are running the `./scripts/develop.sh` you can log in using the default
23-
credentials: `admin@coder.com` and `SomeSecurePassword!`.
22+
are running `./scripts/develop.sh` you can log in using the default credentials.
23+
24+
### Default Credentials: `admin@coder.com` and `SomeSecurePassword!`.
2425

2526
## Tech Stack
2627

27-
All our dependencies are described in `site/package.json` but here are the most
28-
important ones:
28+
All our dependencies are described in `site/package.json` but the following are
29+
the most important:
2930

3031
- [React](https://reactjs.org/) as framework
3132
- [Typescript](https://www.typescriptlang.org/) to keep our sanity
@@ -43,8 +44,7 @@ important ones:
4344

4445
## Structure
4546

46-
All the code related to the UI is inside the `site` folder and we defined a few
47-
conventions to help people to navigate through it.
47+
All the code related to the UI resides in the `site` folder.
4848

4949
- **e2e** - End-to-end (E2E) tests
5050
- **src** - Source code
@@ -53,49 +53,51 @@ conventions to help people to navigate through it.
5353
(largely code that has no server-side equivalent)
5454
- **api** - API code as function calls and types
5555
- **queries** - react-query queries and mutations
56-
- **components** - UI components
57-
- **hooks** - Hooks that can be used across the application
56+
- **components** - Generic UI components without Coder specific business logic
57+
- **hooks** - React hooks that can be used across the application
58+
- **modules** - Coder specific UI components
5859
- **pages** - Page components
5960
- **testHelpers** - Helper functions to help with integration tests
61+
- **theme** - configuration and color definitions for the color themes
6062
- **util** - Helper functions that can be used across the application
6163
- **static** - Static UI assets like images, fonts, icons, etc
6264

6365
## Routing
6466

65-
We use [react-router](https://reactrouter.com/en/main) as our routing engine and
66-
adding a new route is very easy. If the new route needs to be authenticated, put
67-
it under the `<RequireAuth>` route and if it needs to live inside of the
68-
dashboard, put it under the `<DashboardLayout>` route.
67+
We use [react-router](https://reactrouter.com/en/main) as our routing engine.
6968

70-
The `RequireAuth` component handles all the authentication logic for the routes
71-
and the `DashboardLayout` wraps the route adding a navbar and passing down
72-
common dashboard data.
69+
- Authenticated routes - routes needing authentication should be placed inside
70+
the `<RequireAuth>` route. The `RequireAuth` component handles all the
71+
authentication logic for the routes.
72+
- Dashboard routes - routes that live in the dashboard should be placed under
73+
the `<DashboardLayout>` route. The `DashboardLayout` adds a navbar and passes
74+
down common dashboard data.
7375

7476
## Pages
7577

7678
Pages are the top-level components of the app. The page component lives under
77-
the `src/pages` folder and each page should have its own folder so we can better
78-
group the views, tests, utility functions and so on. We use a structure where
79-
the page component is responsible for fetching all the data and passing it down
80-
to the view. We explain this decision a bit better in the next section.
79+
the `src/pages` folder and each page should have its own folder to better group
80+
the views, tests, utility functions and so on. The code is structured so that a
81+
page component is responsible for fetching all the data and passing it down to
82+
the view. We explain this decision a bit better in the next section.
8183

8284
> ℹ️ Code that is only related to the page should live inside of the page folder
8385
> but if at some point it is used in other pages or components, you should
84-
> consider moving it to the `src` level in the `utils`, `hooks` or `components`
85-
> folder.
86+
> consider moving it to the `src` level in the `utils`, `hooks`, `components`,
87+
> or `modules` folder.
8688
8789
### States
8890

8991
A page usually has at least three states: **loading**, **ready**/**success**,
9092
and **error**, so always remember to handle these scenarios while you are coding
91-
a page. We also encourage you to add visual testing for these three states using
92-
a `*.stories.ts` file.
93+
a page. Visual testing is expected for these three states using a `*.stories.ts`
94+
file.
9395

9496
## Fetching data
9597

9698
We use [TanStack Query v4](https://tanstack.com/query/v4/docs/react/quick-start)
9799
to fetch data from the API. The queries and mutation should be placed inside of
98-
the api/queries folder when it is possible.
100+
the api/queries folder.
99101

100102
### Where to fetch data
101103

@@ -141,12 +143,14 @@ export const WithQuota: Story = {
141143

142144
### API
143145

144-
We are using [axios](https://github.com/axios/axios) as our fetching library and
145-
writing the API functions in the `site/src/api/api.ts` files. We also have
146-
auto-generated types from our Go server on `site/src/api/typesGenerated.ts`.
147-
Usually, every endpoint has its own ` Request` and `Response` types, but
148-
sometimes you need to pass extra parameters to make the call, like in the
149-
example below:
146+
Our project utilizes [axios](https://github.com/axios/axios) as the HTTP client
147+
for making API requests. The API functions are centralized in
148+
`site/src/api/api.ts`. We leverage auto-generated TypeScript types derived from
149+
our Go server, which are located in `site/src/api/typesGenerated.ts`.
150+
151+
Typically, each API endpoint corresponds to its own `Request` and `Response`
152+
types. However, some endpoints require additional parameters for successful
153+
execution. Here's an illustrative example:"
150154

151155
```ts
152156
export const getAgentListeningPorts = async (
@@ -159,8 +163,8 @@ export const getAgentListeningPorts = async (
159163
};
160164
```
161165

162-
Sometimes, a frontend operation can have multiple API calls, so it is okay to
163-
wrap it as a single function.
166+
Sometimes, a frontend operation can have multiple API calls which can be wrapped
167+
as a single function.
164168

165169
```ts
166170
export const updateWorkspaceVersion = async (
@@ -171,10 +175,13 @@ export const updateWorkspaceVersion = async (
171175
};
172176
```
173177

174-
If you need more granular errors or control, you may should consider keep them
175-
separated and use XState for that.
178+
## Components and Modules
179+
180+
Components should be atomic, generic and should not describe any specific
181+
business logic. Modules are similar to components except that they can be more
182+
complex and they do contain business logic specific to the product.
176183

177-
## Components
184+
### MUI
178185

179186
The codebase is currently using MUI v5. Please see the
180187
[official documentation](https://mui.com/material-ui/getting-started/). In
@@ -184,8 +191,9 @@ out of the box.
184191

185192
### Structure
186193

187-
Each component gets its own folder. Make sure you add a test and Storybook
188-
stories for the component as well. By keeping these tidy, the codebase will
194+
Each component and module gets its own folder. Module folders may group multiple
195+
files in a hierarchical structure. Storybook stories and component tests using
196+
Storybook interactions are required. By keeping these tidy, the codebase will
189197
remain easy to navigate, healthy and maintainable for all contributors.
190198

191199
### Accessibility
@@ -221,13 +229,30 @@ import { visuallyHidden } from "@mui/utils";
221229
</Button>;
222230
```
223231

224-
### Should I create a new component?
232+
### Should I create a new component or module?
233+
234+
Components could technically be used in any codebase and still feel at home. A
235+
module would only make sense in the Coder codebase.
236+
237+
- Component
238+
- Simple
239+
- Atomic, used in multiple places
240+
- Good Examples: `Badge`, `Form`, `Timeline`
241+
- Module
242+
- Simple or Complex
243+
- Used in multiple places
244+
- Good Examples: `Provisioner`, `DashboardLayout`, `DeploymentBanner`
245+
246+
Do not assume existing components and modules have been categorized correctly.
225247

226-
As with most things in the world, it depends. If you are creating a new
227-
component to encapsulate some UI abstraction like `UsersTable` it is ok but you
228-
should always try to use the base components that are provided by the library or
229-
from the codebase. It's recommended that you always do a quick search before
230-
creating a custom primitive component like dialogs, popovers, buttons, etc.
248+
## Styling
249+
250+
We use [Emotion](https://emotion.sh/) to handle css styles.
251+
252+
## Forms
253+
254+
We use [Formik](https://formik.org/docs) for forms along with
255+
[Yup](https://github.com/jquense/yup) for schema definition and validation.
231256

232257
## Testing
233258

@@ -293,10 +318,9 @@ that:
293318

294319
### Tests getting too slow
295320

296-
A few times you can notice tests can take a very long time to get done.
297-
Sometimes it is because the test itself is complex and runs a lot of stuff, and
298-
sometimes it is because of how we are querying things. In the next section, we
299-
are going to talk more about them.
321+
You may have observed that certain tests in our suite can be notably
322+
time-consuming. Sometimes it is because the test itself is complex and sometimes
323+
it is because of how the test is querying elements.
300324

301325
#### Using `ByRole` queries
302326

@@ -326,12 +350,6 @@ const form = screen.getByTestId("form");
326350
user.click(within(form).getByRole("button"));
327351
```
328352

329-
#### `jest.spyOn` with the API is not working
330-
331-
For some unknown reason, we figured out the `jest.spyOn` is not able to mock the
332-
API function when they are passed directly into the services XState machine
333-
configuration.
334-
335353
❌ Does not work
336354

337355
```ts

0 commit comments

Comments
 (0)