Some changes

This commit is contained in:
bang666asik 2025-02-11 21:52:34 +05:30
commit 9ddf4e0bda
57 changed files with 17683 additions and 0 deletions

3
.eslintrc.json Normal file
View File

@ -0,0 +1,3 @@
{
"extends": ["next/core-web-vitals", "next/typescript"]
}

36
.gitignore vendored Normal file
View File

@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

239
README.md Normal file
View File

@ -0,0 +1,239 @@
# ALMAZE: Intelligent Multi-Agent Problem-Solving Ecosystem
![ALMAZE Banner]()
## Table of Contents
1. [Introduction](#introduction)
2. [Safety Guidelines](#safety-guidelines)
3. [AI Agents](#ai-agents)
4. [System Architecture](#system-architecture)
5. [Getting Started](#getting-started)
- [Prerequisites](#prerequisites)
- [Backend Installation](#backend-installation)
- [Frontend Installation](#frontend-installation)
- [Configuration](#configuration)
- [Running the System](#running-the-system)
6. [Core Components](#core-components)
7. [Frontend Technologies](#frontend-technologies)
8. [Contributing](#contributing)
9. [License](#license)
## Introduction
**ALMAZE** is an advanced multi-agent AI system designed to navigate complex problem-solving landscapes. By leveraging specialized agents working in harmony, ALMAZE breaks down intricate challenges and discovers innovative solutions.
## Safety Guidelines
To ensure responsible and secure AI interaction:
- **Ethical AI Principles**: Prioritize transparency, fairness, and user safety
- **Controlled Environment**: Implement strict access controls and monitoring
- **Data Privacy**: Protect user information with robust encryption
- **Human Oversight**: Maintain human intervention for critical decisions
- **Continuous Validation**: Regularly audit agent behaviors and outputs
## AI Agents
ALMAZE comprises specialized agents, each with a unique role in solving complex problems:
### 🧭 Compass (Central Intelligence)
- **Primary Function**: Task interpretation and workflow management
- Analyzes user goals
- Coordinates agent interactions
- Guides strategic problem-solving
### 🏗️ Architect (System Designer)
- **Primary Function**: Agent ecosystem management and evolution
- Creates and refines agent structures
- Ensures adaptive system capabilities
- Optimizes agent collaboration frameworks
### 🔧 Toolsmith (Resource Creator)
- **Primary Function**: Developing and maintaining agent tools
- Crafts specialized resources
- Enhances agent capabilities
- Provides necessary instruments for task navigation
### 🔍 Scout (Knowledge Gatherer)
- **Primary Function**: Information exploration and mapping
- Collects and synthesizes critical data
- Provides contextual insights
- Supports informed decision-making
### ⭐ TechSage ( Knowledge Amplifier)
- **Primary Function**: Handles tasks related to software development
- Intelligent Knowledge Mapping
- Contextual Intelligence
- Cross-Domain Learning
## System Architecture
ALMAZE follows a comprehensive, layered architecture:
- **Backend**: Python-based multi-agent system
- **Frontend**: React & Next.js web application
- **Authentication**: Privy for secure user management
- **Real-time Communication**: RestAPIs integration
## Getting Started
### Prerequisites
#### Backend Requirements
- Python 3.8+
- pip package manager
- Virtual environment support
#### Frontend Requirements
- Node.js 18+
- npm or yarn
- Next.js 14
- React 18+
### Backend Installation
```bash
# Clone the repository
git clone https://github.com/Almaze-Labs/almaze-api.git
cd almaze-api
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
```
### Frontend Installation
<<<<<<< HEAD
=======
> > > > > > > 57b0960eacdd6ab55583e747a36c4ab29ea49c36
```bash
# Clone the repository
git clone https://github.com/Almaze-Labs/almaze-app.git
cd almaze-app
# Install dependencies
npm install
# Or using yarn
yarn install
# Copy environment template
cp .env.example .env.local
# Fill in required environment variables
```
### Configuration
1. Configure backend agent parameters
2. Set up frontend environment variables
3. Configure authentication providers
4. Set up database connections
### Running the System
#### Backend
```bash
# Basic execution
python app.py
```
#### Frontend
```bash
# Development mode
npm run dev
# or
yarn dev
# Production build
npm run build
npm run start
# or
yarn build
yarn start
```
## Frontend Technologies
### Core Technologies
- **Framework**: Next.js 14
- **UI Library**: React
- **State Management**: Redux Toolkit
- **Authentication**: Privy
- **Styling**: Tailwind CSS
### Key Frontend Features
- **Responsive Design**: Mobile and desktop-friendly
- **Real-time Agent Interaction**: RestAPIs-powered updates
- **Secure Authentication**: Privy-managed user sessions
- **Performance Optimization**: Server-side rendering
- **Dynamic Agent Visualization**: Interactive agent status and workflow
### Authentication Flow
1. User registers/logs in via Privy
2. Secure token generation
3. Role-based access control
4. Session management
## Core Components
- **Multi-Agent Architecture**: Collaborative problem-solving ecosystem
- **Dynamic Adaptation**: Agents evolve to meet changing challenges
- **Intelligent Coordination**: Seamless interaction between specialized agents
- **Flexible Task Management**: Advanced workflow optimization
## Contributing
We welcome contributions! Help us expand the ALMAZE ecosystem.
### Development Setup
```bash
# Backend development
cd almaze-api
pip install -r requirements-dev.txt
# Frontend development
cd almaze-app
```
### Contribution Guidelines
- Follow our Code of Conduct
- Submit detailed pull requests
- Maintain clean, documented code
- Pass all automated tests
## License
This project is licensed under the MIT License.
## Acknowledgments
- Inspired by cutting-edge AI research
- Dedicated to pushing the boundaries of intelligent problem-solving
---
**Disclaimer**: ALMAZE is an experimental AI system. Use responsibly and verify critical outputs.

115
app/api/chat/route.js Normal file
View File

@ -0,0 +1,115 @@
// app/api/chat/route.js
import { NextResponse } from 'next/server';
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000';
const fetchWithRetry = async (url, options) => {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 3000000);
try {
const response = await fetch(url, {
...options,
signal: controller.signal,
});
clearTimeout(timeoutId);
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.detail || `HTTP error! status: ${response.status}`);
}
return response;
} catch (error) {
clearTimeout(timeoutId);
// if (retryCount < MAX_RETRIES - 1) {
// console.log(`Attempt ${retryCount + 1} failed, retrying in ${RETRY_DELAY}ms...`);
// await new Promise(resolve => setTimeout(resolve, RETRY_DELAY));
// return fetchWithRetry(url, options, retryCount + 1);
// }
throw error;
}
};
export async function POST(req) {
try {
const body = await req.json();
const { message, sessionId } = body;
if (!message) {
return NextResponse.json(
{ error: 'Message is required' },
{ status: 400 }
);
}
try {
const response = await fetchWithRetry(
`${API_URL}/api/chat`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message,
session_id: sessionId,
}),
}
);
const data = await response.json();
return NextResponse.json(data);
} catch (error) {
if (error.name === 'AbortError') {
return NextResponse.json(
{
error: 'Request timed out. Please try again.',
retryable: true
},
{ status: 504 }
);
}
if (error.cause?.code === 'UND_ERR_CONNECT_TIMEOUT') {
return NextResponse.json(
{
error: 'Unable to connect to the backend server. Please try again later.',
retryable: true
},
{ status: 503 }
);
}
if (error.message.includes('Failed to fetch') || error.message.includes('ECONNREFUSED')) {
return NextResponse.json(
{
error: 'Backend server is not running. Please try again later.',
retryable: true
},
{ status: 503 }
);
}
throw error;
}
} catch (error) {
// console.error('Error in chat API:', error);
return NextResponse.json(
{
error: error.message || 'Internal server error',
retryable: true
},
{ status: 500 }
);
}
}

199
app/auth/page.tsx Normal file
View File

@ -0,0 +1,199 @@
"use client"
import { memo, useEffect, useState, useCallback } from 'react';
import { useRouter } from 'next/navigation';
import Cookies from 'js-cookie';
import { usePrivy } from '@privy-io/react-auth';
import { Providers } from '@/components/providers/privy-provider';
import { Mail, ArrowRight, Hexagon, LucideIcon } from 'lucide-react';
interface LoginButtonProps {
icon: LucideIcon;
text: string;
onClick: () => void;
}
interface FeatureCardProps {
text: string;
}
// Futuristic geometric background
const BackgroundEffect = memo(function BackgroundEffect() {
return (
<div className="absolute inset-0 overflow-hidden">
{/* Base gradient */}
<div className="absolute inset-0 bg-gradient-to-br from-gray-50 via-gray-100 to-gray-200" />
{/* Geometric patterns */}
<div className="absolute inset-0 opacity-5">
<div className="absolute top-0 left-0 w-full h-full">
{Array.from({ length: 5 }).map((_, i) => (
<div
key={i}
className="absolute transform -translate-x-1/2 -translate-y-1/2"
style={{
left: `${Math.random() * 100}%`,
top: `${Math.random() * 100}%`,
width: `${Math.random() * 300 + 100}px`,
height: `${Math.random() * 300 + 100}px`,
border: '2px solid rgba(0,0,0,1)',
transform: `rotate(${Math.random() * 360}deg)`,
}}
>
<Hexagon className="w-full h-full stroke-current opacity-40" />
</div>
))}
</div>
</div>
{/* Modern gradient orbs */}
<div className="absolute top-0 right-0 w-[500px] h-[500px] bg-gradient-to-br from-gray-200/40 to-transparent rounded-full blur-3xl transform rotate-12 opacity-60" />
<div className="absolute bottom-0 left-0 w-[500px] h-[500px] bg-gradient-to-tr from-gray-200/40 to-transparent rounded-full blur-3xl transform -rotate-12 opacity-60" />
</div>
);
});
// Enhanced loading animation
const LoadingSpinner = memo(function LoadingSpinner() {
return (
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-gray-50 via-gray-50 to-gray-50">
<div className="relative">
<div className="absolute inset-0 border-2 border-gray-800/20 rounded-lg blur animate-pulse" />
<div className="relative flex items-center justify-center w-16 h-16">
<div className="absolute w-full h-full border-t-2 border-gray-800 rounded-full animate-spin" />
<div className="absolute w-10 h-10 border-t-2 border-gray-800/50 rounded-full animate-spin-slow" />
</div>
</div>
</div>
);
});
// Enhanced button with modern hover effects
const LoginButton = memo(function LoginButton({ icon: Icon, text, onClick }: LoginButtonProps) {
return (
<button
onClick={onClick}
className="group relative w-full flex items-center justify-between px-6 py-4 rounded-xl
bg-gradient-to-r from-gray-700/90 to-gray-600/90 hover:from-gray-800 hover:to-gray-700
text-white transform transition-all duration-300
hover:shadow-[0_0_20px_rgba(0,0,0,0.1)] hover:scale-[1.01]"
>
<div className="absolute inset-px rounded-[11px] bg-gradient-to-r from-white/[0.08] to-transparent opacity-0 group-hover:opacity-100 transition-opacity" />
<div className="flex items-center space-x-3 z-10">
<div className="p-1 rounded-lg bg-white/10">
<Icon className="w-4 h-4" />
</div>
<span className="font-medium tracking-wide">{text}</span>
</div>
<div className="flex items-center z-10">
<ArrowRight className="w-5 h-5 transform group-hover:translate-x-1 transition-transform" />
</div>
</button>
);
});
// Modern feature card
const FeatureCard = memo(function FeatureCard({ text }: FeatureCardProps) {
return (
<div className="relative group">
<div className="absolute inset-0 bg-gradient-to-r from-gray-600/20 to-gray-500/20 rounded-xl blur-sm transform transition-all duration-300 group-hover:scale-105 opacity-0 group-hover:opacity-100" />
<div className="relative p-4 rounded-xl bg-white/[0.03] border border-white/10 backdrop-blur-sm
transform transition-all duration-300">
<p className="text-sm text-gray-600 font-medium">{text}</p>
</div>
</div>
);
});
const LoginContent = memo(function LoginContent() {
const router = useRouter();
const [isLoading, setIsLoading] = useState(true);
const privy = usePrivy();
const handleLogin = useCallback(() => privy.login(), [privy]);
// const handleWalletConnect = useCallback(() => privy.connectWallet(), [privy]);
useEffect(() => {
if (privy?.ready) {
setIsLoading(false);
if (privy.authenticated) {
localStorage.setItem('useremail', privy.user?.email?.address ?? "Guest");
Cookies.set('privy-authenticated', 'true', { path: '/', expires: 1 });
router.push('/dashboard');
}
}
}, [privy.ready, privy.authenticated, router]);
if (isLoading) return <LoadingSpinner />;
return (
<main className="min-h-screen relative overflow-hidden">
<BackgroundEffect />
<div className="relative min-h-screen flex items-center justify-center p-4">
<div className="w-full max-w-md">
<div className="relative p-8 rounded-2xl overflow-hidden">
{/* Card backdrop blur effect */}
<div className="absolute inset-0 bg-white/40 backdrop-blur-xl rounded-2xl" />
{/* Content */}
<div className="relative">
<div className="text-center mb-10">
<h1 className="text-5xl font-bold text-transparent bg-clip-text bg-gradient-to-b from-gray-800 to-gray-600 mb-3">
ALMAZE
</h1>
<div className="flex items-center justify-center gap-3 text-gray-500">
<span className="w-2 h-2 rounded-full bg-gray-400" />
<span className="text-lg tracking-wide">Secure</span>
<span className="w-2 h-2 rounded-full bg-gray-400" />
<span className="text-lg tracking-wide">Seamless</span>
<span className="w-2 h-2 rounded-full bg-gray-400" />
<span className="text-lg tracking-wide">Smart</span>
</div>
</div>
<div className="space-y-4 mb-8">
<LoginButton
icon={Mail}
text="Continue with ALMAZE"
onClick={handleLogin}
/>
{/* <LoginButton
icon={Wallet}
text="Connect Wallet"
onClick={handleWalletConnect}
/> */}
</div>
<div className="text-center">
<p className="text-gray-500 text-sm">
By continuing, you agree to our{' '}
<a href="#" className="text-gray-700 hover:text-gray-900 underline underline-offset-4 transition-colors">
Terms of Service
</a>
</p>
</div>
</div>
</div>
<div className="mt-8 grid grid-cols-3 gap-4">
<FeatureCard text="Secure Storage" />
<FeatureCard text="Fast Transactions" />
<FeatureCard text="24/7 Support" />
</div>
</div>
</div>
</main>
);
});
const Home = memo(function Home() {
return (
<Providers>
<LoginContent />
</Providers>
);
});
export default Home;

592
app/dashboard/page.tsx Normal file
View File

@ -0,0 +1,592 @@
'use client'
import React, { useState, useEffect, useRef, useCallback } from 'react';
import { v4 as uuidv4 } from 'uuid';
import Cookies from 'js-cookie';
import { usePrivy, useWallets } from '@privy-io/react-auth';
import { useRouter } from 'next/navigation';
import { Providers } from '@/components/providers/privy-provider';
import { StarredChat } from '@/components/chat/sidebar/StarredChat';
import { SidebarHeader } from '@/components/chat/sidebar/SidebarHeader';
import { IntegrationButton } from '@/components/chat/IntegrationButton';
import { ChatInput } from '@/components/chat/ChatInput';
import { WelcomeHeader } from '@/components/chat/WelcomeHeader';
import MessageBubble from '@/components/chat/MessageBubble';
import { motion, AnimatePresence } from 'framer-motion';
import { Settings, LogOut, Compass ,Landmark, Wrench, ScanSearch, Computer } from 'lucide-react';
import Avatar, { genConfig } from 'react-nice-avatar';
import logo from "@/public/assets/logo/landing-logo-blue.png"
import { NICKNAMES } from '@/components/chat/constants/nicknames';
interface Message {
id: string;
role: 'user' | 'assistant' | 'system';
content: string;
timestamp: string;
}
interface Conversation {
id: string;
title: string;
date: string;
messages: Message[];
isStarred: boolean;
}
function DashboardContent() {
const [conversations, setConversations] = useState<Conversation[]>([]);
const [messages, setMessages] = useState<Message[]>([]);
const [input, setInput] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [sessionId, setSessionId] = useState(() => uuidv4());
const [currentConversation, setCurrentConversation] = useState<Conversation | null>(null);
const [isMobile, setIsMobile] = useState(false);
const [isSidebarOpen, setSidebarOpen] = useState(false);
const messagesEndRef = useRef<HTMLDivElement>(null);
const [showLogout, setShowLogout] = useState(false);
const [userName, setUserName] = useState('ALMAZE');
const [avatarConfig, setAvatarConfig] = useState(() => genConfig());
const { ready, authenticated, logout: privyLogout } = usePrivy();
const router = useRouter();
const { wallets } = useWallets();
const sidebarTimeoutRef = useRef<NodeJS.Timeout>();
const [isLongResponse, setIsLongResponse] = useState(false);
//Random Username Generator
useEffect(() => {
const randomIndex = Math.floor(Math.random() * NICKNAMES.length);
const selectedName = NICKNAMES[randomIndex];
setUserName(selectedName);
setAvatarConfig(genConfig(selectedName));
}, []);
useEffect(() => {
const handleResize = () => {
const mobile = window.innerWidth <= 768;
setIsMobile(mobile);
setSidebarOpen(false);
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
const scrollToBottom = useCallback(() => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
}, []);
const startNewChat = useCallback(() => {
const newSessionId = uuidv4();
setSessionId(newSessionId);
setMessages([]);
setCurrentConversation(null);
setSidebarOpen(false);
// Force scroll to input
setTimeout(() => {
const inputElement = document.querySelector('input[type="text"]');
(inputElement as HTMLInputElement)?.focus();
}, 100);
}, [isMobile]);
const handleStarChat = useCallback((id: string) => {
setConversations(prev => prev.map(conv =>
conv.id === id ? { ...conv, isStarred: !conv.isStarred } : conv
));
}, []);
const loadConversation = useCallback((conversation: Conversation) => {
setSessionId(conversation.id);
setMessages(conversation.messages);
setCurrentConversation(conversation);
if (isMobile) setSidebarOpen(false);
}, [isMobile]);
// Removed unused deleteConversation function
const handleSidebarHover = (isHovering: boolean) => {
if (isMobile) return;
if (sidebarTimeoutRef.current) {
clearTimeout(sidebarTimeoutRef.current);
}
if (isHovering) {
setSidebarOpen(true);
} else {
sidebarTimeoutRef.current = setTimeout(() => {
setSidebarOpen(false);
}, 300); // Small delay before closing
}
};
useEffect(() => {
if (ready && !authenticated) {
router.push('/');
}
}, [ready, authenticated, router]);
const handleLogout = useCallback(async () => {
try {
// Disconnect any connected wallets first
for (const wallet of wallets) {
try {
await wallet.disconnect();
} catch (e) {
console.error('Error disconnecting wallet:', e);
}
}
// Remove cookie before Privy logout to prevent race conditions
Cookies.remove('privy-authenticated', { path: '/' });
// Perform Privy logout
await privyLogout();
// Clear any local storage items
localStorage.removeItem('privy:embedded-wallet:iframe-ready');
localStorage.removeItem('privy:embedded-wallet:ready');
// Redirect to auth page
router.push('/');
} catch (error) {
console.error('Logout error:', error);
// Ensure redirect happens even if there's an error
router.push('/');
}
}, [privyLogout, router, wallets]);
// console.log("Cook: ",Cookies.get("privy-authenticated"))
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!input.trim() || isLoading) return;
const userMessage: Message = {
id: uuidv4(),
role: 'user',
content: input,
timestamp: new Date().toISOString()
};
setMessages(prev => [...prev, userMessage]);
setInput('');
setIsLoading(true);
const timer = setTimeout(() => {
setIsLongResponse(true);
}, 10000);
scrollToBottom();
try {
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
message: input,
sessionId: sessionId,
}),
});
if (!response.ok) throw new Error('Failed to get response');
const data = await response.json();
const messageContent = processResponse(data);
const assistantMessage: Message = {
id: uuidv4(),
role: 'assistant',
content: messageContent,
timestamp: new Date().toISOString()
};
setMessages(prev => [...prev, assistantMessage]);
if (!currentConversation) {
const newConversation: Conversation = {
id: sessionId,
title: input.slice(0, 30) + (input.length > 30 ? '...' : ''),
date: new Date().toLocaleDateString(),
messages: [userMessage, assistantMessage],
isStarred: false
};
setConversations(prev => [newConversation, ...prev]);
setCurrentConversation(newConversation);
}
} catch (error) {
console.error('Error:', error);
setMessages(prev => [...prev, {
id: uuidv4(),
role: 'system',
content: 'Sorry, something went wrong. Please try again.',
timestamp: new Date().toISOString()
}]);
} finally {
setIsLoading(false);
setIsLongResponse(false);
clearTimeout(timer);
scrollToBottom();
}
};
return (
<Providers>
<div className="flex h-screen bg-gray-50">
{/* Always visible sidebar strip */}
<div
className="fixed left-0 top-0 h-full z-40 flex border shadow-sm bg-white"
onMouseEnter={() => handleSidebarHover(true)}
onMouseLeave={() => handleSidebarHover(false)}
>
{/* Thin visible strip when sidebar is closed */}
<div className={`w-14 h-full bg-white hover:bg-gray-50 transition-colors ${isSidebarOpen ? 'hidden' : 'block'}`} />
<AnimatePresence>
{isSidebarOpen && (
<motion.div
initial={{ width: 0, opacity: 0 }}
animate={{ width: 320, opacity: 1 }}
exit={{ width: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: "easeInOut" }}
className="bg-white border-r flex flex-col overflow-hidden h-full"
>
<SidebarHeader onNewChat={startNewChat} logo={logo}/>
<div className="flex-1 overflow-y-auto">
{/* Starred Chats */}
<div className="p-4">
<h2 className="text-xs text-gray-500 font-medium mb-2">STARRED CHATS</h2>
<div className="space-y-2">
{conversations
.filter(chat => chat.isStarred)
.map(chat => (
<StarredChat
key={chat.id}
title={chat.title}
isStarred={chat.isStarred}
onClick={() => loadConversation(chat)}
onStar={() => handleStarChat(chat.id)}
/>
))}
</div>
</div>
{/* Regular Conversations */}
<div className="p-4">
<h2 className="text-xs text-gray-500 font-medium mb-2">CONVERSATIONS</h2>
<div className="space-y-2">
{conversations
.filter(chat => !chat.isStarred)
.map(chat => (
<StarredChat
key={chat.id}
title={chat.title}
isStarred={chat.isStarred}
onClick={() => loadConversation(chat)}
onStar={() => handleStarChat(chat.id)}
/>
))}
</div>
</div>
</div>
{/* User Section with Logout */}
<div className="p-4 border-t">
<div
className="relative"
onMouseEnter={() => setShowLogout(true)}
onMouseLeave={() => setShowLogout(false)}
>
<div className="flex items-center justify-between p-2 hover:bg-gray-50 rounded-lg cursor-pointer w-full">
<div className="flex items-center gap-2 w-full">
<Avatar style={{ width: '2rem', height: '2rem' }} {...avatarConfig} />
<div className='flex flex-col w-full'>
<div className='flex flex-row items-center justify-between w-full'>
<span className="text-sm text-gray-600">{userName}</span>
<Settings className="h-4 w-4 text-gray-400 mr-2" />
</div>
<div className="text-[8px] text-gray-400">
<span className="truncate">{sessionId}</span>
</div>
</div>
</div>
</div>
<AnimatePresence>
{showLogout && (
<motion.button
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
onClick={handleLogout}
className="absolute bottom-full left-0 w-full p-2 mb-1 bg-white shadow-lg rounded-lg border flex items-center gap-2 text-gray-600 hover:bg-gray-50"
>
<LogOut className="h-4 w-4" />
<span className="text-sm">Logout</span>
</motion.button>
)}
</AnimatePresence>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</div>
{/* Main Content Area with proper margin for sidebar strip */}
<div className={`flex-1 flex flex-col relative transition-all duration-300 ${isSidebarOpen ? 'ml-[320px]' : 'ml-2'}`}>
{/* Main Chat Area */}
<div className="flex-1 flex flex-col relative bg-gray-50">
{isMobile && (
<button
onClick={() => setSidebarOpen(!isSidebarOpen)}
className="absolute top-4 left-4 z-50 p-2 bg-white rounded-lg shadow-lg"
>
</button>
)}
<div className="flex-1 p-8 flex flex-col items-center justify-center max-w-3xl mx-auto w-full">
{messages.length === 0 ? (
<>
<WelcomeHeader name={userName} version="v1.0 - Launching ALMAZE" />
<p className="text-gray-500 text-center mb-8 max-w-lg">
Ready to help you with your tasks and questions.
</p>
<div className="w-full mb-8 text-[15px] text-gray-400 ">
<ChatInput
input={input}
setInput={setInput}
handleSubmit={handleSubmit}
isLoading={isLoading}
/>
</div>
{/* Integration Buttons */}
<div>
<h3 className="text-sm font-medium text-gray-700 mb-4 text-center">
EXPLORE INTEGRATIONS
</h3>
<div className="flex flex-wrap gap-3 justify-center">
<IntegrationButton
Icon={Compass}
label="COMPASS"
color="#1DA2FF"
onClick={() => {}}
/>
<IntegrationButton
Icon={Landmark}
label="ARCHITECT"
color="#FFBA17"
onClick={() => {}}
/>
<IntegrationButton
Icon={Wrench}
label="TOOLSMITH"
color="#FF5C3D"
onClick={() => {}}
/>
<IntegrationButton
Icon={ScanSearch}
label="SCOUT"
color="#9700F4"
onClick={() => {}}
/>
<IntegrationButton
Icon={Computer}
label="TECHSAGE"
color="#8FBC8F"
onClick={() => {}}
/>
</div>
</div>
</>
) : (
<div className="w-full space-y-6 bg-gray-50">
{messages.map((message, i) => (
<MessageBubble
key={message.id}
message={message}
isLast={i === messages.length - 1}
userName={userName}
avatarConfig={avatarConfig}
/>
))}
{isLoading && (
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
className="flex flex-col items-center justify-center p-4 gap-3"
>
{/* Dots animation */}
<div className="flex gap-2">
<motion.div
animate={{ scale: [1, 1.2, 1] }}
transition={{ repeat: Infinity, duration: 1 }}
className="w-2 h-2 bg-blue-500 rounded-full"
/>
<motion.div
animate={{ scale: [1, 1.2, 1] }}
transition={{ repeat: Infinity, duration: 1, delay: 0.2 }}
className="w-2 h-2 bg-blue-400 rounded-full"
/>
<motion.div
animate={{ scale: [1, 1.2, 1] }}
transition={{ repeat: Infinity, duration: 1, delay: 0.4 }}
className="w-2 h-2 bg-blue-300 rounded-full"
/>
</div>
{/* Processing message that appears after delay */}
{isLongResponse && (
<motion.div
initial={{ opacity: 0, y: 5 }}
animate={{ opacity: 1, y: 0 }}
className="text-center"
>
<motion.p
className="text-[#1DA2FF] text-sm font-offbit"
animate={{ opacity: [0.5, 1, 0.5] }}
transition={{
duration: 2,
repeat: Infinity,
ease: "easeInOut"
}}
>
Hold on a moment...
</motion.p>
</motion.div>
)}
</motion.div>
)}
<div ref={messagesEndRef} />
<div className=" mt-6 w-full text-[15px] text-gray-400 ">
<ChatInput
input={input}
setInput={setInput}
handleSubmit={handleSubmit}
isLoading={isLoading}
/>
</div>
</div>
)}
</div>
</div>
</div>
</div>
</Providers>
);
}
// Helper function to process API response
function processResponse(data: { response: string; agent_responses?: { agent: string; response: string }[] }): string {
try {
const responseObj = JSON.parse(data.response);
let messageContent = '';
const compassResponse = responseObj.agent_responses?.find(
(response: { agent: string }) => response.agent === "compass"
);
if (compassResponse) {
messageContent = compassResponse.response;
} else {
// Process Scout Response
const scoutResponse = responseObj.agent_responses?.find(
(response: { agent: string }) => response.agent === "scout"
);
if (scoutResponse) {
try {
const researchData = JSON.parse(scoutResponse.response);
messageContent = researchData.message || scoutResponse.response;
} catch {
messageContent = scoutResponse.response;
}
messageContent = messageContent
.replace(/\b(bound)\b/gi, '**$1**')
.replace(/(bound)/gi, '**$1**');
}
// Process Tech Sage Response
const techSageResponse = responseObj.agent_responses?.find(
(response: { agent: string }) => response.agent === "techsage"
);
if (techSageResponse) {
try {
const engineerData = JSON.parse(techSageResponse.response);
messageContent = formatEngineerResponse(engineerData);
} catch (parseError) {
console.error('Error parsing techsage response:', parseError);
messageContent = techSageResponse.response;
}
}
}
return messageContent || 'Received a response but couldn\'t process it properly.';
} catch (error) {
console.error('Error processing response:', error);
return data.response;
}
}
// Helper function to format engineer response
function formatEngineerResponse(engineerData: { status: string; message: string; suggestions?: string[]; query: string; analysis: { task_type: string; language: string; technologies: string[] }; implementation: { files: { filename: string; language: string; content: string }[]; setup?: string; usage?: string; api_docs?: string; configuration?: string }; files_created?: string[] }): string {
if (engineerData.status === "error") {
let content = `⚠️ Error: ${engineerData.message}\n\n`;
if (engineerData.suggestions?.length) {
content += "Suggestions:\n";
engineerData.suggestions.forEach((suggestion: string) => {
content += `- ${suggestion}\n`;
});
}
return content;
}
let content = `# ${engineerData.query}\n\n`;
content += `## Project Analysis\n`;
content += `- Type: ${engineerData.analysis.task_type}\n`;
content += `- Language: ${engineerData.analysis.language}\n`;
content += `- Technologies: ${engineerData.analysis.technologies.join(", ")}\n\n`;
content += `## Implementation\n\n`;
engineerData.implementation.files.forEach((file: { filename: string; language: string; content: string }) => {
content += `### File: ${file.filename}\n`;
content += `\`\`\`${file.language}\n${file.content}\n\`\`\`\n\n`;
});
if (engineerData.implementation.setup) {
content += `## Setup Instructions\n${engineerData.implementation.setup}\n\n`;
}
if (engineerData.implementation.usage) {
content += `## Usage Examples\n${engineerData.implementation.usage}\n\n`;
}
if (engineerData.implementation.api_docs) {
content += `## API Documentation\n${engineerData.implementation.api_docs}\n\n`;
}
if (engineerData.implementation.configuration) {
content += `## Configuration\n${engineerData.implementation.configuration}\n\n`;
}
if (engineerData.files_created?.length) {
content += `## Files Created\n`;
engineerData.files_created.forEach((file: string) => {
content += `- \`${file}\`\n`;
});
}
return content;
}
export default function Dashboard() {
return (
<Providers>
<DashboardContent />
</Providers>
);
}

BIN
app/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

142
app/globals.css Normal file
View File

@ -0,0 +1,142 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@font-face {
font-family: 'OffBit';
src: url('../public/fonts/OffBit-DotBold.ttf') format('truetype');
font-weight: normal;
font-style: normal;
font-display: swap; /* Added for better font loading performance */
}
/* Update the body font-family to prioritize OffBit */
body {
font-family: 'OffBit', Arial, Helvetica, sans-serif;
}
@layer utilities {
.text-balance {
text-wrap: balance;
}
}
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--radius: 0.5rem;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 0 0% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 9%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
@keyframes blob {
0% {
transform: translate(0px, 0px) scale(1);
}
33% {
transform: translate(30px, -50px) scale(1.1);
}
66% {
transform: translate(-20px, 20px) scale(0.9);
}
100% {
transform: translate(0px, 0px) scale(1);
}
}
.animate-blob {
animation: blob 7s infinite;
}
.animation-delay-2000 {
animation-delay: 2s;
}
.animation-delay-4000 {
animation-delay: 4s;
}
@keyframes blob {
0% {
transform: translate(0px, 0px) scale(1);
}
33% {
transform: translate(30px, -50px) scale(1.1);
}
66% {
transform: translate(-20px, 20px) scale(0.9);
}
100% {
transform: translate(0px, 0px) scale(1);
}
}
.animate-blob {
animation: blob 7s infinite;
}
.animation-delay-2000 {
animation-delay: 2s;
}
.animation-delay-4000 {
animation-delay: 4s;
}

301
app/home/AgentsSection.tsx Normal file
View File

@ -0,0 +1,301 @@
"use client";
import { useRef } from "react";
import { JSX } from "react/jsx-runtime";
import Image from "next/image";
import img1 from "@/public/assets/images/agents-section-1.png"
import { TypingAnimation } from "@/components/home/magicui/typing-animation";
import { AnimatedBeam } from "@/components/home/magicui/animated-beam";
import { motion } from "framer-motion";
interface IAgent {
icon: JSX.Element;
color: string;
title: string;
description: string;
}
export default function AgentsSection() {
const containerRef = useRef<HTMLDivElement>(null);
const logoRef = useRef<HTMLDivElement>(null);
const div1Ref = useRef<HTMLDivElement>(null);
const div2Ref = useRef<HTMLDivElement>(null);
const div3Ref = useRef<HTMLDivElement>(null);
const div4Ref = useRef<HTMLDivElement>(null);
const agents: IAgent[] = [
{
icon: (
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M18 33C25.4558 33 31.5 26.9558 31.5 19.5C31.5 12.0442 25.4558 6 18 6C10.5442 6 4.5 12.0442 4.5 19.5C4.5 26.9558 10.5442 33 18 33Z"
stroke="#30A5FF"
strokeWidth="2.25"
strokeLinecap="round"
/>
<path
d="M18 5.25V3"
stroke="#30A5FF"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M15 3H21"
stroke="#30A5FF"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M22.1592 15.3856C23.2592 16.4755 21.4992 25.3399 19.6934 25.4961C18.1784 25.6272 17.7062 22.6392 17.3871 21.6921C17.0723 20.7574 16.7217 20.4208 15.7947 20.1142C13.4398 19.3351 12.2624 18.9456 12.0293 18.3288C11.4119 16.6956 20.7543 13.9935 22.1592 15.3856Z"
stroke="#30A5FF"
strokeWidth="2.25"
/>
</svg>
),
color: "#30A5FF",
title: "Compass",
description:
"The core intelligence of ALMAZE, guiding tasks and agents to achieve user goals effectively.",
},
{
icon: (
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M3 33H33"
stroke="#FFBA17"
strokeWidth="2.25"
strokeLinecap="round"
/>
<path
d="M27 13.5H21C17.277 13.5 16.5 14.277 16.5 18V33H31.5V18C31.5 14.277 30.723 13.5 27 13.5Z"
stroke="#FFBA17"
strokeWidth="2.25"
strokeLinejoin="round"
/>
<path
d="M22.5 33H4.5V7.5C4.5 3.777 5.277 3 9 3H18C21.723 3 22.5 3.777 22.5 7.5V13.5"
stroke="#FFBA17"
strokeWidth="2.25"
strokeLinejoin="round"
/>
<path
d="M4.5 9H9M4.5 15H9M4.5 21H9"
stroke="#FFBA17"
strokeWidth="2.25"
strokeLinecap="round"
/>
<path
d="M22.5 19.5H25.5M22.5 24H25.5"
stroke="#FFBA17"
strokeWidth="2.25"
strokeLinecap="round"
/>
<path
d="M24 33V28.5"
stroke="#FFBA17"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
),
color: "#FFBA17",
title: "Architect",
description:
"Designs and maintains agents, ensuring the maze evolves efficiently to tackle new challenges.",
},
{
icon: (
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M19.5 16.5L27 9" stroke="#FF5C3D" strokeWidth="2.25" />
<path
d="M28.5 10.5L25.5 7.5L29.25 5.25L30.75 6.75L28.5 10.5Z"
stroke="#FF5C3D"
strokeWidth="2.25"
strokeLinejoin="round"
/>
<path
d="M6.03769 13.4623C4.52124 11.9459 4.12642 9.73254 4.85322 7.85322L6.98622 9.98622H9.98622V6.98622L7.85322 4.85322C9.73254 4.12642 11.9459 4.52124 13.4623 6.03769C14.9793 7.5547 15.3739 9.76911 14.646 11.6489L24.3511 21.354C26.2309 20.626 28.4452 21.0207 29.9623 22.5376C31.4787 24.0541 31.8736 26.2674 31.1467 28.1467L29.0137 26.0137H26.0137V29.0137L28.1467 31.1467C26.2674 31.8736 24.0541 31.4787 22.5376 29.9623C21.0217 28.4464 20.6266 26.2342 21.3523 24.3553L11.6447 14.6476C9.76579 15.3733 7.55356 14.9782 6.03769 13.4623Z"
stroke="#FF5C3D"
strokeWidth="2.25"
strokeLinejoin="round"
/>
<path
d="M18.3045 21.75L9.89845 30.1561C9.10672 30.9478 7.8231 30.9478 7.03137 30.1561L5.84379 28.9686C5.05207 28.1769 5.05207 26.8932 5.84379 26.1015L14.2499 17.6953"
stroke="#FF5C3D"
strokeWidth="2.25"
strokeLinejoin="round"
/>
</svg>
),
color: "#FF5C3D",
title: "Tool Smith",
description:
"The creator of resources, Toolsmith crafts and refines the instruments agents need to navigate the maze of tasks effectively.",
},
{
icon: (
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M26.25 26.25L33 33"
stroke="#9700F4"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M30 16.5C30 9.04416 23.9559 3 16.5 3C9.04416 3 3 9.04416 3 16.5C3 23.9559 9.04416 30 16.5 30C23.9559 30 30 23.9559 30 16.5Z"
stroke="#9700F4"
strokeWidth="2.25"
strokeLinejoin="round"
/>
<path
d="M14.2386 11.25C13.1639 11.3151 12.4799 11.4943 11.9871 11.9871C11.4943 12.4799 11.3151 13.1639 11.25 14.2386M18.7614 11.25C19.8361 11.3151 20.5202 11.4943 21.0129 11.9871C21.5057 12.4799 21.6849 13.1639 21.75 14.2386M21.7385 18.9321C21.6647 19.9095 21.4791 20.5467 21.0129 21.0129C20.5202 21.5057 19.8361 21.6849 18.7614 21.75M14.2386 21.75C13.1639 21.6849 12.4799 21.5057 11.9871 21.0129C11.5209 20.5467 11.3354 19.9095 11.2616 18.9321"
stroke="#9700F4"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
),
color: "#9700F4",
title: "Scout",
description:
"Maps knowledge and explores information, providing essential data for informed decision-making within the maze.",
},
];
return (
<section className="pt-36">
<motion.div
initial={{ y: -100, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
transition={{ duration: 0.5, delay: 1 }}
viewport={{ once: true }}
className="mx-auto container max-w-[1128px] px-8 flex flex-col items-center"
>
<p className="font-serif text-sm uppercase text-center text-[#1DA2FF]">
Agents
</p>
<h2 className="my-4 min-h-[48px] font-offbit text-5xl text-center uppercase text-[#1DA2FF]">
<TypingAnimation startOnView={false}> 4 AGENTS POWERING ALMAZE</TypingAnimation>
</h2>
<p className="mb-12 font-medium text-center text-[#001A2C]">
<span className="text-base">Meet the core agents driving ALMAZE</span>
<br />
</p>
<div ref={containerRef} className="relative flex flex-col items-center">
<div ref={logoRef} className="relative z-10 mb-56 flex">
<Image src={img1} alt="" className="w-[86px]" />
</div>
<AnimatedBeam
containerRef={containerRef}
fromRef={div1Ref}
toRef={logoRef}
duration={3}
curvature={350}
reverse
pathColor="#30A5FF"
gradientStartColor="#30A5FF"
gradientStopColor="#30A5FF"
/>
<AnimatedBeam
containerRef={containerRef}
fromRef={logoRef}
toRef={div2Ref}
duration={3}
reverse
pathColor="#FFBA17"
gradientStartColor="#FFBA17"
gradientStopColor="#FFBA17"
/>
<AnimatedBeam
containerRef={containerRef}
fromRef={logoRef}
toRef={div3Ref}
duration={3}
pathColor="#FF5C3D"
gradientStartColor="#FF5C3D"
gradientStopColor="#FF5C3D"
/>
<AnimatedBeam
containerRef={containerRef}
fromRef={div4Ref}
toRef={logoRef}
duration={3}
curvature={350}
pathColor="#9700F4"
gradientStartColor="#9700F4"
gradientStopColor="#9700F4"
/>
<div className="relative z-10 grid grid-cols-4 gap-4">
{agents.map((agent, index) => {
return (
<div
key={index}
ref={
index === 0
? div1Ref
: index === 1
? div2Ref
: index === 2
? div3Ref
: div4Ref
}
className="p-6 border border-[#eee] bg-white rounded-xl flex flex-col items-center gap-2.5"
>
{agent.icon}
<h3
className="font-offbit text-2xl font-semibold uppercase text-center"
style={{
color: agent.color,
}}
>
{agent.title}
</h3>
<p className="text-sm text-center text-[#001A2C]/75">
{agent.description}
</p>
</div>
);
})}
</div>
</div>
</motion.div>
</section>
);
}

63
app/home/CTABox.tsx Normal file
View File

@ -0,0 +1,63 @@
"use client";
import { TypingAnimation } from "@/components/home/magicui/typing-animation";
import { FlickeringGrid } from "@/components/home/magicui/flickering-grid";
import { motion } from "framer-motion";
import { useRouter } from 'next/navigation';
import { usePrivy } from "@privy-io/react-auth";
import { useEffect } from "react";
import Cookies from 'js-cookie';
export default function CTABox() {
const privy = usePrivy();
const router = useRouter();
// const handleLogin = useCallback(() => privy.login(), [privy]);
useEffect(() => {
if (privy?.ready) {
if (privy.authenticated) {
localStorage.setItem('useremail', privy.user?.email?.address ?? "Guest");
Cookies.set('privy-authenticated', 'true', { path: '/', expires: 1 });
router.push('/dashboard');
}
}
}, [privy.ready, privy.authenticated, router]);
return (
<section>
<div className="mx-auto container max-w-[1128px] px-8">
<motion.div
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
transition={{ duration: 0.5, delay: 0.25 }}
viewport={{ once: true }}
className="relative p-16 bg-[#1DA2FF] rounded-2xl overflow-hidden"
>
<div className="relative z-10 flex flex-col items-center">
<h2 className="font-offbit max-w-[750px] min-h-[96px] text-5xl text-center text-white">
<TypingAnimation startOnView={false}>
SELF EVOLVING AGI THAT HELPS YOU COMPLETE MUNDANE TASKS
</TypingAnimation>
</h2>
<p className="my-4 text-center text-white/75">
The autoagentic AGI. Almaze is a self-evolving AGI made of agents
that collaborate, and build new agents <br /> as needed, in order
to complete tasks for a user.
</p>
</div>
<FlickeringGrid
className="z-0 absolute inset-0 size-full"
squareSize={3}
gridGap={5}
color="#fff"
maxOpacity={0.25}
flickerChance={0.1}
width={1064}
height={346}
/>
</motion.div>
</div>
</section>
);
}

View File

@ -0,0 +1,352 @@
"use client";
import { JSX } from "react/jsx-runtime";
import { TypingAnimation } from "@/components/home/magicui/typing-animation";
import { motion, AnimatePresence } from "framer-motion";
import { useState } from "react";
interface IFeature {
icon: JSX.Element;
title: string;
description: JSX.Element;
}
export default function FeaturesSection() {
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);
const features: IFeature[] = [
{
icon: (
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M21.2559 31.3359C27.5304 30.9189 32.5284 25.8499 32.9397 19.4865C33.0201 18.2412 33.0201 16.9515 32.9397 15.7062C32.5284 9.34269 27.5304 4.27382 21.2559 3.85673C19.1152 3.71444 16.8804 3.71474 14.7441 3.85673C8.46958 4.27382 3.47161 9.34269 3.06036 15.7062C2.97988 16.9515 2.97988 18.2412 3.06036 19.4865C3.21015 21.8041 4.23514 23.95 5.44186 25.762C6.14251 27.0306 5.68011 28.6138 4.95031 29.9968C4.42411 30.994 4.16101 31.4926 4.37226 31.8528C4.58352 32.2129 5.05539 32.2245 5.99914 32.2474C7.8655 32.2929 9.12402 31.7637 10.123 31.027C10.6896 30.6093 10.9729 30.4003 11.1682 30.3763C11.3634 30.3523 11.7477 30.5106 12.516 30.8271C13.2066 31.1115 14.0084 31.287 14.7441 31.3359C16.8804 31.4779 19.1152 31.4782 21.2559 31.3359Z"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinejoin="round"
/>
<path
d="M15.7305 10.5016V13.4701M10.5 15.7522H13.578M22.5346 15.7522H25.6125M22.5346 20.212H25.6125M10.5 20.212H13.578M15.7305 22.5304V25.4989M20.2687 22.5304V25.4989M20.2526 10.5016V13.4701M15.078 22.4529H21.0346C21.8629 22.4529 22.5346 21.7813 22.5346 20.9529V14.9701C22.5346 14.1417 21.8629 13.4701 21.0346 13.4701H15.078C14.2495 13.4701 13.578 14.1417 13.578 14.9701V20.9529C13.578 21.7813 14.2495 22.4529 15.078 22.4529Z"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
/>
</svg>
),
title: "Problem Solver",
description: (
<>
Understands context and nuances<br />
Adapts strategies in real-time<br />
Provides clear, actionable guidance
</>
),
},
{
icon: (
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11.25 6.75024C8.76473 6.75024 6.75 8.76497 6.75 11.2502C6.75 12.1032 6.98733 12.9008 7.39956 13.5805C5.32091 13.9781 3.75 15.8057 3.75 18.0002C3.75 20.1947 5.32091 22.0225 7.39956 22.42M11.25 6.75024C11.25 4.67918 12.9289 3.00024 15 3.00024C17.071 3.00024 18.75 4.67918 18.75 6.75024V9.00024M11.25 6.75024C11.25 7.97711 11.8392 9.06636 12.75 9.75053M7.39956 22.42C6.98733 23.0998 6.75 23.8973 6.75 24.7502C6.75 27.2356 8.76473 29.2502 11.25 29.2502C11.25 31.3213 12.9289 33.0002 15 33.0002C17.071 33.0002 18.75 31.3213 18.75 29.2502V27.0002M7.39956 22.42C7.93422 21.5384 8.7631 20.8552 9.75 20.5063"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M26.25 13.5001H23.25C21.8358 13.5001 21.1287 13.5001 20.6894 13.9395C20.25 14.3788 20.25 15.0859 20.25 16.5001V19.5001C20.25 20.9143 20.25 21.6214 20.6894 22.0608C21.1287 22.5001 21.8358 22.5001 23.25 22.5001H26.25C27.6642 22.5001 28.3713 22.5001 28.8106 22.0608C29.25 21.6214 29.25 20.9143 29.25 19.5001V16.5001C29.25 15.0859 29.25 14.3788 28.8106 13.9395C28.3713 13.5001 27.6642 13.5001 26.25 13.5001Z"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M22.5 22.5001V25.5001M27 22.5001V25.5001M22.5 10.5001V13.5001M27 10.5001V13.5001M20.25 15.7501H17.25M20.25 20.2501H17.25M32.25 15.7501H29.25M32.25 20.2501H29.25"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
),
title: "System Architect",
description: (
<>
Develops scalable solutions<br />
Optimizes performance<br />
Ensures system reliability
</>
),
},
{
icon: (
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M28.5 18.0001C28.5 16.7575 29.5074 15.7501 30.75 15.7501C31.9926 15.7501 33 16.7575 33 18.0001C33 19.2427 31.9926 20.2501 30.75 20.2501C29.5074 20.2501 28.5 19.2427 28.5 18.0001Z"
stroke="#1DA2FF"
strokeWidth="2.25"
/>
<path
d="M3 18.0001C3 16.7575 4.00736 15.7501 5.25 15.7501C6.49264 15.7501 7.5 16.7575 7.5 18.0001C7.5 19.2427 6.49264 20.2501 5.25 20.2501C4.00736 20.2501 3 19.2427 3 18.0001Z"
stroke="#1DA2FF"
strokeWidth="2.25"
/>
<path
d="M20.5606 15.4395C20.1213 15.0001 19.4142 15.0001 18 15.0001C16.5858 15.0001 15.8787 15.0001 15.4394 15.4395M20.5606 15.4395C21 15.8788 21 16.5859 21 18.0001C21 19.4143 21 20.1214 20.5606 20.5608M15.4394 15.4395C15 15.8788 15 16.5859 15 18.0001C15 19.4143 15 20.1214 15.4394 20.5608M15.4394 20.5608C15.8787 21.0001 16.5858 21.0001 18 21.0001C19.4142 21.0001 20.1213 21.0001 20.5606 20.5608"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M31.0606 3.43946C30.6213 3.00012 29.9142 3.00012 28.5 3.00012C27.0858 3.00012 26.3787 3.00012 25.9394 3.43946M31.0606 3.43946C31.5 3.87881 31.5 4.58591 31.5 6.00012C31.5 7.41434 31.5 8.12144 31.0606 8.56079M25.9394 3.43946C25.5 3.87881 25.5 4.58591 25.5 6.00012C25.5 7.41434 25.5 8.12144 25.9394 8.56079M25.9394 8.56079C26.3787 9.00012 27.0858 9.00012 28.5 9.00012C29.9142 9.00012 30.6213 9.00012 31.0606 8.56079"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M10.0607 27.4395C9.62131 27.0001 8.91421 27.0001 7.5 27.0001C6.08579 27.0001 5.37869 27.0001 4.93934 27.4395M10.0607 27.4395C10.5 27.8788 10.5 28.5859 10.5 30.0001C10.5 31.4143 10.5 32.1214 10.0607 32.5608M4.93934 27.4395C4.5 27.8788 4.5 28.5859 4.5 30.0001C4.5 31.4143 4.5 32.1214 4.93934 32.5608M4.93934 32.5608C5.37869 33.0001 6.08579 33.0001 7.5 33.0001C8.91421 33.0001 9.62131 33.0001 10.0607 32.5608"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M7.5 18.0001H15"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M21 18.0001H28.5"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M18 15.0001C18 12.0001 19.25 6.00012 25.5 6.00012"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M18 21.0001C18 24.0001 16.75 30.0001 10.5 30.0001"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
),
title: "Tool Crafter",
description: (
<>
Creates custom solutions<br />
Enhances existing tools<br />
Maintains tool efficiency
</>
),
},
{
icon: (
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M31.9762 10.7122L31.2358 9.42731C30.6759 8.45557 30.396 7.9697 29.9196 7.77595C29.4432 7.58221 28.9044 7.73509 27.8269 8.04085L25.9966 8.5564C25.3087 8.71504 24.5869 8.62504 23.9589 8.30231L23.4535 8.01076C22.9149 7.66577 22.5006 7.15712 22.2712 6.55924L21.7704 5.06317C21.441 4.07314 21.2763 3.57812 20.8842 3.29498C20.4922 3.01184 19.9714 3.01184 18.9298 3.01184H17.2576C16.2162 3.01184 15.6954 3.01184 15.3033 3.29498C14.9113 3.57812 14.7466 4.07314 14.4172 5.06317L13.9163 6.55924C13.687 7.15712 13.2727 7.66577 12.7341 8.01076L12.2287 8.30231C11.6006 8.62504 10.8789 8.71504 10.191 8.5564L8.36062 8.04085C7.28311 7.73509 6.74437 7.58221 6.268 7.77595C5.79163 7.9697 5.51167 8.45557 4.95172 9.42731L4.21135 10.7122C3.68649 11.6231 3.42405 12.0785 3.47499 12.5634C3.52591 13.0482 3.87724 13.4389 4.57989 14.2203L6.12645 15.9493C6.50445 16.4278 6.77281 17.2618 6.77281 18.0117C6.77281 18.7618 6.50454 19.5955 6.12649 20.0742L4.57989 21.8032C3.87724 22.5847 3.52593 22.9753 3.47499 23.4603C3.42405 23.9451 3.68649 24.4005 4.21135 25.3113L4.95171 26.5962C5.51164 27.5679 5.79163 28.0539 6.268 28.2475C6.74437 28.4413 7.28313 28.2885 8.36065 27.9826L10.1909 27.4671C10.8789 27.3084 11.6008 27.3985 12.229 27.7213L12.7342 28.0129C13.2728 28.3579 13.687 28.8664 13.9162 29.4643L14.4172 30.9606C14.7466 31.9506 14.9113 32.4456 15.3033 32.7288C15.6954 33.0118 16.2162 33.0118 17.2576 33.0118H18.9298C19.9714 33.0118 20.4922 33.0118 20.8842 32.7288C21.2763 32.4456 21.441 31.9506 21.7704 30.9606L22.2714 29.4643C22.5006 28.8664 22.9147 28.3579 23.4534 28.0129L23.9586 27.7213C24.5868 27.3985 25.3086 27.3084 25.9966 27.4671L27.8269 27.9826C28.9044 28.2885 29.4432 28.4413 29.9196 28.2475C30.396 28.0539 30.6759 27.5679 31.2358 26.5962L31.9762 25.3113C32.5011 24.4005 32.7634 23.9451 32.7126 23.4603C32.6616 22.9753 32.3103 22.5847 31.6077 21.8032L30.061 20.0742C29.683 19.5955 29.4147 18.7618 29.4147 18.0117C29.4147 17.2618 29.6832 16.4278 30.061 15.9493L31.6077 14.2203C32.3103 13.4389 32.6616 13.0482 32.7126 12.5634C32.7634 12.0785 32.5011 11.6231 31.9762 10.7122Z"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
/>
<path
d="M12.75 24.0001C13.7979 22.1885 15.7566 20.9696 18 20.9696C20.2433 20.9696 22.202 22.1885 23.25 24.0001M21 14.2501C21 15.907 19.6569 17.2501 18 17.2501C16.3431 17.2501 15 15.907 15 14.2501C15 12.5933 16.3431 11.2501 18 11.2501C19.6569 11.2501 21 12.5933 21 14.2501Z"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
/>
</svg>
),
title: "Insight Explorer",
description: (
<>
Researches comprehensively<br />
Validates information<br />
Synthesizes findings
</>
),
},
{
icon: (
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.98257 14.5245C11.6031 8.1181 13.4133 4.91488 15.8975 4.09033C17.264 3.63672 18.7361 3.63672 20.1026 4.09033C22.5867 4.91488 24.3969 8.1181 28.0175 14.5245C31.638 20.9309 33.4482 24.1341 32.9052 26.7441C32.6064 28.1801 31.8704 29.4824 30.8025 30.4647C28.8615 32.2502 25.2411 32.2502 18 32.2502C10.759 32.2502 7.13846 32.2502 5.19745 30.4647C4.12963 29.4824 3.39359 28.1801 3.09484 26.7441C2.55179 24.1341 4.36205 20.9309 7.98257 14.5245Z"
stroke="#1DA2FF"
strokeWidth="2.25"
/>
<path
d="M18.3633 25.5001V19.5001C18.3633 18.793 18.3633 18.4395 18.1435 18.2197C17.9239 18.0001 17.5704 18.0001 16.8633 18.0001"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M17.988 13.5001H18.0015"
stroke="#1DA2FF"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
),
title: "Logic Weaver",
description: (
<>
Analyzes relationships<br />
Builds logical frameworks<br />
Creates innovative solutions
</>
),
},
{
icon: (
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19.5 4.50359C18.7949 4.50012 18.0461 4.50012 17.25 4.50012C10.5325 4.50012 7.17373 4.50012 5.08686 6.58698C3 8.67386 3 12.0326 3 18.7501C3 25.4676 3 28.8264 5.08686 30.9133C7.17373 33.0001 10.5325 33.0001 17.25 33.0001C23.9675 33.0001 27.3263 33.0001 29.4132 30.9133C31.5 28.8264 31.5 25.4676 31.5 18.7501C31.5 17.9541 31.5 17.2053 31.4965 16.5001"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
/>
<path
d="M27.75 3.00012L28.1369 4.04567C28.6442 5.41665 28.8978 6.10215 29.3979 6.60221C29.898 7.10228 30.5835 7.35593 31.9545 7.86324L33 8.25012L31.9545 8.637C30.5835 9.14432 29.898 9.39798 29.3979 9.89804C28.8978 10.3981 28.6442 11.0836 28.1369 12.4546L27.75 13.5001L27.3631 12.4546C26.8558 11.0836 26.6022 10.3981 26.1021 9.89804C25.602 9.39798 24.9165 9.14432 23.5455 8.637L22.5 8.25012L23.5455 7.86324C24.9165 7.35593 25.602 7.10228 26.1021 6.60221C26.6022 6.10215 26.8558 5.41665 27.3631 4.04567L27.75 3.00012Z"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinejoin="round"
/>
<path
d="M10.5 26.2501C13.9976 22.5868 20.4648 22.4143 24 26.2501M20.9927 15.0001C20.9927 17.0712 19.3113 18.7501 17.2372 18.7501C15.1633 18.7501 13.482 17.0712 13.482 15.0001C13.482 12.9291 15.1633 11.2501 17.2372 11.2501C19.3113 11.2501 20.9927 12.9291 20.9927 15.0001Z"
stroke="#1DA2FF"
strokeWidth="2.25"
strokeLinecap="round"
/>
</svg>
),
title: "Integration Architect",
description: (
<>
Coordinates operations<br />
Enhances compatibility<br />
Optimizes workflows
</>
),
},
];
return (
<section id="features" className="pt-36">
<motion.div
initial={{ y: -100, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
transition={{ duration: 0.5, delay: 1 }}
viewport={{ once: true }}
className="mx-auto container max-w-[1128px] px-8 flex flex-col items-center"
>
<p className="font-serif text-sm uppercase text-center text-[#1DA2FF]">
Features
</p>
<h2 className="my-4 max-w-[500px] min-h-[96px] font-offbit text-5xl text-center uppercase text-[#1DA2FF]">
<TypingAnimation startOnView={false}>
ALMAZE IS LOADED WITH FEATURES
</TypingAnimation>
</h2>
<p className="mb-12 font-medium text-center text-[#001A2C]">
Discover the powerful features that make Almaze your ultimate AI companion. <br />
From problem-solving to system optimization, explore what Almaze can do for you.
</p>
<div className="w-full grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{features.map((feature, idx) => (
<div
key={idx}
className="relative group block p-2 h-full w-full"
onMouseEnter={() => setHoveredIndex(idx)}
onMouseLeave={() => setHoveredIndex(null)}
>
<AnimatePresence>
{hoveredIndex === idx && (
<motion.span
className="absolute inset-0 h-full w-full bg-[#1DA2FF]/5 block rounded-xl"
layoutId="hoverBackground"
initial={{ opacity: 0 }}
animate={{
opacity: 1,
transition: { duration: 0.15 },
}}
exit={{
opacity: 0,
transition: { duration: 0.15, delay: 0.2 },
}}
/>
)}
</AnimatePresence>
<div
className="p-8 border-2 border-gray-100 bg-white rounded-2xl flex flex-col gap-4 relative z-20 h-full transition-all duration-300 group-hover:border-[#1DA2FF]/20 group-hover:shadow-lg"
>
<div className="p-3 bg-blue-50 rounded-xl w-fit">
{feature.icon}
</div>
<div className="space-y-3">
<h3 className="text-xl font-offbit text-[#001A2C] tracking-wide">
{feature.title}
</h3>
<div className="h-px w-12 bg-[#1DA2FF]"></div>
<p className="text-sm leading-relaxed text-[#001A2C]/75 font-medium">
{feature.description}
</p>
</div>
</div>
</div>
))}
</div>
</motion.div>
</section>
);
}

102
app/home/Footer.tsx Normal file
View File

@ -0,0 +1,102 @@
"use client";
// import Image from "next/image";
// import logoImg from "@/public/assets/images/brand/logo.svg";
// import Link from "next/link";
import { motion } from "framer-motion";
export default function Footer() {
return (
<footer >
<motion.div
initial={{ y: -50, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
transition={{ duration: 0.5, delay: 0.25 }}
viewport={{ once: true }}
className="relative mx-auto container max-w-[1128px] px-8 flex justify-between items-center"
>
<div className="flex items-center gap-3">
<div
className="w-[42px] h-[2px] rounded-md flex justify-center items-center"
>
{/* <svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.2719 1.58659H18.0832L11.9415 8.60617L19.1667 18.1582H13.5094L9.0784 12.365L4.00833 18.1582H1.1954L7.76457 10.65L0.833374 1.58659H6.6343L10.6395 6.88187L15.2719 1.58659ZM14.2853 16.4756H15.843L5.78787 3.18087H4.11626L14.2853 16.4756Z"
fill="#001A2C"
/>
</svg> */}
</div>
<div
className="w-[42px] h-[2px] rounded-md flex justify-center items-center"
>
{/* <svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M8.4297 10.5294C9.3925 11.085 9.87388 11.3629 10.4026 11.3634C10.9313 11.3638 11.4131 11.0868 12.3769 10.5328L18.5205 7.00132C18.7978 6.84191 18.9688 6.5464 18.9688 6.22649C18.9688 5.90659 18.7978 5.61108 18.5205 5.45166L12.3747 1.9189C11.412 1.36549 10.9306 1.08878 10.4024 1.08899C9.87425 1.0892 9.39311 1.36628 8.43081 1.92044L3.14751 4.96293C3.10835 4.98548 3.08878 4.99674 3.07052 5.00742C1.26579 6.06391 0.150771 7.99271 0.135862 10.0839C0.135712 10.105 0.135712 10.1276 0.135712 10.1728C0.135712 10.2179 0.135712 10.2405 0.135862 10.2616C0.150738 12.3504 1.26327 14.2774 3.06479 15.3347C3.08299 15.3454 3.10253 15.3567 3.14164 15.3793L6.45108 17.2901C8.37948 18.4035 9.34367 18.9602 10.4025 18.9605C11.4614 18.9609 12.4259 18.4048 14.3551 17.2927L17.8487 15.2788C18.8146 14.7219 19.2976 14.4435 19.5628 13.9845C19.828 13.5255 19.828 12.968 19.828 11.853V9.69911C19.828 9.38979 19.6605 9.10474 19.3903 8.95422C19.1287 8.80859 18.81 8.81074 18.5505 8.95991L11.3869 13.0778C10.9063 13.3541 10.666 13.4922 10.4023 13.4923C10.1386 13.4923 9.89816 13.3543 9.41736 13.0784L4.56887 10.2952C4.32601 10.1558 4.20456 10.0861 4.10702 10.0735C3.88465 10.0448 3.67084 10.1694 3.58613 10.377C3.54899 10.4681 3.54973 10.6081 3.55124 10.8881C3.55235 11.0943 3.5529 11.1974 3.57216 11.2922C3.61533 11.5045 3.72702 11.6968 3.89013 11.8394C3.96296 11.9031 4.05222 11.9546 4.23078 12.0577L9.41462 15.0496C9.89668 15.3278 10.1377 15.4669 10.4023 15.467C10.667 15.467 10.9081 15.3281 11.3903 15.0501L17.7442 11.3875C17.9089 11.2926 17.9912 11.2451 18.053 11.2808C18.1147 11.3165 18.1147 11.4115 18.1147 11.6016V12.5786C18.1147 12.8574 18.1147 12.9967 18.0484 13.1115C17.9821 13.2262 17.8614 13.2958 17.6199 13.435L12.3792 16.456C11.4144 17.0121 10.932 17.2902 10.4025 17.2899C9.87293 17.2897 9.39078 17.0112 8.4265 16.4542L3.52339 13.6218C3.50782 13.6128 3.50004 13.6083 3.49278 13.6041C2.46472 13.0034 1.83037 11.9043 1.82442 10.7136C1.82438 10.7052 1.82438 10.6962 1.82438 10.6782V9.78145C1.82438 9.12412 2.17446 8.51659 2.74315 8.18696C3.24567 7.89566 3.86551 7.89508 4.36856 8.18545L8.4297 10.5294Z"
fill="#001A2C"
/>
</svg> */}
</div>
<div
className="w-[42px] h-[2px] rounded-md flex justify-center items-center"
>
{/* <svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_1_799)">
<mask
id="mask0_1_799"
maskUnits="userSpaceOnUse"
x="0"
y="0"
width="20"
height="20"
>
<path
d="M19.4737 0.526611H0.526306V19.474H19.4737V0.526611Z"
fill="white"
/>
</mask>
<g mask="url(#mask0_1_799)">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M9.99999 0.526611C4.76578 0.526611 0.526306 4.76609 0.526306 10.0003C0.526306 14.1924 3.23815 17.7332 7.00394 18.9885C7.47762 19.0713 7.65525 18.7871 7.65525 18.5385C7.65525 18.3135 7.64341 17.5675 7.64341 16.774C5.26315 17.2122 4.64736 16.1938 4.45789 15.6608C4.35131 15.3885 3.88946 14.5477 3.48683 14.3227C3.15525 14.145 2.68157 13.7069 3.47499 13.695C4.22104 13.6832 4.75394 14.3819 4.93157 14.6661C5.7842 16.099 7.14604 15.6964 7.69078 15.4477C7.77367 14.8319 8.02236 14.4175 8.29473 14.1806C6.18683 13.9438 3.9842 13.1266 3.9842 9.50293C3.9842 8.47266 4.35131 7.62003 4.95525 6.95687C4.86052 6.72003 4.52894 5.74898 5.04999 4.44635C5.04999 4.44635 5.84341 4.19766 7.65525 5.4174C8.41315 5.20424 9.21841 5.09766 10.0237 5.09766C10.8289 5.09766 11.6342 5.20424 12.3921 5.4174C14.204 4.18582 14.9974 4.44635 14.9974 4.44635C15.5184 5.74898 15.1868 6.72003 15.0921 6.95687C15.6961 7.62003 16.0631 8.46082 16.0631 9.50293C16.0631 13.1385 13.8487 13.9438 11.7408 14.1806C12.0842 14.4766 12.3803 15.045 12.3803 15.9332C12.3803 17.2003 12.3684 18.2187 12.3684 18.5385C12.3684 18.7871 12.5461 19.0832 13.0198 18.9885C16.7619 17.7332 19.4737 14.1806 19.4737 10.0003C19.4737 4.76609 15.2342 0.526611 9.99999 0.526611Z"
fill="#001A2C"
/>
</g>
</g>
<defs>
<clipPath id="clip0_1_799">
<rect
width="20"
height="20"
fill="white"
transform="translate(0 0.000244141)"
/>
</clipPath>
</defs>
</svg> */}
</div>
</div>
</motion.div>
</footer>
);
}

231
app/home/Header.tsx Normal file
View File

@ -0,0 +1,231 @@
"use client";
import Image from "next/image";
import logoImg from "../../public/assets/images/brand/logo.svg";
import Link from "next/link";
import { motion } from "framer-motion";
import { usePrivy } from "@privy-io/react-auth";
import { useRouter } from 'next/navigation';
import Cookies from "js-cookie";
import { useCallback, useEffect, useState } from "react";
export default function Header() {
const privy = usePrivy();
const router = useRouter();
const [activeSection, setActiveSection] = useState("");
const handleLogin = useCallback(() => privy.login(), [privy]);
useEffect(() => {
if (privy?.ready) {
if (privy.authenticated) {
localStorage.setItem('useremail', privy.user?.email?.address ?? "Guest");
Cookies.set('privy-authenticated', 'true', { path: '/', expires: 1 });
router.push('/dashboard');
}
}
}, [privy.ready, privy.authenticated, router]);
// Smooth scroll function
const scrollToSection = (sectionId: string) => {
const element = document.getElementById(sectionId);
if (element) {
setActiveSection(sectionId);
element.scrollIntoView({
behavior: "smooth",
block: "start",
});
}
};
// Intersection Observer to detect active section
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setActiveSection(entry.target.id);
}
});
},
{ threshold: 0.5 }
);
const sections = ["features", "tokenomics"];
sections.forEach((section) => {
const element = document.getElementById(section);
if (element) observer.observe(element);
});
return () => observer.disconnect();
}, []);
const navItems = [
{ name: "Features", href: "features", isExternal: false },
{ name: "Tokenomics", href: "tokenomics", isExternal: false },
{ name: "Docs", href: "https://almaze.gitbook.io/docs/", isExternal: true },
];
return (
<motion.nav
initial={{ y: -50, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
transition={{ duration: 0.5 }}
viewport={{ once: true }}
className="fixed z-[1000] top-0 left-0 w-full"
>
<div className="mx-auto container max-w-[1128px] pt-8 px-8">
<div className="relative py-5 px-6 border border-[#eee] bg-white/80 backdrop-blur-lg rounded-full flex justify-between items-center">
<Link href={"/"} className="flex">
<motion.div
whileHover={{ scale: 1.05 }}
transition={{ type: "spring", stiffness: 400, damping: 10 }}
>
<Image src={logoImg} alt="" className="w-[36px]" />
</motion.div>
</Link>
<ul className="absolute top-1/2 left-1/2 -translate-y-1/2 -translate-x-1/2 flex items-center gap-4">
{navItems.map((item) => (
<li key={item.href}>
{item.isExternal ? (
<motion.a
href={item.href}
target="_blank"
>
<motion.button
className={`relative py-1.5 px-2 rounded-md text-sm font-medium text-[#001A2C] transition-colors duration-200 ${
activeSection === item.href ? "text-[#1DA2FF]" : ""
}`}
whileHover={{ scale: 1.05 }}
transition={{ type: "spring", stiffness: 400, damping: 10 }}
>
{item.name}
{activeSection === item.href && (
<motion.div
className="absolute bottom-0 left-0 h-0.5 w-full bg-[#1DA2FF]"
layoutId="underline"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.3 }}
/>
)}
</motion.button>
</motion.a>
) : (
<motion.button
onClick={() => scrollToSection(item.href)}
className={`relative py-1.5 px-2 rounded-md text-sm font-medium text-[#001A2C] transition-colors duration-200 ${
activeSection === item.href ? "text-[#1DA2FF]" : ""
}`}
whileHover={{ scale: 1.05 }}
transition={{ type: "spring", stiffness: 400, damping: 10 }}
>
{item.name}
{activeSection === item.href && (
<motion.div
className="absolute bottom-0 left-0 h-0.5 w-full bg-[#1DA2FF]"
layoutId="underline"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.3 }}
/>
)}
</motion.button>
)}
</li>
))}
<li>
<motion.a
href="https://github.com/Almaze-Labs"
target="_blank"
rel="noopener noreferrer"
className="py-1.5 px-2 hover:bg-[#001A2C]/5 rounded-md flex items-center gap-1.5 text-sm font-medium text-[#001A2C]"
whileHover={{ scale: 1.05 }}
transition={{ type: "spring", stiffness: 400, damping: 10 }}
>
<svg
width="19"
height="20"
viewBox="0 0 19 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<mask
id="mask0_1_744"
maskUnits="userSpaceOnUse"
x="0"
y="1"
width="19"
height="18"
>
<path d="M18.5 1H0.5V19H18.5V1Z" fill="white" />
</mask>
<g mask="url(#mask0_1_744)">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M9.5 1C4.5275 1 0.5 5.0275 0.5 10C0.5 13.9825 3.07625 17.3463 6.65375 18.5388C7.10375 18.6175 7.2725 18.3475 7.2725 18.1113C7.2725 17.8975 7.26125 17.1888 7.26125 16.435C5 16.8513 4.415 15.8838 4.235 15.3775C4.13375 15.1188 3.695 14.32 3.3125 14.1063C2.9975 13.9375 2.5475 13.5213 3.30125 13.51C4.01 13.4988 4.51625 14.1625 4.685 14.4325C5.495 15.7938 6.78875 15.4113 7.30625 15.175C7.385 14.59 7.62125 14.1963 7.88 13.9713C5.8775 13.7463 3.785 12.97 3.785 9.5275C3.785 8.54875 4.13375 7.73875 4.7075 7.10875C4.6175 6.88375 4.3025 5.96125 4.7975 4.72375C4.7975 4.72375 5.55125 4.4875 7.2725 5.64625C7.9925 5.44375 8.7575 5.3425 9.5225 5.3425C10.2875 5.3425 11.0525 5.44375 11.7725 5.64625C13.4938 4.47625 14.2475 4.72375 14.2475 4.72375C14.7425 5.96125 14.4275 6.88375 14.3375 7.10875C14.9113 7.73875 15.26 8.5375 15.26 9.5275C15.26 12.9813 13.1563 13.7463 11.1538 13.9713C11.48 14.2525 11.7613 14.7925 11.7613 15.6363C11.7613 16.84 11.75 17.8075 11.75 18.1113C11.75 18.3475 11.9188 18.6288 12.3688 18.5388C15.9238 17.3463 18.5 13.9713 18.5 10C18.5 5.0275 14.4725 1 9.5 1Z"
fill="#001A2C"
/>
</g>
</svg>
</motion.a>
</li>
</ul>
<div className="flex items-center gap-3">
<motion.a
href="https://x.com/almaze_ai"
target="_blank"
rel="noopener noreferrer"
whileHover={{ scale: 1.05 }}
transition={{ type: "spring", stiffness: 400, damping: 10 }}
className="w-[42px] h-[42px] border border-[#001A2C]/10 rounded-md flex justify-center items-center hover:bg-[#001A2C]/5"
>
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.2719 1.58659H18.0832L11.9415 8.60617L19.1667 18.1582H13.5094L9.0784 12.365L4.00833 18.1582H1.1954L7.76457 10.65L0.833374 1.58659H6.6343L10.6395 6.88187L15.2719 1.58659ZM14.2853 16.4756H15.843L5.78787 3.18087H4.11626L14.2853 16.4756Z"
fill="#001A2C"
/>
</svg>
</motion.a>
<div className="h-[42px] px-1.5 border border-[#001A2C]/10 rounded-md flex items-center">
<motion.button
className="py-1.5 px-5 bg-[#1DA2FF] rounded-full flex items-center gap-2 text-sm font-medium text-white"
onClick={handleLogin}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
transition={{ type: "spring", stiffness: 400, damping: 10 }}
>
Try Almaze{" "}
<svg
width="4"
height="8"
viewBox="0 0 4 8"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0.5 7L3.5 4L0.5 1"
stroke="white"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</motion.button>
</div>
</div>
</div>
</div>
</motion.nav>
);
}

