Complete rebrand from Apoklisis to Patherly

- Update all frontend branding (title, headers, login/register pages)
- Update documentation (CLAUDE-SETUP, CURRENT-STATE, PROGRESS, LESSONS-LEARNED)
- Update backend scripts and test configuration
- Fix emoji encoding in seed scripts for Windows compatibility
- Sync seed user credentials between seed_data.py and seed_trees.py
- Update database references to patherly/patherly_test

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-01-31 21:55:55 -05:00
parent 06cc83e3fe
commit 2421f10dbd
16 changed files with 60 additions and 60 deletions

View File

@@ -12,7 +12,7 @@
"Bash(git add:*)", "Bash(git add:*)",
"Bash(git commit:*)", "Bash(git commit:*)",
"Bash(git push:*)", "Bash(git push:*)",
"Bash(dir /b \"C:\\\\Dev\\\\Projects\\\\Apoklisis\")", "Bash(dir /b \"C:\\\\Dev\\\\Projects\\\\patherly\")",
"Bash(npm create:*)", "Bash(npm create:*)",
"Bash(npm install:*)", "Bash(npm install:*)",
"Bash(npx tailwindcss:*)", "Bash(npx tailwindcss:*)",

View File

@@ -1,10 +1,10 @@
# Claude Code Setup Reference for Apoklisis # Claude Code Setup Reference for Patherly
This document catalogs all tools, plugins, and MCP servers available to Claude Code when developing Apoklisis, along with guidelines for their effective use. This document catalogs all tools, plugins, and MCP servers available to Claude Code when developing Patherly, along with guidelines for their effective use.
**Last Updated**: 2026-01-29 **Last Updated**: 2026-01-29
**Project**: Apoklisis **Project**: Patherly
**Working Directory**: `c:\Dev\Projects\Apoklisis` **Working Directory**: `c:\Dev\Projects\patherly`
**Platform**: Windows (win32) **Platform**: Windows (win32)
**IDE**: VSCode with Claude Code extension **IDE**: VSCode with Claude Code extension
@@ -289,8 +289,8 @@ These tools must be loaded via ToolSearch before use.
**Connection Details**: **Connection Details**:
- **Connection String**: `postgresql://postgres:postgres@localhost:5432/apoklisis` - **Connection String**: `postgresql://postgres:postgres@localhost:5432/patherly`
- **Container Name**: `apoklisis_postgres` - **Container Name**: `patherly_postgres`
- **Database Version**: PostgreSQL 16 Alpine - **Database Version**: PostgreSQL 16 Alpine
- **Docker Requirement**: Docker Desktop must be running - **Docker Requirement**: Docker Desktop must be running
@@ -362,11 +362,11 @@ curl -X GET "http://localhost:8000/api/v1/trees" -H "Authorization: Bearer <toke
--- ---
## Project-Specific Context: Apoklisis ## Project-Specific Context: Patherly
### Project Overview ### Project Overview
**Apoklisis** is a troubleshooting decision tree web application designed for MSP (Managed Service Provider) engineers. The application allows engineers to create, manage, and navigate through decision trees for common IT support scenarios, improving troubleshooting consistency and efficiency. **Patherly** is a troubleshooting decision tree web application designed for MSP (Managed Service Provider) engineers. The application allows engineers to create, manage, and navigate through decision trees for common IT support scenarios, improving troubleshooting consistency and efficiency.
### Technology Stack ### Technology Stack
@@ -378,7 +378,7 @@ curl -X GET "http://localhost:8000/api/v1/trees" -H "Authorization: Bearer <toke
- **Authentication**: JWT tokens (15-min access, 7-day refresh) - **Authentication**: JWT tokens (15-min access, 7-day refresh)
- **Password Hashing**: bcrypt (via passlib, pinned to 4.1.2 for compatibility) - **Password Hashing**: bcrypt (via passlib, pinned to 4.1.2 for compatibility)
- **API Endpoints**: 18 RESTful endpoints - **API Endpoints**: 18 RESTful endpoints
- **Containerization**: Docker (apoklisis_postgres container) - **Containerization**: Docker (patherly_postgres container)
- **Migrations**: Alembic - **Migrations**: Alembic
**Frontend (Complete + Tree Editor)**: **Frontend (Complete + Tree Editor)**:
@@ -543,10 +543,10 @@ uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
**Database Connection**: **Database Connection**:
- **Host**: localhost:5432 - **Host**: localhost:5432
- **Database**: apoklisis - **Database**: patherly
- **User**: postgres - **User**: postgres
- **Password**: postgres - **Password**: postgres
- **Container**: apoklisis_postgres - **Container**: patherly_postgres
### Recent Work & Git History ### Recent Work & Git History

