Skip to content
Merged
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
56 changes: 56 additions & 0 deletions app/i18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import i18n from "i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import { initReactI18next } from "react-i18next";
import supportedByEN from "../public/locales/en/supportedBy.json";
import supportedByES from "../public/locales/es/supportedBy.json";
import navbarEN from "../public/locales/en/navbar.json";
import navbarES from "../public/locales/es/navbar.json";
import heroEN from "../public/locales/en/hero.json";
import heroES from "../public/locales/es/hero.json";
import featuresEN from "../public/locales/en/features.json";
import featuresES from "../public/locales/es/features.json";
import downloadEN from "../public/locales/en/download.json";
import downloadES from "../public/locales/es/download.json";
import communityEN from "../public/locales/en/community.json";
import communityES from "../public/locales/es/community.json";
import contactEN from "../public/locales/en/contact.json";
import contactES from "../public/locales/es/contact.json";
import footerEN from "../public/locales/en/footer.json";
import footerES from "../public/locales/es/footer.json";


i18n
.use(initReactI18next)
.use(LanguageDetector)
.init({
resources: {
en: {
navbar: navbarEN,
hero: heroEN,
supportedBy: supportedByEN,
features: featuresEN,
download: downloadEN,
community: communityEN,
contact: contactEN,
footer: footerEN,
},
es: {
navbar: navbarES,
hero: heroES,
supportedBy: supportedByES,
features: featuresES,
download: downloadES,
community: communityES,
contact: contactES,
footer: footerES,
}
},
supportedLngs: ["en", "es"],
fallbackLng: "en",

interpolation: {
escapeValue: false
}
});

export default i18n;
3 changes: 3 additions & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client"

import { Navbar } from "@/components/navbar"
import { HeroSection } from "@/components/hero-section"
import { FeaturesSection } from "@/components/features-section"
Expand All @@ -7,6 +9,7 @@ import { SupportedBySection } from "@/components/supported-by-section"
import { CommunitySection } from "@/components/community-section"
import { ContactSection } from "@/components/contact-section"
import { Footer } from "@/components/footer"
import "./i18n"

