feat: beginner-first funnel — plain-language guidance from landing to first trade

A newcomer who can't get from install to a running trade in minutes churns.
This pass removes every jargon wall on that path:

- Landing hero: primary CTA is now 'START THE AUTOPILOT' (routes into the
  guided flow; logged-out users get the guest walkthrough) with a
  plain-language promise line — self-hosted, ~$13 to start, no API keys.
  'CREATE STOCK TRADER' demoted to a 'SEE IT WORK' scroll button.
- Deploy section: 'high-frequency trading node / sandboxed execution env'
  copy replaced with plain words plus the first-five-minutes checklist
  (register → fund $1 + $12 → press start).
- Config page: the guided launch panel now renders FIRST for anyone without
  a running autopilot; the config grid becomes detail below. Steps renamed
  to 'Step 1 · Fund the AI wallet ($1+)' etc., each explained in one plain
  sentence with explicit dollar amounts and safety notes ('it can never
  withdraw your money').
- Every AI-wallet action (deposit, create, preflight fix-links) now lands on
  the /welcome page with the QR code and auto-refreshing balance instead of
  the key-config modal.
- README: first-run three-step guide under the install command (banner asset
  included); six dead landing components removed.

Tests: 128 web tests green; funnel click-verified logged-out and logged-in.
This commit is contained in:
tinkle-community
2026-07-07 20:22:59 +09:00
parent c53a563bff
commit c1b660bb45
12 changed files with 271 additions and 1199 deletions

323
README.md
View File

@@ -1,22 +1,14 @@
<p align="center"><strong>Backed by <a href="https://vergex.trade">vergex.trade</a></strong></p>
<h1 align="center">NOFX</h1>
<p align="center">
<strong>AI trading terminal for global markets.</strong><br/>
<strong>Research, strategy generation, execution, and monitoring for US stocks, commodities, forex, and crypto.</strong>
<img src="docs/assets/nofx-banner.svg" alt="NOFX — AI trading terminal" width="100%"/>
</p>
<p align="center">
<a href="https://github.com/NoFxAiOS/nofx/stargazers"><img src="https://img.shields.io/github/stars/NoFxAiOS/nofx?style=for-the-badge" alt="Stars"></a>
<a href="https://github.com/NoFxAiOS/nofx/releases"><img src="https://img.shields.io/github/v/release/NoFxAiOS/nofx?style=for-the-badge" alt="Release"></a>
<a href="https://github.com/NoFxAiOS/nofx/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-AGPL--3.0-blue.svg?style=for-the-badge" alt="License"></a>
<a href="https://t.me/nofx_dev_community"><img src="https://img.shields.io/badge/Telegram-Community-blue?style=for-the-badge&logo=telegram" alt="Telegram"></a>
</p>
<p align="center">
<a href="https://golang.org/"><img src="https://img.shields.io/badge/Go-1.21+-00ADD8?style=flat&logo=go" alt="Go"></a>
<a href="https://reactjs.org/"><img src="https://img.shields.io/badge/React-18+-61DAFB?style=flat&logo=react" alt="React"></a>
<a href="https://github.com/NoFxAiOS/nofx/stargazers"><img src="https://img.shields.io/github/stars/NoFxAiOS/nofx?style=flat-square&labelColor=1A1813&color=E0483B" alt="Stars"></a>
<a href="https://github.com/NoFxAiOS/nofx/releases"><img src="https://img.shields.io/github/v/release/NoFxAiOS/nofx?style=flat-square&labelColor=1A1813&color=E0483B" alt="Release"></a>
<a href="https://github.com/NoFxAiOS/nofx/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-AGPL--3.0-E0483B?style=flat-square&labelColor=1A1813" alt="License"></a>
<a href="https://t.me/nofx_dev_community"><img src="https://img.shields.io/badge/telegram-community-E0483B?style=flat-square&labelColor=1A1813&logo=telegram&logoColor=white" alt="Telegram"></a>
</p>
<p align="center">
@@ -29,23 +21,29 @@
<a href="docs/i18n/vi/README.md">Tiếng Việt</a>
</p>
---
<br/>
NOFX is an open-source AI trading terminal for active traders who want one workspace for market research, strategy development, execution, and portfolio monitoring.
NOFX is an open-source trading terminal where the strategy is a language model. Each trader runs a continuous loop — read market structure, decide, execute, record the reasoning — while a Go runtime clamps every order to hard risk limits the model cannot override.
The product is built around global liquid markets: US equities, commodity contracts, FX pairs, and digital assets. The AI layer helps translate market intent into watchlists, signals, strategy logic, risk controls, and execution workflows.
Traders compose freely: any model, any of nine exchanges, any strategy. Run several side by side and compare them on a public leaderboard by realized return. Everything runs on your own machine; exchange credentials are encrypted at rest and never leave it.
```bash
curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash
```
Open **http://127.0.0.1:3000**.
The terminal opens at `http://127.0.0.1:3000`.
---
**First run**
1. Register — the first account becomes the owner of the instance.
2. Follow the guided launch: put **$1+ USDC** (Base network) in the AI fee wallet it creates for you, then connect Hyperliquid and deposit **$12+ USDC** to trade with.
3. Start **Autopilot**. The AI scans the market every few minutes and trades on its own; every decision appears on the dashboard as it happens. Stop it anytime with one click.
<br/>
## Register exchanges
Use the links below to open trading accounts for crypto and supported US stock, FX, and commodity derivative markets. These routes are part of NOFX partner programs and may include fee discounts or referral benefits.
NOFX is free and open source. Opening an account through the partner links below carries reduced trading fees and funds continued development.
| Exchange | Status | Register with fee discount |
| :---------------------------------------------------------------------------------------------------------------------------- | :----: | :---------------------------------------------------------------------------------- |
@@ -59,59 +57,47 @@ Use the links below to open trading accounts for crypto and supported US stock,
| <img src="web/public/exchange-icons/aster.svg" width="20" height="20" style="vertical-align: middle;"/> **Aster** | ✅ | [Register](https://www.asterdex.com/en/referral/fdfc0e) |
| <img src="web/public/exchange-icons/lighter.png" width="20" height="20" style="vertical-align: middle;"/> **Lighter** | ✅ | [Register](https://app.lighter.xyz/?referral=68151432) |
---
<br/>
## Quick demo
## Demo
https://github.com/user-attachments/assets/3310f495-14c5-4586-a1cc-3d32e44aa505
---
<br/>
## Markets
## The model proposes. The runtime disposes.
**US Stocks · Commodities · Forex · Crypto**
Decisions come from a language model reading live market structure — candles, EMA/MACD/RSI/ATR/Bollinger, open interest, net flow, signal rankings. Execution does not.
NOFX organizes research, strategy construction, execution, and monitoring around multi-asset workflows instead of single-venue screens.
Every order passes through limits enforced in code, outside the model's reach:
---
| | |
| :----------------------- | :--------------------------------------------------------------------------------- |
| Position limits | Max concurrent positions, notional capped as a ratio of equity, one position per symbol |
| Leverage clamps | Hard caps applied at order-sizing time, independent of what the model requests |
| Exchange-side protection | Stop-loss and take-profit placed on the exchange immediately after every entry |
| Drawdown auto-close | Profitable positions that give back too much from their peak are closed |
| Trade throttling | Minimum hold times, per-symbol re-entry cooldowns, per-cycle and per-hour entry limits |
| Safe mode | Repeated model failures block new entries until the model recovers |
| Launch preflight | Model access, wallet funds, strategy, and exchange balances verified before a trader may start |
## AI model access
Each decision is stored with the model's full reasoning. There is no position without a paper trail.
NOFX routes AI inference through [Claw402](https://claw402.ai) automatically. Users do not need to configure model providers, manage API keys, or maintain separate AI accounts. The terminal accesses supported models on demand through Claw402's pay-as-you-go infrastructure, with traffic routed through the official discounted channel.
<br/>
| Provider | Access |
| :------- | :----- |
| **Claw402** | [Access pay-as-you-go AI models with official discount](https://claw402.ai) |
## Terminal
---
## Capabilities
| Capability | Description |
| :-------------------------- | :-------------------------------------------------------------------------- |
| **AI trading terminal** | Unified workspace for US stocks, commodities, forex, and crypto workflows |
| **AI model access** | Unified model access through Claw402-supported providers |
| **Exchange connectivity** | Binance, Bybit, OKX, Hyperliquid, Bitget, KuCoin, Gate, Aster, and Lighter |
| **Strategy Studio** | Market universes, indicators, risk controls, and strategy logic |
| **Model competition** | Compare model-driven traders with live performance and leaderboard tracking |
| **Telegram agent** | Control and monitor the trading assistant through chat |
| **Portfolio dashboard** | Positions, P/L, execution history, and model decision logs |
---
## Screenshots
| | |
| :--- | :--- |
| **Autopilot** | Guided launch: fund, connect, deposit, start — with server-side preflight throughout |
| **Strategy Studio** | Style presets, coin universes, indicators, leverage, entry confidence, custom prompts |
| **Competition** | Public leaderboard ranked by realized return, each entry attributed to its model |
| **Dashboard** | Live positions, orders, statistics, and the reasoning behind every decision |
<details>
<summary><b>Config Page</b></summary>
<summary>Screenshots</summary>
| Configuration | Traders List |
| :----------------------------------------------------------: | :----------------------------------------------------------: |
| <img src="screenshots/config-ai-exchanges.png" width="400"/> | <img src="screenshots/config-traders-list.png" width="400"/> |
</details>
<details>
<summary><b>Dashboard</b></summary>
<br/>
| Overview | Market Chart |
| :-----------------------------------------------------: | :-------------------------------------------------------------: |
@@ -121,131 +107,51 @@ NOFX routes AI inference through [Claw402](https://claw402.ai) automatically. Us
| :--------------------------------------------------------------: | :-----------------------------------------------------------------: |
| <img src="screenshots/dashboard-trading-stats.png" width="400"/> | <img src="screenshots/dashboard-position-history.png" width="400"/> |
| Positions | Trader Details |
| :----------------------------------------------------------: | :---------------------------------------------------: |
| <img src="screenshots/dashboard-positions.png" width="400"/> | <img src="screenshots/details-page.png" width="400"/> |
</details>
<details>
<summary><b>Strategy Studio</b></summary>
| Strategy Editor | Indicators Config |
| :------------------------------------------------------: | :----------------------------------------------------------: |
| <img src="screenshots/strategy-studio.png" width="400"/> | <img src="screenshots/strategy-indicators.png" width="400"/> |
</details>
<details>
<summary><b>Competition</b></summary>
| Competition Mode |
| :-------------------------------------------------------: |
| <img src="screenshots/competition-page.png" width="400"/> |
| Competition | Configuration |
| :-------------------------------------------------------: | :-----------------------------------------------------------: |
| <img src="screenshots/competition-page.png" width="400"/> | <img src="screenshots/config-ai-exchanges.png" width="400"/> |
</details>
---
<br/>
## Install
## Models
### Linux / macOS
Eight providers with your own keys — DeepSeek, OpenAI, Claude, Qwen, Gemini, Grok, Kimi, MiniMax — including custom endpoints and model names.
```bash
curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash
```
Or no keys at all: [Claw402](https://claw402.ai) meters model usage per call in USDC over the x402 protocol. A wallet on Base replaces every API key.
### Railway (Cloud)
| Provider | Access |
| :------- | :----- |
| **Claw402** | [Pay-as-you-go AI models with official discount](https://claw402.ai) |
[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/nofx?referralCode=nofx)
## Markets
### Docker
Crypto perpetuals on all nine exchanges. On Hyperliquid, the same runtime also trades tokenized US equities, commodities, indices, FX, and pre-IPO perps — TSLA, NVDA, GOLD, SPX, EUR, OPENAI — alongside crypto.
```bash
curl -O https://raw.githubusercontent.com/NoFxAiOS/nofx/main/docker-compose.prod.yml
docker compose -f docker-compose.prod.yml up -d
```
### Windows
Install [Docker Desktop](https://www.docker.com/products/docker-desktop/), then:
```powershell
curl -o docker-compose.prod.yml https://raw.githubusercontent.com/NoFxAiOS/nofx/main/docker-compose.prod.yml
docker compose -f docker-compose.prod.yml up -d
```
### From Source
```bash
# Prerequisites: Go 1.21+, Node.js 18+, TA-Lib
# macOS: brew install ta-lib
# Ubuntu: sudo apt-get install libta-lib0-dev
git clone https://github.com/NoFxAiOS/nofx.git && cd nofx
go build -o nofx && ./nofx # backend
cd web && npm install && npm run dev # frontend (new terminal)
```
### Update
```bash
curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash
```
---
## Setup
**Beginner mode**: Guided onboarding walks new users through model selection, exchange connection, strategy setup, and first deployment.
**Advanced mode**:
1. Configure AI model access
2. Connect exchange credentials
3. Build or import a strategy
4. Create an AI trader profile
5. Launch, monitor, and iterate from the dashboard
All configuration is available from the web UI at **http://127.0.0.1:3000**.
---
## Deploy to server
**HTTP deployment:**
```bash
curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash
# Access via http://YOUR_IP:3000
```
**HTTPS via Cloudflare:**
1. Add domain to [Cloudflare](https://dash.cloudflare.com) (free plan)
2. A record → your server IP (Proxied)
3. SSL/TLS → Flexible
4. Set `TRANSPORT_ENCRYPTION=true` in `.env`
---
<br/>
## Architecture
```
NOFX
┌─────────────────────────────────────────────────┐
│ Trading Terminal │
│ React + TypeScript + TradingView │
US Stocks · Commodities · Forex · Crypto
│ React · TypeScript · TradingView │
Dashboard · Strategy Studio · Competition
├─────────────────────────────────────────────────┤
│ API Server (Go) │
│ JWT auth · encrypted credential store │
├──────────────┬──────────────┬───────────────────┤
│ Strategy │ Telegram │ Trader Runtime │
│ Engine │ Agent │ Risk Controls
│ Strategy │ Autopilot │ Trader Runtime │
│ Engine │ Preflight Risk Engine
├──────────────┴──────────────┴───────────────────┤
│ AI Model Layer │
Unified provider access through Claw402
Model routing · payment · execution support
DeepSeek · OpenAI · Claude · Qwen · Gemini
Grok · Kimi · MiniMax · Claw402 (x402 USDC)
├─────────────────────────────────────────────────┤
│ Exchange Connectivity │
│ Binance · Bybit · OKX · Hyperliquid · Bitget │
@@ -253,26 +159,86 @@ curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bas
└─────────────────────────────────────────────────┘
```
---
<br/>
## Docs
## Install
**Linux / macOS**
```bash
curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash
```
**Railway**
[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/nofx?referralCode=nofx)
**Docker**
```bash
curl -O https://raw.githubusercontent.com/NoFxAiOS/nofx/main/docker-compose.prod.yml
docker compose -f docker-compose.prod.yml up -d
```
**Windows** — install [Docker Desktop](https://www.docker.com/products/docker-desktop/), then:
```powershell
curl -o docker-compose.prod.yml https://raw.githubusercontent.com/NoFxAiOS/nofx/main/docker-compose.prod.yml
docker compose -f docker-compose.prod.yml up -d
```
**From source** — Go 1.21+, Node.js 18+:
```bash
git clone https://github.com/NoFxAiOS/nofx.git && cd nofx
go build -o nofx && ./nofx # backend
cd web && npm install && npm run dev # frontend, in a second terminal
```
**Update** — re-run the install script; it upgrades in place.
<details>
<summary>Server deployment</summary>
<br/>
**HTTP**
```bash
curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash
# http://YOUR_IP:3000
```
**HTTPS via Cloudflare**
1. Add the domain to [Cloudflare](https://dash.cloudflare.com) (free plan)
2. A record → server IP, proxied
3. SSL/TLS → Flexible
4. `TRANSPORT_ENCRYPTION=true` in `.env`
</details>
<br/>
## Documentation
| | |
| :------------------------------------------------------ | :------------------------------------ |
| [Getting Started](docs/getting-started/README.md) | Deployment and exchange API guides |
| [Architecture](docs/architecture/README.md) | System design and module index |
| [Strategy Module](docs/architecture/STRATEGY_MODULE.md) | Coin selection, AI prompts, execution |
| [FAQ](docs/faq/README.md) | Common questions |
| [Getting Started](docs/getting-started/README.md) | Deployment guide |
| [FAQ](docs/guides/faq.en.md) | Common questions |
| [Troubleshooting](docs/guides/TROUBLESHOOTING.md) | Diagnosing common issues |
---
## Community
[Telegram](https://t.me/nofx_dev_community) · [Twitter/X](https://x.com/vergex_ai) · [Issues](https://github.com/NoFxAiOS/nofx/issues) · [vergex.trade](https://vergex.trade) · [Live dashboard](https://vergex.trade/explore)
## Contributing
See [Contributing Guide](CONTRIBUTING.md), [Code of Conduct](CODE_OF_CONDUCT.md), and [Security Policy](SECURITY.md).
Code, documentation, translations, and bug reports are all welcome — see the [Contributing Guide](CONTRIBUTING.md), [Code of Conduct](CODE_OF_CONDUCT.md), and [Security Policy](SECURITY.md).
### Contributor Airdrop Program
NOFX tracks meaningful contributions and intends to reward contributors as the ecosystem grows. Priority issues carry higher reward weight.
NOFX tracks meaningful contributions and intends to reward contributors as the ecosystem grows. Priority issues carry higher weight.
| Contribution | Weight |
| :---------------- | :----: |
@@ -283,20 +249,9 @@ NOFX tracks meaningful contributions and intends to reward contributors as the e
| Bug Reports | ★★ |
| Documentation | ★★ |
---
## Links
| | |
| :-------- | :---------------------------------------------------- |
| Website | [vergex.trade](https://vergex.trade) |
| Dashboard | [vergex.trade/explore](https://vergex.trade/explore) |
| Telegram | [nofx_dev_community](https://t.me/nofx_dev_community) |
| Twitter | [@vergex_ai](https://x.com/vergex_ai) |
> **Risk warning**: Automated trading involves substantial risk. Use appropriate position sizing, understand each exchange venue, and do not trade funds you cannot afford to lose.
---
<a href="https://github.com/NoFxAiOS/nofx/graphs/contributors">
<img src="https://contrib.rocks/image?repo=NoFxAiOS/nofx" alt="Contributors"/>
</a>
## Sponsors
@@ -314,8 +269,14 @@ NOFX tracks meaningful contributions and intends to reward contributors as the e
[Become a sponsor](https://github.com/sponsors/NoFxAiOS)
<br/>
If NOFX is useful to you, a star helps other traders find it.
[![Star History Chart](https://api.star-history.com/svg?repos=NoFxAiOS/nofx&type=Date)](https://star-history.com/#NoFxAiOS/nofx&Date)
## License
[AGPL-3.0](LICENSE)
[![Star History Chart](https://api.star-history.com/svg?repos=NoFxAiOS/nofx&type=Date)](https://star-history.com/#NoFxAiOS/nofx&Date)
<sub>Automated trading involves substantial risk. AI-driven strategies are experimental and can lose money. Size positions appropriately, understand each venue, and never trade funds you cannot afford to lose. Full [disclaimer](DISCLAIMER.md).</sub>

View File

@@ -0,0 +1,44 @@
<svg width="1200" height="380" viewBox="0 0 1200 380" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="frame"><rect width="1200" height="380" rx="14"/></clipPath>
<pattern id="dots" width="28" height="28" patternUnits="userSpaceOnUse">
<circle cx="1.5" cy="1.5" r="1.2" fill="#1A1813" opacity="0.07"/>
</pattern>
</defs>
<g clip-path="url(#frame)">
<rect width="1200" height="380" fill="#F1ECE2"/>
<rect width="1200" height="380" fill="url(#dots)"/>
<!-- title bar -->
<rect width="1200" height="52" fill="#F7F4EC"/>
<line x1="0" y1="52.5" x2="1200" y2="52.5" stroke="#1A1813" stroke-opacity="0.14"/>
<circle cx="30" cy="26" r="6" fill="#D6433A" opacity="0.9"/>
<circle cx="54" cy="26" r="6" fill="#B4B2A9"/>
<circle cx="78" cy="26" r="6" fill="#2E8B57" opacity="0.9"/>
<text x="600" y="31" text-anchor="middle" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace" font-size="13" letter-spacing="2" fill="#8A8478">nofx — ai trading terminal</text>
<!-- wordmark -->
<text x="64" y="182" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace" font-size="92" font-weight="700" letter-spacing="4" fill="#1A1813">NOFX<tspan fill="#E0483B">_</tspan></text>
<text x="64" y="228" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace" font-size="17" letter-spacing="9" fill="#6B6557">AI TRADING TERMINAL</text>
<text x="64" y="286" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace" font-size="15" fill="#6B6557">Language models make the decisions.</text>
<text x="64" y="312" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace" font-size="15" fill="#6B6557">A Go runtime enforces the limits.</text>
<!-- divider -->
<line x1="672" y1="84" x2="672" y2="344" stroke="#1A1813" stroke-opacity="0.12"/>
<!-- session log -->
<g font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace" font-size="14.5">
<text x="712" y="112" fill="#8A8478">$ nofx start</text>
<text x="712" y="146"><tspan fill="#2E8B57"></tspan><tspan fill="#1A1813" dx="10">preflight passed</tspan><tspan fill="#8A8478" dx="10">7/7 checks</tspan></text>
<text x="712" y="180"><tspan fill="#2E8B57"></tspan><tspan fill="#1A1813" dx="10">trader online</tspan><tspan fill="#8A8478" dx="10">deepseek · hyperliquid</tspan></text>
<text x="712" y="222"><tspan fill="#8A8478">decision</tspan><tspan fill="#E0483B" dx="12" font-weight="700">OPEN_LONG</tspan><tspan fill="#1A1813" dx="12">BTC ×3</tspan></text>
<text x="712" y="252"><tspan fill="#8A8478">reason</tspan><tspan fill="#6B6557" dx="12">oi rising · funding neutral · 4h breakout</tspan></text>
<text x="712" y="282"><tspan fill="#8A8478">risk</tspan><tspan fill="#6B6557" dx="12">sl 2.5% · tp +5.0% · placed on exchange</tspan></text>
<text x="712" y="324"><tspan fill="#8A8478">equity</tspan><tspan fill="#1A1813" dx="12">$12,847</tspan><tspan fill="#8A8478" dx="18">pnl</tspan><tspan fill="#2E8B57" dx="12">+4.2%</tspan></text>
</g>
</g>
<rect x="0.5" y="0.5" width="1199" height="379" rx="14" fill="none" stroke="#1A1813" stroke-opacity="0.22"/>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -1,157 +0,0 @@
import { motion } from 'framer-motion'
import { Terminal, Shield, Cpu, BarChart3 } from 'lucide-react'
import { t, Language } from '../../i18n/translations'
interface AboutSectionProps {
language: Language
}
export default function AboutSection({ language }: AboutSectionProps) {
const features = [
{
icon: Shield,
title: language === 'zh' ? 'Full Control' : 'Full Control',
desc: language === 'zh' ? 'Self-hosted, data secure' : 'Self-hosted, data secure',
},
{
icon: Cpu,
title: language === 'zh' ? 'Multi-AI Support' : 'Multi-AI Support',
desc: language === 'zh' ? 'DeepSeek, GPT, Claude...' : 'DeepSeek, GPT, Claude...',
},
{
icon: BarChart3,
title: language === 'zh' ? 'Real-time Monitor' : 'Real-time Monitor',
desc: language === 'zh' ? 'Visual trading dashboard' : 'Visual trading dashboard',
},
]
return (
<section className="py-24 relative overflow-hidden" style={{ background: '#F1ECE2' }}>
{/* Background Decoration */}
<div
className="absolute top-0 right-0 w-96 h-96 rounded-full blur-3xl opacity-30"
style={{ background: 'radial-gradient(circle, rgba(224, 72, 59, 0.08) 0%, transparent 70%)' }}
/>
<div className="max-w-6xl mx-auto px-4">
<div className="grid lg:grid-cols-2 gap-16 items-center">
{/* Left Content */}
<motion.div
initial={{ opacity: 0, x: -30 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
>
<motion.div
className="inline-flex items-center gap-2 px-3 py-1.5 rounded-full mb-6"
style={{
background: 'rgba(224, 72, 59, 0.1)',
border: '1px solid rgba(224, 72, 59, 0.2)',
}}
>
<Terminal className="w-4 h-4" style={{ color: '#E0483B' }} />
<span className="text-xs font-medium" style={{ color: '#E0483B' }}>
{t('aboutNofx', language)}
</span>
</motion.div>
<h2 className="text-4xl lg:text-5xl font-bold mb-6" style={{ color: '#1A1813' }}>
{t('whatIsNofx', language)}
</h2>
<p className="text-lg mb-8 leading-relaxed" style={{ color: '#8A8478' }}>
{t('nofxNotAnotherBot', language)} {t('nofxDescription1', language)}
</p>
{/* Feature Pills */}
<div className="flex flex-wrap gap-3">
{features.map((feature, index) => (
<motion.div
key={feature.title}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay: index * 0.1 }}
className="flex items-center gap-3 px-4 py-3 rounded-xl"
style={{
background: '#F7F4EC',
border: '1px solid rgba(26, 24, 19, 0.14)',
}}
>
<div
className="w-10 h-10 rounded-lg flex items-center justify-center"
style={{ background: 'rgba(224, 72, 59, 0.1)' }}
>
<feature.icon className="w-5 h-5" style={{ color: '#E0483B' }} />
</div>
<div>
<div className="text-sm font-semibold" style={{ color: '#1A1813' }}>
{feature.title}
</div>
<div className="text-xs" style={{ color: '#8A8478' }}>
{feature.desc}
</div>
</div>
</motion.div>
))}
</div>
</motion.div>
{/* Right - Terminal */}
<motion.div
initial={{ opacity: 0, x: 30 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: 0.2 }}
>
<div
className="rounded-2xl overflow-hidden"
style={{
background: '#F7F4EC',
border: '1px solid rgba(26, 24, 19, 0.14)',
boxShadow: '0 6px 24px rgba(26, 24, 19, 0.12)',
}}
>
{/* Terminal Header */}
<div
className="flex items-center gap-2 px-4 py-3"
style={{ background: '#E8E2D5', borderBottom: '1px solid rgba(26, 24, 19, 0.14)' }}
>
<div className="flex gap-2">
<div className="w-3 h-3 rounded-full" style={{ background: '#D6433A' }} />
<div className="w-3 h-3 rounded-full" style={{ background: '#E0483B' }} />
<div className="w-3 h-3 rounded-full" style={{ background: '#2E8B57' }} />
</div>
<span className="text-xs ml-2" style={{ color: '#8A8478' }}>terminal</span>
</div>
{/* Terminal Content */}
<div className="p-6 font-mono text-sm space-y-2">
<div style={{ color: '#8A8478' }}>$ git clone https://github.com/NoFxAiOS/nofx.git</div>
<div style={{ color: '#8A8478' }}>$ cd nofx && chmod +x start.sh</div>
<div style={{ color: '#8A8478' }}>$ ./start.sh start --build</div>
<div className="pt-2" style={{ color: '#E0483B' }}>
{t('startupMessages1', language)}
</div>
<div style={{ color: '#2E8B57' }}>
{t('startupMessages2', language)}
</div>
<div style={{ color: '#2E8B57' }}>
{t('startupMessages3', language)}
</div>
<motion.div
className="flex items-center gap-2 pt-2"
animate={{ opacity: [1, 0.5, 1] }}
transition={{ duration: 1.5, repeat: Infinity }}
>
<span style={{ color: '#E0483B' }}></span>
<span style={{ color: '#1A1813' }}>_</span>
</motion.div>
</div>
</div>
</motion.div>
</div>
</div>
</section>
)
}

View File

@@ -1,29 +0,0 @@
import { useRef } from 'react'
import { motion, useInView } from 'framer-motion'
export default function AnimatedSection({
children,
id,
backgroundColor = '#F1ECE2',
}: {
children: React.ReactNode
id?: string
backgroundColor?: string
}) {
const ref = useRef(null)
const isInView = useInView(ref, { once: true, margin: '-100px' })
return (
<motion.section
id={id}
ref={ref}
className="py-20 px-4"
style={{ background: backgroundColor }}
initial={{ opacity: 0 }}
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
transition={{ duration: 0.6 }}
>
{children}
</motion.section>
)
}

View File

@@ -1,158 +0,0 @@
import { motion } from 'framer-motion'
import { MessageCircle, Heart, Repeat2, ExternalLink } from 'lucide-react'
import { Language } from '../../i18n/translations'
interface TweetProps {
quote: string
authorName: string
handle: string
avatarUrl: string
tweetUrl: string
delay: number
}
function TweetCard({ quote, authorName, handle, avatarUrl, tweetUrl, delay }: TweetProps) {
return (
<motion.a
href={tweetUrl}
target="_blank"
rel="noopener noreferrer"
className="block p-5 rounded-2xl transition-all duration-300 group"
style={{
background: '#F7F4EC',
border: '1px solid rgba(26, 24, 19, 0.14)',
}}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay }}
whileHover={{
y: -4,
borderColor: 'rgba(224, 72, 59, 0.3)',
}}
>
{/* Header */}
<div className="flex items-start justify-between mb-3">
<div className="flex items-center gap-3">
<img
src={avatarUrl}
alt={authorName}
className="w-10 h-10 rounded-full object-cover"
style={{ border: '2px solid rgba(26, 24, 19, 0.14)' }}
/>
<div>
<div className="font-semibold text-sm" style={{ color: '#1A1813' }}>
{authorName}
</div>
<div className="text-xs" style={{ color: '#8A8478' }}>
{handle}
</div>
</div>
</div>
{/* X Logo */}
<div
className="w-6 h-6 flex items-center justify-center opacity-50 group-hover:opacity-100 transition-opacity"
style={{ color: '#1A1813' }}
>
<svg viewBox="0 0 24 24" className="w-4 h-4" fill="currentColor">
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
</svg>
</div>
</div>
{/* Content */}
<p
className="text-sm leading-relaxed mb-4 line-clamp-4"
style={{ color: '#1A1813' }}
>
{quote}
</p>
{/* Footer */}
<div className="flex items-center gap-6 pt-3" style={{ borderTop: '1px solid rgba(26, 24, 19, 0.14)' }}>
<div className="flex items-center gap-1.5 text-xs" style={{ color: '#8A8478' }}>
<MessageCircle className="w-3.5 h-3.5" />
<span>Reply</span>
</div>
<div className="flex items-center gap-1.5 text-xs" style={{ color: '#8A8478' }}>
<Repeat2 className="w-3.5 h-3.5" />
<span>Repost</span>
</div>
<div className="flex items-center gap-1.5 text-xs" style={{ color: '#8A8478' }}>
<Heart className="w-3.5 h-3.5" />
<span>Like</span>
</div>
<div className="ml-auto opacity-0 group-hover:opacity-100 transition-opacity">
<ExternalLink className="w-3.5 h-3.5" style={{ color: '#E0483B' }} />
</div>
</div>
</motion.a>
)
}
interface CommunitySectionProps {
language?: Language
}
export default function CommunitySection({ language }: CommunitySectionProps) {
const tweets: TweetProps[] = []
return (
<section className="py-24 relative" style={{ background: '#F1ECE2' }}>
{/* Background Decoration */}
<div
className="absolute right-0 top-1/2 -translate-y-1/2 w-96 h-96 rounded-full blur-3xl opacity-20"
style={{ background: 'radial-gradient(circle, rgba(224, 72, 59, 0.08) 0%, transparent 70%)' }}
/>
<div className="max-w-6xl mx-auto px-4 relative z-10">
{/* Header */}
<motion.div
className="text-center mb-12"
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
>
<h2 className="text-4xl lg:text-5xl font-bold mb-4" style={{ color: '#1A1813' }}>
{language === 'zh' ? 'Community Voices' : 'Community Voices'}
</h2>
<p className="text-lg" style={{ color: '#8A8478' }}>
{language === 'zh' ? 'See what others are saying' : 'See what others are saying'}
</p>
</motion.div>
{/* Tweet Grid */}
<div className="grid md:grid-cols-3 gap-5">
{tweets.map((tweet, idx) => (
<TweetCard key={idx} {...tweet} />
))}
</div>
{/* CTA */}
<motion.div
className="text-center mt-12"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
>
<a
href="https://x.com/vergex_ai"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 px-6 py-3 rounded-xl font-medium transition-all hover:scale-105"
style={{
background: 'rgba(224, 72, 59, 0.1)',
color: '#E0483B',
border: '1px solid rgba(224, 72, 59, 0.3)',
}}
>
<svg viewBox="0 0 24 24" className="w-5 h-5" fill="currentColor">
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
</svg>
{language === 'zh' ? 'Follow us on X' : 'Follow us on X'}
</a>
</motion.div>
</div>
</section>
)
}

View File

@@ -1,203 +0,0 @@
import { motion } from 'framer-motion'
import { Brain, Swords, BarChart3, Shield, Blocks, LineChart } from 'lucide-react'
import { t, Language } from '../../i18n/translations'
interface FeaturesSectionProps {
language: Language
}
export default function FeaturesSection({ language }: FeaturesSectionProps) {
const features = [
{
icon: Brain,
title: language === 'zh' ? 'AI Strategy Orchestration' : 'AI Strategy Orchestration',
desc: language === 'zh'
? 'Support DeepSeek, GPT, Claude, Qwen and more. Custom prompts, AI autonomously analyzes markets and makes trading decisions'
: 'Support DeepSeek, GPT, Claude, Qwen and more. Custom prompts, AI autonomously analyzes markets and makes trading decisions',
highlight: true,
badge: language === 'zh' ? 'Core' : 'Core',
},
{
icon: Swords,
title: language === 'zh' ? 'Multi-AI Arena' : 'Multi-AI Arena',
desc: language === 'zh'
? 'Multiple AI traders compete in real-time, live PnL leaderboard, automatic survival of the fittest'
: 'Multiple AI traders compete in real-time, live PnL leaderboard, automatic survival of the fittest',
highlight: true,
badge: language === 'zh' ? 'Unique' : 'Unique',
},
{
icon: LineChart,
title: language === 'zh' ? 'Pro Quant Data' : 'Pro Quant Data',
desc: language === 'zh'
? 'Integrated candlesticks, indicators, order book, funding rates, open interest - comprehensive data for AI decisions'
: 'Integrated candlesticks, indicators, order book, funding rates, open interest - comprehensive data for AI decisions',
highlight: true,
badge: language === 'zh' ? 'Pro' : 'Pro',
},
{
icon: Blocks,
title: language === 'zh' ? 'Multi-Exchange Support' : 'Multi-Exchange Support',
desc: language === 'zh'
? 'Binance, OKX, Bybit, Hyperliquid, Aster DEX - one system, multiple exchanges'
: 'Binance, OKX, Bybit, Hyperliquid, Aster DEX - one system, multiple exchanges',
},
{
icon: BarChart3,
title: language === 'zh' ? 'Real-time Dashboard' : 'Real-time Dashboard',
desc: language === 'zh'
? 'Trade monitoring, PnL curves, position analysis, AI decision logs at a glance'
: 'Trade monitoring, PnL curves, position analysis, AI decision logs at a glance',
},
{
icon: Shield,
title: language === 'zh' ? 'Open Source & Self-Hosted' : 'Open Source & Self-Hosted',
desc: language === 'zh'
? 'Fully open source, data stored locally, API keys never leave your server'
: 'Fully open source, data stored locally, API keys never leave your server',
},
]
return (
<section className="py-24 relative" style={{ background: '#F1ECE2' }}>
{/* Background */}
<div
className="absolute inset-0 opacity-[0.04]"
style={{
backgroundImage: `linear-gradient(#E0483B 1px, transparent 1px), linear-gradient(90deg, #E0483B 1px, transparent 1px)`,
backgroundSize: '40px 40px',
}}
/>
<div className="max-w-6xl mx-auto px-4 relative z-10">
{/* Header */}
<motion.div
className="text-center mb-16"
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
>
<h2 className="text-4xl lg:text-5xl font-bold mb-4" style={{ color: '#1A1813' }}>
{t('whyChooseNofx', language)}
</h2>
<p className="text-lg max-w-2xl mx-auto" style={{ color: '#8A8478' }}>
{language === 'zh'
? 'Not just a trading bot, but a complete AI trading operating system'
: 'Not just a trading bot, but a complete AI trading operating system'}
</p>
</motion.div>
{/* Features Grid */}
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-5">
{features.map((feature, index) => (
<motion.div
key={feature.title}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay: index * 0.1 }}
className={`
relative group rounded-2xl p-6 transition-all duration-300
${feature.highlight ? 'md:col-span-1 lg:col-span-1' : ''}
`}
style={{
background: feature.highlight
? 'rgba(224, 72, 59, 0.06)'
: '#F7F4EC',
border: feature.highlight
? '1px solid rgba(224, 72, 59, 0.2)'
: '1px solid rgba(26, 24, 19, 0.14)',
}}
>
{/* Badge */}
{feature.badge && (
<div
className="absolute top-4 right-4 px-2 py-1 rounded text-xs font-medium"
style={{
background: 'rgba(224, 72, 59, 0.15)',
color: '#E0483B',
}}
>
{feature.badge}
</div>
)}
{/* Icon */}
<motion.div
className="w-12 h-12 rounded-xl flex items-center justify-center mb-4"
style={{
background: feature.highlight
? 'rgba(224, 72, 59, 0.15)'
: 'rgba(224, 72, 59, 0.1)',
border: '1px solid rgba(224, 72, 59, 0.2)',
}}
whileHover={{ scale: 1.1, rotate: 5 }}
>
<feature.icon
className="w-6 h-6"
style={{ color: '#E0483B' }}
/>
</motion.div>
{/* Text */}
<h3
className="text-xl font-bold mb-3"
style={{ color: '#1A1813' }}
>
{feature.title}
</h3>
<p
className="text-sm leading-relaxed"
style={{ color: '#8A8478' }}
>
{feature.desc}
</p>
{/* Hover Glow */}
<div
className="absolute -bottom-10 -right-10 w-32 h-32 rounded-full blur-3xl opacity-0 group-hover:opacity-20 transition-opacity duration-500"
style={{ background: '#E0483B' }}
/>
</motion.div>
))}
</div>
{/* Bottom Stats */}
<motion.div
className="mt-16 grid grid-cols-2 md:grid-cols-4 gap-6"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
>
{[
{ value: '10+', label: language === 'zh' ? 'AI Models' : 'AI Models' },
{ value: '5+', label: language === 'zh' ? 'Exchanges' : 'Exchanges' },
{ value: '24/7', label: language === 'zh' ? 'Auto Trading' : 'Auto Trading' },
{ value: '100%', label: language === 'zh' ? 'Open Source' : 'Open Source' },
].map((stat) => (
<div
key={stat.label}
className="text-center p-4 rounded-xl"
style={{
background: '#F7F4EC',
border: '1px solid rgba(26, 24, 19, 0.14)',
}}
>
<div
className="text-2xl font-bold mb-1"
style={{
color: '#E0483B',
}}
>
{stat.value}
</div>
<div className="text-xs" style={{ color: '#8A8478' }}>
{stat.label}
</div>
</div>
))}
</motion.div>
</div>
</section>
)
}

View File

@@ -1,259 +0,0 @@
import { motion } from 'framer-motion'
import { ArrowRight, Play, Github, Zap } from 'lucide-react'
import { Link } from 'react-router-dom'
import { t, Language } from '../../i18n/translations'
import { useGitHubStats } from '../../hooks/useGitHubStats'
import { useCounterAnimation } from '../../hooks/useCounterAnimation'
import { OFFICIAL_LINKS } from '../../constants/branding'
interface HeroSectionProps {
language: Language
}
export default function HeroSection({ language }: HeroSectionProps) {
const { stars, daysOld, isLoading } = useGitHubStats('NoFxAiOS', 'nofx')
const animatedStars = useCounterAnimation({
start: 0,
end: stars,
duration: 2000,
})
return (
<section className="relative min-h-screen flex items-center justify-center overflow-hidden pt-16">
{/* Animated Background */}
<div className="absolute inset-0 overflow-hidden">
{/* Grid Pattern */}
<div
className="absolute inset-0 opacity-[0.03]"
style={{
backgroundImage: `linear-gradient(#E0483B 1px, transparent 1px), linear-gradient(90deg, #E0483B 1px, transparent 1px)`,
backgroundSize: '60px 60px',
}}
/>
{/* Radial Gradient */}
<div
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[800px] h-[800px] rounded-full"
style={{
background:
'radial-gradient(circle, rgba(224, 72, 59, 0.08) 0%, transparent 70%)',
}}
/>
{/* Floating Orbs */}
<motion.div
className="absolute top-20 right-20 w-32 h-32 rounded-full blur-3xl"
style={{ background: 'rgba(224, 72, 59, 0.12)' }}
animate={{
y: [0, 30, 0],
scale: [1, 1.1, 1],
}}
transition={{ duration: 8, repeat: Infinity, ease: 'easeInOut' }}
/>
<motion.div
className="absolute bottom-40 left-20 w-48 h-48 rounded-full blur-3xl"
style={{ background: 'rgba(224, 72, 59, 0.08)' }}
animate={{
y: [0, -40, 0],
scale: [1, 1.2, 1],
}}
transition={{ duration: 10, repeat: Infinity, ease: 'easeInOut' }}
/>
</div>
<div className="relative z-10 max-w-6xl mx-auto px-4 text-center">
{/* Badge */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
className="inline-flex items-center gap-2 px-4 py-2 rounded-full mb-8"
style={{
background: 'rgba(224, 72, 59, 0.1)',
border: '1px solid rgba(224, 72, 59, 0.3)',
}}
>
<Zap className="w-4 h-4" style={{ color: '#E0483B' }} />
<span className="text-sm font-medium" style={{ color: '#E0483B' }}>
{isLoading ? (
t('githubStarsInDays', language)
) : language === 'zh' ? (
<>
<span className="font-bold tabular-nums">
{(animatedStars / 1000).toFixed(1)}K+
</span>{' '}
GitHub Stars in {daysOld} days
</>
) : (
<>
<span className="font-bold tabular-nums">
{(animatedStars / 1000).toFixed(1)}K+
</span>{' '}
GitHub Stars in {daysOld} days
</>
)}
</span>
</motion.div>
{/* Main Title */}
<motion.h1
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.1 }}
className="text-5xl sm:text-6xl lg:text-7xl font-bold mb-6 leading-tight"
>
<span style={{ color: '#1A1813' }}>{t('heroTitle1', language)}</span>
<br />
<span
className="relative inline-block"
style={{
color: '#E0483B',
}}
>
{t('heroTitle2', language)}
<motion.span
className="absolute -bottom-2 left-0 h-1 rounded-full"
style={{ background: '#E0483B' }}
initial={{ width: 0 }}
animate={{ width: '100%' }}
transition={{ duration: 0.8, delay: 0.8 }}
/>
</span>
</motion.h1>
{/* Description */}
<motion.p
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.2 }}
className="text-lg sm:text-xl max-w-3xl mx-auto mb-10 leading-relaxed"
style={{ color: '#8A8478' }}
>
{t('heroDescription', language)}
</motion.p>
{/* CTA Buttons */}
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.3 }}
className="flex flex-col sm:flex-row items-center justify-center gap-4 mb-12"
>
<motion.div
className="group flex items-center gap-3 px-8 py-4 rounded-xl font-bold text-lg transition-all"
style={{
background: '#E0483B',
color: '#F7F4EC',
boxShadow: '0 4px 24px rgba(224, 72, 59, 0.25)',
}}
whileHover={{
scale: 1.02,
boxShadow: '0 8px 32px rgba(224, 72, 59, 0.35)',
}}
whileTap={{ scale: 0.98 }}
>
<Link to="/competition" className="flex items-center gap-3">
<Play className="w-5 h-5" />
{t('liveCompetition', language) || 'Live Competition'}
<ArrowRight className="w-5 h-5 transition-transform group-hover:translate-x-1" />
</Link>
</motion.div>
<motion.a
href={OFFICIAL_LINKS.github}
target="_blank"
rel="noopener noreferrer"
className="group flex items-center gap-3 px-8 py-4 rounded-xl font-bold text-lg transition-all"
style={{
background: '#F7F4EC',
color: '#1A1813',
border: '1px solid rgba(26, 24, 19, 0.14)',
}}
whileHover={{
scale: 1.02,
background: '#F2EEE4',
borderColor: 'rgba(224, 72, 59, 0.3)',
}}
whileTap={{ scale: 0.98 }}
>
<Github className="w-5 h-5" />
{t('viewSourceCode', language)}
</motion.a>
</motion.div>
{/* Stats Row */}
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.4 }}
className="flex flex-wrap items-center justify-center gap-8 sm:gap-12"
>
{[
{ label: 'GitHub Stars', value: `${(stars / 1000).toFixed(1)}K+` },
{
label: language === 'zh' ? 'Exchanges' : 'Exchanges',
value: '5+',
},
{
label: language === 'zh' ? 'AI Models' : 'AI Models',
value: '10+',
},
{
label: language === 'zh' ? 'Open Source' : 'Open Source',
value: '100%',
},
].map((stat, index) => (
<motion.div
key={stat.label}
className="text-center"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.5 + index * 0.1 }}
>
<div
className="text-3xl sm:text-4xl font-bold mb-1"
style={{
color: '#E0483B',
}}
>
{stat.value}
</div>
<div className="text-sm" style={{ color: '#8A8478' }}>
{stat.label}
</div>
</motion.div>
))}
</motion.div>
{/* Powered By */}
<motion.p
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.6, delay: 0.8 }}
className="mt-16 text-xs"
style={{ color: '#8A8478' }}
>
{t('poweredBy', language)}
</motion.p>
</div>
{/* Scroll Indicator */}
<motion.div
className="absolute bottom-8 left-1/2 -translate-x-1/2"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 1 }}
>
<motion.div
className="w-6 h-10 rounded-full flex justify-center pt-2"
style={{ border: '2px solid rgba(224, 72, 59, 0.3)' }}
animate={{ y: [0, 8, 0] }}
transition={{ duration: 2, repeat: Infinity }}
>
<motion.div
className="w-1.5 h-3 rounded-full"
style={{ background: '#E0483B' }}
/>
</motion.div>
</motion.div>
</section>
)
}

View File

@@ -1,167 +0,0 @@
import { motion } from 'framer-motion'
import { Download, Rocket, TrendingUp, AlertTriangle } from 'lucide-react'
import { t, Language } from '../../i18n/translations'
interface HowItWorksSectionProps {
language: Language
}
export default function HowItWorksSection({ language }: HowItWorksSectionProps) {
const steps = [
{
icon: Download,
number: '01',
title: language === 'zh' ? 'One-Click Deploy' : 'One-Click Deploy',
desc: language === 'zh'
? 'Run a single command on your server to deploy'
: 'Run a single command on your server to deploy',
code: 'curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash',
},
{
icon: Rocket,
number: '02',
title: language === 'zh' ? 'Access Dashboard' : 'Access Dashboard',
desc: language === 'zh'
? 'Access your server via browser'
: 'Access your server via browser',
code: 'http://YOUR_SERVER_IP:3000',
},
{
icon: TrendingUp,
number: '03',
title: language === 'zh' ? 'Start Trading' : 'Start Trading',
desc: language === 'zh'
? 'Create trader, let AI do the work'
: 'Create trader, let AI do the work',
code: language === 'zh' ? 'Configure Model → Exchange → Create Trader' : 'Configure Model → Exchange → Create Trader',
},
]
return (
<section className="py-24 relative overflow-hidden" style={{ background: '#F1ECE2' }}>
{/* Background Decoration */}
<div
className="absolute left-0 top-1/2 -translate-y-1/2 w-96 h-96 rounded-full blur-3xl opacity-20"
style={{ background: 'radial-gradient(circle, rgba(224, 72, 59, 0.12) 0%, transparent 70%)' }}
/>
<div className="max-w-6xl mx-auto px-4 relative z-10">
{/* Header */}
<motion.div
className="text-center mb-16"
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
>
<h2 className="text-4xl lg:text-5xl font-bold mb-4" style={{ color: '#1A1813' }}>
{t('howToStart', language)}
</h2>
<p className="text-lg" style={{ color: '#8A8478' }}>
{t('fourSimpleSteps', language)}
</p>
</motion.div>
{/* Steps Timeline */}
<div className="relative">
{/* Connecting Line */}
<div
className="absolute left-[39px] top-0 bottom-0 w-px hidden lg:block"
style={{ background: 'linear-gradient(to bottom, transparent, rgba(224, 72, 59, 0.3), transparent)' }}
/>
<div className="space-y-6">
{steps.map((step, index) => (
<motion.div
key={step.number}
initial={{ opacity: 0, x: -30 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ delay: index * 0.15 }}
className="relative"
>
<div
className="flex flex-col lg:flex-row items-start gap-6 p-6 rounded-2xl transition-all duration-300 hover:translate-x-2"
style={{
background: '#F7F4EC',
border: '1px solid rgba(26, 24, 19, 0.14)',
}}
>
{/* Number Circle */}
<div className="flex-shrink-0 relative z-10">
<motion.div
className="w-20 h-20 rounded-2xl flex items-center justify-center"
style={{
background: 'linear-gradient(135deg, rgba(224, 72, 59, 0.15) 0%, rgba(224, 72, 59, 0.05) 100%)',
border: '1px solid rgba(224, 72, 59, 0.3)',
}}
whileHover={{ scale: 1.1 }}
>
<step.icon className="w-8 h-8" style={{ color: '#E0483B' }} />
</motion.div>
</div>
{/* Content */}
<div className="flex-grow">
<div className="flex items-center gap-3 mb-2">
<span
className="text-sm font-mono font-bold"
style={{ color: '#E0483B' }}
>
{step.number}
</span>
<h3 className="text-xl font-bold" style={{ color: '#1A1813' }}>
{step.title}
</h3>
</div>
<p className="mb-4" style={{ color: '#8A8478' }}>
{step.desc}
</p>
{/* Code Block */}
<div
className="inline-flex items-center gap-2 px-4 py-2 rounded-lg font-mono text-sm"
style={{
background: '#E8E2D5',
border: '1px solid rgba(26, 24, 19, 0.14)',
}}
>
<span style={{ color: '#8A8478' }}>$</span>
<span style={{ color: '#1A1813' }}>{step.code}</span>
</div>
</div>
</div>
</motion.div>
))}
</div>
</div>
{/* Risk Warning */}
<motion.div
className="mt-12 p-6 rounded-2xl flex items-start gap-4"
style={{
background: 'rgba(224, 72, 59, 0.05)',
border: '1px solid rgba(224, 72, 59, 0.15)',
}}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
>
<div
className="w-12 h-12 rounded-xl flex items-center justify-center flex-shrink-0"
style={{ background: 'rgba(224, 72, 59, 0.1)' }}
>
<AlertTriangle className="w-6 h-6" style={{ color: '#E0483B' }} />
</div>
<div>
<div className="font-semibold mb-2" style={{ color: '#E0483B' }}>
{t('importantRiskWarning', language)}
</div>
<p className="text-sm leading-relaxed" style={{ color: '#8A8478' }}>
{t('riskWarningText', language)}
</p>
</div>
</motion.div>
</div>
</section>
)
}

View File

@@ -31,14 +31,33 @@ export default function DeploymentHub() {
</h2>
<p className="text-nofx-text-muted text-lg leading-relaxed font-light">
Initialize your own high-frequency trading node in seconds.
Our optimized installer handles all dependencies, bringing the trading system online with a single command.
One command on your laptop or any server installs
everything. Open the address it prints, create your
account, and the guided launch takes you to your
first AI trade in about five minutes around $13
is enough to start.
</p>
{/* the first five minutes, in plain words */}
<ol className="space-y-2 pt-2 font-mono text-sm text-nofx-text-muted">
{[
'Register — the first account owns this instance.',
'Fund two small wallets: $1+ for AI fees, $12+ to trade with (guided, with QR codes).',
'Press Start — the AI trades on its own; stop it anytime.',
].map((step, i) => (
<li key={i} className="flex gap-3">
<span className="flex h-5 w-5 shrink-0 items-center justify-center rounded border border-nofx-gold/30 bg-nofx-gold/10 text-[11px] font-bold text-nofx-gold">
{i + 1}
</span>
<span>{step}</span>
</li>
))}
</ol>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 pt-4">
{[
{ icon: Command, label: "One-Line Install", desc: "No configuration needed" },
{ icon: Shield, label: "Secure Core", desc: "Sandboxed execution env" }
{ icon: Command, label: "One-Line Install", desc: "Docker handles every dependency" },
{ icon: Shield, label: "Your Keys Stay Home", desc: "Runs on your machine, keys encrypted locally" }
].map((item, i) => (
<div key={i} className="flex gap-4 items-start p-4 rounded bg-nofx-bg-lighter border border-[rgba(26,24,19,0.14)] hover:border-nofx-gold/30 transition-colors group">
<div className="p-2 rounded bg-nofx-bg-deeper border border-[rgba(26,24,19,0.14)] text-nofx-gold group-hover:bg-nofx-gold/10 transition-colors">

View File

@@ -1,6 +1,7 @@
import { motion } from 'framer-motion'
import { ArrowRight, Shield, Activity, CircuitBoard, Wifi, Globe, Zap, Star, GitFork, Users, MessageCircle } from 'lucide-react'
import { useState, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { useGitHubStats } from '../../../hooks/useGitHubStats'
import AgentTerminal from '../brand/AgentTerminal'
@@ -16,6 +17,7 @@ const tickerLabels: Record<string, string> = {
}
export default function TerminalHero() {
const navigate = useNavigate()
// Real-time price state
const [prices, setPrices] = useState<Record<string, string>>({
@@ -231,17 +233,29 @@ export default function TerminalHero() {
{/* CTA Buttons */}
<div className="flex flex-col sm:flex-row gap-4 w-full justify-center">
<button
onClick={() => document.getElementById('market-scanner')?.scrollIntoView({ behavior: 'smooth' })}
onClick={() => navigate('/traders')}
className="group relative overflow-hidden bg-nofx-gold text-nofx-bg-lighter px-8 py-4 font-bold font-mono tracking-wider hover:scale-105 transition-transform duration-200"
style={{ clipPath: 'polygon(10% 0, 100% 0, 100% 70%, 90% 100%, 0 100%, 0 30%)' }}
>
<span className="relative z-10 flex items-center gap-2">
CREATE STOCK TRADER <ArrowRight className="w-4 h-4" />
START THE AUTOPILOT <ArrowRight className="w-4 h-4" />
</span>
<div className="absolute inset-0 bg-nofx-text/10 translate-y-full group-hover:translate-y-0 transition-transform duration-300"></div>
</button>
<button
onClick={() => document.getElementById('market-scanner')?.scrollIntoView({ behavior: 'smooth' })}
className="px-8 py-4 font-bold font-mono tracking-wider text-nofx-text border border-[rgba(26,24,19,0.2)] rounded hover:border-nofx-gold/50 hover:text-nofx-gold transition-colors"
>
SEE IT WORK
</button>
</div>
{/* Plain-language promise — the anti-jargon line */}
<p className="mt-5 text-sm text-nofx-text-muted font-mono">
Self-hosted &amp; open source · about $13 is enough to start · guided
setup, no API keys first trade in minutes
</p>
{/* Community Stats Row */}
<CommunityStats />

View File

@@ -3,6 +3,7 @@ import { useNavigate, useSearchParams } from 'react-router-dom'
import useSWR from 'swr'
import { api } from '../../lib/api'
import { ApiError } from '../../lib/httpClient'
import { ROUTES } from '../../router/paths'
import type {
TraderInfo,
CreateTraderRequest,
@@ -667,8 +668,9 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
if (!setupTarget) return
if (setupTarget === 'claw402') {
if (supportedModels.length === 0 && allModels.length === 0) return
handleOpenClaw402Config()
// The welcome page shows the deposit QR, auto-creates the wallet if
// needed, and polls the balance — friendlier than the key-config modal.
navigate(ROUTES.welcome)
} else if (setupTarget === 'hyperliquid') {
handleOpenHyperliquidConfig()
} else if (setupTarget === 'hyperliquid-funds') {
@@ -693,6 +695,21 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
await Promise.all([loadConfigs(), mutateTraders()])
}
const hasRunningTrader = (traders || []).some((trader) => trader.is_running)
const launchPanel = (
<AutopilotLaunchPanel
models={allModels}
exchanges={allExchanges}
exchangeAccountStates={exchangeAccountStates}
traders={traders || []}
isLoggedIn={Boolean(user && token)}
language={language}
onRefresh={refreshLaunchState}
onOpenClaw402Config={handleOpenClaw402Config}
onOpenHyperliquidConfig={handleOpenHyperliquidConfig}
/>
)
return (
<DeepVoidBackground className="py-8" disableAnimation>
<div className="w-full px-4 md:px-8 space-y-8 animate-fade-in">
@@ -767,6 +784,10 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
</div>
</div>
{/* Newcomers see the guided launch FIRST — the config grid is detail.
Once an autopilot is running, the running bot takes back the top. */}
{!hasRunningTrader && launchPanel}
{/* Configuration Status Grid */}
<ConfigStatusGrid
configuredModels={configuredModels}
@@ -784,17 +805,7 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
onCopyAddress={handleCopyAddress}
/>
<AutopilotLaunchPanel
models={allModels}
exchanges={allExchanges}
exchangeAccountStates={exchangeAccountStates}
traders={traders || []}
isLoggedIn={Boolean(user && token)}
language={language}
onRefresh={refreshLaunchState}
onOpenClaw402Config={handleOpenClaw402Config}
onOpenHyperliquidConfig={handleOpenHyperliquidConfig}
/>
{hasRunningTrader && launchPanel}
{/* Traders List */}
<TradersList

View File

@@ -394,20 +394,20 @@ export function AutopilotLaunchPanel({
action?: JSX.Element
}> = [
{
title: 'AI fee wallet',
title: 'Step 1 · Fund the AI wallet ($1+)',
detail:
'Pays Claw402.ai data and model calls with Base USDC. This is separate from trading collateral.',
'The AI pays a tiny fee each time it thinks. Send $1 or more of USDC on the Base network to this address — from Binance, OKX, Coinbase or any wallet. Separate from your trading money.',
status: feeReady ? 'ready' : 'action',
meta: feeWalletAddress
? `${shortAddress(feeWalletAddress)} · ${formatUSDC(feeWalletBalance)} USDC${
feeReady ? '' : ` · needs ≥ ${minAIFeeUSDC} USDC`
}`
: 'Base USDC wallet required',
: 'Takes 1 minute — we create the wallet for you',
action: feeWalletAddress ? (
<div className="flex flex-wrap items-center gap-3">
<button
type="button"
onClick={() => onOpenClaw402Config?.()}
onClick={() => navigate(ROUTES.welcome)}
className="inline-flex items-center gap-1.5 text-xs font-semibold text-nofx-gold hover:text-nofx-accent"
>
<CircleDollarSign className="h-3.5 w-3.5" />
@@ -425,22 +425,22 @@ export function AutopilotLaunchPanel({
) : (
<button
type="button"
onClick={() => onOpenClaw402Config?.()}
onClick={() => navigate(ROUTES.welcome)}
className="inline-flex items-center gap-1.5 text-xs font-semibold text-nofx-gold hover:text-nofx-accent"
>
<ArrowRight className="h-3.5 w-3.5" />
Open
Create
</button>
),
},
{
title: 'Hyperliquid trading wallet',
title: 'Step 2 · Connect Hyperliquid',
detail:
'Connect an EVM wallet, approve a NOFX Agent, approve the builder fee, then save it to NOFX.',
'Approve NOFX once with your crypto wallet (Rabby or MetaMask). This lets the AI place trades for you — it can never withdraw your money.',
status: hyperliquidConnected ? 'ready' : 'action',
meta: hyperliquidExchange?.hyperliquidWalletAddr
? `${shortAddress(hyperliquidExchange.hyperliquidWalletAddr)} · authorized`
: 'Agent and trading authorization required',
: 'A few clicks + 3 wallet signatures',
action: (
<button
type="button"
@@ -453,9 +453,9 @@ export function AutopilotLaunchPanel({
),
},
{
title: 'Trading balance',
title: 'Step 3 · Add trading money ($12+)',
detail:
'Deposit USDC to Hyperliquid. NOFX uses it as margin for the Claw402 Autopilot strategy.',
'Deposit USDC into your Hyperliquid account. This is what the AI trades with — start small, you can add more anytime.',
status: tradingBalanceReady
? 'ready'
: hyperliquidConnected
@@ -465,18 +465,20 @@ export function AutopilotLaunchPanel({
? `${formatUSDC(tradingBalance)} USDC available${
tradingBalanceReady ? '' : ` · needs ≥ ${minTradingUSDC} USDC`
}`
: 'Connect Hyperliquid first',
: 'Finish step 2 first',
},
{
title: 'NOFX Autopilot',
title: 'Step 4 · Press start',
detail:
'Reads the Claw402 board, fetches Signal Lab and liquidation structure, confirms with candles, then trades full-size 10x only when the setup is strong enough.',
'The AI reads the market every few minutes, picks its trades, and manages them on its own. Watch every decision live on the dashboard — stop it with one click anytime.',
status: allReady ? 'ready' : 'blocked',
meta: autopilotTrader?.is_running
? 'Running'
? 'Running — open the dashboard to watch'
: autopilotTrader
? 'Ready to start'
: 'Ready to create when setup is complete',
: allReady
? 'Everything is ready — press the button'
: 'Unlocks when steps 13 are green',
},
]
@@ -485,16 +487,10 @@ export function AutopilotLaunchPanel({
return (
<button
type="button"
onClick={() => {
if (onOpenClaw402Config) {
onOpenClaw402Config()
} else {
navigate(ROUTES.welcome)
}
}}
onClick={() => navigate(ROUTES.welcome)}
className="inline-flex items-center justify-center gap-2 rounded-lg bg-nofx-gold px-4 py-3 text-sm font-bold text-white hover:bg-nofx-accent"
>
Open Claw402 wallet
Set up the AI wallet
<ArrowRight className="h-4 w-4" />
</button>
)
@@ -584,8 +580,8 @@ export function AutopilotLaunchPanel({
Start NOFX Autopilot in minutes
</h2>
<p className="mt-2 max-w-2xl text-sm leading-6 text-nofx-text-muted">
One strategy, one launch path. Fund the AI fee wallet, authorize
Hyperliquid, deposit USDC, then run the Claw402 Autopilot.
Four small steps, about $13 total. No API keys, no config
files the AI trades for you, and you can stop it anytime.
</p>
</div>
<div className="flex flex-wrap gap-2">