diff --git a/.github/workflows/backend-ci.yml b/.github/workflows/backend-ci.yml index 3b4b296..7118702 100644 --- a/.github/workflows/backend-ci.yml +++ b/.github/workflows/backend-ci.yml @@ -28,7 +28,7 @@ jobs: - name: dotnet build and publish run: | cd backend - dotnet publish --configuration Release --artifacts-path ./publish/ backend.sln + dotnet publish --configuration Release --artifacts-path ./publish/ Socialize.slnx # Deploy to Azure WebApp - name: Deploy to Azure WebApp diff --git a/.gitignore b/.gitignore index 69ed443..d02de66 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,16 @@ .DS_Store Thumbs.db +# .NET +bin/ +obj/ +TestResults/ + +# Node +node_modules/ +dist/ +.vite/ + # Local environment files *.local .env.local diff --git a/AGENTS.md b/AGENTS.md index 3b01f0b..2ec85cb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,103 +1,74 @@ -# AGENTS.md +# AGENTS -## Purpose -This document is a working guide for coding agents in this repository. It captures the current architecture, conventions, and safe execution workflow for making reliable changes. +This repository is designed for human + AI agent collaboration. -## Documentation-First Workflow -Agents must treat repository documentation as the source of truth. Conversation history is secondary and may be incomplete, stale, or contradictory. +## Read Order -Before making any substantial code change, agents must read the relevant docs first. At minimum, inspect: -- `AGENTS.md` -- `docs/LLM_DEVELOPMENT_WORKFLOW.md` -- `docs/PRODUCT.md` when product behavior, UX, or user workflow may change -- `docs/ARCHITECTURE.md` when structure, module boundaries, routing, data flow, or integration points may change -- `docs/CONVENTIONS.md` when adding or modifying code patterns -- `docs/DECISIONS.md` before revisiting architecture or product decisions -- the active `docs/tasks/TASK-*.md` file when one exists +Before meaningful code changes, read: -If one of these files does not exist yet, do not invent broad behavior from chat history. State what is missing and proceed only with the narrowest safe interpretation of the current task. +1. `README.md` +2. `docs/AGENTIC_WORKFLOW.md` +3. `docs/ARCHITECTURE.md` +4. `docs/DEVELOPMENT_WORKFLOW.md` +5. `docs/PRODUCT.md` +6. `docs/CONVENTIONS.md` +7. Relevant file in `docs/FEATURES/` +8. Relevant file in `docs/TASKS/` -For non-trivial work, follow this sequence: -1. Read the relevant docs and existing code. -2. Restate the task in a short summary. -3. Identify backend impact, frontend impact, data impact, and documentation impact. -4. List files likely to change. -5. Surface ambiguities or risky assumptions. -6. Propose a minimal implementation plan. -7. Implement only the approved or clearly requested scope. -8. Validate with the relevant commands before finishing when possible. +## Core Rules -Do not use a long chat thread as the durable memory for the project. Durable decisions, conventions, and task requirements belong in repository docs. - -## Pair Working Mode -- Work as a pair with the repository owner, not as an isolated implementer. -- Before substantial changes, read the relevant docs first, then restate the task briefly and inspect the existing code. -- Surface assumptions, tradeoffs, and blockers early instead of silently picking risky directions. -- Prefer small, reviewable increments when the product direction is still being shaped. -- When requirements are exploratory, help turn them into concrete workflows, domain language, and next implementation steps. -- Do not rewrite broad areas of the codebase without clear justification from the current task. -- Preserve user changes in the worktree and treat uncommitted files as active collaboration unless told otherwise. -- When creating commits, use the Conventional Commits format, for example `docs: update product planning`. +- Do not invent architecture. +- Work from docs, feature specs, and task files instead of long chat history. +- Keep backend code under `backend/src/Socialize.Api`. +- The solution file is `backend/Socialize.slnx`. +- Backend feature code currently follows FastEndpoints module folders under `Modules/`. +- Frontend feature work should prefer `frontend/src/features/` for new isolated slices while preserving existing route/store code until a task migrates it. +- Frontend runtime config must flow through `frontend/src/config.js`. +- If backend contracts change, run `./scripts/update-openapi.sh` when the backend is running. +- Dev servers use HTTP and bind to `0.0.0.0` for LAN access. +- Avoid broad refactors unless the task explicitly asks for one. ## Repository Layout -- `backend/`: ASP.NET Core (`net10.0`) API using FastEndpoints, EF Core (PostgreSQL), ASP.NET Identity, and modular bounded contexts for workflow data. -- `frontend/`: Vue 3 + Vite + Vuetify + Pinia + Vue Router + Tailwind CSS SPA. -- `.github/workflows/`: build/deploy pipelines for backend (Azure Web App) and frontend (Azure Static Web Apps). + +- `backend/src/Socialize.Api/`: ASP.NET Core `net10.0` API using FastEndpoints, EF Core, PostgreSQL, ASP.NET Identity, and workflow modules. +- `backend/tests/Socialize.Tests/`: backend test project scaffold. +- `frontend/`: Vue 3 + Vite + Vuetify + Pinia SPA. +- `docs/FEATURES/`: product and technical feature specs. +- `docs/TASKS/`: implementation tickets for coding agents. +- `docs/PROMPTS/`: reusable agent prompt templates. +- `docs/DECISIONS/`: architecture and product decision records. +- `shared/openapi/`: backend OpenAPI schema snapshots. +- `scripts/`: root developer workflow commands. +- `deploy/caddy/`: Caddy reverse proxy config for Docker Compose. ## Local Runbook -### Backend -- Prereqs: .NET 10 SDK, Docker, PostgreSQL container. -- Start database: - - `cd backend` - - `./scripts/start-infrastructure.sh` -- Run API: - - `dotnet run --project Socialize.Api.csproj` (from `backend/`) -- Local API URL: - - `http://localhost:5000` -- Swagger/OpenAPI UI in dev: - - `/api` -### Frontend -- Prereqs: Node/npm. -- Runtime configuration: - - frontend app config is loaded from `.env.development` and `.env.production` - - `frontend/src/config.js` is the single frontend source of truth for runtime env access -- Commands: - - `cd frontend && npm install` - - `npm run dev` - - `npm run build` -- Local dev server: - - `http://localhost:5173` +Start infrastructure: -## Backend Architecture -### Composition Root -- Entry point: `backend/Program.cs`. -- Registers: - - Web services/auth (`backend/DependencyInjection.cs`) - - Infrastructure services (`backend/Infrastructure/DependencyInjection.cs`) - - Modules: Identity, Workspaces, Clients, Projects, ContentItems, Assets, Comments, Approvals, Notifications. -- Each module has: - - `Add{Module}Module(...)` to register DbContext/services. - - `Use{Module}ModuleAsync()` to auto-run migrations at startup. +```bash +./scripts/start-infrastructure.sh +``` -### API Style -- FastEndpoints-based handlers. -- Pattern: request/response records + optional FluentValidation validator + handler class. -- Tagging via `Options(o => o.WithTags("..."))`. -- File upload handlers call `AllowFileUploads()`. +Run backend: -### Data Boundaries -- Separate DbContext per module: - - Identity, Workspaces, Clients, Projects, ContentItems, Assets, Comments, Approvals, Notifications. -- Migrations are module-scoped under each `Modules/*/Migrations` folder. +```bash +./scripts/dev-backend.sh +``` -### Auth/Security -- JWT is generated manually in `Infrastructure/Security/GenerateJwtToken.cs`. -- Refresh-token flow is implemented in Identity handlers (`/api/users/login`, `/api/users/refresh`). -- User claim helpers live in `Infrastructure/Security/ClaimsPrincipalExtensions.cs`. -- Role-gated frontend routes currently use `Administrator` and `Manager` checks for settings access. +Run frontend: + +```bash +./scripts/dev-frontend.sh +``` + +Update OpenAPI: + +```bash +./scripts/update-openapi.sh +``` + +## Current Domain Modules -### Current Domain Modules - `Identity`: authentication, refresh tokens, email verification, password reset, social login. - `Workspaces`: workspace membership, workspace settings, access scoping. - `Clients`: client records and primary contacts tied to workspaces. @@ -108,82 +79,44 @@ Do not use a long chat thread as the durable memory for the project. Durable dec - `Approvals`: review decisions and workflow state transitions. - `Notifications`: activity feed and unread workflow notifications. -## Frontend Architecture -### Bootstrap -- `frontend/src/main.js` wires Vue app + Pinia + Vuetify + Router + i18n + Google OAuth + Toasts. -- `frontend/src/config.js` is the app-facing runtime configuration module. Do not scatter `import.meta.env` reads across the app. +## Task Discipline -### Routing -- Defined in `frontend/src/router/router.js`. -- Route guards enforce: - - `meta.requiresAuth` - - `meta.notAuthenticated` - - optional `meta.roles` -- Primary authenticated app routes live under `/app/*`. +Agents should work from task files in `docs/TASKS/`. -### State Management -- Pinia stores: - - `authStore`: token lifecycle + refresh concurrency guard. - - `workspaceStore`: active workspace context. - - `clientsStore`: client list and creation flows. - - `projectsStore`: project list and creation flows. - - `contentItemsStore` and `contentItemDetailStore`: content item listing/detail flows. - - `reviewQueueStore`: pending review work. - - `notificationsStore`: workflow notifications. - - `userProfileStore`: current user profile and account edits. +A good task: -### API Client -- Axios client in `frontend/src/plugins/api.js`. -- Injects bearer token, proactively refreshes near expiry, retries once on 401. +- has a clear goal +- names the relevant feature spec +- has a small scope +- lists likely files +- lists validation commands -## High-Value Domains -- Identity and social login (`backend/Modules/Identity/*`, `frontend/src/views/auth/*`). -- Workspace-scoped operations and role checks (`backend/Modules/Workspaces/*`, `frontend/src/stores/workspaceStore.js`, `frontend/src/router/router.js`). -- Client and project workflow (`backend/Modules/Clients/*`, `backend/Modules/Projects/*`, `frontend/src/views/app/ClientsView.vue`, `frontend/src/views/app/ProjectsView.vue`). -- Content review lifecycle (`backend/Modules/ContentItems/*`, `backend/Modules/Assets/*`, `backend/Modules/Comments/*`, `backend/Modules/Approvals/*`, `frontend/src/views/app/ContentItemsView.vue`, `frontend/src/views/app/ContentItemDetailView.vue`, `frontend/src/views/app/ReviewQueueView.vue`). -- Notifications and workflow awareness (`backend/Modules/Notifications/*`, `frontend/src/stores/notificationsStore.js`). +If no task exists, create one before implementing a meaningful feature. -## Task-Driven Development With Agents -Use `docs/tasks/TASK-*.md` files as LLM-friendly implementation tickets. A task file should be self-contained enough for a fresh agent to understand the desired change without relying on a long conversation. +## Validation -A good task file defines: -- objective and product context -- scope and out of scope -- backend requirements, API contract, validation, data, authorization -- frontend requirements, route/screen, components, state, API integration, UX states -- files likely involved -- acceptance criteria -- validation plan -- risks and open questions +Backend: -Features are fullstack by default unless the task explicitly says otherwise. Do not assume a feature is backend-only. For user-facing work, define both backend and frontend behavior before implementation. +```bash +dotnet build backend/Socialize.slnx +dotnet test backend/Socialize.slnx +``` -When an adjacent issue is discovered outside the task scope, do not fix it opportunistically. Report it as a suggested backlog item or add it to `docs/BACKLOG.md` if explicitly asked. +Frontend: -## Agent Working Rules For This Repo -1. Keep module boundaries intact. Do not couple DbContexts across modules. -2. When adding endpoints, follow existing FastEndpoints pattern with validator + explicit route + tag. -3. If schema changes are needed, generate migration in the matching module only. -4. Preserve token refresh behavior in frontend client/store; avoid introducing parallel refresh races. -5. Keep frontend runtime configuration centralized in `frontend/src/config.js` and `.env.*`; do not introduce ad hoc env fallbacks. -6. Preserve workspace scoping and route-role checks when editing app flows. -7. Do not commit secrets. Existing appsettings and env files include sensitive-looking values; treat them as legacy and avoid propagating. -8. For non-trivial features, prefer a `docs/tasks/TASK-*.md` file before implementation. -9. Treat frontend behavior as part of the feature definition: route, components, Pinia store usage, API integration, loading/error/success states, and navigation must be explicit or derived from existing patterns. -10. If requirements conflict with repository docs, stop and surface the conflict instead of silently choosing one. +```bash +cd frontend +npm run build +``` -## Validation Checklist Before Finishing -- Backend: - - `cd backend && dotnet build Socialize.Api.csproj` - - run affected endpoint flows if change touches handlers/auth/workspace scoping/data writes -- Frontend: - - `cd frontend && npm run build` - - validate affected route/store interactions in browser when UI behavior changed -- If migrations were changed: - - ensure module context name/output directory remain consistent with `backend/scripts/add-migration.sh`. +Contract changes: -## Notes / Known Sharp Edges -- Frontend config should come through `.env.development` / `.env.production` and `frontend/src/config.js`; avoid direct `import.meta.env` reads in feature code. -- Backend development now runs on HTTP locally (`http://localhost:5000`), while HTTPS redirection stays enabled outside development. -- `frontend/.env.development` is currently checked in and points `VITE_API_URL` to `http://192.168.1.2:5000`; verify whether changes should target `localhost` or the LAN host before editing. -- Some style/formatting is inconsistent across JS/Vue/C# files; minimize churn to touched lines. +```bash +./scripts/update-openapi.sh +``` + +## Sharp Edges + +- Existing checked-in env and appsettings files may include legacy sensitive-looking values; do not propagate those values into new docs or templates. +- The frontend is still JavaScript, not the TypeScript starter app generated by the bootstrap script. New OpenAPI scaffolding exists, but migrating app code to generated typed API calls should happen by task. +- Some existing frontend code still lives under `views/`, `stores/`, and `plugins/`. Move it into feature folders only when a task explicitly owns that migration. diff --git a/README.md b/README.md index 482002e..17cbafc 100644 --- a/README.md +++ b/README.md @@ -1,88 +1,101 @@ # Socialize -Socialize is a workflow application for social media content review, revision, approval, and publication readiness. +Socialize is a workspace-based workflow application for social media content review, revision, approval, and publication readiness. -It is not a public social network. The current product direction is a workspace-based review tool for internal teams, providers, and client approvers. +It is not a public social network. The product is for internal teams, providers, and client approvers coordinating content work before publication. -## Repository Structure +## Monorepo -- `backend/`: ASP.NET Core `net10.0` API with FastEndpoints, EF Core, PostgreSQL, and modular bounded contexts. -- `frontend/`: Vue 3 + Vite + Vuetify + Pinia SPA. -- `docs/`: product, planning, and archived project documentation. - -## Current Backend Modules - -- `Identity` -- `Workspaces` -- `Clients` -- `Projects` -- `ContentItems` -- `Assets` -- `Comments` -- `Approvals` -- `Notifications` +- Backend: .NET 10 Web API in `backend/src/Socialize.Api` +- Backend tests: `backend/tests/Socialize.Tests` +- Frontend: Vue 3 + Vite + Vuetify + Pinia in `frontend` +- API contract: OpenAPI snapshot in `shared/openapi` +- Deployment: Docker Compose + Caddy +- Agentic workflow: specs, task files, and prompt templates under `docs` ## Local Development -### Backend - -Prerequisites: - -- .NET 10 SDK -- Docker - -Start infrastructure: +Terminal 1: ```bash -cd backend ./scripts/start-infrastructure.sh +./scripts/dev-backend.sh ``` -Run the API: +Terminal 2: ```bash -cd backend -dotnet run --project Socialize.Api.csproj +./scripts/dev-frontend.sh ``` -Local backend URL: +Frontend: -- `http://localhost:5000` -- Swagger UI: `http://localhost:5000/api` +```txt +http://localhost:5173 +http://:5173 +``` -### Frontend +Backend: -Prerequisites: +```txt +http://localhost:5080 +http://:5080 +``` -- Node.js / npm +Swagger UI: -The frontend reads runtime values from: +```txt +http://localhost:5080/api +``` -- `frontend/.env.development` -- `frontend/.env.production` -- `frontend/src/config.js` +## Update Frontend API Types -Run the frontend: +The backend must be running first. + +```bash +./scripts/update-openapi.sh +``` + +This writes: + +```txt +shared/openapi/openapi.json +frontend/src/api/schema.d.ts +``` + +## Docker Compose + +```bash +docker compose up --build +``` + +Then open: + +```txt +http://localhost:8080 +http://:8080 +``` + +## Solution + +```bash +dotnet build backend/Socialize.slnx +dotnet test backend/Socialize.slnx +``` + +## Frontend Build ```bash cd frontend -npm install -npm run dev +npm run build ``` -Local frontend URL: +## Agentic Workflow -- `http://localhost:5173` +Start here: -## Validation +```txt +docs/AGENTIC_WORKFLOW.md +``` -- Backend: `cd backend && dotnet build Socialize.Api.csproj` -- Frontend: `cd frontend && npm run build` - -## Docs - -- [docs/README.md](/home/jbourdon/repos/social-media/docs/README.md) -- [docs/product/vision.md](/home/jbourdon/repos/social-media/docs/product/vision.md) -- [docs/product/glossary.md](/home/jbourdon/repos/social-media/docs/product/glossary.md) -- [docs/constraints.md](/home/jbourdon/repos/social-media/docs/constraints.md) -- [AGENTS.md](/home/jbourdon/repos/social-media/AGENTS.md) +Use feature specs, task files, and prompt templates instead of asking agents to work from vague chat history. diff --git a/backend/Socialize.slnx b/backend/Socialize.slnx new file mode 100644 index 0000000..dffc9aa --- /dev/null +++ b/backend/Socialize.slnx @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/backend/backend.sln b/backend/backend.sln deleted file mode 100644 index f90568c..0000000 --- a/backend/backend.sln +++ /dev/null @@ -1,16 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Socialize.Api", "Socialize.Api.csproj", "{D790B528-6968-4CCD-A25D-A108A82CBDAC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D790B528-6968-4CCD-A25D-A108A82CBDAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D790B528-6968-4CCD-A25D-A108A82CBDAC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D790B528-6968-4CCD-A25D-A108A82CBDAC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D790B528-6968-4CCD-A25D-A108A82CBDAC}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/backend/scripts/add-migration.sh b/backend/scripts/add-migration.sh index ac6fb74..7973d1f 100755 --- a/backend/scripts/add-migration.sh +++ b/backend/scripts/add-migration.sh @@ -13,5 +13,7 @@ fi dotnet ef migrations add \ --context "Socialize.Modules.${MODULE_NAME}.Data.${MODULE_NAME}DbContext" \ --configuration Debug \ + --project "src/Socialize.Api/Socialize.Api.csproj" \ + --startup-project "src/Socialize.Api/Socialize.Api.csproj" \ --output-dir "Modules/${MODULE_NAME}/Migrations" \ "$MIGRATION_NAME" diff --git a/backend/scripts/update-databases.sh b/backend/scripts/update-databases.sh index 5917e5c..1075575 100755 --- a/backend/scripts/update-databases.sh +++ b/backend/scripts/update-databases.sh @@ -16,6 +16,8 @@ UPDATE_COMMAND=( dotnet ef database update --context "Socialize.Modules.${MODULE_NAME}.Data.${MODULE_NAME}DbContext" --configuration Debug + --project "src/Socialize.Api/Socialize.Api.csproj" + --startup-project "src/Socialize.Api/Socialize.Api.csproj" ) if [ -n "$TARGET_MIGRATION" ]; then diff --git a/backend/Common/Domain/Entity.cs b/backend/src/Socialize.Api/Common/Domain/Entity.cs similarity index 100% rename from backend/Common/Domain/Entity.cs rename to backend/src/Socialize.Api/Common/Domain/Entity.cs diff --git a/backend/Data/AppDbContext.cs b/backend/src/Socialize.Api/Data/AppDbContext.cs similarity index 100% rename from backend/Data/AppDbContext.cs rename to backend/src/Socialize.Api/Data/AppDbContext.cs diff --git a/backend/DependencyInjection.cs b/backend/src/Socialize.Api/DependencyInjection.cs similarity index 100% rename from backend/DependencyInjection.cs rename to backend/src/Socialize.Api/DependencyInjection.cs diff --git a/backend/src/Socialize.Api/Dockerfile b/backend/src/Socialize.Api/Dockerfile new file mode 100644 index 0000000..6e7fa65 --- /dev/null +++ b/backend/src/Socialize.Api/Dockerfile @@ -0,0 +1,25 @@ +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /src + +COPY backend/Socialize.slnx backend/ +COPY backend/src/Socialize.Api/Socialize.Api.csproj backend/src/Socialize.Api/ +COPY backend/tests/Socialize.Tests/Socialize.Tests.csproj backend/tests/Socialize.Tests/ + +RUN dotnet restore backend/Socialize.slnx + +COPY backend/ backend/ + +RUN dotnet publish backend/src/Socialize.Api/Socialize.Api.csproj \ + -c Release \ + -o /app/publish \ + --no-restore + +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime +WORKDIR /app +COPY --from=build /app/publish . + +ENV ASPNETCORE_URLS=http://0.0.0.0:8080 +ENV ASPNETCORE_ENVIRONMENT=Production + +EXPOSE 8080 +ENTRYPOINT ["dotnet", "Socialize.Api.dll"] diff --git a/backend/Folder.DotSettings b/backend/src/Socialize.Api/Folder.DotSettings similarity index 100% rename from backend/Folder.DotSettings rename to backend/src/Socialize.Api/Folder.DotSettings diff --git a/backend/GlobalUsings.cs b/backend/src/Socialize.Api/GlobalUsings.cs similarity index 100% rename from backend/GlobalUsings.cs rename to backend/src/Socialize.Api/GlobalUsings.cs diff --git a/backend/Infrastructure/BlobStorage/BlobStructure.txt b/backend/src/Socialize.Api/Infrastructure/BlobStorage/BlobStructure.txt similarity index 100% rename from backend/Infrastructure/BlobStorage/BlobStructure.txt rename to backend/src/Socialize.Api/Infrastructure/BlobStorage/BlobStructure.txt diff --git a/backend/Infrastructure/BlobStorage/Contracts/CommonFileNames.cs b/backend/src/Socialize.Api/Infrastructure/BlobStorage/Contracts/CommonFileNames.cs similarity index 100% rename from backend/Infrastructure/BlobStorage/Contracts/CommonFileNames.cs rename to backend/src/Socialize.Api/Infrastructure/BlobStorage/Contracts/CommonFileNames.cs diff --git a/backend/Infrastructure/BlobStorage/Contracts/ContainerNames.cs b/backend/src/Socialize.Api/Infrastructure/BlobStorage/Contracts/ContainerNames.cs similarity index 100% rename from backend/Infrastructure/BlobStorage/Contracts/ContainerNames.cs rename to backend/src/Socialize.Api/Infrastructure/BlobStorage/Contracts/ContainerNames.cs diff --git a/backend/Infrastructure/BlobStorage/Contracts/ContentTypes.cs b/backend/src/Socialize.Api/Infrastructure/BlobStorage/Contracts/ContentTypes.cs similarity index 100% rename from backend/Infrastructure/BlobStorage/Contracts/ContentTypes.cs rename to backend/src/Socialize.Api/Infrastructure/BlobStorage/Contracts/ContentTypes.cs diff --git a/backend/Infrastructure/BlobStorage/Contracts/IBlobStorage.cs b/backend/src/Socialize.Api/Infrastructure/BlobStorage/Contracts/IBlobStorage.cs similarity index 100% rename from backend/Infrastructure/BlobStorage/Contracts/IBlobStorage.cs rename to backend/src/Socialize.Api/Infrastructure/BlobStorage/Contracts/IBlobStorage.cs diff --git a/backend/Infrastructure/BlobStorage/Contracts/SubDirectoryNames.cs b/backend/src/Socialize.Api/Infrastructure/BlobStorage/Contracts/SubDirectoryNames.cs similarity index 100% rename from backend/Infrastructure/BlobStorage/Contracts/SubDirectoryNames.cs rename to backend/src/Socialize.Api/Infrastructure/BlobStorage/Contracts/SubDirectoryNames.cs diff --git a/backend/Infrastructure/BlobStorage/Services/AzureBlobStorage.cs b/backend/src/Socialize.Api/Infrastructure/BlobStorage/Services/AzureBlobStorage.cs similarity index 100% rename from backend/Infrastructure/BlobStorage/Services/AzureBlobStorage.cs rename to backend/src/Socialize.Api/Infrastructure/BlobStorage/Services/AzureBlobStorage.cs diff --git a/backend/Infrastructure/Configuration/WebsiteOptions.cs b/backend/src/Socialize.Api/Infrastructure/Configuration/WebsiteOptions.cs similarity index 100% rename from backend/Infrastructure/Configuration/WebsiteOptions.cs rename to backend/src/Socialize.Api/Infrastructure/Configuration/WebsiteOptions.cs diff --git a/backend/Infrastructure/DependencyInjection.cs b/backend/src/Socialize.Api/Infrastructure/DependencyInjection.cs similarity index 100% rename from backend/Infrastructure/DependencyInjection.cs rename to backend/src/Socialize.Api/Infrastructure/DependencyInjection.cs diff --git a/backend/Infrastructure/Development/DevelopmentSeedExtensions.cs b/backend/src/Socialize.Api/Infrastructure/Development/DevelopmentSeedExtensions.cs similarity index 100% rename from backend/Infrastructure/Development/DevelopmentSeedExtensions.cs rename to backend/src/Socialize.Api/Infrastructure/Development/DevelopmentSeedExtensions.cs diff --git a/backend/Infrastructure/Development/DevelopmentSeedOptions.cs b/backend/src/Socialize.Api/Infrastructure/Development/DevelopmentSeedOptions.cs similarity index 100% rename from backend/Infrastructure/Development/DevelopmentSeedOptions.cs rename to backend/src/Socialize.Api/Infrastructure/Development/DevelopmentSeedOptions.cs diff --git a/backend/Infrastructure/Emailer/Configuration/EmailerOptions.cs b/backend/src/Socialize.Api/Infrastructure/Emailer/Configuration/EmailerOptions.cs similarity index 100% rename from backend/Infrastructure/Emailer/Configuration/EmailerOptions.cs rename to backend/src/Socialize.Api/Infrastructure/Emailer/Configuration/EmailerOptions.cs diff --git a/backend/Infrastructure/Emailer/Contracts/IEmailSender.cs b/backend/src/Socialize.Api/Infrastructure/Emailer/Contracts/IEmailSender.cs similarity index 100% rename from backend/Infrastructure/Emailer/Contracts/IEmailSender.cs rename to backend/src/Socialize.Api/Infrastructure/Emailer/Contracts/IEmailSender.cs diff --git a/backend/Infrastructure/Emailer/Services/LoggerEmailSender.cs b/backend/src/Socialize.Api/Infrastructure/Emailer/Services/LoggerEmailSender.cs similarity index 100% rename from backend/Infrastructure/Emailer/Services/LoggerEmailSender.cs rename to backend/src/Socialize.Api/Infrastructure/Emailer/Services/LoggerEmailSender.cs diff --git a/backend/Infrastructure/Emailer/Services/PostmarkEmailSender.cs b/backend/src/Socialize.Api/Infrastructure/Emailer/Services/PostmarkEmailSender.cs similarity index 100% rename from backend/Infrastructure/Emailer/Services/PostmarkEmailSender.cs rename to backend/src/Socialize.Api/Infrastructure/Emailer/Services/PostmarkEmailSender.cs diff --git a/backend/Infrastructure/Emailer/Services/ResendEmailSender.cs b/backend/src/Socialize.Api/Infrastructure/Emailer/Services/ResendEmailSender.cs similarity index 100% rename from backend/Infrastructure/Emailer/Services/ResendEmailSender.cs rename to backend/src/Socialize.Api/Infrastructure/Emailer/Services/ResendEmailSender.cs diff --git a/backend/Infrastructure/Payments/Stripe/Configuration/StripeOptions.cs b/backend/src/Socialize.Api/Infrastructure/Payments/Stripe/Configuration/StripeOptions.cs similarity index 100% rename from backend/Infrastructure/Payments/Stripe/Configuration/StripeOptions.cs rename to backend/src/Socialize.Api/Infrastructure/Payments/Stripe/Configuration/StripeOptions.cs diff --git a/backend/Infrastructure/Security/AccessScopeService.cs b/backend/src/Socialize.Api/Infrastructure/Security/AccessScopeService.cs similarity index 100% rename from backend/Infrastructure/Security/AccessScopeService.cs rename to backend/src/Socialize.Api/Infrastructure/Security/AccessScopeService.cs diff --git a/backend/Infrastructure/Security/ClaimsPrincipalExtensions.cs b/backend/src/Socialize.Api/Infrastructure/Security/ClaimsPrincipalExtensions.cs similarity index 100% rename from backend/Infrastructure/Security/ClaimsPrincipalExtensions.cs rename to backend/src/Socialize.Api/Infrastructure/Security/ClaimsPrincipalExtensions.cs diff --git a/backend/Infrastructure/Security/GenerateJwtToken.cs b/backend/src/Socialize.Api/Infrastructure/Security/GenerateJwtToken.cs similarity index 100% rename from backend/Infrastructure/Security/GenerateJwtToken.cs rename to backend/src/Socialize.Api/Infrastructure/Security/GenerateJwtToken.cs diff --git a/backend/Infrastructure/Security/KnownClaims.cs b/backend/src/Socialize.Api/Infrastructure/Security/KnownClaims.cs similarity index 100% rename from backend/Infrastructure/Security/KnownClaims.cs rename to backend/src/Socialize.Api/Infrastructure/Security/KnownClaims.cs diff --git a/backend/Infrastructure/Security/MissingClaimException.cs b/backend/src/Socialize.Api/Infrastructure/Security/MissingClaimException.cs similarity index 100% rename from backend/Infrastructure/Security/MissingClaimException.cs rename to backend/src/Socialize.Api/Infrastructure/Security/MissingClaimException.cs diff --git a/backend/Infrastructure/Security/PasswordGenerator.cs b/backend/src/Socialize.Api/Infrastructure/Security/PasswordGenerator.cs similarity index 100% rename from backend/Infrastructure/Security/PasswordGenerator.cs rename to backend/src/Socialize.Api/Infrastructure/Security/PasswordGenerator.cs diff --git a/backend/Infrastructure/Security/RefreshTokenGenerator.cs b/backend/src/Socialize.Api/Infrastructure/Security/RefreshTokenGenerator.cs similarity index 100% rename from backend/Infrastructure/Security/RefreshTokenGenerator.cs rename to backend/src/Socialize.Api/Infrastructure/Security/RefreshTokenGenerator.cs diff --git a/backend/Infrastructure/YouTube/YouTubeUrlHelper.cs b/backend/src/Socialize.Api/Infrastructure/YouTube/YouTubeUrlHelper.cs similarity index 100% rename from backend/Infrastructure/YouTube/YouTubeUrlHelper.cs rename to backend/src/Socialize.Api/Infrastructure/YouTube/YouTubeUrlHelper.cs diff --git a/backend/Migrations/20260423061407_Initial.Designer.cs b/backend/src/Socialize.Api/Migrations/20260423061407_Initial.Designer.cs similarity index 100% rename from backend/Migrations/20260423061407_Initial.Designer.cs rename to backend/src/Socialize.Api/Migrations/20260423061407_Initial.Designer.cs diff --git a/backend/Migrations/20260423061407_Initial.cs b/backend/src/Socialize.Api/Migrations/20260423061407_Initial.cs similarity index 100% rename from backend/Migrations/20260423061407_Initial.cs rename to backend/src/Socialize.Api/Migrations/20260423061407_Initial.cs diff --git a/backend/Migrations/AppDbContextModelSnapshot.cs b/backend/src/Socialize.Api/Migrations/AppDbContextModelSnapshot.cs similarity index 100% rename from backend/Migrations/AppDbContextModelSnapshot.cs rename to backend/src/Socialize.Api/Migrations/AppDbContextModelSnapshot.cs diff --git a/backend/Modules/Approvals/Data/ApprovalDecision.cs b/backend/src/Socialize.Api/Modules/Approvals/Data/ApprovalDecision.cs similarity index 100% rename from backend/Modules/Approvals/Data/ApprovalDecision.cs rename to backend/src/Socialize.Api/Modules/Approvals/Data/ApprovalDecision.cs diff --git a/backend/Modules/Approvals/Data/ApprovalRequest.cs b/backend/src/Socialize.Api/Modules/Approvals/Data/ApprovalRequest.cs similarity index 100% rename from backend/Modules/Approvals/Data/ApprovalRequest.cs rename to backend/src/Socialize.Api/Modules/Approvals/Data/ApprovalRequest.cs diff --git a/backend/Modules/Approvals/DependencyInjection.cs b/backend/src/Socialize.Api/Modules/Approvals/DependencyInjection.cs similarity index 100% rename from backend/Modules/Approvals/DependencyInjection.cs rename to backend/src/Socialize.Api/Modules/Approvals/DependencyInjection.cs diff --git a/backend/Modules/Approvals/Handlers/CreateApprovalRequest.cs b/backend/src/Socialize.Api/Modules/Approvals/Handlers/CreateApprovalRequest.cs similarity index 100% rename from backend/Modules/Approvals/Handlers/CreateApprovalRequest.cs rename to backend/src/Socialize.Api/Modules/Approvals/Handlers/CreateApprovalRequest.cs diff --git a/backend/Modules/Approvals/Handlers/GetApprovals.cs b/backend/src/Socialize.Api/Modules/Approvals/Handlers/GetApprovals.cs similarity index 100% rename from backend/Modules/Approvals/Handlers/GetApprovals.cs rename to backend/src/Socialize.Api/Modules/Approvals/Handlers/GetApprovals.cs diff --git a/backend/Modules/Approvals/Handlers/SubmitApprovalDecision.cs b/backend/src/Socialize.Api/Modules/Approvals/Handlers/SubmitApprovalDecision.cs similarity index 100% rename from backend/Modules/Approvals/Handlers/SubmitApprovalDecision.cs rename to backend/src/Socialize.Api/Modules/Approvals/Handlers/SubmitApprovalDecision.cs diff --git a/backend/Modules/Assets/Data/Asset.cs b/backend/src/Socialize.Api/Modules/Assets/Data/Asset.cs similarity index 100% rename from backend/Modules/Assets/Data/Asset.cs rename to backend/src/Socialize.Api/Modules/Assets/Data/Asset.cs diff --git a/backend/Modules/Assets/Data/AssetRevision.cs b/backend/src/Socialize.Api/Modules/Assets/Data/AssetRevision.cs similarity index 100% rename from backend/Modules/Assets/Data/AssetRevision.cs rename to backend/src/Socialize.Api/Modules/Assets/Data/AssetRevision.cs diff --git a/backend/Modules/Assets/DependencyInjection.cs b/backend/src/Socialize.Api/Modules/Assets/DependencyInjection.cs similarity index 100% rename from backend/Modules/Assets/DependencyInjection.cs rename to backend/src/Socialize.Api/Modules/Assets/DependencyInjection.cs diff --git a/backend/Modules/Assets/Handlers/CreateAssetRevision.cs b/backend/src/Socialize.Api/Modules/Assets/Handlers/CreateAssetRevision.cs similarity index 100% rename from backend/Modules/Assets/Handlers/CreateAssetRevision.cs rename to backend/src/Socialize.Api/Modules/Assets/Handlers/CreateAssetRevision.cs diff --git a/backend/Modules/Assets/Handlers/CreateGoogleDriveAsset.cs b/backend/src/Socialize.Api/Modules/Assets/Handlers/CreateGoogleDriveAsset.cs similarity index 100% rename from backend/Modules/Assets/Handlers/CreateGoogleDriveAsset.cs rename to backend/src/Socialize.Api/Modules/Assets/Handlers/CreateGoogleDriveAsset.cs diff --git a/backend/Modules/Assets/Handlers/GetAssets.cs b/backend/src/Socialize.Api/Modules/Assets/Handlers/GetAssets.cs similarity index 100% rename from backend/Modules/Assets/Handlers/GetAssets.cs rename to backend/src/Socialize.Api/Modules/Assets/Handlers/GetAssets.cs diff --git a/backend/Modules/Clients/Data/Client.cs b/backend/src/Socialize.Api/Modules/Clients/Data/Client.cs similarity index 100% rename from backend/Modules/Clients/Data/Client.cs rename to backend/src/Socialize.Api/Modules/Clients/Data/Client.cs diff --git a/backend/Modules/Clients/DependencyInjection.cs b/backend/src/Socialize.Api/Modules/Clients/DependencyInjection.cs similarity index 100% rename from backend/Modules/Clients/DependencyInjection.cs rename to backend/src/Socialize.Api/Modules/Clients/DependencyInjection.cs diff --git a/backend/Modules/Clients/Handlers/ChangeClientPortrait.cs b/backend/src/Socialize.Api/Modules/Clients/Handlers/ChangeClientPortrait.cs similarity index 100% rename from backend/Modules/Clients/Handlers/ChangeClientPortrait.cs rename to backend/src/Socialize.Api/Modules/Clients/Handlers/ChangeClientPortrait.cs diff --git a/backend/Modules/Clients/Handlers/CreateClient.cs b/backend/src/Socialize.Api/Modules/Clients/Handlers/CreateClient.cs similarity index 100% rename from backend/Modules/Clients/Handlers/CreateClient.cs rename to backend/src/Socialize.Api/Modules/Clients/Handlers/CreateClient.cs diff --git a/backend/Modules/Clients/Handlers/GetClients.cs b/backend/src/Socialize.Api/Modules/Clients/Handlers/GetClients.cs similarity index 100% rename from backend/Modules/Clients/Handlers/GetClients.cs rename to backend/src/Socialize.Api/Modules/Clients/Handlers/GetClients.cs diff --git a/backend/Modules/Clients/Handlers/UpdateClient.cs b/backend/src/Socialize.Api/Modules/Clients/Handlers/UpdateClient.cs similarity index 100% rename from backend/Modules/Clients/Handlers/UpdateClient.cs rename to backend/src/Socialize.Api/Modules/Clients/Handlers/UpdateClient.cs diff --git a/backend/Modules/Comments/Data/Comment.cs b/backend/src/Socialize.Api/Modules/Comments/Data/Comment.cs similarity index 100% rename from backend/Modules/Comments/Data/Comment.cs rename to backend/src/Socialize.Api/Modules/Comments/Data/Comment.cs diff --git a/backend/Modules/Comments/DependencyInjection.cs b/backend/src/Socialize.Api/Modules/Comments/DependencyInjection.cs similarity index 100% rename from backend/Modules/Comments/DependencyInjection.cs rename to backend/src/Socialize.Api/Modules/Comments/DependencyInjection.cs diff --git a/backend/Modules/Comments/Handlers/CreateComment.cs b/backend/src/Socialize.Api/Modules/Comments/Handlers/CreateComment.cs similarity index 100% rename from backend/Modules/Comments/Handlers/CreateComment.cs rename to backend/src/Socialize.Api/Modules/Comments/Handlers/CreateComment.cs diff --git a/backend/Modules/Comments/Handlers/GetComments.cs b/backend/src/Socialize.Api/Modules/Comments/Handlers/GetComments.cs similarity index 100% rename from backend/Modules/Comments/Handlers/GetComments.cs rename to backend/src/Socialize.Api/Modules/Comments/Handlers/GetComments.cs diff --git a/backend/Modules/Comments/Handlers/ResolveComment.cs b/backend/src/Socialize.Api/Modules/Comments/Handlers/ResolveComment.cs similarity index 100% rename from backend/Modules/Comments/Handlers/ResolveComment.cs rename to backend/src/Socialize.Api/Modules/Comments/Handlers/ResolveComment.cs diff --git a/backend/Modules/ContentItems/Data/ContentItem.cs b/backend/src/Socialize.Api/Modules/ContentItems/Data/ContentItem.cs similarity index 100% rename from backend/Modules/ContentItems/Data/ContentItem.cs rename to backend/src/Socialize.Api/Modules/ContentItems/Data/ContentItem.cs diff --git a/backend/Modules/ContentItems/Data/ContentItemRevision.cs b/backend/src/Socialize.Api/Modules/ContentItems/Data/ContentItemRevision.cs similarity index 100% rename from backend/Modules/ContentItems/Data/ContentItemRevision.cs rename to backend/src/Socialize.Api/Modules/ContentItems/Data/ContentItemRevision.cs diff --git a/backend/Modules/ContentItems/DependencyInjection.cs b/backend/src/Socialize.Api/Modules/ContentItems/DependencyInjection.cs similarity index 100% rename from backend/Modules/ContentItems/DependencyInjection.cs rename to backend/src/Socialize.Api/Modules/ContentItems/DependencyInjection.cs diff --git a/backend/Modules/ContentItems/Handlers/CreateContentItem.cs b/backend/src/Socialize.Api/Modules/ContentItems/Handlers/CreateContentItem.cs similarity index 100% rename from backend/Modules/ContentItems/Handlers/CreateContentItem.cs rename to backend/src/Socialize.Api/Modules/ContentItems/Handlers/CreateContentItem.cs diff --git a/backend/Modules/ContentItems/Handlers/CreateContentItemRevision.cs b/backend/src/Socialize.Api/Modules/ContentItems/Handlers/CreateContentItemRevision.cs similarity index 100% rename from backend/Modules/ContentItems/Handlers/CreateContentItemRevision.cs rename to backend/src/Socialize.Api/Modules/ContentItems/Handlers/CreateContentItemRevision.cs diff --git a/backend/Modules/ContentItems/Handlers/GetContentItem.cs b/backend/src/Socialize.Api/Modules/ContentItems/Handlers/GetContentItem.cs similarity index 100% rename from backend/Modules/ContentItems/Handlers/GetContentItem.cs rename to backend/src/Socialize.Api/Modules/ContentItems/Handlers/GetContentItem.cs diff --git a/backend/Modules/ContentItems/Handlers/GetContentItemRevisions.cs b/backend/src/Socialize.Api/Modules/ContentItems/Handlers/GetContentItemRevisions.cs similarity index 100% rename from backend/Modules/ContentItems/Handlers/GetContentItemRevisions.cs rename to backend/src/Socialize.Api/Modules/ContentItems/Handlers/GetContentItemRevisions.cs diff --git a/backend/Modules/ContentItems/Handlers/GetContentItems.cs b/backend/src/Socialize.Api/Modules/ContentItems/Handlers/GetContentItems.cs similarity index 100% rename from backend/Modules/ContentItems/Handlers/GetContentItems.cs rename to backend/src/Socialize.Api/Modules/ContentItems/Handlers/GetContentItems.cs diff --git a/backend/Modules/ContentItems/Handlers/UpdateContentItemStatus.cs b/backend/src/Socialize.Api/Modules/ContentItems/Handlers/UpdateContentItemStatus.cs similarity index 100% rename from backend/Modules/ContentItems/Handlers/UpdateContentItemStatus.cs rename to backend/src/Socialize.Api/Modules/ContentItems/Handlers/UpdateContentItemStatus.cs diff --git a/backend/Modules/Identity/Configuration/JwtOptions.cs b/backend/src/Socialize.Api/Modules/Identity/Configuration/JwtOptions.cs similarity index 100% rename from backend/Modules/Identity/Configuration/JwtOptions.cs rename to backend/src/Socialize.Api/Modules/Identity/Configuration/JwtOptions.cs diff --git a/backend/Modules/Identity/Contracts/IUserLookup.cs b/backend/src/Socialize.Api/Modules/Identity/Contracts/IUserLookup.cs similarity index 100% rename from backend/Modules/Identity/Contracts/IUserLookup.cs rename to backend/src/Socialize.Api/Modules/Identity/Contracts/IUserLookup.cs diff --git a/backend/Modules/Identity/Contracts/KnownRoles.cs b/backend/src/Socialize.Api/Modules/Identity/Contracts/KnownRoles.cs similarity index 100% rename from backend/Modules/Identity/Contracts/KnownRoles.cs rename to backend/src/Socialize.Api/Modules/Identity/Contracts/KnownRoles.cs diff --git a/backend/Modules/Identity/Contracts/UserReference.cs b/backend/src/Socialize.Api/Modules/Identity/Contracts/UserReference.cs similarity index 100% rename from backend/Modules/Identity/Contracts/UserReference.cs rename to backend/src/Socialize.Api/Modules/Identity/Contracts/UserReference.cs diff --git a/backend/Modules/Identity/Data/IdentityService.cs b/backend/src/Socialize.Api/Modules/Identity/Data/IdentityService.cs similarity index 100% rename from backend/Modules/Identity/Data/IdentityService.cs rename to backend/src/Socialize.Api/Modules/Identity/Data/IdentityService.cs diff --git a/backend/Modules/Identity/Data/Role.cs b/backend/src/Socialize.Api/Modules/Identity/Data/Role.cs similarity index 100% rename from backend/Modules/Identity/Data/Role.cs rename to backend/src/Socialize.Api/Modules/Identity/Data/Role.cs diff --git a/backend/Modules/Identity/Data/User.cs b/backend/src/Socialize.Api/Modules/Identity/Data/User.cs similarity index 100% rename from backend/Modules/Identity/Data/User.cs rename to backend/src/Socialize.Api/Modules/Identity/Data/User.cs diff --git a/backend/Modules/Identity/Data/UserManager.cs b/backend/src/Socialize.Api/Modules/Identity/Data/UserManager.cs similarity index 100% rename from backend/Modules/Identity/Data/UserManager.cs rename to backend/src/Socialize.Api/Modules/Identity/Data/UserManager.cs diff --git a/backend/Modules/Identity/DependencyInjection.cs b/backend/src/Socialize.Api/Modules/Identity/DependencyInjection.cs similarity index 100% rename from backend/Modules/Identity/DependencyInjection.cs rename to backend/src/Socialize.Api/Modules/Identity/DependencyInjection.cs diff --git a/backend/Modules/Identity/Handlers/ChangeAddress.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/ChangeAddress.cs similarity index 100% rename from backend/Modules/Identity/Handlers/ChangeAddress.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/ChangeAddress.cs diff --git a/backend/Modules/Identity/Handlers/ChangeAlias.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/ChangeAlias.cs similarity index 100% rename from backend/Modules/Identity/Handlers/ChangeAlias.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/ChangeAlias.cs diff --git a/backend/Modules/Identity/Handlers/ChangeBirthDate.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/ChangeBirthDate.cs similarity index 100% rename from backend/Modules/Identity/Handlers/ChangeBirthDate.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/ChangeBirthDate.cs diff --git a/backend/Modules/Identity/Handlers/ChangeEmail.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/ChangeEmail.cs similarity index 100% rename from backend/Modules/Identity/Handlers/ChangeEmail.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/ChangeEmail.cs diff --git a/backend/Modules/Identity/Handlers/ChangeFullname.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/ChangeFullname.cs similarity index 100% rename from backend/Modules/Identity/Handlers/ChangeFullname.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/ChangeFullname.cs diff --git a/backend/Modules/Identity/Handlers/ChangePhone.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/ChangePhone.cs similarity index 100% rename from backend/Modules/Identity/Handlers/ChangePhone.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/ChangePhone.cs diff --git a/backend/Modules/Identity/Handlers/ChangePortrait.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/ChangePortrait.cs similarity index 100% rename from backend/Modules/Identity/Handlers/ChangePortrait.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/ChangePortrait.cs diff --git a/backend/Modules/Identity/Handlers/ForgotPassword.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/ForgotPassword.cs similarity index 100% rename from backend/Modules/Identity/Handlers/ForgotPassword.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/ForgotPassword.cs diff --git a/backend/Modules/Identity/Handlers/GetCurrentUser.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/GetCurrentUser.cs similarity index 100% rename from backend/Modules/Identity/Handlers/GetCurrentUser.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/GetCurrentUser.cs diff --git a/backend/Modules/Identity/Handlers/GetCurrentUserProfilePicture.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/GetCurrentUserProfilePicture.cs similarity index 100% rename from backend/Modules/Identity/Handlers/GetCurrentUserProfilePicture.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/GetCurrentUserProfilePicture.cs diff --git a/backend/Modules/Identity/Handlers/Login.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/Login.cs similarity index 100% rename from backend/Modules/Identity/Handlers/Login.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/Login.cs diff --git a/backend/Modules/Identity/Handlers/LoginWithFacebook.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/LoginWithFacebook.cs similarity index 100% rename from backend/Modules/Identity/Handlers/LoginWithFacebook.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/LoginWithFacebook.cs diff --git a/backend/Modules/Identity/Handlers/LoginWithGoogle.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/LoginWithGoogle.cs similarity index 100% rename from backend/Modules/Identity/Handlers/LoginWithGoogle.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/LoginWithGoogle.cs diff --git a/backend/Modules/Identity/Handlers/RefreshToken.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/RefreshToken.cs similarity index 100% rename from backend/Modules/Identity/Handlers/RefreshToken.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/RefreshToken.cs diff --git a/backend/Modules/Identity/Handlers/Register.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/Register.cs similarity index 100% rename from backend/Modules/Identity/Handlers/Register.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/Register.cs diff --git a/backend/Modules/Identity/Handlers/ResendVerification.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/ResendVerification.cs similarity index 100% rename from backend/Modules/Identity/Handlers/ResendVerification.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/ResendVerification.cs diff --git a/backend/Modules/Identity/Handlers/ResetPassword.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/ResetPassword.cs similarity index 100% rename from backend/Modules/Identity/Handlers/ResetPassword.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/ResetPassword.cs diff --git a/backend/Modules/Identity/Handlers/SetPassword.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/SetPassword.cs similarity index 100% rename from backend/Modules/Identity/Handlers/SetPassword.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/SetPassword.cs diff --git a/backend/Modules/Identity/Handlers/VerifyEmail.cs b/backend/src/Socialize.Api/Modules/Identity/Handlers/VerifyEmail.cs similarity index 100% rename from backend/Modules/Identity/Handlers/VerifyEmail.cs rename to backend/src/Socialize.Api/Modules/Identity/Handlers/VerifyEmail.cs diff --git a/backend/Modules/Identity/IdentityResultExtensions.cs b/backend/src/Socialize.Api/Modules/Identity/IdentityResultExtensions.cs similarity index 100% rename from backend/Modules/Identity/IdentityResultExtensions.cs rename to backend/src/Socialize.Api/Modules/Identity/IdentityResultExtensions.cs diff --git a/backend/Modules/Identity/Models/Result.cs b/backend/src/Socialize.Api/Modules/Identity/Models/Result.cs similarity index 100% rename from backend/Modules/Identity/Models/Result.cs rename to backend/src/Socialize.Api/Modules/Identity/Models/Result.cs diff --git a/backend/Modules/Identity/Models/RoleModel.cs b/backend/src/Socialize.Api/Modules/Identity/Models/RoleModel.cs similarity index 100% rename from backend/Modules/Identity/Models/RoleModel.cs rename to backend/src/Socialize.Api/Modules/Identity/Models/RoleModel.cs diff --git a/backend/Modules/Identity/Models/UserDto.cs b/backend/src/Socialize.Api/Modules/Identity/Models/UserDto.cs similarity index 100% rename from backend/Modules/Identity/Models/UserDto.cs rename to backend/src/Socialize.Api/Modules/Identity/Models/UserDto.cs diff --git a/backend/Modules/Identity/Models/UserModel.cs b/backend/src/Socialize.Api/Modules/Identity/Models/UserModel.cs similarity index 100% rename from backend/Modules/Identity/Models/UserModel.cs rename to backend/src/Socialize.Api/Modules/Identity/Models/UserModel.cs diff --git a/backend/Modules/Identity/Services/AccessTokenFactory.cs b/backend/src/Socialize.Api/Modules/Identity/Services/AccessTokenFactory.cs similarity index 100% rename from backend/Modules/Identity/Services/AccessTokenFactory.cs rename to backend/src/Socialize.Api/Modules/Identity/Services/AccessTokenFactory.cs diff --git a/backend/Modules/Identity/Services/EmailVerificationService.cs b/backend/src/Socialize.Api/Modules/Identity/Services/EmailVerificationService.cs similarity index 100% rename from backend/Modules/Identity/Services/EmailVerificationService.cs rename to backend/src/Socialize.Api/Modules/Identity/Services/EmailVerificationService.cs diff --git a/backend/Modules/Identity/Services/UserLookup.cs b/backend/src/Socialize.Api/Modules/Identity/Services/UserLookup.cs similarity index 100% rename from backend/Modules/Identity/Services/UserLookup.cs rename to backend/src/Socialize.Api/Modules/Identity/Services/UserLookup.cs diff --git a/backend/Modules/Notifications/Contracts/INotificationEventWriter.cs b/backend/src/Socialize.Api/Modules/Notifications/Contracts/INotificationEventWriter.cs similarity index 100% rename from backend/Modules/Notifications/Contracts/INotificationEventWriter.cs rename to backend/src/Socialize.Api/Modules/Notifications/Contracts/INotificationEventWriter.cs diff --git a/backend/Modules/Notifications/Data/NotificationEvent.cs b/backend/src/Socialize.Api/Modules/Notifications/Data/NotificationEvent.cs similarity index 100% rename from backend/Modules/Notifications/Data/NotificationEvent.cs rename to backend/src/Socialize.Api/Modules/Notifications/Data/NotificationEvent.cs diff --git a/backend/Modules/Notifications/DependencyInjection.cs b/backend/src/Socialize.Api/Modules/Notifications/DependencyInjection.cs similarity index 100% rename from backend/Modules/Notifications/DependencyInjection.cs rename to backend/src/Socialize.Api/Modules/Notifications/DependencyInjection.cs diff --git a/backend/Modules/Notifications/Handlers/GetNotifications.cs b/backend/src/Socialize.Api/Modules/Notifications/Handlers/GetNotifications.cs similarity index 100% rename from backend/Modules/Notifications/Handlers/GetNotifications.cs rename to backend/src/Socialize.Api/Modules/Notifications/Handlers/GetNotifications.cs diff --git a/backend/Modules/Notifications/Handlers/MarkNotificationAsRead.cs b/backend/src/Socialize.Api/Modules/Notifications/Handlers/MarkNotificationAsRead.cs similarity index 100% rename from backend/Modules/Notifications/Handlers/MarkNotificationAsRead.cs rename to backend/src/Socialize.Api/Modules/Notifications/Handlers/MarkNotificationAsRead.cs diff --git a/backend/Modules/Notifications/Services/NotificationEventWriter.cs b/backend/src/Socialize.Api/Modules/Notifications/Services/NotificationEventWriter.cs similarity index 100% rename from backend/Modules/Notifications/Services/NotificationEventWriter.cs rename to backend/src/Socialize.Api/Modules/Notifications/Services/NotificationEventWriter.cs diff --git a/backend/Modules/Projects/Data/Project.cs b/backend/src/Socialize.Api/Modules/Projects/Data/Project.cs similarity index 100% rename from backend/Modules/Projects/Data/Project.cs rename to backend/src/Socialize.Api/Modules/Projects/Data/Project.cs diff --git a/backend/Modules/Projects/DependencyInjection.cs b/backend/src/Socialize.Api/Modules/Projects/DependencyInjection.cs similarity index 100% rename from backend/Modules/Projects/DependencyInjection.cs rename to backend/src/Socialize.Api/Modules/Projects/DependencyInjection.cs diff --git a/backend/Modules/Projects/Handlers/CreateProject.cs b/backend/src/Socialize.Api/Modules/Projects/Handlers/CreateProject.cs similarity index 100% rename from backend/Modules/Projects/Handlers/CreateProject.cs rename to backend/src/Socialize.Api/Modules/Projects/Handlers/CreateProject.cs diff --git a/backend/Modules/Projects/Handlers/GetProjects.cs b/backend/src/Socialize.Api/Modules/Projects/Handlers/GetProjects.cs similarity index 100% rename from backend/Modules/Projects/Handlers/GetProjects.cs rename to backend/src/Socialize.Api/Modules/Projects/Handlers/GetProjects.cs diff --git a/backend/Modules/Workspaces/Data/Workspace.cs b/backend/src/Socialize.Api/Modules/Workspaces/Data/Workspace.cs similarity index 100% rename from backend/Modules/Workspaces/Data/Workspace.cs rename to backend/src/Socialize.Api/Modules/Workspaces/Data/Workspace.cs diff --git a/backend/Modules/Workspaces/Data/WorkspaceInvite.cs b/backend/src/Socialize.Api/Modules/Workspaces/Data/WorkspaceInvite.cs similarity index 100% rename from backend/Modules/Workspaces/Data/WorkspaceInvite.cs rename to backend/src/Socialize.Api/Modules/Workspaces/Data/WorkspaceInvite.cs diff --git a/backend/Modules/Workspaces/DependencyInjection.cs b/backend/src/Socialize.Api/Modules/Workspaces/DependencyInjection.cs similarity index 100% rename from backend/Modules/Workspaces/DependencyInjection.cs rename to backend/src/Socialize.Api/Modules/Workspaces/DependencyInjection.cs diff --git a/backend/Modules/Workspaces/Handlers/CreateWorkspace.cs b/backend/src/Socialize.Api/Modules/Workspaces/Handlers/CreateWorkspace.cs similarity index 100% rename from backend/Modules/Workspaces/Handlers/CreateWorkspace.cs rename to backend/src/Socialize.Api/Modules/Workspaces/Handlers/CreateWorkspace.cs diff --git a/backend/Modules/Workspaces/Handlers/CreateWorkspaceInvite.cs b/backend/src/Socialize.Api/Modules/Workspaces/Handlers/CreateWorkspaceInvite.cs similarity index 100% rename from backend/Modules/Workspaces/Handlers/CreateWorkspaceInvite.cs rename to backend/src/Socialize.Api/Modules/Workspaces/Handlers/CreateWorkspaceInvite.cs diff --git a/backend/Modules/Workspaces/Handlers/GetWorkspaceInvites.cs b/backend/src/Socialize.Api/Modules/Workspaces/Handlers/GetWorkspaceInvites.cs similarity index 100% rename from backend/Modules/Workspaces/Handlers/GetWorkspaceInvites.cs rename to backend/src/Socialize.Api/Modules/Workspaces/Handlers/GetWorkspaceInvites.cs diff --git a/backend/Modules/Workspaces/Handlers/GetWorkspaceMembers.cs b/backend/src/Socialize.Api/Modules/Workspaces/Handlers/GetWorkspaceMembers.cs similarity index 100% rename from backend/Modules/Workspaces/Handlers/GetWorkspaceMembers.cs rename to backend/src/Socialize.Api/Modules/Workspaces/Handlers/GetWorkspaceMembers.cs diff --git a/backend/Modules/Workspaces/Handlers/GetWorkspaces.cs b/backend/src/Socialize.Api/Modules/Workspaces/Handlers/GetWorkspaces.cs similarity index 100% rename from backend/Modules/Workspaces/Handlers/GetWorkspaces.cs rename to backend/src/Socialize.Api/Modules/Workspaces/Handlers/GetWorkspaces.cs diff --git a/backend/Program.cs b/backend/src/Socialize.Api/Program.cs similarity index 100% rename from backend/Program.cs rename to backend/src/Socialize.Api/Program.cs diff --git a/backend/Properties/launchSettings.json b/backend/src/Socialize.Api/Properties/launchSettings.json similarity index 86% rename from backend/Properties/launchSettings.json rename to backend/src/Socialize.Api/Properties/launchSettings.json index fcc2c5e..66f2ca2 100644 --- a/backend/Properties/launchSettings.json +++ b/backend/src/Socialize.Api/Properties/launchSettings.json @@ -5,7 +5,7 @@ "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": false, - "applicationUrl": "http://0.0.0.0:5000", + "applicationUrl": "http://0.0.0.0:5080", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/backend/Socialize.Api.csproj b/backend/src/Socialize.Api/Socialize.Api.csproj similarity index 100% rename from backend/Socialize.Api.csproj rename to backend/src/Socialize.Api/Socialize.Api.csproj diff --git a/backend/appsettings.Development.json b/backend/src/Socialize.Api/appsettings.Development.json similarity index 94% rename from backend/appsettings.Development.json rename to backend/src/Socialize.Api/appsettings.Development.json index 2ec502b..44b146a 100644 --- a/backend/appsettings.Development.json +++ b/backend/src/Socialize.Api/appsettings.Development.json @@ -12,7 +12,7 @@ }, "Authentication": { "Jwt": { - "Issuer": "http://localhost:5000", + "Issuer": "http://localhost:5080", "Audience": "socialize-local", "Key": "socialize-dev-local-signing-key-please-change", "Lifetime": "00:05:00", diff --git a/backend/appsettings.Production.json b/backend/src/Socialize.Api/appsettings.Production.json similarity index 100% rename from backend/appsettings.Production.json rename to backend/src/Socialize.Api/appsettings.Production.json diff --git a/backend/appsettings.json b/backend/src/Socialize.Api/appsettings.json similarity index 100% rename from backend/appsettings.json rename to backend/src/Socialize.Api/appsettings.json diff --git a/backend/tests/Socialize.Tests/Socialize.Tests.csproj b/backend/tests/Socialize.Tests/Socialize.Tests.csproj new file mode 100644 index 0000000..7b907dd --- /dev/null +++ b/backend/tests/Socialize.Tests/Socialize.Tests.csproj @@ -0,0 +1,25 @@ + + + + net10.0 + enable + enable + false + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/backend/tests/Socialize.Tests/UnitTest1.cs b/backend/tests/Socialize.Tests/UnitTest1.cs new file mode 100644 index 0000000..6545e83 --- /dev/null +++ b/backend/tests/Socialize.Tests/UnitTest1.cs @@ -0,0 +1,10 @@ +namespace Socialize.Tests; + +public class UnitTest1 +{ + [Fact] + public void Test1() + { + + } +} diff --git a/bootstrap-vdp-agentic.sh b/bootstrap-vdp-agentic.sh new file mode 100755 index 0000000..ad55c54 --- /dev/null +++ b/bootstrap-vdp-agentic.sh @@ -0,0 +1,1415 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_RAW="${1:-}" + +if [[ -z "$PROJECT_RAW" ]]; then + echo "Usage: $0 [--no-install]" + echo "Example: $0 surveyable" + exit 1 +fi + +NO_INSTALL=false +for arg in "$@"; do + case "$arg" in + --no-install) NO_INSTALL=true ;; + esac +done + +require_cmd() { + if ! command -v "$1" >/dev/null 2>&1; then + echo "Missing required command: $1" + exit 1 + fi +} + +require_cmd dotnet +require_cmd npm + +# Fix old npm config warning: +# npm warn Unknown builtin config "globalignorefile" +if npm config get globalignorefile >/dev/null 2>&1; then + npm config delete globalignorefile >/dev/null 2>&1 || true +fi + +to_pascal_case() { + echo "$1" \ + | tr '[:upper:]' '[:lower:]' \ + | sed -E 's/[^a-z0-9]+/ /g' \ + | awk '{ + out=""; + for (i=1; i<=NF; i++) { + word=$i; + out = out toupper(substr(word,1,1)) substr(word,2); + } + print out; + }' +} + +PROJECT_DIR="$PROJECT_RAW" +PASCAL="$(to_pascal_case "$PROJECT_RAW")" + +if [[ -z "$PASCAL" ]]; then + echo "Project name must contain at least one letter or number." + exit 1 +fi + +API_NAME="${PASCAL}.Api" +TEST_NAME="${PASCAL}.Tests" +SLNX_NAME="${PASCAL}.slnx" + +BACKEND_PORT=5080 +FRONTEND_PORT=5173 +COMPOSE_PORT=8080 + +echo "Project directory: $PROJECT_DIR" +echo ".NET solution: $SLNX_NAME" +echo "API project: $API_NAME" +echo "Test project: $TEST_NAME" +echo "Backend dev URL: http://0.0.0.0:$BACKEND_PORT" +echo "Frontend dev URL: http://0.0.0.0:$FRONTEND_PORT" +echo + +mkdir -p "$PROJECT_DIR" +cd "$PROJECT_DIR" + +mkdir -p backend/src backend/tests docs deploy/caddy shared/openapi scripts + +######################################## +# Backend: .NET 10 API + Tests + .slnx +######################################## +cd backend + +dotnet new sln -n "$PASCAL" + +if [[ ! -f "$SLNX_NAME" ]]; then + echo "Expected $SLNX_NAME, but dotnet did not create it." + echo "Detected SDK:" + dotnet --version + exit 1 +fi + +dotnet new webapi -n "$API_NAME" -o "src/$API_NAME" --framework net10.0 +dotnet new xunit -n "$TEST_NAME" -o "tests/$TEST_NAME" --framework net10.0 + +dotnet sln "$SLNX_NAME" add "src/$API_NAME/$API_NAME.csproj" +dotnet sln "$SLNX_NAME" add "tests/$TEST_NAME/$TEST_NAME.csproj" + +dotnet add "tests/$TEST_NAME/$TEST_NAME.csproj" reference "src/$API_NAME/$API_NAME.csproj" + +API_DIR="src/$API_NAME" +rm -f "$API_DIR/WeatherForecast.cs" || true + +mkdir -p "$API_DIR/Endpoints/Health" +mkdir -p "$API_DIR/Contracts/Health" +mkdir -p "$API_DIR/Domain" +mkdir -p "$API_DIR/Infrastructure" +mkdir -p "$API_DIR/Properties" + +cat > "$API_DIR/Properties/launchSettings.json" < "$API_DIR/Contracts/Health/HealthResponse.cs" < "$API_DIR/Contracts/Health/HelloResponse.cs" < "$API_DIR/Endpoints/Health/HealthEndpoints.cs" < + Results.Ok(new HealthResponse("ok", DateTimeOffset.UtcNow))) + .WithName("GetHealth") + .WithOpenApi(); + + group.MapGet("/hello", () => + Results.Ok(new HelloResponse("Hello from the .NET API"))) + .WithName("GetHello") + .WithOpenApi(); + + return group; + } +} +EOF + +cat > "$API_DIR/Program.cs" <(options => +{ + options.SerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase; +}); + +const string DevCorsPolicy = "DevCors"; + +builder.Services.AddCors(options => +{ + options.AddPolicy(DevCorsPolicy, policy => + { + policy + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials() + .SetIsOriginAllowed(origin => + { + if (string.IsNullOrWhiteSpace(origin)) return false; + + var uri = new Uri(origin); + + return uri.Host is "localhost" or "127.0.0.1" + || uri.Host.StartsWith("192.168.") + || uri.Host.StartsWith("10.") + || uri.Host.StartsWith("172."); + }); + }); +}); + +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.MapOpenApi(); + app.UseCors(DevCorsPolicy); +} + +app.MapHealthEndpoints(); + +app.Run(); +EOF + +cat > "$API_DIR/Dockerfile" < src/app/main.ts <<'EOF' +import { createApp } from 'vue' +import App from '../App.vue' + +createApp(App).mount('#app') +EOF + +sed -i 's|/src/main.ts|/src/app/main.ts|g' index.html + +cat > src/App.vue <<'EOF' + + + +EOF + +cat > src/pages/HomePage.vue <<'EOF' + + + + + +EOF + +cat > src/features/health/types.ts <<'EOF' +export type HealthStatus = { + status: string + serverTimeUtc: string +} +EOF + +cat > src/features/health/api.ts < src/features/health/components/HealthPanel.vue <<'EOF' + + + + + +EOF + +cat > src/api/client.ts <({ + baseUrl: import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:$BACKEND_PORT', +}) +EOF + +cat > src/api/schema.d.ts <<'EOF' +export interface paths { + '/api/health': { + get: { + responses: { + 200: { + content: { + 'application/json': { + status: string + serverTimeUtc: string + } + } + } + } + } + } +} +EOF + +cat > scripts/fetch-openapi.mjs < vite.config.ts < Dockerfile < scripts/dev-backend.sh < scripts/dev-frontend.sh < scripts/update-openapi.sh < docker-compose.yml < deploy/caddy/Caddyfile <<'EOF' +:80 { + root * /srv + encode gzip zstd + + handle /api/* { + reverse_proxy api:8080 + } + + handle { + try_files {path} /index.html + file_server + } +} +EOF + +######################################## +# Docs + Agentic workflow +######################################## +mkdir -p docs/FEATURES docs/TASKS docs/PROMPTS docs/DECISIONS + +cat > README.md <:$FRONTEND_PORT +\`\`\` + +Backend: + +\`\`\`txt +http://localhost:$BACKEND_PORT +http://:$BACKEND_PORT +\`\`\` + +## Update frontend API types from backend + +The backend must be running first. + +\`\`\`bash +./scripts/update-openapi.sh +\`\`\` + +This writes: + +\`\`\`txt +shared/openapi/openapi.json +frontend/src/api/schema.d.ts +\`\`\` + +## Docker Compose + +\`\`\`bash +docker compose up --build +\`\`\` + +Then open: + +\`\`\`txt +http://localhost:$COMPOSE_PORT +http://:$COMPOSE_PORT +\`\`\` + +## Solution + +\`\`\`bash +dotnet build backend/$SLNX_NAME +dotnet test backend/$SLNX_NAME +\`\`\` + +## Agentic workflow + +Start here: + +\`\`\`txt +docs/AGENTIC_WORKFLOW.md +\`\`\` + +Use feature specs, task files, and prompt templates instead of asking agents to work from vague chat history. +EOF + +cat > docs/ARCHITECTURE.md < OpenAPI -> frontend TypeScript types +\`\`\` +EOF + +cat > docs/DEVELOPMENT_WORKFLOW.md < docs/AGENTIC_WORKFLOW.md <<'EOF' +# Agentic Workflow + +This repository is designed to be worked on by humans and coding agents. + +The goal is to avoid the common failure mode where the first AI prompt creates a lot of code and every later prompt degrades because the agent loses architectural context. + +## Core rule + +Agents do not work from vague chat history. + +Agents work from repository files: + +1. `AGENTS.md` +2. `docs/ARCHITECTURE.md` +3. `docs/DEVELOPMENT_WORKFLOW.md` +4. `docs/FEATURES/.md` +5. `docs/TASKS//.md` +6. `docs/PROMPTS/.md` + +## Workflow loop + +For every meaningful change: + +1. Define or update a feature spec in `docs/FEATURES/` +2. Create a small task in `docs/TASKS//` +3. Use the correct prompt template from `docs/PROMPTS/` +4. Ask the agent to implement only that task +5. Review the diff +6. Run tests/builds +7. Update OpenAPI when backend contracts change +8. Commit the task separately + +## Unit of work + +A task should usually be small enough to finish in one agent session. + +Good task examples: + +- Add `POST /api/auth/login` +- Add `LoginPage.vue` +- Add typed API wrapper for auth +- Add validation for registration email +- Add integration test for health endpoint + +Bad task examples: + +- Build auth +- Make the whole SaaS +- Redesign the app +- Add billing and dashboard and admin + +## Backend task pattern + +Backend changes should generally touch: + +```txt +backend/src/.Api/Endpoints// +backend/src/.Api/Contracts// +backend/tests/.Tests/ +``` + +Do not create new backend projects unless there is a clear architectural reason. + +## Frontend task pattern + +Frontend changes should generally touch: + +```txt +frontend/src/features// +frontend/src/pages/ +frontend/src/api/ +``` + +Prefer feature folders over global folders. + +## Contract workflow + +When backend endpoints or contracts change: + +```bash +./scripts/dev-backend.sh +./scripts/update-openapi.sh +``` + +Then check frontend TypeScript errors and fix affected frontend code. + +## Agent guardrails + +Agents must not: + +- invent architecture +- perform broad unrelated refactors +- manually duplicate generated API types +- ignore existing docs +- change deployment defaults without updating docs +- silently replace the chosen backend/frontend structure + +Agents should: + +- make small changes +- update feature specs when behavior changes +- update task files if implementation scope changes +- run or list validation commands +EOF + +cat > docs/FEATURE_TEMPLATE.md <<'EOF' +# Feature: + +## Status + +Draft | In Progress | Complete + +## Goal + +Describe the user-facing outcome. + +## User stories + +- As a , I want , so that . + +## Backend + +### Endpoints + +- `GET /api/...` +- `POST /api/...` + +### Contracts + +- `` +- `` + +### Domain rules + +- Rule 1 +- Rule 2 + +## Frontend + +### Pages + +- `` + +### Components + +- `` + +### State + +- Local component state +- Store state, if needed + +## API contract + +Describe what needs to appear in OpenAPI. + +## Done when + +- [ ] Backend endpoint implemented +- [ ] Backend tests added +- [ ] OpenAPI updated +- [ ] Frontend calls generated API types/client +- [ ] Frontend UI implemented +- [ ] Build/test passes + +## Notes + +Architectural notes, edge cases, and decisions. +EOF + +cat > docs/TASK_TEMPLATE.md <<'EOF' +# Task: + +## Feature + +`docs/FEATURES/.md` + +## Goal + +One concrete change. + +## Context + +What the agent needs to know before coding. + +## Files likely to change + +- `backend/src/...` +- `frontend/src/...` + +## Constraints + +- Follow existing architecture. +- Do not refactor unrelated files. +- Do not manually duplicate generated API types. +- Keep the diff focused. + +## Implementation steps + +1. Step one +2. Step two +3. Step three + +## Done when + +- [ ] Code implemented +- [ ] Tests/build pass +- [ ] OpenAPI regenerated if backend contracts changed +- [ ] Docs updated if behavior changed + +## Validation commands + +```bash +dotnet test backend/*.slnx +cd frontend && npm run build +``` +EOF + +cat > docs/PROMPT_TEMPLATE.md <<'EOF' +# General Agent Prompt Template + +You are working in this repository. + +## Read first + +- `AGENTS.md` +- `README.md` +- `docs/ARCHITECTURE.md` +- `docs/DEVELOPMENT_WORKFLOW.md` +- `docs/AGENTIC_WORKFLOW.md` +- `` +- `` + +## Task + +Implement: + +`` + +## Rules + +- Implement only this task. +- Do not refactor unrelated code. +- Follow existing backend/frontend structure. +- Backend feature code goes under `Endpoints/` and `Contracts/`. +- Frontend feature code goes under `frontend/src/features/`. +- If backend contracts change, update OpenAPI using `./scripts/update-openapi.sh`. +- Do not manually duplicate generated API types. + +## Output expected + +- Code changes +- Tests where appropriate +- Minimal docs update if behavior changed +- Summary of what changed +- Validation commands run +EOF + +cat > docs/PROMPTS/backend-task.md <<'EOF' +# Backend Task Prompt + +You are implementing a backend task in this repository. + +## Read first + +- `AGENTS.md` +- `docs/ARCHITECTURE.md` +- `docs/DEVELOPMENT_WORKFLOW.md` +- `docs/AGENTIC_WORKFLOW.md` +- Relevant feature spec in `docs/FEATURES/` +- Relevant task file in `docs/TASKS/` + +## Instructions + +- Implement only the requested backend task. +- Use the existing one-project backend structure. +- Put endpoints under `Endpoints//`. +- Put request/response contracts under `Contracts//`. +- Add or update tests under `backend/tests/`. +- Do not introduce repository/service layers unless the task explicitly requires it. +- Do not split the backend into multiple projects. + +## After coding + +Run or recommend: + +```bash +dotnet build backend/*.slnx +dotnet test backend/*.slnx +./scripts/update-openapi.sh +``` +EOF + +cat > docs/PROMPTS/frontend-task.md <<'EOF' +# Frontend Task Prompt + +You are implementing a frontend task in this repository. + +## Read first + +- `AGENTS.md` +- `docs/ARCHITECTURE.md` +- `docs/DEVELOPMENT_WORKFLOW.md` +- `docs/AGENTIC_WORKFLOW.md` +- Relevant feature spec in `docs/FEATURES/` +- Relevant task file in `docs/TASKS/` + +## Instructions + +- Implement only the requested frontend task. +- Put feature code under `frontend/src/features//`. +- Put route-level pages under `frontend/src/pages/`. +- Use generated API types from `frontend/src/api/schema.d.ts`. +- Do not manually recreate backend DTOs. +- Do not create global services unless the feature truly needs shared behavior. + +## After coding + +Run or recommend: + +```bash +cd frontend +npm run build +``` +EOF + +cat > docs/PROMPTS/debug.md <<'EOF' +# Debug Prompt + +You are debugging a specific failure in this repository. + +## Read first + +- `AGENTS.md` +- `docs/ARCHITECTURE.md` +- `docs/DEVELOPMENT_WORKFLOW.md` + +## Error + +Paste the full error here. + +## Instructions + +- Identify the most likely root cause. +- Make the smallest safe fix. +- Do not refactor unrelated code. +- Explain how to verify the fix. + +## Validation + +List the exact command(s) to run after the fix. +EOF + +cat > docs/PROMPTS/refactor.md <<'EOF' +# Refactor Prompt + +You are refactoring part of this repository. + +## Read first + +- `AGENTS.md` +- `docs/ARCHITECTURE.md` +- `docs/AGENTIC_WORKFLOW.md` +- Relevant feature spec + +## Scope + +Describe the exact refactor boundary. + +## Rules + +- Preserve behavior. +- Do not add features. +- Keep the diff focused. +- Update docs if structure or workflow changes. +- Run tests/builds after. + +## Validation + +```bash +dotnet test backend/*.slnx +cd frontend && npm run build +``` +EOF + +cat > docs/FEATURES/health.md <<'EOF' +# Feature: Health + +## Status + +Complete + +## Goal + +Verify that the frontend can call the backend through the generated OpenAPI TypeScript contract. + +## Backend + +### Endpoints + +- `GET /api/health` +- `GET /api/hello` + +### Contracts + +- `HealthResponse` +- `HelloResponse` + +## Frontend + +### Components + +- `HealthPanel.vue` + +### API + +- `features/health/api.ts` + +## Done when + +- [x] Backend exposes health endpoint +- [x] Frontend calls health endpoint +- [x] OpenAPI can generate frontend types +EOF + +mkdir -p docs/TASKS/health + +cat > docs/TASKS/health/001-verify-health-slice.md <<'EOF' +# Task: Verify health vertical slice + +## Feature + +`docs/FEATURES/health.md` + +## Goal + +Verify the generated project works end-to-end. + +## Steps + +1. Run the backend. +2. Run the frontend. +3. Open the frontend from localhost and optionally from another LAN machine. +4. Regenerate OpenAPI types. +5. Build/test. + +## Validation commands + +```bash +./scripts/dev-backend.sh +./scripts/dev-frontend.sh +./scripts/update-openapi.sh +dotnet test backend/*.slnx +cd frontend && npm run build +``` + +## Done when + +- [ ] Health panel shows backend status +- [ ] OpenAPI types regenerate successfully +- [ ] Backend tests pass +- [ ] Frontend build passes +EOF + +cat > docs/DECISIONS/0001-use-simple-dotnet-vue-monorepo.md < AGENTS.md <\` and \`Contracts/\`. +- Frontend feature code goes under \`frontend/src/features/\`. +- Frontend API types are generated from backend OpenAPI. +- Do not manually duplicate backend DTOs into frontend code. +- If backend DTOs or endpoints change, run \`./scripts/update-openapi.sh\`. +- Dev servers must use HTTP and bind to \`0.0.0.0\` for LAN access. +- Avoid broad refactors unless the task explicitly asks for one. + +## Task discipline + +Agents should work from task files in \`docs/TASKS/\`. + +A good task: + +- has a clear goal +- names the relevant feature +- has a small scope +- lists validation commands + +If no task exists, create one before implementing a meaningful feature. + +## Validation + +For backend changes: + +\`\`\`bash +dotnet build backend/$SLNX_NAME +dotnet test backend/$SLNX_NAME +\`\`\` + +For frontend changes: + +\`\`\`bash +cd frontend +npm run build +\`\`\` + +For contract changes: + +\`\`\`bash +./scripts/update-openapi.sh +\`\`\` +EOF + +cat > .gitignore <<'EOF' +# .NET +bin/ +obj/ +TestResults/ +*.user +*.suo + +# Node +node_modules/ +dist/ +.vite/ + +# Env +.env +.env.* + +# IDE +.vscode/ +.idea/ + +# OS +.DS_Store +Thumbs.db +EOF + +echo +echo "Bootstrap complete." +echo +echo "Next:" +echo " cd $PROJECT_DIR" +echo " ./scripts/dev-backend.sh" +echo " ./scripts/dev-frontend.sh" +echo +echo "After backend is running:" +echo " ./scripts/update-openapi.sh" +echo +echo "Agentic workflow:" +echo " docs/AGENTIC_WORKFLOW.md" diff --git a/deploy/caddy/Caddyfile b/deploy/caddy/Caddyfile new file mode 100644 index 0000000..5750b18 --- /dev/null +++ b/deploy/caddy/Caddyfile @@ -0,0 +1,21 @@ +:80 { + root * /srv + encode gzip zstd + + handle /api/* { + reverse_proxy api:8080 + } + + handle /health { + reverse_proxy api:8080 + } + + handle /swagger/* { + reverse_proxy api:8080 + } + + handle { + try_files {path} /index.html + file_server + } +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..3967385 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,39 @@ +services: + postgres: + image: postgres:latest + environment: + POSTGRES_USER: sa + POSTGRES_PASSWORD: P@ssword123! + POSTGRES_DB: socialize + ports: + - "5433:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U sa -d socialize"] + interval: 5s + timeout: 5s + retries: 20 + + api: + build: + context: . + dockerfile: backend/src/Socialize.Api/Dockerfile + environment: + ASPNETCORE_ENVIRONMENT: Development + ASPNETCORE_URLS: http://0.0.0.0:8080 + ConnectionStrings__PostgresConnection: Host=postgres;Port=5432;Database=socialize;Username=sa;Password=P@ssword123! + depends_on: + postgres: + condition: service_healthy + expose: + - "8080" + + web: + build: + context: . + dockerfile: frontend/Dockerfile + depends_on: + - api + ports: + - "8080:80" + volumes: + - ./deploy/caddy/Caddyfile:/etc/caddy/Caddyfile:ro diff --git a/docs/AGENTIC_WORKFLOW.md b/docs/AGENTIC_WORKFLOW.md new file mode 100644 index 0000000..5e6eb1e --- /dev/null +++ b/docs/AGENTIC_WORKFLOW.md @@ -0,0 +1,81 @@ +# Agentic Workflow + +This repository is designed to be worked on by humans and coding agents. + +The goal is to avoid the common failure mode where the first AI prompt creates a lot of code and later prompts degrade because the agent loses product and architecture context. + +## Core Rule + +Agents do not work from vague chat history. + +Agents work from repository files: + +1. `AGENTS.md` +2. `docs/ARCHITECTURE.md` +3. `docs/DEVELOPMENT_WORKFLOW.md` +4. `docs/PRODUCT.md` +5. `docs/CONVENTIONS.md` +6. `docs/FEATURES/.md` +7. `docs/TASKS//.md` +8. `docs/PROMPTS/.md` + +## Workflow Loop + +For every meaningful change: + +1. Define or update a feature spec in `docs/FEATURES/`. +2. Create a small task in `docs/TASKS//`. +3. Use the correct prompt template from `docs/PROMPTS/`. +4. Ask the agent to implement only that task. +5. Review the diff. +6. Run tests and builds. +7. Update OpenAPI when backend contracts change. +8. Commit the task separately. + +## Unit Of Work + +A task should usually be small enough to finish in one agent session. + +Good task examples: + +- Add one endpoint. +- Add one route-level screen. +- Add one Pinia store action and its API integration. +- Add validation for one request model. +- Add tests for one workflow transition. + +Bad task examples: + +- Build all approvals. +- Redesign the app. +- Fix every workspace issue. +- Add publishing, billing, and analytics together. + +## Contract Workflow + +When backend endpoints or contracts change: + +```bash +./scripts/dev-backend.sh +./scripts/update-openapi.sh +``` + +Then check frontend errors and update affected frontend code. + +## Agent Guardrails + +Agents must not: + +- invent architecture +- perform broad unrelated refactors +- manually duplicate generated API types when generated types are available +- ignore existing docs +- change deployment defaults without updating docs +- silently replace the chosen backend/frontend structure + +Agents should: + +- make small changes +- update feature specs when behavior changes +- update task files if implementation scope changes +- run or list validation commands diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..0d76698 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,92 @@ +# Architecture + +## Backend + +```txt +backend/ +├─ Socialize.slnx +├─ src/Socialize.Api/ +│ ├─ Common/ +│ ├─ Data/ +│ ├─ Infrastructure/ +│ ├─ Migrations/ +│ ├─ Modules/ +│ └─ Program.cs +└─ tests/Socialize.Tests/ +``` + +The backend is one API project plus one test project. + +The original bootstrap scaffold uses `Endpoints/` and `Contracts/` for a minimal API. Socialize already uses FastEndpoints modules, so current backend feature code stays under `Modules/` until a task intentionally changes that pattern. + +## Backend Composition + +Entry point: + +```txt +backend/src/Socialize.Api/Program.cs +``` + +Composition registers: + +- web services and auth in `DependencyInjection.cs` +- infrastructure in `Infrastructure/DependencyInjection.cs` +- domain modules for Identity, Workspaces, Clients, Projects, ContentItems, Assets, Comments, Approvals, and Notifications + +## Data Ownership + +The current implementation uses a shared `AppDbContext` in: + +```txt +backend/src/Socialize.Api/Data/AppDbContext.cs +``` + +Workflow data is organized by module folders. Do not couple unrelated modules through ad hoc service calls; keep ownership boundaries explicit. + +## Frontend + +```txt +frontend/src/ +├─ api/ +├─ app/ +├─ components/ +├─ features/ +├─ layouts/ +├─ pages/ +├─ plugins/ +├─ router/ +├─ stores/ +└─ views/ +``` + +The generated scaffold expects `app/`, `features/`, `pages/`, `router/`, `stores/`, and `api/`. Socialize currently has substantial existing code under `views/`, `stores/`, and `plugins/`. New isolated feature work should prefer `features//`; existing screens should be migrated only by explicit task. + +## API Contract + +The backend exposes NSwag OpenAPI in development at: + +```txt +http://localhost:5080/swagger/v1/swagger.json +``` + +The frontend updates its OpenAPI model with: + +```bash +./scripts/update-openapi.sh +``` + +Contract flow: + +```txt +Backend contracts -> OpenAPI -> frontend TypeScript types +``` + +## Deployment Shape + +Docker Compose runs: + +- `postgres` +- `api` +- `web` + +Caddy serves the frontend and reverse-proxies API paths to the backend. diff --git a/docs/BACKLOG.md b/docs/BACKLOG.md new file mode 100644 index 0000000..f4846f7 --- /dev/null +++ b/docs/BACKLOG.md @@ -0,0 +1,14 @@ +# Backlog + +## Technical + +- Migrate frontend app entry and route-level views toward the generated `app/`, `pages/`, and `features/` structure. +- Replace manually maintained frontend API shapes with generated OpenAPI types where practical. +- Add meaningful backend tests for workspace scoping and content approval transitions. +- Add frontend route smoke tests for the authenticated app shell. + +## Product + +- Define the external reviewer experience. +- Clarify publishing handoff states after approval. +- Define reminder and notification escalation rules. diff --git a/docs/CONVENTIONS.md b/docs/CONVENTIONS.md new file mode 100644 index 0000000..e5e9298 --- /dev/null +++ b/docs/CONVENTIONS.md @@ -0,0 +1,34 @@ +# Conventions + +## Backend + +- Use FastEndpoints handlers for API work. +- Keep request/response records near the handler unless an existing module pattern says otherwise. +- Add FluentValidation validators for non-trivial input. +- Use explicit routes and tags. +- Preserve workspace scoping for workspace-owned data. +- Keep schema changes in the owning data area and update migrations intentionally. + +## Frontend + +- Use `frontend/src/config.js` for runtime configuration. +- Use the shared Axios API client in `frontend/src/plugins/api.js` for current JavaScript flows. +- Preserve auth refresh behavior in `authStore` and the API plugin. +- Route-level authenticated app screens live under `/app/*`. +- New isolated feature slices should prefer `frontend/src/features//`. +- Do not move existing views/stores into feature folders unless a task owns that migration. + +## Docs + +- Current feature behavior belongs in `docs/FEATURES/`. +- Implementation work belongs in `docs/TASKS//`. +- Reusable prompts belong in `docs/PROMPTS/`. +- Durable decisions belong in `docs/DECISIONS/`. +- Archived material belongs in `docs/archive/`. + +## Validation + +- Backend changes: `dotnet build backend/Socialize.slnx` +- Backend behavior changes: `dotnet test backend/Socialize.slnx` +- Frontend changes: `cd frontend && npm run build` +- Backend contract changes: `./scripts/update-openapi.sh` diff --git a/docs/DECISIONS/0001-adopt-agentic-scaffold.md b/docs/DECISIONS/0001-adopt-agentic-scaffold.md new file mode 100644 index 0000000..4443f01 --- /dev/null +++ b/docs/DECISIONS/0001-adopt-agentic-scaffold.md @@ -0,0 +1,27 @@ +# Decision 0001: Adopt Agentic Scaffold + +## Status + +Accepted + +## Context + +The current project was not originally generated by `bootstrap-vdp-agentic.sh`, but future work should follow the structure and workflow that script creates. + +## Decision + +Move the existing Socialize implementation into the scaffold shape: + +- backend project under `backend/src/Socialize.Api` +- backend tests under `backend/tests/Socialize.Tests` +- root scripts under `scripts/` +- Docker Compose and Caddy deployment files +- OpenAPI snapshot under `shared/openapi` +- agentic docs under `docs/FEATURES`, `docs/TASKS`, `docs/PROMPTS`, and `docs/DECISIONS` + +## Consequences + +- Existing code is preserved. +- Path-sensitive docs, scripts, and CI must target the new layout. +- The frontend remains JavaScript for now, even though the generated scaffold uses Vue TypeScript. +- Future work should use small task files and feature specs. diff --git a/docs/decisions/ADR-TEMPLATE.md b/docs/DECISIONS/ADR-TEMPLATE.md similarity index 100% rename from docs/decisions/ADR-TEMPLATE.md rename to docs/DECISIONS/ADR-TEMPLATE.md diff --git a/docs/decisions/README.md b/docs/DECISIONS/README.md similarity index 100% rename from docs/decisions/README.md rename to docs/DECISIONS/README.md diff --git a/docs/DEVELOPMENT_WORKFLOW.md b/docs/DEVELOPMENT_WORKFLOW.md new file mode 100644 index 0000000..fd9de3a --- /dev/null +++ b/docs/DEVELOPMENT_WORKFLOW.md @@ -0,0 +1,71 @@ +# Development Workflow + +## Before Coding + +Read: + +1. `README.md` +2. `AGENTS.md` +3. `docs/ARCHITECTURE.md` +4. `docs/AGENTIC_WORKFLOW.md` +5. `docs/DEVELOPMENT_WORKFLOW.md` +6. Relevant feature spec in `docs/FEATURES/` +7. Relevant task file in `docs/TASKS/` + +## Backend + +```bash +./scripts/start-infrastructure.sh +./scripts/dev-backend.sh +``` + +Backend URL: + +```txt +http://localhost:5080 +``` + +Swagger UI: + +```txt +http://localhost:5080/api +``` + +## Frontend + +```bash +./scripts/dev-frontend.sh +``` + +Frontend URL: + +```txt +http://localhost:5173 +``` + +## API Model Sync + +When backend request/response models change: + +```bash +./scripts/update-openapi.sh +``` + +Then check frontend build errors. + +## Validation + +```bash +dotnet build backend/Socialize.slnx +dotnet test backend/Socialize.slnx +cd frontend && npm run build +``` + +## Commit Discipline + +Use Conventional Commits: + +```bash +git commit -m "feat: add content approval request flow" +git commit -m "docs: add agentic workflow tasks" +``` diff --git a/docs/specs/content-approval-workflow.md b/docs/FEATURES/content-approval-workflow.md similarity index 100% rename from docs/specs/content-approval-workflow.md rename to docs/FEATURES/content-approval-workflow.md diff --git a/docs/FEATURES/platform-scaffold.md b/docs/FEATURES/platform-scaffold.md new file mode 100644 index 0000000..d05cbf7 --- /dev/null +++ b/docs/FEATURES/platform-scaffold.md @@ -0,0 +1,60 @@ +# Feature: Agentic Platform Scaffold + +## Status + +In Progress + +## Goal + +Align Socialize with the structure generated by `bootstrap-vdp-agentic.sh` while preserving the current product implementation. + +## Backend + +The backend is located at: + +```txt +backend/src/Socialize.Api +``` + +The solution is: + +```txt +backend/Socialize.slnx +``` + +The test project is: + +```txt +backend/tests/Socialize.Tests +``` + +## Frontend + +The frontend remains the existing Vue 3 app. The scaffold directories `frontend/src/api`, `frontend/src/features`, `frontend/src/pages`, `frontend/src/layouts`, and `frontend/src/app` are available for incremental migration. + +## API Contract + +OpenAPI workflow: + +```bash +./scripts/update-openapi.sh +``` + +Writes: + +```txt +shared/openapi/openapi.json +frontend/src/api/schema.d.ts +``` + +## Done When + +- [x] Backend code lives under `backend/src/Socialize.Api` +- [x] Backend solution exists at `backend/Socialize.slnx` +- [x] Test project exists under `backend/tests/Socialize.Tests` +- [x] Root scripts exist +- [x] Docker Compose and Caddy files exist +- [x] Agentic docs, specs, tasks, and prompts exist +- [ ] OpenAPI generation verified against a running backend +- [x] Backend build passes +- [x] Frontend build passes diff --git a/docs/use-cases/review-workflows.md b/docs/FEATURES/review-workflows.md similarity index 100% rename from docs/use-cases/review-workflows.md rename to docs/FEATURES/review-workflows.md diff --git a/docs/FEATURES/workspace-review-workflow.md b/docs/FEATURES/workspace-review-workflow.md new file mode 100644 index 0000000..0cff285 --- /dev/null +++ b/docs/FEATURES/workspace-review-workflow.md @@ -0,0 +1,52 @@ +# Feature: Workspace Review Workflow + +## Status + +Draft + +## Goal + +Support workspace-scoped social media content review from content creation through comments, revision, approval, and ready-to-publish handoff. + +## User Stories + +- As a social media manager, I want content items grouped by workspace, client, and project so that I can manage review work for multiple accounts. +- As a client approver, I want one clear place to review content, comment, and approve or request changes. +- As an account manager, I want notifications and review queues so that work does not stall silently. + +## Backend Modules + +- Identity +- Workspaces +- Clients +- Projects +- ContentItems +- Assets +- Comments +- Approvals +- Notifications + +## Frontend Areas + +- `/app` +- `/app/workspaces/new` +- `/app/clients` +- `/app/projects` +- `/app/content` +- `/app/content/:id` +- `/app/reviews` +- `/app/settings` + +## Domain Rules + +- Workspace is the top-level scoping boundary. +- Content items belong to a workspace and may belong to a client or project. +- Comments, approvals, assets, and notifications must remain traceable to the workflow entity they relate to. +- Ready-to-publish state should come from explicit approval workflow transitions. + +## Done When + +- [ ] Workspace access is enforced consistently +- [ ] Content item lifecycle is documented as a state machine +- [ ] Approval decisions create traceable notifications/events +- [ ] Review queue behavior is covered by tasks and validation diff --git a/docs/specs/TEMPLATE.md b/docs/FEATURE_TEMPLATE.md similarity index 100% rename from docs/specs/TEMPLATE.md rename to docs/FEATURE_TEMPLATE.md diff --git a/docs/LLM_DEVELOPMENT_WORKFLOW.md b/docs/LLM_DEVELOPMENT_WORKFLOW.md index 556a861..43ff96c 100644 --- a/docs/LLM_DEVELOPMENT_WORKFLOW.md +++ b/docs/LLM_DEVELOPMENT_WORKFLOW.md @@ -1,593 +1,20 @@ # LLM Development Workflow -## Purpose -This document defines how to use coding agents such as Codex, Claude Code, ChatGPT, or similar tools on this repository without losing architectural coherence over time. +This document is kept as a compatibility pointer for older references. -The core rule is simple: +The current agentic workflow now lives in: + +- `docs/AGENTIC_WORKFLOW.md` +- `docs/DEVELOPMENT_WORKFLOW.md` +- `docs/ARCHITECTURE.md` +- `docs/CONVENTIONS.md` +- `docs/FEATURES/` +- `docs/TASKS/` +- `docs/PROMPTS/` +- `docs/DECISIONS/` + +Core rule: > The repository is the source of truth. The chat is only a temporary execution surface. -Coding agents should not rely on long conversation history to understand the product, architecture, or current task. Important context must live in versioned files inside the repository. - -## Why This Workflow Exists - -LLM coding tools are very strong at creating an initial project or implementing isolated changes. They become less reliable when the work shifts from greenfield generation to incremental product engineering. - -The common failure mode is this: - -1. The first prompt creates a large amount of useful code. -2. Later prompts become increasingly specific and corrective. -3. The agent starts forgetting prior decisions, duplicating patterns, inventing architecture, or changing unrelated files. -4. Most of the work becomes re-explaining context instead of shipping features. - -This does not mean the tools are useless. It means the workflow must change. - -Early-stage prompting can be broad. Mature product work must be driven by stable docs, scoped tasks, acceptance criteria, and reviewable diffs. - -## Operating Model - -Use coding agents as fast implementation partners, not as autonomous product owners. - -Agents should: - -- read repository documentation first; -- understand the current task before editing; -- propose a small implementation plan; -- make minimal, reviewable changes; -- preserve existing architecture and conventions; -- report risks, assumptions, and validation steps. - -Agents should not: - -- use chat history as the primary source of truth; -- invent product behavior when docs are missing; -- perform broad rewrites during a feature task; -- silently change unrelated files; -- mix backend, frontend, database, UX, and refactoring work without a scoped plan. - -## Repository Documentation Model - -The repository should contain a small set of durable documents that agents always consult. - -Recommended structure: - -```text -docs/ - PRODUCT.md - ARCHITECTURE.md - CONVENTIONS.md - DECISIONS.md - BACKLOG.md - LLM_DEVELOPMENT_WORKFLOW.md - tasks/ - TASK-001-example.md - TASK-002-example.md -AGENTS.md -``` - -### `AGENTS.md` - -`AGENTS.md` is the entry point for coding agents. - -It should tell agents: - -- how to work in this repo; -- what docs to read first; -- how the backend and frontend are structured; -- what commands to run; -- what rules are non-negotiable; -- how to validate work before finishing. - -This file should stay concise enough that agents actually follow it. - -### `docs/PRODUCT.md` - -Defines the product from the user's perspective. - -Include: - -- what the product is; -- target users; -- major workflows; -- important UX principles; -- feature boundaries; -- what the product explicitly does not do yet. - -Use this file to prevent agents from inventing product behavior. - -### `docs/ARCHITECTURE.md` - -Defines the technical structure. - -Include: - -- backend architecture; -- frontend architecture; -- module boundaries; -- authentication model; -- data ownership; -- routing model; -- state management model; -- API integration patterns. - -Use this file to prevent agents from inventing new architecture for each task. - -### `docs/CONVENTIONS.md` - -Defines repeatable implementation patterns. - -Include: - -- C# style and backend endpoint conventions; -- FastEndpoints patterns; -- EF Core migration rules; -- Vue component conventions; -- Pinia store conventions; -- API client usage; -- validation and error handling patterns; -- testing expectations; -- naming conventions. - -Use this file to reduce code style drift. - -### `docs/DECISIONS.md` - -A lightweight architecture decision log. - -Each entry should capture: - -- date; -- decision; -- context; -- consequences. - -Example: - -```md -## 2026-04-23 — Runtime frontend config is centralized - -Decision: Frontend runtime configuration must be accessed through `frontend/src/config.js`. - -Context: Direct `import.meta.env` reads scattered across feature code make configuration harder to audit. - -Consequence: New frontend code should import config from `frontend/src/config.js` instead of reading env variables directly. -``` - -Use this file to prevent agents from revisiting settled choices. - -### `docs/BACKLOG.md` - -A human-readable backlog of possible future work. - -Use this for ideas, improvements, bugs, and deferred refactors. - -Important rule: - -> If an agent sees an adjacent problem that is outside the current task, it should add or suggest a backlog item instead of fixing it opportunistically. - -### `docs/tasks/TASK-xxx.md` - -Task files are the LLM-friendly equivalent of Jira tickets. - -They are not just backend tickets. A product feature is usually fullstack and should describe backend, frontend, UX behavior, data model, validation, and acceptance criteria. - -The task file should be specific enough that a fresh agent can implement it without reading a long chat thread. - -## Task File Template - -Use this template for implementation tasks. - -```md -# TASK-000 — Short Feature Name - -## Status -Draft | Ready | In Progress | Done | Blocked - -## Objective -Describe the user-visible or technical outcome in 1-3 sentences. - -## Product Context -Explain why this exists and where it fits in the product workflow. - -## Scope -- What this task includes. -- Keep this list concrete. - -## Out of Scope -- What this task explicitly must not include. -- Add adjacent ideas here to prevent scope creep. - -## Existing References -Agents must inspect these before implementation: -- `docs/PRODUCT.md` -- `docs/ARCHITECTURE.md` -- `docs/CONVENTIONS.md` -- relevant existing backend files -- relevant existing frontend files - -## Backend Requirements -### API Contract -Endpoint: -- `METHOD /api/example` - -Request: -```json -{ - "example": "value" -} -``` - -Response: -```json -{ - "id": "string" -} -``` - -### Validation -- Rule 1 -- Rule 2 - -### Data / Persistence -- Entity changes, if any. -- DbContext/module affected, if any. -- Migration required: yes/no. - -### Security / Authorization -- Authentication required: yes/no. -- Roles or workspace access rules. - -## Frontend Requirements -### Route / Screen -- Route: `/app/example` -- View file: `frontend/src/views/app/ExampleView.vue` - -### Components -- `ExampleForm.vue` -- `ExampleList.vue` - -### State Management -- Pinia store used or created. -- Existing store actions to reuse. - -### API Integration -- Existing API client usage. -- Expected loading, success, and error behavior. - -### UX Behavior -- Empty state. -- Loading state. -- Validation display. -- Toasts or inline errors. -- Navigation after success, if any. - -## Files Likely Involved -Backend: -- `backend/...` - -Frontend: -- `frontend/...` - -Docs: -- `docs/...` - -## Acceptance Criteria -- User can complete the intended workflow. -- Backend validates invalid input correctly. -- Frontend displays loading and error states correctly. -- Existing auth, workspace scoping, and refresh behavior are preserved. -- Build passes. - -## Validation Plan -Backend: -- `cd backend && dotnet build Socialize.Api.csproj` -- Additional manual or automated checks. - -Frontend: -- `cd frontend && npm run build` -- Additional manual route/store checks. - -## Risks / Edge Cases -- Risk 1 -- Risk 2 - -## Open Questions -- Question 1 -``` - -## Feature Definition: Fullstack by Default - -A feature should normally be defined across these dimensions: - -1. Product workflow: what the user is trying to accomplish. -2. UX behavior: screens, states, feedback, errors, navigation. -3. Frontend implementation: routes, components, stores, API calls. -4. Backend implementation: endpoints, validation, persistence, authorization. -5. Data model: entities, migrations, ownership boundaries. -6. Acceptance criteria: what must be true before the task is done. -7. Validation plan: commands and manual checks. - -Avoid defining features as backend-only unless the task is explicitly backend-only. - -## Recommended Agent Workflow - -Use this sequence for non-trivial changes. - -### 1. Prepare or update the task file - -Create a `docs/tasks/TASK-xxx.md` file before asking an agent to implement a feature. - -The task can be rough at first, but it must state: - -- objective; -- scope; -- out of scope; -- backend requirements, if any; -- frontend requirements, if any; -- acceptance criteria. - -### 2. Start a fresh agent thread per task - -Do not run an entire project through one endless chat. - -Use one thread for one task or one small group of tightly related subtasks. - -### 3. Ask for analysis before implementation - -Default prompt: - -```text -Read AGENTS.md and the relevant docs first. -Then read docs/tasks/TASK-000-short-name.md. -Do not edit files yet. -Summarize the task, identify the relevant backend and frontend files, list risks, and propose a minimal implementation plan. -``` - -### 4. Implement one bounded step at a time - -Default prompt: - -```text -Implement only step 1 from the plan. -Keep the diff minimal. -Do not refactor unrelated code. -Do not change public behavior outside this task. -At the end, summarize changes and list validation steps. -``` - -### 5. Review the diff - -The repository owner reviews: - -- scope creep; -- architectural drift; -- duplicated code; -- inconsistent UI behavior; -- unsafe auth or workspace scoping changes; -- broken conventions. - -### 6. Validate - -Run the relevant commands from `AGENTS.md` and the task file. - -Minimum expected validation: - -- backend build for backend changes; -- frontend build for frontend changes; -- affected user flow checked manually when UI behavior changes. - -### 7. Update docs if the task changed architecture or product behavior - -If implementation creates a durable decision, update `docs/DECISIONS.md`. - -If implementation changes structure, update `docs/ARCHITECTURE.md`. - -If implementation changes conventions, update `docs/CONVENTIONS.md`. - -If implementation changes user-facing behavior, update `docs/PRODUCT.md`. - -## Prompt Patterns - -### Planning Prompt - -```text -You are working in an existing repository. - -First read: -- AGENTS.md -- docs/PRODUCT.md -- docs/ARCHITECTURE.md -- docs/CONVENTIONS.md -- docs/DECISIONS.md -- docs/tasks/TASK-000-short-name.md - -Do not edit files yet. - -Return: -1. summary of the task; -2. relevant existing files; -3. backend impact; -4. frontend impact; -5. risks and ambiguities; -6. minimal implementation plan; -7. validation plan. -``` - -### Implementation Prompt - -```text -Implement the task from docs/tasks/TASK-000-short-name.md. - -Rules: -- follow AGENTS.md; -- follow docs/ARCHITECTURE.md and docs/CONVENTIONS.md; -- keep the diff minimal; -- do not refactor unrelated code; -- preserve auth, workspace scoping, token refresh, and runtime config patterns; -- if you discover missing requirements, stop and report them instead of inventing behavior. - -At the end, provide: -- files changed; -- summary of behavior added; -- validation performed; -- validation still needed; -- risks or follow-up items. -``` - -### Frontend-Only Prompt - -```text -Implement only the frontend part of docs/tasks/TASK-000-short-name.md. - -Do not modify backend code. -Use existing routes, stores, API client, UI framework, and runtime config conventions. -Preserve loading, error, empty, and success states described in the task. -``` - -### Backend-Only Prompt - -```text -Implement only the backend part of docs/tasks/TASK-000-short-name.md. - -Do not modify frontend code. -Follow the existing FastEndpoints, validation, module, DbContext, and migration conventions. -Preserve auth and workspace scoping rules. -``` - -### Review Prompt - -```text -Review the current diff against: -- AGENTS.md -- docs/ARCHITECTURE.md -- docs/CONVENTIONS.md -- docs/tasks/TASK-000-short-name.md - -Look specifically for: -- scope creep; -- architectural drift; -- broken frontend state patterns; -- broken backend module boundaries; -- auth or workspace scoping regressions; -- missing loading/error states; -- missing validation; -- missing tests or manual checks. - -Do not edit files. Return findings only. -``` - -## Rules for Frontend Work - -Frontend changes must be explicit in the task. - -A frontend task should identify: - -- route or screen; -- components to create or modify; -- Pinia stores involved; -- API calls involved; -- loading state; -- error state; -- empty state; -- success feedback; -- navigation behavior; -- role/access behavior; -- responsive or layout expectations, if relevant. - -Agents must not invent a new frontend architecture for a single feature. - -They should reuse: - -- existing Vue patterns; -- existing Vuetify/Tailwind conventions; -- existing Pinia stores where appropriate; -- existing Axios client; -- existing router guards; -- existing toast/error patterns. - -## Rules for Backend Work - -Backend changes must respect module boundaries. - -A backend task should identify: - -- endpoint route and method; -- request and response shape; -- validation rules; -- module ownership; -- DbContext affected; -- migration requirement; -- authorization rules; -- workspace scoping rules; -- expected errors. - -Agents must not couple module DbContexts or bypass existing auth/security helpers. - -## Handling Ambiguity - -When a requirement is unclear, agents should not silently invent behavior. - -Preferred behavior: - -1. State the ambiguity. -2. Propose the safest default. -3. Keep implementation narrow. -4. Add an open question or backlog item if needed. - -For small ambiguities that do not affect architecture or product behavior, the agent may choose the safest existing pattern and document the assumption. - -For large ambiguities, the agent should stop before implementation. - -## Handling Refactors - -Refactors should be separate tasks unless they are strictly required for the current feature. - -If a refactor is needed, the task should state: - -- why the refactor is necessary; -- what files are in scope; -- what behavior must remain unchanged; -- how to validate no regression occurred. - -Agents should not do opportunistic cleanup in unrelated files. - -## Handling Backlog Items - -When an agent notices an issue outside scope, it should not fix it by default. - -It should report it as: - -```md -Suggested backlog item: -- Title: -- Reason: -- Affected files: -- Risk if ignored: -``` - -The repository owner can then decide whether to create a task. - -## Definition of Done - -A task is done when: - -- implementation matches the task file; -- scope and out-of-scope boundaries were respected; -- relevant backend and/or frontend validation passed; -- user-facing behavior was manually checked when applicable; -- docs were updated if durable behavior or architecture changed; -- remaining risks or follow-up items were explicitly listed. - -## Practical Mental Model - -Use this model: - -- `AGENTS.md` tells the agent how to behave. -- `docs/PRODUCT.md` tells the agent what the product is. -- `docs/ARCHITECTURE.md` tells the agent how the system is shaped. -- `docs/CONVENTIONS.md` tells the agent how to write code here. -- `docs/DECISIONS.md` tells the agent what choices are already settled. -- `docs/BACKLOG.md` stores ideas that are not current work. -- `docs/tasks/TASK-xxx.md` tells the agent what to do now. - -The more this information lives in the repo, the less each new prompt has to reconstruct the project from memory. +For new work, create or update a feature spec in `docs/FEATURES/`, create a small task in `docs/TASKS//`, and ask the agent to implement only that task. diff --git a/docs/PRODUCT.md b/docs/PRODUCT.md new file mode 100644 index 0000000..0276f25 --- /dev/null +++ b/docs/PRODUCT.md @@ -0,0 +1,47 @@ +# Product + +Socialize is a workflow application for social media content review, revision, approval, and publication readiness. + +It is not a public social network. It is a workspace-based coordination tool for internal teams, providers, and client approvers. + +## Primary Users + +- Social media manager +- Account manager or customer success manager +- Client approver +- External provider or production partner +- Internal producer +- Internal employee or content contributor +- Administrator + +## Core Product Shape + +- workspace-based account boundary +- agencies able to manage multiple workspaces +- content items as the main reviewable unit +- assets and revisions tracked against content items +- comments and approvals attached to the work itself +- notifications driven by workflow events + +## Must Do Well + +- centralize review state +- preserve a clear audit trail +- make the latest approved version obvious +- support internal review before client review +- support client-facing review with low friction +- keep publication handoff clear once approval is complete + +## Not In Version 1 + +- public social feed +- full direct publishing engine +- full DAM platform +- analytics suite +- billing or subscription flows + +## Current Sources + +- `docs/product/vision.md` +- `docs/product/glossary.md` +- `docs/constraints.md` diff --git a/docs/PROMPTS/backend-task.md b/docs/PROMPTS/backend-task.md new file mode 100644 index 0000000..f33120e --- /dev/null +++ b/docs/PROMPTS/backend-task.md @@ -0,0 +1,30 @@ +# Backend Task Prompt + +You are implementing a backend task in this repository. + +## Read First + +- `AGENTS.md` +- `docs/ARCHITECTURE.md` +- `docs/DEVELOPMENT_WORKFLOW.md` +- `docs/AGENTIC_WORKFLOW.md` +- Relevant feature spec in `docs/FEATURES/` +- Relevant task file in `docs/TASKS/` + +## Instructions + +- Implement only the requested backend task. +- Keep code under `backend/src/Socialize.Api`. +- Follow the existing FastEndpoints module structure. +- Add or update tests under `backend/tests/Socialize.Tests` when the behavior is testable. +- Do not introduce repository/service layers unless the task explicitly requires it. + +## After Coding + +Run or recommend: + +```bash +dotnet build backend/Socialize.slnx +dotnet test backend/Socialize.slnx +./scripts/update-openapi.sh +``` diff --git a/docs/PROMPTS/debug.md b/docs/PROMPTS/debug.md new file mode 100644 index 0000000..c615cbd --- /dev/null +++ b/docs/PROMPTS/debug.md @@ -0,0 +1,24 @@ +# Debug Prompt + +You are debugging a specific failure in this repository. + +## Read First + +- `AGENTS.md` +- `docs/ARCHITECTURE.md` +- `docs/DEVELOPMENT_WORKFLOW.md` + +## Error + +Paste the full error here. + +## Instructions + +- Identify the most likely root cause. +- Make the smallest safe fix. +- Do not refactor unrelated code. +- Explain how to verify the fix. + +## Validation + +List the exact command or commands to run after the fix. diff --git a/docs/PROMPTS/frontend-task.md b/docs/PROMPTS/frontend-task.md new file mode 100644 index 0000000..282addc --- /dev/null +++ b/docs/PROMPTS/frontend-task.md @@ -0,0 +1,30 @@ +# Frontend Task Prompt + +You are implementing a frontend task in this repository. + +## Read First + +- `AGENTS.md` +- `docs/ARCHITECTURE.md` +- `docs/DEVELOPMENT_WORKFLOW.md` +- `docs/AGENTIC_WORKFLOW.md` +- Relevant feature spec in `docs/FEATURES/` +- Relevant task file in `docs/TASKS/` + +## Instructions + +- Implement only the requested frontend task. +- Existing route-level app screens live under `frontend/src/views/app`. +- New isolated feature slices should prefer `frontend/src/features/`. +- Use `frontend/src/config.js` for runtime configuration. +- Preserve token refresh behavior in `authStore` and `frontend/src/plugins/api.js`. +- Use generated API types from `frontend/src/api/schema.d.ts` when the endpoint has been generated. + +## After Coding + +Run or recommend: + +```bash +cd frontend +npm run build +``` diff --git a/docs/PROMPTS/refactor.md b/docs/PROMPTS/refactor.md new file mode 100644 index 0000000..6e92152 --- /dev/null +++ b/docs/PROMPTS/refactor.md @@ -0,0 +1,29 @@ +# Refactor Prompt + +You are refactoring part of this repository. + +## Read First + +- `AGENTS.md` +- `docs/ARCHITECTURE.md` +- `docs/AGENTIC_WORKFLOW.md` +- Relevant feature spec + +## Scope + +Describe the exact refactor boundary. + +## Rules + +- Preserve behavior. +- Do not add features. +- Keep the diff focused. +- Update docs if structure or workflow changes. +- Run tests/builds after. + +## Validation + +```bash +dotnet test backend/Socialize.slnx +cd frontend && npm run build +``` diff --git a/docs/PROMPT_TEMPLATE.md b/docs/PROMPT_TEMPLATE.md new file mode 100644 index 0000000..fad1b02 --- /dev/null +++ b/docs/PROMPT_TEMPLATE.md @@ -0,0 +1,37 @@ +# General Agent Prompt Template + +You are working in this repository. + +## Read First + +- `AGENTS.md` +- `README.md` +- `docs/ARCHITECTURE.md` +- `docs/DEVELOPMENT_WORKFLOW.md` +- `docs/AGENTIC_WORKFLOW.md` +- `` +- `` + +## Task + +Implement: + +`` + +## Rules + +- Implement only this task. +- Do not refactor unrelated code. +- Follow existing backend/frontend structure. +- Backend code currently belongs under `backend/src/Socialize.Api/Modules/`. +- New isolated frontend feature code should prefer `frontend/src/features/`. +- If backend contracts change, update OpenAPI using `./scripts/update-openapi.sh`. +- Do not manually duplicate generated API types when generated types exist. + +## Output Expected + +- Code changes +- Tests where appropriate +- Minimal docs update if behavior changed +- Summary of what changed +- Validation commands run diff --git a/docs/README.md b/docs/README.md index dc463ae..77d65f2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,32 +1,40 @@ # Docs -This folder contains the project documentation used to guide product, implementation, and architecture work. +This folder contains the project documentation used to guide product, implementation, architecture, and agentic development work. -## Current Product Docs +## Start Here -- [product/vision.md](/home/jbourdon/repos/social-media/docs/product/vision.md): current product intent, users, scope, and priorities. -- [product/glossary.md](/home/jbourdon/repos/social-media/docs/product/glossary.md): canonical domain vocabulary. Prefer these terms in code, UI copy, and specs. -- [constraints.md](/home/jbourdon/repos/social-media/docs/constraints.md): business and technical invariants that should not be violated casually. +- [AGENTIC_WORKFLOW.md](/home/jbourdon/repos/social-media/docs/AGENTIC_WORKFLOW.md): human + agent development loop. +- [ARCHITECTURE.md](/home/jbourdon/repos/social-media/docs/ARCHITECTURE.md): technical structure and module boundaries. +- [DEVELOPMENT_WORKFLOW.md](/home/jbourdon/repos/social-media/docs/DEVELOPMENT_WORKFLOW.md): local commands and validation. +- [PRODUCT.md](/home/jbourdon/repos/social-media/docs/PRODUCT.md): current product definition. +- [CONVENTIONS.md](/home/jbourdon/repos/social-media/docs/CONVENTIONS.md): implementation and documentation conventions. -## Current Delivery Docs +## Agentic Scaffold -- [use-cases/review-workflows.md](/home/jbourdon/repos/social-media/docs/use-cases/review-workflows.md): scenario-driven workflow descriptions. -- [specs/content-approval-workflow.md](/home/jbourdon/repos/social-media/docs/specs/content-approval-workflow.md): structured feature spec for the primary workflow. -- [specs/TEMPLATE.md](/home/jbourdon/repos/social-media/docs/specs/TEMPLATE.md): template for future feature specs. +- [FEATURES/](/home/jbourdon/repos/social-media/docs/FEATURES): feature specs and product behavior. +- [TASKS/](/home/jbourdon/repos/social-media/docs/TASKS): small implementation tickets for agents. +- [PROMPTS/](/home/jbourdon/repos/social-media/docs/PROMPTS): reusable task prompts. +- [DECISIONS/](/home/jbourdon/repos/social-media/docs/DECISIONS): decision records. +- [FEATURE_TEMPLATE.md](/home/jbourdon/repos/social-media/docs/FEATURE_TEMPLATE.md): feature spec template. +- [TASK_TEMPLATE.md](/home/jbourdon/repos/social-media/docs/TASK_TEMPLATE.md): task template. +- [PROMPT_TEMPLATE.md](/home/jbourdon/repos/social-media/docs/PROMPT_TEMPLATE.md): general prompt template. -## Decision Records +## Current Product Sources -- [decisions/README.md](/home/jbourdon/repos/social-media/docs/decisions/README.md): ADR conventions and when to add a decision record. -- [decisions/ADR-TEMPLATE.md](/home/jbourdon/repos/social-media/docs/decisions/ADR-TEMPLATE.md): template for new architecture or product decisions. +- [product/vision.md](/home/jbourdon/repos/social-media/docs/product/vision.md): product intent, users, scope, and priorities. +- [product/glossary.md](/home/jbourdon/repos/social-media/docs/product/glossary.md): canonical domain vocabulary. +- [constraints.md](/home/jbourdon/repos/social-media/docs/constraints.md): business and technical invariants. +- [BACKLOG.md](/home/jbourdon/repos/social-media/docs/BACKLOG.md): deferred technical and product work. ## Archived -- [archive/PLAN.md](/home/jbourdon/repos/social-media/docs/archive/PLAN.md): early pivot plan; useful for historical context, but stale as an execution checklist. -- [archive/SOCIALIZE.md](/home/jbourdon/repos/social-media/docs/archive/SOCIALIZE.md): original consolidated product brief before the docs were split into focused source-of-truth files. -- [archive/Stripe.md](/home/jbourdon/repos/social-media/docs/archive/Stripe.md): legacy Hutopy monetization notes for memberships and tips. -- [archive/WORKSHEET.md](/home/jbourdon/repos/social-media/docs/archive/WORKSHEET.md): historical implementation worksheet from an earlier transition phase. +- [archive/PLAN.md](/home/jbourdon/repos/social-media/docs/archive/PLAN.md): early pivot plan. +- [archive/SOCIALIZE.md](/home/jbourdon/repos/social-media/docs/archive/SOCIALIZE.md): original consolidated product brief. +- [archive/Stripe.md](/home/jbourdon/repos/social-media/docs/archive/Stripe.md): legacy Hutopy monetization notes. +- [archive/WORKSHEET.md](/home/jbourdon/repos/social-media/docs/archive/WORKSHEET.md): historical transition worksheet. ## Root Docs - [README.md](/home/jbourdon/repos/social-media/README.md): repository overview and local development setup. -- [AGENTS.md](/home/jbourdon/repos/social-media/AGENTS.md): working guide for coding agents. This stays at repo root intentionally. +- [AGENTS.md](/home/jbourdon/repos/social-media/AGENTS.md): working guide for coding agents. diff --git a/docs/TASKS/platform-scaffold/001-align-repository-with-bootstrap-scaffold.md b/docs/TASKS/platform-scaffold/001-align-repository-with-bootstrap-scaffold.md new file mode 100644 index 0000000..e74698c --- /dev/null +++ b/docs/TASKS/platform-scaffold/001-align-repository-with-bootstrap-scaffold.md @@ -0,0 +1,64 @@ +# Task: Align repository with bootstrap scaffold + +## Feature + +`docs/FEATURES/platform-scaffold.md` + +## Goal + +Move the current Socialize repository into the structure that `bootstrap-vdp-agentic.sh` would have generated, without replacing the existing product implementation. + +## Context + +The script generates a simple .NET + Vue monorepo with: + +- backend under `backend/src/.Api` +- tests under `backend/tests/.Tests` +- root scripts under `scripts/` +- Docker Compose and Caddy deployment files +- OpenAPI sync into `shared/openapi` +- agentic docs under `docs/FEATURES`, `docs/TASKS`, `docs/PROMPTS`, and `docs/DECISIONS` + +Socialize already has a larger FastEndpoints backend and Vue app. Preserve that implementation while adopting the scaffold. + +## Files Likely To Change + +- `backend/Socialize.slnx` +- `backend/src/Socialize.Api/**` +- `backend/tests/Socialize.Tests/**` +- `scripts/**` +- `deploy/caddy/Caddyfile` +- `docker-compose.yml` +- `docs/**` +- `README.md` +- `AGENTS.md` +- `.github/workflows/backend-ci.yml` +- `frontend/package.json` +- `frontend/scripts/fetch-openapi.mjs` +- `frontend/src/api/schema.d.ts` + +## Constraints + +- Preserve existing product code. +- Do not convert the frontend to TypeScript in this task. +- Do not rewrite backend modules into minimal API folders in this task. +- Do not introduce new secrets. + +## Done When + +- [x] Backend implementation moved under `backend/src/Socialize.Api` +- [x] Backend solution points at the new project path +- [x] Test project scaffold exists +- [x] Root scripts exist +- [x] OpenAPI sync command exists +- [x] Agentic docs/specs/tasks/prompts exist +- [x] Backend build passes +- [x] Frontend build passes + +## Validation Commands + +```bash +dotnet build backend/Socialize.slnx +dotnet test backend/Socialize.slnx +cd frontend && npm run build +``` diff --git a/docs/TASKS/workspace-review-workflow/001-document-content-state-machine.md b/docs/TASKS/workspace-review-workflow/001-document-content-state-machine.md new file mode 100644 index 0000000..9312c14 --- /dev/null +++ b/docs/TASKS/workspace-review-workflow/001-document-content-state-machine.md @@ -0,0 +1,39 @@ +# Task: Document content state machine + +## Feature + +`docs/FEATURES/workspace-review-workflow.md` + +## Goal + +Define the current and intended content item states, transitions, and approval side effects before further workflow implementation. + +## Context + +The code already contains content items, approvals, comments, assets, notifications, and review queue screens. The workflow needs one durable spec so future agents do not infer state transitions from scattered UI code. + +## Files Likely To Change + +- `docs/FEATURES/workspace-review-workflow.md` +- `docs/FEATURES/content-approval-workflow.md` +- optionally `docs/DECISIONS/*.md` + +## Constraints + +- Documentation-only task. +- Do not change backend or frontend code. +- Distinguish current behavior from proposed behavior. + +## Done When + +- [ ] States are listed +- [ ] Allowed transitions are listed +- [ ] Actor permissions are listed +- [ ] Notification side effects are listed +- [ ] Open questions are explicit + +## Validation Commands + +```bash +git diff -- docs/FEATURES docs/DECISIONS +``` diff --git a/docs/TASK_TEMPLATE.md b/docs/TASK_TEMPLATE.md new file mode 100644 index 0000000..3ced8e7 --- /dev/null +++ b/docs/TASK_TEMPLATE.md @@ -0,0 +1,46 @@ +# Task: + +## Feature + +`docs/FEATURES/.md` + +## Goal + +One concrete change. + +## Context + +What the agent needs to know before coding. + +## Files Likely To Change + +- `backend/src/Socialize.Api/...` +- `frontend/src/...` +- `docs/...` + +## Constraints + +- Follow existing architecture. +- Do not refactor unrelated files. +- Do not manually duplicate generated API types when generated types exist. +- Keep the diff focused. + +## Implementation Steps + +1. Step one. +2. Step two. +3. Step three. + +## Done When + +- [ ] Code implemented +- [ ] Tests/build pass +- [ ] OpenAPI regenerated if backend contracts changed +- [ ] Docs updated if behavior changed + +## Validation Commands + +```bash +dotnet test backend/Socialize.slnx +cd frontend && npm run build +``` diff --git a/frontend/.env.development b/frontend/.env.development index d568be4..b4bf1c3 100644 --- a/frontend/.env.development +++ b/frontend/.env.development @@ -1,4 +1,4 @@ -VITE_API_URL=http://192.168.1.2:5000 +VITE_API_URL=http://192.168.1.2:5080 VITE_STRIPE_API_KEY=pk_test_51OoveVDrRyqXtNdB2st1NgA8WQA9rhgGaf3q7bCpAOoQyyRS30HMCzGeHba7meVGCSPfb1BVWmOTmFOcr9MkKf5H00bLu5MqsS VITE_GOOGLE_CLIENT_ID=213344094492-9dbaet2gaschju3hj1sgv1umk0qpd833.apps.googleusercontent.com VITE_FACEBOOK_APP_ID=1076433907621883 diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..2e67e1a --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,11 @@ +FROM node:22-alpine AS build +WORKDIR /app + +COPY frontend/package*.json ./ +RUN npm ci + +COPY frontend/ ./ +RUN npm run build + +FROM caddy:2-alpine AS runtime +COPY --from=build /app/dist /srv diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 50520ac..be158c2 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { - "name": "hutopy", - "version": "0.5", + "name": "socialize", + "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "hutopy", - "version": "0.5", + "name": "socialize", + "version": "0.1.0", "dependencies": { "@intlify/unplugin-vue-i18n": "^6.0.5", "@mdi/js": "^7.4.47", @@ -39,6 +39,7 @@ "eslint": "^8.57.1", "eslint-plugin-tailwindcss": "^3.18.0", "eslint-plugin-vue": "^9.22.0", + "openapi-typescript": "7.13.0", "postcss": "^8.5.3", "prettier": "^3.5.3", "rollup-plugin-visualizer": "^6.0.1", @@ -58,6 +59,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", @@ -67,9 +83,10 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -1050,6 +1067,96 @@ "url": "https://opencollective.com/pkgr" } }, + "node_modules/@redocly/ajv": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.11.2.tgz", + "integrity": "sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js-replace": "^1.0.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@redocly/ajv/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/config": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.22.0.tgz", + "integrity": "sha512-gAy93Ddo01Z3bHuVdPWfCwzgfaYgMdaZPcfL7JZ7hWJoK9V0lXDbigTWkhiPFAaLWzbOJ+kbUQG1+XwIm0KRGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/openapi-core": { + "version": "1.34.12", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.34.12.tgz", + "integrity": "sha512-b32XWsz6enN6K4bx8xWsqUaXTJR/DnYT3lL1CzDYzIYKw243NNlz6fexmr71q/U4HrEcMoJGBvwAfcxOb8ymQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/ajv": "8.11.2", + "@redocly/config": "0.22.0", + "colorette": "1.4.0", + "https-proxy-agent": "7.0.6", + "js-levenshtein": "1.1.6", + "js-yaml": "4.1.1", + "minimatch": "5.1.9", + "pluralize": "8.0.0", + "yaml-ast-parser": "0.0.43" + }, + "engines": { + "node": ">=18.17.0", + "npm": ">=9.5.0" + } + }, + "node_modules/@redocly/openapi-core/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@redocly/openapi-core/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@redocly/openapi-core/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@rollup/pluginutils": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", @@ -1078,7 +1185,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "android" @@ -1091,7 +1197,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "android" @@ -1104,7 +1209,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -1117,7 +1221,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -1130,7 +1233,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -1143,7 +1245,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -1156,7 +1257,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1169,7 +1269,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1182,7 +1281,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1195,7 +1293,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1208,7 +1305,6 @@ "cpu": [ "loong64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1221,7 +1317,6 @@ "cpu": [ "ppc64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1234,7 +1329,6 @@ "cpu": [ "riscv64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1247,7 +1341,6 @@ "cpu": [ "riscv64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1260,7 +1353,6 @@ "cpu": [ "s390x" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1273,7 +1365,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1286,7 +1377,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1299,7 +1389,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1312,7 +1401,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1325,7 +1413,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1939,6 +2026,16 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -2250,6 +2347,13 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", + "dev": true, + "license": "MIT" + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -2319,6 +2423,13 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true, + "license": "MIT" + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3516,6 +3627,19 @@ "node": ">=0.8.19" } }, + "node_modules/index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3675,10 +3799,28 @@ "jiti": "bin/jiti.js" } }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -4139,6 +4281,40 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openapi-typescript": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-7.13.0.tgz", + "integrity": "sha512-EFP392gcqXS7ntPvbhBzbF8TyBA+baIYEm791Hy5YkjDYKTnk/Tn5OQeKm5BIZvJihpp8Zzr4hzx0Irde1LNGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/openapi-core": "^1.34.6", + "ansi-colors": "^4.1.3", + "change-case": "^5.4.4", + "parse-json": "^8.3.0", + "supports-color": "^10.2.2", + "yargs-parser": "^21.1.1" + }, + "bin": { + "openapi-typescript": "bin/cli.js" + }, + "peerDependencies": { + "typescript": "^5.x" + } + }, + "node_modules/openapi-typescript/node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -4207,6 +4383,37 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-json/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4334,6 +4541,16 @@ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==" }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/postcss": { "version": "8.5.5", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.5.tgz", @@ -4603,6 +4820,16 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -5294,6 +5521,13 @@ "punycode": "^2.1.0" } }, + "node_modules/uri-js-replace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uri-js-replace/-/uri-js-replace-1.0.1.tgz", + "integrity": "sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==", + "dev": true, + "license": "MIT" + }, "node_modules/url-template": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", @@ -5766,6 +6000,13 @@ "node": ">= 14.6" } }, + "node_modules/yaml-ast-parser": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/yaml-eslint-parser": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/yaml-eslint-parser/-/yaml-eslint-parser-1.3.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 956c92e..09b1ccd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,12 +1,15 @@ { - "name": "hutopy", - "version": "0.5", + "name": "socialize", + "version": "0.1.0", "private": true, "type": "module", "scripts": { "dev": "vite", "build": "vite build", - "preview": "vite preview" + "preview": "vite preview", + "api:schema": "node scripts/fetch-openapi.mjs", + "api:types": "openapi-typescript ../shared/openapi/openapi.json -o src/api/schema.d.ts", + "api:update": "npm run api:schema && npm run api:types" }, "dependencies": { "@intlify/unplugin-vue-i18n": "^6.0.5", @@ -40,6 +43,7 @@ "eslint": "^8.57.1", "eslint-plugin-tailwindcss": "^3.18.0", "eslint-plugin-vue": "^9.22.0", + "openapi-typescript": "7.13.0", "postcss": "^8.5.3", "prettier": "^3.5.3", "rollup-plugin-visualizer": "^6.0.1", diff --git a/frontend/scripts/fetch-openapi.mjs b/frontend/scripts/fetch-openapi.mjs new file mode 100644 index 0000000..56052ff --- /dev/null +++ b/frontend/scripts/fetch-openapi.mjs @@ -0,0 +1,19 @@ +import { mkdir, writeFile } from 'node:fs/promises'; + +const url = process.env.OPENAPI_URL ?? 'http://localhost:5080/swagger/v1/swagger.json'; +const output = new URL('../../shared/openapi/openapi.json', import.meta.url); + +console.log(`Fetching OpenAPI schema from ${url}`); + +const response = await fetch(url); + +if (!response.ok) { + throw new Error(`Failed to fetch OpenAPI schema: ${response.status} ${response.statusText}`); +} + +const schema = await response.text(); + +await mkdir(new URL('../../shared/openapi', import.meta.url), { recursive: true }); +await writeFile(output, schema); + +console.log(`Wrote ${output.pathname}`); diff --git a/frontend/src/api/schema.d.ts b/frontend/src/api/schema.d.ts new file mode 100644 index 0000000..f4bf2c8 --- /dev/null +++ b/frontend/src/api/schema.d.ts @@ -0,0 +1,3 @@ +// Generated from the backend OpenAPI schema. +// Run ./scripts/update-openapi.sh after backend contract changes. +export interface paths {} diff --git a/frontend/src/app/.gitkeep b/frontend/src/app/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/frontend/src/app/.gitkeep @@ -0,0 +1 @@ + diff --git a/frontend/src/features/.gitkeep b/frontend/src/features/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/frontend/src/features/.gitkeep @@ -0,0 +1 @@ + diff --git a/frontend/src/layouts/.gitkeep b/frontend/src/layouts/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/frontend/src/layouts/.gitkeep @@ -0,0 +1 @@ + diff --git a/frontend/src/pages/.gitkeep b/frontend/src/pages/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/frontend/src/pages/.gitkeep @@ -0,0 +1 @@ + diff --git a/frontend/vite.config.js b/frontend/vite.config.js index b130ed2..86543ae 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -21,8 +21,18 @@ export default defineConfig({ ], server: { port: 5173, // Ensure this matches your WebStorm debug URL - open: true, // Automatically opens the browser + open: false, host: '0.0.0.0', + proxy: { + '/api': { + target: 'http://localhost:5080', + changeOrigin: true, + }, + '/health': { + target: 'http://localhost:5080', + changeOrigin: true, + }, + }, }, build: { sourcemap: true, // Enable source maps for debugging diff --git a/scripts/dev-backend.sh b/scripts/dev-backend.sh new file mode 100755 index 0000000..9791c0d --- /dev/null +++ b/scripts/dev-backend.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail + +dotnet run --project backend/src/Socialize.Api/Socialize.Api.csproj --urls http://0.0.0.0:5080 diff --git a/scripts/dev-frontend.sh b/scripts/dev-frontend.sh new file mode 100755 index 0000000..d840f21 --- /dev/null +++ b/scripts/dev-frontend.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd frontend +npm run dev diff --git a/scripts/start-infrastructure.sh b/scripts/start-infrastructure.sh new file mode 100755 index 0000000..2c628a9 --- /dev/null +++ b/scripts/start-infrastructure.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd backend +./scripts/start-infrastructure.sh diff --git a/scripts/update-openapi.sh b/scripts/update-openapi.sh new file mode 100755 index 0000000..a9fdb92 --- /dev/null +++ b/scripts/update-openapi.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd frontend +npm run api:update diff --git a/shared/openapi/.gitkeep b/shared/openapi/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/shared/openapi/.gitkeep @@ -0,0 +1 @@ +