diff --git a/.depcheckrc b/.depcheckrc index 9a0dcc8..aeca52f 100644 --- a/.depcheckrc +++ b/.depcheckrc @@ -1,2 +1,2 @@ -ignores: ["@types/node", "@types/react-dom", "autoprefixer", "postcss", "@commitlint/config-conventional", "prettier"] +ignores: ["@types/node", "@types/react-dom", "autoprefixer", "postcss", "@commitlint/config-conventional", "prettier", "@t3-oss/env-nextjs"] skip-missing: false diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..76bd9ee --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +# ----------------------------------------------------------------------------- +# App +# ----------------------------------------------------------------------------- +NEXT_PUBLIC_APP_URL=http://localhost:3000 diff --git a/app/layout.tsx b/app/layout.tsx index 8636523..effd69e 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,79 +1,96 @@ -import { Inter, Fjalla_One } from "next/font/google"; +import { Inter as FontSans } from "next/font/google"; +import localFont from "next/font/local"; +import "@/styles/globals.css"; +import { siteConfig } from "@/config/site"; +import { absoluteUrl, cn } from "@/lib/utils"; +import { Analytics } from "@/components/analytics"; +import { TailwindIndicator } from "@/components/tailwind-indicator"; import { ThemeProvider } from "@/components/theme-provider"; -import "tailwindcss/tailwind.css"; -import { Metadata } from "next"; - -export const metadata: Metadata = { +export const metadata = { title: { - default: "hellob.art", - template: "%s | hellob.art", + default: siteConfig.name, + template: `%s | ${siteConfig.name}`, }, - description: "a simple portfolio made by bart van der braak", - metadataBase: new URL("https://hellob.art"), - openGraph: { - title: "hellob.art", - description: "a simple portfolio made by bart van der braak", - url: "https://hellob.art", - siteName: "hellob.art", - locale: "en-US", - type: "website", - }, - robots: { - index: true, - follow: true, - googleBot: { - index: true, - follow: true, - "max-video-preview": -1, - "max-image-preview": "large", - "max-snippet": -1, + description: siteConfig.description, + keywords: [ + "Next.js", + "React", + "Tailwind CSS", + "Server Components", + "Radix UI", + ], + authors: [ + { + name: "Bart van der Braak", + url: siteConfig.url, }, + ], + creator: "shadcn", + themeColor: [ + { media: "(prefers-color-scheme: light)", color: "white" }, + { media: "(prefers-color-scheme: dark)", color: "black" }, + ], + openGraph: { + type: "website", + locale: "en_US", + url: siteConfig.url, + title: siteConfig.name, + description: siteConfig.description, + siteName: siteConfig.name, }, twitter: { - title: "hellob.art", card: "summary_large_image", + title: siteConfig.name, + description: siteConfig.description, + images: [`${siteConfig.url}/og.jpg`], + creator: "@bartvdbraak", }, icons: { - shortcut: "/favicon.png", + icon: "/favicon.ico", + shortcut: "/favicon-16x16.png", + apple: "/apple-touch-icon.png", }, + manifest: `${siteConfig.url}/site.webmanifest`, }; interface RootLayoutProps { children: React.ReactNode; } -const inter = Inter({ +const fontSans = FontSans({ subsets: ["latin"], - variable: "--font-inter", + variable: "--font-sans", }); -const fjallaOne = Fjalla_One({ - subsets: ["latin"], - weight: "400", - variable: "--font-fjalla-one", +// Font files can be colocated inside of `pages` +const fontHeading = localFont({ + src: "../assets/fonts/CalSans-SemiBold.woff2", + variable: "--font-heading", }); interface RootLayoutProps { children: React.ReactNode; } -export default async function RootLayout({ children }: RootLayoutProps) { +export default function RootLayout({ children }: RootLayoutProps) { return ( - <> - + + - - - - {children} - - - - + + {children} + + + + + ); } diff --git a/assets/fonts/CalSans-SemiBold.ttf b/assets/fonts/CalSans-SemiBold.ttf new file mode 100644 index 0000000..4a2950a Binary files /dev/null and b/assets/fonts/CalSans-SemiBold.ttf differ diff --git a/assets/fonts/CalSans-SemiBold.woff b/assets/fonts/CalSans-SemiBold.woff new file mode 100644 index 0000000..da45991 Binary files /dev/null and b/assets/fonts/CalSans-SemiBold.woff differ diff --git a/assets/fonts/CalSans-SemiBold.woff2 b/assets/fonts/CalSans-SemiBold.woff2 new file mode 100644 index 0000000..36d71b7 Binary files /dev/null and b/assets/fonts/CalSans-SemiBold.woff2 differ diff --git a/assets/fonts/Inter-Bold.ttf b/assets/fonts/Inter-Bold.ttf new file mode 100644 index 0000000..8e82c70 Binary files /dev/null and b/assets/fonts/Inter-Bold.ttf differ diff --git a/assets/fonts/Inter-Regular.ttf b/assets/fonts/Inter-Regular.ttf new file mode 100644 index 0000000..8d4eebf Binary files /dev/null and b/assets/fonts/Inter-Regular.ttf differ diff --git a/components/analytics.tsx b/components/analytics.tsx new file mode 100644 index 0000000..52e59d2 --- /dev/null +++ b/components/analytics.tsx @@ -0,0 +1,7 @@ +"use client"; + +import { Analytics as VercelAnalytics } from "@vercel/analytics/react"; + +export function Analytics() { + return ; +} diff --git a/components/tailwind-indicator.tsx b/components/tailwind-indicator.tsx new file mode 100644 index 0000000..5644c1b --- /dev/null +++ b/components/tailwind-indicator.tsx @@ -0,0 +1,16 @@ +export function TailwindIndicator() { + if (process.env.NODE_ENV === "production") return null; + + return ( +
+
xs
+
+ sm +
+
md
+
lg
+
xl
+
2xl
+
+ ); +} diff --git a/config/site.ts b/config/site.ts index 21a25d7..1076851 100644 --- a/config/site.ts +++ b/config/site.ts @@ -1,7 +1,6 @@ export const siteConfig = { - name: "Taxonomy", - description: - "An open source application built using the new router, server components and everything new in Next.js 13.", + name: "hellob.art", + description: "a simple portfolio made by bart van der braak.", url: "https://hellob.art", ogImage: "https://hellob.art/og.jpg", links: { diff --git a/env.mjs b/env.mjs new file mode 100644 index 0000000..4043621 --- /dev/null +++ b/env.mjs @@ -0,0 +1,15 @@ +import { createEnv } from "@t3-oss/env-nextjs"; +import { z } from "zod"; + +export const env = createEnv({ + server: { + // This is optional because it's only used in development. + // See https://next-auth.js.org/deployment. + }, + client: { + NEXT_PUBLIC_APP_URL: z.string().min(1), + }, + runtimeEnv: { + NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL, + }, +}); diff --git a/lib/utils.ts b/lib/utils.ts index 7927ae7..9045e10 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,6 +1,8 @@ import { ClassValue, clsx } from "clsx"; import { twMerge } from "tailwind-merge"; +import { env } from "@/env.mjs"; + export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } @@ -13,3 +15,7 @@ export function formatDate(input: string | number): string { year: "numeric", }); } + +export function absoluteUrl(path: string) { + return `${env.NEXT_PUBLIC_APP_URL}${path}`; +} diff --git a/package.json b/package.json index 58d2a18..24963c5 100644 --- a/package.json +++ b/package.json @@ -17,9 +17,12 @@ "format:check": "prettier . --check --cache" }, "dependencies": { + "@t3-oss/env-nextjs": "^0.4.0", + "@tailwindcss/typography": "^0.5.9", "@types/node": "20.3.1", "@types/react": "18.2.12", "@types/react-dom": "18.2.5", + "@vercel/analytics": "^1.0.1", "autoprefixer": "10.4.14", "class-variance-authority": "^0.6.0", "clsx": "^1.2.1", @@ -32,6 +35,7 @@ "react-dom": "18.2.0", "tailwind-merge": "^1.13.1", "tailwindcss": "3.3.2", + "tailwindcss-animate": "^1.0.6", "typescript": "5.1.3" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 313c3a8..3b917d3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,6 +1,16 @@ lockfileVersion: '6.0' +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + dependencies: + '@t3-oss/env-nextjs': + specifier: ^0.4.0 + version: 0.4.0(typescript@5.1.3)(zod@3.21.4) + '@tailwindcss/typography': + specifier: ^0.5.9 + version: 0.5.9(tailwindcss@3.3.2) '@types/node': specifier: 20.3.1 version: 20.3.1 @@ -10,6 +20,9 @@ dependencies: '@types/react-dom': specifier: 18.2.5 version: 18.2.5 + '@vercel/analytics': + specifier: ^1.0.1 + version: 1.0.1 autoprefixer: specifier: 10.4.14 version: 10.4.14(postcss@8.4.24) @@ -46,6 +59,9 @@ dependencies: tailwindcss: specifier: 3.3.2 version: 3.3.2 + tailwindcss-animate: + specifier: ^1.0.6 + version: 1.0.6(tailwindcss@3.3.2) typescript: specifier: 5.1.3 version: 5.1.3 @@ -307,6 +323,39 @@ packages: tslib: 2.5.3 dev: false + /@t3-oss/env-core@0.4.0(typescript@5.1.3)(zod@3.21.4): + resolution: {integrity: sha512-6JlMp0Vru15q/axHzBKsQQjiyGS6k+EsZBY1iErGVmOGzNSoVluBahnYFP7tEkwZ7KoRgSq4NRIc1Ez7SVYuxQ==} + peerDependencies: + typescript: '>=4.7.2' + zod: ^3.0.0 + dependencies: + typescript: 5.1.3 + zod: 3.21.4 + dev: false + + /@t3-oss/env-nextjs@0.4.0(typescript@5.1.3)(zod@3.21.4): + resolution: {integrity: sha512-K1u2i+S/uEhjfg++FqWlOzS6x237EARRbWGowH2MkDkFu2q7ZJSiJBJT8e47L7NHWH5IyZrTCM6BdOxyWEnQuQ==} + peerDependencies: + typescript: '>=4.7.2' + zod: ^3.0.0 + dependencies: + '@t3-oss/env-core': 0.4.0(typescript@5.1.3)(zod@3.21.4) + typescript: 5.1.3 + zod: 3.21.4 + dev: false + + /@tailwindcss/typography@0.5.9(tailwindcss@3.3.2): + resolution: {integrity: sha512-t8Sg3DyynFysV9f4JDOVISGsjazNb48AeIYQwcL+Bsq5uf4RYL75C1giZ43KISjeDGBaTN3Kxh7Xj/vRSMJUUg==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders' + dependencies: + lodash.castarray: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + postcss-selector-parser: 6.0.10 + tailwindcss: 3.3.2 + dev: false + /@types/json5@0.0.29: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: false @@ -399,6 +448,10 @@ packages: eslint-visitor-keys: 3.4.1 dev: false + /@vercel/analytics@1.0.1: + resolution: {integrity: sha512-Ux0c9qUfkcPqng3vrR0GTrlQdqNJ2JREn/2ydrVuKwM3RtMfF2mWX31Ijqo1opSjNAq6rK76PwtANw6kl6TAow==} + dev: false + /acorn-jsx@5.3.2(acorn@8.8.2): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1801,6 +1854,14 @@ packages: p-locate: 5.0.0 dev: false + /lodash.castarray@4.4.0: + resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==} + dev: false + + /lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: false + /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: false @@ -2192,6 +2253,14 @@ packages: postcss-selector-parser: 6.0.13 dev: false + /postcss-selector-parser@6.0.10: + resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: false + /postcss-selector-parser@6.0.13: resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} engines: {node: '>=4'} @@ -2545,6 +2614,14 @@ packages: resolution: {integrity: sha512-tRtRN22TDokGi2TuYSvuHQuuW6BJ/zlUEG+iYpAQ9i66msc/0eU/+HPccbPnNNH0mCPp0Ob8thaC8Uy9CxHitQ==} dev: false + /tailwindcss-animate@1.0.6(tailwindcss@3.3.2): + resolution: {integrity: sha512-4WigSGMvbl3gCCact62ZvOngA+PRqhAn7si3TQ3/ZuPuQZcIEtVap+ENSXbzWhpojKB8CpvnIsrwBu8/RnHtuw==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders' + dependencies: + tailwindcss: 3.3.2 + dev: false + /tailwindcss@3.3.2: resolution: {integrity: sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==} engines: {node: '>=14.0.0'} @@ -2767,7 +2844,3 @@ packages: /zod@3.21.4: resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==} dev: false - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png new file mode 100644 index 0000000..a85c95d Binary files /dev/null and b/public/android-chrome-192x192.png differ diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png new file mode 100644 index 0000000..77f5f8d Binary files /dev/null and b/public/android-chrome-512x512.png differ diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000..2927923 Binary files /dev/null and b/public/apple-touch-icon.png differ diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png new file mode 100644 index 0000000..8ec71a0 Binary files /dev/null and b/public/favicon-16x16.png differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png new file mode 100644 index 0000000..07beefd Binary files /dev/null and b/public/favicon-32x32.png differ diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..7b847e6 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/logo.svg b/public/logo.svg index 0662165..df5c129 100644 --- a/public/logo.svg +++ b/public/logo.svg @@ -1,8 +1,8 @@ - + stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> + diff --git a/public/og.jpg b/public/og.jpg new file mode 100644 index 0000000..75473bf Binary files /dev/null and b/public/og.jpg differ diff --git a/public/site.webmanifest b/public/site.webmanifest new file mode 100644 index 0000000..9e16ccb --- /dev/null +++ b/public/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "hellob.art", + "short_name": "hellob.art", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#5c5c5c", + "background_color": "#5c5c5c", + "display": "standalone" +} diff --git a/styles/globals.css b/styles/globals.css new file mode 100644 index 0000000..95d8cab --- /dev/null +++ b/styles/globals.css @@ -0,0 +1,81 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 47.4% 11.2%; + + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + + --popover: 0 0% 100%; + --popover-foreground: 222.2 47.4% 11.2%; + + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + + --card: 0 0% 100%; + --card-foreground: 222.2 47.4% 11.2%; + + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + + --destructive: 0 100% 50%; + --destructive-foreground: 210 40% 98%; + + --ring: 215 20.2% 65.1%; + + --radius: 0.5rem; + } + + .dark { + --background: 224 71% 4%; + --foreground: 213 31% 91%; + + --muted: 223 47% 11%; + --muted-foreground: 215.4 16.3% 56.9%; + + --accent: 216 34% 17%; + --accent-foreground: 210 40% 98%; + + --popover: 224 71% 4%; + --popover-foreground: 215 20.2% 65.1%; + + --border: 216 34% 17%; + --input: 216 34% 17%; + + --card: 224 71% 4%; + --card-foreground: 213 31% 91%; + + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 1.2%; + + --secondary: 222.2 47.4% 11.2%; + --secondary-foreground: 210 40% 98%; + + --destructive: 0 63% 31%; + --destructive-foreground: 210 40% 98%; + + --ring: 216 34% 17%; + + --radius: 0.5rem; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + font-feature-settings: "rlig" 1, "calt" 1; + } +} diff --git a/tailwind.config.js b/tailwind.config.js index 8758409..ccbbb40 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,36 +1,82 @@ const { fontFamily } = require("tailwindcss/defaultTheme"); -const colors = require("tailwindcss/colors"); /** @type {import('tailwindcss').Config} */ module.exports = { content: [ - "./pages/**/*.{js,ts,jsx,tsx,mdx}", - "./components/**/*.{js,ts,jsx,tsx,mdx}", - "./app/**/*.{js,ts,jsx,tsx,mdx}", + "./app/**/*.{ts,tsx}", + "./components/**/*.{ts,tsx}", + "./ui/**/*.{ts,tsx}", + "./content/**/*.{md,mdx}", ], + darkMode: ["class"], theme: { container: { center: true, - padding: "1.5rem", + padding: "2rem", screens: { - "2xl": "1440px", + "2xl": "1400px", }, }, extend: { colors: { - primary: colors.zinc, + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + }, + borderRadius: { + lg: `var(--radius)`, + md: `calc(var(--radius) - 2px)`, + sm: "calc(var(--radius) - 4px)", }, fontFamily: { - sans: ["Inter", "var(--font-inter)", ...fontFamily.sans], - display: ["Fjalla One", "var(--font-fjalla-one)"], + sans: ["var(--font-sans)", ...fontFamily.sans], + heading: ["var(--font-heading)", ...fontFamily.sans], }, - backgroundImage: { - "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", - "gradient-conic": - "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", - filter: "brightness(120%) saturate(120%) blur(2px)", + keyframes: { + "accordion-down": { + from: { height: 0 }, + to: { height: "var(--radix-accordion-content-height)" }, + }, + "accordion-up": { + from: { height: "var(--radix-accordion-content-height)" }, + to: { height: 0 }, + }, + }, + animation: { + "accordion-down": "accordion-down 0.2s ease-out", + "accordion-up": "accordion-up 0.2s ease-out", }, }, }, - plugins: [], + plugins: [require("tailwindcss-animate"), require("@tailwindcss/typography")], };