diff --git a/packages/apps/src/index.ts b/packages/apps/src/index.ts index 5ffd9d08..62d7b4cf 100644 --- a/packages/apps/src/index.ts +++ b/packages/apps/src/index.ts @@ -7,6 +7,7 @@ export type AppManifest = { iconPath: string; size?: number; devOriginOverride: string; + demoVideoSrc: string; }; export const apps = [ @@ -16,9 +17,10 @@ export const apps = [ name: 'Gnocchi', description: 'Organize your weekly cooking and groceries', mainImageUrl: 'https://gnocchi.club/og-image.png', - iconPath: 'icon.png', + iconPath: 'android-chrome-512x512.png', size: 4, devOriginOverride: 'http://localhost:6220', + demoVideoSrc: '/videos/gnocchi.mp4', } satisfies AppManifest<'gnocchi'>, { id: 'trip-tick', @@ -28,6 +30,7 @@ export const apps = [ iconPath: 'icon.png', size: 2, devOriginOverride: 'http://localhost:6221', + demoVideoSrc: '', } satisfies AppManifest<'trip-tick'>, ] as const; diff --git a/web/.gitignore b/web/.gitignore index fd3dbb57..6dd43ec6 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -34,3 +34,5 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +.DS_Store diff --git a/web/public/videos/gnocchi.mp4 b/web/public/videos/gnocchi.mp4 new file mode 100644 index 00000000..af13db5c Binary files /dev/null and b/web/public/videos/gnocchi.mp4 differ diff --git a/web/src/components/paws/Paws.tsx b/web/src/components/paws/Paws.tsx index 54c7e4e4..af7d817e 100644 --- a/web/src/components/paws/Paws.tsx +++ b/web/src/components/paws/Paws.tsx @@ -4,18 +4,17 @@ export interface PawsProps {} export function Paws({}: PawsProps) { return ( -
- - +
+
+ + +
); } diff --git a/web/src/components/promo/AppDemo.tsx b/web/src/components/promo/AppDemo.tsx new file mode 100644 index 00000000..c4fb1a37 --- /dev/null +++ b/web/src/components/promo/AppDemo.tsx @@ -0,0 +1,43 @@ +import './phone.css'; +import { AppId, appsById, getAppUrl } from '@biscuits/apps'; +import PhoneDemo from './PhoneDemo.jsx'; +import { Button } from '@a-type/ui/components/button'; +import classNames from 'classnames'; + +export interface AppDemoProps { + appId: AppId; + index: number; +} + +export function AppDemo({ appId, index }: AppDemoProps) { + const app = appsById[appId]; + + const url = getAppUrl(app); + + return ( +
+
+ {app.name} +

{app.name}

+

{app.description}

+ +
+
+ +
+
+ ); +} diff --git a/web/src/components/promo/PhoneDemo.tsx b/web/src/components/promo/PhoneDemo.tsx new file mode 100644 index 00000000..e4704ca0 --- /dev/null +++ b/web/src/components/promo/PhoneDemo.tsx @@ -0,0 +1,36 @@ +import { useMemo } from 'react'; + +export interface PhoneDemoProps { + src: string; +} + +export function PhoneDemo({ src }: PhoneDemoProps) { + const animationDelay = useMemo(() => { + return `${(Math.random() * 3).toFixed(2)}s`; + }, []); + + return ( +
+
+
+ Video Coming Soon +
+
+
+ ); +} + +export default PhoneDemo; diff --git a/web/src/components/promo/phone.css b/web/src/components/promo/phone.css new file mode 100644 index 00000000..4c28d299 --- /dev/null +++ b/web/src/components/promo/phone.css @@ -0,0 +1,49 @@ +.phone-wrapper { + perspective-origin: 50% 50%; + transform-style: preserve-3d; + perspective: 1000px; +} + +@keyframes drift-3d { + 0% { + transform: rotateY(-10deg) rotateX(-3deg); + } + 10% { + transform: rotateY(-12deg) rotateX(2deg); + } + 20% { + transform: rotateY(-8deg) rotateX(0deg); + } + 30% { + transform: rotateY(-14deg) rotateX(-3deg); + } + 40% { + transform: rotateY(-6deg) rotateX(2deg); + } + 50% { + transform: rotateY(-10deg) rotateX(0deg); + } + 60% { + transform: rotateY(-12deg) rotateX(-3deg); + } + 70% { + transform: rotateY(-18deg) rotateX(2deg); + } + 80% { + transform: rotateY(-14deg) rotateX(0deg); + } + 90% { + transform: rotateY(-6deg) rotateX(-5deg); + } + 100% { + transform: rotateY(-10deg) rotateX(-3deg); + } +} + +.phone { + width: 100%; + height: 100%; + position: relative; + transform: rotateY(-10deg) rotateX(-3deg); + animation: drift-3d 30s infinite; +} diff --git a/web/src/pages/HomePage.tsx b/web/src/pages/HomePage.tsx index 0b4d6d71..308ea3d4 100644 --- a/web/src/pages/HomePage.tsx +++ b/web/src/pages/HomePage.tsx @@ -1,11 +1,13 @@ import { AppsGrid } from '@/components/AppsGrid.jsx'; import { UserMenu } from '@/components/auth/UserMenu.js'; +import { AppDemo } from '@/components/promo/AppDemo.jsx'; import { PageContent, PageFixedArea, PageRoot, } from '@a-type/ui/components/layouts'; import { P } from '@a-type/ui/components/typography'; +import { apps } from '@biscuits/apps'; import { Link } from '@verdant-web/react-router'; import classNames from 'classnames'; import { Suspense, lazy } from 'react'; @@ -40,7 +42,7 @@ export default function HomePage() {

Scratch-made apps @@ -53,7 +55,10 @@ export default function HomePage() { forever; no ads, no tracking. Learn how.

- + {/* */} + {apps.map((app, index) => ( + + ))} );