import React, { useState, useEffect, useRef } from 'react'; import ReactDOM from 'react-dom/client'; import { HashRouter as Router, Routes, Route, Link, useLocation } from 'react-router-dom'; // --- DATA --- const PORTFOLIO_DATA = [ { id: 'chase-2026', title: 'YAMAHA 125 YZ', thumbnail: 'yamaha.jpg', gear: 'Drone FPV 3.5" + GoPro Hero 13', status: 'À VENIR PROCHAINEMENT EN 2026', hasTimer: true, isUnknown: true, targetDate: undefined }, { id: 'secret-2026', title: '?????', thumbnail: 'https://images.unsplash.com/photo-1508614589041-895b88991e3e?auto=format&fit=crop&w=1920&q=80', gear: 'DJI AIR 3S', status: 'À VENIR', hasTimer: true, isUnknown: false, targetDate: '2026-04-07T00:00:00' } ]; // --- UTILS --- const useReveal = () => { const { pathname } = useLocation(); useEffect(() => { const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('active'); } }); }, { threshold: 0.1 }); const elements = document.querySelectorAll('.reveal'); elements.forEach(el => observer.observe(el)); setTimeout(() => { elements.forEach(el => { const rect = el.getBoundingClientRect(); if (rect.top < window.innerHeight) el.classList.add('active'); }); }, 500); return () => observer.disconnect(); }, [pathname]); }; const CountdownTimer: React.FC<{ targetDate?: string, isUnknown?: boolean }> = ({ targetDate, isUnknown }) => { const [timeLeft, setTimeLeft] = useState({ days: 0, hours: 0, minutes: 0, seconds: 0 }); useEffect(() => { if (isUnknown || !targetDate) return; const target = new Date(targetDate).getTime(); const timer = setInterval(() => { const now = new Date().getTime(); const distance = target - now; if (distance < 0) { clearInterval(timer); return; } setTimeLeft({ days: Math.floor(distance / (1000 * 60 * 60 * 24)), hours: Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)), minutes: Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)), seconds: Math.floor((distance % (1000 * 60)) / 1000) }); }, 1000); return () => clearInterval(timer); }, [targetDate, isUnknown]); const Block = ({ v, l }: { v: string | number, l: string }) => (
{isUnknown ? '??' : v.toString().padStart(2, '0')} {l}
); return (
); }; // --- COMPONENTS --- const Navbar = () => { const [scrolled, setScrolled] = useState(false); const location = useLocation(); useEffect(() => { const handle = () => setScrolled(window.scrollY > 50); window.addEventListener('scroll', handle); return () => window.removeEventListener('scroll', handle); }, []); const navLinks = [ { name: 'Portfolio', path: '/portfolio' }, { name: 'Prestations', path: '/prestations' }, { name: 'À Propos', path: '/a-propos' }, { name: 'Contact', path: '/contact' }, ]; return ( ); }; const Home = () => { useReveal(); return (
Basty FPV

BASTY FPV

Cinematic FPV Pilot & Creative Visuals

DÉCOUVRIR LE TRAVAIL ENTER THE FPV WORLD
); }; const Portfolio = () => { useReveal(); return (
RÉALISATIONS

SHOW
CASE

{PORTFOLIO_DATA.map(proj => (
{proj.hasTimer && (
)} {proj.title}
{proj.status}

{proj.title}

{proj.gear}

))}
); }; const Prestations = () => { useReveal(); const list = [ { title: 'FPV CINÉMATIQUE', icon: '🎬', desc: 'Prises de vues immersives et fluides pour publicités, clips et storytelling.', items: ['Drone FPV 3.5 Pouces', '4K 120 FPS / D-LOG M', 'Stabilisation ReelSteady GO'] }, { title: 'CHASE CAM / SUIVI', icon: '🏎️', desc: 'Tracking dynamique de véhicules, sportifs ou événements en mouvement.', items: ['Suivi haute vitesse', 'Proximité millimétrée', 'Action synchronisée'] }, { title: 'EXPLORATION CINEWHOOP', icon: '🏛️', desc: 'Visites virtuelles en intérieur (immobilier, industrie). Vol sécurisé.', items: ['Protection d\'hélices', 'Passage en espaces réduits', 'Storytelling intérieur'] }, { title: 'MONTAGE & ÉDITION', icon: '✂️', desc: 'Post-production complète sur Adobe : montage, sound design et colorgrading.', items: ['Adobe Premiere Pro', 'Sound Design Immersif', 'Multi-formats'] } ]; return (
MISSIONS & CAPACITÉS

NOS
SERVICES

{list.map((s, i) => (
{s.icon}

{s.title}

{s.desc}

    {s.items.map((item, idx) => (
  • {item}
  • ))}
))}
); }; const About = () => { useReveal(); return (
THE CREATIVE MIND

BASTIAN
BÉLON

Expert en immersion dynamique, basé dans les Hauts-de-France.

Mon approche du FPV dépasse le simple pilotage : je conçois chaque vol comme une partition cinématographique. Alliant précision technique et vision artistique, je transforme des environnements complexes en récits visuels fluides.

Spécialisé dans le Somme (80) et le Pas-de-Calais (62), j'accompagne marques et créatifs pour capturer l'impossible, du suivi haute vitesse au CineWhoop intérieur chirurgical.

LOGICIEL

  • Adobe Premiere Pro
  • ReelSteady / RSGO

DRONES

  • FPV 3.5 POUCES
  • DJI AIR 3S
  • DJI MINI 3 PRO

CAMERA

  • GOPRO HERO 13
belon.bastian@bastyfpv.fr
Cinematic drone view
Perspective aérienne — 2025
); }; const Contact = () => { useReveal(); const [status, setStatus] = useState('idle'); const [form, setForm] = useState({ name: '', email: '', message: '', location: '', zip: '' }); const handleSubmit = async (e) => { e.preventDefault(); setStatus('sending'); try { const res = await fetch("https://api.web3forms.com/submit", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ access_key: "3006180d-83af-44b8-b7f2-b0ace60a4a4a", ...form }) }); if ((await res.json()).success) setStatus('sent'); else setStatus('error'); } catch { setStatus('error'); } }; if (status === 'sent') return (

READY FOR TAKE OFF.

Message transmis. Bastian revient vers vous sous 48h.

); return (
PRE-FLIGHT BRIEFING

PARLONS
PROJET

Zone : Somme (80) & Pas-de-Calais (62)
setForm({...form, name: e.target.value})} className="bg-transparent border-b border-white/10 py-4 outline-none focus:border-white uppercase tracking-widest text-sm" required /> setForm({...form, email: e.target.value})} className="bg-transparent border-b border-white/10 py-4 outline-none focus:border-white uppercase tracking-widest text-sm" required />
setForm({...form, location: e.target.value})} className="bg-transparent border-b border-white/10 py-4 outline-none focus:border-white uppercase tracking-widest text-sm" required /> setForm({...form, zip: e.target.value})} className="bg-transparent border-b border-white/10 py-4 outline-none focus:border-white uppercase tracking-widest text-sm" required />
); }; // --- APP --- const App = () => { const { pathname } = useLocation(); useEffect(() => { window.scrollTo(0, 0); const timeout = setTimeout(() => document.body.classList.add('loaded'), 1500); return () => clearTimeout(timeout); }, [pathname]); return (
} /> } /> } /> } /> } />

BFPV © 2026 — SOMME & PAS-DE-CALAIS

); }; const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement); root.render();