Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions docs/screenshots/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# EchoEd Screenshots

Screenshots captured from the local Angular app at `http://127.0.0.1:4200`.

## Files

- `landing-desktop.png` - public landing page desktop viewport.
- `landing-mobile.png` - public landing page mobile viewport.
- `login-demo-entry.png` - login and demo entry screen.
- `registration-request-demo.png` - account creation/request demo screen.
- `student-dashboard.png` - seeded demo student dashboard.
- `teacher-dashboard.png` - seeded demo teacher dashboard.
- `intro-africa-storybook-in-progress.png` - Introduction to Africa lesson in progress with a storybook open.
- `social/` - social-ready screenshots for launch posts, link previews, and feed posts.

## Social Screenshots

- `social/echoed-landing-linkedin-1200x630.png` - landscape landing page image for LinkedIn, X, Facebook, and link previews.
- `social/echoed-demo-login-1200x630.png` - demo access/login image for posts explaining how to try EchoEd.
- `social/echoed-student-dashboard-1200x630.png` - student experience image for educator-facing posts.
- `social/echoed-teacher-dashboard-1200x630.png` - teacher dashboard image for educator and school-facing posts.
- `social/echoed-storybook-linkedin-1200x630.png` - Introduction to Africa storybook image for launch posts.
- `social/echoed-storybook-square-1080x1080.png` - square storybook image for feed posts.
- `social/echoed-landing-portrait-1080x1350.png` - portrait landing page image for feed posts.

## Notes

