diff --git a/www/.gitignore b/www/.gitignore new file mode 100644 index 00000000..5ef6a520 --- /dev/null +++ b/www/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/www/README.md b/www/README.md new file mode 100644 index 00000000..e215bc4c --- /dev/null +++ b/www/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/www/biome.json b/www/biome.json new file mode 100644 index 00000000..41b3b952 --- /dev/null +++ b/www/biome.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.2.0/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": true, + "includes": ["**", "!node_modules", "!.next", "!dist", "!build"] + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2 + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "suspicious": { + "noUnknownAtRules": "off" + } + }, + "domains": { + "next": "recommended", + "react": "recommended" + } + }, + "assist": { + "actions": { + "source": { + "organizeImports": "on" + } + } + } +} diff --git a/www/components.json b/www/components.json new file mode 100644 index 00000000..edcaef26 --- /dev/null +++ b/www/components.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "registries": {} +} diff --git a/www/index.html b/www/index.html deleted file mode 100644 index 47da445f..00000000 --- a/www/index.html +++ /dev/null @@ -1,264 +0,0 @@ - - - - - - - Arch - Intelligent Prompt Gateway - - - - - -
- GitHub - Docs - Discord - Contact -
-
-
- Arch Gateway Logo -
- Arch - Build fast, hyper-personalized agents with intelligent infra | Product Hunt -
Build fast, observable, and personalized agents
-
Arch is an intelligent gateway designed to protect, observe and personalize AI agents with your APIs
-
- Get Started - Documentation -
-
-
-

Why Arch?

-

Arch is built on (and by the core contributors of) Envoy proxy with the belief that: -

-

Prompts are nuanced and opaque user requests, which require the same capabilities as traditional HTTP requests - including secure handling, intelligent routing, robust observability, and seamless integration with backend (API) - systems for personalization — all outside business logic.

-
-
-

Key Features

-
-
-

Out-of-process architecture, built on Envoy

- Arch takes a dependency on Envoy and is a self-contained process designed to run alongside your application servers. - Arch extend's Envoy's HTTP connection management subsystem, filtering, and telemetry capabilities exclusively for - prompts and LLMs. -
    -
  • Proven success with companies like Airbnb, Dropbox, Google, and others.
  • -
  • Works with any application language such as Python, Java, C++, Go, PHP, etc.
  • -
  • Quick deployment and transparent upgrades.
  • -
-
- -
-

Engineered with (fast) LLMs

- Arch is engineered with specialized (sub-billion) LLMs that are designed for fast, cost-effective, and accurate handling of prompts. - These LLMs are best-in-class for critical prompt-related tasks like: -
    -
  • Function Calling: Function-calling helps you personalize GenAI applications with your API operations via user prompts.
  • -
  • Prompt Guards: Centrally manages safety features to prevent toxic or jailbreak prompts.
  • -
  • Intent-drift detection: Able to detect shifts in user intent to improve retrieval accuracy and response efficiency.
  • -
-
- -
-

Traffic Management

- Arch offers several capabilities for LLM calls originating from your applications, including a vendor-agnostic SDK to make LLM calls, smart retries on errors from upstream LLMs, and automatic cutover to other LLMs configured in Arch for continuous availability and disaster recovery scenarios. -

Arch extends Envoy’s cluster subsystem to manage upstream connections to LLMs so that you can build resilient AI applications. -
- -
-

Front/Edge Gateway

- There is substantial benefit in using the same software at the edge (observability, traffic shaping algorithms, applying guardrails, etc.) as for outbound LLM inference use cases.

Arch is exceptionally well suited as an edge gateway for AI applications. This includes TLS termination, rate limiting, and prompt-based routing. -
- -
-

Best-in-Class Monitoring

- Arch offers several monitoring metrics that help you understand three critical aspects of your application: latency, token usage, and error rates by an upstream LLM provider. -

Latency measures the speed at which your application is responding to users, which includes metrics like time to first token (TFT), time per output token (TOT), and the total latency as perceived by users. -
- -
-

End-to-End Tracing

- Arch propagates trace context using the W3C Trace Context standard, specifically through the traceparent header compatible with OpenTelemetry. -

This allows each component in the system to record its part of the request flow, enabling end-to-end tracing across the entire application. Arch ensures that developers can capture this trace data consistently and in a format compatible with various observability tools. -
-
-
-

Let's get started

-
- Get Started - Documentation -
- - diff --git a/www/next.config.ts b/www/next.config.ts new file mode 100644 index 00000000..e9ffa308 --- /dev/null +++ b/www/next.config.ts @@ -0,0 +1,7 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + /* config options here */ +}; + +export default nextConfig; diff --git a/www/package-lock.json b/www/package-lock.json new file mode 100644 index 00000000..2f8af1cd --- /dev/null +++ b/www/package-lock.json @@ -0,0 +1,1907 @@ +{ + "name": "website", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "website", + "version": "0.1.0", + "dependencies": { + "@radix-ui/react-slot": "^1.2.3", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "framer-motion": "^12.23.24", + "lucide-react": "^0.548.0", + "next": "16.0.0", + "react": "19.2.0", + "react-dom": "19.2.0", + "tailwind-merge": "^3.3.1" + }, + "devDependencies": { + "@biomejs/biome": "2.2.0", + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "tailwindcss": "^4", + "tw-animate-css": "^1.4.0", + "typescript": "^5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@biomejs/biome": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.2.0.tgz", + "integrity": "sha512-3On3RSYLsX+n9KnoSgfoYlckYBoU6VRM22cw1gB4Y0OuUVSYd/O/2saOJMrA4HFfA1Ff0eacOvMN1yAAvHtzIw==", + "dev": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "2.2.0", + "@biomejs/cli-darwin-x64": "2.2.0", + "@biomejs/cli-linux-arm64": "2.2.0", + "@biomejs/cli-linux-arm64-musl": "2.2.0", + "@biomejs/cli-linux-x64": "2.2.0", + "@biomejs/cli-linux-x64-musl": "2.2.0", + "@biomejs/cli-win32-arm64": "2.2.0", + "@biomejs/cli-win32-x64": "2.2.0" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.2.0.tgz", + "integrity": "sha512-zKbwUUh+9uFmWfS8IFxmVD6XwqFcENjZvEyfOxHs1epjdH3wyyMQG80FGDsmauPwS2r5kXdEM0v/+dTIA9FXAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.2.0.tgz", + "integrity": "sha512-+OmT4dsX2eTfhD5crUOPw3RPhaR+SKVspvGVmSdZ9y9O/AgL8pla6T4hOn1q+VAFBHuHhsdxDRJgFCSC7RaMOw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.2.0.tgz", + "integrity": "sha512-6eoRdF2yW5FnW9Lpeivh7Mayhq0KDdaDMYOJnH9aT02KuSIX5V1HmWJCQQPwIQbhDh68Zrcpl8inRlTEan0SXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.2.0.tgz", + "integrity": "sha512-egKpOa+4FL9YO+SMUMLUvf543cprjevNc3CAgDNFLcjknuNMcZ0GLJYa3EGTCR2xIkIUJDVneBV3O9OcIlCEZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.2.0.tgz", + "integrity": "sha512-5UmQx/OZAfJfi25zAnAGHUMuOd+LOsliIt119x2soA2gLggQYrVPA+2kMUxR6Mw5M1deUF/AWWP2qpxgH7Nyfw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.2.0.tgz", + "integrity": "sha512-I5J85yWwUWpgJyC1CcytNSGusu2p9HjDnOPAFG4Y515hwRD0jpR9sT9/T1cKHtuCvEQ/sBvx+6zhz9l9wEJGAg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.2.0.tgz", + "integrity": "sha512-n9a1/f2CwIDmNMNkFs+JI0ZjFnMO0jdOyGNtihgUNFnlmd84yIYY2KMTBmMV58ZlVHjgmY5Y6E1hVTnSRieggA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.2.0.tgz", + "integrity": "sha512-Nawu5nHjP/zPKTIryh2AavzTc/KEg4um/MxWdXW0A6P/RZOyIpa7+QSjeXwAwX/utJGaCoXRPWtF3m5U/bB3Ww==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.6.0.tgz", + "integrity": "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz", + "integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.3" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz", + "integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.3" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz", + "integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz", + "integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz", + "integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz", + "integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz", + "integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz", + "integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz", + "integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz", + "integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.3" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz", + "integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.3" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz", + "integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.3" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz", + "integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.3" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz", + "integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.3" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz", + "integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz", + "integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.3" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz", + "integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.5.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz", + "integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz", + "integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz", + "integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@next/env": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.0.tgz", + "integrity": "sha512-s5j2iFGp38QsG1LWRQaE2iUY3h1jc014/melHFfLdrsMJPqxqDQwWNwyQTcNoUSGZlCVZuM7t7JDMmSyRilsnA==", + "license": "MIT" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.0.tgz", + "integrity": "sha512-/CntqDCnk5w2qIwMiF0a9r6+9qunZzFmU0cBX4T82LOflE72zzH6gnOjCwUXYKOBlQi8OpP/rMj8cBIr18x4TA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.0.tgz", + "integrity": "sha512-hB4GZnJGKa8m4efvTGNyii6qs76vTNl+3dKHTCAUaksN6KjYy4iEO3Q5ira405NW2PKb3EcqWiRaL9DrYJfMHg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.0.tgz", + "integrity": "sha512-E2IHMdE+C1k+nUgndM13/BY/iJY9KGCphCftMh7SXWcaQqExq/pJU/1Hgn8n/tFwSoLoYC/yUghOv97tAsIxqg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.0.tgz", + "integrity": "sha512-xzgl7c7BVk4+7PDWldU+On2nlwnGgFqJ1siWp3/8S0KBBLCjonB6zwJYPtl4MUY7YZJrzzumdUpUoquu5zk8vg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.0.tgz", + "integrity": "sha512-sdyOg4cbiCw7YUr0F/7ya42oiVBXLD21EYkSwN+PhE4csJH4MSXUsYyslliiiBwkM+KsuQH/y9wuxVz6s7Nstg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.0.tgz", + "integrity": "sha512-IAXv3OBYqVaNOgyd3kxR4L3msuhmSy1bcchPHxDOjypG33i2yDWvGBwFD94OuuTjjTt/7cuIKtAmoOOml6kfbg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.0.tgz", + "integrity": "sha512-bmo3ncIJKUS9PWK1JD9pEVv0yuvp1KPuOsyJTHXTv8KDrEmgV/K+U0C75rl9rhIaODcS7JEb6/7eJhdwXI0XmA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.0.tgz", + "integrity": "sha512-O1cJbT+lZp+cTjYyZGiDwsOjO3UHHzSqobkPNipdlnnuPb1swfcuY6r3p8dsKU4hAIEO4cO67ZCfVVH/M1ETXA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.16.tgz", + "integrity": "sha512-BX5iaSsloNuvKNHRN3k2RcCuTEgASTo77mofW0vmeHkfrDWaoFAFvNHpEgtu0eqyypcyiBkDWzSMxJhp3AUVcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.4", + "enhanced-resolve": "^5.18.3", + "jiti": "^2.6.1", + "lightningcss": "1.30.2", + "magic-string": "^0.30.19", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.16" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.16.tgz", + "integrity": "sha512-2OSv52FRuhdlgyOQqgtQHuCgXnS8nFSYRp2tJ+4WZXKgTxqPy7SMSls8c3mPT5pkZ17SBToGM5LHEJBO7miEdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.16", + "@tailwindcss/oxide-darwin-arm64": "4.1.16", + "@tailwindcss/oxide-darwin-x64": "4.1.16", + "@tailwindcss/oxide-freebsd-x64": "4.1.16", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.16", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.16", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.16", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.16", + "@tailwindcss/oxide-linux-x64-musl": "4.1.16", + "@tailwindcss/oxide-wasm32-wasi": "4.1.16", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.16", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.16" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.16.tgz", + "integrity": "sha512-8+ctzkjHgwDJ5caq9IqRSgsP70xhdhJvm+oueS/yhD5ixLhqTw9fSL1OurzMUhBwE5zK26FXLCz2f/RtkISqHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.16.tgz", + "integrity": "sha512-C3oZy5042v2FOALBZtY0JTDnGNdS6w7DxL/odvSny17ORUnaRKhyTse8xYi3yKGyfnTUOdavRCdmc8QqJYwFKA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.16.tgz", + "integrity": "sha512-vjrl/1Ub9+JwU6BP0emgipGjowzYZMjbWCDqwA2Z4vCa+HBSpP4v6U2ddejcHsolsYxwL5r4bPNoamlV0xDdLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.16.tgz", + "integrity": "sha512-TSMpPYpQLm+aR1wW5rKuUuEruc/oOX3C7H0BTnPDn7W/eMw8W+MRMpiypKMkXZfwH8wqPIRKppuZoedTtNj2tg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.16.tgz", + "integrity": "sha512-p0GGfRg/w0sdsFKBjMYvvKIiKy/LNWLWgV/plR4lUgrsxFAoQBFrXkZ4C0w8IOXfslB9vHK/JGASWD2IefIpvw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.16.tgz", + "integrity": "sha512-DoixyMmTNO19rwRPdqviTrG1rYzpxgyYJl8RgQvdAQUzxC1ToLRqtNJpU/ATURSKgIg6uerPw2feW0aS8SNr/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.16.tgz", + "integrity": "sha512-H81UXMa9hJhWhaAUca6bU2wm5RRFpuHImrwXBUvPbYb+3jo32I9VIwpOX6hms0fPmA6f2pGVlybO6qU8pF4fzQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.16.tgz", + "integrity": "sha512-ZGHQxDtFC2/ruo7t99Qo2TTIvOERULPl5l0K1g0oK6b5PGqjYMga+FcY1wIUnrUxY56h28FxybtDEla+ICOyew==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.16.tgz", + "integrity": "sha512-Oi1tAaa0rcKf1Og9MzKeINZzMLPbhxvm7rno5/zuP1WYmpiG0bEHq4AcRUiG2165/WUzvxkW4XDYCscZWbTLZw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.16.tgz", + "integrity": "sha512-B01u/b8LteGRwucIBmCQ07FVXLzImWESAIMcUU6nvFt/tYsQ6IHz8DmZ5KtvmwxD+iTYBtM1xwoGXswnlu9v0Q==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.5.0", + "@emnapi/runtime": "^1.5.0", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.0.7", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.16.tgz", + "integrity": "sha512-zX+Q8sSkGj6HKRTMJXuPvOcP8XfYON24zJBRPlszcH1Np7xuHXhWn8qfFjIujVzvH3BHU+16jBXwgpl20i+v9A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.16.tgz", + "integrity": "sha512-m5dDFJUEejbFqP+UXVstd4W/wnxA4F61q8SoL+mqTypId2T2ZpuxosNSgowiCnLp2+Z+rivdU0AqpfgiD7yCBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.16.tgz", + "integrity": "sha512-Qn3SFGPXYQMKR/UtqS+dqvPrzEeBZHrFA92maT4zijCVggdsXnDBMsPFJo1eArX3J+O+Gi+8pV4PkqjLCNBk3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.1.16", + "@tailwindcss/oxide": "4.1.16", + "postcss": "^8.4.41", + "tailwindcss": "4.1.16" + } + }, + "node_modules/@types/node": { + "version": "20.19.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.23.tgz", + "integrity": "sha512-yIdlVVVHXpmqRhtyovZAcSy0MiPcYWGkoO4CGe/+jpP0hmNuihm4XhHbADpK++MsiLHP5MVlv+bcgdF99kSiFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", + "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.2", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.2.tgz", + "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001751", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001751.tgz", + "integrity": "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/framer-motion": { + "version": "12.23.24", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.24.tgz", + "integrity": "sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.23.23", + "motion-utils": "^12.23.6", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/lightningcss": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", + "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.30.2", + "lightningcss-darwin-arm64": "1.30.2", + "lightningcss-darwin-x64": "1.30.2", + "lightningcss-freebsd-x64": "1.30.2", + "lightningcss-linux-arm-gnueabihf": "1.30.2", + "lightningcss-linux-arm64-gnu": "1.30.2", + "lightningcss-linux-arm64-musl": "1.30.2", + "lightningcss-linux-x64-gnu": "1.30.2", + "lightningcss-linux-x64-musl": "1.30.2", + "lightningcss-win32-arm64-msvc": "1.30.2", + "lightningcss-win32-x64-msvc": "1.30.2" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", + "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", + "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", + "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", + "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", + "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", + "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", + "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", + "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", + "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", + "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", + "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lucide-react": { + "version": "0.548.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.548.0.tgz", + "integrity": "sha512-63b16z63jM9yc1MwxajHeuu0FRZFsDtljtDjYm26Kd86UQ5HQzu9ksEtoUUw4RBuewodw/tGFmvipePvRsKeDA==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/motion-dom": { + "version": "12.23.23", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz", + "integrity": "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.23.6" + } + }, + "node_modules/motion-utils": { + "version": "12.23.6", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz", + "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/next/-/next-16.0.0.tgz", + "integrity": "sha512-nYohiNdxGu4OmBzggxy9rczmjIGI+TpR5vbKTsE1HqYwNm1B+YSiugSrFguX6omMOKnDHAmBPY4+8TNJk0Idyg==", + "license": "MIT", + "dependencies": { + "@next/env": "16.0.0", + "@swc/helpers": "0.5.15", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=20.9.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "16.0.0", + "@next/swc-darwin-x64": "16.0.0", + "@next/swc-linux-arm64-gnu": "16.0.0", + "@next/swc-linux-arm64-musl": "16.0.0", + "@next/swc-linux-x64-gnu": "16.0.0", + "@next/swc-linux-x64-musl": "16.0.0", + "@next/swc-win32-arm64-msvc": "16.0.0", + "@next/swc-win32-x64-msvc": "16.0.0", + "sharp": "^0.34.4" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/react": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", + "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", + "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.0" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz", + "integrity": "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.0", + "semver": "^7.7.2" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.4", + "@img/sharp-darwin-x64": "0.34.4", + "@img/sharp-libvips-darwin-arm64": "1.2.3", + "@img/sharp-libvips-darwin-x64": "1.2.3", + "@img/sharp-libvips-linux-arm": "1.2.3", + "@img/sharp-libvips-linux-arm64": "1.2.3", + "@img/sharp-libvips-linux-ppc64": "1.2.3", + "@img/sharp-libvips-linux-s390x": "1.2.3", + "@img/sharp-libvips-linux-x64": "1.2.3", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.3", + "@img/sharp-libvips-linuxmusl-x64": "1.2.3", + "@img/sharp-linux-arm": "0.34.4", + "@img/sharp-linux-arm64": "0.34.4", + "@img/sharp-linux-ppc64": "0.34.4", + "@img/sharp-linux-s390x": "0.34.4", + "@img/sharp-linux-x64": "0.34.4", + "@img/sharp-linuxmusl-arm64": "0.34.4", + "@img/sharp-linuxmusl-x64": "0.34.4", + "@img/sharp-wasm32": "0.34.4", + "@img/sharp-win32-arm64": "0.34.4", + "@img/sharp-win32-ia32": "0.34.4", + "@img/sharp-win32-x64": "0.34.4" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/tailwind-merge": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz", + "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.16.tgz", + "integrity": "sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tw-animate-css": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz", + "integrity": "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Wombosvideo" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/www/package.json b/www/package.json new file mode 100644 index 00000000..e5e31613 --- /dev/null +++ b/www/package.json @@ -0,0 +1,33 @@ +{ + "name": "website", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "biome check", + "format": "biome format --write" + }, + "dependencies": { + "@radix-ui/react-slot": "^1.2.3", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "framer-motion": "^12.23.24", + "lucide-react": "^0.548.0", + "next": "16.0.0", + "react": "19.2.0", + "react-dom": "19.2.0", + "tailwind-merge": "^3.3.1" + }, + "devDependencies": { + "@biomejs/biome": "2.2.0", + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "tailwindcss": "^4", + "tw-animate-css": "^1.4.0", + "typescript": "^5" + } +} diff --git a/www/postcss.config.mjs b/www/postcss.config.mjs new file mode 100644 index 00000000..61e36849 --- /dev/null +++ b/www/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; + +export default config; diff --git a/www/public/BuildWithChoice.svg b/www/public/BuildWithChoice.svg new file mode 100644 index 00000000..e048240a --- /dev/null +++ b/www/public/BuildWithChoice.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/www/public/Contextual.svg b/www/public/Contextual.svg new file mode 100644 index 00000000..345096b3 --- /dev/null +++ b/www/public/Contextual.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/www/public/LaunchFaster.svg b/www/public/LaunchFaster.svg new file mode 100644 index 00000000..5f699610 --- /dev/null +++ b/www/public/LaunchFaster.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/www/public/LogoMarkSquare.svg b/www/public/LogoMarkSquare.svg new file mode 100644 index 00000000..57fb5b33 --- /dev/null +++ b/www/public/LogoMarkSquare.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/www/public/LogoOutline.svg b/www/public/LogoOutline.svg new file mode 100644 index 00000000..3e10f84c --- /dev/null +++ b/www/public/LogoOutline.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/www/public/Logomark.svg b/www/public/Logomark.svg new file mode 100644 index 00000000..6d8e13fa --- /dev/null +++ b/www/public/Logomark.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/www/public/ShipConfidently.svg b/www/public/ShipConfidently.svg new file mode 100644 index 00000000..1519b678 --- /dev/null +++ b/www/public/ShipConfidently.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/www/public/Telemetry.svg b/www/public/Telemetry.svg new file mode 100644 index 00000000..2c8b7163 --- /dev/null +++ b/www/public/Telemetry.svg @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/www/public/file.svg b/www/public/file.svg new file mode 100644 index 00000000..004145cd --- /dev/null +++ b/www/public/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/www/public/fonts/IBMPlexSans-VariableFont_wdth,wght.ttf b/www/public/fonts/IBMPlexSans-VariableFont_wdth,wght.ttf new file mode 100644 index 00000000..9add8756 Binary files /dev/null and b/www/public/fonts/IBMPlexSans-VariableFont_wdth,wght.ttf differ diff --git a/www/public/fonts/JetBrainsMono-Medium.woff2 b/www/public/fonts/JetBrainsMono-Medium.woff2 new file mode 100644 index 00000000..669d04cd Binary files /dev/null and b/www/public/fonts/JetBrainsMono-Medium.woff2 differ diff --git a/www/public/fonts/JetBrainsMono-Regular.woff2 b/www/public/fonts/JetBrainsMono-Regular.woff2 new file mode 100644 index 00000000..40da4276 Binary files /dev/null and b/www/public/fonts/JetBrainsMono-Regular.woff2 differ diff --git a/www/public/fonts/jetbrains-mono-bold.woff2 b/www/public/fonts/jetbrains-mono-bold.woff2 new file mode 100644 index 00000000..4917f434 Binary files /dev/null and b/www/public/fonts/jetbrains-mono-bold.woff2 differ diff --git a/www/public/globe.svg b/www/public/globe.svg new file mode 100644 index 00000000..567f17b0 --- /dev/null +++ b/www/public/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/www/public/logos/chase.svg b/www/public/logos/chase.svg new file mode 100644 index 00000000..40d2ae76 --- /dev/null +++ b/www/public/logos/chase.svg @@ -0,0 +1,68 @@ + + + + + diff --git a/www/public/logos/huggingface.svg b/www/public/logos/huggingface.svg new file mode 100644 index 00000000..7e254084 --- /dev/null +++ b/www/public/logos/huggingface.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/www/public/logos/oracle.svg b/www/public/logos/oracle.svg new file mode 100644 index 00000000..0981dfcf --- /dev/null +++ b/www/public/logos/oracle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/www/public/logos/sandisk.svg b/www/public/logos/sandisk.svg new file mode 100644 index 00000000..7618250e --- /dev/null +++ b/www/public/logos/sandisk.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/www/public/logos/tmobile.svg b/www/public/logos/tmobile.svg new file mode 100644 index 00000000..6c78536b --- /dev/null +++ b/www/public/logos/tmobile.svg @@ -0,0 +1,165 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/www/public/next.svg b/www/public/next.svg new file mode 100644 index 00000000..5174b28c --- /dev/null +++ b/www/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/www/public/plano.svg b/www/public/plano.svg new file mode 100644 index 00000000..6561a1fd --- /dev/null +++ b/www/public/plano.svg @@ -0,0 +1,3 @@ + + + diff --git a/www/public/vercel.svg b/www/public/vercel.svg new file mode 100644 index 00000000..77053960 --- /dev/null +++ b/www/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/www/public/window.svg b/www/public/window.svg new file mode 100644 index 00000000..b2b2a44f --- /dev/null +++ b/www/public/window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/www/src/app/favicon.ico b/www/src/app/favicon.ico new file mode 100644 index 00000000..718d6fea Binary files /dev/null and b/www/src/app/favicon.ico differ diff --git a/www/src/app/globals.css b/www/src/app/globals.css new file mode 100644 index 00000000..9396a0d4 --- /dev/null +++ b/www/src/app/globals.css @@ -0,0 +1,217 @@ +@import "tailwindcss"; +@import "tw-animate-css"; + +@custom-variant dark (&:is(.dark *)); + +/* Font Face Declarations */ +@font-face { + font-family: "IBM Plex Sans"; + src: url("/fonts/IBMPlexSans-VariableFont_wdth,wght.ttf") format("truetype-variations"); + font-weight: 100 700; /* Variable font weight range */ + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "JetBrains Mono"; + src: url("/fonts/JetBrainsMono-Regular.woff2") format("woff2"); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "JetBrains Mono"; + src: url("/fonts/JetBrainsMono-Medium.woff2") format("woff2"); + font-weight: 500; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "JetBrains Mono"; + src: url("/fonts/jetbrains-mono-bold.woff2") format("woff2"); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +:root { + /* Base colors */ + --background: #ffffff; + --foreground: #171717; + + /* Brand colors from Figma */ + --primary: #7780d9; + --primary-dark: #4141b2; + --primary-darker: #2a3178; + --secondary: #9797ea; + + /* Purple shades */ + --purple-50: #edefff; + --purple-100: #b9bfff; + --purple-200: #b0b7ff; + --purple-300: #abb2fa; + --purple-400: #969ff4; + --purple-500: #acb3fe; + + /* Neutral colors */ + --muted: #787878; + --muted-foreground: #494949; + --border: #d1d1d1; + + /* Dark section */ + --dark-bg: #1a1a1a; + --dark-foreground: #ffffff; + --radius: 0.625rem; + --card: #ffffff; + --card-foreground: #171717; + --popover: #ffffff; + --popover-foreground: #171717; + --primary-foreground: #ffffff; + --secondary-foreground: #171717; + --accent: #edefff; + --accent-foreground: #171717; + --destructive: #ef4444; + --input: #d1d1d1; + --ring: #7780d9; + --chart-1: #7780d9; + --chart-2: #9797ea; + --chart-3: #abb2fa; + --chart-4: #969ff4; + --chart-5: #acb3fe; + --sidebar: #ffffff; + --sidebar-foreground: #171717; + --sidebar-primary: #7780d9; + --sidebar-primary-foreground: #ffffff; + --sidebar-accent: #edefff; + --sidebar-accent-foreground: #171717; + --sidebar-border: #d1d1d1; + --sidebar-ring: #7780d9; +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-primary: var(--primary); + --color-primary-dark: var(--primary-dark); + --color-primary-darker: var(--primary-darker); + --color-secondary: var(--secondary); + --color-purple-50: var(--purple-50); + --color-purple-100: var(--purple-100); + --color-purple-200: var(--purple-200); + --color-purple-300: var(--purple-300); + --color-purple-400: var(--purple-400); + --color-purple-500: var(--purple-500); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-border: var(--border); + --color-dark-bg: var(--dark-bg); + --color-dark-foreground: var(--dark-foreground); + + /* Font families for Tailwind */ + --font-sans: "IBM Plex Sans", system-ui, sans-serif; + --font-mono: "JetBrains Mono", monospace; + + /* Font weights - variable font supports 100-700 */ + --font-weight-thin: 100; + --font-weight-extralight: 200; + --font-weight-light: 300; + --font-weight-normal: 400; + --font-weight-medium: 500; + --font-weight-semibold: 600; + --font-weight-bold: 700; + --color-sidebar-ring: var(--sidebar-ring); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar: var(--sidebar); + --color-chart-5: var(--chart-5); + --color-chart-4: var(--chart-4); + --color-chart-3: var(--chart-3); + --color-chart-2: var(--chart-2); + --color-chart-1: var(--chart-1); + --color-ring: var(--ring); + --color-input: var(--input); + --color-destructive: var(--destructive); + --color-accent-foreground: var(--accent-foreground); + --color-accent: var(--accent); + --color-secondary-foreground: var(--secondary-foreground); + --color-primary-foreground: var(--primary-foreground); + --color-popover-foreground: var(--popover-foreground); + --color-popover: var(--popover); + --color-card-foreground: var(--card-foreground); + --color-card: var(--card); + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); +} + +/* Global letter-spacing for fonts */ +.font-sans, +[class*="font-sans"] { + letter-spacing: -4.56px; +} + +.font-mono, +[class*="font-mono"] { + letter-spacing: -0.96px; +} + +body { + font-family: var(--font-sans); +} + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.922 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --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(1 0 0 / 10%); + --sidebar-ring: oklch(0.556 0 0); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + html { + background: linear-gradient(to top right, #ffffff, #dcdfff); + min-height: 100%; + } + body { + @apply text-foreground; + background: linear-gradient(to top right, #ffffff, #dcdfff); + min-height: 100vh; + overflow-x: hidden; + } +} diff --git a/www/src/app/layout.tsx b/www/src/app/layout.tsx new file mode 100644 index 00000000..a64ce0f9 --- /dev/null +++ b/www/src/app/layout.tsx @@ -0,0 +1,21 @@ +import type { Metadata } from "next"; +import "./globals.css"; + +export const metadata: Metadata = { + title: "Plano - The AI-native network for agents", + description: "Build and scale AI agents without handling the low-level plumbing.", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + {children} + + + ); +} diff --git a/www/src/app/page.tsx b/www/src/app/page.tsx new file mode 100644 index 00000000..f6bd5518 --- /dev/null +++ b/www/src/app/page.tsx @@ -0,0 +1,32 @@ +"use client"; + +import React from "react"; +import { Navbar } from "@/components/Navbar"; +import { Hero } from "@/components/Hero"; +import { IntroSection } from "@/components/IntroSection"; +import { IdeaToAgentSection } from "@/components/IdeaToAgentSection"; +import { UseCasesSection } from "@/components/UseCasesSection"; +import { VerticalCarouselSection } from "@/components/VerticalCarouselSection"; +import { UnlockPotentialSection } from "@/components/UnlockPotentialSection"; +import { Footer } from "@/components/Footer"; +import { LogoCloud } from "@/components/LogoCloud"; + +export default function Home() { + return ( +
+ +
+ + + + + + + + + {/* Rest of the sections will be refactored next */} +
+
+ ); +} diff --git a/www/src/components/AsciiDiagram.tsx b/www/src/components/AsciiDiagram.tsx new file mode 100644 index 00000000..c9cd3d5e --- /dev/null +++ b/www/src/components/AsciiDiagram.tsx @@ -0,0 +1,90 @@ +import React from 'react'; + +interface AsciiDiagramProps { + title?: string; + content: string; + className?: string; +} + +export const AsciiDiagram: React.FC = ({ + title, + content, + className = "" +}) => { + return ( +
+ {title && ( +

+ {title} +

+ )} +
+
+          {content}
+        
+
+
+ ); +}; + +// Programmatic diagram builder for non-coders +interface DiagramStep { + id: string; + label: string; + type?: 'input' | 'inner' | 'regular'; + x: number; + y: number; +} + +interface FlowConnection { + from: string; + to: string; + label?: string; +} + +interface DiagramConfig { + title: string; + steps: DiagramStep[]; + connections: FlowConnection[]; +} + +// Simple ASCII diagram generator +export const createDiagram = (config: DiagramConfig): string => { + // This is a simplified version - you can extend this to automatically generate + // the ASCII art from the config + // For now, return the manually created diagrams + return ''; +}; + +// Helper to create boxes +export const createBox = ( + label: string, + type: 'input' | 'inner' | 'regular' = 'regular', + width: number = 20 +): string[] => { + const padding = Math.max(0, Math.floor((width - label.length) / 2)); + const spaces = ' '.repeat(padding); + const remaining = width - label.length - padding; + + let chars; + switch (type) { + case 'input': + chars = { tl: '╔', tr: '╗', bl: '╚', br: '╝', h: '═', v: '║' }; + break; + case 'inner': + chars = { tl: '┏', tr: '┓', bl: '┗', br: '┛', h: '━', v: '┃' }; + break; + case 'regular': + default: + chars = { tl: '┌', tr: '┐', bl: '└', br: '┘', h: '─', v: '│' }; + } + + return [ + `${chars.tl}${chars.h.repeat(width)}${chars.tr}`, + `${chars.v}${spaces}${label}${' '.repeat(remaining)}${chars.v}`, + `${chars.bl}${chars.h.repeat(width)}${chars.br}`, + ]; +}; diff --git a/www/src/components/DiagramBuilder.tsx b/www/src/components/DiagramBuilder.tsx new file mode 100644 index 00000000..3d4f2f4c --- /dev/null +++ b/www/src/components/DiagramBuilder.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { createFlowDiagram, FlowDiagramConfig } from '@/utils/asciiBuilder'; +import { AsciiDiagram } from './AsciiDiagram'; + +interface DiagramBuilderProps { + config: FlowDiagramConfig; + title?: string; +} + +/** + * Simple Diagram Builder Component + * + * Usage: + * + * + */ +export const DiagramBuilder: React.FC = ({ config, title }) => { + const asciiDiagram = createFlowDiagram(config); + + return ; +}; + diff --git a/www/src/components/Footer.tsx b/www/src/components/Footer.tsx new file mode 100644 index 00000000..a343b616 --- /dev/null +++ b/www/src/components/Footer.tsx @@ -0,0 +1,98 @@ +import React from "react"; +import Link from "next/link"; +import Image from "next/image"; + +const footerLinks = { + company: [ + { label: "Product", href: "/product" }, + { label: "Use Cases", href: "/use-cases" }, + { label: "Blog", href: "/blog" }, + { label: "Plano LLMs", href: "/llms" } + ], + developerResources: [ + { label: "Documentation", href: "/docs" } + ] +}; + +export function Footer() { + return ( +
+
+ {/* Main Grid Layout */} +
+ {/* Left Column - Tagline and Copyright */} +
+

