5.2 KiB
Review every point below carefully for files to ensure they follow consistent code style and best practices.
-
Every single function must accept a single object parameter and destructure it in the signature (for readability and future extensibility), if there's 1 or more values. This applies to all functions, not just react components. Even zustand stores. exception: tiny one-liner callbacks (e.g.
array.find(x => ...),map,filter,sort) do not need destructuring if it hurts readability or adds noise. -
No
anyreferences. -
JSX is clean; No comments in there explaining what each part does. Must extract JSX into sub-components (always placed below the main component). A part only needs to be extracted if it's either used in multiple places of the file OR is complex enough to be worth extracting. If a component is used acrosss multiple files, it should be extracted to a separate file.
-
General interfaces must be placed in the
typesfolder. Example:src/components/timeline/index.tsxdefining aTimelineTrackinterface is wrong and should be moved tosrc/types/timeline.ts. -
No AI comments — only human comments. Example of AI comments: explaining too much, code is readable without the comment, changelog-style comments, using more words than necessary, etc.
-
All comments must be all lowercase.
-
JSX: Use
gap-2instead ofmb-2ormt-2for consistent spacing. -
Code is scannable. Use variables and helper functions to make intent clear at a glance. Complex code should be clean.
-
Separation of concerns: Each file should have one single purpose/responsibility. Example:
src/components/timeline/index.tsxshould not define a function to validate element track compatibility. That's a separate concern and belongs in a separate file.src/lib/timeline-utils.tsshould not declare a TRACK_COLORS constant. That belongs in src/constants. Think carefully about what belongs in what file. -
Files with react components must use this order for functions: main function (top) -> sub-components (below).
-
Use zustand correctly. React component should never use
someStore.getState(). Instead, use theuseSomeStorehook. -
Business logic is in
src/libfolder. Example: zustand store has a method to remove a bookmark, the method should be a wrapper of a function insrc/lib/that handles the actual logic. -
Booleans must be named like
isSomethingorhasSomethingorshouldSomething. NotsomethingorsomethingIs. -
No text in docs or UI ever uses title case. Example:
Hello Worldis wrong. It should beHello world. -
Use
size-10instead ofh-10 w-10when the width and height are the same. -
When using
size-on an SVG (lucide, react-icons, @opencut/ui/icons, etc.) inside of a (not ), make sure to use the!modifier to ensure the size is applied correctly. This is becuase the component has a default size ofsize-4that can only be overridden with the!modifier. That also means, don't do!size-4since that's the default size.
- Example:
<Button>
<PlusIcon className="!size-6" /> // This is correct ✅
<PlusIcon className="size-6" /> // This is wrong ❌
<PlusIcon className="!size-4" /> // This is wrong ❌
<span>Add</span>
</Button>
-
For components that need to subscribe to data from the editor api (
src/core,src/managers), use theuseEditorhook. -
In react components: store/manager methods should not be passed as props to sub-components. If a sub-component can access the same methods, it should do so. Example:
import { useTimelineStore } from "@/stores/timeline-store"; // ❌ Do NOT do this: function ParentComponent() { const { selectedElements } = useTimelineStore(); return <ChildComponent selectedElements={selectedElements} />; } function ChildComponent({ selectedElements }) {} // ✅ Do this: function ParentComponent() { return <ChildComponent />; } function ChildComponent() { const { selectedElements } = useTimelineStore(); }
19. Components render UI. Domain logic (data transformations, business rules, state mutations) lives in hooks, utilities, or managers. Simple interaction logic (gesture detection, modifier keys) can stay in components if not too many lines of code/complex.
19. Readability matters more than short names in the age of AI coding. Do not shorten names for the sake of "typing less". Nobody is typing code these days. AI agents are. Hence, clarity and readability are the most important things. Example: "element" is better than "el".
# Functions
- Next.js page components should use the keyword `export default function`
- Main react component should use the keyword `export function`
- Sub-components should use the keyword `function`
- Utility functions should use the keyword `function`
- Functions inside of react components should use the keyword `const`
In other words: use common sense and good judgement. Don't be lazy. Consider every decision to be like gold: extremely important and valuable. Every decision, every edit must be carefully considered. Everything matters. We want to scale this project massively. And every line of code contributes to that.