Files
marketplaces/docs/PROJECT-STRUCTURE.md
sdarbinyan 261ce6d55b docs: final documentation consolidation - one canonical doc set
Audited every *.md in docs/ and root. Merged five overlapping backend
docs (BACKEND_INTEGRATION.md + AUTHENTICATION.md + ERROR_CONTRACT.md +
MAINTENANCE_MODE.md + the already-archived BACKEND_API.md/
BACKEND_API_REMAINING_WORK.md) into one canonical docs/BACKEND.md
(4775 lines, 10 numbered sections) - deleted the four standalone
files outright now that their content is fully inlined.

Archived (not deleted - real historical value): ADMIN.md (Sprint
19-28 build log, sprint-report-shaped, not a living reference) and
FRONTEND-ROADMAP.md (despite its name, a shipped-history changelog
with detail no other doc has - not a forward roadmap, so keeping it
in root alongside NEXT_PHASE.md was exactly the "10 roadmaps"
confusion being cleaned up).

Deleted outright (zero value): SPRINTS.md - a leftover copy-pasted
sprint-kickoff prompt saved as a file, not documentation.

Rewrote docs/PROJECT_STATUS.md with completion-percentage estimates
per area (frontend/backend/UI/admin/storefront) and an explicit
first-customer-readiness call. Rewrote docs/NEXT_PHASE.md to the
strict 5-phase structure (backend integration -> production testing
-> performance -> monitoring -> v2 ideas), pointing to PRODUCT_BACKLOG
.md/FUTURE_FEATURES.md for phase 5 detail instead of duplicating it.

Rewrote root README.md - was stale (referenced deleted pages/info,
pages/legal folders from a prior RC pass), now covers architecture,
frontend/backend status, how to run, mock<->API switch mechanism
(useMockData in environment.ts), current folder structure, and a
documentation map.

Updated docs/PROJECT_INDEX.md (the stated entry point) to link only
the surviving doc set - every remaining document is reachable from it.

Fixed every broken/stale cross-reference to the deleted/renamed
backend docs across ARCHITECTURE.md, EDITOR.md, FRONTEND.md,
PROJECT-STRUCTURE.md, StaticPages.md, KNOWN-ISSUES.md (10 individual
link fixes, verified by repo-wide grep before and after). Left
CHANGELOG.md's two historical entries untouched - changelogs are
append-only history, not live navigation, editing past entries would
misrepresent what was true at the time.

