feat: add new design

This commit is contained in:
Mauricio Siu
2024-11-01 16:58:46 -06:00
parent 0f1f1a1935
commit 7ebe7814de
18 changed files with 670 additions and 134 deletions

File diff suppressed because one or more lines are too long

View File

@@ -4,6 +4,8 @@ import { Hero } from "@/components/Hero";
import { PrimaryFeatures } from "@/components/PrimaryFeatures"; import { PrimaryFeatures } from "@/components/PrimaryFeatures";
import { Testimonials } from "@/components/Testimonials"; import { Testimonials } from "@/components/Testimonials";
import { FeaturesSectionDemo } from "@/components/features"; import { FeaturesSectionDemo } from "@/components/features";
import { Pricing } from "@/components/pricing";
import { RippleDemo } from "@/components/sponsors";
export default function Home() { export default function Home() {
return ( return (
@@ -13,7 +15,12 @@ export default function Home() {
<FeaturesSectionDemo /> <FeaturesSectionDemo />
<PrimaryFeatures /> <PrimaryFeatures />
<Testimonials /> <Testimonials />
<div className="w-full relative">
<Pricing />
</div>
<Faqs /> <Faqs />
<RippleDemo />
<CallToAction /> <CallToAction />
</main> </main>
</div> </div>

View File

@@ -1,9 +0,0 @@
import { Pricing } from "@/components/pricing";
export default function Home() {
return (
<div className="w-full">
<Pricing />
</div>
);
}

View File

@@ -12,6 +12,34 @@ const faqs = [
question: "faq.q1", question: "faq.q1",
answer: "faq.a1", answer: "faq.a1",
}, },
{
question: "faq.q11",
answer: "faq.a11",
},
{
question: "faq.q12",
answer: "faq.a12",
},
{
question: "faq.q13",
answer: "faq.a13",
},
{
question: "faq.q14",
answer: "faq.a14",
},
{
question: "faq.q15",
answer: "faq.a15",
},
{
question: "faq.q17",
answer: "faq.a17",
},
{
question: "faq.q18",
answer: "faq.a18",
},
{ {
question: "faq.q2", question: "faq.q2",
answer: "faq.a2", answer: "faq.a2",
@@ -36,6 +64,10 @@ const faqs = [
question: "faq.q8", question: "faq.q8",
answer: "faq.a8", answer: "faq.a8",
}, },
{
question: "faq.q16",
answer: "faq.a16",
},
{ {
question: "faq.q9", question: "faq.q9",
answer: "faq.a9", answer: "faq.a9",
@@ -74,7 +106,9 @@ export function Faqs() {
> >
{faqs.map((column, columnIndex) => ( {faqs.map((column, columnIndex) => (
<AccordionItem value={`${columnIndex}`} key={columnIndex}> <AccordionItem value={`${columnIndex}`} key={columnIndex}>
<AccordionTrigger>{t(column.question)}</AccordionTrigger> <AccordionTrigger className="text-left">
{t(column.question)}
</AccordionTrigger>
<AccordionContent>{t(column.answer)}</AccordionContent> <AccordionContent>{t(column.answer)}</AccordionContent>
</AccordionItem> </AccordionItem>
))} ))}

View File

@@ -67,10 +67,14 @@ export function Footer() {
aria-label="Dokploy on Twitter" aria-label="Dokploy on Twitter"
> >
<svg <svg
aria-hidden="true" stroke="currentColor"
className="h-6 w-6 fill-muted-foreground group-hover:fill-muted-foreground/70" fill="currentColor"
strokeWidth="0"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5 fill-muted-foreground group-hover:fill-muted-foreground/70"
> >
<path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0 0 22 5.92a8.19 8.19 0 0 1-2.357.646 4.118 4.118 0 0 0 1.804-2.27 8.224 8.224 0 0 1-2.605.996 4.107 4.107 0 0 0-6.993 3.743 11.65 11.65 0 0 1-8.457-4.287 4.106 4.106 0 0 0 1.27 5.477A4.073 4.073 0 0 1 2.8 9.713v.052a4.105 4.105 0 0 0 3.292 4.022 4.093 4.093 0 0 1-1.853.07 4.108 4.108 0 0 0 3.834 2.85A8.233 8.233 0 0 1 2 18.407a11.615 11.615 0 0 0 6.29 1.84" /> <path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8L200.7 275.5 26.8 48H172.4L272.9 180.9 389.2 48zM364.4 421.8h39.1L151.1 88h-42L364.4 421.8z" />
</svg> </svg>
</Link> </Link>
<Link <Link

View File

@@ -3,13 +3,14 @@
import { Link } from "@/i18n/routing"; import { Link } from "@/i18n/routing";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { Popover, Transition } from "@headlessui/react"; import { Popover, Transition } from "@headlessui/react";
import { HeartIcon } from "lucide-react"; import { ChevronRight, HeartIcon } from "lucide-react";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { Fragment, type JSX, type SVGProps } from "react"; import { Fragment, type JSX, type SVGProps } from "react";
import { Container } from "./Container"; import { Container } from "./Container";
import { NavLink } from "./NavLink"; import { NavLink } from "./NavLink";
import { trackGAEvent } from "./analitycs"; import { trackGAEvent } from "./analitycs";
import { Logo } from "./shared/Logo"; import { Logo } from "./shared/Logo";
import AnimatedGradientText from "./ui/animated-gradient-text";
import { Button, buttonVariants } from "./ui/button"; import { Button, buttonVariants } from "./ui/button";
function MobileNavLink({ function MobileNavLink({
@@ -119,7 +120,7 @@ function MobileNavigation() {
as="div" as="div"
className="absolute inset-x-0 top-full mt-4 flex origin-top flex-col rounded-2xl border border-border bg-background p-4 text-lg tracking-tight text-primary shadow-xl ring-1 ring-border/5" className="absolute inset-x-0 top-full mt-4 flex origin-top flex-col rounded-2xl border border-border bg-background p-4 text-lg tracking-tight text-primary shadow-xl ring-1 ring-border/5"
> >
<MobileNavLink href="/pricing">Pricing</MobileNavLink> <MobileNavLink href="#pricing">Pricing</MobileNavLink>
<MobileNavLink href="/#faqs">{t("navigation.faqs")}</MobileNavLink> <MobileNavLink href="/#faqs">{t("navigation.faqs")}</MobileNavLink>
<MobileNavLink href={linkT("docs.intro")} target="_blank"> <MobileNavLink href={linkT("docs.intro")} target="_blank">
{t("navigation.docs")} {t("navigation.docs")}
@@ -144,7 +145,7 @@ export function Header() {
<Logo className="h-10 w-auto" /> <Logo className="h-10 w-auto" />
</Link> </Link>
<div className="hidden md:flex md:gap-x-6"> <div className="hidden md:flex md:gap-x-6">
<NavLink href="/pricing">{t("navigation.pricing")}</NavLink> <NavLink href="#pricing">{t("navigation.pricing")}</NavLink>
<NavLink href="/#faqs">{t("navigation.faqs")}</NavLink> <NavLink href="/#faqs">{t("navigation.faqs")}</NavLink>
<NavLink href={linkT("docs.intro")} target="_blank"> <NavLink href={linkT("docs.intro")} target="_blank">
{t("navigation.docs")} {t("navigation.docs")}
@@ -152,7 +153,20 @@ export function Header() {
</div> </div>
</div> </div>
<div className="flex items-center gap-x-2 md:gap-x-5"> <div className="flex items-center gap-x-2 md:gap-x-5">
<Link <Link href="https://x.com/getdokploy" target="_blank">
<svg
stroke="currentColor"
fill="currentColor"
strokeWidth="0"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5 fill-muted-foreground group-hover:fill-muted-foreground/70 hover:fill-muted-foreground/80"
>
<path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8L200.7 275.5 26.8 48H172.4L272.9 180.9 389.2 48zM364.4 421.8h39.1L151.1 88h-42L364.4 421.8z" />
</svg>
</Link>
{/* <Link
className={buttonVariants({ className={buttonVariants({
variant: "outline", variant: "outline",
className: " flex items-center gap-2 !rounded-full", className: " flex items-center gap-2 !rounded-full",
@@ -164,14 +178,18 @@ export function Header() {
{t("navigation.support")}{" "} {t("navigation.support")}{" "}
</span> </span>
<HeartIcon className="animate-heartbeat size-4 fill-red-600 text-red-500 " /> <HeartIcon className="animate-heartbeat size-4 fill-red-600 text-red-500 " />
</Link> </Link> */}
<Button className="rounded-full" asChild> <Button className="rounded-full" asChild>
<Link <Link
href="https://app.dokploy.com" href="https://app.dokploy.com/register"
aria-label="Dokploy on GitHub" aria-label="Sign In Dokploy Cloud"
target="_blank" target="_blank"
> >
{t("navigation.dashboard")} <div className="group flex-row relative mx-auto flex max-w-fit items-center justify-center rounded-2xl text-sm font-medium w-full">
<span>{t("navigation.dashboard")}</span>
<ChevronRight className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" />
</div>
</Link> </Link>
</Button> </Button>
<div className="-mr-1 md:hidden"> <div className="-mr-1 md:hidden">

View File

@@ -158,7 +158,7 @@ export function PrimaryFeatures() {
{features.map((feature, index) => ( {features.map((feature, index) => (
<Tab.Panel key={`panel-${index}`}> <Tab.Panel key={`panel-${index}`}>
<div className="relative sm:px-6 "> <div className="relative sm:px-6 ">
<div className="absolute -inset-x-4 bottom-[-4.25rem] top-[-6.5rem] bg-white/10 ring-1 ring-inset ring-white/10 sm:inset-x-0 sm:rounded-t-xl" /> <div className="absolute -inset-x-4 bottom-[-4.25rem] top-[-6.5rem] bg-card/60 ring-1 ring-inset ring-white/10 sm:inset-x-0 sm:rounded-t-xl" />
<p className="relative mx-auto max-w-2xl text-base text-white sm:text-center mb-10"> <p className="relative mx-auto max-w-2xl text-base text-white sm:text-center mb-10">
{t(feature.description)} {t(feature.description)}
</p> </p>
@@ -174,7 +174,7 @@ export function PrimaryFeatures() {
bounce: 0.2, bounce: 0.2,
duration: 0.8, duration: 0.8,
}} }}
className="mt-10 h-[24rem] w-[45rem] overflow-hidden rounded-xl border shadow-xl sm:w-auto lg:mt-0 lg:h-[40rem] " className="mt-10 h-[24rem] w-[45rem] overflow-hidden rounded-xl border-b shadow-xl sm:w-auto lg:mt-0 lg:h-[40rem] "
> >
<div className="relative"> <div className="relative">
<Safari <Safari

View File

@@ -188,11 +188,11 @@ export function Testimonials() {
aria-label="What our customers are saying" aria-label="What our customers are saying"
className=" py-20 sm:py-32" className=" py-20 sm:py-32"
> >
<div className="mx-auto max-w-2xl md:text-center"> <div className="mx-auto max-w-2xl md:text-center px-4">
<h2 className="font-display text-3xl tracking-tight sm:text-4xl"> <h2 className="font-display text-3xl tracking-tight sm:text-4xl text-center">
Why Developers Love Dokploy Why Developers Love Dokploy
</h2> </h2>
<p className="mt-4 text-lg tracking-tight text-muted-foreground "> <p className="mt-4 text-lg tracking-tight text-muted-foreground text-center">
Think were bragging? Hear from the devs who once doubted toountil Think were bragging? Hear from the devs who once doubted toountil
Dokploy made their lives (and deployments) surprisingly easier. Dokploy made their lives (and deployments) surprisingly easier.
</p> </p>

View File

@@ -98,7 +98,7 @@ export function FeaturesSectionDemo() {
flexible database managementall with Dokploys developer-focused flexible database managementall with Dokploys developer-focused
features. features.
</p> </p>
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 relative z-10 py-10 max-w-7xl mx-auto mt-10"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 relative z-10 py-10 max-w-7xl mx-auto mt-10 max-sm:p-0 max-sm:mx-0 max-sm:w-full">
{features.map((feature, index) => ( {features.map((feature, index) => (
<Feature key={feature.title} {...feature} index={index} /> <Feature key={feature.title} {...feature} index={index} />
))} ))}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,29 @@
import { PlusCircleIcon } from "lucide-react";
import { useTranslations } from "next-intl";
import { Button } from "./ui/button";
import Ripple from "./ui/ripple";
export const RippleDemo = () => {
const t = useTranslations("HomePage");
return (
<div className="mt-20 flex flex-col justify-center gap-y-10 w-full">
<div className="flex flex-col justify-start gap-4 px-4">
<h1 className="mx-auto max-w-2xl font-display text-3xl font-medium tracking-tight text-primary sm:text-5xl text-center">
{t("hero.sponsors.title")}
</h1>
<p className="mx-auto max-w-2xl text-lg tracking-tight text-muted-foreground text-center">
{t("hero.sponsors.description")}
</p>
</div>
<div className="relative flex h-[500px] w-full flex-col items-center justify-center overflow-hidden rounded-lg border bg-background md:shadow-xl">
<p className="z-10 whitespace-pre-wrap text-center text-5xl font-medium tracking-tighter text-white">
<Button variant="secondary" className="rounded-full p-0 m-0">
<PlusCircleIcon className="size-10 text-muted-foreground hover:text-primary transition-colors" />
</Button>
{/* <PlusCircleIcon className="size-10 " /> */}
</p>
<Ripple />
</div>
</div>
);
};

View File

@@ -0,0 +1,50 @@
"use client";
import * as AvatarPrimitive from "@radix-ui/react-avatar";
import * as React from "react";
import { cn } from "@/lib/utils";
const Avatar = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Root
ref={ref}
className={cn(
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
className,
)}
{...props}
/>
));
Avatar.displayName = AvatarPrimitive.Root.displayName;
const AvatarImage = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Image>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Image
ref={ref}
className={cn("aspect-square h-full w-full", className)}
{...props}
/>
));
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
const AvatarFallback = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Fallback>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Fallback
ref={ref}
className={cn(
"flex h-full w-full items-center justify-center rounded-full bg-muted",
className,
)}
{...props}
/>
));
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
export { Avatar, AvatarImage, AvatarFallback };

View File

@@ -0,0 +1,172 @@
"use client";
import React, { type CSSProperties } from "react";
import { cn } from "@/lib/utils";
import { Avatar, AvatarFallback, AvatarImage } from "./avatar";
interface RippleProps {
mainCircleSize?: number;
mainCircleOpacity?: number;
numCircles?: number;
className?: string;
}
const Ripple = React.memo(function Ripple({
mainCircleSize = 210,
mainCircleOpacity = 0.24,
numCircles = 8,
className,
}: RippleProps) {
const avatarsFirstRing = [
"https://github.com/shadcn.png", // URLs de los avatares del primer aro
"https://github.com/shadcn.png",
"https://github.com/shadcn.png",
"https://github.com/shadcn.png",
"https://github.com/shadcn.png",
];
const avatarsSecondRing = [
"https://github.com/shadcn.png", // URLs de los avatares del segundo aro
"https://github.com/shadcn.png",
"https://github.com/shadcn.png",
"https://github.com/shadcn.png",
"https://github.com/shadcn.png",
"https://github.com/shadcn.png",
];
const avatarsThirdRing = [
"https://github.com/shadcn.png", // URLs de los avatares del tercer aro
"https://github.com/shadcn.png",
"https://github.com/shadcn.png",
"https://github.com/shadcn.png",
"https://github.com/shadcn.png",
"https://github.com/shadcn.png",
"https://github.com/shadcn.png",
"https://github.com/shadcn.png",
];
return (
<div
className={cn(
// "pointer-events-none select-none absolute inset-0 [mask-image:linear-gradient(to_bottom,white,transparent)]",
className,
)}
>
<div>
{Array.from({ length: numCircles }, (_, i) => {
const size = mainCircleSize + i * 70;
const opacity = mainCircleOpacity - i * 0.03;
const animationDelay = `${i * 0.06}s`;
const borderStyle = i === numCircles - 1 ? "dashed" : "solid";
const borderOpacity = 5 + i * 5;
return (
<div
key={i}
className={`absolute animate-ripple rounded-full bg-foreground/25 shadow-xl border [--i:${i}]`}
style={{
width: `${size}px`,
height: `${size}px`,
opacity,
animationDelay,
borderStyle,
borderWidth: "1px",
borderColor: `hsl(var(--foreground), ${borderOpacity / 100})`,
top: "50%",
left: "50%",
transform: "translate(-50%, -50%) scale(1)",
}}
>
{i === 0 && (
<div className="relative w-full h-full flex justify-center items-center">
{avatarsFirstRing.map((src, index) => {
const angle = (360 / avatarsFirstRing.length) * index;
const radius = mainCircleSize / 2;
const x = radius * Math.cos((angle * Math.PI) / 180);
const y = radius * Math.sin((angle * Math.PI) / 180);
return (
<div
key={index}
className="absolute"
style={{
top: "50%",
left: "50%",
transform: `translate(${x}px, ${y}px) translate(-50%, -50%)`,
}}
>
<Avatar>
<AvatarImage src={src} />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
</div>
);
})}
</div>
)}
{i === 1 && (
<div className="relative w-full h-full flex justify-center items-center">
{avatarsSecondRing.map((src, index) => {
const angle = (360 / avatarsSecondRing.length) * index;
const radius = mainCircleSize / 2 + 70; // Radio mayor para el segundo aro
const x = radius * Math.cos((angle * Math.PI) / 180);
const y = radius * Math.sin((angle * Math.PI) / 180);
return (
<div
key={index}
className="absolute"
style={{
top: "50%",
left: "50%",
transform: `translate(${x}px, ${y}px) translate(-50%, -50%)`,
}}
>
<Avatar>
<AvatarImage src={src} />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
</div>
);
})}
</div>
)}
{i === 3 && (
<div className="relative w-full h-full flex justify-center items-center">
{avatarsThirdRing.map((src, index) => {
const angle = (360 / avatarsThirdRing.length) * index;
const radius = mainCircleSize / 2 + 140; // Radio mayor para el tercer aro
const x = radius * Math.cos((angle * Math.PI) / 180);
const y = radius * Math.sin((angle * Math.PI) / 180);
return (
<div
key={index}
className="absolute"
style={{
top: "50%",
left: "50%",
transform: `translate(${x}px, ${y}px) translate(-50%, -50%)`,
}}
>
<Avatar>
<AvatarImage src={src} />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
</div>
);
})}
</div>
)}
</div>
);
})}
</div>
</div>
);
});
Ripple.displayName = "Ripple";
export default Ripple;

View File

@@ -0,0 +1,48 @@
"use client";
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
import * as React from "react";
import { cn } from "@/lib/utils";
const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
>(({ className, children, ...props }, ref) => (
<ScrollAreaPrimitive.Root
ref={ref}
className={cn("relative overflow-hidden", className)}
{...props}
>
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
));
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
const ScrollBar = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
>(({ className, orientation = "vertical", ...props }, ref) => (
<ScrollAreaPrimitive.ScrollAreaScrollbar
ref={ref}
orientation={orientation}
className={cn(
"flex touch-none select-none transition-colors",
orientation === "vertical" &&
"h-full w-2.5 border-l border-l-transparent p-[1px]",
orientation === "horizontal" &&
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
className,
)}
{...props}
>
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
</ScrollAreaPrimitive.ScrollAreaScrollbar>
));
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
export { ScrollArea, ScrollBar };

View File

@@ -6,7 +6,7 @@
"docs": "Docs", "docs": "Docs",
"pricing": "Pricing", "pricing": "Pricing",
"support": "Support", "support": "Support",
"dashboard": "Dashboard", "dashboard": "Sign In",
"discord": "Discord", "discord": "Discord",
"i18nButtonPlaceholder": "Language", "i18nButtonPlaceholder": "Language",
"i18nEn": "English", "i18nEn": "English",
@@ -91,7 +91,23 @@
"q9": "What types of applications can I deploy with Dokploy?", "q9": "What types of applications can I deploy with Dokploy?",
"a9": "You can deploy any application that can be Dockerized, with no limits. Dokploy supports builds from Git repositories, Dockerfiles, Nixpacks, and Buildpacks like Heroku and Paketo.", "a9": "You can deploy any application that can be Dockerized, with no limits. Dokploy supports builds from Git repositories, Dockerfiles, Nixpacks, and Buildpacks like Heroku and Paketo.",
"q10": "How does Dokploy handle database management?", "q10": "How does Dokploy handle database management?",
"a10": "Dokploy supports multiple database systems including Postgres, MySQL, MariaDB, MongoDB, and Redis, providing tools for easy deployment and management and backups directly from the dashboard." "a10": "Dokploy supports multiple database systems including Postgres, MySQL, MariaDB, MongoDB, and Redis, providing tools for easy deployment and management and backups directly from the dashboard.",
"q11": "How does Dokploy's Open Source plan work?",
"a11": "You can host Dokploy UI on your own infrastructure and you will be responsible for the maintenance and updates.",
"q12": "Do I need to provide my own server for the managed plan?",
"a12": "Yes, in the managed plan, you provide your own server eg(Hetzner, Hostinger, AWS, ETC.) VPS, and we manage the Dokploy UI infrastructure for you.",
"q13": "What happens if I need more than one server?",
"a13": "The first server costs $4.50/month, if you buy more than one it will be $3.50/month per server.",
"q14": "Is there a limit on the number of deployments?",
"a14": "No, there is no limit on the number of deployments in any of the plans.",
"q15": "What happens if I exceed my purchased server limit?",
"a15": "The most recently added servers will be deactivated. You won't be able to create services on inactive servers until they are reactivated.",
"q16": "Do you offer a refunds?",
"a16": "We do not offer refunds. However, you can cancel your subscription at any time. Feel free to try our open-source version for free before making a purchase.",
"q17": "What kind of support do you offer?",
"a17": "We offer community support for the open source version and priority support for paid plans (Via Discord or Email at support@dokploy.com).",
"q18": "What's the catch on the Paid Plan?",
"a18": "Nothing, you link your server(VPS) to your account and you can deploy unlimited applications, databases, and users and you get unlimited updates, deployments, backups and more."
}, },
"footer": { "footer": {
"copyright": "Copyright © {year} Dokploy. All rights reserved." "copyright": "Copyright © {year} Dokploy. All rights reserved."
@@ -126,13 +142,10 @@
}, },
"features": { "features": {
"f1": "Complete Flexibility: Install Dokploy UI on your own infrastructure", "f1": "Complete Flexibility: Install Dokploy UI on your own infrastructure",
"f2": "Unlimited Deployments", "f2": "Self-hosted Infrastructure",
"f3": "Self-hosted Infrastructure", "f3": "Community Support",
"f4": "Community Support", "f4": "Access to Core Features",
"f5": "Access to Core Features", "f5": "Access to All Updates",
"f6": "Dokploy Integration",
"f7": "Basic Backups",
"f8": "Access to All Updates",
"f9": "Unlimited Servers" "f9": "Unlimited Servers"
}, },
"go": "Installation" "go": "Installation"
@@ -146,8 +159,12 @@
"servers": "{serverQuantity} Servers (You bring the servers)", "servers": "{serverQuantity} Servers (You bring the servers)",
"features": { "features": {
"f1": "Managed Hosting: No need to manage your own servers", "f1": "Managed Hosting: No need to manage your own servers",
"f2": "Priority Support", "f2": "Unlimited Deployments",
"f3": "Future-Proof Features" "f3": "Unlimited Databases",
"f4": "Unlimited Applications",
"f5": "Unlimited Users",
"f6": "Priority Support",
"f7": "New Updates"
}, },
"go": "Subscribe" "go": "Subscribe"
} }

View File

@@ -15,6 +15,8 @@
"@headlessui/react": "^1.7.17", "@headlessui/react": "^1.7.17",
"@headlessui/tailwindcss": "^0.2.0", "@headlessui/tailwindcss": "^0.2.0",
"@radix-ui/react-accordion": "^1.2.1", "@radix-ui/react-accordion": "^1.2.1",
"@radix-ui/react-avatar": "^1.1.1",
"@radix-ui/react-scroll-area": "^1.2.0",
"@radix-ui/react-select": "^2.0.0", "@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-switch": "^1.0.3",

View File

@@ -124,6 +124,14 @@ const config = {
backgroundPosition: "var(--bg-size) 0", backgroundPosition: "var(--bg-size) 0",
}, },
}, },
ripple: {
"0%, 100%": {
transform: "translate(-50%, -50%) scale(1)",
},
"50%": {
transform: "translate(-50%, -50%) scale(0.9)",
},
},
}, },
animation: { animation: {
"accordion-down": "accordion-down 0.2s ease-out", "accordion-down": "accordion-down 0.2s ease-out",
@@ -132,6 +140,7 @@ const config = {
marquee: "marquee var(--duration) linear infinite", marquee: "marquee var(--duration) linear infinite",
"marquee-vertical": "marquee-vertical var(--duration) linear infinite", "marquee-vertical": "marquee-vertical var(--duration) linear infinite",
gradient: "gradient 8s linear infinite", gradient: "gradient 8s linear infinite",
ripple: "ripple var(--duration,2s) ease calc(var(--i, 0)*.2s) infinite",
}, },
}, },
}, },

61
pnpm-lock.yaml generated
View File

@@ -91,6 +91,12 @@ importers:
'@radix-ui/react-accordion': '@radix-ui/react-accordion':
specifier: ^1.2.1 specifier: ^1.2.1
version: 1.2.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) version: 1.2.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@radix-ui/react-avatar':
specifier: ^1.1.1
version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@radix-ui/react-scroll-area':
specifier: ^1.2.0
version: 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@radix-ui/react-select': '@radix-ui/react-select':
specifier: ^2.0.0 specifier: ^2.0.0
version: 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) version: 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
@@ -618,6 +624,19 @@ packages:
'@types/react-dom': '@types/react-dom':
optional: true optional: true
'@radix-ui/react-avatar@1.1.1':
resolution: {integrity: sha512-eoOtThOmxeoizxpX6RiEsQZ2wj5r4+zoeqAwO0cBaFQGjJwIH3dIX0OCxNrCyrrdxG+vBweMETh3VziQG7c1kw==}
peerDependencies:
'@types/react': 18.3.5
'@types/react-dom': 18.3.0
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-collapsible@1.1.0': '@radix-ui/react-collapsible@1.1.0':
resolution: {integrity: sha512-zQY7Epa8sTL0mq4ajSJpjgn2YmCgyrG7RsQgLp3C0LQVkG7+Tf6Pv1CeNWZLyqMjhdPkBa5Lx7wYBeSu7uCSTA==} resolution: {integrity: sha512-zQY7Epa8sTL0mq4ajSJpjgn2YmCgyrG7RsQgLp3C0LQVkG7+Tf6Pv1CeNWZLyqMjhdPkBa5Lx7wYBeSu7uCSTA==}
peerDependencies: peerDependencies:
@@ -968,6 +987,19 @@ packages:
'@types/react-dom': '@types/react-dom':
optional: true optional: true
'@radix-ui/react-scroll-area@1.2.0':
resolution: {integrity: sha512-q2jMBdsJ9zB7QG6ngQNzNwlvxLQqONyL58QbEGwuyRZZb/ARQwk3uQVbCF7GvQVOtV6EU/pDxAw3zRzJZI3rpQ==}
peerDependencies:
'@types/react': 18.3.5
'@types/react-dom': 18.3.0
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-select@2.1.1': '@radix-ui/react-select@2.1.1':
resolution: {integrity: sha512-8iRDfyLtzxlprOo9IicnzvpsO1wNCkuwzzCM+Z5Rb5tNOpCdMvcc2AkzX0Fz+Tz9v6NJ5B/7EEgyZveo4FBRfQ==} resolution: {integrity: sha512-8iRDfyLtzxlprOo9IicnzvpsO1wNCkuwzzCM+Z5Rb5tNOpCdMvcc2AkzX0Fz+Tz9v6NJ5B/7EEgyZveo4FBRfQ==}
peerDependencies: peerDependencies:
@@ -3461,6 +3493,18 @@ snapshots:
'@types/react': 18.3.5 '@types/react': 18.3.5
'@types/react-dom': 18.3.0 '@types/react-dom': 18.3.0
'@radix-ui/react-avatar@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@radix-ui/react-context': 1.1.1(@types/react@18.3.5)(react@18.2.0)
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.5)(react@18.2.0)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.5)(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
optionalDependencies:
'@types/react': 18.3.5
'@types/react-dom': 18.3.0
'@radix-ui/react-collapsible@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': '@radix-ui/react-collapsible@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies: dependencies:
'@radix-ui/primitive': 1.1.0 '@radix-ui/primitive': 1.1.0
@@ -3932,6 +3976,23 @@ snapshots:
'@types/react': 18.3.5 '@types/react': 18.3.5
'@types/react-dom': 18.3.0 '@types/react-dom': 18.3.0
'@radix-ui/react-scroll-area@1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@radix-ui/number': 1.1.0
'@radix-ui/primitive': 1.1.0
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.5)(react@18.2.0)
'@radix-ui/react-context': 1.1.1(@types/react@18.3.5)(react@18.2.0)
'@radix-ui/react-direction': 1.1.0(@types/react@18.3.5)(react@18.2.0)
'@radix-ui/react-presence': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.5)(react@18.2.0)
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.5)(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
optionalDependencies:
'@types/react': 18.3.5
'@types/react-dom': 18.3.0
'@radix-ui/react-select@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': '@radix-ui/react-select@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies: dependencies:
'@radix-ui/number': 1.1.0 '@radix-ui/number': 1.1.0