diff --git a/.DS_Store b/.DS_Store index 0fb5f74..35a3b20 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..ac47ff6 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,61 @@ +name: Deploy to GitHub Pages + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 8 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install + + - name: Build + run: pnpm build + + - name: Setup Pages + uses: actions/configure-pages@v4 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: './out' + + deploy: + environment: + name: github-pages + url: https://www.dash-ai.com/ + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + diff --git a/.gitignore b/.gitignore index 0e4802d..b0d93fb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,47 @@ -*.DS_Store +__pycache__ + + +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +frontend/.next/ +frontend/node_modules +.next/ +/out/ + +# production +/build + +# misc .DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env +backend/.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +backend/data/new_docs_test +.next +.vscode \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..538d1cf --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM node:20.16.0-bullseye-slim + +# Instalar pnpm +RUN npm install -g pnpm + +WORKDIR /app + +# Copiar archivos de dependencias +COPY package.json pnpm-lock.yaml ./ + +# Instalar dependencias con pnpm +RUN pnpm install +COPY . . + +#RUN pnpm run build + +CMD ["pnpm", "run", "dev"] diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..1f0dab6 --- /dev/null +++ b/app/globals.css @@ -0,0 +1,124 @@ +@import "tailwindcss"; +@import "tw-animate-css"; + +@custom-variant dark (&:is(.dark *)); + +:root { + --background: oklch(0.98 0 0); + --foreground: oklch(0.98 0 0); + --card: oklch(0.12 0 0); + --card-foreground: oklch(0.98 0 0); + --popover: oklch(0.12 0 0); + --popover-foreground: oklch(0.98 0 0); + --primary: oklch(0.75 0.18 195); + --primary-foreground: oklch(0.1 0 0); + --secondary: oklch(0.28 0 0); + --secondary-foreground: oklch(0.98 0 0); + --muted: oklch(0.22 0 0); + --muted-foreground: oklch(0.65 0 0); + --accent: oklch(0.65 0.18 45); + --accent-foreground: oklch(0.1 0 0); + --destructive: oklch(0.577 0.245 27.325); + --destructive-foreground: oklch(0.985 0 0); + --border: oklch(0.28 0 0); + --input: oklch(0.28 0 0); + --ring: oklch(0.75 0.18 195); + --chart-1: oklch(0.75 0.18 195); + --chart-2: oklch(0.65 0.18 45); + --chart-3: oklch(0.6 0.15 240); + --chart-4: oklch(0.7 0.15 280); + --chart-5: oklch(0.55 0.12 210); + --radius: 0.75rem; + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} + +.dark { + --background: oklch(0.08 0 0); + --foreground: oklch(0.98 0 0); + --card: oklch(0.12 0 0); + --card-foreground: oklch(0.98 0 0); + --popover: oklch(0.12 0 0); + --popover-foreground: oklch(0.98 0 0); + --primary: oklch(0.75 0.18 195); + --primary-foreground: oklch(0.1 0 0); + --secondary: oklch(0.28 0 0); + --secondary-foreground: oklch(0.98 0 0); + --muted: oklch(0.22 0 0); + --muted-foreground: oklch(0.65 0 0); + --accent: oklch(0.65 0.18 45); + --accent-foreground: oklch(0.1 0 0); + --destructive: oklch(0.577 0.245 27.325); + --destructive-foreground: oklch(0.985 0 0); + --border: oklch(0.28 0 0); + --input: oklch(0.28 0 0); + --ring: oklch(0.75 0.18 195); + --chart-1: oklch(0.75 0.18 195); + --chart-2: oklch(0.65 0.18 45); + --chart-3: oklch(0.6 0.15 240); + --chart-4: oklch(0.7 0.15 280); + --chart-5: oklch(0.55 0.12 210); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(0.269 0 0); + --sidebar-ring: oklch(0.439 0 0); +} + +@theme inline { + /* optional: --font-sans, --font-serif, --font-mono if they are applied in the layout.tsx */ + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..070369f --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,43 @@ +import type React from "react" +import type { Metadata } from "next" +import { Geist, Geist_Mono } from "next/font/google" +import { Analytics } from "@vercel/analytics/next" +import "./globals.css" + +const _geist = Geist({ subsets: ["latin"] }) +const _geistMono = Geist_Mono({ subsets: ["latin"] }) + +export const metadata: Metadata = { + title: "DashAI - Plataforma Open Source de IA", + description: + "Integra, experimenta y visualiza modelos de IA mediante una interfaz visual intuitiva. Democratizando el acceso al machine learning.", + generator: "v0.app", + icons: { + icon: [ + { + url: "/icon-light-32x32.png", + media: "(prefers-color-scheme: light)", + }, + { + url: "/icon-dark-32x32.png", + media: "(prefers-color-scheme: dark)", + }, + ], + apple: "/apple-icon.png", + }, +} + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode +}>) { + return ( + + + {children} + + + + ) +} diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..805f9f3 --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,24 @@ +import { Navbar } from "@/components/navbar" +import { HeroSection } from "@/components/hero-section" +import { FeaturesSection } from "@/components/features-section" +//import { ModulesCarousel } from "@/components/modules-carousel" +import { DownloadSection } from "@/components/download-section" +import { SupportedBySection } from "@/components/supported-by-section" +import { CommunitySection } from "@/components/community-section" +import { ContactSection } from "@/components/contact-section" +import { Footer } from "@/components/footer" + +export default function Home() { + return ( +
+ + + + + + + +
+
+ ) +} diff --git a/components.json b/components.json new file mode 100644 index 0000000..4ee62ee --- /dev/null +++ b/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} diff --git a/components/community-section.tsx b/components/community-section.tsx new file mode 100644 index 0000000..2f3c559 --- /dev/null +++ b/components/community-section.tsx @@ -0,0 +1,110 @@ +"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" + +const communityLinks = [ + { + icon: Github, + title: "GitHub", + description: "Explore the source code", + link: siteConfig.github.url, + // stats: "2.5k stars", + }, + // { + // icon: Package, + // title: "Plugin Hub", + // description: "Browse community plugins", + // link: siteConfig.resources.pluginHub, + // // stats: "100+ plugins", + // }, + { + icon: BookOpen, + title: "Docs", + description: "Visit the technical documentation", + link: siteConfig.docs.url, + // stats: "Complete guides", + }, + { + icon: Code2, + title: "Contribute", + description: "Improve the project", + link: siteConfig.github.contribute, + // stats: "Open to all", + }, +] + +export function CommunitySection() { + return ( +
+
+
+

+ {"Built and extended by the community"} +

+

+ { + "DashAI's plugin architecture enables anyone to contribute new capabilities. Build plugins, improve the core, and shape the future of open source AI tools." + } +

+
+ +
+ {communityLinks.map((item, index) => { + const Icon = item.icon + return ( + window.open(item.link, "_blank", "noopener,noreferrer")} + > + +
+ +
+

{item.title}

+

{item.description}

+ {item.stats} +
+
+ ) + })} +
+ + {/* + +

{"Ready to build your first plugin?"}

+

+ { + "Our comprehensive documentation guides you through creating plugins and contributing to the core platform" + } +

+ +
+
*/} +
+
+ ) +} diff --git a/components/contact-section.tsx b/components/contact-section.tsx new file mode 100644 index 0000000..4bce56c --- /dev/null +++ b/components/contact-section.tsx @@ -0,0 +1,137 @@ +'use client' + +import { useState } from 'react' +import { Button } from '@/components/ui/button' + +export function ContactSection() { + const [formData, setFormData] = useState({ + name: '', + email: '', + message: '', + }) + const [status, setStatus] = useState<'idle' | 'sending' | 'success' | 'error'>('idle') + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + setStatus('sending') + + try { + const formPayload = { + name: formData.name, + email: formData.email, + message: formData.message, + _subject: `Nuevo mensaje de contacto de DashAI - ${formData.name}`, + } + + console.log('Sending form data:', formPayload) + + const response = await fetch(`https://formspree.io/f/mnnwakle`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + body: JSON.stringify(formPayload), + }) + + const responseData = await response.json() + console.log('Formspree response:', response.status, responseData) + + if (response.ok) { + setStatus('success') + setFormData({ name: '', email: '', message: '' }) + setTimeout(() => setStatus('idle'), 5000) + } else { + // Mostrar error más específico + const errorMessage = responseData.error || responseData.message || 'Error al enviar el mensaje' + console.error('Formspree error:', responseData) + setStatus('error') + setTimeout(() => setStatus('idle'), 5000) + } + } catch (error) { + console.error('Form submission error:', error) + setStatus('error') + setTimeout(() => setStatus('idle'), 3000) + } + } + + const handleChange = (e: React.ChangeEvent) => { + setFormData(prev => ({ + ...prev, + [e.target.name]: e.target.value + })) + } + + return ( +
+
+
+

+ Contact Us +

+

+ Have questions or feedback about DashAI? Feel free to get in touch — we’d love to hear from you. +

+
+ +
+
+ +
+ +
+ +
+ +
+