Media and embeds

A compact reference for loading local and remote images, setting a favicon, making internal and external links, playing video, and embedding a PDF. Every remote URL was checked when the example was written; the app needs internet access to display those resources.

media/
├── app.py             # favicon + local static-files mount
├── settings.py        # the remote asset URLs in one place
├── static/
│   └── logo.svg       # a downloaded local asset
└── views/
    ├── styles/
    └── pages/media.py # images, links, video and document embeds

1. Favicon and local files

Set a favicon with a local or remote URL. Mount a local directory once, then address files under that URL prefix:

app.py
"""Media: images, favicons, links, embedded documents and videos.

Run:  python app.py --dev     # hot reload, readable errors
      python app.py --prod    # production server

Needs internet access: every asset below is loaded from a public URL, which is the point.
"""

from rational import App

from settings import FAVICON, STATIC_DIR
from views.pages import router

app = App(title="Media", description="Images, favicons, links, embeds.", favicon=FAVICON)
app.include(router)
app.static("/static", STATIC_DIR)

if __name__ == "__main__":
    app.run()

This example keeps three verified favicon choices in settings.py and displays all three on the page. An application still has one active favicon at a time; choose it by changing FAVICON.

2. Images

    def render(self):
        return Column(
            Heading("Media", level=1),
            Text("Images, favicons, links, embedded documents and videos. This page needs internet.", muted=True),
            Grid(
                # -- images ----------------------------------------------------------------------
                EmbedCard(
                    "A local image",
                    "Serve your own files with app.static('/static', 'static'); the URL stays stable.",
                    Image("/static/logo.svg", alt="The Rational Web example logo"),
                    Link("Source: static/logo.svg", href="/static/logo.svg", external=True, size="sm"),
                ),
                EmbedCard(
                    "A remote image",
                    "Any public URL works. alt is required for meaningful images; "
                    'use alt="" for decorative images. Lazy loading is on by default.',
                    Image(PHOTO_JPG, alt="A stock photo of a dog", width=600, height=400),
                    Link("Source: picsum.photos", href="https://picsum.photos", external=True, size="sm"),
                ),
                EmbedCard(
                    "An SVG, sized by style",
                    "SVGs scale: set a width in the style instead of attributes.",
                    Image(LOGO_SVG, alt="The Python logo", style=Style(width=220, height="auto")),
                ),
                EmbedCard(
                    "Favicon choices",
                    "Pass any local or remote image URL as App(favicon=...). This app uses the first one.",
                    Grid(
                        *[
                            Link(
                                Image(url, alt=f"{name} favicon", width=48, height=48),
                                name,
                                href=url,
                                external=True,
                                key=name,
                            )
                            for name, url in FAVICON_CHOICES
                        ],
                        min_column_width=100,
                        gap="sm",
                    ),
                ),
                # -- links -----------------------------------------------------------------------
                EmbedCard(
                    "Links",
                    "external=True adds target=_blank and rel=noopener noreferrer. ButtonLink looks like a button.",
                    Link("python.org", href="https://www.python.org", external=True),
                    Link("A link inside the app", href="/about"),
                    Link("Mail and phone are just URLs", href="mailto:hi@example.org"),
                ),
                # -- video -------------------------------------------------------------------------
                EmbedCard(
                    "A video, with controls",
                    "h() builds any HTML element: sources, tracks, fallbacks. Multiple formats let the browser choose.",
                    h(
                        "video",
                        h("source", src=VIDEO_MP4, type="video/mp4"),
                        h("source", src=VIDEO_WEBM, type="video/webm"),
                        "Your browser cannot play this video.",
                        controls=True,
                        style=Style(width="100%", border_radius="md"),
                    ),
                ),
                # -- documents ----------------------------------------------------------------------
                EmbedCard(
                    "A PDF, inline",
                    "An iframe shows documents in the page. The same element embeds maps and other pages.",
                    h(
                        "iframe",
                        src=PDF_DOC + "#view=FitH",
                        title="An example PDF document",
                        style=Style(
                            width="100%", height=340, border_style="solid", border_width=1, border_color="border"
                        ),
                    ),
                    Link("Or link to it directly", href=PDF_DOC, external=True),
                ),
                key="cards",
                min_column_width=320,
                gap="md",
                style=GRID,
            ),
            tag="main",
            max_width=1100,
            style=PAGE,
        )

Image accepts local paths and complete remote URLs. alt is required: describe meaningful images; use alt="" only for decoration. It adds lazy loading and asynchronous decoding by default. Width and height attributes prevent layout shifts; Style can size scalable SVGs.

4. Videos and documents

Rational’s named primitives cover common accessible elements. The h() escape hatch builds anything else:

h(
    "video",
    h("source", src=VIDEO_MP4, type="video/mp4"),
    h("source", src=VIDEO_WEBM, type="video/webm"),
    "Your browser cannot play this video.",
    controls=True,
    style=Style(width="100%"),
)

h(
    "iframe",
    src=PDF_DOC,
    title="An example PDF document",
    style=Style(width="100%", height=340),
)

Multiple video sources let the browser choose a supported format. An iframe needs a useful title for accessibility. Third-party sites may forbid iframe embedding with their security headers; in that case, provide an external Link instead.

Run it

$ cd examples/media
$ python app.py --dev