Monorepo for Tangled tangled.org

revert "appview/pages: seo improvements, sitemap, schemae and more"

This reverts commit 8fb22cb34756cc2930bb780548d45bde56cdbe65.

Signed-off-by: oppiliappan <me@oppi.li>

oppi.li a82cd010 8fb22cb3

verified
+43 -319
-46
appview/pages/repoinfo/repoinfo.go
··· 1 package repoinfo 2 3 import ( 4 - "encoding/json" 5 "fmt" 6 "path" 7 "slices" ··· 118 func (r RolesInRepo) IsPushAllowed() bool { 119 return slices.Contains(r.Roles, "repo:push") 120 } 121 - 122 - // PrimaryLanguage returns the first (most used) language from a list, or empty string if none 123 - func PrimaryLanguage(languages []interface{}) string { 124 - if len(languages) == 0 { 125 - return "" 126 - } 127 - 128 - // Languages are already sorted by percentage in descending order 129 - // Just get the first one 130 - if firstLang, ok := languages[0].(map[string]interface{}); ok { 131 - if name, ok := firstLang["Name"].(string); ok { 132 - return name 133 - } 134 - } 135 - 136 - return "" 137 - } 138 - 139 - // StructuredData generates Schema.org JSON-LD structured data for the repository 140 - func (r RepoInfo) StructuredData(primaryLanguage string) string { 141 - data := map[string]interface{}{ 142 - "@context": "https://schema.org", 143 - "@type": "SoftwareSourceCode", 144 - "name": r.Name, 145 - "description": r.Description, 146 - "codeRepository": "https://tangled.org/" + r.FullName(), 147 - "url": "https://tangled.org/" + r.FullName(), 148 - "author": map[string]interface{}{ 149 - "@type": "Person", 150 - "name": r.owner(), 151 - "url": "https://tangled.org/" + r.owner(), 152 - }, 153 - } 154 - 155 - // Add programming language if available 156 - if primaryLanguage != "" { 157 - data["programmingLanguage"] = primaryLanguage 158 - } 159 - 160 - jsonBytes, err := json.Marshal(data) 161 - if err != nil { 162 - return "{}" 163 - } 164 - return string(jsonBytes) 165 - }
··· 1 package repoinfo 2 3 import ( 4 "fmt" 5 "path" 6 "slices" ··· 117 func (r RolesInRepo) IsPushAllowed() bool { 118 return slices.Contains(r.Roles, "repo:push") 119 }
-22
appview/pages/templates/fragments/breadcrumb.html
··· 1 - {{ define "fragments/breadcrumb" }} 2 - {{ $items := . }} 3 - {{ if gt (len $items) 0 }} 4 - <script type="application/ld+json"> 5 - { 6 - "@context": "https://schema.org", 7 - "@type": "BreadcrumbList", 8 - "itemListElement": [ 9 - {{ range $idx, $item := $items }} 10 - {{ if gt $idx 0 }},{{ end }} 11 - { 12 - "@type": "ListItem", 13 - "position": {{ add $idx 1 }}, 14 - "name": "{{ index $item 0 }}", 15 - "item": "{{ index $item 1 }}" 16 - } 17 - {{ end }} 18 - ] 19 - } 20 - </script> 21 - {{ end }} 22 - {{ end }}
···
+2 -27
appview/pages/templates/goodfirstissues/index.html
··· 1 {{ define "title" }}good first issues{{ end }} 2 3 {{ define "extrameta" }} 4 - <meta name="description" content="Discover beginner-friendly good first issues across open source projects on Tangled. Perfect for new contributors looking to get started with open source development." /> 5 - <meta name="keywords" content="good first issues, beginner issues, open source contribution, first time contributor, beginner friendly, open source projects" /> 6 - 7 <meta property="og:title" content="good first issues · tangled" /> 8 - <meta property="og:type" content="website" /> 9 <meta property="og:url" content="https://tangled.org/goodfirstissues" /> 10 - <meta property="og:description" content="Find beginner-friendly issues across all repositories to get started with open source contributions on Tangled." /> 11 - 12 - <meta name="twitter:card" content="summary" /> 13 - <meta name="twitter:title" content="good first issues · tangled" /> 14 - <meta name="twitter:description" content="Find beginner-friendly issues to get started with open source contributions." /> 15 - 16 - <!-- structured data for good first issues page --> 17 - <script type="application/ld+json"> 18 - { 19 - "@context": "https://schema.org", 20 - "@type": "CollectionPage", 21 - "name": "Good First Issues", 22 - "description": "A curated collection of beginner-friendly issues across open source projects", 23 - "url": "https://tangled.org/goodfirstissues", 24 - "isPartOf": { 25 - "@type": "WebSite", 26 - "name": "Tangled", 27 - "url": "https://tangled.org" 28 - } 29 - } 30 - </script> 31 {{ end }} 32 - 33 - {{ define "canonical" }}https://tangled.org/goodfirstissues{{ end }} 34 35 {{ define "content" }} 36 <div class="grid grid-cols-10">
··· 1 {{ define "title" }}good first issues{{ end }} 2 3 {{ define "extrameta" }} 4 <meta property="og:title" content="good first issues · tangled" /> 5 + <meta property="og:type" content="object" /> 6 <meta property="og:url" content="https://tangled.org/goodfirstissues" /> 7 + <meta property="og:description" content="Find good first issues to contribute to open source projects" /> 8 {{ end }} 9 10 {{ define "content" }} 11 <div class="grid grid-cols-10">
+2 -26
appview/pages/templates/layouts/base.html
··· 4 <head> 5 <meta charset="UTF-8" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"/> 7 - <meta name="description" content="tightly-knit social coding"/> 8 - <meta name="keywords" content="git hosting, social coding, version control, pull requests, CI/CD, code collaboration, open source, decentralized"/> 9 <meta name="htmx-config" content='{"includeIndicatorStyles": false}'> 10 - <meta name="author" content="Tangled"/> 11 - 12 - <!-- Canonical URL --> 13 - <link rel="canonical" href="{{ block "canonical" . }}https://tangled.org{{ .Request.URL.Path }}{{ end }}" /> 14 15 <script defer src="/static/htmx.min.js"></script> 16 <script defer src="/static/htmx-ext-ws.min.js"></script> ··· 24 <link rel="preconnect" href="https://avatar.tangled.sh" /> 25 <link rel="preconnect" href="https://camo.tangled.sh" /> 26 27 - <!-- RSS Feed Discovery --> 28 - {{ block "rss" . }}{{ end }} 29 - 30 <!-- pwa manifest --> 31 <link rel="manifest" href="/pwa-manifest.json" /> 32 ··· 34 <link rel="preload" href="/static/fonts/InterVariable.woff2" as="font" type="font/woff2" crossorigin /> 35 36 <link rel="stylesheet" href="/static/tw.css?{{ cssContentHash }}" type="text/css" /> 37 - <title>{{ block "title" . }}{{ end }}</title> 38 - 39 - <!-- Structured Data --> 40 - {{ block "structuredData" . }} 41 - <script type="application/ld+json"> 42 - { 43 - "@context": "https://schema.org", 44 - "@type": "Organization", 45 - "name": "Tangled", 46 - "url": "https://tangled.org", 47 - "logo": "https://tangled.org/favicon.svg", 48 - "description": "tightly-knit social coding", 49 - "sameAs": [] 50 - } 51 - </script> 52 - {{ end }} 53 - 54 {{ block "extrameta" . }}{{ end }} 55 </head> 56 <body class="min-h-screen flex flex-col gap-4 bg-slate-100 dark:bg-gray-900 dark:text-white transition-colors duration-200">
··· 4 <head> 5 <meta charset="UTF-8" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"/> 7 + <meta name="description" content="Social coding, but for real this time!"/> 8 <meta name="htmx-config" content='{"includeIndicatorStyles": false}'> 9 10 <script defer src="/static/htmx.min.js"></script> 11 <script defer src="/static/htmx-ext-ws.min.js"></script> ··· 19 <link rel="preconnect" href="https://avatar.tangled.sh" /> 20 <link rel="preconnect" href="https://camo.tangled.sh" /> 21 22 <!-- pwa manifest --> 23 <link rel="manifest" href="/pwa-manifest.json" /> 24 ··· 26 <link rel="preload" href="/static/fonts/InterVariable.woff2" as="font" type="font/woff2" crossorigin /> 27 28 <link rel="stylesheet" href="/static/tw.css?{{ cssContentHash }}" type="text/css" /> 29 + <title>{{ block "title" . }}{{ end }} · tangled</title> 30 {{ block "extrameta" . }}{{ end }} 31 </head> 32 <body class="min-h-screen flex flex-col gap-4 bg-slate-100 dark:bg-gray-900 dark:text-white transition-colors duration-200">
+1 -20
appview/pages/templates/layouts/profilebase.html
··· 10 <meta property="og:image" content="{{ $avatarUrl }}" /> 11 <meta property="og:image:width" content="512" /> 12 <meta property="og:image:height" content="512" /> 13 - 14 <meta name="twitter:card" content="summary" /> 15 <meta name="twitter:title" content="{{ $handle }}" /> 16 <meta name="twitter:description" content="{{ or .Card.Profile.Description $handle }}" /> 17 <meta name="twitter:image" content="{{ $avatarUrl }}" /> 18 - 19 - <!-- structured data for user profile --> 20 - <script type="application/ld+json"> 21 - { 22 - "@context": "https://schema.org", 23 - "@type": "Person", 24 - "name": "{{ or .Card.Profile.DisplayName .Card.UserHandle .Card.UserDid }}", 25 - "url": "https://tangled.org/{{ or .Card.UserHandle .Card.UserDid }}", 26 - "image": "{{ $avatarUrl }}", 27 - "description": "{{ .Card.Profile.Description }}"{{ if .Card.UserHandle }}, 28 - "identifier": "{{ .Card.UserHandle }}"{{ end }} 29 - } 30 - </script> 31 - {{ end }} 32 - 33 - {{ define "canonical" }}https://tangled.org/{{ or .Card.UserHandle .Card.UserDid }}{{ end }} 34 - 35 - {{ define "rss" }} 36 - <link rel="alternate" type="application/atom+xml" title="{{ or .Card.UserHandle .Card.UserDid }} Activity Feed" href="https://tangled.org/{{ or .Card.UserHandle .Card.UserDid }}/feed.atom" /> 37 {{ end }} 38 39 {{ define "content" }}
··· 10 <meta property="og:image" content="{{ $avatarUrl }}" /> 11 <meta property="og:image:width" content="512" /> 12 <meta property="og:image:height" content="512" /> 13 + 14 <meta name="twitter:card" content="summary" /> 15 <meta name="twitter:title" content="{{ $handle }}" /> 16 <meta name="twitter:description" content="{{ or .Card.Profile.Description $handle }}" /> 17 <meta name="twitter:image" content="{{ $avatarUrl }}" /> 18 {{ end }} 19 20 {{ define "content" }}
-36
appview/pages/templates/repo/index.html
··· 5 {{ template "repo/fragments/meta" . }} 6 7 {{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo) }} 8 - 9 - <!-- Structured Data for Repository --> 10 - <script type="application/ld+json"> 11 - { 12 - "@context": "https://schema.org", 13 - "@type": "SoftwareSourceCode", 14 - "name": "{{ .RepoInfo.Name }}", 15 - "description": "{{ .RepoInfo.Description }}", 16 - "codeRepository": "https://tangled.org/{{ .RepoInfo.FullName }}", 17 - "programmingLanguage": {{ if .Languages }}{{ range $idx, $lang := .Languages }}{{ if eq $idx 0 }}"{{ $lang.Name }}"{{ end }}{{ end }}{{ else }}"Unknown"{{ end }}, 18 - "url": "https://tangled.org/{{ .RepoInfo.FullName }}", 19 - "author": { 20 - "@type": "Person", 21 - "name": "{{ .RepoInfo.OwnerWithAt }}", 22 - "url": "https://tangled.org/{{ .RepoInfo.OwnerWithAt }}" 23 - }{{ if .RepoInfo.Source }}, 24 - "isBasedOn": { 25 - "@type": "SoftwareSourceCode", 26 - "name": "{{ .RepoInfo.Source.Name }}", 27 - "url": "https://tangled.org/{{ didOrHandle .RepoInfo.Source.Did .RepoInfo.SourceHandle }}/{{ .RepoInfo.Source.Name }}" 28 - }{{ end }} 29 - } 30 - </script> 31 - 32 - <!-- Breadcrumb Navigation --> 33 - {{ template "fragments/breadcrumb" (list 34 - (list "Home" "https://tangled.org") 35 - (list .RepoInfo.OwnerWithAt (printf "https://tangled.org/%s" .RepoInfo.OwnerWithAt)) 36 - (list .RepoInfo.Name (printf "https://tangled.org/%s" .RepoInfo.FullName)) 37 - ) }} 38 - {{ end }} 39 - 40 - {{ define "canonical" }}https://tangled.org/{{ .RepoInfo.FullName }}{{ end }} 41 - 42 - {{ define "rss" }} 43 - <link rel="alternate" type="application/atom+xml" title="{{ .RepoInfo.FullName }} Activity Feed" href="https://tangled.org/{{ .RepoInfo.FullName }}/feed.atom" /> 44 {{ end }} 45 46 {{ define "repoContent" }}
··· 5 {{ template "repo/fragments/meta" . }} 6 7 {{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo) }} 8 {{ end }} 9 10 {{ define "repoContent" }}
+19
appview/pages/templates/repo/issues/fragments/og.html
···
··· 1 + {{ define "repo/issues/fragments/og" }} 2 + {{ $title := printf "%s #%d" .Issue.Title .Issue.IssueId }} 3 + {{ $description := or .Issue.Body .RepoInfo.Description }} 4 + {{ $url := printf "https://tangled.org/%s/issues/%d" .RepoInfo.FullName .Issue.IssueId }} 5 + {{ $imageUrl := printf "https://tangled.org/%s/issues/%d/opengraph" .RepoInfo.FullName .Issue.IssueId }} 6 + 7 + <meta property="og:title" content="{{ unescapeHtml $title }}" /> 8 + <meta property="og:type" content="object" /> 9 + <meta property="og:url" content="{{ $url }}" /> 10 + <meta property="og:description" content="{{ $description }}" /> 11 + <meta property="og:image" content="{{ $imageUrl }}" /> 12 + <meta property="og:image:width" content="1200" /> 13 + <meta property="og:image:height" content="600" /> 14 + 15 + <meta name="twitter:card" content="summary_large_image" /> 16 + <meta name="twitter:title" content="{{ unescapeHtml $title }}" /> 17 + <meta name="twitter:description" content="{{ $description }}" /> 18 + <meta name="twitter:image" content="{{ $imageUrl }}" /> 19 + {{ end }}
+16 -16
appview/pages/templates/repo/pulls/fragments/og.html
··· 1 - {{ define "pulls/fragments/og" }} 2 - {{ $title := printf "%s #%d" .Pull.Title .Pull.PullId }} 3 - {{ $description := or .Pull.Body .RepoInfo.Description }} 4 - {{ $url := printf "https://tangled.org/%s/pulls/%d" .RepoInfo.FullName .Pull.PullId }} 5 - {{ $imageUrl := printf "https://tangled.org/%s/pulls/%d/opengraph" .RepoInfo.FullName .Pull.PullId }} 6 7 - <meta property="og:title" content="{{ unescapeHtml $title }}" /> 8 - <meta property="og:type" content="object" /> 9 - <meta property="og:url" content="{{ $url }}" /> 10 - <meta property="og:description" content="{{ $description }}" /> 11 - <meta property="og:image" content="{{ $imageUrl }}" /> 12 - <meta property="og:image:width" content="1200" /> 13 - <meta property="og:image:height" content="600" /> 14 15 - <meta name="twitter:card" content="summary_large_image" /> 16 - <meta name="twitter:title" content="{{ unescapeHtml $title }}" /> 17 - <meta name="twitter:description" content="{{ $description }}" /> 18 - <meta name="twitter:image" content="{{ $imageUrl }}" /> 19 {{ end }}
··· 1 + {{ define "repo/pulls/fragments/og" }} 2 + {{ $title := printf "%s #%d" .Pull.Title .Pull.PullId }} 3 + {{ $description := or .Pull.Body .RepoInfo.Description }} 4 + {{ $url := printf "https://tangled.org/%s/pulls/%d" .RepoInfo.FullName .Pull.PullId }} 5 + {{ $imageUrl := printf "https://tangled.org/%s/pulls/%d/opengraph" .RepoInfo.FullName .Pull.PullId }} 6 7 + <meta property="og:title" content="{{ unescapeHtml $title }}" /> 8 + <meta property="og:type" content="object" /> 9 + <meta property="og:url" content="{{ $url }}" /> 10 + <meta property="og:description" content="{{ $description }}" /> 11 + <meta property="og:image" content="{{ $imageUrl }}" /> 12 + <meta property="og:image:width" content="1200" /> 13 + <meta property="og:image:height" content="600" /> 14 15 + <meta name="twitter:card" content="summary_large_image" /> 16 + <meta name="twitter:title" content="{{ unescapeHtml $title }}" /> 17 + <meta name="twitter:description" content="{{ $description }}" /> 18 + <meta name="twitter:image" content="{{ $imageUrl }}" /> 19 {{ end }}
+3 -49
appview/pages/templates/timeline/home.html
··· 1 {{ define "title" }}tangled &middot; tightly-knit social coding{{ end }} 2 3 {{ define "extrameta" }} 4 - {{ $desc := "Collaborate on code with decentralized git hosting, modern contribution and review workflows, and lightweight CI/CD pipelines." }} 5 - {{ $title = "tangled · tightly-knit social coding" }} 6 - 7 - <meta name="description" content="{{ $desc }}" /> 8 - <meta property="og:title" content="{{ $title }}" /> 9 - <meta property="og:type" content="website" /> 10 <meta property="og:url" content="https://tangled.org" /> 11 - <meta property="og:description" content="Decentralized git hosting with improved pull requests and lightweight CI/CD. Host repositories on your own infrastructure." /> 12 - <meta property="og:image" content="https://assets.tangled.network/tangled_og.png" /> 13 - <meta property="og:image:width" content="1200" /> 14 - <meta property="og:image:height" content="630" /> 15 - 16 - <meta name="twitter:card" content="summary_large_image" /> 17 - <meta name="twitter:title" content="{{ $title }}" /> 18 - <meta name="twitter:description" content="{{ $desc }}" /> 19 - <meta name="twitter:image" content="https://assets.tangled.network/tangled_og.png" /> 20 - 21 - <!-- Enhanced Structured Data for Homepage --> 22 - <script type="application/ld+json"> 23 - { 24 - "@context": "https://schema.org", 25 - "@type": "WebSite", 26 - "name": "Tangled", 27 - "alternateName": "Tangled", 28 - "url": "https://tangled.org", 29 - "description": "{{ $desc }}", 30 - "potentialAction": { 31 - "@type": "SearchAction", 32 - "target": "https://tangled.org/?q={search_term_string}", 33 - "query-input": "required name=search_term_string" 34 - } 35 - } 36 - </script> 37 - <script type="application/ld+json"> 38 - { 39 - "@context": "https://schema.org", 40 - "@type": "SoftwareApplication", 41 - "name": "Tangled", 42 - "applicationCategory": "DeveloperTool", 43 - "offers": { 44 - "@type": "Offer", 45 - "price": "0", 46 - "priceCurrency": "USD" 47 - }, 48 - "operatingSystem": "Web", 49 - "description": "{{ $desc }}" 50 - } 51 - </script> 52 {{ end }} 53 - 54 - {{ define "canonical" }}https://tangled.org{{ end }} 55 56 57 {{ define "content" }}
··· 1 {{ define "title" }}tangled &middot; tightly-knit social coding{{ end }} 2 3 {{ define "extrameta" }} 4 + <meta property="og:title" content="timeline · tangled" /> 5 + <meta property="og:type" content="object" /> 6 <meta property="og:url" content="https://tangled.org" /> 7 + <meta property="og:description" content="tightly-knit social coding" /> 8 {{ end }} 9 10 11 {{ define "content" }}
-1
appview/state/router.go
··· 34 35 router.Get("/pwa-manifest.json", s.WebAppManifest) 36 router.Get("/robots.txt", s.RobotsTxt) 37 - router.Get("/sitemap.xml", s.Sitemap) 38 39 userRouter := s.UserRouter(&middleware) 40 standardRouter := s.StandardRouter(&middleware)
··· 34 35 router.Get("/pwa-manifest.json", s.WebAppManifest) 36 router.Get("/robots.txt", s.RobotsTxt) 37 38 userRouter := s.UserRouter(&middleware) 39 standardRouter := s.StandardRouter(&middleware)
-76
appview/state/state.go
··· 208 209 robotsTxt := `User-agent: * 210 Allow: / 211 - Disallow: /settings 212 - Disallow: /notifications 213 - Disallow: /login 214 - Disallow: /logout 215 - Disallow: /signup 216 - Disallow: /oauth 217 - Disallow: */settings$ 218 - Disallow: */settings/* 219 - 220 - Crawl-delay: 1 221 - 222 - Sitemap: https://tangled.org/sitemap.xml 223 ` 224 w.Write([]byte(robotsTxt)) 225 - } 226 - 227 - func (s *State) Sitemap(w http.ResponseWriter, r *http.Request) { 228 - w.Header().Set("Content-Type", "application/xml; charset=utf-8") 229 - w.Header().Set("Cache-Control", "public, max-age=3600") 230 - 231 - // basic sitemap with static pages 232 - sitemap := `<?xml version="1.0" encoding="UTF-8"?> 233 - <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 234 - <url> 235 - <loc>https://tangled.org</loc> 236 - <changefreq>daily</changefreq> 237 - <priority>1.0</priority> 238 - </url> 239 - <url> 240 - <loc>https://tangled.org/timeline</loc> 241 - <changefreq>hourly</changefreq> 242 - <priority>0.9</priority> 243 - </url> 244 - <url> 245 - <loc>https://tangled.org/goodfirstissues</loc> 246 - <changefreq>daily</changefreq> 247 - <priority>0.8</priority> 248 - </url> 249 - <url> 250 - <loc>https://tangled.org/terms</loc> 251 - <changefreq>monthly</changefreq> 252 - <priority>0.3</priority> 253 - </url> 254 - <url> 255 - <loc>https://tangled.org/privacy</loc> 256 - <changefreq>monthly</changefreq> 257 - <priority>0.3</priority> 258 - </url> 259 - <url> 260 - <loc>https://tangled.org/brand</loc> 261 - <changefreq>monthly</changefreq> 262 - <priority>0.5</priority> 263 - </url> 264 - </urlset>` 265 - w.Write([]byte(sitemap)) 266 - } 267 - 268 - // https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Manifest 269 - const manifestJson = `{ 270 - "name": "tangled", 271 - "description": "tightly-knit social coding.", 272 - "icons": [ 273 - { 274 - "src": "/favicon.svg", 275 - "sizes": "144x144" 276 - } 277 - ], 278 - "start_url": "/", 279 - "id": "org.tangled", 280 - 281 - "display": "standalone", 282 - "background_color": "#111827", 283 - "theme_color": "#111827" 284 - }` 285 - 286 - func (p *State) PWAManifest(w http.ResponseWriter, r *http.Request) { 287 - w.Header().Set("Content-Type", "application/json") 288 - w.Write([]byte(manifestJson)) 289 } 290 291 func (s *State) TermsOfService(w http.ResponseWriter, r *http.Request) {
··· 208 209 robotsTxt := `User-agent: * 210 Allow: / 211 ` 212 w.Write([]byte(robotsTxt)) 213 } 214 215 func (s *State) TermsOfService(w http.ResponseWriter, r *http.Request) {