diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 8c9b472..98c957c 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; +import { TooltipProvider } from "@/components/ui/tooltip"; const geistSans = Geist({ variable: "--font-geist-sans", @@ -27,7 +28,7 @@ export default function RootLayout({ - {children} + {children} ); diff --git a/src/app/markets/components/PairsCard.tsx b/src/app/markets/components/PairsCard.tsx index ba62ff1..1505d2f 100644 --- a/src/app/markets/components/PairsCard.tsx +++ b/src/app/markets/components/PairsCard.tsx @@ -3,8 +3,15 @@ import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Settings2Icon, ZapIcon } from "lucide-react"; import TokenCard from "./TokenCard"; +import { Token } from "@/modules/tokens/types"; -export default function PairsCard({ title }: { title: string }) { +export default function PairsCard({ + title, + tokens, +}: { + title: string; + tokens: Token[]; +}) { return ( @@ -39,10 +46,12 @@ export default function PairsCard({ title }: { title: string }) { - - + + {tokens.map((token) => ( +
+ +
+ ))}
); diff --git a/src/app/markets/components/TokenCard.tsx b/src/app/markets/components/TokenCard.tsx index 9ba14dd..51e0fdd 100644 --- a/src/app/markets/components/TokenCard.tsx +++ b/src/app/markets/components/TokenCard.tsx @@ -1,5 +1,7 @@ import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; +import MinimalTooltip from "@/components/utils/MinimalTooltip"; +import { humanizeNumber } from "@/lib/renderUtils"; import { cn } from "@/lib/utils"; import { Token, TokenLiveData } from "@/modules/tokens/types"; import { @@ -10,12 +12,14 @@ import { CrosshairIcon, EyeIcon, GhostIcon, - IconNode, LucideIcon, + UserIcon, UsersIcon, UserStarIcon, ZapIcon, } from "lucide-react"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; export default function TokenCard({ token }: { token: Token }) { const live: TokenLiveData = { @@ -26,53 +30,158 @@ export default function TokenCard({ token }: { token: Token }) { bundleHold: 3, }; + const router = useRouter(); + return ( -
-
- {token.logoURI ? ( - Token - ) : ( -
- +
{ + if (e.ctrlKey || e.metaKey) { + window.open(`/token/${token.mint}`, "_blank", "noopener,noreferrer"); + } else { + router.push(`/token/${token.mint}`); + } + }} + onContextMenu={() => + window.open(`/token/${token.mint}`, "_blank", "noopener,noreferrer") + } + > + {/* Left: logo */} +
+
+ {token.logoURI ? ( + Token + ) : ( +
+ +
+ )} +
+ + {/* Main content */} +
+ {/* Symbol + name */} +
+

{token.symbol}

+

{ + e.preventDefault(); + e.stopPropagation(); + navigator.clipboard.writeText(token.mint); + }} + > + {token.name} + +

+
+ + {/* Stats */} +
+

20m

+ + +

+ + 10 +

+
+ + +

+ + 10 +

+
+
+ + {/* Twitter */} +
+ {token.twitterPost ? ( + <> + + e.stopPropagation()} + > + by @{token.twitterPost.author?.username} + + + + +

+ + {humanizeNumber(token.twitterPost.author?.followers)} +

+
+ + ) : ( + by @username + )} +
+ + {/* Badges */} +
+ + + + + + + + + + + + + + + + + + +
- )} -

-
-
-
-

{token.symbol}

-

- {token.name} -

-
-
-

20m

-

- - 10 -

-

- - 10 -

-
-
- - - - -
-
- - -
diff --git a/src/app/markets/page.tsx b/src/app/markets/page.tsx index 8aa6cca..93d6d14 100644 --- a/src/app/markets/page.tsx +++ b/src/app/markets/page.tsx @@ -9,10 +9,58 @@ export default function Markets() {
-
- - - +
+ + +
diff --git a/src/app/page.tsx b/src/app/page.tsx index 5776a87..9b5b65d 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,3 +1,146 @@ -export default function Home() { - return
hello world
; +import Link from "next/link"; + +export default function Landing() { + return ( +
+ {/* Background gradients */} +
+
+
+
+ + {/* Hero */} +
+
+

+ Trade memecoins
+ + without trading blind + +

+ +

+ Nexa filters noise, intercepts high-rug setups, and executes faster, + so you spend less time guessing and more time surviving. +

+ +
+ + + + + + +
+
+
+ + {/* Live signal strip */} + {/*
+
+ 🟢 12 rugs intercepted today + ⚡ Median execution: 420ms + 📉 Top 10 holder risk flagged + 🔍 Bundler detected pre-launch +
+
*/} + + {/* Why Nexa */} +
+
+
+

Risk-aware by default

+

+ Every trade is evaluated against holder concentration, bundlers, + deployer behavior, and liquidity signals, before execution. +

+
+ +
+

AI where it matters

+

+ No magic predictions. Just automated checks that experienced + traders already do, instantly and consistently. +

+
+ +
+

Built for speed

+

+ Optimized request batching, Solana-native execution, and Jupiter + routing keep latency low even during peak volume. +

+
+
+
+ + {/* Risk interception highlight */} +
+
+

+ Nexa can stop you before you buy a rug +

+

+ When high-risk patterns are detected, Nexa blocks execution by + default and tells you exactly why. If you still want in, that's your + call. But it won't be blind. +

+
+
+ + {/* How it works */} +
+

How it works

+ +
+
+ + 1. Detect + + New pairs, migrations, and liquidity events are tracked in real + time. +
+
+ + 2. Analyze + + Risk signals, holder distribution, and deployer behavior are scored. +
+
+ + 3. Decide + + AI filters or manual overrides determine execution eligibility. +
+
+ + 4. Execute + + Trades are routed through Jupiter with minimal latency. +
+
+
+ + {/* Fees & alignment */} +
+
+

+ Fees that scale with success +

+

+ Nexa charges a small platform fee on executed trades, with optional + AI and quant features available per-use. No subscriptions. No hidden + incentives. +

+
+
+
+ ); } diff --git a/src/components/layout/Navbar.tsx b/src/components/layout/Navbar.tsx index d6b0494..6cf907b 100644 --- a/src/components/layout/Navbar.tsx +++ b/src/components/layout/Navbar.tsx @@ -1,3 +1,5 @@ +"use client"; + import Link from "next/link"; import { Button } from "../ui/button"; import { @@ -8,6 +10,8 @@ import { WalletIcon, } from "lucide-react"; import { SolanaLogo } from "../logos"; +import { cn } from "@/lib/utils"; +import { usePathname } from "next/navigation"; const links = [ { @@ -23,6 +27,7 @@ const links = [ export default function Navbar() { const personalItemClass = "rounded-full bg-card p-2! aspect-square group hover:bg-accent/20 hover:text-accent"; + const pathname = usePathname(); return (