2nd chunk of `content/manuals/extensions/extensions-sdk/build/frontend-extension-tutorial.md`
b30c60c115c99f5fb87d8c703aa1ee428223dee8eaac21500000000100000fc6
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM node:18.9-alpine3.15 AS client-builder
WORKDIR /ui
# cache packages in layer
COPY ui/package.json /ui/package.json
COPY ui/package-lock.json /ui/package-lock.json
RUN --mount=type=cache,target=/usr/src/app/.npm \
npm set cache /usr/src/app/.npm && \
npm ci
# install
COPY ui /ui
RUN npm run build
FROM alpine
LABEL org.opencontainers.image.title="My extension" \
org.opencontainers.image.description="Your Desktop Extension Description" \
org.opencontainers.image.vendor="Awesome Inc." \
com.docker.desktop.extension.api.version="0.3.3" \
com.docker.desktop.extension.icon="https://www.docker.com/wp-content/uploads/2022/03/Moby-logo.png" \
com.docker.extension.screenshots="" \
com.docker.extension.detailed-description="" \
com.docker.extension.publisher-url="" \
com.docker.extension.additional-urls="" \
com.docker.extension.changelog=""
COPY metadata.json .
COPY docker.svg .
COPY --from=client-builder /ui/build ui
```
> Note
>
> In the example Dockerfile, you can see that the image label `com.docker.desktop.extension.icon` is set to an icon URL. The Extensions Marketplace displays this icon without installing the extension. The Dockerfile also includes `COPY docker.svg .` to copy an icon file inside the image. This second icon file is used to display the extension UI in the Dashboard, once the extension is installed.
{{< /tab >}}
{{< tab name="Vue" >}}
> [!IMPORTANT]
>
> We don't have a working Dockerfile for Vue yet. [Fill out the form](https://docs.google.com/forms/d/e/1FAIpQLSdxJDGFJl5oJ06rG7uqtw1rsSBZpUhv_s9HHtw80cytkh2X-Q/viewform?usp=pp_url&entry.1333218187=Vue)
> and let us know if you'd like a Dockerfile for Vue.
{{< /tab >}}
{{< tab name="Angular" >}}
> [!IMPORTANT]
>
> We don't have a working Dockerfile for Angular yet. [Fill out the form](https://docs.google.com/forms/d/e/1FAIpQLSdxJDGFJl5oJ06rG7uqtw1rsSBZpUhv_s9HHtw80cytkh2X-Q/viewform?usp=pp_url&entry.1333218187=Angular)
> and let us know if you'd like a Dockerfile for Angular.
{{< /tab >}}
{{< tab name="Svelte" >}}
> [!IMPORTANT]
>
> We don't have a working Dockerfile for Svelte yet. [Fill out the form](https://docs.google.com/forms/d/e/1FAIpQLSdxJDGFJl5oJ06rG7uqtw1rsSBZpUhv_s9HHtw80cytkh2X-Q/viewform?usp=pp_url&entry.1333218187=Svelte)
> and let us know if you'd like a Dockerfile for Svelte.
{{< /tab >}}
{{< /tabs >}}
## Configure the metadata file
In order to add a tab in Docker Desktop for your extension, you have to configure it in the `metadata.json`
file the root of your extension directory.
```json
{
"icon": "docker.svg",
"ui": {
"dashboard-tab": {
"title": "UI Extension",
"root": "/ui",
"src": "index.html"
}
}
}
```
The `title` property is the name of the extension that is displayed in the left-menu of the Docker Desktop Dashboard.
The `root` property is the path to the frontend application in the extension's container filesystem used by the
system to deploy it on the host.
The `src` property is the path to the HTML entry point of the frontend application within the `root` folder.
For more information on the `ui` section of the `metadata.json`, see [Metadata](../architecture/metadata.md#ui-section).
## Build the extension and install it
Now that you have configured the extension, you need to build the extension image that Docker Desktop will use to
install it.
```bash
docker build --tag=awesome-inc/my-extension:latest .
```
This built an image tagged `awesome-inc/my-extension:latest`, you can run `docker inspect
awesome-inc/my-extension:latest` to see more details about it.
Finally, you can install the extension and see it appearing in the Docker Desktop Dashboard.
```bash
docker extension install awesome-inc/my-extension:latest
```
## Use the Extension APIs client
To use the Extension APIs and perform actions with Docker Desktop, the extension must first import the
`@docker/extension-api-client` library. To install it, run the command below: