LevelStone — Rachat immobilier
; import HeroSection from
; import HowItWorks from
; import FormSection from
; import OfferCasesSection from
; import AdvantagesSection from
; import ComparisonSection from
; import ComplexSituationsSection from
; import LocationsSection from
; import RecentAcquisitions from
; import AboutSection from
; import TrustSection from
; import SocialProof from
; import FAQSection from
; import CTASection from
; import InternalLinks from
; import StickyMobileCTA from
; const organizationJsonLd = {
Rachat immobilier rapide : appartement avec travaux, bien occupé, passoire énergétique, succession. Offre en 48h, achat comptant sur fonds propres.
> <SEOHead title=
LevelStone rachète votre appartement en 48h. Achat comptant, sans frais, travaux, succession, passoire énergétique. Paris, IDF, Nice, Marseille.
; import { Button } from
; import { Menu, X } from
; import { Link, useLocation } from
; const navLinks = [ { label:
}, ]; const Navbar = () => { const [open, setOpen] = useState(false); const [scrolled, setScrolled] = useState(false); const location = useLocation(); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 20); onScroll(); window.addEventListener(
, onScroll, { passive: true }); return () => window.removeEventListener(
, onScroll); }, []); const handleNavClick = (href: string) => { setOpen(false); if (href.startsWith(
)) { if (location.pathname !==
) { window.location.href =
+ href; return; } document.getElementById(href.slice(1))?.scrollIntoView({ behavior:
}); } }; const scrollToForm = () => { setOpen(false); if (location.pathname !==
; return; } document.getElementById(
)?.scrollIntoView({ behavior:
bg-background/60 backdrop-blur-md
container mx-auto px-4 sm:px-6 lg:px-8
flex items-center justify-between h-20
> {navLinks.map((link) => link.href.startsWith(
> {link.label} </Link> ) )} <Button variant=
> <Button variant=
aria-label=
link.href.startsWith("#") ? (
Proposer un bien
; import { cva, type VariantProps } from
; const buttonVariants = cva(
, { variants: { variant: { default:
bg-destructive text-destructive-foreground hover:bg-destructive/90
border border-input bg-background hover:bg-accent hover:text-accent-foreground
bg-secondary text-secondary-foreground hover:bg-secondary/80
text-primary underline-offset-4 hover:underline
bg-primary text-primary-foreground font-semibold shadow-[0_8px_30px_-8px_hsl(232_100%_62%/0.5)] hover:bg-primary/90 hover:-translate-y-0.5 hover:shadow-[0_12px_40px_-8px_hsl(232_100%_62%/0.6)]
border border-foreground/15 text-foreground bg-background/60 backdrop-blur-md hover:bg-background hover:border-foreground/30
bg-foreground text-background font-semibold hover:bg-primary hover:text-primary-foreground hover:-translate-y-0.5
bg-primary text-primary-foreground font-bold shadow-lg hover:bg-primary/90 hover:-translate-y-0.5 text-base
, }, }, defaultVariants: { variant:
, }, }, ); 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 :
; import AddressAutocomplete from
; import { motion } from
; import { ArrowRight, Lock, Check, Star, Building2, TrendingUp } from
); const handleStart = () => { if (adresse.length > 3) { const el = document.getElementById(
); if (el) { el.scrollIntoView({ behavior:
}); window.dispatchEvent(new CustomEvent(
style={{ background:
> <AddressAutocomplete value={adresse} onChange={setAdresse} placeholder=
onKeyDown={(e) => e.key ===
&& handleStart()} /> </div> <Button variant=
Fonds propres disponibles
Signature rapide chez le notaire
> <img src={heroImage} alt=
loading=
fetchPriority=
Offre ferme en 48h · 100% sans engagement
Achat de votre bien
immobilier en
Vous souhaitez vendre rapidement un bien immobilier ? Nous achetons votre appartement avec travaux, bien occupé ou passoire énergétique — sans agence, sans condition de financement. Achat direct sur fonds propres.
Recevoir mon offre
Biens de 100 000 € à 3 000 000 €
Offre LevelStone
Acceptée
Appartement à rénover
3 pièces · 65 m² · Paris 11e
; type Suggestion = { label: string; context: string; postcode: string; city: string; }; interface AddressAutocompleteProps { value: string; onChange: (value: string) => void; onSelect?: (suggestion: Suggestion) => void; placeholder?: string; className?: string; id?: string; required?: boolean; onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void; } const AddressAutocomplete = ({ value, onChange, onSelect, placeholder =
, city: f.properties.city ||
, })); setSuggestions(results); setOpen(results.length > 0); setActiveIndex(-1); } catch { setSuggestions([]); } }, []); const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; onChange(val); clearTimeout(debounceRef.current); debounceRef.current = setTimeout(() => fetchSuggestions(val), 300); }; const selectSuggestion = (s: Suggestion) => { onChange(s.label); onSelect?.(s); setOpen(false); setSuggestions([]); }; const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { if (open && suggestions.length > 0) { if (e.key ===
) { e.preventDefault(); setActiveIndex((i) => (i < suggestions.length - 1 ? i + 1 : 0)); return; } if (e.key ===
) { e.preventDefault(); setActiveIndex((i) => (i > 0 ? i - 1 : suggestions.length - 1)); return; } if (e.key ===
&& activeIndex >= 0) { e.preventDefault(); selectSuggestion(suggestions[activeIndex]); return; } if (e.key ===
) { setOpen(false); return; } } onKeyDown?.(e); }; // Close on click outside useEffect(() => { const handler = (e: MouseEvent) => { if (containerRef.current && !containerRef.current.contains(e.target as Node)) { setOpen(false); } }; document.addEventListener(
, handler); return () => document.removeEventListener(
> <input id={id} type=
required={required} value={value} onChange={handleChange} onKeyDown={handleKeyDown} onFocus={() => suggestions.length > 0 && setOpen(true)} placeholder={placeholder} autoComplete=
, i === activeIndex ?
text-foreground hover:bg-accent/5
; import { useRef } from
; import { ArrowRight } from
; const steps = [ { number:
Vous nous proposez le bien
Une adresse, quelques infos, 30 secondes. Nous accusons réception immédiatement.
Analyse & visite par un expert
Un spécialiste étudie le potentiel du bien et se déplace pour une visite sur place.
Offre détaillée sous 48h. Signature chez le notaire dans les meilleurs délais.
], }); const titleY = useTransform(scrollYProgress, [0, 1], [
]); return ( <section id=
> {steps.map((step, index) => ( <motion.div key={step.number} initial={{ opacity: 0, y: 40 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true, margin:
onClick={() => document.getElementById(
Trois étapes.
Confidentiel · Réponse en 48h · Sans engagement
; const FormSection = () => { return ( <section id=
relative py-16 sm:py-24 bg-secondary overflow-hidden
Le formulaire
Proposez votre
30 secondes pour remplir. 48 heures pour recevoir une offre.
; import { motion, AnimatePresence } from
; import { ArrowRight, ArrowLeft, CheckCircle, Lock, Upload, X, FileText, ImageIcon, Loader2 } from
; import { Progress } from
; import { supabase } from
; import { useToast } from
; import { trackEvent } from
; const propertyTypes = [ { value:
}, ]; const propertyStates = [ { value:
}, ]; const occupationOptions = [ { value:
Occupé par le propriétaire
}, ]; const dpeOptions = [
]; const saleDelays = [ { value:
}, ]; type UploadedFile = { file: File; id: string; progress: number; }; const ACCEPTED_TYPES =
; const LeadForm = () => { const { toast } = useToast(); const [step, setStep] = useState(1); const [submitted, setSubmitted] = useState(false); const [sending, setSending] = useState(false); const [files, setFiles] = useState<UploadedFile[]>([]); const fileInputRef = useRef<HTMLInputElement>(null); const [formData, setFormData] = useState({ adresse:
, anneeConstruction:
, }); useEffect(() => { const handler = (e: Event) => { const addr = (e as CustomEvent).detail; if (addr) { setFormData((prev) => ({ ...prev, adresse: addr })); setStep(2); } }; window.addEventListener(
, handler); return () => window.removeEventListener(
}); setSubmitted(true); } catch (err) { console.error('Email send error:', err); toast({ title:
Une erreur est survenue. Veuillez réessayer.
> Notre équipe vous contacte sous 24h. </p> </motion.div> ); } const OptionButton = ({ value, label, field }: { value: string; label: string; field: string }) => ( <button type=
border-border hover:border-accent/40 text-muted-foreground
}`} /> ))} </div> <AnimatePresence mode=
> <Label htmlFor=
>Adresse complète</Label> <AddressAutocomplete id=
value={formData.adresse} onChange={(v) => updateField(
, v)} placeholder=
> {propertyTypes.map((t) => ( <OptionButton key={t.value} value={t.value} label={t.label} field=
>Surface (m²)</Label> <Input id=
type=
value={formData.surface} onChange={(e) => updateField(
, e.target.value)} placeholder=
>Nombre de pièces</Label> <Input id=
value={formData.pieces} onChange={(e) => updateField(
>Année de construction</Label> <Input id=
value={formData.anneeConstruction} onChange={(e) => updateField(
>Étage du bien</Label> <Input id=
value={formData.etage} onChange={(e) => updateField(
> <OptionButton value=
> {propertyStates.map((s) => ( <OptionButton key={s.value} value={s.value} label={s.label} field=
> {occupationOptions.map((o) => ( <OptionButton key={o.value} value={o.value} label={o.label} field=
> {dpeOptions.map((d) => ( <button key={d} type=
onClick={() => updateField(
:
> {saleDelays.map((d) => ( <OptionButton key={d.value} value={d.value} label={d.label} field=
>Prix souhaité (€)</Label> <Input id=
inputMode=
value={formData.prixSouhaite} onChange={(e) => updateField(
>Commentaires</Label> <textarea id=
value={formData.commentaires} onChange={(e) => updateField(
>JPG, PNG, WEBP, PDF — max. 10 fichiers</span> <input ref={fileInputRef} type=
> {f.file.type.startsWith(
>{(f.file.size / 1024 / 1024).toFixed(1)} Mo</span> )} <button type=
>Nom complet</Label> <Input id=
value={formData.nom} onChange={(e) => updateField(
>Téléphone</Label> <Input id=
value={formData.telephone} onChange={(e) => updateField(
>Email</Label> <Input id=
value={formData.email} onChange={(e) => updateField(
> {step > 1 ? ( <button type=
> En soumettant ce formulaire, vous acceptez que LevelStone collecte vos données afin de vous recontacter dans le cadre de votre projet immobilier. Pour en savoir plus, consultez notre{
text-accent hover:underline
✅ Demande envoyée avec succès
Notre équipe vous contacte sous 24h.
Optionnel — indiquez votre estimation ou prix attendu.
Optionnel — toute information utile à notre équipe.
Ajoutez des photos, plans ou votre DPE (PDF ou images) — optionnel, jusqu'à 10 fichiers.
Cliquez pour ajouter des fichiers
JPG, PNG, WEBP, PDF — max. 10 fichiers
) : (
Confidentiel – Réponse en 24h – Sans engagement
Politique de confidentialité
; const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<
, className, )} ref={ref} {...props} /> ); }, ); Input.displayName =
; import * as LabelPrimitive from
; const labelVariants = cva(
; import * as ProgressPrimitive from
; import { ArrowRight, ArrowUpRight } from
; import imgRenover from
; import imgHaussmann from
Travaux lourds, légers, insalubrité, humidité — nous achetons en l'état.
}, { img: imgUrgent, title:
Indivision, désaccords entre héritiers, prêt relais, mutation, divorce.
}, { img: imgOccupe, title:
Locataire en place, bail en cours, impayés ou occupation irrégulière.
, tag: null }, { img: imgDPE, title:
DPE F/G, interdiction de location — nous prenons en charge la rénovation.
}, { img: imgHaussmann, title:
Immeuble de rapport, copropriété, parties communes vétustes.
Murs commerciaux & bureaux