Skip to content
Draft

moti3 #232

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
e88e0c0
gradiento animu
fedealvarezcampos Oct 20, 2025
c6d3131
reveal
fedealvarezcampos Oct 21, 2025
bab1c5c
motion
fedealvarezcampos Oct 21, 2025
6558147
nit steps
fedealvarezcampos Oct 21, 2025
bcec497
tag
fedealvarezcampos Oct 21, 2025
d839e2f
shader transition
fedealvarezcampos Oct 21, 2025
03f0209
motion
fedealvarezcampos Oct 21, 2025
717458d
motion, get version
fedealvarezcampos Oct 21, 2025
7ab8ece
motion
fedealvarezcampos Oct 21, 2025
9ac4bbd
motion
fedealvarezcampos Oct 21, 2025
74f7f22
motion
fedealvarezcampos Oct 21, 2025
f4c560f
motion
fedealvarezcampos Oct 21, 2025
2c90be1
bezi
fedealvarezcampos Oct 21, 2025
8c3c1bc
nit
fedealvarezcampos Oct 21, 2025
3ed1c67
nit tag
fedealvarezcampos Oct 21, 2025
2269001
Merge branch 'main' of github.com:basementstudio/xmcp into moti
fedealvarezcampos Oct 21, 2025
9c550ec
no card stagger
fedealvarezcampos Oct 21, 2025
f4b53a3
nit timin
fedealvarezcampos Oct 21, 2025
f49a539
noblur
fedealvarezcampos Oct 21, 2025
6919d15
anim changes
fedealvarezcampos Oct 22, 2025
ff5b5cf
anim changes
fedealvarezcampos Oct 22, 2025
de065f8
anim changes
fedealvarezcampos Oct 22, 2025
de6dbf0
nit
fedealvarezcampos Oct 22, 2025
b0e83cf
handle canvas fix
fedealvarezcampos Oct 22, 2025
44ac646
e
fedealvarezcampos Oct 22, 2025
e423b77
handle init fade
fedealvarezcampos Oct 22, 2025
8261b7d
handle nojs
fedealvarezcampos Oct 22, 2025
c990006
nit
fedealvarezcampos Oct 23, 2025
be82275
better handle step transition
fedealvarezcampos Oct 23, 2025
1d8b76c
pause steps when not in view
fedealvarezcampos Oct 23, 2025
1debe8a
nit
fedealvarezcampos Oct 23, 2025
275bd4d
merge
fedealvarezcampos Oct 28, 2025
c64cc97
fade buttons etc
fedealvarezcampos Oct 29, 2025
17b4c7e
fade buttons etc
fedealvarezcampos Oct 29, 2025
8f596a0
header anim
fedealvarezcampos Oct 29, 2025
4ddb9a1
merge
fedealvarezcampos Oct 29, 2025
5e641a6
nit
fedealvarezcampos Oct 29, 2025
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
10 changes: 3 additions & 7 deletions apps/website/app/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
type BlogPost,
} from "../../utils/blog";
import { BlogHero } from "../../components/blog/hero";
import { BlogCard } from "@/components/home/blog";
import { BlogCard } from "@/components/home/blog/client-index";
import { BlogHeroHeading } from "@/components/blog/index/hero-heading";

export const dynamic = "force-static";

Expand All @@ -28,12 +29,7 @@ export default function BlogPage() {
<main className="grid grid-cols-12 gap-[20px] max-w-[1200px] w-full mx-auto px-4">
<div className="col-span-full grid grid-cols-12 gap-y-8 py-8 md:py-16">
<div className="flex flex-col items-center justify-center max-w-[720px] w-full mx-auto gap-4 col-span-12 mb-8">
<h1 className="display text-center text-balance z-10 text-gradient">
Blog
</h1>
<p className="text-brand-neutral-100 text-base col-span-12 max-w-[650px] lg:col-span-5 mt-auto text-center">
Read the latest updates, guides, and insights about xmcp.
</p>
<BlogHeroHeading />
</div>

{featuredPost && <BlogHero featuredPost={featuredPost} />}
Expand Down
11 changes: 3 additions & 8 deletions apps/website/app/examples/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Metadata } from "next";
import { ExampleCardsList } from "../../components/examples/cards/list";
import { ExampleCardsList } from "@/components/examples/cards/list";
import { ExamplesHeroHeading } from "@/components/examples/cards/hero-heading";

export const dynamic = "force-static";

