fix: Docker build and runtime fixes
- Fix duplicate 'signature' variable in webhooks.ts - Add Prisma binary target for Alpine Linux - Fix tsconfig path alias (@/* -> ./src/*) - Add missing next-themes dependency - Add build args for NEXT_PUBLIC_* env vars - Fix SSR issues with zustand and providers - Add providers-wrapper with dynamic ssr:false import - Add SSL certs and public dir for nginx - Update Dockerfiles for proper Prisma engine handling
This commit is contained in:
+9
-2
@@ -4,7 +4,7 @@ FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
|
||||
# Install build tools for native modules
|
||||
RUN apk add --no-cache python3 make g++
|
||||
RUN apk add --no-cache python3 make g++ libusb-dev eudev-dev linux-headers
|
||||
|
||||
# Copy root package files for workspace install
|
||||
COPY package*.json ./
|
||||
@@ -16,9 +16,16 @@ RUN npm install --legacy-peer-deps
|
||||
# Copy frontend source
|
||||
COPY frontend/ ./frontend/
|
||||
|
||||
# Build args for Next.js
|
||||
ARG NEXT_PUBLIC_API_URL
|
||||
ARG NEXT_PUBLIC_SOLANA_NETWORK
|
||||
ARG NEXT_PUBLIC_SOLANA_RPC_URL
|
||||
|
||||
# Build Next.js app
|
||||
WORKDIR /app/frontend
|
||||
RUN npm run build
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ENV NODE_OPTIONS="--max-old-space-size=4096"
|
||||
RUN npx next build --webpack
|
||||
|
||||
# Production stage
|
||||
FROM node:20-alpine
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const path = require('path');
|
||||
|
||||
const nextConfig = {
|
||||
experimental: {
|
||||
appDir: true,
|
||||
webpack: (config) => {
|
||||
config.resolve.alias['@'] = path.join(__dirname, 'src');
|
||||
config.parallelism = 1;
|
||||
return config;
|
||||
},
|
||||
async rewrites() {
|
||||
return [
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"clsx": "^2.0.0",
|
||||
"lucide-react": "^0.294.0",
|
||||
"next": "^16.2.3",
|
||||
"next-themes": "^0.2.1",
|
||||
"react": "^19.2.5",
|
||||
"react-dom": "^19.2.5",
|
||||
"recharts": "^2.10.3",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Metadata } from 'next';
|
||||
import { Inter } from 'next/font/google';
|
||||
import './globals.css';
|
||||
import { Providers } from '@/components/providers';
|
||||
import { ProvidersWrapper } from '@/components/providers-wrapper';
|
||||
import { Toaster } from 'sonner';
|
||||
|
||||
const inter = Inter({ subsets: ['latin'] });
|
||||
@@ -19,10 +19,10 @@ export default function RootLayout({
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<body className={inter.className}>
|
||||
<Providers>
|
||||
<ProvidersWrapper>
|
||||
{children}
|
||||
<Toaster position="top-right" />
|
||||
</Providers>
|
||||
</ProvidersWrapper>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
'use client';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useRouter, useSearchParams } from 'next/navigation';
|
||||
import { authApi } from '@/lib/api';
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
'use client';
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
const DynamicProviders = dynamic(
|
||||
() => import('./providers').then((mod) => ({ default: mod.Providers })),
|
||||
{ ssr: false }
|
||||
);
|
||||
|
||||
export function ProvidersWrapper({ children }: { children: ReactNode }) {
|
||||
return <DynamicProviders>{children}</DynamicProviders>;
|
||||
}
|
||||
+10
-20
@@ -1,5 +1,4 @@
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
@@ -21,22 +20,13 @@ interface AppState {
|
||||
logout: () => void;
|
||||
}
|
||||
|
||||
export const useStore = create<AppState>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
user: null,
|
||||
token: null,
|
||||
isAuthenticated: false,
|
||||
setUser: (user) => set({ user, isAuthenticated: !!user }),
|
||||
setToken: (token) => set({ token }),
|
||||
logout: () => {
|
||||
localStorage.removeItem('token');
|
||||
set({ user: null, token: null, isAuthenticated: false });
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: 'coop-credits-storage',
|
||||
partialize: (state) => ({ user: state.user, token: state.token }),
|
||||
}
|
||||
)
|
||||
);
|
||||
export const useStore = create<AppState>()((set) => ({
|
||||
user: null,
|
||||
token: null,
|
||||
isAuthenticated: false,
|
||||
setUser: (user) => set({ user, isAuthenticated: !!user }),
|
||||
setToken: (token) => set({ token }),
|
||||
logout: () => {
|
||||
set({ user: null, token: null, isAuthenticated: false });
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": ["./*"]
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
|
||||
Reference in New Issue
Block a user