create-carlonicora-app 1.8.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. package/package.json +1 -1
  2. package/template/apps/api/package.json +34 -34
  3. package/template/apps/api/src/neo4j.migrations/20250901_002.ts +24 -31
  4. package/template/apps/api/src/neo4j.migrations/queries/migration.queries.ts +0 -2
  5. package/template/apps/api/templates/email/en/activationEmail.hbs +27 -0
  6. package/template/apps/api/templates/email/en/registrationAdminNotification.hbs +48 -0
  7. package/template/apps/api/templates/email/en/waitlistAdminNotification.hbs +47 -0
  8. package/template/apps/api/templates/email/en/waitlistConfirmation.hbs +30 -0
  9. package/template/apps/api/templates/email/en/waitlistInvitation.hbs +29 -0
  10. package/template/apps/api/templates/email/footer.hbs +3 -0
  11. package/template/apps/api/templates/email/header.hbs +3 -0
  12. package/template/apps/web/messages/en.json +13 -0
  13. package/template/apps/web/package.json +30 -29
  14. package/template/apps/web/scripts/validate-translations.mjs +252 -0
  15. package/template/apps/web/src/app/[locale]/(main)/(features)/settings/[module]/page.tsx +26 -0
  16. package/template/apps/web/src/app/[locale]/(main)/(features)/settings/layout.tsx +12 -0
  17. package/template/apps/web/src/app/[locale]/(main)/(features)/settings/oauth/[clientId]/page.tsx +174 -0
  18. package/template/apps/web/src/app/[locale]/(main)/(features)/settings/oauth/new/page.tsx +88 -0
  19. package/template/apps/web/src/app/[locale]/(main)/(features)/settings/oauth/page.tsx +115 -0
  20. package/template/apps/web/src/app/[locale]/(main)/(features)/settings/page.tsx +24 -0
  21. package/template/apps/web/src/features/common/components/navigations/CreationDropDown.tsx +1 -79
  22. package/template/package.json +14 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-carlonicora-app",
3
- "version": "1.8.0",
3
+ "version": "1.11.0",
4
4
  "description": "Create a NestJS + Next.js monorepo project with Neo4j and JSON:API",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -2,39 +2,39 @@
2
2
  "author": "",
