refactor: update launch configurations and enhance HeroSection with Google login functionality

This commit is contained in:
DESKTOP-RTLN3BA\$punk 2026-01-07 17:46:38 -08:00
parent fabbae2b48
commit 73eeb555b2
2 changed files with 181 additions and 23 deletions

94
.vscode/launch.json vendored
View file

@ -5,7 +5,7 @@
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: UV Run with Reload",
"name": "Backend: FastAPI",
"type": "debugpy",
"request": "launch",
"module": "uvicorn",
@ -25,7 +25,7 @@
"python": "${command:python.interpreterPath}"
},
{
"name": "Python Debugger: main.py (direct)",
"name": "Backend: FastAPI (main.py)",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/surfsense_backend/main.py",
@ -34,17 +34,95 @@
"cwd": "${workspaceFolder}/surfsense_backend"
},
{
"name": "Python Debugger: Chat DeepAgent",
"name": "Frontend: Next.js",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}/surfsense_web",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"console": "integratedTerminal",
"serverReadyAction": {
"pattern": "- Local:.+(https?://.+)",
"uriFormat": "%s",
"action": "debugWithChrome"
}
},
{
"name": "Frontend: Next.js (Server-Side Debug)",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}/surfsense_web",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "debug:server"],
"console": "integratedTerminal",
"serverReadyAction": {
"pattern": "- Local:.+(https?://.+)",
"uriFormat": "%s",
"action": "debugWithChrome"
}
},
{
"name": "Celery: Worker",
"type": "debugpy",
"request": "launch",
"module": "app.agents.new_chat.chat_deepagent",
"module": "celery",
"args": [
"-A",
"app.celery_app:celery_app",
"worker",
"--loglevel=info",
"--pool=solo"
],
"console": "integratedTerminal",
"justMyCode": false,
"cwd": "${workspaceFolder}/surfsense_backend",
"python": "${command:python.interpreterPath}",
"env": {
"PYTHONPATH": "${workspaceFolder}/surfsense_backend"
"python": "${command:python.interpreterPath}"
},
{
"name": "Celery: Beat Scheduler",
"type": "debugpy",
"request": "launch",
"module": "celery",
"args": [
"-A",
"app.celery_app:celery_app",
"beat",
"--loglevel=info"
],
"console": "integratedTerminal",
"justMyCode": false,
"cwd": "${workspaceFolder}/surfsense_backend",
"python": "${command:python.interpreterPath}"
}
],
"compounds": [
{
"name": "Full Stack: Backend + Frontend + Celery",
"configurations": [
"Backend: FastAPI",
"Frontend: Next.js",
"Celery: Worker",
"Celery: Beat Scheduler"
],
"stopAll": true,
"presentation": {
"hidden": false,
"group": "Full Stack",
"order": 1
}
},
{
"name": "Full Stack: Backend + Frontend",
"configurations": [
"Backend: FastAPI",
"Frontend: Next.js"
],
"stopAll": true,
"presentation": {
"hidden": false,
"group": "Full Stack",
"order": 2
}
}
]
}
}

View file

