Claude
Skills
Sign in
Back

eve-fullstack-app-design

Included with Lifetime
$97 forever

Architect a full-stack application on Eve Horizon — manifest-driven services, managed databases, build pipelines, deployment strategies, secrets, and observability. Use when designing a new app, planning a migration, or evaluating your architecture.

Design

What this skill does


# Full-Stack App Design on Eve Horizon

Architect applications where the manifest is the blueprint, the platform handles infrastructure, and every design decision is intentional.

## When to Use

Load this skill when:
- Designing a new application from scratch on Eve
- Migrating an existing app onto the platform
- Evaluating whether your current architecture uses Eve's capabilities well
- Planning service topology, database strategy, or deployment pipelines
- Deciding between managed and external services

This skill teaches *design thinking* for Eve's PaaS layer. For CLI usage and operational detail, load the corresponding eve-se skills (`eve-manifest-authoring`, `eve-deploy-debugging`, `eve-auth-and-secrets`, `eve-pipelines-workflows`).

## The Manifest as Blueprint

The manifest (`.eve/manifest.yaml`) is the single source of truth for your application's shape. Treat it as an architectural document, not just configuration.

### What the Manifest Declares

| Concern | Manifest Section | Design Decision |
|---------|-----------------|-----------------|
| Service topology | `services` | What processes run, how they connect |
| Infrastructure | `services[].x-eve` | Managed DB, ingress, roles |
| Build strategy | `services[].build` + `registry` | What gets built, where images live |
| Release pipeline | `pipelines` | How code flows from commit to production |
| Environment shape | `environments` | Which environments exist, what pipelines they use |
| Agent configuration | `x-eve.agents`, `x-eve.chat` | Agent profiles, team dispatch, chat routing |
| Runtime defaults | `x-eve.defaults` | Harness, workspace, git policies |

**Design principle**: If an agent or operator can't understand your app's shape by reading the manifest, the manifest is incomplete.

## Service Topology

### Choose Your Services

Most Eve apps follow one of these patterns:

**API + Database** (simplest):
```
services:
  api:        # HTTP service with ingress
  db:         # managed Postgres
```

**API + Worker + Database**:
```
services:
  api:        # HTTP service (user-facing)
  worker:     # Background processor (jobs, queues)
  db:         # managed Postgres
```

**Multi-Service**:
```
services:
  web:        # Frontend/SSR
  api:        # Backend API
  worker:     # Background jobs
  db:         # managed Postgres
  redis:      # external cache (x-eve.external: true)
```

### Service Design Rules

1. **One concern per service.** Separate HTTP serving from background processing. An API service should not also run scheduled jobs.
2. **Use managed DB for Postgres.** Declare `x-eve.role: managed_db` and let the platform provision, connect, and inject credentials. No manual connection strings.
3. **Mark external services explicitly.** Use `x-eve.external: true` with `x-eve.connection_url` for services hosted outside Eve (Redis, third-party APIs).
4. **Use `x-eve.role: job` for one-off tasks.** Migrations, seeds, and data backfills are job services, not persistent processes.
5. **Expose ingress intentionally.** Only services that need external HTTP access get `x-eve.ingress.public: true`. Internal services communicate via cluster networking.
6. **Choose a hostname strategy early.** Every public service gets a generated platform URL by default. Layer on `x-eve.ingress.alias` for a friendlier platform-subdomain (`ingest.eh1.incept5.dev`), or `x-eve.ingress.domains: [limelee.com]` to bring your own domain. Custom domains are env-scoped and first-bind-wins — design which environment owns the apex (usually `production`) before declaring it. See `eve-manifest-authoring` and `eve-deploy-debugging` for declaration and DNS verification flow.

### Stable Outbound IPs (Egress)

Most apps don't care about their outbound source IP — but if you integrate with vendors that allowlist source IPs (cameras, payment processors, partner APIs with strict source-IP rules), declare opt-in stable egress at the service level. The platform schedules the pod onto a public-egress node group with `hostNetwork: true`, giving the service a stable, predictable outbound path instead of a shared NAT mapping. Treat this as a deliberate architectural choice for the one or two services that need it — not a default.

