Skip to content

feat: Monorepo support with root-level app configuration #8

@joelhooks

Description

@joelhooks

Summary

Add monorepo support to allow a single root-level .secrets.json to manage credentials for multiple apps, eliminating the need for per-directory config files.

Problem

The current .secrets.json model is per-directory, which creates friction for monorepos. In repos like course-builder with 15+ apps, each app needs different Vercel project credentials. Right now you'd need:

  • 15 separate .secrets.json files
  • Manual navigation to each app directory to sync secrets
  • No unified view of credential configuration

This is clunky as hell.

Proposed Solution

Introduce a type: "monorepo" schema where a root-level .secrets.json contains an apps map. Each app gets its own source configuration and can be synced individually or in bulk.

Schema Example

{
  "type": "monorepo",
  "apps": {
    "ai-hero": {
      "source": "vercel",
      "project": "ai-hero",
      "scope": "production"
    },
    "epic-web": {
      "source": "vercel", 
      "project": "epic-web",
      "scope": "production"
    },
    "marketing-site": {
      "source": "vercel",
      "project": "marketing-site", 
      "scope": "production"
    }
  },
  "ttl": "1h"
}

CLI Usage

# Sync secrets for a specific app
secrets env ai-hero

# Sync all apps at once
secrets env --all

# Run a command with a specific app's secrets
secrets exec ai-hero -- bun dev

# Initialize a monorepo config interactively
secrets init --monorepo

Implementation Hints

  1. Config Detection (internal/project/config.go)

    • Update FindProjectConfig to detect type: "monorepo"
    • Add MonorepoConfig struct with Apps map[string]AppConfig
    • Keep backward compatibility with existing single-app configs
  2. Command Updates

    • env command: accept optional app name as first arg; require --all flag for bulk sync
    • exec command: accept app name as first arg before -- delimiter
    • init command: add --monorepo flag to scaffold monorepo config
  3. App Resolution Flow

    // Pseudocode
    if config.Type == "monorepo" {
        if appName == "" {
            return error "app name required for monorepo"
        }
        appConfig := config.Apps[appName]
        // use appConfig.Source, appConfig.Project, etc.
    }
  4. File Writing (env command)

    • For monorepo mode with specific app: write .env.local in app subdirectory (e.g., apps/ai-hero/.env.local)
    • For monorepo mode with --all: iterate apps and write each app's .env.local in its subdirectory
    • For legacy single-app mode: keep current behavior (write to project root)
  5. Validation

    • Ensure app names in apps map are valid directory names
    • Validate each app's source config (Vercel project exists, etc.)
    • Provide clear errors if app name doesn't exist in config

Acceptance Criteria

  • Root-level .secrets.json can define type: "monorepo" with apps map
  • secrets env <app-name> syncs secrets for specified app
  • secrets env --all syncs secrets for all apps in monorepo
  • secrets exec <app-name> -- <cmd> runs command with app-specific secrets
  • secrets init --monorepo creates monorepo-style config interactively
  • Backward compatibility: existing single-app configs continue working
  • Clear error messages when app name is missing or invalid
  • Documentation updated with monorepo examples
  • Tests cover monorepo config detection and app resolution

Related

This unblocks course-builder and any other monorepo with multiple Vercel deployments needing distinct credential sets.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions