diff --git a/.gitignore b/.gitignore index f05287c..9386099 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,4 @@ sam3_src/ # Local processing & debug arrow_processing/ debug_output/ +TODO.md diff --git a/apps/web/next-env.d.ts b/apps/web/next-env.d.ts new file mode 100644 index 0000000..9edff1c --- /dev/null +++ b/apps/web/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +import "./.next/types/routes.d.ts"; + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/apps/web/next.config.ts b/apps/web/next.config.ts new file mode 100644 index 0000000..3fae878 --- /dev/null +++ b/apps/web/next.config.ts @@ -0,0 +1,11 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + output: 'export', + distDir: 'dist', + images: { + unoptimized: true, + }, +}; + +export default nextConfig; diff --git a/apps/web/package.json b/apps/web/package.json new file mode 100644 index 0000000..120756d --- /dev/null +++ b/apps/web/package.json @@ -0,0 +1,34 @@ +{ + "name": "web", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "eslint" + }, + "dependencies": { + "@vercel/analytics": "^1.5.0", + "axios": "^1.13.6", + "clsx": "^2.1.1", + "framer-motion": "^12.35.2", + "lucide-react": "^0.577.0", + "next": "16.1.6", + "react": "19.2.3", + "react-dom": "19.2.3", + "react-dropzone": "^15.0.0", + "socket.io-client": "^4.8.3", + "tailwind-merge": "^3.5.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "16.1.6", + "tailwindcss": "^4", + "typescript": "^5" + } +} diff --git a/apps/web/postcss.config.mjs b/apps/web/postcss.config.mjs new file mode 100644 index 0000000..5d6d845 --- /dev/null +++ b/apps/web/postcss.config.mjs @@ -0,0 +1,8 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + '@tailwindcss/postcss': {}, + }, +}; + +export default config; diff --git a/apps/web/src/app/globals.css b/apps/web/src/app/globals.css new file mode 100644 index 0000000..f38c098 --- /dev/null +++ b/apps/web/src/app/globals.css @@ -0,0 +1,23 @@ +@import "tailwindcss"; + +:root { + --background: #ffffff; + --foreground: #171717; +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +html { + scroll-behavior: smooth; +} + +body { + color: var(--foreground); + background: var(--background); + font-family: var(--font-geist-sans), system-ui, sans-serif; +} diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx new file mode 100644 index 0000000..26f28b7 --- /dev/null +++ b/apps/web/src/app/layout.tsx @@ -0,0 +1,110 @@ +import type { Metadata } from "next"; +import { Geist, Geist_Mono } from "next/font/google"; +import { Analytics } from "@vercel/analytics/react"; +import "./globals.css"; + +const geistSans = Geist({ + variable: "--font-geist-sans", + subsets: ["latin"], +}); + +const geistMono = Geist_Mono({ + variable: "--font-geist-mono", + subsets: ["latin"], +}); + +export const metadata: Metadata = { + title: "EditBanana - Convert Images to Editable Diagrams | AI-Powered", + description: "Transform static diagrams, flowcharts, and architecture images into fully editable DrawIO files. AI-powered conversion with 99% accuracy. Free to try!", + keywords: "diagram converter, image to editable, flowchart OCR, architecture diagram tool, diagram to drawio, convert image to diagram", + authors: [{ name: "BIT DataLab" }], + creator: "BIT DataLab", + publisher: "EditBanana", + metadataBase: new URL("https://editbanana.anxin6.cn"), + alternates: { + canonical: "/", + }, + openGraph: { + type: "website", + locale: "en_US", + url: "https://editbanana.anxin6.cn", + siteName: "EditBanana", + title: "EditBanana - Convert Images to Editable Diagrams", + description: "Transform static diagrams into fully editable DrawIO files with AI. 99% accuracy, free to try!", + images: [ + { + url: "/og-image.png", + width: 1200, + height: 630, + alt: "EditBanana - AI Diagram Converter", + }, + ], + }, + twitter: { + card: "summary_large_image", + title: "EditBanana - Convert Images to Editable Diagrams", + description: "Transform static diagrams into fully editable DrawIO files with AI. 99% accuracy, free to try!", + images: ["/og-image.png"], + creator: "@editbanana", + }, + robots: { + index: true, + follow: true, + googleBot: { + index: true, + follow: true, + "max-video-preview": -1, + "max-image-preview": "large", + "max-snippet": -1, + }, + }, + verification: { + google: "google-site-verification-code", + }, +}; + +// JSON-LD structured data for SoftwareApplication +const jsonLd = { + "@context": "https://schema.org", + "@type": "SoftwareApplication", + name: "EditBanana", + applicationCategory: "GraphicsApplication", + operatingSystem: "Web", + description: "AI-powered tool to convert images and PDFs to editable DrawIO diagrams", + offers: { + "@type": "Offer", + price: "0", + priceCurrency: "USD", + description: "Free to try", + }, + aggregateRating: { + "@type": "AggregateRating", + ratingValue: "4.8", + ratingCount: "100", + }, + url: "https://editbanana.anxin6.cn", + screenshot: "https://editbanana.anxin6.cn/og-image.png", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + +