Compare commits

..

3 Commits

Author SHA1 Message Date
7bd10f6328 Strip AI tooling and working docs for dev push 2026-04-13 15:28:46 +10:00
ab25af2e67 Add external asset hosting for Chromatic image rendering
Migrate Gitea remotes to git.tensordesign.com.au. Add assetUrl() utility
that resolves image paths from Gitea ParsonsAssets repo when
STORYBOOK_ASSET_BASE is set, enabling images on Chromatic-published
Storybook while keeping local dev unchanged via staticDirs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 15:28:14 +10:00
5b2a41f4e4 Add /publish skill for consistent multi-target deployment
Pushes to backup (full), fa-dev + sheffield (stripped via worktree),
and Chromatic in one command. Replaces ad-hoc push workflow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:50:41 +10:00
6 changed files with 53 additions and 36 deletions

3
.gitignore vendored
View File

@@ -28,6 +28,9 @@ docs/reference/how-to-work-with-both-tools.md
docs/reference/mcp-setup.md docs/reference/mcp-setup.md
docs/reference/retroactive-review-plan.md docs/reference/retroactive-review-plan.md
# Deploy scripts (contain credentials)
scripts/
# Build logs # Build logs
build-storybook.log build-storybook.log

View File

@@ -13,6 +13,7 @@ import type { SxProps, Theme } from '@mui/material/styles';
import { Typography } from '../../atoms/Typography'; import { Typography } from '../../atoms/Typography';
import { Button } from '../../atoms/Button'; import { Button } from '../../atoms/Button';
import { ProviderCardCompact } from '../../molecules/ProviderCardCompact'; import { ProviderCardCompact } from '../../molecules/ProviderCardCompact';
import { assetUrl } from '../../../utils/assetUrl';
import { Divider } from '../../atoms/Divider'; import { Divider } from '../../atoms/Divider';
import { FuneralFinderV3, type FuneralFinderV3SearchParams } from '../../organisms/FuneralFinder'; import { FuneralFinderV3, type FuneralFinderV3SearchParams } from '../../organisms/FuneralFinder';
@@ -638,7 +639,7 @@ export const HomePage = React.forwardRef<HTMLDivElement, HomePageProps>(
}} }}
> >
<img <img
src="/brandassets/images/Homepage/people.png" src={assetUrl('/images/Homepage/people.png')}
alt="Family planning together with care and confidence" alt="Family planning together with care and confidence"
/> />
</Box> </Box>

View File

