From c473c88c3339849448d85a33da28a9c03bcad0fe Mon Sep 17 00:00:00 2001 From: juancwu Date: Fri, 30 Jan 2026 03:21:12 +0000 Subject: [PATCH] feat: add terms and privacy pages --- internal/handler/home.go | 8 ++ internal/routes/routes.go | 2 + internal/ui/components/icon/icon_data.go | 12 +-- internal/ui/components/icon/icon_defs.go | 1 + internal/ui/pages/auth.templ | 8 ++ internal/ui/pages/auth_password.templ | 8 ++ internal/ui/pages/privacy.templ | 103 +++++++++++++++++++++++ internal/ui/pages/public_notfound.templ | 7 ++ internal/ui/pages/terms.templ | 97 +++++++++++++++++++++ 9 files changed, 240 insertions(+), 6 deletions(-) create mode 100644 internal/ui/pages/privacy.templ create mode 100644 internal/ui/pages/terms.templ diff --git a/internal/handler/home.go b/internal/handler/home.go index 4d150c2..42d6dd5 100644 --- a/internal/handler/home.go +++ b/internal/handler/home.go @@ -24,6 +24,14 @@ func (h *homeHandler) HomePage(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/app/dashboard", http.StatusSeeOther) } +func (h *homeHandler) PrivacyPage(w http.ResponseWriter, r *http.Request) { + ui.Render(w, r, pages.Privacy()) +} + +func (h *homeHandler) TermsPage(w http.ResponseWriter, r *http.Request) { + ui.Render(w, r, pages.Terms()) +} + func (home *homeHandler) NotFoundPage(w http.ResponseWriter, r *http.Request) { ui.Render(w, r, pages.NotFound()) } diff --git a/internal/routes/routes.go b/internal/routes/routes.go index 35d115c..1612132 100644 --- a/internal/routes/routes.go +++ b/internal/routes/routes.go @@ -29,6 +29,8 @@ func SetupRoutes(a *app.App) http.Handler { // Home mux.HandleFunc("GET /{$}", home.HomePage) mux.HandleFunc("GET /forbidden", home.ForbiddenPage) + mux.HandleFunc("GET /privacy", home.PrivacyPage) + mux.HandleFunc("GET /terms", home.TermsPage) // Auth pages authRateLimiter := middleware.RateLimitAuth() diff --git a/internal/ui/components/icon/icon_data.go b/internal/ui/components/icon/icon_data.go index b703eaf..b2823e8 100644 --- a/internal/ui/components/icon/icon_data.go +++ b/internal/ui/components/icon/icon_data.go @@ -122,7 +122,7 @@ var internalSvgData = map[string]string{ `, "chevron-down": ``, "circle-small": ``, - "command": ``, + "command": ``, "id-card": ` @@ -1761,7 +1761,7 @@ var internalSvgData = map[string]string{ "folder-closed": ` `, "flag-triangle-right": ``, - "funnel": ``, + "funnel": ``, "phone-missed": ` `, @@ -2466,7 +2466,7 @@ var internalSvgData = map[string]string{ `, - "wifi-zero": ``, + "wifi-zero": ``, "arrow-big-right": ``, "bell-electric": ` @@ -3419,7 +3419,7 @@ var internalSvgData = map[string]string{ `, "arrow-big-up": ``, - "headphones": ``, + "headphones": ``, "medal": ` @@ -5173,7 +5173,7 @@ var internalSvgData = map[string]string{ "square-stop": ` `, "triangle-right": ``, - "triangle": ``, + "triangle": ``, "wallet-minimal": ` `, "dessert": ` @@ -6160,7 +6160,7 @@ var internalSvgData = map[string]string{ "laptop": ` `, "navigation-2": ``, - "twitter": ``, + "twitter": ``, "wine": ` diff --git a/internal/ui/components/icon/icon_defs.go b/internal/ui/components/icon/icon_defs.go index 0e4f42c..ae8dc80 100644 --- a/internal/ui/components/icon/icon_defs.go +++ b/internal/ui/components/icon/icon_defs.go @@ -1,6 +1,7 @@ // templui component icon - version: v1.2.0 installed by templui v1.2.0 // 📚 Documentation: https://templui.io/docs/components/icon package icon + // This file is auto generated // Using Lucide icons version 0.544.0 var AlarmClockOff = Icon("alarm-clock-off") diff --git a/internal/ui/pages/auth.templ b/internal/ui/pages/auth.templ index dc31fbb..5cd8c06 100644 --- a/internal/ui/pages/auth.templ +++ b/internal/ui/pages/auth.templ @@ -70,6 +70,14 @@ templ Auth(errorMsg string) { Sign in with password instead

+ +

+ By continuing, you agree to our +
+ Terms of Service + and + Privacy Policy. +

} diff --git a/internal/ui/pages/auth_password.templ b/internal/ui/pages/auth_password.templ index 17ee020..b670b5c 100644 --- a/internal/ui/pages/auth_password.templ +++ b/internal/ui/pages/auth_password.templ @@ -90,6 +90,14 @@ templ AuthPassword(errorMsg string) { Sign up with magic link

+ +

+ By continuing, you agree to our +
+ Terms of Service + and + Privacy Policy. +

} diff --git a/internal/ui/pages/privacy.templ b/internal/ui/pages/privacy.templ new file mode 100644 index 0000000..8df563a --- /dev/null +++ b/internal/ui/pages/privacy.templ @@ -0,0 +1,103 @@ +package pages + +import ( + "git.juancwu.dev/juancwu/budgit/internal/ctxkeys" + "git.juancwu.dev/juancwu/budgit/internal/ui/layouts" + "git.juancwu.dev/juancwu/budgit/internal/ui/components/button" + "git.juancwu.dev/juancwu/budgit/internal/ui/components/icon" +) + +templ Privacy() { + {{ cfg := ctxkeys.Config(ctx) }} + @layouts.Auth(layouts.SEOProps{ + Title: "Privacy Policy", + Description: "Privacy Policy for " + cfg.AppName, + Path: "/privacy", + }) { +
+
+ @button.Button(button.Props{ + Variant: button.VariantGhost, + Size: button.SizeSm, + Href: "/", + Class: "mb-4", + }) { + @icon.ArrowLeft() + Back to Home + } +

Privacy Policy

+

Last updated: January 30, 2026

+
+
+
+

1. Introduction

+

+ Welcome to { cfg.AppName } ("we," "our," or "us"). We are committed to protecting your personal information and your right to privacy. + This Privacy Policy applies to our website and any related services (collectively, the "Service"). +

+

+ { cfg.AppName } is operated by an individual developer based in Canada as a hobby project. +

+
+
+

2. Information We Collect

+

We collect information that you provide directly to us when you use the Service:

+
    +
  • Account Information: When you register, we collect your email address and name (if provided).
  • +
  • + User Content: We store the financial data, shopping lists, and other content you manually enter into the Service. + Note: We do not connect to your bank accounts or financial institutions. The "financial" data stored is purely what you choose to type in, similar to a spreadsheet. +
  • +
  • Usage Data: We may collect anonymous, aggregated information about how the Service is accessed and used (e.g., pages viewed, time spent) to help us improve the product.
  • +
+
+
+

3. How We Use Your Information

+

We use the information we collect to:

+
    +
  • Provide, maintain, and improve the Service.
  • +
  • Authenticate your identity (via Magic Links or password).
  • +
  • Send you administrative emails (e.g., login links, space invitations, welcome emails).
  • +
  • Respond to your comments or questions.
  • +
+
+
+

4. Cookies and Tracking

+

+ We use cookies and similar technologies primarily for essential functions, such as keeping you logged in. + By using the Service, you consent to the use of these essential cookies. +

+
+
+

5. Data Storage and Third Parties

+

+ Our Service is hosted on virtual private servers provided by Hostinger located in the United States. + While we are based in Canada, your data may be processed and stored in the United States and subject to its laws. +

+

+ We self-host our email delivery system. We do not sell, trade, or otherwise transfer your personally identifiable information to outside parties for marketing purposes. +

+
+
+

6. Children's Privacy

+

+ Our Service is not directed to anyone under the age of 13. We do not knowingly collect personal information from children under 13. +

+
+
+

7. Your Rights

+

+ Depending on your location, you may have rights regarding your personal data, including the right to access, correct, or delete your data. + You can delete your data by deleting your account within the application or by contacting us. +

+
+
+

8. Contact Us

+

+ If you have any questions about this Privacy Policy, please contact us at { cfg.SupportEmail }. +

+
+
+
+ } +} diff --git a/internal/ui/pages/public_notfound.templ b/internal/ui/pages/public_notfound.templ index 69d152a..fae952f 100644 --- a/internal/ui/pages/public_notfound.templ +++ b/internal/ui/pages/public_notfound.templ @@ -1,6 +1,7 @@ package pages import "git.juancwu.dev/juancwu/budgit/internal/ui/layouts" +import "git.juancwu.dev/juancwu/budgit/internal/ctxkeys" templ NotFound() { @layouts.Base() { @@ -12,6 +13,12 @@ templ NotFound() { ← Back to Home + {{ cfg := ctxkeys.Config(ctx) }} + if cfg.SupportEmail != "" { +

+ Need help? Contact { cfg.SupportEmail } +

+ } } diff --git a/internal/ui/pages/terms.templ b/internal/ui/pages/terms.templ new file mode 100644 index 0000000..ce1e47e --- /dev/null +++ b/internal/ui/pages/terms.templ @@ -0,0 +1,97 @@ +package pages + +import ( + "git.juancwu.dev/juancwu/budgit/internal/ctxkeys" + "git.juancwu.dev/juancwu/budgit/internal/ui/layouts" + "git.juancwu.dev/juancwu/budgit/internal/ui/components/button" + "git.juancwu.dev/juancwu/budgit/internal/ui/components/icon" +) + +templ Terms() { + {{ cfg := ctxkeys.Config(ctx) }} + @layouts.Auth(layouts.SEOProps{ + Title: "Terms and Conditions", + Description: "Terms and Conditions for " + cfg.AppName, + Path: "/terms", + }) { +
+
+ @button.Button(button.Props{ + Variant: button.VariantGhost, + Size: button.SizeSm, + Href: "/", + Class: "mb-4", + }) { + @icon.ArrowLeft() + Back to Home + } +

Terms and Conditions

+

Last updated: January 30, 2026

+
+
+
+

1. Agreement to Terms

+

+ By accessing or using { cfg.AppName } (the "Service"), you agree to be bound by these Terms and Conditions. + If you disagree with any part of the terms, you may not access the Service. +

+
+
+

2. Description of Service

+

+ { cfg.AppName } is a personal budgeting and expense tracking tool provided as a hobby project. + It allows users to manually input and track financial data, shopping lists, and related information. +

+
+

Disclaimer: Not Financial Advice

+

+ The Service is for informational and organizational purposes only. It is not intended to provide legal, tax, or financial advice. + We are not responsible for any financial decisions you make based on the information you track within the Service. +

+
+
+
+

3. Accounts

+

+ When you create an account with us, you must provide accurate and complete information. + You are responsible for safeguarding the password or magic link used to access the Service and for any activities or actions under your account. +

+
+
+

4. "As Is" and "As Available" Disclaimer

+

+ The Service is provided on an "AS IS" and "AS AVAILABLE" basis. The Service is provided without warranties of any kind, whether express or implied, including, but not limited to, implied warranties of merchantability, fitness for a particular purpose, non-infringement, or course of performance. +

+

+ As a hobby project, we do not warrant that the Service will function uninterrupted, secure, or available at any particular time or location, or that any errors or defects will be corrected. +

+
+
+

5. Limitation of Liability

+

+ In no event shall the operator, nor any partners, agents, suppliers, or affiliates, be liable for any indirect, incidental, special, consequential or punitive damages, including without limitation, loss of profits, data, use, goodwill, or other intangible losses, resulting from your access to or use of or inability to access or use the Service. +

+
+
+

6. User Conduct

+

+ You agree not to use the Service for any unlawful purpose or in any way that interrupts, damages, or impairs the service. + We reserve the right to terminate or suspend your account immediately, without prior notice or liability, for any reason whatsoever, including without limitation if you breach the Terms. +

+
+
+

7. Governing Law

+

+ These Terms shall be governed and construed in accordance with the laws of Canada, without regard to its conflict of law provisions. +

+
+
+

8. Changes to Terms

+

+ We reserve the right, at our sole discretion, to modify or replace these Terms at any time. By continuing to access or use our Service after those revisions become effective, you agree to be bound by the revised terms. +

+
+
+
+ } +}