Showcase

Static sites on orbitalhq.io. Add a directory, open a merge request.

Showcase hosts public, customer-facing content: demos, guides and prototypes. Each top-level directory in the repo is one site. A merge request gets a preview. Merging to main publishes the site.

vyne/showcase
showcase/├── about/         # about.showcase.orbitalhq.io├── hello-world/   # hello-world.showcase.orbitalhq.io├── your-site/     # your-site.showcase.orbitalhq.io├── scripts/       # pipeline scripts├── AGENTS.md└── README.md
One directory per site. The directory name is the subdomain.

Two domains: one for previews, one for live sites.

Previews, from merge requests

*.audition.orbitalhq.io

acme-demo--mr12.audition.orbitalhq.io

One per site in each open merge request. Deleted when the MR is merged or closed.

Live sites, from main

*.showcase.orbitalhq.io

acme-demo.showcase.orbitalhq.io

Updated each time a change to the site merges to main.

How it works

Add a directory, open a merge request, merge.

GitLab CI builds and deploys only the directories you changed. DNS and HTTPS are set up on the first deploy.

  1. Step 1

    Add a directory

    Its name becomes the subdomain. Put a built app or plain HTML inside it.

  2. Step 2

    Open a merge request

    The pipeline builds the site and deploys a preview to name--mr12.audition.orbitalhq.io. The link appears on the MR.

  3. Step 3

    Merge

    The site goes live at name.showcase.orbitalhq.io. The preview is deleted.

Check a site name

Uses the same rules as the pipeline.

    Preview
    Production

    Create a site

    Pick a name, then add your files.

    A site is either a built app with a package.json, or a folder of plain HTML. Add a .showcase.json only if the defaults don't fit.

    Naming rules

    • 3 to 50 characters: lowercase a-z, 0-9 and single dashes.
    • No double dashes, and no dash at the start or end.
    • Not scripts, schema or node_modules, and not starting with a dot.

    What goes inside

    • Built app: a package.json with a build script, and a committed package-lock.json. The build should write to dist/.
    • Plain static files: an index.html and your assets. Nothing is built.

    Check it locally

    From the repo root, build the site, then run the deploy script with --dry-run. It checks that the build output exists and that the generated config is valid. Nothing is uploaded.

    acme-demo/.showcase.json
    {  "$schema": "../schema/showcase.schema.json",  "build": {    "image": "node:22",    "command": "npm ci && npm run build",    "output": "dist"  },  "spa": true}
    Terminal
    (cd acme-demo && npm ci && npm run build)node scripts/deploy-site.mjs acme-demo --dry-run
    Fields in .showcase.json
    FieldDefaultWhat it does
    build.imagenode:22The Docker image the build runs in. Use it to pick a Node version.
    build.commandnpm ci && npm run build with a package.json, otherwise noneShell command run inside your directory. null serves the files as they are.
    build.outputdist with a package.json, otherwise .The folder, relative to your directory, that gets published.
    spafalsetrue serves index.html for unknown paths, for client-side routers. Otherwise unknown paths get the nearest 404.html.

    For headers and redirects, add Cloudflare _headers and _redirects files to your build output. With Vite, put them in public/.

    Previews

    Every merge request gets its own URL.

    Push a branch and open a merge request against main. The MR shows a link to the preview.

    Terminal
    git checkout main && git pullgit checkout -b add-acme-demo# add acme-demo/, then:git add acme-demogit commit -m "Add acme-demo showcase site"git push -u origin HEADglab mr create --fill --target-branch main
    Preview URL<dir>--mr<number>.audition.orbitalhq.io
    First deployAbout two minutes before HTTPS works, while the certificate is issued
    Later pushesLive as soon as the deploy job finishes
    Search enginesPreviews send X-Robots-Tag: noindex
    Clean-upDeleted when the MR is merged or closed, or two weeks after the last deploy

    What you can deploy

    Anything that builds to static files

    Each site is served from the root of its own subdomain, so leave the framework's base path as /.

    Vite

    React, Vue, Svelte

    Defaults work. Add "spa": true for a client-side router.

    Next.js

    Static export

    Set output: 'export', then "output": "out".

    Astro

    Static output

    Defaults work.

    SvelteKit

    adapter-static

    "output": "build"

    Angular

    Browser build

    Output is dist/<project>/browser. Add "spa": true.

    Create React App

    Build folder

    Output is build. Add "spa": true.

    Docs sites

    VitePress, Docusaurus

    Point build.output at the generated folder.

    Plain HTML

    No build

    Leave out package.json. The folder is served as it is.

    Works

    HTML, CSS, JavaScript, images and fonts. Client-side routing with "spa": true. Custom headers and redirects.

    Doesn't work

    Server-side rendering, API routes, serverless functions, runtime secrets and databases. If a site needs these, it doesn't belong here.

    Coding agents

    Point your agent at AGENTS.md.

    The repo has instructions for coding agents. They cover naming, the config file, the local check and opening the merge request.

    Prompt
    Clone git@gitlab.com:vyne/showcase.git, read AGENTS.md and follow it.Create a showcase site called acme-demo from the app in ./my-app.Build it and run the dry-run deploy locally, then open a merge request and give me the preview URL from the pipeline.

    Start with a branch and a directory.

    The README has the full checklist, the config reference and fixes for common pipeline failures.