### App Object Storage

Apps that need to store files (uploads, avatars, exports) can declare object store buckets in the manifest:

```yaml
services:
  api:
    x-eve:
      object_store:
        buckets:
          - name: uploads
            visibility: private
          - name: avatars
            visibility: public
```

> **Note:** The database schema for app object stores exists, but automatic provisioning from the manifest is not yet wired. See `references/object-store-filesystem.md` for current status.

When wired, the platform injects `STORAGE_ENDPOINT`, `STORAGE_ACCESS_KEY`, `STORAGE_SECRET_KEY`, `STORAGE_BUCKET`, and `STORAGE_FORCE_PATH_STYLE` into the service container.

**Credential isolation**: app pods receive **app-scoped** storage credentials, not platform-internal credentials. A compromised app service can't reach platform buckets or other tenants' data. Design with this boundary in mind — don't try to share credentials across apps; declare each app's buckets and let the platform issue scoped keys.

### Cloud FS / Google Drive Storage

For document-oriented storage, use cloud FS mounts. Each org connects its own Google Drive via BYOA OAuth credentials, then mounts folders into the org filesystem:

```bash
eve integrations configure google-drive --client-id "..." --client-secret "..."
eve integrations connect google-drive
eve cloud-fs mount --org org_xxx --provider google-drive --folder-id <id> --label "Shared Drive"
```

Apps can browse and search mounted Drive content through Eve's Cloud FS surface (`eve cloud-fs ls`, `eve cloud-fs search`, and the per-mount Cloud FS API routes). This is complementary to object store buckets -- use cloud FS for shared documents and collaboration, use object store for app-managed binary assets.

### Platform-Injected Variables

Every deployed service receives `EVE_API_URL`, `EVE_PUBLIC_API_URL`, `EVE_PROJECT_ID`, `EVE_ORG_ID`, and `EVE_ENV_NAME`. Use `EVE_API_URL` for server-to-server calls. Use `EVE_PUBLIC_API_URL` for browser-facing code. Design your app to read these rather than hardcoding URLs.

## Reference Architecture: SPA + API + Managed DB

The most common Eve fullstack pattern. A nginx-fronted SPA proxies API calls to an internal backend, with managed Postgres and eve-migrate for schema management.

### Service Layout

```
services:
  web:        # nginx SPA (public ingress, proxies /api/ → api service)
  api:        # NestJS/Express backend (internal, no public ingress)
  db:         # managed Postgres 16
  migrate:    # eve-migrate job (runs SQL migrations)
```

**Why nginx proxy?** The web service's nginx reverse-proxies `/api/` to the internal API service. This eliminates CORS, removes the need for hard-coded API hostnames, and gives the SPA same-origin access to the backend. The API service has no public ingress — it's only reachable inside the cluster.

### Manifest Shape

```yaml
services:
  api:
    build:
      context: ./apps/api
      dockerfile: ./apps/api/Dockerfile
    ports: [3000]
    environment:
      NODE_ENV: production
      DATABASE_URL: ${managed.db.url}
      CORS_ORIGIN: "https://myapp.eh1.incept5.dev"
    # No x-eve.ingress — API is internal only

  web:
    build:
      context: ./apps/web
      dockerfile: ./apps/web/Dockerfile
    ports: [80]
    environment:
      API_SERVICE_HOST: ${ENV_NAME}-api    # k8s service DNS for nginx proxy
    depends_on:
      api:
        condition: service_healthy
    x-eve:
      ingress:
        public: true
        port: 80
        alias: myapp                        # https://myapp.{org}-{project}-{env}.eh1.incept5.dev

  migrate:
    image: public.ecr.aws/w7c4v0w3/eve-horizon/migrate:latest
    environment:
      DATABASE_URL: ${managed.db.url}
      MIGRATIONS_DIR: /migrations
  

Related in Design