EN
Tous les projets

Agence immobilière

Un site éditorial pour une agence immobilière au Maroc, avec un back-office où l’équipe publie elle-même ses annonces, ses photos et ses visites filmées.

Rôle
Design et développement full-stack
Statut
En développement
Catégorie
Site d’agence et back-office
Lieu et année
Maroc, 2026
Technologies
Next.js, React, TypeScript, Tailwind CSS, GSAP, Lenis, SQLite, Zod
Liens
Pas encore lancé publiquement, et le code source n’est pas public. Le nom et le logo de l’agence sont masqués.
Page d’accueil : une villa au crépuscule, en pleine page.
Biens à la une dans une grille asymétrique.
Fiche d’un bien avec chiffres clés et photo de paysage.
Une fiche de bien sur téléphone.
légendé comme un magazine
visites filmées, en 9:16

L’histoire

  1. Le défi

    Une agence qui vend et loue des villas, des riads et des appartements au Maroc voulait que chaque bien soit présenté comme un article de magazine, avec un back-office assez simple pour publier annonces, photos et visites filmées sans aide.

  2. L’approche

    Un site éditorial en français : chapitres numérotés, photos pleine largeur légendées et une grille de biens asymétrique, avec des animations GSAP sur Lenis. Derrière, un back-office protégé sur SQLite pour les annonces, l’envoi de photos, les visites vidéo verticales et les demandes.

  3. Le résultat

    Le site et le back-office sont construits et remplis avec neuf annonces de démonstration. Il reste les photos de l’agence, ses vraies annonces et les notifications par e-mail avant le lancement.

Le site public

  • Un catalogue de biens avec recherche et filtres : transaction, type, prix, chambres et surface.
  • Des fiches de biens avec une galerie navigable au clavier, les chiffres clés et une fiche technique.
  • Des visites filmées : une vidéo verticale lue en 9:16, ou un lien vers la publication TikTok du bien.
  • Un parcours vendeur : estimation gratuite, mandat en quatre étapes et formulaire de contact déjà réglé sur « vendre ».
  • Des animations qui respectent le réglage d’animations réduites : le grain se fige, le mouvement s’arrête et le contenu reste visible.

Le back-office

  • Connexion obligatoire sur chaque page d’administration via le middleware, avec cookies de session signés et mots de passe hachés avec bcrypt.
  • Un tableau de bord avec des compteurs, les dernières demandes et les annonces récentes.
  • Annonces : créer, modifier, supprimer, mettre en avant et changer leur statut.
  • Des photos ré-encodées en JPEG à 2000 px maximum, métadonnées retirées, et chaque fichier vérifié comme vraie image.
  • Des demandes suivies de « nouvelle » à « traitée » puis « archivée ».

Sous le capot

de vrais extraits du code

Ne jamais faire confiance à un fichier envoyé

Le type MIME déclaré n’est qu’une affirmation du navigateur. Chaque photo est décodée puis ré-encodée sur le serveur, ce qui retire ses métadonnées et rejette tout ce qui n’est pas vraiment une image.

src/app/admin/actions.ts

if (!TYPES_IMAGE.includes(f.type)) {
  return { ok: false, message: `Format refusé : ${f.name}. JPEG, PNG, WebP ou AVIF.` };
}
if (f.size > TAILLE_MAX) {
  return { ok: false, message: `Fichier trop lourd : ${f.name} (12 Mo maximum).` };
}

const nom = `${crypto.randomUUID()}.jpg`;
try {
  // Re-encoding strips metadata and proves the bytes really are an image —
  // a declared MIME type is only a claim by the client.
  await sharp(Buffer.from(await f.arrayBuffer()))
    .rotate()
    .resize({ width: 2000, withoutEnlargement: true })
    .jpeg({ quality: 82, mozjpeg: true })
    .toFile(path.join(dossier, nom));
} catch {
  return { ok: false, message: `Fichier illisible : ${f.name}. Ce n'est pas une image valide.` };
}

Une seule porte pour le back-office

Chaque page d’administration passe par la même vérification avant de s’afficher ; sans session valide, le visiteur arrive sur la page de connexion puis revient là où il allait.

src/middleware.ts

export async function middleware(req: NextRequest) {
  const session = await lireJeton(req.cookies.get(NOM_COOKIE)?.value);

  if (!session) {
    const url = new URL("/admin/connexion", req.url);
    url.searchParams.set("suite", req.nextUrl.pathname);
    return NextResponse.redirect(url);
  }
  return NextResponse.next();
}

// Everything under /admin except the login page itself.
export const config = {
  matcher: ["/admin/((?!connexion).*)", "/admin"],
};

Choix

Une référence, pas une copie

Un site éditorial de référence a donné la direction. Son échelle typographique et sa grammaire de mise en page ont été reprises ; les textes, l’étalonnage des photos et chaque ligne de code ont été écrits pour ce projet.

Des données structurées honnêtes

Les données d’annonces pour les moteurs de recherche restent désactivées tant que les annonces ne sont pas réelles : publier des offres d’exemple auprès de Google serait trompeur.

La vidéo là où est le public

L’agence filme ses biens à la verticale : chaque annonce accepte donc un fichier en 9:16, ou renvoie simplement vers la publication TikTok qui fait déjà les vues.

Page d’accueil avec une villa au crépuscule en pleine page.
Accueil
Biens à la une dans une grille asymétrique.
Biens à la une
Page d’accueil sur téléphone.
L’accueil sur téléphone
Catalogue des biens avec recherche et filtres.
Catalogue avec recherche et filtres
Cartes de biens avec des cadrages alternés.
La grille de biens asymétrique
Fiche d’un bien avec chiffres clés et photo de paysage.
Fiche d’un bien
Une fiche de bien sur téléphone avec sa galerie.
Un bien sur téléphone
Galerie et fiche technique d’un bien.
Galerie et fiche technique
Page vendeurs : « Vous avez un bien à vendre ou à louer. »
Le parcours vendeur
Le mandat en quatre étapes expliqué.
Un mandat en quatre étapes
Tableau de bord du back-office avec compteurs, dernières demandes et annonces récentes.
Tableau de bord du back-office
Liste des annonces du back-office avec statut et mise en avant.
Annonces
Éditeur d’annonce avec envoi de photos et de vidéos.
Éditeur d’annonce avec photos et vidéos

Statut

Les photos du site sont des images libres sous licence, étalonnées pour s’accorder, et les neuf annonces comme les demandes sont des contenus de démonstration. Le nom, le logo, le numéro de téléphone et les réseaux sociaux de l’agence sont absents de cette étude de cas.