more stuff

This commit is contained in:
Shreyans Jain 2025-09-04 16:50:55 -07:00
parent ebc8c1f60d
commit 593bb2556a
No known key found for this signature in database
9 changed files with 407 additions and 93 deletions

View file

@ -11,13 +11,20 @@ import {
CardTitle,
} from "@ui/components/card"
import { Avatar, AvatarFallback, AvatarImage } from "@ui/components/avatar"
import { ShareIcon, LoaderIcon } from "lucide-react"
import { ShareIcon, LoaderIcon, ArrowRightIcon } from "lucide-react"
import Link from "next/link"
import { useParams } from "next/navigation"
import { useParams, useRouter } from "next/navigation"
import { labelVariants } from "@ui/text/label"
import { cn } from "@lib/utils"
import { headingVariants } from "@ui/text/heading"
import { titleVariants } from "@ui/text/title"
import { useSession } from "@lib/auth"
export default function ReferralInvitePage() {
const params = useParams()
const code = params.code as string
const router = useRouter()
const session = useSession()
const {
data: referrerData,
@ -48,6 +55,10 @@ export default function ReferralInvitePage() {
retry: 1,
})
if (session.data) {
router.push("/")
}
const referrer = referrerData?.referrer
if (isLoading) {
@ -55,7 +66,13 @@ export default function ReferralInvitePage() {
<div className="min-h-screen flex items-center justify-center p-4 bg-[#0f1419]">
<div className="flex flex-col items-center gap-4">
<LoaderIcon className="w-8 h-8 text-orange-500 animate-spin" />
<p className="text-white/60">Loading invitation...</p>
<p
className={cn(
labelVariants({ level: 1, weight: "regular", color: "muted" }),
)}
>
Loading invitation...
</p>
</div>
</div>
)
@ -64,15 +81,22 @@ export default function ReferralInvitePage() {
if (error || !code) {
return (
<div className="min-h-screen flex items-center justify-center p-4 bg-[#0f1419]">
<Card className="max-w-md w-full bg-[#1a1f2a] border-white/10">
<Card className="max-w-md w-full bg-sm-shark">
<CardHeader className="text-center">
<div className="mx-auto mb-4 w-16 h-16 rounded-full bg-red-500/10 flex items-center justify-center">
<ShareIcon className="w-8 h-8 text-red-500" />
</div>
<CardTitle className="text-2xl font-bold text-white">
<CardTitle
className={cn(titleVariants({ level: 2, weight: "bold" }))}
>
Invalid Referral Link
</CardTitle>
<CardDescription className="text-white/60 mt-2">
<CardDescription
className={cn(
labelVariants({ level: 1, weight: "regular", color: "muted" }),
"mt-2",
)}
>
{error instanceof Error ? error.message : "Invalid referral code"}
</CardDescription>
</CardHeader>
@ -80,10 +104,17 @@ export default function ReferralInvitePage() {
<div className="space-y-4">
<div className="text-center">
<Link
className="text-orange-500 hover:text-orange-400 text-sm underline"
className={cn(
labelVariants({
level: 1,
weight: "regular",
color: "default",
}),
"underline underline-offset-2 hover:opacity-50 transition-all",
)}
href="https://supermemory.ai"
>
Learn more about supermemory
Learn more
</Link>
</div>
</div>
@ -95,7 +126,7 @@ export default function ReferralInvitePage() {
return (
<div className="min-h-screen flex items-center justify-center p-4 bg-[#0f1419]">
<Card className="max-w-md w-full bg-[#1a1f2a] border-white/10">
<Card className="max-w-md w-full bg-sm-shark">
<CardHeader className="text-center">
<div className="mx-auto mb-4">
<Avatar className="w-20 h-20">
@ -105,10 +136,17 @@ export default function ReferralInvitePage() {
</AvatarFallback>
</Avatar>
</div>
<CardTitle className="text-2xl font-bold text-white">
<CardTitle
className={cn(titleVariants({ level: 2, weight: "bold" }))}
>
You've been invited!
</CardTitle>
<CardDescription className="text-white/60 mt-2">
<CardDescription
className={cn(
labelVariants({ level: 1, weight: "regular", color: "muted" }),
"mt-2",
)}
>
<span className="text-orange-400 font-semibold">
{referrer?.name}
</span>{" "}
@ -117,29 +155,66 @@ export default function ReferralInvitePage() {
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="bg-[#0f1419] rounded-lg p-4 border border-white/10">
<h3 className="text-white font-semibold mb-2">
<div
className={
(cn(
headingVariants({
level: "h2",
weight: "medium",
}),
),
"text-white text-center")
}
>
You and {referrer?.name} both get a free month of{" "}
<b>supermemory pro</b>
</div>
<div className="bg-sm-shark rounded-lg p-4 border border-white/10">
<h3
className={cn(headingVariants({ level: "h3", weight: "bold" }))}
>
What is supermemory?
</h3>
<p className="text-white/70 text-sm leading-relaxed">
<p
className={cn(
labelVariants({
level: 1,
weight: "regular",
color: "muted",
}),
)}
>
supermemory is an AI-powered personal knowledge base that helps
you store, organize, and interact with all your digital
memories.
</p>
</div>
<Link href={`/login?ref=${code}`} className="block">
<Button className="w-full bg-orange-500 hover:bg-orange-600 text-white">
Get Started
</Button>
</Link>
<Button
className={cn(
labelVariants({ level: 1, weight: "medium" }),
"w-full",
)}
asChild
>
<Link href={`/login?ref=${code}`}>
Get Started <ArrowRightIcon className="w-4 h-4" />
</Link>
</Button>
<div className="text-center">
<Link
className="text-orange-500 hover:text-orange-400 text-sm underline"
className={cn(
labelVariants({
level: 1,
weight: "regular",
color: "default",
}),
"underline underline-offset-2 hover:opacity-50 transition-all",
)}
href="https://supermemory.ai"
>
Learn more about supermemory
Learn more
</Link>
</div>
</div>

View file

@ -1,56 +1,95 @@
"use client";
"use client"
import { Button } from "@ui/components/button";
import { Button } from "@ui/components/button"
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@ui/components/card";
import { ShareIcon } from "lucide-react";
import Link from "next/link";
} from "@ui/components/card"
import { ArrowRightIcon, HeartIcon, ShareIcon } from "lucide-react"
import Link from "next/link"
import { labelVariants } from "@ui/text/label"
import { cn } from "@lib/utils"
import { headingVariants } from "@ui/text/heading"
import { titleVariants } from "@ui/text/title"
export default function ReferralHomePage() {
return (
<div className="min-h-screen flex items-center justify-center p-4 bg-[#0f1419]">
<Card className="max-w-md w-full bg-[#1a1f2a] border-white/10">
<CardHeader className="text-center">
<div className="mx-auto mb-4 w-16 h-16 rounded-full bg-orange-500/10 flex items-center justify-center">
<ShareIcon className="w-8 h-8 text-orange-500" />
<Card className="max-w-md w-full bg-sm-shark">
<CardHeader className="flex flex-col items-center gap-4">
<div className="mx-auto size-16 rounded-full bg-black/40 flex items-center justify-center">
<HeartIcon className="h-full" />
</div>
<div className="flex flex-col items-center gap-1">
<CardTitle
className={cn(titleVariants({ level: 3, weight: "bold" }))}
>
Missing Referral Code?
</CardTitle>
<CardDescription
className={cn(
labelVariants({
level: 1,
weight: "regular",
color: "muted",
}),
"text-center",
)}
>
It looks like you're missing a referral code. Get one from a
friend or join directly!
</CardDescription>
</div>
<CardTitle className="text-2xl font-bold text-white">
Missing Referral Code
</CardTitle>
<CardDescription className="text-white/60 mt-2">
It looks like you're missing a referral code. Get one from a friend
or join directly!
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="bg-[#0f1419] rounded-lg p-4 border border-white/10">
<h3 className="text-white font-semibold mb-2">
What is supermemory?
</h3>
<p className="text-white/70 text-sm leading-relaxed">
supermemory is an AI-powered personal knowledge base that helps
you store, organize, and interact with all your digital
memories.
</p>
</div>
<CardContent className="flex flex-col gap-4">
<div className="bg-sm-shark rounded-lg p-4 border border-white/10">
<h3
className={cn(headingVariants({ level: "h3", weight: "bold" }))}
>
What is supermemory?
</h3>
<p
className={cn(
labelVariants({ level: 1, weight: "regular", color: "muted" }),
)}
>
supermemory is an AI-powered personal knowledge base that helps
you store, organize, and interact with all your digital memories.
</p>
</div>
<div className="text-center">
<Link
className="text-orange-500 hover:text-orange-400 text-sm underline"
href="https://supermemory.ai"
>
Learn more about supermemory
</Link>
</div>
<Button
className={cn(
labelVariants({ level: 1, weight: "medium" }),
"w-full",
)}
asChild
>
<Link href={"/login"}>
Get Started <ArrowRightIcon className="w-4 h-4" />
</Link>
</Button>
<div className="text-center">
<Link
className={cn(
labelVariants({
level: 1,
weight: "regular",
color: "default",
}),
"underline underline-offset-2 hover:opacity-50 transition-all",
)}
href="https://supermemory.ai"
>
Learn more
</Link>
</div>
</CardContent>
</Card>
</div>
);
)
}

View file

@ -47,6 +47,6 @@ export default async function middleware(request: Request) {
export const config = {
matcher: [
"/((?!_next/static|_next/image|images|icon.png|monitoring|opengraph-image.png|ingest|api|login|api/emails).*)",
"/((?!_next/static|_next/image|images|icon.png|monitoring|opengraph-image.png|ingest|api|login|api/emails|ref).*)",
],
}

View file

@ -1,63 +1,63 @@
import { withSentryConfig } from "@sentry/nextjs";
import type { NextConfig } from "next";
import { withSentryConfig } from "@sentry/nextjs"
import type { NextConfig } from "next"
const nextConfig: NextConfig = {
experimental: {
reactCompiler: true,
viewTransition: true,
},
eslint: {
ignoreDuringBuilds: true,
},
poweredByHeader: false,
async rewrites() {
return [
{
source: "/ingest/static/:path*",
destination: "https://us-assets.i.posthog.com/static/:path*",
},
{
source: "/ingest/:path*",
destination: "https://us.i.posthog.com/:path*",
},
];
},
skipTrailingSlashRedirect: true,
};
experimental: {
reactCompiler: true,
viewTransition: true,
},
eslint: {
ignoreDuringBuilds: true,
},
poweredByHeader: false,
async rewrites() {
return [
{
source: "/ingest/static/:path*",
destination: "https://us-assets.i.posthog.com/static/:path*",
},
{
source: "/ingest/:path*",
destination: "https://us.i.posthog.com/:path*",
},
]
},
skipTrailingSlashRedirect: true,
}
export default withSentryConfig(nextConfig, {
// For all available options, see:
// For all available options, see:
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
org: "supermemory",
project: "consumer-app",
project: "consumer-app",
// Only print logs for uploading source maps in CI
// Only print logs for uploading source maps in CI
silent: !process.env.CI,
// For all available options, see:
// For all available options, see:
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
// Upload a larger set of source maps for prettier stack traces (increases build time)
widenClientFileUpload: true,
// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
// This can increase your server load as well as your hosting bill.
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
// side errors will fail.
tunnelRoute: "/monitoring",
// Automatically tree-shake Sentry logger statements to reduce bundle size
// Automatically tree-shake Sentry logger statements to reduce bundle size
disableLogger: true,
// Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)
// Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)
// See the following for more information:
// https://docs.sentry.io/product/crons/
// https://vercel.com/docs/cron-jobs
automaticVercelMonitors: true,
});
})
import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";
import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"
initOpenNextCloudflareForDev();
initOpenNextCloudflareForDev()

View file

@ -20,6 +20,7 @@
"boxen": "^8.0.1",
"cloudflare": "^4.5.0",
"compromise": "^14.14.4",
"cva": "^1.0.0-beta.4",
"dedent": "^1.6.0",
"destr": "^2.0.5",
"drizzle-orm": "^0.44.3",
@ -2002,6 +2003,8 @@
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
"cva": ["cva@1.0.0-beta.4", "", { "dependencies": { "clsx": "^2.1.1" }, "peerDependencies": { "typescript": ">= 4.5.5" }, "optionalPeers": ["typescript"] }, "sha512-F/JS9hScapq4DBVQXcK85l9U91M6ePeXoBMSp7vypzShoefUBxjQTo3g3935PUHgQd+IW77DjbPRIxugy4/GCQ=="],
"cytoscape": ["cytoscape@3.33.1", "", {}, "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ=="],
"cytoscape-cose-bilkent": ["cytoscape-cose-bilkent@4.1.0", "", { "dependencies": { "cose-base": "^1.0.0" }, "peerDependencies": { "cytoscape": "^3.2.0" } }, "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ=="],

View file

@ -34,6 +34,7 @@
"boxen": "^8.0.1",
"cloudflare": "^4.5.0",
"compromise": "^14.14.4",
"cva": "^1.0.0-beta.4",
"dedent": "^1.6.0",
"destr": "^2.0.5",
"drizzle-orm": "^0.44.3",

View file

@ -0,0 +1,63 @@
import { Root } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "cva"
import { cn } from "../../lib/utils"
export const headingVariants = cva({
base: "tracking-[-0.4px]",
variants: {
level: {
h1: "text-sm sm:text-base md:text-lg lg:text-xl leading-[32px]",
h2: "text-xs sm:text-sm md:text-base lg:text-lg leading-[30px]",
h3: "text-[0.625rem] sm:text-xs md:text-sm lg:text-base leading-[28px]",
h4: "text-[0.5rem] sm:text-[0.625rem] md:text-xs lg:text-sm leading-[24px]",
},
weight: {
bold: "font-bold",
medium: "font-medium",
},
},
defaultVariants: {
level: "h1",
weight: "medium",
},
})
export interface HeadingProps
extends React.HTMLAttributes<HTMLHeadingElement>,
VariantProps<typeof headingVariants> {
asChild?: boolean
}
export function Heading({
className,
level = "h1",
weight = "medium",
asChild,
...props
}: HeadingProps) {
const Comp = asChild ? Root : level
return (
<Comp
className={cn(headingVariants({ level, weight }), className)}
{...props}
/>
)
}
// Export individual variant classes for compatibility
export const headingH1Bold = () =>
headingVariants({ level: "h1", weight: "bold" })
export const headingH1Medium = () =>
headingVariants({ level: "h1", weight: "medium" })
export const headingH2Bold = () =>
headingVariants({ level: "h2", weight: "bold" })
export const headingH2Medium = () =>
headingVariants({ level: "h2", weight: "medium" })
export const headingH3Bold = () =>
headingVariants({ level: "h3", weight: "bold" })
export const headingH3Medium = () =>
headingVariants({ level: "h3", weight: "medium" })
export const headingH4Bold = () =>
headingVariants({ level: "h4", weight: "bold" })
export const headingH4Medium = () =>
headingVariants({ level: "h4", weight: "medium" })

View file

@ -0,0 +1,68 @@
import { Root } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "cva"
import { cn } from "../../lib/utils"
export const labelVariants = cva({
base: "tracking-[-0.4px]",
variants: {
level: {
1: "text-[0.875rem] md:text-[1rem] leading-[1.5rem]",
2: "text-[0.25rem] sm:text-[0.375rem] md:text-[0.5rem] lg:text-[0.625rem] leading-[18px]",
3: "text-[0.125rem] sm:text-[0.25rem] md:text-[0.375rem] lg:text-[0.5rem] leading-[16px] tracking-[-0.2px]",
},
weight: {
medium: "font-medium",
regular: "font-normal",
},
color: {
default: "",
muted: "text-sm-silver-chalice",
},
},
compoundVariants: [
{
level: [2, 3],
color: "default",
class: "text-sm-silver-chalice",
},
],
defaultVariants: {
level: 1,
weight: "regular",
color: "default",
},
})
export interface LabelProps
extends Omit<React.HTMLAttributes<HTMLParagraphElement>, "color">,
VariantProps<typeof labelVariants> {
asChild?: boolean
}
export function Label({
className,
level = 1,
weight = "regular",
color = "default",
asChild,
...props
}: LabelProps) {
const Comp = asChild ? Root : "p"
return (
<Comp
className={cn(labelVariants({ level, weight, color }), className)}
{...props}
/>
)
}
// Export individual variant classes for compatibility
export const label1Medium = () => labelVariants({ level: 1, weight: "medium" })
export const label1Regular = () =>
labelVariants({ level: 1, weight: "regular" })
export const label2Medium = () => labelVariants({ level: 2, weight: "medium" })
export const label2Regular = () =>
labelVariants({ level: 2, weight: "regular" })
export const label3Medium = () => labelVariants({ level: 3, weight: "medium" })
export const label3Regular = () =>
labelVariants({ level: 3, weight: "regular" })

View file

@ -0,0 +1,65 @@
import { Root } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "cva"
import { cn } from "../../lib/utils"
export const titleVariants = cva({
base: "tracking-[-0.4px]",
variants: {
level: {
1: "text-xl sm:text-2xl md:text-3xl lg:text-4xl leading-[70px] tracking-[-0.8px]",
2: "text-lg sm:text-xl md:text-2xl lg:text-3xl leading-[48px]",
3: "text-base sm:text-lg md:text-xl lg:text-2xl leading-[40px]",
},
weight: {
bold: "font-bold",
medium: "font-medium",
},
},
compoundVariants: [
{
level: 2,
weight: "medium",
class: "leading-[32px] md:leading-[48px]",
},
],
defaultVariants: {
level: 1,
weight: "medium",
},
})
export interface TitleProps
extends React.HTMLAttributes<HTMLHeadingElement>,
VariantProps<typeof titleVariants> {
asChild?: boolean
}
export function Title({
className,
level = 1,
weight = "medium",
asChild,
...props
}: TitleProps) {
const levelMap = {
1: "h1",
2: "h2",
3: "h3",
} as const
const Comp = asChild ? Root : levelMap[level]
return (
<Comp
className={cn(titleVariants({ level, weight }), className)}
{...props}
/>
)
}
// Export individual variant classes for compatibility
export const title1Bold = () => titleVariants({ level: 1, weight: "bold" })
export const title1Medium = () => titleVariants({ level: 1, weight: "medium" })
export const title2Bold = () => titleVariants({ level: 2, weight: "bold" })
export const title2Medium = () => titleVariants({ level: 2, weight: "medium" })
export const title3Bold = () => titleVariants({ level: 3, weight: "bold" })
export const title3Medium = () => titleVariants({ level: 3, weight: "medium" })