# Theme Portfolio — Improvement & Growth Plan

> Package: capell-app/theme-portfolio · Kind: theme · Tier: premium · Product group: Capell Themes · Bundle: themes · Status: Complete

## 1. Snapshot

Theme key `portfolio` is registered in `src/PortfolioThemeServiceProvider.php` via `ThemeRegistry::register()` with a single `BladeThemeRenderer` (layout `capell-theme-portfolio::page`) and one preset (`portfolio`, warm-clay `#7c2d12` / rose `#f43f5e`). The definition declares 17 `includedSections`; 16 ship as real `resources/views/sections/*.blade.php` templates (navigation is delegated to foundation and its local template is a near-empty stub) — namely hero, about-bio, features, proof, content-listing, work-grid, case-studies, case-study-detail, process, services, testimonials, speaking-media-kit, availability, newsletter, cta, footer. The demo command `capell:theme-portfolio-demo` (`src/Console/Commands/DemoCommand.php`) delegates to `InstallPortfolioThemeDemoAction`, which calls foundation's shared `ThemeDemoPageInstaller` (seeds ≥7 route-backed pages with Unsplash media); demo "layouts" are driven by foundation, not declared per-layout in this package. The theme overrides every standard section with portfolio-specific Blade and inherits foundation behaviour (definition `extends: 'default'`). Marketplace and Composer copy now use buyer-facing creator/consultant case-study positioning. Health checks now verify provider, package file, manifest, and screenshot boundaries. Screenshots: `capell.json` declares 6 committed assets: the extension-card and hero JPG previews plus 3 route-backed PNG captures for homepage, case-study, and services/enquiry workflows. `docs/screenshots.json` declares **9** deployment captures, all committed under `docs/screenshots/`.

## Completed Improvement Slices

- **2026-06-03:** Rewrote marketplace/Composer copy, replaced the critical health-check stub with real diagnostics, and documented the intentional split between runtime `extends: default` and manifest dependency `extends: capell-app/foundation-theme`.
- **2026-06-04:** Moved newsletter chrome into translations, removed the inert `action="#"` fallback, added hydrated `formAction`/`formMethod` support, and covered static/hydrated newsletter rendering in tests.
- **2026-06-05:** Reconciled product-group docs to `Capell Themes`, documented the manifest/runtime `extends` split in README and overview docs, and added manifest/docs assertions for both boundaries.
- **2026-06-05:** Made testimonials and speaking/media-kit sections read `$section->items` first, with translated fallback summary/card/quote defaults for unhydrated demo states.
- **2026-06-06:** Replaced the 3 SVG marketplace layout diagrams with Capell runner PNG captures and fulfilled the 9-entry `docs/screenshots.json` contract.
- **2026-06-07:** Wired Newsletter's public subscribe route into the Portfolio newsletter section automatically when the Newsletter package is installed, preserving hydrated form overrides while giving theme captures a real package-owned action.

## 2. Improvements (existing functionality)

