Forking HotCRM

Use HotCRM as the starting point for your own marketplace app.

HotCRM is the reference implementation for ObjectStack marketplace apps. Forking it gives you a battle-tested skeleton (objects, hooks, AI agents, dashboards, i18n, security) that you can rename and customize for any vertical — HR, project management, help desk, billing, you name it.

Why fork?

A working ObjectStack app needs ~15 conventions wired correctly:

  • Namespace prefix on every object
  • File-suffix protocol (*.object.ts, *.hook.ts, *.actions.ts)
  • ObjectQL (no raw SQL)
  • AI tool exposure via *.actions.ts
  • Strict @objectstack/spec schema validation
  • i18n bundles for all locales you ship
  • Profile + positions + sharing rules
  • Approval processes
  • Hooks correctly lowered for the build pipeline
  • Dashboards backed by analytics datasets
  • Documentation that's actually accurate

Writing all of that from scratch is a week. Forking HotCRM and renaming it is an hour.

Step-by-step

1. Clone

git clone https://github.com/objectstack-ai/hotcrm.git my-app
cd my-app
git remote rename origin upstream     # so you can `git pull upstream main` for HotCRM updates
git remote add origin git@github.com:<you>/<my-app>.git

2. Rename the manifest

HotCRM ships one artifact carrying two packages, and each declares its own manifest. Edit the app package's, in src/sales/index.ts — it is also the artifact's identity:

 manifest: {
-  id: 'app.objectstack.hotcrm',
-  namespace: 'crm',
+  id: 'app.acme.myapp',
+  namespace: 'acme',
   version: '1.0.0',
   type: 'app',
-  name: 'HotCRM',
-  description: 'AI-Native CRM for the ObjectStack marketplace ...',
+  name: 'Acme MyApp',
+  description: 'Your app, your tagline.',
 },

Then give the service module in src/service/index.ts the same namespace, an id under yours (app.acme.myapp.service), and point its dependencies at your new app id. objectstack.config.ts only composes the two and needs no edit.

3. Rename the prefix everywhere

The crm_ prefix is in ~85 files. Use a one-shot rename:

# macOS (BSD sed)
find src content -type f \( -name "*.ts" -o -name "*.mdx" -o -name "*.json" \) \
  -exec sed -i '' 's/crm_/acme_/g' {} +

# Linux (GNU sed)
find src content -type f \( -name "*.ts" -o -name "*.mdx" -o -name "*.json" \) \
  -exec sed -i 's/crm_/acme_/g' {} +

# Rename the translation file that's literally called crm.translation.ts
mv src/sales/translations/crm.translation.ts src/sales/translations/acme.translation.ts

Then update src/sales/translations/index.ts to reference the new filename.

4. Cut what you don't need

HotCRM ships 18 objects across Sales / Service / Marketing / Revenue. Most apps need fewer:

# Example: keep only Sales. Service, Revenue and Marketing are whole
# packages now (ADR-0130), so they go as directories.
rm -r src/service src/revenue src/marketing
rm src/sales/objects/forecast.object.ts

Then drop those three directories from objectstack.composition.ts — their imports, the service module's stack and its seed families — compose the app package alone in objectstack.config.ts, and prune the sales-side hooks, actions, flows, dashboards, translations and docs that reference removed objects. pnpm typecheck will flag the broken references.

5. Add what you do need

Follow the file-suffix protocol. <package> is the one of sales / service / revenue / marketing that owns the entity — a directory under src/ is a package (ADR-0130), and a file that never reaches its package's barrel is registered by nothing:

New entityFile
Data modelsrc/<package>/objects/<entity>.object.ts
Server-side triggersrc/<package>/objects/<entity>.hook.ts — beside its object, registered in src/<package>/objects/hooks.ts
API + AI toolsrc/<package>/actions/<entity>.actions.ts
UI layoutsrc/<package>/pages/<entity>.page.ts
List viewsrc/<package>/views/<entity>.view.ts
i18nappend to src/sales/translations/{en,zh-CN,es-ES,ja-JP}.ts

Every file goes through @objectstack/spec schema validation at build time. Mistakes fail loudly.

6. Verify

pnpm typecheck
pnpm build
pnpm dev    # smoke-test in the browser at http://localhost:4001

7. Publish

objectstack cloud login
objectstack package publish dist/objectstack.json \
  --visibility marketplace \
  --category <your-category> \
  --note "Initial release."

See Publishing your first marketplace app for full CLI reference.

Stay in sync with HotCRM

HotCRM keeps evolving. Pull in upstream improvements:

git fetch upstream
git merge upstream/main          # or rebase, your call

Merge conflicts mostly happen in src/sales/translations/* (additive) and src/*/objects/*.object.ts (if you renamed them). The file-suffix protocol keeps conflict surface small.

What you can safely change

Everything. HotCRM ships under Apache-2.0 — you can rename it, rebrand it, sell support around it. The only ask: if you find a bug in the convention (not your business logic), upstream it back. That makes the reference better for everyone.

On this page