Should you build a CRM from scratch, or start from a framework?
Building a CRM yourself
People ask this as: build a custom crm from scratch vs using a crm framework
The comparison with no competitor in it: your own empty repository against this framework. What you get is CRM machinery — module manifests that generate their own migrations, deterministic workflows, a human-approval boundary, audit and trace. What you still write is most of what a business calls a CRM: authentication, import, export, search, email, and the database it should have been on. This is a framework, not an application, so the honest form of this page is a subtraction rather than a pitch.
Where this stops
Read this before the rest of the page. Every line below is a thing this does not do.
Every fact about another project on this page is single-sourced to
docs/strategy/COMPETITOR_MAP.md and dated 2026-08-04. Nothing from
another project was installed, configured or run, and there is no network access here to re-verify
any of it.
- This is a framework, not an application you sign up for. There is no hosted CRM, no free tier and no account (L-07).
- Ownership means vendored source, not a dependency: `npm create accordo` scaffolds a project with the framework source copied in, and upgrading means merging rather than bumping (L-08).
- The framework authenticates nobody, and ships no verifier. In local-development mode an actor header is an assertion, not an identity, and that server must not be exposed to a network (L-01).
- The synchronous factory uses SQLite; the async factory supports one tenant on dedicated PostgreSQL databases. Shared-database row tenancy and general production readiness are not claimed (L-02).
- Customer Data Foundation supports bounded JSON imports with preview/apply, per-row receipts and idempotency, deterministic duplicate candidates, and human-governed canonical identity as logical links. It does not provide CSV ingestion, physical merge, complete export/erasure, bulk editing, saved views or global search (L-06).
- Durable jobs, a transactional outbox and scheduled asks exist for self-hosted applications that explicitly start a worker. Nothing autostarts; a timer opens an ask, never makes a decision, and no managed worker service or recurrence is included (L-04).
- No email, calendar or marketing integration. A notification provider contract exists; no adapter sends anything to anyone (L-05).
- No claim about how quickly an agent finishes a CRM with this, because the benchmark has not been run (L-03).
- Real customer data does not go in yet: no export and no erasure path, so a subject access or deletion request cannot be serviced (L-09).
No authentication ships: the framework authenticates nobody. Production Spine v1 (ADR-038) gives the framework verified identity, organizations and memberships, server-authoritative authorization and one tenant per application instance — so tenancy and authorization now exist and are enforced. What does not exist is authentication: no login, password, session or OIDC implementation ships, and a deployment must supply the adapter that verifies the request. Production mode refuses to start without one. In local-development mode an actor header is accepted as an assertion and is not an identity, which is the default developer posture. This is not shared-database multi-tenancy and it is not a readiness claim. Every claim and every limitation is on one page.
Where building from scratch wins
Total control is the real advantage, not a slogan: nothing in your schema is shaped by someone else's idea of what a Company is, and no upgrade ever asks you to reconcile your domain with a framework's opinion of it. That advantage is larger here than usual, because ownership in this project means vendored source rather than a dependency — `npm create accordo`, the published `create-accordo@0.1.0`, scaffolds a project that boots, inspects and passes the project doctor by copying the framework source into it, so upgrading means merging, not bumping (L-08). If the end state was going to be a fork you maintain, starting from your own repository means every convention in it is one you chose.
Work remains on both paths: deployment authentication and hosting, business-service adapters and complete personal-data operations. The synchronous factory uses SQLite; the async factory supports one tenant on dedicated PostgreSQL databases. Shared-database row tenancy and general production readiness are not claimed (L-02). Customer Data Foundation supports bounded JSON imports with preview/apply, per-row receipts and idempotency, deterministic duplicate candidates, and human-governed canonical identity as logical links. It does not provide CSV ingestion, physical merge, complete export/erasure, bulk editing, saved views or global search (L-06). Durable jobs, a transactional outbox and scheduled asks exist for self-hosted applications that explicitly start a worker. Nothing autostarts; a timer opens an ask, never makes a decision, and no managed worker service or recurrence is included (L-04). These bounded contracts reduce framework work; they do not supply an operated CRM.
The third win is the first week. A form, a table and a list against a database you already run is a day of work, with no manifest, no policy version and no migration convention standing between you and a working screen. This framework starts paying on the second commercial rule, not on the first screen, and if there is never a second commercial rule it does not start paying at all.
Where this is different
What you stop writing is the machinery around the record rather than the record itself. A module manifest becomes a migration, a service, a REST resource, an SDK method and Admin screens with no page code (C-01), and generated modules then evolve through explicit revisions, a checked-in state file and append-only named migrations, so history is added to rather than rewritten (C-19). The fifth object costs roughly what the first one did, which is the opposite of how a hand-rolled CRM ages.
The parts a bespoke CRM reaches last are here first. Commercial policy is deterministic code rather than a model's judgement: a renewal at or above the threshold stops and waits for a named human (C-03), and a test asserts that an agent cannot make that decision on the human's behalf, so the boundary is a property of the system rather than a promise in a README (C-04). Every mutation goes through a module service or a named workflow and leaves an audit event and a step-level trace behind it (C-16). None of that is hard to write once. It is hard to write consistently, in every path, under deadline — which is the failure mode the from-scratch CRM actually has, and it shows up as archaeology eighteen months later when someone asks who approved a discount and under which rule.
The dependency surface is deliberately close to nothing: Node 22 and a checkout, no build step, no bundler, no framework underneath your framework; SQLite is Node's built-in adapter and PostgreSQL requires the one pinned pg@8.23.0 driver (C-17). And one command composes the starter's whole application from manifests, drives it end to end, and then prints the things its own inspector says it cannot see (C-22). That last part is the tell — the machinery is built to be interrogated by a coding agent and reviewed by a human, which is a different design goal from the one a hand-rolled CRM is usually optimising for.
How to choose
Build it yourself when an existing stack already supplies the needed process, or when generic CRUD is the whole requirement. Accordo can supply policy, approvals, persistence and bounded import machinery; authentication, hosting, billing and complete personal-data operations still need separate work (L-01, L-06, L-09).
Start from this framework if the process is the product — stages, approvals, discount policy, obligations, handovers — and someone will ask in six months why a number was what it was. It fits when a coding agent is doing most of the typing and you want the output as reviewable source with conventions the agent can read back, and when you would otherwise be deriving approvals, audit and trace by hand for the third time. You keep the repository either way; the question is only whether the first thousand lines in it are yours or the framework's.
What this comparison does not cover
No time or cost estimate, and no build-rate figure. The agent build benchmark is designed and published but has not been run, so no Successful Agent Build Rate exists and any number quoted for this project is not ours (L-03). Nothing on this page says an agent finishes faster here, because that has not been measured.
No comparison to any specific starter, template or boilerplate. This page compares against the empty repository, not against a named project — the dated competitor research the rest of this cluster reads carries facts about other software, and this entry needs none of them, so it uses none.
Nothing about production posture or hosting. There is no hosted CRM, no free tier and no account; the output is an application in your repository that you run (L-07). The comparison assumes you are the one deploying it, and says nothing about how.
Common questions
What do I actually save versus starting from an empty repository?
The machinery teams re-derive under deadline: generated migrations, services, REST and Admin from a module manifest, deterministic workflows, versioned policies with human approval, audit and trace. Your domain logic is still yours to write.
What do I still have to build myself?
The framework supports SQLite and dedicated PostgreSQL, with authorization and per-instance tenancy. Deployment authentication and hosting remain application work. Durable jobs, outbox and scheduled asks need explicitly started self-host workers; no managed service ships. Live business adapters, billing and complete personal-data operations remain gaps.
The evidence this page rests on
Claims and limitations are printed from site/claims.json word for word. Job statuses come from docs/benchmarks/jobs.json; a job with no page of its own is listed with its status rather than linked.
Claims
- C-01 Write a module manifest; the agent turns it into a migration, a service, a REST resource, an SDK method and Admin screens — with no page code.
LimitGenerated CRUD only. The factory does not generate workflows or approvals for a custom object — that is still handwritten (JTBD-06, partially supported).
- C-03 Commercial policy is deterministic code, not a model's judgement: a renewal at or above the threshold stops and waits for a named human.
LimitProven for the built-in renewal object and its single value threshold. A general policy engine over arbitrary custom objects does not exist.
- C-04 The agent cannot approve on the human's behalf. A test asserts the refusal, so the boundary is a property of the system rather than a promise in a README.
LimitIn local-development mode the actor is asserted, not authenticated: no authentication ships, so an actor header there is not an identity. This holds a boundary against an honest agent, not against an attacker with network access.
- C-16 Every mutation goes through a module service or a named workflow, and leaves an audit event and a step-level trace behind it.
LimitAudit records what the process did under an asserted actor. It is not a tamper-evident or externally attestable log, and it is not a compliance control.
- C-17 SQLite is Node's built-in node:sqlite. PostgreSQL requires one pinned runtime driver, pg@8.23.0. There is no ORM, no query builder, no build step and no framework underneath your framework.
LimitApplications that select PostgreSQL carry pg@8.23.0. The SQLite path still needs no third-party driver. This is not a production-readiness claim and not shared-database tenancy; composition is dedicated-database, not row tenancy.
- C-19 Generated modules evolve without rewriting history: explicit revisions, a checked-in state file and append-only named migrations.
LimitThe view is source-only: what the checked-in revisions and migrations say is knowable; what a particular database has actually applied is not.
- C-22 One command composes the whole thing and then inspects it: 76 modules, 9 packages, 71 resources, 64 actions, 7 policies and 1 providers, applied from manifests and driven end to end — then it prints the eleven things the inspector says it cannot see.
LimitIt composes the starter's application, not yours, and it runs entirely locally against SQLite with no authentication. The counts describe what that starter applies; a different composition gives different numbers. Wall-clock time varies by machine and is deliberately not claimed.
Limitations
- L-01 No authentication ships: the framework authenticates nobody. Production Spine v1 (ADR-038) gives the framework verified identity, organizations and memberships, server-authoritative authorization and one tenant per application instance — so tenancy and authorization now exist and are enforced. What does not exist is authentication: no login, password, session or OIDC implementation ships, and a deployment must supply the adapter that verifies the request. Production mode refuses to start without one. In local-development mode an actor header is accepted as an assertion and is not an identity, which is the default developer posture. This is not shared-database multi-tenancy and it is not a readiness claim.
- L-02 Not shared-database tenancy. createAccordoAppAsync can boot one tenant onto dedicated PostgreSQL databases. Shared-database row-level tenancy is not implemented, and this is not a production-readiness claim.
- L-03 The build benchmark has not been run. The protocol is designed and published; no Successful Agent Build Rate exists yet. Any number you see quoted for this project is not ours.
- L-04 Timers exist; a service that runs them for you does not. Durable jobs, a transactional outbox and scheduled asks exist for self-hosted applications that explicitly start a worker. Nothing autostarts; a timer opens an ask, never makes a decision, and no managed worker service or recurrence is included.
- L-05 No email, calendar or marketing integrations. An in-memory notification provider contract exists. MK1 marketing records supplied funnel observations and human-reviewed proposals only; it has no sending, publishing or spending path.
- L-06 Bounded customer imports and logical identity; incomplete data operations. Customer Data Foundation supports bounded JSON imports with preview/apply, per-row receipts and idempotency, deterministic duplicate candidates, and human-governed canonical identity as logical links. It does not provide CSV ingestion, physical merge, complete export/erasure, bulk editing, saved views or global search.
- L-07 This is a framework, not a product you sign up for. There is no hosted CRM, no free tier and no account. The output is an application in your repository that you run.
- L-08 Ownership means vendored source: there is no framework dependency to bump. The published create-accordo@0.1.0 scaffolds vendored source; it is the August 19 snapshot, not the current repository feature set. Use a current source checkout for the capabilities described here; upgrades require merging source (L-08). The framework is copied into the project, not installed as a framework library dependency. The accordo npm name is an empty reservation; the @accordo scope is claimed and deliberately empty.
- L-09 Personal-data readiness requires deployment work beyond the foundation. Customer Data Foundation supplies bounded import and identity governance, not complete personal-data operations. Authentication must be supplied by the deployment, and complete subject export and erasure remain absent; the framework alone does not establish compliance or suitability for real customer data. Lead scoring remains deterministic, versioned and explainable.
Jobs it covers
- JTBD-01 Manage a custom CRM business object end to end — validated end to end
- JTBD-02 Request commercial approval on a deal — validated end to end
- JTBD-03 Manage a deal through pipeline stages — validated end to end
- JTBD-06 Manage a custom object with an approval rule — partially supported
- JTBD-07 Schedule next actions / follow-ups — partially supported
- JTBD-15 Enforce team / tenant permissions — partially supported
- JTBD-DO-01 Import records from CSV — partially supported
- JTBD-DO-04 Export records — partially supported
- JTBD-DO-07 Search across modules — not supported