From 2c7973b15e923d58e5fbcce3fad5b2168e800bfb Mon Sep 17 00:00:00 2001 From: STIWARTs Date: Wed, 4 Mar 2026 15:46:26 +0530 Subject: [PATCH 1/3] feat: implement scroll animations, hover states, and drawing svgs to eliminate static feel --- packages/frontend/src/app/page.tsx | 70 +++++++-- .../src/components/InteractiveGrid.tsx | 148 ++++++++---------- 2 files changed, 120 insertions(+), 98 deletions(-) diff --git a/packages/frontend/src/app/page.tsx b/packages/frontend/src/app/page.tsx index 8cd2c6c..36e7f07 100644 --- a/packages/frontend/src/app/page.tsx +++ b/packages/frontend/src/app/page.tsx @@ -74,8 +74,8 @@ export default function HomePage() { AutoDev
- Product How it works + Product Customers Pricing
@@ -223,9 +223,10 @@ export default function HomePage() { key={i} initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} + whileHover={{ y: -8, transition: { duration: 0.2 } }} viewport={{ once: true }} transition={{ delay: i * 0.15 }} - className="relative z-10 flex flex-col items-center text-center" + className="relative z-10 flex flex-col items-center text-center cursor-default bg-brand-surface p-6 rounded-sm border border-transparent hover:border-brand-border/50 hover:bg-brand-bg/50 transition-colors" >
@@ -268,23 +269,53 @@ export default function HomePage() { >
-
+
FRONTEND
Next.js App
-
+ {/* Connecting Line */} - -
+ + + +
BACKEND
Express API
REST + WebSockets
-
+ {/* Connecting Line */} - -
+ + + +
DATABASE
PostgreSQL
-
+
@@ -357,13 +388,24 @@ export default function HomePage() {
{/* Message 1 */} -
+
How does the authentication middleware work here? (कृपया हिंदी में समझाएं)
-
+ {/* Message 2 */} -
+

ज़रूर!

इस प्रोजेक्ट में, ऑथेंटिकेशन src/middleware/auth.ts में संभाला गया है।

@@ -373,7 +415,7 @@ export default function HomePage() {
  • अगर टोकन सही है, तो यह यूज़र डेटा को req.user में डाल देता है ताकि आगे इस्तेमाल हो सके।
  • -
    +
    diff --git a/packages/frontend/src/components/InteractiveGrid.tsx b/packages/frontend/src/components/InteractiveGrid.tsx index 7dc86fa..2e8ade8 100644 --- a/packages/frontend/src/components/InteractiveGrid.tsx +++ b/packages/frontend/src/components/InteractiveGrid.tsx @@ -17,37 +17,13 @@ export function InteractiveGrid() { canvas.width = width; canvas.height = height; - // We keep target angles for smooth interpolation - const cells: { targetAngle: number; currentAngle: number; cx: number; cy: number }[] = []; - const spacing = 35; // Pixels between each vector arrow - - let cols = Math.ceil(width / spacing); - let rows = Math.ceil(height / spacing); - - const initCells = () => { - cells.length = 0; - cols = Math.ceil(width / spacing); - rows = Math.ceil(height / spacing); - for (let i = 0; i < cols; i++) { - for (let j = 0; j < rows; j++) { - cells.push({ - cx: i * spacing + spacing / 2, - cy: j * spacing + spacing / 2, - targetAngle: 0, - currentAngle: 0 - }); - } - } - }; - initCells(); - - const mouse = { x: -1000, y: -1000 }; + const mouse = { x: width / 2, y: height / 2, targetX: width / 2, targetY: height / 2 }; let isMousePresent = false; const handleMouseMove = (e: MouseEvent) => { const rect = canvas.getBoundingClientRect(); - mouse.x = e.clientX - rect.left; - mouse.y = e.clientY - rect.top; + mouse.targetX = e.clientX - rect.left; + mouse.targetY = e.clientY - rect.top; isMousePresent = true; }; @@ -63,7 +39,6 @@ export function InteractiveGrid() { height = window.innerHeight; canvas.width = width; canvas.height = height; - initCells(); }; window.addEventListener("resize", handleResize); @@ -72,63 +47,68 @@ export function InteractiveGrid() { const render = () => { ctx.clearRect(0, 0, width, height); - time += 0.01; + time += 0.005; + + // Smooth interpolation for mouse + if (!isMousePresent) { + // Ambient wandering when mouse is away + mouse.targetX = width / 2 + Math.sin(time) * 300; + mouse.targetY = height / 2 + Math.cos(time * 0.8) * 200; + } + mouse.x += (mouse.targetX - mouse.x) * 0.05; + mouse.y += (mouse.targetY - mouse.y) * 0.05; + + const gridSize = 40; - for (const cell of cells) { - const { cx, cy } = cell; - - let dist = 1000; - - if (isMousePresent) { - const dx = mouse.x - cx; - const dy = mouse.y - cy; - cell.targetAngle = Math.atan2(dy, dx); - dist = Math.sqrt(dx * dx + dy * dy); - } else { - // Idle ambient wave motion - cell.targetAngle = Math.sin(time + cx * 0.005) * Math.cos(time + cy * 0.005) * Math.PI; - } - - // Smooth rotation interpolation - // To prevent spinning the wrong way across the -PI/PI boundary: - let diff = cell.targetAngle - cell.currentAngle; - while (diff < -Math.PI) diff += Math.PI * 2; - while (diff > Math.PI) diff -= Math.PI * 2; - - cell.currentAngle += diff * 0.1; - - ctx.save(); - ctx.translate(cx, cy); - ctx.rotate(cell.currentAngle); - - // Calculate intensity based on distance from mouse - // Max influence radius is 400px - const intensity = isMousePresent ? Math.max(0, 1 - dist / 400) : 0; - - // Draw the vector line - ctx.beginPath(); - ctx.moveTo(0, 0); - const lineLength = 6 + intensity * 10; // Stretches out when near cursor - ctx.lineTo(lineLength, 0); - - if (intensity > 0) { - ctx.strokeStyle = `rgba(226, 90, 52, ${0.1 + intensity * 0.8})`; // Brand accent color glow - } else { - ctx.strokeStyle = `rgba(161, 161, 170, 0.15)`; // Muted idle color - } - - ctx.lineWidth = 1.5; - ctx.lineCap = "round"; - ctx.stroke(); - - // Draw the origin dot - ctx.beginPath(); - ctx.arc(0, 0, 1.5, 0, Math.PI * 2); - ctx.fillStyle = intensity > 0 ? `rgba(226, 90, 52, ${0.3 + intensity * 0.7})` : `rgba(161, 161, 170, 0.4)`; - ctx.fill(); - - ctx.restore(); + // Subtle parallax shift based on mouse position + // This makes the entire grid gently shift in the opposite direction of the mouse + const parallaxX = (mouse.x / width - 0.5) * -40; + const parallaxY = (mouse.y / height - 0.5) * -40; + + // Draw grid + ctx.lineWidth = 1; + ctx.beginPath(); + + // Calculate start and end points including parallax offset + const startX = (parallaxX % gridSize) - gridSize; + const startY = (parallaxY % gridSize) - gridSize; + + for (let x = startX; x <= width + gridSize; x += gridSize) { + ctx.moveTo(x, 0); + ctx.lineTo(x, height); + } + for (let y = startY; y <= height + gridSize; y += gridSize) { + ctx.moveTo(0, y); + ctx.lineTo(width, y); } + + // Muted technical grid color + ctx.strokeStyle = "rgba(161, 161, 170, 0.4)"; + ctx.stroke(); + + // Apply the flashlight mask using destination-in + const gradient = ctx.createRadialGradient( + mouse.x, mouse.y, 0, + mouse.x, mouse.y, 600 + ); + // Center is fully opaque, edges fade to transparent + gradient.addColorStop(0, "rgba(255, 255, 255, 1)"); + gradient.addColorStop(1, "rgba(255, 255, 255, 0)"); + + ctx.globalCompositeOperation = "destination-in"; + ctx.fillStyle = gradient; + ctx.fillRect(0, 0, width, height); + + // Add a subtle brand-colored ambient glow over the focused area of the grid + ctx.globalCompositeOperation = "source-over"; + const ambientGlow = ctx.createRadialGradient( + mouse.x, mouse.y, 0, + mouse.x, mouse.y, 400 + ); + ambientGlow.addColorStop(0, "rgba(226, 90, 52, 0.1)"); // Subtle brand accent + ambientGlow.addColorStop(1, "rgba(226, 90, 52, 0)"); + ctx.fillStyle = ambientGlow; + ctx.fillRect(0, 0, width, height); animationFrameId = requestAnimationFrame(render); }; @@ -146,7 +126,7 @@ export function InteractiveGrid() { return ( ); } From 687a96f33bae3e29216afc7f83492ceafe95f25c Mon Sep 17 00:00:00 2001 From: STIWARTs Date: Thu, 5 Mar 2026 23:47:25 +0530 Subject: [PATCH 2/3] feat: animate logo link with smooth scroll to top --- packages/frontend/src/app/page.tsx | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/app/page.tsx b/packages/frontend/src/app/page.tsx index 36e7f07..a4ea154 100644 --- a/packages/frontend/src/app/page.tsx +++ b/packages/frontend/src/app/page.tsx @@ -67,7 +67,16 @@ export default function HomePage() { {/* ─── NAVIGATION ─── */}