Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
53c176c
Remove animation and refactor the page
tristantr Dec 22, 2025
0adcd33
Align vertically the content
tristantr Dec 22, 2025
d1c5db6
Replace loattie
tristantr Dec 22, 2025
90343ce
Add benchmarks animation to deploy at scale card
tristantr Dec 22, 2025
8884db4
Update Deploy at scale href to add benchmarks
tristantr Dec 22, 2025
2fd1f2b
Remove sections from homepage
tristantr Dec 22, 2025
5e7913b
New wordings
tristantr Dec 22, 2025
a94ea62
Align mobile version to desktop
tristantr Dec 23, 2025
4db481a
Add loattie performance for mobile version
tristantr Dec 23, 2025
e1148c1
Add Datadog-like product dropdowns
tristantr Dec 23, 2025
2de0ccd
Change benchmarkes charts by performance loattie
tristantr Dec 23, 2025
e3a0576
Nits
tristantr Dec 23, 2025
76445bd
Nits
tristantr Dec 23, 2025
585e2aa
Comment Video section
tristantr Dec 23, 2025
b7cff83
Improve wordings of Product section
tristantr Dec 23, 2025
45ad23c
Improve organization
tristantr Dec 23, 2025
59a3c37
Add Core principles section
tristantr Dec 23, 2025
ee6002c
Fix loatie
tristantr Dec 23, 2025
8acde99
Fix case study button
tristantr Dec 23, 2025
26a67e9
Remove accordion
tristantr Dec 24, 2025
30511f8
Add animation
tristantr Dec 24, 2025
5580a23
Add animation in Develop and Iterate with instand feedback
tristantr Dec 24, 2025
090f254
Fix title font
tristantr Dec 24, 2025
0aee985
Comment animation for now
tristantr Dec 24, 2025
d31c637
Improve wordings
tristantr Dec 24, 2025
94f5489
Improve animations
tristantr Jan 5, 2026
cc9951b
Improve wordings
tristantr Jan 5, 2026
38c2067
Add video for first card
tristantr Jan 6, 2026
d381c4d
Improve product video section
tristantr Jan 6, 2026
968ea0a
Nits
tristantr Jan 6, 2026
62b052b
Remove arrows
tristantr Jan 6, 2026
ada9f73
Align mobile section to desktop
tristantr Jan 6, 2026
2bcd43f
Add landing videos
tristantr Jan 7, 2026
2c7eb03
Add subtitles in each Build tabs
tristantr Jan 7, 2026
d792e4c
Improve core principles section
tristantr Jan 7, 2026
8600cd1
nits
tristantr Jan 7, 2026
9e63409
Fix testimonial cards on mobile version
tristantr Jan 7, 2026
e2ee0bb
Improve wordings
tristantr Jan 7, 2026
d798041
Fix lottie animation
tristantr Jan 7, 2026
37fe674
Add autoplay to all animations in core concepts
tristantr Jan 7, 2026
eba5b32
Change videos
tristantr Jan 8, 2026
6dd65c2
Better wording
tristantr Jan 8, 2026
1b1e9d5
Better wording
tristantr Jan 8, 2026
95c935e
Align mobile version
tristantr Jan 8, 2026
5cb5fbe
Nits
tristantr Jan 8, 2026
adf2090
Add new video
tristantr Jan 9, 2026
623d9ea
Remove dead code
tristantr Jan 9, 2026
73bcd48
Align wordings
tristantr Jan 9, 2026
20d6871
Improve UX of videos
tristantr Jan 9, 2026
1e14378
Fix
tristantr Jan 9, 2026
7ae68fd
Improve wordings
tristantr Jan 9, 2026
08b9e1b
Improve wording
tristantr Jan 9, 2026
abe5e2d
Nits
tristantr Jan 9, 2026
c99e724
Fix link
tristantr Jan 9, 2026
52af021
Fix too much motion loatties
tristantr Jan 12, 2026
b3ce45f
Replace mp4 by webm
tristantr Jan 12, 2026
d56b93d
Change monitoring video to webm
tristantr Jan 12, 2026
4b4c83e
Remove glitches for tab videos
tristantr Jan 12, 2026
ee9394b
Improve wording
tristantr Jan 12, 2026
9e22993
Temporary commit
tristantr Jan 13, 2026
81fee53
Improve videos
tristantr Jan 14, 2026
931036a
Improve videos
tristantr Jan 15, 2026
1a218cd
Improve videos and remove data video
tristantr Jan 15, 2026
4c27508
Add local dev in Build section
tristantr Jan 15, 2026
a921dc6
Change landing structure
tristantr Jan 15, 2026
fbf38cd
Improve wordings
tristantr Jan 15, 2026
ac29481
Nits
tristantr Jan 15, 2026
0abacf4
Improve title sizes
tristantr Jan 15, 2026
c6a79e6
Add Youtube videos
tristantr Jan 15, 2026
098190f
Compress App video
tristantr Jan 15, 2026
e9b652f
Merge branch 'main' into tl/build-review-deploy-monitor-section
tristantr Jan 15, 2026
5f962ef
The nittest of the nits
tristantr Jan 15, 2026
3e02469
Hide Products dropdown while I improve the section
tristantr Jan 15, 2026
92f8a47
update
rubenfiszel Jan 15, 2026
1d93142
update
rubenfiszel Jan 15, 2026
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
15 changes: 15 additions & 0 deletions src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -596,4 +596,19 @@ div.testimonials a:hover .wm-name {

video:fullscreen {
object-fit: contain !important;
}

/* Improve readability of BenchmarkVisualization chart text */
.benchmark-chart-container canvas {
filter: brightness(1.2) contrast(1.1);
}

.benchmark-chart-container[data-theme="dark"] {
--chart-text-color: #ffffff;
--chart-axis-color: #e5e7eb;
}

.benchmark-chart-container[data-theme="light"] {
--chart-text-color: #1f2937;
--chart-axis-color: #4b5563;
}
2 changes: 1 addition & 1 deletion src/landing/AppAnimation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export default function AppAnimation({ active, only }) {
variant5: {
top: 360,
left: 300,
text: 'Build complex apps with our 50+ atomic components, and add code only when needed.',
//text: 'Build complex apps with our 50+ atomic components, and add code only when needed.',
displayArrow: false
}
};
Expand Down
113 changes: 32 additions & 81 deletions src/landing/CallToAction.jsx
Original file line number Diff line number Diff line change
@@ -1,85 +1,36 @@
import React, { useState } from 'react';
import { useColorMode } from '@docusaurus/theme-common';
import { ArrowRight } from 'lucide-react';
import BookDemoModal from '../components/BookDemoModal';

export default function CallToAction({ color }) {
const { colorMode } = useColorMode();
const [bookDemoOpen, setBookDemoOpen] = useState(false);
export default function CallToAction() {
const [bookDemoOpen, setBookDemoOpen] = useState(false);

const colorMap = {
blue: {
light: '#bfdbfe',
dark: '#3b82f6'
},
orange: {
light: '#fb923c',
dark: '#7c2d12'
},
green: {
light: '#bbf7d0',
dark: '#10b981'
}
};

const c = colorMap[color ?? 'blue'][colorMode];

return (
<div className="w-full py-16">
<div className="">
<div className="relative isolate overflow-hidden bg-gray-900 dark:bg-white px-6 py-24 text-center rounded-3xl sm:px-16">
<h2 className="mx-auto max-w-4xl text-4xl font-bold tracking-tight text-white dark:text-gray-900">
Build endpoints, workflows & ETLs, UIs with code only where it matters
</h2>
<p className="mx-auto mt-6 max-w-4xl text-lg leading-8 text-gray-300 dark:text-gray-600">
Get started building your internal tool in under 10 minutes
</p>
<div className="mt-10 flex items-center justify-center gap-x-6">
<a
href="https://app.windmill.dev/user/login"
onClick={() => window.plausible('try-cloud')}
data-analytics='"try-cloud"'
className="rounded-md bg-white px-3.5 py-1.5 text-base hover:text-blue-500 font-semibold leading-7 text-gray-900 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white !no-underline"
rel="nofollow"
>
Get started for free
</a>
<button
onClick={() => setBookDemoOpen(true)}
className="text-base font-semibold leading-7 text-white !no-underline dark:text-gray-900 cursor-pointer bg-transparent border-none"
>
Schedule a demo <span aria-hidden="true">→</span>
</button>
</div>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1024 1024"
className="absolute top-1/2 left-1/2 -z-10 h-[64rem] w-[64rem] -translate-x-1/2"
aria-hidden="true"
>
<circle
cx={512}
cy={512}
r={512}
fill="url(#827591b1-ce8c-4110-b064-7cb85a0b12171)"
fillOpacity="0.7"
/>
<defs>
<radialGradient
id="827591b1-ce8c-4110-b064-7cb85a0b12171"
cx={0}
cy={0}
r={1}
gradientUnits="userSpaceOnUse"
gradientTransform="translate(512 512) rotate(90) scale(512)"
>
<stop stopColor={c} />
<stop offset={1} stopColor={c} stopOpacity={0} />
</radialGradient>
</defs>
</svg>
</div>
</div>
<BookDemoModal open={bookDemoOpen} setOpen={setBookDemoOpen} />
</div>
);
}
return (
<div className="w-full">
<div className="dark:bg-gray-900 bg-gray-50 px-8 sm:px-12 py-10 text-center rounded-xl">
<h2 className="mx-auto max-w-4xl text-3xl font-bold tracking-tight text-transparent bg-clip-text bg-gradient-to-br from-blue-500 to-blue-700 dark:from-blue-400 dark:to-blue-600 sm:text-4xl">
Start building with Windmill
</h2>
<div className="mt-6 flex flex-col sm:flex-row items-center justify-center gap-4">
<a
href="https://app.windmill.dev/user/login"
onClick={() => window.plausible('try-cloud')}
data-analytics='"try-cloud"'
className="rounded-lg bg-blue-600 hover:bg-blue-700 px-6 py-3 text-base font-semibold text-white shadow-sm transition-colors !no-underline"
rel="nofollow"
>
Get started for free
</a>
<button
onClick={() => setBookDemoOpen(true)}
className="group flex items-center gap-2 text-base font-semibold text-gray-900 dark:text-white bg-transparent border-none cursor-pointer hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
>
Schedule a demo
<ArrowRight size={20} className="group-hover:translate-x-1 transition-transform" />
</button>
</div>
</div>
<BookDemoModal open={bookDemoOpen} setOpen={setBookDemoOpen} />
</div>
);
}
133 changes: 133 additions & 0 deletions src/landing/CombinedAnimation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import React, { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';

export default function CombinedAnimation() {
const [currentIndex, setCurrentIndex] = useState(0);

const images = [
{
id: 'script',
src: '/illustrations/animscripts.png',
alt: 'VS Code editor with test panel and execution results',
label: 'Scripts',
subtitle: 'Write scripts in 20+ languages (Python, TS, Go, Bash...)'
},
{
id: 'flow',
src: '/illustrations/animflows.png',
alt: 'Flow diagram with execution logs and performance metrics',
label: 'Flows',
subtitle: 'Orchestrate scripts into scalable workflows'
},
{
id: 'app',
src: '/illustrations/animapps.png',
alt: 'App builder with button, table, and code editor',
label: 'Apps',
subtitle: 'Generate production-ready frontends with AI'
}
];

// Auto-switch every 4 seconds
useEffect(() => {
const interval = setInterval(() => {
setDirection(1); // Always forward for auto-advance
setCurrentIndex((prev) => (prev + 1) % images.length);
}, 4000);

return () => clearInterval(interval);
}, [images.length]);

const slideVariants = {
enter: (direction: number) => ({
x: direction > 0 ? '100%' : '-100%',
opacity: 0
}),
center: {
x: 0,
opacity: 1
},
exit: (direction: number) => ({
x: direction > 0 ? '-100%' : '100%',
opacity: 0
})
};

const [direction, setDirection] = useState(0);

const goToSlide = (index: number) => {
const newDirection = index > currentIndex ? 1 : -1;
setDirection(newDirection);
setCurrentIndex(index);
};

return (
<div className="relative w-full overflow-hidden rounded-lg px-0">
{/* Title and Subtitle - Hidden on mobile, visible on desktop */}
<div className="hidden md:block text-center">
<AnimatePresence mode="wait">
<motion.div
key={currentIndex}
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 10 }}
transition={{ duration: 0.3 }}
>
<div className="text-lg md:text-xl font-semibold text-gray-900 dark:text-white">
{images[currentIndex].label}
</div>
<div className="text-sm md:text-base text-gray-600 dark:text-gray-400 mt-1">
{images[currentIndex].subtitle}
</div>
</motion.div>
</AnimatePresence>
</div>
{/* Image container */}
<div className="relative w-full min-h-[250px] md:min-h-[400px]">
<AnimatePresence mode="wait" custom={direction}>
<motion.div
key={currentIndex}
custom={direction}
variants={slideVariants}
initial="enter"
animate="center"
exit="exit"
transition={{
x: { type: 'spring', stiffness: 300, damping: 30 },
opacity: { duration: 0.2 }
}}
className="absolute inset-0 w-full flex items-center justify-center"
>
<img
src={images[currentIndex].src}
alt={images[currentIndex].alt}
className="w-full h-auto max-w-full object-contain rounded-lg"
loading="lazy"
onError={(e) => {
console.error('Failed to load image:', images[currentIndex].src);
(e.target as HTMLImageElement).style.display = 'none';
}}
/>
</motion.div>
</AnimatePresence>
</div>

{/* Navigation dots */}
<div className="absolute bottom-2 md:bottom-4 left-1/2 transform -translate-x-1/2 flex gap-2 z-10">
{images.map((_, index) => (
<button
key={index}
onClick={() => goToSlide(index)}
className={`h-1.5 md:h-2 rounded-full transition-all ${
index === currentIndex
? 'w-6 md:w-8 bg-white dark:bg-gray-200'
: 'w-1.5 md:w-2 bg-white/50 dark:bg-gray-500/50 hover:bg-white/75 dark:hover:bg-gray-400/75'
}`}
aria-label={`Go to ${images[index].label}`}
/>
))}
</div>
</div>
);
}

