Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/web/src/app/sitemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ export const sitemapRoutes: MetadataRoute.Sitemap = [
changeFrequency: "weekly",
priority: 0.7,
},
{
url: "/support",
lastModified: new Date(),
changeFrequency: "monthly",
priority: 0.6,
},
{
url: "/privacy",
lastModified: new Date(),
Expand Down
187 changes: 187 additions & 0 deletions apps/web/src/app/support/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
"use client";

import { useEffect, useState } from "react";
import { Navbar } from "@/components/landing/navbar";
import { Footer } from "@/components/landing/footer";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { authClient } from "@/lib/auth-client";
import { AlertTriangle, ExternalLink, Github, Mail } from "lucide-react";


const categories = [
{ value: "bug", label: "Bug Report" },
{ value: "feature", label: "Feature Request" },
{ value: "question", label: "Question" },
{ value: "billing", label: "Billing" },
{ value: "other", label: "Other" },
] as const;

const GITHUB_NEW_ISSUE = "https://github.com/snhsish/crosscode/issues/new";

export default function SupportPage() {
const [category, setCategory] = useState<string>("question");
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const [email, setEmail] = useState("");

useEffect(() => {
authClient.getSession().then(({ data }) => {
if (data?.user?.email) setEmail(data.user.email);
});
}, []);

const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
const issueTitle = `[${categories.find((c) => c.value === category)?.label ?? category}] ${title}`.slice(0, 120);
const bodyParts = [description];
if (email.trim()) bodyParts.push(`\n---\nContact: ${email.trim()}`);
bodyParts.push("\n_via /support_");
const body = bodyParts.join("\n\n");
const params = new URLSearchParams({
title: issueTitle,
body,
labels: `support,${category}`,
});
window.location.href = `${GITHUB_NEW_ISSUE}?${params.toString()}`;
};

return (
<div className="flex min-h-screen flex-col">
<Navbar />
<main className="flex-1">
<div className="container py-12 md:py-20">
<div className="mx-auto max-w-3xl text-center">
<h1 className="text-4xl md:text-5xl font-bold tracking-tight">Support</h1>
<p className="mt-4 text-lg text-muted-foreground">
Need help? Create a GitHub issue and we&apos;ll get back to you.
</p>
</div>

<div className="mx-auto mt-12 max-w-2xl">
<div className="rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 dark:border-amber-900/50 dark:bg-amber-950/30">
<div className="flex gap-3">
<AlertTriangle className="h-5 w-5 shrink-0 text-amber-600 dark:text-amber-500" />
<div className="space-y-1">
<p className="text-sm font-medium text-amber-900 dark:text-amber-100">This will be public</p>
<p className="text-sm text-amber-800 dark:text-amber-200/80">
Issues created from this form are visible publicly on GitHub. For sensitive or private support, email{" "}
<a href="mailto:support@crosscode.site" className="font-medium underline underline-offset-4 hover:text-amber-900 dark:hover:text-amber-100">
support@crosscode.site
</a>
{" "}instead.
</p>
</div>
</div>
</div>

<Card className="mt-6">
<CardHeader>
<div className="flex items-center gap-3">
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10">
<Github className="h-5 w-5 text-primary" />
</div>
<div>
<CardTitle className="text-xl">Create a support issue</CardTitle>
<CardDescription className="mt-1">You&apos;ll be redirected to GitHub to submit</CardDescription>
</div>
</div>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-5">
<div className="space-y-2">
<label htmlFor="category" className="text-sm font-medium">
Category
</label>
<select
id="category"
value={category}
onChange={(e) => setCategory(e.target.value)}
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
>
{categories.map((c) => (
<option key={c.value} value={c.value}>
{c.label}
</option>
))}
</select>
</div>

<div className="space-y-2">
<label htmlFor="title" className="text-sm font-medium">
Title <span className="text-destructive">*</span>
</label>
<Input
id="title"
placeholder="Brief summary of your request"
value={title}
onChange={(e) => setTitle(e.target.value)}
required
maxLength={120}
/>
</div>

<div className="space-y-2">
<label htmlFor="description" className="text-sm font-medium">
Description <span className="text-destructive">*</span>
</label>
<textarea
id="description"
placeholder="Describe your issue or question in detail..."
value={description}
onChange={(e) => setDescription(e.target.value)}
required
rows={6}
maxLength={2000}
className="flex min-h-[120px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
/>
<p className="text-xs text-muted-foreground text-right">{description.length}/2000</p>
</div>

<div className="space-y-2">
<label htmlFor="email" className="text-sm font-medium">
Contact email <span className="text-muted-foreground font-normal">(optional)</span>
</label>
<Input
id="email"
type="email"
placeholder="you@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>

<Button type="submit" className="w-full" disabled={!title.trim() || !description.trim()}>
<Github className="h-4 w-4" />
Continue on GitHub
<ExternalLink className="h-4 w-4" />
</Button>

<div className="flex flex-col items-center gap-2 border-t pt-5 sm:flex-row sm:justify-center">
<p className="text-sm text-muted-foreground">For private matters</p>
<Button variant="outline" size="sm" asChild>
<a href="mailto:support@crosscode.site">
<Mail className="h-4 w-4" />
support@crosscode.site
</a>
</Button>
</div>
</form>
</CardContent>
</Card>

<p className="mt-6 text-center text-sm text-muted-foreground">
Already on GitHub?{" "}
<a href={GITHUB_NEW_ISSUE} target="_blank" rel="noopener noreferrer" className="underline underline-offset-4 hover:text-foreground">
Open a new issue directly
</a>
.
</p>
</div>
</div>
</main>
<Footer />
</div>
);
}
55 changes: 27 additions & 28 deletions apps/web/src/components/landing/cta.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
import Link from "next/link";
import { Terminal, ArrowRight } from "lucide-react";
import { Terminal, ArrowRight, Github } from "lucide-react";
import { Button } from "@/components/ui/button";
import { FlickeringGrid } from "./flickering-grid";