217
app/home/HeroSection.tsx Normal file
View File

@ -0,0 +1,217 @@
"use client";
import Image from "next/image";
import { cn } from "@/lib/utils";
import { useCallback, useEffect, useState } from "react";
import { usePrivy } from "@privy-io/react-auth";
import { useRouter } from 'next/navigation';
import { TypingAnimation } from "@/components/home/magicui/typing-animation";
import { InteractiveGridPattern } from "@/components/home/magicui/interactive-grid-pattern";
import { motion } from "framer-motion";
import axios from "axios";
import Cookies from "js-cookie";
// import bgImg from "@/assets/images/hero-section-bg.png";
import img1 from "@/public/assets/images/hero-section-1.png";
export default function HeroSection() {
const [isCopied, setIsCopied] = useState<boolean>(false);
const privy = usePrivy();
const router = useRouter();
const handleLogin = useCallback(() => privy.login(), [privy]);
const [CA, setCA] = useState("");
useEffect(() => {
axios.get("https://catools.dev3vds1.link/get/almaze-labs")
.then(response => {
const data = response.data
if (data) {
// console.log(`this is the data addr : ${data.address}`)
setCA(data[0].address);
}
})
.catch(error => {
console.error("Error fetching CA:", error);
});
}, []);
useEffect(() => {
if (privy?.ready) {
if (privy.authenticated) {
localStorage.setItem('useremail', privy.user?.email?.address ?? "Guest");
Cookies.set('privy-authenticated', 'true', { path: '/', expires: 1 });
router.push('/dashboard');
}
}
}, [privy.ready, privy.authenticated, router]);
useEffect(() => {
if (isCopied) {
setTimeout(() => {
setIsCopied(false);
}, 3000);
}
});
return (
<section className="relative pt-56">
<div className="relative z-10 mx-auto container max-w-[1128px] px-8 flex flex-col items-center">
<motion.div
initial={{ y: -50, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
transition={{ duration: 0.5, delay: 0.25 }}
viewport={{ once: true }}
className="mb-6 h-[42px] px-1.5 border border-white/50 rounded-md flex items-center"
>
<button
onClick={() => {
navigator.clipboard.writeText(
CA
);
setIsCopied(true);
}}
className="py-1.5 px-5 bg-[#001A2C] rounded-full flex items-center gap-2 text-sm font-medium text-white"
>
CA :{" "}
{isCopied
? "Copied!"
: CA}
<svg
width="16"
height="17"
viewBox="0 0 16 17"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_1_771)">
<path
d="M5.68437 5.91912V4.13412C5.68437 3.42005 5.68437 3.06301 5.82334 2.79028C5.94558 2.55037 6.14063 2.35532 6.38054 2.23308C6.65327 2.09412 7.01031 2.09412 7.72437 2.09412H12.5694C13.2834 2.09412 13.6405 2.09412 13.9132 2.23308C14.1531 2.35532 14.3482 2.55037 14.4704 2.79028C14.6094 3.06301 14.6094 3.42005 14.6094 4.13412V8.97912C14.6094 9.69318 14.6094 10.0502 14.4704 10.323C14.3482 10.5629 14.1531 10.7579 13.9132 10.8801C13.6405 11.0191 13.2834 11.0191 12.5694 11.0191H10.7844M3.89937 14.8441H8.74437C9.45844 14.8441 9.8155 14.8441 10.0882 14.7051C10.3281 14.5829 10.5232 14.3879 10.6454 14.148C10.7844 13.8752 10.7844 13.5182 10.7844 12.8041V7.95912C10.7844 7.24505 10.7844 6.88801 10.6454 6.61528C10.5232 6.37537 10.3281 6.18032 10.0882 6.05808C9.8155 5.91912 9.45844 5.91912 8.74437 5.91912H3.89937C3.18531 5.91912 2.82827 5.91912 2.55554 6.05808C2.31563 6.18032 2.12058 6.37537 1.99834 6.61528C1.85937 6.88801 1.85938 7.24505 1.85938 7.95912V12.8041C1.85938 13.5182 1.85937 13.8752 1.99834 14.148C2.12058 14.3879 2.31563 14.5829 2.55554 14.7051C2.82827 14.8441 3.1853 14.8441 3.89937 14.8441Z"
stroke="white"
strokeWidth="1.275"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_1_771">
<rect
width="15.3"
height="15.3"
fill="white"
transform="translate(0.584351 0.81897)"
/>
</clipPath>
</defs>
</svg>
</button>
</motion.div>
<motion.h1
initial={{ y: -50, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
transition={{ duration: 0.5, delay: 0.5 }}
viewport={{ once: true }}
className="mb-3 max-w-[950px] min-h-[120px] font-offbit text-6xl text-center uppercase text-[#1DA2FF]"
>
<TypingAnimation startOnView = {false}>
SELF EVOLVING AGI THAT HELPS YOU COMPLETE MUNDANE TASKS
</TypingAnimation>
</motion.h1>
<motion.p
initial={{ y: -50, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
transition={{ duration: 0.5, delay: 0.75 }}
viewport={{ once: true }}
className="mb-6 text-lg font-medium text-center text-[#001A2C]"
>
The autoagentic AGI. Almaze is a self-evolving AGI made of agents that
collaborate, and build new agents <br /> as needed, in order to
complete tasks for a user.
</motion.p>
<motion.div
initial={{ y: -50, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
transition={{ duration: 0.5, delay: 1 }}
viewport={{ once: true }}
className="mb-14 flex items-center gap-4"
>
<div className="h-[42px] px-1.5 border border-[#001A2C]/10 rounded-md flex items-center">
<button className="py-1.5 px-5 bg-[#1DA2FF] rounded-full flex items-center gap-2 text-sm font-medium text-white" onClick={handleLogin}>
Try Almaze{" "}
<svg
width="4"
height="8"
viewBox="0 0 4 8"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0.5 7L3.5 4L0.5 1"
stroke="white"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</button>
</div>
<div className="h-[42px] px-1.5 border border-[#001A2C]/10 rounded-md flex items-center">
<a href="https://almaze.gitbook.io/docs" target="_blank" >
<button className="py-1.5 px-5 bg-[#001A2C] rounded-full flex items-center gap-2 text-sm font-medium text-white">
<svg
width="15"
height="15"
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_1_784)">
<path
d="M6.3921 8.00633C7.05703 8.3901 7.38949 8.58199 7.75463 8.58231C8.11974 8.58263 8.45254 8.39133 9.11815 8.00871L13.361 5.56978C13.5526 5.45968 13.6706 5.2556 13.6706 5.03466C13.6706 4.81373 13.5526 4.60964 13.361 4.49954L9.11662 2.05973C8.45173 1.67753 8.11928 1.48643 7.75452 1.48657C7.38974 1.48671 7.05746 1.67807 6.39286 2.06079L2.74409 4.16201C2.71704 4.17759 2.70352 4.18536 2.69091 4.19274C1.44452 4.92238 0.674463 6.25445 0.664167 7.69867C0.664062 7.71327 0.664062 7.72886 0.664062 7.76008C0.664062 7.79125 0.664062 7.80683 0.664166 7.82141C0.67444 9.26401 1.44278 10.5948 2.68695 11.325C2.69953 11.3324 2.71302 11.3402 2.74003 11.3558L5.02562 12.6754C6.35742 13.4444 7.02331 13.8288 7.75458 13.8291C8.48584 13.8294 9.15201 13.4453 10.4843 12.6773L12.8971 11.2864C13.5642 10.9018 13.8977 10.7095 14.0809 10.3925C14.2641 10.0755 14.2641 9.69052 14.2641 8.92048V7.43294C14.2641 7.21931 14.1484 7.02245 13.9617 6.9185C13.7811 6.81792 13.561 6.81941 13.3818 6.92243L8.43443 9.76631C8.10251 9.95714 7.93653 10.0525 7.75439 10.0526C7.57228 10.0526 7.40625 9.95733 7.0742 9.76674L3.72571 7.84463C3.55798 7.74835 3.47411 7.7002 3.40675 7.69151C3.25318 7.6717 3.10551 7.75772 3.04701 7.9011C3.02136 7.96399 3.02187 8.06068 3.02291 8.25408C3.02367 8.39648 3.02406 8.46766 3.03736 8.53313C3.06717 8.67978 3.14431 8.81257 3.25696 8.91107C3.30726 8.95505 3.3689 8.99065 3.49222 9.06181L7.07231 11.1281C7.40523 11.3202 7.57168 11.4163 7.75446 11.4164C7.93725 11.4164 8.10376 11.3204 8.43677 11.1285L12.8249 8.59899C12.9386 8.53341 12.9955 8.50064 13.0382 8.52527C13.0808 8.54992 13.0808 8.61556 13.0808 8.74687V9.42158C13.0808 9.6141 13.0808 9.71034 13.035 9.7896C12.9892 9.86884 12.9058 9.91693 12.739 10.0131L9.11971 12.0994C8.45339 12.4835 8.12023 12.6755 7.75454 12.6754C7.38883 12.6752 7.05584 12.4829 6.38989 12.0981L3.00368 10.1421C2.99293 10.1359 2.98755 10.1327 2.98254 10.1298C2.27254 9.71493 1.83444 8.95592 1.83033 8.13359C1.8303 8.12779 1.8303 8.12158 1.8303 8.10915V7.4898C1.8303 7.03584 2.07207 6.61626 2.46483 6.38861C2.81188 6.18743 3.23996 6.18703 3.58737 6.38756L6.3921 8.00633Z"
fill="white"
/>
</g>
<defs>
<clipPath id="clip0_1_784">
<rect
width="13.8125"
height="13.8125"
fill="white"
transform="translate(0.570312 0.734619)"
/>
</clipPath>
</defs>
</svg>
Open Gitbook
</button>
</a>
</div>
</motion.div>
<motion.div
initial={{ y: 50, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
transition={{ duration: 0.5, delay: 1.25 }}
viewport={{ once: true }}
className="w-full"
>
<Image src={img1} alt="" className="w-full" />
</motion.div>
</div>
{/* <Image src={bgImg} alt="" className="absolute top-0 left-0 w-full" /> */}
<InteractiveGridPattern
className={cn(
"[mask-image:radial-gradient(1000px_circle_at_center,transparent,white)]",
"absolute -top-[350px] left-0 w-full h-full skew-y-6"
)}
/>
</section>
);
}

291
app/home/RoadmapSection.tsx Normal file
View File

@ -0,0 +1,291 @@
"use client";
import { TypingAnimation } from "@/components/home/magicui/typing-animation";
import Image from "next/image";
import img1 from "@/public/assets/images/roadmap-section-1.png";
import Link from "next/link";
import { FlickeringGrid } from "@/components/home/magicui/flickering-grid";
import { motion } from "framer-motion";
export default function RoadmapSection() {
return (
<section className="py-36">
<motion.div
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
transition={{ duration: 0.5, delay: 1 }}
viewport={{ once: true }}
className="mx-auto container max-w-[1128px] px-8"
>
<div className="relative bg-[#001A2C] rounded-xl">
<div className="relative z-10">
<div className="p-16 pb-8 grid grid-cols-2 items-center gap-12">
<div className="flex flex-col items-start">
<p className="mb-3 font-serif text-sm uppercase text-white">
Roadmap
</p>
<h2 className="mb-1.5 min-h-[80px] font-offbit text-4xl uppercase text-white">
<TypingAnimation startOnView={false}>
WE HAVE BIG PLANS FOR ALMAZE IN 2025
</TypingAnimation>
</h2>
<p className="mb-5 text-white/75">
Discover our strategic roadmap for 2025, outlining key phases and milestones designed to drive innovation and growth for ALMAZE.
</p>
<div className="h-[42px] px-1.5 border border-white/50 rounded-md flex items-center">
<a href="https://almaze.gitbook.io/docs" target="_blank">
<button className="py-1.5 px-5 bg-white rounded-full flex items-center gap-2 text-sm font-medium text-[#001A2C]">
<svg
width="15"
height="15"
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
href="https://almaze.gitbook.io/docs"
>
<g clipPath="url(#clip0_1_784)">
<path
d="M6.3921 8.00633C7.05703 8.3901 7.38949 8.58199 7.75463 8.58231C8.11974 8.58263 8.45254 8.39133 9.11815 8.00871L13.361 5.56978C13.5526 5.45968 13.6706 5.2556 13.6706 5.03466C13.6706 4.81373 13.5526 4.60964 13.361 4.49954L9.11662 2.05973C8.45173 1.67753 8.11928 1.48643 7.75452 1.48657C7.38974 1.48671 7.05746 1.67807 6.39286 2.06079L2.74409 4.16201C2.71704 4.17759 2.70352 4.18536 2.69091 4.19274C1.44452 4.92238 0.674463 6.25445 0.664167 7.69867C0.664062 7.71327 0.664062 7.72886 0.664062 7.76008C0.664062 7.79125 0.664062 7.80683 0.664166 7.82141C0.67444 9.26401 1.44278 10.5948 2.68695 11.325C2.69953 11.3324 2.71302 11.3402 2.74003 11.3558L5.02562 12.6754C6.35742 13.4444 7.02331 13.8288 7.75458 13.8291C8.48584 13.8294 9.15201 13.4453 10.4843 12.6773L12.8971 11.2864C13.5642 10.9018 13.8977 10.7095 14.0809 10.3925C14.2641 10.0755 14.2641 9.69052 14.2641 8.92048V7.43294C14.2641 7.21931 14.1484 7.02245 13.9617 6.9185C13.7811 6.81792 13.561 6.81941 13.3818 6.92243L8.43443 9.76631C8.10251 9.95714 7.93653 10.0525 7.75439 10.0526C7.57228 10.0526 7.40625 9.95733 7.0742 9.76674L3.72571 7.84463C3.55798 7.74835 3.47411 7.7002 3.40675 7.69151C3.25318 7.6717 3.10551 7.75772 3.04701 7.9011C3.02136 7.96399 3.02187 8.06068 3.02291 8.25408C3.02367 8.39648 3.02406 8.46766 3.03736 8.53313C3.06717 8.67978 3.14431 8.81257 3.25696 8.91107C3.30726 8.95505 3.3689 8.99065 3.49222 9.06181L7.07231 11.1281C7.40523 11.3202 7.57168 11.4163 7.75446 11.4164C7.93725 11.4164 8.10376 11.3204 8.43677 11.1285L12.8249 8.59899C12.9386 8.53341 12.9955 8.50064 13.0382 8.52527C13.0808 8.54992 13.0808 8.61556 13.0808 8.74687V9.42158C13.0808 9.6141 13.0808 9.71034 13.035 9.7896C12.9892 9.86884 12.9058 9.91693 12.739 10.0131L9.11971 12.0994C8.45339 12.4835 8.12023 12.6755 7.75454 12.6754C7.38883 12.6752 7.05584 12.4829 6.38989 12.0981L3.00368 10.1421C2.99293 10.1359 2.98755 10.1327 2.98254 10.1298C2.27254 9.71493 1.83444 8.95592 1.83033 8.13359C1.8303 8.12779 1.8303 8.12158 1.8303 8.10915V7.4898C1.8303 7.03584 2.07207 6.61626 2.46483 6.38861C2.81188 6.18743 3.23996 6.18703 3.58737 6.38756L6.3921 8.00633Z"
fill="#001A2C"
/>
</g>
<defs>
<clipPath id="clip0_1_784">
<rect
width="13.8125"
height="13.8125"
fill="white"
transform="translate(0.570312 0.734619)"
/>
</clipPath>
</defs>
</svg>
Open Gitbook
</button>
</a>
</div>
</div>
<div className="flex">
<Image src={img1} alt="" className="w-full" />
</div>
</div>
<div className="px-16 grid grid-cols-4">
<div className="pb-6 pr-6 border-r border-dashed border-white/50">
<svg
width="27"
height="27"
viewBox="0 0 27 27"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12.015 2.36791C12.4661 2.10614 12.9784 1.96826 13.5 1.96826C14.0216 1.96826 14.5339 2.10614 14.985 2.36791L14.9861 2.36904L22.4235 6.64404C22.8755 6.90617 23.2505 7.28268 23.5107 7.73571C23.771 8.18874 23.9074 8.70231 23.9063 9.22479V17.7782C23.9052 18.2997 23.7677 18.812 23.5077 19.264C23.2476 19.7161 22.8738 20.0924 22.4235 20.3555L22.4201 20.3578L14.9861 24.6317H14.9839C14.5329 24.8932 14.0208 25.031 13.4994 25.031C12.9781 25.031 12.466 24.8932 12.015 24.6317H12.0139L4.57989 20.3567H4.57651C4.1243 20.0945 3.74915 19.7179 3.48885 19.2646C3.22854 18.8113 3.09227 18.2975 3.09376 17.7748V9.22254C3.09487 8.70097 3.23228 8.18875 3.49237 7.73666C3.75246 7.28457 4.12619 6.9083 4.57651 6.64517L4.57989 6.64292L12.015 2.36791ZM15.1875 8.99979C15.1876 8.84413 15.1446 8.69148 15.0633 8.55874C14.982 8.426 14.8656 8.31833 14.7269 8.24764C14.5882 8.17696 14.4327 8.14602 14.2775 8.15825C14.1223 8.17047 13.9735 8.22539 13.8476 8.31692L10.7539 10.5669C10.5728 10.6985 10.4514 10.8966 10.4163 11.1177C10.3813 11.3388 10.4356 11.5648 10.5671 11.7459C10.6987 11.927 10.8969 12.0484 11.118 12.0835C11.3391 12.1185 11.565 12.0642 11.7461 11.9327L13.5011 10.6569V17.9998C13.5011 18.2236 13.59 18.4382 13.7483 18.5964C13.9065 18.7546 14.1211 18.8435 14.3449 18.8435C14.5687 18.8435 14.7833 18.7546 14.9415 18.5964C15.0997 18.4382 15.1886 18.2236 15.1886 17.9998L15.1875 8.99979Z"
fill="#1DA2FF"
/>
</svg>
<p className="mt-3 mb-2 text-xs font-medium text-[#1DA2FF]">
Q1 2025
</p>
<h3 className="mb-3 text-lg font-semibold text-white">
Phase 01
</h3>
<p className="text-sm text-white/75">
In this phase, we will focus on enhancing our core features and improving user experience to ensure a seamless interaction with our platform.
</p>
</div>
<div className="pb-6 px-6 border-r border-dashed border-white/50">
<svg
width="28"
height="27"
viewBox="0 0 28 27"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12.265 2.36791C12.7161 2.10614 13.2284 1.96826 13.75 1.96826C14.2716 1.96826 14.7839 2.10614 15.235 2.36791L15.2361 2.36904L22.6735 6.64404C23.1255 6.90617 23.5005 7.28268 23.7607 7.73571C24.021 8.18874 24.1574 8.70231 24.1563 9.22479V17.7782C24.1552 18.2997 24.0177 18.812 23.7577 19.264C23.4976 19.7161 23.1238 20.0924 22.6735 20.3555L22.6701 20.3578L15.2361 24.6317H15.2339C14.7829 24.8932 14.2708 25.031 13.7494 25.031C13.2281 25.031 12.716 24.8932 12.265 24.6317H12.2639L4.82989 20.3567H4.82651C4.3743 20.0945 3.99915 19.7179 3.73885 19.2646C3.47854 18.8113 3.34227 18.2975 3.34376 17.7748V9.22254C3.34487 8.70097 3.48228 8.18875 3.74237 7.73666C4.00246 7.28457 4.37619 6.9083 4.82651 6.64517L4.82989 6.64292L12.265 2.36791ZM11.7813 11.6289C11.7813 10.9775 12.0141 10.5534 12.3134 10.2845C12.6273 10.0022 13.0671 9.84354 13.534 9.84354C13.9998 9.84354 14.4408 10.001 14.7546 10.2845C15.0528 10.5534 15.2856 10.9775 15.2856 11.6289C15.2856 12.5987 14.6511 13.6213 13.6094 14.6709C12.8309 15.4562 11.9399 16.148 11.14 16.7679C10.8858 16.9659 10.6394 17.1572 10.4088 17.3417C10.2724 17.4511 10.1734 17.6001 10.1254 17.7682C10.0774 17.9363 10.0828 18.1151 10.1409 18.28C10.1989 18.4449 10.3068 18.5876 10.4495 18.6886C10.5922 18.7896 10.7627 18.8437 10.9375 18.8435H16.5625C16.7863 18.8435 17.0009 18.7546 17.1591 18.5964C17.3174 18.4382 17.4063 18.2236 17.4063 17.9998C17.4063 17.776 17.3174 17.5614 17.1591 17.4032C17.0009 17.2449 16.7863 17.156 16.5625 17.156H13.3675C13.8546 16.7544 14.353 16.3179 14.8075 15.8589C15.9123 14.7452 16.9731 13.304 16.9731 11.6289C16.9731 10.5264 16.5569 9.63767 15.883 9.03017C15.2226 8.43616 14.3654 8.15604 13.534 8.15604C12.7015 8.15604 11.8443 8.43616 11.1839 9.03017C10.5089 9.63767 10.0938 10.5264 10.0938 11.6289C10.0938 11.8527 10.1827 12.0673 10.3409 12.2255C10.4991 12.3838 10.7137 12.4727 10.9375 12.4727C11.1613 12.4727 11.3759 12.3838 11.5341 12.2255C11.6924 12.0673 11.7813 11.8527 11.7813 11.6289Z"
fill="#1DA2FF"
/>
</svg>
<p className="mt-3 mb-2 text-xs font-medium text-[#1DA2FF]">
Q2 2025
</p>
<h3 className="mb-3 text-lg font-semibold text-white">
Phase 02
</h3>
<p className="text-sm text-white/75">
During this phase, we will expand our platform&apos;s capabilities by integrating advanced analytics and machine learning features to provide deeper insights and more personalized experiences for our users.
</p>
</div>
<div className="pb-6 px-6 border-r border-dashed border-white/50">
<svg
width="28"
height="27"
viewBox="0 0 28 27"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12.265 2.36791C12.7161 2.10614 13.2284 1.96826 13.75 1.96826C14.2716 1.96826 14.7839 2.10614 15.235 2.36791L15.2361 2.36904L22.6735 6.64404C23.1255 6.90617 23.5005 7.28268 23.7607 7.73571C24.021 8.18874 24.1574 8.70231 24.1563 9.22479V17.7782C24.1552 18.2997 24.0177 18.812 23.7577 19.264C23.4976 19.7161 23.1238 20.0924 22.6735 20.3555L22.6701 20.3578L15.2361 24.6317H15.2339C14.7829 24.8932 14.2708 25.031 13.7494 25.031C13.2281 25.031 12.716 24.8932 12.265 24.6317H12.2639L4.82989 20.3567H4.82651C4.3743 20.0945 3.99915 19.7179 3.73885 19.2646C3.47854 18.8113 3.34227 18.2975 3.34376 17.7748V9.22254C3.34487 8.70097 3.48228 8.18875 3.74237 7.73666C4.00246 7.28457 4.37619 6.9083 4.82651 6.64517L4.82989 6.64292L12.265 2.36791ZM11.7813 11.6289C11.7813 10.9775 12.0141 10.5534 12.3134 10.2845C12.6273 10.0022 13.0671 9.84354 13.534 9.84354C13.9998 9.84354 14.4408 10.001 14.7546 10.2845C15.0528 10.5534 15.2856 10.9775 15.2856 11.6289C15.2856 12.5987 14.6511 13.6213 13.6094 14.6709C12.8309 15.4562 11.9399 16.148 11.14 16.7679C10.8858 16.9659 10.6394 17.1572 10.4088 17.3417C10.2724 17.4511 10.1734 17.6001 10.1254 17.7682C10.0774 17.9363 10.0828 18.1151 10.1409 18.28C10.1989 18.4449 10.3068 18.5876 10.4495 18.6886C10.5922 18.7896 10.7627 18.8437 10.9375 18.8435H16.5625C16.7863 18.8435 17.0009 18.7546 17.1591 18.5964C17.3174 18.4382 17.4063 18.2236 17.4063 17.9998C17.4063 17.776 17.3174 17.5614 17.1591 17.4032C17.0009 17.2449 16.7863 17.156 16.5625 17.156H13.3675C13.8546 16.7544 14.353 16.3179 14.8075 15.8589C15.9123 14.7452 16.9731 13.304 16.9731 11.6289C16.9731 10.5264 16.5569 9.63767 15.883 9.03017C15.2226 8.43616 14.3654 8.15604 13.534 8.15604C12.7015 8.15604 11.8443 8.43616 11.1839 9.03017C10.5089 9.63767 10.0938 10.5264 10.0938 11.6289C10.0938 11.8527 10.1827 12.0673 10.3409 12.2255C10.4991 12.3838 10.7137 12.4727 10.9375 12.4727C11.1613 12.4727 11.3759 12.3838 11.5341 12.2255C11.6924 12.0673 11.7813 11.8527 11.7813 11.6289Z"
fill="#1DA2FF"
/>
</svg>
<p className="mt-3 mb-2 text-xs font-medium text-[#1DA2FF]">
Q3 2025
</p>
<h3 className="mb-3 text-lg font-semibold text-white">
Phase 03
</h3>
<p className="text-sm text-white/75">
In this phase, we will focus on expanding our market reach and establishing strategic partnerships to drive growth and enhance our platform&apos;s value proposition.
</p>
</div>
<div className="pb-6 pl-6">
<svg
width="28"
height="27"
viewBox="0 0 28 27"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12.765 2.36791C13.2161 2.10614 13.7284 1.96826 14.25 1.96826C14.7716 1.96826 15.2839 2.10614 15.735 2.36791L15.7361 2.36904L23.1735 6.64404C23.6255 6.90617 24.0005 7.28268 24.2607 7.73571C24.521 8.18874 24.6574 8.70231 24.6563 9.22479V17.7782C24.6552 18.2997 24.5177 18.812 24.2577 19.264C23.9976 19.7161 23.6238 20.0924 23.1735 20.3555L23.1701 20.3578L15.7361 24.6317H15.7339C15.2829 24.8932 14.7708 25.031 14.2494 25.031C13.7281 25.031 13.216 24.8932 12.765 24.6317H12.7639L5.32989 20.3567H5.32651C4.8743 20.0945 4.49915 19.7179 4.23885 19.2646C3.97854 18.8113 3.84227 18.2975 3.84376 17.7748V9.22254C3.84487 8.70097 3.98228 8.18875 4.24237 7.73666C4.50246 7.28457 4.87619 6.9083 5.32651 6.64517L5.32989 6.64292L12.765 2.36791ZM15.7193 9.22591C15.7506 9.11868 15.7603 9.00629 15.7478 8.89528C15.7354 8.78426 15.701 8.67682 15.6467 8.57919C15.5924 8.48157 15.5192 8.3957 15.4315 8.32656C15.3437 8.25743 15.2431 8.20641 15.1355 8.17647C15.0279 8.14653 14.9154 8.13826 14.8045 8.15214C14.6937 8.16602 14.5867 8.20178 14.4898 8.25733C14.3928 8.31289 14.3079 8.38713 14.2399 8.47577C14.1719 8.5644 14.1222 8.66566 14.0936 8.77366C13.6628 10.3239 12.7886 11.7774 11.9978 12.8619C11.5851 13.4272 11.14 13.9681 10.6646 14.4819C10.6378 14.5102 10.6108 14.5384 10.5836 14.5663L10.5634 14.5865L10.5589 14.591C10.441 14.7091 10.3607 14.8595 10.3282 15.0232C10.2958 15.1868 10.3126 15.3565 10.3765 15.5106C10.4405 15.6647 10.5487 15.7964 10.6875 15.8891C10.8263 15.9817 10.9894 16.0311 11.1563 16.031H14.5313V17.9998C14.5313 18.2236 14.6202 18.4382 14.7784 18.5964C14.9366 18.7546 15.1512 18.8435 15.375 18.8435C15.5988 18.8435 15.8134 18.7546 15.9716 18.5964C16.1299 18.4382 16.2188 18.2236 16.2188 17.9998V16.031H16.7813C17.005 16.031 17.2196 15.9421 17.3779 15.7839C17.5361 15.6257 17.625 15.4111 17.625 15.1873C17.625 14.9635 17.5361 14.7489 17.3779 14.5907C17.2196 14.4324 17.005 14.3435 16.7813 14.3435H16.2188V13.4998C16.2188 13.276 16.1299 13.0614 15.9716 12.9032C15.8134 12.7449 15.5988 12.656 15.375 12.656C15.1512 12.656 14.9366 12.7449 14.7784 12.9032C14.6202 13.0614 14.5313 13.276 14.5313 13.4998V14.3435H12.9945C13.1126 14.1917 13.2364 14.0285 13.3613 13.8564C14.2106 12.692 15.2119 11.0507 15.7193 9.22591Z"
fill="#1DA2FF"
/>
</svg>
<p className="mt-3 mb-2 text-xs font-medium text-[#1DA2FF]">
Q4 2025
</p>
<h3 className="mb-3 text-lg font-semibold text-white">
Phase 04
</h3>
<p className="text-sm text-white/75">
This phase will focus on launching new features and services, enhancing our platform&apos;s scalability, and ensuring robust security measures to protect user data.
</p>
</div>
</div>
<div className="border-t border-dashed border-white/50 py-6 px-16 flex justify-between items-center">
<p className="text-white/75">Learn more about ALMAZE here</p>
<div className="flex items-center gap-3">
<Link
href={"https://x.com/almaze_ai"}
target="_blank"
className="px-4 h-[42px] border border-white/25 rounded-md flex justify-center items-center gap-2.5 text-sm font-medium text-white"
>
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.2718 1.58643H18.0831L11.9413 8.606L19.1666 18.1581H13.5093L9.07828 12.3648L4.00821 18.1581H1.19528L7.76445 10.6498L0.833252 1.58643H6.63418L10.6394 6.8817L15.2718 1.58643ZM14.2852 16.4754H15.8429L5.78775 3.1807H4.11614L14.2852 16.4754Z"
fill="white"
/>
</svg>
Twitter/X
</Link>
<Link
href={"https://almaze.gitbook.io/docs"}
target="_blank"
className="px-4 h-[42px] border border-white/25 rounded-md flex justify-center items-center gap-2.5 text-sm font-medium text-white"
>
Gitbook
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M8.4297 10.5294C9.3925 11.085 9.87388 11.3629 10.4026 11.3634C10.9313 11.3638 11.4131 11.0868 12.3769 10.5328L18.5205 7.00132C18.7978 6.84191 18.9688 6.5464 18.9688 6.22649C18.9688 5.90659 18.7978 5.61108 18.5205 5.45166L12.3747 1.9189C11.412 1.36549 10.9306 1.08878 10.4024 1.08899C9.87425 1.0892 9.39311 1.36628 8.43081 1.92044L3.14751 4.96293C3.10835 4.98548 3.08878 4.99674 3.07052 5.00742C1.26579 6.06391 0.150771 7.99271 0.135862 10.0839C0.135712 10.105 0.135712 10.1276 0.135712 10.1728C0.135712 10.2179 0.135712 10.2405 0.135862 10.2616C0.150738 12.3504 1.26327 14.2774 3.06479 15.3347C3.08299 15.3454 3.10253 15.3567 3.14164 15.3793L6.45108 17.2901C8.37948 18.4035 9.34367 18.9602 10.4025 18.9605C11.4614 18.9609 12.4259 18.4048 14.3551 17.2927L17.8487 15.2788C18.8146 14.7219 19.2976 14.4435 19.5628 13.9845C19.828 13.5255 19.828 12.968 19.828 11.853V9.69911C19.828 9.38979 19.6605 9.10474 19.3903 8.95422C19.1287 8.80859 18.81 8.81074 18.5505 8.95991L11.3869 13.0778C10.9063 13.3541 10.666 13.4922 10.4023 13.4923C10.1386 13.4923 9.89816 13.3543 9.41736 13.0784L4.56887 10.2952C4.32601 10.1558 4.20456 10.0861 4.10702 10.0735C3.88465 10.0448 3.67084 10.1694 3.58613 10.377C3.54899 10.4681 3.54973 10.6081 3.55124 10.8881C3.55235 11.0943 3.5529 11.1974 3.57216 11.2922C3.61533 11.5045 3.72702 11.6968 3.89013 11.8394C3.96296 11.9031 4.05222 11.9546 4.23078 12.0577L9.41462 15.0496C9.89668 15.3278 10.1377 15.4669 10.4023 15.467C10.667 15.467 10.9081 15.3281 11.3903 15.0501L17.7442 11.3875C17.9089 11.2926 17.9912 11.2451 18.053 11.2808C18.1147 11.3165 18.1147 11.4115 18.1147 11.6016V12.5786C18.1147 12.8574 18.1147 12.9967 18.0484 13.1115C17.9821 13.2262 17.8614 13.2958 17.6199 13.435L12.3792 16.456C11.4144 17.0121 10.932 17.2902 10.4025 17.2899C9.87293 17.2897 9.39078 17.0112 8.4265 16.4542L3.52339 13.6218C3.50782 13.6128 3.50004 13.6083 3.49278 13.6041C2.46472 13.0034 1.83037 11.9043 1.82442 10.7136C1.82438 10.7052 1.82438 10.6962 1.82438 10.6782V9.78145C1.82438 9.12412 2.17446 8.51659 2.74315 8.18696C3.24567 7.89566 3.86551 7.89508 4.36856 8.18545L8.4297 10.5294Z"
fill="white"
/>
</svg>
</Link>
<Link
href={"https://github.com/Almaze-Labs"}
target="_blank"
className="px-4 h-[42px] border border-white/25 rounded-md flex justify-center items-center gap-2.5 text-sm font-medium text-white"
>
Github
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_1_695)">
<mask
id="mask0_1_695"
maskUnits="userSpaceOnUse"
x="0"
y="0"
width="20"
height="20"
>
<path
d="M19.4737 0.526367H0.526367V19.4737H19.4737V0.526367Z"
fill="white"
/>
</mask>
<g mask="url(#mask0_1_695)">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M10.0001 0.526367C4.76584 0.526367 0.526367 4.76584 0.526367 10.0001C0.526367 14.1922 3.23821 17.733 7.004 18.9883C7.47768 19.0711 7.65531 18.7869 7.65531 18.5383C7.65531 18.3132 7.64347 17.5672 7.64347 16.7737C5.26321 17.2119 4.64742 16.1935 4.45795 15.6606C4.35137 15.3883 3.88953 14.5474 3.48689 14.3225C3.15531 14.1448 2.68163 13.7067 3.47505 13.6948C4.2211 13.683 4.754 14.3816 4.93163 14.6658C5.78426 16.0988 7.1461 15.6962 7.69084 15.4474C7.77374 14.8316 8.02242 14.4172 8.29479 14.1804C6.18689 13.9435 3.98426 13.1264 3.98426 9.50268C3.98426 8.47242 4.35137 7.61979 4.95531 6.95663C4.86058 6.71979 4.529 5.74874 5.05005 4.4461C5.05005 4.4461 5.84347 4.19742 7.65531 5.41716C8.41321 5.204 9.21847 5.09742 10.0237 5.09742C10.829 5.09742 11.6343 5.204 12.3922 5.41716C14.2041 4.18558 14.9974 4.4461 14.9974 4.4461C15.5185 5.74874 15.1869 6.71979 15.0922 6.95663C15.6962 7.61979 16.0632 8.46058 16.0632 9.50268C16.0632 13.1383 13.8488 13.9435 11.7409 14.1804C12.0843 14.4764 12.3804 15.0448 12.3804 15.933C12.3804 17.2001 12.3685 18.2185 12.3685 18.5383C12.3685 18.7869 12.5462 19.083 13.0198 18.9883C16.7619 17.733 19.4737 14.1804 19.4737 10.0001C19.4737 4.76584 15.2343 0.526367 10.0001 0.526367Z"
fill="white"
/>
</g>
</g>
<defs>
<clipPath id="clip0_1_695">
<rect width="20" height="20" fill="white" />
</clipPath>
</defs>
</svg>
</Link>
</div>
</div>
</div>
<FlickeringGrid
className="z-0 absolute inset-0 size-full"
squareSize={2}
gridGap={5}
color="#fff"
maxOpacity={0.15}
flickerChance={0.1}
width={1064}
height={766}
/>
</div>
</motion.div>
</section>
);
}

View File

@ -0,0 +1,174 @@
"use client";
import { useState } from "react";
import { TypingAnimation } from "@/components/home/magicui/typing-animation";
import { motion, AnimatePresence } from "framer-motion";
export default function TokenomicsSection() {
const [activeState, setActiveState] = useState<number>(1);
const handleStateChange = (state: number) => {
setActiveState(state);
};
const tabs = [
{
id: 1,
color: "#1DA2FF",
title: "CIRCULATING SUPPLY",
percentage: "95%",
content: {
title: "CIRCULATING SUPPLY (95%)",
background: "tokenomics-section-bg.png",
text: "The circulating supply represents the total amount of tokens that are currently available in the market. This ensures liquidity and accessibility for all participants. Our commitment to transparency and fairness is reflected in the high percentage of tokens allocated for circulation.",
bullets: [
"Ensures liquidity and accessibility for all participants.",
"Reflects our commitment to transparency and fairness.",
"Supports the growth and sustainability of our community."
]
}
},
{
id: 2,
color: "#FBBC05",
title: "TEAM ALLOCATIONS",
percentage: "2%",
content: {
title: "TEAM ALLOCATIONS (2%)",
background: "tokenomics-section-bg-2.png",
text: "The team allocation represents a small portion of the total supply, dedicated to rewarding the team for their hard work and commitment. This ensures that the team remains motivated and aligned with the project's long-term goals.",
bullets: [
"Rewards the team for their dedication and hard work.",
"Aligns the team's interests with the project's success.",
"Supports the ongoing development and growth of the project."
]
}
},
{
id: 3,
color: "#EA4335",
title: "MARKETING OPERATIONS",
percentage: "1%",
content: {
title: "MARKETING OPERATIONS (1%)",
background: "tokenomics-section-bg-3.png",
text: "The marketing operations allocation is dedicated to promoting our project and expanding our reach. This ensures that we can effectively communicate our vision and attract new participants.",
bullets: [
"Supports promotional activities and campaigns.",
"Helps in expanding our community and user base.",
"Ensures effective communication of our project's vision and goals."
]
}
},
{
id: 4,
color: "#2AD458",
title: "TREASURY",
percentage: "2%",
content: {
title: "TREASURY (2%)",
background: "tokenomics-section-bg-4.png",
text: "The treasury allocation is reserved for the long-term sustainability and growth of the project. This fund will be used for future development, partnerships, and unforeseen expenses.",
bullets: [
"Ensures the project's long-term sustainability and growth.",
"Provides funds for future development and partnerships.",
"Covers unforeseen expenses and emergencies."
]
}
}
];
return (
<section id="tokenomics" className="pt-36">
<motion.div
initial={{ y: -100, opacity: 0 }}
whileInView={{ y: 0, opacity: 1 }}
transition={{ duration: 0.5, delay: 1 }}
viewport={{ once: true }}
className="mx-auto container max-w-[1128px] px-8 flex flex-col items-center"
>
<p className="font-serif text-sm uppercase text-center text-[#1DA2FF]">
Tokenomics
</p>
<h2 className="my-4 max-w-[450px] min-h-[96px] font-offbit text-5xl text-center uppercase text-[#1DA2FF]">
<TypingAnimation startOnView = {false}>GREAT TOKENS SIMPLE TOKENOMICS</TypingAnimation>
</h2>
<p className="mb-12 font-medium text-center text-[#001A2C]">
Discover the transparent and fair distribution of our tokens, designed to ensure <br /> sustainability and growth for our community.
</p>
<div className="w-full border border-[#eee] bg-white rounded-xl">
<div className="border-b border-[#eee] grid grid-cols-4">
{tabs.map((tab) => (
<div
key={tab.id}
onClick={() => handleStateChange(tab.id)}
className={`border-r border-[#eee] py-5 px-7 cursor-pointer transition-all duration-300
${activeState === tab.id ? 'bg-gray-50' : 'hover:bg-gray-50/50'}`}
>
<div className="mb-3 flex items-center gap-2.5">
<span
className="w-[15px] h-[15px] rounded block"
style={{ backgroundColor: tab.color }}
/>
<p className="text-sm font-medium uppercase text-[#001A2C]">
{tab.title}
</p>
</div>
<h3
className="font-offbit text-5xl uppercase transition-all duration-300 "
style={{ color: tab.color }}
>
{tab.percentage}
</h3>
</div>
))}
</div>
<div className="p-5">
<div className="relative font-offbit h-[280px] overflow-hidden rounded-xl">
<AnimatePresence mode="wait">
{tabs.map((tab) => (
activeState === tab.id && (
<motion.div
key={tab.id}
initial={{ x: 100, opacity: 0 }}
animate={{ x: 0, opacity: 1 }}
exit={{ x: -100, opacity: 0 }}
transition={{
type: "spring",
stiffness: 100,
damping: 20,
duration: 0.3
}}
className="absolute inset-0 p-8 rounded-xl"
style={{
background: `url('/images/${tab.content.background}')`,
backgroundSize: "cover",
backgroundPosition: "center",
backgroundColor: "#1DA2FF",
}}
>
<h4 className="mb-1.5 text-3xl uppercase text-white">
{tab.content.title}
</h4>
<div className="text-sm font-serif leading-[24px] text-white space-y-4">
<p>{tab.content.text}</p>
<ul className="space-y-1">
{tab.content.bullets.map((bullet, index) => (
<li key={index}> {bullet}</li>
))}
</ul>
</div>
</motion.div>
)
))}
</AnimatePresence>
</div>
</div>
</div>
</motion.div>
</section>
);
}

36
app/layout.tsx Normal file
View File

@ -0,0 +1,36 @@
// import type { Metadata } from "next";
// import localFont from "next/font/local";
import { Inter } from 'next/font/google';
import './globals.css';
import { Metadata } from 'next';
const inter = Inter({ subsets: ['latin'] });
export const metadata: Metadata = {
title: "Almaze: Self Evolving AI that Helps You Complete Mundane Tasks",
description:
"The autoagentic AGI. Almaze is a self-evolving AGI made of agents that collaborate, and build new agents as needed, in order to complete tasks for a user.",
openGraph: {
type: "website",
url: "https://e8ogg8s4k8c84osoo8wo4ks4.dev3vds1.link/",
title: "Almaze: Self Evolving AI that Helps You Complete Mundane Tasks",
description:
"The autoagentic AGI. Almaze is a self-evolving AGI made of agents that collaborate, and build new agents as needed, in order to complete tasks for a user.",
images: `https://ai-proj-04.vercel.app/og-banner.png`,
},
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
{children}
</body>
</html>
);}

26
app/page.tsx Normal file
View File

@ -0,0 +1,26 @@
import Header from "./home/Header";
// import CTABox from "./home/CTABox";
import Footer from "./home/Footer";
import HeroSection from "@/app/home/HeroSection";
import FeaturesSection from "@/app/home/FeaturesSection";
import AgentsSection from "@/app/home/AgentsSection";
import TokenomicsSection from "@/app/home/TokenomicsSection";
import RoadmapSection from "@/app/home/RoadmapSection";
import { Providers } from "@/components/providers/privy-provider";
export default function Home() {
return (
<Providers>
<main>
<Header />
<HeroSection />
<FeaturesSection />
<AgentsSection />
<TokenomicsSection />
<RoadmapSection />
{/* <CTABox /> */}
<Footer />
</main>
</Providers>
);
}

13
app/phantom.svg Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 25 25" style="enable-background:new 0 0 25 25;" xml:space="preserve">
<style type="text/css">
.st0{fill:#AB9FF2;}
.st1{fill:#FFFFFF;}
</style>
<path class="st0" d="M22.5,0h-20C1.1,0,0,1.1,0,2.5v20C0,23.9,1.1,25,2.5,25h20c1.4,0,2.5-1.1,2.5-2.5v-20C25,1.1,23.9,0,22.5,0z"/>
<path class="st1" d="M19.6,8.8c-0.2-0.3-0.5-0.5-0.9-0.5H6.3c-0.7,0-1.1,0.8-0.7,1.4l2.8,3.9c0.2,0.3,0.5,0.5,0.9,0.5h12.4
c0.7,0,1.1-0.8,0.7-1.4L19.6,8.8z"/>
<path class="st1" d="M12.3,15.5c-0.2-0.3-0.5-0.5-0.9-0.5H3.7c-0.7,0-1.1,0.8-0.7,1.4l2.8,3.9c0.2,0.3,0.5,0.5,0.9,0.5h7.7
c0.7,0,1.1-0.8,0.7-1.4L12.3,15.5z"/>
</svg>

After

Width:  |  Height:  |  Size: 794 B

21
components.json Normal file
View File

@ -0,0 +1,21 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "app/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}

View File

@ -0,0 +1,22 @@
interface ChatInputProps {
input: string;
setInput: (value: string) => void;
handleSubmit: (e: React.FormEvent) => Promise<void>;
isLoading: boolean;
}
export const ChatInput = ({ input, setInput, handleSubmit, isLoading }: ChatInputProps) => (
<form onSubmit={handleSubmit} className="relative">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="What's on your mind?"
className="w-full px-4 py-3 rounded-xl bg-white border border-gray-200 focus:ring-1 focus:ring-[#1DA2FF] focus:outline-none hover:ring-[#1DA2FF] hover:ring-1 transition duration-200 ease-linear"
disabled={isLoading}
/>
<div className="absolute right-4 top-1/2 -translate-y-1/2 flex items-center gap-2 text-[12px] text-gray-400">
Press <kbd className="px-1.5 py-0.5 bg-gray-100 rounded text-xs"></kbd> to send
</div>
</form>
);

View File

@ -0,0 +1,22 @@
import { motion } from "framer-motion";
import { LucideIcon } from "lucide-react";
interface IntegrationButtonProps {
Icon: LucideIcon;
label: string;
color: string;
onClick: () => void;
}
export const IntegrationButton = ({ Icon, label, color, onClick }: IntegrationButtonProps) => (
<motion.button
className="flex items-center gap-2 px-4 py-2 rounded-md border border-gray-200 bg-white "
onClick={onClick}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
style={{ color: color }}
>
<Icon size={24} />
<span className="text-sm font-medium font-offbit">{label}</span>
</motion.button>
);

View File

@ -0,0 +1,240 @@
import React, { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import Avatar, { AvatarConfig } from 'react-nice-avatar';
import ReactMarkdown from 'react-markdown';
import { Bot, Copy, Check } from 'lucide-react';
interface Message {
id: string;
role: 'user' | 'assistant' | 'system';
content: string;
timestamp: string;
}
interface MessageBubbleProps {
message: Message;
isLast: boolean;
userName?: string;
avatarConfig?: AvatarConfig;
}
const MessageBubble = ({ message, userName, avatarConfig }: MessageBubbleProps) => {
const isUser = message.role === 'user';
const [isCopied, setIsCopied] = useState(false);
const [isHovered, setIsHovered] = useState(false);
const [copiedCodeBlock, setCopiedCodeBlock] = useState<string | null>(null);
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(message.content);
setIsCopied(true);
setTimeout(() => setIsCopied(false), 2000);
} catch (err) {
console.error('Failed to copy text:', err);
}
};
const handleCodeCopy = async (code: string) => {
try {
await navigator.clipboard.writeText(code);
setCopiedCodeBlock(code);
setTimeout(() => setCopiedCodeBlock(null), 2000);
} catch (err) {
console.error('Failed to copy code:', err);
}
};
const bubbleVariants = {
hidden: {
opacity: 0,
y: 20,
scale: 0.95
},
visible: {
opacity: 1,
y: 0,
scale: 1,
transition: {
type: "spring",
stiffness: 300,
damping: 24
}
}
};
const iconVariants = {
hover: {
scale: 1.2,
rotate: 360,
transition: { duration: 0.5 }
}
};
const copyButtonVariants = {
hidden: { opacity: 0, scale: 0.8 },
visible: { opacity: 1, scale: 1 },
exit: { opacity: 0, scale: 0.8 }
};
return (
<motion.div
initial="hidden"
animate="visible"
variants={bubbleVariants}
className={`flex ${isUser ? 'justify-end' : 'justify-start'} items-start gap-3`}
>
{!isUser && (
<motion.div
className="flex-shrink-0 bg-[#1DA2FF] rounded-full p-2"
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
>
<motion.div
variants={iconVariants}
whileHover="hover"
>
<Bot className="w-6 h-6 text-white" />
</motion.div>
</motion.div>
)}
<div
className={`flex flex-col ${isUser ? 'items-end' : 'items-start'} relative`}
onMouseEnter={() => !isUser && setIsHovered(true)}
onMouseLeave={() => !isUser && setIsHovered(false)}
>
<motion.div
className="flex items-center gap-2 mb-1"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.2 }}
>
<span className="text-sm text-gray-600 font-offbit">
{isUser ? userName : 'ALMAZE'}
</span>
<span className="text-xs text-gray-400">
{new Date(message.timestamp).toLocaleTimeString()}
</span>
</motion.div>
<motion.div
className={`rounded-xl px-4 py-2 max-w-2xl relative ${
isUser
? 'bg-[#1DA2FF] text-white'
: 'bg-white border border-gray-200'
}`}
whileHover={{ scale: 1.006 }}
transition={{ type: "spring", stiffness: 400, damping: 17 }}
>
{!isUser && (
<AnimatePresence>
{isHovered && (
<motion.button
initial="hidden"
animate="visible"
exit="exit"
variants={copyButtonVariants}
className="absolute -top-2 -right-2 p-2 rounded-full bg-gray-100 hover:bg-gray-200 transition-colors shadow-sm"
onClick={handleCopy}
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
>
{isCopied ? (
<motion.div
initial={{ scale: 0 }}
animate={{ scale: 1 }}
exit={{ scale: 0 }}
>
<Check className="w-4 h-4 text-green-500" />
</motion.div>
) : (
<Copy className="w-4 h-4 text-gray-500" />
)}
</motion.button>
)}
</AnimatePresence>
)}
<div className="mt-2">
<ReactMarkdown
className="prose prose-sm"
components={{
code({ inline, className, children, ...props }: { inline?: boolean, className?: string, children?: React.ReactNode }) {
const match = /language-(\w+)/.exec(className || '');
const code = String(children).replace(/\n$/, '');
if (inline) {
return (
<code
className={`${isUser ? 'bg-blue-400/50' : 'bg-gray-100'} rounded px-1 py-0.5 text-sm`}
{...props}
>
{children}
</code>
);
}
return (
<div className="relative group">
<div className="absolute right-2 top-2 flex items-center gap-2">
{match && (
<span className="text-xs text-gray-500 bg-white/80 px-2 py-1 rounded">
{match[1]}
</span>
)}
<button
onClick={() => handleCodeCopy(code)}
className="opacity-0 group-hover:opacity-100 transition-opacity bg-white hover:bg-gray-50 text-gray-600 px-2 py-1 rounded text-xs flex items-center gap-1 shadow-sm"
>
{copiedCodeBlock === code ? (
<>
<Check className="w-3 h-3" />
Copied
</>
) : (
<>
<Copy className="w-3 h-3" />
Copy code
</>
)}
</button>
</div>
<div
className={`${
isUser ? 'bg-blue-400/50' : 'bg-gray-100'
} rounded-lg my-2 overflow-hidden`}
>
<div className="overflow-x-auto">
<pre className="p-2 text-sm">
<code {...props}>{code}</code>
</pre>
</div>
</div>
</div>
);
},
p: ({ children }) => (
<p className="whitespace-pre-wrap break-words">{children}</p>
),
}}
>
{message.content}
</ReactMarkdown>
</div>
</motion.div>
</div>
{isUser && (
<motion.div
className="flex-shrink-0"
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
transition={{ type: "spring", stiffness: 400, damping: 17 }}
>
<Avatar style={{ width: '2.5rem', height: '2.5rem' }} {...avatarConfig} />
</motion.div>
)}
</motion.div>
);
};
export default MessageBubble;

View File

@ -0,0 +1,33 @@
interface WelcomeHeaderProps {
name: string;
version: string;
}
const getTimeBasedGreeting = (): string => {
const hour = new Date().getHours();
if (hour >= 5 && hour < 12) {
return "GOOD MORNING";
} else if (hour >= 12 && hour < 17) {
return "GOOD AFTERNOON";
} else {
return "GOOD EVENING";
}
};
export const WelcomeHeader = ({ name, version }: WelcomeHeaderProps) => {
const greeting = getTimeBasedGreeting();
return (
<>
<div className="flex flex-col justify-center items-center gap-5">
<button className="shadow-[0_4px_14px_0_rgb(0,118,255,39%)] hover:shadow-[0_6px_20px_rgba(0,118,255,23%)] hover:bg-[rgba(0,118,255,0.9)] px-4 py-3 bg-[#1DA2FF] text-white font-light transition duration-200 ease-linear z-100 rounded-full text-sm w-1/2">
{version} {">"}
</button>
<h1 className="text-5xl mt-3 mb-2 font-offbit">
{greeting}, <span className="text-[#1DA2FF]">{name}</span>
</h1>
</div>
</>
);
};

View File

@ -0,0 +1,32 @@
export const NICKNAMES = [
'FROST',
'ECHO',
'SAGE',
'SKY',
'NORTH',
'WAVE',
'SPARK',
'DUSK',
'DAWN',
'MIST',
'SNOW',
'RAIN',
'ASH',
'STAR',
'CLOUD',
'LEAF',
'ZEN',
'AURA',
'REEF',
'VALE',
'MOON',
'PINE',
'EAST',
'PEAK',
'FLARE',
'CLIFF',
'PRISM',
'SWIFT'
] as const;
export type Nickname = typeof NICKNAMES[number];

View File

@ -0,0 +1,34 @@
import { RiTwitterXLine } from "react-icons/ri";
import { SiGithub , SiGitbook } from "react-icons/si";
import Image, { StaticImageData } from 'next/image';
interface SidebarHeaderProps {
onNewChat: () => void;
logo: StaticImageData;
}
export const SidebarHeader = ({ onNewChat, logo }: SidebarHeaderProps) => (
<div className="p-4 border-b">
<div className="flex items-center justify-between mb-10">
<Image src={logo} alt="Almaze Logo" width={26} />
<div className="flex items-center space-x-4 mt-1">
<a href="https://x.com/almaze_ai" target='_blank'>
<RiTwitterXLine className='cursor-pointer text-gray-600 hover:text-gray-800 transition-colors'/>
</a>
<a href="https://almaze.gitbook.io/docs/" target='_blank'>
<SiGitbook className='cursor-pointer text-gray-600 hover:text-gray-800 transition-colors'/>
</a>
<a href="https://github.com/Almaze-Labs" target='_blank'>
<SiGithub className='cursor-pointer text-gray-600 hover:text-gray-800 transition-colors'/>
</a>
</div>
</div>
<button
onClick={onNewChat}
className="w-full py-4 text-blue-500 border-2 border-dashed border-blue-200 rounded-lg bg-gradient-to-t from-[rgba(29,162,255,0.2)] to-[rgba(29,162,255,0)] hover:bg-blue-50 transition-colors text-sm"
>
Start a new chat
</button>
</div>
);

View File

@ -0,0 +1,63 @@
import Image, { StaticImageData } from 'next/image';
import { Star } from 'lucide-react';
import { motion } from 'framer-motion';
import { RiTwitterXLine } from "react-icons/ri";
import { SiGithub , SiGitbook } from "react-icons/si";
interface StarredChatProps {
title: string;
isStarred: boolean;
onClick: () => void;
onStar: (e: React.MouseEvent) => void;
}
export const StarredChat = ({ title, isStarred, onClick, onStar }: StarredChatProps) => (
<motion.button
className="w-full flex items-center justify-between p-2 hover:bg-gray-50 rounded-lg group"
onClick={onClick}
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
>
<span className="text-sm text-gray-700 truncate">{title}</span>
<Star
className={`w-4 h-4 ${isStarred ? 'text-blue-500' : 'text-gray-300 opacity-0 group-hover:opacity-100'}`}
onClick={(e) => {
e.stopPropagation();
onStar(e);
}}
/>
</motion.button>
);
interface SidebarHeaderProps {
onNewChat: () => void;
logo: StaticImageData;
}
export const SidebarHeader = ({ onNewChat, logo }: SidebarHeaderProps) => (
<div className="p-4 border-b">
<div className="flex items-center justify-between mb-10">
<Image src={logo} alt="Almaze Logo" width={26} />
<div className="flex items-center space-x-4 mt-1">
<a href="https://x.com/almaze_ai" target='_blank'>
<RiTwitterXLine className='cursor-pointer text-gray-600 hover:text-gray-800 transition-colors'/>
</a>
<a href="https://almaze.gitbook.io/docs/" target='_blank'>
<SiGitbook className='cursor-pointer text-gray-600 hover:text-gray-800 transition-colors'/>
</a>
<a href="https://github.com/Almaze-Labs" target='_blank'>
<SiGithub className='cursor-pointer text-gray-600 hover:text-gray-800 transition-colors'/>
</a>
</div>
</div>
<button
onClick={onNewChat}
className="w-full py-4 text-blue-500 border-2 border-dashed border-blue-200 rounded-lg bg-gradient-to-t from-[rgba(29,162,255,0.2)] to-[rgba(29,162,255,0)] hover:bg-blue-50 transition-colors text-sm"
>
Start a new chat
</button>
</div>
);

View File

@ -0,0 +1,16 @@
import React from 'react';
const LoadingSpinner = () => {
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-opacity-50 bg-gray-900">
<div className="relative">
<div className="w-16 h-16 border-4 border-t-4 border-gray-200 border-t-blue-500 rounded-full animate-spin"></div>
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-white text-xs">
Loading
</div>
</div>
</div>
);
};
export default LoadingSpinner;

View File

@ -0,0 +1,189 @@
"use client";
import { motion } from "framer-motion";
import { RefObject, useEffect, useId, useState } from "react";
import { cn } from "@/lib/utils";
export interface AnimatedBeamProps {
className?: string;
containerRef: RefObject<HTMLElement | null>; // Container ref
fromRef: RefObject<HTMLElement | null>;
toRef: RefObject<HTMLElement | null>;
curvature?: number;
reverse?: boolean;
pathColor?: string;
pathWidth?: number;
pathOpacity?: number;
gradientStartColor?: string;
gradientStopColor?: string;
delay?: number;
duration?: number;
startXOffset?: number;
startYOffset?: number;
endXOffset?: number;
endYOffset?: number;
}
export const AnimatedBeam: React.FC<AnimatedBeamProps> = ({
className,
containerRef,
fromRef,
toRef,
curvature = 0,
reverse = false, // Include the reverse prop
duration = Math.random() * 3 + 4,
delay = 0,
pathColor = "gray",
pathWidth = 2,
pathOpacity = 0.2,
gradientStartColor = "#ffaa40",
gradientStopColor = "#9c40ff",
startXOffset = 0,
startYOffset = 0,
endXOffset = 0,
endYOffset = 0,
}) => {
const id = useId();
const [pathD, setPathD] = useState("");
const [svgDimensions, setSvgDimensions] = useState({ width: 0, height: 0 });
// Calculate the gradient coordinates based on the reverse prop
const gradientCoordinates = reverse
? {
x1: ["90%", "-10%"],
x2: ["100%", "0%"],
y1: ["0%", "0%"],
y2: ["0%", "0%"],
}
: {
x1: ["10%", "110%"],
x2: ["0%", "100%"],
y1: ["0%", "0%"],
y2: ["0%", "0%"],
};
useEffect(() => {
const updatePath = () => {
if (containerRef.current && fromRef.current && toRef.current) {
const containerRect = containerRef.current.getBoundingClientRect();
const rectA = fromRef.current.getBoundingClientRect();
const rectB = toRef.current.getBoundingClientRect();
const svgWidth = containerRect.width;
const svgHeight = containerRect.height;
setSvgDimensions({ width: svgWidth, height: svgHeight });
const startX =
rectA.left - containerRect.left + rectA.width / 2 + startXOffset;
const startY =
rectA.top - containerRect.top + rectA.height / 2 + startYOffset;
const endX =
rectB.left - containerRect.left + rectB.width / 2 + endXOffset;
const endY =
rectB.top - containerRect.top + rectB.height / 2 + endYOffset;
const controlY = startY - curvature;
const d = `M ${startX},${startY} Q ${
(startX + endX) / 2
},${controlY} ${endX},${endY}`;
setPathD(d);
}
};
// Initialize ResizeObserver
const resizeObserver = new ResizeObserver((entries) => {
// For all entries, recalculate the path
for (const entry of entries) {
console.log(entry);
updatePath();
}
});
// Observe the container element
if (containerRef.current) {
resizeObserver.observe(containerRef.current);
}
// Call the updatePath initially to set the initial path
updatePath();
// Clean up the observer on component unmount
return () => {
resizeObserver.disconnect();
};
}, [
containerRef,
fromRef,
toRef,
curvature,
startXOffset,
startYOffset,
endXOffset,
endYOffset,
]);
return (
<svg
fill="none"
width={svgDimensions.width}
height={svgDimensions.height}
xmlns="http://www.w3.org/2000/svg"
className={cn(
"pointer-events-none absolute left-0 top-0 transform-gpu stroke-2",
className
)}
viewBox={`0 0 ${svgDimensions.width} ${svgDimensions.height}`}
>
<path
d={pathD}
stroke={pathColor}
strokeWidth={pathWidth}
strokeOpacity={pathOpacity}
strokeLinecap="round"
/>
<path
d={pathD}
strokeWidth={pathWidth}
stroke={`url(#${id})`}
strokeOpacity="1"
strokeLinecap="round"
/>
<defs>
<motion.linearGradient
className="transform-gpu"
id={id}
gradientUnits={"userSpaceOnUse"}
initial={{
x1: "0%",
x2: "0%",
y1: "0%",
y2: "0%",
}}
animate={{
x1: gradientCoordinates.x1,
x2: gradientCoordinates.x2,
y1: gradientCoordinates.y1,
y2: gradientCoordinates.y2,
}}
transition={{
delay,
duration,
ease: [0.16, 1, 0.3, 1], // https://easings.net/#easeOutExpo
repeat: Infinity,
repeatDelay: 0,
}}
>
<stop stopColor={gradientStartColor} stopOpacity="0"></stop>
<stop stopColor={gradientStartColor}></stop>
<stop offset="32.5%" stopColor={gradientStopColor}></stop>
<stop
offset="100%"
stopColor={gradientStopColor}
stopOpacity="0"
></stop>
</motion.linearGradient>
</defs>
</svg>
);
};

View File

@ -0,0 +1,194 @@
"use client";
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
interface FlickeringGridProps {
squareSize?: number;
gridGap?: number;
flickerChance?: number;
color?: string;
width?: number;
height?: number;
className?: string;
maxOpacity?: number;
}
export const FlickeringGrid: React.FC<FlickeringGridProps> = ({
squareSize = 4,
gridGap = 6,
flickerChance = 0.3,
color = "rgb(0, 0, 0)",
width,
height,
className,
maxOpacity = 0.3,
}) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
const [isInView, setIsInView] = useState(false);
const [canvasSize, setCanvasSize] = useState({ width: 0, height: 0 });
const memoizedColor = useMemo(() => {
const toRGBA = (color: string) => {
if (typeof window === "undefined") {
return `rgba(0, 0, 0,`;
}
const canvas = document.createElement("canvas");
canvas.width = canvas.height = 1;
const ctx = canvas.getContext("2d");
if (!ctx) return "rgba(255, 0, 0,";
ctx.fillStyle = color;
ctx.fillRect(0, 0, 1, 1);
const [r, g, b] = Array.from(ctx.getImageData(0, 0, 1, 1).data);
return `rgba(${r}, ${g}, ${b},`;
};
return toRGBA(color);
}, [color]);
const setupCanvas = useCallback(
(canvas: HTMLCanvasElement, width: number, height: number) => {
const dpr = window.devicePixelRatio || 1;
canvas.width = width * dpr;
canvas.height = height * dpr;
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;
const cols = Math.floor(width / (squareSize + gridGap));
const rows = Math.floor(height / (squareSize + gridGap));
const squares = new Float32Array(cols * rows);
for (let i = 0; i < squares.length; i++) {
squares[i] = Math.random() * maxOpacity;
}
return { cols, rows, squares, dpr };
},
[squareSize, gridGap, maxOpacity]
);
const updateSquares = useCallback(
(squares: Float32Array, deltaTime: number) => {
for (let i = 0; i < squares.length; i++) {
if (Math.random() < flickerChance * deltaTime) {
squares[i] = Math.random() * maxOpacity;
}
}
},
[flickerChance, maxOpacity]
);
const drawGrid = useCallback(
(
ctx: CanvasRenderingContext2D,
width: number,
height: number,
cols: number,
rows: number,
squares: Float32Array,
dpr: number
) => {
ctx.clearRect(0, 0, width, height);
ctx.fillStyle = "transparent";
ctx.fillRect(0, 0, width, height);
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
const opacity = squares[i * rows + j];
ctx.fillStyle = `${memoizedColor}${opacity})`;
ctx.fillRect(
i * (squareSize + gridGap) * dpr,
j * (squareSize + gridGap) * dpr,
squareSize * dpr,
squareSize * dpr
);
}
}
},
[memoizedColor, squareSize, gridGap]
);
useEffect(() => {
const canvas = canvasRef.current;
const container = containerRef.current;
if (!canvas || !container) return;
const ctx = canvas.getContext("2d");
if (!ctx) return;
let animationFrameId: number;
let gridParams: ReturnType<typeof setupCanvas>;
const updateCanvasSize = () => {
const newWidth = width || container.clientWidth;
const newHeight = height || container.clientHeight;
setCanvasSize({ width: newWidth, height: newHeight });
gridParams = setupCanvas(canvas, newWidth, newHeight);
};
updateCanvasSize();
let lastTime = 0;
const animate = (time: number) => {
if (!isInView) return;
const deltaTime = (time - lastTime) / 1000;
lastTime = time;
updateSquares(gridParams.squares, deltaTime);
drawGrid(
ctx,
canvas.width,
canvas.height,
gridParams.cols,
gridParams.rows,
gridParams.squares,
gridParams.dpr
);
animationFrameId = requestAnimationFrame(animate);
};
const resizeObserver = new ResizeObserver(() => {
updateCanvasSize();
});
resizeObserver.observe(container);
const intersectionObserver = new IntersectionObserver(
([entry]) => {
setIsInView(entry.isIntersecting);
},
{ threshold: 0 }
);
intersectionObserver.observe(canvas);
if (isInView) {
animationFrameId = requestAnimationFrame(animate);
}
return () => {
cancelAnimationFrame(animationFrameId);
resizeObserver.disconnect();
intersectionObserver.disconnect();
};
}, [setupCanvas, updateSquares, drawGrid, width, height, isInView]);
return (
<div ref={containerRef} className={`w-full h-full ${className}`}>
<canvas
ref={canvasRef}
className="pointer-events-none"
style={{
width: canvasSize.width,
height: canvasSize.height,
}}
/>
</div>
);
};

View File

@ -0,0 +1,72 @@
import { cn } from "@/lib/utils";
import React, { useState } from "react";
/**
* InteractiveGridPattern is a component that renders a grid pattern with interactive squares.
*
* @param width - The width of each square.
* @param height - The height of each square.
* @param squares - The number of squares in the grid. The first element is the number of horizontal squares, and the second element is the number of vertical squares.
* @param className - The class name of the grid.
* @param squaresClassName - The class name of the squares.
*/
interface InteractiveGridPatternProps extends React.SVGProps<SVGSVGElement> {
width?: number;
height?: number;
squares?: [number, number]; // [horizontal, vertical]
className?: string;
squaresClassName?: string;
}
/**
* The InteractiveGridPattern component.
*
* @see InteractiveGridPatternProps for the props interface.
* @returns A React component.
*/
export function InteractiveGridPattern({
width = 40,
height = 40,
squares = [100, 100],
className,
squaresClassName,
...props
}: InteractiveGridPatternProps) {
const [horizontal, vertical] = squares;
const [hoveredSquare, setHoveredSquare] = useState<number | null>(null);
return (
<svg
width={width * horizontal}
height={height * vertical}
className={cn(
"absolute inset-0 h-full w-full border border-[#1DA2FF]/30",
className
)}
{...props}
>
{Array.from({ length: horizontal * vertical }).map((_, index) => {
const x = (index % horizontal) * width;
const y = Math.floor(index / horizontal) * height;
return (
<rect
key={index}
x={x}
y={y}
width={width}
height={height}
className={cn(
"stroke-[#1DA2FF]/30 transition-all duration-100 ease-in-out [&:not(:hover)]:duration-1000",
hoveredSquare === index
? "fill-[#1DA2FF]/30"
: "fill-transparent",
squaresClassName
)}
onMouseEnter={() => setHoveredSquare(index)}
onMouseLeave={() => setHoveredSquare(null)}
/>
);
})}
</svg>
);
}

View File

@ -0,0 +1,83 @@
"use client";
import { cn } from "@/lib/utils";
import { motion, MotionProps } from "framer-motion";
import { useEffect, useRef, useState } from "react";
interface TypingAnimationProps extends MotionProps {
children: string;
className?: string;
duration?: number;
delay?: number;
as?: React.ElementType;
startOnView?: boolean;
}
export function TypingAnimation({
children,
className,
duration = 50,
delay = 0,
as: Component = "div",
startOnView = true,
...props
}: TypingAnimationProps) {
const MotionComponent = motion.create(Component, {
forwardMotionProps: true,
});
const [displayedText, setDisplayedText] = useState<string>("");
const [started, setStarted] = useState(false);
const elementRef = useRef<HTMLElement | null>(null);
useEffect(() => {
if (!startOnView) {
const startTimeout = setTimeout(() => {
setStarted(true);
}, delay);
return () => clearTimeout(startTimeout);
}
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setTimeout(() => {
setStarted(true);
}, delay);
observer.disconnect();
}
},
{ threshold: 0.1 }
);
if (elementRef.current) {
observer.observe(elementRef.current);
}
return () => observer.disconnect();
}, [delay, startOnView]);
useEffect(() => {
if (!started) return;
let i = 0;
const typingEffect = setInterval(() => {
if (i < children.length) {
setDisplayedText(children.substring(0, i + 1));
i++;
} else {
clearInterval(typingEffect);
}
}, duration);
return () => {
clearInterval(typingEffect);
};
}, [children, duration, started]);
return (
<MotionComponent ref={elementRef} className={cn("", className)} {...props}>
{displayedText}
</MotionComponent>
);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 KiB

