diff --git a/.ai/frontend-state.json b/.ai/frontend-state.json index 5127d10..f9d6670 100644 --- a/.ai/frontend-state.json +++ b/.ai/frontend-state.json @@ -2,7 +2,7 @@ "agent": "Claude Code", "area": "frontend", "currentPhase": "F7 API integration (in progress)", - "lastVerifiedTask": "TMS-F7-006b", + "lastVerifiedTask": "TMS-F0-013", "nextRecommendedTask": "F7 on claude/f7-api-integration (PR #23). DONE: TMS-F7-001..004 (http foundation, per-domain data source, artworks+collections, nullable price), F7-005 (Studio on approved placements), F7-006a (canonical lineId + cart client), F7-006b (cart UI on the server cart: server totals, issue lines kept + reasons, hasIssues blocks checkout, promotion 422 vs 200-with-null). NEXT: TMS-F7-008 customer auth cutover (/api/v1/auth/*, opaque tms_session cookie) — it unblocks TMS-F7-007 saved designs (client + tests already done in lib/designs-api.ts) and makes the guest-cart merge real. BLOCKERS: (1) no live API locally — Postgres has only B1 identity tables and migrating it would disturb the parallel backend session, so everything is stub-verified; (2) TMS-FBR-020 — a cart line is pure ids and cannot be rendered from its own response, so lib/cart-view.ts joins labels from /artworks + /garments as an interim.", "completedTasks": [ "TMS-F0-001", @@ -17,6 +17,7 @@ "TMS-F0-010", "TMS-F0-011", "TMS-F0-012", + "TMS-F0-013", "TMS-F1-001", "TMS-F1-002", "TMS-F1-003", @@ -64,7 +65,7 @@ ], "buildStatus": "passing", "testStatus": "passing", - "visualRegressionStatus": "baselines-committed (4 viewports, homepage; Windows-rendered, not in CI)", + "visualRegressionStatus": "TMS-F0-013 logo surfaces verified at 375px and 1440px (storefront header/footer/menu, admin login/shell); prior homepage baselines remain committed", "mockDependencies": [ "storefront:home:featuredArtworks (TMS-FBR-001)", "storefront:/artworks listing + detail (TMS-FBR-001)", @@ -96,7 +97,7 @@ "storefront:studio guide (/studio-guide) — deterministic mock assistant (lib/studio-guide.ts), no LLM/live tools; guardrails deflect stock/price/delivery; order-status = tool_error + retry; real assistant endpoint + tool results are backend (TMS-FBR-009)", "storefront:loyalty & referrals (/account/loyalty) — illustrative email-derived points/tier + rewards + referral code (lib/loyalty.ts); redeem/share are preview-only; real ledger/earn/redeem + referral attribution are backend (TMS-FBR-008)" ], - "branch": "claude/f5-post-merge", + "branch": "codex/fatu-logo-system", "buildStatusNote": "F5 (growth & AI) COMPLETE — all of TMS-F5-001…010 Verified (pnpm check green). Storefront: 001 drops, 002 waitlist, 003 pre-order/made-to-order, 004 reviews, 005 community gallery, 006 artwork passport, 007 shoppable stories, 008 studio guide, 010 loyalty & referrals. Admin: 009 brand storyteller. F0–F4 Verified AND MERGED TO MAIN (2026-07-15). The F0→F4 PR stack (#4→#8) was merged bottom-up with merge commits (main HEAD e919e7e; merge commits 9599d35/190d8c7/d0201a1/f0de066/e919e7e) and all five phase branches deleted; pnpm check re-run green on the integrated main (13/13 build tasks, all unit tests, format/lint/typecheck/db:validate). Recovery note: PR #5 auto-closed when gh's --delete-branch removed its base (f0) before the auto-retarget fired; recovered by recreating the f0 branch, reopening #5, retargeting to main — thereafter each next PR was retargeted to main BEFORE merge and branches were deleted only as final cleanup. Only open item is defect TMS-F1-DEF-001 (soft 404, SEO-only). Admin Vitest 125 tests (was 116 — +9 storyteller); storefront 195 (was 89 — +24 drops, +6 waitlist, +10 fulfilment, +11 passport, +11 stories, +13 reviews, +12 community, +8 studio-guide, +11 loyalty). Note: pnpm audit 410 outage since F3-004 (this is the only failing CI 'quality' check — a retired npm endpoint, not a code issue); no new deps added.", - "lastUpdated": "2026-07-16T03:30:00Z" + "lastUpdated": "2026-07-20T23:40:00+01:00" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 8359250..335f0c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,17 @@ All notable changes to Tai Manic Studios are documented here. The project uses a four-part release version: `major.minor.patch.micro`. +## [0.1.1.0] - 2026-07-21 + +### Added + +- Added the supplied F.A.T.U brand mark across the storefront and admin experience, including responsive navigation, authentication, and footer placements. +- Added branded browser icons, an Apple touch icon, social sharing artwork, and an installable storefront manifest. + +### Changed + +- Replaced text-only F.A.T.U wordmarks with reusable, optimized logo components and documented the verified frontend handoff. + ## [0.1.0.0] - 2026-07-14 ### Added diff --git a/VERSION b/VERSION index 482e997..5cff5f1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.0.0 +0.1.1.0 diff --git a/apps/admin/app/apple-icon.png b/apps/admin/app/apple-icon.png new file mode 100644 index 0000000..99a5824 Binary files /dev/null and b/apps/admin/app/apple-icon.png differ diff --git a/apps/admin/app/icon.png b/apps/admin/app/icon.png new file mode 100644 index 0000000..ccbd3d8 Binary files /dev/null and b/apps/admin/app/icon.png differ diff --git a/apps/admin/app/layout.tsx b/apps/admin/app/layout.tsx index 0538b2a..92ff941 100644 --- a/apps/admin/app/layout.tsx +++ b/apps/admin/app/layout.tsx @@ -19,8 +19,13 @@ const sans = IBM_Plex_Sans({ }); export const metadata: Metadata = { + applicationName: 'F.A.T.U Admin', title: { default: 'Admin · From Africa To You', template: '%s · F.A.T.U Admin' }, description: 'Operational console for From Africa To You.', + icons: { + icon: [{ url: '/icon.png', type: 'image/png', sizes: '512x512' }], + apple: [{ url: '/apple-icon.png', type: 'image/png', sizes: '180x180' }], + }, robots: { index: false, follow: false, nocache: true }, }; diff --git a/apps/admin/components/admin-login-form.tsx b/apps/admin/components/admin-login-form.tsx index 60df9dd..796b4b2 100644 --- a/apps/admin/components/admin-login-form.tsx +++ b/apps/admin/components/admin-login-form.tsx @@ -5,6 +5,7 @@ import { useRouter } from 'next/navigation'; import { useEffect, useState } from 'react'; import { type AuthErrors, validateLogin } from '@/lib/admin-auth'; import { useAdminAuth } from './admin-auth-provider'; +import { BrandLogo } from './brand-logo'; const inputClass = 'h-11 w-full rounded-md border bg-surface px-3 text-sm text-ink outline-none placeholder:text-muted focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-focus-ring)]'; @@ -33,7 +34,12 @@ export function AdminLoginForm() { return (
- F.A.T.U +

Admin

diff --git a/apps/admin/components/admin-shell.tsx b/apps/admin/components/admin-shell.tsx index 9e3e0b5..191c860 100644 --- a/apps/admin/components/admin-shell.tsx +++ b/apps/admin/components/admin-shell.tsx @@ -18,6 +18,7 @@ import Link from 'next/link'; import { usePathname, useRouter } from 'next/navigation'; import { type MouseEvent, useCallback, useEffect, useRef } from 'react'; import { useAdminAuth } from './admin-auth-provider'; +import { BrandLogo } from './brand-logo'; const NAV = [ { href: '/', label: 'Dashboard', icon: LayoutDashboard }, @@ -63,11 +64,18 @@ function NavList({ pathname, onNavigate }: { pathname: string; onNavigate?: () = ); } -function BrandMark({ className }: { className?: string }) { +function AdminBrand({ compact = false }: { compact?: boolean }) { return ( - - F.A.T.U - +
+ + + Admin + +
); } @@ -135,10 +143,7 @@ export function AdminShell({ children }: { children: React.ReactNode }) { {/* Desktop sidebar — fixed in the viewport; only main content scrolls */}
@@ -197,12 +199,7 @@ export function AdminShell({ children }: { children: React.ReactNode }) { className="m-0 h-dvh max-h-none w-[min(20rem,85vw)] max-w-none bg-canvas p-0 text-ink backdrop:bg-black/50 open:flex open:flex-col" >
-
- - - Admin - -
+ } diff --git a/apps/admin/components/brand-logo.tsx b/apps/admin/components/brand-logo.tsx new file mode 100644 index 0000000..9d112c1 --- /dev/null +++ b/apps/admin/components/brand-logo.tsx @@ -0,0 +1,31 @@ +import { cn } from '@tms/ui'; +import Image from 'next/image'; + +export interface BrandLogoProps { + alt?: string; + className?: string; + priority?: boolean; + sizes?: string; +} + +/** The canonical F.A.T.U brand mark, cropped and optimized from the supplied artwork. */ +export function BrandLogo({ + alt = '', + className, + priority = false, + sizes = '40px', +}: BrandLogoProps) { + return ( + + {alt} + + ); +} diff --git a/apps/admin/public/brand/fatu-logo.png b/apps/admin/public/brand/fatu-logo.png new file mode 100644 index 0000000..7a5ab51 Binary files /dev/null and b/apps/admin/public/brand/fatu-logo.png differ diff --git a/apps/storefront/app/apple-icon.png b/apps/storefront/app/apple-icon.png new file mode 100644 index 0000000..99a5824 Binary files /dev/null and b/apps/storefront/app/apple-icon.png differ diff --git a/apps/storefront/app/icon.png b/apps/storefront/app/icon.png new file mode 100644 index 0000000..ccbd3d8 Binary files /dev/null and b/apps/storefront/app/icon.png differ diff --git a/apps/storefront/app/layout.tsx b/apps/storefront/app/layout.tsx index de698b8..110f35d 100644 --- a/apps/storefront/app/layout.tsx +++ b/apps/storefront/app/layout.tsx @@ -25,6 +25,7 @@ const sans = IBM_Plex_Sans({ export const metadata: Metadata = { metadataBase: new URL('https://fromafricatoyou.com'), + applicationName: 'F.A.T.U', title: { default: 'From Africa To You — Art-led apparel', template: '%s · From Africa To You', @@ -36,7 +37,26 @@ export const metadata: Metadata = { siteName: 'From Africa To You', title: 'From Africa To You — Art-led apparel', description: 'A premium digital art gallery and interactive clothing-design experience.', + images: [ + { + url: '/opengraph-image.png', + width: 1200, + height: 630, + alt: 'F.A.T.U — From Africa To You', + }, + ], }, + twitter: { + card: 'summary_large_image', + title: 'From Africa To You — Art-led apparel', + description: 'A premium digital art gallery and interactive clothing-design experience.', + images: ['/opengraph-image.png'], + }, + icons: { + icon: [{ url: '/icon.png', type: 'image/png', sizes: '512x512' }], + apple: [{ url: '/apple-icon.png', type: 'image/png', sizes: '180x180' }], + }, + manifest: '/manifest.webmanifest', robots: { index: true, follow: true }, }; diff --git a/apps/storefront/app/manifest.ts b/apps/storefront/app/manifest.ts new file mode 100644 index 0000000..7ad3428 --- /dev/null +++ b/apps/storefront/app/manifest.ts @@ -0,0 +1,20 @@ +import type { MetadataRoute } from 'next'; + +export default function manifest(): MetadataRoute.Manifest { + return { + name: 'From Africa To You', + short_name: 'F.A.T.U', + description: 'Original African artwork, made wearable.', + start_url: '/', + display: 'standalone', + background_color: '#fafaf7', + theme_color: '#fafaf7', + icons: [ + { + src: '/icon.png', + sizes: '512x512', + type: 'image/png', + }, + ], + }; +} diff --git a/apps/storefront/app/opengraph-image.png b/apps/storefront/app/opengraph-image.png new file mode 100644 index 0000000..2d9290a Binary files /dev/null and b/apps/storefront/app/opengraph-image.png differ diff --git a/apps/storefront/components/site/brand-logo.tsx b/apps/storefront/components/site/brand-logo.tsx new file mode 100644 index 0000000..43c8335 --- /dev/null +++ b/apps/storefront/components/site/brand-logo.tsx @@ -0,0 +1,39 @@ +import { cn } from '@tms/ui'; +import Image from 'next/image'; + +export interface BrandLogoProps { + alt?: string; + className?: string; + inverse?: boolean; + priority?: boolean; + sizes?: string; +} + +/** The canonical F.A.T.U brand mark, cropped and optimized from the supplied artwork. */ +export function BrandLogo({ + alt = '', + className, + inverse = false, + priority = false, + sizes = '48px', +}: BrandLogoProps) { + return ( + + {alt} + + ); +} diff --git a/apps/storefront/components/site/site-footer.tsx b/apps/storefront/components/site/site-footer.tsx index 30861a3..ab7a856 100644 --- a/apps/storefront/components/site/site-footer.tsx +++ b/apps/storefront/components/site/site-footer.tsx @@ -1,6 +1,7 @@ import { Container } from '@tms/ui'; import { ArrowRight, Instagram, Twitter } from 'lucide-react'; import Link from 'next/link'; +import { BrandLogo } from '@/components/site/brand-logo'; import { footerNav } from '@/lib/nav'; /** @@ -25,9 +26,12 @@ export function SiteFooter() { {/* Mobile: brand full-width, then nav in a 2×2 grid. Desktop: brand + four columns. */}
- - F.A.T.U - +

Hand-drawn art from across Africa, printed on cotton. From Africa, to you.

diff --git a/apps/storefront/components/site/site-header.tsx b/apps/storefront/components/site/site-header.tsx index f026eca..d80add2 100644 --- a/apps/storefront/components/site/site-header.tsx +++ b/apps/storefront/components/site/site-header.tsx @@ -7,6 +7,7 @@ import { usePathname } from 'next/navigation'; import { type MouseEvent, useCallback, useEffect, useRef } from 'react'; import { useAuth } from '@/components/account/auth-provider'; import { useCart } from '@/components/cart/cart-provider'; +import { BrandLogo } from '@/components/site/brand-logo'; import { primaryNav } from '@/lib/nav'; /** @@ -62,9 +63,10 @@ export function SiteHeader() {