fix: layout improvements

This commit is contained in:
Vasily Zubarev
2025-04-04 13:36:03 +02:00
parent 1d53434f94
commit bd6cd2c25c
4 changed files with 60 additions and 19 deletions

View File

@@ -131,7 +131,6 @@ services:
ports: ports:
- "7331:7331" - "7331:7331"
environment: environment:
- NODE_ENV=production
- SELF_HOSTED_MODE=true - SELF_HOSTED_MODE=true
- UPLOAD_PATH=/app/data/uploads - UPLOAD_PATH=/app/data/uploads
- DATABASE_URL=postgresql://postgres:postgres@localhost:5432/taxhacker - DATABASE_URL=postgresql://postgres:postgres@localhost:5432/taxhacker
@@ -146,7 +145,7 @@ Configure TaxHacker to suit your needs with these environment variables:
| Variable | Required | Description | Example | | Variable | Required | Description | Example |
|----------|----------|-------------|---------| |----------|----------|-------------|---------|
| `PORT` | No | Port to run the server on | `7331` | | `PORT` | No | Port to run the app on | `7331` (default) |
| `UPLOAD_PATH` | Yes | Local directory for uploading files | `./data/uploads` | | `UPLOAD_PATH` | Yes | Local directory for uploading files | `./data/uploads` |
| `DATABASE_URL` | Yes | PostgreSQL connection string | `postgresql://user@localhost:5432/taxhacker` | | `DATABASE_URL` | Yes | PostgreSQL connection string | `postgresql://user@localhost:5432/taxhacker` |
| `SELF_HOSTED_MODE` | No | Set it to "true" if you're self-hosting the app: it enables auto-login, custom API keys, and more | `false` | | `SELF_HOSTED_MODE` | No | Set it to "true" if you're self-hosting the app: it enables auto-login, custom API keys, and more | `false` |

View File

@@ -29,6 +29,11 @@ export async function analyzeFileAction(
return { success: false, error: "File not found or does not belong to the user" } return { success: false, error: "File not found or does not belong to the user" }
} }
const apiKey = settings.openai_api_key || config.ai.openaiApiKey || ""
if (!apiKey) {
return { success: false, error: "OpenAI API key is not set" }
}
let attachments: AnalyzeAttachment[] = [] let attachments: AnalyzeAttachment[] = []
try { try {
attachments = await loadAttachmentsForAI(user, file) attachments = await loadAttachmentsForAI(user, file)
@@ -46,12 +51,7 @@ export async function analyzeFileAction(
const schema = fieldsToJsonSchema(fields) const schema = fieldsToJsonSchema(fields)
const results = await analyzeTransaction( const results = await analyzeTransaction(prompt, schema, attachments, apiKey)
prompt,
schema,
attachments,
settings.openai_api_key || config.ai.openaiApiKey
)
console.log("Analysis results:", results) console.log("Analysis results:", results)

View File

@@ -14,10 +14,32 @@ export const metadata: Metadata = {
apple: "/apple-touch-icon.png", apple: "/apple-touch-icon.png",
}, },
manifest: "/site.webmanifest", manifest: "/site.webmanifest",
metadataBase: new URL(config.app.baseURL),
openGraph: {
type: "website",
locale: "en_US",
url: config.app.baseURL,
title: config.app.title,
description: config.app.description,
siteName: config.app.title,
},
twitter: {
card: "summary_large_image",
title: config.app.title,
description: config.app.description,
},
robots: {
index: true,
follow: true,
},
} }
export const viewport: Viewport = { export const viewport: Viewport = {
themeColor: "#ffffff", themeColor: "#ffffff",
width: "device-width",
initialScale: 1,
maximumScale: 1,
userScalable: false,
} }
export default async function RootLayout({ children }: { children: React.ReactNode }) { export default async function RootLayout({ children }: { children: React.ReactNode }) {
@@ -25,8 +47,9 @@ export default async function RootLayout({ children }: { children: React.ReactNo
<html lang="en"> <html lang="en">
<head> <head>
<meta name="theme-color" content="#ffffff" /> <meta name="theme-color" content="#ffffff" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
</head> </head>
<body>{children}</body> <body className="min-h-screen bg-white antialiased">{children}</body>
</html> </html>
) )
} }

View File

@@ -1,31 +1,50 @@
import { z } from "zod"
const envSchema = z.object({
BASE_URL: z.string().url().default("http://localhost:7331"),
PORT: z.string().default("7331"),
SELF_HOSTED_MODE: z.enum(["true", "false"]).default("false"),
OPENAI_API_KEY: z.string().optional(),
BETTER_AUTH_SECRET: z
.string()
.min(16, "Auth secret must be at least 16 characters")
.default("please-set-your-key-here"),
DISABLE_SIGNUP: z.enum(["true", "false"]).default("false"),
RESEND_API_KEY: z.string().default("please-set-your-resend-api-key-here"),
RESEND_FROM_EMAIL: z.string().default("TaxHacker <user@localhost>"),
RESEND_AUDIENCE_ID: z.string().default(""),
})
const env = envSchema.parse(process.env)
const config = { const config = {
app: { app: {
title: "TaxHacker", title: "TaxHacker",
description: "Your personal AI accountant", description: "Your personal AI helper for taxes",
version: process.env.npm_package_version || "0.0.1", version: process.env.npm_package_version || "0.0.1",
baseURL: process.env.BASE_URL || "http://localhost:" + process.env.PORT, baseURL: env.BASE_URL || `http://localhost:${env.PORT || "7331"}`,
}, },
upload: { upload: {
acceptedMimeTypes: "image/*,.pdf,.doc,.docx,.xls,.xlsx", acceptedMimeTypes: "image/*,.pdf,.doc,.docx,.xls,.xlsx",
}, },
selfHosted: { selfHosted: {
isEnabled: process.env.SELF_HOSTED_MODE === "true", isEnabled: env.SELF_HOSTED_MODE === "true",
redirectUrl: "/self-hosted/redirect", redirectUrl: "/self-hosted/redirect",
welcomeUrl: "/self-hosted", welcomeUrl: "/self-hosted",
}, },
ai: { ai: {
openaiApiKey: process.env.OPENAI_API_KEY || "", openaiApiKey: env.OPENAI_API_KEY,
}, },
auth: { auth: {
secret: process.env.BETTER_AUTH_SECRET || "please-set-secret", secret: env.BETTER_AUTH_SECRET,
loginUrl: "/enter", loginUrl: "/enter",
disableSignup: process.env.DISABLE_SIGNUP === "true" || process.env.SELF_HOSTED_MODE === "true", disableSignup: env.DISABLE_SIGNUP === "true" || env.SELF_HOSTED_MODE === "true",
}, },
email: { email: {
apiKey: process.env.RESEND_API_KEY || "please-set-api-key", apiKey: env.RESEND_API_KEY,
from: process.env.RESEND_FROM_EMAIL || "user@localhost", from: env.RESEND_FROM_EMAIL,
audienceId: process.env.RESEND_AUDIENCE_ID || "", audienceId: env.RESEND_AUDIENCE_ID,
}, },
} } as const
export default config export default config