Assets and Fonts

Images, fonts and data files live in an assets/ directory and are referenced by relative path. The same code works under nib run and inside a built .app.

Where assets are found

Nib looks for the directory in this order, relative to the entry script:

  1. assets/ next to the script
  2. ../assets/ (a script in src/ finds assets/ at the project root)
  3. src/assets/ from the working directory

nib create puts it at src/assets/. To use another location:

nib.run(main, assets_dir="my_assets")          # relative to the script, or absolute
nib.App.set_assets_dir("/absolute/path")       # before nib.run()

Images

nib.Image(src="logo.png", width=64, height=64)              # assets/logo.png
nib.Image(src="photos/banner.jpg", aspect_ratio=nib.ContentMode.FIT)
nib.Image(src="/Users/me/Desktop/photo.jpg")                # absolute paths pass through
nib.Image(src="https://example.com/image.png")              # URLs are fetched by the runtime

src/assets/icon.png becomes the app icon when you run nib build.

Fonts

Every .ttf, .otf, .ttc, .woff and .woff2 file anywhere under assets/ is registered before the first render. The font name is the file name without its extension:

src/assets/fonts/
├── Inter-Regular.ttf
└── Inter-Bold.ttf
nib.Text("Hello", font=nib.Font.custom("Inter-Regular", size=16))
canvas.draw([nib.draw.Text("Canvas", x=10, y=40, font=nib.Font.custom("Inter-Bold", size=20))])

Fonts outside the project, or served from a URL, are registered through app.fonts. Entries override an auto-detected font with the same name:

app.fonts = {
    "MyFont": "/Users/me/Library/Fonts/MyFont.ttf",
    "WebFont": "https://example.com/fonts/WebFont.otf",
}

The runtime downloads URL fonts in the background and uses them once they arrive; a font that fails to load is logged and skipped.

Other files

For anything Python reads itself, resolve the path first:

import json

path = nib.App.resolve_asset("data/defaults.json")   # "" with a warning when missing
if path:
    with open(path) as f:
        defaults = json.load(f)

Absolute paths and URLs are returned unchanged.

Inside a built app

nib build copies the directory to Contents/Resources/assets/ and the SDK resolves paths from there. Paths that only work in development (../../data/file.txt) do not; keep static files under assets/.