commit 5420eb6f41967c9bfd4640928816ca5b547f5be3 Author: vitaliimulika-dev Date: Fri Jan 16 13:20:49 2026 +0200 Initial commit diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..02269f0 --- /dev/null +++ b/.env.production @@ -0,0 +1 @@ +DISABLE_ESLINT_PLUGIN=true diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..8687ee0 --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,62 @@ +name: Build + +on: + workflow_dispatch: + inputs: + branch: + description: 'Branch to build' + required: true + default: 'main' + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Checkout branch + uses: actions/checkout@v3 + with: + ref: ${{ gitea.event.inputs.branch }} + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 24 + + - name: Install dependencies + run: | + set -euo pipefail + npm install --no-audit --silent 2>&1 | tee install.log + env: + NODE_OPTIONS: '--max-old-space-size=4096' + + - name: Build (react-scripts build) + env: + CI: 'false' + NODE_OPTIONS: '--max-old-space-size=4096' + run: | + set -euo pipefail + npm run build 2>&1 | tee build.log + timeout-minutes: 5 + + - name: Verify build folder exists + run: test -d build || (echo "No build folder. Check build logs above."; exit 1) + + - name: Upload logs on failure + if: failure() + uses: actions/upload-artifact@v3 + with: + name: build-logs + path: | + install.log + build.log + npm-debug.log* + if-no-files-found: ignore + + - name: Build completed + if: success() + run: echo "Build completed successfully" diff --git a/package.json b/package.json new file mode 100644 index 0000000..64b9aae --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "nestjs-jobs-website", + "version": "0.1.0", + "private": true, + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-scripts": "^5.0.1", + "lucide-react": "^0.400.0", + "framer-motion": "^11.0.0" + }, + "devDependencies": { + "tailwindcss": "^3.4.0", + "postcss": "^8.4.0", + "autoprefixer": "^10.4.0" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} \ No newline at end of file diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..90d08b4 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +} \ No newline at end of file diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..70c8f41 --- /dev/null +++ b/public/index.html @@ -0,0 +1,1235 @@ + + + + + + + + + + + + NestJS Jobs - Official Job Board + + + +
+ + + + + \ No newline at end of file diff --git a/src/App.js b/src/App.js new file mode 100644 index 0000000..f38a900 --- /dev/null +++ b/src/App.js @@ -0,0 +1,26 @@ +import React from 'react'; +import Header from './components/Header'; +import Hero from './components/Hero'; +import JobsSection from './components/JobsSection'; +import TeamAugmentation from './components/TeamAugmentation'; +import CompaniesSection from './components/CompaniesSection'; +import SupportSection from './components/SupportSection'; +import NewsletterSection from './components/NewsletterSection'; +import Footer from './components/Footer'; + +function App() { + return ( +
+
+ + + + + + +
+
+ ); +} + +export default App; \ No newline at end of file diff --git a/src/components/CompaniesSection.js b/src/components/CompaniesSection.js new file mode 100644 index 0000000..6edd7ec --- /dev/null +++ b/src/components/CompaniesSection.js @@ -0,0 +1,83 @@ +import React from 'react'; +import { motion } from 'framer-motion'; + +const CompaniesSection = () => { + const companies = [ + { name: 'Sanofi', logo: 'https://www.jobs.nestjs.com/img/logos/sanofi.png', url: 'https://www.sanofi.com/' }, + { name: 'IBM', logo: 'https://www.jobs.nestjs.com/img/logos/ibm.svg', url: 'https://www.ibm.com/' }, + { name: 'BMW', logo: 'https://www.jobs.nestjs.com/img/logos/bmw.svg' }, + { name: 'Mercedes', logo: 'https://www.jobs.nestjs.com/img/logos/mercedes.png', url: 'https://www.mercedes-benz.com/' }, + { name: 'Société Générale', logo: 'https://www.jobs.nestjs.com/img/logos/societe-generale-logo.png', url: 'https://www.societegenerale.fr/' }, + { name: 'Decathlon', logo: 'https://www.jobs.nestjs.com/img/logos/decathlon.png', url: 'https://www.decathlon.com/' }, + { name: 'GitLab', logo: 'https://www.jobs.nestjs.com/img/logos/gitlab.png', url: 'https://about.gitlab.com/' }, + { name: 'Roche', logo: 'https://www.jobs.nestjs.com/img/logos/roche-logo.png', url: 'https://roche.com/' }, + { name: 'Adidas', logo: 'https://www.jobs.nestjs.com/img/logos/adidas.svg', url: 'https://adidas.com/' }, + { name: 'JetBrains', logo: 'https://www.jobs.nestjs.com/img/logos/jetbrains.svg', url: 'https://www.jetbrains.com/' }, + { name: 'TotalEnergies', logo: 'https://www.jobs.nestjs.com/img/logos/totalenergies.svg', url: 'https://totalenergies.com/' }, + { name: 'Autodesk', logo: 'https://www.jobs.nestjs.com/img/logos/autodesk.png', url: 'https://www.autodesk.com/' }, + { name: 'Red Hat', logo: 'https://www.jobs.nestjs.com/img/logos/red-hat.svg', url: 'https://www.redhat.com/' }, + { name: 'REWE', logo: 'https://www.jobs.nestjs.com/img/logos/rewe.svg', url: 'https://www.rewe-digital.com/' }, + { name: 'Capgemini', logo: 'https://www.jobs.nestjs.com/img/logos/capgemini.svg', url: 'https://capgemini.com/' } + ]; + + const CompanyLogo = ({ company }) => { + const logoElement = ( + {`${company.name} + ); + + if (company.url) { + return ( + + {logoElement} + + ); + } + + return logoElement; + }; + + return ( +
+
+ +

+ Who is using Nest? +

+

+ Nest is proudly powering a large ecosystem of enterprises and products out there. Wanna see your logo here? Find out more. +

+
+ + + {companies.map((company, index) => ( + + + + ))} + +
+
+ ); +}; + +export default CompaniesSection; \ No newline at end of file diff --git a/src/components/Footer.js b/src/components/Footer.js new file mode 100644 index 0000000..bd2133f --- /dev/null +++ b/src/components/Footer.js @@ -0,0 +1,53 @@ +import React from 'react'; +import { Github } from 'lucide-react'; + +const Footer = () => { + return ( + + ); +}; + +export default Footer; \ No newline at end of file diff --git a/src/components/Header.js b/src/components/Header.js new file mode 100644 index 0000000..2372047 --- /dev/null +++ b/src/components/Header.js @@ -0,0 +1,70 @@ +import React, { useState } from 'react'; +import { Menu, X, Github } from 'lucide-react'; + +const Header = () => { + const [isMenuOpen, setIsMenuOpen] = useState(false); + + return ( +
+
+
+ {/* Logo */} +
+ + NestJS - A progressive Node.js framework + +
+ + {/* Desktop Navigation */} + + + {/* Mobile menu button */} +
+ +
+
+ + {/* Mobile Navigation */} + {isMenuOpen && ( +
+
+ HOME + JOBS + SIGN IN + RESOURCES +
+
+ )} +
+
+ ); +}; + +export default Header; \ No newline at end of file diff --git a/src/components/Hero.js b/src/components/Hero.js new file mode 100644 index 0000000..d61ee0b --- /dev/null +++ b/src/components/Hero.js @@ -0,0 +1,48 @@ +import React from 'react'; +import { motion } from 'framer-motion'; + +const Hero = () => { + return ( +
+ {/* Dark overlay */} +
+ + {/* Content */} +
+ + Official NestJS job board + + + + Discover companies looking for developers with NestJS experience and find your next role. + + + + + + +
+
+ ); +}; + +export default Hero; \ No newline at end of file diff --git a/src/components/JobsSection.js b/src/components/JobsSection.js new file mode 100644 index 0000000..0f1c709 --- /dev/null +++ b/src/components/JobsSection.js @@ -0,0 +1,190 @@ +import React from 'react'; +import { motion } from 'framer-motion'; +import { Search, Globe, MapPin, DollarSign } from 'lucide-react'; + +const JobsSection = () => { + const jobs = [ + { + id: 1, + title: "Senior Software Engineer", + company: "Trilon", + location: "Remote", + region: "🌏 Worldwide", + featured: true, + timeAgo: "a month ago", + logo: "https://nestjs-jobs-bucket-localhost.s3.amazonaws.com/65dc7731-a4bb-4bbe-bc20-7401691a9ec5.png" + }, + { + id: 2, + title: "Senior Product Engineer", + company: "Pandektes", + location: "Remote", + region: "🇩🇰 Denmark", + salary: "$120k - $150k", + timeAgo: "a day ago", + logo: "https://nestjs-jobs-bucket-localhost.s3.amazonaws.com/612b8b42-9610-43b1-92bd-15373110159f.png" + } + ]; + + const expiredJobs = [ + { + id: 3, + title: "Full-Stack Developer Angular/NestJS/PHP/MySQL", + company: "Nylon Technology", + location: "Remote", + region: "🇺🇸 United States, Continental...", + salary: "$100k - $130k", + timeAgo: "a month ago" + }, + { + id: 4, + title: "Full Stack Typescript Developer (NextJs, NestJs)", + company: "ClickTech", + location: "Remote", + region: "🌏 Worldwide", + salary: "$40k - $50k", + timeAgo: "2 months ago" + }, + { + id: 5, + title: "NestJS Testing Specialist (Freelancer/Consultant)", + company: "Kapital", + location: "🌏 Worldwide", + timeAgo: "2 months ago" + }, + { + id: 6, + title: "Full-Stack Engineer (Mid-Senior) [NestJS, NextJS]", + company: "OASYS NOW", + location: "🇳🇱 Netherlands, Delft", + salary: "$60k - $80k", + timeAgo: "2 months ago" + } + ]; + + const JobCard = ({ job, isExpired = false }) => ( + +
+ {job.logo && ( + {`${job.company} + )} +
+
+

{job.title}

+ {job.featured && ( + + ✨ FEATURED + + )} +
+

at {job.company}

+
+ + + {job.location} + + {job.region} + {job.salary && ( + + + {job.salary} + + )} + {job.timeAgo} +
+
+
+
+ ); + + return ( +
+
+ {/* Header */} + +

+ Find your next opportunity +

+

+ Browse through our list of NestJS jobs, find your perfect match and apply. Use filters for more accurate results! +

+
+ + {/* Newsletter Signup */} + +
+
+

Get NestJS jobs right to your inbox

+

Subscribe to our newsletter to get notified.

+
+
+ + +
+
+
+ + {/* Filter Icons */} + + + + 🥁 + 📈 + + + {/* Active Jobs */} +
+ {jobs.map((job) => ( + + ))} +
+ + {/* Expired Jobs */} + +

Expired listings

+
+ {expiredJobs.map((job) => ( + + ))} +
+
+
+
+ ); +}; + +export default JobsSection; \ No newline at end of file diff --git a/src/components/NewsletterSection.js b/src/components/NewsletterSection.js new file mode 100644 index 0000000..604df69 --- /dev/null +++ b/src/components/NewsletterSection.js @@ -0,0 +1,48 @@ +import React from 'react'; +import { motion } from 'framer-motion'; + +const NewsletterSection = () => { + return ( +
+
+ + Join our Newsletter + + + + Subscribe to stay up to date with the latest Nest updates, features, and videos! + + + + + + +
+
+ ); +}; + +export default NewsletterSection; \ No newline at end of file diff --git a/src/components/SupportSection.js b/src/components/SupportSection.js new file mode 100644 index 0000000..a913aaf --- /dev/null +++ b/src/components/SupportSection.js @@ -0,0 +1,41 @@ +import React from 'react'; +import { motion } from 'framer-motion'; + +const SupportSection = () => { + return ( +
+
+ + Does your team need additional support? + + + + Nest core team members can work directly with your team on a daily basis to help take your project to the next-level. Let us partner with you and your team to develop the most ambitious projects. + + + + Contact us + +
+
+ ); +}; + +export default SupportSection; \ No newline at end of file diff --git a/src/components/TeamAugmentation.js b/src/components/TeamAugmentation.js new file mode 100644 index 0000000..0d0d3e5 --- /dev/null +++ b/src/components/TeamAugmentation.js @@ -0,0 +1,44 @@ +import React from 'react'; +import { motion } from 'framer-motion'; + +const TeamAugmentation = () => { + return ( +
+ {/* Dark overlay */} +
+ +
+ + Team augmentation. By your side at every step + + + + Nest core team members can work directly with your team on a daily basis to help take your project to the next-level. Let us partner with you and your team to develop the most ambitious projects. + + + + Contact us to learn more + +
+
+ ); +}; + +export default TeamAugmentation; \ No newline at end of file diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..e9cf7c2 --- /dev/null +++ b/src/index.css @@ -0,0 +1,56 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --background: #ffffff; + --card: #f9f9f9; + --foreground: #000612e6; + --primary-cta: #e91e63; + --secondary-cta: #f9f9f9; + --accent: #e2e2e2; + --background-accent: #c4c4c4; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.btn-primary { + @apply bg-primary-cta text-white px-6 py-3 rounded-theme font-medium hover:opacity-90 transition-opacity; +} + +.btn-secondary { + @apply bg-transparent border border-white text-white px-6 py-3 rounded-theme font-medium hover:bg-white hover:text-foreground transition-colors; +} + +.job-card { + @apply bg-card border border-accent rounded-theme p-4 hover:shadow-lg transition-shadow; +} + +.company-logo { + @apply w-24 h-12 object-contain grayscale hover:grayscale-0 transition-all; +} + +.hero-bg { + background-image: url('https://www.jobs.nestjs.com/assets/header-2-CGRpDzPN.jpg'); + background-size: cover; + background-position: center; + background-repeat: no-repeat; +} + +.support-bg { + background-image: url('https://www.jobs.nestjs.com/assets/support-ChYF6me3.jpg'); + background-size: cover; + background-position: center; + background-repeat: no-repeat; +} \ No newline at end of file diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..0881df3 --- /dev/null +++ b/src/index.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import './index.css'; +import App from './App'; + +const container = document.getElementById('root'); +const root = createRoot(container); + +root.render( + + + +); \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..3139031 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,35 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + "./src/**/*.{js,jsx,ts,tsx}", + "./public/index.html" + ], + theme: { + extend: { + colors: { + background: 'var(--background)', + card: 'var(--card)', + foreground: 'var(--foreground)', + 'primary-cta': 'var(--primary-cta)', + 'secondary-cta': 'var(--secondary-cta)', + accent: 'var(--accent)', + 'background-accent': 'var(--background-accent)' + }, + fontFamily: { + sans: ['Inter', 'system-ui', 'sans-serif'] + }, + borderRadius: { + 'theme': '0.5rem', + 'theme-capped': '1rem' + }, + spacing: { + '18': '4.5rem', + '88': '22rem', + '100': '25rem', + '112': '28rem', + '128': '32rem' + } + } + }, + plugins: [] +} \ No newline at end of file diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..760984a --- /dev/null +++ b/vercel.json @@ -0,0 +1,5 @@ +{ + "installCommand": "npm install", + "buildCommand": "CI=false npm run build", + "outputDirectory": "build" +} \ No newline at end of file