View File

@ -0,0 +1,55 @@
'use client';
import { PrivyProvider } from '@privy-io/react-auth';
import { ReactNode , useEffect } from 'react';
import {toSolanaWalletConnectors} from '@privy-io/react-auth/solana';
export function Providers({ children }: { children: ReactNode }) {
useEffect(() => {
localStorage.removeItem('privy:embedded-wallet:iframe-ready');
localStorage.removeItem('privy:embedded-wallet:ready');
}, []);
const solanaConnectors = toSolanaWalletConnectors({
// By default, shouldAutoConnect is enabled
shouldAutoConnect: true,
});
return (
<PrivyProvider
appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID || ''}
config={{
"appearance": {
"accentColor": "#6A6FF5",
"theme":"#FFFFFF",
"showWalletLoginFirst": false,
"logo": "https://auth.privy.io/logos/privy-logo.png",
"walletChainType": 'solana-only',
"walletList": [
"phantom"
]
},
"externalWallets": {
"solana": {
"connectors": solanaConnectors,
},
},
"loginMethods": [
"email",
"wallet"
],
"embeddedWallets": {
"createOnLogin": "all-users",
"requireUserPasswordOnCreate": false,
"showWalletUIs": true
},
"mfa": {
"noPromptOnMfaRequired": false
}
}}
>
{children}
</PrivyProvider>
);
}