1. **Shipped 2026-06-05: Make testimonials data-driven** — testimonials now render supplied `$section->items` first and fall back to translated demo quotes/attribution only when empty — `resources/views/sections/testimonials.blade.php` — Done
2. **Shipped 2026-06-05: Make speaking/media-kit data-driven** — speaking/media-kit cards now render supplied `$section->items` first and fall back to translated demo cards only when empty — `resources/views/sections/speaking-media-kit.blade.php` — Done
3. **Shipped 2026-06-05: Translate hardcoded copy in services/stats** — services fallback labels/cards plus hero and work-grid stat pills now use `capell-theme-portfolio::generic` translations, with render coverage proving the same defaults still output and source guards keeping those literals out of Blade — `resources/views/sections/services.blade.php`, `hero.blade.php`, `work-grid.blade.php` — Done
4. **Shipped 2026-06-07: Translate newsletter chrome and connect package capture** — newsletter labels, placeholder, form label, and button copy come from `generic.php`; the section renders a real form when hydrated with `formAction`, and now automatically falls back to Newsletter's `capell-newsletter.subscribe` route when the Newsletter package is installed. Static states still show a translated CTA instead of posting to `action="#"`. — `resources/views/sections/newsletter.blade.php`, `src/PortfolioThemeServiceProvider.php`, `resources/lang/en/generic.php` — Done
5. **Hero/work-grid stats translated and overrideable.** Vanity stat copy is no longer hard-coded in Blade; translated defaults and hydrated section data keep demo output editable. — `resources/views/sections/hero.blade.php`, `resources/views/sections/work-grid.blade.php` — Done
6. **Empty-state strategy unified.** Case studies, work grid, services, testimonials, and speaking/media-kit now use shared dashed premium-layout placeholders when section items are empty. — `resources/views/sections/{case-studies,work-grid,services,testimonials,speaking-media-kit}.blade.php` — Done
7. **Dark preset/variant shipped.** The theme now registers `portfolio-dark` and ships scoped `.dark .portfolio-shell` surface/card/border/text overrides. — `resources/css/theme-portfolio.css`, `src/PortfolioThemeServiceProvider.php` — Done
8. **Reduced-motion users are guarded from theme motion.** `theme-portfolio.css` disables portfolio-shell animation/transition duration, removes carousel snap motion, and neutralizes hover translate/scale effects inside `@media (prefers-reduced-motion: reduce)` while preserving the skip-link focus reveal. — `resources/css/theme-portfolio.css` — Done
9. **Shipped 2026-06-07: promote raw hex to design tokens.** Recurring section palette colours now use semantic `portfolio-*` token classes backed by `--portfolio-*` / `--theme-*` custom properties, and tests guard section Blade against raw hex colour utilities. — `resources/css/theme-portfolio.css` + section blades — Done
10. **Navigation inheritance accepted.** The local navigation view remains a deliberate foundation-delegated stub; the real public navigation is inherited rather than duplicated. — `resources/views/sections/navigation.blade.php` — Done

## 3. Missing Features (gaps)

Manifest `capabilities[]` = `["theme-portfolio", "theme-portfolio-frontend"]` (frontend rendering only — no editor/authoring capability declared).

Table-stakes for a portfolio vertical are now present at the theme boundary:

- **Work/project showcase grid shipped.** Work-grid/content-listing render portfolio work with translated defaults, hydrated data, image attributes, empty states, and render-budget coverage.
- **Case-study detail shipped.** Case-study sections remain the strongest differentiator, with outcome-led scope/role/timeline/result framing.
- **About / bio shipped.** The `about-bio` section gives creators a first-person/studio-story lane with supplied item cards first and translated creator-profile defaults when empty.
- **Skills / capabilities matrix covered.** Services/process/media-kit sections cover sellable capabilities; a dedicated tools/stack section would be future polish.
- **Gallery / lightbox shipped.** `gallery-lightbox` renders hydrated media with image attributes, empty states, and public-output coverage.
- **Contact / enquiry covered by availability/newsletter.** Availability, footer, services, and Newsletter-connected capture cover current renderer scope; a dedicated project enquiry package/form remains future product depth.
- **Resume / CV shipped.** `resume-cv` renders hydrated experience/timeline data with safe empty states.
- **Client logos shipped.** `client-logos` gives logo-wall proof as a distinct section.
- **Functional newsletter capture shipped.** Portfolio passes Newsletter's named public subscribe route into the newsletter section when `capell-app/newsletter` is installed; hydrated `formAction` still wins for custom implementations.

Differentiator vs table-stakes: Portfolio now owns the personal/creator lane through first-person bio, single-operator availability, media kit, audience/newsletter growth, gallery, resume/CV, and logo proof, while Agency owns team/campaign/services positioning.

## 4. Issues / Risks

