Glance widget to display the latest Nebula videos from selected creators/channels.
- type: custom-api
title: Nebula
title-url: https://nebula.tv/
cache: 1h
frameless: true
url: https://content.api.nebula.app/video_episodes/
parameters:
ordering: -published_at
page_size: "100"
options:
max_items: 12
channel-ids:
- video_channel:9cea6296-223e-4c7e-a245-d96db75de32f # Jet Lag: The Game
- video_channel:8f3a2a56-3f9f-4ce0-b105-ede41688d84b # Half as Interesting
- video_channel:fe4d9c1c-017b-494c-9afc-e79e6859b211 # Wendover Productions
template: |
{{ if ne .Response.StatusCode 200 }}
<div class="widget-content-frame padding-widget color-negative">Failed to fetch Nebula videos.</div>
{{ else }}
{{ $channels := .Options.JSON "channel-ids" }}
{{ $maxItems := (index .Options "max_items") }}
{{ if not $maxItems }}{{ $maxItems = 12 }}{{ end }}
{{ $shown := 0 }}
<div class="carousel-container">
<div class="cards-horizontal carousel-items-container">
{{ range $video := .JSON.Array "results" }}
{{ if and (lt $shown $maxItems) (ne "" (findMatch (concat "(^|[^A-Za-z0-9:_-])" ($video.String "channel_id") "([^A-Za-z0-9:_-]|$)") $channels)) }}
<div class="card widget-content-frame thumbnail-parent">
{{ if $video.Exists "images.thumbnail.src" }}
<img class="video-thumbnail thumbnail" loading="lazy" src="{{ $video.String "images.thumbnail.src" }}" alt="">
{{ else }}
<svg class="video-thumbnail" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="120" height="120" fill="#EFF1F3"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M33.2503 38.4816C33.2603 37.0472 34.4199 35.8864 35.8543 35.875H83.1463C84.5848 35.875 85.7503 37.0431 85.7503 38.4816V80.5184C85.7403 81.9528 84.5807 83.1136 83.1463 83.125H35.8543C34.4158 83.1236 33.2503 81.957 33.2503 80.5184V38.4816ZM80.5006 41.1251H38.5006V77.8751L62.8921 53.4783C63.9172 52.4536 65.5788 52.4536 66.6039 53.4783L80.5006 67.4013V41.1251ZM43.75 51.6249C43.75 54.5244 46.1005 56.8749 49 56.8749C51.8995 56.8749 54.25 54.5244 54.25 51.6249C54.25 48.7254 51.8995 46.3749 49 46.3749C46.1005 46.3749 43.75 48.7254 43.75 51.6249Z" fill="#687787"/>
</svg>
{{ end }}
<div class="margin-top-10 margin-bottom-widget flex flex-column grow padding-inline-widget">
<a class="text-truncate-2-lines margin-bottom-auto color-primary-if-not-visited" href="{{ $video.String "share_url" }}" target="_blank" rel="noreferrer">{{ $video.String "title" }}</a>
<ul class="list-horizontal-text flex-nowrap margin-top-7">
<li class="shrink-0" {{ $video.String "published_at" | parseTime "rfc3339" | toRelativeTime }}></li>
<li class="min-width-0">
<a class="block text-truncate" href="{{ concat "https://nebula.tv/" ($video.String "channel_slug") }}" target="_blank" rel="noreferrer">{{ $video.String "channel_title" }}</a>
</li>
</ul>
</div>
</div>
{{ $shown = add $shown 1 }}
{{ end }}
{{ end }}
</div>
</div>
{{ end }}Full file: nebula-widget-carousel.yml
- type: custom-api
title: Nebula
title-url: https://nebula.tv/
cache: 1h
frameless: true
url: https://content.api.nebula.app/video_episodes/
parameters:
ordering: -published_at
page_size: "100"
options:
max_items: 12
collapse_after: 5
channel-ids:
- video_channel:9cea6296-223e-4c7e-a245-d96db75de32f # Jet Lag: The Game
- video_channel:8f3a2a56-3f9f-4ce0-b105-ede41688d84b # Half as Interesting
- video_channel:fe4d9c1c-017b-494c-9afc-e79e6859b211 # Wendover Productions
template: |
{{ if ne .Response.StatusCode 200 }}
<div class="widget-content-frame padding-widget color-negative">Failed to fetch Nebula videos.</div>
{{ else }}
{{ $channels := .Options.JSON "channel-ids" }}
{{ $maxItems := (index .Options "max_items") }}
{{ $collapseAfter := (index .Options "collapse_after") }}
{{ if not $maxItems }}{{ $maxItems = 12 }}{{ end }}
{{ if not $collapseAfter }}{{ $collapseAfter = 5 }}{{ end }}
{{ $shown := 0 }}
<ul class="list list-gap-10 collapsible-container" data-collapse-after="{{ $collapseAfter }}" style="list-style: none; padding: 0; margin: 0;">
{{ range $video := .JSON.Array "results" }}
{{ if and (lt $shown $maxItems) (ne "" (findMatch (concat "(^|[^A-Za-z0-9:_-])" ($video.String "channel_id") "([^A-Za-z0-9:_-]|$)") $channels)) }}
<a href="{{ $video.String "share_url" }}" target="_blank" rel="noreferrer" style="text-decoration: none;">
<li style="padding: 10px 0; border-bottom: 1px solid var(--border-color);">
<div style="display: flex; gap: 12px; align-items: flex-start;">
<div style="flex-shrink: 0; width: 120px; height: 68px; border-radius: 6px; overflow: hidden;">
{{ if $video.Exists "images.thumbnail.src" }}
<img src="{{ $video.String "images.thumbnail.src" }}" alt="" style="width: 100%; height: 100%; object-fit: cover;">
{{ else }}
<svg viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg" style="width: 100%; height: 100%;">
<rect width="120" height="120" fill="#EFF1F3"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M33.2503 38.4816C33.2603 37.0472 34.4199 35.8864 35.8543 35.875H83.1463C84.5848 35.875 85.7503 37.0431 85.7503 38.4816V80.5184C85.7403 81.9528 84.5807 83.1136 83.1463 83.125H35.8543C34.4158 83.1236 33.2503 81.957 33.2503 80.5184V38.4816ZM80.5006 41.1251H38.5006V77.8751L62.8921 53.4783C63.9172 52.4536 65.5788 52.4536 66.6039 53.4783L80.5006 67.4013V41.1251ZM43.75 51.6249C43.75 54.5244 46.1005 56.8749 49 56.8749C51.8995 56.8749 54.25 54.5244 54.25 51.6249C54.25 48.7254 51.8995 46.3749 49 46.3749C46.1005 46.3749 43.75 48.7254 43.75 51.6249Z" fill="#687787"/>
</svg>
{{ end }}
</div>
<div style="flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px;">
<div class="text-truncate-2-lines color-primary">{{ $video.String "title" }}</div>
<div class="size-h6 color-subdue" style="display: flex; gap: 6px; align-items: center;">
<span>{{ $video.String "published_at" | parseTime "rfc3339" | toRelativeTime }}</span>
<span>•</span>
<span class="text-truncate">{{ $video.String "channel_title" }}</span>
</div>
</div>
</div>
</li>
</a>
{{ $shown = add $shown 1 }}
{{ end }}
{{ end }}
</ul>
{{ end }}Full file: nebula-widget-list.yml
max_items: maximum number of videos to render (default:12)collapse_after: list-only collapse threshold (default:5)channel-ids: only include videos from these channel IDs
- Go to the channel's page on Nebula (e.g. https://nebula.tv/channel/half-as-interesting)
- Open dev tools and go to the Network tab
- Refresh the page and look for a request to
https://content.api.nebula.app/video_channels/(you can filter by "video_channels" in the Network tab) - Click on that request and look at the "Response" tab, where you'll see a request which includes the channel ID (e.g.
video_channel:8f3a2a56-3f9f-4ce0-b105-ede41688d84bfor Half as Interesting). It can look something like this:
- The Nebula endpoint for the latest videos only fetches 100 at most, meaning that sometimes you won't hit the maximum item count (depending on how many channel ids you have and frequency of video releases)
- This endpoint is unofficial and there is no official public Nebula API, so it may break at any time if they change their internal APIs. Please use this API carefully and do not make excessive requests to it.

