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 (
);
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}"],