Frontend, Go backend, and AWS infrastructure for apps.debugjois.dev.
app/is a TanStack Start app on Nitro. It runs as a Node.js Lambda behind API Gateway and CloudFront and serves the public apps, the admin-only logger, and the admin sign-in. See app/README.md.backend/is a Go Lambda shipped as a container image, with no HTTP API. The app invokes it directly for daily-log and podcast transcription actions, and an EventBridge rule runs it daily. The same code builds CLIs for local use. See backend/README.md.infra/holds the AWS CDK stacks anddeploy.sh, which deploys them without CDK bootstrap. See infra/README.md.
Agents start with AGENTS.md. It lists the checks to run, the repo conventions, and the commands that change AWS.
Go and Node come from flake.nix, with their nixpkgs versions pinned by
flake.lock. npm is pinned separately in the flake because it releases
independently of Node. The flake also supplies the AWS, GitHub, Google Cloud,
and media CLIs. Application dependencies stay in package-lock.json and
go.mod and go.sum. Builds are not Nix derivations.
Supported hosts are x86-64 and ARM64 Linux and Apple Silicon macOS. Current nixpkgs has dropped Intel macOS.
Go helper tools (gopls, golangci-lint, govulncheck, go-mod-upgrade,
gomajor) are pinned in scripts/install-go-tools.sh, which builds them with
go install and the active compiler. The dev shell puts their install
directory, ~/.cache/apps-debugjois-dev/go-tools/bin, on PATH and sets
GOTOOLCHAIN=local so Go never downloads a compiler on its own.
-
Install Nix with flakes enabled (
experimental-features = nix-command flakesinnix.conf). -
Enter the environment. With direnv, which nix-direnv makes faster:
direnv allow
Or by hand:
nix develop
-
Install project dependencies:
npm --prefix app ci npm --prefix infra ci (cd backend && go mod download) ./scripts/install-go-tools.sh
Tests and builds need no credentials. Live integrations and deployments do. Each component README lists what its commands need.
docker with buildx is not in the flake. Install it separately to build
backend images with infra/deploy.sh --with-backend-image.
- Run
nix flake updateto refresh Go, Node, and the other nixpkgs packages. - When npm releases ahead of the version bundled with Node, update npm's
version and tarball hash in
flake.nix. - Update Go helper pins in
scripts/install-go-tools.sh, then rerun it. Pass names to install only those helpers, for example./scripts/install-go-tools.sh golangci-lint. - Re-enter
nix developafter flake changes. Format the flake withnix fmt flake.nix. backend/go.moddeclares the minimum Go language version, not a compiler patch pin. The backend Docker build reads its compiler version fromgo env GOVERSIONin the active environment.
npm install scripts need explicit allowScripts approval in each project's
package.json. Review with npm --prefix infra install-scripts ls and approve
only reviewed packages and versions, not all scripts globally.
A fresh Amp orb runs .agents/setup. It installs Nix if missing, builds the
flake's tool profile (packages.default) into
~/.cache/apps-debugjois-dev/nix-tools, adds a ~/.bash_profile hook through
.agents/profile-hook that puts the profile on PATH for login shells inside
the repo, and installs the npm and Go dependencies and the Go helpers.
Setup reuses the tool profile when the flake fingerprint matches. Once the
tools are available, the two npm installs, Go module download, and Go helper
installs run concurrently; setup waits for all of them and fails if any fails.
Each task logs its elapsed time. A cold start still downloads the full Nix
profile (including Google Cloud and media tools) and compiles all five Go
helpers. Warm runs reuse Nix and Go caches, but npm ci reinstalls dependencies
from each lockfile.
.agents/resume rebuilds the tool profile when flake.nix or flake.lock
changed since the last build. It also moves the hook back to the end of
~/.bash_profile, because Amp appends a block there on activation that
sources ~/.env, whose PATH would otherwise hide the Nix tools. Resume does
not rebuild Go helpers.
After editing the flake or the Go helper pins in an orb, refresh the tools and start a new login shell:
.agents/nix-tools
./scripts/install-go-tools.shEvery workflow uses .github/actions/setup-tools. It installs Nix, caches the
Nix store and the npm and Go download and build caches, and activates the
smaller packages.ci profile from the flake. Jobs request only the Go helpers
they need, from the same version list local development uses. The CDK CLI
comes from the infra lockfile, not a global install. AWS OIDC and Docker buildx
stay GitHub Actions responsibilities.
| Workflow | Trigger | Effect |
|---|---|---|
| App Test and Deploy | Push to main touching app/ |
infra/deploy.sh --with-artifact |
| Backend Test and Deploy | Push to main touching backend/ or the flake |
infra/deploy.sh --with-backend-image |
| Infra Build | Push to main touching infra/ |
Type-check and synth only |
| Infra Deploy | Manual | infra/deploy.sh reusing the deployed artifacts |
| CI | Every PR, and pushes changing the flake or workflows | nix flake check plus all three component check suites |
| Backend Go Vulnerability | PRs touching backend/ or the flake, and Thursdays |
govulncheck ./...; on failure, dispatches the fixing upgrade |
| Dependency Upgrades | Mondays | npm PRs for app/ and infra/: within-major and majors |
| Go Major Version Upgrades | Mondays | PR applying Go major versions with gomajor |
| Go Dependency Upgrades | Tuesdays | PR bumping Go minor and patch versions |
| Toolchain Upgrades | Wednesdays | PR running nix flake update and bumping npm and Go helpers |
| Dependabot Auto-merge | Dependabot PRs | Enables auto-merge on non-major updates |
| Site Search Index | Hourly, manual, and pushes changing the indexer | Indexes the daily log and publishes it for /site-search |
The deploy workflows share one concurrency group, so deploys run one at a time. A flake change redeploys the backend because the image is built with the flake's Go. The app Lambda runs on the AWS-managed Node runtime, so it does not redeploy. Pull requests never deploy or write to production.
Site Search Index checks out deepakjois/debugjois.dev, indexes its daily
notes, and syncs the index to site-search/index/ in the static asset bucket.
A scheduled run publishes only when that repo's main moved since the
deployed index. infra/deploy.sh leaves that prefix alone.
Every upgrade arrives as a PR, and CI runs on it. Low-risk PRs merge on their own once CI passes, which deploys them:
| Source | Auto-merges | Notes |
|---|---|---|
deps/upgrades (npm within major) |
Yes | Versions must be 3 days old; see .github/scripts/ncurc.cjs |
deps/go-upgrades (Go minor and patch) |
Yes | |
deps/toolchains (flake, npm, Go tools) |
Yes | Fails if Docker has not published the matching golang image |
| Dependabot GitHub Actions and security | Non-major | Actions are grouped weekly on Thursdays with a 3-day cooldown |
deps/npm-majors and deps/go-majors |
No | Opened even when the build breaks; fix on the branch, then merge |
Dependabot opens only security PRs for npm and Go modules, since the upgrade workflows own routine bumps. The scheduled vulnerability check dispatches Go Dependency Upgrades for module findings and Toolchain Upgrades for standard library findings, so a fix is usually already on its way when it fails.
Auto-merging workflows run on different days because the deploy concurrency group keeps only one pending run. A PR that fails CI stays open for you, and the next weekly run updates the same branch.
Upgrade PRs are opened and merged with a GitHub App token, because PRs and
merges made with GITHUB_TOKEN trigger no workflows: CI would never run on the
PR and the merge would never deploy.
-
Create a GitHub App owned by your account with webhooks off and repository permissions Contents, Pull requests, and Workflows set to read and write. Install it on this repository only, and generate a private key.
-
Store its client ID and key as both Actions and Dependabot secrets. Workflows that Dependabot triggers can read only Dependabot secrets.
for app in actions dependabot; do gh secret set DEPS_APP_CLIENT_ID --app "$app" --body "<client id>" gh secret set DEPS_APP_PRIVATE_KEY --app "$app" < path/to/private-key.pem done
-
Allow auto-merge and delete merged branches:
gh repo edit deepakjois/apps.debugjois.dev --enable-auto-merge --delete-branch-on-merge
-
Once CI has run on
main, require itschecksjob onmain. Repository admins bypass the rule, so direct pushes still work. Without a required check, auto-merge would merge before CI finishes.gh api repos/deepakjois/apps.debugjois.dev/rulesets --method POST --input - <<'JSON' { "name": "require-ci", "target": "branch", "enforcement": "active", "conditions": { "ref_name": { "include": ["~DEFAULT_BRANCH"], "exclude": [] } }, "bypass_actors": [{ "actor_id": 5, "actor_type": "RepositoryRole", "bypass_mode": "always" }], "rules": [{ "type": "required_status_checks", "parameters": { "strict_required_status_checks_policy": false, "required_status_checks": [{ "context": "checks", "integration_id": 15368 }] } }] } JSON