From 4bf6db5183dd779d22ebdd52b6ee80134dbdefb2 Mon Sep 17 00:00:00 2001 From: Mao Nakamoto <41178744+catomean@users.noreply.github.com> Date: Mon, 31 Aug 2026 10:17:23 +0200 Subject: [PATCH 1/3] chore: add a formatter, matching the style this repo already writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit singleQuote=false was chosen by counting this repo's own imports, not by fleet decree. The fleet is genuinely split and the two repos that already had a .prettierrc disagreed with each other, so there was no standard to restore. Quote style does not cross repo boundaries; having a gate does. Markdown is ignored for now — prettier rewraps prose, which would bury the real diff. Co-Authored-By: Claude Opus 5 --- .prettierignore | 31 +++++++++++++++++++++++++++++++ .prettierrc | 9 +++++++++ package-lock.json | 20 ++++++++++++++++++++ package.json | 9 ++++++--- 4 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..b698663 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,31 @@ +# Build output and vendored trees — formatting these is noise. +node_modules +.next +dist +build +out +coverage +.turbo +.vercel +*.min.js +*.min.css + +# Generated during a build, so it is absent locally and present in CI — which +# makes a clean local --check no evidence at all. Contentlayer's output also +# uses import assertions, which prettier's parser rejects outright. +.contentlayer +.astro +.svelte-kit +storybook-static +test-results +playwright-report + +# Lockfiles are generated; prettier would rewrite them wholesale. +package-lock.json +pnpm-lock.yaml +yarn.lock + +# Markdown is deliberately out of scope for now. Prettier rewraps prose, which +# is where it is most opinionated and least useful, and it would bury the real +# diff. Remove this line when you want docs formatted too. +*.md diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..a2f11f0 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,9 @@ +{ + "semi": true, + "singleQuote": false, + "printWidth": 100, + "tabWidth": 2, + "trailingComma": "all", + "arrowParens": "always", + "endOfLine": "lf" +} diff --git a/package-lock.json b/package-lock.json index 44a3fbd..0a28e85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,10 +27,14 @@ "drizzle-kit": "^0.31.10", "eslint": "^9", "eslint-config-next": "^15.0.0", + "prettier": "3.9.6", "tailwindcss": "^4.0.0", "tsx": "^4.23.12", "typescript": "^5", "vitest": "^2.1.5" + }, + "engines": { + "node": ">=20" } }, "node_modules/@alloc/quick-lru": { @@ -6932,6 +6936,22 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz", + "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", diff --git a/package.json b/package.json index f055b8b..ed5ec9d 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,12 @@ "lint": "next lint", "typecheck": "tsc --noEmit", "test": "vitest run", - "verify": "npm run typecheck && npm run lint && npm run test", + "verify": "npm run format:check && npm run typecheck && npm run lint && npm run test", "db:generate": "drizzle-kit generate", "db:migrate": "tsx src/db/migrate.ts", - "db:studio": "drizzle-kit studio" + "db:studio": "drizzle-kit studio", + "format": "prettier --write .", + "format:check": "prettier --check ." }, "dependencies": { "dotenv": "^17.4.2", @@ -29,14 +31,15 @@ }, "devDependencies": { "@eslint/eslintrc": "^3", + "@tailwindcss/postcss": "^4.0.0", "@types/leaflet": "^1.9.14", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "@tailwindcss/postcss": "^4.0.0", "drizzle-kit": "^0.31.10", "eslint": "^9", "eslint-config-next": "^15.0.0", + "prettier": "3.9.6", "tailwindcss": "^4.0.0", "tsx": "^4.23.12", "typescript": "^5", From 8ddf7b4f70a3118cd60c6677f227fc6876a18f30 Mon Sep 17 00:00:00 2001 From: Mao Nakamoto <41178744+catomean@users.noreply.github.com> Date: Mon, 31 Aug 2026 10:17:32 +0200 Subject: [PATCH 2/3] style: format with prettier (10 files) Mechanical. No behaviour change. This SHA is listed in .git-blame-ignore-revs so `git blame` skips it. Co-Authored-By: Claude Opus 5 --- .github/workflows/auto-merge.yml | 4 ++-- .github/workflows/ci.yml | 2 +- drizzle/meta/0000_snapshot.json | 2 +- drizzle/meta/_journal.json | 2 +- src/app/actions.ts | 13 ++++++++++--- src/app/layout.tsx | 6 +----- src/app/new/page.tsx | 4 +++- src/app/page.tsx | 4 +++- src/app/stashes/[id]/page.tsx | 4 +++- src/lib/coordinates.test.ts | 7 ++++++- 10 files changed, 31 insertions(+), 17 deletions(-) diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index 3e97f5a..71ba922 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -18,7 +18,7 @@ name: Auto-merge on: workflow_run: - workflows: ['CI'] + workflows: ["CI"] types: [completed] # HOURLY, not */10 as in the rest of the fleet — this repo is PRIVATE, so # Actions minutes are billed. Every other repo running this sweep is public, @@ -31,7 +31,7 @@ on: # common path is workflow_run above, which fires within seconds of CI going # green. Make this repo public and */10 becomes free again. schedule: - - cron: '0 * * * *' + - cron: "0 * * * *" workflow_dispatch: {} permissions: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5cf8db8..23941a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: env: POSTGRES_PASSWORD: ci POSTGRES_DB: hamstercheek - ports: ['5432:5432'] + ports: ["5432:5432"] options: >- --health-cmd pg_isready --health-interval 5s --health-timeout 5s --health-retries 10 diff --git a/drizzle/meta/0000_snapshot.json b/drizzle/meta/0000_snapshot.json index 170ca80..f0153af 100644 --- a/drizzle/meta/0000_snapshot.json +++ b/drizzle/meta/0000_snapshot.json @@ -72,4 +72,4 @@ "schemas": {}, "tables": {} } -} \ No newline at end of file +} diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index 670757b..b5b9885 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -10,4 +10,4 @@ "breakpoints": true } ] -} \ No newline at end of file +} diff --git a/src/app/actions.ts b/src/app/actions.ts index 86e45dc..1c3424f 100644 --- a/src/app/actions.ts +++ b/src/app/actions.ts @@ -14,7 +14,10 @@ const ALLOWED_PHOTO_TYPES = new Set(["image/jpeg", "image/png", "image/webp"]); export type CreateStashState = { error?: string }; -export async function createStash(_prevState: CreateStashState, formData: FormData): Promise { +export async function createStash( + _prevState: CreateStashState, + formData: FormData, +): Promise { const name = String(formData.get("name") ?? "").trim(); const description = String(formData.get("description") ?? "").trim(); const lat = Number(formData.get("lat")); @@ -34,7 +37,8 @@ export async function createStash(_prevState: CreateStashState, formData: FormDa if (!ALLOWED_PHOTO_TYPES.has(photo.type)) { return { error: "Photo must be a JPEG, PNG, or WebP image." }; } - const extension = photo.type === "image/png" ? "png" : photo.type === "image/webp" ? "webp" : "jpg"; + const extension = + photo.type === "image/png" ? "png" : photo.type === "image/webp" ? "webp" : "jpg"; const filename = `${randomUUID()}.${extension}`; await mkdir(UPLOADS_DIR, { recursive: true }); const bytes = Buffer.from(await photo.arrayBuffer()); @@ -51,7 +55,10 @@ export async function createStash(_prevState: CreateStashState, formData: FormDa } export async function deleteStash(id: number): Promise { - const [deleted] = await db.delete(stashes).where(eq(stashes.id, id)).returning({ photoUrl: stashes.photoUrl }); + const [deleted] = await db + .delete(stashes) + .where(eq(stashes.id, id)) + .returning({ photoUrl: stashes.photoUrl }); if (deleted?.photoUrl) { await unlink(path.join(process.cwd(), "public", deleted.photoUrl)).catch(() => {}); diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 1485f84..917dd15 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -6,11 +6,7 @@ export const metadata: Metadata = { description: "Store and find your valuables, off the grid.", }; -export default function RootLayout({ - children, -}: { - children: React.ReactNode; -}) { +export default function RootLayout({ children }: { children: React.ReactNode }) { return ( {children} diff --git a/src/app/new/page.tsx b/src/app/new/page.tsx index d4802d2..1af9a50 100644 --- a/src/app/new/page.tsx +++ b/src/app/new/page.tsx @@ -58,7 +58,9 @@ export default function NewStashPage() {
Location -

Click the map to drop a pin where the box is buried or hidden.

+

+ Click the map to drop a pin where the box is buried or hidden. +

{coords ? formatCoordinates(coords) : "No location selected yet"} diff --git a/src/app/page.tsx b/src/app/page.tsx index 67f9749..d57134c 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -38,7 +38,9 @@ export default async function Home() { >

{item.name}

-

{formatCoordinates({ lat: item.lat, lng: item.lng })}

+

+ {formatCoordinates({ lat: item.lat, lng: item.lng })} +

{item.photoUrl && ( diff --git a/src/app/stashes/[id]/page.tsx b/src/app/stashes/[id]/page.tsx index 2c77ed1..83f222e 100644 --- a/src/app/stashes/[id]/page.tsx +++ b/src/app/stashes/[id]/page.tsx @@ -30,7 +30,9 @@ export default async function StashDetailPage({ params }: { params: Promise<{ id

{stash.name}

-

{formatCoordinates({ lat: stash.lat, lng: stash.lng })}

+

+ {formatCoordinates({ lat: stash.lat, lng: stash.lng })} +

diff --git a/src/lib/coordinates.test.ts b/src/lib/coordinates.test.ts index e6e5065..6d98db3 100644 --- a/src/lib/coordinates.test.ts +++ b/src/lib/coordinates.test.ts @@ -1,5 +1,10 @@ import { describe, expect, it } from "vitest"; -import { formatCoordinates, isValidCoordinates, isValidLatitude, isValidLongitude } from "./coordinates"; +import { + formatCoordinates, + isValidCoordinates, + isValidLatitude, + isValidLongitude, +} from "./coordinates"; describe("isValidLatitude", () => { it("accepts values within -90..90", () => { From 2a796f2bc6ab7ef3241932db66275e6f7c75027f Mon Sep 17 00:00:00 2001 From: Mao Nakamoto <41178744+catomean@users.noreply.github.com> Date: Mon, 31 Aug 2026 10:17:33 +0200 Subject: [PATCH 3/3] chore: teach git blame to skip the reformat Co-Authored-By: Claude Opus 5 --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..1ee211d --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Bulk reformats. `git config blame.ignoreRevsFile .git-blame-ignore-revs` +8ddf7b4f70a3118cd60c6677f227fc6876a18f30 # prettier, 10 files