e89f60f8a51b4214d0b9087ab29084fa8a155424
Job Info Test - Project Overview
What is this?
Job-Info-Test is a modern, modular application testbed for exploring and validating:
- Microsoft Graph API interactions - token acquisition, caching, refresh, data queries
- PocketBase integration - OAuth2 flows, user management, data persistence
- Industry-standard UI/UX patterns - reactive components, state management, real-time updates
- Developer experience (DX) - clean APIs, TypeScript support, proper error handling, observability
- Architecture best practices - modular design, separation of concerns, testability
It uses a Mode system where different technology implementations can be built and tested in parallel without interfering with each other.
Purpose
This is not just an auth test—it's a reference implementation playground for:
- Building real, production-quality features with Graph API (user data, calendar, files, etc.)
- Implementing reactive, modern UI with Svelte and industry best practices
- Creating clean, maintainable code architecture that teams can learn from
- Testing complex workflows combining Graph + PocketBase + custom logic
- Demonstrating proper error handling, loading states, and data synchronization
- Building DX-first APIs that are a pleasure to use and extend
Development Standards
These rules MUST be followed on every code change. Review before editing.
1. Variable Naming — Strict Consistency
- Auth and token variable names are NOT flexible — they are fixed throughout the project
- Use identical names every time a value is referenced, passed, or used
- Examples of correct consistency:
- Graph token: always
graphToken(nevergraph_token,token, oraccessToken) - PocketBase token: always
pbToken(neverpocketbaseToken,pb_token, oruserToken) - User ID: always
userId(neveruser_id,uid, orid) - Current user: always
currentUser(neveruser,loggedInUser, orauthUser)
- Graph token: always
- Why: Eliminates confusion about what value is being used and where it comes from
- Enforcement: If a variable name changes, it must change everywhere it's used in that mode
2. Mode Independence — Standalone Projects
- Each mode is completely independent — can run on any machine without parent directory
- Copy modules in, never depend on them externally
- If
auth-moduleis used in multiple modes, copy it into each mode's directory - Never import from
../auth-moduleor../../auth-module - Each mode has its own complete copy of all dependencies
- If
- Modes must not reference each other
- No imports between Mode1 and Mode1Svelte
- No shared backend code between modes
- Benefit: Can delete, move, or duplicate a mode without breaking anything else
3. Development Scope — Edit Only Your Mode
- Only edit the mode you're actively working on — all other modes untouched
- You can reference other modes for patterns/examples, but don't code in them
- Exception: Only modify another mode if explicitly agreed upon in writing
- Corollary: If shared logic needs updating (like auth-module), update it in your working mode, test it, then copy it to other modes if approved
4. Ports — 3005 & 3006 ONLY
- Work exclusively with ports 3005 and 3006
- Port 3005: Active mode backend + frontend
- Port 3006: ModeSwitch orchestrator
- Do NOT check any other ports — ignore them entirely
- Ignore all other running services — focus only on these two ports
5. Service Restart — Kill, Then Start
- Always assume something is running on the port before starting
- Always kill first, then start:
pkill -f "bun.*server.ts" || true sleep 1 PORT=3005 bun run backend/server.ts - This prevents port-binding conflicts and ensures clean startup
6. Service Validation — One Check, Then Stop
- Do ONE comprehensive health check after startup
- Verify backend is listening on correct port
- Verify frontend is accessible
- Verify all critical endpoints respond (auth endpoints, health checks)
- Verify no error messages in logs
- Then STOP checking — if health is good, leave it running
- Do NOT check 3, 4, or multiple times — it wastes time and adds no value
- If health check passes, service is ready — move forward to next task
7. Git Commits & Sync — Developer Agreement Required
- Never commit or sync without explicit developer approval
- Only prompt for commit/sync AFTER code verification
- Code must be working as intended
- Tests passing (if applicable)
- Health checks passing
- Developer has confirmed the feature/fix is complete
- Workflow: Build → Test → Confirm Working → Then ask about commit
- No automatic commits or premature prompts
Architecture
Job-Info-Test/
├── auth-module/ # Shared, reusable auth component (root copy)
├── Mode1/ # Hono + vanilla JavaScript (LOCKED/READ-ONLY reference)
├── Mode1Svelte/ # Hono + SvelteKit (active development - modern DX/UX)
├── ModeSwitch/ # Orchestrator to manage mode switching
├── Mode6Test/ # Legacy testing environment
└── README.md # This file
The Mode System
Each Mode is a completely independent project that:
- Has its own copy of
auth-module(no cross-dependencies) - Runs on the same ports (3005 backend, 3006 orchestrator)
- Can be swapped via ModeSwitch without affecting others
- Shares the same secret configuration (
/home/admin/secrets/.env)
Current Modes
Mode1 (READ-ONLY Reference Implementation)
- Frontend: Vanilla HTML + JavaScript
- Backend: Hono (TypeScript)
- Status: Reference implementation, locked to prevent accidental changes
- Port: 3005
Mode1Svelte (Active Development)
- Frontend: SvelteKit (Svelte components, reactive)
- Backend: Hono (same as Mode1)
- Status: Being converted to full SvelteKit following industry best practices
- Port: 3005
Key Components
Auth Module (/auth-module/)
Reusable authentication component with:
-
Backend (
backend.ts):AuthConfigManager- Loads and provides configurationGraphTokenManager- Acquires Microsoft Graph tokens via MSALPocketBaseValidator- Validates user tokensBackendAuth- Orchestrates backend auth flow
-
Frontend (
frontend.ts):PocketBaseAuth- OAuth2 login/logout/state managementinitPocketBaseAuth()- Initialize with callbacks
-
Types (
types.ts):FrontendConfig- Configuration provided to frontendAuthState- Frontend authentication state
ModeSwitch Orchestrator (/ModeSwitch/)
- Listens on port 3006
- Manages active mode switching via
POST /switch/:mode - Returns mode status and health checks
- Starts/stops backend servers as needed
How It Works
Startup Flow
- ModeSwitch starts on port 3006 (orchestrator)
- Active mode backend starts on port 3005
- Frontend served at
http://localhost:3005(orhttps://ji-test.ccllc.pro) - Frontend fetches config from
/api/auth/config - Backend loads secrets from
/home/admin/secrets/.env
Auth Flow
-
Frontend OAuth Login:
- User clicks login button
- Browser redirected to PocketBase OAuth provider
- PocketBase returns user and token
- Frontend stores token in
pbAuth.getAuthState()
-
Backend Graph Token:
- Frontend calls
/api/auth/graph/token - Backend uses MSAL to acquire Microsoft Graph token
- Token cached with 60-second expiration buffer
- Frontend receives token with JWT payload details
- Frontend calls
-
Token Comparison:
- Frontend sends PocketBase token to
/api/auth/compare-tokens - Backend validates PB token and decodes Graph token JWT
- Returns side-by-side comparison showing they're different systems
- Frontend sends PocketBase token to
Running the Project
Via ModeSwitch (Recommended)
# Start ModeSwitch (listens on 3006)
cd /home/admin/Job-Info-Test/ModeSwitch
PORT=3006 bun run backend/orchestrator.ts
# In another terminal, switch to desired mode
curl -X POST http://localhost:3006/switch/Mode1Svelte
# Access frontend
open https://ji-test.ccllc.pro
# or
open http://localhost:3005
Direct Mode Start
# Start Mode1Svelte directly
cd /home/admin/Job-Info-Test/Mode1Svelte
PORT=3005 bun run backend/server.ts
# Access frontend
open http://localhost:3005
Configuration
Secrets (/home/admin/secrets/.env):
CLIENT_ID=<Azure app client ID>
TENANT_ID=<Azure tenant ID>
CLIENT_SECRET=<Azure app client secret>
PB_URL=<PocketBase server URL>
PB_DB=<PocketBase database name>
These are loaded:
- Backend: Automatically on server startup via
dotenv - Frontend: Via API endpoint
/api/auth/config(no hardcoded URLs)
Project Structure Details
Mode1 (Reference - READ-ONLY)
Mode1/
├── auth-module/ # Self-contained copy
├── backend/
│ └── server.ts # Hono + auth endpoints
├── frontend/
│ ├── index.html # Test dashboard
│ └── dist/ # Built assets
└── package.json
Mode1Svelte (In Development)
Mode1Svelte/
├── auth-module/ # Self-contained copy
├── backend/
│ └── server.ts # Hono + auth endpoints
├── src/
│ ├── routes/ # SvelteKit pages (to be added)
│ ├── lib/ # Svelte components (to be added)
│ └── app.svelte # Root component (to be added)
└── svelte.config.js # SvelteKit config (to be added)
Development Notes
- Mode1 is locked to preserve the reference implementation
- Mode1Svelte is the active development branch
- Both modes can run simultaneously on different orchestrator instances
- No code dependencies between modes—each is fully independent
- Auth-module changes should be made in root
/auth-module/, then copied to each mode
Testing
Dashboard at https://ji-test.ccllc.pro:
- ✅ Complete auth flow (PocketBase OAuth2)
- ✅ Microsoft Graph token acquisition, caching, refresh
- ✅ Real Graph API interactions (user profile, mail, calendar, files, etc.)
- ✅ PocketBase data queries and mutations
- ✅ Token comparison and validation
- ✅ Error states and loading indicators
- ✅ Timestamped logs and observability
- ✅ Real-time data synchronization patterns
Next Steps
- Convert Mode1Svelte to full SvelteKit with modern component architecture
- Build Graph API features - implement real use cases beyond auth
- Create reactive Svelte components - proper state management, stores, lifecycle
- Add TypeScript throughout - strict types, better DX
- Implement data layers - abstracting Graph API and PocketBase queries
- Build responsive UI - mobile-first design, accessibility (a11y)
- Add observability - logging, error tracking, performance monitoring
- Create component library - reusable, well-documented Svelte components
- Write comprehensive tests - unit, integration, E2E
- Document patterns - make this a reference for modern full-stack Svelte apps
Description
Languages
HTML
41.8%
TypeScript
38.2%
Svelte
16%
JavaScript
3.8%
CSS
0.2%