# Implementation Plan: Website / Workspace Foundation

**Branch**: `183-website-workspace-foundation` | **Date**: 2026-04-08 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/183-website-workspace-foundation/spec.md`
**Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/183-website-workspace-foundation/spec.md` and repo-context planning for the first real multi-app workspace slice.

## Summary

Introduce the first true multi-app foundation by adding a public website application under `apps/website` while keeping the existing Laravel platform stable under `apps/platform`. The implementation uses a minimal root orchestration model: one official Node workspace standard at repo root, one static-first website runtime, thin root scripts that orchestrate instead of re-implementing app logic, and a clear split between repo-level metadata, website runtime concerns, and platform runtime concerns.

Key approach: adopt `pnpm` workspaces as the official root package-manager standard, initialize the public website as an Astro app under `apps/website`, migrate the platform's Node command surface from npm to pnpm so the repo has one official JavaScript package-manager model, keep the platform Sail-first and Docker-backed, keep the website outside Sail in this first slice, and update only the root docs, tooling, and tasks that need multi-app awareness. The plan explicitly avoids shared packages, Turbo or Nx, a docs app, a customer app, a generalized app-runner framework, or any new TenantPilot product behavior.

The feature leaves Filament v5 on Livewire v4 unchanged, keeps panel providers registered in `apps/platform/bootstrap/providers.php`, does not add or alter globally searchable resources, introduces no destructive operator actions, and preserves the existing deploy-time `cd apps/platform && php artisan filament:assets` responsibility for platform assets.

## Technical Context

**Language/Version**: PHP 8.4.15 and Laravel 12 for `apps/platform`; Node.js 20+ with pnpm 10 workspace tooling; Astro v6 for `apps/website`; Bash and Docker Compose for root orchestration  
**Primary Dependencies**: `laravel/framework`, `filament/filament`, `livewire/livewire`, `laravel/sail`, `vite`, `tailwindcss`, `pnpm` workspaces, Astro, existing `./scripts/platform-sail` wrapper, repo-root Docker Compose  
**Storage**: Existing PostgreSQL, Redis, and filesystem storage for `apps/platform`; static build artifacts for `apps/website`; repository-managed workspace manifests and docs; no new database persistence  
**Testing**: Existing Pest v4 platform tests through Sail; website boot/build smoke; root command smoke; parallel-run and build-isolation validation; targeted task and MCP smoke where tooling changes  
**Target Platform**: macOS and Linux developer machines, Dockerized Laravel platform runtime, Node-based static public website runtime, Dokploy-style container deployment for the platform and static-site deployment for the website
**Project Type**: Multi-app repo with repo-root orchestration, one Laravel platform app, and one static-first public website app  
**Performance Goals**: Preserve current platform boot/build behavior; keep website dev/build lightweight; allow platform and website to run in parallel on distinct ports with no cross-app artifact pollution  
**Constraints**: One official workspace standard only; no shared packages; no docs/customer/API surfaces; no website embedding into Blade or Filament; no root-level monorepo framework; keep platform Sail-first; root orchestrates while apps execute  
**Scale/Scope**: Two first-class applications under `apps/`, root orchestration manifests and scripts, documentation and task updates, and smoke validation across local boot, coexistence, and build separation

## Constitution Check

*GATE: Passed before Phase 0 research. Re-checked after Phase 1 design and still passing.*

