Skip to Content

Chapitre 2.5 — Naissance de Drill

Où on en est : toolchain complète, téléphone et émulateur opérationnels. On crée maintenant le projet qui nous accompagnera 18 parties durant — proprement.

⏱️ TL;DRpnpm create expo-app drill, nettoyage du template d’exemple (on garde la structure, on vide le contenu), configuration d’app.json (nom, slug, scheme), premier écran d’accueil à nous, arborescence cible (components/, lib/, constants/), git init + premier commit. Drill affiche « Prêt à drill? » sur votre téléphone.

🎯 Objectifs

  • Créer le projet Drill sur une base saine et le nettoyer du contenu d’exemple.
  • Poser l’arborescence et les conventions qui tiendront tout le cours.
  • Configurer l’identité de base dans app.json.
  • Premier commit git d’un projet Expo (et savoir quoi ignorer).

Création et état des lieux

cd C:\Users\Alexl\Desktop pnpm create expo-app@latest drill cd drill npx expo start

Scannez, vérifiez que le template tourne sur le téléphone. À partir d’ici, chaque chapitre du cours modifie CE projet.

Le nettoyage

Le template livre un exemple riche (deux onglets, composants de démo, animations). Pédagogique, mais on veut partir de zéro maîtrisé. Le template fournit d’ailleurs un script pour ça :

npm run reset-project # → déplace l'exemple dans app-example/ et crée un app/ minimal

Répondez y pour déplacer (on pourra fouiller app-example/ plus tard comme référence), puis supprimez app-example/ quand vous n’en aurez plus besoin. Il reste :

drill/ ├── app/ │ ├── _layout.tsx ← layout racine minimal │ └── index.tsx ← l'unique écran (route /) ├── assets/ ├── app.json ├── package.json └── tsconfig.json

L’arborescence cible du cours

Créez tout de suite les dossiers vides qui structureront la suite :

drill/ ├── app/ ← écrans (Expo Router) — Parties 5+ ├── components/ ← UI réutilisable — dès la Partie 3 ├── lib/ ← logique pure TS — scoring, tirage… (Partie 6) ├── constants/ ← thème, config — Partie 4 └── assets/ ← images, sons, polices

Règle d’or maintenue jusqu’au bout : lib/ ne doit jamais importer react-native. La logique de score, le tirage aléatoire des questions, le calcul de streak — tout ça est du TypeScript pur, testable en un clin d’œil (Partie 14).

L’identité dans app.json

// app.json — les champs qu'on fixe dès aujourd'hui { "expo": { "name": "Drill", "slug": "drill", "scheme": "drill", "version": "0.1.0", "orientation": "portrait", "userInterfaceStyle": "automatic", "newArchEnabled": true } }
  • name: "Drill" — le nom sous l’icône.
  • scheme: "drill" — les URLs drill://… ouvriront l’app (deep links, Partie 5 ; la notification du défi quotidien s’en servira en Partie 9).
  • orientation: "portrait" — un quiz se joue en portrait ; on verrouille et on ne pense plus jamais au paysage.
  • Le package Android (com.alex.drill) attendra la Partie 12 — il n’est nécessaire qu’au premier build.

Le premier écran

Remplaçons l’écran minimal par le nôtre — votre premier vrai code RN (les composants sont expliqués en détail dès le prochain chapitre ; ici, on plante le drapeau) :

// app/index.tsx import { StyleSheet, Text, View } from 'react-native' export default function HomeScreen() { return ( <View style={styles.container}> <Text style={styles.title}>Drill</Text> <Text style={styles.subtitle}>Prêt à drill ?</Text> </View> ) } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: '#0b1216', gap: 8, }, title: { color: '#58c4dc', fontSize: 48, fontWeight: '800', }, subtitle: { color: '#e2e8f0', fontSize: 18, }, })
// app/_layout.tsx import { Stack } from 'expo-router' export default function RootLayout() { return <Stack screenOptions={{ headerShown: false }} /> }

Sauvegardez : votre téléphone affiche l’écran sombre « Drill / Prêt à drill ? ». Première pierre posée.

💡 Pour un dev Next.js — Trois différences déjà visibles dans ce petit fichier : View/Text au lieu de div/h1 ; les styles sont un objet JS passé par prop (pas de classe, pas de fichier CSS) ; et flex: 1 sur le conteneur racine — l’équivalent de height: 100vh, indispensable sinon la View ne mesure que son contenu. Tout s’éclaircit dans les Parties 3 et 4.

Git

Le .gitignore généré est déjà correct (il exclut node_modules/, .expo/, et les dossiers natifs générables). Vérifiez juste ces lignes clés, puis committez :

# .gitignore (déjà présent — les lignes qui comptent) node_modules/ .expo/ dist/ # generated native folders (CNG) /android /ios
git init git add -A git commit -m "Drill : projet Expo SDK 57 nettoyé, premier écran"

⚠️ Piège — Ne committez PAS .expo/ (état local de la CLI) ni, pour l’instant, android/ (généré par prebuild — CNG, chapitre 1.3). Un repo Expo propre ne contient QUE du TS, la config et les assets. Si un jour android/ apparaît après un expo run:android, le .gitignore ci-dessus l’ignore déjà.

Récapitulatif de la Partie 2

Vous avez désormais :

  • ✅ Node + pnpm + la CLI Expo opérationnels
  • ✅ Expo Go sur le téléphone, connecté en WiFi (et le plan B USB/tunnel)
  • ✅ Android Studio : SDK, émulateur Pixel, adb dans le PATH
  • ✅ VS Code + DevTools (j) + element inspector
  • Drill v0.1.0 : projet propre, arborescence posée, premier écran, premier commit

✏️ Exercices

1. Faites la manip complète vous-même (création → reset → arborescence → app.json → écran → commit). Puis vérifiez : git log --oneline montre 1 commit, git status est propre.

✅ Solution

Suivre le chapitre dans l’ordre. Vérifications : l’app affiche l’écran Drill sur le téléphone, git status ne liste ni .expo/ ni node_modules/, et npx expo-doctor ne remonte aucune erreur bloquante.

2. Changez la couleur du titre pour la couleur officielle de VOTRE thème préféré, observez le Fast Refresh, puis remettez #58c4dc (c’est le cyan React qu’on gardera).

✅ Solution

Modifier styles.title.color, sauvegarder → le changement apparaît sans perdre l’état. Noter au passage : la valeur est une string dans un objet JS, pas une propriété CSS — les erreurs de frappe se voient à l’exécution, pas à la compilation (NativeWind + TS amélioreront ça, Partie 4).

3. Créez lib/greeting.ts exportant greeting(name: string): string, importez-la dans l’écran et affichez son résultat. Pourquoi ce petit exercice illustre-t-il la règle d’or de lib/ ?

✅ Solution

// lib/greeting.ts export function greeting(name: string): string { return `Prêt à drill, ${name} ?` }

Import et usage : <Text style={styles.subtitle}>{greeting('Alex')}</Text>. La fonction ne sait pas que RN existe : elle serait testable avec Jest sans aucun mock, et réutilisable dans un script Node. Toute la logique de jeu de Drill suivra ce modèle.

🧠 Quiz

1. Que fait npm run reset-project dans le template Expo ?

Réponse

Il déplace le contenu d’exemple (onglets de démo, composants) vers app-example/ et crée un app/ minimal (_layout.tsx + index.tsx) — un point de départ propre.

2. À quoi servira le champ scheme d’app.json ?

Réponse

Aux deep links : les URLs drill://… ouvriront l’app directement sur un écran donné (Partie 5), notamment depuis la notification du défi quotidien (Partie 9).

3. Citez deux entrées indispensables du .gitignore d’un projet Expo.

Réponse

node_modules/, .expo/ (état local CLI), et les dossiers natifs générés /android /ios (artefacts CNG régénérables par prebuild).

4. Pourquoi lib/ ne doit-il jamais importer react-native ?

Réponse

Pour garder la logique métier pure : testable avec Jest sans environnement RN, réutilisable hors app, et insensible aux changements d’UI. Le scoring de Drill n’a pas besoin de View.

5. Que fait flex: 1 sur la View racine de l’écran ?

Réponse

Elle prend tout l’espace disponible de son parent (l’écran entier ici). Sans ça, la View ne mesurerait que son contenu et le centrage vertical n’aurait aucun espace où opérer. Détails flexbox en Partie 4.


👉 Partie suivante : Partie 3 — Fondamentaux : penser natif — View, Text, Pressable, FlatList : le vocabulaire de base, et les pièges qui piègent tous les devs web.