diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..a9a5bac --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +node_modules +.next +.git +.github +vite.log +vite.err.log +Dockerfile +docker-compose.yml +npm-debug.log +pnpm-debug.log diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 25c1826..46f167c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,3 +28,54 @@ jobs: - name: Build Next.js app run: pnpm run build + push-image: + needs: build + runs-on: ubuntu-latest + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + steps: + - name: checkout + uses: actions/checkout@v4 + + - name: setup buildx + uses: docker/setup-buildx-action@v3 + + - name: log in to harbor + uses: docker/login-action@v3 + with: + registry: registry.reversed.dev + username: ${{ secrets.HARBOR_USERNAME }} + password: ${{ secrets.HARBOR_PASSWORD }} + + - name: build and push image + uses: docker/build-push-action@v6 + with: + context: . + push: true + provenance: false + sbom: false + tags: | + registry.reversed.dev/my-portfolio/my-portfolio:latest + registry.reversed.dev/my-portfolio/my-portfolio:${{ github.sha }} + + deploy-coolify: + needs: push-image + runs-on: ubuntu-latest + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + steps: + - name: wait 5 seconds before redeploy + run: sleep 5 + + - name: Redeploy Coolify + run: | + response_file="$(mktemp)" + http_code="$(curl -sS -o "$response_file" -w "%{http_code}" -X GET "${{ secrets.COOLIFY_WEBHOOK }}" \ + -H "Authorization: Bearer ${{ secrets.COOLIFY_TOKEN }}")" + + echo "Coolify webhook HTTP status: $http_code" + echo "Coolify webhook response body:" + cat "$response_file" + + if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then + echo "Redeploy request failed with non-2xx status." + exit 1 + fi \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..dc99c3b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +FROM node:24-alpine AS base +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable + +FROM base AS deps +WORKDIR /app +COPY package.json pnpm-lock.yaml ./ +RUN pnpm install --frozen-lockfile + +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . +RUN pnpm build + +FROM node:24-alpine AS runner +WORKDIR /app +ENV NODE_ENV=production +ENV PORT=3000 +ENV HOSTNAME=0.0.0.0 + +RUN addgroup -S nodejs && adduser -S nextjs -G nodejs + +COPY --from=builder /app/public ./public +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 +CMD ["node", "server.js"] diff --git a/README.md b/README.md index e215bc4..9267a36 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,64 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# My Portfolio -## Getting Started +Personal portfolio built with Next.js, React, TypeScript, and Tailwind CSS. -First, run the development server: +## What It Includes + +- Hero section with typing intro +- Work experience and skills sections +- Uptime and activity panels +- Project and mini-project showcases +- Contact page and admin page + +## Development + +Install dependencies: ```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev +pnpm install ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +Run the development server: -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +```bash +pnpm dev +``` -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +Open [http://localhost:3000](http://localhost:3000) in your browser. -## Learn More +## Production Build -To learn more about Next.js, take a look at the following resources: +Create a production build: -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +```bash +pnpm build +``` -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +Start the production server locally: -## Deploy on Vercel +```bash +pnpm start +``` -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +## Docker -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +This project includes a standalone Docker image setup. + +Build the image: + +```bash +docker build -t my-portfolio:latest . +``` + +Run with Docker Compose: + +```bash +docker compose up --build +``` + +The app will be available on port `6756` via `docker-compose.yml`. + +## Notes + +- `next.config.ts` uses `output: "standalone"` so the Docker image can ship a minimal runtime. +- The activity graph on the home page is loaded from a remote SVG source. diff --git a/docker-compose.yml b/docker-compose.yml index 3df7385..e171eb5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,16 +1,9 @@ services: app: - image: node:24 - working_dir: /app - volumes: - - .:/app + build: + context: . + dockerfile: Dockerfile + image: my-portfolio:latest restart: always ports: - "6756:3000" - command: > - sh -c " - npm i -g pnpm && - pnpm install && - pnpm build && - pnpm start - " \ No newline at end of file diff --git a/next.config.ts b/next.config.ts index e9ffa30..68a6c64 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,7 +1,7 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { - /* config options here */ + output: "standalone", }; export default nextConfig; diff --git a/src/sections/Activity.tsx b/src/sections/Activity.tsx index 76a64b8..c6bf8a0 100644 --- a/src/sections/Activity.tsx +++ b/src/sections/Activity.tsx @@ -16,13 +16,7 @@ export function Activity() {
- +
Git activity graph - +
);