Skip to content

feat(onboarding): mint the first workspace instead of asking for its … #74

feat(onboarding): mint the first workspace instead of asking for its …

feat(onboarding): mint the first workspace instead of asking for its … #74

Workflow file for this run

name: Deploy app
# Deploy the Talyn application — app.talyn.dev — to Vercel on every push to
# main that touches it. Unlike apps/marketing this IS an npm workspace member
# (it depends on @talyn/client and @talyn/shared), so everything installs from
# the ROOT lockfile, not a private one.
#
# NAMING: the two Vercel deploys are "web" (the marketing WEBSITE,
# www.talyn.dev, deploy-marketing.yml, VERCEL_PROJECT_ID_WEB) and "app" (the
# APPLICATION, app.talyn.dev, this file, VERCEL_PROJECT_ID_APP). The source
# directory is still apps/web, which reads backwards against that — the
# secret, not the folder, is what decides where a build lands, so check the
# secret. Pointing this at the website's project id would publish the app's
# bundle over www.talyn.dev.
#
# THIS WORKFLOW IS THE ONLY DEPLOY PATH. apps/web/vercel.json sets
# `"git": { "deploymentEnabled": false }`, which turns off Vercel's own
# push-triggered builds — otherwise every push to main deploys app.talyn.dev
# TWICE, once from here and once from Vercel's Git integration, and whichever
# finishes last wins the production alias.
#
# That race is not theoretical: on 2026-08-04 the two paths disagreed about
# env (Vercel's build had the real Supabase values, the CLI build got
# `[SENSITIVE]` placeholders) and the losing-but-later build served a white
# screen. Keeping one path means one thing to reason about — and this is the
# one to keep, because `check` typechecks before anything deploys.
#
# Deploys here still work: `git.deploymentEnabled` only governs Vercel's Git
# hooks, not an explicit `vercel deploy --prebuilt`.
on:
push:
branches: [main]
paths:
- 'apps/web/**'
- 'packages/client/**'
- 'packages/shared/**'
- '.github/workflows/deploy-app.yml'
workflow_dispatch: {}
jobs:
check:
runs-on: ubuntu-latest
# Skip on forks — no secrets there and nothing to deploy.
if: github.repository == 'Gilbert09/talyn'
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Install Node.js and NPM
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- name: Install dependencies
run: npm install
- name: Build workspace deps
run: |
npm run build -w @talyn/shared
npm run build -w @talyn/client
- name: Typecheck
run: npx tsc --noEmit -p apps/web/tsconfig.json
deploy:
needs: check
runs-on: ubuntu-latest
if: github.repository == 'Gilbert09/talyn'
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID_APP }}
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Install Node.js and NPM
uses: actions/setup-node@v4
with:
node-version: 22
# Until the Vercel project exists, a push that touches apps/web would
# fail this job red on a missing project id. Skip cleanly instead —
# `check` above still gates the code. (The guard lives inside a step,
# not in `if:`, because the `secrets` context is not available in job
# conditions — same reason publish.yml guards its sourcemap upload
# this way.)
- name: Is the Vercel project configured?
id: gate
run: |
if [ -z "${{ secrets.VERCEL_PROJECT_ID_APP }}" ]; then
echo "VERCEL_PROJECT_ID_APP not set — skipping deploy."
echo "configured=false" >> "$GITHUB_OUTPUT"
else
echo "configured=true" >> "$GITHUB_OUTPUT"
fi
- name: Install Vercel CLI
if: steps.gate.outputs.configured == 'true'
run: npm i -g vercel
# Run from the repo root — the Vercel project's Root Directory is pulled
# with the project settings. VITE_TALYN_* build values live as Vercel
# project environment variables so `vercel build` sees them.
#
# Those variables must NOT be marked "Sensitive" in Vercel. `vercel pull`
# cannot decrypt a sensitive variable — it writes the literal string
# `[SENSITIVE]`, which then gets baked into the bundle. buildEnv.ts
# rejects that value by name now, so the build fails loudly instead of
# shipping a white screen (which is what happened to the web app on
# 2026-08-04, because the guard only checked for EMPTY).
- name: Pull Vercel environment
if: steps.gate.outputs.configured == 'true'
run: vercel pull --yes --environment=production --token="${{ secrets.VERCEL_TOKEN }}"
- name: Build
if: steps.gate.outputs.configured == 'true'
env:
# Passed explicitly rather than relying on VERCEL_GIT_COMMIT_SHA:
# `--prebuilt` runs after OUR checkout, so Vercel injects that
# variable empty and the build shipped as "web/" with no SHA.
VITE_TALYN_BUILD_SHA: ${{ github.sha }}
run: vercel build --prod --token="${{ secrets.VERCEL_TOKEN }}"
- name: Deploy
if: steps.gate.outputs.configured == 'true'
run: vercel deploy --prebuilt --prod --token="${{ secrets.VERCEL_TOKEN }}"