Skip to content

Latest commit

 

History

History
73 lines (62 loc) · 5.13 KB

File metadata and controls

73 lines (62 loc) · 5.13 KB

Transloadit Repository Guide

coding style

Coding style:

  • Favor async run() { over run = async () => { inside ES6 classes
  • Favor if (!(err instanceof Error)) { throw new Error(Was thrown a non-error: ${err}) } inside catch blocks to ensure the error is always an instance of Error
  • Favor using real paths (../lib/schemas.ts) over aliases (@/app/lib/schemas).
  • Favor for (const comment of comments) { over comments.forEach((comment) => {
  • Favor named exports over default exports, with the exception of Next.js pages
  • Do not wrap each function body and function call in try/catch blocks. It pollutes the code. Assume we will always have an e.g. main().catch((err) => { console.error(err); process.exit(1) }) to catch us. I repeat: Avoid over-use of try-catch such as try { // foo } catch (err) { console.error('error while foo'); throw err }, assume we catch errors on a higher level and do not need the extra explananation.
  • If you must use try/catch, for simple cases, favor alphalib/tryCatch.ts (const [err, data] = await tryCatch(promise)) over let data; try { data = await promise } catch (err) { }
  • Before creating new files and new code, see if we can leverage existing work, maybe slighty adapt that without breaking BC, to keep things DRY.
  • Favor early exits, so quickly continue, return false (or throw if needed), over nesting everything in positive conditions, creating christmas trees.
  • Use Prettier with 100 char line width, single quotes for JS/TS, semi: false
  • Use descriptive names: PascalCase for components/types, camelCase for variables/methods/schemas
  • Alphabetize imports, group by source type (built-in/external/internal)
  • Favor US English over UK English, so summarizeError over summarise Error
  • 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.
  • Use typographic characters: ellipsis () instead of ..., curly quotes (' ") instead of straight quotes in user-facing text
  • Put API keys and secrets in .env files, not hardcoded in components
  • Check for existing hooks before creating new ones (e.g., useUppy() for Uppy functionality)

general

General:

  • Do not touch .env files!
  • Favor Yarn (4) over npm
  • Never run any dev server yourself. I have one running that auto-reloads on changes.
  • 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 terminal. B) You can use tail for logs, but be smart and use -n instead of -f, or the conversation will block
  • Use the gh tool to interact with GitHub (search/view an Issue, create a PR).
  • 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.
  • 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.

playwright

  • Prefer user-centric locators: getByRole/getByText with accessible names; avoid page.locator('body'), innerText(), or raw CSS unless there is no accessible alternative.
  • Make positive assertions on expected UI/text instead of looping over regexes to assert absence.
  • Keep tests simple: no control-flow loops or extra variables for straightforward assertions.
  • Navigate with relative URLs (page.goto('/path')) by setting baseURL in playwright.config.ts; avoid stringing environment URLs in tests.
  • 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.
  • Each unexpected error should surface and fail the test.

typescript

For Typescript:

  • Favor contentGapItemSchema = z.object() over ContentGapItemSchema = z.object()
  • Favor from './PosterboyCommand.ts' over from './PosterboyCommand'
  • Favor return ideas.filter(isPresent) over ideas.filter((idea): idea is Idea => idea !== null)
  • Favor using .tsx over .jsx file extensions.
  • 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.
  • Favor satisfies over as, consider as a sin
  • Favor unknown over any, consider any a sin
  • Favor validating data with Zod over using any or custom type guards
  • We use the rewriteRelativeImportExtensions TS 5.7 compiler option, so for local TypeScript files, import with the .ts / .tsx extension (not js, not extensionless)
  • Favor defining props as an interface over inline
  • Favor explicit return types over inferring them as it makes typescript a lot faster in the editor on our scale