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/specschema 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>.git2. 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.tsThen 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.tsThen 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 entity | File |
|---|---|
| Data model | src/<package>/objects/<entity>.object.ts |
| Server-side trigger | src/<package>/objects/<entity>.hook.ts — beside its object, registered in src/<package>/objects/hooks.ts |
| API + AI tool | src/<package>/actions/<entity>.actions.ts |
| UI layout | src/<package>/pages/<entity>.page.ts |
| List view | src/<package>/views/<entity>.view.ts |
| i18n | append 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:40017. 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 callMerge 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.