@ -5,6 +5,29 @@ import Link from "next/link";
import React, { useEffect, useRef, useState } from "react";
import Balancer from "react-wrap-balancer";
import { cn } from "@/lib/utils";
import { trackLoginAttempt } from "@/lib/posthog/events";
// Official Google "G" logo with brand colors
const GoogleLogo = ({ className }: { className?: string }) => (
<svg className={className} viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
fill="#4285F4"
/>
<path
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
fill="#34A853"
/>
<path
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
fill="#FBBC05"
/>
<path
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
fill="#EA4335"
/>
</svg>
);
export function HeroSection() {
const containerRef = useRef<HTMLDivElement>(null);
@ -60,7 +83,7 @@ export function HeroSection() {
<h2 className="relative z-50 mx-auto mb-4 mt-4 max-w-4xl text-balance text-center text-3xl font-semibold tracking-tight text-gray-700 md:text-7xl dark:text-neutral-300">
<Balancer>
The AI Workspace{" "}
<div className="relative mx-auto inline-block w-max [filter:drop-shadow(0px_1px_3px_rgba(27,_37,_80,_0.14))]">
<div className="relative mx-auto inline-block w-max filter-[drop-shadow(0px_1px_3px_rgba(27,37,80,0.14))]">
<div className="text-black [text-shadow:0_0_rgba(0,0,0,0.1)] dark:text-white">
<span className="">Built for Teams</span>
</div>
@ -73,12 +96,7 @@ export function HeroSection() {
your team.
</p>
<div className="mb-10 mt-8 flex w-full flex-col items-center justify-center gap-4 px-8 sm:flex-row md:mb-20">
<Link
href="/login"
className="group relative z-20 flex h-10 w-full cursor-pointer items-center justify-center space-x-2 rounded-lg bg-black p-px px-4 py-2 text-center text-sm font-semibold leading-6 text-white no-underline transition duration-200 sm:w-52 dark:bg-white dark:text-black"
>
Get Started
</Link>
<GetStartedButton />
{/* <Link
href="/pricing"
className="shadow-input group relative z-20 flex h-10 w-full cursor-pointer items-center justify-center space-x-2 rounded-lg bg-white p-px px-4 py-2 text-sm font-semibold leading-6 text-black no-underline transition duration-200 hover:-translate-y-0.5 sm:w-52 dark:bg-neutral-800 dark:text-white"
@ -115,6 +133,68 @@ export function HeroSection() {
);
}
function GetStartedButton() {
const isGoogleAuth = process.env.NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE === "GOOGLE";
const handleGoogleLogin = () => {
trackLoginAttempt("google");
window.location.href = `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/auth/google/authorize-redirect`;
};
if (isGoogleAuth) {
return (
<motion.button
type="button"
onClick={handleGoogleLogin}
whileHover="hover"
whileTap={{ scale: 0.98 }}
initial="idle"
className="group relative z-20 flex h-11 w-full cursor-pointer items-center justify-center gap-3 overflow-hidden rounded-xl bg-white px-6 py-2.5 text-sm font-semibold text-neutral-700 shadow-lg ring-1 ring-neutral-200/50 transition-shadow duration-300 hover:shadow-xl sm:w-56 dark:bg-neutral-900 dark:text-neutral-200 dark:ring-neutral-700/50"
variants={{
idle: { scale: 1, y: 0 },
hover: { scale: 1.02, y: -2 },
}}
>
{/* Animated gradient background on hover */}
<motion.div
className="absolute inset-0 bg-linear-to-r from-blue-50 via-green-50 to-yellow-50 dark:from-blue-950/30 dark:via-green-950/30 dark:to-yellow-950/30"
variants={{
idle: { opacity: 0 },
hover: { opacity: 1 },
}}
transition={{ duration: 0.3 }}
/>
{/* Google logo with subtle animation */}
<motion.div
className="relative"
variants={{
idle: { rotate: 0 },
hover: { rotate: [0, -8, 8, 0] },
}}
transition={{ duration: 0.4, ease: "easeInOut" }}
>
<GoogleLogo className="h-5 w-5" />
</motion.div>
<span className="relative">Continue with Google</span>
</motion.button>
);
}
return (
<motion.div
whileHover={{ scale: 1.02, y: -2 }}
whileTap={{ scale: 0.98 }}
>
<Link
href="/login"
className="group relative z-20 flex h-11 w-full cursor-pointer items-center justify-center gap-2 rounded-xl bg-black px-6 py-2.5 text-sm font-semibold text-white shadow-lg transition-shadow duration-300 hover:shadow-xl sm:w-56 dark:bg-white dark:text-black"
>
Get Started
</Link>
</motion.div>
);
}
const BackgroundGrids = () => {
return (
<div className="pointer-events-none absolute inset-0 z-0 grid h-full w-full -rotate-45 transform select-none grid-cols-2 gap-10 md:grid-cols-4">
@ -126,7 +206,7 @@ const BackgroundGrids = () => {
<GridLineVertical className="left-0" />
<GridLineVertical className="left-auto right-0" />
</div>
<div className="relative h-full w-full bg-gradient-to-b from-transparent via-neutral-100 to-transparent dark:via-neutral-800">
<div className="relative h-full w-full bg-linear-to-b from-transparent via-neutral-100 to-transparent dark:via-neutral-800">
<GridLineVertical className="left-0" />
<GridLineVertical className="left-auto right-0" />
</div>
@ -237,7 +317,7 @@ const CollisionMechanism = React.forwardRef<
repeatDelay: beamOptions.repeatDelay || 0,
}}
className={cn(
"absolute left-96 top-20 m-auto h-14 w-px rounded-full bg-gradient-to-t from-orange-500 via-yellow-500 to-transparent",
"absolute left-96 top-20 m-auto h-14 w-px rounded-full bg-linear-to-t from-orange-500 via-yellow-500 to-transparent",
beamOptions.className
)}
/>
@ -276,7 +356,7 @@ const Explosion = ({ ...props }: React.HTMLProps<HTMLDivElement>) => {
animate={{ opacity: [0, 1, 0] }}
exit={{ opacity: 0 }}
transition={{ duration: 1, ease: "easeOut" }}
className="absolute -inset-x-10 top-0 m-auto h-[4px] w-10 rounded-full bg-gradient-to-r from-transparent via-orange-500 to-transparent blur-sm"
className="absolute -inset-x-10 top-0 m-auto h-[4px] w-10 rounded-full bg-linear-to-r from-transparent via-orange-500 to-transparent blur-sm"
></motion.div>
{spans.map((span) => (
<motion.span
@ -284,7 +364,7 @@ const Explosion = ({ ...props }: React.HTMLProps<HTMLDivElement>) => {
initial={{ x: span.initialX, y: span.initialY, opacity: 1 }}
animate={{ x: span.directionX, y: span.directionY, opacity: 0 }}
transition={{ duration: Math.random() * 1.5 + 0.5, ease: "easeOut" }}
className="absolute h-1 w-1 rounded-full bg-gradient-to-b from-orange-500 to-yellow-500"
className="absolute h-1 w-1 rounded-full bg-linear-to-b from-orange-500 to-yellow-500"
/>
))}
</div>
@ -307,11 +387,11 @@ const GridLineVertical = ({ className, offset }: { className?: string; offset?:
} as React.CSSProperties
}
className={cn(
"absolute top-[calc(var(--offset)/2*-1)] h-[calc(100%+var(--offset))] w-[var(--width)]",
"absolute top-[calc(var(--offset)/2*-1)] h-[calc(100%+var(--offset))] w-(--width)",
"bg-[linear-gradient(to_bottom,var(--color),var(--color)_50%,transparent_0,transparent)]",
"[background-size:var(--width)_var(--height)]",
"[mask:linear-gradient(to_top,var(--background)_var(--fade-stop),transparent),_linear-gradient(to_bottom,var(--background)_var(--fade-stop),transparent),_linear-gradient(black,black)]",
"[mask-composite:exclude]",
"bg-size-[var(--width)_var(--height)]",
"[mask:linear-gradient(to_top,var(--background)_var(--fade-stop),transparent),linear-gradient(to_bottom,var(--background)_var(--fade-stop),transparent),linear-gradient(black,black)]",
"mask-exclude",
"z-30",
"dark:bg-[linear-gradient(to_bottom,var(--color-dark),var(--color-dark)_50%,transparent_0,transparent)]",
className