atproto pds in zig pds.zat.dev
pds atproto
24

Configure Feed

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

http: add link preview metadata

zzstoatzz (May 28, 2026, 12:07 PM -0500) 74bb383f 1cc67103

+57 -2
+29 -1
src/http/landing/mod.zig
··· 86 86 const pulse = try renderPulse(allocator, recent_records); 87 87 const public_url = config.publicUrl(); 88 88 const public_host = try escapeHtml(allocator, displayHost(public_url)); 89 + const public_url_html = try escapeHtml(allocator, public_url); 90 + const preview_image = try escapeHtml(allocator, try std.fmt.allocPrint(allocator, "{s}/favicon.svg", .{public_url})); 89 91 90 92 return std.fmt.allocPrint(allocator, 91 93 \\<!doctype html> ··· 96 98 \\ <meta name="color-scheme" content="dark light"> 97 99 \\ <title>zds</title> 98 100 \\ <meta name="description" content="an at protocol personal data server"> 101 + \\ <link rel="canonical" href="{s}/"> 102 + \\ <meta property="og:type" content="website"> 103 + \\ <meta property="og:site_name" content="zds"> 104 + \\ <meta property="og:title" content="{s}"> 105 + \\ <meta property="og:description" content="an at protocol personal data server"> 106 + \\ <meta property="og:url" content="{s}/"> 107 + \\ <meta property="og:image" content="{s}"> 108 + \\ <meta name="twitter:card" content="summary"> 109 + \\ <meta name="twitter:title" content="{s}"> 110 + \\ <meta name="twitter:description" content="an at protocol personal data server"> 111 + \\ <meta name="twitter:image" content="{s}"> 99 112 \\ <link rel="icon" href="/favicon.svg" type="image/svg+xml"> 100 113 \\ <style>{s}</style> 101 114 \\</head> ··· 165 178 \\ <script>{s}</script> 166 179 \\</body> 167 180 \\</html> 168 - , .{ assets.css, signal.style, public_host, signal.html, pulse, accounts.written(), collection_items.written(), assets.script }); 181 + , .{ 182 + public_url_html, 183 + public_host, 184 + public_url_html, 185 + preview_image, 186 + public_host, 187 + preview_image, 188 + assets.css, 189 + signal.style, 190 + public_host, 191 + signal.html, 192 + pulse, 193 + accounts.written(), 194 + collection_items.written(), 195 + assets.script, 196 + }); 169 197 } 170 198 171 199 fn renderPulse(allocator: std.mem.Allocator, records: []const store.RecentRecord) ![]const u8 {
+28 -1
src/internal/passkeys.zig
··· 55 55 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); 56 56 defer arena.deinit(); 57 57 const allocator = arena.allocator(); 58 + const public_url = config.publicUrl(); 59 + const public_host = try htmlEscape(allocator, displayHost(public_url)); 60 + const security_url = try htmlEscape(allocator, try std.fmt.allocPrint(allocator, "{s}/security", .{public_url})); 61 + const preview_image = try htmlEscape(allocator, try std.fmt.allocPrint(allocator, "{s}/favicon.svg", .{public_url})); 58 62 const body = try std.fmt.allocPrint(allocator, 59 63 \\<!doctype html> 60 64 \\<html lang="en"> ··· 62 66 \\<meta charset="utf-8"> 63 67 \\<meta name="viewport" content="width=device-width, initial-scale=1"> 64 68 \\<title>zds security</title> 69 + \\<meta name="description" content="manage passkeys for accounts hosted on {s}"> 70 + \\<link rel="canonical" href="{s}"> 71 + \\<meta property="og:type" content="website"> 72 + \\<meta property="og:site_name" content="zds"> 73 + \\<meta property="og:title" content="zds security"> 74 + \\<meta property="og:description" content="manage passkeys for accounts hosted on {s}"> 75 + \\<meta property="og:url" content="{s}"> 76 + \\<meta property="og:image" content="{s}"> 77 + \\<meta name="twitter:card" content="summary"> 78 + \\<meta name="twitter:title" content="zds security"> 79 + \\<meta name="twitter:description" content="manage passkeys for accounts hosted on {s}"> 80 + \\<meta name="twitter:image" content="{s}"> 81 + \\<link rel="icon" href="/favicon.svg" type="image/svg+xml"> 65 82 \\<style> 66 83 \\:root{{color-scheme:dark;--bg:#070807;--panel:#101510;--line:#263326;--text:#f1f2ec;--muted:#a7a299;--accent:#8fb0ff;--green:#37c978;--field:#101410;--bad:#ffb4a8}} 67 84 \\@media (prefers-color-scheme:light){{:root{{--bg:#f6f4ed;--panel:#fffdf7;--line:#d8d0c0;--text:#161412;--muted:#625c53;--accent:#315dcb;--green:#1b7340;--field:#fffaf1;--bad:#9f1d1d;color-scheme:light}}}} ··· 107 124 \\<script>{s}</script> 108 125 \\</body> 109 126 \\</html> 110 - , .{ try htmlEscape(allocator, displayHost(config.publicUrl())), securityScript }); 127 + , .{ 128 + public_host, 129 + security_url, 130 + public_host, 131 + security_url, 132 + preview_image, 133 + public_host, 134 + preview_image, 135 + public_host, 136 + securityScript, 137 + }); 111 138 try respondHtml(request, .ok, body); 112 139 } 113 140