Not touched (explicitly out of scope): docs/architecture/foundation/**
(enforced ADRs/governance, permanent not sprint-shaped),
docs/context/** (Barry Cache infrastructure, "do not edit by hand"
per CLAUDE.md), .claude/worktrees/** (separate git worktrees
containing an unrelated project's docs, not this repo's documentation).

docs/ root: 22 files -> 16. Plus 5 in docs/archive/ (was 3).
2026-07-26 14:56:25 +04:00

8.0 KiB

PROJECT STRUCTURE

Folder-by-folder tour of src/app/**, then one worked example (the Sprint 19 admin dashboard) followed as a literal file-by-file walk-through, ending with a checklist for adding your own feature.

Standards referenced below are enforced, not suggestions: docs/architecture/foundation/Folder-Blueprint.md, Naming-Conventions.md, Dependency-Rules.md, Import-Boundary-Matrix.md.

Top-level folders

Folder What belongs here Why
core/ Per-domain: DTOs, mappers, domain models, repositories, domain services (e.g. core/categories/, core/products/, core/search/, core/admin-auth/). Isolates backend-shaped data (DTOs) from the rest of the app. Only the mapper inside a domain's core/<domain>/ folder is allowed to see both DTO and domain model shapes (ADR-003 import boundaries).
facades/ Cross-feature facades not owned by a single feature, e.g. facades/platform/category.facade.ts, facades/platform/search.facade.ts. The only thing components are allowed to inject for data/state (ADR-006/007). Feature-local facades instead live inside that feature's own facade/ folder (see features/project-editor/facade/, features/admin/dashboard/facade/).
features/ One folder per feature/domain: project-editor/, admin/<subfeature>/, backoffice/<subfeature>/, website/catalog/, website/product/, search/, content-management/, diagnostics/. Organized by feature, not by file type — a feature's models/services/facade/components/pages all live together (docs/architecture/foundation/Folder-Blueprint.md).
shared/ shared/models/config/* (the BootstrapConfig and ~20 sub-configs), reusable presentational UI, utils. Feature-agnostic by contract — shared/ must never import from features/ (Import-Boundary-Matrix).
widgets/ contracts/ (widget manifest contract), registry/ (manifest service), resolvers/ (data-source resolver), ui/ (widget components). The dynamic rendering engine — see docs/ARCHITECTURE.md.
dynamic-renderer/ section-engine/, page-renderer/, section-renderer/, widget-host/. The page-composition pipeline that turns bootstrap JSON into rendered pages.
layouts/ Page-chrome containers, e.g. layouts/containers/dynamic-page-layout.component.ts. Top-level layout composition, one level above pages.
i18n/ translations.ts (interface), en.ts/ru.ts/hy.ts, translate.pipe.ts, TranslateService. Single source of truth for all user-facing copy — see docs/FRONTEND.md.
pages/ Top-level routed pages not part of a larger feature module (home, cart, category). Simpler routed pages that don't warrant a full features/ module.
components/ Reusable standalone components shared across features/pages (product-card, telegram-login). Presentational, input/output-only (ADR-006) — no facade/HttpClient/storage access.
guards/ Route guards. Kept separate from core/admin-auth/ because admin-auth.guard.ts is domain-specific; generic guards live here.

Worked example, end to end: the Sprint 19 admin dashboard

src/app/features/admin/dashboard/ — read in the order a new engineer would build it.

  1. Modelmodels/admin-dashboard.model.ts. Plain interfaces/types for card data, card status (loading|empty|error|pending-backend|ready), health-check entries. No behavior, no imports from Angular DI.

  2. Gateway interfaceservices/admin-dashboard-metrics.gateway.interface.ts. An abstract contract (AdminDashboardMetricsGateway) for "however we get category/product counts" — deliberately decoupled from how (local computation vs. real API) so the facade never knows which implementation is active.

  3. Gateway implementationservices/admin-dashboard-metrics.local.gateway.ts. AdminDashboardMetricsLocalGateway implements AdminDashboardMetricsGateway, composing BackofficeDataService.loadCategories()/loadProducts() (already used elsewhere) into counts. A future AdminDashboardMetricsApiGateway would implement the same interface against a real endpoint (see docs/BACKEND.md §3 CRUD Contracts / §8 migration guide) — nothing above this layer changes when that happens.

  4. DI tokenservices/admin-dashboard-metrics-gateway.token.ts. const ADMIN_DASHBOARD_METRICS_GATEWAY = new InjectionToken<AdminDashboardMetricsGateway>(...), bound to the local gateway by default in app.config.ts. This is the swap point: rebinding this token to a real API gateway is the only change needed to go from mock to real data.

  5. Supporting serviceservices/admin-dashboard-history.service.ts. localStorage-backed activity log, scoped per tenant — a second, narrower concern (recent activity) that doesn't belong in the metrics gateway.

  6. Facadefacade/admin-dashboard.facade.ts. AdminDashboardFacade is the only thing the components below are allowed to inject. It composes ProjectEditorFacade (existing — bootstrap/status/validation), ADMIN_DASHBOARD_METRICS_GATEWAY (via the token, not the concrete class), and AdminDashboardHistoryService, and exposes computed signals per card (status + value) plus the health-check list and quick-actions list.

  7. Presentational componentscomponents/admin-dashboard-card.component.*, admin-dashboard-quick-actions.component.*, admin-dashboard-activity.component.*, admin-dashboard-health.component.*. Each takes only @Input()s (card data, health entries, quick-action list) — no HttpClient, no localStorage, no route access, no facade injection. This is what makes them independently testable and reusable.

  8. Page containerpages/admin-dashboard-page.component.*. Injects AdminDashboardFacade, computes per-card status from bootstrap-loaded/metrics-error/empty conditions, prefixes routerLinks with the current locale (LanguageService.currentLanguage()), and passes plain data down to the presentational components above. This is the only place in the feature that knows about routing or the facade.

  9. Route wiringapp.routes.ts. /:lang/backoffice/dashboard -> AdminDashboardPageComponent, guarded by adminAuthGuard; /:lang/backoffice (empty path) redirects to dashboard.

Full narrative and known gaps: docs/archive/ADMIN.md (historical build log) and docs/BACKEND.md (current contract).

Steps to add a new feature (derived from the example above)

  1. Decide: does this belong in features/<area>/<feature>/, or is it simple enough for pages/? Route-guarded, multi-component admin/backoffice work goes in features/admin/* or features/backoffice/*.
  2. Define the domain model(s) first (models/*.model.ts) — no behavior, no DI.
  3. If the feature needs data that might later come from a real backend, define a gateway/repository interface before writing any implementation.
  4. Implement a local/mock gateway against existing data sources where possible (reuse, don't duplicate — check core/* and other features' services first).
  5. Create an InjectionToken for the gateway and bind it to the local implementation in app.config.ts (or the relevant provider scope). This is the seam a backend integration will use later — never inject the concrete class directly from a facade or component.
  6. Write the facade. It is the only consumer of the gateway token, and the only thing components inject.
  7. Build presentational components as @Input()/@Output()-only — verify none of them import HttpClient, storage, or a facade.
  8. Build the container/page component that injects the facade and wires routing.
  9. Add routes in app.routes.ts, with adminAuthGuard (or the relevant guard) if it's an admin surface.
  10. Add every new user-facing string to i18n/translations.ts (interface) then en.ts/ru.ts/hy.ts — never hardcode copy in a template.
  11. Document backend gaps (if any) in docs/BACKEND.md §3 (CRUD Contracts, endpoints by domain), marking proposed/unimplemented endpoints as such.
  12. Run npm run arch:check (import boundaries + circular dependencies) and npx tsc -p tsconfig.app.json --noEmit before committing.