Skip to content

Svelte App

A Svelte single-page application deployed on AppMecca. This example demonstrates deploying a JavaScript framework application as a standalone service.

Overview

Repository git@gitlab.com:appmecca-sample-apps/svelte-app.git
Tech Stack Svelte / SvelteKit / Node.js
Services web (port 3000)
Database None
Cache None
URL Pattern https://svelte-app-web.{env}.appmecca.net

What This App Demonstrates

  • Deploying a Svelte/SvelteKit application on AppMecca
  • SvelteKit with adapter-node for server-side rendering
  • Node.js runtime containers (as opposed to Nginx for static SPAs)
  • Alternative JavaScript framework deployment alongside React and Vue

appmecca.yaml

containers:
  - name: web
    dockerfile: Dockerfile
    context: .

deploy:
  - name: web
    container: web
    port: 3000
    health_check:
      path: /health

The configuration is straightforward -- a single container running the SvelteKit Node.js server on port 3000.

Step-by-Step Deployment

1. Register the app

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

2. Build the container

mecca build trigger -e dev -g git@gitlab.com:appmecca-sample-apps/svelte-app.git
Expected output
Build started: build-xxxxxxxx
Cloning repository...
Building container: web
Step 1/10 : FROM node:20-slim AS builder
Step 6/10 : RUN npm run build
Pushing to the image registry: appmecca-dev-svelte-app
Build complete. Duration: 48s

3. Deploy

mecca app deploy -e dev svelte-app
Expected output
Deploying svelte-app to dev...
Deployment queued: deploy-xxxxxxxx
Waiting for agents...
Container started: svelte-app-web
Health check passed: /health -> 200 OK
Deployment complete.

Services:
  web: https://svelte-app-web.dev.appmecca.net

4. Verify

mecca app show -e dev svelte-app

Test the health endpoint:

curl https://svelte-app-web.dev.appmecca.net/health
{"status": "healthy"}

Key Concepts

SSR vs. static Svelte

SvelteKit supports multiple output modes through adapters. This sample app uses adapter-node, which runs a Node.js server and enables server-side rendering.

Adapter Output Runtime Use case
adapter-node Node.js server Node.js process (port 3000) SSR, API routes, dynamic content
adapter-static Static HTML/CSS/JS Nginx (port 80) Pre-rendered pages, pure SPAs

Runs a live Node.js server. Pages are rendered on the server for each request. Supports API routes and dynamic server-side logic.

// svelte.config.js
import adapter from '@sveltejs/adapter-node';

export default {
  kit: {
    adapter: adapter()
  }
};

Generates static HTML files at build time. Serve them with Nginx using the same pattern as the Static Site example.

// svelte.config.js
import adapter from '@sveltejs/adapter-static';

export default {
  kit: {
    adapter: adapter({ fallback: 'index.html' })
  }
};

Choosing an adapter

Use adapter-node when you need server-side rendering, API routes in +server.js files, or dynamic content that changes per request. Use adapter-static for marketing sites, documentation, or apps where all content can be pre-rendered.

Multi-stage Dockerfile

The Dockerfile compiles the SvelteKit app and runs it with a minimal Node.js image:

FROM node:20-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-slim
WORKDIR /app
COPY --from=builder /app/build/ ./build/
COPY --from=builder /app/package*.json ./
RUN npm ci --only=production
EXPOSE 3000
CMD ["node", "build"]

Unlike the React example (which serves static files with Nginx), the Svelte SSR app runs an actual Node.js process. The final image is larger (~200 MB) because it includes the Node.js runtime.

Health check endpoint

For SvelteKit apps, define a health endpoint as a server route:

// src/routes/health/+server.js
export function GET() {
  return new Response(
    JSON.stringify({ status: 'healthy' }),
    { headers: { 'Content-Type': 'application/json' } }
  );
}

This is a SvelteKit API route -- it runs on the server and responds to GET requests at /health.

Viewing logs

Monitor your Svelte app's server-side output. The app name is the positional argument; the service is selected with -s:

mecca logs svelte-app -s web -e dev

Useful filters:

# Container stdout/stderr only, last 24 hours
mecca logs svelte-app -s web --type container --since 24h -e dev

# Errors only
mecca logs svelte-app -s web --level error -e dev

# Full-text search
mecca logs svelte-app -s web --search "timeout" -e dev

What's Next?