diff --git a/.gitignore b/.gitignore
index 5ef6a52..906100b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
+
+# bun
+bun.lock*
\ No newline at end of file
diff --git a/components.json b/components.json
new file mode 100644
index 0000000..0e8b633
--- /dev/null
+++ b/components.json
@@ -0,0 +1,21 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "new-york",
+ "rsc": true,
+ "tsx": true,
+ "tailwind": {
+ "config": "tailwind.config.ts",
+ "css": "src/app/globals.css",
+ "baseColor": "neutral",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib",
+ "hooks": "@/hooks"
+ },
+ "iconLibrary": "lucide"
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 1713654..4076fbd 100644
--- a/package.json
+++ b/package.json
@@ -9,26 +9,31 @@
"lint": "next lint"
},
"dependencies": {
+ "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
- "lucide-react": "^0.488.0",
- "motion": "^12.7.3",
+ "lucide-react": "^0.503.0",
+ "motion": "^12.7.4",
"next": "15.3.1-canary.10",
"next-themes": "^0.4.6",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-icons": "^5.5.0",
"tailwind-merge": "^3.2.0",
- "tailwindcss-animate": "^1.0.7"
+ "tailwindcss-animate": "^1.0.7",
+ "tw-animate-css": "^1.2.8"
},
"devDependencies": {
- "typescript": "^5",
- "@types/node": "^20",
- "@types/react": "^19",
- "@types/react-dom": "^19",
- "@tailwindcss/postcss": "^4",
- "tailwindcss": "^4",
- "eslint": "^9",
+ "typescript": "^5.8.3",
+ "@types/node": "^20.17.30",
+ "@types/react": "^19.1.2",
+ "@types/react-dom": "^19.1.2",
+ "@tailwindcss/postcss": "^4.1.4",
+ "tailwindcss": "^4.1.4",
+ "eslint": "^9.25.1",
"eslint-config-next": "15.3.1-canary.10",
- "@eslint/eslintrc": "^3"
- }
+ "@eslint/eslintrc": "^3.3.1"
+ },
+ "trustedDependencies": [
+ "unrs-resolver"
+ ]
}
diff --git a/src/app/globals.css b/src/app/globals.css
index 64bfaa6..39250c8 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -1,65 +1,108 @@
@import "tailwindcss";
+@custom-variant dark (&:is(.dark *));
+
:root {
- --background: 210 20% 98%;
- --foreground: 222.2 84% 4.9%;
- --card: 0 0% 100%;
- --card-foreground: 222.2 84% 4.9%;
+ --card: oklch(1 0 0);
+ --card-foreground: oklch(0.145 0 0);
- --popover: 0 0% 100%;
- --popover-foreground: 222.2 84% 4.9%;
+ --popover: oklch(1 0 0);
+ --popover-foreground: oklch(0.145 0 0);
- --primary: 222.2 47.4% 11.2%;
- --primary-foreground: 210 40% 98%;
+ --primary: oklch(0.205 0 0);
+ --primary-foreground: oklch(0.985 0 0);
- --secondary: 210 40% 96.1%;
- --secondary-foreground: 222.2 47.4% 11.2%;
+ --secondary: oklch(0.97 0 0);
+ --secondary-foreground: oklch(0.205 0 0);
- --muted: 210 40% 96.1%;
- --muted-foreground: 215.4 16.3% 46.9%;
+ --muted: oklch(0.97 0 0);
+ --muted-foreground: oklch(0.556 0 0);
- --accent: 210 40% 96.1%;
- --accent-foreground: 222.2 47.4% 11.2%;
+ --accent: oklch(0.97 0 0);
+ --accent-foreground: oklch(0.205 0 0);
- --destructive: 0 84.2% 60.2%;
+ --destructive: oklch(0.577 0.245 27.325);
--destructive-foreground: 210 40% 98%;
- --border: 214.3 31.8% 91.4%;
- --input: 214.3 31.8% 91.4%;
- --ring: 222.2 84% 4.9%;
+ --border: oklch(0.922 0 0);
+ --input: oklch(0.922 0 0);
+ --ring: oklch(0.708 0 0);
- --radius: 0.5rem;
+ --radius: 0.625rem;
+
+ --background: oklch(1 0 0);
+
+ --foreground: oklch(0.145 0 0);
+
+ --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.145 0 0);
+
+ --sidebar-primary: oklch(0.205 0 0);
+
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+
+ --sidebar-accent: oklch(0.97 0 0);
+
+ --sidebar-accent-foreground: oklch(0.205 0 0);
+
+ --sidebar-border: oklch(0.922 0 0);
+
+ --sidebar-ring: oklch(0.708 0 0);
}
.dark {
- --background: 270 50% 10%;
- --foreground: 210 40% 98%;
+ --background: oklch(0.145 0 0);
+ --foreground: oklch(0.985 0 0);
- --card: 222.2 84% 4.9%;
- --card-foreground: 210 40% 98%;
+ --card: oklch(0.205 0 0);
+ --card-foreground: oklch(0.985 0 0);
- --popover: 222.2 84% 4.9%;
- --popover-foreground: 210 40% 98%;
+ --popover: oklch(0.205 0 0);
+ --popover-foreground: oklch(0.985 0 0);
- --primary: 210 40% 98%;
- --primary-foreground: 222.2 47.4% 11.2%;
+ --primary: oklch(0.922 0 0);
+ --primary-foreground: oklch(0.205 0 0);
- --secondary: 217.2 32.6% 17.5%;
- --secondary-foreground: 210 40% 98%;
+ --secondary: oklch(0.269 0 0);
+ --secondary-foreground: oklch(0.985 0 0);
- --muted: 217.2 32.6% 17.5%;
- --muted-foreground: 215 20.2% 65.1%;
+ --muted: oklch(0.269 0 0);
+ --muted-foreground: oklch(0.708 0 0);
- --accent: 217.2 32.6% 17.5%;
- --accent-foreground: 210 40% 98%;
+ --accent: oklch(0.269 0 0);
+ --accent-foreground: oklch(0.985 0 0);
- --destructive: 0 62.8% 30.6%;
+ --destructive: oklch(0.704 0.191 22.216);
--destructive-foreground: 210 40% 98%;
- --border: 217.2 32.6% 17.5%;
- --input: 217.2 32.6% 17.5%;
- --ring: 212.7 26.8% 83.9%;
+ --border: oklch(1 0 0 / 10%);
+ --input: oklch(1 0 0 / 15%);
+ --ring: oklch(0.556 0 0);
+ --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.205 0 0);
+ --sidebar-foreground: oklch(0.985 0 0);
+ --sidebar-primary: oklch(0.488 0.243 264.376);
+ --sidebar-primary-foreground: oklch(0.985 0 0);
+ --sidebar-accent: oklch(0.269 0 0);
+ --sidebar-accent-foreground: oklch(0.985 0 0);
+ --sidebar-border: oklch(1 0 0 / 10%);
+ --sidebar-ring: oklch(0.556 0 0);
}
@theme inline {
@@ -67,6 +110,39 @@
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
+ --color-sidebar-ring: var(--sidebar-ring);
+ --color-sidebar-border: var(--sidebar-border);
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
+ --color-sidebar-accent: var(--sidebar-accent);
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
+ --color-sidebar-primary: var(--sidebar-primary);
+ --color-sidebar-foreground: var(--sidebar-foreground);
+ --color-sidebar: var(--sidebar);
+ --color-chart-5: var(--chart-5);
+ --color-chart-4: var(--chart-4);
+ --color-chart-3: var(--chart-3);
+ --color-chart-2: var(--chart-2);
+ --color-chart-1: var(--chart-1);
+ --color-ring: var(--ring);
+ --color-input: var(--input);
+ --color-border: var(--border);
+ --color-destructive: var(--destructive);
+ --color-accent-foreground: var(--accent-foreground);
+ --color-accent: var(--accent);
+ --color-muted-foreground: var(--muted-foreground);
+ --color-muted: var(--muted);
+ --color-secondary-foreground: var(--secondary-foreground);
+ --color-secondary: var(--secondary);
+ --color-primary-foreground: var(--primary-foreground);
+ --color-primary: var(--primary);
+ --color-popover-foreground: var(--popover-foreground);
+ --color-popover: var(--popover);
+ --color-card-foreground: var(--card-foreground);
+ --color-card: var(--card);
+ --radius-sm: calc(var(--radius) - 4px);
+ --radius-md: calc(var(--radius) - 2px);
+ --radius-lg: var(--radius);
+ --radius-xl: calc(var(--radius) + 4px);
}
body {
@@ -80,3 +156,12 @@ body {
background-origin: border-box;
background-clip: padding-box, border-box;
}
+
+@layer base {
+ * {
+ @apply border-border outline-ring/50;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 96732f2..432fdc9 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,26 +1,68 @@
import Header from "@/components/Header"
import { Interactives } from "@/components/header/Interactives"
+import Defaults from "@/defaults"
+import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
+import { CalendarDays, Clock } from "lucide-react"
+
+const posts = [
+ {
+ id: 1,
+ title: "Post Ex 1",
+ description: "Just another example post",
+ date: "2025-04-22",
+ readTime: "5 min read",
+ category: "Amazing Category"
+ },
+ {
+ id: 2,
+ title: "Post Ex 2",
+ description: "Just another example post",
+ date: "2025-04-22",
+ readTime: "4 min read",
+ category: "Fantastic Category"
+ },
+]
export default function Home() {
return (
-
{process.env.NEXT_PUBLIC_MBLOG_NAME}
+
{process.env.NEXT_PUBLIC_MBLOG_NAME || Defaults.blogName}
- This is some really nice content. It has so so so so so so so so so much text.
+ {Defaults.blogDescription}
- {Array.from({ length: 10 }).map((_, i) => (
-
-
-
Very nice card
-
- This is some really nice content. It has so so so so so so so so so much text.
-
-
-
- ))}
+
+ {posts.map((post) => (
+
+
+
+ {post.category}
+ {post.title}
+ {post.description}
+
+
+
+
+
+ {post.date}
+
+
+
+ {post.readTime}
+
+
+
+
+
+
+
+
+ ))}
+
)
diff --git a/src/components/header/Interactives.tsx b/src/components/header/Interactives.tsx
index 0a25c28..0afb49e 100644
--- a/src/components/header/Interactives.tsx
+++ b/src/components/header/Interactives.tsx
@@ -1,7 +1,6 @@
"use client"
import type React from "react"
-
import { useState, useRef, useEffect } from "react"
import { useTheme } from "next-themes"
import { cn } from "@/lib/utils"
@@ -66,7 +65,6 @@ export function Interactives({ children, className = "" }: InteractivesProps) {
transparent 60%
)
`,
- border: isHovering ? '1px solid rgba(147, 51, 234, 0.5)' : '1px solid transparent',
opacity: isHovering ? 1 : 0,
}
}
@@ -80,9 +78,9 @@ export function Interactives({ children, className = "" }: InteractivesProps) {
onMouseEnter={() => setIsHovering(true)}
onMouseLeave={() => setIsHovering(false)}
>
-
+
diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx
new file mode 100644
index 0000000..d05bbc6
--- /dev/null
+++ b/src/components/ui/card.tsx
@@ -0,0 +1,92 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+function Card({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardAction({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardContent({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ )
+}
+
+export {
+ Card,
+ CardHeader,
+ CardFooter,
+ CardTitle,
+ CardAction,
+ CardDescription,
+ CardContent,
+}
diff --git a/src/defaults.ts b/src/defaults.ts
new file mode 100644
index 0000000..ba84b57
--- /dev/null
+++ b/src/defaults.ts
@@ -0,0 +1,4 @@
+export default class Defaults {
+ static readonly blogName = "My Blog"
+ static readonly blogDescription = "This is a placeholder description for your blog. It's time for setup!"
+}
\ No newline at end of file