Skip to content

Commit 36c2aed

Browse files
authored
Docs: replace whatsnew and roadmap with guide section (#982)
* Docs: update .gitignore to include landing build artifacts * Docs: add GuideSection, remove WhatsNew and Roadmap sections (WIP) * Docs: prevent user selection on images * Docs: update font configuration in astro config * Docs: add guide video to GuideSection * Docs: add yt api to envs * Docs: add padding to video container in GuideSection * Docs: update video scrolling layout * Docs: revert font provider configuration in astro.config.mjs
1 parent 4fee26b commit 36c2aed

9 files changed

Lines changed: 269 additions & 50 deletions

File tree

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,40 @@
11
name: Live-debugger landing page publish
22
on:
3-
push:
4-
paths:
5-
- ".github/workflows/landing-publish.yml"
6-
- landing/**
7-
branches:
8-
- main
9-
workflow_dispatch:
3+
push:
4+
paths:
5+
- ".github/workflows/landing-publish.yml"
6+
- landing/**
7+
branches:
8+
- main
9+
workflow_dispatch:
1010

1111
jobs:
12-
live-debugger-landing-publish:
13-
if: github.repository == 'software-mansion/live-debugger'
14-
runs-on: ubuntu-latest
15-
steps:
16-
- name: Check out
17-
uses: actions/checkout@v4
18-
with:
19-
submodules: "true"
20-
- name: Use Node.js
21-
uses: actions/setup-node@v4
22-
with:
23-
cache: "npm"
24-
cache-dependency-path: landing/package-lock.json
25-
- name: Install node dependencies
26-
working-directory: landing
27-
run: npm install
28-
- name: Build landing page
29-
working-directory: landing
30-
env:
31-
ENABLE_ANALYTICS: ${{ vars.ENABLE_ANALYTICS || 'false' }}
32-
run: npm run build
12+
live-debugger-landing-publish:
13+
if: github.repository == 'software-mansion/live-debugger'
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Check out
17+
uses: actions/checkout@v4
18+
with:
19+
submodules: "true"
20+
- name: Use Node.js
21+
uses: actions/setup-node@v4
22+
with:
23+
cache: "npm"
24+
cache-dependency-path: landing/package-lock.json
25+
- name: Install node dependencies
26+
working-directory: landing
27+
run: npm install
28+
- name: Build landing page
29+
working-directory: landing
30+
env:
31+
ENABLE_ANALYTICS: ${{ vars.ENABLE_ANALYTICS || 'false' }}
32+
YOUTUBE_API_KEY: ${{ secrets.YOUTUBE_API_KEY || '' }}
33+
run: npm run build
3334

34-
- name: Publish generated content to GitHub Pages
35-
uses: JamesIves/github-pages-deploy-action@releases/v3
36-
with:
37-
FOLDER: landing/dist
38-
BRANCH: gh-pages
39-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35+
- name: Publish generated content to GitHub Pages
36+
uses: JamesIves/github-pages-deploy-action@releases/v3
37+
with:
38+
FOLDER: landing/dist
39+
BRANCH: gh-pages
40+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,8 @@ devtools_*
3838
screenshots/
3939

4040
shell.nix
41+
42+
# landing build artifacts
43+
landing/.astro/
44+
landing/dist/
45+
landing/.env.local

landing/astro.config.mjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ export default defineConfig({
1414
default: "false",
1515
optional: true,
1616
}),
17+
YOUTUBE_API_KEY: envField.string({
18+
access: "public",
19+
context: "server",
20+
default: "",
21+
optional: true,
22+
}),
1723
},
1824
},
1925
vite: {
5.36 MB
Binary file not shown.
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
---
2+
import ContentWrapper from "../components/ContentWrapper.tsx";
3+
import CTA from "@/components/CTA.astro";
4+
import { Book, ChevronLeft, ChevronRight, Play } from "lucide-react";
5+
6+
const API_KEY = import.meta.env.YOUTUBE_API_KEY;
7+
const playlistId = "PLSk21zn8fFZBOOhmNtBaHhk6N2SJ5_ve4";
8+
9+
type PlaylistVideo = {
10+
id: string;
11+
title: string;
12+
thumbnail: string;
13+
};
14+
15+
type YouTubePlaylistItem = {
16+
snippet?: {
17+
title?: string;
18+
resourceId?: {
19+
videoId?: string;
20+
};
21+
thumbnails?: {
22+
medium?: { url?: string };
23+
default?: { url?: string };
24+
};
25+
};
26+
};
27+
28+
async function getPlaylistVideos(): Promise<PlaylistVideo[]> {
29+
if (!API_KEY) return [];
30+
31+
const videos: PlaylistVideo[] = [];
32+
let nextPageToken: string | undefined;
33+
34+
do {
35+
const params = new URLSearchParams({
36+
part: "snippet",
37+
maxResults: "50",
38+
playlistId,
39+
key: API_KEY,
40+
});
41+
42+
if (nextPageToken) {
43+
params.set("pageToken", nextPageToken);
44+
}
45+
46+
const res = await fetch(
47+
`https://www.googleapis.com/youtube/v3/playlistItems?${params.toString()}`
48+
);
49+
50+
if (!res.ok) {
51+
break;
52+
}
53+
54+
const data: { items?: YouTubePlaylistItem[]; nextPageToken?: string } =
55+
await res.json();
56+
57+
const pageVideos = (data.items ?? [])
58+
.map((item) => {
59+
const id = item.snippet?.resourceId?.videoId;
60+
const title = item.snippet?.title;
61+
const thumbnail =
62+
item.snippet?.thumbnails?.medium?.url ||
63+
item.snippet?.thumbnails?.default?.url;
64+
65+
if (!id || !title || !thumbnail) return null;
66+
67+
return { id, title, thumbnail };
68+
})
69+
.filter((video): video is PlaylistVideo => video !== null);
70+
71+
videos.push(...pageVideos);
72+
nextPageToken = data.nextPageToken;
73+
} while (nextPageToken);
74+
75+
return videos;
76+
}
77+
78+
const videos = await getPlaylistVideos();
79+
---
80+
81+
<section
82+
id="guide"
83+
class="bg-bg-additional flex w-full items-center justify-center py-15 sm:py-20 md:py-28 lg:py-32"
84+
>
85+
<ContentWrapper
86+
className="font-aeonik text-primary flex w-full flex-col items-center justify-center gap-12 sm:gap-14 md:gap-16 lg:gap-18"
87+
>
88+
<div class="flex flex-col items-center justify-center gap-4">
89+
<h2 class="text-primary text-center text-2xl font-bold">
90+
See all LiveDebugger features
91+
</h2>
92+
</div>
93+
94+
<div class="w-full overflow-hidden">
95+
<video
96+
class="aspect-video w-full"
97+
autoplay
98+
muted
99+
loop
100+
playsinline
101+
preload="none"
102+
>
103+
<source
104+
src="/live-debugger/assets/guide-video.webm"
105+
type="video/webm"
106+
/>
107+
</video>
108+
</div>
109+
110+
<div class="pb-6">
111+
<CTA
112+
title="Visit the LiveDebugger Tour"
113+
buttonText="View on GitHub"
114+
url="https://github.com/software-mansion-labs/live-debugger-tour"
115+
>
116+
<Book
117+
className="h-7 w-7 sm:h-8 sm:w-8 md:h-10 md:w-10"
118+
strokeWidth={1}
119+
/>
120+
</CTA>
121+
</div>
122+
123+
<div class="relative w-full">
124+
<button
125+
type="button"
126+
class="bg-bg-primary text-white border-white/10 hover:bg-bg-primary/80 absolute top-1/2 left-0 z-10 inline-flex h-10 w-10 -translate-y-1/2 items-center justify-center border transition"
127+
aria-label="Scroll videos left"
128+
data-guide-scroll-left
129+
>
130+
<ChevronLeft className="h-5 w-5" />
131+
</button>
132+
<button
133+
type="button"
134+
class="bg-bg-primary text-white border-white/10 hover:bg-bg-primary/80 absolute top-1/2 right-0 z-10 inline-flex h-10 w-10 -translate-y-1/2 items-center justify-center border transition"
135+
aria-label="Scroll videos right"
136+
data-guide-scroll-right
137+
>
138+
<ChevronRight className="h-5 w-5" />
139+
</button>
140+
<div
141+
class="guide-scrollbar-hidden mx-auto w-[calc(100%-104px)] overflow-x-auto"
142+
data-guide-scroll
143+
>
144+
<div class="flex min-w-max gap-4">
145+
{
146+
videos.map((video) => (
147+
<div class="bg-bg-primary w-[220px] shrink-0 overflow-hidden sm:w-[250px] md:w-[280px]">
148+
<a
149+
href={`https://www.youtube.com/watch?v=${video.id}`}
150+
target="_blank"
151+
rel="noreferrer"
152+
class="group relative block aspect-video w-full overflow-hidden"
153+
aria-label={video.title}
154+
>
155+
<img
156+
src={video.thumbnail}
157+
alt={video.title}
158+
class="h-full w-full object-cover transition group-hover:scale-105"
159+
loading="lazy"
160+
/>
161+
<div class="absolute inset-0 flex items-center justify-center bg-black/30 opacity-0 transition group-hover:opacity-100">
162+
<Play className="h-8 w-8 text-white" strokeWidth={1.5} />
163+
</div>
164+
</a>
165+
</div>
166+
))
167+
}
168+
</div>
169+
</div>
170+
</div>
171+
</ContentWrapper>
172+
</section>
173+
174+
<style>
175+
.guide-scrollbar-hidden {
176+
scrollbar-width: none;
177+
-ms-overflow-style: none;
178+
}
179+
180+
.guide-scrollbar-hidden::-webkit-scrollbar {
181+
display: none;
182+
}
183+
</style>
184+
185+
<script is:inline>
186+
const scrollContainer = document.querySelector("[data-guide-scroll]");
187+
const leftButton = document.querySelector("[data-guide-scroll-left]");
188+
const rightButton = document.querySelector("[data-guide-scroll-right]");
189+
190+
const scrollByAmount = () => {
191+
if (!scrollContainer) return 280;
192+
return Math.max(220, Math.floor(scrollContainer.clientWidth * 0.7));
193+
};
194+
195+
leftButton?.addEventListener("click", () => {
196+
scrollContainer?.scrollBy({ left: -scrollByAmount(), behavior: "smooth" });
197+
});
198+
199+
rightButton?.addEventListener("click", () => {
200+
scrollContainer?.scrollBy({ left: scrollByAmount(), behavior: "smooth" });
201+
});
202+
</script>

landing/src/components/ui/Header.tsx

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,14 @@ import { getStorageValue } from "@/lib/utils";
77

88
export interface HeaderProps extends React.HTMLAttributes<HTMLElement> {}
99

10-
const DEFAULT_LATEST_NEWS_ID = "v0.5.0";
10+
const DEFAULT_LATEST_NEWS_ID = "v1.0.0";
1111
const GITHUB_API_URL =
1212
"https://api.github.com/repos/software-mansion/live-debugger/releases/latest";
1313

1414
const navItems = [
1515
{ name: "Features", href: "#features" },
1616
{ name: "Getting started", href: "#gettingstarted" },
17-
{ name: "What's new", href: "#whatsnew" },
18-
{ name: "Roadmap", href: "#roadmap" },
17+
{ name: "Guide", href: "#guide" },
1918
];
2019

2120
const sectionThemes = [
@@ -24,8 +23,7 @@ const sectionThemes = [
2423
{ id: "videosection", theme: "dark" },
2524
{ id: "debugcases", theme: "light" },
2625
{ id: "gettingstarted", theme: "light" },
27-
{ id: "whatsnew", theme: "light" },
28-
{ id: "roadmap", theme: "light" },
26+
{ id: "guide", theme: "light" },
2927
{ id: "footer", theme: "dark" },
3028
];
3129

@@ -119,7 +117,7 @@ const Header = React.forwardRef<HTMLElement, HeaderProps>(
119117
? "border-b border-white/40"
120118
: "border-b border-black/10"
121119
: "border-b border-transparent",
122-
className,
120+
className
123121
)}
124122
{...props}
125123
>
@@ -139,9 +137,7 @@ const Header = React.forwardRef<HTMLElement, HeaderProps>(
139137
"transition-all hover:scale-105",
140138
activeTheme === "dark"
141139
? "hover:text-slate-300"
142-
: "hover:text-primary/70",
143-
"last:hidden",
144-
"lg:last:block",
140+
: "hover:text-primary/70"
145141
)}
146142
onClick={() => {
147143
if (item.href === "#whatsnew") {
@@ -173,7 +169,7 @@ const Header = React.forwardRef<HTMLElement, HeaderProps>(
173169
"font-aeonik text-md font-light",
174170
activeTheme === "dark"
175171
? "hover:text-slate-300"
176-
: "hover:text-primary/70",
172+
: "hover:text-primary/70"
177173
)}
178174
>
179175
Docs
@@ -185,7 +181,7 @@ const Header = React.forwardRef<HTMLElement, HeaderProps>(
185181
className={cn(
186182
activeTheme === "dark"
187183
? "hover:text-slate-300"
188-
: "hover:text-primary/70",
184+
: "hover:text-primary/70"
189185
)}
190186
>
191187
<Github className="size-6 sm:size-7 md:size-8" />
@@ -195,7 +191,7 @@ const Header = React.forwardRef<HTMLElement, HeaderProps>(
195191
</div>
196192
</header>
197193
);
198-
},
194+
}
199195
);
200196

201197
Header.displayName = "Header";

landing/src/layouts/Layout.astro

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ const enableAnalytics =
2323
name="description"
2424
content="A must-have tool for Elixir developers. See your LiveComponents tree, inspect assigns, trace and filter callback executions, and more."
2525
/>
26+
<link
27+
rel="preload"
28+
as="video"
29+
href={`/live-debugger/assets/guide-video.webm`}
30+
type="video/webm"
31+
/>
2632
<Font cssVariable="--font-aeonik" preload />
2733
<!-- Google Tag Manager -->
2834
{

0 commit comments

Comments
 (0)