Skip to content

Add OpenGraph preview canvas extension#1312

Open
IEvangelist wants to merge 21 commits into
mainfrom
dapine/og-preview-canvas
Open

Add OpenGraph preview canvas extension#1312
IEvangelist wants to merge 21 commits into
mainfrom
dapine/og-preview-canvas

Conversation

@IEvangelist

@IEvangelist IEvangelist commented Jun 29, 2026

Copy link
Copy Markdown
Member

Adds a self-contained GitHub Copilot OpenGraph preview canvas extension under .github/extensions/og-preview/.

What it does

  • Renders how a URL's OpenGraph metadata appears across Facebook, X, LinkedIn, Slack, and Discord.
  • Shows the raw OG/Twitter metadata and diagnostics for missing or malformed tags.
  • Supports localhost URLs for previewing local dev servers.
  • Exposes two canvas actions: preview_url and get_metadata.

Implementation

  • Dependency-free ES modules: extension.mjs plus lib/ (HTTP fetch + OG parsing) and ui/ (HTML/CSS/JS).
  • No build step or external packages.

Examples

image image image image

Validation

Authored and validated end-to-end in a prior session: previews, raw metadata, diagnostics, and localhost handling all confirmed working. All JS files pass node --check.

Opened as a draft for review.

IEvangelist and others added 4 commits June 29, 2026 15:40
Previews OpenGraph metadata as rendered by Facebook, X, LinkedIn, Slack, and Discord. Supports localhost URLs and exposes preview_url and get_metadata canvas actions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Derive chrome surface colors from the guaranteed --text-color-default
  token via color-mix (with neutral translucent fallbacks) so the URL
  input, raw-metadata tables, and borders adapt to dark mode instead of
  using light-only fallback tokens.
- Refresh the host panel title whenever a new URL is loaded by re-opening
  the canvas instance (guarded against reload loops), and update the
  iframe document.title.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Rebuild the chrome on documented app theme tokens with shadcn-style
  controls (soft radii, ghost/primary buttons, segmented tabs) and a
  single on-theme accent, so the canvas is indistinguishable from the app
  in light and dark.
- Add an open_og_preview agent tool that opens/focuses the canvas (with an
  optional URL) so it can be summoned on command.
- Add a collapsible page-info footer (final URL, HTTP status, tag count,
  diagnostics summary) with a remembered open/closed state.
- Add an aspire.dev quick-example chip and auto-complete the URL scheme
  (https://, or http:// for localhost).
- Add per-value copy buttons in the raw-metadata view.
- Add realistic skeleton loaders that mirror the happy-path layout, with
  shimmer and View-Transition cross-fades, honoring prefers-reduced-motion.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…mit links

- Add /api/raw route + interactive scrollable code/file hovercard
- Rich raw-metadata value formatting (colors, numbers, dates, tokens, pills)
- Link Twitter/X handles to x.com and recognized commit SHAs to GitHub
- Compact page-info footer (stat strip + conditional canonical line)
- Theme-aware brand preview cards (dark variants via body[data-mode])
- Unify hover dismissal (scroll/blur/Escape) and fix stuck loading banner

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@IEvangelist IEvangelist marked this pull request as ready for review June 30, 2026 08:38
Copilot AI review requested due to automatic review settings June 30, 2026 08:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new self-contained GitHub Copilot canvas extension under .github/extensions/og-preview/ that runs a local loopback server to fetch a target URL, parse OpenGraph/Twitter metadata, and render multi-platform unfurl previews plus raw metadata/diagnostics in a custom UI.

Changes:

  • Introduces a new Copilot canvas extension (extension.mjs) with actions (preview_url, get_metadata) and a loopback HTTP server providing /api/fetch, /api/img, /api/raw, and /events.
  • Adds a dependency-free Node HTTP(S) fetcher and regex-based OG/meta parser (lib/http-fetch.mjs, lib/parse-og.mjs).
  • Adds a complete UI (HTML/CSS/JS) for previews, raw metadata display, diagnostics, copy helpers, and loading skeletons.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
.github/extensions/og-preview/extension.mjs Implements the canvas, loopback server routes, SSE push, and agent tools/actions.
.github/extensions/og-preview/lib/http-fetch.mjs Dependency-free HTTP(S) fetch with redirects/timeout/size cap.
.github/extensions/og-preview/lib/parse-og.mjs Parses meta/link/title tags into resolved fields, grouped raw tags, and diagnostics.
.github/extensions/og-preview/ui/index.html UI skeleton for URL input, tabbed sections, and footer.
.github/extensions/og-preview/ui/app.js Client-side rendering, skeleton states, hover previews, copy actions, and SSE handling.
.github/extensions/og-preview/ui/styles.css Styling for canvas chrome and platform-like preview cards.
.github/extensions/og-preview/README.md Documents features, routes, actions/tools, and file layout.
.github/extensions/og-preview/copilot-extension.json Declares the extension name and version.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/extensions/og-preview/lib/http-fetch.mjs
Comment thread .github/extensions/og-preview/lib/parse-og.mjs Outdated
Comment thread .github/extensions/og-preview/ui/index.html Outdated
Comment thread .github/extensions/og-preview/lib/http-fetch.mjs
…ons, faithful X card

- Make Browse the default first tab; it now drives the previews. In-frame
  navigation binds the landed route to the top-level URL (bidirectional).
- Render the browse frame via srcdoc (inline proxied HTML) so it loads inside
  the canvas host without "refused to connect"; bridge no longer self-navigates.
- Lay previews out in a multi-column masonry grid to remove wasted vertical space.
- Unify all disclosure chevrons (previews, raw metadata, diagnostics, footer)
  to one stroked chevron with a smooth transition; move the preview chevron to
  the right of its header.
- Polish collapsible sections: rounded header bounding box, hover state, and a
  grid-rows height animation.
- Fix the X/Twitter card to render summary_large_image faithfully — image with a
  bottom-left domain pill and no overlapping/floating text; small summary card
  used as the no-image fallback.
- Add Bluesky and Microsoft Teams previews with brand icons; prefix the canvas
  title with "OG Viewer - {url}".

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@IEvangelist IEvangelist marked this pull request as draft June 30, 2026 13:27
IEvangelist and others added 5 commits June 30, 2026 09:47
…istence

- Run JS inside the Browse iframe safely: inject in-memory localStorage/
  sessionStorage/cookie shims so opaque-origin boot code stops throwing, and
  harden the sandbox to "allow-scripts allow-forms".
- Unify the Browse route input with the top URL input styling; bump the browse
  icon to 15px.
- Fix about:srcdoc navigation: resolve about: URLs' query/hash back onto the real
  page URL in the bridge, and ignore non-http nav targets in the parent.
- Add a Previews layout toggle: List (default, larger single column) vs Grid
  (compact masonry), persisted to localStorage.
- Persist in-frame client state (e.g. aspire.dev's selected language tab): tag
  pushState/replaceState navigations as "soft" so the parent refreshes previews
  without reloading the frame, while link clicks ("hard") still re-render it.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ader

- Replace malformed grid toggle icon with a clean 2x2 grid octicon
- Add a "Link previews" header to the previews toolbar, left of the layout toggle
- Add Reddit (compact link card) and Mastodon (vertical status card) previews with brand icons, colors, and light/dark styles

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- http-fetch: reject (not hang) when the response exceeds the size cap;
  add an SSRF guard that denies private/link-local/unique-local/CGNAT and
  cloud-metadata (169.254.169.254) ranges by default while always allowing
  localhost/loopback (opt in to private targets via OG_ALLOW_PRIVATE_NETWORK).
- parse-og: resolve a relative <link rel=canonical> href against the base URL.
- ARIA tabs: real aria-selected/aria-controls + role=tabpanel/aria-labelledby
  linkage, roving tabindex, and Arrow/Home/End keyboard navigation.
- /api/raw: return a clear error instead of dumping an HTML error/redirect
  page into the code hovercard (fixes e.g. a .mdx value resolving to a 404 HTML
  page); guards both HTTP >= 400 and HTML content on a non-html extension.
- Browse tab: drop its separate URL bar and drive it from the main address bar;
  move an "open in browser" button into the main toolbar (shown only on Browse);
  Reload now force-refreshes the embedded frame on the Browse tab.
- Previews: the List layout now flows into multiple columns on wide panels
  (column-width 480px) while staying single-column on narrow panels.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Swap the jarring "Fetching…" loading banner (which inserted between the
header and content and shifted layout) for a thin trickle bar pinned to the
bottom edge of the sticky toolbar. It fades in/out with body.is-busy and the
fill width animates from JS (10% → cap 90% while loading, snap to 100% on
completion). Removes the old spinner keyframes; #status now shows errors only.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The browse iframe is sandboxed without allow-same-origin (opaque origin), so
the framed page's ES-module scripts were blocked by CORS and its JS never ran
(no theme toggle, sidebar, menus). Route the page's scripts, stylesheets and
fonts through /api/proxy with Access-Control-Allow-Origin so the opaque-origin
frame can load them — no allow-same-origin, so the page still can't reach the
host canvas. Subresources use a path-style proxy URL
(/api/proxy/<scheme>/<host>/<path>) so a bundle's relative imports resolve back
through the proxy automatically. Rewrites JS root-relative/absolute import
specifiers and CSS url()/@import targets; inline <style> and inline
<script type=module> are rewritten too. Verified on aspire.dev: modules execute
(mermaid renders), theme toggle works (light→dark), and link navigation still
posts real URLs. Known limitation: Vite dynamic code-split chunks
(root-relative at runtime) aren't proxied, so a few advanced diagram features
stay inert.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@IEvangelist IEvangelist marked this pull request as ready for review June 30, 2026 20:43
@IEvangelist IEvangelist enabled auto-merge (squash) June 30, 2026 20:43
The code hovercard now detects github.com blob/raw URLs, fetches the
corresponding raw.githubusercontent.com content, and renders it with a
dependency-free multi-language syntax highlighter (markdown/MDX, markup,
JSON, CSS, SQL, YAML/TOML, C-like). Failing diagnostics now include a
copyable, ready-to-paste AI fix prompt describing the issue, the page URL,
and the expected meta tag.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@IEvangelist IEvangelist marked this pull request as draft July 1, 2026 12:53
auto-merge was automatically disabled July 1, 2026 12:53

Pull request was converted to draft

IEvangelist and others added 10 commits July 1, 2026 08:18
Add two action buttons to the footer of each diagnostics "AI fix prompt":
"Open in Copilot" (opens a Copilot coding session for the page's source
repo, seeded with the prompt) and "Create issue" (files an issue on the
repo and assigns Copilot). The extension auto-detects the page's GitHub
source repo by scanning the full fetched HTML (edit/blob/tree/commit/raw
links), not just OG metadata. When no repo is found, the footer shows a
muted note instead of buttons.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- ui/styles.css: give the AI fix prompt footer proper horizontal + vertical
  inset (padding: 9px 11px) aligned with the prompt body, an accent-tinted top
  border, and a fixed empty/no-repo note state; restore the .diag-docs selector
  that a prior edit accidentally clobbered (its declarations were orphaned, so
  the "Open Graph …" docs link lost its top margin and touched the AI prompt
  box); align the AI-prompt-header copy button with the snippet copy button
  (head padding-right 8px -> 6px so both sit 7px from the box's right edge).
- extension.mjs: the "Open in Copilot" injected instruction
  (buildOpenSessionMessage) now explicitly tells the agent that if the detected
  repo is NOT one of the user's configured projects, it must say so plainly and
  offer alternatives (use "Create issue", or add the repo as a project) rather
  than improvising a sandbox session.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ar carets

- ui/app.js: replace the "Open in Copilot" button's device-desktop octicon with
  the official GitHub Copilot octicon (copilot-16); the "Create issue" button now
  uses the official issue-opened-16 path; remove the now-unused device-desktop
  entry from the OCTICONS map. The detected-repo footer slug is now a real link
  (span.diag-ai-repo -> a.diag-ai-repo with href, target=_blank, rel=noreferrer).
- ui/styles.css: (1) Scrollbar carets fix — Chromium M121+ (the Copilot App
  WebView) ignores all ::-webkit-scrollbar pseudo-elements on any element that
  also sets standard scrollbar-width/scrollbar-color, so the existing
  ::-webkit-scrollbar-button{display:none} was ignored and stepper carets
  rendered. Move scrollbar-width/scrollbar-color into an
  @supports(-moz-appearance:none) (Firefox-only) block and keep the fully custom
  ::-webkit-scrollbar rules (all -button variants display:none) for Chromium.
  (2) Add link styling for a.diag-ai-repo (hover accent + underline slug,
  focus-visible outline).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add a new experimental "Agent readiness" section in the Diagnostics tab that
probes emerging AI-agent standards (robots.txt, sitemap, Link headers,
llms.txt, Markdown negotiation, AI-bot rules, Content Signals, MCP, A2A,
Agent Skills, AI-plugin, DNS-AID, OAuth protected-resource/authorization-server,
API Catalog) grouped into 5 categories, with per-check AI fix prompts and
repo-detected Open-in-Copilot/Create-issue actions. Backed by a new server
route /api/agent-readiness in lib/agent-readiness.mjs.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Extend the OG diagnostics with ogp.me optional/structured checks: og:locale
(optional), and, when og:image is present, og:image:alt (recommended),
og:image dimensions = width+height (recommended), og:image:type (optional),
and og:image:secure_url (optional). Image sub-checks are only emitted when an
og:image exists. Adds matching DIAG_HELP guidance (why/fix/example/docs ->
ogp.me#structured) so each new check expands with an AI fix prompt.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Replace the header "Try aspire.dev" chip with a colorized "I'm feeling lucky"
button group: the gradient main button previews a random site (showing the
current target host as a pill), and a shuffle button (official sync octicon,
spin animation) retargets to a different random site without loading. Rotates
over a curated list of OG-rich sites (aspire.dev, github.com, microsoft.com,
astro.build, grpc.io, docker.com, typescriptlang.org, reddit, vercel, nextjs,
MDN, stripe, cloudflare, nasa, nodejs, bsky). The empty-state "Try aspire.dev"
chip becomes a larger "I'm feeling lucky" button that loads a fresh random site.
Removes the now-unused .examples/.chip CSS and data-example handler.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@IEvangelist IEvangelist marked this pull request as ready for review July 1, 2026 16:07
@IEvangelist IEvangelist enabled auto-merge (squash) July 1, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants