Skip to content

Repository files navigation

sales-pipeline-crm

Replace Salesforce with a custom CRM built in Xano. A self-contained sidestep template that re-implements Salesforce's documented Opportunity / deal-management model as transparent, inspectable XanoScript — with a Kanban + forecast-dashboard frontend for a live demo.

Every Salesforce-mirroring behavior here is modeled from the public Salesforce Object Reference / Help documentation (cited below), not a live integration. There is no Salesforce account, OAuth, or API call anywhere in this project — it runs entirely on shipped seed data. It is an independent re-implementation for teaching and demo purposes, not affiliated with or endorsed by Salesforce.

Honesty caveat. Salesforce does not publish an exact default probability for every standard stage. The seed therefore uses Salesforce's documented example probability values (10 / 10 / 20 / … / 90 / 100 / 0) and says so — it never claims these are "Salesforce's defaults." Treat every number here as illustrative of the mechanics, not as authoritative Salesforce configuration.


Quick start

npm install
npm run dev            # run the frontend (Vite)

The app opens on a login screen with a "Load demo data" button. It calls the idempotent POST /seed endpoint (manager + 3 reps, the 10 standard stages, accounts/contacts/leads, and ~20 deals) and hands you demo credentials. Log in as the manager to see all records, or as a rep to see the owner-scoped view.

Deploy (backend + static frontend, one command)

sidestep login                       # once, to authenticate against your Xano account
npm run build                        # build the static frontend
npm run xano:deploy                  # ship the backend + built frontend together
  • npm run xano:export compiles the backend to workspace.json (don't commit it).
  • npm run typecheck / npm run build must stay green.

Architecture

xano/
  index.ts                 default-exported workspace() registering everything
  lib.ts                   shared statement-stack helpers (scoping, ExpectedRevenue, day math)
  tables/*.ts              the 9 tables (each maps to a real Salesforce object)
  api/groups.ts            the 4 API groups (canonical slugs pinned)
  api/auth.ts              signup / login / me
  api/crm-*.ts             accounts, contacts, leads, stages, board, deals, contact-roles, activities
  api/analytics.ts         dashboard/stats + cumulative forecast
  api/seed.ts              idempotent demo seed
frontend/src/
  lib/api.ts               THE ONE CONTRACT — request paths + types derived from the query defs
  App.tsx + components/    Kanban board, deal drawer, leads view, forecast dashboard

The one contract. frontend/src/lib/api.ts imports the sidestep query defs and derives request paths (getPath()) and request/response types (InferInput / InferResponse). Nothing in the UI hand-types a URL or a request body — change a def and the frontend types follow.


Entities → tables (each maps to a real Salesforce object)

Table Salesforce object Notes
user User + Collaborative Forecast quota reps / managers, role + monthly/quarterly quota; the auth table
account Account
contact Contact AccountId lookup modeled as the account FK
lead Lead + convertLead status, rating, source, is_converted + converted_*_id
pipeline_stage OpportunityStage sort order, default probability, forecast category, is_closed/is_won
deal Opportunity the pipeline record
opportunity_contact_role OpportunityContactRole deal↔contact junction, role + is_primary
deal_stage_history OpportunityHistory from/to stage, amount + probability snapshots, days-in-stage
activity Task + Event consolidated; WhatId→deal, WhoId→contact

Custom logic (each cites its Salesforce source)

  1. Stage-driven probability. Advancing a deal snapshots the stage's default_probability onto deal.probability; a rep can override it. Source: Opportunity Probability"implied, but not directly controlled, by StageName… you can override." (Opportunity object reference)

  2. ExpectedRevenue = Amount × Probability / 100, recomputed on any amount / probability / stage change. Source: Opportunity ExpectedRevenue"the product of the Amount field and the Probability." (Opportunity object reference)

  3. Forecast category from stage (overridable); the Closed Won stage maps to Closed and the Closed Lost stage to Omitted. Source: the standard Stage-to-Forecast-Category mapping. (Forecast Categories)

  4. Cumulative forecast rollup (unweighted raw amounts): Open Pipeline = Pipeline + BestCase + Commit, Best Case = BestCase + Commit + Closed, Commit = Commit + Closed, Closed Only = Closed — plus a separate weighted ExpectedRevenue total. Source: cumulative forecast rollup methods. (Cumulative Forecast Rollups)

  5. Guarded stage transition. No advancing a closed deal; a manager may skip stages, a rep may not (one stage at a time, forward only); every transition writes a deal_stage_history row with days_in_previous_stage. Source: OpportunityHistory + stage validation. (OpportunityHistory, Validation Rules)

  6. Won / Lost close-out. Moving to the is_won / is_lost stage sets is_closed / is_won, forces probability 100 / 0, and stamps actual_close_date; Lost requires a reason. Idempotent (a second call is a no-op). Source: IsClosed / IsWon"directly controlled by StageName." (Opportunity object reference)

  7. LastActivityDate roll-up. The most recent of (latest event due date, latest closed task due date). Source: Opportunity LastActivityDate. (Opportunity object reference)

  8. Kanban attention alerts — the three documented flags: an overdue task, no open activities, and no activity for 30 days. Source: the Opportunity Kanban alerts. (Work with Kanban)

  9. Lead conversion. Creates/links an Account + Contact (and an optional Opportunity), then sets is_converted and the converted_*_id back-references. Source: the convertLead API. (Database.convertLead)

  10. Quota attainment. Per rep: closed-won ÷ quota → attainment %, bucketed into color bands (0 grey / 1–33 red / 34–66 orange / 67+ green). Source: Collaborative Forecast quotas. (Forecast quotas)

As with the seed probabilities, the exact band thresholds and the Kanban alert windows are illustrative choices consistent with the documented behaviors — they demonstrate the mechanic, not a byte-for-byte reproduction of a specific Salesforce org's configuration.


Endpoints

Group Endpoints
auth (/api:auth) signup, login, me
crm (/api:crm) accounts (+create), contacts (+create), leads (+create, lead_convert), stages, board, deals (+deal_get, deal_create, deal_update, deal_advance, deal_win, deal_lose), contact_roles (+add, set-primary), activities (+create, complete)
analytics (/api:analytics) dashboard, forecast
seed (/api:seed) seed (idempotent)

Auth model. user is the auth table with role (rep | manager) and a per-user quota. Reps are scoped to records they own; managers see everything. The scoping is one shared helper (ownerScopedList in xano/lib.ts) applied across every list endpoint, and deal mutations run through an owner/manager access guard.


Learn the library from the library

This backend is authored entirely against the sidestep package's own types:

  • node_modules/@sidestep/core/llms.txt — a compact tour of every builder.
  • The published TypeScript types and JSDoc (node_modules/@sidestep/core/**/*.d.ts).

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages