diff --git a/.cursor/mcp.json b/.cursor/mcp.json deleted file mode 100644 index d7a82c2..0000000 --- a/.cursor/mcp.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "mcpServers": { - "shadcn": { - "command": "npx", - "args": ["-y", "shadcn@canary", "registry:mcp"], - "env": { - "REGISTRY_URL": "https://animate-ui.com/r/registry.json" - } - } - } -} diff --git a/.env.local.example b/.env.local.example new file mode 100644 index 0000000..840ae83 --- /dev/null +++ b/.env.local.example @@ -0,0 +1,23 @@ +# Environment variables for Fortura Data Solutions website + +# Next.js environment +NODE_ENV=development + +# API endpoints (if applicable) +# NEXT_PUBLIC_API_URL=http://localhost:3001/api + +# Analytics (if self-hosted) +# NEXT_PUBLIC_PLAUSIBLE_DOMAIN=your-domain.com +# NEXT_PUBLIC_PLAUSIBLE_API_HOST=https://plausible.your-domain.com + +# Contact form submission endpoint +# CONTACT_FORM_ENDPOINT=https://n8n.your-domain.com/webhook/contact-form + +# Calendly integration (if applicable) +# CALENDLY_URL=https://calendly.com/your-calendly-url + +# Email service (if applicable) +# NEXT_PUBLIC_EMAIL_SERVICE_ENDPOINT=https://api.email-service.com/send + +# Feature flags +# NEXT_PUBLIC_FEATURE_FLAG_NEW_DESIGN=true \ No newline at end of file diff --git a/061cecebb592 b/061cecebb592 new file mode 100644 index 0000000..e69de29 diff --git a/46db0b326091 b/46db0b326091 new file mode 100644 index 0000000..e69de29 diff --git a/4cf371dfcf97 b/4cf371dfcf97 new file mode 100644 index 0000000..e69de29 diff --git a/631b88c73ff0 b/631b88c73ff0 new file mode 100644 index 0000000..e69de29 diff --git a/7cdef5a33192 b/7cdef5a33192 new file mode 100644 index 0000000..e69de29 diff --git a/8fccc2e8a28d b/8fccc2e8a28d new file mode 100644 index 0000000..e69de29 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 51730da..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,348 +0,0 @@ -# Contributing to Animate UI - -Thank you for your interest in **contributing to Animate UI**! Your support is highly appreciated, and we look forward to your contributions. This guide will help you understand the project structure and provide detailed instructions for adding a new component or effect to Animate UI. - -**Note:** You only need to modify a few files to add a new component, and it should take you around 10 minutes to complete. - -## Getting Started - -### Fork and Clone the Repository - -#### 1. Fork the Repository - -Click [here](https://github.com/animate-ui/animate-ui/fork) to fork the repository. - -#### 2. Clone your Fork to Your Local Machine - -```bash - git clone https://github.com//animate-ui.git -``` - -#### 3. Navigate to the Project Directory - -```bash -cd animate-ui -``` - -#### 4. Create a New Branch for Your Changes - -```bash -git checkout -b my-branch -``` - -#### 5. Install Dependencies - -```bash -pnpm i -``` - -#### 6. Run the Project - -```bash -pnpm dev -``` - -## Edit a Component - -If you need to modify a component to correct or improve it, you must : - -- add a screenshot (photo or video as appropriate) of before and after the modification -- clearly explain why you made the modification - -### Edit the code - -Edit the component in the `registry` folder. Don't forget to adapt the demo and documentation if necessary. - -You shouldn't change your behavior completely unless there's a good reason. - -### Build the Registry - -To update the registry, run the following command: - -```bash -pnpm registry:build -``` - -## Adding a New Component - -The addition of a new component must comply with certain rules: - -- The component must be animated in some way (css, motion, ...). -- You can't just copy/paste component code from other libraries. You can be inspired by a component, but it must have added value. For example, I took Shadcn's components and animated them. So I didn't copy and paste the component, I added something to it. -- If you take inspiration from a component (CodePen, another library, etc.), remember to add the “Credits” section to your documentation. It's important to respect the work of other developers. - -To submit your component, please include a demo video in the MR. Once the component has been submitted, it must be validated by @imskyleen. - -To **add a new component to Animate UI**, you will need to update several files. Follow these steps: - -### Create the Component - -#### Basics - -Create your main component in `apps/www/registry/[category]/my-component/index.tsx`. - -```tsx title="my-component/index.tsx" -'use client'; - -import * as React from 'react'; - -type MyComponentProps = { - myProps: string; -} & React.ComponentProps<'div'>; - -function MyComponent({ myProps, ...props }) { - return
{/* Your component */}
; -} - -export { MyComponent, type MyComponentProps }; -``` - -#### Registry item - -Create a `apps/www/registry/[category]/my-component/registry-item.json` file to export your component : - -```json title="my-component/registry-item.json" -{ - "$schema": "https://ui.shadcn.com/schema/registry-item.json", - "name": "my-component", - "type": "registry:ui", - "title": "My Component", - "description": "My Component Description", - "dependencies": [...], - "devDependencies": [...], - "files": [ - { - "path": "registry/[category]/my-component/index.tsx", - "type": "registry:ui", - "target": "components/animate-ui/demo/[category]/my-component.tsx" - } - ] -} -``` - -### Create a demo - -#### Basics - -Create your demo in `apps/www/registry/demo/[category]/my-component/index.tsx`. - -```tsx title="my-component/index.tsx" -'use client'; - -import { - MyComponent, - type MyComponentProps, -} from '@/registry/[category]/my-component'; - -type MyComponentDemoProps = { - myProps: string; -} & MyComponentProps; - -export const MyComponentDemo = ({ myProps }) => { - return ; -}; -``` - -#### Registry item - -```json title="my-component/registry-item.json" -{ - "$schema": "https://ui.shadcn.com/schema/registry-item.json", - "name": "my-component-demo", - "type": "registry:ui", - "title": "My Component Deo", - "description": "Demo showing my component", - "registryDependencies": ["https://animate-ui.com/r/my-component"], - "files": [ - { - "path": "registry/demo/[category]/my-component/index.tsx", - "type": "registry:ui", - "target": "components/[category]/demo/my-component.tsx" - } - ] -} -``` - -#### Add a Tweakpane - -You can add a Tweakpane allowing users to play with your demo props. - -Your demo must accept the props you want in your tweakpane : - -```tsx title="my-component-demo/index.tsx" -import { MyComponent } from '@/registry/[category]/my-component'; - -type MyComponentDemoProps = { - props1: number; - props2: number; - props3: string; - props4: string; - props5: boolean; -}; - -export function MyComponentDemo({ - props1, - props2, - props3, - props4, - props5, -}: MyComponentDemoProps) { - return ; -} -``` - -You must then specify the demo props information in your demo's `registry-item.json` file: - -```json title="my-component-demo/registry-item.json" -{ - ... - "meta": { - "demoProps": { - "MyComponent": { - "props1": { "value": 700, "min": 0, "max": 2000, "step": 100 }, - "props2": { "value": 0 }, - "props3": { "value": "foo" }, - "props4": { - "value": "center", - "options": { - "start": "start", - "center": "center", - "end": "end" - } - }, - "props5": { "value": true } - } - } - }, - ... -} -``` - -**You need to run `pnpm registry:build` to see the updated tweakpane in the demo.** - -#### How to use `demoProps` - -##### Number - -Simple number input: - -```json -"myNumber": { "value": 10 } -``` - -Slider: - -```json -"myNumber": { "value": 10, "min": 0, "max": 100, "step": 1 } -``` - -Select: - -```json -"myNumber": { - "value": 10, - "options": { - "Big": 30, - "Medium": 20, - "Small": 10 - } -} -``` - -##### String - -Simple text input: - -```json -"myString": { "value": "Hello World" } -``` - -Select: - -```json -"myNumber": { - "value": "small", - "options": { - "Big": "big", - "Medium": "medium", - "Small": "small" - } -} -``` - -##### Boolean - -```json -"myBoolean": { "value": true } -``` - -### Update the Documentation Sidebar - -Add your component to the documentation sidebar by updating the file `content/docs/meta.json`. - -```json title="meta.json" -{ - "title": "Animate UI", - "root": true, - "pages": [ - ..., - "[category]/my-component" - ... - ] -} -``` - -### Create the Component Documentation - -Create an MDX file to document your component in `content/docs/[category]/my-component.mdx`. - -```mdx ---- -title: My Component -description: Description for the new component -author: - name: your name - url: https://link-to-your-profile.com -new: true ---- - - - -## Installation - - - -## Usage - -[Basic usage of the component] - -## Props - - - -## Credits - -- Credits to [you](https://link-to-your-profile.com) for creating the component -``` - -### Build the Registry - -To update the registry, run the following command: - -```bash -pnpm registry:build -``` - -## Ask for Help - -If you need any assistance or have questions, please feel free to open a [GitHub issue](https://github.com/animate-ui/animate-ui/issues/new). We are here to help! - -Thank you again for your contribution to Animate UI! We look forward to seeing your improvements and new components. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a80f0c1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +# Use Node.js 20 as the base image +FROM node:20-alpine + +# Set the working directory +WORKDIR /app + +# Install pnpm globally +RUN npm install -g pnpm + +# Copy package.json and pnpm-lock.yaml files +COPY package.json pnpm-lock.yaml ./ + +# Copy turbo.json +COPY turbo.json ./ + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Copy the rest of the application code +COPY . . + +# Build the application +RUN pnpm build + +# Expose port 3000 +EXPOSE 3000 + +# Start the application +CMD ["pnpm", "start"] \ No newline at end of file diff --git a/README.md b/README.md index 77a4d9c..5936e6c 100644 --- a/README.md +++ b/README.md @@ -30,16 +30,148 @@ We built our platform for high-demand environments like VFX studios, where petab This repository contains the code for the Fortura Data Solutions marketing website. It's built with Next.js, TypeScript, and Tailwind CSS. -For information on how to set up the development environment, run the site locally, or contribute, please see our [contributing guide](CONTRIBUTING.md). +### Prerequisites + +- Node.js >= 20 +- pnpm >= 8 +- Docker (optional, for containerized deployment) + +### Environment Variables + +To run this project, you'll need to set up the following environment variables: + +```bash +# Create a .env.local file in the root directory +cp .env.local.example .env.local +``` + +Then edit the `.env.local` file to include your configuration: + +```env +# Next.js environment +NODE_ENV=development + +# API endpoints (if applicable) +# NEXT_PUBLIC_API_URL=http://localhost:3001/api + +# Analytics (if self-hosted) +# NEXT_PUBLIC_PLAUSIBLE_DOMAIN=your-domain.com +# NEXT_PUBLIC_PLAUSIBLE_API_HOST=https://plausible.your-domain.com + +# Contact form submission endpoint +# CONTACT_FORM_ENDPOINT=https://n8n.your-domain.com/webhook/contact-form + +# Calendly integration (if applicable) +# CALENDLY_URL=https://calendly.com/your-calendly-url +``` + +### Development + +To run the development server: + +```bash +# Install dependencies +pnpm install + +# Run the development server +pnpm dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +### Docker Deployment + +To build and run the application using Docker: + +1. Build the Docker image: + ```bash + docker build -t fortura-website -f apps/www/Dockerfile . + ``` + +2. Run the container: + ```bash + docker run -p 3000:3000 --env-file .env.local fortura-website + ``` + +Alternatively, use docker-compose: +```bash +docker-compose up --build +``` + +The application will be available at [http://localhost:3000](http://localhost:3000). + +### Production Build + +To create a production build: + +```bash +# Build the application +pnpm build + +# Start the production server +pnpm start +``` + +## Troubleshooting + +### TS2742 from Fumadocs generated files (Next.js 15 type-check) + +TypeScript can flag the generated Fumadocs output in `apps/www/.source/index.ts` because the inferred type of `docs` references private internals from `fumadocs-mdx/dist/...`. Next 15 enforces strict type portability and fails with TS2742. + +Fast unblock (recommended and safe): exclude generated files from type-check. + +1) Ensure `apps/www/tsconfig.json` excludes the generated folder and relaxes lib checks: + +```json +{ + "compilerOptions": { + "skipLibCheck": true + }, + "exclude": [ + ".source", + ".source/**/*" + ] +} +``` + +2) Clean and rebuild the app: + +```bash +rm -rf apps/www/.source +pnpm -C apps/www build +``` + +Proper fix (long-term): align Fumadocs + Zod and regenerate. + +1) Upgrade deps (workspace-wide): + +```bash +pnpm -w up fumadocs-mdx@latest fumadocs-core@latest fumadocs-ui@latest @types/mdx@latest +pnpm -w up zod@^4 +``` + +2) Regenerate the `.source` output: + +```bash +rm -rf apps/www/.source +pnpm -C apps/www build +``` + +3) If the generator still emits a generic that triggers TS2742, enforce a portable annotation in `apps/www/.source/index.ts` (temporary): + +```ts +import { _runtime } from 'fumadocs-mdx'; +type DocsData = ReturnType; +export const docs: DocsData = _runtime.docs(/* generated arrays */); +// or fallback: export const docs: unknown = _runtime.docs(/* generated arrays */); +``` + +Note: Keeping `.source` excluded from type-checks is fine even after upgrades; it also speeds up CI. ## Documentation Detailed documentation for Fortura's services, migration guides, and operational procedures is available to clients on our internal portal. -## Contributing - -Visit our [contributing guide](CONTRIBUTING.md) to learn how to contribute to the website's codebase. - ## License -This website's code is licensed under a proprietary license. See [LICENSE.md](LICENSE.md) for details. \ No newline at end of file +This website's code is licensed under a proprietary license. See [LICENSE.md](LICENSE.md) for details. diff --git a/Running b/Running new file mode 100644 index 0000000..e69de29 diff --git a/Using b/Using new file mode 100644 index 0000000..e69de29 diff --git a/animate-ui@0.0.1 b/animate-ui@0.0.1 new file mode 100644 index 0000000..e69de29 diff --git a/apps/www/.source-typed.ts b/apps/www/.source-typed.ts new file mode 100644 index 0000000..59281b4 --- /dev/null +++ b/apps/www/.source-typed.ts @@ -0,0 +1,13 @@ +// Typed facade for the generated .source/index.ts +// Keep this file portable and avoid referencing internal fumadocs types. + +// Minimal surface used by the app (extend if you need more methods) +export type DocsApi = { + toFumadocsSource(): unknown; +}; + +// Defer loading the generated module to runtime and avoid importing its types +export const docs: DocsApi = { + // eslint-disable-next-line @typescript-eslint/no-var-requires + toFumadocsSource: () => require('./.source/index').docs.toFumadocsSource(), +}; diff --git a/apps/www/Dockerfile b/apps/www/Dockerfile new file mode 100644 index 0000000..44f9e5b --- /dev/null +++ b/apps/www/Dockerfile @@ -0,0 +1,26 @@ +# Use Node.js 20 as the base image +FROM node:20-alpine + +# Set the working directory +WORKDIR /app + +# Install pnpm globally +RUN npm install -g pnpm + +# Copy package.json and pnpm-lock.yaml files +COPY package.json pnpm-lock.yaml ./ + +# Install dependencies +RUN pnpm install --frozen-lockfile + +# Copy the rest of the application code +COPY . . + +# Build the application +RUN pnpm build + +# Expose port 3000 +EXPOSE 3000 + +# Start the application +CMD ["pnpm", "start"] \ No newline at end of file diff --git a/apps/www/app/(home)/page.tsx b/apps/www/app/(home)/page.tsx index 4ac6bc1..37b3c53 100644 --- a/apps/www/app/(home)/page.tsx +++ b/apps/www/app/(home)/page.tsx @@ -6,348 +6,256 @@ import * as React from 'react'; // Import layout components from our new shared `ui` library import { Navbar } from '@workspace/ui/components/layout'; import { Footer } from '@workspace/ui/components/layout'; -import { Container, Section, Grid } from '@workspace/ui/components/layout'; +import { Container } from '@workspace/ui/components/layout'; +import { AnimatedSection } from '@workspace/ui/components/animate-ui/section'; +// import { ScrollProgressBar } from '@workspace/ui/components/animate-ui/scroll-progress'; +// import { Collapsible, CollapsibleTrigger, CollapsibleContent } from '@workspace/ui/components/animate-ui/collapsible'; +import { motion, useScroll, useTransform } from 'motion/react'; +// import { ParallaxLayers } from '@workspace/ui/components/animate-ui/parallax-layers'; // Import the useTone hook to access the global tone setting import { useTone } from '@workspace/ui/hooks/use-tone'; // Import Lucide icons for the value proposition section -import { DollarSignIcon, WrenchIcon, MapIcon, LockIcon, CloudOffIcon, ZapIcon } from 'lucide-react'; -import { PlaceholderIcon } from '@workspace/ui/components/icons'; +import { WrenchIcon, LockIcon, CloudOffIcon, ZapIcon } from 'lucide-react'; // Import UI components from our shared library import { Button } from '@workspace/ui/components/ui'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@workspace/ui/components/ui'; +import Image from 'next/image'; // Import new content components import { MetricsKPI } from '@workspace/ui/components/content'; -import { LogosMarquee } from '@workspace/ui/components/content'; -import { Steps } from '@workspace/ui/components/content'; -import { FeatureCard, CaseStudyCard } from '@workspace/ui/components/content/cards'; +// import { Steps } from '@workspace/ui/components/content'; import { TrustSection } from '@workspace/ui/components/content'; -import { FAQAccordion } from '@workspace/ui/components/interactive'; +// import { FAQAccordion } from '@workspace/ui/components/interactive'; import { FinalCTASection } from '@workspace/ui/components/content'; +import { CostReductionChart } from '@workspace/ui/components/content/cost-reduction-chart'; export default function HomePage() { const { tone } = useTone(); // Access the current tone // Content definitions based on tone - const heroHeadline = tone === 'direct' - ? "Own your infrastructure. Slash your bill." - : "Cut waste, keep performance."; - const heroSubcopyLine1 = tone === 'direct' - ? "Your hosting provider is fucking you. Cloud rent bleeds $25k–$500k/mo." - : "Cloud rent is bleeding your budget dry."; - const heroSubcopyLine2 = tone === 'direct' - ? "Own the hardware. Keep the performance. Kill the waste." - : "Own your stack. Colocate it. Keep the performance, ditch the waste."; + const heroHeadline = + tone === 'direct' + ? 'Own your infrastructure. Slash your bill.' + : 'Cut waste, keep performance.'; + const heroSubcopyLine1 = + tone === 'direct' + ? 'Your hosting provider is fucking you. Cloud rent bleeds $25k–$500k/mo.' + : 'Cloud rent is bleeding your budget dry.'; + const heroSubcopyLine2 = + tone === 'direct' + ? 'Own the hardware. Keep the performance. Kill the waste.' + : 'Own your stack. Colocate it. Keep the performance, ditch the waste.'; - const valuePropositions = tone === 'direct' ? [ + // Core value propositions based on core selling points + const coreValuePropositions = [ { - icon: , - title: "Stop getting scammed.", - description: "Cloud rent bleeds $25k–$500k/mo. Own the hardware. Keep the performance. Kill the waste." + title: 'Stop getting scammed', + description: + 'Cloud providers are bleeding you dry. We help you cut costs by up to 65% by moving away from endless rental fees to a one-time hardware purchase plus low colocation costs.', }, { - icon: , - title: "Build on what works.", - description: "Keep your stack. We wire it together and automate the boring." + title: 'Keep your existing stack', + description: + "We don't force you to replace your tools. Instead, we integrate what works and automate the boring parts, so your team can focus on what they do best.", }, { - icon: , - title: "Pave desire paths.", - description: "We embed with your team, shape the system to how they actually work." - } - ] : [ - { - icon: , - title: "Cut waste, keep performance.", - description: "Move from renting to owning. Dramatically reduce monthly costs without sacrificing speed or reliability." + title: 'Work with your actual workflows', + description: + 'We embed with your team, map your real processes, and build automation around how you actually work—not how consultants think you should work.', }, - { - icon: , - title: "Integrate, don't replace.", - description: "We work with your existing tools and workflows. No disruptive rip-and-replace projects." - }, - { - icon: , - title: "Build around real workflows.", - description: "We map your actual processes, then build automation that fits like a glove." - } ]; - // Mock data for LogosMarquee - const logos = Array(6).fill(null).map((_, i) => ({ - name: `Client ${i + 1}`, - icon: - })); - - // Mock data for Process Steps - const processSteps = [ + // Benefits of owned infrastructure + const benefits = [ { - title: "Discovery", - description: "We deep-dive into your current infrastructure, workloads, and pain points.", - youDo: "Share access to cloud billing, architecture docs, and team interviews.", - weDo: "Analyze costs, identify waste, and map technical dependencies." + title: 'Ownership', + description: + 'Own your hardware and data. No more vendor lock-in or unpredictable pricing.', }, { - title: "Shadow & Map", - description: "We observe how your teams actually work and map desire paths.", - youDo: "Participate in workflow observations and workshops.", - weDo: "Document real workflows, identify automation opportunities, and draft the future state." + title: 'Performance', + description: + 'Direct-attached storage and local networks outperform virtualized cloud infrastructure.', }, { - title: "Architect", - description: "We design a tailored, owned infrastructure solution.", - youDo: "Review and approve the proposed architecture and migration plan.", - weDo: "Specify hardware, select software stack, and design for performance and cost." + title: 'Privacy', + description: + 'Your data never leaves your control. AI models run locally with zero data leakage.', }, { - title: "Pilot", - description: "We build and test a critical component in the new environment.", - youDo: "Provide feedback on performance, usability, and integration.", - weDo: "Deploy, test, and iterate on the pilot component with your team." + title: 'Cost Savings', + description: + "Break-even in under 12 months. After that, it's all savings.", }, - { - title: "Migrate", - description: "We execute the planned migration with zero downtime.", - youDo: "Validate functionality and performance post-migration.", - weDo: "Cutover workloads, decommission old systems, and optimize the new stack." - }, - { - title: "Operate", - description: "We manage the infrastructure, you focus on your core business.", - youDo: "Use the system and provide ongoing feedback for improvements.", - weDo: "Monitor, maintain, upgrade, and support the infrastructure 24/7." - } ]; - // Mock data for Case Studies - const caseStudies = [ - { - title: "VFX Studio Migration", - description: "Migrated a major VFX studio from cloud rendering to a colocated HPC cluster, reducing costs by 65%.", - kpi1: { value: "65%", label: "Cost ↓" }, - kpi2: { value: "2x", label: "Performance ↑" }, - ctaText: "See build", - ctaHref: "/case-studies/vfx-studio" - }, - { - title: "Legal Document Management", - description: "Consolidated scattered legal tech stack into a secure, private Nextcloud instance with AI search.", - kpi1: { value: "$120k/mo", label: "Saved" }, - kpi2: { value: "0", label: "Egress Fees" }, - ctaText: "See build", - ctaHref: "/case-studies/legal-firm" - }, - { - title: "Research Data Pipeline", - description: "Built a local ML training environment for a research institute, eliminating data transfer bottlenecks.", - kpi1: { value: "90%", label: "Time-to-Train ↓" }, - kpi2: { value: "Break-even: 8mo", label: "" }, - ctaText: "See build", - ctaHref: "/case-studies/research-institute" - } - ]; - - // Mock data for Trust Section + // Trust factors const trustItems = [ { icon: , - text: "Your data. Your hardware. Your rules." - }, - { - icon: , - text: "Colocated. Monitored. Upgradable without downtime." + text: 'Your data. Your hardware. Your rules.', }, { icon: , - text: "AI-native, privacy-first. No third-party model training." - } - ]; - - // Mock data for FAQ - // (This is just for homepage preview; full FAQ is on /faq page) - const faqItems = [ - { - question: "What uptime can I expect?", - answer: "We design for 99.9%+ uptime through redundant hardware, proactive monitoring, and colocation in Tier III+ facilities." + text: 'AI-native, privacy-first. No third-party AI.', }, { - question: "How is support handled?", - answer: "You get direct access to our engineering team via Slack, email, or phone. We provide 24/7 monitoring and alerting." - } + icon: , + text: 'No license fees. You own it, forever.', + }, + { + icon: , + text: 'Ultimate freedom. Any tool, any stack, reshaped to work together for your unique use-case.', + }, ]; + // Hero right panel scroll-linked fade + const heroRef = React.useRef(null); + const { scrollYProgress: heroProgress } = useScroll({ + target: heroRef, + offset: ['start end', 'end start'], + }); + const heroPanelOpacity = useTransform(heroProgress, [0, 1], [1, 0.96]); + const heroPanelY = useTransform(heroProgress, [0, 1], [0, 8]); + return (
- {/* Hero Section */} -
- -

- {heroHeadline} -

-

- {heroSubcopyLine1} -

-

- {heroSubcopyLine2} -

- - {/* KPI Metrics */} -
- - - -
-
-
- - {/* Value Proposition Section */} -
- -
- {valuePropositions.map((item, index) => ( - - -
- {item.icon} -
- {item.title} -
- - {item.description} - -
- ))} -
-
-
- - {/* Proof Strip / Logos Marquee */} -
- -

Trusted by forward-thinking teams

- -
-
- - {/* Process Snapshot */} -
- - - -
- - {/* Case Study Rail */} -
- -
-

Proven Results

-

- Real outcomes from real migrations. -

-
- - {caseStudies.map((study, index) => ( - - ))} - -
-
- - {/* Pricing Preview / Own vs Rent */} -
- -
-

Own vs Rent

-

- Cloud is a rental agreement with infinite term. Owned hardware + colocation breaks even in under 12 months. -

-
-
-

Why Owned Infrastructure Wins

-
    -
  • - - Capex: You buy the hardware once. Depreciate over 3-5 years. -
  • -
  • - - Low Opex: Colocation is ~$200/server/mo. Managed ops is ~$500/server/mo. -
  • -
  • - - No Egress Fees: Move data freely within your network. -
  • -
  • - - Performance: Direct-attached storage and local networks are faster than VPCs. -
  • -
  • - - No Vendor Lock-in: Standard hardware and open-source software. -
  • -
-
-

- Break-even is typically < 12 months. After that, it's pure savings. + {/* Hero Section (banded, two-column, grid background) */} + + +

+
+

+ {heroHeadline} +

+

+ {heroSubcopyLine1}

+

+ {heroSubcopyLine2} +

+ + {/* KPI Metrics */} +
+ + + +
+ +
+ {/* Optional decorative hero art (drop /hero/home-hero-art.webp in public) */} + +
+
-
+ + + {/* Core Value Propositions - Vertical List */} + + + + + + + {/* Cost Reduction Chart */} + + + + + + + {/* Benefits Section */} + + +
+

Why Owned Infrastructure?

+

+ The benefits of moving from cloud rental to hardware ownership +

+
+
+ {benefits.map((benefit, index) => ( +
+
+ {index < 9 ? `0${index + 1}` : index + 1} +
+

{benefit.title}

+

+ {benefit.description} +

+
+ ))} +
+
+
{/* Trust Section */} -
- - + + + -
- - {/* FAQ Accordion Preview */} -
- -
-

Common Questions

-

- Answers to key concerns about migrating and self-hosting. -

-
- -
- -
-
-
+ {/* Final CTA */} -
- + + -
+
diff --git a/apps/www/app/about/page.tsx b/apps/www/app/about/page.tsx index 6521e06..5a2c885 100644 --- a/apps/www/app/about/page.tsx +++ b/apps/www/app/about/page.tsx @@ -3,127 +3,166 @@ 'use client'; import * as React from 'react'; -import { ExternalLinkIcon, AwardIcon, UsersIcon, ZapIcon } from 'lucide-react'; +import { AwardIcon, UsersIcon, ZapIcon } from 'lucide-react'; import { Navbar } from '@workspace/ui/components/layout'; import { Footer } from '@workspace/ui/components/layout'; -import { Container, Section, Grid } from '@workspace/ui/components/layout'; +import { Container } from '@workspace/ui/components/layout'; +import { AnimatedSection } from '@workspace/ui/components/animate-ui/section'; import { Callout } from '@workspace/ui/components/content'; -import { Badge } from '@workspace/ui/components/content'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@workspace/ui/components/ui'; -import { Button } from '@workspace/ui/components/ui'; +import { FinalCTASection } from '@workspace/ui/components/content'; +import Image from 'next/image'; export default function AboutPage() { return (
-
- -
-

About Fortura

-

- We built it for VFX first. That's why it works for everyone else. + + {/* Hero Section */} + + +

+

+ About Fortura +

+

+ We built it for VFX first. That's why it works for everyone else.

- -
- -
-
-

Our Origin Story

-

- Fortura was born in the high-stakes world of Visual Effects (VFX) production. VFX studios operate on razor-thin margins, require massive computational power, and deal with enormous datasets (petabytes) that need to move fast. -

-

- We saw firsthand how the cloud billing model was financially unsustainable for these studios. They were hemorrhaging money on egress fees, rent for virtual machines that sat idle half the time, and paying premium prices for "enterprise" support that often lagged behind community forums. -

-

- So, we built a better way. A way to own the hardware, colocate it for low-cost power and bandwidth, and automate the hell out of operations so a small team could manage massive infrastructure. -

-
-
- {/* Placeholder for an image or graphic */} -
- VFX Studio Image/Graphic -
-
-
-
-
- -
- -

Why That Matters

- - - - - Petabyte Scale - - - - We cut our teeth on systems handling hundreds of terabytes to petabytes of data. This means we know how to design for scale, performance, and cost-efficiency from the ground up. - - - - - - - Low Budgets - - - - VFX studios have tight budgets. Every dollar spent on infrastructure is a dollar not spent on creative talent or compute rendering the next shot. This discipline forces us to find the absolute cheapest, most efficient solutions. - - - - - - - Real-Time Demands - - - - In VFX, deadlines are absolute. A render farm that's down is a studio that's losing money. This means we obsess over uptime, redundancy, and zero-downtime upgrades. What works for 24/7 VFX pipelines works for any business-critical application. - - - - -
-
- -
- -

Our Mission

-

- Our mission is to fundamentally change how enterprises think about infrastructure. The cloud model of "rent forever" is a bad deal for anyone with significant scale or data. It's a wealth transfer from innovative businesses to cloud providers. -

-

- We show you how to own your infrastructure, colocate it for performance and cost, and operate it with a tiny fraction of the overhead of a cloud provider. You keep the performance, you keep the data, and you keep the savings. -

- - "Your hosting provider is fucking you." This isn't just a tagline; it's a technical reality. We're here to help you take control. - -
-
- -
- -

Ready to take control?

-

- Book a free architecture call to see how much you can save by moving from renting to owning. -

- -
-
-
+ + + {/* Origin Story */} + + +
+
+

Our Origin Story

+
+

+ Fortura was born in the high-stakes world of Visual Effects + (VFX) production. VFX studios operate on razor-thin margins, + require massive computational power, and deal with enormous + datasets (petabytes) that need to move fast. +

+

+ We saw firsthand how the cloud billing model was financially + unsustainable for these studios. They were hemorrhaging money + on egress fees, rent for virtual machines that sat idle half + the time, and paying premium prices for "enterprise" support + that often lagged behind community forums. +

+

+ So, we built a better way. A way to own the hardware, colocate + it for low-cost power and bandwidth, and automate the hell out + of operations so a small team could manage massive + infrastructure. +

+
+
+
+
+ VFX studio render and review environment +
+
+
+
+
+ + {/* Why That Matters */} + + +

+ Why That Matters +

+
+
+
+ +
+

Petabyte Scale

+

+ We cut our teeth on systems handling hundreds of terabytes to + petabytes of data. This means we know how to design for scale, + performance, and cost-efficiency from the ground up. +

+
+
+
+ +
+

Low Budgets

+

+ VFX studios have tight budgets. Every dollar spent on + infrastructure is a dollar not spent on creative talent or + compute rendering the next shot. This discipline forces us to + find the absolute cheapest, most efficient solutions. +

+
+
+
+ +
+

Real-Time Demands

+

+ In VFX, deadlines are absolute. A render farm that's down is a + studio that's losing money. This means we obsess over uptime, + redundancy, and zero-downtime upgrades. What works for 24/7 VFX + pipelines works for any business-critical application. +

+
+
+
+
+ + {/* Our Mission */} + + +

Our Mission

+
+

+ Our mission is to fundamentally change how enterprises think about + infrastructure. The cloud model of "rent forever" is a bad deal + for anyone with significant scale or data. It's a wealth transfer + from innovative businesses to cloud providers. +

+

+ We show you how to own your infrastructure, colocate it for + performance and cost, and operate it with a tiny fraction of the + overhead of a cloud provider. You keep the performance, you keep + the data, and you keep the savings. +

+ + + "Your hosting provider is fucking you." + {' '} + This isn't just a tagline; it's a technical reality. We're here to + help you take control. + +
+
+
+ + {/* Final CTA */} + + + + + +
); -} \ No newline at end of file +} diff --git a/apps/www/app/api/search/route.ts b/apps/www/app/api/search/route.ts index df88962..f72419d 100644 --- a/apps/www/app/api/search/route.ts +++ b/apps/www/app/api/search/route.ts @@ -1,4 +1,5 @@ import { source } from '@/lib/source'; import { createFromSource } from 'fumadocs-core/search/server'; -export const { GET } = createFromSource(source); +// Fast unblock: relax types here to avoid coupling to full LoaderOutput shape +export const { GET } = createFromSource(source as any); diff --git a/apps/www/app/case-studies/page.tsx b/apps/www/app/case-studies/page.tsx new file mode 100644 index 0000000..dcd6d91 --- /dev/null +++ b/apps/www/app/case-studies/page.tsx @@ -0,0 +1,89 @@ +"use client"; + +import * as React from "react"; + +import { Container } from "@workspace/ui/components/layout"; +import { Navbar, Footer } from "@workspace/ui/components/layout"; +import { AnimatedSection } from '@workspace/ui/components/animate-ui/section'; + +export default function CaseStudiesPage() { + const caseStudies = [ + { + title: "VFX Studio Migration", + description: + "Migrated a major VFX studio from cloud rendering to a colocated HPC cluster, reducing costs by 65%.", + kpi1: { value: "65%", label: "Cost ↓" }, + kpi2: { value: "2x", label: "Performance ↑" }, + ctaText: "See build", + ctaHref: "/case-studies/vfx-studio", + }, + { + title: "Legal Document Management", + description: + "Consolidated scattered legal tech stack into a secure, private Nextcloud instance with AI search.", + kpi1: { value: "$120k/mo", label: "Saved" }, + kpi2: { value: "0", label: "Egress Fees" }, + ctaText: "See build", + ctaHref: "/case-studies/legal-firm", + }, + { + title: "Research Data Pipeline", + description: + "Built a local ML training environment for a research institute, eliminating data transfer bottlenecks.", + kpi1: { value: "90%", label: "Time-to-Train ↓" }, + kpi2: { value: "Break-even: 8mo", label: "" }, + ctaText: "See build", + ctaHref: "/case-studies/research-institute", + }, + ]; + + return ( +
+ + + {/* Hero Section */} + + +
+

