A vibe coded tangled fork which supports pijul.
at c4216345ee957971bb3ac156ffba8a3a7c20a6e6 524 lines 26 kB view raw
1{{ define "title" }}tangled &middot; tightly-knit social coding{{ end }} 2 3{{ define "extrameta" }} 4 <!-- Open Graph Meta Tags --> 5 <meta property="og:title" content="tangled · tightly-knit social coding" /> 6 <meta property="og:type" content="website" /> 7 <meta property="og:url" content="https://tangled.org" /> 8 <meta property="og:description" content="The next-generation social coding platform." /> 9 <meta property="og:image" content="https://assets.tangled.network/tangled_og.png" /> 10 <meta property="og:image:width" content="1200" /> 11 <meta property="og:image:height" content="630" /> 12 13 <!-- Twitter Card Meta Tags --> 14 <meta name="twitter:card" content="summary_large_image" /> 15 <meta name="twitter:title" content="Tangled" /> 16 <meta name="twitter:description" content="The next-generation social coding platform." /> 17 <meta name="twitter:image" content="https://assets.tangled.network/tangled_og.png" /> 18 19 <!-- Additional SEO --> 20 <meta name="description" content="The next-generation social coding platform. Host repos on your infrastructure with knots, use stacked pull requests, and run CI with spindles." /> 21 <link rel="canonical" href="https://tangled.org" /> 22{{ end }} 23 24 25{{ define "content" }} 26 <div class="flex flex-col gap-20 md:gap-40 my-20 md:my-32"> 27 {{ template "timeline/fragments/hero" . }} 28 {{ template "timeline/fragments/preview" . }} 29 {{ template "features1" . }} 30 {{ template "features2" . }} 31 {{ template "recentUpdates" . }} 32 {{ template "community" . }} 33 </div> 34{{ end }} 35 36{{ block "topbarLayout" . }} 37 <header class="max-w-screen-xl mx-auto w-full col-span-full md:col-span-1 md:col-start-2" style="z-index: 20;"> 38 {{ if .LoggedInUser }} 39 <div id="upgrade-banner" 40 hx-get="/upgradeBanner" 41 hx-trigger="load" 42 hx-swap="innerHTML"> 43 </div> 44 {{ end }} 45 {{ template "layouts/fragments/topbar" . }} 46 </header> 47{{ end }} 48 49{{ block "footerLayout" . }} 50 <footer class="z-10"> 51 {{ template "layouts/fragments/footer" . }} 52 </footer> 53{{ end }} 54 55{{ block "bodyClasses" . }} 56 bg-transparent bg-gradient-to-b from-white to-slate-100 dark:bg-none dark:bg-gray-900 57{{ end }} 58 59{{ block "mainLayout" . }} 60 <div class="flex-grow relative"> 61 <div 62 class="absolute opacity-50 dark:opacity-5 inset-x-0 top-0 bottom-[-50px] md:bottom-[-150px] pointer-events-none bg-[url('https://assets.tangled.network/yarn_ball.svg')] bg-no-repeat bg-right-bottom bg-[length:500px] md:bg-[length:1000px] w-full"> 63 </div> 64 <div class="max-w-screen-xl mx-auto flex flex-col gap-4 relative z-10"> 65 {{ block "contentLayout" . }} 66 <main> 67 {{ block "content" . }}{{ end }} 68 </main> 69 {{ end }} 70 71 {{ block "contentAfterLayout" . }} 72 <main> 73 {{ block "contentAfter" . }}{{ end }} 74 </main> 75 {{ end }} 76 </div> 77 </div> 78{{ end }} 79 80{{ define "features1" }} 81 {{ $labelStyle := "normal-case cursor-pointer w-auto md:w-full p-4 md:px-6 rounded bg-white dark:bg-gray-800 font-medium text-base md:text-lg opacity-50 border border-gray-200 dark:border-gray-700 relative overflow-hidden" }} 82 {{ $spanStyle := "z-10 items-center justify-between gap-2 w-full" }} 83 {{ $connectorStyle := "w-0.5 h-6 bg-gray-300 dark:bg-gray-600 opacity-0 mx-auto" }} 84 {{ $contentStyle := "hidden bg-white dark:bg-gray-800 rounded shadow-sm p-6 md:p-8 border border-gray-200 dark:border-gray-700 grid-cols-1 animate-fadein" }} 85 {{ $progressOverlayStyle := "absolute inset-0 bg-gray-600/10 dark:bg-gray-100/10 w-0 transition-none" }} 86 87 <style> 88 @media (max-width: 768px) { 89 .features-grid:has(#feature-prs:checked) { 90 grid-template-columns: 1fr auto auto; 91 } 92 93 .features-grid:has(#feature-knots:checked) { 94 grid-template-columns: auto 1fr auto; 95 } 96 97 .features-grid:has(#feature-spindles:checked) { 98 grid-template-columns: auto auto 1fr; 99 } 100 101 #feature-prs:checked ~ label[for="feature-prs"] .label-text, 102 #feature-knots:checked ~ label[for="feature-knots"] .label-text, 103 #feature-spindles:checked ~ label[for="feature-spindles"] .label-text { 104 display: inline-flex !important; 105 } 106 #feature-prs:checked ~ label[for="feature-prs"] .icon-only, 107 #feature-knots:checked ~ label[for="feature-knots"] .icon-only, 108 #feature-spindles:checked ~ label[for="feature-spindles"] .icon-only { 109 display: none !important; 110 } 111 } 112 </style> 113 114 <div class="features-grid w-full grid grid-cols-3 gap-x-6 px-2"> 115 <input type="radio" id="feature-prs" name="feature" class="peer/prs hidden" checked /> 116 <input type="radio" id="feature-knots" name="feature" class="peer/knots hidden" /> 117 <input type="radio" id="feature-spindles" name="feature" class="peer/spindles hidden" /> 118 119 <label for="feature-prs" class="{{ $labelStyle }} peer-checked/prs:opacity-100 peer-checked/prs:shadow-sm"> 120 <span class="label-text hidden md:inline-flex {{ $spanStyle }}">A better way to review {{ i "git-pull-request" "size-5" }}</span> 121 <span class="icon-only inline-flex md:hidden {{ $spanStyle }}">{{ i "git-pull-request" "size-5" }}</span> 122 <div class="{{ $progressOverlayStyle }}" data-progress="prs"></div> 123 </label> 124 125 <label for="feature-knots" class="{{ $labelStyle }} peer-checked/knots:opacity-100 peer-checked/knots:shadow-sm"> 126 <span class="label-text hidden md:inline-flex {{ $spanStyle }}">Completely self-hostable {{ i "hard-drive" "size-5" }}</span> 127 <span class="icon-only inline-flex md:hidden {{ $spanStyle }}">{{ i "hard-drive" "size-5" }}</span> 128 <div class="{{ $progressOverlayStyle }}" data-progress="knots"></div> 129 </label> 130 131 <label for="feature-spindles" class="{{ $labelStyle }} peer-checked/spindles:opacity-100 peer-checked/spindles:shadow-sm"> 132 <span class="label-text hidden md:inline-flex {{ $spanStyle }}">Quick and easy CI {{ i "layers-2" "size-5" }}</span> 133 <span class="icon-only inline-flex md:hidden {{ $spanStyle }}">{{ i "layers-2" "size-5" }}</span> 134 <div class="{{ $progressOverlayStyle }}" data-progress="spindles"></div> 135 </label> 136 137 <div class="{{ $connectorStyle }} peer-checked/prs:opacity-100"></div> 138 <div class="{{ $connectorStyle }} peer-checked/knots:opacity-100"></div> 139 <div class="{{ $connectorStyle }} peer-checked/spindles:opacity-100"></div> 140 141 {{ $titleStyle := "text-2xl md:text-6xl my-2 md:mb-4 text-black dark:text-white font-medium" }} 142 {{ $textContentStyle := "pb-6 md:text-xl" }} 143 {{ $imgContentStyle := "w-full min-h-96 min-h-[400px] md:min-h-[500px] rounded overflow-hidden place-content-center bg-gradient-to-b from-slate-50 to-slate-100 dark:from-gray-800 dark:to-gray-900 border border-gray-200 dark:border-gray-700" }} 144 {{ $linkDesktopStyle := "hover:no-underline items-center gap-2 p-3 text-base btn" }} 145 146 <div class="col-span-3 {{ $contentStyle }} peer-checked/prs:grid relative"> 147 <div class="{{ $textContentStyle }} flex gap-4 md:gap-8"> 148 <section class="space-y-4"> 149 <h1 class="{{ $titleStyle }}">Pull requests, reimagined</h1> 150 <p class="text-gray-600 dark:text-gray-400"> 151 Break down large features into small, reviewable chunks. Stack pull 152 requests on top of each other and ship faster with better code 153 reviews. Tangled natively supports stacking using Jujutsu. 154 </p> 155 <a href="https://blog.tangled.org/stacking" class="hover:no-underline inline-flex md:hidden items-center gap-2 text-sm text-black dark:text-white font-medium"> 156 Learn more 157 {{ i "arrow-right" "size-4" }} 158 </a> 159 </section> 160 <div class="w-fit hidden md:flex items-center"> 161 <div class="size-32 rounded-full flex items-center justify-center bg-green-100 dark:bg-green-900 -mr-4" > 162 {{ i "wand-sparkles" "size-16 text-green-500 dark:text-green-500" }} 163 </div> 164 <div class="size-40 rounded-full flex items-center justify-center bg-indigo-100 dark:bg-indigo-900 z-10"> 165 {{ i "git-pull-request" "size-24 text-indigo-500 dark:text-indigo-500 rotate-12" }} 166 </div> 167 </div> 168 </div> 169 <div class="{{ $imgContentStyle }} min-h-[500px] relative overflow-hidden"> 170 <div class="w-full h-full relative overflow-hidden"> 171 <img src="https://assets.tangled.network/home-page-prs.png" class="h-full w-[200%] md:w-full object-cover object-left" /> 172 </div> 173 </div> 174 <a href="https://blog.tangled.org/stacking" class="hover:no-underline hidden md:inline-flex absolute -bottom-6 -right-12 items-center gap-2 p-3 text-base btn"> 175 Learn more 176 {{ i "arrow-right" "size-4" }} 177 </a> 178 </div> 179 180 <div class="col-span-3 {{ $contentStyle }} peer-checked/knots:grid"> 181 <div class="{{ $textContentStyle }} flex place-content-between gap-4 md:gap-8"> 182 <section class="space-y-4"> 183 <h1 class="{{ $titleStyle }}">Run it at home</h1> 184 <p class="text-gray-600 dark:text-gray-400"> 185 Host your repositories on your own infrastructure with <a href="https://docs.tangled.org/knot-self-hosting-guide.html#knot-self-hosting-guide" class="no-underline">knots</a>. 186 Run CI on your own machines with <a href="https://docs.tangled.org/spindles.html#self-hosting-guide" class="no-underline">spindles</a>. 187 <br> 188 Don't want to self-host? All are welcome on our hosted instances. 189 </p> 190 </section> 191 <div class="w-fit hidden md:flex items-center"> 192 <div class="size-32 rounded-full flex items-center justify-center bg-green-100 dark:bg-green-900 -mr-4" > 193 {{ i "workflow" "size-16 text-green-500 dark:text-green-500" }} 194 </div> 195 <div class="size-40 rounded-full flex items-center justify-center bg-indigo-100 dark:bg-indigo-900 z-10"> 196 {{ i "server" "size-24 text-indigo-500 dark:text-indigo-500" }} 197 </div> 198 </div> 199 </div> 200 <div class="{{ $imgContentStyle }} min-h-[500px] relative overflow-hidden"> 201 <div class="w-full h-full relative overflow-hidden"> 202 <img src="https://assets.tangled.network/home-page-self-host.png" class="h-full w-[200%] md:w-full object-cover object-center" /> 203 </div> 204 </div> 205 </div> 206 207 <div class="col-span-3 {{ $contentStyle }} peer-checked/spindles:grid"> 208 <div class="{{ $textContentStyle }} flex place-content-between gap-4 md:gap-8"> 209 <section class="space-y-4"> 210 <h1 class="{{ $titleStyle }}">Nix-powered CI</h1> 211 <p class="text-gray-600 dark:text-gray-400"> 212 Pick and choose dependencies for your CI pipelines from <a 213 href="https://docs.tangled.org/spindles.html#dependencies" 214 class="no-underline"><code>nixpkgs</code></a>, one of the biggest 215 package repositories. 216 <br> 217 Support for Docker and MicroVM based runners coming soon! 218 </p> 219 </section> 220 <div class="w-fit hidden md:flex items-center"> 221 <div class="size-32 rounded-full flex items-center justify-center bg-green-100 dark:bg-green-900 -mr-4" > 222 {{ i "package" "size-16 text-green-500 dark:text-green-500" }} 223 </div> 224 <div class="size-40 rounded-full flex items-center justify-center bg-indigo-100 dark:bg-indigo-900 z-10"> 225 {{ i "snowflake" "size-24 text-indigo-500 dark:text-indigo-500 rotate-12" }} 226 </div> 227 </div> 228 </div> 229 <div class="{{ $imgContentStyle }} flex items-end pb-0 overflow-hidden"> 230 <div class="w-full h-full relative overflow-hidden"> 231 <img src="https://assets.tangled.network/home-page-ci.png" class="h-full w-[200%] md:w-full object-cover object-left md:object-center" /> 232 </div> 233 </div> 234 </div> 235 </div> 236 237 <script> 238 document.addEventListener('DOMContentLoaded', function() { 239 const featureIds = ['feature-prs', 'feature-knots', 'feature-spindles']; 240 const progressNames = ['prs', 'knots', 'spindles']; 241 let currentIndex = 0; 242 let timerInterval = null; 243 244 function stopTimer() { 245 if (timerInterval) { 246 clearInterval(timerInterval); 247 timerInterval = null; 248 } 249 document.querySelectorAll('[data-progress]').forEach(el => { 250 el.classList.remove('animate-progress'); 251 }); 252 } 253 254 const firstProgress = document.querySelector('[data-progress="prs"]'); 255 if (firstProgress) { 256 firstProgress.classList.add('animate-progress'); 257 } 258 259 document.querySelectorAll('label[for^="feature-"]').forEach(label => { 260 label.addEventListener('click', stopTimer); 261 }); 262 263 timerInterval = setInterval(function() { 264 document.querySelectorAll('[data-progress]').forEach(el => { 265 el.classList.remove('animate-progress'); 266 void el.offsetWidth; // force reflow 267 }); 268 269 currentIndex = (currentIndex + 1) % featureIds.length; 270 document.getElementById(featureIds[currentIndex]).checked = true; 271 272 const activeProgress = document.querySelector('[data-progress="' + progressNames[currentIndex] + '"]'); 273 if (activeProgress) { 274 activeProgress.classList.add('animate-progress'); 275 } 276 }, 5000); 277 }); 278 </script> 279{{ end }} 280 281{{ define "features2" }} 282 {{ $cardStyle := "bg-white dark:bg-gray-800 rounded shadow-sm border border-gray-200 dark:border-gray-700" }} 283 {{ $cardInnerStyle := "flex flex-row items-center gap-4 md:gap-6 p-4 md:p-6 md:pt-8 relative" }} 284 {{ $contentStyle := "flex-1 flex flex-col" }} 285 {{ $titleStyle := "text-xl md:text-2xl font-bold mb-2 md:mb-3 text-gray-900 dark:text-gray-100" }} 286 {{ $descriptionStyle := "text-gray-600 dark:text-gray-300 text-sm md:text-base leading-relaxed mb-5 md:mb-0" }} 287 {{ $linkMobileStyle := "hover:no-underline inline-flex md:hidden items-center gap-2 text-sm text-black dark:text-white font-medium" }} 288 {{ $iconContainerStyle := "relative shrink-0 w-24 h-24 md:w-48 md:h-48" }} 289 {{ $iconCircleStyle := "rounded-full flex items-center justify-center border border-gray-200 dark:border-gray-700" }} 290 {{ $linkDesktopStyle := "hover:no-underline hidden md:inline-flex absolute -bottom-10 -right-14 items-center gap-2 p-3 text-base btn" }} 291 292 <div class="w-full flex flex-col gap-6 md:gap-40 max-w-5xl mx-auto px-2"> 293 <div class="{{ $cardStyle }} md:mr-32"> 294 <div class="{{ $cardInnerStyle }}"> 295 {{ $moreLink := "https://docs.tangled.org/quick-start-guide.html#login-or-sign-up" }} 296 <div class="{{ $contentStyle }}"> 297 <h3 class="{{ $titleStyle }}">Built on AT Protocol</h3> 298 <p class="{{ $descriptionStyle }}"> 299 AT Protocol enables federated code-collaboration. Submit 300 pull-requests or bug-reports to any repository hosted on any 301 server. 302 <br> 303 <br> 304 Bring an existing AT Protocol account (such as your Bluesky 305 account), or signup for one with us. 306 </p> 307 <a href="{{ $moreLink }}" class="{{ $linkMobileStyle }}"> 308 Learn more 309 {{ i "arrow-right" "size-4" }} 310 </a> 311 </div> 312 <div class="{{ $iconContainerStyle }}"> 313 <div class="{{ $iconCircleStyle }} w-full h-full bg-blue-100 dark:bg-blue-900/50"> 314 {{ i "at-sign" "size-12 md:size-24" "text-blue-500 dark:text-blue-500" "rotate-12" }} 315 </div> 316 <div class="{{ $iconCircleStyle }} absolute -top-2 -left-2 w-10 h-10 md:w-16 md:h-16 rounded-full bg-white dark:bg-gray-800 -rotate-12"> 317 {{ i "globe" "size-4 md:size-8" "text-blue-500 dark:text-blue-500" }} 318 </div> 319 <a href="{{ $moreLink }}" class="{{ $linkDesktopStyle }}"> 320 Learn more 321 {{ i "arrow-right" "size-4" }} 322 </a> 323 </div> 324 </div> 325 </div> 326 327 <div class="{{ $cardStyle }} md:ml-32"> 328 <div class="{{ $cardInnerStyle }}"> 329 {{ $moreLink := "https://tangled.org/core" }} 330 <div class="{{ $contentStyle }}"> 331 <h3 class="{{ $titleStyle }}">Free and Open-source</h3> 332 <p class="{{ $descriptionStyle }}"> 333 All of Tangled is open-source and built in the open! 334 Check out the <a class="underline" href="https://tangled.org/core">monorepo</a> and join in on the fun. 335 <br> 336 <br> 337 We welcome contributions however big or small. You can start contributing by picking up a 338 <a class="underline" href="https://tangled.org/tangled.org/core/issues">good-first-issue</a>. 339 </p> 340 <a href="{{ $moreLink }}" class="{{ $linkMobileStyle }}"> 341 View source 342 {{ i "arrow-right" "size-4" }} 343 </a> 344 </div> 345 <div class="{{ $iconContainerStyle }}"> 346 <div class="{{ $iconCircleStyle }} w-full h-full bg-green-100 dark:bg-green-900/50"> 347 {{ i "package-open" "size-12 md:size-24" "text-green-500 dark:text-green-500" "-rotate-12" }} 348 </div> 349 <div class="absolute -top-2 -left-2 w-10 h-10 md:w-16 md:h-16 rounded-full bg-white dark:bg-gray-800 flex items-center justify-center border border-gray-200 dark:border-gray-700 rotate-12"> 350 {{ i "heart" "size-4 md:size-8" "text-green-500 dark:text-green-500" }} 351 </div> 352 <a href="{{ $moreLink }}" class="{{ $linkDesktopStyle }}"> 353 View source 354 {{ i "arrow-right" "size-4" }} 355 </a> 356 </div> 357 </div> 358 </div> 359 360 <div class="{{ $cardStyle }} md:mr-32"> 361 <div class="{{ $cardInnerStyle }}"> 362 {{ $moreLink := "/timeline" }} 363 <div class="{{ $contentStyle }}"> 364 <h3 class="{{ $titleStyle }}">Social coding is back</h3> 365 <p class="{{ $descriptionStyle }}"> 366 Discover trending projects, follow your friends and star your favourite repositories. Coding is better together! 367 <br> 368 <br> 369 You can use one account for all of the atmosphere. If you have 370 friends on Bluesky, you will find them on Tangled with the same 371 handle. 372 </p> 373 <a href="{{ $moreLink }}" class="{{ $linkMobileStyle }}"> 374 Explore timeline 375 {{ i "arrow-right" "size-4" }} 376 </a> 377 </div> 378 <div class="{{ $iconContainerStyle }}"> 379 <div class="{{ $iconCircleStyle }} w-full h-full bg-amber-100 dark:bg-amber-900/50"> 380 {{ i "message-circle-heart" "size-12 md:size-24" "text-amber-500 dark:text-amber-500" "rotate-12" }} 381 </div> 382 <div class="absolute -top-2 -left-2 w-10 h-10 md:w-16 md:h-16 rounded-full bg-white dark:bg-gray-800 flex items-center justify-center border border-gray-200 dark:border-gray-700 -rotate-12"> 383 {{ i "users" "size-4 md:size-8" "text-amber-500 dark:text-amber-500" }} 384 </div> 385 <a href="{{ $moreLink }}" class="{{ $linkDesktopStyle }}"> 386 Explore timeline 387 {{ i "arrow-right" "size-4" }} 388 </a> 389 </div> 390 </div> 391 </div> 392 </div> 393{{ end }} 394 395{{ define "changelog" }} 396 <div class="w-full px-2 py-16 md:py-24"> 397 <h2 class="text-3xl md:text-4xl font-bold mb-8 text-gray-900 dark:text-gray-100">Changelog</h2> 398 399 <div class="grid grid-cols-1 gap-6 mb-6"> 400 {{ range $index := list 0 1 2 3 }} 401 <div class="bg-white dark:bg-gray-800 rounded shadow-sm border border-gray-200 dark:border-gray-700 p-6"> 402 <div class="flex items-center gap-2 mb-3"> 403 <span class="text-xs font-medium text-gray-500 dark:text-gray-400">v1.{{ sub 3 $index }}.0</span> 404 <span class="text-xs text-gray-400 dark:text-gray-500"></span> 405 <span class="text-xs text-gray-500 dark:text-gray-400">Feb {{ sub 16 $index }}, 2026</span> 406 </div> 407 <h3 class="text-lg font-semibold mb-2 text-gray-900 dark:text-gray-100">Feature Update {{ sub 4 $index }}</h3> 408 <p class="text-sm text-gray-600 dark:text-gray-300 leading-relaxed"> 409 Improvements to the platform including bug fixes, performance enhancements, and new features. 410 </p> 411 </div> 412 {{ end }} 413 </div> 414 415 <div class="flex justify-end"> 416 <a href="/changelog" class="hover:no-underline inline-flex items-center gap-2 px-4 py-2 text-base btn"> 417 View full changelog 418 {{ i "arrow-right" "size-4" }} 419 </a> 420 </div> 421 </div> 422{{ end }} 423 424{{ define "recentUpdates" }} 425 <div class="w-full px-2 py-16 md:py-24"> 426 <h2 class="px-4 text-3xl md:text-4xl font-bold text-gray-900 dark:text-gray-100 mb-2">Recent updates</h2> 427 <p class="px-4 mb-8 text-gray-500 dark:text-gray-400"> 428 Follow <a href="https://bsky.app/profile/tangled.org">@tangled.org</a> on Bluesky for more! 429 </p> 430 <div class="columns-1 md:columns-2 lg:columns-3 gap-6"> 431 {{ range $index, $post := .BlueskyPosts }} 432 <div class="{{ if ge $index 3 }}hidden md:block{{ end }}"> 433 {{ template "post" $post }} 434 </div> 435 {{ end }} 436 </div> 437 </div> 438{{ end }} 439 440{{ define "post" }} 441 <div class="bg-white dark:bg-gray-800 rounded shadow-sm border border-gray-200 dark:border-gray-700 px-6 py-4 flex flex-col gap-2 break-inside-avoid mb-6"> 442 <div class="flex items-center justify-between text-sm text-gray-500 dark:text-gray-400"> 443 <span class="flex items-center gap-2"> 444 {{ template "user/fragments/picHandle" "tangled.org" }} 445 </span> 446 <span>{{ template "repo/fragments/shortTimeAgo" .CreatedAt }}</span> 447 </div> 448 <p class="text-gray-900 dark:text-gray-100 text-base leading-relaxed whitespace-pre-wrap">{{ .Text }}</p> 449 450 {{ if .Embed }} 451 {{ if .Embed.EmbedImages_View }} 452 <div class="grid {{ if eq (len .Embed.EmbedImages_View.Images) 1 }}grid-cols-1{{ else if eq (len .Embed.EmbedImages_View.Images) 2 }}grid-cols-2{{ else }}grid-cols-2{{ end }} gap-2"> 453 {{ range .Embed.EmbedImages_View.Images }} 454 <img src="{{ .Fullsize }}" alt="{{ .Alt }}" class="rounded w-full h-auto object-cover border border-gray-200 dark:border-gray-700" loading="lazy" /> 455 {{ end }} 456 </div> 457 {{ else if .Embed.EmbedExternal_View }} 458 <a href="{{ .Embed.EmbedExternal_View.External.Uri }}" target="_blank" rel="noopener noreferrer" class="hover:no-underline block border border-gray-200 dark:border-gray-700 rounded overflow-hidden hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"> 459 {{ if .Embed.EmbedExternal_View.External.Thumb }} 460 <img src="{{ .Embed.EmbedExternal_View.External.Thumb }}" alt="" class="w-full h-48 object-cover" loading="lazy" /> 461 {{ end }} 462 <div class="p-3"> 463 <div class="font-medium text-gray-900 dark:text-gray-100 text-sm mb-1">{{ .Embed.EmbedExternal_View.External.Title }}</div> 464 <div class="text-xs text-gray-600 dark:text-gray-400 line-clamp-2">{{ .Embed.EmbedExternal_View.External.Description }}</div> 465 <div class="text-xs text-gray-500 dark:text-gray-500 mt-1">{{ .Embed.EmbedExternal_View.External.Uri }}</div> 466 </div> 467 </a> 468 {{ else if .Embed.EmbedVideo_View }} 469 <div class="rounded overflow-hidden bg-gray-100 dark:bg-gray-700 aspect-video flex items-center justify-center"> 470 <span class="text-gray-500 dark:text-gray-400 text-sm">Video embed</span> 471 </div> 472 {{ end }} 473 {{ end }} 474 475 <a href="https://bsky.app/profile/tangled.org/post/{{ .Rkey }}" 476 target="_blank" 477 rel="noopener noreferrer" 478 class="flex items-center justify-between gap-4 text-sm text-gray-500 dark:text-gray-400 pt-2 no-underline hover:no-underline"> 479 <div class="flex items-center gap-4"> 480 <div class="flex items-center gap-1"> 481 {{ i "heart" "size-4" }} 482 <span>{{ .LikeCount }}</span> 483 </div> 484 <div class="flex items-center gap-1"> 485 {{ i "repeat-2" "size-4" }} 486 <span>{{ .RepostCount }}</span> 487 </div> 488 <div class="flex items-center gap-1"> 489 {{ i "message-square" "size-4 -scale-x-1" }} 490 <span>{{ add64 .ReplyCount .QuoteCount }}</span> 491 </div> 492 </div> 493 {{ i "arrow-up-right" "size-4" }} 494 </a> 495 </div> 496{{ end }} 497 498{{ define "community" }} 499 <div class="w-full px-2 py-16 md:py-24"> 500 <div class="max-w-2xl mx-auto text-center space-y-6"> 501 <h2 class="text-3xl md:text-6xl font-bold text-gray-900 dark:text-gray-100">Join the network</h2> 502 <p class="text-xl text-gray-600 dark:text-gray-300"> 503 You can participate in the Tangled network with an AT account. If you 504 don't know what that is, you can sign up for one below. 505 <br> 506 <a href="https://docs.tangled.org/quick-start-guide.html#login-or-sign-up">Read more on the docs.</a> 507 </p> 508 <form class="flex gap-2 items-stretch w-full md:max-w-md mx-auto p-2 border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 rounded shadow-sm" method="get" action="/signup"> 509 <input 510 type="email" 511 id="email" 512 name="id" 513 tabindex="4" 514 required 515 placeholder="Enter your email" 516 class="py-2 w-full" 517 /> 518 <button class="btn-create flex items-center gap-2 text-base whitespace-nowrap" type="submit"> 519 join now 520 {{ i "arrow-right" "size-4" }} 521 </button> 522 </form> 523 </div> 524{{ end }}