The source code for our eny.social landing page, which is mirrored in a different repository as part of the CI setup. eny.social
social-network eny local-first
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(layout): do more shapy stuff

Sam Sauer 02ec7c39 498655f8

+36 -40
+1 -1
app/components/GrainedBlob.tsx
··· 59 59 result="noise1Clipped" 60 60 /> 61 61 <feFlood 62 - floodColor="color-mix(in srgb, var(--cotton-candy) 93%, black)" 62 + floodColor="color-mix(in srgb, var(--cotton-candy) 75%, #DF6666)" 63 63 result="color1Flood" 64 64 /> 65 65 <feComposite
+1 -12
app/components/Hero.tsx
··· 99 99 </clipPath> 100 100 </defs> 101 101 </svg> 102 - {/* Monte Carlo accent blob behind photo */} 103 - <svg 104 - className="absolute -bottom-8 -left-8 h-48 w-48 opacity-40" 105 - viewBox="0 0 200 200" 106 - fill="none" 107 - > 108 - <path 109 - d="M150 100C150 140 130 170 100 180C70 190 30 160 20 120C10 80 40 30 80 20C120 10 150 50 150 100Z" 110 - fill="var(--monte-carlo)" 111 - /> 112 - </svg> 113 - {/* Full-size blob-masked photo */} 102 + {/* Full-size blob-masked photo */} 114 103 <div 115 104 // className="relative w-[130%] -mr-[30%] lg:w-[170%] lg:-mr-[70%] lg:[transform:translate(2%,-20%)]" 116 105 className="relative w-[130%] -mr-[30%] lg:w-[170%] aspect-square lg:-mr-[70%] lg:[transform:translate(2%,-20%)]"
+25 -21
app/components/RememberWhen.tsx
··· 3 3 export default function RememberWhen() { 4 4 return ( 5 5 <section className="relative px-6 py-24"> 6 - {/* SVG clip path definition */} 6 + {/* SVG clip path definitions — all shapes are 350x400 */} 7 7 <svg className="clip-svg" xmlns="http://www.w3.org/2000/svg"> 8 8 <defs> 9 - <clipPath id="custom-mask" clipPathUnits="objectBoundingBox"> 9 + {/* Original shape (image 1) */} 10 + <clipPath id="mask-1" clipPathUnits="objectBoundingBox"> 10 11 <path 11 12 transform="scale(0.002857, 0.0025)" 12 13 d="M1.20005e-05 150L9.81496e-06 200L0 250C-3.62117e-06 332.843 67.1573 400 150 400H250C305.228 400 350 355.228 350 300C350 244.772 305.228 200 250 200C305.228 200 350 155.228 350 100C350 44.7715 305.229 6.78525e-06 250 4.37114e-06L150 0C67.1573 -3.62117e-06 1.56217e-05 67.1573 1.20005e-05 150Z" 13 14 /> 14 15 </clipPath> 16 + {/* A-shape (image 2) */} 17 + <clipPath id="mask-2" clipPathUnits="objectBoundingBox"> 18 + <path 19 + transform="scale(0.002857, 0.0025)" 20 + d="M200 2.18557e-06L175 0L150 1.30732e-05C67.1573 5.83088e-06 2.14485e-05 67.1573 1.42062e-05 150L0 312.5C-4.2247e-06 360.825 39.1751 400 87.5 400C135.825 400 175 360.825 175 312.5C175 360.825 214.175 400 262.5 400C310.825 400 350 360.825 350 312.5V150C350 67.1573 282.843 9.42791e-06 200 2.18557e-06Z" 21 + /> 22 + </clipPath> 23 + {/* U-shape (image 3) */} 24 + <clipPath id="mask-3" clipPathUnits="objectBoundingBox"> 25 + <path 26 + transform="scale(0.002857, 0.0025)" 27 + d="M150 400H175H200C282.843 400 350 332.843 350 250V87.5C350 39.1751 310.825 0 262.5 0C214.175 0 175 39.1751 175 87.5C175 39.1751 135.825 0 87.5 0C39.1751 0 0 39.1751 0 87.5V250C0 332.843 67.1573 400 150 400Z" 28 + /> 29 + </clipPath> 15 30 </defs> 16 31 </svg> 17 32 18 - {/* Decorative blob */} 19 - <svg 20 - className="absolute -left-16 top-0 h-64 w-64 opacity-15" 21 - viewBox="0 0 300 300" 22 - fill="none" 23 - > 24 - <path 25 - d="M200 150C200 210 170 260 130 270C90 280 40 240 20 180C0 120 40 50 100 30C160 10 200 70 200 150Z" 26 - fill="var(--monte-carlo)" 27 - /> 28 - </svg> 29 33 30 34 <div className="relative mx-auto max-w-4xl text-center"> 31 35 <SectionIntroLabel>Remember when</SectionIntroLabel> ··· 38 42 {/* Three masked photos */} 39 43 <div className="mt-12 flex items-center justify-center gap-6 md:gap-10"> 40 44 {[ 41 - "/images/pexels-kindelmedia-7148409 1.png", 42 - "/images/pexels-shvets-production-7533377 1.png", 43 - "/images/pexels-guilhermealmeida-1858175.png", 44 - ].map((src, i) => ( 45 + { src: "/images/pexels-kindelmedia-7148409 1.png", mask: "mask-1" }, 46 + { src: "/images/pexels-shvets-production-7533377 1.png", mask: "mask-2" }, 47 + { src: "/images/pexels-guilhermealmeida-1858175.png", mask: "mask-3" }, 48 + ].map((item, i) => ( 45 49 <div 46 50 key={i} 47 - className="masked-container w-[197px] h-[225px] md:w-[263px] md:h-[300px]" 51 + className="relative w-[197px] h-[225px] md:w-[263px] md:h-[300px] overflow-hidden" 52 + style={{ clipPath: `url(#${item.mask})` }} 48 53 > 49 54 <img 50 - src={src} 55 + src={item.src} 51 56 alt="" 52 - className="absolute inset-0 h-full w-full object-cover" 53 - style={{ width: "140%", height: "140%", top: "-20%", left: "-20%" }} 57 + className="h-full w-full object-cover object-center" 54 58 /> 55 59 </div> 56 60 ))}
+3 -6
app/globals.css
··· 236 236 } 237 237 238 238 .masked-container img { 239 - width: 140%; 240 - height: 140%; 239 + width: 100%; 240 + height: 100%; 241 241 object-fit: cover; 242 - position: absolute; 243 - top: -20%; 244 - left: -20%; 245 - animation: drift 4s ease-in-out forwards; 242 + object-position: center; 246 243 } 247 244 248 245 @keyframes drift {
+3
public/shapes/a-shape.svg
··· 1 + <svg width="350" height="400" viewBox="0 0 350 400" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M200 2.18557e-06L175 0L150 1.30732e-05C67.1573 5.83088e-06 2.14485e-05 67.1573 1.42062e-05 150L0 312.5C-4.2247e-06 360.825 39.1751 400 87.5 400C135.825 400 175 360.825 175 312.5C175 360.825 214.175 400 262.5 400C310.825 400 350 360.825 350 312.5V150C350 67.1573 282.843 9.42791e-06 200 2.18557e-06Z" fill="#FBD1A2"/> 3 + </svg>
+3
public/shapes/u-shape.svg
··· 1 + <svg width="350" height="400" viewBox="0 0 350 400" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 + <path d="M150 400H175H200C282.843 400 350 332.843 350 250V87.5C350 39.1751 310.825 0 262.5 0C214.175 0 175 39.1751 175 87.5C175 39.1751 135.825 0 87.5 0C39.1751 0 0 39.1751 0 87.5V250C0 332.843 67.1573 400 150 400Z" fill="#00B2CA"/> 3 + </svg>