From 6629bd3f77f67f5de96cd8c89cf5514d8013997c Mon Sep 17 00:00:00 2001 From: operatoruplift Date: Wed, 18 Mar 2026 13:56:30 +0800 Subject: [PATCH 01/36] Fix content bugs, update models, add ProblemStatement and MarketOpportunity sections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix "Opeartor" typo in Terms and dataService - Fix garbled Feature #4 description (duplicated text) - Fix empty contract address → "Coming Soon" - Update email from gmail to matt@operatoruplift.com - Update AI model list (Claude Opus 4, GPT-4.1, Gemini 2.5 Pro, etc.) - Add macOS/Linux tabs to DownloadWidget, change modal to "Coming Soon" - Delete dead CodeSnippet component (rendered null, no imports) - Add ProblemStatement section (80+ apps problem → solution pillars) - Add MarketOpportunity section ($65B market stats, "Why now?" narrative) - Merge with master: security linkUrls, copyright 2026, footer Contact link - Incorporate TractionBar from master into page composition Co-Authored-By: Claude Opus 4.6 (1M context) --- app/page.tsx | 30 +- src/components/CodeSnippet.tsx | 10 - src/components/DownloadWidget.tsx | 78 ++--- src/components/TrustedBy.tsx | 14 +- src/sections/MarketOpportunity.tsx | 75 +++++ src/sections/ProblemStatement.tsx | 102 +++++++ src/sections/Terms.tsx | 2 +- src/services/dataService.ts | 443 ++++++++++++++++------------- 8 files changed, 490 insertions(+), 264 deletions(-) delete mode 100644 src/components/CodeSnippet.tsx create mode 100644 src/sections/MarketOpportunity.tsx create mode 100644 src/sections/ProblemStatement.tsx diff --git a/app/page.tsx b/app/page.tsx index 2903fe8..650b066 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -2,24 +2,28 @@ import Navbar from '@/src/components/Navbar'; import Hero from '@/src/sections/Hero'; +import ProblemStatement from '@/src/sections/ProblemStatement'; import Product from '@/src/sections/Product'; +import MarketOpportunity from '@/src/sections/MarketOpportunity'; import Security from '@/src/sections/Security'; import DeveloperDocs from '@/src/sections/DeveloperDocs'; -import BuildWithUs from '@/src/sections/BuildWithUs'; import TractionBar from '@/src/sections/TractionBar'; +import BuildWithUs from '@/src/sections/BuildWithUs'; import Footer from '@/src/components/Footer'; export default function Home() { - return ( -
- - - - - - - -
-
- ); + return ( +
+ + + + + + + + + +
+
+ ); } diff --git a/src/components/CodeSnippet.tsx b/src/components/CodeSnippet.tsx deleted file mode 100644 index 964c3ce..0000000 --- a/src/components/CodeSnippet.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -// This component is deprecated in favor of DownloadWidget.tsx -// Keeping file to prevent import errors in untracked files, -// but it renders nothing. - -const CodeSnippet: React.FC = () => { - return null; -}; - -export default CodeSnippet; \ No newline at end of file diff --git a/src/components/DownloadWidget.tsx b/src/components/DownloadWidget.tsx index b82d6a4..c3e030a 100644 --- a/src/components/DownloadWidget.tsx +++ b/src/components/DownloadWidget.tsx @@ -7,11 +7,16 @@ interface DownloadWidgetProps { } const DownloadWidget: React.FC = ({ data }) => { - const [activeTab, setActiveTab] = useState<'windows'>('windows'); + const [activeTab, setActiveTab] = useState<'windows' | 'macos' | 'linux'>('windows'); const [showModal, setShowModal] = useState(false); - const currentDownload = data.downloads[activeTab]; - const downloadUrl = '#'; + const platformInfo: Record = { + windows: { label: 'Download for Windows', version: 'v0.0.1-beta (x64)' }, + macos: { label: 'Download for macOS', version: 'v0.0.1-beta (ARM64)' }, + linux: { label: 'Download for Linux', version: 'v0.0.1-beta (x64)' }, + }; + + const current = platformInfo[activeTab]; const handleDownloadClick = () => { setShowModal(true); @@ -19,12 +24,7 @@ const DownloadWidget: React.FC = ({ data }) => { const handleConfirmDownload = () => { setShowModal(false); - const link = document.createElement('a'); - link.href = downloadUrl; - link.download = 'Uplift.exe'; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); + // Download URL will be set when builds are available }; const handleCancelDownload = () => { @@ -34,15 +34,26 @@ const DownloadWidget: React.FC = ({ data }) => { return ( <>
- + {/* OS Selection Tabs */}
+ +
{/* Main Download Button Container */} @@ -63,7 +85,7 @@ const DownloadWidget: React.FC = ({ data }) => {
- {currentDownload.version} + {current.version} SHA256 Signed
@@ -71,11 +93,11 @@ const DownloadWidget: React.FC = ({ data }) => { {/* Modal */} {showModal && ( -
-
e.stopPropagation()} style={{ @@ -84,7 +106,7 @@ const DownloadWidget: React.FC = ({ data }) => { > {/* Subtle gradient overlay */}
- + {/* Close button */} -
diff --git a/src/components/TrustedBy.tsx b/src/components/TrustedBy.tsx index 915ca97..f88ab71 100644 --- a/src/components/TrustedBy.tsx +++ b/src/components/TrustedBy.tsx @@ -3,14 +3,14 @@ import React from 'react'; const TrustedBy: React.FC = () => { const models = [ - { name: "GPT-4o", provider: "OpenAI" }, - { name: "Claude 3.5 Sonnet", provider: "Anthropic" }, - { name: "Gemini 1.5 Pro", provider: "Google" }, - { name: "Llama 3.1", provider: "Meta" }, + { name: "GPT-4.1", provider: "OpenAI" }, + { name: "Claude Opus 4", provider: "Anthropic" }, + { name: "Gemini 2.5 Pro", provider: "Google" }, + { name: "Llama 4", provider: "Meta" }, { name: "Mistral Large", provider: "Mistral AI" }, - { name: "Command R+", provider: "Cohere" }, - { name: "Grok-1", provider: "xAI" }, - { name: "DeepSeek-V2", provider: "DeepSeek" }, + { name: "Command A", provider: "Cohere" }, + { name: "Grok 3", provider: "xAI" }, + { name: "DeepSeek-R1", provider: "DeepSeek" }, ]; // Duplicate the array to ensure seamless scrolling diff --git a/src/sections/MarketOpportunity.tsx b/src/sections/MarketOpportunity.tsx new file mode 100644 index 0000000..cff77d7 --- /dev/null +++ b/src/sections/MarketOpportunity.tsx @@ -0,0 +1,75 @@ +'use client'; + +import React from 'react'; +import { APP_CONTENT } from '@/src/services/dataService'; + +const TrendingUpIcon = ({ size = 28, className = '' }: { size?: number; className?: string }) => ( + + + + +); + +const MarketOpportunity: React.FC = () => { + const { market } = APP_CONTENT; + + return ( +
+ {/* Glow blobs */} +
+
+ +
+
+
+ + Market Opportunity + +
+

+ {market.headline} +

+

+ {market.subhead} +

+
+ + {/* Stats grid */} +
+ {market.stats.map((stat) => ( +
+

+ {stat.value} +

+

{stat.label}

+
+ ))} +
+ + {/* Narrative */} +
+
+
+ +
+
+

+ Why now? The AI inflection point. +

+

+ We are at the exact moment — models are good enough, compute is cheap enough, and users are frustrated enough — + that a local-first AI OS can replace every productivity app people use today. + Operator Uplift is positioned to capture the consumer AI automation market before big tech consolidates it. +

+
+
+
+
+
+ ); +}; + +export default MarketOpportunity; diff --git a/src/sections/ProblemStatement.tsx b/src/sections/ProblemStatement.tsx new file mode 100644 index 0000000..81e3fb0 --- /dev/null +++ b/src/sections/ProblemStatement.tsx @@ -0,0 +1,102 @@ +'use client'; + +import React from 'react'; +import { APP_CONTENT } from '@/src/services/dataService'; + +const ArrowRightIcon = ({ size = 14, className = '' }: { size?: number; className?: string }) => ( + + + +); + +const ProblemStatement: React.FC = () => { + const { problem } = APP_CONTENT; + + return ( +
+ {/* Subtle grid background */} +
+ +
+ {/* Big number callout */} +
+
+ + The Problem + +
+ +
+ + {problem.stat} + +
+ + {problem.stat} + +
+
+ +

+ apps on your phone. +

+

+ {problem.subline} +

+
+ + {/* Three pillars — problem → solution */} + + + {/* Solution bridge */} +
+
+

+ The fix: + {problem.solution} +

+
+
+
+
+ ); +}; + +export default ProblemStatement; diff --git a/src/sections/Terms.tsx b/src/sections/Terms.tsx index e940c4e..cd27c46 100644 --- a/src/sections/Terms.tsx +++ b/src/sections/Terms.tsx @@ -19,7 +19,7 @@ const Terms: React.FC = () => {

1. Acceptance of Terms

- By accessing and using the Opeartor Uplift platform ("Service"), you agree to comply with and be bound by these Terms of Service. If you do not agree to these terms, you may not access or use the Service. + By accessing and using the Operator Uplift platform ("Service"), you agree to comply with and be bound by these Terms of Service. If you do not agree to these terms, you may not access or use the Service.

diff --git a/src/services/dataService.ts b/src/services/dataService.ts index e483f4d..1dfb3e3 100644 --- a/src/services/dataService.ts +++ b/src/services/dataService.ts @@ -1,213 +1,254 @@ import { AppData } from '@/lib/types'; -export const APP_CONTENT: AppData = { - hero: { - visionTag: "VISION", - headline: "Millions of Agents. One Voice.", - subhead: "Local first AI agents you control, running on your device.", - description: "Install agents, run tasks in secure sessions, and approve access with clear permissions.", - contractAddress: "", - contractLabel: "Internal currency for computation", - downloads: { - windows: { - id: "windows", - label: "Download for Windows", - url: "#", - version: "v0.0.1-beta (x64)", - type: "windows" - } - } - }, +export interface ProblemPillar { + id: string; + emoji: string; + problem: string; + solution: string; + description: string; + href: string; +} - product: { - tag: "PRODUCT", - headline: "Local-First Agent Command Center", - subhead: "Install agents, run tasks in secure sessions, and approve access with clear permissions.", - features: [ - { - id: 'isolated', - navTitle: 'ISOLATED ENV', - cardTitle: '1. Isolated Environment', - description: 'Agents use private, encrypted local memory where supported, with optional sync, so your data starts on your device and stays under your control.', - iconType: 'kanban' - }, - { - id: 'store', - navTitle: 'AGENT STORE', - cardTitle: '2. Agent Store', - description: 'Discover, install, and run agents from a Solana-powered marketplace. Developers can price agents, and payment rails may include Solana-based credits, while users get one-click agent deployment with transparent permissions and ownership', - iconType: 'globe' - }, - { - id: 'runtime', - navTitle: 'SESSION RUNTIME', - cardTitle: '3. Session Runtime', - description: 'Each task runs in a session based runtime that starts fast, stays isolated, and ends cleanly. When the session ends, the agent loses access to your system. This plug-and-play mechanism ensures fast execution, strict isolation, and no long-term access to your system once the session ends.', - iconType: 'terminal' - }, - { - id: 'tokens', - navTitle: 'TIME LIMITED ACCESS KEYS', - cardTitle: '4. Time Limited Access Keys', - description: 'Time-limited access keys define exactly what an agent can see or do for a specific task. Keys unlock the Agentic Vault only for that session and can be revoked at any time, ensuring that permissions are precise, revocable, and always under your control.', - iconType: 'message' - }, - { - id: 'permissions', - navTitle: 'PERMISSIONS', - cardTitle: '5. Permission Actions', - description: 'Every file read, device control, and network call is a permission action that you can see and approve. Operator Uplift enforces the boundaries you set\u2014file access, device control, and network calls\u2014are governed by explicit permissions. No silent behavior, no surprises.', - iconType: 'check' - } - ] - }, +export interface ProblemData { + stat: string; + subline: string; + pillars: ProblemPillar[]; + solution: string; +} - security: { - tag: "ENTERPRISE", - headline: "Operator Uplift delivers an enterprise-grade agentic infrastructure", - subhead: "With isolated runtimes for maximum security, a unified interface that minimizes learning curve, and seamless integration of private AI agents for scalable automation.", - features: { - security: { - tag: "SECURE AT EVERY LEVEL", - title: "Local-first security and full compliance", - description: "Operator Uplift uses isolated sandboxes, encrypted local memory and token based access rules to ensure that your data, intellectual property, logs and workflows never leave your environment. Agents receive only the context you explicitly approve for a limited time window, which prevents oversharing and eliminates the risk of cloud based data leakage.", - linkText: "Learn more about security", - linkUrl: "https://help.operatoruplift.com/" - }, - enterprise: { - tag: "ACROSS YOUR DEVELOPMENT STACK", - title: "Independent of interfaces and external vendors", - description: "Operator Uplift integrates with any model provider, internal API, or device. Deploy the agents with one interface, and evolve them over time without vendor lock-in. As your internal systems mature, your agents upgrade seamlessly with shared memory, cross-device sync, and modular extensions.", - linkText: "Learn more about enterprise", - linkUrl: "/contact" - } - } - }, +export interface MarketStat { + value: string; + label: string; +} - developerDocs: { - tag: "BUILD WITH US", - headline: "Developer Docs", - description: "Everything you need to integrate Operator Uplift agents into your infrastructure. Explore our guides, samples, and API references.", - links: [ - { - title: "Quickstart Guide", - description: "Get up and running with Operator Uplift in minutes. Deploy your first agent container.", - iconType: 'terminal', - url: "https://help.operatoruplift.com/" - }, - { - title: "Core Concepts", - description: "Deep dive into the architecture, session tokens, and security vaults.", - iconType: 'kanban', - url: "https://help.operatoruplift.com/" - }, - { - title: "API Reference", - description: "Complete reference for the Agent Store API and Runtime SDKs.", - iconType: 'globe', - url: "https://help.operatoruplift.com/" - } - ] - }, +export interface MarketData { + headline: string; + subhead: string; + stats: MarketStat[]; +} - buildWithUs: { - tag: "BUILD WITH US", - cta: "START BUILDING", - headline: "Ready to build the software of the future?", - buttonText: "Start Building", - url: "https://help.operatoruplift.com" - }, - - contact: { - tag: "GET IN TOUCH", - headline: "Let's Connect", - subhead: "We know no one likes to fill forms, so just choose your way of communication and we'll come there, and if you're looking for job follow us on", - subheadLinkText: "LinkedIn", - subheadLinkUrl: "https://linkedin.com/company/operatoruplift", - options: [ - { - id: 'whatsapp', - title: 'WhatsApp', - description: 'Chat with us instantly', - iconType: 'whatsapp', - url: 'https://wa.me/18049311722' - }, - { - id: 'email', - title: 'Email', - description: 'operatoruplift@gmail.com', - iconType: 'email', - url: 'mailto:operatoruplift@gmail.com' - }, - { - id: 'meeting', - title: 'Book a Meeting', - description: 'Schedule a video call', - iconType: 'calendar', - url: 'https://cal.com/rvaclassic' - }, - { - id: 'twitter', - title: 'X (Twitter)', - description: 'Follow and DM us', - iconType: 'twitter', - url: 'https://x.com/OperatorUplift' - }, - { - id: 'discord', - title: 'Discord', - description: 'Join our community', - iconType: 'discord', - url: 'https://discord.gg/eka7hqJcAY' - }, - { - id: 'linkedin', - title: 'LinkedIn', - description: 'Connect professionally', - iconType: 'linkedin', - url: 'https://www.linkedin.com/company/operatoruplift' - } - ] +export const APP_CONTENT: AppData & { problem: ProblemData; market: MarketData } = { + problem: { + stat: '80+', + subline: 'The average person uses 80+ apps. None of them talk to each other. Your data is trapped, your attention fragmented, your time wasted.', + pillars: [ + { id: 'fragmentation', emoji: '🔄', problem: 'App Overload', solution: 'One Agent', description: 'Stop alt-tabbing between 80 apps. One agent, one interface, every capability.', href: '#product' }, + { id: 'cloud-lock', emoji: '☁️', problem: 'Cloud Lock-in', solution: 'Local-First', description: 'Your data lives on your hardware. Your models run on your GPU. Zero vendor lock-in.', href: '#product' }, + { id: 'value-leak', emoji: '💸', problem: 'Value Extraction', solution: 'You Own It', description: 'Big tech monetizes your data. Operator Uplift lets you own, stake, and profit from your agents.', href: '#product' }, + ], + solution: 'A local-first AI operating system that replaces your entire app stack with one intelligent agent.', + }, + market: { + headline: 'Massive and Growing.', + subhead: 'The AI agent market is projected to reach $65B by 2028. Operator Uplift is positioned at the intersection of AI, crypto, and consumer software.', + stats: [ + { value: '$65B', label: 'AI Agent Market by 2028' }, + { value: '3.2B', label: 'Smartphone Users Worldwide' }, + { value: '40%', label: 'CAGR in AI Automation' }, + { value: '#1', label: 'Local-First AI OS' }, + ], + }, + hero: { + visionTag: "VISION", + headline: "Millions of Agents. One Voice.", + subhead: "Local first AI agents you control, running on your device.", + description: "Install agents, run tasks in secure sessions, and approve access with clear permissions.", + contractAddress: "Coming Soon", + contractLabel: "Internal currency for computation", + downloads: { + windows: { + id: "windows", + label: "Download for Windows", + url: "#", + version: "v0.0.1-beta (x64)", + type: "windows" + } + } + }, + product: { + tag: "PRODUCT", + headline: "Local-First Agent Command Center", + subhead: "Install agents, run tasks in secure sessions, and approve access with clear permissions.", + features: [ + { + id: 'isolated', + navTitle: 'ISOLATED ENV', + cardTitle: '1. Isolated Environment', + description: 'Agents use private, encrypted local memory where supported, with optional sync, so your data starts on your device and stays under your control.', + iconType: 'kanban' + }, + { + id: 'store', + navTitle: 'AGENT STORE', + cardTitle: '2. Agent Store', + description: 'Discover, install, and run agents from a Solana-powered marketplace. Developers can price agents, and payment rails may include Solana-based credits, while users get one-click agent deployment with transparent permissions and ownership.', + iconType: 'globe' + }, + { + id: 'runtime', + navTitle: 'SESSION RUNTIME', + cardTitle: '3. Session Runtime', + description: 'Each task runs in a session based runtime that starts fast, stays isolated, and ends cleanly. When the session ends, the agent loses access to your system. This plug-and-play mechanism ensures fast execution, strict isolation, and no long-term access to your system once the session ends.', + iconType: 'terminal' + }, + { + id: 'tokens', + navTitle: 'TIME LIMITED ACCESS KEYS', + cardTitle: '4. Time Limited Access Keys', + description: 'Time-limited access keys define exactly what an agent can see or do for a specific task. Keys unlock the Agentic Vault only for that session and can be revoked at any time, ensuring that permissions are precise, revocable, and always under your control.', + iconType: 'message' + }, + { + id: 'permissions', + navTitle: 'PERMISSIONS', + cardTitle: '5. Permission Actions', + description: 'Every file read, device control, and network call is a permission action that you can see and approve. Operator Uplift enforces the boundaries you set\u2014file access, device control, and network calls\u2014are governed by explicit permissions. No silent behavior, no surprises.', + iconType: 'check' + } + ] + }, + security: { + tag: "ENTERPRISE", + headline: "Operator Uplift delivers an enterprise-grade agentic infrastructure", + subhead: "With isolated runtimes for maximum security, a unified interface that minimizes learning curve, and seamless integration of private AI agents for scalable automation.", + features: { + security: { + tag: "SECURE AT EVERY LEVEL", + title: "Local-first security and full compliance", + description: "Operator Uplift uses isolated sandboxes, encrypted local memory and token based access rules to ensure that your data, intellectual property, logs and workflows never leave your environment. Agents receive only the context you explicitly approve for a limited time window, which prevents oversharing and eliminates the risk of cloud based data leakage.", + linkText: "Learn more about security", + linkUrl: "https://help.operatoruplift.com/" + }, + enterprise: { + tag: "ACROSS YOUR DEVELOPMENT STACK", + title: "Independent of interfaces and external vendors", + description: "Operator Uplift integrates with any model provider, internal API, or device. Deploy the agents with one interface, and evolve them over time without vendor lock-in. As your internal systems mature, your agents upgrade seamlessly with shared memory, cross-device sync, and modular extensions.", + linkText: "Learn more about enterprise", + linkUrl: "/contact" + } + } + }, + developerDocs: { + tag: "BUILD WITH US", + headline: "Developer Docs", + description: "Everything you need to integrate Operator Uplift agents into your infrastructure. Explore our guides, samples, and API references.", + links: [ + { + title: "Quickstart Guide", + description: "Get up and running with Operator Uplift in minutes. Deploy your first agent container.", + iconType: 'terminal', + url: "https://help.operatoruplift.com/" + }, + { + title: "Core Concepts", + description: "Deep dive into the architecture, session tokens, and security vaults.", + iconType: 'kanban', + url: "https://help.operatoruplift.com/" + }, + { + title: "API Reference", + description: "Complete reference for the Agent Store API and Runtime SDKs.", + iconType: 'globe', + url: "https://help.operatoruplift.com/" + } + ] + }, + buildWithUs: { + tag: "BUILD WITH US", + cta: "START BUILDING", + headline: "Ready to build the software of the future?", + buttonText: "Start Building", + url: "https://help.operatoruplift.com" + }, + contact: { + tag: "GET IN TOUCH", + headline: "Let's Connect", + subhead: "We know no one likes to fill forms, so just choose your way of communication and we'll come there, and if you're looking for job follow us on", + subheadLinkText: "LinkedIn", + subheadLinkUrl: "https://linkedin.com/company/operatoruplift", + options: [ + { + id: 'whatsapp', + title: 'WhatsApp', + description: 'Chat with us instantly', + iconType: 'whatsapp', + url: 'https://wa.me/18049311722' + }, + { + id: 'email', + title: 'Email', + description: 'matt@operatoruplift.com', + iconType: 'email', + url: 'mailto:matt@operatoruplift.com' + }, + { + id: 'meeting', + title: 'Book a Meeting', + description: 'Schedule a video call', + iconType: 'calendar', + url: 'https://cal.com/rvaclassic' + }, + { + id: 'twitter', + title: 'X (Twitter)', + description: 'Follow and DM us', + iconType: 'twitter', + url: 'https://x.com/OperatorUplift' + }, + { + id: 'discord', + title: 'Discord', + description: 'Join our community', + iconType: 'discord', + url: 'https://discord.gg/eka7hqJcAY' + }, + { + id: 'linkedin', + title: 'LinkedIn', + description: 'Connect professionally', + iconType: 'linkedin', + url: 'https://www.linkedin.com/company/operatoruplift' + } + ] + }, + footer: { + tag: "FOOTER", + copyright: "\u00a9 Operator Uplift 2026. All rights reserved.", + socials: { + twitter: "https://x.com/OperatorUplift", + linkedin: "https://www.linkedin.com/company/operatoruplift", + github: "https://github.com/operatoruplift" }, - - footer: { - tag: "FOOTER", - copyright: "\u00a9 Operator Uplift 2026. All rights reserved.", - socials: { - twitter: "https://x.com/OperatorUplift", - linkedin: "https://www.linkedin.com/company/operatoruplift", - github: "https://github.com/operatoruplift" - }, - sections: { - resources: { - title: "Resources", - links: [ - { label: "Docs", url: "https://help.operatoruplift.com" }, - { label: "Contact Sales", action: "contact" } - ] - }, - company: { - title: "Company", - links: [ - { label: "Careers", url: "https://linkedin.com/company/operatoruplift" }, - { label: "Contact", action: "contact" } - ] - }, - legal: { - title: "Legal", - links: [ - { label: "Privacy Policy", action: "privacy" }, - { label: "Terms of Service", action: "terms" } - ] - } - } + sections: { + resources: { + title: "Resources", + links: [ + { label: "Docs", url: "https://help.operatoruplift.com" }, + { label: "Contact Sales", action: "contact" } + ] + }, + company: { + title: "Company", + links: [ + { label: "Careers", url: "https://linkedin.com/company/operatoruplift" }, + { label: "Contact", action: "contact" } + ] + }, + legal: { + title: "Legal", + links: [ + { label: "Privacy Policy", action: "privacy" }, + { label: "Terms of Service", action: "terms" } + ] + } } + } }; export const fetchAppData = async (): Promise => { - return new Promise((resolve) => { - setTimeout(() => { - resolve(APP_CONTENT); - }, 50); - }); + return new Promise((resolve) => { + setTimeout(() => { + resolve(APP_CONTENT); + }, 50); + }); }; From 96c9d12305ee2ae04f4907d9651e108618a4e46d Mon Sep 17 00:00:00 2001 From: operatoruplift Date: Wed, 18 Mar 2026 14:20:57 +0800 Subject: [PATCH 02/36] Align website with pitch deck, fix CSS bug, clean up manifest and metadata - Align hero with deck slide 1: "Your Life, Automated" / "One App. Every Agent. All Yours." - Align ProblemStatement with deck slides 2/5: 40+ apps, Siloed Memory / Exposed Privacy / No Boundaries - Align MarketOpportunity with deck slide 8: $103B TAM, $18B SAM, 100M+ SOM - Reframe TractionBar honestly: "Beta Users (Previous Build)" instead of implying live product - Fix CSS syntax bug: missing closing brace on .animate-slide-right broke nested utilities - Clean manifest.json: remove non-standard fields, use local icon paths, correct theme color - Update layout.tsx metadata: title/description aligned with new hero, added keywords Co-Authored-By: Claude Opus 4.6 (1M context) --- app/globals.css | 8 ++-- app/layout.tsx | 20 +++++----- manifest.json | 61 ++++++------------------------- src/sections/ProblemStatement.tsx | 2 +- src/sections/TractionBar.tsx | 58 ++++++++++++++--------------- src/services/dataService.ts | 24 ++++++------ 6 files changed, 69 insertions(+), 104 deletions(-) diff --git a/app/globals.css b/app/globals.css index 6a9ae11..f5ea91b 100644 --- a/app/globals.css +++ b/app/globals.css @@ -137,19 +137,20 @@ .animate-slide-right { animation: slide-right 3s linear infinite; + } - /* Additional responsive utilities */ + /* Additional responsive utilities */ .text-responsive { word-wrap: break-word; overflow-wrap: break-word; hyphens: auto; } - + .prevent-overflow { max-width: 100%; overflow: hidden; } - + @media (min-width: 640px) { .sm\:text-responsive { word-wrap: normal; @@ -157,5 +158,4 @@ hyphens: none; } } - } } diff --git a/app/layout.tsx b/app/layout.tsx index 7c5fd7f..83719f7 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -2,19 +2,20 @@ import type { Metadata } from "next"; import "./globals.css"; export const metadata: Metadata = { - title: "Operator Uplift - Local-First Agent Command Center", - description: "Local-first AI agents with secure, private memory. Build, deploy, and monetize autonomous agents on Solana—no cloud required", keywords: ["Local AI", "Agent Platform", "Solana AI", "Private Memory", "Autonomous Agents", "Local Runtime", "Agent Marketplace"], + title: "Operator Uplift - Your Life, Automated", + description: "One App. Every Agent. All Yours. Local-first AI agents with secure, private memory. Build, deploy, and monetize autonomous agents on Solana — no cloud required.", + keywords: ["Local AI", "Agent Platform", "Solana AI", "Private Memory", "Autonomous Agents", "Local Runtime", "Agent Marketplace", "AI OS", "Local-First"], openGraph: { - title: "Operator Uplift - Local-First Agent Command Center", - description: "Local-first AI agents with secure, private memory. Build, deploy, and monetize autonomous agents on Solana—no cloud required", + title: "Operator Uplift - Your Life, Automated", + description: "One App. Every Agent. All Yours. Local-first AI agents with secure, private memory — no cloud required.", url: "https://operatoruplift.com", siteName: "Operator Uplift", images: [ { - url: "/logo.svg", // Recommended: Replace with a 1200x630 .png image + url: "/logo.svg", width: 1200, height: 630, - alt: "Operator Uplift AI Platform", + alt: "Operator Uplift - Local-First AI OS", }, ], locale: "en_US", @@ -22,14 +23,15 @@ export const metadata: Metadata = { }, twitter: { card: "summary_large_image", - title: "Operator Uplift - Local-First Agent Command Center", description: "Local-first AI agents with secure, private memory. Build, deploy, and monetize autonomous agents on Solana—no cloud required", + title: "Operator Uplift - Your Life, Automated", + description: "One App. Every Agent. All Yours. Local-first AI agents with secure, private memory — no cloud required.", creator: "@OperatorUplift", - images: ["/logo.svg"], // Recommended: Replace with a 1200x630 .png image + images: ["/logo.svg"], }, icons: { icon: "/logo.svg", }, - manifest: "/manifest.json", + manifest: "/manifest.json", }; import Script from "next/script"; diff --git a/manifest.json b/manifest.json index d7d9b29..6f91ed8 100644 --- a/manifest.json +++ b/manifest.json @@ -1,61 +1,24 @@ { - "background_color": "#ffffff", - "description": "Local-first AI agents with secure, private memory. Build, deploy, and monetize autonomous agents on Solana—no cloud required", - "dir": "ltr", - "display": "standalone", "name": "Operator Uplift", - "orientation": "any", - "scope": "/", "short_name": "Operator Uplift", + "description": "Local-first AI agents with secure, private memory. Build, deploy, and monetize autonomous agents on Solana — no cloud required.", "start_url": "/", - "theme_color": "#ffffff", + "scope": "/", + "display": "standalone", + "dir": "ltr", + "orientation": "any", + "background_color": "#050505", + "theme_color": "#E77630", "icons": [ { - "src": "https://operatoruplift.com/favicon.ico?favicon.d4311b7b.ico", + "src": "/favicon.ico", "type": "image/x-icon", - "sizes": "48x48", - "isSquare": true, - "isPng": false, - "isWebp": false, - "isJpg": false, - "width": 48, - "is512x512": false, - "is256x256": false, - "is192x192": false - }, - { - "src": "https://operatoruplift.com/logo.svg", - "isSquare": false, - "isPng": false, - "isWebp": false, - "isJpg": false, - "width": 0, - "is512x512": false, - "is256x256": false, - "is192x192": false + "sizes": "48x48" }, { - "src": "https://www.operatoruplift.com/logo.svg", - "isSquare": false, - "isPng": false, - "isWebp": false, - "isJpg": false, - "width": 0, - "is512x512": false, - "is256x256": false, - "is192x192": false - }, - { - "src": "https://operatoruplift.com/favicon.ico", - "type": "image/x-icon", - "isSquare": false, - "isPng": false, - "isWebp": false, - "isJpg": false, - "width": 0, - "is512x512": false, - "is256x256": false, - "is192x192": false + "src": "/logo.svg", + "type": "image/svg+xml", + "sizes": "any" } ] } diff --git a/src/sections/ProblemStatement.tsx b/src/sections/ProblemStatement.tsx index 81e3fb0..241407b 100644 --- a/src/sections/ProblemStatement.tsx +++ b/src/sections/ProblemStatement.tsx @@ -44,7 +44,7 @@ const ProblemStatement: React.FC = () => {

- apps on your phone. + apps. None are yours.

{problem.subline} diff --git a/src/sections/TractionBar.tsx b/src/sections/TractionBar.tsx index 5cf0f25..ac8aa68 100644 --- a/src/sections/TractionBar.tsx +++ b/src/sections/TractionBar.tsx @@ -2,36 +2,36 @@ import React from 'react'; import { FadeIn } from '@/src/components/Animators'; const TractionBar: React.FC = () => { - const stats = [ - { value: '90%', label: 'Retention Rate' }, - { value: '300+', label: 'Beta Users' }, - { value: '$0', label: 'Paid Marketing' }, - ]; + const stats = [ + { value: '300+', label: 'Beta Users (Previous Build)' }, + { value: '90%', label: 'Retention Rate' }, + { value: '$0', label: 'Paid Marketing' }, + ]; - return ( -

- -
-
- {stats.map((stat, index) => ( - - {index > 0 && ( -
- )} -
- {stat.value} - {stat.label} -
- - ))} -
-

- Organic growth, built on trust. Free during beta. -

-
- -
- ); + return ( +
+ +
+
+ {stats.map((stat, index) => ( + + {index > 0 && ( +
+ )} +
+ {stat.value} + {stat.label} +
+ + ))} +
+

+ We validated demand with our first build. Now we're rebuilding the right foundation. +

+
+ +
+ ); }; export default TractionBar; diff --git a/src/services/dataService.ts b/src/services/dataService.ts index 1dfb3e3..b80a6f3 100644 --- a/src/services/dataService.ts +++ b/src/services/dataService.ts @@ -29,30 +29,30 @@ export interface MarketData { export const APP_CONTENT: AppData & { problem: ProblemData; market: MarketData } = { problem: { - stat: '80+', - subline: 'The average person uses 80+ apps. None of them talk to each other. Your data is trapped, your attention fragmented, your time wasted.', + stat: '40+', + subline: 'You have 40 apps. 40 subscriptions. 40 different places storing your data. None of them talk to each other. None are yours.', pillars: [ - { id: 'fragmentation', emoji: '🔄', problem: 'App Overload', solution: 'One Agent', description: 'Stop alt-tabbing between 80 apps. One agent, one interface, every capability.', href: '#product' }, - { id: 'cloud-lock', emoji: '☁️', problem: 'Cloud Lock-in', solution: 'Local-First', description: 'Your data lives on your hardware. Your models run on your GPU. Zero vendor lock-in.', href: '#product' }, - { id: 'value-leak', emoji: '💸', problem: 'Value Extraction', solution: 'You Own It', description: 'Big tech monetizes your data. Operator Uplift lets you own, stake, and profit from your agents.', href: '#product' }, + { id: 'siloed-memory', emoji: '🧠', problem: 'Siloed Memory', solution: 'Unified Context', description: 'No unified shared context across your tools. Your agents should remember everything — across apps, sessions, and devices.', href: '#product' }, + { id: 'exposed-privacy', emoji: '🔓', problem: 'Exposed Privacy', solution: 'Local-First', description: 'Your data leaks to unknown servers. With Operator Uplift, your data lives on your hardware. Zero vendor lock-in.', href: '#product' }, + { id: 'no-boundaries', emoji: '⚠️', problem: 'No Boundaries', solution: 'You Own It', description: 'Agents monetize your private data. Operator Uplift gives you full ownership — every permission explicit, every action approved.', href: '#product' }, ], solution: 'A local-first AI operating system that replaces your entire app stack with one intelligent agent.', }, market: { headline: 'Massive and Growing.', - subhead: 'The AI agent market is projected to reach $65B by 2028. Operator Uplift is positioned at the intersection of AI, crypto, and consumer software.', + subhead: 'The AI agent market is accelerating. Operator Uplift is positioned at the intersection of AI, crypto, and consumer software.', stats: [ - { value: '$65B', label: 'AI Agent Market by 2028' }, - { value: '3.2B', label: 'Smartphone Users Worldwide' }, - { value: '40%', label: 'CAGR in AI Automation' }, + { value: '$103B', label: 'Total Addressable Market' }, + { value: '$18B', label: 'Serviceable Addressable Market' }, + { value: '100M+', label: 'Target Users (SOM)' }, { value: '#1', label: 'Local-First AI OS' }, ], }, hero: { visionTag: "VISION", - headline: "Millions of Agents. One Voice.", - subhead: "Local first AI agents you control, running on your device.", - description: "Install agents, run tasks in secure sessions, and approve access with clear permissions.", + headline: "Your Life, Automated.", + subhead: "One App. Every Agent. All Yours.", + description: "Local-first AI agents you control, running on your device. Install agents, run tasks in secure sessions, and approve access with clear permissions.", contractAddress: "Coming Soon", contractLabel: "Internal currency for computation", downloads: { From cad01c7658a4b535a4973973d977ed12490b1db3 Mon Sep 17 00:00:00 2001 From: operatoruplift Date: Wed, 18 Mar 2026 14:44:22 +0800 Subject: [PATCH 03/36] Add metadataBase to resolve OG image warning Co-Authored-By: Claude Opus 4.6 (1M context) --- app/layout.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/layout.tsx b/app/layout.tsx index 83719f7..668dde5 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -2,6 +2,7 @@ import type { Metadata } from "next"; import "./globals.css"; export const metadata: Metadata = { + metadataBase: new URL("https://operatoruplift.com"), title: "Operator Uplift - Your Life, Automated", description: "One App. Every Agent. All Yours. Local-first AI agents with secure, private memory. Build, deploy, and monetize autonomous agents on Solana — no cloud required.", keywords: ["Local AI", "Agent Platform", "Solana AI", "Private Memory", "Autonomous Agents", "Local Runtime", "Agent Marketplace", "AI OS", "Local-First"], From ceab72c9ea521677a49fe1ee743f3780af434aa9 Mon Sep 17 00:00:00 2001 From: operatoruplift Date: Wed, 18 Mar 2026 14:53:58 +0800 Subject: [PATCH 04/36] Fix OPERATOR UPLIFT centering in Security card, upgrade HeroAnimation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix Enterprise orbital: widen container from w-20 to w-24, center text with line break and text-center so "OPERATOR UPLIFT" doesn't overflow - Upgrade HeroAnimation from Antigravity Workspace build: - Loops infinitely (18s cycle) instead of stopping after 15s - Phase labels type out with fade: AWAITING INPUT → DETECTING SIGNAL → ESTABLISHING CONTEXT → ISOLATING ENVIRONMENT → APPLYING GUARDRAILS → AGENT ACTIVE - Chat interface appears in final phase with animated message bubbles and typing indicator - Guard phase draws pulsing dashed boundary with scan line - Connection lines use distance-based opacity - Mobile responsive: fewer particles, smaller sizes, adjusted thresholds Co-Authored-By: Claude Opus 4.6 (1M context) --- src/components/HeroAnimation.tsx | 292 ++++++++++++++++++++++++------- src/sections/Security.tsx | 4 +- 2 files changed, 233 insertions(+), 63 deletions(-) diff --git a/src/components/HeroAnimation.tsx b/src/components/HeroAnimation.tsx index a2ab063..54746ad 100644 --- a/src/components/HeroAnimation.tsx +++ b/src/components/HeroAnimation.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState } from 'react'; +import React, { useEffect, useRef } from 'react'; interface Particle { x: number; @@ -6,6 +6,8 @@ interface Particle { vx: number; vy: number; size: number; + targetX?: number; + targetY?: number; alpha: number; isHero?: boolean; isAgent?: boolean; @@ -17,7 +19,6 @@ interface HeroAnimationProps { const HeroAnimation: React.FC = ({ className = "w-full h-full block" }) => { const canvasRef = useRef(null); - const [completed, setCompleted] = useState(false); useEffect(() => { const canvas = canvasRef.current; @@ -28,100 +29,274 @@ const HeroAnimation: React.FC = ({ className = "w-full h-ful let animationFrameId: number; let width = 0; let height = 0; + let isMobile = false; let particles: Particle[] = []; let phase: 'FLOW' | 'SPARK' | 'CONNECT' | 'FORM' | 'GUARD' | 'CHAT' = 'FLOW'; + let labelText = ""; let startTime = Date.now(); + const PRIMARY_COLOR = '#E77630'; const resize = () => { - const parent = canvas.parentElement; - if (parent) { - width = canvas.width = parent.offsetWidth; - height = canvas.height = parent.offsetHeight; - } + width = canvas.width = canvas.parentElement?.offsetWidth || window.innerWidth; + height = canvas.height = canvas.parentElement?.offsetHeight || window.innerHeight; + isMobile = width < 768; initParticles(); }; const initParticles = () => { particles = []; - const count = 50; + const count = isMobile ? 30 : 60; + for (let i = 0; i < count; i++) { particles.push({ x: Math.random() * width, y: Math.random() * height, - vx: (Math.random() + 0.1) * 1.5, - vy: (Math.random() - 0.5) * 0.4, + vx: (Math.random() + 0.2) * (isMobile ? 1 : 2), + vy: (Math.random() - 0.5) * 0.5, size: Math.random() * 2 + 1, - alpha: Math.random() * 0.4 + 0.1, + alpha: Math.random() * 0.5 + 0.1, isHero: i === 0, isAgent: i < 6 }); } }; + const drawLabel = (cx: number, cy: number, text: string, progress: number) => { + if (!text) return; + ctx.save(); + ctx.translate(cx, cy + 160); + ctx.globalAlpha = Math.min(1, Math.sin(progress * Math.PI)); + + ctx.font = "10px 'SF Mono', 'Menlo', monospace"; + ctx.textAlign = "center"; + ctx.fillStyle = PRIMARY_COLOR; + ctx.shadowColor = PRIMARY_COLOR; + ctx.shadowBlur = 10; + + const chars = Math.floor(text.length * Math.min(1, progress * 3)); + const currentText = text.substring(0, chars); + + ctx.fillText(`[ ${currentText} ]`, 0, 0); + + ctx.strokeStyle = `rgba(255, 255, 255, 0.2)`; + ctx.beginPath(); + ctx.moveTo(-20, 15); + ctx.lineTo(20, 15); + ctx.stroke(); + + ctx.restore(); + }; + + const drawChatInterface = (cx: number, cy: number, progress: number) => { + ctx.save(); + ctx.translate(cx, cy); + + const w = isMobile ? 160 : 200; + const h = isMobile ? 200 : 260; + const scale = Math.min(1, Math.max(0.8, progress * 2)); + + ctx.scale(scale, scale); + + ctx.strokeStyle = `rgba(255, 255, 255, ${0.1 + Math.min(0.2, progress)})`; + ctx.lineWidth = 0.5; + ctx.fillStyle = 'rgba(5, 5, 5, 0.8)'; + + ctx.beginPath(); + // @ts-ignore + if (ctx.roundRect) { + ctx.roundRect(-w / 2, -h / 2, w, h, 12); + } else { + ctx.rect(-w / 2, -h / 2, w, h); + } + ctx.fill(); + ctx.stroke(); + + ctx.beginPath(); + ctx.moveTo(-w / 2, -h / 2 + 30); + ctx.lineTo(w / 2, -h / 2 + 30); + ctx.stroke(); + + ctx.fillStyle = 'rgba(255, 255, 255, 0.2)'; + ctx.beginPath(); + ctx.arc(-w / 2 + 20, -h / 2 + 15, 2, 0, Math.PI * 2); + ctx.arc(-w / 2 + 32, -h / 2 + 15, 2, 0, Math.PI * 2); + ctx.fill(); + + const timeInChat = progress * 5; + + const bubbles = [ + { start: 0.5, type: 'user', width: w * 0.6, height: 24 }, + { start: 1.5, type: 'system', width: w * 0.7, height: 40 }, + { start: 3.5, type: 'user', width: w * 0.4, height: 24 }, + { start: 4.5, type: 'typing', width: 40, height: 20 }, + ]; + + bubbles.forEach((b, i) => { + if (timeInChat > b.start) { + const isUser = b.type === 'user'; + const xPos = isUser ? (w / 2 - 20 - b.width) : (-w / 2 + 20); + const yPos = -h / 2 + 50 + (i * 50); + + ctx.fillStyle = isUser ? 'rgba(255, 255, 255, 0.08)' : 'rgba(255, 85, 0, 0.1)'; + ctx.beginPath(); + if (ctx.roundRect) { + ctx.roundRect(xPos, yPos, b.width, b.height, 6); + } else { + ctx.rect(xPos, yPos, b.width, b.height); + } + ctx.fill(); + + if (b.type === 'typing') { + const dotTime = Date.now() / 200; + ctx.fillStyle = PRIMARY_COLOR; + for (let d = 0; d < 3; d++) { + const active = Math.floor(dotTime) % 3 === d; + ctx.globalAlpha = active ? 1 : 0.3; + ctx.beginPath(); + ctx.arc(xPos + 12 + (d * 8), yPos + 10, 1.5, 0, Math.PI * 2); + ctx.fill(); + } + ctx.globalAlpha = 1; + } + } + }); + + ctx.restore(); + }; + const render = () => { const now = Date.now(); - const elapsed = now - startTime; - - if (elapsed > 15000) { - setCompleted(true); - cancelAnimationFrame(animationFrameId); - return; + let elapsed = now - startTime; + const LOOP_DURATION = 18000; + + if (elapsed > LOOP_DURATION) { + startTime = now; + elapsed = 0; + phase = 'FLOW'; + initParticles(); } - if (elapsed < 2000) phase = 'FLOW'; - else if (elapsed < 4000) phase = 'SPARK'; - else if (elapsed < 6000) phase = 'CONNECT'; - else if (elapsed < 8500) phase = 'FORM'; - else if (elapsed < 11000) phase = 'GUARD'; - else phase = 'CHAT'; + if (elapsed < 2000) { phase = 'FLOW'; labelText = "AWAITING INPUT"; } + else if (elapsed < 4000) { phase = 'SPARK'; labelText = "DETECTING SIGNAL"; } + else if (elapsed < 6500) { phase = 'CONNECT'; labelText = "ESTABLISHING CONTEXT"; } + else if (elapsed < 9000) { phase = 'FORM'; labelText = "ISOLATING ENVIRONMENT"; } + else if (elapsed < 11500) { phase = 'GUARD'; labelText = "APPLYING GUARDRAILS"; } + else { phase = 'CHAT'; labelText = "AGENT ACTIVE"; } ctx.clearRect(0, 0, width, height); - - const cx = width * 0.65; - const cy = height * 0.5; + + const cx = width > 1024 ? width * 0.75 : width / 2; + const cy = height / 2; particles.forEach((p, i) => { - if (phase === 'FLOW' || phase === 'SPARK') { + if (phase === 'FLOW' || phase === 'SPARK' || (phase === 'CONNECT' && !p.isHero)) { p.x += p.vx; p.y += p.vy; if (p.x > width) p.x = 0; if (p.y > height) p.y = 0; - } else if (p.isAgent) { - let tx = cx; - let ty = cy; - const orbit = 80; - if (i === 0) { tx = cx - orbit; ty = cy - orbit; } - else if (i === 1) { tx = cx + orbit; ty = cy - orbit; } - else if (i === 2) { tx = cx + orbit; ty = cy + orbit; } - else if (i === 3) { tx = cx - orbit; ty = cy + orbit; } - else if (i === 4) { tx = cx; ty = cy - orbit * 1.2; } - else if (i === 5) { tx = cx; ty = cy + orbit * 1.2; } - - p.x += (tx - p.x) * 0.06; - p.y += (ty - p.y) * 0.06; - } else { - p.alpha *= 0.98; + if (p.y < 0) p.y = height; } + else if (phase === 'FORM' || phase === 'GUARD' || phase === 'CHAT') { + if (p.isAgent) { + let tx = cx; + let ty = cy; + const w = isMobile ? 160 : 200; + const h = isMobile ? 200 : 260; - ctx.fillStyle = (p.isHero || p.isAgent) ? PRIMARY_COLOR : '#ffffff'; - ctx.globalAlpha = p.alpha; - ctx.beginPath(); - ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); - ctx.fill(); - }); + if (i === 0) { tx = cx - w / 2; ty = cy - h / 2; } + else if (i === 1) { tx = cx + w / 2; ty = cy - h / 2; } + else if (i === 2) { tx = cx + w / 2; ty = cy + h / 2; } + else if (i === 3) { tx = cx - w / 2; ty = cy + h / 2; } + else if (i === 4) { tx = cx; ty = cy - h / 2; } + else if (i === 5) { tx = cx; ty = cy + h / 2; } + + p.x += (tx - p.x) * 0.08; + p.y += (ty - p.y) * 0.08; + } else { + p.alpha *= 0.95; + } + } + + if (phase === 'SPARK' && p.isHero) { + p.x += (cx - p.x) * 0.05; + p.y += (cy - p.y) * 0.05; + + ctx.shadowBlur = 15; + ctx.shadowColor = PRIMARY_COLOR; + ctx.fillStyle = PRIMARY_COLOR; + ctx.beginPath(); + ctx.arc(p.x, p.y, p.size * 2, 0, Math.PI * 2); + ctx.fill(); + ctx.shadowBlur = 0; + } + + if (phase === 'CONNECT' || phase === 'FORM') { + if (p.isHero) { + particles.forEach(other => { + const dist = Math.hypot(p.x - other.x, p.y - other.y); + if (dist < (isMobile ? 150 : 300)) { + ctx.beginPath(); + ctx.moveTo(p.x, p.y); + ctx.lineTo(other.x, other.y); + ctx.lineWidth = isMobile ? 0.2 : 0.5; + ctx.strokeStyle = `rgba(255, 85, 0, ${1 - dist / (isMobile ? 150 : 300)})`; + ctx.stroke(); + } + }); + } + } - if (phase === 'CONNECT' || phase === 'FORM' || phase === 'GUARD') { - ctx.strokeStyle = `rgba(231, 118, 48, 0.2)`; - ctx.lineWidth = 0.5; - for (let i = 0; i < 6; i++) { - for (let j = i + 1; j < 6; j++) { + if ((phase === 'FORM' || phase === 'GUARD') && p.isAgent) { + particles.filter(n => n.isAgent && n !== p).forEach(neighbor => { ctx.beginPath(); - ctx.moveTo(particles[i].x, particles[i].y); - ctx.lineTo(particles[j].x, particles[j].y); + ctx.moveTo(p.x, p.y); + ctx.lineTo(neighbor.x, neighbor.y); + ctx.strokeStyle = `rgba(255, 255, 255, 0.15)`; + ctx.lineWidth = 0.5; ctx.stroke(); - } + }); + } + + if (phase === 'GUARD') { + const size = isMobile ? 130 : 160; + ctx.save(); + ctx.translate(cx, cy); + ctx.strokeStyle = `rgba(255, 255, 255, ${Math.abs(Math.sin(elapsed / 200)) * 0.4 + 0.1})`; + ctx.lineWidth = 1; + ctx.setLineDash([10, 10]); + ctx.beginPath(); + ctx.rect(-size / 2, -size / 2, size, size); + ctx.stroke(); + + ctx.fillStyle = 'rgba(255, 85, 0, 0.05)'; + ctx.fillRect(-size / 2, -size / 2 + (elapsed % 1000) / 1000 * size, size, 2); + ctx.restore(); } + + if (phase === 'CHAT') { + drawChatInterface(cx, cy, Math.min(1, (elapsed - 11500) / 1000)); + } + + const mobileAlphaMod = isMobile ? 0.4 : 1; + + ctx.fillStyle = p.isHero || (phase !== 'FLOW' && p.isAgent) ? PRIMARY_COLOR : '#fff'; + if (phase === 'CHAT' && p.isAgent) ctx.fillStyle = '#fff'; + + ctx.globalAlpha = p.alpha * mobileAlphaMod; + ctx.beginPath(); + ctx.arc(p.x, p.y, p.size * (isMobile ? 0.7 : 1), 0, Math.PI * 2); + ctx.fill(); + ctx.globalAlpha = 1; + }); + + if (phase !== 'FLOW') { + const phaseStartTimes: Record = { SPARK: 2000, CONNECT: 4000, FORM: 6500, GUARD: 9000, CHAT: 11500 }; + const phaseDuration = 2500; + const currentPhaseStart = phaseStartTimes[phase] || 0; + const progress = Math.min(1, Math.max(0, (elapsed - currentPhaseStart) / phaseDuration)); + + drawLabel(cx, cy, labelText, progress); } animationFrameId = requestAnimationFrame(render); @@ -140,11 +315,6 @@ const HeroAnimation: React.FC = ({ className = "w-full h-ful return (
- {completed && ( -
- System_Ready -
- )}
); }; diff --git a/src/sections/Security.tsx b/src/sections/Security.tsx index 536537f..42f3956 100644 --- a/src/sections/Security.tsx +++ b/src/sections/Security.tsx @@ -124,9 +124,9 @@ const Security: React.FC = () => { {/* Adjusted scale/padding to fix cropping */}
-
+
- OPERATOR UPLIFT + OPERATOR
UPLIFT
{/* Scaled down container to keep orbiting elements within bounds */} From 0a57e4c2f82ad28bba16132ff39cb76332d18bdb Mon Sep 17 00:00:00 2001 From: operatoruplift Date: Thu, 19 Mar 2026 19:04:10 +0800 Subject: [PATCH 05/36] Build full webapp: dashboard, auth, agent builder, marketplace, security MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Marketing site fixes: - Center "THE PROBLEM" tag above 40+ number with flex column layout - ProblemStatement/MarketOpportunity: use bg-background, dashed TechCards, orange divider dots to match site design language - DeveloperDocs divider dot: grey → orange - TractionBar: 90% → 96% retention rate - TrustedBy: update model names (Claude Opus 4.6, GPT-4.1, Llama 3.3, etc) - Hero: add "Launch App" + "Sign Up Free" CTAs, hide empty contract address - Navbar: replace "Get Started" with orange "Launch App" button - HeroAnimation: move GUARD/CHAT render outside particle loop (fix flickering) New dashboard pages (10 routes): - /app — Cockpit with stats, event stream, health monitor, ATP treasury - /chat — Full chat with model picker, sessions, markdown, localStorage - /marketplace — Agent store with install buttons, search/filter, categories - /security — Blackwall with live threat stream, protection matrix, export - /settings — Profile/notifications/appearance/security/API keys/data export (all settings persist to localStorage) - /agents/builder — 4-step wizard: Template → Configure → Model → Deploy (saves to localStorage, shows in sidebar) - /notifications — Interactive feed with mark-read, delete, unread badges - /login — Email + OAuth login (demo mode → /app) - /signup — Signup with password strength meter, links to Terms/Privacy Dashboard infrastructure: - DashboardLayout with sidebar, header, nebula/particle backgrounds - CockpitSidebar with nav sections, search, My Agents (live from localStorage) - UserHeader with breadcrumbs, ⌘K command bar, notifications, avatar dropdown - CommandBar with keyboard nav to all routes - MobileNav bottom bar for responsive dashboard - Toast notification system - UI components: Card, Badge, GlowButton, Toast - AgentProvider context, CinematicBackgrounds effects All buttons functional — no dead-end interactions: - Marketplace Install → localStorage + toast - Agent Builder Deploy → localStorage + sidebar update - Settings Save → localStorage persist - API Key generate/copy/revoke → working - Data Export → downloads JSON file - Security Export Logs → downloads threat log - Chat attachments/mic → toast feedback - Initialize Agent → navigates to builder Co-Authored-By: Claude Opus 4.6 (1M context) --- app/(auth)/login/page.tsx | 52 ++++ app/(auth)/signup/page.tsx | 81 ++++++ app/(dashboard)/agents/builder/page.tsx | 167 ++++++++++++ app/(dashboard)/app/page.tsx | 218 ++++++++++++++++ app/(dashboard)/chat/page.tsx | 221 ++++++++++++++++ app/(dashboard)/layout.tsx | 5 + app/(dashboard)/marketplace/page.tsx | 134 ++++++++++ app/(dashboard)/notifications/page.tsx | 71 +++++ app/(dashboard)/security/page.tsx | 149 +++++++++++ app/(dashboard)/settings/page.tsx | 224 ++++++++++++++++ app/globals.css | 74 ++++++ lib/utils.ts | 6 + package-lock.json | 247 +++++++++++++----- package.json | 7 +- src/components/HeroAnimation.tsx | 43 +-- src/components/Navbar.tsx | 24 +- src/components/TrustedBy.tsx | 10 +- src/components/cockpit/CockpitSidebar.tsx | 118 +++++++++ .../effects/CinematicBackgrounds.tsx | 77 ++++++ src/components/layout/DashboardLayout.tsx | 35 +++ src/components/mobile/MobileNav.tsx | 46 ++++ src/components/mobile/index.ts | 1 + src/components/providers/AgentProvider.tsx | 42 +++ src/components/ui/Badge.tsx | 28 ++ src/components/ui/Card.tsx | 45 ++++ src/components/ui/CommandBar.tsx | 95 +++++++ src/components/ui/GlowButton.tsx | 21 ++ src/components/ui/Toast.tsx | 95 +++++++ src/components/ui/UserHeader.tsx | 55 ++++ src/sections/DeveloperDocs.tsx | 2 +- src/sections/Hero.tsx | 22 +- src/sections/MarketOpportunity.tsx | 112 ++++---- src/sections/ProblemStatement.tsx | 102 ++++---- src/sections/TractionBar.tsx | 2 +- src/services/dataService.ts | 4 +- 35 files changed, 2428 insertions(+), 207 deletions(-) create mode 100644 app/(auth)/login/page.tsx create mode 100644 app/(auth)/signup/page.tsx create mode 100644 app/(dashboard)/agents/builder/page.tsx create mode 100644 app/(dashboard)/app/page.tsx create mode 100644 app/(dashboard)/chat/page.tsx create mode 100644 app/(dashboard)/layout.tsx create mode 100644 app/(dashboard)/marketplace/page.tsx create mode 100644 app/(dashboard)/notifications/page.tsx create mode 100644 app/(dashboard)/security/page.tsx create mode 100644 app/(dashboard)/settings/page.tsx create mode 100644 lib/utils.ts create mode 100644 src/components/cockpit/CockpitSidebar.tsx create mode 100644 src/components/effects/CinematicBackgrounds.tsx create mode 100644 src/components/layout/DashboardLayout.tsx create mode 100644 src/components/mobile/MobileNav.tsx create mode 100644 src/components/mobile/index.ts create mode 100644 src/components/providers/AgentProvider.tsx create mode 100644 src/components/ui/Badge.tsx create mode 100644 src/components/ui/Card.tsx create mode 100644 src/components/ui/CommandBar.tsx create mode 100644 src/components/ui/GlowButton.tsx create mode 100644 src/components/ui/Toast.tsx create mode 100644 src/components/ui/UserHeader.tsx diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx new file mode 100644 index 0000000..f864dbc --- /dev/null +++ b/app/(auth)/login/page.tsx @@ -0,0 +1,52 @@ +"use client"; + +import { useState } from 'react'; +import Link from 'next/link'; +import { Bot, Github, Chrome, ArrowRight, Mail, Lock, Eye, EyeOff } from 'lucide-react'; +import { GlowButton } from '@/src/components/ui/GlowButton'; + +export default function LoginPage() { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [showPassword, setShowPassword] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + const handleLogin = async (e: React.FormEvent) => { + e.preventDefault(); + setIsLoading(true); + // Demo mode: just redirect to dashboard + localStorage.setItem('token', 'demo-token'); + localStorage.setItem('user', JSON.stringify({ email, name: 'Commander' })); + window.location.href = '/app'; + }; + + return ( +
+
+
+
+ +
+ OperatorUplift + +

Welcome back

+

Sign in to continue to your dashboard

+
+
+ + +
+
or continue with email
+
+
setEmail(e.target.value)} placeholder="you@example.com" className="w-full bg-white/5 border border-white/10 rounded-lg pl-12 pr-4 py-3 text-white focus:border-primary/50 focus:outline-none transition-colors" required />
+
setPassword(e.target.value)} placeholder="••••••••" className="w-full bg-white/5 border border-white/10 rounded-lg pl-12 pr-12 py-3 text-white focus:border-primary/50 focus:outline-none transition-colors" required />
+ {isLoading ? 'Signing in...' : 'Sign In'} +
+

Don't have an account?{' '}Sign up for free

+
+
+ ); +} diff --git a/app/(auth)/signup/page.tsx b/app/(auth)/signup/page.tsx new file mode 100644 index 0000000..701306d --- /dev/null +++ b/app/(auth)/signup/page.tsx @@ -0,0 +1,81 @@ +"use client"; + +import { useState } from 'react'; +import Link from 'next/link'; +import { Bot, Github, Chrome, ArrowRight, Mail, Lock, Eye, EyeOff, User } from 'lucide-react'; +import { GlowButton } from '@/src/components/ui/GlowButton'; + +export default function SignupPage() { + const [name, setName] = useState(''); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [showPassword, setShowPassword] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + const strength = password.length === 0 ? 0 : password.length < 6 ? 1 : password.length < 10 ? 2 : /[A-Z]/.test(password) && /[0-9]/.test(password) && /[^A-Za-z0-9]/.test(password) ? 4 : 3; + const strengthLabels = ['', 'Weak', 'Fair', 'Good', 'Strong']; + const strengthColors = ['', 'bg-red-500', 'bg-yellow-500', 'bg-blue-500', 'bg-emerald-500']; + + const handleSignup = async (e: React.FormEvent) => { + e.preventDefault(); + setIsLoading(true); + localStorage.setItem('token', 'demo-token'); + localStorage.setItem('user', JSON.stringify({ email, name })); + window.location.href = '/app'; + }; + + return ( +
+
+
+
+ +
+ OperatorUplift + +

Create your account

+

Start building with AI agents today

+
+ +
+ + +
+ +
or sign up with email
+ +
+
+ +
setName(e.target.value)} placeholder="Your name" className="w-full bg-white/5 border border-white/10 rounded-lg pl-12 pr-4 py-3 text-white focus:border-primary/50 focus:outline-none transition-colors" required />
+
+
+ +
setEmail(e.target.value)} placeholder="you@example.com" className="w-full bg-white/5 border border-white/10 rounded-lg pl-12 pr-4 py-3 text-white focus:border-primary/50 focus:outline-none transition-colors" required />
+
+
+ +
+ + setPassword(e.target.value)} placeholder="Create a password" className="w-full bg-white/5 border border-white/10 rounded-lg pl-12 pr-12 py-3 text-white focus:border-primary/50 focus:outline-none transition-colors" required minLength={6} /> + +
+ {password.length > 0 && ( +
+
{[1,2,3,4].map(i =>
)}
+

{strengthLabels[strength]}

+
+ )} +
+ {isLoading ? 'Creating account...' : 'Create Account'} + + +

Already have an account? Sign in

+

By signing up, you agree to our Terms and Privacy Policy

+
+
+ ); +} diff --git a/app/(dashboard)/agents/builder/page.tsx b/app/(dashboard)/agents/builder/page.tsx new file mode 100644 index 0000000..b99689c --- /dev/null +++ b/app/(dashboard)/agents/builder/page.tsx @@ -0,0 +1,167 @@ +"use client"; + +import { useState } from 'react'; +import { Sparkles, ArrowRight, ArrowLeft, Check, Bot, Brain, Code, FileText, Globe, Shield, Zap, MessageSquare } from 'lucide-react'; +import { GlowButton } from '@/src/components/ui/GlowButton'; +import { Card, CardContent } from '@/src/components/ui/Card'; +import { Badge } from '@/src/components/ui/Badge'; +import { MobilePageWrapper } from '@/src/components/mobile'; +import { useToast } from '@/src/components/ui/Toast'; + +const TEMPLATES = [ + { id: 'general', name: 'General Assistant', icon: Sparkles, color: 'text-primary', desc: 'A versatile agent for everyday tasks', capabilities: ['Chat', 'Research', 'Writing'] }, + { id: 'code', name: 'Code Expert', icon: Code, color: 'text-emerald-400', desc: 'Specialized in code generation, review, and debugging', capabilities: ['Code Gen', 'Debug', 'Refactor'] }, + { id: 'research', name: 'Research Agent', icon: Brain, color: 'text-[#9945FF]', desc: 'Deep research across papers, docs, and the web', capabilities: ['Papers', 'Citations', 'Summarize'] }, + { id: 'writer', name: 'Content Writer', icon: FileText, color: 'text-[#00D4FF]', desc: 'Blog posts, docs, social media, and more', capabilities: ['Blog', 'Social', 'Docs'] }, + { id: 'security', name: 'Security Analyst', icon: Shield, color: 'text-red-400', desc: 'Threat detection, vulnerability scanning, compliance', capabilities: ['OWASP', 'Audit', 'Monitor'] }, + { id: 'web', name: 'Web Agent', icon: Globe, color: 'text-amber-400', desc: 'Browse, scrape, and interact with the web', capabilities: ['Browse', 'Scrape', 'API'] }, +]; + +const MODELS = [ + { id: 'claude-opus-4-6', name: 'Claude Opus 4.6', provider: 'Anthropic', badge: 'RECOMMENDED' }, + { id: 'gpt-4.1', name: 'GPT-4.1', provider: 'OpenAI', badge: 'FAST' }, + { id: 'gemini-2.5-pro', name: 'Gemini 2.5 Pro', provider: 'Google', badge: 'LONG CTX' }, + { id: 'deepseek-v3', name: 'DeepSeek V3', provider: 'DeepSeek', badge: 'OPEN' }, +]; + +export default function AgentBuilderPage() { + const [step, setStep] = useState(0); + const [name, setName] = useState(''); + const [description, setDescription] = useState(''); + const [template, setTemplate] = useState(''); + const [model, setModel] = useState('claude-4-sonnet'); + const [systemPrompt, setSystemPrompt] = useState(''); + const { showToast } = useToast(); + + const steps = ['Template', 'Configure', 'Model', 'Review']; + const selectedTemplate = TEMPLATES.find(t => t.id === template); + + const handleDeploy = () => { + const agent = { name, description, template, model, systemPrompt, id: Date.now().toString(), createdAt: new Date().toISOString() }; + const existing = JSON.parse(localStorage.getItem('custom-agents') || '[]'); + existing.push(agent); + localStorage.setItem('custom-agents', JSON.stringify(existing)); + showToast(`Agent "${name}" deployed successfully!`, 'success'); + setStep(0); setName(''); setDescription(''); setTemplate(''); setSystemPrompt(''); + }; + + return ( + +
+
+ {/* Header */} +
+
+
+ +
+ WIZARD +
+

Agent Builder

+

Create and deploy custom AI agents in minutes

+
+ + {/* Step indicators */} +
+ {steps.map((s, i) => ( +
+
+ {i < step ? : i + 1} +
+ + {i < steps.length - 1 &&
} +
+ ))} +
+ + {/* Step content */} + + {step === 0 && ( +
+

Choose a template

+
+ {TEMPLATES.map(t => { + const Icon = t.icon; + return ( + + ); + })} +
+
+ )} + + {step === 1 && ( +
+

Configure your agent

+
setName(e.target.value)} className="w-full bg-white/5 border border-white/10 rounded-lg px-4 py-3 text-white focus:border-primary/50 focus:outline-none" placeholder="My Agent" />
+
setDescription(e.target.value)} className="w-full bg-white/5 border border-white/10 rounded-lg px-4 py-3 text-white focus:border-primary/50 focus:outline-none" placeholder="What does this agent do?" />
+