View File

@@ -151,7 +151,7 @@ frontend/
### Documentation ### Documentation
``` ```
Apoklisis/ patherly/
├── CLAUDE-SETUP.md # Full context for Claude Code ├── CLAUDE-SETUP.md # Full context for Claude Code
├── CURRENT-STATE.md # This file - quick status ├── CURRENT-STATE.md # This file - quick status
├── LESSONS-LEARNED.md # Bugs and fixes reference ├── LESSONS-LEARNED.md # Bugs and fixes reference
@@ -169,15 +169,15 @@ Apoklisis/
### Start Development ### Start Development
```powershell ```powershell
# Terminal 1: Database # Terminal 1: Database
docker start apoklisis_postgres docker start patherly_postgres
# Terminal 2: Backend # Terminal 2: Backend
cd C:\Dev\Projects\Apoklisis\backend cd C:\Dev\Projects\patherly\backend
.\venv\Scripts\activate .\venv\Scripts\activate
uvicorn app.main:app --reload uvicorn app.main:app --reload
# Terminal 3: Frontend # Terminal 3: Frontend
cd C:\Dev\Projects\Apoklisis\frontend cd C:\Dev\Projects\patherly\frontend
npm run dev npm run dev
``` ```
@@ -188,7 +188,7 @@ npm run dev
### Run Tests ### Run Tests
```powershell ```powershell
cd C:\Dev\Projects\Apoklisis\backend cd C:\Dev\Projects\patherly\backend
.\venv\Scripts\activate .\venv\Scripts\activate
pytest pytest
``` ```

View File