3
3
  "dependencies": {
4
4
  "@carlonicora/nestjs-neo4jsonapi": "workspace:*",
5
- "@aws-sdk/client-s3": "^3.975.0",
6
- "@aws-sdk/s3-request-presigner": "^3.975.0",
7
- "@azure/msal-node": "^5.0.2",
5
+ "@aws-sdk/client-s3": "^3.984.0",
6
+ "@aws-sdk/s3-request-presigner": "^3.984.0",
7
+ "@azure/msal-node": "^5.0.3",
8
8
  "@azure/openai": "^2.0.0",
9
9
  "@azure/storage-blob": "^12.30.0",
10
10
  "@fastify/multipart": "^9.4.0",
11
11
  "@fastify/static": "^9.0.0",
12
12
  "@fastify/swagger": "^9.6.1",
13
13
  "@getbrevo/brevo": "^3.0.1",
14
- "@langchain/aws": "^1.2.1",
15
- "@langchain/community": "^1.1.7",
16
- "@langchain/core": "^1.1.17",
17
- "@langchain/langgraph": "^1.1.2",
18
- "@langchain/ollama": "^1.2.1",
19
- "@langchain/openai": "^1.2.3",
14
+ "@langchain/aws": "^1.2.2",
15
+ "@langchain/community": "^1.1.12",
16
+ "@langchain/core": "^1.1.19",
17
+ "@langchain/langgraph": "^1.1.3",
18
+ "@langchain/ollama": "^1.2.2",
19
+ "@langchain/openai": "^1.2.5",
20
20
  "@langchain/textsplitters": "^1.0.1",
21
21
  "@microsoft/microsoft-graph-client": "^3.0.7",
22
22
  "@microsoft/microsoft-graph-types": "^2.43.1",
23
23
  "@nestjs/bullmq": "^11.0.4",
24
24
  "@nestjs/cli": "^11.0.16",
25
- "@nestjs/common": "^11.1.12",
26
- "@nestjs/config": "^4.0.2",
27
- "@nestjs/core": "^11.1.12",
25
+ "@nestjs/common": "^11.1.13",
26
+ "@nestjs/config": "^4.0.3",
27
+ "@nestjs/core": "^11.1.13",
28
28
  "@nestjs/event-emitter": "^3.0.1",
29
29
  "@nestjs/jwt": "^11.0.2",
30
- "@nestjs/microservices": "^11.1.12",
30
+ "@nestjs/microservices": "^11.1.13",
31
31
  "@nestjs/passport": "^11.0.5",
32
- "@nestjs/platform-fastify": "^11.1.12",
33
- "@nestjs/platform-socket.io": "^11.1.12",
34
- "@nestjs/schedule": "^6.1.0",
35
- "@nestjs/swagger": "^11.2.5",
32
+ "@nestjs/platform-fastify": "^11.1.13",
33
+ "@nestjs/platform-socket.io": "^11.1.13",
34
+ "@nestjs/schedule": "^6.1.1",
35
+ "@nestjs/swagger": "^11.2.6",
36
36
  "@nestjs/throttler": "^6.5.0",
37
- "@nestjs/websockets": "^11.1.12",
37
+ "@nestjs/websockets": "^11.1.13",
38
38
  "@opentelemetry/api": "^1.9.0",
39
39
  "@opentelemetry/exporter-trace-otlp-http": "^0.211.0",
40
40
  "@opentelemetry/instrumentation-fastify": "^0.55.0",
@@ -47,20 +47,20 @@
47
47
  "@sendgrid/mail": "^8.1.6",
48
48
  "adm-zip": "^0.5.16",
49
49
  "async": "^3.2.6",
50
- "axios": "^1.13.3",
50
+ "axios": "^1.13.4",
51
51
  "bcryptjs": "^3.0.3",
52
- "bullmq": "^5.67.1",
52
+ "bullmq": "^5.67.3",
53
53
  "cheerio": "^1.2.0",
54
54
  "class-transformer": "^0.5.1",
55
55
  "class-validator": "^0.14.3",
56
- "dotenv": "^17.2.3",
57
- "fast-xml-parser": "^5.3.3",
58
- "fastify": "^5.7.1",
56
+ "dotenv": "^17.2.4",
57
+ "fast-xml-parser": "^5.3.4",
58
+ "fastify": "^5.7.4",
59
59
  "handlebars": "^4.7.8",
60
60
  "ioredis": "^5.9.2",
61
- "jsdom": "^27.4.0",
61
+ "jsdom": "^28.0.0",
62
62
  "jszip": "^3.10.1",
63
- "langchain": "^1.2.13",
63
+ "langchain": "^1.2.18",
64
64
  "lodash": "^4.17.23",
65
65
  "marked": "^17.0.1",
66
66
  "mathjs": "^15.1.0",
@@ -70,14 +70,14 @@
70
70
  "nestjs-cls": "^6.2.0",
71
71
  "nestjs-i18n": "^10.6.0",
72
72
  "node-tesseract-ocr": "^2.2.1",
73
- "nodemailer": "^7.0.12",
73
+ "nodemailer": "^8.0.0",
74
74
  "officeparser": "^6.0.4",
75
- "openai": "^6.16.0",
75
+ "openai": "^6.18.0",
76
76
  "passport": "^0.7.0",
77
77
  "passport-jwt": "^4.0.1",
78
78
  "pdf-parse": "^2.4.5",
79
79
  "pdf2pic": "^3.2.0",
80
- "pdfjs-dist": "^5.4.530",
80
+ "pdfjs-dist": "^5.4.624",
81
81
  "pino": "^10.3.0",
82
82
  "pino-loki": "^3.0.0",
83
83
  "pino-pretty": "^13.1.3",
@@ -100,21 +100,21 @@
100
100
  "devDependencies": {
101
101
  "@eslint/js": "^9.39.2",
102
102
  "@nestjs/schematics": "^11.0.9",
103
- "@nestjs/testing": "^11.1.12",
103
+ "@nestjs/testing": "^11.1.13",
104
104
  "@types/jsdom": "^27.0.0",
105
105
  "@types/microsoft-graph": "^2.40.1",
106
106
  "@types/supertest": "^6.0.3",
107
107
  "@types/web-push": "^3.6.4",
108
- "@typescript-eslint/eslint-plugin": "^8.53.1",
109
- "@typescript-eslint/parser": "^8.53.1",
108
+ "@typescript-eslint/eslint-plugin": "^8.54.0",
109
+ "@typescript-eslint/parser": "^8.54.0",
110
110
  "@vitest/coverage-v8": "^4.0.18",
111
- "commander": "^14.0.2",
111
+ "commander": "^14.0.3",
112
112
  "esbuild": "^0.27.2",
113
113
  "eslint": "^9.39.2",
114
114
  "eslint-config-prettier": "^10.1.8",
115
115
  "eslint-plugin-prettier": "^5.5.5",
116
- "glob": "^13.0.0",
117
- "globals": "^17.1.0",
116
+ "glob": "^13.0.1",
117
+ "globals": "^17.3.0",
118
118
  "nodemon": "^3.1.11",
119
119
  "source-map-support": "^0.5.21",
120
120
  "supertest": "^7.2.2",
@@ -2,17 +2,16 @@
2
2
  * This migration creates the initial set of modules in the database.
3
3
  */
4
4
 
5
- import { Action, MigrationInterface } from "@carlonicora/nestjs-neo4jsonapi";
6
- import { moduleQuery } from "src/neo4j.migrations/queries/migration.queries";
5
+ import { Action, MigrationInterface } from '@carlonicora/nestjs-neo4jsonapi';
6
+ import { moduleQuery } from 'src/neo4j.migrations/queries/migration.queries';
7
7
 
8
8
  export const migration: MigrationInterface[] = [
9
9
  {
10
10
  query: moduleQuery,
11
11
  queryParams: {
12
- moduleName: "Auth",
13
- moduleId: "035fe8a6-d467-40c0-9d1d-6a87f0dd286e",
14
- featureId: "17036fb0-060b-4c83-a617-f32259819783",
15
- isCore: true,
12
+ moduleName: 'Auth',
13
+ moduleId: '035fe8a6-d467-40c0-9d1d-6a87f0dd286e',
14
+ featureId: '17036fb0-060b-4c83-a617-f32259819783',
16
15
  permissions: JSON.stringify([
17
16
  { type: Action.Create, value: true },
18
17
  { type: Action.Read, value: true },
@@ -24,30 +23,27 @@ export const migration: MigrationInterface[] = [
24
23
  {
25
24
  query: moduleQuery,
26
25
  queryParams: {
27
- moduleName: "Company",
28
- moduleId: "f9e77c8f-bfd1-4fd4-80b0-e1d891ab7113",
29
- featureId: "17036fb0-060b-4c83-a617-f32259819783",
30
- isCore: true,
26
+ moduleName: 'Company',
27
+ moduleId: 'f9e77c8f-bfd1-4fd4-80b0-e1d891ab7113',
28
+ featureId: '17036fb0-060b-4c83-a617-f32259819783',
31
29
  permissions: JSON.stringify([{ type: Action.Read, value: true }]),
32
30
  },
33
31
  },
34
32
  {
35
33
  query: moduleQuery,
36
34
  queryParams: {
37
- moduleName: "Feature",
38
- moduleId: "025fdd23-2803-4360-9fd9-eaa3612c2e23",
39
- featureId: "17036fb0-060b-4c83-a617-f32259819783",
40
- isCore: true,
35
+ moduleName: 'Feature',
36
+ moduleId: '025fdd23-2803-4360-9fd9-eaa3612c2e23',
37
+ featureId: '17036fb0-060b-4c83-a617-f32259819783',
41
38
  permissions: JSON.stringify([{ type: Action.Read, value: true }]),
42
39
  },
43
40
  },
44
41
  {
45
42
  query: moduleQuery,
46
43
  queryParams: {
47
- moduleName: "Notification",
48
- moduleId: "9259d704-c670-4e77-a3a1-a728ffc5be3d",
49
- featureId: "17036fb0-060b-4c83-a617-f32259819783",
50
- isCore: true,
44
+ moduleName: 'Notification',
45
+ moduleId: '9259d704-c670-4e77-a3a1-a728ffc5be3d',
46
+ featureId: '17036fb0-060b-4c83-a617-f32259819783',
51
47
  permissions: JSON.stringify([
52
48
  { type: Action.Read, value: true },
53
49
  { type: Action.Update, value: true },
@@ -57,33 +53,30 @@ export const migration: MigrationInterface[] = [
57
53
  {
58
54
  query: moduleQuery,
59
55
  queryParams: {
60
- moduleName: "Role",
61
- moduleId: "9f6416e6-7b9b-4e1a-a99f-833191eca8a9",
62
- featureId: "17036fb0-060b-4c83-a617-f32259819783",
63
- isCore: true,
56
+ moduleName: 'Role',
57
+ moduleId: '9f6416e6-7b9b-4e1a-a99f-833191eca8a9',
58
+ featureId: '17036fb0-060b-4c83-a617-f32259819783',
64
59
  permissions: JSON.stringify([{ type: Action.Read, value: true }]),
65
60
  },
66
61
  },
67
62
  {
68
63
  query: moduleQuery,
69
64
  queryParams: {
70
- moduleName: "S3",
71
- moduleId: "db41ba46-e171-4324-8845-99353eba8568",
72
- featureId: "17036fb0-060b-4c83-a617-f32259819783",
73
- isCore: true,
65
+ moduleName: 'S3',
66
+ moduleId: 'db41ba46-e171-4324-8845-99353eba8568',
67
+ featureId: '17036fb0-060b-4c83-a617-f32259819783',
74
68
  permissions: JSON.stringify([{ type: Action.Read, value: true }]),
75
69
  },
76
70
  },
77
71
  {
78
72
  query: moduleQuery,
79
73
  queryParams: {
80
- moduleName: "User",
81
- moduleId: "04cfc677-0fd2-4f5e-adf4-2483a00c0277",
82
- featureId: "17036fb0-060b-4c83-a617-f32259819783",
83
- isCore: true,
74
+ moduleName: 'User',
75
+ moduleId: '04cfc677-0fd2-4f5e-adf4-2483a00c0277',
76
+ featureId: '17036fb0-060b-4c83-a617-f32259819783',
84
77
  permissions: JSON.stringify([
85
78
  { type: Action.Read, value: true },
86
- { type: Action.Update, value: "id" },
79
+ { type: Action.Update, value: 'id' },
87
80
  ]),
88
81
  },
89
82
  },
@@ -17,12 +17,10 @@ export const moduleQuery = `
17
17
  ON CREATE SET
18
18
  module.name=$moduleName,
19
19
  module.permissions = $permissions,
20
- module.isCore = $isCore,
21
20
  module.createdAt = datetime(),
22
21
  module.updatedAt = datetime()
23
22
  ON MATCH SET
24
23
  module.name = $moduleName,
25
- module.isCore = $isCore,
26
24
  module.updatedAt = CASE WHEN module.permissions <> $permissions THEN datetime() ELSE module.updatedAt END,
27
25
  module.permissions = CASE WHEN module.permissions <> $permissions THEN $permissions ELSE module.permissions END
28
26
  WITH module
@@ -0,0 +1,27 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>Welcome to {{name}}</title>
6
+ </head>
7
+ <body style="margin:0; padding:0; background-color:#f4f4f4; font-family:Arial, sans-serif;">
8
+ <div style="width:100%; padding:20px; background-color:#f4f4f4;">
9
+ <div style="max-width:600px; margin:0 auto; background-color:#ffffff; padding:40px; border-radius:8px; text-align:center; border:1px solid #4A5568;">
10
+ {{> header}}
11
+ <div style="text-align:left;">
12
+ <div style="font-size:24px; color:#4A5568; margin-bottom:20px;">Activate your account</div>
13
+ <div style="font-size:16px; color:#555555; margin-bottom:30px; line-height:1.5; text-align:left;">
14
+ <p style="margin:0;">Hello!</p>
15
+ <p style="margin:0;">Your account is ready to be activated</p>
16
+ <p style="margin:0; margin-top: 10px;">The activation link is valid until {{expirationDate}} at {{expirationTime}}.</p>
17
+ <p style="margin:0;">Thanks</p>
18
+ </div>
19
+ <div style="text-align:center; margin-bottom:20px;margin-top:75px;">
20
+ <a href="{{activationLink}}" style="display:inline-block; padding:12px 24px; font-size:16px; color:#ffffff; background-color:#4A5568; text-decoration:none; border-radius:4px;">Activate Account</a>
21
+ </div>
22
+ </div>
23
+ {{> footer}}
24
+ </div>
25
+ </div>
26
+ </body>
27
+ </html>
@@ -0,0 +1,48 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>New User Registration</title>
5
+ </head>
6
+ <body style="margin: 0; padding: 0; font-family: Arial, sans-serif; background-color: #f9f9f9;">
7
+ {{> header}}
8
+ <div style="padding: 30px; max-width: 600px; margin: 0 auto; background-color: #ffffff;">
9
+ <h2 style="color: #333; margin-top: 0;">New User Registration</h2>
10
+ <p style="color: #555; line-height: 1.6;">
11
+ Hi <strong>{{adminName}}</strong>,
12
+ </p>
13
+ <p style="color: #555; line-height: 1.6;">
14
+ A new user has completed their registration and activated their account.
15
+ </p>
16
+
17
+ <div style="background-color: #f5f5f5; border-radius: 8px; padding: 20px; margin: 20px 0;">
18
+ <table style="width: 100%; border-collapse: collapse;">
19
+ <tr>
20
+ <td style="color: #888; padding: 8px 0; width: 120px; vertical-align: top;">Name:</td>
21
+ <td style="color: #333; padding: 8px 0;"><strong>{{userName}}</strong></td>
22
+ </tr>
23
+ <tr>
24
+ <td style="color: #888; padding: 8px 0; vertical-align: top;">Email:</td>
25
+ <td style="color: #333; padding: 8px 0;">
26
+ <a href="mailto:{{userEmail}}" style="color: #0066cc;">{{userEmail}}</a>
27
+ </td>
28
+ </tr>
29
+ <tr>
30
+ <td style="color: #888; padding: 8px 0; vertical-align: top;">Company:</td>
31
+ <td style="color: #333; padding: 8px 0;">{{companyName}}</td>
32
+ </tr>
33
+ <tr>
34
+ <td style="color: #888; padding: 8px 0; vertical-align: top;">Activated at:</td>
35
+ <td style="color: #333; padding: 8px 0;">{{activatedAt}}</td>
36
+ </tr>
37
+ </table>
38
+ </div>
39
+
40
+ <div style="margin-top: 30px; text-align: center;">
41
+ <a href="{{dashboardLink}}" style="background: #1a1a1a; color: #fff; padding: 12px 24px; text-decoration: none; border-radius: 4px; display: inline-block;">
42
+ View Admin Dashboard
43
+ </a>
44
+ </div>
45
+ </div>
46
+ {{> footer}}
47
+ </body>
48
+ </html>
@@ -0,0 +1,47 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>New Waitlist Confirmation</title>
5
+ </head>
6
+ <body style="margin: 0; padding: 0; font-family: Arial, sans-serif; background-color: #f9f9f9;">
7
+ {{> header}}
8
+ <div style="padding: 30px; max-width: 600px; margin: 0 auto; background-color: #ffffff;">
9
+ <h2 style="color: #333; margin-top: 0;">New Waitlist Confirmation</h2>
10
+ <p style="color: #555; line-height: 1.6;">
11
+ Hi <strong>{{adminName}}</strong>,
12
+ </p>
13
+ <p style="color: #555; line-height: 1.6;">
14
+ A user has confirmed their email address on the waitlist.
15
+ </p>
16
+
17
+ <div style="background-color: #f5f5f5; border-radius: 8px; padding: 20px; margin: 20px 0;">
18
+ <table style="width: 100%; border-collapse: collapse;">
19
+ <tr>
20
+ <td style="color: #888; padding: 8px 0; width: 120px; vertical-align: top;">Email:</td>
21
+ <td style="color: #333; padding: 8px 0;">
22
+ <a href="mailto:{{userEmail}}" style="color: #0066cc;"><strong>{{userEmail}}</strong></a>
23
+ </td>
24
+ </tr>
25
+ <tr>
26
+ <td style="color: #888; padding: 8px 0; vertical-align: top;">Confirmed at:</td>
27
+ <td style="color: #333; padding: 8px 0;">{{confirmedAt}}</td>
28
+ </tr>
29
+ </table>
30
+ </div>
31
+
32
+ {{#if questionnaire}}
33
+ <div style="margin: 20px 0;">
34
+ <p style="color: #888; margin-bottom: 8px; font-size: 14px;">Questionnaire responses:</p>
35
+ <div style="background-color: #fafafa; border-left: 4px solid #1a1a1a; padding: 15px; color: #333; line-height: 1.6; white-space: pre-wrap;">{{questionnaire}}</div>
36
+ </div>
37
+ {{/if}}
38
+
39
+ <div style="margin-top: 30px; text-align: center;">
40
+ <a href="{{dashboardLink}}" style="background: #1a1a1a; color: #fff; padding: 12px 24px; text-decoration: none; border-radius: 4px; display: inline-block;">
41
+ View Waitlist Dashboard
42
+ </a>
43
+ </div>
44
+ </div>
45
+ {{> footer}}
46
+ </body>
47
+ </html>
@@ -0,0 +1,30 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>Confirm Your Waitlist Registration</title>
6
+ </head>
7
+ <body style="margin:0; padding:0; background-color:#f4f4f4; font-family:Arial, sans-serif;">
8
+ <div style="width:100%; padding:20px; background-color:#f4f4f4;">
9
+ <div style="max-width:600px; margin:0 auto; background-color:#ffffff; padding:40px; border-radius:8px; text-align:center; border:1px solid #4A5568;">
10
+ {{> header}}
11
+ <div style="text-align:left;">
12
+ <div style="font-size:24px; color:#4A5568; margin-bottom:20px;">Confirm Your Waitlist Registration</div>
13
+ <div style="font-size:16px; color:#555555; margin-bottom:30px; line-height:1.5; text-align:left;">
14
+ <p style="margin:0;">Hello!</p>
15
+ <p style="margin:0; margin-top:10px;">Thank you for joining our waitlist!</p>
16
+ <p style="margin:0; margin-top:10px;">Please click the button below to confirm your email address and secure your spot.</p>
17
+ <p style="margin:0; margin-top:10px;">This link is valid until {{expirationDate}} at {{expirationTime}}.</p>
18
+ </div>
19
+ <div style="text-align:center; margin-bottom:20px; margin-top:75px;">
20
+ <a href="{{confirmationLink}}" style="display:inline-block; padding:12px 24px; font-size:16px; color:#ffffff; background-color:#4A5568; text-decoration:none; border-radius:4px;">Confirm Email</a>
21
+ </div>
22
+ <div style="font-size:14px; color:#888888; text-align:center; margin-top:20px;">
23
+ <p style="margin:0;">If you did not sign up for our waitlist, you can safely ignore this email.</p>
24
+ </div>
25
+ </div>
26
+ {{> footer}}
27
+ </div>
28
+ </div>
29
+ </body>
30
+ </html>
@@ -0,0 +1,29 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>You are Invited to Register!</title>
6
+ </head>
7
+ <body style="margin:0; padding:0; background-color:#f4f4f4; font-family:Arial, sans-serif;">
8
+ <div style="width:100%; padding:20px; background-color:#f4f4f4;">
9
+ <div style="max-width:600px; margin:0 auto; background-color:#ffffff; padding:40px; border-radius:8px; text-align:center; border:1px solid #4A5568;">
10
+ {{> header}}
11
+ <div style="text-align:left;">
12
+ <div style="font-size:24px; color:#4A5568; margin-bottom:20px;">You are Invited to Register!</div>
13
+ <div style="font-size:16px; color:#555555; margin-bottom:30px; line-height:1.5; text-align:left;">
14
+ <p style="margin:0; font-weight:600; color:#4A5568;">Great news! Your spot on the waitlist has been confirmed.</p>
15
+ <p style="margin:0; margin-top:10px;">You have been selected to join our platform. Click the button below to complete your registration.</p>
16
+ <p style="margin:0; margin-top:10px;">This invitation is valid until {{expirationDate}} at {{expirationTime}}.</p>
17
+ </div>
18
+ <div style="text-align:center; margin-bottom:20px; margin-top:75px;">
19
+ <a href="{{registrationLink}}" style="display:inline-block; padding:12px 24px; font-size:16px; color:#ffffff; background-color:#4A5568; text-decoration:none; border-radius:4px;">Complete Registration</a>
20
+ </div>
21
+ <div style="font-size:14px; color:#888888; text-align:center; margin-top:20px;">
22
+ <p style="margin:0;">We are excited to have you join us!</p>
23
+ </div>
24
+ </div>
25
+ {{> footer}}
26
+ </div>
27
+ </div>
28
+ </body>
29
+ </html>
@@ -0,0 +1,3 @@
1
+ <div style="background: #f5f5f5; padding: 20px; text-align: center; font-size: 12px; color: #666; font-family: Arial, sans-serif;">
2
+ <p style="margin: 0;">{{name}}</p>
3
+ </div>
@@ -0,0 +1,3 @@
1
+ <div style="background: #1a1a1a; padding: 20px; text-align: center;">
2
+ <h1 style="color: #fff; margin: 0; font-family: Arial, sans-serif;">{{name}}</h1>
3
+ </div>
@@ -506,6 +506,19 @@
506
506
  }
507
507
  }
508
508
  },
509
+ "subscription": {
510
+ "trial_expired_title": "Your Trial Has Expired",
511
+ "trial_expired_description": "Your 14-day free trial has ended. Subscribe to continue using {{name}}.",
512
+ "trial_expiring_title": "Trial Expiring Soon",
513
+ "trial_expiring_tooltip": "Your trial expires in {days} days. Subscribe now to keep your data.",
514
+ "subscribe_now": "Subscribe Now",
515
+ "delete_account": "Delete Account",
516
+ "delete_confirmation_title": "Delete Your Account?",
517
+ "delete_confirmation_description": "This action cannot be undone. All your data, photos, and settings will be permanently deleted.",
518
+ "delete_confirmation_prompt": "Type \"{companyName}\" to confirm",
519
+ "delete_button": "Delete Account Permanently",
520
+ "cancel": "Cancel"
521
+ },
509
522
  "content": {
510
523
  "news": "Recent Relevant Contents",
511
524
  "fields": {
@@ -5,7 +5,8 @@
5
5
  "scripts": {
6
6
  "build": "dotenv -e ../../.env -- next build",
7
7
  "dev": "dotenv -e ../../.env -- next dev",
8
- "lint": "eslint .",
8
+ "lint": "eslint . && pnpm validate-translations",
9
+ "validate-translations": "node scripts/validate-translations.mjs",
9
10
  "start": "dotenv -e ../../.env -- next start -H 0.0.0.0",
10
11
  "test": "vitest run",
11
12
  "test:coverage": "vitest run --coverage",
@@ -19,30 +20,30 @@
19
20
  "engines": {
20
21
  "node": "22"
21
22
  },
22
- "packageManager": "pnpm@10.28.1",
23
+ "packageManager": "pnpm@10.28.2",
23
24
  "dependencies": {
24
- "@aws-sdk/lib-storage": "^3.975.0",
25
- "@aws-sdk/s3-request-presigner": "^3.975.0",
26
- "@aws-sdk/xhr-http-handler": "^3.972.0",
25
+ "@aws-sdk/lib-storage": "^3.984.0",
26
+ "@aws-sdk/s3-request-presigner": "^3.984.0",
27
+ "@aws-sdk/xhr-http-handler": "^3.984.0",
27
28
  "@base-ui/react": "^1.1.0",
28
29
  "@carlonicora/nextjs-jsonapi": "workspace:*",
29
30
  "@dnd-kit/core": "^6.3.1",
30
31
  "@dnd-kit/modifiers": "^9.0.0",
31
32
  "@dnd-kit/sortable": "^10.0.0",
32
33
  "@dnd-kit/utilities": "^3.2.2",
33
- "@floating-ui/react": "^0.27.16",
34
+ "@floating-ui/react": "^0.27.17",
34
35
  "@hello-pangea/dnd": "^18.0.1",
35
36
  "@hookform/resolvers": "^5.2.2",
36
37
  "@mdx-js/loader": "^3.1.1",
37
38
  "@mdx-js/react": "^3.1.1",
38
- "@next/mdx": "^16.1.4",
39
- "@next/third-parties": "16.1.4",
39
+ "@next/mdx": "^16.1.6",
40
+ "@next/third-parties": "16.1.6",
40
41
  "@{{name}}/shared": "workspace:*",
41
- "@stripe/react-stripe-js": "^5.4.1",
42
- "@stripe/stripe-js": "^8.6.4",
42
+ "@stripe/react-stripe-js": "^5.6.0",
43
+ "@stripe/stripe-js": "^8.7.0",
43
44
  "@tanstack/react-table": "^8.21.3",
44
45
  "@types/mdx": "^2.0.13",
45
- "autoprefixer": "^10.4.23",
46
+ "autoprefixer": "^10.4.24",
46
47
  "class-variance-authority": "^0.7.1",
47
48
  "clsx": "^2.1.1",
48
49
  "cmdk": "^1.1.1",
@@ -50,38 +51,38 @@
50
51
  "cookies-next": "^6.1.1",
51
52
  "date-fns": "^4.1.0",
52
53
  "embla-carousel-react": "^8.6.0",
53
- "framer-motion": "^12.29.0",
54
+ "framer-motion": "^12.33.0",
54
55
  "fs": "^0.0.1-security",
55
56
  "fuse.js": "^7.1.0",
56
57
  "i18n-iso-countries": "^7.14.0",
57
- "i18next": "^25.8.0",
58
+ "i18next": "^25.8.4",
58
59
  "input-otp": "^1.4.2",
59
- "jotai": "^2.16.2",
60
+ "jotai": "^2.17.1",
60
61
  "jsonwebtoken": "^9.0.3",
61
62
  "jszip": "^3.10.1",
62
63
  "lodash": "^4.17.23",
63
64
  "lucide": "^0.563.0",
64
65
  "lucide-react": "^0.563.0",
65
- "mailparser": "^3.9.1",
66
+ "mailparser": "^3.9.3",
66
67
  "mammoth": "^1.11.0",
67
- "next": "16.1.4",
68
- "next-intl": "^4.7.0",
68
+ "next": "16.1.6",
69
+ "next-intl": "^4.8.2",
69
70
  "next-share": "^0.27.0",
70
71
  "next-themes": "^0.4.6",
71
72
  "pako": "^2.1.0",
72
73
  "papaparse": "^5.5.3",
73
- "pdfjs-dist": "^5.4.530",
74
+ "pdfjs-dist": "^5.4.624",
74
75
  "postal-mime": "^2.7.3",
75
- "react": "19.2.3",
76
+ "react": "19.2.4",
76
77
  "react-cookie": "8.0.1",
77
78
  "react-day-picker": "^9.13.0",
78
- "react-dom": "19.2.3",
79
- "react-dropzone": "^14.3.8",
79
+ "react-dom": "19.2.4",
80
+ "react-dropzone": "^14.4.0",
80
81
  "react-hook-form": "^7.71.1",
81
82
  "react-horizontal-scrolling-menu": "^8.2.0",
82
- "react-i18next": "^16.5.3",
83
+ "react-i18next": "^16.5.4",
83
84
  "react-masonry-css": "^1.0.16",
84
- "react-resizable-panels": "^4.5.2",
85
+ "react-resizable-panels": "^4.6.0",
85
86
  "react-spinners": "^0.17.0",
86
87
  "react-toastify": "^11.0.5",
87
88
  "recharts": "^3.7.0",
@@ -99,8 +100,8 @@
99
100
  "yjs": "^13.6.29"
100
101
  },
101
102
  "devDependencies": {
102
- "@next/eslint-plugin-next": "16.1.4",
103
- "@playwright/test": "^1.58.0",
103
+ "@next/eslint-plugin-next": "16.1.6",
104
+ "@playwright/test": "^1.58.1",
104
105
  "@tailwindcss/postcss": "^4",
105
106
  "@tailwindcss/typography": "^0.5.19",
106
107
  "@testing-library/dom": "^10.4.1",
@@ -117,14 +118,14 @@
117
118
  "@types/negotiator": "^0.6.4",
118
119
  "@types/pako": "^2.0.4",
119
120
  "@types/papaparse": "^5.5.2",
120
- "@types/react": "19.2.9",
121
+ "@types/react": "19.2.13",
121
122
  "@types/react-dom": "19.2.3",
122
123
  "@types/turndown": "^5.0.6",
123
- "@vitejs/plugin-react": "^5.1.2",
124
+ "@vitejs/plugin-react": "^5.1.3",
124
125
  "@vitest/coverage-v8": "^4.0.18",
125
- "dotenv": "^17.2.3",
126
+ "dotenv": "^17.2.4",
126
127
  "eslint": "^9.39.2",
127
- "eslint-config-next": "16.1.4",
128
+ "eslint-config-next": "16.1.6",
128
129
  "eslint-plugin-i18next": "^6.1.3",
129
130
  "eslint-plugin-react": "^7.37.5",
130
131
  "prettier-plugin-tailwindcss": "^0.7.2",