From a3f00b90335cd1b392c6b0a4ea1af68c45fc83fb Mon Sep 17 00:00:00 2001 From: Ben Croker Date: Thu, 3 Apr 2025 21:43:21 -0600 Subject: [PATCH] Add Videos page [deploy-site] --- site/router.go | 1 + site/routes_bundler.templ | 2 +- site/routes_videos.go | 66 +++++++++++++++++++++++++++++++++++++++ site/routes_videos.templ | 29 +++++++++++++++++ site/shared.templ | 3 ++ 5 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 site/routes_videos.go create mode 100644 site/routes_videos.templ diff --git a/site/router.go b/site/router.go index 7cd56dc0..6a3a06a9 100644 --- a/site/router.go +++ b/site/router.go @@ -133,6 +133,7 @@ func setupRoutes(ctx context.Context, router chi.Router) (err error) { setupHowTos(ctx, router), setupExamples(ctx, router, sessionSignals), setupTests(ctx, router), + setupVideos(router), setupEssays(ctx, router), setupErrors(router), setupMemes(router), diff --git a/site/routes_bundler.templ b/site/routes_bundler.templ index b3551c28..1fd42ef5 100644 --- a/site/routes_bundler.templ +++ b/site/routes_bundler.templ @@ -15,7 +15,7 @@ templ PageBundler(r *http.Request, manifest PluginManifest, store *BundlerStore) @header(r)
-
Bundler
+

Bundler

While Datastar is still one of the smallest frameworks available, you can bundle only the plugins you need to reduce the size even further.
diff --git a/site/routes_videos.go b/site/routes_videos.go new file mode 100644 index 00000000..6622bae4 --- /dev/null +++ b/site/routes_videos.go @@ -0,0 +1,66 @@ +package site + +import ( + "net/http" + "strconv" + + "github.com/go-chi/chi/v5" + datastar "github.com/starfederation/datastar/sdk/go" +) + +type Video struct { + Code string + Title string +} + +func setupVideos(router chi.Router) error { + videos := []Video{ + {Code: "4vb9C_K7zCU", Title: " Delaney exposes Alien Signals—not so extraterrestrial after all"}, + {Code: "0K71AyAF6E4", Title: "Real-time Hypermedia - Delaney Gillilan"}, + {Code: "OV6xS865pF0", Title: "Immutability & Event Sourcing "}, + {Code: "YRzPqPELZdY", Title: "DataStar, Engineering, and Web Apps with Delaney Gillilan"}, + {Code: "IrtBBqyDrJU", Title: "Codeiomorph with Micah "}, + {Code: "HbTFlUqELVc", Title: "Hypermedia at 144fps!?"}, + {Code: "DTURjpV2ZHQ", Title: "Getting to grips with Datastar "}, + {Code: "QPRigsY_4E8", Title: "054: Datastar with Delaney Gillilan"}, + {Code: "zu92P9wyUfI", Title: "Tuning the engine; Codeiomorph; Pub/Sub; NATS "}, + {Code: "a6ByFsFCN0c", Title: "Beta 3; Full-stack framework; CQRS"}, + {Code: "hUqFY9TQvdM", Title: "Datastar – The progressive performance framework"}, + {Code: "p4X02rEPkJY", Title: "What Datastar is Not, with JLarky"}, + {Code: "99wTA9sFEWE", Title: "Datastar v1"}, + {Code: "J-DzgNA6F-4", Title: "[D*#4] ‐ Build a dopamine hell with Datastar!"}, + {Code: "1cbqmVkzcJQ", Title: "[D*#3] ‐ Build a chess game with Datastar"}, + {Code: "t2NC7jGtD60", Title: "[D*#2] ‐ Build a Twitch room with Datastar "}, + {Code: "vLekrUywdRI", Title: "[D*#1] - Build a game with Python and Datastar!"}, + {Code: "UXPD3LblwVA", Title: "I recreated Google's worst product feature using datastar"}, + {Code: "aVjU1st-52g", Title: "Intro to Datastar (and Craft CMS)"}, + {Code: "FMKdE4QFyNk", Title: "Puffy does Realtime Hypermedia - Patrick Marchand - EuroBSDCon 2024"}, + } + + router.Route("/videos", func(videosRouter chi.Router) { + videosRouter.Get("/", func(w http.ResponseWriter, r *http.Request) { + PageVideos(r, videos...).Render(r.Context(), w) + }) + + videosRouter.Get("/data/{index}", func(w http.ResponseWriter, r *http.Request) { + sse := datastar.NewSSE(w, r) + + indexStr := chi.URLParam(r, "index") + if indexStr == "" { + http.Error(w, "Missing index", http.StatusBadRequest) + return + } + + index, err := strconv.Atoi(indexStr) + if err != nil || index < 0 || index >= len(videos) { + http.Error(w, "Invalid index", http.StatusBadRequest) + return + } + code := videos[index].Code + + sse.MergeFragments(`
`) + }) + }) + + return nil +} diff --git a/site/routes_videos.templ b/site/routes_videos.templ new file mode 100644 index 00000000..c891dded --- /dev/null +++ b/site/routes_videos.templ @@ -0,0 +1,29 @@ +package site + +import "net/http" +import "strconv" + +templ PageVideos(r *http.Request, videos ...Video) { + @Page("Videos", "A day without a good video is like a joke without a punchline—pointless.", "/videos") { + @header(r) +
+
+

Videos

+
Subscribe to our YouTube channel and never miss a video update.
+
+
+ for key, video := range videos { + {{ + id := "video-" + strconv.Itoa(key) + action := "@get('/videos/data/" + strconv.Itoa(key) + "')" + thumbnail := "https://img.youtube.com/vi/" + video.Code + "/maxresdefault.jpg" + title := video.Title + }} +
+ { +
+ } +
+
+ } +} diff --git a/site/shared.templ b/site/shared.templ index cf5b38f4..cde42c0b 100644 --- a/site/shared.templ +++ b/site/shared.templ @@ -103,6 +103,9 @@ templ headerTopLevelLinks(r *http.Request) { @headerTopLevelLink(r, "How Tos") @headerTopLevelLink(r, "Examples") @headerDropdownMenu("More") { +
  • + @headerTopLevelLink(r, "Videos") +
  • @headerTopLevelLink(r, "Essays")