diff --git a/apps/blogs/.vercel/project.json b/apps/blogs/.vercel/project.json new file mode 100644 index 0000000..576f6a3 --- /dev/null +++ b/apps/blogs/.vercel/project.json @@ -0,0 +1,16 @@ +{ + "projectId": "prj_NgfV08gylZB0IMTiK3SBS9eG7BFa", + "orgId": "team_fRT3JqS9WXaErZ3MPOJqCcdg", + "projectName": "vectorless-blog", + "settings": { + "createdAt": 1781973251317, + "framework": "nextjs", + "devCommand": null, + "installCommand": null, + "buildCommand": null, + "outputDirectory": null, + "rootDirectory": "apps/blogs", + "directoryListing": false, + "nodeVersion": "24.x" + } +} diff --git a/apps/blogs/app/VectorlessIcon.tsx b/apps/blogs/app/VectorlessIcon.tsx new file mode 100644 index 0000000..977e1d2 --- /dev/null +++ b/apps/blogs/app/VectorlessIcon.tsx @@ -0,0 +1,50 @@ +import { cn } from "@/lib/utils"; + +interface VectorlessIconProps { + size?: number; + className?: string; +} + +export function VectorlessIcon({ size = 32, className }: VectorlessIconProps) { + return ( + + ); +} + +export function VectorlessDot({ size = 16, className }: VectorlessIconProps) { + return ( + + ); +} + +export default VectorlessIcon; diff --git a/apps/blogs/app/globals.css b/apps/blogs/app/globals.css index c9a35af..475d2e5 100644 --- a/apps/blogs/app/globals.css +++ b/apps/blogs/app/globals.css @@ -1,40 +1,115 @@ @import "tailwindcss"; @import "tw-animate-css"; +@custom-variant dark (&:is(.dark *)); + @theme { --font-sans: var(--font-geist), ui-sans-serif, system-ui, sans-serif; - --font-display: var(--font-plus-jakarta), var(--font-geist), ui-sans-serif, system-ui, sans-serif; - --font-mono: var(--font-geist-mono), ui-monospace, SFMono-Regular, monospace; + --font-display: var(--font-geist), ui-sans-serif, system-ui, sans-serif; + --font-mid: var(--font-geist), ui-sans-serif, system-ui, sans-serif; + --font-data: var(--font-geist-mono), ui-monospace, SFMono-Regular, monospace; --font-serif: var(--font-instrument-serif), ui-serif, Georgia, serif; - --color-bg-base: #FAF6EE; - --color-bg-paper: #FAF8F5; - --color-text-base: #0F0F0F; - --color-text-secondary: #3F3F3E; - --color-text-muted: #70706F; + --color-bg-base: #ffffff; + --color-bg-dark: #0a0a0a; + --color-bg-deep: #050505; + + --color-text-base: #0a0a0a; + --color-text-dark: #0a0a0a; + --color-text-secondary: #3f3f36; + --color-text-muted: #71717a; + --color-brand-blue: #1456f0; --color-brand-pink: #ea5ec1; - --color-border-light: #F0EDE6; - --color-border-gray: #E3DFD5; + --color-primary-500: #3b82f6; + --color-primary-600: #2563eb; + + --color-border-light: #f2f3f5; + --color-border-gray: #e5e7eb; + + /* shadcn/ui color mappings for Tailwind v4 */ + --color-background: hsl(var(--background)); + --color-foreground: hsl(var(--foreground)); + --color-card: hsl(var(--card)); + --color-card-foreground: hsl(var(--card-foreground)); + --color-popover: hsl(var(--popover)); + --color-popover-foreground: hsl(var(--popover-foreground)); + --color-primary: hsl(var(--primary)); + --color-primary-foreground: hsl(var(--primary-foreground)); + --color-secondary: hsl(var(--secondary)); + --color-secondary-foreground: hsl(var(--secondary-foreground)); + --color-muted: hsl(var(--muted)); + --color-muted-foreground: hsl(var(--muted-foreground)); + --color-accent: hsl(var(--accent)); + --color-accent-foreground: hsl(var(--accent-foreground)); + --color-destructive: hsl(var(--destructive)); + --color-destructive-foreground: hsl(var(--destructive-foreground)); + --color-border: hsl(var(--border)); + --color-input: hsl(var(--input)); + --color-ring: hsl(var(--ring)); + + --animate-gradient: gradient 8s linear infinite; + @keyframes gradient { + to { background-position: 200% center; } + } +} + +/* ─── shadcn/ui Design Tokens ─── */ +:root { + --background: 0 0% 100%; + --foreground: 0 0% 13.3%; + --card: 0 0% 100%; + --card-foreground: 0 0% 13.3%; + --popover: 0 0% 100%; + --popover-foreground: 0 0% 13.3%; + --primary: 222 89% 51%; + --primary-foreground: 0 0% 100%; + --secondary: 210 15% 95%; + --secondary-foreground: 210 15% 30%; + --muted: 210 15% 96%; + --muted-foreground: 210 10% 45%; + --accent: 210 15% 95%; + --accent-foreground: 210 15% 30%; + --destructive: 0 84% 60%; + --destructive-foreground: 0 0% 100%; + --border: 220 13% 91%; + --input: 220 13% 91%; + --ring: 222 89% 51%; + --radius: 0.625rem; } @layer base { html, body { - background-color: #FAF6EE !important; - color: #0F0F0F; + background-color: #ffffff !important; + color: #0a0a0a; margin: 0; padding: 0; width: 100%; height: 100%; } + + * { + border-color: hsl(var(--border)); + } } @layer utilities { + .hide-scrollbar { + -ms-overflow-style: none; + scrollbar-width: none; + } + .hide-scrollbar::-webkit-scrollbar { + display: none; + } + .grid-paper { background-image: - linear-gradient(to right, rgba(20, 86, 240, 0.03) 1px, transparent 1px), - linear-gradient(to bottom, rgba(20, 86, 240, 0.03) 1px, transparent 1px); + linear-gradient(to right, rgba(20, 86, 240, 0.05) 1px, transparent 1px), + linear-gradient(to bottom, rgba(20, 86, 240, 0.05) 1px, transparent 1px); background-size: 56px 56px; } -} + .text-balance { + text-wrap: balance; + } +} diff --git a/apps/blogs/app/layout.tsx b/apps/blogs/app/layout.tsx index 52204ab..e2df046 100644 --- a/apps/blogs/app/layout.tsx +++ b/apps/blogs/app/layout.tsx @@ -1,10 +1,9 @@ import type { Metadata } from "next"; -import { Geist, Geist_Mono, Instrument_Serif, Plus_Jakarta_Sans } from "next/font/google"; +import { Geist, Geist_Mono, Instrument_Serif } from "next/font/google"; import "./globals.css"; const geist = Geist({ subsets: ["latin"], variable: "--font-geist" }); const geistMono = Geist_Mono({ subsets: ["latin"], variable: "--font-geist-mono" }); -const plusJakartaSans = Plus_Jakarta_Sans({ subsets: ["latin"], variable: "--font-plus-jakarta" }); const instrumentSerif = Instrument_Serif({ weight: "400", subsets: ["latin"], @@ -24,10 +23,10 @@ export default function RootLayout({ return (
{children} diff --git a/apps/blogs/app/page.tsx b/apps/blogs/app/page.tsx index 031874f..f680adb 100644 --- a/apps/blogs/app/page.tsx +++ b/apps/blogs/app/page.tsx @@ -1,24 +1,20 @@ 'use client'; -import React, { useState, useEffect, useRef } from 'react'; +import React, { useState, useEffect } from 'react'; import { motion, AnimatePresence } from 'motion/react'; +import Link from 'next/link'; import { ArrowRight, X, Calendar, Clock, - Check, - Sparkles, - Search, - FileText, - Database, - Cpu, - Play, + Search, + BookOpen, Terminal, - ArrowUpRight, - BookOpen, - ChevronRight + ChevronRight, + Menu } from 'lucide-react'; +import { VectorlessIcon, VectorlessDot } from './VectorlessIcon'; // Categories matching our blog categories type Category = 'All' | 'Product Updates' | 'Engineering' | 'Guides' | 'Features'; @@ -155,50 +151,22 @@ const BLOG_POSTS: BlogPost[] = [ } ]; -function VectorlessIcon({ size = 32, className }: { size?: number; className?: string }) { - return ( - - ); -} - -// Highly stylized schematic vectors +// Technical blueprint vectors function BlueprintIllustration({ type }: { type: BlogPost['imageType'] }) { if (type === 'architecture') { return ( @@ -208,13 +176,10 @@ function BlueprintIllustration({ type }: { type: BlogPost['imageType'] }) { return (