Skip to content

chore: new landing page #2369

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 0 additions & 19 deletions site/src/app/(v2)/(framer)/page.tsx

This file was deleted.

69 changes: 69 additions & 0 deletions site/src/app/(v2)/(marketing)/CommandCenterSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"use client";

import { useState } from "react";
import { Icon, faCheck } from "@rivet-gg/icons";

// Command Center section
export const CommandCenterSection = () => {
const [activeTab, setActiveTab] = useState("monitoring");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: activeTab state is set but no content changes based on tab selection


const tabs = [
{ id: "monitoring", title: "Monitoring", },
{ id: "logs", title: "Logs", },
{ id: "local-dev", title: "Local Dev", },
{ id: "collaboration", title: "Collaboration", },
];

const features = [
"Live Logs", "Crash Reporting", "Log Retention", "Error Tracing", "Performance Metrics", "Alerts"
];

return (
<div className="mx-auto max-w-7xl px-6 py-28 lg:py-44 lg:px-8 mt-16">
<div className="text-center mb-12">
<h2 className="text-3xl font-bold tracking-tight text-white">The command center your backend is missing</h2>
<p className="mt-4 text-lg text-white/70">Complete visibility and control over your serverless infrastructure</p>
</div>

<div className="flex justify-center mb-12">
<div className="inline-flex space-x-1">
{tabs.map((tab) => (
<button
key={tab.id}
className={`px-6 py-3 rounded-md text-base font-medium transition-all duration-200 border ${
activeTab === tab.id
? "bg-zinc-900 text-white border-zinc-700"
: "text-white/60 hover:text-white hover:bg-black/10 border-transparent"
}`}
onClick={() => setActiveTab(tab.id)}
>
{tab.title}
</button>
))}
</div>
</div>

<div className="flex justify-center mb-12">
<div className="flex space-x-12">
{features.map((feature, index) => (
<div key={index} className="flex items-center">
<div className="text-white/40 mr-2">
<Icon icon={faCheck} className="text-sm" />
</div>
<span className="text-sm text-white/80">{feature}</span>
</div>
))}
</div>
Comment on lines +47 to +56
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: features list lacks mobile responsiveness - will overflow on small screens

Suggested change
<div className="flex space-x-12">
{features.map((feature, index) => (
<div key={index} className="flex items-center">
<div className="text-white/40 mr-2">
<Icon icon={faCheck} className="text-sm" />
</div>
<span className="text-sm text-white/80">{feature}</span>
</div>
))}
</div>
<div className="flex flex-wrap gap-4 justify-center">
{features.map((feature, index) => (
<div key={index} className="flex items-center">
<div className="text-white/40 mr-2">
<Icon icon={faCheck} className="text-sm" />
</div>
<span className="text-sm text-white/80">{feature}</span>
</div>
))}
</div>

</div>

<div className="flex justify-center">
<div className="w-full max-w-4xl h-[480px] bg-zinc-900 border border-white/5 rounded-xl overflow-hidden">
{/* Placeholder for hub screenshot */}
<div className="w-full h-full flex items-center justify-center text-white/40">
Hub Screenshot Placeholder
</div>
</div>
</div>
</div>
);
};
114 changes: 114 additions & 0 deletions site/src/app/(v2)/(marketing)/CommunitySection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
"use client";

import Link from "next/link";
import { Icon, faDiscord, faGithub, faTwitter, faBluesky } from "@rivet-gg/icons";

