A container registry that uses the AT Protocol for manifest storage and S3 for blob storage.
0
fork

Configure Feed

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

add 404 page

+122 -4
+32
pkg/appview/handlers/errors.go
··· 1 + package handlers 2 + 3 + import ( 4 + "html/template" 5 + "net/http" 6 + ) 7 + 8 + // NotFoundHandler handles 404 errors 9 + type NotFoundHandler struct { 10 + Templates *template.Template 11 + RegistryURL string 12 + } 13 + 14 + func (h *NotFoundHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 15 + RenderNotFound(w, r, h.Templates, h.RegistryURL) 16 + } 17 + 18 + // RenderNotFound renders the 404 page template. 19 + // Use this from other handlers when a resource is not found. 20 + func RenderNotFound(w http.ResponseWriter, r *http.Request, templates *template.Template, registryURL string) { 21 + w.WriteHeader(http.StatusNotFound) 22 + 23 + data := struct { 24 + PageData 25 + }{ 26 + PageData: NewPageData(r, registryURL), 27 + } 28 + 29 + if err := templates.ExecuteTemplate(w, "404", data); err != nil { 30 + http.Error(w, "Page not found", http.StatusNotFound) 31 + } 32 + }
+3 -3
pkg/appview/handlers/repository.go
··· 37 37 // Resolve identifier (handle or DID) to canonical DID and current handle 38 38 did, resolvedHandle, _, err := atproto.ResolveIdentity(r.Context(), identifier) 39 39 if err != nil { 40 - http.Error(w, "User not found", http.StatusNotFound) 40 + RenderNotFound(w, r, h.Templates, h.RegistryURL) 41 41 return 42 42 } 43 43 ··· 48 48 return 49 49 } 50 50 if owner == nil { 51 - http.Error(w, "User not found", http.StatusNotFound) 51 + RenderNotFound(w, r, h.Templates, h.RegistryURL) 52 52 return 53 53 } 54 54 ··· 136 136 } 137 137 138 138 if len(tagsWithPlatforms) == 0 && len(manifests) == 0 { 139 - http.Error(w, "Repository not found", http.StatusNotFound) 139 + RenderNotFound(w, r, h.Templates, h.RegistryURL) 140 140 return 141 141 } 142 142
+1 -1
pkg/appview/handlers/user.go
··· 23 23 // Resolve identifier (handle or DID) to canonical DID and current handle 24 24 did, resolvedHandle, pdsEndpoint, err := atproto.ResolveIdentity(r.Context(), identifier) 25 25 if err != nil { 26 - http.Error(w, "User not found", http.StatusNotFound) 26 + RenderNotFound(w, r, h.Templates, h.RegistryURL) 27 27 return 28 28 } 29 29
+8
pkg/appview/routes/routes.go
··· 224 224 } 225 225 router.Get("/auth/logout", logoutHandler.ServeHTTP) 226 226 router.Post("/auth/logout", logoutHandler.ServeHTTP) 227 + 228 + // Custom 404 handler 229 + router.NotFound(middleware.OptionalAuth(deps.SessionStore, deps.Database)( 230 + &uihandlers.NotFoundHandler{ 231 + Templates: deps.Templates, 232 + RegistryURL: registryURL, 233 + }, 234 + ).ServeHTTP) 227 235 } 228 236 229 237 // CORSMiddleware returns a middleware that sets CORS headers for API endpoints
+56
pkg/appview/static/css/style.css
··· 2373 2373 padding: 0.75rem; 2374 2374 } 2375 2375 } 2376 + 2377 + /* 404 Error Page */ 2378 + .error-page { 2379 + display: flex; 2380 + align-items: center; 2381 + justify-content: center; 2382 + min-height: calc(100vh - 60px); 2383 + text-align: center; 2384 + padding: 2rem; 2385 + } 2386 + 2387 + .error-content { 2388 + max-width: 480px; 2389 + } 2390 + 2391 + .error-icon { 2392 + width: 80px; 2393 + height: 80px; 2394 + color: var(--secondary); 2395 + margin-bottom: 1.5rem; 2396 + } 2397 + 2398 + .error-code { 2399 + font-size: 8rem; 2400 + font-weight: 700; 2401 + color: var(--primary); 2402 + line-height: 1; 2403 + margin-bottom: 0.5rem; 2404 + } 2405 + 2406 + .error-content h1 { 2407 + font-size: 2rem; 2408 + margin-bottom: 0.75rem; 2409 + color: var(--fg); 2410 + } 2411 + 2412 + .error-content p { 2413 + font-size: 1.125rem; 2414 + color: var(--secondary); 2415 + margin-bottom: 2rem; 2416 + } 2417 + 2418 + @media (max-width: 768px) { 2419 + .error-code { 2420 + font-size: 5rem; 2421 + } 2422 + 2423 + .error-icon { 2424 + width: 60px; 2425 + height: 60px; 2426 + } 2427 + 2428 + .error-content h1 { 2429 + font-size: 1.5rem; 2430 + } 2431 + }
+22
pkg/appview/templates/pages/404.html
··· 1 + {{ define "404" }} 2 + <!DOCTYPE html> 3 + <html lang="en"> 4 + <head> 5 + <title>404 - Lost at Sea | ATCR</title> 6 + {{ template "head" . }} 7 + </head> 8 + <body> 9 + {{ template "nav-simple" . }} 10 + <main class="error-page"> 11 + <div class="error-content"> 12 + <i data-lucide="anchor" class="error-icon"></i> 13 + <div class="error-code">404</div> 14 + <h1>Lost at Sea</h1> 15 + <p>The page you're looking for has drifted into uncharted waters.</p> 16 + <a href="/" class="btn btn-primary">Return to Port</a> 17 + </div> 18 + </main> 19 + <script>lucide.createIcons();</script> 20 + </body> 21 + </html> 22 + {{ end }}