Skip to content

PyWeb 0.4.0

Choose a tag to compare

@MaanavKrishna MaanavKrishna released this 03 Oct 14:20
· 6 commits to main since this release

Apps that are bigger, livelier and smarter: npm packages without
Node.js, multi-page apps with layouts and client-side navigation,
streaming for AI features, and page data that follows the database.

Added

  • npm packages without Node.js. pyweb add chart.js/auto downloads a
    package from the npm registry, checks its sha512 checksum, follows its
    imports from the browser entry point and copies only the files it
    needs (and its dependencies) into static/vendor/, pinning versions in
    pyweb.lock. pyweb add with no arguments reinstalls from the lock;
    pyweb remove takes a package out. Browser code binds exports with
    Chart = npm("chart.js/auto") or npm("pkg", "Export"). Calling a
    class constructs it and keyword arguments become an options object.
    Each page imports only the packages it uses, through an import map
    that the Content Security Policy allows by hash. CommonJS-only and
    Node.js-only packages are refused with an explanation, and an
    uninstalled package is a compile error that names the command to run.
  • ref={el} sets a page variable to an element, in time for
    on_mount, for libraries that draw into the page.
  • Changing an attribute of a package's object (chart.value = 5)
    re-renders whatever shows it.
  • Web components (custom elements from npm) work in markup.
  • pyweb lsp: hover shows an npm binding's installed version and
    TypeScript signature; completion offers installed packages in
    npm(" and a module's exports after name..
  • New docs page: npm packages.
  • Layouts. @app.layout wraps every page (or, with
    @app.layout("/admin"), pages under a prefix) in shared markup;
    {children} marks where the page goes. Layouts nest, have their own
    server code, state and handlers, and pages can opt out with
    layout=None or pick one with layout="Name".
  • Client-side navigation. Links between pages fetch the next page's
    HTML and swap it in below the layouts both pages share, so layout
    state (an open menu, a player) survives. Links are prefetched on
    hover or focus, back/forward restore the scroll position, and anything
    unusual falls back to a full page load. navigate("/path") from
    pyweb.browser does the same from browser code; on_unmount runs
    when a page is left; App(client_nav=False) turns it off.
  • Current links. Links to the current page get
    aria-current="page" and links to its parent sections
    aria-current="true", on the server and after each navigation.
  • Head tags. @app.page(description=..., image=..., noindex=...) and
    head(title=..., description=...) in page code add description, Open
    Graph and Twitter tags; App(base_url=...) adds canonical URLs and
    absolute image links.
  • Error pages in .pyweb. @app.error(404) / @app.error(500) pages
    take path, status, message or request_id and use root layouts.
  • Typed query parameters. Page parameters that aren't in the route
    are read from the query string and converted by annotation (int,
    float, bool, list[...]); bad or missing values answer 400.
  • New docs page: Layouts & navigation.
  • Streaming server functions. A @server function that yields
    sends each value as it's produced (NDJSON over the same RPC endpoint);
    browser code reads it with async for. stream.cancel() or leaving the
    loop aborts the request and closes the generator on the server, so an
    upstream AI call stops too. Errors raised part-way arrive as
    RPCError. Works with async def generators, under pyweb serve,
    pyweb dev and ASGI, and TestClient.rpc returns the streamed values.
  • <Markdown text={...} /> (from pyweb) renders Markdown to safe
    HTML on the server and updates it in the browser as the text changes,
    with the same rules in both places. Raw HTML is shown as text and
    links only accept http(s), mailto and relative URLs.
  • ai-chat template and example: a streaming chat with Stop and
    Markdown replies that talks to Anthropic, any OpenAI-compatible server
    (OpenAI, Ollama, vLLM, ...) or a built-in demo model, chosen by
    environment variables. pyweb new NAME --template ai-chat.
  • New docs page: Building AI apps.
  • Live data. rows = live(db, "select ...", params) in a page or
    layout renders the rows and keeps them current: writes through
    pyweb.db (and pyweb.models) announce their table after commit, each
    distinct query re-runs once per change (bursts coalesced) and sends
    rows to every page showing it only when they changed. Pages follow a
    signed feed; db.notify("table") covers writes made elsewhere. With
    RedisBus it works across processes, and any process can take over a
    query from the page's signed description.
  • New docs page: Live data.
  • watch(lambda: value, handler) (from pyweb.browser) runs a
    handler whenever a value changes, for work outside markup such as
    redrawing a chart or saving a draft.
  • pyweb add applies packages' browser field (browser versions of
    files, modules turned off), so packages such as ethers install.
  • New examples: dashboard (live queries and a Chart.js chart from
    npm), site (layouts, navigation, query parameters, a 404 page) and
    ai-chat. The playground has the site and AI chat examples.
  • New docs page: Recipe: wallets & web3 (wallet sign-in with ethers and
    eth-account).
  • A layout's {children} can sit on a line of its own.

Fixed

  • Subscriptions and cleanups set up in on_mount now end when the page
    is left (they were never stopped).

Changed

  • The experimental pyweb.live module (in-memory live tables) is now
    pyweb.livetable; pyweb.live is the new live-query function.
  • pyweb.npm (TypeScript declarations to dataclasses) is now
    pyweb.dts, and its command is pyweb dts. pyweb build no longer
    writes an esm.sh import map; packages come from pyweb.lock.
  • The default Content Security Policy adds worker-src 'self' blob: so
    packages can start Web Workers.
  • The starter stylesheet styles Markdown and chat bubbles.
  • The browser runtime is about 14 KB gzipped (was about 11 KB), for
    client-side navigation and npm support.
  • New website design: a colour system where blue means the browser and
    amber the server, self-hosted Inter / Bricolage Grotesque / JetBrains
    Mono, dark code windows, and a landing page that shows each line of an
    app with where it runs (worked out by the compiler) next to the real
    compiled output.
  • The example apps and the pyweb new stylesheet use the new palette.