// Community section
export const CommunitySection = () => {
const platforms = [
{ name: "Discord", icon: faDiscord, href: "https://discord.gg/rivet" },
{ name: "Discussions", icon: faGithub, href: "https://github.com/rivet-gg/discussions" },
{ name: "X", icon: faTwitter, href: "https://x.com/rivet_gg" },
{ name: "Bluesky", icon: faBluesky, href: "https://bsky.app/profile/rivet.gg" }
];

// Tweets for each column
const columnTweets = [
// Column 1
[
{
user: "Jane Doe",
handle: "@janedoe",
content: "Just deployed my first stateful job with @rivet_gg and I'm blown away by how simple it was. The documentation is excellent!"
},
{
user: "Mike Williams",
handle: "@mikew",
content: "As someone new to serverless, Rivet made the learning curve much smoother. Their tutorials are super straightforward."
},
{
user: "Sara Chen",
handle: "@sarac",
content: "Been using @rivet_gg for our AI agents and the performance is incredible. Self-hosting was a breeze too!"
}
],
// Column 2
[
{
user: "John Smith",
handle: "@johnsmith",
content: "Rivet has completely changed how we handle our functions. Our team's productivity has doubled since we made the switch."
},
{
user: "Emma Rodriguez",
handle: "@emmar",
content: "The desktop sandbox feature in @rivet_gg is a game changer for our GUI-based applications. Nothing else comes close."
},
{
user: "David Kim",
handle: "@davidk",
content: "Our entire backend is running on Rivet now. The monitoring tools make my job 10x easier as a DevOps engineer."
}
],
// Column 3
[
{
user: "Alex Johnson",
handle: "@alexj",
content: "I've tried all the serverless platforms out there, and @rivet_gg is hands down the best one for my needs. The open-source aspect sealed the deal for me."
},
{
user: "Taylor Morgan",
handle: "@taylorm",
content: "Moving from AWS to self-hosted @rivet_gg cut our costs by 70% while improving performance. Best decision we made this year."
},
{
user: "Jordan Lee",
handle: "@jordanl",
content: "The Rivet community is amazing! Got help with my implementation within minutes of posting a question."
}
]
];

return (
<div className="mx-auto max-w-7xl px-6 py-28 lg:py-44 lg:px-8 mt-16">
<div className="text-center mb-10">
<h2 className="text-3xl font-bold tracking-tight text-white">Join the community</h2>
<p className="mt-4 text-lg text-white/70">Connect with thousands of developers building with Rivet</p>
</div>

<div className="flex justify-center space-x-3 mb-16">
{platforms.map((platform, index) => (
<Link key={index} href={platform.href} className="group">
<div className="flex items-center justify-center h-10 px-5 rounded-md border border-zinc-700 bg-zinc-900 group-hover:bg-zinc-800 group-hover:border-zinc-600 transition-all">
<Icon icon={platform.icon} className="text-white/60 group-hover:text-white/90 mr-2 transition-colors" />
<span className="text-sm text-white/60 group-hover:text-white/90 transition-colors">{platform.name}</span>
</div>
</Link>
Comment on lines +81 to +87
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Missing rel="noopener noreferrer" for external links and target="_blank" attributes for better security and UX

Suggested change
{platforms.map((platform, index) => (
<Link key={index} href={platform.href} className="group">
<div className="flex items-center justify-center h-10 px-5 rounded-md border border-zinc-700 bg-zinc-900 group-hover:bg-zinc-800 group-hover:border-zinc-600 transition-all">
<Icon icon={platform.icon} className="text-white/60 group-hover:text-white/90 mr-2 transition-colors" />
<span className="text-sm text-white/60 group-hover:text-white/90 transition-colors">{platform.name}</span>
</div>
</Link>
{platforms.map((platform, index) => (
<Link key={index} href={platform.href} target="_blank" rel="noopener noreferrer" className="group">
<div className="flex items-center justify-center h-10 px-5 rounded-md border border-zinc-700 bg-zinc-900 group-hover:bg-zinc-800 group-hover:border-zinc-600 transition-all">
<Icon icon={platform.icon} className="text-white/60 group-hover:text-white/90 mr-2 transition-colors" />
<span className="text-sm text-white/60 group-hover:text-white/90 transition-colors">{platform.name}</span>
</div>
</Link>

))}
</div>

<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{columnTweets.map((column, columnIndex) => (
<div key={columnIndex} className="flex flex-col space-y-6">
{column.map((tweet, tweetIndex) => (
<div
key={`${columnIndex}-${tweetIndex}`}
className="rounded-xl p-6 bg-black/20 border border-white/5 flex flex-col hover:bg-black/30 hover:border-white/10 transition-all"
>
<div className="flex items-center mb-4">
<div className="w-10 h-10 rounded-full bg-zinc-700 mr-3"></div>
<div>
<div className="text-white font-medium">{tweet.user}</div>
<div className="text-white/50 text-sm">{tweet.handle}</div>
</div>
</div>
<p className="text-white/80">{tweet.content}</p>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Tweet content should have a role="article" for better screen reader support

</div>
))}
</div>
))}
</div>
</div>
);
};
33 changes: 33 additions & 0 deletions site/src/app/(v2)/(marketing)/CopyCommand.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"use client";

import { Icon, faCopy, faCheck } from "@rivet-gg/icons";
import { useState } from "react";

// Copy command component with clipboard functionality
export const CopyCommand = ({ command }: { command: string }) => {
const [copied, setCopied] = useState(false);

const handleCopy = () => {
// Copy the command without the $ symbol
navigator.clipboard.writeText(command);
setCopied(true);
setTimeout(() => setCopied(false), 1000);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Consider using useEffect cleanup to clear timeout on unmount to prevent memory leaks.

};

return (
<div
onClick={handleCopy}
className="inline-flex items-center bg-black/40 rounded-md border border-white/10 px-4 py-2.5 font-mono text-sm group relative cursor-pointer active:scale-[0.98] active:bg-black/60 transition-all"
Comment on lines +18 to +20
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Use button element instead of div for better accessibility. Add role="button" and keyboard handlers (onKeyDown) to support keyboard interaction.

Suggested change
<div
onClick={handleCopy}
className="inline-flex items-center bg-black/40 rounded-md border border-white/10 px-4 py-2.5 font-mono text-sm group relative cursor-pointer active:scale-[0.98] active:bg-black/60 transition-all"
<button
onClick={handleCopy}
onKeyDown={e => e.key === 'Enter' && handleCopy()}
className="inline-flex items-center bg-black/40 rounded-md border border-white/10 px-4 py-2.5 font-mono text-sm group relative cursor-pointer active:scale-[0.98] active:bg-black/60 transition-all"

>
<span className="text-gray-500 mr-2 font-mono">$</span>
<span className="text-white/90 font-mono">{command}</span>
<div
className="ml-3 text-gray-400 group-hover:text-[#FF5C00] transition-colors"
aria-label={copied ? "Copied!" : "Copy to clipboard"}
>
<Icon icon={copied ? faCheck : faCopy} className={`${copied ? "text-[#FF5C00]" : ""} transition-all`} />
</div>
<div className="absolute inset-0 bg-white/5 opacity-0 group-hover:opacity-100 group-active:opacity-0 transition-opacity rounded-md pointer-events-none"></div>
</div>
);
};
43 changes: 43 additions & 0 deletions site/src/app/(v2)/(marketing)/CtaSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use client";

import Link from "next/link";
import { Button } from "@rivet-gg/components";
import { Icon, faArrowRight } from "@rivet-gg/icons";

// CTA section
export const CtaSection = () => {
return (
<div className="mx-auto max-w-7xl px-6 py-36 lg:py-52 lg:px-8 border-t border-white/5 mt-24">
<div className="text-center">
<h2 className="text-4xl font-bold tracking-tight text-white">Get building today</h2>
<p className="mt-6 text-xl text-white/70 max-w-2xl mx-auto">
Start for free, no credit card required. Deploy your first serverless project in minutes.
</p>

<div className="mt-12 flex items-center justify-center gap-x-6">
<Button
size="lg"
asChild
className="px-4 pr-6 py-3 text-base bg-gradient-to-b from-[#FF5C00] to-[#FF5C00]/90 border border-[#FF5C00]/30 hover:border-[#FF5C00]/60 transition-all duration-200 group"
>
<Link href="#deploy" className="flex items-center justify-center relative">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: href='#deploy' points to a non-existent anchor. Should likely point to an actual deployment page route

<span>Deploy in 1 Minute</span>
<Icon icon={faArrowRight} className="absolute right-2 text-sm opacity-0 group-hover:opacity-100 group-hover:translate-x-1 transition-all duration-200" />
</Link>
</Button>
<Button
variant="outline"
size="lg"
asChild
className="px-4 pr-6 py-3 text-base border-white/10 hover:border-white/30 transition-all duration-200 group"
>
<Link href="#demo" className="flex items-center justify-center relative">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: href='#demo' points to a non-existent anchor. Should likely point to an actual demo booking page route

<span>Book Demo</span>
<Icon icon={faArrowRight} className="absolute right-2 text-sm opacity-0 group-hover:opacity-100 group-hover:translate-x-1 transition-all duration-200" />
</Link>
</Button>
</div>
</div>
</div>
);
};
93 changes: 93 additions & 0 deletions site/src/app/(v2)/(marketing)/TutorialsSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"use client";

import Link from "next/link";
import { Icon, faCode, faLayerGroup, faTerminal, faDesktop, faListCheck, faArrowsToCircle, faArrowRight, faDatabase } from "@rivet-gg/icons";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: faListCheck is imported but never used in the component

Suggested change
import { Icon, faCode, faLayerGroup, faTerminal, faDesktop, faListCheck, faArrowsToCircle, faArrowRight, faDatabase } from "@rivet-gg/icons";
import { Icon, faCode, faLayerGroup, faTerminal, faDesktop, faArrowsToCircle, faArrowRight, faDatabase } from "@rivet-gg/icons";


// Tutorials section
export const TutorialsSection = () => {
const tutorials = [
{
title: "Deploy your first function",
description: "Get started with serverless functions in minutes",
icons: [faCode],
href: "/docs/tutorials/first-function",
useCases: ["APIs", "Webhooks", "Edge computing"]
},
{
title: "Create a stateful actor",
description: "Build services that maintain state between requests",
icons: [faLayerGroup],
href: "/docs/tutorials/stateful-actor",
useCases: ["AI agents", "Stateful workers", "Long-running processes"]
},
{
title: "Build a workflow",
description: "Orchestrate complex multi-step processes",
icons: [faArrowsToCircle],
href: "/docs/tutorials/workflows",
useCases: ["Multi-agent systems", "Business logic", "ETL pipelines"]
},
{
title: "Run AI generated code in a sandbox",
description: "Execute untrusted code safely with isolation",
icons: [faTerminal],
href: "/docs/tutorials/ai-sandbox",
useCases: ["LLM code execution", "User code execution", "AI agents"]
},
{
title: "Access desktop sandbox",
description: "Run GUI applications in an isolated environment",
icons: [faDesktop],
href: "/docs/tutorials/desktop-sandbox",
useCases: ["Remote desktops", "Browser automation", "Visual apps"]
},
{
title: "Store agent memory",
description: "Persist and retrieve AI agent context and knowledge",
icons: [faDatabase],
href: "/docs/tutorials/agent-memory",
useCases: ["RAG", "Vector embeddings", "AI agent state"]
}
];

return (
<div className="mx-auto max-w-7xl px-6 py-28 lg:py-44 lg:px-8 mt-16">
<div className="text-center mb-12">
<h2 className="text-3xl font-bold tracking-tight text-white">Start building in seconds</h2>
<p className="mt-4 text-lg text-white/70">Follow our step-by-step tutorials to deploy your first project quickly</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{tutorials.map((tutorial, index) => (
<Link key={index} href={tutorial.href} className="group">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: using array index as key could cause issues with React reconciliation if tutorials are reordered - consider using a unique id

<div className="rounded-xl h-[280px] bg-[#121212] group-hover:bg-zinc-800/90 border border-white/5 group-hover:border-white/20 shadow-sm transition-all duration-200 flex flex-col overflow-hidden">
{/* Top section with icons */}
<div className="bg-black/40 p-4 flex items-center justify-center h-[120px] w-full">
<div className="flex space-x-4">
{tutorial.icons.map((icon, iconIndex) => (
<div key={iconIndex} className="flex items-center justify-center w-14 h-14">
<Icon
icon={icon}
className="text-4xl text-white/50 group-hover:text-[#FF5C00] transition-colors duration-200"
/>
</div>
))}
</div>
</div>

{/* Bottom section with content */}
<div className="p-5 flex flex-col flex-1">
<h3 className="text-xl font-semibold text-white mb-2">{tutorial.title}</h3>
<p className="text-white/60 text-sm">{tutorial.description}</p>

<div className="flex items-center mt-auto pt-3 text-[#FF5C00] opacity-0 group-hover:opacity-100 transition-opacity">
<span className="text-sm font-medium">View tutorial</span>
<Icon icon={faArrowRight} className="ml-2 text-xs group-hover:translate-x-0.5 transition-all" />
</div>
</div>
</div>
</Link>
))}
</div>
</div>
);
};
10 changes: 10 additions & 0 deletions site/src/app/(v2)/(marketing)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { FancyHeader } from "@/components/v2/FancyHeader";

export default function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<FancyHeader />
{children}
</>
);
}
Loading
Loading