From 3efd23a258a937f411803b8de9a93d7e3852d2be Mon Sep 17 00:00:00 2001 From: tristantr Date: Tue, 27 Jan 2026 10:26:26 +0100 Subject: [PATCH 01/20] Start public apps section --- src/landing/ExampleCard.tsx | 91 ++++++++++++ src/landing/ExampleLayout.tsx | 169 +++++++++++++++++++++++ src/landing/LandingHeader.jsx | 2 +- src/pages/examples/ai-agent.jsx | 42 ++++++ src/pages/examples/customer-support.jsx | 42 ++++++ src/pages/examples/data-pipeline.jsx | 42 ++++++ src/pages/examples/index.jsx | 116 ++++++++++++++++ src/pages/examples/payment-dashboard.jsx | 42 ++++++ 8 files changed, 545 insertions(+), 1 deletion(-) create mode 100644 src/landing/ExampleCard.tsx create mode 100644 src/landing/ExampleLayout.tsx create mode 100644 src/pages/examples/ai-agent.jsx create mode 100644 src/pages/examples/customer-support.jsx create mode 100644 src/pages/examples/data-pipeline.jsx create mode 100644 src/pages/examples/index.jsx create mode 100644 src/pages/examples/payment-dashboard.jsx diff --git a/src/landing/ExampleCard.tsx b/src/landing/ExampleCard.tsx new file mode 100644 index 000000000..a1b1dc579 --- /dev/null +++ b/src/landing/ExampleCard.tsx @@ -0,0 +1,91 @@ +import React from 'react'; +import { motion } from 'framer-motion'; +import Link from '@docusaurus/Link'; + +interface ExampleCardProps { + title: string; + description: string; + href: string; + thumbnail?: string; + color?: 'blue' | 'teal' | 'orange' | 'purple'; +} + +export default function ExampleCard({ + title, + description, + href, + thumbnail, + color = 'blue' +}: ExampleCardProps) { + const gradients = { + blue: 'from-blue-500/20 to-blue-600/20', + teal: 'from-teal-500/20 to-teal-600/20', + orange: 'from-orange-500/20 to-orange-600/20', + purple: 'from-purple-500/20 to-purple-600/20' + }; + + const borders = { + blue: 'hover:border-blue-500', + teal: 'hover:border-teal-500', + orange: 'hover:border-orange-500', + purple: 'hover:border-purple-500' + }; + + const textGradients = { + blue: 'from-blue-600 to-blue-800 dark:from-blue-300 dark:to-blue-500', + teal: 'from-teal-600 to-teal-800 dark:from-teal-300 dark:to-teal-500', + orange: 'from-orange-600 to-orange-800 dark:from-orange-300 dark:to-orange-500', + purple: 'from-purple-600 to-purple-800 dark:from-purple-300 dark:to-purple-500' + }; + + return ( + + + {/* Thumbnail */} +
+ {thumbnail ? ( + {title} + ) : ( +
+ Preview +
+ )} +
+ + {/* Content */} +
+

+ {title} +

+

+ {description} +

+
+
+ + ); +} diff --git a/src/landing/ExampleLayout.tsx b/src/landing/ExampleLayout.tsx new file mode 100644 index 000000000..d926fc11f --- /dev/null +++ b/src/landing/ExampleLayout.tsx @@ -0,0 +1,169 @@ +import React from 'react'; +import Head from '@docusaurus/Head'; +import Link from '@docusaurus/Link'; +import LayoutProvider from '@theme/Layout/Provider'; +import LandingHeader from './LandingHeader'; +import Footer from './Footer'; +import { motion } from 'framer-motion'; +import { ArrowLeftIcon } from '@heroicons/react/24/outline'; + +interface ExampleLayoutProps { + title: string; + description: string; + iframeUrl: string; + children?: React.ReactNode; +} + +export default function ExampleLayout({ + title, + description, + iframeUrl, + children +}: ExampleLayoutProps) { + return ( + +
+ + {title} | Examples | Windmill + + + + + + +
+
+ {/* Back link */} + + + + Back to examples + + + + {/* Main content */} +
+ {/* Sidebar */} + +
+

+ {title} +

+

+ {description} +

+ + {children} + +
+ + Try Windmill + +
+ + {/* Social share */} +
+

+ Share this example +

+ +
+
+
+ + {/* Iframe container */} + +
+ {/* App header bar */} +
+
+
+
+
+
+
+ {title} +
+
+ + {/* Iframe */} +
+ {iframeUrl ? ( +