Notes:
- Use React Native elements only; do not replace them with DOM elements in specs or dummy app code.
- Prefer React Native components for all new code, including spec/dummy pages.
- Do not edit
build/outputs manually; regenerate with the appropriate build command instead. - Do not force-add ignored
build/outputs to git; keep PRs focused on source changes and let release/build workflows regenerate package artifacts. - When a debugging or implementation session reveals a reusable lesson, document it before finishing in this repo's README/docs, relevant skills, and the applicable
AGENTS.mdfiles. - Only run builds when releasing a new package; development runs against source files.
- When using
gh pr create/edit, pass multi-line bodies with real newlines (not literal\n) so GitHub renders them correctly. - Avoid unrelated changes (for example, adding placeholder modules in specs) unless they are necessary for the requested change.
- Before committing, review the current diff and propose commit message(s) grouped by logical change sets.
- Prefer
describeoverRSpec.describein specs. - Do not add
# frozen_string_literal: trueto files. - Before adding RuboCop disable directives, check the existing repo RuboCop config first and prefer code that passes under that config without new disables; avoid review-only style churn.
- Prefer multiple small, individually working commits when possible.
- Always run Rubocop on changed Ruby files.
- If a RuboCop config exists for the current Ruby project, run RuboCop on changed Ruby files before pushing or opening a PR.
- Always run ESLint on changed or new JavaScript files.
- Add concise comments for non-obvious groups of code so the intent and invariants are clear without reverse-engineering the flow.
- ESLint
sort-importsorders import lines by member syntax group (none/all/multiple/single) and then the first local specifier name, not by module specifier; adjust import order accordingly. - When creating PRs, choose a sensible branch name and commit messages without prompting.
- When you fix something in this repo, keep the change on a feature branch and make sure there is a matching PR for that branch before you consider the work complete.
- For system specs, use
ruby-gem/scripts/run-system-spec.sh [spec/path.rb:line](wraps the README system spec command). - For Firefox system specs in this repo, prefer the headless Firefox path (
SELENIUM_DRIVER=firefox ruby-gem/scripts/run-system-spec.sh ...) and do not wrap that path inxvfb-run; Chrome still uses the xvfb-backed path. - Do not add
Capybara.reset_sessions!inbefore(:each)hooks here. Capybara RSpec already resets sessions after each example, and duplicate pre-example resets add major Firefox overhead. - When installing gems, run
bundle installin bothruby-gem/andruby-gem/spec/dummy/before running specs. - If
ruby-gem/scripts/run-system-spec.shfails, run the README system spec command manually fromruby-gem/. - In
ApiMaker::ModelContentGeneratorService, handle Ransack allowlist runtime errors ("Ransack needs ...") for associations/attributes/scopes by returning[]so frontend model generation does not crash on third-party models. - Do not “fix” flaky specs by only increasing waits/timeouts. First determine whether behavior regressed (for example, element never rendered) and collect/inspect CI artifacts before adjusting timing.
- Avoid unnecessary defensive conditions for guaranteed contracts. Prefer failing fast over silently accepting impossible states.
- In ApiMaker table workplace helpers and commands,
current_usermay legitimately benilfor websocket/content-parser requests; returnnil/empty results for current-workplace lookups instead of dereferencing the user. - Before adding fallback logic for hook/context timing, inspect the provider source first; do not assume first-render hydration gaps without source confirmation.
- Do not add helper methods for simple values or expressions that are only used in one place; inline them at the usage site instead.
- Keep
testIDvalues unique within a rendered screen/component so selectors stay unambiguous. - In Selenium/spec helpers, do not assume a
testIDselector points at the editable control itself; React Native Web may put thetestIDon a wrapper, so descend to the realinput/textarea/checkbox element before typing or clearing. - In JavaScript class method definitions, use
methodName(args)(no space before parentheses). - Keep single-tag JSDoc blocks on one line (for example
/** @returns {boolean} */). - In ShapeHook classes, keep
setup()as the first instance method. - Keep component props ordered alphabetically.
- To typecheck a single file, run
npm run typecheck:file --file=src/path/to/file.jsfromnpm-api-maker/(you can also passnpm-api-maker/src/...or setFILE=src/path/to/file.js). - Do not "fix" render/update bugs by replacing
useMemo()withuseEffect()as a blanket change; preserve hook semantics and debug the underlying state flow first. - In
npm-api-maker, keep the checked-in.npmrcwithlegacy-peer-deps=truewhile the package targets ESLint 10 andeslint-plugin-reacthas not yet published an ESLint 10 peer range; remove that workaround only after the upstream peer support lands. - In
npm-api-maker, keep peer-facing runtime imports that are needed by linked local/CI builds, lint, or tests (for examplereact-native-vector-icons,flash-notifications,history, andi18n-on-steroids) installed indevDependenciesas well when tooling resolves modules from the package directory itself. - In
on-location-changed,WithLocationPathinitializesqueryParamssynchronously fromglobalThis.location.searchviauseState(params());useQueryParams()beingundefinedindicates a missing/explicitly-undefined provider, not a normal first-render hydration phase.
- For Peakflow/API Maker-style frontend-model backends, keep resource metadata and authorization abilities co-located in one resource class tree; do not split them into parallel
resourcesandauthorization/resourcesdirectories. - Prefer ApiMaker commands in
app/api_maker/commandsfor new app actions instead of adding custom Rails controllers when ApiMaker can support the flow. - In Rails apps using ApiMaker, prefer ApiMaker model/model-class websocket events over custom ActionCable channels when possible; add a custom channel only when ApiMaker events cannot represent the required stream.
- In ApiMaker realtime UIs, use model-level update subscriptions when the UI needs updated model attributes; model-class events carry event names/args, not serialized updated models.
- For realtime UI backed by ApiMaker events, do one initial fetch and then rely on websocket/model events; do not add browser polling unless there is a documented hard requirement that events cannot satisfy.
- Use the Layout
headerprop for screen titles; avoid custom per-screen headers unless explicitly requested. - Use
Textfrom@kaspernj/api-maker/build/utils/textfor default styles. - Prefer
useBreakpoint()(responsive-breakpoints via Api Maker dependencies) overuseWindowDimensions()for responsive logic. - When using API Maker
Linkon web (renders as an<a>), center content with an innerViewinstead of relying on flex alignment on the anchor itself. - Prefer
Formfrom@kaspernj/api-maker/build/formwith uncontrolled inputs to avoid state-driven re-renders. - When multiple screens repeat the same label + input form markup, extract a shared form input component (for example a screen-specific base text input) instead of duplicating blocks.
- Use Api Maker
FormandformObjectRefto track uncontrolled input values instead of manual instance fields. - In ShapeComponents using Api Maker
Form, pass bothformObjectRefandsetForm, then read values viathis.formObjectRef.current || this.formto avoid mount-timing races. - Use Api Maker
Iconfor icons instead of raw<i>tags or FontAwesome class names onText. - In app code, prefer importing frontend models from individual files (for example
models/project.js) instead of aggregating throughmodels. - In app code, avoid
import {...} from "models"; import each frontend model from its dedicated model file path. - Prefer link-based navigation (
Linkwithto) for navigation-only actions so users can open routes in new tabs/windows; useAppHistory.push/Params.changeParamsonly when imperative navigation is required by side effects or control flow. - For Api Maker
Linkon web (anchor rendering), use mouse events (onMouseEnter/onMouseLeave) for hover behavior instead ofonHoverIn/onHoverOut. - For Link rows that render text, keep visual text styles (for example
colorand underline decoration) on the innerTextelement rather than theLinkwrapper. - Use
useQueryParamswhen building filterable routes in React UI. - Layout
controlsprops must be callbacks; do not pass React nodes directly. - In ShapeComponent routes, pass
controls={this.tt.controls}and setcontrolsonthis.setInstance(...). - Prefer passing
navbarControlsas a callback and letLayoutresolve it, rather than pre-rendering. - When layout controls depend on a model, pass
cacheKey(likemodel?.id()) to force re-renders.