Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
Achetez et vendez des cryptomonnaies au prix réel du marché avec 10 000 $ fictifs. Projet éducatif, aucun argent réel.
Translation pending
GamesTypeScript · CSSGitHub @maxence-svenssonOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
Achetez et vendez des cryptomonnaies au prix réel du marché avec 10 000 $ fictifs, suivez vos plus-values et comparez-vous aux autres joueurs. Aucun argent réel. Je voulais m'entraîner sur Next.js et m'amuser sur un sujet qui m'intéresse : la finance. Un simulateur de trading réunit les deux, avec des données en temps réel et des calculs où l'exactitude compte, même quand l'argent est fictif.Read the full README ↗
Achetez et vendez des cryptomonnaies au prix réel du marché avec 10 000 $ fictifs, suivez vos plus-values et comparez-vous aux autres joueurs. Aucun argent réel.
Démo : https://papertrade-five-peach.vercel.app
Je voulais m'entraîner sur Next.js et m'amuser sur un sujet qui m'intéresse : la finance. Un simulateur de trading réunit les deux, avec des données en temps réel et des calculs où l'exactitude compte, même quand l'argent est fictif.
BTC puis Entrée, ⌘K pour y accéder) et
touches de fonction F1 à F3 pour changer d'écran| Domaine | Outils |
|---|---|
| Framework | Next.js 16 (App Router, Server Components, Server Actions), React 19, TypeScript strict |
| Interface | Tailwind CSS 4, Lightweight Charts, IBM Plex Mono |
| Données | PostgreSQL, Drizzle ORM, Zod |
| Auth | Better Auth (compte invité, OAuth GitHub) |
| Qualité | Vitest (tests unitaires et d'intégration sur Postgres), ESLint, GitHub Actions |
| Hébergement | Vercel + Neon (offres gratuites) |
Une interface de terminal de marché plutôt que d'application grand public : une seule police à
chasse fixe (IBM Plex Mono), des noirs neutres, l'ambre pour tout ce qui est interactif, le vert et
le rouge réservés aux variations. Pas d'arrondis ni d'ombres : des panneaux séparés par des filets.
Les choix et leurs raisons sont dans
design-system/papertrade/MASTER.md.
aria-sort, confirmations dans un <dialog> natif. Aucun raccourci à
touche unique (WCAG 2.1.4).Le formulaire n'envoie que l'actif, le sens et la quantité. La Server Action
(src/app/actions.ts) identifie l'utilisateur par sa session, valide
l'entrée avec Zod puis relit le prix chez Binance, sans cache, avant d'exécuter l'ordre. Modifier
la requête à la main ne permet donc pas d'acheter moins cher.
Chaque ordre s'exécute dans une transaction qui verrouille le portefeuille et la position
(SELECT … FOR UPDATE, voir src/lib/data/portfolio.ts). Le test
d'intégration envoie 10 achats simultanés de 2 000 $ avec 10 000 $ : exactement 5 passent.
Sans le verrou, les 10 passent (vérifié en le retirant). Des contraintes CHECK en base
(liquidités ≥ 0, quantité > 0) servent de dernier filet de sécurité.
En JavaScript, 0.1 + 0.2 !== 0.3. Les montants sont donc stockés en numeric(28, 8) et calculés
avec decimal.js (src/lib/trading.ts). Les arrondis se font au détriment du
joueur (coût d'achat arrondi au-dessus, produit de vente en dessous), comme sur une vraie
plateforme. Ces règles sont couvertes par des tests unitaires.
Toute l'application partage une connexion WebSocket
(src/lib/price-store.ts). Elle s'ouvre quand un composant en a besoin,
se ferme quand plus personne ne l'écoute et se reconnecte avec une attente exponentielle. Les
mises à jour sont regroupées toutes les 500 ms et lues via useSyncExternalStore : un composant
ne se re-rend que si le prix de son actif a changé.
Les réponses de l'API Binance sont validées avec Zod avant usage, et mises en cache côté serveur (10 s pour les prix, 30 s pour l'historique). Les prix servis par le serveur s'affichent dès le premier rendu, puis le flux temps réel prend le relais.
Un invité qui se déconnecte est supprimé. Une tâche planifiée Vercel
(src/app/api/cron/cleanup/route.ts) efface chaque nuit les
invités dont toutes les sessions ont expiré.
Prérequis : Node.js 24 ou plus, et Docker.
npm install
cp .env.example .env.local # puis renseigner BETTER_AUTH_SECRET (openssl rand -base64 32)
docker compose up -d # Postgres sur le port 5433
npm run db:migrate
npm run dev # http://localhost:3000
| Commande | Rôle |
|---|---|
npm run dev | Serveur de développement |
npm test | Tests unitaires et d'intégration (base Docker requise) |
npm run lint | ESLint |
npm run typecheck | Vérification TypeScript |
npm run db:generate | Génère une migration après modification du schéma |
npm run db:migrate | Applique les migrations |
npm run db:studio | Explore la base dans Drizzle Studio |
DATABASE_URL est ajoutée automatiquement.BETTER_AUTH_SECRET : générée avec openssl rand -base64 32CRON_SECRET : générée avec openssl rand -hex 16Pour activer la connexion GitHub (optionnel) :
https://<votre-projet>.vercel.app/api/auth/callback/github.BETTER_AUTH_URL (l'URL publique, pour que l'adresse de retour
envoyée à GitHub soit toujours la même), GITHUB_CLIENT_ID et GITHUB_CLIENT_SECRET (en
« Sensitive »).Une OAuth App n'accepte qu'une adresse de retour : la connexion GitHub fonctionne en production, pas sur les prévisualisations des pull requests.
Bon à savoir :
vercel.json place les fonctions à Francfort (fra1), près de la base.src/
├── app/ Pages, Server Actions (actions.ts) et routes API
├── components/ Composants partagés : prix en direct, en-tête, historique…
└── lib/
├── trading.ts Règles de calcul des ordres (tests unitaires)
├── data/ Accès aux données : ordres, portefeuille, classement
├── db/ Schéma Drizzle et connexion Postgres
├── binance.ts API REST Binance (serveur)
├── price-store.ts Flux WebSocket des prix (navigateur)
└── auth.ts Configuration Better Auth
design-system/ Design system (tokens, typographie, règles d'accessibilité)
drizzle/ Migrations SQL générées
scripts/migrate.mts Application des migrations (lancé au build)
Projet éducatif : aucune transaction réelle n'est effectuée et rien ici ne constitue un conseil en investissement. Données de marché fournies par Binance (prix en USDT, assimilés au dollar).