Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
import type { NextConfig } from 'next';
|
|
|
|
|
|
2026-05-06 15:16:47 +02:00
|
|
|
const isProd = process.env.NODE_ENV === 'production';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Security headers applied to every response. Per audit-pass-#3 finding:
|
|
|
|
|
* the previous config emitted no CSP, X-Frame-Options, HSTS, or
|
|
|
|
|
* X-Content-Type-Options — the app was open to clickjacking + MIME
|
|
|
|
|
* sniffing.
|
|
|
|
|
*
|
|
|
|
|
* CSP notes:
|
|
|
|
|
* - 'unsafe-inline' on style-src is required by Tailwind's runtime
|
|
|
|
|
* style injection and Radix; revisit when Tailwind v4 ships a
|
|
|
|
|
* nonce story.
|
|
|
|
|
* - 'unsafe-eval' on script-src is dev-only — Next dev uses eval for
|
|
|
|
|
* HMR. Production drops it.
|
|
|
|
|
* - connect-src allows ws/wss for Socket.IO and https: for outgoing
|
|
|
|
|
* fetches; tighten in prod via per-port branding URLs once we move
|
|
|
|
|
* the s3 image references into a known allowlist.
|
|
|
|
|
* - img-src https: is wide because port branding pulls from
|
|
|
|
|
* s3.portnimara.com plus per-port image URLs configured at runtime.
|
|
|
|
|
*/
|
|
|
|
|
const csp = [
|
|
|
|
|
"default-src 'self'",
|
|
|
|
|
`script-src 'self' 'unsafe-inline'${isProd ? '' : " 'unsafe-eval'"}`,
|
|
|
|
|
"style-src 'self' 'unsafe-inline'",
|
|
|
|
|
"img-src 'self' data: blob: https:",
|
|
|
|
|
"font-src 'self' data:",
|
|
|
|
|
"connect-src 'self' ws: wss: https:",
|
|
|
|
|
"frame-ancestors 'none'",
|
|
|
|
|
"base-uri 'self'",
|
|
|
|
|
"form-action 'self'",
|
|
|
|
|
"object-src 'none'",
|
|
|
|
|
].join('; ');
|
|
|
|
|
|
|
|
|
|
const securityHeaders = [
|
|
|
|
|
{ key: 'Content-Security-Policy', value: csp },
|
|
|
|
|
{ key: 'X-Frame-Options', value: 'DENY' },
|
|
|
|
|
{ key: 'X-Content-Type-Options', value: 'nosniff' },
|
|
|
|
|
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
|
|
|
|
|
{ key: 'Permissions-Policy', value: 'camera=(self), microphone=(), geolocation=()' },
|
|
|
|
|
...(isProd
|
|
|
|
|
? [{ key: 'Strict-Transport-Security', value: 'max-age=31536000; includeSubDomains' }]
|
|
|
|
|
: []),
|
|
|
|
|
];
|
|
|
|
|
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
const nextConfig: NextConfig = {
|
|
|
|
|
output: 'standalone',
|
|
|
|
|
serverExternalPackages: [
|
|
|
|
|
'pino',
|
|
|
|
|
'pino-pretty',
|
|
|
|
|
'bullmq',
|
|
|
|
|
'ioredis',
|
|
|
|
|
'minio',
|
|
|
|
|
'postgres',
|
|
|
|
|
'better-auth',
|
|
|
|
|
'nodemailer',
|
|
|
|
|
],
|
|
|
|
|
images: {
|
|
|
|
|
remotePatterns: [{ protocol: 'https', hostname: '*.portnimara.com' }],
|
|
|
|
|
},
|
|
|
|
|
experimental: {
|
|
|
|
|
typedRoutes: true,
|
|
|
|
|
},
|
feat(eoi): in-app pathway fills the same source PDF as Documenso
When the in-app pathway is used for EOI templates, we now load the same
source PDF that the Documenso template uploads and fill its AcroForm
fields with values from EoiContext via pdf-lib. Field names mirror the
Documenso template's formValues keys exactly (Name, Email, Address,
Yacht Name, Length, Width, Draft, Berth Number + Lease_10 / Purchase
checkboxes), so both pathways produce equivalent legal documents — only
the renderer differs.
The form is left interactive (not flattened) so a recipient can still
adjust values before signing. Non-EOI templates (welcome letters,
acknowledgments, etc.) keep using the existing HTML→pdfme path.
Adds:
- pdf-lib direct dep
- src/lib/pdf/fill-eoi-form.ts — load + fill helpers, EOI_TEMPLATE_PDF_PATH
env override
- assets/ + README documenting the expected source PDF
- next.config outputFileTracingIncludes so the asset is bundled in the
standalone build
Tests: 8 new (4 fill-form unit + 2 source-PDF route + 2 fallback);
645/645 green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 13:38:02 +02:00
|
|
|
outputFileTracingIncludes: {
|
|
|
|
|
// Bundle the EOI source PDF so the in-app EOI pathway can read it at
|
|
|
|
|
// runtime in the standalone build. Reading via fs.readFile from
|
|
|
|
|
// process.cwd() requires the file to be traced explicitly.
|
|
|
|
|
'/api/v1/document-templates/**': ['./assets/eoi-template.pdf'],
|
|
|
|
|
},
|
2026-05-06 15:16:47 +02:00
|
|
|
async headers() {
|
|
|
|
|
return [
|
|
|
|
|
{
|
|
|
|
|
source: '/:path*',
|
|
|
|
|
headers: securityHeaders,
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default nextConfig;
|