| Principle | Status | Notes |
|-----------|--------|-------|
| Inventory-first | Pass | No inventory, snapshot, or backup truth changes; this is repo topology and runtime orchestration only |
| Read/write separation | Pass | No new product mutation flow, operator write surface, or external write behavior is introduced |
| Graph contract path | Pass | No Microsoft Graph calls or contract-registry changes are in scope |
| Deterministic capabilities | Pass | Capability derivation and registries remain unchanged |
| RBAC-UX planes and 404 vs 403 | Pass | `/admin`, `/admin/t/{tenant}/...`, and `/system` authorization semantics remain unchanged |
| Workspace isolation | Pass | No new workspace-scoped data access or workspace routing behavior is introduced |
| Tenant isolation | Pass | No tenant-owned routes, queries, or UI semantics are broadened |
| Global search safety | Pass | No resource or global-search behavior changes are planned |
| Dangerous and destructive confirmations | Pass | No new destructive operator actions are introduced |
| Run observability | Pass | No new long-running product operations or `OperationRun` flows are introduced |
| Ops-UX 3-surface feedback | Pass | Not applicable because no operation UX is added or changed |
| Data minimization | Pass | No new secrets, logs, payload mirrors, or persisted product truth are added |
| Proportionality (PROP-001) | Pass | The design adds only one website app and the minimum root orchestration needed to support it |
| No premature abstraction (ABSTR-001) | Pass | The plan explicitly rejects Turbo, Nx, packages, a generic app-runner wrapper, and a generalized Sail abstraction |
| Persisted truth (PERSIST-001) | Pass | Only repository artifacts are added; no new application tables or persisted domain entities |
| Behavioral state (STATE-001) | Pass | No new domain status or reason-code family is introduced |
| UI semantics (UI-SEM-001) | Pass | No new operator semantic layer is introduced; the website is a separate public app |
| Filament-native UI (UI-FIL-001) | Pass | Platform Filament surfaces stay unchanged |
| Filament v5 / Livewire v4 compliance | Pass | Platform remains on Filament v5 with Livewire v4; the website app does not affect that stack |
| Provider registration location | Pass | Provider registration remains in `apps/platform/bootstrap/providers.php` |
| Global search hard rule | Pass | No globally searchable resource gains or losses are introduced |
| Asset strategy | Pass | Platform assets remain app-local and keep the `filament:assets` deploy step; website assets build independently from `apps/website` |
| Testing plan | Pass | The plan includes platform regression smoke, website boot/build smoke, root command smoke, and coexistence validation |

## Phase 0 Research

Research outcomes are captured in `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/183-website-workspace-foundation/research.md`.

Key decisions:

- Adopt `pnpm` workspaces as the official JavaScript package-manager standard for the multi-app repo. The root receives `package.json` plus `pnpm-workspace.yaml`, and the platform's Node command surface migrates from npm to pnpm so the repo has one official package-manager story.
- Use Astro v6 as the website stack because the spec explicitly wants a public-surface, static-first foundation with minimal runtime coupling.
- Keep the platform Sail-first and Docker-backed, but do not Dockerize the website in this first slice. The website should run as a plain Node app to keep the first multi-app step proportional.
- Keep `./scripts/platform-sail` as a platform-only compatibility helper. Do not introduce a generic `scripts/sail <app>` abstraction because only one app uses Sail today.
- Keep Boost MCP and Laravel-specific editor integration platform-only. The website app is not a second Laravel runtime in this slice, so `.vscode/mcp.json` and `opencode.json` only need clearer scoping, not a second Boost server.
- Limit root task updates to the official entry tasks and any affected labels or notes. This slice does not justify a wholesale task-system rewrite.

## Phase 1 Design

Design artifacts are created under `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/183-website-workspace-foundation/`:

- `data-model.md`: repository-artifact and runtime-boundary model for root orchestration, platform app, website app, and tooling surfaces
- `contracts/workspace-command-model.md`: canonical root and app-local command contract for platform, website, and parallel local development
- `contracts/coexistence-smoke.openapi.yaml`: HTTP and orchestration smoke contract for website/platform coexistence
- `quickstart.md`: implementation, validation, and rollout checklist for the workspace foundation

Design decisions:

- The root owns JavaScript workspace orchestration, but PHP and Laravel runtime ownership stays inside `apps/platform`.
- The official root command model is intentionally small: install workspace dependencies, start the platform, start the website, start both, build the website, and build platform frontend assets.
- The platform retains its current Docker Compose topology and `./scripts/platform-sail` wrapper. The website does not join Docker Compose in this slice.
- The root does not introduce `packages/`, shared tokens, shared components, or cross-app runtime modules.
- Root documentation and tooling are updated only where multi-app awareness is now necessary: README, Agents/GEMINI/Copilot guidance, entry tasks, and root-level config that references the platform as the only app.

## Project Structure

### Documentation (this feature)

```text
specs/183-website-workspace-foundation/
├── spec.md
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│   ├── workspace-command-model.md
│   └── coexistence-smoke.openapi.yaml
├── checklists/
│   └── requirements.md
└── tasks.md
```

### Source Code (repository root)

```text
repo-root/
├── apps/
│   ├── platform/
│   │   ├── app/
│   │   ├── bootstrap/
│   │   ├── config/
│   │   ├── database/
│   │   ├── public/
│   │   ├── resources/
│   │   ├── routes/
│   │   ├── storage/
│   │   ├── tests/
│   │   ├── artisan
│   │   ├── composer.json
│   │   ├── package.json
│   │   └── vite.config.js
│   └── website/
│       ├── package.json
│       ├── astro.config.mjs
│       ├── public/
│       └── src/
├── docs/
├── specs/
├── scripts/
├── .specify/
├── .github/
├── .vscode/
├── docker-compose.yml
├── package.json
├── pnpm-workspace.yaml
├── README.md
├── Agents.md
├── GEMINI.md
├── boost.json
└── opencode.json
```

**Structure Decision**: Repo-root workspace orchestration plus two app roots under `apps/`: the existing Laravel platform and a new Astro website. No `packages/` layer, no docs app, and no generalized monorepo framework are introduced.

## Implementation Strategy

### Phase A — Establish The Official Root Workspace Standard

**Goal**: Make the repo root the canonical JavaScript workspace entry point without turning it into an application runtime.

| Step | Area | Change |
|------|------|--------|
| A.1 | Workspace manifests | Add a minimal root `package.json` and `pnpm-workspace.yaml` for `apps/*` |
| A.2 | Package-manager contract | Declare pnpm as the official JS package-manager standard and remove the implicit npm-only assumption from root docs and tooling |
| A.3 | Lockfile model | Replace per-app `package-lock.json` usage for maintained app packages with one root `pnpm-lock.yaml` |
| A.4 | Root scripts | Define thin root scripts for platform start, website start, parallel dev, website build, and platform frontend build |

### Phase B — Align The Platform App With The Workspace Standard

**Goal**: Keep `apps/platform` stable while letting it participate in the official pnpm-based workspace model.

| Step | Area | Change |
|------|------|--------|
| B.1 | Platform package manifest | Update `apps/platform/package.json` scripts to work under pnpm instead of npm-only assumptions |
| B.2 | Composer scripts | Adjust `apps/platform/composer.json` Node-invoking scripts from `npm` to `pnpm` where they are part of the supported workflow |
| B.3 | Sail runtime path | Keep `./scripts/platform-sail` and existing Compose wiring; rely on Corepack/pnpm availability inside Sail instead of building a new orchestration wrapper |
| B.4 | Asset isolation | Preserve platform asset outputs under `apps/platform/public/build` and keep deploy-time `php artisan filament:assets` unchanged |

### Phase C — Create The Website App As A Separate Public Runtime

**Goal**: Introduce `apps/website` as a real standalone app with its own dev and build lifecycle.

| Step | Area | Change |
|------|------|--------|
| C.1 | Website scaffold | Create `apps/website` with Astro config, package manifest, `src/`, and `public/` |
| C.2 | Public pages | Add the narrow initial public site structure needed for the foundation slice, without CMS/blog/docs/customer scope |
| C.3 | Dev/build scripts | Ensure website dev and build commands run from root orchestration and app-local commands alike |
| C.4 | Runtime separation | Keep website ports, environment assumptions, and build output isolated from the platform app |

### Phase D — Update Root Orchestration, Tooling, And Docs

**Goal**: Make the repo entry path obvious and keep automation aligned with the new topology.

| Step | Area | Change |
|------|------|--------|
| D.1 | README and architecture notes | Document the multi-app topology, official command model, and app-local ownership clearly |
| D.2 | Agent and editor guidance | Update `Agents.md`, `GEMINI.md`, `.github/copilot-instructions.md`, and related guidance where root multi-app knowledge now matters |
| D.3 | VS Code and root tooling | Add or adjust official entry tasks for platform, website, and parallel dev; keep Boost MCP platform-only but document that scope explicitly |
| D.4 | Ignore and repo hygiene | Update ignore files and related repo metadata for `apps/website`, root lockfiles, and website build artifacts |

### Phase E — Validate Coexistence And Build Separation

**Goal**: Prove the multi-app repo behaves coherently before implementation is considered complete.

| Step | Area | Change |
|------|------|--------|
| E.1 | Platform stability | Verify existing platform boot paths and focused regression tests still pass |
| E.2 | Website boot | Verify the website starts independently and is reachable on its own dev port |
| E.3 | Parallel dev | Verify the platform and website can run together without port or artifact collisions |
| E.4 | Build separation | Verify website build outputs remain isolated and platform frontend build still works independently |
| E.5 | Documentation usability | Verify a contributor can follow the updated root entry docs without hidden steps |

## Key Design Decisions

### D-001 — pnpm Becomes The One Official JavaScript Workspace Standard

