diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7221c88..5393e40 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -14,7 +14,7 @@ jobs:
name: Build App
runs-on: ubuntu-latest
- steps:
+ steps:
- name: Checkout Repo
uses: actions/checkout@v4
@@ -96,6 +96,6 @@ jobs:
run: |
export DEPLOYMENT_VERSION="${GITHUB_SHA:0:7}-$(date +%s)"
nomad job run -var="deployment_version=$DEPLOYMENT_VERSION" infra/nomad/portfolio.nomad.hcl
- env:
+ env:
NOMAD_ADDR: ${{ vars.NOMAD_ADDR }}
- NOMAD_TOKEN: ${{ secrets.NOMAD_TOKEN }}
\ No newline at end of file
+ NOMAD_TOKEN: ${{ secrets.NOMAD_TOKEN }}
diff --git a/.github/workflows/dep.yml b/.github/workflows/dep.yml
index ff0fdd4..778d4fc 100644
--- a/.github/workflows/dep.yml
+++ b/.github/workflows/dep.yml
@@ -10,25 +10,25 @@ jobs:
name: SBOM Generation and Upload
runs-on: ubuntu-latest
steps:
- - name: Checkout repository
- uses: actions/checkout@v3
+ - name: Checkout repository
+ uses: actions/checkout@v3
- - name: Setup PNPM and Node
- uses: pnpm/setup@v3
- with:
- runtime: node@24
+ - name: Setup PNPM and Node
+ uses: pnpm/setup@v3
+ with:
+ runtime: node@24
- - name: Generate SBOM
- run: pnpm sbom --sbom-format cyclonedx --sbom-type application --out sbom.cyclonedx.json
+ - name: Generate SBOM
+ run: pnpm sbom --sbom-format cyclonedx --sbom-type application --out sbom.cyclonedx.json
- - name: Upload SBOM
- uses: DependencyTrack/gh-upload-sbom@v4
- with:
- protocol: ${{ vars.DT_API_PROTOCOL }}
- server-hostname: ${{ vars.DT_API_HOSTNAME }}
- port: ${{ vars.DT_API_PORT }}
- api-key: ${{ secrets.DT_API_KEY }}
- project-name: 'Liam Portfolio'
- project-version: 'main'
- auto-create: true
- bom-filename: 'sbom.cyclonedx.json'
+ - name: Upload SBOM
+ uses: DependencyTrack/gh-upload-sbom@v4
+ with:
+ protocol: ${{ vars.DT_API_PROTOCOL }}
+ server-hostname: ${{ vars.DT_API_HOSTNAME }}
+ port: ${{ vars.DT_API_PORT }}
+ api-key: ${{ secrets.DT_API_KEY }}
+ project-name: 'Liam Portfolio'
+ project-version: 'main'
+ auto-create: true
+ bom-filename: 'sbom.cyclonedx.json'
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..fa311db
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,7 @@
+package-lock.json
+pnpm-lock.yaml
+yarn.lock
+src/app/(payload)/admin/importMap.js
+src/payload-types.ts
+src/migrations
+infra/**
\ No newline at end of file
diff --git a/README.md b/README.md
index ce021bb..9fceba3 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Liam Pietralla Porfolio
-The portfolio is built using Next.JS and Payload CMS. Payload is running directly in the Next app, and can be accessed by appending /admin to the route.
+The portfolio is built using Next.JS and Payload CMS. Payload is running directly in the Next app, and can be accessed by appending /admin to the route.
## Development
@@ -18,7 +18,7 @@ pnpm dev
### Payload CMS
-Payload will require rebuilding on the types file once any changes are made:
+Payload will require rebuilding on the types file once any changes are made:
```bash
pnpm run payload:generate:types
@@ -46,4 +46,4 @@ Once the container is built, you can run it with the following command:
```bash
docker run -p 3000:3000 -v liam-portfolio-data:/app/portfolio-data -e PAYLOAD_SECRET=your_secret liam-portfolio
-```
\ No newline at end of file
+```
diff --git a/compose.yml b/compose.yml
index baf98af..0d6e828 100644
--- a/compose.yml
+++ b/compose.yml
@@ -1,5 +1,4 @@
services:
-
db:
image: postgres:18
restart: unless-stopped
@@ -8,7 +7,7 @@ services:
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=portfolio-dev
ports:
- - "5432:5432"
+ - '5432:5432'
volumes:
- portfolio_db_data:/var/lib/postgresql
@@ -16,7 +15,7 @@ services:
image: ghcr.io/achtungsoftware/alarik:latest
restart: unless-stopped
ports:
- - "9000:8080"
+ - '9000:8080'
environment:
- API_BASE_URL=http://localhost:9000
- CONSOLE_BASE_URL=http://localhost:9001
@@ -33,7 +32,7 @@ services:
image: ghcr.io/achtungsoftware/alarik-console:latest
restart: unless-stopped
ports:
- - "9001:3000"
+ - '9001:3000'
environment:
- NUXT_PUBLIC_API_BASE_URL=http://localhost:9000
- NUXT_PUBLIC_CONSOLE_BASE_URL=http://localhost:9001
@@ -55,8 +54,8 @@ services:
mc mb alarik/payload-media &&
echo 'S3 bucket created';
fi
- "
+ "
volumes:
portfolio_s3_data:
- portfolio_db_data:
\ No newline at end of file
+ portfolio_db_data:
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 719cea2..d60a2ca 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,25 +1,25 @@
-import { dirname } from "path";
-import { fileURLToPath } from "url";
-import { FlatCompat } from "@eslint/eslintrc";
+import { dirname } from 'path'
+import { fileURLToPath } from 'url'
+import { FlatCompat } from '@eslint/eslintrc'
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = dirname(__filename);
+const __filename = fileURLToPath(import.meta.url)
+const __dirname = dirname(__filename)
const compat = new FlatCompat({
baseDirectory: __dirname,
-});
+})
const eslintConfig = [
- ...compat.extends("next/core-web-vitals", "next/typescript"),
+ ...compat.extends('next/core-web-vitals', 'next/typescript'),
{
ignores: [
- "node_modules/**",
- ".next/**",
- "out/**",
- "build/**",
- "next-env.d.ts",
+ 'node_modules/**',
+ '.next/**',
+ 'out/**',
+ 'build/**',
+ 'next-env.d.ts',
],
},
-];
+]
-export default eslintConfig;
+export default eslintConfig
diff --git a/next.config.ts b/next.config.ts
index b257179..7fcee93 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -1,8 +1,8 @@
-import { withPayload } from "@payloadcms/next/withPayload";
-import type { NextConfig } from "next";
+import { withPayload } from '@payloadcms/next/withPayload'
+import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
- output: "standalone",
- };
+ output: 'standalone',
+}
-export default withPayload(nextConfig);
+export default withPayload(nextConfig)
diff --git a/package.json b/package.json
index 5ac525d..94bad67 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,7 @@
"build": "next build",
"start": "payload migrate && next start",
"lint": "eslint",
+ "format": "prettier --write .",
"payload:generate-types": "payload generate:types",
"payload:migrate:create": "payload migrate:create"
},
@@ -35,6 +36,8 @@
"@types/react-dom": "19.3.0",
"eslint": "^9.39.5",
"eslint-config-next": "16.1.2",
+ "prettier": "^3.9.10",
+ "prettier-plugin-tailwindcss": "^0.8.1",
"tailwindcss": "^4.3.3",
"typescript": "^5.9.3"
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ed9d739..d8d5568 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -230,6 +230,12 @@ importers:
eslint-config-next:
specifier: 16.1.2
version: 16.1.2(@typescript-eslint/parser@8.53.0(eslint@9.39.5(jiti@2.5.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(jiti@2.5.1)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
+ prettier:
+ specifier: ^3.9.10
+ version: 3.9.10
+ prettier-plugin-tailwindcss:
+ specifier: ^0.8.1
+ version: 0.8.1(prettier@3.9.10)
tailwindcss:
specifier: ^4.3.3
version: 4.3.3
@@ -3905,11 +3911,71 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
+ prettier-plugin-tailwindcss@0.8.1:
+ resolution: {integrity: sha512-iaFMYqDsE4ffdDkn5qup0j5f2aCEBFZrdrZnvu9QKTlWx/iGPeQ4HHu7b7fCPMxeo9nwQBiOAh2nSypdFYWJkw==}
+ engines: {node: '>=20.19'}
+ peerDependencies:
+ '@ianvs/prettier-plugin-sort-imports': '*'
+ '@prettier/plugin-hermes': '*'
+ '@prettier/plugin-oxc': '*'
+ '@prettier/plugin-pug': '*'
+ '@shopify/prettier-plugin-liquid': '*'
+ '@trivago/prettier-plugin-sort-imports': '*'
+ '@zackad/prettier-plugin-twig': '*'
+ prettier: ^3.0
+ prettier-plugin-astro: '*'
+ prettier-plugin-css-order: '*'
+ prettier-plugin-jsdoc: '*'
+ prettier-plugin-marko: '*'
+ prettier-plugin-multiline-arrays: '*'
+ prettier-plugin-organize-attributes: '*'
+ prettier-plugin-organize-imports: '*'
+ prettier-plugin-sort-imports: '*'
+ prettier-plugin-svelte: '*'
+ peerDependenciesMeta:
+ '@ianvs/prettier-plugin-sort-imports':
+ optional: true
+ '@prettier/plugin-hermes':
+ optional: true
+ '@prettier/plugin-oxc':
+ optional: true
+ '@prettier/plugin-pug':
+ optional: true
+ '@shopify/prettier-plugin-liquid':
+ optional: true
+ '@trivago/prettier-plugin-sort-imports':
+ optional: true
+ '@zackad/prettier-plugin-twig':
+ optional: true
+ prettier-plugin-astro:
+ optional: true
+ prettier-plugin-css-order:
+ optional: true
+ prettier-plugin-jsdoc:
+ optional: true
+ prettier-plugin-marko:
+ optional: true
+ prettier-plugin-multiline-arrays:
+ optional: true
+ prettier-plugin-organize-attributes:
+ optional: true
+ prettier-plugin-organize-imports:
+ optional: true
+ prettier-plugin-sort-imports:
+ optional: true
+ prettier-plugin-svelte:
+ optional: true
+
prettier@3.8.0:
resolution: {integrity: sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==}
engines: {node: '>=14'}
hasBin: true
+ prettier@3.9.10:
+ resolution: {integrity: sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==}
+ engines: {node: '>=14'}
+ hasBin: true
+
process-warning@5.0.0:
resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==}
@@ -8915,8 +8981,14 @@ snapshots:
prelude-ls@1.2.1: {}
+ prettier-plugin-tailwindcss@0.8.1(prettier@3.9.10):
+ dependencies:
+ prettier: 3.9.10
+
prettier@3.8.0: {}
+ prettier@3.9.10: {}
+
process-warning@5.0.0: {}
prompts@2.4.2:
diff --git a/postcss.config.mjs b/postcss.config.mjs
index c7bcb4b..86e8e3c 100644
--- a/postcss.config.mjs
+++ b/postcss.config.mjs
@@ -1,5 +1,5 @@
const config = {
- plugins: ["@tailwindcss/postcss"],
-};
+ plugins: ['@tailwindcss/postcss'],
+}
-export default config;
+export default config
diff --git a/prettier.config.js b/prettier.config.js
new file mode 100644
index 0000000..4cf3630
--- /dev/null
+++ b/prettier.config.js
@@ -0,0 +1,13 @@
+// @ts-check
+
+/** @type {import('prettier').Config} */
+const config = {
+ semi: false,
+ singleQuote: true,
+ trailingComma: 'all',
+ plugins: ['prettier-plugin-tailwindcss'],
+ tailwindStylesheet: 'src/app/globals.css',
+ tailwindFunctions: ['cn', 'cva'],
+}
+
+export default config
diff --git a/src/app/(app)/layout.tsx b/src/app/(app)/layout.tsx
index 2abaada..8990699 100644
--- a/src/app/(app)/layout.tsx
+++ b/src/app/(app)/layout.tsx
@@ -1,35 +1,35 @@
-import type { Metadata } from "next";
-import { Geist, Geist_Mono } from "next/font/google";
-import "../globals.css";
+import type { Metadata } from 'next'
+import { Geist, Geist_Mono } from 'next/font/google'
+import '../globals.css'
const geistSans = Geist({
- variable: "--font-geist-sans",
- subsets: ["latin"],
-});
+ variable: '--font-geist-sans',
+ subsets: ['latin'],
+})
const geistMono = Geist_Mono({
- variable: "--font-geist-mono",
- subsets: ["latin"],
-});
+ variable: '--font-geist-mono',
+ subsets: ['latin'],
+})
export const metadata: Metadata = {
- title: "Liam Pietralla",
- description: "Enthusiastic Software Developer & DevOps Engineer",
-};
+ title: 'Liam Pietralla',
+ description: 'Enthusiastic Software Developer & DevOps Engineer',
+}
export default function RootLayout({
children,
}: Readonly<{
- children: React.ReactNode;
+ children: React.ReactNode
}>) {
return (
{children}
- );
+ )
}
diff --git a/src/app/(app)/page.tsx b/src/app/(app)/page.tsx
index 765f530..885e262 100644
--- a/src/app/(app)/page.tsx
+++ b/src/app/(app)/page.tsx
@@ -1,51 +1,78 @@
-import IndexLink from "@/components/home-page-link";
-import Rule from "@/components/horizontal-rule";
-import { getHome } from "@/services/home-service";
-import { Mail } from "lucide-react";
-import Image from "next/image";
+import IndexLink from '@/components/home-page-link'
+import Rule from '@/components/horizontal-rule'
+import { getHome } from '@/services/home-service'
+import { Mail } from 'lucide-react'
+import Image from 'next/image'
-import ProfileImage from "../../../public/images/liam_pietralla.jpg";
+import ProfileImage from '../../../public/images/liam_pietralla.jpg'
const IndexPage = async () => {
- const home = await getHome();
+ const home = await getHome()
return (
-
-
-
+
+
+
-
+
Liam Pietralla
-
-
Enthusiastic Software Developer
-
& DevOps Engineer
+
+
Enthusiastic Software Developer
+
+ & DevOps Engineer
+
-
-
- {home.mainLinks.map(link => (
+
+
+ {home.mainLinks.map((link) => (
))}
-
- );
+ )
}
-export default IndexPage;
+export default IndexPage
diff --git a/src/app/(app)/projects/page.tsx b/src/app/(app)/projects/page.tsx
index 6b0820c..5fe992f 100644
--- a/src/app/(app)/projects/page.tsx
+++ b/src/app/(app)/projects/page.tsx
@@ -1,28 +1,45 @@
-import ProjectCard from "@/components/project-card";
-import { getProjects } from "@/services/projects-service";
-import Image from "next/image";
-import Link from "next/link";
+import ProjectCard from '@/components/project-card'
+import { getProjects } from '@/services/projects-service'
+import Image from 'next/image'
+import Link from 'next/link'
-import ProfileImage from "../../../../public/images/liam_pietralla.jpg";
+import ProfileImage from '../../../../public/images/liam_pietralla.jpg'
const ProjectsPage = async () => {
- const projects = await getProjects();
+ const projects = await getProjects()
return (
-
-
-
-
+
+
+
+
Liam Pietralla
-
+
-
Projects
-
- A collection of interesting projects that I am working on currently or have worked on in the past.
+
+ Projects
+
+
+ A collection of interesting projects that I am working on currently or
+ have worked on in the past.
-
+
{projects.docs.map((project, index) => (
-
+
))}
@@ -31,4 +48,4 @@ const ProjectsPage = async () => {
)
}
-export default ProjectsPage;
+export default ProjectsPage
diff --git a/src/app/(payload)/admin/[[...segments]]/not-found.tsx b/src/app/(payload)/admin/[[...segments]]/not-found.tsx
index 6410836..601c44d 100644
--- a/src/app/(payload)/admin/[[...segments]]/not-found.tsx
+++ b/src/app/(payload)/admin/[[...segments]]/not-found.tsx
@@ -15,7 +15,10 @@ type Args = {
}>
}
-export const generateMetadata = ({ params, searchParams }: Args): Promise
=>
+export const generateMetadata = ({
+ params,
+ searchParams,
+}: Args): Promise =>
generatePageMetadata({ config, params, searchParams })
const NotFound = ({ params, searchParams }: Args) =>
diff --git a/src/app/(payload)/admin/[[...segments]]/page.tsx b/src/app/(payload)/admin/[[...segments]]/page.tsx
index 0de685c..d323d0a 100644
--- a/src/app/(payload)/admin/[[...segments]]/page.tsx
+++ b/src/app/(payload)/admin/[[...segments]]/page.tsx
@@ -15,7 +15,10 @@ type Args = {
}>
}
-export const generateMetadata = ({ params, searchParams }: Args): Promise =>
+export const generateMetadata = ({
+ params,
+ searchParams,
+}: Args): Promise =>
generatePageMetadata({ config, params, searchParams })
const Page = ({ params, searchParams }: Args) =>
diff --git a/src/app/(payload)/api/[...slug]/route.ts b/src/app/(payload)/api/[...slug]/route.ts
index f61b68e..fbd4ab2 100644
--- a/src/app/(payload)/api/[...slug]/route.ts
+++ b/src/app/(payload)/api/[...slug]/route.ts
@@ -15,7 +15,7 @@ type NextCtx = { params: Promise<{ slug?: string[] }> }
type PayloadCtx = { params: Promise<{ slug: string[] }> }
const coerceCtx = (ctx: NextCtx): PayloadCtx => ({
- params: ctx.params.then(p => ({ slug: p?.slug ?? [] })),
+ params: ctx.params.then((p) => ({ slug: p?.slug ?? [] })),
})
export function GET(req: Request, ctx: NextCtx) {
@@ -40,4 +40,4 @@ export function PUT(req: Request, ctx: NextCtx) {
export function OPTIONS(req: Request, ctx: NextCtx) {
return REST_OPTIONS(config)(req, coerceCtx(ctx))
-}
\ No newline at end of file
+}
diff --git a/src/app/(payload)/api/graphql-playground/route.ts b/src/app/(payload)/api/graphql-playground/route.ts
index 385a693..eb0eb84 100644
--- a/src/app/(payload)/api/graphql-playground/route.ts
+++ b/src/app/(payload)/api/graphql-playground/route.ts
@@ -6,4 +6,4 @@ import { GRAPHQL_PLAYGROUND_GET } from '@payloadcms/next/routes'
export async function GET(req: Request): Promise {
return GRAPHQL_PLAYGROUND_GET(config)(req)
-}
\ No newline at end of file
+}
diff --git a/src/app/(payload)/api/graphql/route.ts b/src/app/(payload)/api/graphql/route.ts
index 6809b14..a0003de 100644
--- a/src/app/(payload)/api/graphql/route.ts
+++ b/src/app/(payload)/api/graphql/route.ts
@@ -7,7 +7,7 @@ type NextCtx = { params: Promise<{ slug?: string[] }> }
type PayloadCtx = { params: Promise<{ slug: string[] }> }
const coerceCtx = (ctx: NextCtx): PayloadCtx => ({
- params: ctx.params.then(p => ({ slug: p?.slug ?? [] })),
+ params: ctx.params.then((p) => ({ slug: p?.slug ?? [] })),
})
export function POST(req: Request) {
@@ -16,4 +16,4 @@ export function POST(req: Request) {
export function OPTIONS(req: Request, ctx: NextCtx) {
return REST_OPTIONS(config)(req, coerceCtx(ctx))
-}
\ No newline at end of file
+}
diff --git a/src/app/(payload)/layout.tsx b/src/app/(payload)/layout.tsx
index 8df141a..9501c96 100644
--- a/src/app/(payload)/layout.tsx
+++ b/src/app/(payload)/layout.tsx
@@ -23,7 +23,11 @@ const serverFunction: ServerFunctionClient = async function (args) {
}
const Layout = ({ children }: Args) => (
-
+
{children}
)
diff --git a/src/app/api/health/route.ts b/src/app/api/health/route.ts
index 32aafe5..8561001 100644
--- a/src/app/api/health/route.ts
+++ b/src/app/api/health/route.ts
@@ -1,14 +1,14 @@
-import pkg from "../../../../package.json";
+import pkg from '../../../../package.json'
export async function GET() {
const response = {
- "status": "Healthy",
- "version": pkg.version
- };
+ status: 'Healthy',
+ version: pkg.version,
+ }
return new Response(JSON.stringify(response), {
status: 200,
headers: {
- "Content-Type": "application/json"
- }
- });
-}
\ No newline at end of file
+ 'Content-Type': 'application/json',
+ },
+ })
+}
diff --git a/src/app/globals.css b/src/app/globals.css
index d6753cc..1bf85f6 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -1,4 +1,4 @@
-@import "tailwindcss";
+@import 'tailwindcss';
:root {
--background: #0a0a0a;
@@ -31,7 +31,7 @@ body {
.aurora::before,
.aurora::after {
- content: "";
+ content: '';
position: absolute;
width: 60vw;
height: 60vw;
@@ -56,18 +56,32 @@ body {
}
@keyframes drift-1 {
- 0% { transform: translate(0, 0) scale(1); }
- 100% { transform: translate(15vw, 10vh) scale(1.15); }
+ 0% {
+ transform: translate(0, 0) scale(1);
+ }
+ 100% {
+ transform: translate(15vw, 10vh) scale(1.15);
+ }
}
@keyframes drift-2 {
- 0% { transform: translate(0, 0) scale(1); }
- 100% { transform: translate(-12vw, -8vh) scale(1.2); }
+ 0% {
+ transform: translate(0, 0) scale(1);
+ }
+ 100% {
+ transform: translate(-12vw, -8vh) scale(1.2);
+ }
}
@keyframes fade-in-up {
- from { opacity: 0; transform: translateY(16px); }
- to { opacity: 1; transform: translateY(0); }
+ from {
+ opacity: 0;
+ transform: translateY(16px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
}
.animate-fade-in-up {
@@ -76,8 +90,12 @@ body {
}
@keyframes fade-in {
- from { opacity: 0; }
- to { opacity: 1; }
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
}
.animate-fade-in {
@@ -90,7 +108,7 @@ body {
}
.glow-ring::before {
- content: "";
+ content: '';
position: absolute;
inset: -6px;
border-radius: 9999px;
@@ -102,8 +120,12 @@ body {
}
@keyframes spin-slow {
- from { transform: rotate(0deg); }
- to { transform: rotate(360deg); }
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
}
.glass {
@@ -111,7 +133,11 @@ body {
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.08);
- transition: background 0.3s ease, border-color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
+ transition:
+ background 0.3s ease,
+ border-color 0.3s ease,
+ transform 0.3s ease,
+ box-shadow 0.3s ease;
}
.glass-hover:hover {
diff --git a/src/collections/Media.ts b/src/collections/Media.ts
index b0dc9a4..f7621eb 100644
--- a/src/collections/Media.ts
+++ b/src/collections/Media.ts
@@ -1,26 +1,26 @@
-import type { CollectionConfig } from "payload"
+import type { CollectionConfig } from 'payload'
export const Media: CollectionConfig = {
- slug: "media",
+ slug: 'media',
access: {
read: () => true,
},
fields: [
{
- name: "alt",
- type: "text",
+ name: 'alt',
+ type: 'text',
required: true,
},
],
upload: {
imageSizes: [
{
- name: "thumbnail",
+ name: 'thumbnail',
width: 150,
height: 150,
- position: "centre",
- }
+ position: 'centre',
+ },
],
- adminThumbnail: "thumbnail",
- }
+ adminThumbnail: 'thumbnail',
+ },
}
diff --git a/src/collections/Projects.ts b/src/collections/Projects.ts
index 8f8f69d..0e418f3 100644
--- a/src/collections/Projects.ts
+++ b/src/collections/Projects.ts
@@ -1,61 +1,61 @@
-import { revalidatePath } from "next/cache";
-import { CollectionConfig } from "payload";
+import { revalidatePath } from 'next/cache'
+import { CollectionConfig } from 'payload'
export const Projects: CollectionConfig = {
- slug: "project",
+ slug: 'project',
access: {
read: () => true,
},
fields: [
{
- name: "title",
- type: "text",
+ name: 'title',
+ type: 'text',
required: true,
},
{
- name: "description",
- type: "textarea",
+ name: 'description',
+ type: 'textarea',
required: true,
},
{
- name: "featuredImage",
- type: "relationship",
- relationTo: "media",
+ name: 'featuredImage',
+ type: 'relationship',
+ relationTo: 'media',
required: false,
},
{
- name: "tags",
- type: "array",
+ name: 'tags',
+ type: 'array',
required: false,
fields: [
{
- name: "tag",
- type: "text",
+ name: 'tag',
+ type: 'text',
required: true,
},
],
},
{
- name: "viewLink",
- type: "text",
+ name: 'viewLink',
+ type: 'text',
required: false,
},
{
- name: "repositoryLink",
- type: "text",
+ name: 'repositoryLink',
+ type: 'text',
required: false,
- }
+ },
],
hooks: {
afterChange: [
async () => {
- revalidatePath("/projects");
- }
+ revalidatePath('/projects')
+ },
],
afterDelete: [
async () => {
- revalidatePath("/projects");
- }
- ]
- }
-}
\ No newline at end of file
+ revalidatePath('/projects')
+ },
+ ],
+ },
+}
diff --git a/src/collections/Users.ts b/src/collections/Users.ts
index 8ba30e8..c683d0e 100644
--- a/src/collections/Users.ts
+++ b/src/collections/Users.ts
@@ -1,9 +1,9 @@
-import type { CollectionConfig } from "payload"
+import type { CollectionConfig } from 'payload'
export const Users: CollectionConfig = {
- slug: "users",
+ slug: 'users',
admin: {
- useAsTitle: "email",
+ useAsTitle: 'email',
},
auth: true,
fields: [
diff --git a/src/components/home-page-link.tsx b/src/components/home-page-link.tsx
index 777a605..9caf476 100644
--- a/src/components/home-page-link.tsx
+++ b/src/components/home-page-link.tsx
@@ -1,42 +1,42 @@
-import Link from "next/link";
-import { DynamicIcon, IconName } from "lucide-react/dynamic";
-import { lucidIconMap } from "@/lib/lucid-options";
+import Link from 'next/link'
+import { DynamicIcon, IconName } from 'lucide-react/dynamic'
+import { lucidIconMap } from '@/lib/lucid-options'
interface HomePageLinkProps {
- title: string;
- url: string;
- icon: string;
- id?: string | null;
- isPopover?: boolean;
+ title: string
+ url: string
+ icon: string
+ id?: string | null
+ isPopover?: boolean
}
const HomePageLink = ({ title, icon, url, isPopover }: HomePageLinkProps) => {
- const isRelative = !url.startsWith("http");
- const IconComponent = lucidIconMap[icon as IconName];
+ const isRelative = !url.startsWith('http')
+ const IconComponent = lucidIconMap[icon as IconName]
if (isPopover) {
const LinkContent = (
-
+
{icon && }
- );
+ )
const Popover = (
-
+
{title}
- );
+ )
if (isRelative) {
return (
-
+
{LinkContent}
{Popover}
)
} else {
return (
-
+
@@ -45,12 +45,12 @@ const HomePageLink = ({ title, icon, url, isPopover }: HomePageLinkProps) => {
} else {
const Content = (
<>
-
+
{icon && } {title}
-
+
>
- );
+ )
if (isRelative) {
return (
@@ -68,5 +68,4 @@ const HomePageLink = ({ title, icon, url, isPopover }: HomePageLinkProps) => {
}
}
-
-export default HomePageLink;
+export default HomePageLink
diff --git a/src/components/horizontal-rule.tsx b/src/components/horizontal-rule.tsx
index 6c83abe..3699e8e 100644
--- a/src/components/horizontal-rule.tsx
+++ b/src/components/horizontal-rule.tsx
@@ -1,15 +1,15 @@
-import { cn } from "@/lib/utils";
-import { CSSProperties } from "react";
+import { cn } from '@/lib/utils'
+import { CSSProperties } from 'react'
interface RuleProps {
- className?: string;
- style?: CSSProperties;
+ className?: string
+ style?: CSSProperties
}
const HorizontalRule = ({ className, style }: RuleProps) => {
return (
-
+
)
}
-export default HorizontalRule;
+export default HorizontalRule
diff --git a/src/components/project-card.tsx b/src/components/project-card.tsx
index 9144652..df21882 100644
--- a/src/components/project-card.tsx
+++ b/src/components/project-card.tsx
@@ -1,20 +1,29 @@
-import Image from "next/image";
-import HorizontalRule from "./horizontal-rule";
-import { Code, ExternalLink } from "lucide-react";
-import { Project } from "@/payload-types";
+import Image from 'next/image'
+import HorizontalRule from './horizontal-rule'
+import { Code, ExternalLink } from 'lucide-react'
+import { Project } from '@/payload-types'
const ProjectCard = (project: Project) => {
return (
-
+
{project.title}
- {project.featuredImage && typeof project.featuredImage === "object" && (
-
+ {project.featuredImage && typeof project.featuredImage === 'object' && (
+
)}
{project.description}
-
+
{(project?.tags || []).map((tag) => (
-
+
{tag.tag}
))}
@@ -24,20 +33,20 @@ const ProjectCard = (project: Project) => {
@@ -45,4 +54,4 @@ const ProjectCard = (project: Project) => {
)
}
-export default ProjectCard;
+export default ProjectCard
diff --git a/src/globals/home.ts b/src/globals/home.ts
index 83c46a7..32b5da0 100644
--- a/src/globals/home.ts
+++ b/src/globals/home.ts
@@ -1,54 +1,54 @@
-import { lucideOptions } from "@/lib/lucid-options";
-import { revalidatePath } from "next/cache";
-import { GlobalConfig } from "payload";
+import { lucideOptions } from '@/lib/lucid-options'
+import { revalidatePath } from 'next/cache'
+import { GlobalConfig } from 'payload'
export const Home: GlobalConfig = {
- slug: "home",
+ slug: 'home',
access: {
read: () => true,
},
fields: [
{
- name: "mainLinks",
- type: "array",
+ name: 'mainLinks',
+ type: 'array',
required: true,
fields: [
{
- name: "title",
- type: "text",
+ name: 'title',
+ type: 'text',
required: true,
},
{
- name: "url",
- type: "text",
+ name: 'url',
+ type: 'text',
required: true,
},
{
- name: "icon",
- type: "select",
+ name: 'icon',
+ type: 'select',
options: lucideOptions,
required: true,
},
],
},
{
- name: "popoverLinks",
- type: "array",
+ name: 'popoverLinks',
+ type: 'array',
required: true,
fields: [
{
- name: "title",
- type: "text",
+ name: 'title',
+ type: 'text',
required: true,
},
{
- name: "url",
- type: "text",
+ name: 'url',
+ type: 'text',
required: true,
},
{
- name: "icon",
- type: "select",
+ name: 'icon',
+ type: 'select',
options: lucideOptions,
required: true,
},
@@ -58,8 +58,8 @@ export const Home: GlobalConfig = {
hooks: {
afterChange: [
async () => {
- revalidatePath("/");
- }
+ revalidatePath('/')
+ },
],
- }
-}
\ No newline at end of file
+ },
+}
diff --git a/src/lib/lucid-options.ts b/src/lib/lucid-options.ts
index 2743bd3..bc4cad7 100644
--- a/src/lib/lucid-options.ts
+++ b/src/lib/lucid-options.ts
@@ -1,15 +1,15 @@
-import { Code2, Github, Linkedin, LucideIcon, Notebook } from "lucide-react"
+import { Code2, Github, Linkedin, LucideIcon, Notebook } from 'lucide-react'
-export const lucideOptions: { label: string, value: string }[] = [
- { label: "Code 2", value: "code-2" },
- { label: "Notebook", value: "notebook" },
- { label: "Github", value: "github" },
- { label: "Linkedin", value: "linkedin" },
-];
+export const lucideOptions: { label: string; value: string }[] = [
+ { label: 'Code 2', value: 'code-2' },
+ { label: 'Notebook', value: 'notebook' },
+ { label: 'Github', value: 'github' },
+ { label: 'Linkedin', value: 'linkedin' },
+]
export const lucidIconMap: Record = {
- "code-2": Code2,
- "notebook": Notebook,
- "github": Github,
- "linkedin": Linkedin,
-};
\ No newline at end of file
+ 'code-2': Code2,
+ notebook: Notebook,
+ github: Github,
+ linkedin: Linkedin,
+}
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index bd0c391..fed2fe9 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -1,5 +1,5 @@
-import { clsx, type ClassValue } from "clsx"
-import { twMerge } from "tailwind-merge"
+import { clsx, type ClassValue } from 'clsx'
+import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
diff --git a/src/payload.config.ts b/src/payload.config.ts
index c578f0e..2c50e1b 100644
--- a/src/payload.config.ts
+++ b/src/payload.config.ts
@@ -1,15 +1,15 @@
-import { postgresAdapter } from "@payloadcms/db-postgres"
-import { lexicalEditor } from "@payloadcms/richtext-lexical"
-import path from "path"
-import { buildConfig } from "payload"
-import { s3Storage } from "@payloadcms/storage-s3"
-import sharp from "sharp"
-import { fileURLToPath } from "url"
+import { postgresAdapter } from '@payloadcms/db-postgres'
+import { lexicalEditor } from '@payloadcms/richtext-lexical'
+import path from 'path'
+import { buildConfig } from 'payload'
+import { s3Storage } from '@payloadcms/storage-s3'
+import sharp from 'sharp'
+import { fileURLToPath } from 'url'
-import { Media } from "./collections/Media"
-import { Projects } from "./collections/Projects"
-import { Users } from "./collections/Users"
-import { Home } from "./globals/home"
+import { Media } from './collections/Media'
+import { Projects } from './collections/Projects'
+import { Users } from './collections/Users'
+import { Home } from './globals/home'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
@@ -24,13 +24,13 @@ export default buildConfig({
collections: [Users, Media, Projects],
globals: [Home],
editor: lexicalEditor(),
- secret: process.env.PAYLOAD_SECRET || "",
+ secret: process.env.PAYLOAD_SECRET || '',
typescript: {
- outputFile: path.resolve(dirname, "payload-types.ts"),
+ outputFile: path.resolve(dirname, 'payload-types.ts'),
},
db: postgresAdapter({
pool: {
- connectionString: process.env.DATABASE_URL || "",
+ connectionString: process.env.DATABASE_URL || '',
},
}),
sharp,
@@ -39,16 +39,16 @@ export default buildConfig({
collections: {
media: true,
},
- bucket: process.env.S3_BUCKET || "",
+ bucket: process.env.S3_BUCKET || '',
config: {
forcePathStyle: true,
- region: process.env.S3_REGION || "",
+ region: process.env.S3_REGION || '',
credentials: {
- accessKeyId: process.env.S3_ACCESS_KEY_ID || "",
- secretAccessKey: process.env.S3_SECRET_ACCESS_KEY || "",
+ accessKeyId: process.env.S3_ACCESS_KEY_ID || '',
+ secretAccessKey: process.env.S3_SECRET_ACCESS_KEY || '',
},
endpoint: process.env.S3_ENDPOINT || undefined,
- }
+ },
}),
],
})
diff --git a/src/services/home-service.ts b/src/services/home-service.ts
index a5ebe28..3b3370f 100644
--- a/src/services/home-service.ts
+++ b/src/services/home-service.ts
@@ -4,6 +4,6 @@ import config from '@payload-config'
export const getHome = async () => {
const payload = await getPayload({ config })
return await payload.findGlobal({
- slug: "home"
+ slug: 'home',
})
-}
\ No newline at end of file
+}
diff --git a/src/services/projects-service.ts b/src/services/projects-service.ts
index c8cc49c..8c048fe 100644
--- a/src/services/projects-service.ts
+++ b/src/services/projects-service.ts
@@ -4,6 +4,6 @@ import config from '@payload-config'
export const getProjects = async () => {
const payload = await getPayload({ config })
return await payload.find({
- collection: "project"
+ collection: 'project',
})
-}
\ No newline at end of file
+}
diff --git a/tsconfig.json b/tsconfig.json
index 75e90e3..a14a139 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,11 +1,7 @@
{
"compilerOptions": {
"target": "ES2017",
- "lib": [
- "dom",
- "dom.iterable",
- "esnext"
- ],
+ "lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -23,12 +19,8 @@
}
],
"paths": {
- "@/*": [
- "./src/*"
- ],
- "@payload-config": [
- "./src/payload.config.ts"
- ]
+ "@/*": ["./src/*"],
+ "@payload-config": ["./src/payload.config.ts"]
}
},
"include": [
@@ -38,7 +30,5 @@
".next/types/**/*.ts",
".next/dev/types/**/*.ts"
],
- "exclude": [
- "node_modules"
- ]
+ "exclude": ["node_modules"]
}