Appeler un service avec une clé
IA (OpenAI, Mistral…), paiements, envoi d’e-mails, cartes : la clé reste sur le serveur et n’arrive jamais dans le navigateur.
Certaines choses ne doivent pas se passer dans le navigateur de tes visiteurs : appeler une API avec une clé secrète, envoyer un e-mail, recevoir un webhook. Pour cela, ton app peut avoir son propre serveur, avec des routes sous /api. Il n’existe que si ton app en a besoin, et Highwind s’occupe de toute sa configuration.
Appeler un service avec une clé
IA (OpenAI, Mistral…), paiements, envoi d’e-mails, cartes : la clé reste sur le serveur et n’arrive jamais dans le navigateur.
Envoyer des messages
Formulaire de contact par e-mail, notification dans Slack, inscription ajoutée à une feuille Google Sheets.
Recevoir des webhooks
Un service externe (paiement, formulaire, automatisation) prévient ton app qu’un événement a eu lieu.
Contourner une API fermée au navigateur
Certaines API refusent les appels venant directement d’une page web : le serveur les appelle à sa place.
Si ton app a seulement besoin de garder des données pour le visiteur, ou d’une base de données avec des comptes utilisateurs, le serveur n’est pas forcément nécessaire : voir Où vont les données.
Une app n’a pas de serveur au départ. Quand une fonction en a besoin, l’agent l’ajoute lui-même (étape « Ajoute un serveur à l’app » dans le fil), ou en branchant un connecteur qui en a besoin.
Highwind crée le fichier worker/index.ts à partir de son modèle et branche toute la configuration. L’agent n’écrit jamais cette configuration lui-même.
L’agent ajoute les routes dont ton app a besoin dans worker/index.ts, par exemple POST /api/contact.
Le front de ton app appelle ces routes avec des adresses relatives (fetch("/api/contact")), qui fonctionnent dans l’aperçu comme une fois publiée.
Si une route a besoin d’une clé, l’agent te la demande avec une carte dans le chat : voir Les secrets.
Tu peux aussi le demander directement :
Ajoute un formulaire de contact qui m'envoie chaque message par e-mail àcontact@monatelier.fr, avec validation des champs.Ajoute une route qui génère une description de produit avec OpenAI à partirdu nom et des caractéristiques saisis./api/*. Tout le reste (les pages, les images, les scripts) est le front de ton app.fetch, Request, Response, crypto.subtle), mais pas de système de fichiers, pas de processus qui tourne en continu et pas d’Express.worker/index.ts est supprimé, l’app redevient statique.worker/index.tsLe serveur déclare ses routes dans une table routes (« MÉTHODE /api/chemin »), lit ses secrets dans env et répond avec l’utilitaire json() :
export interface Env { RESEND_API_KEY: string;}
const routes: Record<string, Handler> = { "GET /api/health": () => json({ ok: true }), "POST /api/contact": async (request, env) => { const { email, message } = await request.json(); if (!email || !message) return json({ error: "Champs obligatoires manquants" }, 400); if (!env.RESEND_API_KEY) return json({ error: "Clé Resend pas encore ajoutée" }, 503); // … envoi de l'e-mail avec env.RESEND_API_KEY return json({ ok: true }); },};Quand une route ne fait pas ce que tu attends, les logs montrent ce qui s’est passé : les console.log du serveur et les erreurs, avec le fichier et la ligne.
Dans la barre de l’aperçu, clique sur l’icône Logs du serveur. Le panneau s’ouvre en bas de l’aperçu.
Choisis l’onglet :
console.log et les erreurs des routes /api, et les messages de Vite), rafraîchi en continu. Les lignes d’erreur sont en rouge./api y apparaît avec son statut et sa durée, avec les console.log et les erreurs. Ni les en-têtes ni l’adresse IP des visiteurs ne sont affichés.Si tu ne comprends pas l’erreur, demande à l’agent de corriger : il lit lui-même ces logs (outil read_logs), dans l’aperçu ou en ligne.
Le formulaire de contact répond une erreur dans l'app publiée alors qu'il marchedans l'aperçu. Regarde les logs en ligne et corrige.N’importe qui peut appeler les routes /api de ton app, pas seulement ses pages. L’agent applique donc ces règles à chaque route :
src/).Highwind ajoute ses propres garde-fous sur les apps publiées :
| Garde-fou | Valeur |
|---|---|
Requêtes /api par visiteur et par app |
120 par minute, puis erreur 429 (« réessaie dans une minute ») |
Requêtes /api par app, tous visiteurs confondus |
3 000 par minute |
| Temps de calcul par requête | 1 seconde de CPU (l’attente des API externes ne compte pas) |
| Appels sortants par requête | 200 |
Les pages et les fichiers statiques de ton app ne sont pas concernés par ces limites.