Build With Me · Apprendre

Apprendre à construire, niveau par niveau.

Neuf niveaux, du vocabulaire de base à l’exploitation d’un produit. Chaque niveau renvoie à ce qui existe vraiment pour l’apprendre : Build School pour le web, la documentation officielle et les guides de ce site pour Apple et l’IA.

Les niveaux

De zéro à un produit qui tourne.

iPhone, iPad, Mac — avec la documentation Apple.

  1. 0

    Les bases de l’ordinateur et du développement

    Fichiers et dossiers, terminal, ce qu’est un serveur, une base de données, une API — le vocabulaire qui évite de se perdre.

  2. 1

    Les fondations de la programmation

    Variables, fonctions, conditions, collections, types — dans le langage de votre plateforme.

  3. 2

    Git, GitHub et environnement de développement

    Versionner chaque étape, revenir en arrière, travailler avec un agent de code sans perdre le contrôle.

  4. 3

    Le développement propre à la plateforme

    Les écrans, l’état, la navigation et les conventions de votre plateforme.

  5. 4

    Bases de données et backend

    Modéliser les données, l’authentification, l’autorisation et les intégrations.

  6. 5

    Déploiement et distribution

    Mettre en ligne, distribuer une bêta, soumettre à un store.

  7. 6

    Architecture produit

    Où vivent les règles, les données et les responsabilités — et ce qui rend un changement sûr.

  8. 7

    Ingénierie logicielle de production

    Tests, sécurité, surveillance des erreurs, préparation au lancement prouvée.

  9. 8

    Faire vivre et grandir un produit

    Analytics, référencement, retours utilisateurs, rythme des versions.

Formats

Écrit d’abord, jamais seulement oral.

  • Guides écrits pas à pas
  • Checklists à cocher
  • Exemples de code vérifiés
  • Enregistrements d’écran sous-titrés (dans Build School)
  • Projets d’entraînement
  • Aucune leçon uniquement narrée

Starters

Des points de départ qui existent vraiment.

Un starter n’est marqué disponible que si ses fichiers et ses instructions existent. Les autres sont prévus, et indiqués comme tels.

App SwiftUI de base (iOS)Une liste de tâches : un modèle @Observable partagé par l’environnement, ajout, coche, suppression, état vide.Disponible · iOS 17+
Prérequis
Un Mac avec Xcode 26 ou plus récent.
Versions prises en charge
iOS 17+
Variables d’environnement
Aucune.
Sécurité
Aucune donnée ne quitte l’appareil et rien n’est enregistré : les tâches disparaissent à la fermeture. Ajoutez SwiftData pour les garder.
Licence
MIT
Maintenance
Revu à chaque version majeure de Xcode.

Installation

  1. Dans Xcode : File → New → Project → iOS → App. Interface : SwiftUI. Nom de votre choix.
  2. Réglez la cible de déploiement (Minimum Deployments) sur iOS 17 ou plus récent.
  3. Remplacez tout le contenu du fichier <Nom>App.swift par le code ci-dessous, et supprimez ContentView.swift (le starter le contient).
  4. Lancez avec ⌘R sur un simulateur, puis sur votre iPhone (un compte Apple gratuit suffit pour tester sur votre appareil).
StarterApp.swift
import SwiftUI
import Observation

@main
struct StarterApp: App {
    @State private var store = TaskStore()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(store)
        }
    }
}

struct TaskItem: Identifiable, Hashable {
    let id = UUID()
    var title: String
    var isDone = false
}

@Observable
final class TaskStore {
    var items: [TaskItem] = []

    func add(_ title: String) {
        let trimmed = title.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmed.isEmpty else { return }
        items.append(TaskItem(title: trimmed))
    }

    func toggle(_ item: TaskItem) {
        guard let index = items.firstIndex(where: { $0.id == item.id }) else { return }
        items[index].isDone.toggle()
    }

    func delete(at offsets: IndexSet) {
        items.remove(atOffsets: offsets)
    }
}

struct ContentView: View {
    @Environment(TaskStore.self) private var store
    @State private var draft = ""

    var body: some View {
        NavigationStack {
            List {
                Section {
                    HStack {
                        TextField("New task", text: $draft)
                            .onSubmit(addDraft)
                        Button("Add", action: addDraft)
                            .disabled(draft.trimmingCharacters(in: .whitespaces).isEmpty)
                    }
                }
                Section {
                    if store.items.isEmpty {
                        ContentUnavailableView("No tasks yet", systemImage: "checklist", description: Text("Add your first task above."))
                    }
                    ForEach(store.items) { item in
                        Button {
                            store.toggle(item)
                        } label: {
                            Label(item.title, systemImage: item.isDone ? "checkmark.circle.fill" : "circle")
                        }
                        .accessibilityValue(item.isDone ? "Done" : "Not done")
                    }
                    .onDelete(perform: store.delete)
                }
            }
            .navigationTitle("Tasks")
        }
    }

    private func addDraft() {
        store.add(draft)
        draft = ""
    }
}

#Preview {
    ContentView()
        .environment(TaskStore())
}

Typechecked: Xcode 27.1 (iOS SDK 27.1, macOS SDK 27.0), Swift 5 and Swift 6 modes — 2026-10-23

App SwiftUI avec navigation (iOS)Une liste et un détail avec NavigationStack : liens par valeur, routes typées, recherche, barre d’outils.Disponible · iOS 17+
Prérequis
Un Mac avec Xcode 26 ou plus récent.
Versions prises en charge
iOS 17+
Variables d’environnement
Aucune.
Sécurité
Données d’exemple écrites dans le code, sans réseau. Remplacez-les par les vôtres.
Licence
MIT
Maintenance
Revu à chaque version majeure de Xcode.

Installation

  1. Dans Xcode : File → New → Project → iOS → App. Interface : SwiftUI. Nom de votre choix.
  2. Réglez la cible de déploiement (Minimum Deployments) sur iOS 17 ou plus récent.
  3. Remplacez tout le contenu du fichier <Nom>App.swift par le code ci-dessous, et supprimez ContentView.swift (le starter le contient).
  4. Lancez avec ⌘R sur un simulateur, puis sur votre iPhone (un compte Apple gratuit suffit pour tester sur votre appareil).
NavigationStarterApp.swift
import SwiftUI

@main
struct NavigationStarterApp: App {
    var body: some Scene {
        WindowGroup {
            PlaceList()
        }
    }
}

struct Place: Identifiable, Hashable {
    let id = UUID()
    let name: String
    let canton: String
    let note: String
}

enum Route: Hashable {
    case place(Place)
    case about
}

struct PlaceList: View {
    // Sample data, written here for the starter — replace with your own.
    private let places = [
        Place(name: "Lausanne", canton: "Vaud", note: "Sample entry."),
        Place(name: "Zürich", canton: "Zürich", note: "Sample entry."),
        Place(name: "Lugano", canton: "Ticino", note: "Sample entry."),
    ]
    @State private var path: [Route] = []
    @State private var query = ""

    private var filtered: [Place] {
        query.isEmpty ? places : places.filter { $0.name.localizedCaseInsensitiveContains(query) }
    }

    var body: some View {
        NavigationStack(path: $path) {
            List(filtered) { place in
                NavigationLink(value: Route.place(place)) {
                    VStack(alignment: .leading) {
                        Text(place.name).font(.headline)
                        Text(place.canton).font(.subheadline).foregroundStyle(.secondary)
                    }
                }
            }
            .searchable(text: $query)
            .navigationTitle("Places")
            .toolbar {
                Button("About") { path.append(.about) }
            }
            .navigationDestination(for: Route.self) { route in
                switch route {
                case .place(let place):
                    PlaceDetail(place: place)
                case .about:
                    Text("A NavigationStack starter: value-based links and a typed route.")
                        .padding()
                        .navigationTitle("About")
                }
            }
        }
    }
}

struct PlaceDetail: View {
    let place: Place

    var body: some View {
        Form {
            LabeledContent("Canton", value: place.canton)
            Section("Note") { Text(place.note) }
        }
        .navigationTitle(place.name)
    }
}

Typechecked: Xcode 27.1 (iOS SDK 27.1, macOS SDK 27.0), Swift 5 and Swift 6 modes — 2026-10-23

