-
Notifications
You must be signed in to change notification settings - Fork 3
Code Standards
Taylor Snead edited this page Aug 23, 2022
·
2 revisions
- Add comments to all top-level items describing what it is in more detail, why it's separate from other things, why it was written like it is, etc.
- You could also add a comment describing the whole file (e.g. Typescript, Rust). This can provide the scope of that file/module.
- If you are considering adding a new element of change to your PR, the answer is probably to make a separate PR.
- Code is formatted with
prettier
- Encapsulate all code that deals with a
Context
in one file. Never export the context itself, only export a Provider component and one or more hooks exposing context data. - Use components defined in
website/src/components
whenever possible- Otherwise use components from
reakit
if there is one
- Otherwise use components from
- Add types wherever possible (objects, variables, function arguments, etc) and avoid the
any
type unless you really need it - Avoid the
as
operator for typecasting - Avoid unnecessary HTML elements. If you are nesting two or three
div
elements without any siblings, then reconsider your approach. - Always supply an
aria-label
to non-text elements (like icons or icon buttons) - Use the relevant semantic HTML element instead of
div
when possible - React components have
PascalCase
names, while other constants and functions getcamelCase
names - Use abbreviations in names sparingly -- most of the time the full name is easier for others to understand
- Avoid brand/library names in our own code. For example, prefer
graphqlClient
overapolloClient
orurqlClient
. - For React hooks, always check the dependency list to ensure that all other input state is accounted for.
const [x, setX] = useState(0)
useEffect(() => {
doSomething(x)
}, [x]) // <-- make sure x is here because it's used within the hook
- Avoid exceptional returns in React components when possible because it can lead to mistakes with hooks.
// Do this!
if (condition) {
return null
} else {
return (...)
}
// ...instead of this
if (condition) {
return null
}
// ...
return (...)
- Be mindful of how much rendering your hooks require the component to do.
- Use
useMemo
when creating expensive objects during render. - Use primary constants for the default value of
useState
because those values are recomputed every render. You can also douseState(() => initialValue)
to provide a lazy initial state. - Combine multiple
useEffect
calls into one whenever possible
- Use
When creating a new React context to store global state, there are a few guidelines to consider.
- Put the context object in a new file and call it
XContext
where X names the state, along with a provider componentXProvider
and one or more hooks that allow components to consume/affect the state. - Never export
XContext
itself, put all direct usage of it in the same file. - If the context interacts with an external system like cookies, local storage, or a 3rd party API then encapsulate as much direct usage of that system into the provider itself to avoid leaking implementation details.
- Styles are written in
.css.ts
files then imported into.tsx
files - All styles are mobile-first, with desktop styles applied based on media queries. For example:
const myStyle = style({
color: "blue", // blue on mobile
"@media": {
[mediaQueries.medium]: { color: "red" }, // red on tablets and smaller desktop screens
[mediaQueries.large]: { color: "maroon" }, // maroon on larger screens
}
})
- Avoid
vw
andvh
units, especially for desktop styles. Use fixed or percentage sizes instead. - Avoid magic numbers in styles, use values from
src/style/constants
when possible. You can also add reusable constants if one is missing. For example, usevspace
for vertical spacing andhspace
for horizontal spacing instead of values like10px
. - Never write pixel font sizes. Always use
rem
units for that
- Code is formatted with
rustfmt
/cargo fmt
- Avoid using
.unwrap()
onOption<T>
because on failure it causes the program to crash instead of allowing us to handle the error
- Code is formatted with
sqlfluff fix types/queries
in the root folder - Always run
dev-generate-types
before committing SQL changes, and also commit the changes tosqlx-data.json
- Table names are singular nouns, i.e.
word
,document
,edited_collection
- Use all lowercase for everything, including keywords like
select
,where
,join
, etc. - Always specify the type of join you're using. e.g.
inner join
instead of shortcutjoin
- When you use a join, fully specify all column selections by table name. For example, if I use a join to access both
document
andword
tables, never use plainindex_in_document
to refer to that column. Useword.index_in_document
instead, even when there isn't a name conflict between the tables. - Use standard SQL by default and when possible, but dip into Postgres extensions when convenient
- Never ever edit database migrations that are already merged to main and applied on live deployments. We always have to make new migration files for new changes, because postgres skips completed migrations based on the file name and our migration process will fail if an existing migration is edited
- Almost always use an
autouuid
for primary keys. This is a "surrogate" key when we might also have a "natural" key in a separate unique column.
id autouuid primary key,
slug text unique,