Upstreet Docs
    SDK

    Web subclient deep dive—projects, assets, and content fetching. Create, manage, and serve AI-generated websites.

    Web Subclient

    The client.web subclient lets you manage web projects and assets—AI-generated websites with HTML, CSS, JavaScript, and images. Create projects, list and manage assets, and fetch raw content for serving or embedding.


    Projects API

    MethodSignatureDescription
    list() => Promise<WebProject[]>List all your web projects
    listPublic() => Promise<WebProject[]>List public web projects
    getById(id: string) => Promise<WebProject | null>Get project by ID
    getByName(name: string) => Promise<WebProject | null>Get project by name
    create(params) => Promise<WebProject>Create a new project
    update(params) => Promise<WebProject>Update project settings
    delete(params: { id }) => Promise<void>Delete a project

    Assets API

    MethodSignatureDescription
    list(projectId, opts?) => Promise<WebAsset[]>List assets in a project
    get(projectId, path) => Promise<WebAsset | null>Get asset by path (triggers generation if missing)
    delete(projectId, path) => Promise<void>Delete an asset at path

    Content Fetching

    MethodSignatureDescription
    getContent(projectId, path) => Promise<Response>Fetch raw content as a Response (HTML, CSS, etc.)

    WebAsset Fields

    FieldTypeDescription
    idstringAsset ID
    project_idstringProject ID
    pathstringFile path (e.g. /index.html)
    content_typestringMIME type (e.g. text/html)
    text_contentstring | nullText content when applicable
    statusstringpending, generating, completed, or failed
    urlstring | nullDirect URL when completed

    Quick Start

    1. Create a project

    const project = await client.web.projects.create({
      name: 'My Site',
      description: 'A minimal portfolio',
      visibility: 'public',
    });

    2. List or fetch assets

    const assets = await client.web.assets.list(project.id, { limit: 20, offset: 0 });
    const asset = await client.web.assets.get(project.id, '/index.html');

    3. Fetch raw content

    const res = await client.web.getContent(project.id, '/index.html');
    const html = await res.text();

    Projects Methods

    web.projects.list()

    web.projects.list(): Promise<WebProject[]>

    Returns all web projects for the authenticated user.

    const projects = await client.web.projects.list();

    web.projects.listPublic()

    web.projects.listPublic(): Promise<WebProject[]>

    Returns all public web projects (no auth required for read).

    const publicProjects = await client.web.projects.listPublic();

    web.projects.getById(id)

    web.projects.getById(id: string): Promise<WebProject | null>

    Fetches a project by ID. Returns null if not found.

    const project = await client.web.projects.getById('project-uuid');

    web.projects.getByName(name)

    web.projects.getByName(name: string): Promise<WebProject | null>

    Fetches a project by name. Returns null if not found.

    const project = await client.web.projects.getByName('My Site');

    web.projects.create(params)

    web.projects.create(params: {
      name: string;
      description?: string;
      visibility?: 'public' | 'private';
    }): Promise<WebProject>

    Creates a new web project.

    const project = await client.web.projects.create({
      name: 'Doc Site',
      description: 'API documentation',
      visibility: 'public',
    });

    web.projects.update(params)

    web.projects.update(params: UpdateWebProjectParams): Promise<WebProject>

    Updates project settings (prompt, models, visibility, etc.). Include id in params.

    await client.web.projects.update({
      id: project.id,
      project_prompt: 'Clean tech docs with code blocks',
    });

    web.projects.delete(params)

    web.projects.delete(params: { id: string }): Promise<void>

    Deletes a web project.

    await client.web.projects.delete({ id: project.id });

    Assets Methods

    web.assets.list(projectId, opts?)

    web.assets.list(
      projectId: string,
      opts?: { limit?: number; offset?: number }
    ): Promise<WebAsset[]>

    Lists assets in a project with optional pagination.

    const assets = await client.web.assets.list(project.id, { limit: 10, offset: 0 });

    web.assets.get(projectId, path)

    web.assets.get(projectId: string, path: string): Promise<WebAsset | null>

    Gets an asset by path. If the asset doesn't exist, requesting it may trigger AI generation.

    Requesting a non-existent path can trigger on-demand AI generation based on the project prompt. Poll get() until status is completed or failed.

    const asset = await client.web.assets.get(project.id, '/about.html');
    if (asset?.status === 'completed') {
      console.log(asset.url);
    }

    web.assets.delete(projectId, path)

    web.assets.delete(projectId: string, path: string): Promise<void>

    Deletes an asset at the given path.

    await client.web.assets.delete(project.id, '/old-page.html');

    getContent(projectId, path)

    web.getContent(projectId: string, path: string): Promise<Response>

    Fetches raw content for a path. Returns a standard Response (from fetch) so you can use .text(), .json(), .blob(), etc. Useful for iframes, SSR, or direct serving.

    const res = await client.web.getContent(project.id, '/index.html');
    const html = await res.text();
    // or
    const cssRes = await client.web.getContent(project.id, '/styles.css');
    const css = await cssRes.text();

    Code Examples

    import { PUClient } from 'pu-client';
    
    const client = new PUClient({ apiKey: process.env.PU_API_KEY! });
    
    const project = await client.web.projects.create({
      name: 'Landing Page',
      description: 'Product landing',
      visibility: 'public',
    });
    
    await client.web.projects.update({
      id: project.id,
      project_prompt: 'Modern SaaS landing with hero, features, CTA.',
    });
    
    const asset = await client.web.assets.get(project.id, '/index.html');
    if (asset?.status === 'completed') {
      const res = await client.web.getContent(project.id, '/index.html');
      const html = await res.text();
    }
    import { PUClient } from 'pu-client';
    
    const client = new PUClient({ apiKey: process.env.PU_API_KEY! });
    
    const projects = await client.web.projects.list();
    const project = projects[0];
    
    const assets = await client.web.assets.list(project.id, { limit: 50 });
    for (const a of assets) {
      if (a.status === 'completed') {
        const res = await client.web.getContent(project.id, a.path);
        console.log(`${a.path}: ${(await res.text()).slice(0, 100)}...`);
      }
    }

    Asset Status

    StatusDescription
    pendingRequested but not yet started
    generatingAI is producing the asset
    completedReady; url and content available
    failedGeneration failed

    Next Steps