PhotoGPT Developers

Generate a professional portrait, upscale it, create a website banner, and animate a subtle intro video.

Personal Website Hero Assets

Use this workflow for founder profiles, portfolio sites, speaker pages, or a polished about page. It turns a trained identity model into a portrait, a wider first-viewport banner, and a restrained intro video.

Before you start

Complete Setup and Training first. These snippets assume modelId or model_id, triggerImageGeneration, triggerImageUpscaling, triggerVideoGeneration, waitForJob, and firstImage are already available.

Workflow

  1. Generate a clean hero portrait with POST /images/generation.
  2. Upscale the selected portrait with POST /images/upscaling.
  3. Create a wide website banner with POST /images/generation.
  4. Animate the banner with POST /videos/generation.

Generate a clean hero portrait

The trained model gives you consistent identity across website images.

const heroImageJobId = await triggerImageGeneration({
  modelID: modelId,
  prompt:
    'confident personal website hero portrait, clean studio background, modern professional lighting',
  width: 1024,
  height: 1024,
  numImages: 2,
  enhanceFace: true,
})

const heroImage = firstImage(await waitForJob(heroImageJobId), 'Website hero portrait')
hero_image_job_id = trigger_image_generation(
    {
        "modelID": model_id,
        "prompt": "confident personal website hero portrait, clean studio background, modern professional lighting",
        "width": 1024,
        "height": 1024,
        "numImages": 2,
        "enhanceFace": True,
    }
)

hero_image = first_image(wait_for_job(hero_image_job_id), "Website hero portrait")

Upscale the hero portrait

Upscale the selected hero portrait so the website banner generation has a sharper reference.

const heroUpscaleJobId = await triggerImageUpscaling({
  imageID: heroImage.id,
})

const heroUpscaledImage = firstImage(await waitForJob(heroUpscaleJobId), 'Website hero upscale')
hero_upscale_job_id = trigger_image_upscaling(
    {
        "imageID": hero_image["id"],
    }
)

hero_upscaled_image = first_image(
    wait_for_job(hero_upscale_job_id),
    "Website hero upscale",
)

Create a wide website banner

Use the upscaled portrait as reference and generate a wider image that works in a first viewport or social preview.

const heroBannerJobId = await triggerImageGeneration({
  modelID: 'gpt-image-2',
  prompt:
    'editorial website hero image, confident founder portrait, laptop and notebook on desk, refined modern brand style',
  aspectRatio: '16:9',
  numImages: 1,
  referenceImageURLs: [heroUpscaledImage.url],
  options: {
    openai: {
      imageSize: '1K',
      outputFormat: 'jpeg',
      quality: 'high',
    },
  },
})

const heroBanner = firstImage(await waitForJob(heroBannerJobId), 'Website hero banner')
hero_banner_job_id = trigger_image_generation(
    {
        "modelID": "gpt-image-2",
        "prompt": "editorial website hero image, confident founder portrait, laptop and notebook on desk, refined modern brand style",
        "aspectRatio": "16:9",
        "numImages": 1,
        "referenceImageURLs": [hero_upscaled_image["url"]],
        "options": {
            "openai": {
                "imageSize": "1K",
                "outputFormat": "jpeg",
                "quality": "high",
            },
        },
    }
)

hero_banner = first_image(wait_for_job(hero_banner_job_id), "Website hero banner")

Generate a subtle intro video

Use the banner as the first frame and keep motion restrained for a professional website.

const heroVideoJobId = await triggerVideoGeneration({
  modelID: 'seedance-2.0',
  prompt:
    'personal website intro video, founder looks toward camera, slight push-in camera movement, professional and approachable',
  numVideos: 1,
  referenceImages: [
    {
      url: heroBanner.url,
      role: 'first_frame',
    },
  ],
  options: {
    seedance: {
      duration: 6,
      ratio: '16:9',
      resolution: '1080p',
      generateAudio: false,
    },
  },
})

const heroVideoJob = await waitForJob(heroVideoJobId, 8000)
const heroVideo = heroVideoJob.videos?.[0]
hero_video_job_id = trigger_video_generation(
    {
        "modelID": "seedance-2.0",
        "prompt": "personal website intro video, founder looks toward camera, slight push-in camera movement, professional and approachable",
        "numVideos": 1,
        "referenceImages": [
            {
                "url": hero_banner["url"],
                "role": "first_frame",
            },
        ],
        "options": {
            "seedance": {
                "duration": 6,
                "ratio": "16:9",
                "resolution": "1080p",
                "generateAudio": False,
            },
        },
    }
)

hero_video_job = wait_for_job(hero_video_job_id, interval_seconds=8)
hero_video = hero_video_job.get("videos", [])[0]

Production notes

  • Keep this workflow visually restrained: simple background, clean lighting, minimal motion.
  • Use 16:9 for first-viewport banners and social previews.
  • Use the final banner as the video first frame so the page and video share a consistent opening visual.

On this page