@@ -8,6 +8,7 @@ import { HomePage } from './HomePage';
import type { FeaturedProvider, TrustStat } from './HomePage'; import type { FeaturedProvider, TrustStat } from './HomePage';
import { Navigation } from '../../organisms/Navigation'; import { Navigation } from '../../organisms/Navigation';
import { Footer } from '../../organisms/Footer'; import { Footer } from '../../organisms/Footer';
import { assetUrl } from '../../../utils/assetUrl';
// ─── Shared helpers ────────────────────────────────────────────────────────── // ─── Shared helpers ──────────────────────────────────────────────────────────
@@ -231,7 +232,7 @@ export const Default: Story = {
args: { args: {
navigation: nav, navigation: nav,
footer, footer,
heroImageUrl: '/brandassets/images/heroes/parsonshero.png', heroImageUrl: assetUrl('/images/heroes/parsonshero.png'),
stats: trustStats, stats: trustStats,
featuredProviders, featuredProviders,
onSelectFeaturedProvider: (id) => console.log('Featured provider:', id), onSelectFeaturedProvider: (id) => console.log('Featured provider:', id),

View File

@@ -9,6 +9,7 @@ import type { FeaturedProvider, TrustStat, PartnerLogo } from './HomePage';
import React from 'react'; import React from 'react';
import { Navigation } from '../../organisms/Navigation'; import { Navigation } from '../../organisms/Navigation';
import { Footer } from '../../organisms/Footer'; import { Footer } from '../../organisms/Footer';
import { assetUrl } from '../../../utils/assetUrl';
// ─── Shared helpers ────────────────────────────────────────────────────────── // ─── Shared helpers ──────────────────────────────────────────────────────────
@@ -177,8 +178,8 @@ const featuredProviders: FeaturedProvider[] = [
name: 'H.Parsons Funeral Directors', name: 'H.Parsons Funeral Directors',
location: 'Wollongong, NSW', location: 'Wollongong, NSW',
verified: true, verified: true,
imageUrl: '/brandassets/images/venues/hparsons-funeral-home-kiama/01.jpg', imageUrl: assetUrl('/images/venues/hparsons-funeral-home-kiama/01.jpg'),
logoUrl: '/brandassets/images/providers/hparsons-funeral-directors/logo.png', logoUrl: assetUrl('/images/providers/hparsons-funeral-directors/logo.png'),
rating: 4.6, rating: 4.6,
reviewCount: 7, reviewCount: 7,
startingPrice: 900, startingPrice: 900,
@@ -188,8 +189,8 @@ const featuredProviders: FeaturedProvider[] = [
name: 'Rankins Funerals', name: 'Rankins Funerals',
location: 'Wollongong, NSW', location: 'Wollongong, NSW',
verified: true, verified: true,
imageUrl: '/brandassets/images/venues/rankins-funeral-home-warrawong/01.jpg', imageUrl: assetUrl('/images/venues/rankins-funeral-home-warrawong/01.jpg'),
logoUrl: '/brandassets/images/providers/rankins-funerals/logo.png', logoUrl: assetUrl('/images/providers/rankins-funerals/logo.png'),
rating: 4.8, rating: 4.8,
reviewCount: 23, reviewCount: 23,
startingPrice: 1200, startingPrice: 1200,
@@ -199,8 +200,8 @@ const featuredProviders: FeaturedProvider[] = [
name: 'Easy Funerals', name: 'Easy Funerals',
location: 'Sydney, NSW', location: 'Sydney, NSW',
verified: true, verified: true,
imageUrl: '/brandassets/images/venues/lakeside-memorial-park-chapel/01.jpg', imageUrl: assetUrl('/images/venues/lakeside-memorial-park-chapel/01.jpg'),
logoUrl: '/brandassets/images/providers/easy-funerals/logo.png', logoUrl: assetUrl('/images/providers/easy-funerals/logo.png'),
rating: 4.5, rating: 4.5,
reviewCount: 42, reviewCount: 42,
startingPrice: 850, startingPrice: 850,
@@ -209,30 +210,30 @@ const featuredProviders: FeaturedProvider[] = [
const partnerLogos: PartnerLogo[] = [ const partnerLogos: PartnerLogo[] = [
{ {
src: '/brandassets/images/providers/hparsons-funeral-directors/logo.png', src: assetUrl('/images/providers/hparsons-funeral-directors/logo.png'),
alt: 'H.Parsons Funeral Directors', alt: 'H.Parsons Funeral Directors',
}, },
{ src: '/brandassets/images/providers/rankins-funerals/logo.png', alt: 'Rankins Funerals' }, { src: assetUrl('/images/providers/rankins-funerals/logo.png'), alt: 'Rankins Funerals' },
{ src: '/brandassets/images/providers/easy-funerals/logo.png', alt: 'Easy Funerals' }, { src: assetUrl('/images/providers/easy-funerals/logo.png'), alt: 'Easy Funerals' },
{ src: '/brandassets/images/providers/lady-anne-funerals/logo.png', alt: 'Lady Anne Funerals' }, { src: assetUrl('/images/providers/lady-anne-funerals/logo.png'), alt: 'Lady Anne Funerals' },
{ {
src: '/brandassets/images/providers/killick-family-funerals/logo.png', src: assetUrl('/images/providers/killick-family-funerals/logo.png'),
alt: 'Killick Family Funerals', alt: 'Killick Family Funerals',
}, },
{ {
src: '/brandassets/images/providers/kenneallys-funerals/logo.png', src: assetUrl('/images/providers/kenneallys-funerals/logo.png'),
alt: "Kenneally's Funerals", alt: "Kenneally's Funerals",
}, },
{ {
src: '/brandassets/images/providers/wollongong-city-funerals/logo.png', src: assetUrl('/images/providers/wollongong-city-funerals/logo.png'),
alt: 'Wollongong City Funerals', alt: 'Wollongong City Funerals',
}, },
{ {
src: '/brandassets/images/providers/hparsons-funeral-directors-shoalhaven/logo.png', src: assetUrl('/images/providers/hparsons-funeral-directors-shoalhaven/logo.png'),
alt: 'H.Parsons Shoalhaven', alt: 'H.Parsons Shoalhaven',
}, },
{ {
src: '/brandassets/images/providers/mackay-family-funerals/logo.webp', src: assetUrl('/images/providers/mackay-family-funerals/logo.webp'),
alt: 'Mackay Family Funerals', alt: 'Mackay Family Funerals',
}, },
]; ];
@@ -257,13 +258,13 @@ export const Default: Story = {
args: { args: {
navigation: nav, navigation: nav,
footer, footer,
heroImageUrl: '/brandassets/images/heroes/hero-3.png', heroImageUrl: assetUrl('/images/heroes/hero-3.png'),
heroHeading: 'Compare funeral director pricing near you and arrange with confidence', heroHeading: 'Compare funeral director pricing near you and arrange with confidence',
heroSubheading: 'Transparent pricing \u00B7 No hidden fees \u00B7 Arrange 24/7', heroSubheading: 'Transparent pricing \u00B7 No hidden fees \u00B7 Arrange 24/7',
stats: trustStats, stats: trustStats,
featuredProviders, featuredProviders,
discoverMapSlot: React.createElement('img', { discoverMapSlot: React.createElement('img', {
src: '/brandassets/images/placeholder/map.png', src: assetUrl('/images/placeholder/map.png'),
alt: 'Map showing provider locations', alt: 'Map showing provider locations',
style: { width: '100%', height: '100%', objectFit: 'cover' }, style: { width: '100%', height: '100%', objectFit: 'cover' },
}), }),

View File

@@ -10,6 +10,7 @@ import { FuneralFinderV4 } from '../../organisms/FuneralFinder/FuneralFinderV4';
import React from 'react'; import React from 'react';
import { Navigation } from '../../organisms/Navigation'; import { Navigation } from '../../organisms/Navigation';
import { Footer } from '../../organisms/Footer'; import { Footer } from '../../organisms/Footer';
import { assetUrl } from '../../../utils/assetUrl';
// ─── Shared helpers ────────────────────────────────────────────────────────── // ─── Shared helpers ──────────────────────────────────────────────────────────
@@ -178,8 +179,8 @@ const featuredProviders: FeaturedProvider[] = [
name: 'H.Parsons Funeral Directors', name: 'H.Parsons Funeral Directors',
location: 'Wollongong, NSW', location: 'Wollongong, NSW',
verified: true, verified: true,
imageUrl: '/brandassets/images/venues/hparsons-funeral-home-kiama/01.jpg', imageUrl: assetUrl('/images/venues/hparsons-funeral-home-kiama/01.jpg'),
logoUrl: '/brandassets/images/providers/hparsons-funeral-directors/logo.png', logoUrl: assetUrl('/images/providers/hparsons-funeral-directors/logo.png'),
rating: 4.6, rating: 4.6,
reviewCount: 7, reviewCount: 7,
startingPrice: 900, startingPrice: 900,
@@ -189,8 +190,8 @@ const featuredProviders: FeaturedProvider[] = [
name: 'Rankins Funerals', name: 'Rankins Funerals',
location: 'Wollongong, NSW', location: 'Wollongong, NSW',
verified: true, verified: true,
imageUrl: '/brandassets/images/venues/rankins-funeral-home-warrawong/01.jpg', imageUrl: assetUrl('/images/venues/rankins-funeral-home-warrawong/01.jpg'),
logoUrl: '/brandassets/images/providers/rankins-funerals/logo.png', logoUrl: assetUrl('/images/providers/rankins-funerals/logo.png'),
rating: 4.8, rating: 4.8,
reviewCount: 23, reviewCount: 23,
startingPrice: 1200, startingPrice: 1200,
@@ -200,8 +201,8 @@ const featuredProviders: FeaturedProvider[] = [
name: 'Easy Funerals', name: 'Easy Funerals',
location: 'Sydney, NSW', location: 'Sydney, NSW',
verified: true, verified: true,
imageUrl: '/brandassets/images/venues/lakeside-memorial-park-chapel/01.jpg', imageUrl: assetUrl('/images/venues/lakeside-memorial-park-chapel/01.jpg'),
logoUrl: '/brandassets/images/providers/easy-funerals/logo.png', logoUrl: assetUrl('/images/providers/easy-funerals/logo.png'),
rating: 4.5, rating: 4.5,
reviewCount: 42, reviewCount: 42,
startingPrice: 850, startingPrice: 850,
@@ -210,30 +211,30 @@ const featuredProviders: FeaturedProvider[] = [
const partnerLogos: PartnerLogo[] = [ const partnerLogos: PartnerLogo[] = [
{ {
src: '/brandassets/images/providers/hparsons-funeral-directors/logo.png', src: assetUrl('/images/providers/hparsons-funeral-directors/logo.png'),
alt: 'H.Parsons Funeral Directors', alt: 'H.Parsons Funeral Directors',
}, },
{ src: '/brandassets/images/providers/rankins-funerals/logo.png', alt: 'Rankins Funerals' }, { src: assetUrl('/images/providers/rankins-funerals/logo.png'), alt: 'Rankins Funerals' },
{ src: '/brandassets/images/providers/easy-funerals/logo.png', alt: 'Easy Funerals' }, { src: assetUrl('/images/providers/easy-funerals/logo.png'), alt: 'Easy Funerals' },
{ src: '/brandassets/images/providers/lady-anne-funerals/logo.png', alt: 'Lady Anne Funerals' }, { src: assetUrl('/images/providers/lady-anne-funerals/logo.png'), alt: 'Lady Anne Funerals' },
{ {
src: '/brandassets/images/providers/killick-family-funerals/logo.png', src: assetUrl('/images/providers/killick-family-funerals/logo.png'),
alt: 'Killick Family Funerals', alt: 'Killick Family Funerals',
}, },
{ {
src: '/brandassets/images/providers/kenneallys-funerals/logo.png', src: assetUrl('/images/providers/kenneallys-funerals/logo.png'),
alt: "Kenneally's Funerals", alt: "Kenneally's Funerals",
}, },
{ {
src: '/brandassets/images/providers/wollongong-city-funerals/logo.png', src: assetUrl('/images/providers/wollongong-city-funerals/logo.png'),
alt: 'Wollongong City Funerals', alt: 'Wollongong City Funerals',
}, },
{ {
src: '/brandassets/images/providers/hparsons-funeral-directors-shoalhaven/logo.png', src: assetUrl('/images/providers/hparsons-funeral-directors-shoalhaven/logo.png'),
alt: 'H.Parsons Shoalhaven', alt: 'H.Parsons Shoalhaven',
}, },
{ {
src: '/brandassets/images/providers/mackay-family-funerals/logo.webp', src: assetUrl('/images/providers/mackay-family-funerals/logo.webp'),
alt: 'Mackay Family Funerals', alt: 'Mackay Family Funerals',
}, },
]; ];
@@ -258,7 +259,7 @@ export const Default: Story = {
args: { args: {
navigation: nav, navigation: nav,
footer, footer,
heroImageUrl: '/brandassets/images/heroes/hero-3.png', heroImageUrl: assetUrl('/images/heroes/hero-3.png'),
heroHeading: 'Compare funeral directors pricing near you and arrange with confidence', heroHeading: 'Compare funeral directors pricing near you and arrange with confidence',
heroSubheading: 'Transparent pricing \u00B7 No hidden fees \u00B7 Arrange 24/7', heroSubheading: 'Transparent pricing \u00B7 No hidden fees \u00B7 Arrange 24/7',
finderSlot: React.createElement(FuneralFinderV4, { finderSlot: React.createElement(FuneralFinderV4, {
@@ -267,7 +268,7 @@ export const Default: Story = {
stats: trustStats, stats: trustStats,
featuredProviders, featuredProviders,
discoverMapSlot: React.createElement('img', { discoverMapSlot: React.createElement('img', {
src: '/brandassets/images/placeholder/map.png', src: assetUrl('/images/placeholder/map.png'),
alt: 'Map showing provider locations', alt: 'Map showing provider locations',
style: { width: '100%', height: '100%', objectFit: 'cover' }, style: { width: '100%', height: '100%', objectFit: 'cover' },
}), }),

10
src/utils/assetUrl.ts Normal file
View File

@@ -0,0 +1,10 @@
/**
* Resolves a static asset path. In local dev the path is served by Storybook's
* staticDirs; when STORYBOOK_ASSET_BASE is set (e.g. Chromatic builds) it
* prepends the external host URL so images load from Gitea.
*/
export const assetUrl = (path: string): string => {
const base =
typeof import.meta !== 'undefined' ? (import.meta.env?.STORYBOOK_ASSET_BASE ?? '') : '';
return `${base}${path}`;
};