Getting started
Set up PharmaFlow on your machine, prerequisites, install, environment configuration, demo seed, and running the apps.
This page gets you from a clean machine to a running pharmacy. The goal is a local instance where you can sign in as admin, ring up the demo sale, and see stock move.
Prerequisites
Before you clone the repository, make sure your machine has:
- Bun 1.4.3 - the runtime and package manager, pinned in the root
package.json(packageManager: "bun@1.4.3"). - Node.js 22.12 or newer - required by Blume, the docs tool in
apps/knowledgebase(itspackage.jsondeclaresnode >= 22.12.0). - Git - to clone the repository.
You do not need a Postgres server to run the demo. The demo database is SQLite, and the seed writes the demo file into the packages/database data directory chosen by packages/database/src/paths.ts. Point DATABASE_URL at Postgres only when you want the multi organization tenant schemas described in apps/server/src/core/database/tenancy.ts.
Clone and install
git clone https://github.com/vernonthedev/pharmaflow.git
cd pharmaflow
bun install
Configure your environment
The server reads its config with readEnv in apps/server/src/core/config/env.ts, which reads the Bun runtime env first and process.env second. Copy the examples and fill in the values:
cp apps/server/.env.example apps/server/.env
cp apps/register/.env.example apps/register/.env
JWT_SECRET=<at-least-32-characters-long-random-string>
PORT=8000
LOG_LEVEL=info
TRUST_PROXY=false
apps/server/.env.example documents every key, including JWT_EXPIRE_MINUTES (default 480), ALLOWED_ORIGINS (the default already includes the tauri://localhost desktop origins), LOG_PRETTY, and the AWS_* keys that configure S3 image storage in apps/server/src/core/storage/storage.ts. apps/server/src/core/auth/token.ts refuses to sign tokens with a JWT_SECRET shorter than 32 characters.
You can leave DATABASE_URL empty. The server then opens the SQLite file that resolveDatabaseFile() in packages/database/src/paths.ts resolves inside the packages/database data directory (apps/server/src/core/database/db.ts). Set DATABASE_URL to run against Postgres instead; the server detects the backend with usesPostgres() in apps/server/src/core/database/db.ts.
Seed the demo data
bun --cwd packages/database seed
This deletes and recreates the database at DATABASE_PATH, defaulting to the file defaultTarget in packages/database/src/seed.ts resolves inside the packages/database data directory (packages/database/src/paths.ts). It creates the demo branches, users, medicines, batches, and the DEMO10 coupon. Demo logins are admin@demo.pharmaflow, pharm1@demo.pharmaflow, and pharm2@demo.pharmaflow, all with password Demo@1234.
Run the apps
bun run dev:server
bun run dev:register
bun run dev:knowledgebase
- The API serves
http://localhost:8000, withGET /healthas the smoke check (apps/server/src/index.ts). Every feature route mounts under/api/v1(apps/server/src/app.ts). - The register runs on
http://localhost:3000. - The docs run on the URL Blume prints, with Guides on
/and the API reference on/api(apps/knowledgebase/blume.config.ts). - For the offline desktop app, run
bunx -p @tauri-apps/cli tauri devfrom the repository root.apps/console/tauri.conf.jsonwraps the register UI and itsbeforeDevCommandstarts the register dev server for you.
Root scripts you will use most: bun run dev:server, dev:register, dev:knowledgebase, dev:marketing, dev:app (server plus register through turbo), docs:api (regenerates apps/knowledgebase/openapi.json from the server routes), typecheck, lint, and format (root package.json).