Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
- Use `AutoForm` for forms instead of manually creating form components.
- After create/edit/delete operations, always refresh the data in the table to reflect the changes with notification using toast `sonner`.
- Use `React.lazy` and `Suspense` for code splitting and lazy loading for content-heavy dialogs like dialogs in forms.
- Don't use big comments. Remember that code is self-documenting. Use comments only when necessary to explain complex logic or decisions.
5 changes: 2 additions & 3 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,12 @@
"next-intl": "^4.13.0",
"react": "^19.2.7",
"react-dom": "^19.2.7",
"use-intl": "^4.13.0",
"ws": "^8.21.0",
"zod": "^4.4.3"
},
"devDependencies": {
"@hono/node-server": "^2.0.6",
"@react-email/components": "^1.0.12",
"@react-email/ui": "^6.6.6",
"@types/node": "^26.0.1",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
Expand All @@ -40,7 +39,7 @@
"@vitnode/nodemailer": "workspace:*",
"dotenv": "^17.4.2",
"eslint": "^10.5.0",
"react-email": "^6.6.4",
"react-email": "^6.6.6",
"tsc-alias": "^1.8.17",
"tsx": "^4.22.4",
"typescript": "^6.0.3"
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/content/docs/dev/email/components/card.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
EmailCardHeader,
EmailCardTitle,
} from '@vitnode/core/emails/ui/card';
import { Text } from '@react-email/components';
import { Text } from 'react-email';
```

```tsx
Expand Down
20 changes: 9 additions & 11 deletions apps/docs/content/docs/dev/email/templates.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Inside your:
you can create your email templates. The templates should be React components that return JSX and to be exported as default.

