-
Notifications
You must be signed in to change notification settings - Fork 3
Cloudflare changes #66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds a new public env var PUBLIC_CLOUDFLARE_URL and uses it in publish/watch components. Updates Vite optimizeDeps to exclude @kixelated/hang and switches the dependency to a local link. Adjusts deployment (wrangler envs, just deploy param), adds preview, and revises infra (image tags, firewall TCP 443, health check relocation, relay config). Adds layout tweaks and two blog posts. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Poem
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
infra/relay.yml.tpl (1)
106-119: Make iptables rules idempotent to avoid duplicates on restarts.Repeated ExecStart will append duplicates. Check before adding.
[Service] Type=oneshot RemainAfterExit=true -ExecStart=iptables -A INPUT -p udp --dport 443 -j ACCEPT -ExecStart=iptables -A INPUT -p tcp --dport 443 -j ACCEPT +ExecStart=/bin/sh -c 'iptables -C INPUT -p udp --dport 443 -j ACCEPT || iptables -A INPUT -p udp --dport 443 -j ACCEPT' +ExecStart=/bin/sh -c 'iptables -C INPUT -p tcp --dport 443 -j ACCEPT || iptables -A INPUT -p tcp --dport 443 -j ACCEPT'
🧹 Nitpick comments (29)
.env.production (1)
4-4: New PUBLIC_CLOUDFLARE_URL looks fine; consider lint-friendly formatting and secret hygiene.
- Optional: drop quotes to satisfy dotenv-linter and keep keys alphabetized with the other PUBLIC_* vars.
- Verify no real tokens are committed in .env.production; prefer Cloudflare Pages/Wrangler secrets for production.
Apply if you want the lint fix:
-PUBLIC_CLOUDFLARE_URL="https://relay.cloudflare.mediaoverquic.com" +PUBLIC_CLOUDFLARE_URL=https://relay.cloudflare.mediaoverquic.comsrc/pages/source.mdx (1)
23-23: Minor wording tweak for flow.Suggest a tiny grammar polish.
-| [hang-gst](https://github.com/kixelated/hang-gst) | A GStreamer plugin for publishing and consuming media. Separate repository to avoid GStreamer build dependency. | +| [hang-gst](https://github.com/kixelated/hang-gst) | A GStreamer plugin for publishing and consuming media. Separate repository to avoid a GStreamer build dependency. |infra/relay.tf (1)
92-109: TCP 443 opened — consider enabling flow logs and future origin hardeningNice addition. Two follow-ups:
- Enable firewall logging to aid debugging/forensics.
- If you later front this with Cloudflare only, consider restricting source_ranges to Cloudflare IPs to block direct origin hits.
Apply to enable logging:
resource "google_compute_firewall" "relay" { name = "relay" network = "default" allow { protocol = "udp" ports = ["443"] } allow { protocol = "tcp" ports = ["443"] } + log_config { + metadata = "INCLUDE_ALL_METADATA" + } + source_ranges = ["0.0.0.0/0"] target_tags = ["relay"] }justfile (1)
66-67: Add a Cloudflare-runtime previewAstro preview runs on Node, not the CF runtime. Consider a CF preview for parity.
Add alongside the current target:
preview-cf: build pnpm wrangler pages dev ./distsrc/pages/issues.mdx (1)
20-20: Asterisk on Firefox — clarify support detailsAdd a short note (version/flags/nightly) or remove the asterisk to avoid ambiguity.
infra/relay-lb.tf (1)
75-81: Health check is commented outThis resource sits inside a block comment and won’t be created. If the intent was to move it from infra/relay.tf into active use, relocate it outside the comment (and ensure any backend service references are also active). Otherwise consider removing to reduce confusion.
Example (uncommented):
resource "google_compute_http_health_check" "relay" { name = "relay" request_path = "/health" check_interval_sec = 5 timeout_sec = 5 }infra/input.tf (1)
1-24: Add explicit types and light validation on inputs.Improves Terraform plan safety and earlier failure on misconfig.
Example:
variable "project" { + type = string description = "project id" default = "quic-video" } variable "region" { + type = string description = "region" default = "us-central1" } variable "zone" { + type = string description = "zone" default = "us-central1-a" } variable "email" { + type = string description = "Your email address, used for LetsEncrypt" default = "admin@moq.dev" + validation { + condition = can(regex("^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$", var.email)) + error_message = "email must be a valid email address." + } } variable "domain" { + type = string description = "domain name" default = "moq.dev" }wrangler.jsonc (2)
5-7: Ensure local deploy maps to the dev environment
Add a local deploy recipe injustfile(for example,dev-deploy) that invokespnpm wrangler deploy --env devso it uses the
moq-dev-localname and avoids accidentally pushing the wrong target.
15-31: Useroutesarray instead ofrouteand validate config with--dry-run
- Replace the singular
"route"block with a"routes"array to support multiple patterns, e.g.:(developers.cloudflare.com)- "route": { - "pattern": "new.moq.dev", - "custom_domain": true - } + "routes": [ + { "pattern": "new.moq.dev", "custom_domain": true } + ]- Run
npx wrangler deploy --dry-runto compile and catch config/schema errors before actual deployment
(developers.cloudflare.com)src/layouts/global.astro (3)
32-35: Image perf: lazy-load non-critical nav icons and set explicit dimensions to reduce CLS.Logo should stay eager; other icons can be lazy and sized.
-<img src="/layout/watch.svg" class="w-32" alt="Watch" /> +<img src="/layout/watch.svg" class="w-32" width="128" height="128" loading="lazy" alt="Watch" /> -<img src="/layout/publish.svg" class="w-32" alt="Publish" /> +<img src="/layout/publish.svg" class="w-32" width="128" height="128" loading="lazy" alt="Publish" /> -<img src="/layout/explain.svg" class="w-32" alt="Blog" /> +<img src="/layout/explain.svg" class="w-32" width="128" height="128" loading="lazy" alt="Blog" /> -<img src="/layout/source.svg" class="w-32" alt="Source" /> +<img src="/layout/source.svg" class="w-32" width="128" height="128" loading="lazy" alt="Source" /> -<img src="/layout/discord.svg" class="w-32" alt="Discord" /> +<img src="/layout/discord.svg" class="w-32" width="128" height="128" loading="lazy" alt="Discord" />Also applies to: 41-56
53-55: External link hardening for Discord.Open in a new tab and add rel to prevent tab‑napping.
-<a href="https://discord.gg/FCYF3p99mr"> +<a href="https://discord.gg/FCYF3p99mr" target="_blank" rel="noopener noreferrer">
61-63: Date rendering can shift by timezone; format deterministically.Use UTC or an explicit format to avoid off‑by‑one rendering across locales.
- published {new Date(frontmatter.date).toLocaleDateString()} + published {new Date(frontmatter.date + 'T00:00:00Z').toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: '2-digit', timeZone: 'UTC' })}src/pages/blog/first-app.mdx (1)
32-35: Conciseness nit.Minor copy tweak.
-And of course, all of the functionality (except for user accounts) uses Media over QUIC. +And of course, all the functionality (except for user accounts) uses Media over QUIC.infra/relay.yml.tpl (2)
87-105: Harden the systemd unit and auto-start on boot.Add basic sandboxing and ensure services survive reboots.
[Service] Restart=on-failure RestartSec=5s +NoNewPrivileges=true +ProtectSystem=full +ProtectHome=true +PrivateTmp=true ExecStart=docker run --rm \ @@ ExecStop=docker stop moq-relayAnd in runcmd:
runcmd: - systemctl daemon-reload - systemctl restart docker + - systemctl enable allow-quic + - systemctl enable moq-relay - systemctl start moq-relay
33-33: Typo in comment.“Unfortuantely” → “Unfortunately”.
- # Unfortuantely, cos-cloud doesn't seem to support the ca_certs module + # Unfortunately, cos-cloud doesn't seem to support the ca_certs modulesrc/pages/blog/first-cdn.mdx (4)
43-48: Consider referencing the configured env var instead of hardcoding the Cloudflare URL in examples.To keep docs and UI consistent and avoid drift, prefer showing examples that read from
PUBLIC_CLOUDFLARE_URL(or mention it explicitly in the prose) rather than hardcodinghttps://relay.cloudflare.mediaoverquic.com.Example snippet for HTML components:
<!-- Example showing how to inject the URL from a build-time env --> <hang-publish url="%PUBLIC_CLOUDFLARE_URL%" name="unique-name-abc123" audio video controls captions></hang-publish> <hang-watch url="%PUBLIC_CLOUDFLARE_URL%" name="unique-name-abc123" muted controls captions></hang-watch>Also applies to: 57-62, 173-206, 212-226
84-88: Highlight the risk of guessable names more explicitly.Since there’s no auth, call out that broadcasts are public-by-name and recommend sufficiently random names (e.g., 128-bit tokens) to prevent hijacking or unwanted watchers.
20-23: Add lazy-loading for images to improve LCP.Images in figures can be
loading="lazy"anddecoding="async"to reduce page weight.Apply this diff:
-  + {loading="lazy" decoding="async"}-  + {loading="lazy" decoding="async"}Also applies to: 97-100
134-137: Defer the YouTube iframe for better performance.Add
loading="lazy"to the iframe.- <iframe width="560" height="315" src="https://www.youtube.com/embed/ZXsQAXx_ao0?si=xsAscm04CnwAer4b" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen style="margin: 0 auto;"></iframe> + <iframe loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/ZXsQAXx_ao0?si=xsAscm04CnwAer4b" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen style="margin: 0 auto;"></iframe>src/pages/watch.astro (1)
10-12: Tighten the copy.Suggest replacing “Pls” with “Please” and optionally link a reporting channel.
- Watching a <strong>PUBLIC</strong> broadcast. Pls report any bad stuff. + Watching a <strong>PUBLIC</strong> broadcast. Please report any abuse via <a class="underline" href="/issues">Issues</a>..env.development (1)
1-3: Silence dotenv-linter warnings (quotes + ordering).Remove quotes and place
PUBLIC_CLOUDFLARE_URLbeforePUBLIC_RELAY_TOKENto satisfy linters. No functional change.-PUBLIC_RELAY_URL="http://localhost:4443" -PUBLIC_RELAY_TOKEN="" -PUBLIC_CLOUDFLARE_URL="https://relay.cloudflare.mediaoverquic.com" +PUBLIC_RELAY_URL=http://localhost:4443 +PUBLIC_CLOUDFLARE_URL=https://relay.cloudflare.mediaoverquic.com +PUBLIC_RELAY_TOKEN=src/components/watch.tsx (4)
10-15: Guard against missing env and invalid URL.If
PUBLIC_CLOUDFLARE_URLis empty at build/run time,new URL()throws. Add a fallback or a clearer error.- let url: URL; + let url: URL; if (name === "bbb") { url = new URL(`${import.meta.env.PUBLIC_RELAY_URL}/demo?jwt=${import.meta.env.PUBLIC_RELAY_TOKEN}`); } else { - url = new URL(import.meta.env.PUBLIC_CLOUDFLARE_URL); + const cf = import.meta.env.PUBLIC_CLOUDFLARE_URL; + if (!cf) { + console.warn("PUBLIC_CLOUDFLARE_URL is not set; falling back to PUBLIC_RELAY_URL."); + url = new URL(import.meta.env.PUBLIC_RELAY_URL); + } else { + url = new URL(cf); + } }
58-63: Harden external link attributes.For
target="_blank", includenoopenerto preventwindow.openeraccess.- <a href="/blog/first-cdn" rel="noreferrer" target="_blank"> + <a href="/blog/first-cdn" rel="noopener noreferrer" target="_blank">
30-56: Avoid duplication of the “Features” list across pages.The same list exists in
publish.tsx. Extract a small shared component (e.g.,Features.tsx) to DRY this up.
11-15: Minimize magic values.
"bbb"is a hidden feature flag. Consider centralizing the demo name in a constant and documenting the behavior.- if (name === "bbb") { + const DEMO_NAME = "bbb"; + if (name === DEMO_NAME) {src/components/publish.tsx (4)
8-9: Guard against missing env and invalid URL.Add a check before constructing the URL to avoid runtime throws when the env var is missing.
- const url = new URL(import.meta.env.PUBLIC_CLOUDFLARE_URL); + const cf = import.meta.env.PUBLIC_CLOUDFLARE_URL; + const url = new URL(cf || import.meta.env.PUBLIC_RELAY_URL);
16-19: Harden external link attributes.Add
noopenerwhen usingtarget="_blank".- <a href={`/watch?name=${name}`} rel="noreferrer" target="_blank" class="ml-2 text-2xl"> + <a href={`/watch?name=${name}`} rel="noopener noreferrer" target="_blank" class="ml-2 text-2xl">
36-67: DRY the “Features” list.Same recommendation as in
watch.tsx: pull into a shared component.
65-67: Defer non-critical image loading.Add lazy-loading and async decoding to the Cloudflare logo.
- <img src="/blog/first-cdn/cloudflare.png" alt="Cloudflare" class="w-64" /> + <img src="/blog/first-cdn/cloudflare.png" alt="Cloudflare" class="w-64" loading="lazy" decoding="async" />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (8)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlpublic/blog/first-app/demo.pngis excluded by!**/*.pngpublic/blog/first-app/icon.pngis excluded by!**/*.pngpublic/blog/first-app/preview.pngis excluded by!**/*.pngpublic/blog/first-app/snarky.pngis excluded by!**/*.pngpublic/blog/first-cdn/cloudflare.pngis excluded by!**/*.pngpublic/blog/first-cdn/global.pngis excluded by!**/*.pngpublic/layout/favicon.svgis excluded by!**/*.svg
📒 Files selected for processing (20)
.env.development(1 hunks).env.production(1 hunks)astro.config.ts(1 hunks)env.d.ts(1 hunks)infra/input.tf(1 hunks)infra/relay-lb.tf(1 hunks)infra/relay.tf(2 hunks)infra/relay.yml.tpl(2 hunks)justfile(1 hunks)package.json(1 hunks)src/components/publish.tsx(2 hunks)src/components/watch.tsx(2 hunks)src/layouts/global.astro(2 hunks)src/pages/blog/first-app.mdx(1 hunks)src/pages/blog/first-cdn.mdx(1 hunks)src/pages/index.mdx(3 hunks)src/pages/issues.mdx(2 hunks)src/pages/source.mdx(1 hunks)src/pages/watch.astro(1 hunks)wrangler.jsonc(2 hunks)
🧰 Additional context used
🪛 dotenv-linter (3.3.0)
.env.development
[warning] 3-3: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
[warning] 3-3: [UnorderedKey] The PUBLIC_CLOUDFLARE_URL key should go before the PUBLIC_RELAY_TOKEN key
(UnorderedKey)
.env.production
[warning] 4-4: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
[warning] 4-4: [UnorderedKey] The PUBLIC_CLOUDFLARE_URL key should go before the PUBLIC_RELAY_TOKEN key
(UnorderedKey)
🪛 GitHub Check: check
src/components/publish.tsx
[failure] 12-12:
Property 'hang-support' does not exist on type 'JSX.IntrinsicElements'.
src/components/watch.tsx
[failure] 28-28:
Property 'hang-watch' does not exist on type 'JSX.IntrinsicElements'.
[failure] 26-26:
Property 'hang-watch' does not exist on type 'JSX.IntrinsicElements'.
[failure] 19-19:
Property 'hang-support' does not exist on type 'JSX.IntrinsicElements'.
🪛 GitHub Actions: pr
src/components/publish.tsx
[error] 12-12: TypeScript error TS2339: Property 'hang-support' does not exist on type 'JSX.IntrinsicElements'.
🪛 LanguageTool
src/pages/blog/first-cdn.mdx
[grammar] ~11-~11: There might be a mistake here.
Context: ...Cloudflare 🚨 It's finally happening! 🚨 Cloudflare has [just announced](https://...
(QB_NEW_EN)
[grammar] ~14-~14: There might be a mistake here.
Context: ...MoQ on their massive, anycast network. Try it out, and convince your boss' boss...
(QB_NEW_EN)
[grammar] ~34-~34: There might be a mistake here.
Context: .../main/js/hang) (smash that star button). You can publish a live broadcast in the ...
(QB_NEW_EN)
[grammar] ~65-~65: There might be a mistake here.
Context: ...PI) and transmitted using MoQ of course. But that's a whole separate blog post; i...
(QB_NEW_EN)
[grammar] ~69-~69: There might be a mistake here.
Context: ...e get access to individual video frames. There's a super secret section at the ...
(QB_NEW_EN)
[grammar] ~73-~73: There might be a mistake here.
Context: ...t side but WebSupport is a big deal. We are no longer forced to use WebRTC, b...
(QB_NEW_EN)
[style] ~86-~86: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...sts start/stop, so that won't work. - **There's no [Safari support](https://caniuse.c...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~89-~89: ‘in the meantime’ might be wordy. Consider a shorter alternative.
Context: ...m/kixelated/moq/tree/main/rs/moq-relay) in the meantime. I've been adding new features and fixi...
(EN_WORDINESS_PREMIUM_IN_THE_MEANTIME)
[style] ~93-~93: Consider setting off ‘too’ with commas if you want to emphasize an abrupt change of thought.
Context: .../relay.tf) that powers relay.moq.dev. You too can run your own "global" CDN with 3 no...
(MISSING_COMMA_WITH_TOO)
[grammar] ~108-~108: There might be a mistake here.
Context: ...thy is a tragedy and boredom is a crime. > - [Bo Burnham](https://www.youtube.co...
(QB_NEW_EN)
[grammar] ~116-~116: There might be a mistake here.
Context: ...efore there's been any real world usage. It's been over 3 years since I fought Am...
(QB_NEW_EN)
[style] ~117-~117: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...archive/id/draft-lcurley-warp-00.html). It's going to be at least another 3 years ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[grammar] ~122-~122: There might be a mistake here.
Context: ... in 2015, with the RFC released in 2021. And they had a boatload of production da...
(QB_NEW_EN)
[grammar] ~129-~129: There might be a mistake here.
Context: ... the mentality that MoQ needs right now. Just build something. **Just release...
(QB_NEW_EN)
[grammar] ~130-~130: There might be a mistake here.
Context: ...eds right now. Just build something. Just release something. **Just do it...
(QB_NEW_EN)
[grammar] ~131-~131: There might be a mistake here.
Context: ...something**. Just release something. Just do it.
(QB_NEW_EN)
[grammar] ~149-~149: There might be a mistake here.
Context: ...LS / RTMP using relatively new Web APIs. Don't judge MoQ based on these initial o...
(QB_NEW_EN)
[grammar] ~150-~150: There might be a mistake here.
Context: ...ge MoQ based on these initial offerings. We've got a ton of work to do. **Let...
(QB_NEW_EN)
[grammar] ~155-~155: There might be a mistake here.
Context: ...). Somehow there's 900+ people in there. Ping me and I will do whatever I can to ...
(QB_NEW_EN)
[grammar] ~156-~156: There might be a mistake here.
Context: ...me and I will do whatever I can to help. Especially if it means putting one mor...
(QB_NEW_EN)
[grammar] ~170-~170: There might be a mistake here.
Context: ...nge and is probably already out of date. When in doubt, [consult the source code]...
(QB_NEW_EN)
[grammar] ~208-~208: There might be a mistake here.
Context: ...cret* features behind undocumented APIs. Like running an object detection model i...
(QB_NEW_EN)
[grammar] ~209-~209: There might be a mistake here.
Context: ... Like running an object detection model in browser and publishing the results as a...
(QB_NEW_EN)
[grammar] ~209-~209: There might be a mistake here.
Context: ...d publishing the results as a MoQ track. Stay tuned for a blog post about that if...
(QB_NEW_EN)
[grammar] ~210-~210: There might be a mistake here.
Context: ...out a better use-case than a cat cam. 🐈 typescript // Publish a broadcast. const publish = new Watch.Publish({ enabled: true, url: "https://relay.cloudflare.mediaoverquic.com", name: "unique-name-abc123", device: "camera", video: { enabled: true, detection: { enabled: true, } }, }) Also, for the record, Typescript is real...
(QB_NEW_EN)
[grammar] ~228-~228: There might be a mistake here.
Context: ...r the record, Typescript is really nice. 🤮 Javascript 🤮 is still an abomination...
(QB_NEW_EN)
src/pages/blog/first-app.mdx
[grammar] ~11-~11: There might be a mistake here.
Context: ... hang.live 🚨 It's finally happening! 🚨 4 months ago I...
(QB_NEW_EN)
[style] ~13-~13: The word ‘quit’ might seem too casual. In this context, consider opting for a more formal alternative.
Context: ... months ago](/blog/application-first) I quit my job and went all-in on MoQ. 4 months...
(QUIT_MY_JOB)
[grammar] ~22-~22: There might be a mistake here.
Context: ...igure> hang.live is place to hang out with friends after a ...
(QB_NEW_EN)
[grammar] ~22-~22: There might be a mistake here.
Context: ... hang out with friends after a long day. It's meant to be fun and stupid. Everyth...
(QB_NEW_EN)
[style] ~32-~32: Consider removing “of” to be more concise
Context: ... And of course, all of the functionality (except for user accounts...
(ALL_OF_THE)
[grammar] ~39-~39: There might be a mistake here.
Context: ...vering around my office. ## Open Source Even if you don't want to use a site des...
(QB_NEW_EN)
[grammar] ~44-~44: There might be a mistake here.
Context: ... the x,y,z coordinates of a broadcast. However, every component is opt-in via...
(QB_NEW_EN)
[grammar] ~47-~47: There might be a mistake here.
Context: ...e contractors that shall not be named. I want to help you grow that list, [jo...
(QB_NEW_EN)
[grammar] ~48-~48: There might be a mistake here.
Context: ...Discord](https://discord.gg/FCYF3p99mr). Seriously, this has become a personal ve...
(QB_NEW_EN)
[grammar] ~51-~51: There might be a mistake here.
Context: ... vibe coded UI is closed source for now. I still have ambitions of [hang.live](ht...
(QB_NEW_EN)
[grammar] ~72-~72: There might be a mistake here.
Context: ...t of meme videos and sounds; try /brb. Seriously just [try it out](https://hang...
(QB_NEW_EN)
[grammar] ~78-~78: There might be a mistake here.
Context: .... ## Huge Disclaimer This shit is hard. Nothing has been optimized and the user ...
(QB_NEW_EN)
[grammar] ~79-~79: There might be a mistake here.
Context: ...erience still leaves much to be desired. Just like the [Cloudflare CDN](/blog/fir...
(QB_NEW_EN)
[style] ~83-~83: As an alternative to the over-used intensifier ‘really’, consider replacing this phrase.
Context: ...olled by Google for over a decade. It's really good at powering Google Meet, but it gets ex...
(EN_WEAK_ADJECTIVE)
[style] ~96-~96: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...erated and just needs to be toned down. Maybe we don't need hundreds of wiggling line...
(REP_MAYBE)
🔇 Additional comments (12)
env.d.ts (1)
6-6: Typing for PUBLIC_CLOUDFLARE_URL: LGTM.Correctly scoped as a public string on ImportMetaEnv.
astro.config.ts (1)
39-41: Excluding @kixelated/hang from optimizeDeps: LGTM.Appropriate when using a linked package; harmless otherwise since optimizeDeps is dev-only.
src/pages/index.mdx (3)
11-11: Cloudflare mention — LGTMReads well and matches the rest of the PR’s Cloudflare positioning.
42-42: No action neededTrailing newline/formatting looks fine.
27-28: Verified gstreamer and ffmpeg URLs — both repositories exist and match the intended targets.justfile (1)
57-59: Clarify deployment target as Cloudflare Workers
justfile lines 57–59-# Deploy the site to Cloudflare Pages +# Deploy to Cloudflare Workers deploy env="staging": build pnpm wrangler deploy --env {{env}}Likely an incorrect or invalid review comment.
src/pages/issues.mdx (2)
24-27: New “What works” bullets — LGTMClear and helpful additions.
58-58: No action neededFormatting tweak is fine.
infra/input.tf (1)
1-68: No remaining Cloudflare token references
Confirmed no occurrences of cloudflare_dns_token or cloudflare_zone_token in the codebase.infra/relay.yml.tpl (1)
59-69: TLS/web config looks consistent; manual verification needed for multi-cert arrays and listeners
The grep yielded no output—please confirm the deployedmoq-relayversion supports multi-cert arrays and the[web.https]block, and verify (e.g. viajournalctlor your logs) that both QUIC (UDP 443) and HTTPS (TCP 443) listeners are bound and certificates loaded..env.development (1)
3-3: Ensure production parity.Verify
.env.productionalso definesPUBLIC_CLOUDFLARE_URLwith the intended value (or a Cloudflare Preview value).Would you like a quick script to diff environment keys across environments?
src/components/watch.tsx (1)
19-28: Declare hang- custom elements in JSX*
Add a global JSX augmentation (e.g.src/types/hang-elements.d.ts) withIntrinsicElementsentries for"hang-support","hang-publish", and"hang-watch"(typed asany) to unblock the TSX errors.
| variable "docker_relay" { | ||
| description = "Docker image for moq-relay" | ||
| default = "docker.io/kixelated/moq-relay:0.8.8" | ||
| default = "docker.io/kixelated/moq-relay:0.9.2" | ||
| } | ||
|
|
||
| variable "docker_hang" { | ||
| description = "Docker image for hang" | ||
| default = "docker.io/kixelated/hang:0.2.5" | ||
| } | ||
|
|
||
| variable "cloudflare_dns_token" { | ||
| description = "Cloudflare DNS API token - edit permissions for moq.dev" | ||
| sensitive = true | ||
| } | ||
|
|
||
| variable "cloudflare_zone_token" { | ||
| description = "Cloudflare Zone API token - read permissions for all zones" | ||
| sensitive = true | ||
| default = "docker.io/kixelated/hang:0.2.9" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Pin Docker images by digest to prevent supply‑chain drift.
Tags are mutable; use immutable digests for deterministic, auditable deploys.
Apply:
-variable "docker_relay" {
- description = "Docker image for moq-relay"
- default = "docker.io/kixelated/moq-relay:0.9.2"
-}
+variable "docker_relay" {
+ description = "Docker image for moq-relay"
+ # Example with digest; update to the correct digest from your registry
+ default = "docker.io/kixelated/moq-relay@sha256:<relay-digest>"
+}
-variable "docker_hang" {
- description = "Docker image for hang"
- default = "docker.io/kixelated/hang:0.2.9"
-}
+variable "docker_hang" {
+ description = "Docker image for hang"
+ # Example with digest; update to the correct digest from your registry
+ default = "docker.io/kixelated/hang@sha256:<hang-digest>"
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| variable "docker_relay" { | |
| description = "Docker image for moq-relay" | |
| default = "docker.io/kixelated/moq-relay:0.8.8" | |
| default = "docker.io/kixelated/moq-relay:0.9.2" | |
| } | |
| variable "docker_hang" { | |
| description = "Docker image for hang" | |
| default = "docker.io/kixelated/hang:0.2.5" | |
| } | |
| variable "cloudflare_dns_token" { | |
| description = "Cloudflare DNS API token - edit permissions for moq.dev" | |
| sensitive = true | |
| } | |
| variable "cloudflare_zone_token" { | |
| description = "Cloudflare Zone API token - read permissions for all zones" | |
| sensitive = true | |
| default = "docker.io/kixelated/hang:0.2.9" | |
| } | |
| variable "docker_relay" { | |
| description = "Docker image for moq-relay" | |
| # Example with digest; update to the correct digest from your registry | |
| default = "docker.io/kixelated/moq-relay@sha256:<relay-digest>" | |
| } | |
| variable "docker_hang" { | |
| description = "Docker image for hang" | |
| # Example with digest; update to the correct digest from your registry | |
| default = "docker.io/kixelated/hang@sha256:<hang-digest>" | |
| } |
🤖 Prompt for AI Agents
In infra/input.tf around lines 26 to 34, the variables define Docker images
using mutable tags which can drift; update them to pinned image digests
(image@sha256:<digest>) instead of tag-only defaults. Obtain the exact sha256
digests from the image registry (docker pull or registry API) for
docker.io/kixelated/moq-relay:0.9.2 and docker.io/kixelated/hang:0.2.9 and
replace the default values with the corresponding image@sha256:<digest> strings,
or alternatively make the variables required (no default) and document that
callers must supply a digest-pinned image; ensure any other references in the
code use the new digest variables.
| }, | ||
| "dependencies": { | ||
| "@kixelated/hang": "^0.3.9", | ||
| "@kixelated/hang": "link:../moq/js/hang", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Local link dependency will break CI/Cloudflare builds.
link:../moq/js/hang assumes a sibling repo on disk and won’t exist in remote builders, causing installs/builds to fail. Use a published semver or a Git dependency for reproducible builds; keep local linking as a dev-only override.
Recommended revert for main:
- "@kixelated/hang": "link:../moq/js/hang",
+ "@kixelated/hang": "^0.3.9",Dev-only options:
- Use
pnpm link --globallocally without committing. - Or add a per-developer
.npmrcwith@kixelated:registry=pointing to a private feed if testing prereleases. - If you need unreleased code, reference a Git tag/commit:
"@kixelated/hang": "github:kixelated/moq#<commit-or-tag>:js/hang"(ensure your build environment has access).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "@kixelated/hang": "link:../moq/js/hang", | |
| "@kixelated/hang": "^0.3.9", |
🤖 Prompt for AI Agents
In package.json around line 16, the dependency "@kixelated/hang":
"link:../moq/js/hang" is a local filesystem link that will break CI/Cloudflare
builds; replace it with a published semver or a remote Git reference for
reproducible builds (e.g. a package version or
"github:kixelated/moq#<commit-or-tag>:js/hang"), and keep any local link only as
a developer-only override (use pnpm link locally or per-developer .npmrc) so
commits do not include link: paths that remote builders can't resolve.
| <hang-support prop:mode="publish" prop:show="partial" /> | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same TSX custom element typing issue as watch.tsx.
The hang-* tags need the global JSX declaration to pass type checking. See suggested src/types/hang-elements.d.ts.
Also applies to: 21-34
🧰 Tools
🪛 GitHub Check: check
[failure] 12-12:
Property 'hang-support' does not exist on type 'JSX.IntrinsicElements'.
🪛 GitHub Actions: pr
[error] 12-12: TypeScript error TS2339: Property 'hang-support' does not exist on type 'JSX.IntrinsicElements'.
🤖 Prompt for AI Agents
In src/components/publish.tsx around lines 12 to 13 (and also covering lines
21-34), the custom JSX tag <hang-support> is not typed so TypeScript fails type
checking; add a global JSX declaration file (e.g., src/types/hang-elements.d.ts)
that augments the JSX.IntrinsicElements with entries for "hang-support" (and any
other hang-* tags used on lines 21-34) specifying appropriate props (e.g.,
mode?: string; show?: string; [key: string]: any), export it as a global
declaration (declare global { namespace JSX { interface IntrinsicElements {
"hang-support": any; /* or specific props */ /* add other hang-* tags here */ }
} }) and ensure this file is included by tsconfig.json so the compiler picks up
the custom element typings.
| [hang.live](https://hang.live) is place to hang out with friends after a long day. | ||
| It's meant to be fun and stupid. | ||
| Everything is **live** and focused on human interaction. | ||
| People will *eventually* need a break from AI slop... even if that means disqualifying myself from VC funding. | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix a couple of public-facing grammar nits.
Improves polish without changing tone.
-[hang.live](https://hang.live) is place to hang out with friends after a long day.
+[hang.live](https://hang.live) is a place to hang out with friends after a long day.
@@
-The vibe coded UI is closed source for now.
+The vibe-coded UI is closed source for now.Also applies to: 51-54
🧰 Tools
🪛 LanguageTool
[grammar] ~22-~22: There might be a mistake here.
Context: ...igure> hang.live is place to hang out with friends after a ...
(QB_NEW_EN)
[grammar] ~22-~22: There might be a mistake here.
Context: ... hang out with friends after a long day. It's meant to be fun and stupid. Everyth...
(QB_NEW_EN)
🤖 Prompt for AI Agents
In src/pages/blog/first-app.mdx around lines 22–26 (and also apply the same
fixes to lines 51–54): correct the public-facing grammar by inserting the
missing article ("is place" -> "is a place") and ensure punctuation/spacing is
consistent (single spaces after sentences and terminal periods where
appropriate) while preserving the original tone and emphasis.
Summary by CodeRabbit
New Features
UI/Style
Documentation
Chores