View File

@ -0,0 +1,47 @@
import React, { useEffect, useRef, useState } from 'react';
interface FadeInSectionProps {
children: React.ReactNode;
direction?: 'up' | 'down' | 'left' | 'right';
className?: string;
}
export const FadeInSection: React.FC<FadeInSectionProps> = ({
children,
direction = 'up',
className = ''
}) => {
const [isVisible, setIsVisible] = useState(false);
const domRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => setIsVisible(entry.isIntersecting));
}, { threshold: 0.1 });
const { current } = domRef;
if (current) observer.observe(current);
return () => {
if (current) observer.unobserve(current);
};
}, []);
const directionClasses = {
up: 'translate-y-10',
down: '-translate-y-10',
left: 'translate-x-10',
right: '-translate-x-10'
};
return (
<div
ref={domRef}
className={`transition-all duration-1000 transform ${directionClasses[direction]}
${isVisible ? 'opacity-100 translate-y-0 translate-x-0' : 'opacity-0'}
${className}`}
>
{children}
</div>
);
};

View File

@ -0,0 +1,34 @@
// components/TypewriterText.tsx
'use client';
import { useState, useEffect } from 'react';
interface TypewriterTextProps {
text: string;
speed?: number;
}
export function TypewriterText({ text, speed = 20 }: TypewriterTextProps) {
const [displayedText, setDisplayedText] = useState('');
const [currentIndex, setCurrentIndex] = useState(0);
useEffect(() => {
if (currentIndex < text.length) {
const timeout = setTimeout(() => {
setDisplayedText(prev => prev + text[currentIndex]);
setCurrentIndex(currentIndex + 1);
}, speed);
return () => clearTimeout(timeout);
}
}, [currentIndex, text, speed]);
useEffect(() => {
// Reset when text changes
setDisplayedText('');
setCurrentIndex(0);
}, [text]);
return <div>{displayedText}</div>;
}