export function CTA() {
return (
<section id="cli" className="container py-20">
<div className="mx-auto max-w-4xl rounded-3xl bg-primary px-6 md:px-8 py-12 md:py-16 text-center text-primary-foreground relative overflow-hidden">
<div className="absolute inset-0 [mask-image:radial-gradient(circle_at_center,black_0%,transparent_70%)]">
<FlickeringGrid />
<section id="cli" className="container py-16">
<div className="mx-auto max-w-3xl rounded-2xl border bg-card px-6 py-12 text-center md:px-10 md:py-14">
<span className="inline-flex items-center gap-1.5 rounded-full border bg-muted px-3 py-1 text-xs font-medium tracking-wide text-muted-foreground">
<Terminal className="h-3 w-3" />
One command away
</span>
<h2 className="mt-5 text-balance text-3xl font-semibold tracking-tight md:text-4xl">
Ready to get started?
</h2>
<p className="mx-auto mt-3 max-w-xl text-balance text-sm leading-relaxed text-muted-foreground md:text-[15px]">
Run one command on your PC, scan the QR code from your phone, and you&apos;re connected. No accounts, no config files, no friction.
</p>
<div className="mt-6 inline-flex items-center gap-2 rounded-lg border bg-muted px-4 py-2 font-mono text-sm">
<Terminal className="h-3.5 w-3.5 text-muted-foreground" />
<span>npx crosscode</span>
</div>
<div className="relative z-10">
<h2 className="text-3xl md:text-4xl font-bold">Ready to get started?</h2>
<p className="mt-4 text-lg opacity-90 max-w-2xl mx-auto">
Run one command on your PC, scan the QR code from your phone, and you&apos;re connected.
</p>
<div className="mt-8 flex flex-col sm:flex-row items-center justify-center gap-4">
<div className="flex items-center gap-2 rounded-lg bg-primary-foreground/10 px-6 py-3 font-mono text-sm">
<Terminal className="h-4 w-4" />
<span>npx crosscode</span>
</div>
</div>
<div className="mt-6 flex items-center justify-center gap-3">
<Button variant="secondary" size="lg" asChild>
<Link href="/login">Login</Link>
</Button>
<Button variant="secondary" size="lg" asChild>
<a href="https://github.com/snhsish/crosscode" target="_blank" rel="noopener noreferrer">
View on GitHub
<ArrowRight className="ml-2 h-4 w-4" />
</a>
</Button>
</div>
<div className="mt-6 flex flex-col items-center justify-center gap-3 sm:flex-row">
<Button size="lg" asChild>
<Link href="/download">Get Started</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<a href="https://github.com/snhsish/crosscode" target="_blank" rel="noopener noreferrer">
<Github className="h-4 w-4" />
View on GitHub
<ArrowRight className="h-4 w-4" />
</a>
</Button>
</div>
</div>
</section>
Expand Down
78 changes: 0 additions & 78 deletions apps/web/src/components/landing/flickering-grid.tsx

This file was deleted.

24 changes: 22 additions & 2 deletions apps/web/src/components/landing/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function Footer() {
return (
<footer className="border-t bg-background">
<div className="container py-12 md:py-16">
<div className="grid gap-8 md:grid-cols-2 lg:grid-cols-4">
<div className="grid gap-8 md:grid-cols-2 lg:grid-cols-5">
<div className="space-y-4">
<div className="flex items-center gap-2">
<BrandLogo />
Expand Down Expand Up @@ -88,8 +88,18 @@ export function Footer() {
Features
</Link>
</li>
</ul>
</div>
<div className="space-y-4">
<h3 className="text-sm font-semibold">Developers</h3>
<ul className="space-y-3">
<li>
<Link href="/docs" className="text-sm text-muted-foreground hover:text-foreground transition-colors">
Docs
</Link>
</li>
<li>
<Link href="/#cli" className="text-sm text-muted-foreground hover:text-foreground transition-colors">
<Link href="/docs/cli" className="text-sm text-muted-foreground hover:text-foreground transition-colors">
CLI
</Link>
</li>
Expand All @@ -113,6 +123,11 @@ export function Footer() {
<div className="space-y-4">
<h3 className="text-sm font-semibold">Community</h3>
<ul className="space-y-3">
<li>
<Link href="/support" className="text-sm text-muted-foreground hover:text-foreground transition-colors">
Support
</Link>
</li>
<li>
<a
href="https://discord.gg/K6k6ebkJkx"
Expand Down Expand Up @@ -158,6 +173,11 @@ export function Footer() {
Privacy Policy
</Link>
</li>
<li>
<Link href="/legal/fair-usage" className="text-sm text-muted-foreground hover:text-foreground transition-colors">
Fair Usage
</Link>
</li>
</ul>
</div>
</div>
Expand Down
Loading
Loading