+ Plano is the powerful, intelligent platform that empowers teams to seamlessly build, automate, and scale agentic systems with ease. +

+ + {/* Copyright */} +
+

+ © Katanemo Labs, Inc. 2025 / Plano by Katanemo Labs, Inc. +

+
+
+ + {/* Right Column - Navigation Links */} +
+ {/* Company Links */} +
+

+ Company +

+ +
+ + {/* Developer Resources */} +
+

+ Developer Resources +

+ +
+
+
+
+ + {/* Half-Cut Plano Logo Background */} +
+
+
+ Plano Logo +
+
+
+
+ ); +} diff --git a/www/src/components/Hero.tsx b/www/src/components/Hero.tsx new file mode 100644 index 00000000..128975fc --- /dev/null +++ b/www/src/components/Hero.tsx @@ -0,0 +1,50 @@ +import React from "react"; +import { Button } from "./ui/button"; +import Link from "next/link"; +import { NetworkAnimation } from "./NetworkAnimation"; + +export function Hero() { + return ( +
+
+ +
+
+
+ {/* Version Badge */} +
+
+ v0.3.12 + + RAG Agent Launch! +
+
+ + {/* Main Heading */} +

+ The AI-native + network for agents +

+
+ + {/* Subheading with CTA Buttons on the right */} +
+

+ Build and scale AI agents without handling the low-level plumbing. +

+ + {/* CTA Buttons */} +
+ + +
+
+
+
+ ); +} + diff --git a/www/src/components/IdeaToAgentSection.tsx b/www/src/components/IdeaToAgentSection.tsx new file mode 100644 index 00000000..b0b10e60 --- /dev/null +++ b/www/src/components/IdeaToAgentSection.tsx @@ -0,0 +1,161 @@ +"use client"; + +import React, { useState, useEffect } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import { Button } from "./ui/button"; + +const carouselData = [ + { + id: 1, + category: "LAUNCH FASTER", + title: "Focus on core objectives", + description: "Plano handles the heavy lifting for agentic apps with purpose-built LLMs that automate request clarification, query routing, and data extraction. Ship faster without juggling prompt engineering or infrastructure details.", + image: "/LaunchFaster.svg" + }, + { + id: 2, + category: "SCALE EFFICIENTLY", + title: "Build without limits", + description: "From prototype to production, Plano scales with your needs. Handle thousands of concurrent requests while maintaining consistent performance and reliability across your agent network.", + image: "/ShipConfidently.svg" + }, + { + id: 3, + category: "DEPLOY CONFIDENTLY", + title: "Production-ready infrastructure", + description: "Enterprise-grade security, monitoring, and governance built-in. Deploy your agents with confidence knowing they're protected by battle-tested infrastructure and compliance frameworks.", + image: "/BuildWithChoice.svg" + }, + { + id: 4, + category: "INTEGRATE SEAMLESSLY", + title: "Connect everything", + description: "Unified API access across all major LLM providers. Switch between models, combine capabilities, and route requests intelligently without vendor lock-in or complex integrations.", + image: "/Telemetry.svg" + }, + { + id: 5, + category: "OPTIMIZE CONTINUOUSLY", + title: "Learn and improve", + description: "Built-in analytics and feedback loops help your agents get smarter over time. Track performance, identify bottlenecks, and optimize workflows with real-time insights and automated improvements.", + image: "/Contextual.svg" + } +]; + +export function IdeaToAgentSection() { + const [currentSlide, setCurrentSlide] = useState(0); + const [isAutoPlaying, setIsAutoPlaying] = useState(true); + + // Auto-advance slides + useEffect(() => { + if (!isAutoPlaying) return; + + const interval = setInterval(() => { + setCurrentSlide((prev) => (prev + 1) % carouselData.length); + }, 10000); // 10 seconds per slide + + return () => clearInterval(interval); + }, [isAutoPlaying]); + + const handleSlideClick = (index: number) => { + setCurrentSlide(index); + setIsAutoPlaying(false); + // Resume auto-play after 10 seconds + setTimeout(() => setIsAutoPlaying(true), 10000); + }; + + return ( +
+
+ {/* Main Heading */} +

+ Idea to agent — without overhead +

+ + {/* Progress Indicators */} +
+ {carouselData.map((_, index) => ( + + ))} +
+ + {/* Carousel Content */} +
+ + +
+ {/* Left Content */} +
+
+ {/* Category */} +

+ {carouselData[currentSlide].category} +

+ + {/* Title */} +

+ {carouselData[currentSlide].title} +

+ + {/* Description */} +
+

+ {carouselData[currentSlide].description} +

+
+ + +
+
+ + {/* Right Image - Only show if current slide has an image */} + {carouselData[currentSlide].image && ( +
+ {carouselData[currentSlide].category} +
+ )} +
+
+
+
+
+
+ ); +} diff --git a/www/src/components/IntroSection.tsx b/www/src/components/IntroSection.tsx new file mode 100644 index 00000000..0ef69f3c --- /dev/null +++ b/www/src/components/IntroSection.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { AsciiDiagram } from "@/components/AsciiDiagram"; +import { diagrams } from "@/data/diagrams"; + +export function IntroSection() { + return ( +
+
+
+ {/* Left Content */} +
+ {/* Heading */} +

+ Go beyond AI nascent demos +

+ + {/* Body Text */} +
+

+ Plano is the infrastructure layer for building, scaling, and routing AI agents. It sits between your app and your models, enforcing safety guardrails, orchestrating multi-agent workflows, and unifying access across large language models. +

+
+

+ Developers use Plano to build faster, platform teams use it to unify governance, and AI leads use it to run continuously learning systems that stay aligned, safe, and performant. From SaaS backends to distributed ecosystems, Plano turns raw agent logic into something you can deploy, monitor, and evolve in production. +

+
+
+ + {/* Right Diagram */} +
+ +
+
+
+
+ ); +} + diff --git a/www/src/components/Logo.tsx b/www/src/components/Logo.tsx new file mode 100644 index 00000000..24dacbf6 --- /dev/null +++ b/www/src/components/Logo.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import Image from "next/image"; + +export function Logo() { + return ( +
+ {/* LogoMarkSquare SVG */} + Plano Logo +
+ ); +} + diff --git a/www/src/components/LogoCloud.tsx b/www/src/components/LogoCloud.tsx new file mode 100644 index 00000000..049acd45 --- /dev/null +++ b/www/src/components/LogoCloud.tsx @@ -0,0 +1,50 @@ +import React from "react"; +import Image from "next/image"; + +const customerLogos = [ + { + name: "HuggingFace", + src: "/logos/huggingface.svg" + }, + { + name: "T-Mobile", + src: "/logos/tmobile.svg" + }, + { + name: "Chase", + src: "/logos/chase.svg" + }, + { + name: "SanDisk", + src: "/logos/sandisk.svg" + }, + { + name: "Oracle", + src: "/logos/oracle.svg" + } +]; + +export function LogoCloud() { + return ( +
+
+
+ {customerLogos.map((logo) => ( +
+ {`${logo.name} +
+ ))} +
+
+
+ ); +} diff --git a/www/src/components/Navbar.tsx b/www/src/components/Navbar.tsx new file mode 100644 index 00000000..5b747fe2 --- /dev/null +++ b/www/src/components/Navbar.tsx @@ -0,0 +1,68 @@ +"use client"; + +import React from "react"; +import Link from "next/link"; +import { Logo } from "./Logo"; +import { Button } from "./ui/button"; +import { cn } from "@/lib/utils"; + +const navItems = [ + { href: "/docs", label: "docs" }, + { href: "/pricing", label: "pricing" }, + { href: "/blog", label: "blog" }, +]; + +export function Navbar() { + return ( + + ); +} + diff --git a/www/src/components/NetworkAnimation.tsx b/www/src/components/NetworkAnimation.tsx new file mode 100644 index 00000000..d3ddbcb9 --- /dev/null +++ b/www/src/components/NetworkAnimation.tsx @@ -0,0 +1,199 @@ +"use client"; + +import React, { useEffect, useState } from "react"; +import { motion } from "framer-motion"; + +interface Node { + id: string; + x: number; + y: number; + size: number; + delay: number; +} + +interface Connection { + from: string; + to: string; +} + +interface Particle { + id: string; + connectionIndex: number; + progress: number; +} + +// 4 separate groups positioned to the right of the heading text, aligned with the text vertically +const nodes: Node[] = [ + // Group 1 + { id: "1", x: 20, y: 35, size: 18, delay: 0 }, + { id: "2", x: 70, y: 42, size: 12, delay: 0.8 }, + { id: "3", x: 76, y: 38, size: 16, delay: 1.6 }, + + // // Group 2 + // { id: "4", x: 80, y: 30, size: 18, delay: 0.4 }, + // { id: "5", x: 87, y: 36, size: 12, delay: 1.2 }, + // { id: "6", x: 92, y: 33, size: 16, delay: 2.0 }, + + // Group 3 + { id: "7", x: 62, y: 48, size: 10, delay: 0.6 }, + { id: "8", x: 65, y: 52, size: 18, delay: 1.4 }, + { id: "9", x: 75, y: 48, size: 14, delay: 0.6 }, +]; + +const connections: Connection[] = [ + // Group 1 connections + { from: "1", to: "2" }, + { from: "2", to: "3" }, + + // // Group 2 connections + // { from: "4", to: "5" }, + // { from: "5", to: "6" }, + + // Group 3 connections + { from: "7", to: "8" }, + { from: "8", to: "9" }, +]; + +export function NetworkAnimation() { + const [particles, setParticles] = useState([]); + + // Create and animate particles along connections - much slower + useEffect(() => { + const createParticle = () => { + const connectionIndex = Math.floor(Math.random() * connections.length); + const particle: Particle = { + id: `particle-${Date.now()}-${Math.random()}`, + connectionIndex, + progress: 0, + }; + + setParticles((prev) => [...prev, particle]); + + // Remove particle after animation completes + setTimeout(() => { + setParticles((prev) => prev.filter((p) => p.id !== particle.id)); + }, 5000); // Slower duration + }; + + // Create particles at slower intervals + const interval = setInterval(createParticle, 2500); + return () => clearInterval(interval); + }, []); + + // Animate particles - slower movement + useEffect(() => { + const interval = setInterval(() => { + setParticles((prev) => + prev + .map((p) => ({ ...p, progress: p.progress + 0.008 })) // Much slower + .filter((p) => p.progress <= 1) + ); + }, 50); + + return () => clearInterval(interval); + }, []); + + return ( +
+ + + {/* Simple glow filter */} + + + + + + + + + + {/* Render connections - simple lines with lower opacity */} + {connections.map((conn, index) => { + const fromNode = nodes.find((n) => n.id === conn.from); + const toNode = nodes.find((n) => n.id === conn.to); + if (!fromNode || !toNode) return null; + + const x1 = (fromNode.x / 100) * 1920; + const y1 = (fromNode.y / 100) * 800; + const x2 = (toNode.x / 100) * 1920; + const y2 = (toNode.y / 100) * 800; + + return ( + + ); + })} + + {/* Render data particles with lower opacity */} + {particles.map((particle) => { + const conn = connections[particle.connectionIndex]; + const fromNode = nodes.find((n) => n.id === conn.from); + const toNode = nodes.find((n) => n.id === conn.to); + if (!fromNode || !toNode) return null; + + const x = ((fromNode.x + (toNode.x - fromNode.x) * particle.progress) / 100) * 1920; + const y = ((fromNode.y + (toNode.y - fromNode.y) * particle.progress) / 100) * 800; + + return ( + + ); + })} + + {/* Render nodes with subtle floating animation */} + {nodes.map((node) => { + const size = node.size; + const baseX = (node.x / 100) * 1920; + const baseY = (node.y / 100) * 800; + + return ( + + ); + })} + +
+ ); +} diff --git a/www/src/components/UnlockPotentialSection.tsx b/www/src/components/UnlockPotentialSection.tsx new file mode 100644 index 00000000..ddea25df --- /dev/null +++ b/www/src/components/UnlockPotentialSection.tsx @@ -0,0 +1,36 @@ +import React from "react"; +import { Button } from "./ui/button"; + +interface UnlockPotentialSectionProps { + variant?: "transparent" | "black"; + className?: string; +} + +export function UnlockPotentialSection({ + variant = "transparent", + className = "" +}: UnlockPotentialSectionProps) { + const backgroundClass = variant === "black" ? "bg-[#1a1a1a]" : ""; + const textColor = variant === "black" ? "text-white" : "text-black"; + + return ( +
+
+
+

+ Unlock the full potential of your applications with Plano. +

+ +
+ + +
+
+
+
+ ); +} diff --git a/www/src/components/UseCasesSection.tsx b/www/src/components/UseCasesSection.tsx new file mode 100644 index 00000000..9a3148e2 --- /dev/null +++ b/www/src/components/UseCasesSection.tsx @@ -0,0 +1,89 @@ +import React from "react"; +import { ArrowRightIcon } from "lucide-react"; +import { Button } from "./ui/button"; + +const useCasesData = [ + { + id: 1, + category: "FROM SAAS TO AGENTS", + title: "Transform software into active agents", + link: "Learn more" + }, + { + id: 2, + category: "AGENTIC TASKS", + title: "Train models through live feedback", + link: "Learn more" + }, + { + id: 3, + category: "AGENTIC ROUTING", + title: "Route logic across smart agents", + link: "Learn more" + }, + { + id: 4, + category: "SAAS INTEGRATIONS", + title: "Design networks of intelligent agents", + link: "Learn more" + } +]; + +export function UseCasesSection() { + return ( +
+
+ {/* Section Header */} +
+ {/* USE CASES Badge */} +
+
+ USE CASES +
+
+ + {/* Main Heading and CTA Button */} +
+

+ What's possible with Plano +

+ +
+
+ + {/* 4 Box Grid */} +
+ {useCasesData.map((useCase) => ( +
+ {/* Category */} +
+

+ {useCase.category} +

+ + {/* Title */} +

+ {useCase.title} +

+
+ + {/* Learn More Link */} +
+ +
+
+ ))} +
+ +
+
+ ); +} diff --git a/www/src/components/VerticalCarouselSection.tsx b/www/src/components/VerticalCarouselSection.tsx new file mode 100644 index 00000000..cc5ae6cd --- /dev/null +++ b/www/src/components/VerticalCarouselSection.tsx @@ -0,0 +1,125 @@ +"use client"; + +import React, { useState } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import { Button } from "./ui/button"; + +const verticalCarouselData = [ + { + id: 1, + category: "INTRODUCTION", + title: "Simple to revolutionary", + description: "By handling the critical yet complex tasks of prompt processing, Plano enables you to focus on what truly matters — achieving your business goals. With built-in capabilities like intelligent task routing, jailbreaking prevention, and centralized observability, Plano ensures your system runs smoothly and securely from the start, while continuously scaling with your needs." + }, + { + id: 2, + category: "OPEN SOURCE", + title: "Built on proven foundations", + description: "Plano is built on open-source technologies and proven infrastructure patterns. This ensures transparency, community-driven development, and the ability to customize and extend the platform to meet your specific needs while maintaining enterprise-grade reliability." + }, + { + id: 3, + category: "BUILT ON ENVOY", + title: "Enterprise-grade infrastructure", + description: "Leveraging the battle-tested Envoy Proxy, Plano inherits years of production-hardened networking capabilities. This foundation provides unmatched performance, reliability, and scalability for your AI agent infrastructure." + }, + { + id: 4, + category: "PURPOSE-BUILT", + title: "Designed for AI agents", + description: "Unlike generic API gateways, Plano is purpose-built for AI agent workloads. Every feature is designed with prompt processing, model routing, and agent orchestration in mind, providing optimal performance for your AI applications." + }, + { + id: 5, + category: "PROMPT ROUTING", + title: "Intelligent request handling", + description: "Advanced prompt routing capabilities ensure that each request is directed to the most appropriate model or agent. This intelligent routing optimizes for cost, performance, and accuracy based on your specific requirements and preferences." + } +]; + +export function VerticalCarouselSection() { + const [activeSlide, setActiveSlide] = useState(0); + + const handleSlideClick = (index: number) => { + setActiveSlide(index); + }; + + return ( +
+
+ {/* Main Heading */} +

+ Basic scenarios to powerful agentic apps in minutes +

+ + {/* Vertical Carousel Layout */} +
+ {/* Left Sidebar Navigation */} +
+
+ {/* Sliding Rectangle Indicator */} + + + {verticalCarouselData.map((item, index) => ( +
handleSlideClick(index)} + className="cursor-pointer relative pl-6 transition-all duration-300" + > + {/* Category Text */} + + {item.category} + +
+ ))} +
+
+ + {/* Right Content Area */} +
+ + +
+ {/* Title */} +

+ {verticalCarouselData[activeSlide].title} +

+ + {/* Description */} +
+

+ {verticalCarouselData[activeSlide].description} +

+
+
+
+
+
+
+ +
+
+ ); +} diff --git a/www/src/components/ui/button.tsx b/www/src/components/ui/button.tsx new file mode 100644 index 00000000..9009496f --- /dev/null +++ b/www/src/components/ui/button.tsx @@ -0,0 +1,65 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-[7px] font-mono font-medium tracking-[-0.989px] transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + { + variants: { + variant: { + default: + "bg-[#7780d9] border-[#4141b2] border-[1.562px] border-solid text-white hover:bg-[#7780d9]/90 text-base leading-[1.102]", + primary: + "bg-[#7780d9] border-[#4141b2] border-[1.562px] border-solid text-white hover:bg-[#7780d9]/90 text-base leading-[1.102]", + destructive: + "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", + outline: + "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", + secondary: + "bg-[#edefff] border-[#d1d1d1] border-[1.562px] border-solid text-[#494949] hover:bg-[#edefff]/90 text-base leading-[1.102]", + secondaryDark: + "bg-neutral-600 border-[#d1d1d1]/20 border-[1.562px] border-solid text-white hover:bg-[#1a1a1a]/90 text-base leading-[1.102]", + ghost: + "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-5 py-2 has-[>svg]:px-3", + sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", + lg: "h-10 rounded-[7px] px-5 has-[>svg]:px-4", + icon: "size-9", + "icon-sm": "size-8", + "icon-lg": "size-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +function Button({ + className, + variant, + size, + asChild = false, + ...props +}: React.ComponentProps<"button"> & + VariantProps & { + asChild?: boolean + }) { + const Comp = asChild ? Slot : "button" + + return ( + + ) +} + +export { Button, buttonVariants } diff --git a/www/src/data/diagramTemplates.ts b/www/src/data/diagramTemplates.ts new file mode 100644 index 00000000..3d21cf5a --- /dev/null +++ b/www/src/data/diagramTemplates.ts @@ -0,0 +1,56 @@ +import { createFlowDiagram, FlowStep } from '@/utils/asciiBuilder'; + +/** + * Easy-to-use diagram templates that automatically handle spacing + * Perfect for non-coders who just want to define their flow + */ + +// Example: Simple 3-step process +export const createSimpleProcess = (steps: string[]) => { + return createFlowDiagram({ + title: 'Process Flow', + width: 60, + steps: steps.map(label => ({ label, type: 'regular' as const, shadow: true })) + }); +}; + +// Example: Create a nested container diagram +export const createNestedDiagram = ( + title: string, + innerContent: FlowStep[], + width: number = 70 +) => { + return createFlowDiagram({ + title, + width, + steps: innerContent + }); +}; + +// Pre-built templates +export const templates = { + simpleFlow: createSimpleProcess(['Start', 'Process', 'End']), + + apiFlow: createFlowDiagram({ + title: 'API Request Flow', + width: 65, + steps: [ + { label: 'Client Request', type: 'regular', shadow: true }, + { label: 'API Gateway', type: 'container', shadow: true }, + { label: 'Process', type: 'inner', shadow: true }, + { label: 'Response', type: 'regular', shadow: true } + ] + }), + + dataPipeline: createFlowDiagram({ + title: 'Data Pipeline', + width: 70, + steps: [ + { label: 'Input Data', type: 'regular', shadow: true }, + { label: 'Transform', type: 'inner', shadow: true }, + { label: 'Validate', type: 'regular', shadow: true }, + { label: 'Store', type: 'regular', shadow: true } + ] + }) +}; + diff --git a/www/src/data/diagrams-programmatic.ts b/www/src/data/diagrams-programmatic.ts new file mode 100644 index 00000000..6572c875 --- /dev/null +++ b/www/src/data/diagrams-programmatic.ts @@ -0,0 +1,72 @@ +/** + * Programmatic ASCII Diagram Builder + * + * For non-coders: Define your diagram structure with simple objects, + * and the system will automatically generate the ASCII art. + */ + +interface DiagramStep { + id: string; + label: string; + type: 'input' | 'inner' | 'regular'; + position: { x: number; y: number }; +} + +interface DiagramFlow { + from: string; + to: string; + arrow: 'right' | 'down' | 'left' | 'up'; + label?: string; +} + +interface DiagramConfig { + title: string; + steps: DiagramStep[]; + flows: DiagramFlow[]; +} + +// Example: Define diagram using simple objects +export const myFlow: DiagramConfig = { + title: 'User Registration Flow', + steps: [ + { id: 'start', label: 'User', type: 'input', position: { x: 0, y: 0 } }, + { id: 'step1', label: 'Validate Email', type: 'inner', position: { x: 2, y: 0 } }, + { id: 'step2', label: 'Create Account', type: 'regular', position: { x: 2, y: 1 } }, + { id: 'step3', label: 'Send Welcome', type: 'regular', position: { x: 2, y: 2 } }, + ], + flows: [ + { from: 'start', to: 'step1', arrow: 'right' }, + { from: 'step1', to: 'step2', arrow: 'down' }, + { from: 'step2', to: 'step3', arrow: 'down' }, + ], +}; + +/** + * Convert diagram config to ASCII string + * + * Usage: + * import { buildDiagram } from './ascii-builder'; + * const ascii = buildDiagram(myFlow); + */ +export const buildDiagram = (config: DiagramConfig): string => { + // This function would programmatically build the ASCII + // For now, return a placeholder + let result = ''; + result += `╔═ ${config.title} ══╗\n`; + result += `║ Placeholder for programmatic generation ║\n`; + result += `╚════════════════════════════════════╝\n`; + + // TODO: Implement automatic ASCII generation from config + // This would: + // 1. Layout boxes based on positions + // 2. Add arrows based on flows + // 3. Add shadows automatically + // 4. Handle different box types + + return result; +}; + + + + + diff --git a/www/src/data/diagrams.ts b/www/src/data/diagrams.ts new file mode 100644 index 00000000..0ab2cf61 --- /dev/null +++ b/www/src/data/diagrams.ts @@ -0,0 +1,85 @@ +export const diagrams = { + intentDetection: ` ╔═ Intent Detection ═════════════════════════════╗ + ╔═══════════╗ ║ ║░ + ║ ║░ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ + ║ agent ║░─────────║─▶┃ Cognition ┃ ║░ + ║ ║░ ║ ┃ ┃ ║░ + ╚═══════════╝░ ║ ┃ Action ┃ ║░ + ░░░░░░░░░░░░░ ║ ┗━━━━━━━━━━━━━━━┬━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ + ║ │ ║░ + ║ ▼ ║░ + ║ ┌───────────────────────┐ ║░ + ║ │ Confirm action? │ ║░ + ║ └───────────┬───────────┘ ║░ + ║ │ ║░ + ║ ▼ ║░ + ║ ┌───────────────────────┐ ║░ + ║ │ Execute Action │ ║░ + ║ └───────────────────────┘ ║░ + ║ ║░ + ╚════════════════════════════════════════════════╝░ + ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░`, + + dataFlow: ` ╔═ Data Pipeline ═════════════════════════════╗ +╔═══════════╗ ║ ║░ +║ ║░ ║ ┏━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━┓ ║░ +║ Input ║░────────────║─▶┃ Process ┃────▶┃ Transform ┃ ║░ +║ ║░ ║ ┗━━━━━━━━━━━┛ ┗━━━━━━━┬━━━━━━━━━┛ ║░ +╚═══════════╝░ ║ │ ║░ + ░░░░░░░░░░░░░ ║ ▼ ║░ + ║ ┌──────────────────┐ ║░ + ║ │ Store (DB) │ ║░ + ║ └──────────────────┘ ║░ + ║ ║░ + ╚═════════════════════════════════════════════╝░ + ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░`, + + microservices: ` ╔═ Microservices Architecture ════════════════════╗ +╔═══════════╗ ║ ║░ +║ ║░ ║ ┌─────────────────────────────────────┐ ║░ +║ Client ║░────API─────║─▶│ API Gateway │ ║░ +║ ║░ ║ └──────────┬──────────────┬───────────┘ ║░ +╚═══════════╝░ ║ │ │ ║░ + ░░░░░░░░░░░░░ ║ ▼ ▼ ║░ + ║ ┏━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━┓ ║░ + ║ ┃ Service A ┃ ┃ Service B ┃ ║░ + ║ ┗━━━━━━┬━━━━━━┛ ┗━━━━━━┬━━━━━━┛ ║░ + ║ │ │ ║░ + ║ └────────┬────────┘ ║░ + ║ ▼ ║░ + ║ ┌─────────────────┐ ║░ + ║ │ Database │ ║░ + ║ └─────────────────┘ ║░ + ╚══════════════════════════════════════════════╝░ + ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░`, + + simpleFlow: `╔════════════╗ ╔════════════╗ ╔════════════╗ +║ ║░ ║ ║░ ║ ║░ +║ Step 1 ║░───▶║ Step 2 ║░───▶║ Step 3 ║░ +║ ║░ ║ ║░ ║ ║░ +╚════════════╝░ ╚════════════╝░ ╚════════════╝░ + ░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░`, + + infrastructureLayer: ` ╔═ plano ════════════════════════════════════════╗ + ╔═══════════╗ ║ ║░ + ║ ║░ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ + ║ client ║░─────────║─▶┃ Safety Guardrails ┃ ║░ + ║ ║░ ║ ┃ ┃ ║░ + ╚═══════════╝░ ║ ┗━━━━━━━━━━━━━━━┬━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ + ░░░░░░░░░░░░░ ║ │ ║░ + ║ ▼ ║░ + ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ + ║ ┃ Multi-Agent Workflows ┃ ║░ + ║ ┗━━━━━━━━━━━━━━━┬━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ + ║ │ ║░ + ║ ▼ ║░ + ║ ┌───────────────────────────────┐ ║░ + ║ │ Unified LLM Access │ ║░ + ║ └───────────────────────────────┘ ║░ + ║ ║░ + ╚════════════════════════════════════════════════╝░ + ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░`, +}; + +export type DiagramKey = keyof typeof diagrams; + diff --git a/www/src/pages/examples.tsx b/www/src/pages/examples.tsx new file mode 100644 index 00000000..ee978b31 --- /dev/null +++ b/www/src/pages/examples.tsx @@ -0,0 +1,144 @@ +"use client"; + +import { DiagramBuilder } from "@/components/DiagramBuilder"; +import { createSimpleProcess, templates } from "@/data/diagramTemplates"; +import { createFlowDiagram } from "@/utils/asciiBuilder"; + +export default function ExamplesPage() { + return ( +
+
+

+ Programmatic Diagram Examples +

+ +
+

+ Example 1: Simple Process Flow +

+

+ Create a simple 3-step process programmatically: +

+
+{`import { createSimpleProcess } from '@/data/diagramTemplates';
+
+const diagram = createSimpleProcess(['Start', 'Process', 'End']);`}
+          
+ +
+ +
+

+ Example 2: API Flow with Different Box Types +

+

+ Mix container, inner, and regular boxes: +

+
+{`const diagram = createFlowDiagram({
+  title: 'API Request Flow',
+  width: 65,
+  steps: [
+    { label: 'Client Request', type: 'regular', shadow: true },
+    { label: 'API Gateway', type: 'container', shadow: true },
+    { label: 'Process', type: 'inner', shadow: true },
+    { label: 'Response', type: 'regular', shadow: true }
+  ]
+});`}
+          
+ +
+ +
+

+ Example 3: Data Pipeline +

+ +
+ +
+

+ How to Use Programmatic Diagrams +

+
+
+

1. Import the Builder

+
+{`import { DiagramBuilder } from '@/components/DiagramBuilder';`}
+              
+
+ +
+

2. Define Your Steps

+
+{``}
+              
+
+ +
+

3. Box Types

+
    +
  • regular - Thin box borders (┌─┐)
  • +
  • inner - Thick borders (┏━┓)
  • +
  • container - Extra thick borders (╔═╗)
  • +
+
+ +
+

Benefits

+
    +
  • ✅ No manual spacing calculations
  • +
  • ✅ Automatic alignment
  • +
  • ✅ Easy for non-coders to use
  • +
  • ✅ Consistent formatting
  • +
  • ✅ Type-safe with TypeScript
  • +
+
+
+
+
+
+ ); +} + diff --git a/www/src/utils/asciiBuilder.ts b/www/src/utils/asciiBuilder.ts new file mode 100644 index 00000000..45bd755f --- /dev/null +++ b/www/src/utils/asciiBuilder.ts @@ -0,0 +1,379 @@ +/** + * ASCII Diagram Builder - Auto-spacing and formatting utilities + * + * This module provides utilities to ensure consistent spacing across ASCII diagrams + * similar to the intent detection diagram pattern. + */ + +interface BoxDimensions { + label: string; + width: number; + height: number; +} + +/** + * Calculates proper padding to center content within a container width + */ +export function calculateCenterPadding(contentWidth: number, containerWidth: number): number { + return Math.floor((containerWidth - contentWidth) / 2); +} + +/** + * Creates a horizontal arrow between two positions + */ +export function createArrow(length: number, direction: '→' | '↓' | '↑' | '←' = '→'): string { + return direction.repeat(length); +} + +/** + * Builds a box with specified dimensions, label, and box type + */ +export function buildBox( + label: string, + type: 'container' | 'inner' | 'regular' = 'regular', + shadow: boolean = true, + width?: number +): string[] { + const actualWidth = width || Math.max(label.length + 4, 12); + const paddedLabel = label.padStart(Math.floor((actualWidth - 2 + label.length) / 2), ' ') + .padEnd(actualWidth - 2, ' '); + + const symbols = { + container: { tl: '╔', tr: '╗', bl: '╚', br: '╝', h: '═', v: '║' }, + inner: { tl: '┏', tr: '┓', bl: '┗', br: '┛', h: '━', v: '┃' }, + regular: { tl: '┌', tr: '┐', bl: '└', br: '┘', h: '─', v: '│' } + }; + + const s = symbols[type]; + const shadowChar = '░'; + + const lines = [ + s.tl + s.h.repeat(actualWidth - 2) + s.tr + (shadow ? shadowChar : ''), + s.v + paddedLabel + s.v + (shadow ? shadowChar : ''), + s.bl + s.h.repeat(actualWidth - 2) + s.br + (shadow ? shadowChar : '') + ]; + + if (shadow) { + lines.push(' ' + shadowChar.repeat(actualWidth)); + } + + return lines; +} + +/** + * Fixes spacing in an existing diagram by analyzing and adjusting alignment + */ +export function fixDiagramSpacing(diagram: string): string { + const lines = diagram.split('\n'); + if (lines.length === 0) return diagram; + + // Find the container boundaries (look for ╔ and ╚ markers) + let containerStart = -1; + let containerEnd = -1; + let containerWidth = 0; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + if (line.includes('╔═') && line.includes('╗')) { + containerStart = i; + containerWidth = line.length; + } + if (line.includes('╚') && line.includes('╝')) { + containerEnd = i; + } + } + + if (containerStart === -1 || containerEnd === -1) { + return diagram; // Can't fix if no container found + } + + // The intent detection pattern shows: + // Line 2: title line with ╔═ {title} ═{fill}╗ + // Lines 3-19: content with ║ on sides + // Line 20: bottom ╚══════╝ + // Line 21: shadow line + + // For intent detection, the container content width is about 60 chars + // Total line width including borders is about 68-70 + // Content starts around position 26 + + // Detect pattern by looking at first content line + const firstContentLine = lines[containerStart + 1]; + if (!firstContentLine) return diagram; + + const leftPadding = firstContentLine.indexOf('║'); + const rightPadding = containerWidth - firstContentLine.lastIndexOf('║') - 1; + + // Now standardize all internal lines + const fixedLines = [...lines]; + + for (let i = containerStart + 1; i < containerEnd; i++) { + const line = lines[i]; + const shadowIndex = line.indexOf('░'); + + if (line.trim().startsWith('║')) { + // This is a content line inside the container + // Standardize the padding + const content = extractContainerContent(line); + fixedLines[i] = padContainerLine(content, containerWidth, leftPadding); + } + } + + return fixedLines.join('\n'); +} + +function extractContainerContent(line: string): string { + // Extract content between ║ characters + const startIdx = line.indexOf('║'); + const endIdx = line.lastIndexOf('║'); + if (startIdx === -1 || endIdx === -1 || startIdx === endIdx) return line; + return line.substring(startIdx + 1, endIdx); +} + +function padContainerLine(content: string, containerWidth: number, targetLeftPad: number): string { + const padding = ' '.repeat(targetLeftPad); + const contentLength = content.length; + const rightPadding = containerWidth - targetLeftPad - contentLength - 2; // -2 for two ║ + const rightPad = rightPadding > 0 ? ' '.repeat(rightPadding) : ''; + + return padding + '║' + content + '║' + rightPad + '░'; +} + +/** + * Creates a simple flow diagram programmatically + * Usage: + * ```ts + * const diagram = createFlowDiagram({ + * title: "My Process", + * width: 60, + * steps: [ + * { label: "Step 1", type: "regular" }, + * { label: "Step 2", type: "inner" }, + * { label: "Step 3", type: "regular" } + * ] + * }); + * ``` + */ +export interface FlowStep { + label: string; + type?: 'container' | 'inner' | 'regular'; + shadow?: boolean; +} + +export interface FlowDiagramConfig { + title: string; + width?: number; + steps: FlowStep[]; + layout?: 'vertical' | 'horizontal'; + externalElements?: FlowStep[]; // Elements outside the container (like "agent") +} + +export function createFlowDiagram(config: FlowDiagramConfig): string { + const layout = config.layout || 'vertical'; + + if (layout === 'horizontal') { + return createHorizontalFlow(config); + } else { + return createVerticalFlow(config); + } +} + +function createVerticalFlow(config: FlowDiagramConfig): string { + const width = config.width || 60; + const hasExternal = config.externalElements && config.externalElements.length > 0; + + // Build external elements first + let externalBoxes: string[] = []; + let externalWidth = 0; + + if (hasExternal) { + externalWidth = 20; + for (const extEl of config.externalElements!) { + const extWidth = Math.max(extEl.label.length + 4, 12); + const extBoxLines = buildBox(extEl.label, extEl.type || 'regular', extEl.shadow !== false, extWidth); + + for (const extLine of extBoxLines) { + externalBoxes.push(' '.repeat(2) + extLine); + } + + // Add vertical arrow if not last + if (extEl !== config.externalElements![config.externalElements!.length - 1]) { + const arrowPad = 2 + Math.floor(extWidth / 2); + externalBoxes.push(' '.repeat(arrowPad) + '▼'); + } + } + } + + const titleLine = hasExternal + ? ` ╔═ ${config.title} ${'═'.repeat(Math.max(0, width - config.title.length - 5))}╗` + : `╔═ ${config.title} ${'═'.repeat(Math.max(0, width - config.title.length - 5))}╗`; + + const lines: string[] = []; + lines.push(titleLine); + + // Find max step width + const maxStepWidth = Math.max(...config.steps.map(s => s.label.length), 20); + const stepWidth = maxStepWidth + 4; + + // Build internal steps + const internalLines: string[] = []; + + for (let i = 0; i < config.steps.length; i++) { + const step = config.steps[i]; + const boxLines = buildBox(step.label, step.type || 'regular', step.shadow !== false, stepWidth); + + // Center each box + const leftPadding = calculateCenterPadding(stepWidth, width); + + for (const boxLine of boxLines) { + internalLines.push(' '.repeat(leftPadding) + boxLine); + } + + // Add vertical arrow between steps (except last) + if (i < config.steps.length - 1) { + const arrowPad = calculateCenterPadding(1, width); + internalLines.push(' '.repeat(arrowPad) + '│'); + internalLines.push(' '.repeat(arrowPad) + '▼'); + } + } + + // Combine external and internal elements + const maxHeight = Math.max(externalBoxes.length, internalLines.length); + + for (let row = 0; row < maxHeight; row++) { + let line = ''; + + // External part + if (row < externalBoxes.length) { + line += externalBoxes[row]; + + // Add connecting arrow on middle row + if (row === Math.floor(externalBoxes.length / 2)) { + line += '░'.repeat(6) + '─'.repeat(10) + '─▶║─'; + } else { + line += '░'.repeat(6) + ' '.repeat(10) + ' ║ '; + } + } else if (hasExternal) { + line += ' '.repeat(externalWidth); + if (row < internalLines.length) { + line += '░'.repeat(6) + ' '.repeat(10) + ' ║ '; + } + } else { + line += ' '.repeat(externalWidth); + } + + // Internal container part + if (row < internalLines.length) { + line += internalLines[row]; + } else { + line += ' '.repeat(width); + } + + line += '║░'; + lines.push(line); + } + + // Close container + const bottomPadding = hasExternal ? ' '.repeat(externalWidth + 16) : ''; + const bottomLine = bottomPadding + '╚' + '═'.repeat(width - 1) + '╝░'; + lines.push(bottomLine); + + const shadowLine = (hasExternal ? ' '.repeat(externalWidth + 17) : ' ') + '░'.repeat(width); + lines.push(shadowLine); + + return lines.join('\n'); +} + +function createHorizontalFlow(config: FlowDiagramConfig): string { + const width = config.width || 70; + const hasExternal = config.externalElements && config.externalElements.length > 0; + const lines: string[] = []; + + // Calculate step widths + const maxStepWidth = Math.max(...config.steps.map(s => s.label.length), 16); + const stepWidth = maxStepWidth + 4; + const arrowGap = 12; + const totalStepWidth = config.steps.length * stepWidth + (config.steps.length - 1) * arrowGap; + const containerPadding = Math.max(4, Math.floor((width - totalStepWidth) / 2)); + + // Build internal boxes matrix + const boxMatrix: string[][] = []; + let maxHeight = 0; + for (const step of config.steps) { + const boxLines = buildBox(step.label, step.type || 'regular', step.shadow !== false, stepWidth); + boxMatrix.push(boxLines); + maxHeight = Math.max(maxHeight, boxLines.length); + } + + // Title line - position based on external elements + const titleLeftPad = hasExternal ? 26 : 26; + const titleRepeatCount = Math.max(0, width - config.title.length - 5); + const titleLine = ' '.repeat(titleLeftPad) + `╔═ ${config.title} ${'═'.repeat(titleRepeatCount)}╗`; + lines.push(titleLine); + + // Build external box for rendering + let externalBoxLines: string[] = []; + if (hasExternal) { + const extEl = config.externalElements![0]; + const extWidth = Math.max(extEl.label.length + 4, 16); + externalBoxLines = buildBox(extEl.label, extEl.type || 'regular', extEl.shadow !== false, extWidth); + } + + // Render content rows + for (let row = 0; row < maxHeight; row++) { + let line = ''; + + // External elements on left (if present) + if (hasExternal) { + const extRow = row < externalBoxLines.length ? row : -1; + + if (extRow >= 0) { + line += ' ' + externalBoxLines[extRow]; + + // Add connecting arrow on middle row + if (row === Math.floor(externalBoxLines.length / 2)) { + line += '░'.repeat(5) + '─'.repeat(8) + '─▶║─'; + } else { + line += '░'.repeat(5) + ' '.repeat(8) + ' ║ '; + } + } else { + line += ' '.repeat(26) + '║ '; + } + } else { + line += ' '.repeat(26) + '║ '; + } + + // Internal container boxes with proper padding + line += ' '.repeat(containerPadding); + + for (let i = 0; i < boxMatrix.length; i++) { + const boxLines = boxMatrix[i]; + const boxLine = row < boxLines.length ? boxLines[row] : ' '.repeat(stepWidth + (config.steps[i].shadow !== false ? 1 : 0)); + line += boxLine; + + // Add horizontal arrow between boxes + if (i < boxMatrix.length - 1) { + if (row === Math.floor(maxHeight / 2)) { + line += '─'.repeat(arrowGap) + '►'; + } else { + line += ' '.repeat(arrowGap + 1); + } + } + } + + // Right padding and border + const usedWidth = containerPadding + totalStepWidth; + const rightPad = Math.max(0, width - usedWidth); + line += ' '.repeat(rightPad); + line += '║░'; + lines.push(line); + } + + // Close container + const bottomLine = ' '.repeat(26) + '╚' + '═'.repeat(width - 1) + '╝░'; + lines.push(bottomLine); + const shadowLine = ' '.repeat(27) + '░'.repeat(width); + lines.push(shadowLine); + + return lines.join('\n'); +} diff --git a/www/tsconfig.json b/www/tsconfig.json new file mode 100644 index 00000000..cf9c65d3 --- /dev/null +++ b/www/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts", + "**/*.mts" + ], + "exclude": ["node_modules"] +}