diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/frontend/.gitlab-ci.yml b/frontend/.gitlab-ci.yml new file mode 100644 index 0000000..589e155 --- /dev/null +++ b/frontend/.gitlab-ci.yml @@ -0,0 +1,115 @@ +image: node:22@sha256:f6b9c31ace05502dd98ef777aaa20464362435dcc5e312b0e213121dcf7d8b95 + +workflow: + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH == "production" + - if: $CI_COMMIT_BRANCH == "dev" + - if: $CI_COMMIT_TAG =~ /^v[\d]{1,4}\.[\d]{1,2}\.[\d]{1,2}$/ + +stages: + - build + - docker + - deploy + - sync + +cache: + key: ${CI_COMMIT_REF_SLUG} + paths: + - node_modules/ + - .next/cache/ + +variables: + NEXT_PUBLIC_ENV: "production" + OUTPUT_DIR: ".next" + PROJECT_NAME: $CI_PROJECT_NAME + DOCKER_IMAGE: "registry.boomlab.party/rheinsw/$CI_PROJECT_NAME" + +.deploy_production_rule: &deploy_production_rule + - if: $CI_COMMIT_BRANCH == "production" + when: manual + allow_failure: true + +# Reusable SSH key setup block +.install_deploy_key: &install_deploy_key + - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' + - mkdir -p ~/.ssh + - echo "$DEPLOY_KEY_BASE64" | base64 -d > ~/.ssh/deploy_key + - eval "$(ssh-agent -s)" + - chmod 600 ~/.ssh/deploy_key + - ssh-add ~/.ssh/deploy_key + - ssh-keyscan -p 22 -H '192.168.41.101' >> ~/.ssh/known_hosts || true + +.deploy_script: &deploy_script + - | + echo "Deploying $DOCKER_IMAGE:$TAG to $CONTAINER_NAME on port $PORT..." + + ssh gitlab@192.168.41.101 -p 22 " + echo \"$CI_REGISTRY_PASSWORD\" | docker login $CI_REGISTRY -u \"$CI_REGISTRY_USER\" --password-stdin && + docker pull $DOCKER_IMAGE:$TAG && + docker stop $CONTAINER_NAME || true && + docker rm $CONTAINER_NAME || true && + docker run -d --name $CONTAINER_NAME -p $PORT:3000 $DOCKER_IMAGE:$TAG + " + +build: + stage: build + script: + - npm install + - npx next build + - npm run lint + +dockerize: + stage: docker + image: docker:20.10@sha256:2967f0819c84dd589ed0a023b9d25dcfe7a3c123d5bf784ffbb77edf55335f0c + before_script: + - echo "$CI_REGISTRY_PASSWORD" | docker login "$CI_REGISTRY" -u "$CI_REGISTRY_USER" --password-stdin + script: + - | + RAW_TAG="$CI_COMMIT_REF_NAME" + TAG="${RAW_TAG//\//_}" # replaces "/" with "_" + echo "Sanitized tag: $TAG" + docker build -t $DOCKER_IMAGE:$TAG -f Dockerfile . + + if [[ "$RAW_TAG" == "dev" || "$RAW_TAG" == "production" ]]; then + echo "Pushing Docker image $DOCKER_IMAGE:$TAG" + docker push $DOCKER_IMAGE:$TAG + else + echo "Skipping Docker push for non-dev or production branch: $RAW_TAG" + fi + + +deploy_production: + stage: deploy + rules: *deploy_production_rule + before_script: *install_deploy_key + script: + - TAG="production" + - PORT="4100" + - CONTAINER_NAME="$CI_PROJECT_NAME-production" + - *deploy_script + +deploy_dev: + stage: deploy + before_script: *install_deploy_key + script: + - TAG="dev" + - PORT="5100" + - CONTAINER_NAME="$CI_PROJECT_NAME-dev" + - *deploy_script + only: + - dev + +sync_branches: + stage: sync + rules: + - if: '$CI_COMMIT_BRANCH == "production"' + before_script: + - git config --global user.email "gitlab-ci@rheinsw.com" + - git config --global user.name "GitLab CI" + script: + - git remote set-url origin "https://oauth2:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" + - git checkout dev + - git pull origin dev + - git merge --no-ff origin/production + - git push origin dev diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..f89869b --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,31 @@ +# Use lightweight Node.js 20 base image +FROM node:20-alpine@sha256:9bef0ef1e268f60627da9ba7d7605e8831d5b56ad07487d24d1aa386336d1944 as builder + +# Set working directory +WORKDIR /app + +# Copy package files separately for better Docker caching +COPY package.json package-lock.json ./ + +# Install dependencies +RUN npm ci + +# Copy entire project +COPY . . + +# Build the Next.js app +RUN npm run build + +# Use a minimal base image for running the app +FROM node:20-alpine@sha256:9bef0ef1e268f60627da9ba7d7605e8831d5b56ad07487d24d1aa386336d1944 + +WORKDIR /app + +# Copy built files from the builder stage +COPY --from=builder /app ./ + +# Expose port +EXPOSE 3000 + +# Start Next.js in production mode +CMD ["npm", "run", "start"] diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,36 @@ +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). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +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. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [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. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +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. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/frontend/app/(root)/favicon.ico b/frontend/app/(root)/favicon.ico new file mode 100644 index 0000000..718d6fe Binary files /dev/null and b/frontend/app/(root)/favicon.ico differ diff --git a/frontend/app/(root)/layout.tsx b/frontend/app/(root)/layout.tsx new file mode 100644 index 0000000..518d45e --- /dev/null +++ b/frontend/app/(root)/layout.tsx @@ -0,0 +1,37 @@ +import type {Metadata} from "next"; +import "../globals.css"; + +import Nav from "@/components/Navbar/Nav"; +import Footer from "@/components/Footer/Footer"; +import {ThemeProvider} from "@/components/provider/ThemeProvider"; +import React from "react"; +import {cookies} from "next/headers"; +import {themeColors} from "@/components/Helper/ThemeColors"; + +export const metadata: Metadata = { + title: "Rhein Software", + description: "Rhein Software Development", +}; + +export default async function RootLayout({ + children, + }: Readonly<{ + children: React.ReactNode; +}>) { + const cookieStore = await cookies(); + const theme = cookieStore.get("theme")?.value === "dark" ? "dark" : "light"; + const bgColor = themeColors[theme].primaryBg; + + return ( + + + + +