109 changes: 109 additions & 0 deletions src/landing/CorePrinciple.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import React from 'react';
import LandingSection from './LandingSection';
import { ArrowRight } from 'lucide-react';
import BrowserOnly from '@docusaurus/BrowserOnly';
// @ts-ignore
import polyGlott from '/illustrations/polyglot.json';
// @ts-ignore
import secrets from '/illustrations/secrets.json';
// @ts-ignore
import thirdparty from '/illustrations/thirdparty.json';

// Client-only component that renders a static frame of a Lottie animation
function StaticLottie({ animationData }: { animationData: unknown }) {
const { useLottie } = require('lottie-react');
const { View, goToAndStop, getDuration } = useLottie({
animationData,
loop: false,
autoplay: false
});

React.useEffect(() => {
// Go to 90% of the animation
const totalFrames = getDuration(true);
if (totalFrames > 0) {
goToAndStop(Math.floor(totalFrames * 0.90), true);
}
}, [goToAndStop, getDuration]);

return View;
}

interface FeatureCardProps {
title: string;
description: string;
actionLink: string;
actionUrl?: string;
lottieData?: unknown;
}

function FeatureCard({ title, description, actionLink, actionUrl, lottieData }: FeatureCardProps) {
return (
<div className="flex flex-col h-full rounded-lg bg-gray-50 dark:bg-gray-800/50 backdrop-blur-sm p-6 shadow-lg border border-gray-200 dark:border-gray-700/50 group">
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-3">{title}</h3>
<p className="text-gray-600 dark:text-gray-300 mb-4 flex-grow text-base leading-relaxed">
{description}
</p>
<a
href={actionUrl || '#'}
className="text-sm text-blue-600 dark:text-blue-400 flex flex-row items-center gap-2 group-hover:ml-2 transition-all mb-4 hover:text-blue-700 dark:hover:text-blue-300"
target={actionUrl && actionUrl.startsWith('http') ? '_blank' : undefined}
rel={actionUrl && actionUrl.startsWith('http') ? 'noopener noreferrer' : undefined}
>
{actionLink}
<ArrowRight size={24} />
</a>
{lottieData && (
<div className="mt-auto bg-gray-100 dark:bg-gray-700/80 rounded-md p-4 min-h-[180px] flex items-center justify-center overflow-hidden">
<div className="w-full h-full flex items-center justify-center rounded-md">
<BrowserOnly fallback={<div className="w-full h-full" />}>
{() => <StaticLottie animationData={lottieData} />}
</BrowserOnly>
</div>
</div>
)}
</div>
);
}

