# Common mistakes

This page collects the mistakes developers hit most often when building Comind.work apps. Each entry explains what goes wrong, why it happens, and the correct approach.

## Importing settings instead of reading them at runtime[​](#importing-settings-instead-of-reading-them-at-runtime "Direct link to Importing settings instead of reading them at runtime")

Using a static `import` for workspace settings bakes the compile-time value into the bundle. The app then ignores the per-workspace override entirely. Use `ComindView.getVars()` (client-side) or `ComindServer.getVars()` (server-side) at runtime to retrieve the value the workspace administrator actually configured. See [Settings model](/developer-guide/building-blocks/settings-model.md) for the full runtime API.

## Forgetting the `c_` prefix on custom fields[​](#forgetting-the-c_-prefix-on-custom-fields "Direct link to forgetting-the-c_-prefix-on-custom-fields")

System fields provided by `@comind/base` - `title`, `description`, `state` - have no prefix. Every field you add must use the `c_` prefix: `c_priority`, `c_due_date`, and so on. Omitting the prefix causes silent lookup failures because the runtime searches the wrong field namespace. See [Fields](/developer-guide/building-blocks/fields-and-field-options.md) for naming rules.

## Misunderstanding plugin merge order[​](#misunderstanding-plugin-merge-order "Direct link to Misunderstanding plugin merge order")

Plugins are composed with a deep-merge strategy, and the last plugin in the chain wins. Arrays replace rather than concatenate. If two plugins define a field with the same name, the later definition overwrites the earlier one. Audit merge order explicitly and test the resulting schema whenever you add or reorder plugins. See [Plugins](/developer-guide/building-blocks/plugins-and-inheritfrom.md) for composition details.

## Changing a parent app without checking its children[​](#changing-a-parent-app-without-checking-its-children "Direct link to Changing a parent app without checking its children")

`inheritFrom` creates a live link - every child app inherits the parent's fields, actions, and layouts. A change to the parent propagates to all children on the next install. Always test parent changes across every inheriting app before deploying. See [Plugins](/developer-guide/building-blocks/plugins-and-inheritfrom.md) for the inheritance model.

## Treating calculated fields as always synchronous[​](#treating-calculated-fields-as-always-synchronous "Direct link to Treating calculated fields as always synchronous")

Simple calc fields resolve synchronously during save. Rollups and table-calcs do not - they are processed asynchronously by the background Processor. The UI uses a custom refresh mechanism rather than real-time push. If your logic depends on a rollup result being available immediately, it will read stale data. Design actions and visibility rules to account for the async delay. See [Fields](/developer-guide/building-blocks/fields-and-field-options.md) for calc field types.

## Confusing push and install[​](#confusing-push-and-install "Direct link to Confusing push and install")

The `push` command uploads source code to the server. The `install` command compiles and deploys it. Pushing without installing leaves the running app unchanged. Also verify you are targeting the correct branch - deploying to `main` when you intended `prod`, or vice versa, is a common source of unexpected behavior. See [CLI reference](/developer-guide/reference/cli-reference.md) for the full command list.

## Overlapping permission layers[​](#overlapping-permission-layers "Direct link to Overlapping permission layers")

Record-level ACL and field-level permissions are evaluated independently, and combining them can produce surprising results. Evaluation order is workspace, then app, then record, then field. A field-level restriction can hide data even when the record-level ACL grants access. Map out permission layers before you mix ACL types.

## Too many calculated fields[​](#too-many-calculated-fields "Direct link to Too many calculated fields")

Each calc field that depends on another calc field creates a chain of recalculations. Large chains slow down saves and can cascade through rollups across related apps. Keep calc depth shallow and avoid circular dependency patterns. The grid view also caps rendering at roughly 50 rows, so heavy calc usage compounds performance limits in list views.

## Using React patterns in TSX layouts[​](#using-react-patterns-in-tsx-layouts "Direct link to Using React patterns in TSX layouts")

Layout `.tsx` files look like React components but they are not. They compile to XML strings through the custom `entity` factory. React hooks, state management, and lifecycle methods are unavailable and will fail silently or throw at compile time. Treat layout files as pure template functions that return markup. See [Form layouts](/developer-guide/building-blocks/form-layouts.md) for the correct authoring pattern.

## Exposing secrets through static imports[​](#exposing-secrets-through-static-imports "Direct link to Exposing secrets through static imports")

A static `import` bundles the value into client-side JavaScript, making it visible in the browser. Store secrets in `settings/secrets.ts` and use `COMIND_SECRET_*` environment variables. The runtime injects these values on the server only. See [Settings model](/developer-guide/building-blocks/settings-model.md) for the secrets workflow.

## Assuming action logic runs in the browser[​](#assuming-action-logic-runs-in-the-browser "Direct link to Assuming action logic runs in the browser")

Action logic executes on the server, not in the browser. Browser-only APIs like `fetch`, `document`, and `window` are unavailable. Node-only modules are also unsupported. Write action logic using the server-side globals Comind.work provides. See [Actions](/developer-guide/building-blocks/actions.md) and [Server-side API](/developer-guide/reference/server-side-globals.md) for the available runtime surface.

## Config file not found in git worktrees[​](#config-file-not-found-in-git-worktrees "Direct link to Config file not found in git worktrees")

If Claude Code or another tool runs in a git worktree, it has its own working directory separate from the main repo. Config files like `.config/dev.env` must exist in the worktree path, not just in the main repo root. The worktree does not automatically inherit files outside of git-tracked content. Copy the config file into the worktree directory or create a symlink pointing back to the original.

## API version mismatch warnings on install[​](#api-version-mismatch-warnings-on-install "Direct link to API version mismatch warnings on install")

When the dev environment runs a slightly older platform version than the SDK expects, non-critical warnings appear during `npx comind install`. These warnings are safe to ignore on development environments - the SDK maintains backward compatibility for minor version differences. On production, update the SDK to match the platform version to eliminate the warnings and avoid any edge-case incompatibilities.

## CSS styles cause visible flash on form load[​](#css-styles-cause-visible-flash-on-form-load "Direct link to CSS styles cause visible flash on form load")

Applying broad CSS selectors (like changing `font-family` on `body` or the form container) in custom layouts causes a visible re-render. Platform CSS loads after custom styles and momentarily overrides them, producing a flash of unstyled content.

Fix: target specific elements with scoped class names instead of broad selectors.

```
/* Bad - broad selector, will flash */
body {
  font-family: "Inter", sans-serif;
}

/* Good - scoped selector, no flash */
.myapp-totals {
  font-family: "Inter", sans-serif;
}
```

Use inline styles for one-off overrides where a dedicated class is not worth maintaining.

## Claude refuses to edit .env files[​](#claude-refuses-to-edit-env-files "Direct link to Claude refuses to edit .env files")

Claude Code treats files named `.env` or containing secrets as security-sensitive and may block reads or edits. When prompted, approve the file access manually in the permission dialog. This is a safety feature, not a bug.

Never paste environment variables or API keys directly into the chat. They may be logged or sent to the AI provider as part of the conversation context. Instead, reference the file path and let Claude read it with your explicit approval.
