Skip to content

Express + Svelte Fullstack

Full-stack todo application with a Node.js/Express API and SvelteKit frontend with SPA runtime config injection.

Overview

Tech Stack Node.js / Express (backend) + SvelteKit (frontend)
Services 2 (backend + frontend)
Database PostgreSQL
Pattern Multi-container, SPA config injection

The appmecca.yaml

containers:
  - name: backend
    dockerfile: backend/Dockerfile
    context: backend/

  - name: frontend
    dockerfile: frontend/Dockerfile
    context: frontend/
    args:
      VITE_API_URL: placeholder

deploy:
  - name: backend
    container: backend
    port: 3000
    path: /api
    health_check:
      path: /api/health

  - name: frontend
    container: frontend
    type: spa
    command: 'nginx -g "daemon off;"'   # serves the built bundle from a container
    spa_root: /usr/share/nginx/html
    port: 80
    health_check:
      path: /health
    environment:
      PUBLIC_API_URL: "${service:backend}"

database:
  enabled: true

Key Concepts

SPA Runtime Config (type: spa)

The type: spa and spa_root fields enable runtime configuration injection for static frontends. Instead of baking environment variables at build time, AppMecca writes a __appmecca_config.js file into the spa_root directory at deploy time. The SvelteKit code reads from window.__APPMECCA_CONFIG__ at runtime.

This means the same Docker image can be deployed to different environments with different API URLs -- no rebuild required.

SvelteKit Static Adapter

The frontend uses @sveltejs/adapter-static to compile SvelteKit into a pure static SPA. The built files are served by nginx with SPA routing (try_files $uri /index.html).

You may not need the nginx container at all

This app keeps the frontend in a container so it can use runtime config injection. If you are happy to bake the API URL in at build time, drop the container and make the service type: static with a static_site: block instead — AppMecca then builds the bundle and serves it from the edge cache, with no Dockerfile, no nginx config, no health endpoint and no host memory. See Flask + Vue Fullstack for that shape.

type: spa must be unambiguous

A type: spa service needs either command: (container form, as here) or a static_site: block (edge-served form). With neither, the config is rejected — the platform cannot tell which you intended.

Step-by-Step Deployment

1. Register the app

mecca register git@gitlab.com:appmecca-sample-apps/express-svelte-fullstack.git \
  -e dev

2. Build the containers

mecca build trigger \
  -e dev \
  -g git@gitlab.com:appmecca-sample-apps/express-svelte-fullstack.git

3. Deploy

mecca app deploy -e dev express-svelte-fullstack

4. Verify

mecca queue status takes the action ID printed by the deploy. To look up the app and its exact URLs for your group:

mecca app show express-svelte-fullstack -e dev
curl https://express-svelte-fullstack-backend.dev.appmecca.net/api/health
open https://express-svelte-fullstack-frontend.dev.appmecca.net

What's Next