conceptshared last reviewed 2026-06-04

Aspire technology stack โ€” defaults for new projects

Context

New Aspire projects historically picked their own stack (Next.js + Prisma, NestJS + TypeORM, Django + DRF, etc.), which fragmented the engineering surface and made cross-project hiring/maintenance harder. As of 2026-05-31, there is a single default starting stack for all new apps.

This is a standing instruction: every new Aspire/Zinga/Alby/Goldroom app should start from this stack until there is a clearly better option. If a project uses something else, record the reason as an ADR/spec note before implementation so future agents and humans can see the trade-off.

Detail

Default app stack

LayerDefaultImplementation note
FrontendSvelteKitSSR-first app shell with small client bundles; use the Svelte ecosystem for UI/BFF glue.
Backend APIGoPrefer a small HTTP service boundary; Echo is acceptable where a framework is useful.
Backend ORMGORMDefault relational mapping layer for Go services. Keep raw SQL for hot paths or complex reporting.
Scripting / BFFNode.jsUse for SvelteKit integration, prototypes, CLIs, and glue code rather than core long-lived APIs.
Primary databasePostgreSQLUse JSONB and pgvector where useful; avoid introducing another primary database.
Node/TS ORMPrismaUse when a TypeScript service or SvelteKit server code needs typed DB access.
Cache / queueRedisSessions, rate limits, real-time state, background handoff, and ephemeral workflow state.
Object storageMinIOSelf-hosted S3-compatible storage for user uploads, generated media, AI datasets, and cached assets.
Model gatewayLiteLLM via Aspire LLM GatewayAll app LLM traffic goes through the gateway unless an ADR says otherwise.
Local inferenceLocal models when hardware existsDefer until workstation-class GPU capacity is available; use gateway/cloud fallbacks meanwhile.
TTSElevenLabsCurrent default for voice response synthesis. Cache generated audio in MinIO where practical.
STTProvider-specific, behind app boundaryTwilio speech gather is acceptable for telephony apps; revisit per channel.
VCS / CISelf-hosted GitLabPrefer decoupled repositories and independent pipelines per service.
Production deployGitLab-built artifacts on Coolify now, Kubernetes targetGitLab CI builds/scans/promotes images or artifacts; Coolify runs them as the practical deployment layer. Kubernetes is the target when app scale warrants it.
Proxy / ingressNginx targetCurrent path may still be Cloudflare -> Coolify/Traefik. Move toward Nginx where infrastructure changes justify it.

Repository and deployment default

Existing apps that stay on legacy stacks

AppStackNotes
zinga-* (PMS, Booking, CM, Kitchen, Procure, Ledgr, Pay)Next.js + PrismaAlready shipped, don't refactor
alby-studioNext.js + custom authAlready shipped
Aspire Staff Portal / HubNext.js + NextAuth + Prisma (in Turborepo)Already shipped, integrates with new stack via OIDC
Knowledge OS enginePython (FastAPI + FastMCP)Async ML workloads benefit from Python
WordPress merchant storefronts (Alby Place, Six Degrees, etc.)WordPress + WooCommerce + ElementorMerchant tier; not Aspire-engineered

Product-specific exceptions

Excluded

MCP-friendly tooling

Where possible, prefer apps with official MCP servers (Coolify, GitLab, n8n, Odoo, Stripe, Xero) so agents can drive them programmatically without ad-hoc scripts.

Migration priority for legacy apps

When touching legacy apps, prefer incremental alignment before rewrites:

  1. Add Redis for sessions, rate limits, queues, and real-time/call state.
  2. Add MinIO for user media, generated media, cached TTS, and AI datasets.
  3. Route model calls through LiteLLM/Aspire LLM Gateway.
  4. Move deploys to GitLab-built immutable images/artifacts promoted through staging and prod.
  5. Add or update the project deploy inventory, including Coolify UUIDs, registry image, health checks, smoke tests, and rollback tag.
  6. Split tightly coupled monorepos only when independent deploy cycles or ownership boundaries justify it.
  7. Consider SvelteKit + Go rewrites only when the app is being substantially rebuilt anyway.

Revisit

Stack defaults reviewed quarterly. Last review: 2026-06-04.

Related

๐Ÿ”— Relationships

graph LR aspire_tech_stack["aspire-tech-stack"]:::self aspire_tech_stack --> use_postgresql_by_default["use-postgresql-by-default"] aspire_tech_stack --> aspire_llm_gateway_only_egress["aspire-llm-gateway-only-egress"] aspire_tech_stack --> gitlab_self_hosted_not_github["gitlab-self-hosted-not-github"] aspire_tech_stack --> minio_storage_per_app["minio-storage-per-app"] classDef self fill:#715EE3,color:#fff,stroke:#291F50;