|
| 1 | +# Transloadit Repository Guide |
| 2 | + |
| 3 | +## coding style |
| 4 | + |
| 5 | +Coding style: |
| 6 | + |
| 7 | +- Favor `async run() {` over `run = async () => {` inside ES6 classes |
| 8 | +- Favor `if (!(err instanceof Error)) { throw new Error(`Was thrown a non-error: ${err}`) }` inside |
| 9 | + `catch` blocks to ensure the `error` is always an instance of `Error` |
| 10 | +- Favor using real paths (`../lib/schemas.ts`) over aliases (`@/app/lib/schemas`). |
| 11 | +- Favor `for (const comment of comments) {` over `comments.forEach((comment) => {` |
| 12 | +- Favor named exports over default exports, with the exception of Next.js pages |
| 13 | +- Do not wrap each function body and function call in `try`/`catch` blocks. It pollutes the code. |
| 14 | + Assume we will always have an e.g. |
| 15 | + `main().catch((err) => { console.error(err); process.exit(1) })` to catch us. I repeat: Avoid |
| 16 | + over-use of try-catch such as |
| 17 | + `try { // foo } catch (err) { console.error('error while foo'); throw err }`, assume we catch |
| 18 | + errors on a higher level and do not need the extra explananation. |
| 19 | +- If you must use try/catch, for simple cases, favor `alphalib/tryCatch.ts` |
| 20 | + (`const [err, data] = await tryCatch(promise)`) over |
| 21 | + `let data; try { data = await promise } catch (err) { }` |
| 22 | +- Before creating new files and new code, see if we can leverage existing work, maybe slighty adapt |
| 23 | + that without breaking BC, to keep things DRY. |
| 24 | +- Favor early exits, so quickly `continue`, `return false` (or `throw` if needed), over nesting |
| 25 | + everything in positive conditions, creating christmas trees. |
| 26 | +- Use Prettier with 100 char line width, single quotes for JS/TS, semi: false |
| 27 | +- Use descriptive names: PascalCase for components/types, camelCase for variables/methods/schemas |
| 28 | +- Alphabetize imports, group by source type (built-in/external/internal) |
| 29 | +- Favor US English over UK English, so `summarizeError` over `summarise Error` |
| 30 | +- Favor `.replaceAll('a', 'b)` over `.replace(/a/g, 'b')` or `.replace(new RegExp('a', 'g'), 'b')` when the only need for regeses was replacing all strings. That's usually both easier to read and more performant. |
| 31 | +- Use typographic characters: ellipsis (`…`) instead of `...`, curly quotes (`'` `"`) instead of straight quotes in user-facing text |
| 32 | +- Put API keys and secrets in `.env` files, not hardcoded in components |
| 33 | +- Check for existing hooks before creating new ones (e.g., `useUppy()` for Uppy functionality) |
| 34 | + |
| 35 | +## general |
| 36 | + |
| 37 | +General: |
| 38 | + |
| 39 | +- Do not touch `.env` files! |
| 40 | +- Favor Yarn (4) over npm |
| 41 | +- Never run any dev server yourself. I have one running that auto-reloads on changes. |
| 42 | +- Avoid blocking the conversation with terminal commands. For example: A) most of my git commands run through pagers, so pipe their output to `cat` to avoid blocking the |
| 43 | + terminal. B) You can use `tail` for logs, but be smart and use `-n` instead of `-f`, or the conversation will block |
| 44 | +- Use the `gh` tool to interact with GitHub (search/view an Issue, create a PR). |
| 45 | +- Treat `AGENTS.md` and `CLAUDE.md` as generated artifacts (single source of truth is `.ai/rules/`), managed by `~/code/content/_scripts/alphalib-sync.ts`; never edit those files directly. If you'd like to make a modification, do it here in `.ai/rules/` and the script will ensure proper preservation and syncing. If you need a rule specific to this repo, add it to `.ai/rules/repo.mdc`. |
| 46 | +- All new files are to be in TypeScript. Even if someone suggests: make this new foo3 feature, model it after `foo1.js`, create: `foo3.ts`. Chances are, a `foo2.ts` already exist that you can take a look at also for inspiration. |
| 47 | + |
| 48 | +## playwright |
| 49 | + |
| 50 | +- Prefer user-centric locators: `getByRole`/`getByText` with accessible names; avoid `page.locator('body')`, `innerText()`, or raw CSS unless there is no accessible alternative. |
| 51 | +- Make positive assertions on expected UI/text instead of looping over regexes to assert absence. |
| 52 | +- Keep tests simple: no control-flow loops or extra variables for straightforward assertions. |
| 53 | +- Navigate with relative URLs (`page.goto('/path')`) by setting `baseURL` in `playwright.config.ts`; avoid stringing environment URLs in tests. |
| 54 | +- Stub or mock external/third‑party requests (Intercom, Sentry, etc.) and any auth/login endpoints to keep tests deterministic; return minimal valid JSON when the app expects data. |
| 55 | +- Each unexpected error should surface and fail the test. |
| 56 | + |
| 57 | +## typescript |
| 58 | + |
| 59 | +For Typescript: |
| 60 | + |
| 61 | +- Favor `contentGapItemSchema = z.object()` over `ContentGapItemSchema = z.object()` |
| 62 | +- Favor `from './PosterboyCommand.ts'` over `from './PosterboyCommand'` |
| 63 | +- Favor `return ideas.filter(isPresent)` over `ideas.filter((idea): idea is Idea => idea !== null)` |
| 64 | +- Favor using `.tsx` over `.jsx` file extensions. |
| 65 | +- Use Node v24's native typestripping vs `tsx` or `ts-node`. These days you do not even need to pass `--experimental-strip-types`, `node app.ts` will just work. |
| 66 | +- Favor `satisfies` over `as`, consider `as` a sin |
| 67 | +- Favor `unknown` over `any`, consider `any` a sin |
| 68 | +- Favor validating data with Zod over using `any` or custom type guards |
| 69 | +- We use the `rewriteRelativeImportExtensions` TS 5.7 compiler option, so for local TypeScript |
| 70 | + files, import with the `.ts` / `.tsx` extension (not js, not extensionless) |
| 71 | +- Favor defining props as an interface over inline |
| 72 | +- Favor explicit return types over inferring them as it makes typescript a lot faster in the editor |
| 73 | + on our scale |
0 commit comments