```tsx title="src/emails/test-template.tsx"
import { Text } from '@react-email/components';
import { Text } from 'react-email';
import DefaultTemplateEmail, {
type DefaultTemplateEmailProps,
} from '@vitnode/core/emails/default-template';
Expand Down Expand Up @@ -104,8 +104,8 @@ The `DefaultTemplateEmail` component is a wrapper around your email content that

We implemented [TailwindCSS](https://react.email/docs/components/tailwind) in the email templates to allow you to use utility classes for styling. You can use Tailwind classes directly in your email components.

<Callout type="warn" title="TailwindCSS v4 is not yet supported!">
The current `TailwindCSS` version used is **3.4.10**.
<Callout type="info" title="TailwindCSS v4 is now supported!">
Since React Email v6, the email templates use **TailwindCSS v4**.
</Callout>

### Components
Expand All @@ -130,7 +130,7 @@ We implemented [TailwindCSS](https://react.email/docs/components/tailwind) in th

## Internationalization (I18n)

VitNode supports internationalization (I18n) in email templates thanks to [use-intl](https://next-intl.dev/docs/environments/core-library).
VitNode supports internationalization (I18n) in email templates thanks to [next-intl](https://react.email/docs/guides/internationalization/next-intl).
Comment thread
aXenDeveloper marked this conversation as resolved.

```json title="src/locales/@vitnode/blog/en.json"
{
Expand All @@ -145,11 +145,11 @@ Read more about messages in [Internationalization (I18n) - Messages Docs](/docs/
Use the `createTranslator` function to create a translator instance that can be used to translate messages in your email templates.

```tsx title="src/emails/test-template.tsx"
import { Text } from '@react-email/components';
import { Text } from 'react-email';
import DefaultTemplateEmail, {
type DefaultTemplateEmailProps,
} from '@vitnode/core/emails/default-template';
import { createTranslator } from 'use-intl'; // [!code ++]
import { createTranslator } from 'next-intl'; // [!code ++]

export default function TestTemplateEmail({
i18n,
Expand Down Expand Up @@ -186,7 +186,7 @@ You can also translate the subject of the email using the `createTranslator` fun
```ts title="src/api/modules/users/routes/test.route.ts"
import { z } from 'zod';
// [!code ++]
import { createTranslator } from 'use-intl';
import { createTranslator } from 'next-intl';
import { buildRoute } from '@vitnode/core/api/lib/route';
import { UserModel } from '@vitnode/core/api/models/user';

Expand Down Expand Up @@ -222,21 +222,19 @@ export const testRoute = buildRoute({
If you pass `user` to the `send` method, it will be available in the email template as a prop. This allows you to personalize the email content based on the user data.

```tsx title="src/emails/test-template.tsx"
import { Text } from '@react-email/components';
import { Text } from 'react-email';
import DefaultTemplateEmail, {
type DefaultTemplateEmailProps,
} from '@vitnode/core/emails/default-template';

export default function TestTemplateEmail({
locale,
messages,
user, // [!code ++]
...props
}: DefaultTemplateEmailProps) {
if (!user) return null;

return (
<DefaultTemplateEmail locale={locale} messages={messages} {...props}>
<DefaultTemplateEmail {...props}>
<Text>This message is for {user.name}</Text>
</DefaultTemplateEmail>
);
Expand Down
5 changes: 2 additions & 3 deletions apps/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"devDependencies": {
"@next/bundle-analyzer": "^16.2.9",
"@playwright/test": "^1.61.1",
"@react-email/components": "^1.0.12",
"@react-email/ui": "^6.6.6",
"@tailwindcss/postcss": "^4.3.1",
"@types/mdx": "^2.0.14",
"@types/node": "^26.0.1",
Expand All @@ -61,12 +61,11 @@
"class-variance-authority": "^0.7.1",
"eslint": "^10.5.0",
"postcss": "^8.5.15",
"react-email": "^6.6.4",
"react-email": "^6.6.6",
"shiki": "^4.3.0",
"tailwindcss": "^4.3.1",
"tw-animate-css": "^1.4.0",
"typescript": "^6.0.3",
"use-intl": "^4.13.0",
"zod": "^4.4.3"
}
}
10 changes: 4 additions & 6 deletions packages/create-vitnode-app/src/create/create-package-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,21 +122,21 @@ const rootDevDeps = (eslint: boolean) => ({
const apiDeps = {
"@hono/zod-openapi": versionsPackageJson.honoZodOpenapi,
"@hono/zod-validator": versionsPackageJson.honoZodValidator,
"@react-email/components": versionsPackageJson.reactEmailComponents,
"@vitnode/core": "", // filled dynamically
"drizzle-kit": versionsPackageJson.drizzleKit,
"drizzle-orm": versionsPackageJson.drizzleOrm,
hono: versionsPackageJson.hono,
"next-intl": versionsPackageJson.nextIntl,
react: versionsPackageJson.react,
"react-dom": versionsPackageJson.reactDom,
"use-intl": versionsPackageJson.useIntl,
"react-email": versionsPackageJson.reactEmail,
shadcn: versionsPackageJson.shadcnUi,
zod: versionsPackageJson.zod,
};

const apiDevDeps = (pm: string, eslint: boolean) => ({
"@hono/node-server": "^2.0",
"@react-email/ui": versionsPackageJson.reactEmailUi,
...(pm === "bun" ? { "@types/bun": versionsPackageJson.typesBun } : {}),
"@types/node": versionsPackageJson.typesNode,
"@types/react": versionsPackageJson.typesReact,
Expand All @@ -147,7 +147,6 @@ const apiDevDeps = (pm: string, eslint: boolean) => ({
eslint: versionsPackageJson.eslint,
// Prettier in API only when onlyApi + eslint in original code – we'll preserve by passing include later if needed
}),
"react-email": versionsPackageJson.reactEmail,
"tsc-alias": versionsPackageJson.tscAlias,
tsx: versionsPackageJson.tsx,
typescript: versionsPackageJson.typescript,
Expand All @@ -157,7 +156,6 @@ const singleAppDeps = {
"@hono/zod-openapi": versionsPackageJson.honoZodOpenapi,
"@hono/zod-validator": versionsPackageJson.honoZodValidator,
"@hookform/resolvers": versionsPackageJson.rhfResolvers,
"@react-email/components": versionsPackageJson.reactEmailComponents,
"@vitnode/core": "",
"drizzle-kit": versionsPackageJson.drizzleKit,
"drizzle-orm": versionsPackageJson.drizzleOrm,
Expand All @@ -167,13 +165,14 @@ const singleAppDeps = {
"next-intl": versionsPackageJson.nextIntl,
react: versionsPackageJson.react,
"react-dom": versionsPackageJson.reactDom,
"react-email": versionsPackageJson.reactEmail,
"react-hook-form": versionsPackageJson.rhf,
sonner: versionsPackageJson.sonner,
"use-intl": versionsPackageJson.useIntl,
zod: versionsPackageJson.zod,
};

const singleAppDevDeps = (eslint: boolean) => ({
"@react-email/ui": versionsPackageJson.reactEmailUi,
"@tailwindcss/postcss": versionsPackageJson.tailwindPostcss,
"@types/node": versionsPackageJson.typesNode,
"@types/react": versionsPackageJson.typesReact,
Expand All @@ -185,7 +184,6 @@ const singleAppDevDeps = (eslint: boolean) => ({
prettier: versionsPackageJson.prettier,
"prettier-plugin-tailwindcss": versionsPackageJson.prettierTailwind,
}),
"react-email": versionsPackageJson.reactEmail,
turbo: versionsPackageJson.turbo,
tailwindcss: versionsPackageJson.tailwind,
"tw-animate-css": versionsPackageJson.twAnimateCss,
Expand Down
3 changes: 1 addition & 2 deletions packages/create-vitnode-app/src/create/package-versions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export const versionsPackageJson = {
reactDom: "^19.2",
nextSingle: "16.3.0-preview.5",
nextIntl: "^4.13",
useIntl: "^4.13",
rhf: "^7.80",
rhfResolvers: "^5.1.1",
lucide: "^1.21",
Expand All @@ -34,7 +33,7 @@ export const versionsPackageJson = {
honoZodOpenapi: "^1.3",
honoZodValidator: "^0.8",
reactEmail: "^6.6",
reactEmailComponents: "^1.0",
reactEmailUi: "^6.6",
zod: "^4.4",

cva: "^0.7.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,10 @@ export const createPluginPackageJSON = async ({
"react-email": versionsPackageJson.reactEmail,
"react-hook-form": versionsPackageJson.rhf,
sonner: versionsPackageJson.sonner,
"use-intl": versionsPackageJson.useIntl,
zod: versionsPackageJson.zod,
},
devDependencies: {
"@react-email/components": versionsPackageJson.reactEmailComponents,
"@react-email/ui": versionsPackageJson.reactEmailUi,
"@swc/cli": versionsPackageJson.swcCli,
"@swc/core": versionsPackageJson.swcCore,
"@types/react": versionsPackageJson.typesReact,
Expand Down
6 changes: 2 additions & 4 deletions packages/vitnode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"@hono/zod-openapi": "^1.4.0",
"@hono/zod-validator": "^0.8.0",
"@hookform/resolvers": "^5.4.0",
"@react-email/components": "^1.0.12",
"@react-email/ui": "^6.6.6",
"@swc/cli": "^0.8.1",
"@swc/core": "^1.15.43",
"@testing-library/dom": "^10.4.1",
Expand All @@ -64,7 +64,7 @@
"next-intl": "^4.13.0",
"react": "^19.2.7",
"react-dom": "^19.2.7",
"react-email": "^6.6.4",
"react-email": "^6.6.6",
"react-hook-form": "^7.80.0",
"sonner": "^2.0.7",
"tailwindcss": "^4.3.1",
Expand Down Expand Up @@ -113,7 +113,6 @@
"@bprogress/next": "^3.2.12",
"@dnd-kit/core": "^6.3.1",
"@hono/swagger-ui": "^0.6.1",
"@react-email/preview-server": "^5.2.10",
"@tanstack/react-query": "^5.101.1",
"@tiptap/extension-text-align": "^3.27.1",
"@tiptap/pm": "^3.27.1",
Expand All @@ -140,7 +139,6 @@
"shadcn": "^4.11.0",
"tailwind-merge": "^3.6.0",
"use-debounce": "^10.1.1",
"use-intl": "^4.13.0",
"vaul": "^1.1.2"
}
}
26 changes: 1 addition & 25 deletions packages/vitnode/scripts/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import { basename, join, relative } from "node:path";

import {
buildInitialRouteMap,
cleanupDeletedFiles,
copyFile,
findLocaleRoot,
findRepoRoot,
getAllFiles,
isDirectoryEmpty,
routeKey,
type SourceConfig,
Expand Down Expand Up @@ -258,30 +258,6 @@ const createFileOps = (
return { copyFileWrapper, removeFile };
};

/**
* Remove files in destination that no longer exist in source (skip locales)
*/
const cleanupDeletedFiles = (
sourceDir: string,
destinationDir: string,
removeFileFn: (p: string) => void,
) => {
if (!existsSync(destinationDir)) return;

const isLocaleDir = destinationDir.includes(join("src", "locales"));
if (isLocaleDir) return;

const destFiles = getAllFiles(destinationDir);
for (const destFile of destFiles) {
const relativePath = relative(destinationDir, destFile);
const sourceFile = join(sourceDir, relativePath);

if (!existsSync(sourceFile)) {
removeFileFn(destFile);
}
}
};

/**
* Resolve destination paths for a given source path across all source configs
*/
Expand Down
Loading
Loading