57
components/ui/button.tsx Normal file
View File

@ -0,0 +1,57 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
{
variants: {
variant: {
default:
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
outline:
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2",
sm: "h-8 rounded-md px-3 text-xs",
lg: "h-10 rounded-md px-8",
icon: "h-9 w-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = "Button"
export { Button, buttonVariants }

76
components/ui/card.tsx Normal file
View File

@ -0,0 +1,76 @@
import * as React from "react"
import { cn } from "@/lib/utils"
const Card = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"rounded-xl border bg-card text-card-foreground shadow",
className
)}
{...props}
/>
))
Card.displayName = "Card"
const CardHeader = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex flex-col space-y-1.5 p-6", className)}
{...props}
/>
))
CardHeader.displayName = "CardHeader"
const CardTitle = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("font-semibold leading-none tracking-tight", className)}
{...props}
/>
))
CardTitle.displayName = "CardTitle"
const CardDescription = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
))
CardDescription.displayName = "CardDescription"
const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
))
CardContent.displayName = "CardContent"
const CardFooter = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex items-center p-6 pt-0", className)}
{...props}
/>
))
CardFooter.displayName = "CardFooter"
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }

22
components/ui/input.tsx Normal file
View File

@ -0,0 +1,22 @@
import * as React from "react"
import { cn } from "@/lib/utils"
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className
)}
ref={ref}
{...props}
/>
)
}
)
Input.displayName = "Input"
export { Input }

