Skip to content
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
2 changes: 1 addition & 1 deletion apps/docs/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import "./global.css";
import { GoogleAnalytics } from "@next/third-parties/google";
import { RootProvider } from "fumadocs-ui/provider";
import { Inter } from "next/font/google";
import type { ReactNode } from "react";
import { GoogleAnalytics } from "@next/third-parties/google";
const inter = Inter({
subsets: ["latin"],
});
Expand Down
36 changes: 18 additions & 18 deletions apps/website/app/[locale]/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,25 +105,28 @@ export default async function BlogPostPage({ params }: Props) {
const scripts = doc.querySelectorAll(
'script[type="application/ld+json"], script',
);
scripts.forEach((script) => script.remove());
for (const script of scripts) {
script.remove();
}

// Remover otros elementos no deseados
const unwantedElements = doc.querySelectorAll("style, meta, link");
unwantedElements.forEach((el) => el.remove());
for (const el of unwantedElements) {
el.remove();
}

return doc.body.innerHTML;
} else {
// Fallback para servidor - usar regex para limpiar
return html
.replace(
/<script[^>]*type="application\/ld\+json"[^>]*>[\s\S]*?<\/script>/gi,
"",
)
.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "")
.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "")
.replace(/<meta[^>]*>/gi, "")
.replace(/<link[^>]*>/gi, "");
}
// Fallback para servidor - usar regex para limpiar
return html
.replace(
/<script[^>]*type="application\/ld\+json"[^>]*>[\s\S]*?<\/script>/gi,
"",
)
.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "")
.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "")
.replace(/<meta[^>]*>/gi, "")
.replace(/<link[^>]*>/gi, "");
};

