You are an expert senior software engineer, principal architect, product engineer, and AI systems designer.
We are building Empire OS, a private execution operating system using a Spine + Modules architecture.
The backend spine already defines the shared foundation:
- Auth
- Profiles
- Empire phases
- Module registry
- Global actions
- Module metrics
- Decisions
- Decision votes
- Empire Score
- Events
- Audit logs
- Notifications foundation
- AI decision orchestration foundation
Your job is to build the Module System V3.
Do not build random one-off modules.
Build a reusable, high-tech module architecture where every module follows the same standard and plugs into the Spine cleanly.
This project uses:
- Next.js App Router
- TypeScript
- Supabase
- PostgreSQL
- Row Level Security
- Zod
- Server-first architecture
- API routes only where needed
- Modular folder structure
- No Vite
- No React Router
- No untyped backend calls
- No private data sent to AI without redaction
The Spine owns priority.
Modules own domain detail.
Every module must produce:
- Metrics
- Actions
- Decision context
- Events
- Audit records
- Health status
- Optional notifications
- Optional documents
- Optional AI advisor context
A module is not just a page.
A module is a specialized operating unit inside Empire OS.
Create or improve the shared module contract.
File:
src/spine/module-contract.tsEvery module must implement this:
export type ModuleId =
| "cash-engine"
| "job-hunt"
| "followup-crm"
| "credit-funding"
| "projects"
| "acquisitions"
| string;
export type ModuleStatus =
| "active"
| "light_active"
| "parked"
| "later"
| "disabled";
export type ModuleHealth =
| "green"
| "yellow"
| "red"
| "unknown";
export type ModuleCapability =
| "metrics"
| "actions"
| "decisions"
| "events"
| "notifications"
| "documents"
| "ai_context"
| "health_check"
| "sync";
export type ModuleManifest = {
id: ModuleId;
name: string;
slug: string;
description: string;
phaseId: string;
status: ModuleStatus;
priority: number;
route: string;
icon?: string;
capabilities: ModuleCapability[];
version: string;
owner?: string;
};
export type ModuleMetric = {
moduleId: ModuleId;
key: string;
label: string;
value?: number;
text?: string;
target?: number;
unit?: string;
date?: string;
metadata?: Record<string, unknown>;
};
export type ModuleAction = {
moduleId: ModuleId;
phaseId: string;
title: string;
description?: string;
category: string;
priority: "low" | "medium" | "high" | "critical";
dueAt?: string;
impactScore: number;
urgencyScore: number;
effortScore: number;
empireScoreWeight?: number;
metadata?: Record<string, unknown>;
};
export type DecisionContext = {
moduleId: ModuleId;
summary: string;
facts: Array<{
label: string;
value: string | number | boolean | null;
importance: "low" | "medium" | "high" | "critical";
}>;
risks: string[];
opportunities: string[];
recommendedQuestions: string[];
redacted: boolean;
metadata?: Record<string, unknown>;
};
export type ModuleHealthCheck = {
moduleId: ModuleId;
health: ModuleHealth;
summary: string;
issues: string[];
lastSyncedAt?: string;
};
export type EmpireModule = {
manifest: ModuleManifest;
getMetrics: (userId: string) => Promise<ModuleMetric[]>;
getActions: (userId: string) => Promise<ModuleAction[]>;
getDecisionContext: (userId: string) => Promise<DecisionContext>;
syncToSpine: (userId: string) => Promise<void>;
healthCheck: (userId: string) => Promise<ModuleHealthCheck>;
};Every module must follow this structure:
src/modules/<module-name>/
│
├── manifest.ts
├── types.ts
├── schemas.ts
├── service.ts
├── metrics.ts
├── actions.ts
├── decisions.ts
├── events.ts
├── health.ts
├── api.ts
├── README.md
│
├── components/
│ ├── <ModuleName>Card.tsx
│ ├── <ModuleName>Page.tsx
│ ├── <ModuleName>Form.tsx
│ ├── <ModuleName>List.tsx
│ └── <ModuleName>Detail.tsx
│
└── tests/
├── service.test.ts
├── metrics.test.ts
├── actions.test.ts
└── decisions.test.tsFor backend-first work, create the structure and backend files first.
Frontend components can be stubs only unless specifically requested.
Create a full reusable template module here:
src/modules/_template/The template must include:
manifest.ts
types.ts
schemas.ts
service.ts
metrics.ts
actions.ts
decisions.ts
events.ts
health.ts
api.ts
README.mdThe template should show exactly how a new module plugs into the Spine.
It should not contain random business logic.
It should contain clear TODO markers.
Create or improve:
src/spine/module-registry.tsIt must:
- Import all module contracts
- Register active modules
- Provide lookup helpers
- Provide sync orchestration
- Provide metrics aggregation
- Provide actions aggregation
- Provide health checks
- Provide AI decision context aggregation
Required functions:
export function getAllModules(): EmpireModule[];
export function getActiveModules(): EmpireModule[];
export function getModuleById(moduleId: string): EmpireModule | null;
export async function syncAllModulesToSpine(userId: string): Promise<void>;
export async function getAllModuleMetrics(userId: string): Promise<ModuleMetric[]>;
export async function getAllModuleActions(userId: string): Promise<ModuleAction[]>;
export async function getAllDecisionContexts(userId: string): Promise<DecisionContext[]>;
export async function getModuleHealthReport(userId: string): Promise<ModuleHealthCheck[]>;Create a small adapter layer that converts module outputs into Spine database records.
File:
src/spine/module-adapter.tsIt should include:
export async function syncModuleMetricsToSpine(
userId: string,
moduleId: string,
metrics: ModuleMetric[]
): Promise<void>;
export async function syncModuleActionsToSpine(
userId: string,
moduleId: string,
actions: ModuleAction[]
): Promise<void>;
export async function recordModuleEvent(
userId: string,
moduleId: string,
eventType: string,
payload: Record<string, unknown>
): Promise<void>;The adapter should write to:
module_metricsglobal_actionsaudit_eventseventsif the event table exists
Avoid duplicate actions where possible.
Use stable dedupe keys in metadata.
Build or improve these initial modules:
- Cash Engine
- Job Hunt
- Follow-Up CRM
- Credit / Funding
- Projects
- Acquisitions
Do not overbuild all UI.
Backend services, metrics, actions, decisions, and health checks matter first.
Path:
src/modules/cash-engine/Purpose:
Track income, expenses, daily cash target, weekly cash target, monthly cash target, and runway.
Use or create:
cash_entriesFields should include:
- id
- user_id
- date
- source
- gross_amount
- expenses
- net_amount
- hours
- trips
- notes
- created_at
Create:
export type CashSource =
| "uber_eats"
| "roadie"
| "software_job"
| "contract_work"
| "real_estate"
| "celebration_logistics"
| "other";
export type CashEntry = {
id: string;
userId: string;
date: string;
source: CashSource;
grossAmount: number;
expenses: number;
netAmount: number;
hours?: number;
trips?: number;
notes?: string;
createdAt: string;
};createCashEntry(input)
updateCashEntry(id, input)
deleteCashEntry(id)
getCashEntryById(id)
getTodayCash(userId)
getWeeklyCash(userId)
getMonthlyCash(userId)
getCashBySource(userId, startDate, endDate)
calculateCashGap(userId)
syncCashMetrics(userId)
createCashGapAction(userId)Cash Engine must report:
today_cashtoday_cash_targettoday_cash_gapweekly_cashmonthly_cashaverage_hourly_rateaverage_per_triprunway_daysif bill data exists, otherwise returnunknown
Cash Engine must generate actions like:
- Log today’s income
- Earn remaining daily cash gap
- Review expenses
- Check weekly cash target
- End day cash review
Cash Engine must answer decision questions like:
- Do I need to prioritize cash today?
- Can I afford to spend money on this?
- Should I Uber today or work on long-term tasks?
- What is the cash gap?
The decision context must include:
- today cash
- daily target
- cash gap
- weekly cash
- urgent cash risk
- recommendation summary
Path:
src/modules/job-hunt/Purpose:
Land a high-income software, AI, data, or architecture role.
Use or create:
job_applicationsexport type JobStatus =
| "saved"
| "applied"
| "followed_up"
| "recruiter_screen"
| "interview"
| "final_round"
| "offer"
| "rejected"
| "dead";
export type JobApplication = {
id: string;
userId: string;
company: string;
role: string;
salaryMin?: number;
salaryMax?: number;
status: JobStatus;
priorityScore: number;
recruiterName?: string;
recruiterEmail?: string;
jobUrl?: string;
resumeVersion?: string;
nextAction?: string;
followUpAt?: string;
notes?: string;
createdAt: string;
updatedAt: string;
};createJobApplication(input)
updateJobApplication(id, input)
deleteJobApplication(id)
getJobApplicationById(id)
getActiveJobApplications(userId)
getApplicationsByStatus(userId, status)
getFollowUpsDue(userId)
getHighValueOpportunities(userId)
calculatePipelineValue(userId)
syncJobMetrics(userId)
createJobFollowUpActions(userId)Job Hunt must report:
applications_todayapplications_this_weekfollowups_dueinterviews_activepipeline_value_lowpipeline_value_highhighest_priority_joboffer_probability_estimate
Job Hunt must generate actions like:
- Apply to high-value role
- Follow up with recruiter
- Prepare interview notes
- Update resume
- Send proposal
- Record Loom demo
- Review job pipeline
Job Hunt must support decisions like:
- Should I take this role?
- Employee or contract?
- Should I prioritize job applications over delivery work?
- Which role has the highest upside?
- What is my strongest next career move?
Path:
src/modules/followup-crm/Purpose:
Manage contacts, follow-ups, buyers, brokers, recruiters, lenders, investors, and business relationships.
Use or create:
contactsexport type ContactType =
| "buyer"
| "seller"
| "broker"
| "recruiter"
| "lender"
| "investor"
| "client"
| "partner"
| "other";
export type ContactStatus =
| "active"
| "warm"
| "hot"
| "cold"
| "dead"
| "do_not_contact";
export type Contact = {
id: string;
userId: string;
name: string;
company?: string;
contactType: ContactType;
phone?: string;
email?: string;
status: ContactStatus;
lastContactedAt?: string;
nextFollowUpAt?: string;
relatedModuleId?: string;
notes?: string;
createdAt: string;
updatedAt: string;
};createContact(input)
updateContact(id, input)
deleteContact(id)
getContactById(id)
getContactsByType(userId, contactType)
getFollowUpsDue(userId)
getOverdueFollowUps(userId)
markContacted(contactId, contactedAt)
createFollowUpAction(contactId)
syncFollowUpMetrics(userId)Follow-Up CRM must report:
followups_due_todayoverdue_followupshot_contactswarm_contactscontacts_added_this_weekresponse_rateif tracked, otherwise unknown
Follow-Up CRM must generate:
- Send follow-up text
- Send follow-up email
- Call contact
- Update contact status
- Schedule next follow-up
- Re-engage cold contact
Follow-Up CRM must support:
- Who should I follow up with today?
- Which contact is most valuable?
- Which deal/contact is going cold?
- Should I reach out again or move on?
Path:
src/modules/credit-funding/Purpose:
Track credit profile, disputes, business banking, ChexSystems, Early Warning, LexisNexis, funding readiness, and lender prep.
Create if missing:
credit_snapshots
funding_tasks
funding_documents- id
- user_id
- snapshot_date
- experian_score
- equifax_score
- transunion_score
- utilization_percent
- open_disputes
- chex_status
- early_warning_status
- lexisnexis_status
- notes
- created_at
- id
- user_id
- title
- category
- status
- due_at
- completed_at
- notes
- metadata
- created_at
- updated_at
- id
- user_id
- document_type
- label
- storage_path
- status
- notes
- metadata
- created_at
Credit / Funding must report:
funding_readiness_scoreexperian_scoreequifax_scoretransunion_scoreutilization_percentopen_disputesbanking_file_statusdocuments_ready_countfunding_blockers_count
Credit / Funding must generate:
- Mail dispute
- Check bureau response
- Update address
- Upload document
- Apply for card
- Review funding readiness
- Resolve banking file issue
Credit / Funding must support:
- Am I fundable yet?
- What is the next credit move?
- Should I apply for this card/loan?
- What is blocking funding?
- Should I use cash for credit cleanup?
Path:
src/modules/projects/Purpose:
Rank and manage business projects so attention does not scatter.
Create if missing:
projectsFields:
- id
- user_id
- name
- description
- status
- focus_level
- revenue_potential
- strategic_value
- time_required
- risk_level
- next_action
- blocker
- notes
- created_at
- updated_at
Projects must report:
active_projectsparked_projectsblocked_projectshighest_focus_projecthighest_upside_projectdistraction_risk_score
Projects must generate:
- Move project forward
- Park project
- Define next action
- Remove distraction
- Review project ranking
- Ship MVP step
Projects must support:
- Which project should I focus on?
- Is this project a distraction?
- Should I park this idea?
- Which project creates income fastest?
- Which project supports the empire plan best?
Path:
src/modules/acquisitions/Purpose:
Track property management companies, real estate deals, business acquisitions, LOIs, seller financing, target scoring, and upside.
Create if missing:
acquisition_targets
acquisition_contacts
acquisition_scores- id
- user_id
- name
- target_type
- location
- asking_price
- revenue
- noi
- ebitda
- doors_count
- seller_financing_possible
- status
- next_action
- notes
- metadata
- created_at
- updated_at
- id
- user_id
- target_id
- cash_flow_score
- seller_motivation_score
- financing_score
- upside_score
- risk_score
- overall_score
- notes
- created_at
Acquisitions must report:
active_targetstargets_reviewed_this_weekseller_financing_targetshighest_score_targetaverage_target_scoreestimated_noi_pipeline
Acquisitions must generate:
- Analyze target
- Contact owner
- Request financials
- Score acquisition
- Prepare LOI
- Follow up with seller
- Review financing options
Acquisitions must support:
- Should I pursue this acquisition?
- Is this target worth time?
- Is seller financing likely?
- What is the upside?
- What is the risk?
- What is the next deal action?
Every module should emit events for important changes.
Examples:
cash.entry.created
cash.target.missed
job.application.created
job.followup.due
crm.contact.created
crm.followup.overdue
credit.snapshot.created
project.parked
acquisition.target.scoredCreate module event helpers in each module:
emitCashEvent(...)
emitJobEvent(...)
emitCrmEvent(...)These should call the shared Spine event/audit adapter.
Before sending module data to AI decision advisors, redact sensitive fields.
Never send:
- SSNs
- full account numbers
- tax IDs
- full credit report details
- full bank account numbers
- private document URLs
- exact addresses unless necessary
- sensitive medical details unless the user explicitly requests it
Create:
src/spine/ai/redaction.tsRequired functions:
redactDecisionContext(context)
redactText(input)
redactObject(input)Use redacted context in all module getDecisionContext() outputs.
Each module must include:
health.tsHealth should evaluate:
- Is the module active?
- Is there recent data?
- Are there overdue actions?
- Are key metrics missing?
- Is sync working?
- Are there blockers?
Return:
{
moduleId,
health,
summary,
issues,
lastSyncedAt
}Examples:
- Cash Engine red if no income logged today and cash target not met.
- Job Hunt yellow if no applications this week.
- Follow-Up CRM red if overdue follow-ups exist.
- Credit Funding yellow if no snapshot exists.
- Projects red if too many active projects.
- Acquisitions yellow if no targets reviewed this week.
Use Next.js App Router API route conventions.
Create route stubs only where useful.
Examples:
src/app/api/modules/sync/route.ts
src/app/api/modules/health/route.ts
src/app/api/modules/metrics/route.ts
src/app/api/modules/actions/route.tsThese route stubs should:
- Get the authenticated user
- Call the module registry
- Return normalized data
- Not expose data across users
Create lightweight tests or test-ready structure for:
- Module contract validation
- Metric generation
- Action generation
- Decision context redaction
- Health check result
- Service function validation
Use whatever testing setup already exists.
If no testing setup exists, create a minimal test plan in documentation instead of adding unnecessary dependencies.
Create:
src/modules/README.md
src/modules/_template/README.md
src/modules/cash-engine/README.md
src/modules/job-hunt/README.md
src/modules/followup-crm/README.md
src/modules/credit-funding/README.md
src/modules/projects/README.md
src/modules/acquisitions/README.mdEach module README must include:
- Purpose
- Spine connections
- Tables used
- Metrics produced
- Actions produced
- Decision context produced
- Events emitted
- Health rules
- How to extend it
Build this like a real product foundation.
Do:
- Use strong TypeScript types
- Use Zod validation
- Use Supabase safely
- Use user_id for all user-owned rows
- Use RLS-compatible patterns
- Keep module outputs normalized
- Avoid duplicate code where a shared helper makes sense
- Avoid overengineering
- Keep it readable
- Keep it extensible
Do not:
- Build random UI before backend module structure is stable
- Create module-specific hacks
- Send private data to AI unredacted
- Skip module manifests
- Skip module health checks
- Skip metrics/actions/decision context
- Use Vite
- Use React Router
- Hardcode another user’s data
- Put API secrets in code
When finished, summarize:
- Module architecture files created
- Module template created
- Modules implemented or scaffolded
- Module registry updates
- Module adapter updates
- Metrics each module produces
- Actions each module produces
- Decision context each module produces
- Health checks added
- API route stubs added
- Documentation added
- Next recommended branch
Recommended branch:
git checkout -b feature/module-system-v3Build in this order:
- Shared module contract
- Module adapter
- Module registry
_templatemodule- Cash Engine
- Job Hunt
- Follow-Up CRM
- Credit / Funding
- Projects
- Acquisitions
- AI redaction utilities
- Module health route
- Module sync route
- Documentation
- Validation / test plan
The final result should make it easy to add any future Empire OS module by copying _template, filling in domain logic, and plugging it into the registry.