Coffee journaling on ATProto (alpha) alpha.arabica.social
coffee

feat: footer, tos, about page placeholders

pdewey.com 99754cd6 2d7c59cd

verified
+281
+36
internal/handlers/handlers.go
··· 974 w.WriteHeader(http.StatusOK) 975 } 976 977 // fetchAllData is a helper that fetches all data types in parallel using errgroup. 978 // This is used by handlers that need beans, roasters, grinders, and brewers. 979 func fetchAllData(ctx context.Context, store database.Store) (
··· 974 w.WriteHeader(http.StatusOK) 975 } 976 977 + // About page 978 + func (h *Handler) HandleAbout(w http.ResponseWriter, r *http.Request) { 979 + // Check if user is authenticated 980 + didStr, err := atproto.GetAuthenticatedDID(r.Context()) 981 + isAuthenticated := err == nil && didStr != "" 982 + 983 + data := &bff.PageData{ 984 + Title: "About", 985 + IsAuthenticated: isAuthenticated, 986 + UserDID: didStr, 987 + } 988 + 989 + if err := bff.RenderTemplate(w, "about.tmpl", data); err != nil { 990 + http.Error(w, "Failed to render page", http.StatusInternalServerError) 991 + log.Error().Err(err).Msg("Failed to render about page") 992 + } 993 + } 994 + 995 + // Terms of Service page 996 + func (h *Handler) HandleTerms(w http.ResponseWriter, r *http.Request) { 997 + // Check if user is authenticated 998 + didStr, err := atproto.GetAuthenticatedDID(r.Context()) 999 + isAuthenticated := err == nil && didStr != "" 1000 + 1001 + data := &bff.PageData{ 1002 + Title: "Terms of Service", 1003 + IsAuthenticated: isAuthenticated, 1004 + UserDID: didStr, 1005 + } 1006 + 1007 + if err := bff.RenderTemplate(w, "terms.tmpl", data); err != nil { 1008 + http.Error(w, "Failed to render page", http.StatusInternalServerError) 1009 + log.Error().Err(err).Msg("Failed to render terms page") 1010 + } 1011 + } 1012 + 1013 // fetchAllData is a helper that fetches all data types in parallel using errgroup. 1014 // This is used by handlers that need beans, roasters, grinders, and brewers. 1015 func fetchAllData(ctx context.Context, store database.Store) (
+2
internal/routing/routing.go
··· 48 49 // Page routes (must come before static files) 50 mux.HandleFunc("GET /{$}", h.HandleHome) // {$} means exact match 51 mux.HandleFunc("GET /manage", h.HandleManage) 52 mux.HandleFunc("GET /brews", h.HandleBrewList) 53 mux.HandleFunc("GET /brews/new", h.HandleBrewNew)
··· 48 49 // Page routes (must come before static files) 50 mux.HandleFunc("GET /{$}", h.HandleHome) // {$} means exact match 51 + mux.HandleFunc("GET /about", h.HandleAbout) 52 + mux.HandleFunc("GET /terms", h.HandleTerms) 53 mux.HandleFunc("GET /manage", h.HandleManage) 54 mux.HandleFunc("GET /brews", h.HandleBrewList) 55 mux.HandleFunc("GET /brews/new", h.HandleBrewNew)
+95
templates/about.tmpl
···
··· 1 + {{template "layout" .}} 2 + 3 + {{define "content"}} 4 + <div class="max-w-3xl mx-auto"> 5 + <h1 class="text-4xl font-bold text-brown-800 mb-8">About Arabica</h1> 6 + 7 + <div class="prose prose-lg max-w-none space-y-6"> 8 + <section> 9 + <h2 class="text-2xl font-semibold text-brown-800 mb-4">Your Coffee Journey, Your Data</h2> 10 + <p class="text-gray-700 leading-relaxed"> 11 + Arabica is a coffee brew tracking application built on the AT Protocol, a decentralized social networking protocol. 12 + Unlike traditional apps where your data is locked in a company's database, Arabica stores your brew logs, 13 + coffee beans, and equipment information in <strong>your own Personal Data Server (PDS)</strong>. 14 + </p> 15 + </section> 16 + 17 + <section class="bg-brown-50 p-6 rounded-lg"> 18 + <h3 class="text-xl font-semibold text-brown-800 mb-3">What Makes Arabica Different?</h3> 19 + <ul class="list-disc list-inside space-y-2 text-gray-700"> 20 + <li><strong>You own your data</strong> - All your brew logs live in your PDS, not our servers</li> 21 + <li><strong>Portable identity</strong> - Switch PDS providers anytime without losing your data</li> 22 + <li><strong>Privacy by design</strong> - You control who sees your brews</li> 23 + <li><strong>Open protocol</strong> - Built on the AT Protocol, the same technology powering Bluesky</li> 24 + </ul> 25 + </section> 26 + 27 + <section> 28 + <h2 class="text-2xl font-semibold text-brown-800 mb-4">Features</h2> 29 + <div class="grid md:grid-cols-2 gap-4"> 30 + <div class="bg-white border border-gray-200 p-4 rounded-lg"> 31 + <h4 class="font-semibold text-brown-800 mb-2">Track Your Brews</h4> 32 + <p class="text-gray-600 text-sm">Log every detail: beans, grind size, water temp, brew time, and tasting notes</p> 33 + </div> 34 + <div class="bg-white border border-gray-200 p-4 rounded-lg"> 35 + <h4 class="font-semibold text-brown-800 mb-2">Manage Equipment</h4> 36 + <p class="text-gray-600 text-sm">Keep track of your grinders, brewers, beans, and roasters</p> 37 + </div> 38 + <div class="bg-white border border-gray-200 p-4 rounded-lg"> 39 + <h4 class="font-semibold text-brown-800 mb-2">Community Feed</h4> 40 + <p class="text-gray-600 text-sm">Share your best brews with the community (coming soon: likes and comments!)</p> 41 + </div> 42 + <div class="bg-white border border-gray-200 p-4 rounded-lg"> 43 + <h4 class="font-semibold text-brown-800 mb-2">Export Your Data</h4> 44 + <p class="text-gray-600 text-sm">Export all your brews anytime in JSON format</p> 45 + </div> 46 + </div> 47 + </section> 48 + 49 + <section> 50 + <h2 class="text-2xl font-semibold text-brown-800 mb-4">The AT Protocol Advantage</h2> 51 + <p class="text-gray-700 leading-relaxed"> 52 + The AT Protocol is a decentralized social networking protocol that gives users true ownership of their data 53 + and identity. When you use Arabica: 54 + </p> 55 + <ul class="list-disc list-inside space-y-2 text-gray-700 mt-3"> 56 + <li>Your brew data is stored as ATProto records in collections on your PDS</li> 57 + <li>You authenticate via OAuth with your PDS, not with us</li> 58 + <li>References between records (like linking a brew to a bean) use AT-URIs</li> 59 + <li>Your identity is portable - change PDS providers without losing your account</li> 60 + </ul> 61 + </section> 62 + 63 + <section class="bg-blue-50 border border-blue-200 p-6 rounded-lg"> 64 + <h3 class="text-xl font-semibold text-blue-900 mb-3">Getting Started</h3> 65 + <p class="text-gray-700 mb-4"> 66 + To use Arabica, you'll need an account on a PDS that supports the AT Protocol. 67 + The easiest way is to create a Bluesky account at <a href="https://bsky.app" class="text-blue-600 hover:underline" target="_blank" rel="noopener noreferrer">bsky.app</a>. 68 + </p> 69 + <p class="text-gray-700"> 70 + Once you have an account, simply log in with your handle (e.g., yourname.bsky.social) and start tracking your brews! 71 + </p> 72 + </section> 73 + 74 + <section> 75 + <h2 class="text-2xl font-semibold text-brown-800 mb-4">Open Source</h2> 76 + <p class="text-gray-700 leading-relaxed"> 77 + Arabica is open source software. You can view the code, contribute, or even run your own instance. 78 + Visit our <a href="https://github.com/placeholder/arabica" class="text-blue-600 hover:underline" target="_blank" rel="noopener noreferrer">GitHub repository</a> to learn more. 79 + </p> 80 + </section> 81 + </div> 82 + 83 + <div class="mt-12 text-center"> 84 + {{if not .IsAuthenticated}} 85 + <a href="/login" class="inline-block bg-brown-800 text-white px-8 py-3 rounded-lg hover:bg-brown-700 transition-colors font-semibold"> 86 + Get Started 87 + </a> 88 + {{else}} 89 + <a href="/brews/new" class="inline-block bg-brown-800 text-white px-8 py-3 rounded-lg hover:bg-brown-700 transition-colors font-semibold"> 90 + Log Your Next Brew 91 + </a> 92 + {{end}} 93 + </div> 94 + </div> 95 + {{end}}
+1
templates/layout.tmpl
··· 41 <main class="container mx-auto px-4 py-8"> 42 {{template "content" .}} 43 </main> 44 </body> 45 </html> 46 {{end}}
··· 41 <main class="container mx-auto px-4 py-8"> 42 {{template "content" .}} 43 </main> 44 + {{template "footer" .}} 45 </body> 46 </html> 47 {{end}}
+147
templates/terms.tmpl
···
··· 1 + {{template "layout" .}} 2 + 3 + {{define "content"}} 4 + <div class="max-w-3xl mx-auto"> 5 + <h1 class="text-4xl font-bold text-brown-800 mb-8">Terms of Service</h1> 6 + 7 + <div class="prose prose-lg max-w-none space-y-6"> 8 + <section class="bg-green-50 border border-green-200 p-6 rounded-lg mb-8"> 9 + <h2 class="text-2xl font-semibold text-green-900 mb-4">The Simple Truth</h2> 10 + <p class="text-gray-800 text-lg leading-relaxed"> 11 + <strong>You own all of your data.</strong> Period. Your brew logs, coffee beans, equipment information, 12 + and any other data you create in Arabica belongs to you and is stored in your Personal Data Server (PDS), 13 + not on our servers. 14 + </p> 15 + </section> 16 + 17 + <section> 18 + <h2 class="text-2xl font-semibold text-brown-800 mb-4">1. Your Data Ownership</h2> 19 + <p class="text-gray-700 leading-relaxed"> 20 + All data you create through Arabica is stored in your AT Protocol Personal Data Server (PDS). 21 + Arabica acts as an interface to your PDS but does not own, claim rights to, or permanently store your data. 22 + </p> 23 + <ul class="list-disc list-inside space-y-2 text-gray-700 mt-3"> 24 + <li>You retain full ownership and control of your data</li> 25 + <li>You can export your data at any time</li> 26 + <li>You can delete your data at any time</li> 27 + <li>You can switch PDS providers without losing your data</li> 28 + <li>You can stop using Arabica and your data remains in your PDS</li> 29 + </ul> 30 + </section> 31 + 32 + <section> 33 + <h2 class="text-2xl font-semibold text-brown-800 mb-4">2. What We Store</h2> 34 + <p class="text-gray-700 leading-relaxed mb-3"> 35 + Arabica's servers store minimal data necessary for the application to function: 36 + </p> 37 + <ul class="list-disc list-inside space-y-2 text-gray-700"> 38 + <li><strong>Session information</strong> - Temporary authentication tokens to keep you logged in</li> 39 + <li><strong>Feed registry</strong> - List of users who've opted into the community feed</li> 40 + <li><strong>Temporary cache</strong> - Short-lived cache (5 minutes) of your data to improve performance</li> 41 + </ul> 42 + <p class="text-gray-700 leading-relaxed mt-3"> 43 + We do <strong>not</strong> store your brew logs, beans, equipment, or any other user-generated content 44 + on our servers. That data lives exclusively in your PDS. 45 + </p> 46 + </section> 47 + 48 + <section> 49 + <h2 class="text-2xl font-semibold text-brown-800 mb-4">3. Authentication</h2> 50 + <p class="text-gray-700 leading-relaxed"> 51 + Arabica uses OAuth to authenticate with your PDS. We never see or store your PDS password. 52 + Authentication is handled between your browser and your PDS, with Arabica receiving only 53 + temporary access tokens to read and write data on your behalf. 54 + </p> 55 + </section> 56 + 57 + <section> 58 + <h2 class="text-2xl font-semibold text-brown-800 mb-4">4. Community Feed</h2> 59 + <p class="text-gray-700 leading-relaxed"> 60 + If you opt into the community feed, Arabica will periodically read your public brew records 61 + from your PDS to display them to other users. This is done by: 62 + </p> 63 + <ul class="list-disc list-inside space-y-2 text-gray-700 mt-3"> 64 + <li>Making public API calls to your PDS</li> 65 + <li>Temporarily caching brew data for feed display</li> 66 + <li>Not storing your data permanently on our servers</li> 67 + </ul> 68 + <p class="text-gray-700 leading-relaxed mt-3"> 69 + You can opt out of the community feed at any time, and we'll stop reading your brews. 70 + </p> 71 + </section> 72 + 73 + <section> 74 + <h2 class="text-2xl font-semibold text-brown-800 mb-4">5. Service Availability</h2> 75 + <p class="text-gray-700 leading-relaxed"> 76 + Arabica is provided "as is" without warranties of any kind. We make reasonable efforts to keep 77 + the service running but do not guarantee uptime or availability. Since your data is stored in 78 + your PDS (not our servers), you won't lose your data if Arabica goes offline. 79 + </p> 80 + </section> 81 + 82 + <section> 83 + <h2 class="text-2xl font-semibold text-brown-800 mb-4">6. Privacy</h2> 84 + <p class="text-gray-700 leading-relaxed"> 85 + We respect your privacy and follow these principles: 86 + </p> 87 + <ul class="list-disc list-inside space-y-2 text-gray-700 mt-3"> 88 + <li>We don't sell your data (because we don't have it to sell!)</li> 89 + <li>We don't track you across websites</li> 90 + <li>We use minimal analytics to understand service usage</li> 91 + <li>We don't share your data with third parties</li> 92 + <li>Your PDS and the AT Protocol control the privacy of your brew data</li> 93 + </ul> 94 + </section> 95 + 96 + <section> 97 + <h2 class="text-2xl font-semibold text-brown-800 mb-4">7. Open Source</h2> 98 + <p class="text-gray-700 leading-relaxed"> 99 + Arabica is open source software. You can review the code, run your own instance, or contribute 100 + improvements. The transparency of open source means you can verify that we're handling your data 101 + as described in these terms. 102 + </p> 103 + </section> 104 + 105 + <section> 106 + <h2 class="text-2xl font-semibold text-brown-800 mb-4">8. Changes to Terms</h2> 107 + <p class="text-gray-700 leading-relaxed"> 108 + We may update these terms occasionally. If we make significant changes, we'll notify users through 109 + the application. Continued use of Arabica after changes constitutes acceptance of the new terms. 110 + </p> 111 + </section> 112 + 113 + <section> 114 + <h2 class="text-2xl font-semibold text-brown-800 mb-4">9. Acceptable Use</h2> 115 + <p class="text-gray-700 leading-relaxed"> 116 + Please use Arabica responsibly: 117 + </p> 118 + <ul class="list-disc list-inside space-y-2 text-gray-700 mt-3"> 119 + <li>Don't attempt to access other users' data without permission</li> 120 + <li>Don't abuse the service with excessive API requests</li> 121 + <li>Don't use Arabica for illegal purposes</li> 122 + <li>Be respectful in community interactions</li> 123 + </ul> 124 + </section> 125 + 126 + <section> 127 + <h2 class="text-2xl font-semibold text-brown-800 mb-4">10. Contact</h2> 128 + <p class="text-gray-700 leading-relaxed"> 129 + Questions about these terms? You can reach us through our GitHub repository or by email at 130 + <a href="mailto:contact@example.com" class="text-blue-600 hover:underline">contact@example.com</a> 131 + (placeholder). 132 + </p> 133 + </section> 134 + 135 + <section class="bg-gray-100 p-6 rounded-lg mt-8"> 136 + <p class="text-sm text-gray-600"> 137 + <strong>Last Updated:</strong> January 2026<br> 138 + <strong>Effective Date:</strong> January 2026 139 + </p> 140 + </section> 141 + </div> 142 + 143 + <div class="mt-12 text-center"> 144 + <a href="/" class="text-blue-600 hover:underline">Back to Home</a> 145 + </div> 146 + </div> 147 + {{end}}