View File

@ -0,0 +1,48 @@
"use client"
import * as React from "react"
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
import { cn } from "@/lib/utils"
const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
>(({ className, children, ...props }, ref) => (
<ScrollAreaPrimitive.Root
ref={ref}
className={cn("relative overflow-hidden", className)}
{...props}
>
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
))
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
const ScrollBar = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
>(({ className, orientation = "vertical", ...props }, ref) => (
<ScrollAreaPrimitive.ScrollAreaScrollbar
ref={ref}
orientation={orientation}
className={cn(
"flex touch-none select-none transition-colors",
orientation === "vertical" &&
"h-full w-2.5 border-l border-l-transparent p-[1px]",
orientation === "horizontal" &&
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
className
)}
{...props}
>
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
</ScrollAreaPrimitive.ScrollAreaScrollbar>
))
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
export { ScrollArea, ScrollBar }

View File

@ -0,0 +1,33 @@
import React, { useState, useEffect } from 'react';
interface TypewriterTextProps {
text: string;
}
export const TypewriterText: React.FC<TypewriterTextProps> = ({ text }) => {
const [displayedText, setDisplayedText] = useState('');
const [isTyping, setIsTyping] = useState(true);
useEffect(() => {
if (isTyping) {
if (displayedText.length < text.length) {
const timeout = setTimeout(() => {
setDisplayedText(text.slice(0, displayedText.length + 1));
}, 100);
return () => clearTimeout(timeout);
} else {
setIsTyping(false);
setTimeout(() => {
setDisplayedText('');
setIsTyping(true);
}, 3000);
}
}
}, [displayedText, isTyping, text]);
return (
<span className="border-r-2 border-black animate-pulse">
{displayedText}
</span>
);
};

6
lib/utils.ts Normal file
View File

@ -0,0 +1,6 @@
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}

36
middleware.ts Normal file
View File

@ -0,0 +1,36 @@
import { NextRequest, NextResponse } from "next/server";
export function middleware(request: NextRequest) {
// console.log("Request Pathname:", request.nextUrl.pathname);
// console.log("Authentication Cookie:", request.cookies.get("privy-authenticated")?.value);
const { pathname } = request.nextUrl;
// List of restricted routes
const blockList = ["/dashboard", "/admin", "/private"];
// Check if the route is in the block list
const isRestricted = blockList.some((route) => pathname.startsWith(route));
if (!isRestricted) {
// console.log("Public route accessed or route not in block list.");
return NextResponse.next();
}
// Authentication check
const isAuthenticated = request.cookies.get("privy-authenticated")?.value === "true";
if (!isAuthenticated) {
// console.log("User is not authenticated. Redirecting...");
const url = new URL("/auth", request.url);
return NextResponse.redirect(url);
}
// console.log("User is authenticated. Proceeding...");
return NextResponse.next();
}
// Matcher configuration for middleware
export const config = {
matcher: ["/:path*"], // Apply middleware to all routes
};

7
next.config.mjs Normal file
View File

@ -0,0 +1,7 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
// reactStrictMode: true, // Enable strict mode (recommended)
swcMinify: true,
};
export default nextConfig;

