Series: Building Quorentra CRM from Zero — A Modular, ChatGPT-Native AI CRM
Creating the canonical Quorentra repository, development environment, backend workspace, frontend workspace, configuration structure, and first reproducible project checkpoint.

1. Introduction
In Part 1, we defined the Quorentra MVP.
In Part 2, we designed the complete technical architecture.
Now we start building.
This article creates the canonical Quorentra project repository that the rest of the series will use.
That makes Part 3 more important than it may initially appear.
A poor project structure creates friction throughout the entire development lifecycle.
It causes problems such as:
- Python import errors;
- unclear module boundaries;
- duplicated configuration;
- misplaced tests;
- frontend/backend confusion;
- inconsistent environment variables;
- accidental secrets in Git;
- difficult Dockerization later;
- unclear paths in tutorial articles.
We are going to prevent those problems early.
The objective of this article is not yet to build the CRM.
The objective is to create a clean, reproducible development foundation.
By the end of this article, we will have:
quorentra/├── backend/├── frontend/├── mcp/├── scripts/├── docs/├── docker/├── .env.example├── .gitignore└── README.md
We will also have:
- Git initialized;
- Python virtual environment created;
- backend workspace prepared;
- frontend workspace prepared;
- environment configuration convention established;
- project paths standardized;
- a known Git checkpoint.
This becomes the baseline for every article that follows.
2. Starting Assumptions
This series assumes a local Windows 11 development environment.
You should have the following installed:
- Git;
- Python;
- Node.js;
- npm;
- PostgreSQL.
Later parts will introduce:
We will not install every future dependency now.
A core principle of this series is:
Install infrastructure when the current development stage actually needs it.
That keeps the project understandable.
3. Choose the Project Location
Choose a directory where you keep development projects.
For example:
C:\Users\<your-user>\Documents\GitHub
Open PowerShell and navigate there:
cd C:\Users\<your-user>\Documents\GitHub
Replace <your-user> with your Windows username.
Create the Quorentra directory:
mkdir quorentra
Enter it:
cd quorentra
Confirm the current directory:
Get-Location
You should see a path ending in:
\quorentra
This directory becomes the repository root.
4. Initialize Git
Initialize the repository:
git init
Check the repository:
git status
You should see that Git is tracking an empty repository.
We will make our first commit later in this article.
5. Define the Canonical Repository Structure
Create the top-level directories:
mkdir backendmkdir frontendmkdir mcpmkdir scriptsmkdir docsmkdir docker
The repository should now look like:
quorentra/├── backend/├── frontend/├── mcp/├── scripts/├── docs/└── docker/
These directories have clear responsibilities.
6. Directory Responsibilities
backend
Contains the Python/FastAPI application.
Eventually:
backend/├── app/└── tests/
The backend will contain:
- API routes;
- domain modules;
- application services;
- persistence logic;
- authentication;
- tenant context;
- AI services;
- workflows.
frontend
Contains the React and TypeScript application.
Eventually:
frontend/└── src/
The frontend will provide the conventional CRM web interface.
mcp
Contains Quorentra’s MCP-facing application layer.
This will later expose CRM capabilities to ChatGPT.
We create the directory now so that the architectural boundary is visible from the start, but we will not implement MCP yet.
scripts
Contains utility scripts.
Examples later may include:
scripts/├── test_connection.py├── seed_data.py└── maintenance/
Scripts are not application modules.
They are developer and operational utilities.
docs
Contains technical project documentation.
Examples:
docs/├── architecture/├── adr/└── development/
Later, Architectural Decision Records can live here.
docker
Contains container-related configuration when Docker is introduced.
We are creating the boundary now but deliberately postponing implementation.
7. Create the Backend Structure
Move into the backend directory:
cd backend
Create the application directory:
mkdir app
Create the test directory:
mkdir tests
The structure becomes:
backend/├── app/└── tests/
Now create the initial Python package file.
From PowerShell:
New-Item app\__init__.py -ItemType File
This file can remain empty for now.
The presence of:
app/__init__.py
makes the app directory an explicit Python package.
That will help keep imports predictable throughout the series.
8. Why the Python Package Structure Matters
Later, we will use imports such as:
from app.main import app
and:
from app.db.session import engine
For those imports to work reliably, we must run Python commands from the correct working directory and maintain a consistent package structure.
Our intended backend structure will evolve toward:
backend/└── app/ ├── __init__.py ├── main.py ├── api/ ├── core/ ├── db/ └── modules/
The backend directory is the Python application workspace.
That means future commands such as:
pytest
or:
uvicorn app.main:app --reload
will generally be executed from:
quorentra\backend
This is a convention we will keep throughout the series.
9. Create the Python Virtual Environment
Still inside:
quorentra\backend
create a virtual environment:
python -m venv .venv
The backend structure becomes:
backend/├── .venv/├── app/└── tests/
Activate the environment:
.\.venv\Scripts\Activate.ps1
Your PowerShell prompt should now begin with something similar to:
(.venv)
For example:
(.venv) PS C:\Users\<your-user>\Documents\GitHub\quorentra\backend>
10. If PowerShell Blocks Virtual Environment Activation
Some Windows installations prevent PowerShell scripts from running.
If you see an execution-policy error, inspect the current policy:
Get-ExecutionPolicy
A common development configuration is:
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
Then retry:
.\.venv\Scripts\Activate.ps1
Only change PowerShell execution policy if you understand and accept the implications for your environment.
Alternatively, Command Prompt can activate the environment with:
.venv\Scripts\activate.bat
11. Verify the Python Interpreter
Run:
python --version
Then:
where.exe python
The first Python path should point into:
backend\.venv\Scripts\python.exe
This verifies that the virtual environment is active.
This is especially important when working in VS Code.
A common cause of unresolved imports is that VS Code uses a different Python interpreter from the terminal.
Later, when opening the project in VS Code, make sure the selected interpreter is:
quorentra\backend\.venv\Scripts\python.exe
12. Upgrade pip
Upgrade the package installer inside the virtual environment:
python -m pip install --upgrade pip
Confirm:
pip --version
We now have an isolated Python environment ready for FastAPI dependencies in the next article.
13. Do Not Install FastAPI Yet
It may seem natural to install:
fastapiuvicornsqlalchemyalembicpsycopg
immediately.
We are deliberately not doing that yet.
Part 4 will introduce the first FastAPI application and install exactly the backend packages required for that checkpoint.
This keeps the dependency history understandable.
Each dependency should have a reason for existing.
14. Return to the Repository Root
Deactivate the virtual environment if desired:
deactivate
Return to the repository root:
cd ..
You should now be back at:
quorentra
15. Prepare the Frontend Workspace
We are not creating the full React application yet.
That will happen in the dedicated frontend foundation article.
For now, create a placeholder README:
New-Item frontend\README.md -ItemType File
Later, Vite will populate the directory with the React project.
Why not initialize React immediately?
Because we want each article to have one primary concern.
Part 3 establishes the repository and environment.
The frontend article will establish React properly, verify Node/npm versions, explain the generated structure, and connect the application to FastAPI.
16. Prepare the MCP Workspace
Create a placeholder file:
New-Item mcp\README.md -ItemType File
Eventually this directory will contain the ChatGPT-facing MCP implementation.
For now, it documents an intentional architectural boundary.
17. Prepare the Documentation Structure
Create architecture and ADR directories:
mkdir docs\architecturemkdir docs\adrmkdir docs\development
The structure becomes:
docs/├── architecture/├── adr/└── development/
18. Architectural Decision Records
ADR stands for Architectural Decision Record.
We identified several important decisions in Part 2.
Examples include:
ADR-001 Modular Monolith FirstADR-002 PostgreSQL as System of RecordADR-003 Shared Schema Multi-TenancyADR-004 Application Services Own Use CasesADR-005 Thin InterfacesADR-006 React Is Not the Business LayerADR-007 MCP Is Not a Second BackendADR-008 ChatGPT Is a First-Class Interface
We do not need to create all ADR documents today.
But the location already exists:
docs/adr/
As architectural choices become concrete during implementation, we can record them there.
19. Create the Environment File Strategy
At the repository root, create:
New-Item .env.example -ItemType File
The .env.example file contains configuration names but no secrets.
For now, add:
APP_ENV=developmentBACKEND_HOST=127.0.0.1BACKEND_PORT=8000FRONTEND_HOST=127.0.0.1FRONTEND_PORT=5173
We will add database settings when PostgreSQL integration is implemented.
Later, this file may grow to contain names such as:
DATABASE_URL=SECRET_KEY=OPENAI_API_KEY=
But real secret values should never be stored in .env.example.
20. Local .env
Create the actual local environment file:
Copy-Item .env.example .env
You now have:
.env.env.example
The difference is important.
.env.example
Safe to commit.
Contains example configuration names.
.env
Local machine configuration.
May contain secrets.
Must not be committed.
21. Create .gitignore
At the repository root:
New-Item .gitignore -ItemType File
Add:
# Environment.env# Python__pycache__/*.py[cod]*.pyo*.pyd.Python.pytest_cache/.mypy_cache/.ruff_cache/.coveragehtmlcov/# Virtual environments.venv/venv/# Nodenode_modules/dist/.vite/# IDEs.vscode/.idea/# OS files.DS_StoreThumbs.db# Logs*.log# Temporary files*.tmp*.temp# Coveragecoverage/# Buildbuild/# Local database or runtime artifacts*.db
This prevents common development artifacts from being committed accidentally.
22. Should .vscode Always Be Ignored?
Not necessarily.
Some projects intentionally commit:
.vscode/settings.json.vscode/extensions.json
to standardize the development environment.
For the MVP, we will initially ignore .vscode.
Later, if we decide that shared workspace settings add value, we can explicitly include selected files.
23. Create the Root README
At the repository root:
New-Item README.md -ItemType File
Add:
QuorentraQuorentra is a modular, ChatGPT-native AI CRM.This repository accompanies the series:Building Quorentra CRM from Zero — A Modular, ChatGPT-Native AI CRM ArchitectureQuorentra is designed around: React TypeScript FastAPI PostgreSQL SQLAlchemy Alembic MCP OpenAI Apps SDK ChatGPT pgvectorThe system follows a modular-monolith architecture for the MVP.Quorentra remains the system of record, while ChatGPT acts as a first-class intelligent interaction layer. Repository Structuretextquorentra/├── backend/├── frontend/├── mcp/├── scripts/├── docs/├── docker/├── .env.example├── .gitignore└── README.md
Development Status
Current milestone:
Project foundation
Next milestone:
Minimum FastAPI application
This README will evolve with the project.
---
# 24. Create the Initial Backend README
Add useful context inside:
```text
backend/README.md
From the repository root:
New-Item backend\README.md -ItemType File
Add:
Quorentra BackendThe Quorentra backend is built with Python and FastAPI.Application package:textbackend/app/
Tests:
backend/tests/
Backend commands should generally be run from:
quorentra/backend
This small piece of documentation helps prevent working-directory confusion later.
---
# 25. Update the Frontend README
Edit:
```text
frontend/README.md
and add:
Quorentra FrontendThe Quorentra frontend will be built with React, TypeScript, and Vite.The frontend will provide the conventional CRM web application.ChatGPT will act as a separate first-class interaction surface through the Quorentra MCP and Apps SDK integration.
26. Update the MCP README
Edit:
mcp/README.md
and add:
Quorentra MCPThis directory will contain the Model Context Protocol integration used to expose approved Quorentra capabilities to ChatGPT.MCP is an interface layer.It must not bypass Quorentra application services, authorization, tenant isolation, or business rules.
This documents one of the most important architecture rules from Part 2 directly inside the repository.
27. Add a Scripts README
Create:
New-Item scripts\README.md -ItemType File
Add:
Quorentra ScriptsThis directory contains developer and operational utility scripts.Examples may later include: database connectivity tests; development setup utilities; seed-data scripts; migration helpers; maintenance scripts.Scripts should import Quorentra application code through the canonical backend package structure.
28. The Repository Structure So Far
Your repository should now resemble:
quorentra/│├── backend/│ ├── .venv/│ ├── app/│ │ └── __init__.py│ ├── tests/│ └── README.md│├── frontend/│ └── README.md│├── mcp/│ └── README.md│├── scripts/│ └── README.md│├── docs/│ ├── architecture/│ ├── adr/│ └── development/│├── docker/│├── .env├── .env.example├── .gitignore└── README.md
Remember:
backend/.venv/.env
exist locally but should not appear in Git.
29. Verify .gitignore
Run:
git status
You should see files such as:
.env.example.gitignoreREADME.mdbackend/frontend/mcp/scripts/
You should not see:
.envbackend/.venv/
If you do, stop and correct .gitignore before committing.
30. Check Python from VS Code
If you use VS Code, open the project from the repository root:
code .
Then use:
Ctrl + Shift + P
Search for:
Python: Select Interpreter
Select:
backend\.venv\Scripts\python.exe
This will become important once FastAPI imports are introduced.
A wrong interpreter can produce errors such as:
Import "fastapi" could not be resolved
even when FastAPI is installed correctly in the project virtual environment.
31. Working Directory Convention
We should establish this rule now.
Repository-level commands
Run from:
quorentra/
Examples:
git statusgit add .git commit
Backend commands
Run from:
quorentra/backend/
Examples later:
pytestuvicorn app.main:app --reloadalembic upgrade head
Frontend commands
Run from:
quorentra/frontend/
Examples later:
npm installnpm run devnpm run build
This convention will eliminate a large class of avoidable path errors.
32. Why from app... Sometimes Fails
Suppose later we have:
from app.main import app
and run a script from:
quorentra/
Python may not know that:
quorentra/backend
is the import root.
But when running from:
quorentra/backend
Python sees:
app/
directly.
Therefore:
from app.main import app
works naturally.
This is why our command-location convention matters.
We will also design scripts and tests carefully so developers do not have to constantly manipulate PYTHONPATH.
33. Do Not Add sys.path Hacks
A common workaround is to add code like:
import syssys.path.append(...)
to make imports work.
We should avoid this.
If imports fail, the first questions should be:
- Is the Python interpreter correct?
- Is the command being run from the intended directory?
- Is the package structure correct?
- Is the module actually installed or importable?
Path manipulation should be the exception, not the architecture.
34. Verify Git
Run:
git status
Review every file that will be committed.
Then stage the foundation:
git add .
Check again:
git status
Make sure .env and .venv are absent.
35. First Git Commit
Create the first project checkpoint:
git commit -m "chore: initialize Quorentra project structure"
If Git asks for your identity, configure it:
git config --global user.name "Your Name"git config --global user.email "your-email@example.com"
Then retry the commit.
36. Create a Development Branch Strategy
For a small MVP project, we do not need an elaborate GitFlow model.
A simple strategy is sufficient.
Keep:
main
stable.
Use short-lived feature branches when appropriate:
feature/fastapi-foundationfeature/database-foundationfeature/react-foundationfeature/company-module
For solo development, direct development on main is possible, but feature branches become increasingly useful as the system grows.
The important point is not process complexity.
It is maintaining meaningful checkpoints.
37. Optional: Create a Remote GitHub Repository
If you want Quorentra hosted on GitHub, create an empty repository named:
quorentra
Do not initialize it with another README if the local repository already contains one.
Then connect the remote:
git remote add origin <repository-url>
Verify:
git remote -v
Push:
git branch -M maingit push -u origin main
The repository is now backed up remotely.
38. Version the Project
We will use milestone-style versions throughout the series.
The current codebase is not yet MVO 0.1.
It is the project foundation.
We can think of it as:
Quorentra 0.0.1
The next milestones will gradually become:
0.0.2 — FastAPI running0.0.3 — PostgreSQL connected0.0.4 — React running0.1.0 — MVO complete
Exact version numbers may evolve, but milestone thinking is useful.
It ensures that each article produces a clearly identifiable state.
39. Verify the Complete Project
Before concluding the article, verify the repository.
From:
quorentra/
run:
git status
Expected result:
nothing to commit, working tree clean
Then verify the backend environment:
cd backend.\.venv\Scripts\Activate.ps1python --version
Verify pip:
pip --version
Then deactivate:
deactivate
Return to the root:
cd ..
At this point, the foundation is complete.
40. Acceptance Criteria
Part 3 is complete when all of the following are true:
✓ Quorentra repository exists✓ Git is initialized✓ Canonical top-level directories exist✓ backend/app is a Python package✓ Python virtual environment works✓ VS Code can use the project interpreter✓ frontend workspace exists✓ MCP workspace exists✓ documentation directories exist✓ .env.example exists✓ local .env is ignored✓ .venv is ignored✓ README files document responsibilities✓ Git working tree is clean✓ First commit exists
No CRM functionality exists yet.
That is intentional.
We have created the foundation on which the CRM will be built.
41. Troubleshooting
python Is Not Recognized
Verify that Python is installed and available in PATH:
python --version
If not, reinstall Python or correct the Windows PATH configuration.
code Is Not Recognized
The VS Code command-line launcher may not be installed in PATH.
You can still open the project manually in VS Code using:
File → Open Folder
and select the quorentra directory.
Virtual Environment Will Not Activate
Check PowerShell execution policy:
Get-ExecutionPolicy
Or use Command Prompt:
.venv\Scripts\activate.bat
Wrong Python Interpreter in VS Code
Use:
Ctrl + Shift + P→ Python: Select Interpreter
and select:
backend\.venv\Scripts\python.exe
.env Appears in git status
Check that .gitignore contains:
.env
If .env was already staged:
git restore --staged .env
If it had previously been committed, additional Git cleanup will be required.
Never push secrets to a public repository.
.venv Appears in Git
Make sure .gitignore includes:
.venv/
If necessary:
git restore --staged backend/.venv
42. What We Deliberately Did Not Do
Part 3 did not:
- install FastAPI;
- create
main.py; - install SQLAlchemy;
- connect PostgreSQL;
- configure Alembic;
- create React with Vite;
- configure MCP;
- configure OpenAI;
- create CRM tables;
- write business logic.
This restraint is intentional.
The project now has a stable base, and every following article can introduce one coherent capability.
43. The Development State
Our development path currently looks like:
Architecture ✓ │Repository ✓ │FastAPI ↓PostgreSQL ↓React ↓Identity ↓CRM ↓ChatGPT ↓AI
We have reached the first implementation checkpoint.
44. Next Article
In Part 4, we will create the first running FastAPI application.
We will install the minimum backend dependencies, introduce:
backend/└── app/ ├── __init__.py └── main.py
and build the first endpoint:
GET /api/v1/health
The acceptance criterion will be simple:
HTTP 200 OK
with a structured response showing that the Quorentra API is running.
We will also establish:
- FastAPI application creation;
- API versioning;
- development server execution;
- basic application metadata;
- a first automated API test;
- the canonical Uvicorn command;
- correct Python import behavior.
Part 4 will therefore deliver the first actual running Quorentra component:
Developer │ ▼FastAPI │ ▼/api/v1/health
From that point forward, Quorentra is no longer just an architecture.
It is running software.