Case Studies

+

+ Context → constraints → architecture → migration → outcomes. Real numbers, real stacks. +

+
+
+
+ + {/* Case Studies */} + + + + + + +
+
+ ); +} diff --git a/apps/www/app/contact/page.tsx b/apps/www/app/contact/page.tsx index e88f190..b53c769 100644 --- a/apps/www/app/contact/page.tsx +++ b/apps/www/app/contact/page.tsx @@ -7,8 +7,8 @@ import { ExternalLinkIcon } from 'lucide-react'; import { Navbar } from '@workspace/ui/components/layout'; import { Footer } from '@workspace/ui/components/layout'; -import { Container, Section } from '@workspace/ui/components/layout'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@workspace/ui/components/ui'; +import { Container } from '@workspace/ui/components/layout'; +import { AnimatedSection } from '@workspace/ui/components/animate-ui/section'; import { Button } from '@workspace/ui/components/ui'; import { Input } from '@workspace/ui/components/ui'; import { Textarea } from '@workspace/ui/components/ui'; @@ -54,122 +54,122 @@ export default function ContactPage() { return (
-
- -
-

Contact Us

-

+ + {/* Hero Section */} + + +

+

Contact Us

+

Book a free architecture call, request a cost estimate, or ask a question.

- -
+ + + + + +
{/* Contact Form */} - - - Send us a message - - Fill out the form and we'll get back to you as soon as possible. - - - - {submitSuccess ? ( -
-

Message Sent!

-

Thank you for reaching out. We'll get back to you soon.

+
+

Send us a message

+

+ Fill out the form and we'll get back to you as soon as possible. +

+ + {submitSuccess ? ( +
+

Message Sent!

+

Thank you for reaching out. We'll get back to you soon.

+
+ ) : ( +
+
+ + setName(e.target.value)} + required + className="mt-2 p-4 text-lg" + />
- ) : ( - -
- - setName(e.target.value)} - required - /> -
-
- - setEmail(e.target.value)} - required - /> -
-
- - setCompany(e.target.value)} - /> -
-
- -