diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 4f6f59e..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,84 +0,0 @@ -/** - * This is intended to be a basic starting point for linting in your app. - * It relies on recommended configs out of the box for simplicity, but you can - * and should modify this configuration to best suit your team's needs. - */ - -/** @type {import('eslint').Linter.Config} */ -module.exports = { - root: true, - parserOptions: { - ecmaVersion: "latest", - sourceType: "module", - ecmaFeatures: { - jsx: true, - }, - }, - env: { - browser: true, - commonjs: true, - es6: true, - }, - ignorePatterns: ["!**/.server", "!**/.client"], - - // Base config - extends: ["eslint:recommended"], - - overrides: [ - // React - { - files: ["**/*.{js,jsx,ts,tsx}"], - plugins: ["react", "jsx-a11y"], - extends: [ - "plugin:react/recommended", - "plugin:react/jsx-runtime", - "plugin:react-hooks/recommended", - "plugin:jsx-a11y/recommended", - ], - settings: { - react: { - version: "detect", - }, - formComponents: ["Form"], - linkComponents: [ - { name: "Link", linkAttribute: "to" }, - { name: "NavLink", linkAttribute: "to" }, - ], - "import/resolver": { - typescript: {}, - }, - }, - }, - - // Typescript - { - files: ["**/*.{ts,tsx}"], - plugins: ["@typescript-eslint", "import"], - parser: "@typescript-eslint/parser", - settings: { - "import/internal-regex": "^~/", - "import/resolver": { - node: { - extensions: [".ts", ".tsx"], - }, - typescript: { - alwaysTryTypes: true, - }, - }, - }, - extends: [ - "plugin:@typescript-eslint/recommended", - "plugin:import/recommended", - "plugin:import/typescript", - ], - }, - - // Node - { - files: [".eslintrc.cjs"], - env: { - node: true, - }, - }, - ], -}; diff --git a/.github/workflow/code_quality.yaml b/.github/workflow/code_quality.yaml new file mode 100644 index 0000000..9909b84 --- /dev/null +++ b/.github/workflow/code_quality.yaml @@ -0,0 +1,18 @@ +name: Code quality + +on: + push: + pull_request: + +jobs: + code_quality: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Biome + uses: biomejs/setup-biome@v2 + with: + version: latest + - name: Run Biome + run: biome ci . \ No newline at end of file diff --git a/app/components/EmptyState.tsx b/app/components/EmptyState.tsx deleted file mode 100644 index 1ba5bb7..0000000 --- a/app/components/EmptyState.tsx +++ /dev/null @@ -1,10 +0,0 @@ -export function EmptyState() { - return ( -
-
- I haven't post anything yet! So here's a pic of my cat -
- -
- ); -} diff --git a/app/components/Notbyai.tsx b/app/components/Notbyai.tsx index 1587252..15657db 100644 --- a/app/components/Notbyai.tsx +++ b/app/components/Notbyai.tsx @@ -1,8 +1,11 @@ export function Notbyai() { return (
- - + + nobyai logo
); diff --git a/app/components/PostPreview.tsx b/app/components/PostPreview.tsx index afd03c3..ddf9735 100644 --- a/app/components/PostPreview.tsx +++ b/app/components/PostPreview.tsx @@ -1,4 +1,4 @@ -import { SerializeFrom } from "@remix-run/node"; +import type { SerializeFrom } from "@remix-run/node"; import { Link } from "@remix-run/react"; import { useFormattedDate } from "~/hooks"; import type { Post } from "~/utils/posts.server"; diff --git a/app/root.tsx b/app/root.tsx index eb4de43..3c887ff 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -45,9 +45,10 @@ export default function App() { /> + /> diff --git a/app/routes/blog._index.tsx b/app/routes/blog._index.tsx index 22ef461..6938314 100644 --- a/app/routes/blog._index.tsx +++ b/app/routes/blog._index.tsx @@ -1,5 +1,4 @@ import { useLoaderData } from "@remix-run/react"; -import { EmptyState } from "~/components/EmptyState"; import { PostPreview } from "~/components/PostPreview"; import { Title } from "~/components/Title"; import { findPosts } from "~/utils/posts.server"; @@ -19,15 +18,11 @@ export default function Blog() { return ( <> Here I blog about whatever get my attention - {posts.length > 0 ? ( -
- {posts.map((post, i) => ( - - ))} -
- ) : ( - - )} +
+ {posts.map((post) => ( + + ))} +
); } diff --git a/app/tailwind.css b/app/tailwind.css index bd6213e..b5c61c9 100644 --- a/app/tailwind.css +++ b/app/tailwind.css @@ -1,3 +1,3 @@ @tailwind base; @tailwind components; -@tailwind utilities; \ No newline at end of file +@tailwind utilities; diff --git a/app/utils/posts.server.ts b/app/utils/posts.server.ts index e228247..e198e5e 100644 --- a/app/utils/posts.server.ts +++ b/app/utils/posts.server.ts @@ -1,7 +1,7 @@ import { remarkCodeHike } from "@code-hike/mdx"; -import { readdir, readFile } from "fs/promises"; import { bundleMDX } from "mdx-bundler"; -import path from "path"; +import { readdir, readFile } from "node:fs/promises"; +import path from "node:path"; type FrontMatter = { title: string; @@ -41,7 +41,7 @@ export type Post = Omit & { }; export const findPosts = async () => { - const files = await readdir(`posts`); + const files = await readdir("posts"); const posts: Post[] = []; for (const file of files.filter((file) => file.endsWith(".mdx"))) { const filePath = path.join(process.cwd(), `posts/${file}`); diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..1eefe42 --- /dev/null +++ b/biome.json @@ -0,0 +1,54 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.3/schema.json", + "files": { + "ignoreUnknown": false, + "ignore": ["node_modules", "build"] + }, + "vcs": { + "clientKind": "git", + "defaultBranch": "main", + "enabled": false, + "root": ".", + "useIgnoreFile": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "suspicious": { + "noExplicitAny": "off", + "noConfusingVoidType": "off" + }, + "security": { + "noDangerouslySetInnerHtml": "off" + } + } + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf" + }, + "organizeImports": { + "enabled": true + }, + "javascript": { + "formatter": { + "enabled": true, + "quoteStyle": "double", + "jsxQuoteStyle": "double", + "trailingCommas": "all", + "semicolons": "always", + "arrowParentheses": "always" + } + }, + "overrides": [ + { + "include": ["**/*.{ts,tsx}"], + "javascript": { + "globals": [] + } + } + ] +} diff --git a/package-lock.json b/package-lock.json index 8cf1e11..a6c69cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "remark-mdx-frontmatter": "^5.0.0" }, "devDependencies": { + "@biomejs/biome": "1.9.3", "@mdx-js/rollup": "3.0.1", "@remix-run/dev": "2.12.1", "@tailwindcss/typography": "0.5.15", @@ -665,6 +666,170 @@ "node": ">=6.9.0" } }, + "node_modules/@biomejs/biome": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.3.tgz", + "integrity": "sha512-POjAPz0APAmX33WOQFGQrwLvlu7WLV4CFJMlB12b6ZSg+2q6fYu9kZwLCOA+x83zXfcPd1RpuWOKJW0GbBwLIQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.9.3", + "@biomejs/cli-darwin-x64": "1.9.3", + "@biomejs/cli-linux-arm64": "1.9.3", + "@biomejs/cli-linux-arm64-musl": "1.9.3", + "@biomejs/cli-linux-x64": "1.9.3", + "@biomejs/cli-linux-x64-musl": "1.9.3", + "@biomejs/cli-win32-arm64": "1.9.3", + "@biomejs/cli-win32-x64": "1.9.3" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.3.tgz", + "integrity": "sha512-QZzD2XrjJDUyIZK+aR2i5DDxCJfdwiYbUKu9GzkCUJpL78uSelAHAPy7m0GuPMVtF/Uo+OKv97W3P9nuWZangQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.3.tgz", + "integrity": "sha512-vSCoIBJE0BN3SWDFuAY/tRavpUtNoqiceJ5PrU3xDfsLcm/U6N93JSM0M9OAiC/X7mPPfejtr6Yc9vSgWlEgVw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.3.tgz", + "integrity": "sha512-vJkAimD2+sVviNTbaWOGqEBy31cW0ZB52KtpVIbkuma7PlfII3tsLhFa+cwbRAcRBkobBBhqZ06hXoZAN8NODQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.3.tgz", + "integrity": "sha512-VBzyhaqqqwP3bAkkBrhVq50i3Uj9+RWuj+pYmXrMDgjS5+SKYGE56BwNw4l8hR3SmYbLSbEo15GcV043CDSk+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.3.tgz", + "integrity": "sha512-x220V4c+romd26Mu1ptU+EudMXVS4xmzKxPVb9mgnfYlN4Yx9vD5NZraSx/onJnd3Gh/y8iPUdU5CDZJKg9COA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.3.tgz", + "integrity": "sha512-TJmnOG2+NOGM72mlczEsNki9UT+XAsMFAOo8J0me/N47EJ/vkLXxf481evfHLlxMejTY6IN8SdRSiPVLv6AHlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.3.tgz", + "integrity": "sha512-lg/yZis2HdQGsycUvHWSzo9kOvnGgvtrYRgoCEwPBwwAL8/6crOp3+f47tPwI/LI1dZrhSji7PNsGKGHbwyAhw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.3.tgz", + "integrity": "sha512-cQMy2zanBkVLpmmxXdK6YePzmZx0s5Z7KEnwmrW54rcXK3myCNbQa09SwGZ8i/8sLw0H9F3X7K4rxVNGU8/D4Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, "node_modules/@code-hike/lighter": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@code-hike/lighter/-/lighter-0.7.0.tgz", diff --git a/package.json b/package.json index ac2ad20..40a840c 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,10 @@ "scripts": { "build": "remix vite:build", "dev": "remix vite:dev", - "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "remix-serve ./build/server/index.js", - "typecheck": "tsc" + "typecheck": "tsc", + "lint": "biome lint", + "format": "biome format --write" }, "dependencies": { "@code-hike/mdx": "0.9.0", @@ -25,14 +26,13 @@ "remark-mdx-frontmatter": "^5.0.0" }, "devDependencies": { + "@biomejs/biome": "1.9.3", "@mdx-js/rollup": "3.0.1", "@remix-run/dev": "2.12.1", "@tailwindcss/typography": "0.5.15", - "@types/eslint": "9.6.1", "@types/react": "18.3.8", "@types/react-dom": "18.3.0", "autoprefixer": "10.4.20", - "eslint": "9.11.0", "postcss": "8.4.47", "tailwindcss": "3.4.12", "typescript": "5.6.2", diff --git a/tailwind.config.ts b/tailwind.config.ts index 7251156..a0031ff 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,5 +1,4 @@ - -import type { Config} from "tailwindcss" +import type { Config } from "tailwindcss"; export default { content: ["./app/**/*.{ts,tsx}"],