From 1e4af3da6d174cee95c55137c0e09a08fd5b9fcc Mon Sep 17 00:00:00 2001 From: jwinterm Date: Wed, 18 Feb 2026 17:01:55 -0500 Subject: [PATCH] Add support page, update privacy policy with leaderboard disclosure - New /support page with bug report, feature request, and feedback cards - ContactForm accepts source prop ('inquiry' | 'support') for differentiated emails - Support emails go to apps@such.software with 'App feedback' subject - Added 'High Scores & Leaderboards' section to Bauhaus Echo privacy policy - Added 'Support & Feedback' link to Bauhaus Echo product page footer - Updated privacy policy date to February 18, 2026 --- apps/web/src/actions/submit-contact.ts | 26 ++++--- .../src/app/products/bauhaus-echo/page.tsx | 6 +- .../products/bauhaus-echo/privacy/page.tsx | 16 ++++- apps/web/src/app/support/page.tsx | 67 +++++++++++++++++++ .../src/components/contact/contact-form.tsx | 48 +++++++++---- 5 files changed, 139 insertions(+), 24 deletions(-) create mode 100644 apps/web/src/app/support/page.tsx diff --git a/apps/web/src/actions/submit-contact.ts b/apps/web/src/actions/submit-contact.ts index c2158f4..bf9cf07 100644 --- a/apps/web/src/actions/submit-contact.ts +++ b/apps/web/src/actions/submit-contact.ts @@ -9,8 +9,9 @@ const resend = new Resend(process.env.RESEND_API_KEY); const ContactSchema = z.object({ name: z.string().min(2, "Name is too short"), email: z.string().email("Invalid email address"), - message: z.string().min(10, "Please tell us more about your project"), - token: z.string().min(1, "Security check failed") + message: z.string().min(10, "Please tell us more"), + token: z.string().min(1, "Security check failed"), + source: z.enum(["inquiry", "support"]).default("inquiry"), }); export async function submitContactForm(prevState: any, formData: FormData) { @@ -30,17 +31,23 @@ export async function submitContactForm(prevState: any, formData: FormData) { // 3. Send email via Resend try { - const { name, email, message } = validated.data; + const { name, email, message, source } = validated.data; const contactEmail = process.env.CONTACT_EMAIL || 'sales@such.software'; + const isSupport = source === 'support'; + const subject = isSupport + ? `App feedback from ${name}` + : `New inquiry from ${name}`; + const heading = isSupport ? 'App Support / Feedback' : 'New Project Inquiry'; + const { error } = await resend.emails.send({ from: 'Such Software ', - to: contactEmail, + to: isSupport ? 'apps@such.software' : contactEmail, replyTo: email, - subject: `New inquiry from ${name}`, + subject, text: `Name: ${name}\nEmail: ${email}\n\nMessage:\n${message}`, html: ` -

New Project Inquiry

+

${heading}

Name: ${name}

Email: ${email}

Message:

@@ -53,9 +60,12 @@ export async function submitContactForm(prevState: any, formData: FormData) { return { success: false, message: "Failed to send message. Please try again." }; } - return { success: true, message: "Request received. We will be in touch shortly." }; + return { success: true, message: isSupport + ? "Thanks for your feedback! We'll get back to you shortly." + : "Request received. We will be in touch shortly." + }; } catch (e) { console.error('Email error:', e); return { success: false, message: "System error. Please contact us via email." }; } -} \ No newline at end of file +} diff --git a/apps/web/src/app/products/bauhaus-echo/page.tsx b/apps/web/src/app/products/bauhaus-echo/page.tsx index 199f421..feb868a 100644 --- a/apps/web/src/app/products/bauhaus-echo/page.tsx +++ b/apps/web/src/app/products/bauhaus-echo/page.tsx @@ -84,10 +84,14 @@ export default function BauhausEchoPage() {
- + Privacy Policy • + + Support & Feedback + + • Contact: apps@such.software
diff --git a/apps/web/src/app/products/bauhaus-echo/privacy/page.tsx b/apps/web/src/app/products/bauhaus-echo/privacy/page.tsx index fdce11f..be58f3b 100644 --- a/apps/web/src/app/products/bauhaus-echo/privacy/page.tsx +++ b/apps/web/src/app/products/bauhaus-echo/privacy/page.tsx @@ -21,7 +21,7 @@ export default function BauhausEchoPrivacyPage() {

Privacy Policy for Bauhaus Echo

-

Last Updated: February 6, 2026

+

Last Updated: February 18, 2026

@@ -89,6 +89,20 @@ export default function BauhausEchoPrivacyPage() { We do not have access to your payment information. We only receive confirmation of your purchase status.

+

High Scores & Leaderboards

+

+ If you submit scores to our online leaderboards, we collect: +

+
    +
  • Your chosen display name (anonymous by default)
  • +
  • Your game scores and statistics
  • +
  • A randomly generated anonymous player ID
  • +
+

+ We do not require or collect your real name, email, or any other + personal information to use leaderboards. +

+

Locally Stored Data

The App stores the following data locally on your device:

    diff --git a/apps/web/src/app/support/page.tsx b/apps/web/src/app/support/page.tsx new file mode 100644 index 0000000..97e15a7 --- /dev/null +++ b/apps/web/src/app/support/page.tsx @@ -0,0 +1,67 @@ +import { ContactForm } from "@/components/contact/contact-form"; +import { Header } from "@/components/layout/header"; +import { MobileNav } from "@/components/layout/mobile-nav"; +import Link from "next/link"; +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "Support | Such Software", + description: "Get help with Bauhaus Echo or any Such Software product. Report bugs, request features, or send feedback.", + alternates: { canonical: "/support" }, +}; + +export default function SupportPage() { + return ( +
    +
    +
    + + ← Home + + +

    Support & Feedback

    +

    + Having trouble with one of our apps? Want to suggest a feature? We'd love to hear from you. +

    + +
    +
    +

    Bug Reports

    +

    + Something not working right? Let us know what happened, your device, and OS version — we'll investigate. +

    +
    +
    +

    Feature Requests

    +

    + Have an idea to make the game better? We're always looking for ways to improve. +

    +
    +
    +

    General Feedback

    +

    + Enjoying the game? Hate something? All feedback is welcome and helps us prioritize. +

    +
    +
    + + + +
    +

    + You can also reach us directly at{" "} + + apps@such.software + +

    +

    + + Privacy Policy + +

    +
    +
    + +
    + ); +} diff --git a/apps/web/src/components/contact/contact-form.tsx b/apps/web/src/components/contact/contact-form.tsx index 46a3173..243a3cf 100644 --- a/apps/web/src/components/contact/contact-form.tsx +++ b/apps/web/src/components/contact/contact-form.tsx @@ -6,7 +6,7 @@ import { TurnstileWidget } from './turnstile-widget'; import { useState, useEffect, useRef } from 'react'; import { Button } from '@repo/ui/components/button'; -function SubmitButton() { +function SubmitButton({ label = "Send Message" }: { label?: string }) { const { pending } = useFormStatus(); return ( ); } -export function ContactForm() { +interface ContactFormProps { + source?: 'inquiry' | 'support'; +} + +export function ContactForm({ source = 'inquiry' }: ContactFormProps) { const [state, formAction] = useActionState(submitContactForm, { success: false, message: '' }); const [token, setToken] = useState(''); const formRef = useRef(null); + const isSupport = source === 'support'; + // Reset form on successful submission useEffect(() => { if (state.success && formRef.current) { @@ -43,19 +49,27 @@ export function ContactForm() {
    -

    Project Inquiry

    +

    + {isSupport ? 'Send Feedback' : 'Project Inquiry'} +

    - Tell us about your technical challenges. From Medusa v2 migrations to real-time custom engines, we're ready to architect your solution. + {isSupport + ? 'Found a bug? Have a feature request? We read every message and typically respond within 24 hours.' + : 'Tell us about your technical challenges. From Medusa v2 migrations to real-time custom engines, we\'re ready to architect your solution.'}

    + +
    - +
    - +
    - +