The repo currently has only `apps/platform/package.json` plus a tracked `package-lock.json`, but Spec 183 requires one clear workspace/package-manager standard. pnpm workspaces give the minimal root construct needed for multi-app orchestration without requiring a heavier monorepo framework.

### D-002 — The Website Is A Static-First Astro App, Not A Second Laravel Runtime

The spec calls for a public website foundation, not another back-office application. Astro fits the static-first, public-surface constraint and avoids accidental coupling to platform sessions, Blade, Filament, or Laravel-specific runtime assumptions.

### D-003 — The Platform Stays Sail-First; The Website Does Not Join Docker In V1

The current Compose file and wrapper are already platform-specific and stable. Dockerizing the website now would add extra service orchestration, port strategy, and deployment assumptions that the spec explicitly tries to avoid in the first slice.

### D-004 — Root Scripts Orchestrate; App Logic Stays In The Apps

The root will provide the official entry scripts, but the platform keeps its app-local Sail and Composer logic, and the website keeps its app-local Astro logic. Root scripts are thin delegators, not a new orchestration framework.

### D-005 — No Shared Packages Or Generic App Wrappers In This Slice

This slice deliberately rejects `packages/`, shared token libraries, a generalized `scripts/sail <app>` abstraction, Turbo, Nx, and any cross-app build framework. Those additions would solve hypothetical future variance rather than the current concrete need.

## Risk Assessment

| Risk | Impact | Likelihood | Mitigation |
|------|--------|------------|------------|
| pnpm migration breaks existing platform frontend commands or Composer scripts | High | Medium | Update platform `package.json` and `composer.json` together, and verify pnpm inside Sail before relying on it |
| Contributors confuse root commands, app-local commands, and compatibility helpers | High | Medium | Publish one root command contract and keep app-local commands documented as secondary but valid |
| Website dev port collides with current platform or Vite usage | Medium | Medium | Reserve a distinct website port and document override rules in quickstart and root scripts |
| Root tooling remains platform-only in ways that confuse contributors after website arrives | Medium | High | Update README, task entry points, and agent guidance in the same slice as the website introduction |
| The slice drifts into packages, shared tokens, or a docs app | High | Medium | Treat all extra surfaces and packages as explicit non-goals and block them in review |
| Deployment assumptions for the website are overbuilt too early | Medium | Medium | Keep website deployment guidance minimal and static-site oriented, separate from the platform's Dokploy flow |

## Test Strategy

- Keep platform regression coverage focused: run the minimum representative Sail-driven Pest tests that prove the platform remains stable after the workspace changes.
- Validate platform boot via existing local health and login surfaces such as `/up` and `/admin/login` after root/workspace changes land.
- Validate website boot independently on its own dev server and verify it remains reachable without the platform app running.
- Validate root entry commands for website-only, platform-only, and combined local development flows.
- Validate platform frontend build and website build independently, ensuring outputs remain in their app-local directories.
- Validate at least one affected VS Code task or root tooling entry path so editor automation does not drift behind the repo topology.
- Reconfirm Filament v5 and Livewire v4 compliance by leaving the platform stack untouched and ensuring provider registration remains in `apps/platform/bootstrap/providers.php`.
- Preserve the platform asset deployment contract by keeping `cd apps/platform && php artisan filament:assets` in deployment guidance.

## Complexity Tracking

No constitution violation or exemption is planned. The feature intentionally limits complexity to one new app plus the minimum workspace contract needed to support it.

## Proportionality Review

- **Current operator problem**: The repo needs a public website surface now, but still behaves operationally like a single-app workspace. That makes local setup, docs, and tooling inconsistent the moment a second app is added.
- **Existing structure is insufficient because**: `apps/platform` is correctly isolated, but the repo root still lacks a real workspace standard, root command model, and second-app boundary.
- **Narrowest correct implementation**: Add one website app, one official root workspace standard, a thin root orchestration layer, and only the documentation and tooling updates required to make that structure usable.
- **Ownership cost created**: One additional app lifecycle, one shared JS workspace lockfile, root script maintenance, and multi-app smoke validation.
- **Alternative intentionally rejected**: Embedding the website into Laravel, keeping npm for the platform while adding pnpm only for the website, or introducing shared packages and monorepo frameworks immediately. Each alternative either violates the one-standard rule or adds speculative complexity.
- **Release truth**: Current-release infrastructure truth for the first public website surface, not future-only preparation.