Utilitaire de barre des menus (macOS)Un minuteur dans la barre des menus : MenuBarExtra, une fenêtre de réglages, raccourcis clavier.Disponible · macOS 14+
Prérequis
Un Mac avec Xcode 26 ou plus récent.
Versions prises en charge
macOS 14+
Variables d’environnement
Aucune.
Sécurité
Aucun accès réseau ni fichier. Le modèle Xcode active l’App Sandbox : gardez-le.
Licence
MIT
Maintenance
Revu à chaque version majeure de Xcode.

Installation

  1. Dans Xcode : File → New → Project → macOS → App. Interface : SwiftUI.
  2. Réglez la cible de déploiement sur macOS 14 ou plus récent.
  3. Remplacez le contenu de <Nom>App.swift par le code ci-dessous et supprimez ContentView.swift.
  4. Pour cacher l’icône du Dock, ajoutez la clé LSUIElement (Application is agent) à l’Info.plist de la cible.
  5. Lancez avec ⌘R : l’icône apparaît dans la barre des menus.
MenuBarStarterApp.swift
import SwiftUI
import Observation

@main
struct MenuBarStarterApp: App {
    @State private var timer = FocusTimer()

    var body: some Scene {
        MenuBarExtra {
            TimerMenu()
                .environment(timer)
        } label: {
            Label(timer.label, systemImage: timer.isRunning ? "timer" : "timer.circle")
        }
        .menuBarExtraStyle(.window)

        Settings {
            SettingsView()
                .environment(timer)
        }
    }
}

@Observable
final class FocusTimer {
    var minutes = 25
    private(set) var endDate: Date?

    var isRunning: Bool { endDate != nil }

    var label: String {
        guard let endDate else { return "Focus" }
        let remaining = max(0, Int(endDate.timeIntervalSinceNow / 60))
        return "\(remaining) min"
    }

    func start() { endDate = Date().addingTimeInterval(TimeInterval(minutes * 60)) }
    func stop() { endDate = nil }
}

struct TimerMenu: View {
    @Environment(FocusTimer.self) private var timer
    @Environment(\.openSettings) private var openSettings

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text(timer.isRunning ? "Session running" : "Ready for \(timer.minutes) minutes")
                .font(.headline)
            HStack {
                Button(timer.isRunning ? "Stop" : "Start") {
                    timer.isRunning ? timer.stop() : timer.start()
                }
                .keyboardShortcut(.defaultAction)
                Button("Settings…") { openSettings() }
            }
            Divider()
            Button("Quit") { NSApplication.shared.terminate(nil) }
                .keyboardShortcut("q")
        }
        .padding()
        .frame(width: 240)
    }
}

struct SettingsView: View {
    @Environment(FocusTimer.self) private var timer

    var body: some View {
        @Bindable var timer = timer
        Form {
            Stepper("Session length: \(timer.minutes) min", value: $timer.minutes, in: 5...90, step: 5)
        }
        .padding()
        .frame(width: 320)
    }
}

Typechecked: Xcode 27.1 (iOS SDK 27.1, macOS SDK 27.0), Swift 5 and Swift 6 modes — 2026-10-23

Projet de référence web « Coût Réel » (Build School)Le projet fil rouge de Build School : un calculateur Next.js publié, avec un paiement Stripe en mode test et une seule table Supabase.Dans Build School · Web
App iOS avec appel d’APIURLSession, Codable, états de chargement et d’erreur.Prévu
App Mac à fenêtresFenêtres, menus Commands, documents.Prévu
Page d’accueil webUne page rendue côté serveur, rapide et indexable.Prévu
Squelette SaaS authentifiéComptes, données par utilisateur, autorisation testée.Prévu
Tableau de bord full-stackListes, filtres, export.Prévu
Exemple d’intégration StripeCheckout, webhook vérifié, idempotence.Prévu
Starter assistant IAAppel serveur, sortie structurée, évaluations.Prévu
Starter APIContrat OpenAPI, authentification, limites de débit.Prévu

Prêt à passer à l’étape suivante ?

Décrivez votre projet en quelques réponses : vous obtenez un plan expliqué et une feuille de route, sans compte et sans engagement.

danilson.daveigaramos.pro@gmail.com