diff --git a/dev/docker-compose.yml b/dev/docker-compose.yml index 8c63e89..3b66d9e 100644 --- a/dev/docker-compose.yml +++ b/dev/docker-compose.yml @@ -8,4 +8,11 @@ services: volumes: - ./psql:/var/lib/postgresql/data ports: - - 5432:5432 \ No newline at end of file + - 5432:5432 + redis: + image: redis:alpine + user: 1000:1000 + volumes: + - ./redis:/data + ports: + - 6379:6379 \ No newline at end of file diff --git a/package.json b/package.json index 8c99636..cc3eec9 100644 --- a/package.json +++ b/package.json @@ -30,11 +30,11 @@ "arctic": "^2.3.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.0", - "cmdk": "1.0.0", + "cmdk": "1.1.1", "input-otp": "^1.4.1", "ioredis": "^5.4.1", "lucia": "^3.1.1", - "lucide-react": "^0.368.0", + "lucide-react": "^0.488.0", "next": "^15.3.0", "next-themes": "^0.4.4", "openai": "^4.77.0", @@ -42,11 +42,12 @@ "react-dom": "^19.0.0-rc.1", "react-hook-form": "^7.54.1", "sonner": "^1.4.41", - "tailwind-merge": "^2.2.2", + "tailwind-merge": "^3.2.0", "tailwindcss-animate": "^1.0.7", "zod": "^3.24.1" }, "devDependencies": { + "@tailwindcss/postcss": "^4.1.4", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", @@ -55,7 +56,7 @@ "postcss": "^8", "prisma": "^6.1.0", "shadcn": "^2.1.7", - "tailwindcss": "^3.4.1", + "tailwindcss": "^4.1.4", "typescript": "^5" }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" diff --git a/postcss.config.mjs b/postcss.config.mjs index 1a69fd2..5d6d845 100644 --- a/postcss.config.mjs +++ b/postcss.config.mjs @@ -1,7 +1,7 @@ /** @type {import('postcss-load-config').Config} */ const config = { plugins: { - tailwindcss: {}, + '@tailwindcss/postcss': {}, }, }; diff --git a/src/app/(protected)/create/page.tsx b/src/app/(protected)/create/page.tsx index cd1d484..ee5ba71 100644 --- a/src/app/(protected)/create/page.tsx +++ b/src/app/(protected)/create/page.tsx @@ -28,7 +28,7 @@ export default function CreateForm() { }, ]} submitText="Submit" - submitClassname="w-full !mt-5" + submitClassname="w-full mt-5!" onActionComplete={(res) => { // @ts-ignore yea if (res && res.id) { diff --git a/src/app/(public)/page.tsx b/src/app/(public)/page.tsx index b24f7b1..4992024 100644 --- a/src/app/(public)/page.tsx +++ b/src/app/(public)/page.tsx @@ -16,7 +16,7 @@ export default async function Home() {
{/* Hero Section */} -
+
@@ -31,7 +31,7 @@ export default async function Home() {
-

+

User feedback for developers

@@ -66,7 +66,7 @@ export default async function Home() {

{/* Abstract Decoration */} -
+
{/* Features Cards */} @@ -190,7 +190,7 @@ export default async function Home() { {/* CTA Section */}
-
+

Ready to get started?

Join developers who are building better products with user feedback diff --git a/src/app/globals.css b/src/app/globals.css index dc3e471..5739526 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,85 +1,177 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; +@import 'tailwindcss'; -@layer base { - :root { - --background: 220 23.077% 94.902%; - --foreground: 233.793 16.022% 35.49%; +@custom-variant dark (&:is(.dark *)); - --muted: 222.857 15.909% 82.745%; - --muted-foreground: 233.333 12.796% 41.373%; +@theme inline { + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-background: var(--background); + --color-foreground: var(--foreground); - --popover: 220 23.077% 94.902%; - --popover-foreground: 233.793 16.022% 35.49%; + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); - --card: 220 23.077% 94.902%; - --card-foreground: 233.793 16.022% 35.49%; + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); - --border: 225 13.559% 76.863%; - --input: 225 13.559% 76.863%; + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); - --primary: 219.907 91.489% 53.922%; - --primary-foreground: 220 23.077% 94.902%; + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); - --secondary: 222.857 15.909% 82.745%; - --secondary-foreground: 233.793 16.022% 35.49%; + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); - --accent: 222.857 15.909% 82.745%; - --accent-foreground: 233.793 16.022% 35.49%; + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); - --destructive: 347.077 86.667% 44.118%; - --destructive-foreground: 220 21.951% 91.961%; + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); - --ring: 233.793 16.022% 35.49%; + --color-surface1: var(--surface-1); - --surface-1: 225.0 14.0% 77.0%; - --surface-2: 227.0 12.0% 71.0%; + --color-surface2: var(--surface-2); - --mantle: 220.0 22.0% 92.0%; + --color-mantle: var(--mantle); - --radius: 0.5rem; + --radius-lg: var(--radius); + --radius-md: calc(var(--radius) - 2px); + --radius-sm: calc(var(--radius) - 4px); + + --animate-accordion-down: accordion-down 0.2s ease-out; + --animate-accordion-up: accordion-up 0.2s ease-out; + --animate-caret-blink: caret-blink 1.25s ease-out infinite; + + @keyframes accordion-down { + from { + height: 0; + } + to { + height: var(--radix-accordion-content-height); + } } - - .dark { - --background: 240 21.053% 14.902%; - --foreground: 226.154 63.934% 88.039%; - - --muted: 236.842 16.239% 22.941%; - --muted-foreground: 226.667 35.294% 80%; - - --popover: 240 21.053% 14.902%; - --popover-foreground: 226.154 63.934% 88.039%; - - --card: 240 21.053% 14.902%; - --card-foreground: 226.154 63.934% 88.039%; - - --border: 234.286 13.208% 31.176%; - --input: 234.286 13.208% 31.176%; - - --primary: 217.168 91.87% 75.882%; - --primary-foreground: 240 21.053% 14.902%; - - --secondary: 236.842 16.239% 22.941%; - --secondary-foreground: 226.154 63.934% 88.039%; - - --accent: 236.842 16.239% 22.941%; - --accent-foreground: 226.154 63.934% 88.039%; - - --destructive: 343.269 81.25% 74.902%; - --destructive-foreground: 240 21.311% 11.961%; - - --ring: 226.154 63.934% 88.039%; - - --surface-1: 234.0 13.0% 31.0%; - --surface-2: 233.0 12.0% 39.0%; - - --mantle: 240 21.311% 11.961%; - - --radius: 0.5rem; + @keyframes accordion-up { + from { + height: var(--radix-accordion-content-height); + } + to { + height: 0; + } + } + @keyframes caret-blink { + 0%, + 70%, + 100% { + opacity: 1; + } + 20%, + 50% { + opacity: 0; + } } } +@utility container { + margin-inline: auto; + padding-inline: 2rem; + @media (width >= --theme(--breakpoint-sm)) { + max-width: none; + } + @media (width >= 1400px) { + max-width: 1400px; + } +} + +/* + The default border color has changed to `currentcolor` in Tailwind CSS v4, + so we've added these compatibility styles to make sure everything still + looks the same as it did with Tailwind CSS v3. + + If we ever want to remove these styles, we need to add an explicit border + color utility to any element that depends on these defaults. +*/ +@layer base { + *, + ::after, + ::before, + ::backdrop, + ::file-selector-button { + border-color: var(--color-gray-200, currentcolor); + } +} + +:root { + --radius: 0.5rem; + --background: oklch(1 0 0); + --foreground: oklch(0.141 0.005 285.823); + --card: oklch(1 0 0); + --card-foreground: oklch(0.141 0.005 285.823); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.141 0.005 285.823); + --primary: oklch(0.637 0.237 25.331); + --primary-foreground: oklch(0.971 0.013 17.38); + --secondary: oklch(0.967 0.001 286.375); + --secondary-foreground: oklch(0.21 0.006 285.885); + --muted: oklch(0.967 0.001 286.375); + --muted-foreground: oklch(0.552 0.016 285.938); + --accent: oklch(0.967 0.001 286.375); + --accent-foreground: oklch(0.21 0.006 285.885); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.92 0.004 286.32); + --input: oklch(0.92 0.004 286.32); + --ring: oklch(0.637 0.237 25.331); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.141 0.005 285.823); + --sidebar-primary: oklch(0.637 0.237 25.331); + --sidebar-primary-foreground: oklch(0.971 0.013 17.38); + --sidebar-accent: oklch(0.967 0.001 286.375); + --sidebar-accent-foreground: oklch(0.21 0.006 285.885); + --sidebar-border: oklch(0.92 0.004 286.32); + --sidebar-ring: oklch(0.637 0.237 25.331); +} + +.dark { + --background: oklch(0.141 0.005 285.823); + --foreground: oklch(0.985 0 0); + --card: oklch(0.21 0.006 285.885); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.21 0.006 285.885); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.637 0.237 25.331); + --primary-foreground: oklch(0.971 0.013 17.38); + --secondary: oklch(0.274 0.006 286.033); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.274 0.006 286.033); + --muted-foreground: oklch(0.705 0.015 286.067); + --accent: oklch(0.274 0.006 286.033); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.637 0.237 25.331); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.21 0.006 285.885); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.637 0.237 25.331); + --sidebar-primary-foreground: oklch(0.971 0.013 17.38); + --sidebar-accent: oklch(0.274 0.006 286.033); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.637 0.237 25.331); +} + + @layer base { * { @apply border-border; diff --git a/src/components/app/DottedCreateCard/DottedCreateCard.tsx b/src/components/app/DottedCreateCard/DottedCreateCard.tsx index ffff4ad..da23407 100644 --- a/src/components/app/DottedCreateCard/DottedCreateCard.tsx +++ b/src/components/app/DottedCreateCard/DottedCreateCard.tsx @@ -3,14 +3,14 @@ import Link from 'next/link'; export default function DottedCreateCard() { return ( -

+

Create

-
+
diff --git a/src/components/app/InviteCodeViewer/InviteCodeViewer.tsx b/src/components/app/InviteCodeViewer/InviteCodeViewer.tsx index c898382..3d90390 100644 --- a/src/components/app/InviteCodeViewer/InviteCodeViewer.tsx +++ b/src/components/app/InviteCodeViewer/InviteCodeViewer.tsx @@ -13,7 +13,7 @@ export default function InviteCodeViewer({ code }: { code: string }) { type="text" id="inviteCode" placeholder="Invite code" - className={hover ? '' : 'blur-sm'} + className={hover ? '' : 'blur-xs'} onChange={() => {}} onMouseOver={() => setHover(true)} onMouseOut={() => setHover(false)} diff --git a/src/components/app/NavBar/NavBar.tsx b/src/components/app/NavBar/NavBar.tsx index a306bef..7c5e65b 100644 --- a/src/components/app/NavBar/NavBar.tsx +++ b/src/components/app/NavBar/NavBar.tsx @@ -45,7 +45,7 @@ export default function Navbar() { const [, logoutAction] = useActionState(logout, null); return ( <> -