diff --git a/.eslintrc.cjs b/.eslintrc.cjs
deleted file mode 100644
index 38a7ddc..0000000
--- a/.eslintrc.cjs
+++ /dev/null
@@ -1,53 +0,0 @@
-/** @type {import('eslint').Linter.Config} */
-const config = {
- parser: '@typescript-eslint/parser',
- parserOptions: {
- project: true,
- },
- plugins: ['@typescript-eslint', 'drizzle'],
- extends: [
- 'next/core-web-vitals',
- 'plugin:@typescript-eslint/recommended-type-checked',
- 'plugin:@typescript-eslint/stylistic-type-checked',
- 'prettier',
- ],
- rules: {
- '@typescript-eslint/array-type': 'off',
- '@typescript-eslint/consistent-type-definitions': 'off',
- '@typescript-eslint/consistent-type-imports': [
- 'warn',
- {
- prefer: 'type-imports',
- fixStyle: 'inline-type-imports',
- },
- ],
- '@typescript-eslint/no-unused-vars': [
- 'warn',
- {
- argsIgnorePattern: '^_',
- },
- ],
- '@typescript-eslint/require-await': 'off',
- '@typescript-eslint/no-misused-promises': [
- 'error',
- {
- checksVoidReturn: {
- attributes: false,
- },
- },
- ],
- 'drizzle/enforce-delete-with-where': [
- 'error',
- {
- drizzleObjectName: ['db', 'ctx.db'],
- },
- ],
- 'drizzle/enforce-update-with-where': [
- 'error',
- {
- drizzleObjectName: ['db', 'ctx.db'],
- },
- ],
- },
-};
-module.exports = config;
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 1fd86be..435dc44 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -1,13 +1,17 @@
name: Lint
-on: push
+on:
+ push:
+
jobs:
lint:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: oven-sh/setup-bun@v1
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Setup Biome
+ uses: biomejs/setup-biome@v2
with:
- bun-version: 1.1.12
- - run: bun install
- - run: bun lint
+ version: latest
+ - name: Run Biome
+ run: biome ci .
diff --git a/.husky/_/pre-commit b/.husky/_/pre-commit
new file mode 100755
index 0000000..3fbf5f9
--- /dev/null
+++ b/.husky/_/pre-commit
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+if [ "$LEFTHOOK_VERBOSE" = "1" -o "$LEFTHOOK_VERBOSE" = "true" ]; then
+ set -x
+fi
+
+if [ "$LEFTHOOK" = "0" ]; then
+ exit 0
+fi
+
+call_lefthook()
+{
+ if test -n "$LEFTHOOK_BIN"
+ then
+ "$LEFTHOOK_BIN" "$@"
+ elif lefthook -h >/dev/null 2>&1
+ then
+ lefthook "$@"
+ else
+ dir="$(git rev-parse --show-toplevel)"
+ osArch=$(uname | tr '[:upper:]' '[:lower:]')
+ cpuArch=$(uname -m | sed 's/aarch64/arm64/;s/x86_64/x64/')
+ if test -f "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook"
+ then
+ "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook" "$@"
+ elif test -f "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook"
+ then
+ "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook" "$@"
+ elif test -f "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook"
+ then
+ "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook" "$@"
+ elif test -f "$dir/node_modules/lefthook/bin/index.js"
+ then
+ "$dir/node_modules/lefthook/bin/index.js" "$@"
+
+ elif bundle exec lefthook -h >/dev/null 2>&1
+ then
+ bundle exec lefthook "$@"
+ elif yarn lefthook -h >/dev/null 2>&1
+ then
+ yarn lefthook "$@"
+ elif pnpm lefthook -h >/dev/null 2>&1
+ then
+ pnpm lefthook "$@"
+ elif swift package plugin lefthook >/dev/null 2>&1
+ then
+ swift package --disable-sandbox plugin lefthook "$@"
+ elif command -v mint >/dev/null 2>&1
+ then
+ mint run csjones/lefthook-plugin "$@"
+ elif command -v npx >/dev/null 2>&1
+ then
+ npx lefthook "$@"
+ else
+ echo "Can't find lefthook in PATH"
+ fi
+ fi
+}
+
+call_lefthook run "pre-commit" "$@"
diff --git a/.husky/_/prepare-commit-msg b/.husky/_/prepare-commit-msg
new file mode 100755
index 0000000..e8e8dda
--- /dev/null
+++ b/.husky/_/prepare-commit-msg
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+if [ "$LEFTHOOK_VERBOSE" = "1" -o "$LEFTHOOK_VERBOSE" = "true" ]; then
+ set -x
+fi
+
+if [ "$LEFTHOOK" = "0" ]; then
+ exit 0
+fi
+
+call_lefthook()
+{
+ if test -n "$LEFTHOOK_BIN"
+ then
+ "$LEFTHOOK_BIN" "$@"
+ elif lefthook -h >/dev/null 2>&1
+ then
+ lefthook "$@"
+ else
+ dir="$(git rev-parse --show-toplevel)"
+ osArch=$(uname | tr '[:upper:]' '[:lower:]')
+ cpuArch=$(uname -m | sed 's/aarch64/arm64/;s/x86_64/x64/')
+ if test -f "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook"
+ then
+ "$dir/node_modules/lefthook-${osArch}-${cpuArch}/bin/lefthook" "$@"
+ elif test -f "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook"
+ then
+ "$dir/node_modules/@evilmartians/lefthook/bin/lefthook-${osArch}-${cpuArch}/lefthook" "$@"
+ elif test -f "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook"
+ then
+ "$dir/node_modules/@evilmartians/lefthook-installer/bin/lefthook" "$@"
+ elif test -f "$dir/node_modules/lefthook/bin/index.js"
+ then
+ "$dir/node_modules/lefthook/bin/index.js" "$@"
+
+ elif bundle exec lefthook -h >/dev/null 2>&1
+ then
+ bundle exec lefthook "$@"
+ elif yarn lefthook -h >/dev/null 2>&1
+ then
+ yarn lefthook "$@"
+ elif pnpm lefthook -h >/dev/null 2>&1
+ then
+ pnpm lefthook "$@"
+ elif swift package plugin lefthook >/dev/null 2>&1
+ then
+ swift package --disable-sandbox plugin lefthook "$@"
+ elif command -v mint >/dev/null 2>&1
+ then
+ mint run csjones/lefthook-plugin "$@"
+ elif command -v npx >/dev/null 2>&1
+ then
+ npx lefthook "$@"
+ else
+ echo "Can't find lefthook in PATH"
+ fi
+ fi
+}
+
+call_lefthook run "prepare-commit-msg" "$@"
diff --git a/.husky/pre-commit b/.husky/pre-commit
deleted file mode 100755
index ea5a55b..0000000
--- a/.husky/pre-commit
+++ /dev/null
@@ -1 +0,0 @@
-bunx lint-staged
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
deleted file mode 100644
index a294968..0000000
--- a/.vscode/extensions.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "recommendations": [
- "dbaeumer.vscode-eslint",
- "bradlc.vscode-tailwindcss",
- "lokalise.i18n-ally",
- "vivaxy.vscode-conventional-commits",
- "oven.bun-vscode"
- ]
-}
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index e8f66e4..0000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "files.associations": {
- "*.css": "tailwindcss"
- },
- "tailwindCSS.experimental.classRegex": [
- ["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
- ["cx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
- ],
- "i18n-ally.localesPaths": ["messages"],
- "i18n-ally.keystyle": "nested"
-}
diff --git a/biome.json b/biome.json
new file mode 100644
index 0000000..c477d54
--- /dev/null
+++ b/biome.json
@@ -0,0 +1,34 @@
+{
+ "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
+ "formatter": {
+ "enabled": true,
+ "indentStyle": "space"
+ },
+ "organizeImports": {
+ "enabled": true
+ },
+ "linter": {
+ "enabled": true,
+ "rules": {
+ "recommended": true,
+ "nursery": {
+ "useSortedClasses": "warn"
+ }
+ }
+ },
+ "javascript": {
+ "formatter": {
+ "quoteStyle": "single",
+ "jsxQuoteStyle": "single"
+ }
+ },
+ "vcs": {
+ "enabled": true,
+ "clientKind": "git",
+ "useIgnoreFile": true,
+ "defaultBranch": "main"
+ },
+ "files": {
+ "ignore": [".next"]
+ }
+}
diff --git a/lefthook.yml b/lefthook.yml
new file mode 100644
index 0000000..cf9b74e
--- /dev/null
+++ b/lefthook.yml
@@ -0,0 +1,6 @@
+pre-commit:
+ commands:
+ check:
+ glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
+ stage_fixed: true
+ run: bunx @biomejs/biome check --write --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files}
diff --git a/package.json b/package.json
index a51ace6..2bea4f7 100644
--- a/package.json
+++ b/package.json
@@ -4,20 +4,14 @@
"private": true,
"type": "module",
"scripts": {
- "prepare": "husky",
+ "prepare": "lefthook install",
"postbuild": "next-sitemap",
"prebuild": "next telemetry disable",
"build": "next build",
"dev": "next dev --turbo",
- "lint": "next lint && prettier --write .",
+ "lint": "biome check --write --unsafe",
"start": "next start"
},
- "lint-staged": {
- "*.{js,ts,tsx}": [
- "eslint --fix",
- "prettier --write"
- ]
- },
"dependencies": {
"@libsql/client": "^0.6.2",
"@radix-ui/react-avatar": "^1.1.0",
@@ -55,22 +49,13 @@
"zod": "^3.23.8"
},
"devDependencies": {
- "@trivago/prettier-plugin-sort-imports": "^4.3.0",
- "@types/eslint": "^8.56.10",
+ "@biomejs/biome": "1.8.3",
"@types/node": "^20.14.8",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
- "@typescript-eslint/eslint-plugin": "^7.13.1",
- "@typescript-eslint/parser": "^7.13.1",
"drizzle-kit": "^0.22.7",
- "eslint": "^8.57.0",
- "eslint-config-next": "^14.2.4",
- "eslint-config-prettier": "^9.1.0",
- "eslint-plugin-drizzle": "^0.2.3",
- "lint-staged": "^15.2.7",
+ "lefthook": "^1.7.14",
"postcss": "^8.4.38",
- "prettier": "^3.3.2",
- "prettier-plugin-tailwindcss": "^0.6.5",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss": "^3.4.4",
"tailwindcss-animate": "^1.0.7",
diff --git a/prettier.config.js b/prettier.config.js
deleted file mode 100644
index c34bef6..0000000
--- a/prettier.config.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions & import("@trivago/prettier-plugin-sort-imports").PluginConfig} */
-const config = {
- semi: true,
- singleQuote: true,
- tabWidth: 2,
- useTabs: false,
- jsxSingleQuote: true,
- importOrder: [
- '^[./]',
- '^@/(lib|styles)/(.*)$',
- '^@/hooks/(.*)$',
- '^@/components/(.*)$',
- ],
- importOrderSeparation: true,
- importOrderSortSpecifiers: true,
- tailwindFunctions: ['cx', 'cva'],
- plugins: [
- '@trivago/prettier-plugin-sort-imports',
- 'prettier-plugin-tailwindcss',
- ],
-};
-
-export default config;
diff --git a/src/app/[locale]/(default)/news/(header)/page.tsx b/src/app/[locale]/(default)/news/(header)/page.tsx
index 44255c9..30444ab 100644
--- a/src/app/[locale]/(default)/news/(header)/page.tsx
+++ b/src/app/[locale]/(default)/news/(header)/page.tsx
@@ -1,7 +1,7 @@
import { articleMockData as articleData } from '@/mock-data/article';
import { useTranslations } from 'next-intl';
import { getTranslations, unstable_setRequestLocale } from 'next-intl/server';
-import { createSearchParamsCache, parseAsInteger } from 'nuqs/parsers';
+import { createSearchParamsCache, parseAsInteger } from 'nuqs/server';
import { Suspense } from 'react';
import { PaginationCarousel } from '@/components/layout/PaginationCarousel';
diff --git a/src/app/[locale]/(default)/news/[article]/page.tsx b/src/app/[locale]/(default)/news/[article]/page.tsx
index 0b888b3..c4f6e37 100644
--- a/src/app/[locale]/(default)/news/[article]/page.tsx
+++ b/src/app/[locale]/(default)/news/[article]/page.tsx
@@ -46,12 +46,16 @@ export default function ArticlePage({
return notFound();
}
- const { minutes } = readingTime(article.content!);
- const author = authorData[0]!;
+ const { minutes } = readingTime(article.content as string); // assert because its a mock data file
+ const author = authorData[0] as {
+ name: string;
+ photoUrl: string;
+ initials: string;
+ }; // same as above
return (