export default function Home() {
return (
Expand Down
39 changes: 25 additions & 14 deletions components/community-section.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
"use client"

import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import { Github, BookOpen, Code2, Package } from "lucide-react"
import { siteConfig } from "@/lib/config"
import { useTranslation } from "react-i18next"

const communityLinks = [
{
icon: Github,
title: "GitHub",
description: "Explore the source code",
key: "github",
defaultTitle: "GitHub",
defaultDescription: "Explore the source code",
link: siteConfig.github.url,
// stats: "2.5k stars",
},
Expand All @@ -22,50 +23,60 @@ const communityLinks = [
// },
{
icon: BookOpen,
title: "Docs",
description: "Visit the technical documentation",
key: "docs",
defaultTitle: "Docs",
defaultDescription: "Visit the technical documentation",
link: siteConfig.docs.url,
// stats: "Complete guides",
},
{
icon: Code2,
title: "Contribute",
description: "Improve the project",
key: "contribute",
defaultTitle: "Contribute",
defaultDescription: "Improve the project",
link: siteConfig.github.contribute,
// stats: "Open to all",
},
]

export function CommunitySection() {
const { t } = useTranslation()
return (
<section id="community" className="py-24 px-4">
<div className="container mx-auto">
<div className="text-center mb-16">
<h2 className="text-3xl md:text-5xl font-bold mb-4 text-balance">
{"Built and extended by the community"}
{t("community:title", { defaultValue: "Built and extended by the community" })}
</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto leading-relaxed">
{
"DashAI's plugin architecture enables anyone to contribute new capabilities. Build plugins, improve the core, and shape the future of open source AI tools."
}
{t("community:description", {
defaultValue:
"DashAI's plugin architecture enables anyone to contribute new capabilities. Build plugins, improve the core, and shape the future of open source AI tools.",
})}
</p>
</div>

<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-3 gap-6 mb-12">
{communityLinks.map((item, index) => {
const Icon = item.icon
const title = t(`community:cards.${item.key}.title`, {
defaultValue: item.defaultTitle,
})
const description = t(`community:cards.${item.key}.description`, {
defaultValue: item.defaultDescription,
})
return (
<Card
key={index}
key={item.key}
className="bg-card border-border hover:border-primary/50 transition-all duration-300 cursor-pointer group"
onClick={() => window.open(item.link, "_blank", "noopener,noreferrer")}
>
<CardContent className="p-6 text-center">
<div className="w-14 h-14 rounded-xl bg-primary/10 flex items-center justify-center mx-auto mb-4 group-hover:bg-primary/20 transition-colors">
<Icon className="h-7 w-7 text-primary" />
</div>
<h3 className="text-xl font-semibold mb-2">{item.title}</h3>
<p className="text-muted-foreground mb-3 text-sm leading-relaxed">{item.description}</p>
<h3 className="text-xl font-semibold mb-2">{title}</h3>
<p className="text-muted-foreground mb-3 text-sm leading-relaxed">{description}</p>
<span className="text-xs text-primary font-mono">{item.stats}</span>
</CardContent>
</Card>
Expand Down
26 changes: 18 additions & 8 deletions components/contact-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import { useState } from 'react'
import { Button } from '@/components/ui/button'
import { useTranslation } from 'react-i18next'

export function ContactSection() {
const { t } = useTranslation()
const [formData, setFormData] = useState({
name: '',
email: '',
Expand Down Expand Up @@ -67,10 +69,12 @@ export function ContactSection() {
<div className="max-w-2xl mx-auto">
<div className="text-center mb-12">
<h2 className="text-4xl md:text-5xl font-bold mb-4">
Contact Us
{t('contact:title', { defaultValue: 'Contact Us' })}
</h2>
<p className="text-muted-foreground text-lg">
Have questions or feedback about DashAI? Feel free to get in touch — we’d love to hear from you.
{t('contact:description', {
defaultValue: 'Have questions or feedback about DashAI? Feel free to get in touch — we’d love to hear from you.',
})}
</p>
</div>

Expand All @@ -79,7 +83,7 @@ export function ContactSection() {
<input
type="text"
name="name"
placeholder="Name"
placeholder={t('contact:fields.name', { defaultValue: 'Name' })}
value={formData.name}
onChange={handleChange}
required
Expand All @@ -91,7 +95,7 @@ export function ContactSection() {
<input
type="email"
name="email"
placeholder="Email"
placeholder={t('contact:fields.email', { defaultValue: 'Email' })}
value={formData.email}
onChange={handleChange}
required
Expand All @@ -102,7 +106,7 @@ export function ContactSection() {
<div>
<textarea
name="message"
placeholder="Message"
placeholder={t('contact:fields.message', { defaultValue: 'Message' })}
value={formData.message}
onChange={handleChange}
required
Expand All @@ -116,18 +120,24 @@ export function ContactSection() {
disabled={status === 'sending'}
className="w-full py-6 text-lg font-medium cursor-pointer"
>
{status === 'sending' ? 'Sending...' : status === 'success' ? 'Sent!' : 'Send message'}
{status === 'sending'
? t('contact:status.sending', { defaultValue: 'Sending...' })
: status === 'success'
? t('contact:status.sent', { defaultValue: 'Sent!' })
: t('contact:status.idle', { defaultValue: 'Send message' })}
</Button>

{status === 'success' && (
<p className="text-center text-primary animate-in fade-in duration-300">
Thank you for contacting us! We will get back to you soon.
{t('contact:feedback.success', {
defaultValue: 'Thank you for contacting us! We will get back to you soon.',
})}
</p>
)}

{status === 'error' && (
<p className="text-center text-red-500 animate-in fade-in duration-300">
There was an error. Please try again.
{t('contact:feedback.error', { defaultValue: 'There was an error. Please try again.' })}
</p>
)}
</form>
Expand Down
70 changes: 45 additions & 25 deletions components/download-section.tsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,85 @@
"use client"

import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import { Download, Terminal, Package } from "lucide-react"
import { Download, Package } from "lucide-react"
import { useTranslation } from "react-i18next"

const downloads = [
{
icon: Package,
platform: "macOS Intel processors",
key: "macIntel",
defaultPlatform: "macOS Intel processors",
version: "v0.1.15",
size: "487 MB",
format: "binary",
defaultFormat: "binary",
link: "https://dashai.nyc3.cdn.digitaloceanspaces.com/executables/DashAI-launcher-cpu-x86_64",
},
{
icon: Package,
platform: "macOS ARM processors",
key: "macArm",
defaultPlatform: "macOS ARM processors",
version: "v0.1.15",
size: "381 MB",
format: "binary",
defaultFormat: "binary",
link: "https://dashai.nyc3.cdn.digitaloceanspaces.com/executables/DashAI-launcher-cpu-arm64",
},
{
icon: Package,
platform: "Windows",
key: "windows",
defaultPlatform: "Windows",
version: "v0.1.15",
size: "434 MB",
format: ".exe",
defaultFormat: ".exe",
link: "https://dashai.nyc3.cdn.digitaloceanspaces.com/executables/DashAI-launcher-cpu.exe",
},
// {
// icon: Package,
// platform: "Docker",
// version: "latest",
// size: "~300 MB",
// format: "container",
// link: "#",
// },
]

export function DownloadSection() {
const { t } = useTranslation()
return (
<section id="download" className="py-24 px-4 bg-secondary/30">
<div className="container mx-auto">
<div className="text-center mb-16">
<h2 className="text-3xl md:text-5xl font-bold mb-2 text-balance">Download DashAI</h2>
<span className="block text-base text-primary font-semibold mb-4">Beta Version</span>
<h2 className="text-3xl md:text-5xl font-bold mb-2 text-balance">
{t("download:title", { defaultValue: "Download DashAI" })}
</h2>
<span className="block text-base text-primary font-semibold mb-4">
{t("download:badge", { defaultValue: "Beta Version" })}
</span>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto leading-relaxed">
This early version lets you explore DashAI’s main features. We appreciate your feedback to help us improve before the official release.
{t("download:description", {
defaultValue:
"This early version lets you explore DashAI’s main features. We appreciate your feedback to help us improve before the official release.",
})}
</p>
</div>

<div className="max-w-5xl mx-auto">
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12">
{downloads.map((download, index) => {
const Icon = download.icon
const platform = t(`download:cards.${download.key}.platform`, {
defaultValue: download.defaultPlatform,
})
const format = t(`download:cards.${download.key}.format`, {
defaultValue: download.defaultFormat,
})
return (
<Card
key={index}
key={download.key}
className="bg-card border-border hover:border-primary/50 transition-all duration-300 group cursor-pointer"
>
<CardContent className="p-6">
<div className="w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center mb-4 group-hover:bg-primary/20 transition-colors">
<Icon className="h-6 w-6 text-primary" />
</div>
<h3 className="text-xl font-semibold mb-2">{download.platform}</h3>
<h3 className="text-xl font-semibold mb-2">{platform}</h3>
<div className="space-y-1 mb-4">
<p className="text-sm text-muted-foreground">
{download.version} • {download.size}
</p>
<p className="text-xs text-muted-foreground font-mono">{download.format}</p>
<p className="text-xs text-muted-foreground font-mono">{format}</p>
</div>
<Button
className="w-full bg-primary hover:bg-primary/90 text-primary-foreground cursor-pointer"
Expand All @@ -76,7 +88,7 @@ export function DownloadSection() {
>
<a href={download.link} download>
<Download className="mr-2 h-4 w-4" />
Download
{t("download:button", { defaultValue: "Download" })}
</a>
</Button>
</CardContent>
Expand All @@ -89,12 +101,20 @@ export function DownloadSection() {
<CardContent className="p-8">
<div className="flex flex-col md:flex-row items-center justify-between gap-6">
<div>
<h3 className="text-xl font-semibold mb-2">Install via pip</h3>
<p className="text-muted-foreground text-sm">For developers who prefer command-line installation</p>
<h3 className="text-xl font-semibold mb-2">
{t("download:pip.title", { defaultValue: "Install via pip" })}
</h3>
<p className="text-muted-foreground text-sm">
{t("download:pip.subtitle", {
defaultValue: "For developers who prefer command-line installation",
})}
</p>
</div>
<div className="w-full md:w-auto">
<div className="bg-secondary/50 rounded-lg p-4 font-mono text-sm border border-border">
<code className="text-primary">pip install dashai</code>
<code className="text-primary">
{t("download:pip.command", { defaultValue: "pip install dashai" })}
</code>
</div>
</div>
</div>
Expand Down
Loading
Loading