- **Shipped 2026-06-05: Doc/manifest product-group drift** — `capell.json`, `README.md`, and `docs/overview.md` now agree on `product.group: "Capell Themes"` and tests assert the docs stay aligned with the manifest.
- **Shipped 2026-06-05: Dual `extends` meaning tested and documented** — runtime definition uses `extends: 'default'`, while `capell.json.extends = "capell-app/foundation-theme"`; the README, overview, provider comment, and manifest tests now preserve that distinction.
- **Health check shipped, keep expanding diagnostics as the package grows** — `ThemePortfolioHealthCheck` now verifies provider, package file, manifest, and screenshot boundaries. Add future sections/assets to those diagnostics instead of letting the critical check drift back into a shallow compatibility-only assertion — `src/Health/ThemePortfolioHealthCheck.php`.
- **Stub management contribution** — `src/Manifest/ThemeManagementPageContribution.php` is a bare contract shell (`compatibleCapellApiVersion()` only); confirm `ThemeExtensionPage` needs nothing more, or it is dead surface area — `src/Manifest/ThemeManagementPageContribution.php`.
- **Shipped 2026-06-07: Newsletter package capture route connected** — Newsletter now exposes `capell-newsletter.subscribe`, and Portfolio resolves it at render time when the package is installed. Public submissions are site-scoped through the frontend context, create pending/subscribed subscribers through Newsletter Actions, record consent evidence, and request double opt-in by default. `resources/views/sections/newsletter.blade.php`, `src/PortfolioThemeServiceProvider.php`, `../newsletter/routes/web.php`, `../newsletter/src/Actions/SubscribeFromPublicRequestAction.php`.
- **Public Blade DB-query safety: good** — `page.blade.php` only echoes pre-hydrated `$content` and brand tokens; section templates read `$section->items` arrays and `__()` strings, never Eloquent. `tests/Unit/PublicOutputSafetyTest.php` string-scans all views + lang for `::query(`, `DB::`, `loadMissing(`, `wire:`, `Filament`, `capell-app/theme-portfolio`, model/field markers — solid coverage, no leak found.
- **Shipped 2026-06-06: hero/work image alt and LCP hints are wired.** Hero media now falls back to an informative alt string, declares intrinsic dimensions, and uses eager/high-priority async decoding for first-viewport media. Content-listing project images derive alt text from item metadata/title, declare intrinsic dimensions, and lazy-load with async decoding. Remaining WCAG follow-up: carousel button visibility/affordance. — `resources/views/sections/{hero,content-listing}.blade.php`, `resources/lang/en/generic.php`.
- **Cache safety** — `capell.json.performance.cacheSafety.cacheable = false`, `variesBy: ["site","locale"]`, `sensitiveOutput: false`. Consistent with locale-dependent `__()` output and no per-user data. The inline `style="…tokens…"` in `page.blade.php` is brand-derived (site-scoped), matching `variesBy`. No issue, but document why a visual theme is non-cacheable if a future perf pass questions it.
- **Performance budget covered.** Every Portfolio-owned section now renders anonymously inside the manifest 20ms budget with zero select queries and public-output safety assertions. — `capell.json`, `tests/Unit/PortfolioThemeDefinitionTest.php`.
- **Render test gaps closed for current roadmap.** Footer plus services, testimonials, speaking/media-kit, newsletter, gallery-lightbox, resume-cv, client-logos, and empty-section placeholder branches have focused coverage; navigation is inherited from Foundation. — `tests/Unit/`.

## 5. Marketplace & Selling

The manifest and Composer description now use this buyer-facing 1-sentence summary:

> A premium portfolio theme for creators and consultants — turn selected work into outcome-driven case studies, sell your services and media kit, and grow your audience from one polished site.

The manifest marketplace description now uses this buyer-facing product story:

> Theme Portfolio gives independent creators, consultants, and studios a credibility-first website built around proof, not just pretty pictures. Lead with a work-led hero, walk visitors through outcome-rich case studies (scope, role, timeline, measurable results), and present your services, process, and media kit as things people can actually buy. Connect Media Library for real project imagery, Content Sections for deep case studies, and Newsletter for audience capture — every section degrades gracefully when an integration is not installed. Where an agency theme sells a team and campaigns, Theme Portfolio sells _you_: your work, your authority, and your availability.

**Media status:** the live capture set is now committed — `docs/screenshots.json` declares 9 required screenshots and all 9 PNGs exist under `docs/screenshots/`. The 3 hand-made SVG marketplace mockups have been removed and replaced with real workflow captures. Remaining media depth is optional polish: add refreshed dark-mode marketplace pairs if the gallery needs more variation.

Completed 2026-06-07. Every prioritized roadmap row is closed. Theme Portfolio now has aligned product docs, dual-extends coverage, buyer-facing marketplace copy, route-backed captures, real health diagnostics, translated/data-driven creator sections, Newsletter integration, dark preset/CSS, reduced-motion guards, gallery-lightbox, resume/CV, client-logo sections, semantic colour tokens, per-section render coverage, and 20ms/no-query public-output guards.

**Differentiation & target buyer:** target = solo creator / freelance consultant / one-to-three-person studio who needs to win premium work on credibility. Differentiate from theme-agency by owning first-person voice, single-operator availability/booking, media kit + speaking, and audience growth — not team rosters or multi-service campaign funnels.

**8–12 keywords/tags:** `portfolio`, `case studies`, `personal brand`, `creator`, `consultant`, `freelancer`, `work showcase`, `media kit`, `studio`, `outcomes`, `newsletter`, `premium theme`.

## 6. Prioritized Roadmap

| Item                                                                                                     | Bucket | Effort | Impact | Section ref                                                                                                                                                                                 |
| -------------------------------------------------------------------------------------------------------- | ------ | ------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Generate the 9 declared `screenshots.json` captures (+ dark pair)                                        | Done   | M      | High   | §5 — closed 2026-06-06: 9 route-backed PNG captures are committed and marketplace SVG diagrams were replaced with real workflow screenshots; dark pair remains after dark preset work.      |
| Shipped 2026-06-05: Reconcile product-group drift (overview.md vs capell.json) + document dual `extends` | Done   | S      | Med    | §4                                                                                                                                                                                          |
| Shipped 2026-06-05: Make testimonials + speaking/media-kit data-driven                                   | Done   | M      | High   | §2.1, §2.2                                                                                                                                                                                  |
| Shipped 2026-06-05: Translate hardcoded copy (services, newsletter, stats) + add missing lang keys       | Done   | M      | Med    | §2.3, §2.4, §2.5                                                                                                                                                                            |
| Add About/Bio section (creator lane differentiator vs agency)                                            | Done   | M      | High   | §3                                                                                                                                                                                          |
| Shipped 2026-06-05: Implement real health-check probes                                                   | Done   | S      | Med    | §4 — `ThemePortfolioHealthCheck` verifies the Theme Studio definition, required package files, manifest wiring, health-check registration, marketplace copy, and screenshot assets.         |
| Add image LCP hints (dimensions, lazy/eager, srcset) + fix alt handling                                  | Done   | M      | Med    | §4                                                                                                                                                                                          |
| Unify empty-state strategy across sections                                                               | Done   | M      | Med    | §2.6 — closed 2026-06-07: case-studies, work-grid, services, testimonials, and speaking/media-kit now use the shared dashed premium-layout placeholder when section items are empty.        |
| Add render tests for footer/nav/services/testimonials/speaking/newsletter                                | Done   | M      | Med    | §4 — closed 2026-06-07: focused registry tests cover footer plus services, testimonials, speaking/media-kit, newsletter, and empty-section placeholder branches.                            |
| Wire Newsletter integration to provide real capture actions automatically                                | Done   | M      | High   | §2.4, §4 — closed 2026-06-07: Newsletter exposes `capell-newsletter.subscribe`; Portfolio automatically targets that route when installed while preserving hydrated `formAction` overrides. |
| Ship a dark preset + dark CSS                                                                            | Done   | L      | High   | §2.7, §5 — closed 2026-06-07: the theme now ships a `portfolio-dark` preset plus scoped `.dark .portfolio-shell` surface/card/border/text overrides.                                        |
| Add reduced-motion guards for carousels + hover transforms                                               | Done   | S      | Med    | §2.8                                                                                                                                                                                        |
| Add gallery/lightbox + resume/CV + client-logo sections                                                  | Done   | L      | Med    | §3 — closed 2026-06-07: `gallery-lightbox`, `resume-cv`, and `client-logos` now render hydrated data with image attributes, empty states, and public-output coverage.                       |
| Promote raw hex to design tokens for full theme-editor propagation                                       | Done   | M      | Med    | §2.9 — closed 2026-06-07: section Blade now uses semantic Portfolio token classes for recurring palette colours, with a no-hex Blade guard.                                                 |
| Add a frontend render-budget guardrail test (20ms)                                                       | Done   | M      | Low    | §4 — closed 2026-06-07: every Portfolio-owned section now renders anonymously inside the manifest 20ms budget with zero select queries and public-output safety assertions.                 |