Fix build: resolve Turbopack client bundle and font issues

- Move EXPENSE_CATEGORIES to ~/lib/expense-categories.ts to break
  server router import chain from client component
- Use inline import() types in trpc/react.tsx to prevent Turbopack
  from including server modules (pg, db) in the client bundle
- Replace next/font/google with system font stacks to fix build
  failures in environments without Google Fonts access

https://claude.ai/code/session_012sqEgNQpx676isepeoX4Mi
This commit is contained in:
Claude
2026-04-05 03:00:25 +00:00
parent e6b79ce2c2
commit 4c0eae4b11
6 changed files with 21 additions and 39 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ import { NumberInput } from "~/components/ui/number-input";
import { toast } from "sonner";
import { Plus, Pencil, Trash2, Receipt } from "lucide-react";
import { formatCurrency, SUPPORTED_CURRENCIES } from "~/lib/currency";
import { EXPENSE_CATEGORIES } from "~/server/api/routers/expenses";
import { EXPENSE_CATEGORIES } from "~/lib/expense-categories";
interface ExpenseFormData {
date: Date;
-20
View File
@@ -1,7 +1,6 @@
import "~/styles/globals.css";
import { type Metadata } from "next";
import { Inter, Playfair_Display, Geist_Mono } from "next/font/google";
import { TRPCReactProvider } from "~/trpc/react";
import { Toaster } from "~/components/ui/sonner";
@@ -17,24 +16,6 @@ export const metadata: Metadata = {
icons: [{ rel: "icon", url: "/favicon.ico" }],
};
const inter = Inter({
subsets: ["latin"],
variable: "--font-sans",
display: "swap",
});
const playfair = Playfair_Display({
subsets: ["latin"],
variable: "--font-heading",
display: "swap",
});
const geistMono = Geist_Mono({
subsets: ["latin"],
variable: "--font-geist-mono",
display: "swap",
});
export default function RootLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
@@ -42,7 +23,6 @@ export default function RootLayout({
<html
suppressHydrationWarning
lang="en"
className={`${inter.variable} ${playfair.variable} ${geistMono.variable}`}
>
<body className="bg-background text-foreground relative min-h-screen overflow-x-hidden font-sans antialiased">
<div className="fixed inset-0 -z-10 overflow-hidden pointer-events-none flex items-center justify-center">
+11
View File
@@ -0,0 +1,11 @@
export const EXPENSE_CATEGORIES = [
"Travel",
"Meals & Entertainment",
"Software & Subscriptions",
"Hardware & Equipment",
"Office Supplies",
"Marketing",
"Professional Services",
"Utilities",
"Other",
] as const;
+2 -11
View File
@@ -3,18 +3,9 @@ import { eq, and, desc } from "drizzle-orm";
import { createTRPCRouter, protectedProcedure } from "../trpc";
import { expenses, clients, businesses, invoices } from "~/server/db/schema";
import { TRPCError } from "@trpc/server";
import { EXPENSE_CATEGORIES } from "~/lib/expense-categories";
export const EXPENSE_CATEGORIES = [
"Travel",
"Meals & Entertainment",
"Software & Subscriptions",
"Hardware & Equipment",
"Office Supplies",
"Marketing",
"Professional Services",
"Utilities",
"Other",
] as const;
export { EXPENSE_CATEGORIES };
const createExpenseSchema = z.object({
date: z.date(),
+3 -3
View File
@@ -84,9 +84,9 @@
--color-input: hsl(var(--input));
--color-ring: hsl(var(--ring));
--font-sans: var(--font-sans), sans-serif;
--font-heading: var(--font-heading), serif;
--font-mono: var(--font-geist-mono), monospace;
--font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
--font-heading: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
+4 -4
View File
@@ -7,7 +7,6 @@ import { type inferRouterInputs, type inferRouterOutputs } from "@trpc/server";
import { useState } from "react";
import SuperJSON from "superjson";
import { type AppRouter } from "~/server/api/root";
import { createQueryClient } from "./query-client";
let clientQueryClientSingleton: QueryClient | undefined = undefined;
@@ -22,21 +21,22 @@ const getQueryClient = () => {
return clientQueryClientSingleton;
};
export const api = createTRPCReact<AppRouter>();
// Use inline import() type to avoid pulling server modules into the client bundle
export const api = createTRPCReact<import("~/server/api/root").AppRouter>();
/**
* Inference helper for inputs.
*
* @example type HelloInput = RouterInputs['example']['hello']
*/
export type RouterInputs = inferRouterInputs<AppRouter>;
export type RouterInputs = inferRouterInputs<import("~/server/api/root").AppRouter>;
/**
* Inference helper for outputs.
*
* @example type HelloOutput = RouterOutputs['example']['hello']
*/
export type RouterOutputs = inferRouterOutputs<AppRouter>;
export type RouterOutputs = inferRouterOutputs<import("~/server/api/root").AppRouter>;
export function TRPCReactProvider(props: { children: React.ReactNode }) {
const queryClient = getQueryClient();