# Static Assets

Files in the app's `public/` directory are copied into `dist/` by the build and shipped inside `bundle.zip`, so they are served from the same base URL as `app.js` - the bundle root. The dev server serves them from the same paths, so assets behave identically in development and after publishing.

## Referencing assets at runtime

`getAssetUrl` resolves a root-relative path against the bundle's base URL, whatever the [bundle mode](/serverless-apps/development/dev-and-publish/) currently is:

```ts
import { getAssetUrl } from "@crowdin/serverless-apps-sdk";

const logo = getAssetUrl("/logo.svg");
```

Always build asset URLs this way - the app's page URL is `…/embed/<key>` while bundle assets live under the bundle root, a different path (and, in external and dev modes, a different origin), so document-relative paths like `<img src="logo.svg">` never hit the bundle. The leading slash is optional: `getAssetUrl("/logo.svg")` and `getAssetUrl("logo.svg")` resolve to the same file, matching the manifest's `logo` convention.

## Assets the manifest references

The `logo` fields in the [manifest](/serverless-apps/reference/manifest/) (top-level and per module) use the same space: `"/logo.svg"` means `public/logo.svg` served from the bundle root.

## What belongs in public/

Use `public/` for files that must keep their own URL: logos referenced by the manifest and files your app fetches at runtime. Assets imported from source code are handled by the build itself. Translation catalogs (`dist/locales/*.json`) also live in the bundle, but they are generated by the [i18n pipeline](/serverless-apps/building-app/i18n/), not by you.