Expand All @@ -17,13 +18,7 @@ export default function ExamplesPage() {
<main className="grid grid-cols-12 gap-[20px] max-w-[1200px] w-full mx-auto px-4">
<div className="col-span-12 grid grid-cols-12 gap-[20px] py-8 md:py-16">
<div className="flex flex-col items-center justify-center max-w-[720px] w-full mx-auto gap-4 col-span-12 mb-8">
<h1 className="display text-center text-balance z-10 text-gradient">
Examples & templates
</h1>
<p className="text-brand-neutral-100 text-base col-span-12 max-w-[650px] lg:col-span-5 mt-auto text-center">
Quickstart guides and examples to get you started with xmcp with
real-world implementations and best practices.
</p>
<ExamplesHeroHeading />
</div>
<ExampleCardsList />
</div>
Expand Down
6 changes: 4 additions & 2 deletions apps/website/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -310,12 +310,14 @@ input[type="email"] {
--80-100-80,
linear-gradient(
270deg,
rgba(247, 247, 247, 0.8) 0%,
rgba(247, 247, 247, 0.5) 0%,
#f7f7f7 50%,
rgba(247, 247, 247, 0.8) 100%
rgba(247, 247, 247, 0.5) 100%
)
);
background-clip: text;
background-size: 200% 100%;
background-position: 50% 0%;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;

Expand Down
55 changes: 34 additions & 21 deletions apps/website/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Geist, Geist_Mono } from "next/font/google";
import { Prefooter } from "@/components/layout/prefooter";
import { Toaster } from "@/components/ui/toaster";
import { SpeedInsights } from "@vercel/speed-insights/next";
import { AskAIProvider } from "@/components/ai/ask-context";

const geistSans = Geist({
variable: "--font-geist-sans",
Expand Down Expand Up @@ -80,31 +81,43 @@ export default function RootLayout({
<html lang="en">
<head>
<meta name="theme-color" content="#000000" />
<noscript>
<style>
{`
body * {
visibility: visible !important;
opacity: 1 !important;
}
`}
</style>
</noscript>
</head>
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased min-h-[100dvh] flex flex-col`}
>
<RootProvider
search={{
SearchDialog: DefaultSearchDialog,
options: {
links: [
["Getting Started", "/docs/getting-started/introduction"],
["Configuration", "/docs/configuration/custom-directories"],
["Core Concepts", "/docs/core-concepts/tools"],
["Authentication", "/docs/authentication/api-key"],
["Integrations", "/docs/integrations/nextjs"],
["Deployment", "/docs/deployment/vercel"],
],
},
}}
>
<Header />
{children}
<Prefooter />
<Footer />
<Toaster />
</RootProvider>
<AskAIProvider>
<RootProvider
search={{
SearchDialog: DefaultSearchDialog,
options: {
links: [
["Getting Started", "/docs/getting-started/introduction"],
["Configuration", "/docs/configuration/custom-directories"],
["Core Concepts", "/docs/core-concepts/tools"],
["Authentication", "/docs/authentication/api-key"],
["Integrations", "/docs/integrations/nextjs"],
["Deployment", "/docs/deployment/vercel"],
],
},
}}
>
<Header />
{children}
<Prefooter />
<Footer />
<Toaster />
</RootProvider>
</AskAIProvider>
<Toolbar />
<Analytics />
<SpeedInsights />
Expand Down
5 changes: 4 additions & 1 deletion apps/website/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { HomeHero } from "@/components/home/hero";
import { HomeFeatures } from "@/components/home/features";
import { HomeSteps } from "@/components/home/steps";
import { HomeBlog } from "@/components/home/blog";
import { getLatestVersion } from "@/lib/get-version";

export const dynamic = "force-static";

Expand All @@ -15,9 +16,11 @@ export const metadata: Metadata = {
};

export default async function Home() {
const version = await getLatestVersion();

return (
<main className="grid grid-cols-12 gap-[20px] max-w-[1200px] w-full mx-auto px-4">
<HomeHero />
<HomeHero version={version} />
<HomeFeatures />
<HomeSteps />
<HomeBlog />
Expand Down
24 changes: 4 additions & 20 deletions apps/website/app/showcase/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Metadata } from "next";
import { ShowcaseForm } from "../../components/showcase/form";
import { ShowcaseCards } from "../../components/showcase/cards";
import { Tag } from "@/components/ui/tag";
import { ShowcaseHeroHeading } from "@/components/showcase/index/showcase-hero-heading";
import { ShowcaseSubmissionsHeading } from "@/components/showcase/index/showcase-submissions-heading";

export const metadata: Metadata = {
title: "Showcase - xmcp",
Expand All @@ -17,31 +18,14 @@ export default function ShowcasePage() {
<main className="grid grid-cols-12 gap-[20px] max-w-[1200px] w-full mx-auto px-4">
<div className="col-span-12 grid grid-cols-12 gap-[20px] py-8 md:py-16">
<div className="flex flex-col items-center justify-center max-w-[720px] w-full mx-auto gap-4 col-span-12 mb-8">
<h1 className="display text-center text-balance z-10 text-gradient">
Community MCP servers
</h1>
<p className="text-brand-neutral-100 text-base col-span-12 max-w-[650px] lg:col-span-5 mt-auto text-center">
Explore the first wave of production-ready MCP servers built by
developers worldwide.
</p>
<ShowcaseHeroHeading />
</div>

<ShowcaseCards />

<div className="col-span-12 py-8 md:py-16">
<div className="col-span-12 grid grid-cols-12 gap-[20px] py-8 md:py-16">
<div className="flex flex-col items-start justify-center col-span-12 lg:col-span-9 lg:col-start-2 w-full mx-auto mb-8 gap-3">
<Tag text="Submissions are open" />
<div className="grid grid-cols-12 lg:grid-cols-9 gap-4 md:gap-8 w-full">
<h2 className="heading-2 text-balance col-span-12 lg:col-span-4 mt-auto text-gradient">
Showcase your MCP server
</h2>
<p className="text-brand-neutral-100 text-base col-span-12 max-w-[650px] lg:col-span-5 mt-auto">
Built something amazing with xmcp? Share it with the community
and get featured in our showcase.
</p>
</div>
</div>
<ShowcaseSubmissionsHeading />

<div className="col-span-12">
<ShowcaseForm />
Expand Down
8 changes: 3 additions & 5 deletions apps/website/components/ai/ask-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

import { useEffect, useState } from "react";
import { cn } from "@/lib/cn";
import { AskAIDialog } from "./ask-dialog";
import { Icons } from "../icons";
import { detectWindowsFromClient } from "@/utils/detect-os";
import { useAskAI } from "./ask-context";

export function AskAIButtonClient() {
const [open, setOpen] = useState(false);
const { setOpen } = useAskAI();
const [isWindows, setIsWindows] = useState<boolean | null>(null);

useEffect(() => {
Expand All @@ -25,7 +25,7 @@ export function AskAIButtonClient() {

window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, []);
}, [setOpen]);

return (
<>
Expand Down Expand Up @@ -66,8 +66,6 @@ export function AskAIButtonClient() {
>
<Icons.chat className="size-4" />{" "}
</button>

<AskAIDialog open={open} onOpenChange={setOpen} />
</>
);
}
30 changes: 30 additions & 0 deletions apps/website/components/ai/ask-context.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"use client";

import { createContext, useContext, useState, ReactNode } from "react";
import { AskAIDialog } from "./ask-dialog";

interface AskAIContextType {
open: boolean;
setOpen: (open: boolean) => void;
}

const AskAIContext = createContext<AskAIContextType | null>(null);

export function useAskAI() {
const context = useContext(AskAIContext);
if (!context) {
throw new Error("useAskAI must be used within AskAIProvider");
}
return context;
}

export function AskAIProvider({ children }: { children: ReactNode }) {
const [open, setOpen] = useState(false);

return (
<AskAIContext.Provider value={{ open, setOpen }}>
{children}
<AskAIDialog open={open} onOpenChange={setOpen} />
</AskAIContext.Provider>
);
}
33 changes: 33 additions & 0 deletions apps/website/components/blog/index/hero-heading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"use client";

import { AnimatedHeading } from "@/components/ui/animated-heading";
import { useFadeIn } from "@/lib/anim/use-fade-in";
import { useRef } from "react";

export function BlogHeroHeading() {
const headingRef = useRef<HTMLHeadingElement>(null);
const descriptionRef = useRef<HTMLParagraphElement>(null);

useFadeIn({
refs: [headingRef, descriptionRef],
yOffset: 15,
});

return (
<>
<AnimatedHeading
effectDuration={2}
ref={headingRef}
className="display text-center text-balance z-10 invisible"
>
Blog
</AnimatedHeading>
<p
className="text-brand-neutral-100 text-base col-span-12 max-w-[650px] lg:col-span-5 mt-auto text-center invisible"
ref={descriptionRef}
>
Read the latest updates, guides, and insights about xmcp.
</p>
</>
);
}
2 changes: 1 addition & 1 deletion apps/website/components/examples/cards/cards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export function ExampleCards({ examples }: ExampleCardsProps) {
{selectedTags.length > 0 && (
<button
onClick={clearFilters}
className="text-xs text-brand-neutral-200 hover:text-white transition-colors"
className="text-xs text-brand-neutral-200 hover:text-white transition-colors cursor-pointer"
>
Clear filters
</button>
Expand Down
34 changes: 34 additions & 0 deletions apps/website/components/examples/cards/hero-heading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"use client";

import { useRef } from "react";
import { AnimatedHeading } from "@/components/ui/animated-heading";
import { useFadeIn } from "@/lib/anim/use-fade-in";

export function ExamplesHeroHeading() {
const headingRef = useRef<HTMLHeadingElement>(null);
const descriptionRef = useRef<HTMLParagraphElement>(null);

useFadeIn({
refs: [headingRef, descriptionRef],
yOffset: 15,
});

return (
<>
<AnimatedHeading
effectDuration={2}
className="display text-center text-balance z-10 invisible"
ref={headingRef}
>
Examples & templates
</AnimatedHeading>
<p
className="text-brand-neutral-100 text-base col-span-12 max-w-[650px] lg:col-span-5 mt-auto text-center invisible"
ref={descriptionRef}
>
Quickstart guides and examples to get you started with xmcp with
real-world implementations and best practices.
</p>
</>
);
}
Loading