- Public-page screenshots were captured from the frontend dev server.
- Dashboard screenshots were captured from the local app with the backend running against seeded demo data.
- Do not include real student, school, personal, or production data in demo screenshots.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/landing-desktop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/landing-mobile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/login-demo-entry.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/registration-request-demo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/student-dashboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/teacher-dashboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ <h3 class="text-xl font-bold leading-tight">{{ step.title }}</h3>
</button>
</div>
<div class="mt-4 flex items-center justify-between">
<span class="text-xs text-slate-500">Guided investor-ready walkthrough</span>
<span class="text-xs text-slate-500">Guided community walkthrough</span>
<button
class="px-4 py-2 rounded-full bg-primary text-white font-semibold shadow-soft-card hover:translate-y-[-1px] transition"
type="button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class SidebarComponent {
{ label: 'Review Center', route: '/workspace/review-center', icon: 'ClipboardList', permission: 'nav:review-center' },
{ label: 'Access', route: '/workspace/access', icon: 'Users', permission: 'nav:access' },
{ label: 'Analytics', route: '/workspace/analytics', icon: 'SlidersHorizontal', permission: 'nav:analytics' },
{ label: 'Commercial', route: '/workspace/commercial', icon: 'SlidersHorizontal', permission: 'nav:commercial' },
{ label: 'Community', route: '/workspace/commercial', icon: 'Users', permission: 'nav:commercial' },
]
},
{
Expand Down Expand Up @@ -91,7 +91,7 @@ export class SidebarComponent {
'Review Center': 'RC',
Access: 'AC',
Analytics: 'AN',
Commercial: 'CM',
Community: 'CO',
Learners: 'LR',
Cohorts: 'CH',
Settings: 'ST',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { V2PlatformService } from '../../services/v2-platform.service';
<header class="ee-page-header">
<p class="ee-eyebrow">Access Grants</p>
<h1 id="access-title">Product access management</h1>
<span class="ee-page-copy">Grant product-level access without changing course enrollment, checkout, or lesson governance.</span>
<span class="ee-page-copy">Grant product-level access without changing course enrollment or lesson governance.</span>
<div class="ee-action-row">
<span class="ee-badge ee-badge--draft">Manual grants</span>
<span class="ee-badge">Runtime governance preserved</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ import { V2PlatformService } from '../../services/v2-platform.service';
standalone: true,
imports: [CommonModule, RouterModule],
template: `
<section class="commercial ee-page" aria-labelledby="commercial-title">
<section class="community ee-page" aria-labelledby="community-title">
<header class="ee-page-header">
<p class="ee-eyebrow">Commercial Readiness</p>
<h1 id="commercial-title" class="ee-page-title">Product monetization command center</h1>
<p class="ee-page-copy">Prepare products, visibility, pricing placeholders, and workspace commercial settings. Payments, checkout, subscriptions, and billing execution are not implemented.</p>
<p class="ee-eyebrow">Community Readiness</p>
<h1 id="community-title" class="ee-page-title">Project stewardship dashboard</h1>
<p class="ee-page-copy">Prepare products, visibility, contribution pathways, and workspace community settings for the open-source launch.</p>
</header>

<section class="ee-metrics">
<article class="ee-metric"><span>Products</span><strong>{{ products.length }}</strong></article>
<article class="ee-metric"><span>Drafts</span><strong>{{ countStatus('draft') }}</strong></article>
<article class="ee-metric"><span>Published</span><strong>{{ countStatus('published') }}</strong></article>
<article class="ee-metric"><span>Placeholder ARR</span><strong>$0</strong></article>
<article class="ee-metric"><span>Community review</span><strong>{{ countStatus('in_review') }}</strong></article>
</section>

<section class="ee-grid ee-grid--wide">
Expand All @@ -29,19 +29,19 @@ import { V2PlatformService } from '../../services/v2-platform.service';
<dl><div *ngFor="let item of mapEntries(visibilityCounts())"><dt>{{ label(item[0]) }}</dt><dd>{{ item[1] }}</dd></div></dl>
</article>
<article class="ee-panel">
<h2>Pricing Models</h2>
<h2>Access Models</h2>
<dl><div *ngFor="let item of mapEntries(pricingCounts())"><dt>{{ label(item[0]) }}</dt><dd>{{ item[1] }}</dd></div></dl>
</article>
<article class="ee-panel">
<h2>Product Types</h2>
<dl><div *ngFor="let item of mapEntries(typeCounts())"><dt>{{ label(item[0]) }}</dt><dd>{{ item[1] }}</dd></div></dl>
</article>
<article class="ee-panel">
<h2>Placeholder Metrics</h2>
<h2>Community Signals</h2>
<dl>
<div><dt>Revenue</dt><dd>$0 - payment provider absent</dd></div>
<div><dt>Conversion</dt><dd>0% - checkout absent</dd></div>
<div><dt>ARR</dt><dd>$0 - subscriptions absent</dd></div>
<div><dt>Contributor onboarding</dt><dd>Tracked through GitHub issues and docs</dd></div>
<div><dt>Educator review</dt><dd>Collected through feedback and walkthroughs</dd></div>
<div><dt>Demo access</dt><dd>Manual grants keep the demo bounded</dd></div>
</dl>
</article>
</section>
Expand All @@ -50,20 +50,20 @@ import { V2PlatformService } from '../../services/v2-platform.service';
<div class="ee-panel-header">
<div>
<p class="ee-eyebrow">Workspace Settings</p>
<h2>Commercial placeholders</h2>
<h2>Community placeholders</h2>
</div>
<span class="ee-badge ee-badge--draft">No billing execution</span>
<span class="ee-badge ee-badge--draft">Community launch</span>
</div>
<div class="settings">
<article class="ee-card--interactive" *ngFor="let section of settings"><strong>{{ section }}</strong><span>Placeholder configuration area for future commercialization.</span></article>
<article class="ee-card--interactive" *ngFor="let section of settings"><strong>{{ section }}</strong><span>Placeholder configuration area for future community stewardship.</span></article>
</div>
</section>

<section class="ee-panel">
<div class="ee-panel-header">
<div>
<p class="ee-eyebrow">Inventory</p>
<h2>Commercial product readiness</h2>
<h2>Community product readiness</h2>
</div>
<a class="ee-link-button" routerLink="/workspace/products">Products</a>
</div>
Expand Down Expand Up @@ -95,7 +95,7 @@ import { V2PlatformService } from '../../services/v2-platform.service';
export class CommercialDashboardComponent implements OnInit {
private readonly v2Platform = inject(V2PlatformService);
products: Product[] = [];
readonly settings = ['Branding', 'Billing', 'Domains', 'Plans', 'AI Usage'];
readonly settings = ['Branding', 'Documentation', 'Domains', 'Roadmap', 'AI Usage'];

ngOnInit(): void {
this.v2Platform.getProducts().subscribe(products => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { RouterModule } from '@angular/router';
</div>
</header>

<section class="pitch-strip" aria-label="EchoEd V2 value proposition">
<section class="community-strip" aria-label="EchoEd V2 community walkthrough">
<article *ngFor="let callout of callouts">
<span>{{ callout.kicker }}</span>
<strong>{{ callout.title }}</strong>
Expand Down Expand Up @@ -68,7 +68,7 @@ import { RouterModule } from '@angular/router';
<p class="ee-eyebrow">5-Minute Script</p>
<h2>Tell the platform story in order</h2>
</div>
<span class="ee-badge ee-badge--approved">Pitch ready</span>
<span class="ee-badge ee-badge--approved">Walkthrough ready</span>
</div>
<ol class="demo-flow">
<li *ngFor="let step of steps">
Expand Down Expand Up @@ -120,11 +120,11 @@ import { RouterModule } from '@angular/router';
`,
styles: [`
code { background: #102033; border-radius: 8px; color: #fff; display: block; font-weight: 800; overflow-x: auto; padding: .9rem; }
.pitch-strip { display: grid; gap: .75rem; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); }
.pitch-strip article { background: #fff; border: 1px solid #d8e1ea; border-radius: 8px; box-shadow: 0 14px 32px rgba(16,32,51,.08); display: grid; gap: .35rem; padding: 1rem; }
.pitch-strip span { color: #0f766e; font-size: .72rem; font-weight: 900; text-transform: uppercase; }
.pitch-strip strong { color: #102033; }
.pitch-strip p { color: #526273; margin: 0; }
.community-strip { display: grid; gap: .75rem; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); }
.community-strip article { background: #fff; border: 1px solid #d8e1ea; border-radius: 8px; box-shadow: 0 14px 32px rgba(16,32,51,.08); display: grid; gap: .35rem; padding: 1rem; }
.community-strip span { color: #0f766e; font-size: .72rem; font-weight: 900; text-transform: uppercase; }
.community-strip strong { color: #102033; }
.community-strip p { color: #526273; margin: 0; }
.demo-flow { counter-reset: none; display: grid; gap: .85rem; list-style: none; margin: 0; padding: 0; }
.demo-flow li { border: 1px solid #d8e1ea; border-radius: 8px; display: grid; gap: .85rem; grid-template-columns: 5.5rem 1fr; padding: 1rem; }
.demo-flow li > span { align-items: center; background: #e7f7f4; border-radius: 999px; color: #0f766e; display: inline-flex; font-weight: 900; height: 2.2rem; justify-content: center; padding: 0 .75rem; width: fit-content; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ import { V2PlatformService } from '../../services/v2-platform.service';
<span>{{ product.access_state }}</span>
</div>
<div>
<strong>Commercial URL</strong>
<strong>Public URL</strong>
<span>{{ product.slug ? '/products/' + product.slug : 'Generated when published' }}</span>
</div>
<div>
<strong>Pricing placeholder</strong>
<strong>Access model</strong>
<span>{{ product.price_placeholder || label(product.pricing_model || 'internal') }}</span>
</div>
</div>
Expand All @@ -63,7 +63,7 @@ import { V2PlatformService } from '../../services/v2-platform.service';
</div>

<div class="notice">
Product shell details are additive. Wrapper publishing does not override existing lesson governance, create enrollments, execute checkout, or expose runtime lessons outside existing readiness rules.
Product shell details are additive. Wrapper publishing does not override existing lesson governance, create enrollments, or expose runtime lessons outside existing readiness rules.
</div>
</article>
</section>
Expand Down
26 changes: 13 additions & 13 deletions frontend/src/app/pages/product-studio/product-studio.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const PRODUCT_TYPES = [
</div>
</section>

<section class="panel pitch-cards" aria-label="Product Studio pitch callouts">
<section class="panel workflow-cards" aria-label="Product Studio workflow callouts">
<article><span>Knowledge In</span><strong>Connect project sources</strong><p>Product work starts from traceable workspace knowledge.</p></article>
<article><span>AI Understanding</span><strong>Prepare analysis safely</strong><p>Generation remains marked as future work in this phase.</p></article>
<article><span>Review</span><strong>Govern artifacts and products</strong><p>Review status is additive and does not publish lessons.</p></article>
Expand Down Expand Up @@ -165,12 +165,12 @@ const PRODUCT_TYPES = [
</label>

<label>
Pricing model
Access model
<select name="pricingModel" [(ngModel)]="pricingModel">
<option value="internal">Internal</option>
<option value="free">Free</option>
<option value="paid">Paid placeholder</option>
<option value="enterprise">Enterprise placeholder</option>
<option value="free">Open access</option>
<option value="paid">Invite-only placeholder</option>
<option value="enterprise">Community partner placeholder</option>
</select>
</label>

Expand Down Expand Up @@ -267,11 +267,11 @@ const PRODUCT_TYPES = [
.type-grid button span { color: var(--ee-gold); font-size: .76rem; font-weight: 900; text-transform: uppercase; }
.type-grid button strong { color: var(--ee-text); }
.type-grid .type-card--active { background: rgba(124,58,237,.2); border-color: rgba(167,139,250,.42); box-shadow: inset 0 0 0 1px rgba(167,139,250,.18); }
.pitch-cards { grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); }
.pitch-cards article { animation: ee-motion-card-enter var(--ee-duration-slow, 260ms) var(--ee-easing-standard, ease) both; border: 1px solid var(--ee-border); border-radius: 18px; display: grid; gap: .3rem; padding: .9rem; transition: transform var(--ee-duration-base, 180ms) var(--ee-easing-standard, ease); }
.pitch-cards article:hover { transform: var(--ee-hover-lift, translateY(-3px)); }
.pitch-cards span { color: var(--ee-gold); font-size: .72rem; font-weight: 900; text-transform: uppercase; }
.pitch-cards p { color: var(--ee-text-soft); margin: 0; }
.workflow-cards { grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); }
.workflow-cards article { animation: ee-motion-card-enter var(--ee-duration-slow, 260ms) var(--ee-easing-standard, ease) both; border: 1px solid var(--ee-border); border-radius: 18px; display: grid; gap: .3rem; padding: .9rem; transition: transform var(--ee-duration-base, 180ms) var(--ee-easing-standard, ease); }
.workflow-cards article:hover { transform: var(--ee-hover-lift, translateY(-3px)); }
.workflow-cards span { color: var(--ee-gold); font-size: .72rem; font-weight: 900; text-transform: uppercase; }
.workflow-cards p { color: var(--ee-text-soft); margin: 0; }
.grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(min(24rem, 100%), 1fr)); }
.panel { display: grid; gap: 1rem; padding: clamp(1rem, 3vw, 1.5rem); }
label { color: var(--ee-text-soft); display: grid; font-weight: 800; gap: .4rem; }
Expand All @@ -284,7 +284,7 @@ const PRODUCT_TYPES = [
.product-list article { align-items: center; background: rgba(255,255,255,.045); border: 1px solid var(--ee-border); border-radius: 1rem; display: flex; gap: 1rem; justify-content: space-between; padding: 1rem; transition: transform var(--ee-duration-base, 180ms) var(--ee-easing-standard, ease); }
.product-list article:hover { transform: var(--ee-hover-lift, translateY(-3px)); }
.runtime { color: var(--ee-azure) !important; font-weight: 800; }
@media (prefers-reduced-motion: reduce) { .workflow li, .pitch-cards article, .status { animation: none; } .workflow li:hover, .pitch-cards article:hover, .product-list article:hover { transform: none; } }
@media (prefers-reduced-motion: reduce) { .workflow li, .workflow-cards article, .status { animation: none; } .workflow li:hover, .workflow-cards article:hover, .product-list article:hover { transform: none; } }
`]
})
export class ProductStudioComponent implements OnInit {
Expand Down Expand Up @@ -383,9 +383,9 @@ export class ProductStudioComponent implements OnInit {
access_state: this.selectedCourseId ? 'existing_runtime' : 'private',
visibility: this.visibility,
pricing_model: this.pricingModel,
price_placeholder: this.pricingModel === 'paid' ? 'Price placeholder - checkout not connected' : null,
price_placeholder: this.pricingModel === 'paid' ? 'Access details pending' : null,
currency: this.pricingModel === 'paid' ? 'USD' : null,
metadata: { source: 'product_studio_phase_3', ai_generation: 'not_implemented', checkout: 'not_implemented' },
metadata: { source: 'product_studio_phase_3', ai_generation: 'not_implemented', access_workflow: 'manual' },
}).subscribe({
next: product => {
this.statusMessage = `Product shell ready: ${product.title}`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import { V2PlatformService } from '../../services/v2-platform.service';
<header [style.background-image]="heroBackground()">
<p>{{ label(product.category || product.product_type) }}</p>
<h1 id="product-title">{{ product.title }}</h1>
<span>{{ product.subtitle || product.description || 'Commercial product preview.' }}</span>
<button type="button" disabled>Enroll placeholder</button>
<span>{{ product.subtitle || product.description || 'Community product preview.' }}</span>
<button type="button" disabled>Access placeholder</button>
</header>

<main>
<article>
<h2>Overview</h2>
<p>{{ product.description || 'Product overview will be refined before checkout is connected.' }}</p>
<p>{{ product.description || 'Product overview will be refined as community review continues.' }}</p>
</article>
<article>
<h2>Curriculum summary</h2>
Expand All @@ -36,16 +36,16 @@ import { V2PlatformService } from '../../services/v2-platform.service';
</article>
<article>
<h2>Requirements</h2>
<p>{{ product.audience || 'Audience and prerequisites are placeholders for commercialization readiness.' }}</p>
<p>{{ product.audience || 'Audience and prerequisites are placeholders for community readiness.' }}</p>
</article>
<article>
<h2>Resources</h2>
<p>Resources and downloads will be connected through future product packaging work.</p>
</article>
<aside>
<h2>Pricing</h2>
<h2>Access</h2>
<strong>{{ product.price_placeholder || label(product.pricing_model || 'internal') }}</strong>
<p>Checkout and billing are not connected. This page is a commercial-readiness placeholder.</p>
<p>Access is handled through the demo and existing governed learner runtime.</p>
</aside>
</main>
</section>
Expand Down
Loading
Loading