Connexions, commandes, un tableau de bord avec des données : alors ton projet est une app Node ou Next, pas un site statique. Il tourne chez nous dans son propre container avec sa propre base Postgres (€ 15 par mois après 14 jours d'essai). L'image est construite sur GitHub, jamais sur notre serveur, donc ça passe toujours par un workflow dans ton dépôt :

```yaml
name: Deploy app to Dorelli
on:
  push:
    branches: [main]

permissions:
  contents: read
  id-token: write

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: dorelli-cloud/action@v1
        with:
          plan: app
          email: you@example.com
          site-id: ${{ secrets.DORELLI_SITE_ID }}
          registry-user: ${{ secrets.DORELLI_REGISTRY_USER }}
          registry-password: ${{ secrets.DORELLI_REGISTRY_PASSWORD }}
```

La première exécution crée le site et un jeton de registry, lie le site à ton dépôt et t'indique quels trois secrets régler : l'identifiant du site et les deux valeurs de registry. Avec `permissions: id-token: write`, chaque exécution suivante prouve qu'elle vient de ton dépôt, donc il n'y a pas de jeton de déploiement à conserver ; les valeurs de registry restent, car docker push en a besoin. Dans un dépôt public, tout le monde peut lire ce qu'affiche une exécution, donc crée le mot de passe de registry dans le portail, comme expliqué plus bas. Une première publication a déjà tourné dans un dépôt public ? Crée alors aussi un nouveau jeton de déploiement dans le portail, et fais une exécution avec ce jeton (`deploy-token`) et `bind-github: true` : un jeton apparu un jour dans une exécution ne marche plus, et le site est de nouveau lié. Garde le workflow sur `on: push` vers `main` et évite `pull_request_target` : la plateforme fait confiance à chaque exécution venant de ton dépôt, donc un workflow qui tourne aussi pour les pull requests d'inconnus leur permettrait de publier ton site. Les exécutions lancées par `pull_request_target`, `issues`, `issue_comment`, `discussion` ou `discussion_comment` sont refusées de toute façon. Tu as déjà un site avec un jeton de déploiement ? Ajoute `bind-github: true` à l'étape le temps d'une exécution : la plateforme lie alors le site à ton dépôt, et le jeton peut disparaître. Ton app reçoit `DATABASE_URL` et `PORT` (3000 par défaut) comme variables d'environnement. Pas besoin de Dockerfile : nous utilisons alors `npm ci`, `npm run build`, `npm start`. Tu as ton propre Dockerfile ? Il est utilisé tel quel. Tu as perdu le mot de passe du registry, ou une exécution échoue à docker login ? Dans le portail, onglet Agents de ton app, sous Jeton de registry, clique sur Renouveler et mets le mot de passe dans le secret `DORELLI_REGISTRY_PASSWORD` ; l'utilisateur reste le même, et seul le dernier mot de passe affiché fonctionne.

Vos propres secrets, par exemple une clé d'API : mettez-les dans les secrets de votre dépôt et ajoutez à l'étape un bloc `secrets`, un `NOM=valeur` par ligne, par exemple `API_KEY=${{ secrets.API_KEY }}`. Ils vont uniquement à votre conteneur et arrivent comme variables d'environnement, à partir du deuxième run, une fois le conteneur en place ; nous gardons les noms, jamais les valeurs. Les noms sont en majuscules, chiffres et `_`, 20 au plus par app ; `PORT`, `DATABASE_URL`, `POSTGRES_URL`, `REDIS_URL`, `STORAGE_CONNECTION_STRING` (aussi avec un suffixe) et `DORELLI_*` sont réglés par nous. Les secrets fonctionnent sur nos propres emplacements Azure ; un site en pause ne les reçoit qu'une fois relancé.

L'app descend à zéro sans trafic ; la première visite après une période calme prend 10 à 30 secondes, voir [Démarrages à froid](/docs/apps/cold-start). Les logs, le redémarrage et les variables d'environnement sont dans ton espace, voir [Logs, redémarrage et variables](/docs/apps/portal).