12938
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

51
package.json Normal file
View File

@ -0,0 +1,51 @@
{
"name": "proj1",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@privy-io/react-auth": "^1.99.1",
"@privy-io/wagmi-connector": "^0.1.13",
"@radix-ui/react-scroll-area": "^1.2.2",
"@radix-ui/react-slot": "^1.1.1",
"@react-three/fiber": "^8.17.12",
"@tabler/icons-react": "^3.28.1",
"@types/three": "^0.172.0",
"@types/uuid": "^10.0.0",
"ai": "^4.0.36",
"axios": "^1.7.9",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"framer-motion": "^11.18.2",
"js-cookie": "^3.0.5",
"lucide-react": "^0.471.1",
"next": "14.2.16",
"react": "^18",
"react-dom": "^18",
"react-element-to-jsx-string": "^15.0.0",
"react-icons": "^5.4.0",
"react-markdown": "^9.0.3",
"react-nice-avatar": "^1.5.0",
"react-router-dom": "^7.1.1",
"tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7",
"three": "^0.172.0",
"uuid": "^11.0.5"
},
"devDependencies": {
"@types/js-cookie": "^3.0.6",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"eslint": "^8",
"eslint-config-next": "14.2.16",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5"
}
}

8
postcss.config.mjs Normal file
View File

@ -0,0 +1,8 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
},
};
export default config;

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 KiB

Binary file not shown.

71
tailwind.config.ts Normal file
View File

@ -0,0 +1,71 @@
import type { Config } from "tailwindcss";
const config: Config = {
darkMode: ["class"],
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
fontFamily: {
offbit: ['OffBit', 'monospace'],
},
colors: {
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))'
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))'
},
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))'
},
secondary: {
DEFAULT: 'hsl(var(--secondary))',
foreground: 'hsl(var(--secondary-foreground))'
},
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))'
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))'
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
foreground: 'hsl(var(--destructive-foreground))'
},
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
chart: {
'1': 'hsl(var(--chart-1))',
'2': 'hsl(var(--chart-2))',
'3': 'hsl(var(--chart-3))',
'4': 'hsl(var(--chart-4))',
'5': 'hsl(var(--chart-5))'
}
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)'
},
animation: {
'pulse': 'pulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) infinite',
'slow-spin': 'spin 20s linear infinite',
},
}
},
plugins: [require("tailwindcss-animate")],
};
export default config;

26
tsconfig.json Normal file
View File

@ -0,0 +1,26 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "middleware.ts", "app/api/chat/route.js"],
"exclude": ["node_modules"]
}