@@ -11,12 +11,12 @@
### Database Name Mismatch After Fresh Clone ### Database Name Mismatch After Fresh Clone
**Problem:** After cloning the repo and running `docker-compose up -d`, Alembic migrations fail with `database "decision_tree" does not exist`. **Problem:** After cloning the repo and running `docker-compose up -d`, Alembic migrations fail with `database "decision_tree" does not exist`.
**Cause:** The `.env` file contains the old database name (`decision_tree`) but `docker-compose.yml` creates a database called `apoklisis`. **Cause:** The `.env` file contains the old database name (`decision_tree`) but `docker-compose.yml` creates a database called `patherly`.
**Solution:** Update `.env` to use the correct database name: **Solution:** Update `.env` to use the correct database name:
``` ```
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/apoklisis DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/patherly
DATABASE_URL_SYNC=postgresql://postgres:postgres@localhost:5432/apoklisis DATABASE_URL_SYNC=postgresql://postgres:postgres@localhost:5432/patherly
``` ```
**Files affected:** `backend/.env` **Files affected:** `backend/.env`
@@ -57,7 +57,7 @@ When setting up development on a new machine:
1. **Clone repo:** `git clone <repo-url>` 1. **Clone repo:** `git clone <repo-url>`
2. **Start Docker Desktop** 2. **Start Docker Desktop**
3. **Start database:** `cd backend && docker-compose up -d` 3. **Start database:** `cd backend && docker-compose up -d`
4. **Fix .env database name** if it says `decision_tree` → change to `apoklisis` 4. **Fix .env database name** if it says `decision_tree` → change to `patherly`
5. **Create venv:** `python -m venv venv` 5. **Create venv:** `python -m venv venv`
6. **Activate venv:** `.\venv\Scripts\Activate` 6. **Activate venv:** `.\venv\Scripts\Activate`
7. **Install backend deps:** `pip install -r requirements.txt` 7. **Install backend deps:** `pip install -r requirements.txt`
@@ -422,13 +422,13 @@ module.exports = {
**Solution:** Use Docker exec to run psql inside the container: **Solution:** Use Docker exec to run psql inside the container:
```powershell ```powershell
# Single command # Single command
docker exec -it apoklisis_postgres psql -U postgres -c "SELECT * FROM users;" docker exec -it patherly_postgres psql -U postgres -c "SELECT * FROM users;"
# Interactive session # Interactive session
docker exec -it apoklisis_postgres psql -U postgres docker exec -it patherly_postgres psql -U postgres
# Create database # Create database
docker exec -it apoklisis_postgres psql -U postgres -c "CREATE DATABASE apoklisis_test;" docker exec -it patherly_postgres psql -U postgres -c "CREATE DATABASE patherly_test;"
``` ```
--- ---
@@ -439,7 +439,7 @@ docker exec -it apoklisis_postgres psql -U postgres -c "CREATE DATABASE apoklisi
**Solution:** Check and start the container: **Solution:** Check and start the container:
```powershell ```powershell
docker ps # See running containers docker ps # See running containers
docker start apoklisis_postgres # Start if stopped docker start patherly_postgres # Start if stopped
``` ```
--- ---
@@ -451,7 +451,7 @@ docker start apoklisis_postgres # Start if stopped
**Solution:** Always run git commands from project root: **Solution:** Always run git commands from project root:
```powershell ```powershell
cd C:\Dev\Projects\Apoklisis cd C:\Dev\Projects\patherly
git add . git add .
git commit -m "Your message" git commit -m "Your message"
git push origin main git push origin main
@@ -512,7 +512,7 @@ decision = {
**One-time setup:** **One-time setup:**
```powershell ```powershell
docker exec -it apoklisis_postgres psql -U postgres -c "CREATE DATABASE apoklisis_test;" docker exec -it patherly_postgres psql -U postgres -c "CREATE DATABASE patherly_test;"
``` ```
**Run tests:** **Run tests:**
@@ -560,7 +560,7 @@ pip install httpx
**Solution:** Use a standard domain like `example.com` for seed/test users: **Solution:** Use a standard domain like `example.com` for seed/test users:
```python ```python
# BAD # BAD
"email": "seed.admin@apoklisis.local" "email": "seed.admin@patherly.local"
# GOOD # GOOD
"email": "seed.admin@example.com" "email": "seed.admin@example.com"

View File

@@ -14,7 +14,7 @@ Use this for personal thoughts, todos, and reminders.
- [ ] Answer the 5 key questions in docs/05-QUESTIONS-AND-ACTION-ITEMS.md - [ ] Answer the 5 key questions in docs/05-QUESTIONS-AND-ACTION-ITEMS.md
- [ ] Decide on app name (TroubleTree? DecisionPath? MSP Navigator?) - [ ] Decide on app name (TroubleTree? DecisionPath? MSP Navigator?)
- [ ] Set up Render account for free tier testing - [ ] Set up Render account for free tier testing
- [ ] Add Apoklisis.com to my namecheap account for dynamic dns - [ ] Add patherly.com to my namecheap account for dynamic dns
## 💡 Feature Ideas (Future) ## 💡 Feature Ideas (Future)

View File

@@ -434,7 +434,7 @@ Public and team steps can be rated by users to help surface the most helpful con
│ ○ 🌍 Public - Submit to community library │ │ ○ 🌍 Public - Submit to community library │
│ │ │ │
│ ┌─────────────────────────────────────────────────────────┐│ │ ┌─────────────────────────────────────────────────────────┐│
│ │ 🔗 https://apoklisis.app/tree/abc123xyz ││ │ │ 🔗 https://patherly.app/tree/abc123xyz ││
│ │ [📋 Copy] ││ │ │ [📋 Copy] ││
│ └─────────────────────────────────────────────────────────┘│ │ └─────────────────────────────────────────────────────────┘│
│ │ │ │

View File

@@ -1,4 +1,4 @@
# Project Apoklisis - Development Progress # Project Patherly - Development Progress
**Last Updated**: January 29, 2026 **Last Updated**: January 29, 2026
**Current Phase**: Phase 2 Frontend - COMPLETE & TESTED **Current Phase**: Phase 2 Frontend - COMPLETE & TESTED
@@ -17,7 +17,7 @@ Building a troubleshooting decision tree web application for MSP engineers. The
--- ---
# Apoklisis Development Progress # Patherly Development Progress
> 📚 **Reference**: See [CLAUDE-SETUP.md](./CLAUDE-SETUP.md) for available > 📚 **Reference**: See [CLAUDE-SETUP.md](./CLAUDE-SETUP.md) for available
> development tools and usage guidelines > development tools and usage guidelines
@@ -146,7 +146,7 @@ New files:
**Created** full test suite with 29 integration tests (all passing): **Created** full test suite with 29 integration tests (all passing):
- **Test Framework**: pytest 7.4.3 with pytest-asyncio 0.23.0 - **Test Framework**: pytest 7.4.3 with pytest-asyncio 0.23.0
- **Test Database**: Separate PostgreSQL test database (`apoklisis_test`) - **Test Database**: Separate PostgreSQL test database (`patherly_test`)
- **Coverage**: Auth, Trees, and Sessions endpoints - **Coverage**: Auth, Trees, and Sessions endpoints
- **Fixtures**: Reusable test user, admin user, auth headers, and test tree fixtures - **Fixtures**: Reusable test user, admin user, auth headers, and test tree fixtures
@@ -272,7 +272,7 @@ backend/
psql -U postgres -h localhost psql -U postgres -h localhost
# Create test database # Create test database
CREATE DATABASE apoklisis_test; CREATE DATABASE patherly_test;
\q \q
``` ```

View File

@@ -1,5 +1,5 @@
[pytest] [pytest]
# Pytest configuration for Apoklisis backend tests # Pytest configuration for Patherly backend tests
# Python path - add current directory so 'app' module can be imported # Python path - add current directory so 'app' module can be imported
pythonpath = . pythonpath = .

View File

@@ -1 +1 @@
# Apoklisis scripts package # Patherly scripts package

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
Seed data script for Apoklisis decision trees. Seed data script for Patherly decision trees.
This script creates example troubleshooting trees in the database. This script creates example troubleshooting trees in the database.
Run from the backend directory with: python -m scripts.seed_data Run from the backend directory with: python -m scripts.seed_data
@@ -276,7 +276,7 @@ def get_password_reset_tree() -> dict[str, Any]:
{ {
"id": "resolution_success", "id": "resolution_success",
"type": "solution", "type": "solution",
"title": " Password Reset Complete", "title": "[OK] Password Reset Complete",
"description": "User has successfully logged in with their new password.\n\n**Final Steps:**\n1. Confirm user was prompted to change their password\n2. Verify user successfully set a new personal password\n3. Document the resolution in the ticket\n4. Close the ticket as 'Resolved'\n\n**Resolution Indicators:**\n- User confirms successful login\n- Account shows updated 'Last Logon' timestamp\n- No subsequent lockouts or reset requests" "description": "User has successfully logged in with their new password.\n\n**Final Steps:**\n1. Confirm user was prompted to change their password\n2. Verify user successfully set a new personal password\n3. Document the resolution in the ticket\n4. Close the ticket as 'Resolved'\n\n**Resolution Indicators:**\n- User confirms successful login\n- Account shows updated 'Last Logon' timestamp\n- No subsequent lockouts or reset requests"
} }
] ]
@@ -386,7 +386,7 @@ async def create_tree(client: httpx.AsyncClient, token: str, tree_data: dict) ->
existing_trees = list_response.json() existing_trees = list_response.json()
for tree in existing_trees: for tree in existing_trees:
if tree["name"] == tree_data["name"]: if tree["name"] == tree_data["name"]:
print(f" ⏭️ Tree '{tree_data['name']}' already exists (ID: {tree['id']})") print(f" [SKIP] Tree '{tree_data['name']}' already exists (ID: {tree['id']})")
return tree return tree
# Create the tree # Create the tree
@@ -400,13 +400,13 @@ async def create_tree(client: httpx.AsyncClient, token: str, tree_data: dict) ->
raise Exception(f"Failed to create tree '{tree_data['name']}': {response.text}") raise Exception(f"Failed to create tree '{tree_data['name']}': {response.text}")
tree = response.json() tree = response.json()
print(f" Created tree '{tree_data['name']}' (ID: {tree['id']})") print(f" [OK] Created tree '{tree_data['name']}' (ID: {tree['id']})")
return tree return tree
async def seed_database(): async def seed_database():
"""Main seeding function.""" """Main seeding function."""
print("\n🌱 Apoklisis Database Seeder") print("\n[*] Patherly Database Seeder")
print("=" * 50) print("=" * 50)
async with httpx.AsyncClient(timeout=30.0) as client: async with httpx.AsyncClient(timeout=30.0) as client:
@@ -414,25 +414,25 @@ async def seed_database():
try: try:
health_check = await client.get(f"{API_BASE_URL.replace('/api/v1', '')}/health") health_check = await client.get(f"{API_BASE_URL.replace('/api/v1', '')}/health")
except httpx.ConnectError: except httpx.ConnectError:
print("\n Error: Cannot connect to API server") print("\n[ERROR] Error: Cannot connect to API server")
print(f" Make sure the server is running at {API_BASE_URL}") print(f" Make sure the server is running at {API_BASE_URL}")
print(" Run: uvicorn app.main:app --reload") print(" Run: uvicorn app.main:app --reload")
return False return False
# Get or create admin user # Get or create admin user
print("\n📋 Setting up seed user...") print("\n[1/2] Setting up seed user...")
try: try:
token, user_info = await get_or_create_admin_user(client) token, user_info = await get_or_create_admin_user(client)
if user_info.get("exists"): if user_info.get("exists"):
print(" Using existing seed admin user") print(" [OK] Using existing seed admin user")
else: else:
print(f" Created seed admin user: {SEED_USER['email']}") print(f" [OK] Created seed admin user: {SEED_USER['email']}")
except Exception as e: except Exception as e:
print(f" Failed to setup seed user: {e}") print(f" [ERROR] Failed to setup seed user: {e}")
return False return False
# Create trees # Create trees
print("\n🌳 Creating decision trees...") print("\n[2/2] Creating decision trees...")
trees_to_create = [ trees_to_create = [
get_password_reset_tree(), get_password_reset_tree(),
@@ -445,11 +445,11 @@ async def seed_database():
tree = await create_tree(client, token, tree_data) tree = await create_tree(client, token, tree_data)
created_trees.append(tree) created_trees.append(tree)
except Exception as e: except Exception as e:
print(f" Failed to create '{tree_data['name']}': {e}") print(f" [ERROR] Failed to create '{tree_data['name']}': {e}")
# Summary # Summary
print("\n" + "=" * 50) print("\n" + "=" * 50)
print(f" Seeding complete! Created {len(created_trees)} trees.") print(f"[OK] Seeding complete! Created {len(created_trees)} trees.")
print("\nCreated trees:") print("\nCreated trees:")
for tree in created_trees: for tree in created_trees:
print(f" - {tree['name']} ({tree['category']})") print(f" - {tree['name']} ({tree['category']})")
@@ -458,7 +458,7 @@ async def seed_database():
def main(): def main():
parser = argparse.ArgumentParser(description="Seed the Apoklisis database with example trees") parser = argparse.ArgumentParser(description="Seed the Patherly database with example trees")
parser.add_argument("--direct", action="store_true", help="Insert directly to database (not implemented)") parser.add_argument("--direct", action="store_true", help="Insert directly to database (not implemented)")
args = parser.parse_args() args = parser.parse_args()

View File

@@ -2,7 +2,7 @@
""" """
Comprehensive MSP/SMB Troubleshooting Decision Trees Seed Script. Comprehensive MSP/SMB Troubleshooting Decision Trees Seed Script.
This script populates Apoklisis with realistic troubleshooting decision trees This script populates Patherly with realistic troubleshooting decision trees
covering common Tier 1, Tier 2, and Tier 3 support scenarios. covering common Tier 1, Tier 2, and Tier 3 support scenarios.
Run from the backend directory with: python -m scripts.seed_trees Run from the backend directory with: python -m scripts.seed_trees
@@ -23,8 +23,8 @@ API_BASE_URL = "http://localhost:8000/api/v1"
# Default admin user for seeding # Default admin user for seeding
SEED_USER = { SEED_USER = {
"email": "seed.admin@example.com", "email": "seed.admin@example.com",
"password": "SeedAdmin2024!Secure", "password": "SeedAdmin123!",
"name": "Seed Administrator", "name": "Seed Admin",
"role": "admin" "role": "admin"
} }
@@ -3374,7 +3374,7 @@ async def create_tree(client: httpx.AsyncClient, token: str, tree_data: dict) ->
async def seed_database(): async def seed_database():
"""Main seeding function.""" """Main seeding function."""
print("\n" + "=" * 60) print("\n" + "=" * 60)
print(" APOKLISIS - MSP/SMB Troubleshooting Trees Seeder") print(" PATHERLY - MSP/SMB Troubleshooting Trees Seeder")
print("=" * 60) print("=" * 60)
async with httpx.AsyncClient(timeout=60.0) as client: async with httpx.AsyncClient(timeout=60.0) as client:
@@ -3453,7 +3453,7 @@ async def seed_database():
def main(): def main():
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="Seed the Apoklisis database with MSP/SMB troubleshooting trees" description="Seed the Patherly database with MSP/SMB troubleshooting trees"
) )
parser.add_argument( parser.add_argument(
"--api-url", "--api-url",

View File

@@ -17,7 +17,7 @@ from app.core.config import settings
# Test database URL (separate from production) # Test database URL (separate from production)
TEST_DATABASE_URL = "postgresql+asyncpg://postgres:postgres@localhost:5432/apoklisis_test" TEST_DATABASE_URL = "postgresql+asyncpg://postgres:postgres@localhost:5432/patherly_test"
@pytest.fixture(scope="session") @pytest.fixture(scope="session")

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Apoklisis</title> <title>Patherly</title>
<script> <script>
// Prevent flash of wrong theme on initial load // Prevent flash of wrong theme on initial load
(function() { (function() {

View File

@@ -25,7 +25,7 @@ export function AppLayout() {
<div className="container mx-auto flex h-14 items-center justify-between px-4"> <div className="container mx-auto flex h-14 items-center justify-between px-4">
<div className="flex items-center gap-8"> <div className="flex items-center gap-8">
<Link to="/trees" className="text-lg font-bold text-foreground"> <Link to="/trees" className="text-lg font-bold text-foreground">
Apoklisis Patherly
</Link> </Link>
<nav className="hidden items-center gap-1 sm:flex"> <nav className="hidden items-center gap-1 sm:flex">
{navItems.map((item) => ( {navItems.map((item) => (

View File

@@ -36,7 +36,7 @@ export function LoginPage() {
<div className="flex min-h-screen items-center justify-center bg-background px-4"> <div className="flex min-h-screen items-center justify-center bg-background px-4">
<div className="w-full max-w-md space-y-8"> <div className="w-full max-w-md space-y-8">
<div className="text-center"> <div className="text-center">
<h1 className="text-3xl font-bold tracking-tight text-foreground">Apoklisis</h1> <h1 className="text-3xl font-bold tracking-tight text-foreground">Patherly</h1>
<p className="mt-2 text-muted-foreground">Sign in to your account</p> <p className="mt-2 text-muted-foreground">Sign in to your account</p>
</div> </div>

View File

@@ -45,7 +45,7 @@ export function RegisterPage() {
<div className="flex min-h-screen items-center justify-center bg-background px-4"> <div className="flex min-h-screen items-center justify-center bg-background px-4">
<div className="w-full max-w-md space-y-8"> <div className="w-full max-w-md space-y-8">
<div className="text-center"> <div className="text-center">
<h1 className="text-3xl font-bold tracking-tight text-foreground">Apoklisis</h1> <h1 className="text-3xl font-bold tracking-tight text-foreground">Patherly</h1>
<p className="mt-2 text-muted-foreground">Create your account</p> <p className="mt-2 text-muted-foreground">Create your account</p>
</div> </div>