From def67cc50476737698af2ee35b13b1a34827f28e Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Tue, 26 May 2026 14:26:07 -0400 Subject: [PATCH] Add social preview metadata --- .../assets/policyengine-social-preview.png | Bin 0 -> 21136 bytes app/website.html | 8 +++- .../src/__tests__/layout/root-layout.test.tsx | 40 ++++++++++++++++++ website/src/app/layout.tsx | 30 ++++++++++++- 4 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 app/public/assets/policyengine-social-preview.png create mode 100644 website/src/__tests__/layout/root-layout.test.tsx diff --git a/app/public/assets/policyengine-social-preview.png b/app/public/assets/policyengine-social-preview.png new file mode 100644 index 0000000000000000000000000000000000000000..e39ae2ac41e6bcfc00936d495a2d498baca0751f GIT binary patch literal 21136 zcmeHPX;@R|w#Lv<1uUG3MMS_;PsM=>f{KC=YOB4)!;8qcBGx~-;_h&Za<=;qWT8;Hz|v> zX}^lfY?Za&e6=Mgp}SF3)#e#&)I0o@yH-}5bLBeotf*SY_;tVR`~KpRgQ@E?4#urH zn99kT^(v*Lm2-?fstn+&Ir<3<;rfYsx=cz>x^lsNmydHHu zDo^n6rf4YN)}n@G#T6ZGWLa<@(puVK2>5lgV4qnZ8XX@AEDryxKPdz)%6P*4+sU}33c1ktL%uwk~vUsJf^d@Pvrz(S< zET}7UlPvenR^}#I_E$m(8ASRsKnQBLS?^10hMA9$pV#VL+8pIBs(;YaLvo8NVGKU$ zyJXFs)%Idoc({0~`p6jortA>%WB~6+dE4MB(=iwuJa_*br<(Y8p?m( zCI@x3>&lrLCf9bFAQ)qzs(>sJ{T8@8-E6jmU--()3j`Pg)( zX@u*!x$MpACIXLpU&+udwd^$@WJET$Z$QZK|&aV49!FMxd{M^C~#XKj_#RlT`1rAT7 zPnFF4p0o9Nrex?P!B&vh?v@>nTPV>~6auHO>&>H^L|@qr5cYe$4a5wd0p;bX!;OuC zbM7lSuI)bA=P{QHZ0>|gYL8T{=Xi=cPpPNl0#7SI{6=%tG1RQ%lD{}#Si6Tq%jb^p zcRjWZqPDdCOj{_E{((5pqNNk}|6+2qIR23g{<@Oet$*HGP*czt!%gZ0MSGC`Bo{6P`4v}k+ zsJlJiSr2p7NMdMbMtgzt49r!MMBc;rs>H3BO7D;u*c|g8zQ12Gukrg9%x!cJCJ{n{ zhRb`_$A;96YZ>?4mlW>9{luklQbD zug0e>S5F_dP}EMduX-h;^^!$qC&l}G7r5=9j*HM+QI^@QE3>0|UN@Nz3E^4saom1u ziA{P9P1NL1ieB@cn&0t^d%PTu_~Xj%t(e-VZ{k7(i0rvljAaPV`ILyB21~ch&R_k1 zoQ{24k;tfq{COks6t?ulhCFo#sKX7-POhb^q7%8EHb+Q>e1$Bm--6wbQdj^41H~6==< zuE5gt(O0+0Wj~}wRM`e|f?l>ZW#{G)3)Y&N7T)= zz*KyIEpJHz=?D2bET$Q7deS~3I&#i(vPBzg=PaH85es#Q&EpJ^w z=u-a3YvcA66KpbX1;33{$975zwY3RLoQ0`ROZTAOM_uB5v#k97G4W!{(9RuoBh?O) zPqqboGJ*7b5i|*lmv`Zx2bD~>wm_gPPLB1(CJ+_fpxF36y0}cxt zY`-|c#4-_}Vhg?z#6(JL(_#AwFDMd5=Q!%clKakb-c+Qdyb`=RYZ_idJK{6Z zmD6Z_49QdbLP1i9-xhIxfA4SD@MIp{aox>Zjd|X=oM|-?zP9{YmzN|cr!Ma(#k9Y; zC=O!Y!~9da;RrB!0O+yc(j5DO1?(!8jip;~@pbGQ11<`Sn5D2huPmkVRf+y;wJ0BQ~-il zA-2AUn-EW+`OqI@84}=FCmRtbR@{B_z(hD!&@gg6zH($MW|>l7&fO6~uyr%cnQ&#k zw79KdSrZ!Fu3#Ehx2T*k@Z3MJ8WV5b>m>D>O8j#DYUa21+`ueN53&R=9{tFvX$p0l zuvF>~fuNBwlyVr`$W zgdHGvSJ)R4mIEtr(^(%&N*z3MN2j|{Xxp!wtJY^=*MH)`H%}uEw|d*g`}}}ire-nh z1>O3-wK~Om7MlvSYNwU(h%C)JlLD)J|k3;m{XPKk7-#qL|7?JdAEwrT|A?YdvD_BuqawKLyVTS>oCR=$uYm=?pi+Ps=?6*= zgNXuyMF^6{pc%z_7lwgF{4mD?q~JP=+K1&V-NRf0Vrd^_8kORBhj>+rLn)34oaIrG zuDdx>SIy@koe#(QBR@qxV%IZSG;#S`0~t;DubtqQikX#C3m^=g`11w$=b4`_>|ZUD6vA47U! zQx0v61B&hpwFjtWX*}%3Eo7Wrte)OQlD1Zsm6@Z)qIl3H>53w6BF>L^zUWyl(=Q^Y zP!AsZykf-XStD>|(un6qY>71k&`H)p`X|h*+fnmN2zd}gzU`!L(o#{6kJEMOIV@NX zoHTu-Vq_{?UmBN-STI&J{3#T4x4DxLM!a@O32M+tuC%q(D=WXxvE$)NYn zD3lHavcn9>+W8+NtsW%5jZIjYv7pCdTW5@q>EGLpE7LF$JRl_i13fl#);Lv~OkR6~ zsZ3}*I-J*MP4y%%ZuFD!V@yTZf z-Qmc`%iI)_oY9MX&XmBjIh?uc7x{+G^eYsuC7Y7u59s7Z=qjEX?Nus-m>mIFz3fFrVhW-iVAkaKBzlcn$;=>LORVoeV*qsG^zxI~!J#4hvrXmWJ?mG&NWUt6=fz$Cf$^0c2uyS%9v#VL_KVK4-H|nAF=GSd)O`qm#RC8~ zV0|K*_BfvgIMn;Hbi_n^J~E6$YuN*4uH&Mf5^(CG?7MVaD879p4bVEht`e$v`PBOj zJp=?F2N2Au+hs~0q5y`ZMM_6t>@Isioe&Ze0U>k)asIjb>0WNcU~2WiW}-0f3HM7x z5?&5KD#%CmuX!N=76$+}+&e6f*&&)w?+;xwQ`%9B`~@bK`nTJ{e(k7N%=T@&0CfW1 zxyFgwBKVAPA4ys9U&6qK{Cq)j+#~>>8UQ}6k_`B`G;S)hSfclXR2AQR2NEsu79vOh zAM^N{>n_0fx-PB+d<=WXa1$~|b>QBTQOE$oLaGkpIb3H@K&?i)Qdml1{qZfUg~7~j zi?lC@HKM>2V{>=S&d#=bv<4~m+oO;6$>!?RL|Yjra9A&>YPIfs`n^H?bJMOBb4C_f zC}xQ2!PUo(=@?AS-NkjoJ8$Bvr-w*T^Khf2qo!FhbD!5coFw|_%fQqi2y(^C_A2P) zyG5u{*6djYRL-U(aPbj+MZ+C6aA*c~UfRWXNmCTQ{f}icJ_fh2Az3j~S1}h=m@@6` zp$^XN%3~G_d=Q3sJWu#fAysHY$JQL*c9;!zxhimCxp)!r81 z7P1+N+oMMMAok3o#{nOL;#pDWsqDzAZp8WY+f!vhQPWKOAewQ|^j`u5M@f^0Qs_#d zgPm&r#VtK~6?GuoX(vJ4Sx9KwP2mh{U8Y@^c^%WMWGu)5JPL;-U*CgEs|u`h4ZOmQ z`p_yJm*BdEbRaTC^4LJXm_Ws8EYL-O(P(Hu`Tr=133$rc3<*4GC2dZVdE9AIfH(V| zEySMLwL@RX4q(8PaM`;7B)$j$S+ZZItSUdWN)w5U9sK}*+D_7@NpBjNL`9v(M1sI3 z;!z<$Ji!_1KD2j0e@Np*hP(VUqK-==!e`-~(L>}qE*l=Y$k>tPe+OwGUjg{>$Ya(N zDaia5I!I%uH?3v@qN8Vr0NNA%TRK*LIs+EqA3ZmfpI%f?_fZ?3a%n8iGQIo&c*&;a z!8Q}LrLinK#EmFi@v`kBM1FRcp$UafBlAGiuC~zbA@7#O+GGWnE06J^tFDcuiT|T6 zoF-3)FArUHA(SQ?ThAN-qVv5iAcFAJUn0wMkSbx1(PvLdNdfA#-2mzF&ao^F6N2$@ zf>eX2-;QBpn66I&hzS}8_{ngR&bw1?A`9MD) z9!nI=Duux!Wgya@tBr!GGs(&w4t z0L9*@_dTw-#ElxwWh)k-PFP3_sWQmxsLm+rxN~wolqwKV6q=cFdKrptpQMI(T8k$a z@0=ex&X~Kjv|4KMPU{xMX;O!zo;+&6#M$*8sLqR2tI@G}&<+vH4PyrSGzL;^RhLS; z6pF(d=u^!d`iRv;A4H1@AtaW+2;QKYn`78@=x`x7s4a|!uN8)M~&ZL|#upl*>A zfFQ{?KTMWMp5gO2u34lQ;vf*xYJ!T}uFo1%(NKa)b z=mWu<%>rsGr%blySJ+4ls~KLg1(3bDvQ41hHt|-P{gqpgR@_Q0;GO@}h6L5k za0iUaS@z_ad5VR2(*62@6||h-7yaF&^}lH%4Pgfqp$=F)sU%E_#ozfcBN|=Xz4MXs z{V&p>13yq<3<*PuKmX-k(}RNIvd*5|UYat!(3w|hMT(={qn3i$jM9o^a0Fcz$^Ifm zI7HYx X@PXPFKJbc3m9?uKzqz@Jc;bHmuChhY literal 0 HcmV?d00001 diff --git a/app/website.html b/app/website.html index 892ff441d..3f0308fd9 100644 --- a/app/website.html +++ b/app/website.html @@ -32,8 +32,11 @@ /> + + + @@ -48,8 +51,9 @@ /> +
diff --git a/website/src/__tests__/layout/root-layout.test.tsx b/website/src/__tests__/layout/root-layout.test.tsx new file mode 100644 index 000000000..d7b7fc463 --- /dev/null +++ b/website/src/__tests__/layout/root-layout.test.tsx @@ -0,0 +1,40 @@ +import { describe, expect, test } from "vitest"; +import { metadata } from "../../app/layout"; + +const SOCIAL_PREVIEW_IMAGE = "/assets/policyengine-social-preview.png"; + +describe("RootLayout metadata", () => { + test("includes default social preview metadata", () => { + expect(metadata.openGraph).toEqual( + expect.objectContaining({ + title: "PolicyEngine", + description: metadata.description, + siteName: "PolicyEngine", + type: "website", + images: [ + { + url: SOCIAL_PREVIEW_IMAGE, + width: 1200, + height: 630, + alt: "PolicyEngine", + }, + ], + }), + ); + + expect(metadata.twitter).toEqual( + expect.objectContaining({ + card: "summary_large_image", + site: "@ThePolicyEngine", + title: "PolicyEngine", + description: metadata.description, + images: [ + { + url: SOCIAL_PREVIEW_IMAGE, + alt: "PolicyEngine", + }, + ], + }), + ); + }); +}); diff --git a/website/src/app/layout.tsx b/website/src/app/layout.tsx index 41aaa2447..5382aaf85 100644 --- a/website/src/app/layout.tsx +++ b/website/src/app/layout.tsx @@ -5,6 +5,14 @@ import { SpeedInsights } from "@vercel/speed-insights/next"; import "./globals.css"; const GA_MEASUREMENT_ID = "G-2YHG89FY0N"; +const SITE_DESCRIPTION = + "Free, open-source tools to understand tax and benefit policies. Calculate your taxes and benefits, or analyze policy reforms."; +const SOCIAL_PREVIEW_IMAGE = { + url: "/assets/policyengine-social-preview.png", + width: 1200, + height: 630, + alt: "PolicyEngine", +}; export const metadata: Metadata = { metadataBase: new URL("https://www.policyengine.org"), @@ -12,11 +20,29 @@ export const metadata: Metadata = { template: "%s | PolicyEngine", default: "PolicyEngine", }, - description: - "Free, open-source tools to understand tax and benefit policies. Calculate your taxes and benefits, or analyze policy reforms.", + description: SITE_DESCRIPTION, icons: { icon: "/favicon.svg", }, + openGraph: { + title: "PolicyEngine", + description: SITE_DESCRIPTION, + siteName: "PolicyEngine", + type: "website", + images: [SOCIAL_PREVIEW_IMAGE], + }, + twitter: { + card: "summary_large_image", + site: "@ThePolicyEngine", + title: "PolicyEngine", + description: SITE_DESCRIPTION, + images: [ + { + url: SOCIAL_PREVIEW_IMAGE.url, + alt: SOCIAL_PREVIEW_IMAGE.alt, + }, + ], + }, }; export default function RootLayout({