diff --git a/.env-sample b/.env-sample index b1feac1b..189cc1d1 100644 --- a/.env-sample +++ b/.env-sample @@ -31,12 +31,15 @@ ALGOLIA_UPDATE_API_KEY= MAILER_LITE_API_KEY= MAILER_LITE_GROUP_ID= +# Github token for fetching activity from Github +# https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token +GITHUB_TOKEN= + # Usernames used on social media accounts - used in external links NEXT_PUBLIC_X_USERNAME= NEXT_PUBLIC_FACEBOOK_USERNAME= NEXT_PUBLIC_LINKEDIN_USERNAME= NEXT_PUBLIC_GITHUB_USERNAME= -NEXT_PUBLIC_GUMROAD_USERNAME= NEXT_PUBLIC_EMAIL= # Google Analytics tracking id @@ -52,3 +55,4 @@ NEXT_PUBLIC_ALGOLIA_PROJECTS_INDEX_NAME=projects-preview # Locally exposed host by Next.js server NEXT_PUBLIC_HOST=localhost:3000 + diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 66b1cf8c..00000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -public -*.config.js \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index ad729ed2..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json" - }, - "plugins": ["@typescript-eslint", "unused-imports"], - "extends": [ - "next", - "next/core-web-vitals", - "prettier", - "plugin:@typescript-eslint/recommended", - "plugin:@typescript-eslint/recommended-requiring-type-checking", - "plugin:@typescript-eslint/strict" - ], - "settings": { - "import/parsers": { - "@typescript-eslint/parser": [".ts"] - }, - "import/resolver": { - "node": { - "extensions": [".js", ".ts"], - "moduleDirectory": ["node_modules", "./"] - }, - "typescript": { - "alwaysTryTypes": true - } - } - }, - "rules": { - // Separate import groups with newline by section - "import/order": [ - "error", - { - "alphabetize": { - "caseInsensitive": true, - "order": "asc" - }, - "groups": [ - "builtin", - "external", - "internal", - "parent", - "sibling", - "index", - "type", - "unknown" - ], - "newlines-between": "always", - "warnOnUnassignedImports": true - } - ], - "arrow-body-style": ["warn", "as-needed"], - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "no-unused-vars": [ - "error", - { - "argsIgnorePattern": "^_", - "varsIgnorePattern": "^_" - } - ], - "unused-imports/no-unused-imports": "warn", - "@typescript-eslint/naming-convention": [ - "error", - { - "selector": "enum", - "format": ["UPPER_CASE"] - }, - { - "selector": "enumMember", - "format": ["UPPER_CASE"] - } - ] - } -} diff --git a/.github/workflows/lighthouse.yml b/.github/workflows/lighthouse.yml index 6f955c6f..dd7d09c4 100644 --- a/.github/workflows/lighthouse.yml +++ b/.github/workflows/lighthouse.yml @@ -24,5 +24,6 @@ jobs: with: urls: ${{ steps.waitForVercelPreviewDeployment.outputs.url }} gitHubAccessToken: ${{ secrets.GITHUB_TOKEN }} + device: "all" locale: en prCommentEnabled: true diff --git a/.github/workflows/nextjs_bundle_analysis.yml b/.github/workflows/nextjs_bundle_analysis.yml deleted file mode 100644 index b8a010f1..00000000 --- a/.github/workflows/nextjs_bundle_analysis.yml +++ /dev/null @@ -1,102 +0,0 @@ -name: "Next.js Bundle Analysis" - -on: - pull_request: - push: - branches: - - develop - workflow_dispatch: - -defaults: - run: - working-directory: ./ - -permissions: - contents: read - actions: read - pull-requests: write - -jobs: - analyze: - runs-on: ubuntu-latest - env: - KV_REST_API_TOKEN: ${{ secrets.KV_REST_API_TOKEN }} - KV_REST_API_URL: ${{ secrets.KV_REST_API_URL }} - steps: - - uses: actions/checkout@v3 - - name: Install Node.js - uses: actions/setup-node@v3 - with: - node-version: 20 - - - uses: pnpm/action-setup@v2 - name: Install pnpm - id: pnpm-install - with: - version: 8 - run_install: true - - - name: Restore next build - uses: actions/cache@v3 - id: restore-build-cache - env: - cache-name: cache-next-build - with: - path: .next/cache - key: ${{ runner.os }}-build-${{ env.cache-name }} - - - name: Build next.js app - run: SKIP_ENV_VALIDATION=1 ./node_modules/.bin/next build - - - name: Analyze bundle - run: npx -p nextjs-bundle-analysis report - - - name: Upload bundle - uses: actions/upload-artifact@v3 - with: - name: bundle - path: .next/analyze/__bundle_analysis.json - - - name: Download base branch bundle stats - uses: dawidd6/action-download-artifact@v2 - if: success() && github.event.number - with: - workflow: nextjs_bundle_analysis.yml - branch: ${{ github.event.pull_request.base.ref }} - path: .next/analyze/base - - - name: Compare with base branch bundle - if: success() && github.event.number - run: ls -laR .next/analyze/base && npx -p nextjs-bundle-analysis compare - - - name: Get Comment Body - id: get-comment-body - if: success() && github.event.number - run: | - echo "body<> $GITHUB_OUTPUT - echo "$(cat .next/analyze/__bundle_analysis_comment.txt)" >> $GITHUB_OUTPUT - echo EOF >> $GITHUB_OUTPUT - - - name: Find Comment - uses: peter-evans/find-comment@v2 - if: success() && github.event.number - id: fc - with: - issue-number: ${{ github.event.number }} - body-includes: "" - - - name: Create Comment - uses: peter-evans/create-or-update-comment@v2 - if: success() && github.event.number && steps.fc.outputs.comment-id == 0 - with: - issue-number: ${{ github.event.number }} - body: ${{ steps.get-comment-body.outputs.body }} - - - name: Update Comment - uses: peter-evans/create-or-update-comment@v2 - if: success() && github.event.number && steps.fc.outputs.comment-id != 0 - with: - issue-number: ${{ github.event.number }} - body: ${{ steps.get-comment-body.outputs.body }} - comment-id: ${{ steps.fc.outputs.comment-id }} - edit-mode: replace diff --git a/.gitignore b/.gitignore index 0a5247fb..96adf058 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ # next.js /.next/ /out/ +next-env.d.ts # production /build diff --git a/.lintstagedrc.js b/.lintstagedrc.js deleted file mode 100644 index 325eea7e..00000000 --- a/.lintstagedrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - "*.{js,jsx,ts,tsx,md,mdx,graphql,yml,yaml,css,scss,json}": ["prettier --write"], - "*.{js,jsx,ts,tsx}": [() => "eslint --fix"], -}; diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index 25bf17fc..00000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -18 \ No newline at end of file diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 6559ff86..00000000 --- a/.prettierrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "semi": true, - "singleQuote": false, - "trailingComma": "all", - "tabWidth": 2, - "useTabs": false, - "printWidth": 100 -} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..515478b6 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,21 @@ +{ + "css.customData": [".vscode/tailwind.json"], + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "eslint.rules.customizations": [{ "rule": "*", "severity": "warn" }], + "prettier.ignorePath": ".gitignore", + "tailwindCSS.experimental.classRegex": [ + ["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"], + ["cx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"] + ], + "tailwindCSS.experimental.configFile": "./tailwind.config.js", + "typescript.enablePromptUseWorkspaceTsdk": true, + "typescript.preferences.autoImportFileExcludePatterns": [ + "next/router.d.ts", + "next/dist/client/router.d.ts" + ], + "typescript.tsdk": "node_modules/typescript/lib" +} diff --git a/.vscode/tailwind.json b/.vscode/tailwind.json new file mode 100644 index 00000000..d0cdb0ce --- /dev/null +++ b/.vscode/tailwind.json @@ -0,0 +1,75 @@ +{ + "version": 1.1, + "atDirectives": [ + { + "name": "@tailwind", + "description": "Use the `@tailwind` directive to insert Tailwind's `base`, `components`, `utilities` and `screens` styles into your CSS.", + "references": [ + { + "name": "Tailwind Documentation", + "url": "https://tailwindcss.com/docs/functions-and-directives#tailwind" + } + ] + }, + { + "name": "@apply", + "description": "Use the `@apply` directive to inline any existing utility classes into your own custom CSS. This is useful when you find a common utility pattern in your HTML that you’d like to extract to a new component.", + "references": [ + { + "name": "Tailwind Documentation", + "url": "https://tailwindcss.com/docs/functions-and-directives#apply" + } + ] + }, + { + "name": "@responsive", + "description": "You can generate responsive variants of your own classes by wrapping their definitions in the `@responsive` directive:\n```css\n@responsive {\n .alert {\n background-color: #E53E3E;\n }\n}\n```\n", + "references": [ + { + "name": "Tailwind Documentation", + "url": "https://tailwindcss.com/docs/functions-and-directives#responsive" + } + ] + }, + { + "name": "@screen", + "description": "The `@screen` directive allows you to create media queries that reference your breakpoints by **name** instead of duplicating their values in your own CSS:\n```css\n@screen sm {\n /* ... */\n}\n```\n…gets transformed into this:\n```css\n@media (min-width: 640px) {\n /* ... */\n}\n```\n", + "references": [ + { + "name": "Tailwind Documentation", + "url": "https://tailwindcss.com/docs/functions-and-directives#screen" + } + ] + }, + { + "name": "@variants", + "description": "Generate `hover`, `focus`, `active` and other **variants** of your own utilities by wrapping their definitions in the `@variants` directive:\n```css\n@variants hover, focus {\n .btn-brand {\n background-color: #3182CE;\n }\n}\n```\n", + "references": [ + { + "name": "Tailwind Documentation", + "url": "https://tailwindcss.com/docs/functions-and-directives#variants" + } + ] + }, + { + "name": "@custom-variant", + "description": "Use the `@custom-variant` directive to create a custom variant for a given selector. This is useful when you want to create a variant for a specific element or component.", + "references": [ + { + "name": "Tailwind Documentation", + "url": "https://tailwindcss.com/docs/functions-and-directives#custom-variant" + } + ] + }, + { + "name": "@plugin", + "description": "Use the `@plugin` directive to import a plugin into your CSS.", + "references": [ + { + "name": "Tailwind Documentation", + "url": "https://tailwindcss.com/docs/functions-and-directives#plugin" + } + ] + } + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3e13d6e9..02ff6035 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,36 +27,38 @@ Just put it in `/content` folder and make a PR. It would be good for you to cont Description of the project files and directories. ```bash +├── .github # Github workflows and templates +├── .husky # Husky git hooks +├── .vscode # VSCode settings ├── app/ # Next.js app directory (v13) ├── components/ # React components ├── content/ # All .mdx files with content ├── data/ # Global available data -├── env/ # Env variables handling (validation) ├── hooks/ # Shared React hooks ├── lib/ # Lib files -├── providers/ # React context global state +├── providers/ # React context global state and other providers ├── public/ # All images, icons, fonts ├── scripts/ # Scripts executed during deployment (algolia, redirects, feed) ├── styles/ # All shared styles ├── types/ # TypeScript types ├── utils/ # All utilities ├── .env-sample # Examples of env variables -├── .eslintignore # Files ignored by ESLint -├── .eslintrc.js # ESLint configuration file ├── .gitignore # Files ignored by git +├── .npmrc # NPM configuration ├── .prettierignore # Files ignored by Prettier -├── .prettierrc # Code convention enforced by Prettier ├── build.sh # Deployment script -├── next.config.mjs # Next.js config +├── eslint.config.mjs # ESLint configuration file +├── next.config.ts # Next.js config ├── package.json # Dependencies and additional information +├── pnpm-lock.yaml # Pnpm lockfile +├── prettier.config.mjs # Code convention enforced by Prettier ├── README.md -├── tsconfig.json # Typescript configuration -└── pnpm-lock.yaml # Pnpm lockfile +└── tsconfig.json # Typescript configuration ``` ## Styleguide -Coding conventions are enforced by [ESLint](.eslintrc.json) and [Prettier](.prettierrc). +Coding conventions are enforced by [ESLint](eslint.config.mjs) and [Prettier](prettier.config.mjs). - Semicolons - Double quotes @@ -72,13 +74,14 @@ Coding conventions are enforced by [ESLint](.eslintrc.json) and [Prettier](.pret ## Example component structure ```bash -├── Component/ -│ ├── Component.tsx -│ └── component.module.scss +├── component/ +│ ├── api/ +│ ├── hooks/ +│ ├── utils/ +│ └── component.tsx ``` ```tsx -import styles from "./component.module.scss"; import { memo } from "react"; interface ComponentProps { @@ -94,24 +97,24 @@ Component.displayName = "Component"; ## Tech stack -| Tech | Description | -| --------------------------------------------------------- | ------------------------------------------------------------------- | -| [TypeScript](https://www.typescriptlang.org/) | Static type-checking programming language | -| [Next.js 13](https://nextjs.org/) | The React Framework for Production | -| [React](https://reactjs.org/) | Library for building user interfaces | -| [MDX](https://mdxjs.com/) | Markdown for the component era | -| [Algolia](https://www.algolia.com/) | Implementing powerful search | -| [Github Actions](https://github.com/features/actions) | Automations for workflow improvements | -| [Framer Motion](https://www.framer.com/motion/) | Motion library for React | -| [Context API](https://reactjs.org/docs/context.html) | React structure that enables to share data with multiple components | -| [React Hook Form](https://react-hook-form.com) | Forms with easy-to-use validation | -| [Vercel KV](https://vercel.com/docs/storage/vercel-kv) | Durable Redis database | -| [SCSS](https://sass-lang.com) | CSS with superpowers | -| [CSS Modules](https://github.com/css-modules/css-modules) | Styles convention in React | -| [Zod](https://zod.dev) | TypeScript-first schema validation with static type inference | -| [Husky](https://github.comtypicode/husky) | Git hooks | -| [ESLint](https://eslint.org/) | TypeScript linting | -| [Prettier](https://prettier.io/) | Code formatter | +| Tech | Description | +| ------------------------------------------------------ | ------------------------------------------------------------- | +| [TypeScript](https://www.typescriptlang.org/) | Static type-checking programming language | +| [Next.js](https://nextjs.org/) | The React framework for production | +| [React](https://reactjs.org/) | Library for building user interfaces | +| [MDX](https://mdxjs.com/) | Markdown for the component era | +| [Algolia](https://www.algolia.com/) | Implementing powerful search | +| [Tailwind CSS](https://tailwindcss.com/) | Utility-first CSS framework | +| [Radix UI](https://www.radix-ui.com/) | Accessible and composable headless UI components | +| [Github Actions](https://github.com/features/actions) | Automations for workflow improvements | +| [Motion](https://www.motion.dev/) | Motion library for making animations | +| [React Hook Form](https://react-hook-form.com) | Forms with easy-to-use validation | +| [Vercel KV](https://vercel.com/docs/storage/vercel-kv) | Durable Redis database | +| [SCSS](https://sass-lang.com) | CSS with superpowers | +| [Zod](https://zod.dev) | TypeScript-first schema validation with static type inference | +| [Husky](https://github.comtypicode/husky) | Git hooks | +| [ESLint](https://eslint.org/) | TypeScript linting | +| [Prettier](https://prettier.io/) | Code formatter | ## Scripts diff --git a/README.md b/README.md index 98593d06..029a5622 100644 --- a/README.md +++ b/README.md @@ -12,24 +12,24 @@ Please read [CONTRIBUTING.md](https://github.com/Bartek532/zagrodzki.me/blob/mai ## Tech/framework used 🧰 -| Tech | Description | -| --------------------------------------------------------- | ------------------------------------------------------------------- | -| [TypeScript](https://www.typescriptlang.org/) | Static type-checking programming language | -| [Next.js](https://nextjs.org/) | The React framework for production | -| [React](https://reactjs.org/) | Library for building user interfaces | -| [MDX](https://mdxjs.com/) | Markdown for the component era | -| [Algolia](https://www.algolia.com/) | Implementing powerful search | -| [Github Actions](https://github.com/features/actions) | Automations for workflow improvements | -| [Framer Motion](https://www.framer.com/motion/) | Motion library for React | -| [Context API](https://reactjs.org/docs/context.html) | React structure that enables to share data with multiple components | -| [React Hook Form](https://react-hook-form.com) | Forms with easy-to-use validation | -| [Vercel KV](https://vercel.com/docs/storage/vercel-kv) | Durable Redis database | -| [SCSS](https://sass-lang.com) | CSS with superpowers | -| [CSS Modules](https://github.com/css-modules/css-modules) | Styles convention in React | -| [Zod](https://zod.dev) | TypeScript-first schema validation with static type inference | -| [Husky](https://github.comtypicode/husky) | Git hooks | -| [ESLint](https://eslint.org/) | TypeScript linting | -| [Prettier](https://prettier.io/) | Code formatter | +| Tech | Description | +| ------------------------------------------------------ | ------------------------------------------------------------- | +| [TypeScript](https://www.typescriptlang.org/) | Static type-checking programming language | +| [Next.js](https://nextjs.org/) | The React framework for production | +| [React](https://reactjs.org/) | Library for building user interfaces | +| [MDX](https://mdxjs.com/) | Markdown for the component era | +| [Algolia](https://www.algolia.com/) | Implementing powerful search | +| [Tailwind CSS](https://tailwindcss.com/) | Utility-first CSS framework | +| [Radix UI](https://www.radix-ui.com/) | Accessible and composable headless UI components | +| [Github Actions](https://github.com/features/actions) | Automations for workflow improvements | +| [Motion](https://www.motion.dev/) | Motion library for making animations | +| [React Hook Form](https://react-hook-form.com) | Forms with easy-to-use validation | +| [Vercel KV](https://vercel.com/docs/storage/vercel-kv) | Durable Redis database | +| [SCSS](https://sass-lang.com) | CSS with superpowers | +| [Zod](https://zod.dev) | TypeScript-first schema validation with static type inference | +| [Husky](https://github.comtypicode/husky) | Git hooks | +| [ESLint](https://eslint.org/) | TypeScript linting | +| [Prettier](https://prettier.io/) | Code formatter | ## Performance 💨 diff --git a/app/about/page.tsx b/app/about/page.tsx index 7f2f9ae9..95acc61c 100644 --- a/app/about/page.tsx +++ b/app/about/page.tsx @@ -1,8 +1,13 @@ -import { About } from "components/about/about"; -import { Hero } from "components/common/hero/Hero"; -import { getMetadata } from "lib/metadata"; +import { Content } from "@/components/about/content"; +import { Education } from "@/components/about/education"; +import { Facts } from "@/components/about/facts"; +import { Hero } from "@/components/about/hero"; +import { Recommendations } from "@/components/about/recommendation"; +import { Skills } from "@/components/about/skills"; +import { GitHubActivity } from "@/components/home/github-activity"; +import { getMetadata } from "@/lib/metadata"; -const description = "Want to know more about me? You've come to the right place 🎓"; +const description = "I'm a Software Engineer not afraid of any technology 🎓"; export const metadata = getMetadata({ title: "About", @@ -13,8 +18,13 @@ export const metadata = getMetadata({ const AboutPage = () => ( <> - - + + + + + + + ); diff --git a/app/blog/[slug]/page.tsx b/app/blog/[slug]/page.tsx index 749fbb9b..c1aae22d 100644 --- a/app/blog/[slug]/page.tsx +++ b/app/blog/[slug]/page.tsx @@ -1,14 +1,16 @@ -import { Article, WithContext } from "schema-dts"; +import { FeaturedPosts } from "@/components/blog/featured-posts"; +import { Resource } from "@/components/resource/resource"; +import { getMetadata } from "@/lib/metadata"; +import { getNewestPosts, getPostBySlug, getPostsPaths } from "@/lib/posts"; +import { SITE_TITLE } from "@/utils/consts"; -import { FeaturedPosts } from "components/blog/featured/FeaturedPosts"; -import { Resource } from "components/resource/Resource"; -import { getMetadata } from "lib/metadata"; -import { getNewestPosts, getPostBySlug, getPostsPaths } from "lib/posts"; -import { type MetadataParams } from "types"; -import { SITE_TITLE } from "utils/consts"; +import type { MetadataParams } from "@/types"; +import type { Article, WithContext } from "schema-dts"; + +export async function generateMetadata({ params }: MetadataParams) { + const { slug } = await params; + const { frontmatter } = getPostBySlug(slug); -export async function generateMetadata({ params: { slug } }: MetadataParams) { - const { frontmatter } = await getPostBySlug(slug); return getMetadata({ title: frontmatter.title, description: frontmatter.excerpt, @@ -24,11 +26,12 @@ export function generateStaticParams() { return paths.map((slug) => ({ slug })); } -const PostPage = async ({ params: { slug } }: MetadataParams) => { +const PostPage = async ({ params }: MetadataParams) => { + const { slug } = await params; const featuredPosts = getNewestPosts() .filter((post) => post.slug !== slug) .slice(0, 3); - const { transformedMdx, frontmatter } = await getPostBySlug(slug); + const { content, frontmatter } = getPostBySlug(slug); const jsonLd: WithContext
= { "@context": "https://schema.org", @@ -43,7 +46,7 @@ const PostPage = async ({ params: { slug } }: MetadataParams) => { return ( <> - + {/* Needed to add JSON-LD to the page */}