cstudios-slovakia / ccrm
This package is the base for the Cstudios CRM system
Package info
github.com/cstudios-slovakia/ccrm
Language:TypeScript
Type:composer-plugin
pkg:composer/cstudios-slovakia/ccrm
Requires
- php: >=8.0
- composer-plugin-api: ^1.1 || ^2.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- v1.5.104
- v1.5.97
- v1.5.90
- dev-1.9-jackfruit
- dev-1.8-imbe-fix
- dev-1.8-imbe
- dev-1.7-huckleberry
- dev-hotfix/main-aug-fixes
- dev-feature/customer-requests-2026-08
- dev-feature/customer-requests-2026-07
- dev-opus-5-audit
- dev-1.6-grapefruit
- dev-worktree-crystalline-giggling-zebra
- dev-1.6-grapefruit-fix
- dev-dev
- dev-fix/sync-mass-delete-guard
- dev-worktree-task-state-persist
- dev-worktree-excel-lead-import
- dev-fig-tree-patch
- dev-translations-only
- dev-wt-translations
- dev-fig-tree-perf
- dev-fig-tree
- dev-peto
This package is auto-updated.
Last update: 2026-09-18 23:00:11 UTC
README
CCRM is a React + TypeScript + Vite single-page CRM with a small PHP/MySQL backend.
There are two different setups depending on what you're doing — don't mix them up:
- Local development: run the frontend with hot-reload against a Docker backend. No git deploy involved.
- Production deployment: the app is deployed by cloning this repo
directly into the server's web document root and pulling updates with
git/php ccrm update— there is no build step on the server.
New here? Read Local Development Setup, then docs/TESTING.md — how to run the tests, what they cover and where the results go.
Local Development Setup
- Clone the repo and install JS dependencies:
git clone https://github.com/cstudios-slovakia/ccrm.git cd ccrm npm install - Create your local backend config from the sample and point it at the
Docker Compose database (service name
db, credentials fromdocker-compose.yml):cp config.sample.php config.php
Editconfig.php:DB_HOST=db,DB_NAME=ccrm,DB_USER=ccrm_user,DB_PASS=ccrm_password(or whatever you changed those to indocker-compose.yml). - Start the PHP/MySQL backend in Docker (Apache+PHP on
:8080, MySQL on:3306, a MariaDB vector store on:3307for the RAG/AI features):docker compose up -d --build
- Start the Vite dev server:
npm run dev
vite.config.tsproxies/sync.php,/upload.phpand/api/*from the dev server to the Docker container on:8080, so the app behaves like production while the frontend still gets full HMR. - Open the printed
localhostURL. Sinceconfig.phpalready points at a real (empty) database, the setup wizard skips straight to Seed with Demo Data / Start Fresh and admin-account creation.
Production Deployment
The two live instances (laminam.sk, strechyokoc.sk) are both deployed by
cloning this repo straight into the server's document root — not by
requiring it as a Composer dependency of a separate host project. There is no
Node/Vite build step on the server; the compiled frontend is built locally
and committed to dist/, then published to the docroot by php ccrm update.
First-time install on a new server
-
Prerequisites: SSH access to the host; a MySQL/MariaDB database + user already created; PHP ≥ 8.0 (8.2+ recommended) with the
pdo_mysql,imap,zipandcurlextensions enabled;gitandcomposeravailable over SSH. -
SSH in and clone directly into the (empty) docroot — this folder is the install target, not a parent of it:
cd /path/to/docroot git clone https://github.com/cstudios-slovakia/ccrm.git .
-
Install PHP dependencies (generates
vendor/autoload.php; the package itself has no third-party dependencies):composer install --no-dev
-
Publish the built frontend + backend into the docroot. A fresh clone's root
index.htmlis the Vite dev entry (<script src="/src/main.tsx">), which a browser can't execute — you'll get a blank white page if you skip this.dist/*.php(sync.php, api/,.htaccess) are also git-ignored and don't exist yet on a bare clone. Run the update script once to fix both — it refreshesdist/frompublic/and copiesdist/over the docroot root:php ccrm update
(
git pullwill just report "already up to date" on a fresh clone — that's fine, the publish + migrate steps are what you need here.) -
Make sure the web server user can write to the docroot root (the setup wizard creates
config.php/api_key.txtthere) and touploads/. -
Confirm
mod_rewriteandmod_headersare enabled — the shipped.htaccessuses both for SPA routing, security headers, and blocking.git/. -
Open the site URL in a browser. The setup wizard (
api/setup.php) displays automatically:- Enter your MySQL host/port/name/username/password — it test-connects.
- It writes
config.phpand applies the schema migrations. - Choose Seed with Demo Data or Start Fresh.
- Create your system administrator account.
config.php,api_key.txtanduploads/are git-ignored, so future updates never touch them.
Shipping updates after the first install
From your machine:
npm run deploy
(scripts/deploy.mjs) builds dist/, commits it, pushes your working
branch, then advances main (the branch the server pulls).
On the server:
php ccrm update
Checks the licence, pulls origin/main, runs composer install, publishes
dist/ over the docroot, and runs DB migrations — see the ccrm script at the
repo root.
This is the only update path today, and it needs an SSH session on the host.
A design for updating from a button in the UI (and on a schedule) — feasibility,
risks and a staged implementation plan — is written up in
docs/in-app-updates.md. Not implemented yet.
Tracking a different branch on a non-production box
An install updates from the branch it has checked out, so a box put on a
feature branch keeps following that branch with a plain php ccrm update — no
configuration needed. Production sits on main, so nothing changes there.
Every run echoes where the choice came from:
Deploy branch: 1.9-jackfruit (checked-out branch)
To pin a box to a branch other than the one checked out, record it in the checkout's own git config:
git config ccrm.deployBranch 1.6-grapefruit-fix
php ccrm update # -> Deploy branch: 1.6-grapefruit-fix (git config ccrm.deployBranch)
Prefer this over export CCRM_DEPLOY_BRANCH=... in ~/.bashrc: an environment
variable is invisible to cron and to the shell you exported it in, so the next
plain php ccrm update silently reverts to the old branch. git config lives
with the checkout and holds for every invocation. Undo it with
git config --unset ccrm.deployBranch.
CCRM_DEPLOY_BRANCH=<branch> outranks the git config, as a one-off override
for a single run:
CCRM_DEPLOY_BRANCH=main php ccrm update
That precedence is also the one way git config ccrm.deployBranch appears not to
work: if the variable is exported in the shell (a profile, a wrapper script, a
leftover export from an earlier session) it wins on every run in that shell,
and the echoed source line says so:
Deploy branch: 1.9-jackfruit (CCRM_DEPLOY_BRANCH)
If that source is CCRM_DEPLOY_BRANCH when you expected your git config, the
update now prints a warning naming both values. Clear the variable and whatever
exports it:
unset CCRM_DEPLOY_BRANCH grep -n CCRM_DEPLOY_BRANCH ~/.bashrc ~/.bash_profile ~/.profile ~/.zshrc php ccrm update # -> Deploy branch: main (git config ccrm.deployBranch)
The pull is fast-forward only. A deployment checkout has no history of its own, so anything else means the checkout and the branch have genuinely diverged — the update stops and says which branch it is on versus which one it was told to pull, instead of merging an unrelated branch into a live site.
Licensing
An installation needs a valid licence key to receive updates. That is the only thing a licence controls: nothing in the running CRM is disabled by an expired, missing, or revoked licence, and a lapsed customer keeps a fully working app. Ahead of expiry the app shows a dismissible banner, and Settings → Licence is where a key is entered.
php ccrm license status # what is installed, and does it allow updates php ccrm license set <key-or-token> # activate php ccrm license check # force a re-check with the licence server
The licence server is a Craft CMS channel plus a small module, and its answers
are cryptographically signed — so neither a substituted licence server nor an
edit to the CCRM database can mint a licence, and a vendor outage does not stop
a valid customer updating. Full architecture and setup:
docs/licensing/README.md.
A shipped build must have CCRM_LICENSE_PUBLIC_KEY filled in (in both
api/license_client.php and public/api/license_client.php). While it is
empty the product reports "licensing is not configured", shows no banner and
gates nothing.
Legacy: Composer-package consumption
This repo can still be required as a Composer dependency of a separate host
PHP project — src-php/ComposerPlugin.php copies dist/ into the host's
detected (or configured, via extra.ccrm-install-dir/CCRM_INSTALL_DIR) web
root and applies migrations on composer install/update. This was the
original distribution design, but it is not how either current
production instance is deployed, and it isn't actively exercised anymore —
retest it before relying on it if you need this path.
Security notes
- Authentication is verified server-side (
api/login.php) and uses a PHP session; password hashes are never sent to the browser. - Mutating endpoints require an authenticated session; destructive/admin operations require the admin role.
config.php,api_key.txtanduploads/are git-ignored. Never commit real credentials.
Testing
Full guide: docs/TESTING.md.
npm run test:qa:setup # once per machine - downloads Chromium npm run test:qa # audit the app in a real browser npm run test:unit # fast unit tests npm test # both
Two suites:
- Unit tests (
npm run test:unit) — plainnode --testoversrc/**/*.test.ts. No dependencies, runs in under a second. - QA audit (
npm run test:qa) — Playwright drives the real app in Chromium and reports every action whose actual result differed from its expected result, with a screenshot and a proposed fix. Covers navigation, every module, tabs, drill-downs, create/edit forms and every dropdown.
The QA suite mocks /sync.php, /api/* and /upload.php and seeds its own
data, so it needs no Docker, no PHP and no database — just the Vite dev
server, which it starts for you. It never touches a real backend.
Results are saved per run under test-results/runs/<timestamp>-<kind>/
(report + findings + screenshots, self-contained), with the latest always at
test-results/qa-audit-report.md. The verdict prints in your terminal as soon
as the run ends; reopen it any time with npm run test:qa:report.
When to run it: any time you like, and always when you finish a feature or
a fix. It also runs automatically — npm run deploy refuses to ship if the
audit finds a HIGH-severity defect, and GitHub Actions runs it on every push
and pull request.
Development
The database DDL lives in a single source of truth: public/api/schema.php,
copied into dist/api/schema.php by npm run build (the PHP API and
.htaccess live in public/ and are copied into dist/ on build).