···974974 w.WriteHeader(http.StatusOK)
975975}
976976977977+// About page
978978+func (h *Handler) HandleAbout(w http.ResponseWriter, r *http.Request) {
979979+ // Check if user is authenticated
980980+ didStr, err := atproto.GetAuthenticatedDID(r.Context())
981981+ isAuthenticated := err == nil && didStr != ""
982982+983983+ data := &bff.PageData{
984984+ Title: "About",
985985+ IsAuthenticated: isAuthenticated,
986986+ UserDID: didStr,
987987+ }
988988+989989+ if err := bff.RenderTemplate(w, "about.tmpl", data); err != nil {
990990+ http.Error(w, "Failed to render page", http.StatusInternalServerError)
991991+ log.Error().Err(err).Msg("Failed to render about page")
992992+ }
993993+}
994994+995995+// Terms of Service page
996996+func (h *Handler) HandleTerms(w http.ResponseWriter, r *http.Request) {
997997+ // Check if user is authenticated
998998+ didStr, err := atproto.GetAuthenticatedDID(r.Context())
999999+ isAuthenticated := err == nil && didStr != ""
10001000+10011001+ data := &bff.PageData{
10021002+ Title: "Terms of Service",
10031003+ IsAuthenticated: isAuthenticated,
10041004+ UserDID: didStr,
10051005+ }
10061006+10071007+ if err := bff.RenderTemplate(w, "terms.tmpl", data); err != nil {
10081008+ http.Error(w, "Failed to render page", http.StatusInternalServerError)
10091009+ log.Error().Err(err).Msg("Failed to render terms page")
10101010+ }
10111011+}
10121012+9771013// fetchAllData is a helper that fetches all data types in parallel using errgroup.
9781014// This is used by handlers that need beans, roasters, grinders, and brewers.
9791015func fetchAllData(ctx context.Context, store database.Store) (
+2
internal/routing/routing.go
···48484949 // Page routes (must come before static files)
5050 mux.HandleFunc("GET /{$}", h.HandleHome) // {$} means exact match
5151+ mux.HandleFunc("GET /about", h.HandleAbout)
5252+ mux.HandleFunc("GET /terms", h.HandleTerms)
5153 mux.HandleFunc("GET /manage", h.HandleManage)
5254 mux.HandleFunc("GET /brews", h.HandleBrewList)
5355 mux.HandleFunc("GET /brews/new", h.HandleBrewNew)
+95
templates/about.tmpl
···11+{{template "layout" .}}
22+33+{{define "content"}}
44+<div class="max-w-3xl mx-auto">
55+ <h1 class="text-4xl font-bold text-brown-800 mb-8">About Arabica</h1>
66+77+ <div class="prose prose-lg max-w-none space-y-6">
88+ <section>
99+ <h2 class="text-2xl font-semibold text-brown-800 mb-4">Your Coffee Journey, Your Data</h2>
1010+ <p class="text-gray-700 leading-relaxed">
1111+ Arabica is a coffee brew tracking application built on the AT Protocol, a decentralized social networking protocol.
1212+ Unlike traditional apps where your data is locked in a company's database, Arabica stores your brew logs,
1313+ coffee beans, and equipment information in <strong>your own Personal Data Server (PDS)</strong>.
1414+ </p>
1515+ </section>
1616+1717+ <section class="bg-brown-50 p-6 rounded-lg">
1818+ <h3 class="text-xl font-semibold text-brown-800 mb-3">What Makes Arabica Different?</h3>
1919+ <ul class="list-disc list-inside space-y-2 text-gray-700">
2020+ <li><strong>You own your data</strong> - All your brew logs live in your PDS, not our servers</li>
2121+ <li><strong>Portable identity</strong> - Switch PDS providers anytime without losing your data</li>
2222+ <li><strong>Privacy by design</strong> - You control who sees your brews</li>
2323+ <li><strong>Open protocol</strong> - Built on the AT Protocol, the same technology powering Bluesky</li>
2424+ </ul>
2525+ </section>
2626+2727+ <section>
2828+ <h2 class="text-2xl font-semibold text-brown-800 mb-4">Features</h2>
2929+ <div class="grid md:grid-cols-2 gap-4">
3030+ <div class="bg-white border border-gray-200 p-4 rounded-lg">
3131+ <h4 class="font-semibold text-brown-800 mb-2">Track Your Brews</h4>
3232+ <p class="text-gray-600 text-sm">Log every detail: beans, grind size, water temp, brew time, and tasting notes</p>
3333+ </div>
3434+ <div class="bg-white border border-gray-200 p-4 rounded-lg">
3535+ <h4 class="font-semibold text-brown-800 mb-2">Manage Equipment</h4>
3636+ <p class="text-gray-600 text-sm">Keep track of your grinders, brewers, beans, and roasters</p>
3737+ </div>
3838+ <div class="bg-white border border-gray-200 p-4 rounded-lg">
3939+ <h4 class="font-semibold text-brown-800 mb-2">Community Feed</h4>
4040+ <p class="text-gray-600 text-sm">Share your best brews with the community (coming soon: likes and comments!)</p>
4141+ </div>
4242+ <div class="bg-white border border-gray-200 p-4 rounded-lg">
4343+ <h4 class="font-semibold text-brown-800 mb-2">Export Your Data</h4>
4444+ <p class="text-gray-600 text-sm">Export all your brews anytime in JSON format</p>
4545+ </div>
4646+ </div>
4747+ </section>
4848+4949+ <section>
5050+ <h2 class="text-2xl font-semibold text-brown-800 mb-4">The AT Protocol Advantage</h2>
5151+ <p class="text-gray-700 leading-relaxed">
5252+ The AT Protocol is a decentralized social networking protocol that gives users true ownership of their data
5353+ and identity. When you use Arabica:
5454+ </p>
5555+ <ul class="list-disc list-inside space-y-2 text-gray-700 mt-3">
5656+ <li>Your brew data is stored as ATProto records in collections on your PDS</li>
5757+ <li>You authenticate via OAuth with your PDS, not with us</li>
5858+ <li>References between records (like linking a brew to a bean) use AT-URIs</li>
5959+ <li>Your identity is portable - change PDS providers without losing your account</li>
6060+ </ul>
6161+ </section>
6262+6363+ <section class="bg-blue-50 border border-blue-200 p-6 rounded-lg">
6464+ <h3 class="text-xl font-semibold text-blue-900 mb-3">Getting Started</h3>
6565+ <p class="text-gray-700 mb-4">
6666+ To use Arabica, you'll need an account on a PDS that supports the AT Protocol.
6767+ 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>.
6868+ </p>
6969+ <p class="text-gray-700">
7070+ Once you have an account, simply log in with your handle (e.g., yourname.bsky.social) and start tracking your brews!
7171+ </p>
7272+ </section>
7373+7474+ <section>
7575+ <h2 class="text-2xl font-semibold text-brown-800 mb-4">Open Source</h2>
7676+ <p class="text-gray-700 leading-relaxed">
7777+ Arabica is open source software. You can view the code, contribute, or even run your own instance.
7878+ 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.
7979+ </p>
8080+ </section>
8181+ </div>
8282+8383+ <div class="mt-12 text-center">
8484+ {{if not .IsAuthenticated}}
8585+ <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">
8686+ Get Started
8787+ </a>
8888+ {{else}}
8989+ <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">
9090+ Log Your Next Brew
9191+ </a>
9292+ {{end}}
9393+ </div>
9494+</div>
9595+{{end}}
···11+{{template "layout" .}}
22+33+{{define "content"}}
44+<div class="max-w-3xl mx-auto">
55+ <h1 class="text-4xl font-bold text-brown-800 mb-8">Terms of Service</h1>
66+77+ <div class="prose prose-lg max-w-none space-y-6">
88+ <section class="bg-green-50 border border-green-200 p-6 rounded-lg mb-8">
99+ <h2 class="text-2xl font-semibold text-green-900 mb-4">The Simple Truth</h2>
1010+ <p class="text-gray-800 text-lg leading-relaxed">
1111+ <strong>You own all of your data.</strong> Period. Your brew logs, coffee beans, equipment information,
1212+ and any other data you create in Arabica belongs to you and is stored in your Personal Data Server (PDS),
1313+ not on our servers.
1414+ </p>
1515+ </section>
1616+1717+ <section>
1818+ <h2 class="text-2xl font-semibold text-brown-800 mb-4">1. Your Data Ownership</h2>
1919+ <p class="text-gray-700 leading-relaxed">
2020+ All data you create through Arabica is stored in your AT Protocol Personal Data Server (PDS).
2121+ Arabica acts as an interface to your PDS but does not own, claim rights to, or permanently store your data.
2222+ </p>
2323+ <ul class="list-disc list-inside space-y-2 text-gray-700 mt-3">
2424+ <li>You retain full ownership and control of your data</li>
2525+ <li>You can export your data at any time</li>
2626+ <li>You can delete your data at any time</li>
2727+ <li>You can switch PDS providers without losing your data</li>
2828+ <li>You can stop using Arabica and your data remains in your PDS</li>
2929+ </ul>
3030+ </section>
3131+3232+ <section>
3333+ <h2 class="text-2xl font-semibold text-brown-800 mb-4">2. What We Store</h2>
3434+ <p class="text-gray-700 leading-relaxed mb-3">
3535+ Arabica's servers store minimal data necessary for the application to function:
3636+ </p>
3737+ <ul class="list-disc list-inside space-y-2 text-gray-700">
3838+ <li><strong>Session information</strong> - Temporary authentication tokens to keep you logged in</li>
3939+ <li><strong>Feed registry</strong> - List of users who've opted into the community feed</li>
4040+ <li><strong>Temporary cache</strong> - Short-lived cache (5 minutes) of your data to improve performance</li>
4141+ </ul>
4242+ <p class="text-gray-700 leading-relaxed mt-3">
4343+ We do <strong>not</strong> store your brew logs, beans, equipment, or any other user-generated content
4444+ on our servers. That data lives exclusively in your PDS.
4545+ </p>
4646+ </section>
4747+4848+ <section>
4949+ <h2 class="text-2xl font-semibold text-brown-800 mb-4">3. Authentication</h2>
5050+ <p class="text-gray-700 leading-relaxed">
5151+ Arabica uses OAuth to authenticate with your PDS. We never see or store your PDS password.
5252+ Authentication is handled between your browser and your PDS, with Arabica receiving only
5353+ temporary access tokens to read and write data on your behalf.
5454+ </p>
5555+ </section>
5656+5757+ <section>
5858+ <h2 class="text-2xl font-semibold text-brown-800 mb-4">4. Community Feed</h2>
5959+ <p class="text-gray-700 leading-relaxed">
6060+ If you opt into the community feed, Arabica will periodically read your public brew records
6161+ from your PDS to display them to other users. This is done by:
6262+ </p>
6363+ <ul class="list-disc list-inside space-y-2 text-gray-700 mt-3">
6464+ <li>Making public API calls to your PDS</li>
6565+ <li>Temporarily caching brew data for feed display</li>
6666+ <li>Not storing your data permanently on our servers</li>
6767+ </ul>
6868+ <p class="text-gray-700 leading-relaxed mt-3">
6969+ You can opt out of the community feed at any time, and we'll stop reading your brews.
7070+ </p>
7171+ </section>
7272+7373+ <section>
7474+ <h2 class="text-2xl font-semibold text-brown-800 mb-4">5. Service Availability</h2>
7575+ <p class="text-gray-700 leading-relaxed">
7676+ Arabica is provided "as is" without warranties of any kind. We make reasonable efforts to keep
7777+ the service running but do not guarantee uptime or availability. Since your data is stored in
7878+ your PDS (not our servers), you won't lose your data if Arabica goes offline.
7979+ </p>
8080+ </section>
8181+8282+ <section>
8383+ <h2 class="text-2xl font-semibold text-brown-800 mb-4">6. Privacy</h2>
8484+ <p class="text-gray-700 leading-relaxed">
8585+ We respect your privacy and follow these principles:
8686+ </p>
8787+ <ul class="list-disc list-inside space-y-2 text-gray-700 mt-3">
8888+ <li>We don't sell your data (because we don't have it to sell!)</li>
8989+ <li>We don't track you across websites</li>
9090+ <li>We use minimal analytics to understand service usage</li>
9191+ <li>We don't share your data with third parties</li>
9292+ <li>Your PDS and the AT Protocol control the privacy of your brew data</li>
9393+ </ul>
9494+ </section>
9595+9696+ <section>
9797+ <h2 class="text-2xl font-semibold text-brown-800 mb-4">7. Open Source</h2>
9898+ <p class="text-gray-700 leading-relaxed">
9999+ Arabica is open source software. You can review the code, run your own instance, or contribute
100100+ improvements. The transparency of open source means you can verify that we're handling your data
101101+ as described in these terms.
102102+ </p>
103103+ </section>
104104+105105+ <section>
106106+ <h2 class="text-2xl font-semibold text-brown-800 mb-4">8. Changes to Terms</h2>
107107+ <p class="text-gray-700 leading-relaxed">
108108+ We may update these terms occasionally. If we make significant changes, we'll notify users through
109109+ the application. Continued use of Arabica after changes constitutes acceptance of the new terms.
110110+ </p>
111111+ </section>
112112+113113+ <section>
114114+ <h2 class="text-2xl font-semibold text-brown-800 mb-4">9. Acceptable Use</h2>
115115+ <p class="text-gray-700 leading-relaxed">
116116+ Please use Arabica responsibly:
117117+ </p>
118118+ <ul class="list-disc list-inside space-y-2 text-gray-700 mt-3">
119119+ <li>Don't attempt to access other users' data without permission</li>
120120+ <li>Don't abuse the service with excessive API requests</li>
121121+ <li>Don't use Arabica for illegal purposes</li>
122122+ <li>Be respectful in community interactions</li>
123123+ </ul>
124124+ </section>
125125+126126+ <section>
127127+ <h2 class="text-2xl font-semibold text-brown-800 mb-4">10. Contact</h2>
128128+ <p class="text-gray-700 leading-relaxed">
129129+ Questions about these terms? You can reach us through our GitHub repository or by email at
130130+ <a href="mailto:contact@example.com" class="text-blue-600 hover:underline">contact@example.com</a>
131131+ (placeholder).
132132+ </p>
133133+ </section>
134134+135135+ <section class="bg-gray-100 p-6 rounded-lg mt-8">
136136+ <p class="text-sm text-gray-600">
137137+ <strong>Last Updated:</strong> January 2026<br>
138138+ <strong>Effective Date:</strong> January 2026
139139+ </p>
140140+ </section>
141141+ </div>
142142+143143+ <div class="mt-12 text-center">
144144+ <a href="/" class="text-blue-600 hover:underline">Back to Home</a>
145145+ </div>
146146+</div>
147147+{{end}}