161 lines
8.8 KiB
TypeScript
161 lines
8.8 KiB
TypeScript
"use client";
|
|
|
|
import { useRef } from "react";
|
|
import { ScrollReveal } from "@/components/ScrollReveal";
|
|
import { SectionScrollTitle } from "@/components/SectionScrollTitle";
|
|
import { DOCKER_HUB_URL, GITEA_URL } from "@/lib/plans";
|
|
|
|
function DockerIcon({ className }: { className?: string }) {
|
|
return (
|
|
<svg className={className} viewBox="0 0 24 24" role="img" aria-label="Docker">
|
|
<path
|
|
fill="#2496ED"
|
|
d="M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.185.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.185.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.185.185 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.185.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.082.185.185.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288Z"
|
|
/>
|
|
</svg>
|
|
);
|
|
}
|
|
|
|
function GiteaIcon({ className }: { className?: string }) {
|
|
return (
|
|
<svg className={className} viewBox="0 0 24 24" role="img" aria-label="Gitea">
|
|
<path
|
|
fill="#609926"
|
|
d="M4.209 4.603c-.247 0-.525.02-.84.088-.333.07-1.28.283-2.054 1.027C-.403 7.25.035 9.685.089 10.052c.065.446.263 1.687 1.21 2.768 1.749 2.141 5.513 2.092 5.513 2.092s.462 1.103 1.168 2.119c.955 1.263 1.936 2.248 2.89 2.367 2.406 0 7.212-.004 7.212-.004s.458.004 1.08-.394c.535-.324 1.013-.893 1.013-.893s.492-.527 1.18-1.73c.21-.37.385-.729.538-1.068 0 0 2.107-4.471 2.107-8.823-.042-1.318-.367-1.55-.443-1.627-.156-.156-.366-.153-.366-.153s-4.475.252-6.792.306c-.508.011-1.012.023-1.512.027v4.474l-.634-.301c0-1.39-.004-4.17-.004-4.17-1.107.016-3.405-.084-3.405-.084s-5.399-.27-5.987-.324c-.187-.011-.401-.032-.648-.032zm.354 1.832h.111s.271 2.269.6 3.597C5.549 11.147 6.22 13 6.22 13s-.996-.119-1.641-.348c-.99-.324-1.409-.714-1.409-.714s-.73-.511-1.096-1.52C1.444 8.73 2.021 7.7 2.021 7.7s.32-.859 1.47-1.145c.395-.106.863-.12 1.072-.12zm8.33 2.554c.26.003.509.127.509.127l.868.422-.529 1.075a.686.686 0 0 0-.614.359.685.685 0 0 0 .072.756l-.939 1.924a.69.69 0 0 0-.66.527.687.687 0 0 0 .347.763.686.686 0 0 0 .867-.206.688.688 0 0 0-.069-.882l.916-1.874a.667.667 0 0 0 .237-.02.657.657 0 0 0 .271-.137 8.826 8.826 0 0 1 1.016.512.761.761 0 0 1 .286.282c.073.21-.073.569-.073.569-.087.29-.702 1.55-.702 1.55a.692.692 0 0 0-.676.477.681.681 0 1 0 1.157-.252c.073-.141.141-.282.214-.431.19-.397.515-1.16.515-1.16.035-.066.218-.394.103-.814-.095-.435-.48-.638-.48-.638-.467-.301-1.116-.58-1.116-.58s0-.156-.042-.27a.688.688 0 0 0-.148-.241l.516-1.062 2.89 1.401s.48.218.583.619c.073.282-.019.534-.069.657-.24.587-2.1 4.317-2.1 4.317s-.232.554-.748.588a1.065 1.065 0 0 1-.393-.045l-.202-.08-4.31-2.1s-.417-.218-.49-.596c-.083-.31.104-.691.104-.691l2.073-4.272s.183-.37.466-.497a.855.855 0 0 1 .35-.077z"
|
|
/>
|
|
</svg>
|
|
);
|
|
}
|
|
|
|
const DEPLOY_CARDS = [
|
|
{
|
|
name: "Docker Hub",
|
|
desc: "Pull the image and run Songs2YT on your own server with Docker Compose.",
|
|
Icon: DockerIcon,
|
|
cta: "View on Docker Hub",
|
|
href: DOCKER_HUB_URL,
|
|
accent: "text-[#2496ED]",
|
|
hover:
|
|
"hover:border-[#2496ED]/45 hover:bg-[#2496ED]/[0.06] hover:shadow-lg hover:shadow-[#2496ED]/20",
|
|
titleHover: "group-hover:text-[#2496ED]",
|
|
},
|
|
{
|
|
name: "Gitea",
|
|
desc: "Clone the open-source repository and deploy from source on your infrastructure.",
|
|
Icon: GiteaIcon,
|
|
cta: "View on Gitea",
|
|
href: GITEA_URL,
|
|
accent: "text-[#609926]",
|
|
hover:
|
|
"hover:border-[#609926]/45 hover:bg-[#609926]/[0.06] hover:shadow-lg hover:shadow-[#609926]/20",
|
|
titleHover: "group-hover:text-[#609926]",
|
|
},
|
|
] as const;
|
|
|
|
function DeployCard({
|
|
name,
|
|
desc,
|
|
Icon,
|
|
cta,
|
|
href,
|
|
accent,
|
|
hover,
|
|
titleHover,
|
|
}: (typeof DEPLOY_CARDS)[number]) {
|
|
return (
|
|
<a
|
|
href={href}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className={`group block rounded-xl border border-gray-700/50 bg-surface p-6 transition-all duration-300 ${hover}`}
|
|
>
|
|
<div className="mb-4 flex items-center justify-between">
|
|
<Icon className="h-8 w-8 transition-transform duration-300 group-hover:scale-110" />
|
|
<span className="rounded bg-gray-800 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider text-gray-500 transition-colors duration-300 group-hover:bg-gray-700/80">
|
|
Open Source
|
|
</span>
|
|
</div>
|
|
<h3 className={`text-lg font-semibold text-white transition-colors duration-300 ${titleHover}`}>
|
|
{name}
|
|
</h3>
|
|
<p className="mt-2 text-sm leading-relaxed text-gray-400 transition-colors duration-300 group-hover:text-gray-300">
|
|
{desc}
|
|
</p>
|
|
<p className={`mt-4 text-sm font-medium ${accent} transition-all duration-300 group-hover:underline`}>
|
|
{cta}
|
|
</p>
|
|
</a>
|
|
);
|
|
}
|
|
|
|
export function DownloadSection() {
|
|
const sectionRef = useRef<HTMLElement>(null);
|
|
|
|
return (
|
|
<section
|
|
ref={sectionRef}
|
|
id="download"
|
|
className="relative scroll-mt-24 overflow-x-visible overflow-y-hidden px-6 py-24"
|
|
>
|
|
<SectionScrollTitle sectionRef={sectionRef} title="Download" />
|
|
|
|
<div className="relative z-10 mx-auto max-w-7xl">
|
|
<ScrollReveal>
|
|
<h2 className="mb-4 text-center text-3xl font-bold text-white">Download</h2>
|
|
<p className="mx-auto mb-12 max-w-2xl text-center text-gray-400">
|
|
Songs2YT is open source. Self-host on your own server with Docker or deploy from source.
|
|
</p>
|
|
</ScrollReveal>
|
|
|
|
<div className="grid items-start gap-10 lg:grid-cols-[1fr_1.1fr] lg:gap-12">
|
|
<ScrollReveal direction="left">
|
|
<div className="space-y-6">
|
|
<div>
|
|
<h3 className="text-xl font-semibold text-white">Run it yourself</h3>
|
|
<p className="mt-3 leading-relaxed text-gray-400">
|
|
Host Songs2YT on your infrastructure with full control over data, queues, and
|
|
storage. Ideal for teams and creators who want a private deployment.
|
|
</p>
|
|
</div>
|
|
|
|
<ul className="space-y-3 text-sm text-gray-400">
|
|
<li className="flex items-start gap-3">
|
|
<span className="mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-red-500" />
|
|
Docker image published to Docker Hub
|
|
</li>
|
|
<li className="flex items-start gap-3">
|
|
<span className="mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-red-500" />
|
|
Source code available on Gitea
|
|
</li>
|
|
<li className="flex items-start gap-3">
|
|
<span className="mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-red-500" />
|
|
Gitea Issues community support
|
|
</li>
|
|
<li className="flex items-start gap-3">
|
|
<span className="mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-red-500" />
|
|
PostgreSQL, Redis, FFmpeg, and worker included
|
|
</li>
|
|
</ul>
|
|
|
|
<div className="rounded-xl border border-gray-700/50 bg-surface-dark p-4">
|
|
<p className="mb-3 text-xs font-medium text-gray-500">Quick start</p>
|
|
<pre className="overflow-x-auto text-sm leading-relaxed text-gray-300">
|
|
<code>{`docker pull atakanozban/songs2yt:latest\ndocker compose up -d`}</code>
|
|
</pre>
|
|
</div>
|
|
</div>
|
|
</ScrollReveal>
|
|
|
|
<div className="grid gap-5 sm:grid-cols-2 lg:grid-cols-1">
|
|
{DEPLOY_CARDS.map((card, index) => (
|
|
<ScrollReveal key={card.name} delay={index * 120} direction="right">
|
|
<DeployCard {...card} />
|
|
</ScrollReveal>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|