export default function CorePrinciple() {
return (
<LandingSection bgClass="py-16">
<div className="w-full">
<div className="mb-12 text-left">
<h1 className="tracking-tight leading-tight text-left font-bold text-transparent bg-clip-text bg-gradient-to-br from-blue-500 to-blue-700 dark:from-blue-400 dark:to-blue-600">
Our core principles
</h1>
<span className="text-lg text-gray-700 max-w-3xl dark:text-gray-200">
The foundational beliefs that guide how we build Windmill.
</span>
</div>

{/* 3 cards in a row */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 lg:gap-8">
<FeatureCard
title="Avoid vendor lock-in"
description="Open source and self-hostable. Your code, your data, your infrastructure. Deploy anywhere—cloud, on-premises, or air-gapped."
actionLink="View on GitHub"
actionUrl="https://github.com/windmill-labs/"
lottieData={polyGlott}
/>
<FeatureCard
title="Seamless enterprise integration"
description="Connect to databases (PostgreSQL, MySQL, Snowflake), cloud platforms (AWS, Azure, GCP), message queues (Kafka, SQS, NATS), and 100+ APIs."
actionLink="Explore integrations"
actionUrl="https://www.windmill.dev/docs/integrations/integrations_on_windmill"
lottieData={thirdparty}
/>
<FeatureCard
title="Enterprise-grade security"
description="Granular RBAC, SSO, Secret Management, and comprehensive Audit Logs. Deploy in regulated industries with air-gapped support."
actionLink="Explore enterprise features"
actionUrl="https://www.windmill.dev/docs/misc/enterprise_onboarding"
lottieData={secrets}
/>
</div>
</div>
</LandingSection>
);
}
Loading