Setting up a Walking Skeleton

Svelte Client-side Application


Learning Objectives

  • You know how to add a Svelte-based client-side application to a project.
  • You can create a client-side Svelte project that can retrieve information from a server-side application.

At this point, you should have a working server-side setup that you can start with the docker compose --build command. Now, we will create a client-side setup that uses Svelte.

Setting up client directory with Svelte

In the root folder of the project (that is, the folder that contains the server folder), run the command deno run -A npm:sv@latest create client to create a new Svelte project and a new client folder for it. The command asks for a few options — use the following:

  • Pick “SvelteKit minimal” as the Svelte app template.
  • Select “No” when asked for whether to add type checking with TypeScript.
  • Do not add anything to the project when asked “What would you like to add to your project?”.
  • Select “None” when asked which package manager you wish to install dependencies with.

Once you have selected the options and press enter, a new Svelte project is created to the client folder. The structure of the whole project is now as follows.

tree --dirsfirst
.
├── client
│   ├── src
│   │   ├── lib
│   │   │   └── index.js
│   │   ├── routes
│   │   │   └── +page.svelte
│   │   └── app.html
│   ├── static
│   │   └── favicon.png
│   ├── package.json
│   ├── README.md
│   ├── svelte.config.js
│   └── vite.config.js
├── server
│   ├── app.js
│   ├── app-run.js
│   ├── deno.json
│   ├── deno.lock
│   └── Dockerfile
└── compose.yaml

Next, go to the folder client and run the command deno install --allow-scripts. The command installs the dependencies of the project.

Once the dependencies have been installed, in the client folder, run the command deno run dev --open to start a development server and to open up the page in the browser.

The development server is available at the address http://localhost:5173. Accessing it in a browser, you should see a page with the text “Welcome to SvelteKit”.

Fig 1. --  Running the command 'deno run dev' starts a development server at http://localhost:5173. At the address is a page with 'Welcome to SvelteKit' text.

Fig 1. — Running the command ‘deno run dev’ starts a development server at http://localhost:5173. At the address is a page with ‘Welcome to SvelteKit’ text.

To shut down the server, press Ctrl + C in the terminal where the server is running.

Adding a Dockerfile

To containerize the client-side application, we need to add a Dockerfile to the client folder. Create a file called Dockerfile to the client folder and add the following contents to it.

FROM denoland/deno:alpine-2.0.2

WORKDIR /app

COPY package.json .

RUN DENO_FUTURE=1 deno install

COPY . .

CMD [ "run", "dev", "--host"]

Similar to the server-side application, the Dockerfile uses the Alpine Linux Deno as the base image. The working directory is set to /app, and the package.json file is copied to the image. The dependencies are cached with the DENO_FUTURE=1 deno install command, and the rest of the files are copied to the image. Finally, the command to run the image is defined; the command translates to deno run dev --host.

The --host flag is used to expose the server to the network. This is necessary when running the server in a container, as the server is not accessible from the host machine without it.

Cleaning up

At this point, remove the node_modules folder from the client folder. This is important especially if you use an operating system that is not Linux, as the node_modules folder might contain files that are not compatible with the Linux-based Docker image.

Compose configuration

Next, we modify the compose.yaml file to add the client. Let’s call the service client. The service is built from the folder client of the project (i.e., the folder that has the Svelte application).

For development purposes, we bind the folder src in the folder client of our project to the src folder of the app folder of the container. This way, changes to the source code of the project are immediately reflected in the container. We also expose the port 5173 of the container to the port 5173 of the host machine, and finally define that the client depends on the service server.

This configuration looks as follows.

  client:
    build: client
    restart: unless-stopped
    volumes:
      - ./client:/app
    ports:
      - 5173:5173
    depends_on:
      - server

With the above, the compose.yaml is now as follows.

services:
  client:
    build: client
    restart: unless-stopped
    volumes:
      - ./client/src:/app/src
    ports:
      - 5173:5173
    depends_on:
      - server

  server:
    build: server
    restart: unless-stopped
    volumes:
      - ./server:/app
    ports:
      - 8000:8000

Running the project

Now, in the root folder of the project, we can run the project using the docker compose up --build command. This builds the images and starts the containers.

docker compose up --build
..

Now, the Deno backend is available at the address http://localhost:8000 and the Svelte frontend is available at the address http://localhost:5173.

To stop the project, press Ctrl + C in the terminal where the project is running.

Environment configuration

Next, create a file called .env.development to the root of the Svelte project (the folder client). Add the following line to the file.

PUBLIC_API_URL=http://localhost:8000

The file .env.development is used to define environment variables that are used in the development environment. The variable PUBLIC_API_URL is used to define the address of the API that the Svelte application uses. The prefix PUBLIC_ is used to indicate that the variable is public, meaning that it is available to the client-side code.

The public variables are imported from $env/static/public in the Svelte project.

Retrieving data from the server

To test the connection and to see that the Svelte application can fetch data from the backend, we can create a component that fetches data from the backend and displays it on the page. Create a folder called components to src/lib of the Svelte-project and add component called Message.svelte to the folder. Place the following code to the Message.svelte file.

<script>
  import { PUBLIC_API_URL } from "$env/static/public";
  let message = $state("");

  const fetchMessage = async () => {
    const response = await fetch(PUBLIC_API_URL);
    const data = await response.json();
    message = data.message;
  };
</script>

<button onclick={fetchMessage}>Fetch message</button>

<p>Message is: {message}</p>

Next, modify the +page.svelte in the src/routes to match the following.

<script>
  import Message from "$lib/components/Message.svelte";
</script>

<Message />

Now, with the project running (again, with docker compose up --build), open the address http://localhost:5173 in a browser. You should see a button that says “Fetch message”. Clicking the button should fetch the message “Hello world!” from the server and display it on the page.