+ No need to manage Dokploy UI infrastructure, we take care of
+ it for you.
+
+
+
+ {[
+ "Managed Hosting: No need to manage your own servers",
+ "Priority Support",
+ "Future-Proof Features",
+ ].map((feature) => (
+
+
+ {feature}
+
+ ))}
+
+
+
+
+ {serverQuantity} Servers (You bring the servers)
+
+
+
+
+
+ {
+ setServerQuantity(e.target.value as unknown as number);
+ }}
+ />
+
+
+
+
+
+
+ Subscribe
+
+
+
+
+
+
@@ -212,48 +365,43 @@ export function Pricing() {
const faqs = [
[
{
- question: "How does Dokploy's free plan work?",
+ question: "How does Dokploy's Open Source plan work?",
answer:
- "The free plan allows you to self-host Dokploy on your own infrastructure with unlimited deployments and full access to all features.",
+ "You can host Dokploy UI on your own infrastructure and you will be responsible for the maintenance and updates.",
},
{
question: "Do I need to provide my own server for the managed plan?",
answer:
- "Yes, in the managed plan, you provide your own server, and we manage the Dokploy UI infrastructure for you.",
+ "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.",
},
{
question: "What happens if I need more than one server?",
answer:
- "Each additional server costs $3.99/month and can be easily added to your account.",
+ "The first server costs $4.50/month, if you buy more than one it will be $3.50/month per server.",
},
],
[
- {
- question: "Can I use my custom domain with Dokploy?",
- answer:
- "Yes, custom domain support is available on all plans, including the free version.",
- },
{
question: "Is there a limit on the number of deployments?",
answer:
"No, there is no limit on the number of deployments in any of the plans.",
},
{
- question: "Do I have to manually configure Traefik?",
+ question: "What happens if I exceed my purchased server limit?",
answer:
- "Dokploy offers dynamic Traefik configuration out-of-the-box, so no manual setup is needed.",
+ "The most recently added servers will be deactivated. You won't be able to create services on inactive servers until they are reactivated.",
+ },
+ {
+ question: "Do you offer a refunds?",
+ answer:
+ "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.",
},
],
[
- {
- question: "How do automated backups work?",
- answer:
- "Automated backups are included in the managed plan and are limited to database backups only.",
- },
{
question: "What kind of support do you offer?",
answer:
- "We offer community support for the free plan and priority support for paid plans.",
+ "We offer community support for the open source version and priority support for paid plans.",
},
{
question: "Is Dokploy open-source?",
@@ -279,7 +427,7 @@ export function Faqs() {
{"Frequently asked questions"}
- If you can’t find what you’re looking for, please submit an issue
+ If you can’t find what you’re looking for, please send us an email
to:{" "}
support@dokploy.com
diff --git a/apps/website/components/ui/badge.tsx b/apps/website/components/ui/badge.tsx
new file mode 100644
index 00000000..f38976c0
--- /dev/null
+++ b/apps/website/components/ui/badge.tsx
@@ -0,0 +1,36 @@
+import { type VariantProps, cva } from "class-variance-authority";
+import type * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const badgeVariants = cva(
+ "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
+ {
+ variants: {
+ variant: {
+ default:
+ "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
+ secondary:
+ "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ destructive:
+ "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
+ outline: "text-foreground",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ },
+);
+
+export interface BadgeProps
+ extends React.HTMLAttributes,
+ VariantProps {}
+
+function Badge({ className, variant, ...props }: BadgeProps) {
+ return (
+
+ );
+}
+
+export { Badge, badgeVariants };
diff --git a/apps/website/components/ui/input.tsx b/apps/website/components/ui/input.tsx
new file mode 100644
index 00000000..8fe7ab28
--- /dev/null
+++ b/apps/website/components/ui/input.tsx
@@ -0,0 +1,69 @@
+import { cn } from "@/lib/utils";
+import * as React from "react";
+
+export interface InputProps
+ extends React.InputHTMLAttributes {
+ errorMessage?: string;
+}
+
+const Input = React.forwardRef(
+ ({ className, errorMessage, type, ...props }, ref) => {
+ return (
+ <>
+
+ {errorMessage && (
+
+ {errorMessage}
+
+ )}
+ >
+ );
+ },
+);
+Input.displayName = "Input";
+
+const NumberInput = React.forwardRef(
+ ({ className, errorMessage, ...props }, ref) => {
+ return (
+ {
+ const value = e.target.value;
+ if (value === "") {
+ props.onChange?.(e);
+ } else {
+ const number = Number.parseInt(value, 10);
+ if (!Number.isNaN(number)) {
+ const syntheticEvent = {
+ ...e,
+ target: {
+ ...e.target,
+ value: number,
+ },
+ };
+ props.onChange?.(
+ syntheticEvent as unknown as React.ChangeEvent,
+ );
+ }
+ }
+ }}
+ />
+ );
+ },
+);
+NumberInput.displayName = "NumberInput";
+
+export { Input, NumberInput };
diff --git a/apps/website/components/ui/tabs.tsx b/apps/website/components/ui/tabs.tsx
new file mode 100644
index 00000000..e54c215a
--- /dev/null
+++ b/apps/website/components/ui/tabs.tsx
@@ -0,0 +1,53 @@
+import * as TabsPrimitive from "@radix-ui/react-tabs";
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const Tabs = TabsPrimitive.Root;
+
+const TabsList = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsList.displayName = TabsPrimitive.List.displayName;
+
+const TabsTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
+
+const TabsContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsContent.displayName = TabsPrimitive.Content.displayName;
+
+export { Tabs, TabsList, TabsTrigger, TabsContent };
diff --git a/apps/website/locales/en.json b/apps/website/locales/en.json
index d171e3c7..7c401706 100644
--- a/apps/website/locales/en.json
+++ b/apps/website/locales/en.json
@@ -24,9 +24,9 @@
"projectsDes": "Manage and organize all your projects in one place, keeping detailed track of progress and resource allocation.",
"applications": "Applications & Databases",
"applicationsDes": "Centralize control over your applications and databases for enhanced security and efficiency, simplifying access and management across your infrastructure.",
- "compose": "compose",
+ "compose": "Compose",
"composeDes": "Native Docker Compose support for manage complex applications and services with ease.",
- "multinode": "multinode",
+ "multinode": "Multinode",
"multinodeDes": "Scale applications to multiples nodes using docker swarm to manage the cluster.",
"monitoring": "Monitoring",
"monitoringDes": "Monitor your systems' performance and health in real time, ensuring continuous and uninterrupted operation.",