feat(docs): surface external-service homepage links from block metadata#5034
feat(docs): surface external-service homepage links from block metadata#5034waleedlatif1 wants to merge 2 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryLow Risk Overview
English integration MDX was regenerated in bulk so each third-party integration supplies the new props; formatting on Reviewed by Cursor Bugbot for commit 73a538f. Configure here. |
|
@greptile |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit deb0def. Configure here.
|
@greptile review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 2fa2183. Configure here.
Greptile SummaryThis PR surfaces
Confidence Score: 5/5Safe to merge; all changed surfaces are additive doc/metadata features with no mutations to runtime workflow logic. The doc-generation script changes are isolated to a new extraction path that produces optional metadata — blocks without a BlockMeta.url are unaffected and fall back to the existing rendering path. The BlockInfoCard and landing-page additions are purely presentational and conditionally rendered only when url is present. All 207 generated URL values are well-formed absolute HTTPS URLs verified by the author's manual run. No runtime logic, auth paths, database writes, or API contracts are touched. No files require special attention beyond the doc-generation script, where a prior review already identified the regex word-boundary and MDX-escaping risks that apply to future block additions. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["Block source file\n(*BlockMeta.url)"] --> B["extractBlockMetaBody\nscopes to meta literal"]
B --> C["extractUrlFromBlockMeta\nreturns url string or null"]
C --> D["extractBlockConfigFromContent\nattaches url to BlockConfig"]
D --> E["writeIntegrationsJson\nurl → integrations.json"]
D --> F["generateMarkdownForBlock\nurl → MDX BlockInfoCard props"]
E --> G["Integration Landing Page\nVisit CTA + JSON-LD about:Org"]
F --> H["BlockInfoCard component\noutbound Visit link"]
style A fill:#f0f4ff,stroke:#6b7280
style G fill:#f0fff4,stroke:#6b7280
style H fill:#f0fff4,stroke:#6b7280
Reviews (4): Last reviewed commit: "fix(docs): style block-info-card visit l..." | Re-trigger Greptile |
| export function QuartrIcon(props: SVGProps<SVGSVGElement>) { | ||
| return ( | ||
| <svg {...props} viewBox='0 0 151 40' fill='none' xmlns='http://www.w3.org/2000/svg'> | ||
| <path | ||
| d='M11.5483 29.9995C11.5483 35.5222 19.8031 39.9995 26.1809 39.9995C29.574 39.9995 32.6254 38.7323 34.7384 36.7144L26.1809 29.9995H11.5483Z' | ||
| fill='currentColor' | ||
| /> | ||
| <path | ||
| d='M0 29.9996C0 35.5222 5.17047 39.9995 11.5483 39.9995V19.9998C5.17047 19.9998 0 24.4768 0 29.9996Z' | ||
| fill='currentColor' | ||
| /> | ||
| <path | ||
| d='M26.1808 9.99989V27.5075H37.7292V10.0249C37.7173 4.46985 32.552 -0.0135841 26.1808 2.98331e-05H11.4362V0.00114226C5.11012 0.0536532 0 4.50986 0 9.99989V19.9998H11.5483V9.99989H26.1808' | ||
| fill='currentColor' | ||
| /> | ||
| <path d='M28.1898 29.3275L40.7827 38.9295V29.3275H28.1898Z' fill='currentColor' /> | ||
| <path | ||
| d='M88.7938 25.1089H88.7527C87.927 29.0309 85.4089 30.806 82.0238 30.806C77.0289 30.806 75.2949 27.5033 75.2949 23.3752V11.0324H78.8865V22.4671C78.8865 25.1089 80.0423 27.5033 83.5102 27.5033C86.8123 27.5033 88.7938 25.6872 88.7938 22.4671V11.0324H92.3854V30.3106H88.7938V25.1089Z' | ||
| fill='currentColor' | ||
| /> | ||
| <path | ||
| d='M107.351 23.1277V22.2193H101.613C99.1774 22.2193 97.8563 23.1277 97.8563 24.82C97.8563 26.3063 98.8062 27.7095 101.613 27.7095C105.163 27.7095 107.351 25.7697 107.351 23.1277ZM107.351 25.3982H107.31C106.443 28.948 103.842 30.7235 100.499 30.7235C96.7419 30.7235 94.3067 28.907 94.3067 25.2742C94.3067 21.8892 96.4529 19.371 101.118 19.371H107.351V18.3389C107.351 15.3254 106.196 13.6742 103.14 13.6742C100.375 13.6742 98.8473 14.9538 98.3108 18.1324L94.8843 17.6371C95.5447 13.1375 98.1869 10.6193 103.264 10.6193C108.631 10.6193 110.943 13.3438 110.943 18.2976V30.3106H107.351V25.3982' | ||
| fill='currentColor' | ||
| /> | ||
| <path | ||
| d='M112.909 30.3106V11.0324H116.5V16.9767H116.583C117.367 12.477 119.184 11.0324 122.28 11.0324H123.477V14.995H121.743C118.111 14.995 116.5 16.3988 116.5 20.1141V30.3106H112.909' | ||
| fill='currentColor' | ||
| /> | ||
| <path | ||
| d='M128.24 14.1166L125.391 15.0444V11.0205H128.24V5.69549H131.832V11.0205H137.982V15.0146L131.832 14.1166V24.0654C131.832 26.2122 132.657 27.3266 134.804 27.3266C135.836 27.3266 136.703 27.1203 137.735 26.8313L138.189 30.1339C136.868 30.5465 135.836 30.7944 134.06 30.7944C130.015 30.7944 128.24 28.1524 128.24 24.5609V14.1166' | ||
| fill='currentColor' | ||
| /> | ||
| <path | ||
| d='M140.129 30.3106V11.0324H143.72V16.9767H143.803C144.587 12.477 146.403 11.0324 149.499 11.0324H150.697V14.995H148.963C145.33 14.995 143.72 16.3988 143.72 20.1141V30.3106H140.129' | ||
| fill='currentColor' | ||
| /> | ||
| <path | ||
| d='M70.4206 19.1212C70.4206 14.0209 66.7718 10.045 61.8913 10.045C57.0108 10.045 53.0603 14.0209 53.0603 19.1212C53.0603 24.5028 56.9397 27.7175 61.8913 27.7175C66.8429 27.7175 70.4206 24.5028 70.4206 19.1212V19.1212ZM49.7827 19.1615C49.7827 11.9726 55.2655 6.67151 61.8913 6.67151C68.553 6.67151 73.6979 11.9726 73.6979 19.1615C73.6979 23.4184 71.6333 26.3923 68.9972 28.6411L72.0609 34.2237V34.304H68.4629L66.3614 30.2878C65.1145 30.7696 63.423 31.051 61.8913 31.051C55.1227 31.051 49.7827 26.3098 49.7827 19.1615' | ||
| fill='currentColor' | ||
| /> | ||
| <svg {...props} viewBox='0 0 32 32' fill='none' xmlns='http://www.w3.org/2000/svg'> | ||
| <rect width='32' height='32' rx='6' fill='white' /> | ||
| <g transform='translate(6 6.19) scale(0.16624)'> | ||
| <path | ||
| d='M34.0674 88.4993C34.0674 104.791 58.4191 117.999 77.2336 117.999C87.2434 117.999 96.2453 114.261 102.478 108.308L77.2336 88.4993H34.0674Z' | ||
| fill='black' | ||
| /> | ||
| <path | ||
| d='M0 88.4993C0 104.791 15.253 117.999 34.0677 117.999V58.9997C15.253 58.9997 0 72.2071 0 88.4993Z' | ||
| fill='black' | ||
| /> | ||
| <path | ||
| d='M77.2339 29.4999V81.1477H111.302V29.5736C111.267 13.1861 96.0292 -0.0400894 77.2339 7.20269e-05H33.737V0.00335371C15.075 0.158262 0 13.3042 0 29.4999V58.9997H34.0677V29.4999H77.2339' | ||
| fill='black' | ||
| /> | ||
| <path d='M83.1602 86.5171L120.31 114.843V86.5171H83.1602Z' fill='black' /> | ||
| </g> | ||
| </svg> |
There was a problem hiding this comment.
QuartrIcon hardcodes
fill='black' instead of fill='currentColor'
Every other icon in this file renders its paths with fill='currentColor' so they inherit the parent's text color — in BlockInfoCard that's text-white, which makes them appear as white silhouettes on the colored card background. The new QuartrIcon instead embeds a self-contained white rounded rectangle with black paths. On Quartr's color="#000000" card the icon will render as a white boxed app-icon floating inside a black panel rather than a clean white monochrome glyph like every other integration icon. If the card background ever changes (or the icon is used in a different listing context), the hardcoded colors will not adapt.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| color="${bgColor || '#F5F5F5'}" | ||
| color="${bgColor || '#F5F5F5'}"${url ? `\n name="${name}"\n href="${url}"` : ''} | ||
| /> | ||
|
|
There was a problem hiding this comment.
MDX JSX attributes inject
name and url without escaping
If a block's name or url value ever contains a double-quote ("), the generated MDX attribute will be syntactically broken — e.g. name="Google \"Foo\" Search" or href="https://example.com/?q=\"bar\"" would both corrupt the JSX attribute boundary and prevent the page from rendering. The values are developer-controlled today so the risk is low, but adding simple escaping (value.replace(/"/g, '"')) would make the template resilient to future additions.
- Extract `BlockMeta.url` in generate-docs and project it into integrations.json - Render an outbound 'Visit' link on generated integration doc pages via BlockInfoCard - Add a 'Visit' CTA and a vendor `about` entity reference in the landing JSON-LD for SEO - Regenerate docs (icons sync, per-page BlockInfoCard props)
2fa2183 to
0d54af8
Compare
|
@greptile review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 0d54af8. Configure here.
Greptile SummaryThis PR surfaces
Confidence Score: 4/5Safe to merge. The Visit links and JSON-LD additions are isolated, opt-in (only shown when url is present), and the docs generation script is not run at runtime. The core rendering changes in block-info-card.tsx and page.tsx are clean and correct. The generate-docs.ts script has two related fragility points: the string-extraction regex lacks a word boundary (a scripts/generate-docs.ts — the extractStringPropertyFromContent regex and the MDX attribute template string warrant a quick fix before new block metadata containing URL-suffixed properties is added. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["Block source file\n(*BlockMeta.url)"] --> B["generate-docs.ts\nextractBlockMetaBody\nextractUrlFromBlockMeta"]
B --> C["integrations.json\n{url: 'https://...'}"]
B --> D["MDX file\n<BlockInfoCard href='...' name='...' />"]
C --> E["Integration type\n(types.ts url?: string)"]
E --> F["[slug]/page.tsx\nwebsiteUrl"]
F --> G["JSON-LD about\n{Organization, url}"]
F --> H["Visit CTA button\n(outbound anchor)"]
D --> I["BlockInfoCard\nVisit link (docs site)"]
|
| <BlockInfoCard | ||
| type="${type}" | ||
| color="${bgColor || '#F5F5F5'}" | ||
| color="${bgColor || '#F5F5F5'}"${url ? `\n name="${name}"\n href="${url}"` : ''} |
There was a problem hiding this comment.
The
name and url values are interpolated directly into a JSX attribute string without escaping double-quote characters. A block whose name contains " or a URL with an embedded " would produce malformed JSX in the generated MDX, breaking the doc page for that integration.
| color="${bgColor || '#F5F5F5'}"${url ? `\n name="${name}"\n href="${url}"` : ''} | |
| color="${bgColor || '#F5F5F5'}"${url ? `\n name="${name.replace(/"/g, '"')}"\n href="${url.replace(/"/g, '%22')}"` : ''} |
| <svg {...props} viewBox='0 0 32 32' fill='none' xmlns='http://www.w3.org/2000/svg'> | ||
| <rect width='32' height='32' rx='6' fill='white' /> | ||
| <g transform='translate(6 6.19) scale(0.16624)'> | ||
| <path | ||
| d='M34.0674 88.4993C34.0674 104.791 58.4191 117.999 77.2336 117.999C87.2434 117.999 96.2453 114.261 102.478 108.308L77.2336 88.4993H34.0674Z' | ||
| fill='black' | ||
| /> | ||
| <path | ||
| d='M0 88.4993C0 104.791 15.253 117.999 34.0677 117.999V58.9997C15.253 58.9997 0 72.2071 0 88.4993Z' | ||
| fill='black' | ||
| /> | ||
| <path | ||
| d='M77.2339 29.4999V81.1477H111.302V29.5736C111.267 13.1861 96.0292 -0.0400894 77.2339 7.20269e-05H33.737V0.00335371C15.075 0.158262 0 13.3042 0 29.4999V58.9997H34.0677V29.4999H77.2339' | ||
| fill='black' | ||
| /> | ||
| <path d='M83.1602 86.5171L120.31 114.843V86.5171H83.1602Z' fill='black' /> | ||
| </g> | ||
| </svg> | ||
| ) | ||
| } |
There was a problem hiding this comment.
QuartrIcon ignores color context
The new icon embeds a hard-coded fill='white' background rect and fill='black' paths, so it no longer responds to text-white or any CSS color applied by the parent. Every other icon in the file uses fill='currentColor', which lets the caller (e.g. BlockInfoCard's size-10 text-white) control the fill. On a dark-mode docs site or any non-white background the icon will render as a white square with a black logo regardless of the surrounding theme.
Mark the card not-prose and render the visit link as a bordered pill (no underline, normal weight, muted) so it reads as an intentional button instead of inheriting fumadocs' bold underlined prose-link styling.
|
@greptile review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 73a538f. Configure here.
Summary
BlockMeta.url(external-service homepage, e.g.exa.ai) ingenerate-docs.tsand project it intointegrations.jsonBlockInfoCard(design-system tokens,rel="noopener noreferrer")SoftwareApplication.sameAsentity link in the JSON-LD — strengthens topical authority for SEOBlockInfoCardprops + icons sync (picked up the newer Quartr logo that the docs copy had drifted from)Type of Change
Testing
Tested manually — ran
bun run generate-docs, verified 207 integrations carry aurl, spot-checked MDX (with + without url),tsc --noEmit,bun run lint, andbun run check:api-validationall pass.Checklist