Adapt for self-hosted deployment on Coolify

- Replace @vercel/postgres with standard pg library
- Add Dockerfile for Next.js standalone build
- Add tsconfig.json, postcss.config.js
- Fix globals.css undefined tailwind utilities
- Force dynamic rendering for DB-dependent pages
- Add .dockerignore
This commit is contained in:
Min Zeya Phyo
2026-02-19 16:51:31 +08:00
parent dddb86ea94
commit 98af1c7cec
11 changed files with 112 additions and 10 deletions

7
.dockerignore Normal file
View File

@@ -0,0 +1,7 @@
node_modules
.next
.git
*.md
backend
database
.github

47
Dockerfile Normal file
View File

@@ -0,0 +1,47 @@
FROM node:18-alpine AS base
# Install dependencies only when needed
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY frontend/package.json frontend/package-lock.json* ./
RUN npm ci 2>/dev/null || npm install
# Build the application
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY frontend/ .
# Need DATABASE_URL at build time for Next.js static generation (can be dummy)
ARG DATABASE_URL=postgresql://localhost/burmddit
ENV DATABASE_URL=${DATABASE_URL}
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
# Production image
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# Copy public assets
COPY --from=builder /app/public ./public
# Copy standalone build
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]

View File

@@ -1,5 +1,7 @@
import { sql } from '@vercel/postgres' import { sql } from '@/lib/db'
import { notFound } from 'next/navigation' import { notFound } from 'next/navigation'
export const dynamic = 'force-dynamic'
import Link from 'next/link' import Link from 'next/link'
import Image from 'next/image' import Image from 'next/image'

View File

@@ -3,11 +3,8 @@
@tailwind utilities; @tailwind utilities;
@layer base { @layer base {
* {
@apply border-border;
}
body { body {
@apply bg-background text-foreground; @apply bg-gray-50 text-gray-900;
} }
} }

View File

@@ -1,5 +1,7 @@
import { sql } from '@vercel/postgres' import { sql } from '@/lib/db'
import ArticleCard from '@/components/ArticleCard' import ArticleCard from '@/components/ArticleCard'
export const dynamic = 'force-dynamic'
import TrendingSection from '@/components/TrendingSection' import TrendingSection from '@/components/TrendingSection'
import CategoryNav from '@/components/CategoryNav' import CategoryNav from '@/components/CategoryNav'

16
frontend/lib/db.ts Normal file
View File

@@ -0,0 +1,16 @@
import { Pool } from 'pg'
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
})
// Tagged template literal that mimics @vercel/postgres sql`` syntax
export async function sql(strings: TemplateStringsArray, ...values: any[]) {
// Build parameterized query: replace template expressions with $1, $2, etc.
let text = strings[0]
for (let i = 0; i < values.length; i++) {
text += `$${i + 1}` + strings[i + 1]
}
const result = await pool.query(text, values)
return result
}

View File

@@ -1,5 +1,6 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {
output: 'standalone',
images: { images: {
remotePatterns: [ remotePatterns: [
{ {
@@ -8,9 +9,6 @@ const nextConfig = {
}, },
], ],
}, },
experimental: {
serverActions: true,
},
} }
module.exports = nextConfig module.exports = nextConfig

View File

@@ -14,7 +14,7 @@
"react": "^18", "react": "^18",
"react-dom": "^18", "react-dom": "^18",
"pg": "^8.11.3", "pg": "^8.11.3",
"@vercel/postgres": "^0.5.1" "@types/pg": "^8.10.9"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20", "@types/node": "^20",

View File

@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

0
frontend/public/.gitkeep Normal file
View File

27
frontend/tsconfig.json Normal file
View File

@@ -0,0 +1,27 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}