Skip to content

Commit 40688e4

Browse files
authored
chore: improve content of frontend contributing guide (coder#14619)
* chore: update frontend contributing guide * chore: cleanup language * chore: cleanup * chore: updates for comments
1 parent 90b29df commit 40688e4

File tree

1 file changed

+103
-81
lines changed

1 file changed

+103
-81
lines changed

docs/contributing/frontend.md

Lines changed: 103 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,38 @@
11
# Frontend
22

3-
This is a guide to help the Coder community and also Coder members contribute to
4-
our UI. It is ongoing work but we hope it provides some useful information to
5-
get started. If you have any questions or need help, please send us a message on
6-
our [Discord server](https://discord.com/invite/coder). We'll be happy to help
3+
Welcome to the guide for contributing to the Coder frontend. Whether you’re part
4+
of the community or a Coder team member, this documentation will help you get
5+
started.
6+
7+
If you have any questions, feel free to reach out on our
8+
[Discord server](https://discord.com/invite/coder), and we’ll be happy to assist
79
you.
810

911
## Running the UI
1012

11-
You can run the UI and access the dashboard in two ways:
13+
You can run the UI and access the Coder dashboard in two ways:
14+
15+
1. Build the UI pointing to an external Coder server:
16+
`CODER_HOST=https://mycoder.com pnpm dev` inside of the `site` folder. This
17+
is helpful when you are building something in the UI and already have the
18+
data on your deployed server.
19+
2. Build the entire Coder server + UI locally: `./scripts/develop.sh` in the
20+
root folder. This is useful for contributing to features that are not
21+
deployed yet or that involve both the frontend and backend.
1222

13-
- Build the UI pointing to an external Coder server:
14-
`CODER_HOST=https://mycoder.com pnpm dev` inside of the `site` folder. This is
15-
helpful when you are building something in the UI and already have the data on
16-
your deployed server.
17-
- 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.
23+
In both cases, you can access the dashboard on `http://localhost:8080`. If using
24+
`./scripts/develop.sh` you can log in with the default credentials.
2025

21-
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!`.
26+
> [!TIP]
27+
>
28+
> **Default Credentials:** `admin@coder.com` and `SomeSecurePassword!`.
2429
25-
## Tech Stack
30+
## Tech Stack Overview
2631

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

30-
- [React](https://reactjs.org/) as framework
35+
- [React](https://reactjs.org/) for the UI framework
3136
- [Typescript](https://www.typescriptlang.org/) to keep our sanity
3237
- [Vite](https://vitejs.dev/) to build the project
3338
- [Material V5](https://mui.com/material-ui/getting-started/) for UI components
@@ -39,63 +44,62 @@ important ones:
3944
- [Jest](https://jestjs.io/) for integration testing
4045
- [Storybook](https://storybook.js.org/) and
4146
[Chromatic](https://www.chromatic.com/) for visual testing
42-
- [PNPM](https://pnpm.io/) as package manager
47+
- [PNPM](https://pnpm.io/) as the package manager
4348

4449
## Structure
4550

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.
51+
All UI-related code is in the `site` folder. Key directories include:
4852

4953
- **e2e** - End-to-end (E2E) tests
5054
- **src** - Source code
5155
- **mocks** - [Manual mocks](https://jestjs.io/docs/manual-mocks) used by Jest
5256
- **@types** - Custom types for dependencies that don't have defined types
5357
(largely code that has no server-side equivalent)
54-
- **api** - API code as function calls and types
58+
- **api** - API function calls and types
5559
- **queries** - react-query queries and mutations
56-
- **components** - UI components
57-
- **hooks** - Hooks that can be used across the application
58-
- **pages** - Page components
59-
- **testHelpers** - Helper functions to help with integration tests
60+
- **components** - Reusable UI components without Coder specific business
61+
logic
62+
- **hooks** - Custom React hooks
63+
- **modules** - Coder-specific UI components
64+
- **pages** - Page-level components
65+
- **testHelpers** - Helper functions for integration testing
66+
- **theme** - theme configuration and color definitions
6067
- **util** - Helper functions that can be used across the application
61-
- **static** - Static UI assets like images, fonts, icons, etc
68+
- **static** - Static assets like images, fonts, icons, etc
6269

6370
## Routing
6471

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.
72+
We use [react-router](https://reactrouter.com/en/main) as our routing engine.
6973

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.
74+
- Authenticated routes - Place routes requiring authentication inside the
75+
`<RequireAuth>` route. The `RequireAuth` component handles all the
76+
authentication logic for the routes.
77+
- Dashboard routes - routes that live in the dashboard should be placed under
78+
the `<DashboardLayout>` route. The `DashboardLayout` adds a navbar and passes
79+
down common dashboard data.
7380

7481
## Pages
7582

76-
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.
83+
Page components are the top-level components of the app and reside in the
84+
`src/pages` folder. Each page should have its own folder to group relevant
85+
views, tests, and utility functions. The page component fetches necessary data
86+
and passes to the view. We explain this decision a bit better in the next
87+
section which talks about where to fetch data.
8188

82-
> ℹ️ Code that is only related to the page should live inside of the page folder
83-
> 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.
89+
> ℹ️ If code within a page becomes reusable across other parts of the app,
90+
> consider moving it to `src/utils`, `hooks`, `components`, or `modules`.
8691
87-
### States
92+
### Handling States
8893

89-
A page usually has at least three states: **loading**, **ready**/**success**,
90-
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.
94+
A page typically has three states: **loading**, **ready**/**success**, and
95+
**error**. Ensure you manage these states when developing pages. Use visual
96+
tests for these states with `*.stories.ts` files.
9397

94-
## Fetching data
98+
## Data Fetching
9599

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

100104
### Where to fetch data
101105

@@ -141,12 +145,14 @@ export const WithQuota: Story = {
141145

142146
### API
143147

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:
148+
Our project uses [axios](https://github.com/axios/axios) as the HTTP client for
149+
making API requests. The API functions are centralized in `site/src/api/api.ts`.
150+
Auto-generated TypeScript types derived from our Go server are located in
151+
`site/src/api/typesGenerated.ts`.
152+
153+
Typically, each API endpoint corresponds to its own `Request` and `Response`
154+
types. However, some endpoints require additional parameters for successful
155+
execution. Here's an illustrative example:"
150156

151157
```ts
152158
export const getAgentListeningPorts = async (
@@ -159,8 +165,8 @@ export const getAgentListeningPorts = async (
159165
};
160166
```
161167

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

165171
```ts
166172
export const updateWorkspaceVersion = async (
@@ -171,10 +177,13 @@ export const updateWorkspaceVersion = async (
171177
};
172178
```
173179

174-
If you need more granular errors or control, you may should consider keep them
175-
separated and use XState for that.
180+
## Components and Modules
176181

177-
## Components
182+
Components should be atomic, reusable and free of business logic. Modules are
183+
similar to components except that they can be more complex and can contain
184+
business logic specific to the product.
185+
186+
### MUI
178187

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

185194
### Structure
186195

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
196+
Each component and module gets its own folder. Module folders may group multiple
197+
files in a hierarchical structure. Storybook stories and component tests using
198+
Storybook interactions are required. By keeping these tidy, the codebase will
189199
remain easy to navigate, healthy and maintainable for all contributors.
190200

191201
### Accessibility
@@ -221,13 +231,32 @@ import { visuallyHidden } from "@mui/utils";
221231
</Button>;
222232
```
223233

224-
### Should I create a new component?
234+
### Should I create a new component or module?
235+
236+
Components could technically be used in any codebase and still feel at home. A
237+
module would only make sense in the Coder codebase.
238+
239+
- Component
240+
- Simple
241+
- Atomic, used in multiple places
242+
- Generic, would be useful as a component outside of the Coder product
243+
- Good Examples: `Badge`, `Form`, `Timeline`
244+
- Module
245+
- Simple or Complex
246+
- Used in multiple places
247+
- Good Examples: `Provisioner`, `DashboardLayout`, `DeploymentBanner`
225248

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.
249+
Our codebase has some legacy components that are being updated to follow these
250+
new conventions, but all new components should follow these guidelines.
251+
252+
## Styling
253+
254+
We use [Emotion](https://emotion.sh/) to handle css styles.
255+
256+
## Forms
257+
258+
We use [Formik](https://formik.org/docs) for forms along with
259+
[Yup](https://github.com/jquense/yup) for schema definition and validation.
231260

232261
## Testing
233262

@@ -293,10 +322,9 @@ that:
293322

294323
### Tests getting too slow
295324

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.
325+
You may have observed that certain tests in our suite can be notably
326+
time-consuming. Sometimes it is because the test itself is complex and sometimes
327+
it is because of how the test is querying elements.
300328

301329
#### Using `ByRole` queries
302330

@@ -326,12 +354,6 @@ const form = screen.getByTestId("form");
326354
user.click(within(form).getByRole("button"));
327355
```
328356

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-
335357
❌ Does not work
336358

337359
```ts

0 commit comments

Comments
 (0)