Skip to content

Repository files navigation

pCube Sharing Debugger

Local preview of how a URL appears when shared on social networks. Extracts Open Graph, Twitter Cards, JSON-LD, validates structured data, and renders realistic CSS previews for Facebook, Twitter/X, and LinkedIn.

Built for debugging sites that are only accessible from a whitelisted IP — no external API calls, everything runs locally.

Features

  • Metadata extractionog:*, twitter:*, meta description, canonical URL, favicon, JSON-LD
  • Validation pipeline — unified findings[] with severity taxonomy (ERROR / WARNING / INFO) and stable codes across OG, Twitter, JSON-LD, and general categories
  • Social preview cards — realistic CSS replicas of Facebook, Twitter/X, and LinkedIn link previews, each with platform‑specific styling
  • JS rendering — optional Puppeteer/Chromium for SPAs with JS-injected meta tags; auto‑fallback when the HTTP scraper gets blocked (403)
  • Screenshot — viewport screenshot captured when JS rendering is enabled; automatic cookie‑banner dismissal
  • JSON-LD analysis — extract, flatten (@graph), validate context, required fields, URL absolutes, dates, breadcrumb structure, duplicate type detection (opt‑in via toggle)
  • OG image validation — HEAD request check for reachability, file size, content type; icon/favicon pattern heuristic
  • Favicon check — verifies declared favicon is reachable (HEAD request)
  • Report — one‑click Markdown report with all findings, metadata, and JSON‑LD key summary (copy to clipboard)
  • Dark mode — System / Light / Dark toggle, persisted in localStorage
  • Tailwind v4 — modern CSS pipeline with automatic dark mode support

Quick start

npm install
npm start

Opens http://127.0.0.1:3333 in the browser.

Commands

Command Description
npm start Build CSS + start server on 127.0.0.1:3333 and open browser
npm run dev Server with --watch + Tailwind watcher in parallel; CSS rebuilt automatically
npm run build:css Rebuild Tailwind CSS (after editing src/input.css)
PORT=4444 npm start Custom port

The server listens on 127.0.0.1 only (no external exposure).

API

POST /api/debug

{
  "url": "https://example.com/page",
  "jsRender": false,
  "enableJsonLd": false
}
  • jsRender: true — uses Puppeteer (headless Chromium). Useful for SPAs (React, Vue) that inject meta tags via JavaScript. Also used automatically as fallback when the HTTP scraper receives a 403/4xx.
  • jsRender: false (default) — direct HTTP fetch + cheerio parsing (fast).
  • enableJsonLd: true — enables JSON‑LD extraction and validation (off by default for performance).

Response:

{
  "url": "https://example.com/page",
  "meta": {
    "og": {},
    "twitter": {},
    "general": {},
    "jsonld": [],
    "jldFindings": []
  },
  "previews": { "facebook": {}, "twitter": {}, "linkedin": {} },
  "findings": [
    {
      "severity": "error|warning|info",
      "category": "GENERAL|OG|TWITTER|JSONLD",
      "code": "OG_IMAGE_MISSING",
      "message": "Descrizione in italiano",
      "field": "og:image"
    }
  ],
  "jsRender": false,
  "screenshotUrl": null
}

Findings are sorted by severity (ERROR → WARNING → INFO). Each finding has a stable code for filtering and regression tracking.

When jsRender: true, screenshotUrl contains a base64 JPEG of the page viewport.

Architecture

├── server.mjs              Express entrypoint
├── src/
│   ├── scraper.mjs         Native HTTP fetch + gzip decompression + cheerio HTML parsing
│   ├── puppeteer.mjs       Optional headless Chromium wrapper (cookie‑banner auto‑dismiss)
│   ├── previews.mjs        Social preview card data builder
│   ├── opengraph.mjs       OG + Twitter tag validation, image HEAD checks, favicon check
│   ├── jsonld.mjs          JSON‑LD extraction, normalization, type validation, duplicate detection
│   ├── findings.mjs        Severity/Category enums, sort utility
│   └── input.css           Tailwind v4 source (→ public/style.css)
├── public/
│   ├── index.html          Vanilla HTML UI
│   ├── app.js              Frontend logic (findings rendering, report builder, theme management)
│   └── style.css           Auto‑generated by Tailwind (do not edit)
├── Dockerfile              Multi‑stage Docker build (with Chromium)
└── docker-compose.yml

Docker

HOST=0.0.0.0 docker compose up -d --build

The container includes Chromium via apt, configured via PUPPETEER_EXECUTABLE_PATH. For external access, set HOST=0.0.0.0 (default is 127.0.0.1, local only).

For HTTPS, place behind a reverse proxy (Caddy, Nginx, Traefik).

Finding codes reference

The full taxonomy is defined in the project's findings.mjs and opengraph.mjs / jsonld.mjs modules. Key codes:

Category Code Severity Condition
GENERAL TITLE_OG_TITLE_MISMATCH INFO <title> and og:title differ
GENERAL CANONICAL_OG_URL_MISMATCH WARNING canonical and og:url point to different URLs
GENERAL FAVICON_MISSING INFO No <link rel="icon"> declared
GENERAL FAVICON_UNREACHABLE WARNING Favicon URL returns 4xx/5xx
OG OG_TITLE_MISSING ERROR og:title absent
OG OG_IMAGE_MISSING ERROR og:image absent
OG OG_IMAGE_TOO_SMALL ERROR Below 200×200 px
OG OG_IMAGE_BELOW_RECOMMENDED WARNING Below 1200×630 px
OG OG_IMAGE_LOOKS_LIKE_ICON WARNING URL suggests icon/favicon
OG OG_IMAGE_UNREACHABLE ERROR HEAD request failed
OG OG_DUPLICATE_TAG ERROR Same OG tag declared multiple times
TWITTER TWITTER_CARD_MISSING WARNING twitter:card absent
TWITTER TWITTER_IMAGE_MISSING INFO twitter:image absent, fallback on og:image
JSONLD JSONLD_PARSE_ERROR ERROR Block content is not valid JSON
JSONLD JSONLD_TYPE_MISSING ERROR Node has no @type
JSONLD JSONLD_REQUIRED_FIELD_MISSING ERROR Missing required field for type
JSONLD JSONLD_DUPLICATE_TYPE WARNING Same @type appears multiple times with incompatible structure
JSONLD JSONLD_CONTEXT_NOT_SCHEMAORG WARNING @context not schema.org (or uses http:// instead of https://)
JSONLD JSONLD_CONTEXT_MISSING WARNING Node has @type but no @context declared

Notes

  • og:image must be ≥ 200×200 px; ≥ 1200×630 px recommended for full‑width Facebook previews
  • og:image is the only image tag used by Facebook and LinkedIn; twitter:image is X/Twitter only
  • If og:title is missing, the <title> HTML tag is used as fallback
  • puppeteer downloads Chromium (~300 MB) on npm install. Remove it from package.json if not needed — JS rendering will show a clear error message
  • JSON‑LD analysis is opt‑in via the toggle in the UI (enableJsonLd: false by default)
  • When the HTTP scraper receives a 4xx response (bot‑blocking CDNs like CNN.com), the server automatically falls back to Puppeteer for that request

About

Local preview of how a URL appears when shared on social networks. Extracts Open Graph, Twitter Cards, JSON-LD, validates structured data, and renders realistic CSS previews for Facebook, Twitter/X, and LinkedIn.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages