├── app ├── globals.css ├── create │ └── page.tsx ├── (auth) │ ├── api │ │ └── auth │ │ │ └── [...nextauth] │ │ │ └── route.ts │ └── access │ │ └── page.tsx ├── api │ ├── edgestore │ │ └── [...edgestore] │ │ │ └── route.ts │ └── [post] │ │ └── [id] │ │ └── route.ts ├── posts │ └── page.tsx ├── page.tsx ├── actions │ ├── getCurrentUser.ts │ └── blogActions.ts ├── layout.tsx ├── userposts │ └── page.tsx ├── about │ └── page.tsx ├── blog │ └── [id] │ │ └── page.tsx └── contact │ └── page.tsx ├── public └── assets │ ├── about.jpg │ ├── post1.jpg │ ├── post2.jpg │ ├── post3.jpg │ ├── post4.jpg │ ├── post5.jpg │ ├── post6.jpg │ ├── post7.jpg │ ├── post8.jpg │ ├── post9.jpg │ ├── third.jpg │ ├── access.jpg │ ├── contact.jpg │ ├── second.jpg │ └── signature.png ├── postcss.config.js ├── types ├── userTypes.ts └── postTypes.ts ├── components ├── ui │ ├── Overlay.tsx │ ├── Tag.tsx │ ├── Map.tsx │ ├── Route.tsx │ ├── Input.tsx │ ├── Button.tsx │ ├── Form.tsx │ └── SingleImageDropZone.tsx └── shared │ ├── BlogCard.tsx │ ├── LatestPost.tsx │ ├── Footer.tsx │ ├── TopPost.tsx │ ├── DeletePosts.tsx │ ├── Posts.tsx │ ├── Hero.tsx │ ├── CreateForm.tsx │ ├── MobileMenu.tsx │ └── Navbar.tsx ├── next.config.js ├── utils └── formatDate.ts ├── lib ├── prismadb.ts └── edgestore.ts ├── constants ├── index.ts └── blogData.ts ├── context └── AuthContext.tsx ├── hooks └── useMenuActive.tsx ├── .env ├── tailwind.config.ts ├── .gitignore ├── tsconfig.json ├── package.json ├── README.md └── prisma └── schema.prisma /app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /public/assets/about.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/about.jpg -------------------------------------------------------------------------------- /public/assets/post1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/post1.jpg -------------------------------------------------------------------------------- /public/assets/post2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/post2.jpg -------------------------------------------------------------------------------- /public/assets/post3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/post3.jpg -------------------------------------------------------------------------------- /public/assets/post4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/post4.jpg -------------------------------------------------------------------------------- /public/assets/post5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/post5.jpg -------------------------------------------------------------------------------- /public/assets/post6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/post6.jpg -------------------------------------------------------------------------------- /public/assets/post7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/post7.jpg -------------------------------------------------------------------------------- /public/assets/post8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/post8.jpg -------------------------------------------------------------------------------- /public/assets/post9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/post9.jpg -------------------------------------------------------------------------------- /public/assets/third.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/third.jpg -------------------------------------------------------------------------------- /public/assets/access.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/access.jpg -------------------------------------------------------------------------------- /public/assets/contact.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/contact.jpg -------------------------------------------------------------------------------- /public/assets/second.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/second.jpg -------------------------------------------------------------------------------- /public/assets/signature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevAntonioRogers/exploreX/HEAD/public/assets/signature.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /types/userTypes.ts: -------------------------------------------------------------------------------- 1 | export type userTypes = { 2 | id: string; 3 | name: string | null; 4 | email: string | null; 5 | emailVerified: Date | string | null; 6 | image: string | null; 7 | } | null -------------------------------------------------------------------------------- /components/ui/Overlay.tsx: -------------------------------------------------------------------------------- 1 | const Overlay = () => { 2 | return ( 3 |
4 | ); 5 | }; 6 | 7 | export default Overlay; 8 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | images: { 4 | domains: ["images.unsplash.com", "lh3.googleusercontent.com", "files.edgestore.dev"] 5 | } 6 | } 7 | 8 | module.exports = nextConfig 9 | -------------------------------------------------------------------------------- /app/create/page.tsx: -------------------------------------------------------------------------------- 1 | import getCurrentUser from "../actions/getCurrentUser"; 2 | import CreateForm from "@/components/shared/CreateForm"; 3 | const page = async () => { 4 | const user = await getCurrentUser(); 5 | return ; 6 | }; 7 | 8 | export default page; 9 | -------------------------------------------------------------------------------- /utils/formatDate.ts: -------------------------------------------------------------------------------- 1 | export const formatDate = (dateTime: string) => { 2 | const dateObj = new Date(dateTime); 3 | 4 | const date = dateObj.getDate(); 5 | const month = dateObj.getMonth() + 1; 6 | const year = dateObj.getFullYear(); 7 | 8 | return `${month}-${date}-${year}`; 9 | }; -------------------------------------------------------------------------------- /types/postTypes.ts: -------------------------------------------------------------------------------- 1 | import { User } from "@prisma/client"; 2 | 3 | export interface PostTypes { 4 | id: string; 5 | createdAt: string | Date 6 | title: string; 7 | img: string | null; 8 | desc: string; 9 | featured: boolean; 10 | topPost: boolean; 11 | category: string; 12 | user: User; 13 | } -------------------------------------------------------------------------------- /lib/prismadb.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from "@prisma/client"; 2 | 3 | declare global { 4 | var prisma: PrismaClient | undefined 5 | } 6 | 7 | const client = globalThis.prisma || new PrismaClient() 8 | 9 | if (process.env.NODE_ENV !== "production") globalThis.prisma = client 10 | 11 | 12 | export default client -------------------------------------------------------------------------------- /lib/edgestore.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 |   3 | import { type EdgeStoreRouter } from '../app/api/edgestore/[...edgestore]/route'; 4 | import { createEdgeStoreProvider } from '@edgestore/react'; 5 |   6 | const { EdgeStoreProvider, useEdgeStore } = 7 | createEdgeStoreProvider(); 8 |   9 | export { EdgeStoreProvider, useEdgeStore }; -------------------------------------------------------------------------------- /constants/index.ts: -------------------------------------------------------------------------------- 1 | export const navLinks = [ 2 | { 3 | route: "/", 4 | label: "Home", 5 | }, 6 | { 7 | route: "/posts", 8 | label: "Posts", 9 | }, 10 | { 11 | route: "/about", 12 | label: "About", 13 | }, 14 | { 15 | route: "/contact", 16 | label: "Contact", 17 | }, 18 | ]; 19 | 20 | 21 | -------------------------------------------------------------------------------- /context/AuthContext.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { SessionProvider } from "next-auth/react"; 4 | 5 | export interface AuthContextProps { 6 | children: React.ReactNode; 7 | } 8 | 9 | export default function AuthContext({ 10 | children, 11 | }: AuthContextProps) { 12 | return {children}; 13 | } 14 | -------------------------------------------------------------------------------- /components/ui/Tag.tsx: -------------------------------------------------------------------------------- 1 | interface tagProps { 2 | text: string; 3 | } 4 | const Tag = ({ text }: tagProps) => { 5 | return ( 6 | <> 7 | 8 | {text} 9 | 10 | 11 | ); 12 | }; 13 | 14 | export default Tag; 15 | -------------------------------------------------------------------------------- /hooks/useMenuActive.tsx: -------------------------------------------------------------------------------- 1 | import { useRouter, usePathname } from "next/navigation"; 2 | 3 | const useMenuActive = (route: any) => { 4 | const router = useRouter(); 5 | const pathname = usePathname(); 6 | 7 | const isActive = 8 | (pathname.includes(route) && route.length > 1) || 9 | pathname === route; 10 | return isActive; 11 | }; 12 | 13 | export default useMenuActive; 14 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | DATABASE_URL="mongodb+srv://antonio:antonio@cluster0.xgim6v6.mongodb.net/explore?retryWrites=true&w=majority" 2 | 3 | GOOGLE_CLIENT_ID=622195774824-7qrlg2taf7moioj2i5mbl59e12mr4ht5.apps.googleusercontent.com 4 | GOOGLE_CLIENT_SECRET=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 5 | 6 | EDGE_STORE_ACCESS_KEY=Mk1bdqqh6duz6gbPVxaUEVbaSdNcz3uA 7 | EDGE_STORE_SECRET_KEY=9BcW34XlktzhgpGduSI1YpdtQF4fmx4UxdZhUsUN1wSMavt2 8 | 9 | NEXTAUTH_SECRET=dsfjdsklfjdsfkdskldsfjsdklf -------------------------------------------------------------------------------- /components/ui/Map.tsx: -------------------------------------------------------------------------------- 1 | const Map = () => { 2 | return ( 3 | <> 4 |
5 | 10 |
11 | 12 | ); 13 | }; 14 | 15 | export default Map; 16 | -------------------------------------------------------------------------------- /tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from 'tailwindcss' 2 | 3 | const config: Config = { 4 | content: [ 5 | './pages/**/*.{js,ts,jsx,tsx,mdx}', 6 | './components/**/*.{js,ts,jsx,tsx,mdx}', 7 | './app/**/*.{js,ts,jsx,tsx,mdx}', 8 | ], 9 | theme: { 10 | extend: { 11 | colors: { 12 | primary: '#eb5e28', 13 | secondary: '#252422', 14 | tertiary: '#403d39', 15 | light: '#fffcf2', 16 | } 17 | }, 18 | }, 19 | plugins: [], 20 | } 21 | export default config 22 | -------------------------------------------------------------------------------- /components/ui/Route.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | import clsx from "clsx"; 3 | 4 | interface routeProps { 5 | route: string; 6 | label: string; 7 | isActive?: boolean; 8 | onClick?: () => void; 9 | } 10 | 11 | const Route = ({ 12 | route, 13 | label, 14 | isActive, 15 | onClick, 16 | }: routeProps) => { 17 | return ( 18 | 23 | {label} 24 | 25 | ); 26 | }; 27 | 28 | export default Route; 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | .history 9 | 10 | # testing 11 | /coverage 12 | 13 | # next.js 14 | /.next/ 15 | /out/ 16 | 17 | # production 18 | /build 19 | 20 | # misc 21 | .DS_Store 22 | *.pem 23 | 24 | # debug 25 | npm-debug.log* 26 | yarn-debug.log* 27 | yarn-error.log* 28 | 29 | # local env files 30 | .env*.local 31 | 32 | # vercel 33 | .vercel 34 | 35 | # typescript 36 | *.tsbuildinfo 37 | next-env.d.ts 38 | -------------------------------------------------------------------------------- /app/(auth)/api/auth/[...nextauth]/route.ts: -------------------------------------------------------------------------------- 1 | import NextAuth, {AuthOptions} from "next-auth" 2 | import GoogleProvider from "next-auth/providers/google" 3 | import { PrismaAdapter } from "@auth/prisma-adapter" 4 | import prisma from "@/lib/prismadb" 5 | 6 | 7 | export const authOptions: AuthOptions = ({ 8 | adapter: PrismaAdapter(prisma), 9 | providers: [ 10 | GoogleProvider({ 11 | clientId: process.env.GOOGLE_CLIENT_ID as string, 12 | clientSecret: process.env.GOOGLE_CLIENT_SECRET as string 13 | }), 14 | ], 15 | secret: process.env.NEXTAUTH_SECRET 16 | }) 17 | 18 | const handler = NextAuth(authOptions) 19 | 20 | export {handler as GET, handler as POST} -------------------------------------------------------------------------------- /app/api/edgestore/[...edgestore]/route.ts: -------------------------------------------------------------------------------- 1 | import { initEdgeStore } from '@edgestore/server'; 2 | import { createEdgeStoreNextHandler } from '@edgestore/server/adapters/next/app'; 3 |   4 | const es = initEdgeStore.create(); 5 |   6 | /** 7 | * This is the main router for the Edge Store buckets. 8 | */ 9 | const edgeStoreRouter = es.router({ 10 | publicFiles: es.fileBucket(), 11 | }); 12 |   13 | const handler = createEdgeStoreNextHandler({ 14 | router: edgeStoreRouter, 15 | }); 16 |   17 | export { handler as GET, handler as POST }; 18 |   19 | /** 20 | * This type is used to create the type-safe client for the frontend. 21 | */ 22 | export type EdgeStoreRouter = typeof edgeStoreRouter; -------------------------------------------------------------------------------- /app/posts/page.tsx: -------------------------------------------------------------------------------- 1 | import Posts from "@/components/shared/Posts"; 2 | import TopPost from "@/components/shared/TopPost"; 3 | import prisma from "@/lib/prismadb"; 4 | import { PostTypes } from "@/types/postTypes"; 5 | const page = async () => { 6 | const posts = await prisma.blog.findMany({ 7 | include: { 8 | user: true, 9 | }, 10 | }); 11 | return ( 12 |
13 |
14 | 15 | 16 |
17 |
18 | ); 19 | }; 20 | 21 | export default page; 22 | -------------------------------------------------------------------------------- /app/page.tsx: -------------------------------------------------------------------------------- 1 | import Hero from "@/components/shared/Hero"; 2 | import LatestPost from "@/components/shared/LatestPost"; 3 | import TopPost from "@/components/shared/TopPost"; 4 | import prisma from "@/lib/prismadb"; 5 | const Home = async () => { 6 | const posts = await prisma.blog.findMany({ 7 | include: { 8 | user: true, 9 | }, 10 | }); 11 | return ( 12 | <> 13 | 14 |
15 | 16 | 17 |
18 | 19 | ); 20 | }; 21 | 22 | export default Home; 23 | -------------------------------------------------------------------------------- /app/api/[post]/[id]/route.ts: -------------------------------------------------------------------------------- 1 | import prisma from "@/lib/prismadb" 2 | import { NextResponse, NextRequest } from "next/server" 3 | 4 | interface Params { 5 | id: string 6 | } 7 | 8 | export const GET = async (req: NextRequest, {params}: {params: Params} ) => { 9 | const {id} = params 10 | 11 | try { 12 | const post = await prisma.blog.findUnique({ 13 | where: {id}, 14 | include: {user: true} 15 | }) 16 | 17 | return new NextResponse(JSON.stringify(post, null, 2), {status: 200}) 18 | } catch (err) { 19 | console.log(err); 20 | return new NextResponse( 21 | JSON.stringify({ message: "Something went wrong!" }, null, 2), 22 | { status: 500 } 23 | ); 24 | } 25 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /components/ui/Input.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | interface inputProps { 4 | name: string; 5 | type: string; 6 | placeholder?: string; 7 | value?: string | number | readonly string[] | undefined; 8 | } 9 | 10 | const Input = ({ 11 | name, 12 | type, 13 | placeholder, 14 | value, 15 | }: inputProps) => { 16 | return ( 17 | <> 18 | 26 | 27 | ); 28 | }; 29 | 30 | export default Input; 31 | -------------------------------------------------------------------------------- /components/ui/Button.tsx: -------------------------------------------------------------------------------- 1 | import clsx from "clsx"; 2 | 3 | interface buttonProps { 4 | text: string; 5 | onClick?: () => void; 6 | aria: string; 7 | action?: boolean; 8 | type?: "button" | "submit" | "reset"; 9 | } 10 | 11 | const Button = ({ 12 | text, 13 | onClick, 14 | aria, 15 | action, 16 | type, 17 | }: buttonProps) => { 18 | return ( 19 | 31 | ); 32 | }; 33 | 34 | export default Button; 35 | -------------------------------------------------------------------------------- /app/actions/getCurrentUser.ts: -------------------------------------------------------------------------------- 1 | import { getServerSession } from "next-auth"; 2 | import { authOptions } from "../(auth)/api/auth/[...nextauth]/route"; 3 | import prisma from "@/lib/prismadb" 4 | 5 | export async function getSession() { 6 | return await getServerSession(authOptions) 7 | } 8 | 9 | export default async function getCurrentUser() { 10 | try { 11 | const session = await getSession() 12 | 13 | if (!session?.user?.email){ 14 | return null 15 | } 16 | 17 | const currentUser = await prisma.user.findUnique({ 18 | where: { 19 | email: session.user.email as string 20 | } 21 | }) 22 | 23 | if (!currentUser) { 24 | return null 25 | } 26 | 27 | return { 28 | ...currentUser 29 | } 30 | } 31 | catch (error: any) { 32 | return null 33 | } 34 | } -------------------------------------------------------------------------------- /components/ui/Form.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useRef, FormEvent } from "react"; 4 | import { ReactNode } from "react"; 5 | 6 | interface FormProps { 7 | children: ReactNode; 8 | action: (formData: FormData) => Promise; 9 | className?: string; 10 | onSubmit?: (e: FormEvent) => void; 11 | } 12 | 13 | const Form = ({ 14 | children, 15 | action, 16 | className, 17 | onSubmit, 18 | }: FormProps) => { 19 | const ref = useRef(null); 20 | 21 | return ( 22 |
{ 27 | await action(formData); 28 | ref.current?.reset(); 29 | }} 30 | > 31 | {children} 32 |
33 | ); 34 | }; 35 | 36 | export default Form; 37 | -------------------------------------------------------------------------------- /app/actions/blogActions.ts: -------------------------------------------------------------------------------- 1 | "use server" 2 | 3 | import prisma from "@/lib/prismadb" 4 | import { revalidatePath } from "next/cache" 5 | 6 | export async function createPost(formData: FormData) { 7 | const title = formData.get("title") as string 8 | const desc = formData.get("description") as string 9 | const cat = formData.get("category") as string 10 | const userEmail = formData.get("email") as string 11 | const image = formData.get("image") as string 12 | 13 | await prisma.blog.create({ 14 | data: { 15 | img: image, 16 | title: title, 17 | desc: desc, 18 | category: cat, 19 | userEmail: userEmail 20 | } 21 | }) 22 | 23 | revalidatePath("/create") 24 | } 25 | 26 | export async function deletePost(formData: FormData) { 27 | const id = formData.get("postId") as string 28 | 29 | await prisma.blog.delete({ 30 | where: { 31 | id: id 32 | } 33 | }) 34 | 35 | revalidatePath("/userposts") 36 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "explore-x", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@auth/prisma-adapter": "^1.0.9", 13 | "@edgestore/react": "^0.1.4", 14 | "@edgestore/server": "^0.1.4", 15 | "@prisma/client": "^5.6.0", 16 | "clsx": "^2.0.0", 17 | "lucide-react": "^0.294.0", 18 | "next": "14.0.3", 19 | "next-auth": "^4.24.5", 20 | "react": "^18", 21 | "react-dom": "^18", 22 | "react-dropzone": "^14.2.3", 23 | "react-icons": "^4.12.0", 24 | "react-social-login-buttons": "^3.9.1", 25 | "tailwind-merge": "^2.1.0", 26 | "zod": "^3.22.4" 27 | }, 28 | "devDependencies": { 29 | "@types/node": "^20", 30 | "@types/react": "^18", 31 | "@types/react-dom": "^18", 32 | "autoprefixer": "^10.0.1", 33 | "postcss": "^8", 34 | "prisma": "^5.6.0", 35 | "tailwindcss": "^3.3.0", 36 | "typescript": "^5" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import { Roboto } from "next/font/google"; 3 | import "./globals.css"; 4 | import Navbar from "@/components/shared/Navbar"; 5 | import Footer from "@/components/shared/Footer"; 6 | import AuthContext from "@/context/AuthContext"; 7 | import getCurrentUser from "./actions/getCurrentUser"; 8 | import { EdgeStoreProvider } from "@/lib/edgestore"; 9 | 10 | const roboto = Roboto({ 11 | subsets: ["latin"], 12 | weight: ["100", "400", "700", "900"], 13 | }); 14 | 15 | export const metadata: Metadata = { 16 | title: "ExploreX", 17 | description: "Travel Blog", 18 | }; 19 | 20 | export default async function RootLayout({ 21 | children, 22 | }: { 23 | children: React.ReactNode; 24 | }) { 25 | const user = await getCurrentUser(); 26 | return ( 27 | 28 | 29 | 30 | 33 | 34 | {children} 35 |