diff --git a/.env.example b/.env.example
deleted file mode 100644
index cd6a7d00..00000000
--- a/.env.example
+++ /dev/null
@@ -1,81 +0,0 @@
-# Environment
-NODE_ENV=development
-
-# Ports
-PORT=3000
-
-# URLs
-# These URLs must reference a publicly accessible domain or IP address, not a docker container ID (depending on your compose setup)
-PUBLIC_URL=http://localhost:3000
-STORAGE_URL=http://localhost:9000/default # default is the bucket name specified in the STORAGE_BUCKET variable
-
-# Database (Prisma/PostgreSQL)
-# This can be swapped out to use any other database, like MySQL
-# Note: This is used only in the compose.yml file
-POSTGRES_PORT=5432
-POSTGRES_DB=postgres
-POSTGRES_USER=postgres
-POSTGRES_PASSWORD=postgres
-
-# Database (Prisma/PostgreSQL)
-DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres?schema=public
-
-# Authentication Secrets
-# generated with `openssl rand -base64 64`
-ACCESS_TOKEN_SECRET=access_token_secret
-REFRESH_TOKEN_SECRET=refresh_token_secret
-
-# Chrome Browser (for printing)
-# generated with `openssl rand -hex 32`
-CHROME_PORT=8080
-CHROME_TOKEN=chrome_token
-CHROME_URL=ws://localhost:8080
-# Launch puppeteer with flag to ignore https errors
-# CHROME_IGNORE_HTTPS_ERRORS=true
-
-# Mail Server (for e-mails)
-# For testing, you can use https://ethereal.email/create
-MAIL_FROM=noreply@localhost
-# SMTP_URL=smtp://username:password@smtp.ethereal.email:587
-
-# Storage
-STORAGE_ENDPOINT=localhost
-STORAGE_PORT=9000
-STORAGE_REGION=us-east-1
-STORAGE_BUCKET=default
-STORAGE_ACCESS_KEY=minioadmin
-STORAGE_SECRET_KEY=minioadmin
-STORAGE_USE_SSL=false
-STORAGE_SKIP_BUCKET_CHECK=false
-
-# Nx Cloud (Optional)
-# NX_CLOUD_ACCESS_TOKEN=
-
-# Crowdin (Optional)
-# CROWDIN_PROJECT_ID=
-# CROWDIN_PERSONAL_TOKEN=
-
-# Feature Flags (Optional)
-# DISABLE_SIGNUPS=false
-# DISABLE_EMAIL_AUTH=false
-
-# GitHub (OAuth, Optional)
-# GITHUB_CLIENT_ID=
-# GITHUB_CLIENT_SECRET=
-# GITHUB_CALLBACK_URL=http://localhost:5173/api/auth/github/callback
-
-# Google (OAuth, Optional)
-# GOOGLE_CLIENT_ID=
-# GOOGLE_CLIENT_SECRET=
-# GOOGLE_CALLBACK_URL=http://localhost:5173/api/auth/google/callback
-
-# OpenID (Optional)
-# VITE_OPENID_NAME=
-# OPENID_AUTHORIZATION_URL=
-# OPENID_CALLBACK_URL=http://localhost:5173/api/auth/openid/callback
-# OPENID_CLIENT_ID=
-# OPENID_CLIENT_SECRET=
-# OPENID_ISSUER=
-# OPENID_SCOPE=openid profile email
-# OPENID_TOKEN_URL=
-# OPENID_USER_INFO_URL=
diff --git a/apps/client/src/components/locale-switch.tsx b/apps/client/src/components/locale-switch.tsx
index 50f1c68b..d4bdc795 100644
--- a/apps/client/src/components/locale-switch.tsx
+++ b/apps/client/src/components/locale-switch.tsx
@@ -1,3 +1,4 @@
+import { t } from "@lingui/macro";
import { useLingui } from "@lingui/react";
import { TranslateIcon } from "@phosphor-icons/react";
import { Button, Popover, PopoverContent, PopoverTrigger } from "@reactive-resume/ui";
@@ -13,7 +14,7 @@ export const LocaleSwitch = () => {
return (
-
+
diff --git a/apps/client/src/components/theme-switch.tsx b/apps/client/src/components/theme-switch.tsx
index 37f7501b..2525cf23 100644
--- a/apps/client/src/components/theme-switch.tsx
+++ b/apps/client/src/components/theme-switch.tsx
@@ -1,3 +1,4 @@
+import { t } from "@lingui/macro";
import { CloudSunIcon, MoonIcon, SunIcon } from "@phosphor-icons/react";
import { useTheme } from "@reactive-resume/hooks";
import { Button } from "@reactive-resume/ui";
@@ -25,9 +26,9 @@ export const ThemeSwitch = ({ size = 20, className }: Props) => {
-
-
-
+
+
+
diff --git a/apps/client/src/pages/dashboard/settings/_sections/openai.tsx b/apps/client/src/pages/dashboard/settings/_sections/openai.tsx
index 434e7783..3cf92513 100644
--- a/apps/client/src/pages/dashboard/settings/_sections/openai.tsx
+++ b/apps/client/src/pages/dashboard/settings/_sections/openai.tsx
@@ -4,6 +4,7 @@ import { FloppyDiskIcon, TrashSimpleIcon } from "@phosphor-icons/react";
import {
Alert,
Button,
+ Checkbox,
Form,
FormControl,
FormField,
@@ -11,12 +12,15 @@ import {
FormLabel,
FormMessage,
Input,
- Checkbox,
} from "@reactive-resume/ui";
import { useForm } from "react-hook-form";
import { z } from "zod";
-import { DEFAULT_MAX_TOKENS, DEFAULT_MODEL, DEFAULT_AZURE_API_VERSION } from "@/client/constants/llm";
+import {
+ DEFAULT_AZURE_API_VERSION,
+ DEFAULT_MAX_TOKENS,
+ DEFAULT_MODEL,
+} from "@/client/constants/llm";
import { useOpenAiStore } from "@/client/stores/openai";
const formSchema = z.object({
@@ -41,12 +45,18 @@ type FormValues = z.infer;
export const OpenAISettings = () => {
const {
- apiKey, setApiKey,
- baseURL, setBaseURL,
- model, setModel,
- maxTokens, setMaxTokens,
- isAzure, setIsAzure,
- azureApiVersion, setAzureApiVersion
+ apiKey,
+ setApiKey,
+ baseURL,
+ setBaseURL,
+ model,
+ setModel,
+ maxTokens,
+ setMaxTokens,
+ isAzure,
+ setIsAzure,
+ azureApiVersion,
+ setAzureApiVersion,
} = useOpenAiStore();
const isEnabled = !!apiKey;
@@ -58,12 +68,19 @@ export const OpenAISettings = () => {
baseURL: baseURL ?? "",
model: model ?? DEFAULT_MODEL,
maxTokens: maxTokens ?? DEFAULT_MAX_TOKENS,
- isAzure: isAzure ?? false,
+ isAzure,
azureApiVersion: azureApiVersion ?? DEFAULT_AZURE_API_VERSION,
},
});
- const onSubmit = ({ apiKey, baseURL, model, maxTokens, isAzure, azureApiVersion }: FormValues) => {
+ const onSubmit = ({
+ apiKey,
+ baseURL,
+ model,
+ maxTokens,
+ isAzure,
+ azureApiVersion,
+ }: FormValues) => {
setApiKey(apiKey);
setIsAzure(isAzure);
if (baseURL) {
@@ -93,7 +110,7 @@ export const OpenAISettings = () => {
model: DEFAULT_MODEL,
maxTokens: DEFAULT_MAX_TOKENS,
isAzure: false,
- azureApiVersion: DEFAULT_AZURE_API_VERSION
+ azureApiVersion: DEFAULT_AZURE_API_VERSION,
});
};
@@ -125,10 +142,10 @@ export const OpenAISettings = () => {
- You can also integrate with Azure OpenAI by enabling the "Use Azure OpenAI" checkbox
- and setting the Resource URL to your Azure OpenAI resource (e.g.,
- https://your-resource.openai.azure.com). Set the deployment name in the Model field
- and specify the appropriate API version for your Azure deployment.
+ You can also integrate with Azure OpenAI by enabling the Use Azure OpenAI{" "}
+ checkbox and setting the Resource URL to your Azure OpenAI resource:{" "}
+ https://your-resource.openai.azure.com. Set the deployment name in the
+ Model field and specify the appropriate API version for your Azure deployment.
@@ -136,8 +153,8 @@ export const OpenAISettings = () => {
You can also integrate with Ollama simply by setting the API key to
sk-1234567890abcdef and the Base URL to your Ollama URL, i.e.
- http://localhost:11434/v1. You can also pick and choose models and set the max tokens
- as per your preference.
+ http://localhost:11434/v1. You can also pick and choose models and set the
+ max tokens as per your preference.
@@ -163,10 +180,7 @@ export const OpenAISettings = () => {
render={({ field }) => (
- {form.watch("isAzure")
- ? t`Azure OpenAI Resource URL`
- : t`Base URL`
- }
+ {form.watch("isAzure") ? t`Azure OpenAI Resource URL` : t`Base URL`}
{
control={form.control}
render={({ field }) => (
-
- {form.watch("isAzure")
- ? t`Deployment Name`
- : t`Model`
- }
-
+ {form.watch("isAzure") ? t`Deployment Name` : t`Model`}
@@ -228,7 +237,7 @@ export const OpenAISettings = () => {
{
field.onChange(Boolean(value));
}}
diff --git a/apps/client/src/pages/home/sections/features/index.tsx b/apps/client/src/pages/home/sections/features/index.tsx
index ea417dbc..5989aa4b 100644
--- a/apps/client/src/pages/home/sections/features/index.tsx
+++ b/apps/client/src/pages/home/sections/features/index.tsx
@@ -118,7 +118,7 @@ export const FeaturesSection = () => {
whileInView={{ opacity: 1, x: 0, transition: { delay: index * 0.1 } }}
>
{feature.icon}
- {feature.title}
+ {feature.title}
))}
diff --git a/apps/client/src/services/openai/client.ts b/apps/client/src/services/openai/client.ts
index 5bbb6ef5..7e290abe 100644
--- a/apps/client/src/services/openai/client.ts
+++ b/apps/client/src/services/openai/client.ts
@@ -13,40 +13,25 @@ export const openai = () => {
}
if (isAzure) {
- if (!baseURL) {
- throw new Error(t`Azure OpenAI Base URL is required when using Azure OpenAI.`);
+ if (!baseURL || !model || !azureApiVersion) {
+ throw new Error(
+ t`Azure OpenAI Base URL, deployment name (model), and API version are required when using Azure OpenAI.`,
+ );
}
- if (!model) {
- throw new Error(t`Azure OpenAI deployment name (model) is required when using Azure OpenAI.`);
- }
-
- if (!azureApiVersion) {
- throw new Error(t`Azure OpenAI API version is required when using Azure OpenAI.`);
- }
-
- // Construct Azure OpenAI URL: https://your-resource.openai.azure.com/openai/deployments/your-deployment
- const azureBaseURL = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL;
- const constructedURL = `${azureBaseURL}/openai/deployments/${model}`;
+ const azureBaseURL = baseURL.replace(/\/$/, "");
return new OpenAI({
apiKey,
- baseURL: constructedURL,
- defaultQuery: { "api-version": azureApiVersion ?? undefined },
- dangerouslyAllowBrowser: true,
- });
- }
-
- if (baseURL) {
- return new OpenAI({
- apiKey,
- baseURL,
+ baseURL: `${azureBaseURL}/openai/deployments/${model}`,
+ defaultQuery: { "api-version": azureApiVersion },
dangerouslyAllowBrowser: true,
});
}
return new OpenAI({
apiKey,
+ baseURL,
dangerouslyAllowBrowser: true,
});
};
diff --git a/apps/client/src/stores/openai.ts b/apps/client/src/stores/openai.ts
index 0286afb2..09afdf77 100644
--- a/apps/client/src/stores/openai.ts
+++ b/apps/client/src/stores/openai.ts
@@ -1,7 +1,7 @@
import { create } from "zustand";
import { persist } from "zustand/middleware";
-import { DEFAULT_MAX_TOKENS, DEFAULT_MODEL, DEFAULT_AZURE_API_VERSION } from "../constants/llm";
+import { DEFAULT_AZURE_API_VERSION, DEFAULT_MAX_TOKENS, DEFAULT_MODEL } from "../constants/llm";
type OpenAIStore = {
baseURL: string | null;
diff --git a/apps/server/src/printer/printer.service.ts b/apps/server/src/printer/printer.service.ts
index dfebf7aa..92076d7b 100644
--- a/apps/server/src/printer/printer.service.ts
+++ b/apps/server/src/printer/printer.service.ts
@@ -145,7 +145,7 @@ export class PrinterService {
Promise.all(
// eslint-disable-next-line unicorn/prefer-spread
Array.from(document.images).map((img) => {
- if (img.complete) return;
+ if (img.complete) return Promise.resolve();
return new Promise((resolve) => {
// eslint-disable-next-line unicorn/prefer-add-event-listener
img.onload = img.onerror = resolve;
diff --git a/package.json b/package.json
index bd3a124a..d91c8844 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "@reactive-resume/source",
"description": "A free and open-source resume builder that simplifies the process of creating, updating, and sharing your resume.",
- "version": "4.4.7",
+ "version": "4.4.8",
"license": "MIT",
"private": true,
"packageManager": "pnpm@10.17.1+sha512.17c560fca4867ae9473a3899ad84a88334914f379be46d455cbf92e5cf4b39d34985d452d2583baf19967fa76cb5c17bc9e245529d0b98745721aa7200ecaf7a",