// Convertir HTML a Markdown
Expand Down Expand Up @@ -214,11 +217,8 @@ export default async function BlogPostPage({ params }: Props) {
className="object-cover max-w-lg mx-auto rounded-lg border max-lg:w-64 border-border overflow-hidden"
/>
),
code: ({
className,
children,
inline,
}: { className: string; children: React.ReactNode; inline: boolean }) => {
code: (props: any) => {
const { className, children, inline } = props;
console.log(className, children, inline);
// Si es código inline (no tiene className con language-*), renderizar como span
if (inline || !className || !/language-(\w+)/.test(className)) {
Expand Down
9 changes: 5 additions & 4 deletions apps/website/app/[locale]/blog/tag/[tag]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
export async function generateStaticParams() {
const tags = await getTags();

return tags.map((tag: { slug: string }) => ({
return (tags as Array<{ slug: string }>).map((tag) => ({
tag: tag.slug,
}));
}
Expand All @@ -39,7 +39,8 @@ export default async function TagPage({ params }: Props) {

// Get the tag name from the first post
const tagName =
posts[0].tags?.find((t: { slug: string }) => t.slug === tag)?.name || tag;
(posts as Post[])[0].tags?.find((t: { slug: string }) => t.slug === tag)
?.name || tag;

return (
<div className="container mx-auto px-4 py-12">
Expand Down Expand Up @@ -73,8 +74,8 @@ export default async function TagPage({ params }: Props) {
</div>

<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{posts.map((post: Post) => (
<BlogPostCard key={post.id} post={post} locale={locale} />
{(posts as Post[]).map((post: Post) => (
<BlogPostCard key={post.id} post={post} locale={params.locale} />
))}
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/website/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { GoogleAnalytics } from "@next/third-parties/google";
import clsx from "clsx";
import type { Metadata } from "next";
import { NextIntlClientProvider } from "next-intl";
import { getMessages } from "next-intl/server";
import { Inter, Lexend } from "next/font/google";
import type { ReactNode } from "react";
import { GoogleAnalytics } from "@next/third-parties/google";

type Props = {
children: ReactNode;
Expand Down
9 changes: 5 additions & 4 deletions apps/website/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
SelectItem,
SelectTrigger,
} from "@/components/ui/select";
import { Link, useRouter } from "@/i18n/routing";
import { Link, redirect, useRouter } from "@/i18n/routing";
import { useLocale, useTranslations } from "next-intl";
import type { SVGProps } from "react";
import { Container } from "./Container";
Expand Down Expand Up @@ -91,9 +91,10 @@ export function Footer() {
</Link>
<Select
onValueChange={(locale) => {
router.replace("/", {
locale: locale as "en" | "zh-Hans" | "fr" | "es",
});
// Force a full page reload with the correct locale URL
// For "as-needed" prefix, English uses "/" and other locales use "/{locale}"
const url = locale === "en" ? "/" : `/${locale}`;
window.location.href = url;
}}
value={locale}
>
Expand Down
22 changes: 2 additions & 20 deletions apps/website/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import { cn } from "@/lib/utils";
import { Popover, Transition } from "@headlessui/react";
import { ChevronRight, HeartIcon } from "lucide-react";
import { useTranslations } from "next-intl";
import { Fragment, type JSX, type SVGProps } from "react";
import { Fragment } from "react";
import { Container } from "./Container";
import { NavLink } from "./NavLink";
import { trackGAEvent } from "./analitycs";
import { Logo } from "./shared/Logo";
import AnimatedGradientText from "./ui/animated-gradient-text";
import { Button, buttonVariants } from "./ui/button";
import { Button } from "./ui/button";

function MobileNavLink({
href,
Expand Down Expand Up @@ -65,24 +65,6 @@ function MobileNavIcon({ open }: { open: boolean }) {
);
}

const I18nIcon = (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={24}
height={24}
fill="currentColor"
stroke="currentColor"
strokeWidth={0}
viewBox="0 0 512 512"
{...props}
>
<path
stroke="none"
d="m478.33 433.6-90-218a22 22 0 0 0-40.67 0l-90 218a22 22 0 1 0 40.67 16.79L316.66 406h102.67l18.33 44.39A22 22 0 0 0 458 464a22 22 0 0 0 20.32-30.4zM334.83 362 368 281.65 401.17 362zm-66.99-19.08a22 22 0 0 0-4.89-30.7c-.2-.15-15-11.13-36.49-34.73 39.65-53.68 62.11-114.75 71.27-143.49H330a22 22 0 0 0 0-44H214V70a22 22 0 0 0-44 0v20H54a22 22 0 0 0 0 44h197.25c-9.52 26.95-27.05 69.5-53.79 108.36-31.41-41.68-43.08-68.65-43.17-68.87a22 22 0 0 0-40.58 17c.58 1.38 14.55 34.23 52.86 83.93.92 1.19 1.83 2.35 2.74 3.51-39.24 44.35-77.74 71.86-93.85 80.74a22 22 0 1 0 21.07 38.63c2.16-1.18 48.6-26.89 101.63-85.59 22.52 24.08 38 35.44 38.93 36.1a22 22 0 0 0 30.75-4.9z"
/>
</svg>
);

function MobileNavigation() {
const t = useTranslations("HomePage");
const linkT = useTranslations("Link");
Expand Down
8 changes: 5 additions & 3 deletions apps/website/components/Testimonials.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";
import { cn } from "@/lib/utils";
import { useTranslations } from "next-intl";
import { Marquee } from "./ui/marquee";

// const testimonials = [
Expand Down Expand Up @@ -181,6 +182,8 @@ const ReviewCard = ({
};

export function Testimonials() {
const t = useTranslations("HomePage.testimonials");

return (
<section
id="testimonials"
Expand All @@ -189,11 +192,10 @@ export function Testimonials() {
>
<div className="mx-auto max-w-2xl md:text-center px-4">
<h2 className="font-display text-3xl tracking-tight sm:text-4xl text-center">
Why Developers Love Dokploy
{t("title")}
</h2>
<p className="mt-4 text-lg tracking-tight text-muted-foreground text-center">
Think we’re bragging? Hear from the devs who once doubted too—until
Dokploy made their lives (and deployments) surprisingly easier.
{t("description")}
</p>
</div>

Expand Down
69 changes: 29 additions & 40 deletions apps/website/components/first-features.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,91 +12,80 @@ import {
IconUsers,
} from "@tabler/icons-react";
import { Layers, Lock, UnlockIcon } from "lucide-react";
import { useTranslations } from "next-intl";

export function FirstFeaturesSection() {
const t = useTranslations("HomePage.firstFeatures");

const features = [
{
title: "Flexible Application Deployment",
description:
"Deploy any application using Nixpacks, Heroku Buildpacks, or your custom Dockerfile, tailored to your stack.",
title: t("features.flexibleDeployment.title"),
description: t("features.flexibleDeployment.description"),
icon: <IconRocket />,
},
{
title: "Native Docker Compose Support",
description:
"Deploy complex applications natively with full Docker Compose integration for seamless orchestration.",
title: t("features.dockerCompose.title"),
description: t("features.dockerCompose.description"),
icon: <Layers />,
},
{
title: "Multi-server Support",
description:
"Effortlessly deploy your applications on remote servers, with zero configuration hassle.",
title: t("features.multiServer.title"),
description: t("features.multiServer.description"),
icon: <IconCloud />,
},
{
title: "Advanced User Management",
description:
"Control user access with detailed roles and permissions, keeping your deployments secure and organized.",
title: t("features.userManagement.title"),
description: t("features.userManagement.description"),
icon: <IconUsers />,
},
{
title: "Database Management with Backups",
description:
"Manage and back up MySQL, PostgreSQL, MongoDB, MariaDB, Redis directly from Dokploy.",
title: t("features.databaseManagement.title"),
description: t("features.databaseManagement.description"),
icon: <IconDatabase />,
},
{
title: "API & CLI Access",
description:
"Need custom functionality? Dokploy offers complete API and CLI access to fit your needs.",
title: t("features.apiCli.title"),
description: t("features.apiCli.description"),
icon: <IconTerminal />,
},
{
title: "Docker Swarm Clusters",
description:
"Scale your deployments seamlessly with built-in Docker Swarm support for robust, multi-node applications.",
title: t("features.dockerSwarm.title"),
description: t("features.dockerSwarm.description"),
icon: <IconUsers />,
},
{
title: "Open Source Templates",
description:
"Get started quickly with pre-configured templates for popular tools like Supabase, Cal.com, and Pocketbase.",
title: t("features.templates.title"),
description: t("features.templates.description"),
icon: <IconTemplate />,
},
{
title: "No Vendor Lock-In",
description:
"Experience complete freedom to modify, scale, and customize Dokploy to suit your specific needs.",
title: t("features.noVendorLockIn.title"),
description: t("features.noVendorLockIn.description"),
icon: <UnlockIcon />,
},
{
title: "Real-time Monitoring & Alerts",
description:
"Monitor CPU, memory, and network usage in real-time across your deployments for full visibility.",
title: t("features.monitoring.title"),
description: t("features.monitoring.description"),
icon: <IconActivity />,
},
{
title: "Built for developers",
description:
"Designed specifically for engineers and developers seeking control and flexibility.",
title: t("features.builtForDevelopers.title"),
description: t("features.builtForDevelopers.description"),
icon: <IconTerminal2 />,
},
{
title: "Self-hosted & Open Source",
description:
"Dokploy provides complete control with self-hosting capabilities and open-source transparency.",
title: t("features.selfHosted.title"),
description: t("features.selfHosted.description"),
icon: <IconEaseInOut />,
},
];
return (
<div className="flex flex-col justify-center items-center mt-20 px-4">
<h2 className="font-display text-3xl tracking-tight text-primary sm:text-4xl text-center">
Powerful Deployment, Tailored for You
{t("title")}
</h2>
<p className="mt-4 text-lg tracking-tight text-muted-foreground text-center">
Unlock seamless multi-server deployments, advanced user control, and
flexible database management—all with Dokploy’s developer-focused
features.
{t("description")}
</p>
<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) => (
Expand Down
3 changes: 1 addition & 2 deletions apps/website/components/pricing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,7 @@ export function Pricing() {
/>
</div>
<p className="text-primary mb-2 text-left">
We Recommend to watch the video to understand the
benefits of Dokploy Cloud
{t("pricing.videoTooltip")}
</p>

<HeroVideoDialog
Expand Down
Loading