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(metadata): centralize site copy and add dynamic social share images

+118 -6
+2 -3
app/components/Hero.tsx
··· 1 1 "use client"; 2 2 3 + import { siteTagline } from "@/lib/site"; 3 4 import { useState, useEffect } from "react"; 4 5 import Image from "next/image"; 5 6 import GrainedBlob from "./GrainedBlob"; ··· 157 158 {/* Sub-heading + body */} 158 159 <div className="lg:col-span-5 lg:pl-[calc(100%/5)]"> 159 160 <FadeIn delay={500}> 160 - <h2 className="mb-3"> 161 - A social network that belongs to the people. 162 - </h2> 161 + <h2 className="mb-3">{siteTagline}.</h2> 163 162 </FadeIn> 164 163 <FadeIn delay={600}> 165 164 <p className="section-copy lg:pl-[calc(100%/4)] text-right">
+13 -3
app/layout.tsx
··· 1 1 import type { Metadata } from "next"; 2 + import { siteDescription, siteTitle } from "@/lib/site"; 2 3 import { Instrument_Serif, Instrument_Sans } from "next/font/google"; 3 4 import { Analytics } from "@vercel/analytics/next"; 4 5 import { SpeedInsights } from "@vercel/speed-insights/next"; ··· 17 18 weight: ["400", "500", "600", "700"], 18 19 }); 19 20 21 + /** Canonical site for metadata (OG, etc.). Override via NEXT_PUBLIC_SITE_URL if needed. */ 22 + const siteUrl = 23 + process.env.NEXT_PUBLIC_SITE_URL ?? 24 + (process.env.VERCEL_URL 25 + ? process.env.VERCEL_ENV === "production" 26 + ? "https://eny.social" 27 + : `https://${process.env.VERCEL_URL}` 28 + : "http://localhost:3000"); 29 + 20 30 export const metadata: Metadata = { 21 - title: "eny.social — A social network that belongs to the people", 22 - description: 23 - "No algorithms shaping your reality. Decentralized. Built and hosted in Europe. Starting in Offenbach.", 31 + metadataBase: new URL(siteUrl), 32 + title: siteTitle, 33 + description: siteDescription, 24 34 }; 25 35 26 36 export default function RootLayout({
+6
app/opengraph-image.tsx
··· 1 + export { 2 + default, 3 + alt, 4 + size, 5 + contentType, 6 + } from "../lib/social-share-image";
+6
app/twitter-image.tsx
··· 1 + export { 2 + default, 3 + alt, 4 + size, 5 + contentType, 6 + } from "../lib/social-share-image";
+10
lib/site.ts
··· 1 + /** Site copy shared by layout metadata, OG image, and pages. */ 2 + 3 + export const siteName = "eny.social"; 4 + 5 + export const siteTagline = "A social network that belongs to the people"; 6 + 7 + export const siteDescription = 8 + "No algorithms shaping your reality. Decentralized. Built and hosted in Europe. Starting in Offenbach."; 9 + 10 + export const siteTitle = `${siteName} — ${siteTagline}`;
+81
lib/social-share-image.tsx
··· 1 + import { ImageResponse } from "next/og"; 2 + import { siteDescription, siteName, siteTagline, siteTitle } from "@/lib/site"; 3 + 4 + export const alt = siteTitle; 5 + 6 + export const size = { 7 + width: 1200, 8 + height: 630, 9 + }; 10 + 11 + export const contentType = "image/png"; 12 + 13 + export default async function Image() { 14 + return new ImageResponse( 15 + ( 16 + <div 17 + style={{ 18 + height: "100%", 19 + width: "100%", 20 + display: "flex", 21 + flexDirection: "column", 22 + alignItems: "flex-start", 23 + justifyContent: "center", 24 + padding: "72px 80px", 25 + background: 26 + "linear-gradient(135deg, #fef9f4 0%, #fbd1a2 42%, #7dcfb6 100%)", 27 + fontFamily: 28 + 'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', 29 + }} 30 + > 31 + <div 32 + style={{ 33 + display: "flex", 34 + flexDirection: "column", 35 + alignItems: "flex-start", 36 + }} 37 + > 38 + <span 39 + style={{ 40 + fontSize: 56, 41 + fontWeight: 700, 42 + letterSpacing: -2, 43 + color: "#231f1c", 44 + lineHeight: 1.1, 45 + }} 46 + > 47 + {siteName} 48 + </span> 49 + <span 50 + style={{ 51 + marginTop: 24, 52 + fontSize: 36, 53 + fontWeight: 600, 54 + letterSpacing: -1, 55 + color: "#1d4e89", 56 + maxWidth: 900, 57 + lineHeight: 1.25, 58 + }} 59 + > 60 + {siteTagline} 61 + </span> 62 + <span 63 + style={{ 64 + marginTop: 32, 65 + fontSize: 22, 66 + fontWeight: 500, 67 + color: "#231f1c", 68 + opacity: 0.88, 69 + lineHeight: 1.4, 70 + }} 71 + > 72 + {siteDescription} 73 + </span> 74 + </div> 75 + </div> 76 + ), 77 + { 78 + ...size, 79 + } 80 + ); 81 + }