Skip to content

Create a new application

This guide explains what a SvelteKit app inside this pnpm workspace needs to consume @dg/ui, file by file. The boilerplate is the runnable source for every file named here; this page explains each one rather than copying it. Read the workspace prerequisites first and run shell commands from the repository root.

01Start from the boilerplate

Copy the boilerplate's source files into a uniquely named apps/<name> directory, following its copy procedure: rename the package, choose unused ports and adapt the copied README and AGENTS.md. The workspace already includes apps/*. Domain content, routes, services and local components belong in that directory. Read the composition guide, then select components from the reference index.

The boilerplate is static and assumes hosting at the domain root. If the app needs a server, authentication or runtime endpoints, choose an appropriate adapter and prerender policy in that app. Do not put credentials in static routes or client-side imports. A static UI may call an independently hosted backend; it cannot keep a client-side secret.

02Package and configuration

The package manifest depends on "@dg/ui": "workspace:*" and on the framework version ranges shared by the existing apps; keep them aligned rather than upgrading unrelated dependencies. marked belongs to the documentation app and is unnecessary elsewhere.

The build configuration ships with the toolkit, so an app depends only on its own directory and the package:

  • vite.config.js passes the SvelteKit plugin and the adapter to createViteConfig from @dg/ui/config/vite.js. The factory configures SvelteKit with root-relative asset URLs, so error documents work at nested addresses; it also compiles custom media in every stylesheet, serves the package's fonts and sources in development and bundles @dg/ui during SSR. Do not copy the DS-specific documentation reload plugin.
  • jsconfig.json extends $app/tsconfig, which SvelteKit sync generates, and @dg/ui/config/tsconfig.json, which keeps type checks non-strict. Do not edit or commit generated .svelte-kit files.
  • The manifest's imports field maps #lib/* to ./src/lib/*, so app modules import src/lib files as #lib/..., with their file extension.
  • playwright.config.js passes the app's browser-test port to createPlaywrightConfig from @dg/ui/config/playwright.js, which starts the app's dev server on that port and runs the *.spec.js files in tests/. The manifest's test:ui script runs them.

The package exports these files:

ExportPurpose
@dg/uiPublic Svelte components, listed in the component index.
@dg/ui/styles.cssNormal entry point, imported once in the root layout: tokens, then base.css.
@dg/ui/tokens.cssDesign tokens: shared values and the light and dark palettes, for explicit loading.
@dg/ui/base.cssFont faces, document defaults and shared classes. Needs tokens.
@dg/ui/breakpoints.cssBuild-time custom media input; supplied through the shared Vite factory, not a runtime import.
@dg/ui/fonts/*Self-hosted fonts: Roboto, Roboto Mono and Teodor.
@dg/ui/logo.svgGallery mark for asset imports; the favicon of every gallery app.
@dg/ui/config/*The Vite, TypeScript and Playwright configuration above.

Component imports load only their scoped CSS; the foundations come from styles.css.

03Document and layout

src/app.html sets <html lang> to the audience language. Page places a small script in the document head that restores the saved theme before first paint; it tolerates unavailable storage. The default is light; the toolkit does not infer a system theme. ThemeToggle manages subsequent changes and synchronization.

The root layout composes the quick reference shell once: it imports @dg/ui/styles.css, sets @dg/ui/logo.svg as the favicon, owns the single main landmark and mounts Analytics, which measures visits and adds the privacy control to Footer. Routes supply sections without adding another Page or Main. Set Page's lang to match <html lang> (en or fr): every built-in label of the toolkit follows it. Configure identity and navigation links for the app rather than keeping the boilerplate's example routes.

+layout.js enables prerendering. Dynamic route parameters need discoverable links or explicit prerender entries before a static build can emit them. Runtime data and integrations belong to the app; the toolkit supplies presentation, interaction and audience measurement.

04Error routes and hosting

+error.svelte renders ErrorPage with the error status, a title and noindex. The 404/ route renders the same page without an error, with trailingSlash = "never", so the static build emits one 404.html for the host.

Static output goes to apps/<name>/build/; the deployment files below serve it with clean URLs and a real 404 status.

05Deployment files

Copy Dockerfile, Dockerfile.dockerignore and Caddyfile from the boilerplate and replace boilerplate with the app name in the first two. The Caddyfile already serves clean URLs, 404.html with status 404, /health and the statistics configuration at /analytics-config.json; add app-specific routes there only. That configuration points to the distributed·gallery statistics website by default, so the app measures its audience once deployed, without any setting. Build the image from the repository root with docker build -f apps/<name>/Dockerfile ., then configure the hosting service as described in Deployment. After deploying, check that a nested missing URL returns 404.

06Install, run and verify

pnpm install
pnpm --filter <name> dev

In another terminal, run the workspace checks and build the app:

pnpm check
pnpm check:toolkit
pnpm --filter <name> build
pnpm --filter <name> test:ui
pnpm --filter <name> preview

The workspace checks discover new apps; pnpm build includes apps with a build script and pnpm test:ui apps with a test:ui script. Keep the boilerplate's tests/shell.spec.js, which checks the frame every app shares, with the app's own labels and navigation link, and add the app's browser tests beside it.

Then perform the rendered check on the running app.

Finish with an app README covering purpose, routes, commands, content locations and hosting requirements, and a local AGENTS.md only for app-specific implementation instructions. Link back to this reference instead of repeating toolkit APIs. Add the application to the workspace README's app table. Preserve the lockfile update from installation.

distributed·gallery