Compare commits

..

30 Commits

Author SHA1 Message Date
e994d79895 chore: release 2.2.13-rc.2
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 34s
Build & Deploy / 🧪 QA (push) Successful in 1m4s
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
Build & Deploy / 🏗️ Build (push) Has been cancelled
2026-06-16 13:57:24 +02:00
88e88c8b99 fix: restore large project pins on the reference map 2026-06-16 13:57:24 +02:00
e2a29b41e9 chore: release 2.2.13-rc.1
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 23s
Build & Deploy / 🧪 QA (push) Successful in 58s
Build & Deploy / 🏗️ Build (push) Successful in 1m36s
Build & Deploy / 🚀 Deploy (push) Successful in 24s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 46s
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-06-16 12:53:07 +02:00
62727a7231 test: update homepage test to match new copy (Mitarbeitende)
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 23s
Build & Deploy / 🧪 QA (push) Successful in 1m2s
Build & Deploy / 🏗️ Build (push) Successful in 1m51s
Build & Deploy / 🚀 Deploy (push) Successful in 27s
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 1s
2026-06-16 12:20:50 +02:00
3a6189e0d8 chore: optimize new client images (HEIC to JPG, resize)
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 29s
Build & Deploy / 🧪 QA (push) Failing after 55s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-06-16 12:11:45 +02:00
01e2fdbb7d fix: move EU funding badge from header to footer to prevent overlap
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 31s
Build & Deploy / 🏗️ Build (push) Has been cancelled
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
Build & Deploy / 🧪 QA (push) Has been cancelled
2026-06-16 12:08:55 +02:00
fa7182d351 fix: address remaining UI and content feedback from Marisa
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 37s
Build & Deploy / 🧪 QA (push) Failing after 56s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-06-16 11:43:26 +02:00
e0d43f7f5f fix: implement client feedback (map points, hero text, stats spacing, lang toggle)
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 48s
Build & Deploy / 🧪 QA (push) Successful in 1m30s
Build & Deploy / 🏗️ Build (push) Successful in 2m55s
Build & Deploy / 🚀 Deploy (push) Successful in 42s
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 4s
2026-06-16 10:40:01 +02:00
d09b576137 style: hide scrollbars on mobile and fix desktop overlay scrollbars for company tiles
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 26s
Build & Deploy / 🧪 QA (push) Successful in 1m26s
Build & Deploy / 🏗️ Build (push) Successful in 2m33s
Build & Deploy / 🚀 Deploy (push) Successful in 28s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 56s
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-06-16 09:28:25 +02:00
04599827f9 feat(ui): add actual EU flag image and update path to webp
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 25s
Build & Deploy / 🧪 QA (push) Successful in 1m33s
Build & Deploy / 🏗️ Build (push) Successful in 2m57s
Build & Deploy / 🚀 Deploy (push) Successful in 30s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 56s
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-06-15 16:47:54 +02:00
5368f1a64d feat(ui): smooth radial fade on EU badge and setup custom image path
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 26s
Build & Deploy / 🧪 QA (push) Successful in 1m25s
Build & Deploy / 🏗️ Build (push) Has been cancelled
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
2026-06-15 16:45:40 +02:00
241c97e346 feat(ui): refine EU badge into subtle triangular corner fade with text
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 27s
Build & Deploy / 🧪 QA (push) Successful in 1m25s
Build & Deploy / 🏗️ Build (push) Successful in 2m56s
Build & Deploy / 🚀 Deploy (push) Successful in 30s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 57s
Build & Deploy / 🔔 Notify (push) Successful in 3s
2026-06-15 16:34:50 +02:00
3334e327bf fix(ui): correct z-index and remove mix-blend-screen on EU badge
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 27s
Build & Deploy / 🧪 QA (push) Successful in 1m31s
Build & Deploy / 🏗️ Build (push) Successful in 2m56s
Build & Deploy / 🚀 Deploy (push) Successful in 31s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 58s
Build & Deploy / 🔔 Notify (push) Successful in 3s
2026-06-15 16:21:51 +02:00
145bff90b6 ci: implement dynamic environment priority gate (prod > rc > testing > branch)
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 34s
Build & Deploy / 🧪 QA (push) Successful in 1m32s
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
Build & Deploy / 🏗️ Build (push) Has been cancelled
2026-06-15 16:14:16 +02:00
d2bf48fc60 chore: add project instructions and workflow rules to INSTRUCTIONS.md 2026-06-15 16:08:23 +02:00
5e7ee84dc9 ci: fix deployment concurrency groups by target environment
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 26s
Build & Deploy / 🧪 QA (push) Successful in 1m26s
Build & Deploy / 🏗️ Build (push) Successful in 2m56s
Build & Deploy / 🚀 Deploy (push) Successful in 30s
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-06-15 16:05:42 +02:00
b42e53495d 2.2.13-rc.0
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 25s
Build & Deploy / 🧪 QA (push) Successful in 1m24s
Build & Deploy / 🏗️ Build (push) Successful in 3m2s
Build & Deploy / 🚀 Deploy (push) Successful in 29s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 55s
Build & Deploy / 🔔 Notify (push) Successful in 3s
2026-06-15 15:54:45 +02:00
8813ed3910 fix: enforce hero remounts on route change 2026-06-15 15:54:38 +02:00
1d3c6a0f70 fix(ui): remove dummy certificates from english page
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 35s
Build & Deploy / 🧪 QA (push) Successful in 1m33s
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
Build & Deploy / 🏗️ Build (push) Has been cancelled
2026-06-15 15:52:36 +02:00
8fb3b96bd3 feat(ui): redesign EU flag with perspective image and gradient fade mask
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 27s
Build & Deploy / 🧪 QA (push) Successful in 1m40s
Build & Deploy / 🏗️ Build (push) Successful in 2m54s
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
Build & Deploy / 🚀 Deploy (push) Has been cancelled
2026-06-15 15:46:41 +02:00
67dc56d3ee fix(ui): remove hardcoded dummy certificates without downloads
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 42s
Build & Deploy / 🧪 QA (push) Successful in 1m31s
Build & Deploy / 🏗️ Build (push) Successful in 3m2s
Build & Deploy / 🚀 Deploy (push) Successful in 31s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 1m3s
Build & Deploy / 🔔 Notify (push) Successful in 3s
2026-06-15 15:40:19 +02:00
e5933bad69 feat(ui): optimize career page header layout 2026-06-15 15:40:14 +02:00
11b9e4630b feat(ui): add EU Funding Badge to global layout
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 26s
Build & Deploy / 🧪 QA (push) Successful in 1m24s
Build & Deploy / 🏗️ Build (push) Successful in 2m32s
Build & Deploy / 🔔 Notify (push) Has been cancelled
Build & Deploy / 🚀 Deploy (push) Successful in 30s
Build & Deploy / 🧪 Post-Deploy Verification (push) Has started running
2026-06-15 15:29:23 +02:00
a47d378521 fix(ui): prevent text selection and ghost images during references slider drag
Some checks failed
Build & Deploy / 🔍 Prepare (push) Has been cancelled
Build & Deploy / 🧪 QA (push) Has been cancelled
Build & Deploy / 🏗️ Build (push) Has been cancelled
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
2026-06-15 15:28:21 +02:00
30047cb1c4 fix(nav): optimize dropdown behavior on navigation and scroll
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 44s
Build & Deploy / 🧪 QA (push) Has started running
Build & Deploy / 🏗️ Build (push) Has been cancelled
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
2026-06-15 15:24:46 +02:00
394ac5a19c style(mobile): optimize mobile layout and component spacing
Some checks failed
Build & Deploy / 🔍 Prepare (push) Has been cancelled
Build & Deploy / 🧪 QA (push) Has been cancelled
Build & Deploy / 🏗️ Build (push) Has been cancelled
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
- Hide CorporateBackground on mobile to prevent content overlap
- Increase Header padding on mobile for better logo spacing
- Reduce top spacing in HeroSection on mobile
- Change SubCompanyTiles to horizontally scrollable row on mobile
- Add bottom padding to Footer to clear MobileBottomNav
- Reduce Footer Bento card padding for compact mobile view
2026-06-15 15:23:23 +02:00
d63f196693 chore(content): remove team statistics section from about page
All checks were successful
CI - Lint, Typecheck & Test / quality-assurance (pull_request) Successful in 2m32s
Build & Deploy / 🔍 Prepare (push) Successful in 27s
Build & Deploy / 🧪 QA (push) Successful in 1m33s
Build & Deploy / 🏗️ Build (push) Successful in 2m34s
Build & Deploy / 🚀 Deploy (push) Successful in 29s
Build & Deploy / 🔔 Notify (push) Successful in 2s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 1m3s
2026-06-15 15:13:20 +02:00
6092f1d827 fix(tests): update english terms path from terms.mdx to agb.mdx
Some checks failed
CI - Lint, Typecheck & Test / quality-assurance (pull_request) Has been cancelled
Build & Deploy / 🔍 Prepare (push) Successful in 21s
Build & Deploy / 🧪 QA (push) Successful in 56s
Build & Deploy / 🏗️ Build (push) Successful in 1m37s
Build & Deploy / 🚀 Deploy (push) Successful in 27s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 42s
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-06-15 14:55:48 +02:00
766c385704 fix(content): replace video hero with image hero on messen pages
Some checks failed
CI - Lint, Typecheck & Test / quality-assurance (pull_request) Failing after 58s
Build & Deploy / 🔍 Prepare (push) Successful in 22s
Build & Deploy / 🧪 QA (push) Failing after 59s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 1s
2026-06-15 14:42:56 +02:00
6c9d2b6832 fix(content): update images and review feedback
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 21s
CI - Lint, Typecheck & Test / quality-assurance (pull_request) Failing after 59s
Build & Deploy / 🧪 QA (push) Failing after 49s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 1s
2026-06-15 13:54:57 +02:00
95 changed files with 381 additions and 378 deletions

View File

@@ -17,9 +17,6 @@ env:
PUPPETEER_SKIP_DOWNLOAD: "true"
COREPACK_NPM_REGISTRY: "https://registry.npmmirror.com"
concurrency:
group: deploy-pipeline
cancel-in-progress: true
jobs:
# ──────────────────────────────────────────────────────────────────────────────
@@ -146,6 +143,13 @@ jobs:
echo "short_sha=$SHORT_SHA"
} >> "$GITHUB_OUTPUT"
- name: 🚦 Priority Gate
env:
GITEA_PAT: ${{ secrets.GITEA_PAT }}
CURRENT_RUN_ID: ${{ github.run_id }}
CURRENT_TARGET: ${{ steps.determine.outputs.target }}
run: bash scripts/priority-gate.sh
# ──────────────────────────────────────────────────────────────────────────────
# JOB 2: QA (Lint, Typecheck, Test)
# ──────────────────────────────────────────────────────────────────────────────

View File

@@ -2,145 +2,4 @@
> e-tib-nextjs@2.2.12 lint /Volumes/Alpha SSD/Coding/e-tib.com
> eslint .
/Volumes/Alpha SSD/Coding/e-tib.com/app/[locale]/[slug]/page.tsx
1:20 warning 'redirect' is defined but never used @typescript-eslint/no-unused-vars
75:24 warning Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element @next/next/no-img-element
/Volumes/Alpha SSD/Coding/e-tib.com/app/[locale]/blog/[slug]/page.tsx
1:20 warning 'redirect' is defined but never used @typescript-eslint/no-unused-vars
39:24 warning Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element @next/next/no-img-element
/Volumes/Alpha SSD/Coding/e-tib.com/app/[locale]/error.tsx
7:30 warning 'AlertTriangle' is defined but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/app/[locale]/not-found.tsx
6:10 warning 'Terminal' is defined but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/app/[locale]/referenzen/[slug]/page.tsx
118:26 warning Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element @next/next/no-img-element
/Volumes/Alpha SSD/Coding/e-tib.com/app/[locale]/referenzen/page.tsx
1:21 warning 'Heading' is defined but never used @typescript-eslint/no-unused-vars
1:30 warning 'Badge' is defined but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/app/[locale]/standorte/[slug]/page.tsx
9:10 warning 'getButtonClasses' is defined but never used @typescript-eslint/no-unused-vars
9:28 warning 'ButtonOverlay' is defined but never used @typescript-eslint/no-unused-vars
58:9 warning 't' is assigned a value but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/components/JsonLd.tsx
1:30 warning 'Graph' is defined but never used @typescript-eslint/no-unused-vars
43:31 warning '_' is assigned a value but never used @typescript-eslint/no-unused-vars
48:29 warning '_' is assigned a value but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/CertificatesBlock.tsx
6:10 warning 'Button' is defined but never used @typescript-eslint/no-unused-vars
9:10 warning 'FileText' is defined but never used @typescript-eslint/no-unused-vars
102:5 warning Error: Calling setState synchronously within an effect can trigger cascading renders
Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:
* Update external systems with the latest state from React.
* Subscribe for updates from some external system, calling setState in a callback function when external state changes.
Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/CertificatesBlock.tsx:102:5
100 |
101 | useEffect(() => {
> 102 | setIsMounted(true);
| ^^^^^^^^^^^^ Avoid calling setState() directly within an effect
103 | }, []);
104 |
105 | const badgeText = badge || 'Zertifizierungen & Nachweise'; react-hooks/set-state-in-effect
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/CompetenceBentoGrid.tsx
53:5 warning Error: Calling setState synchronously within an effect can trigger cascading renders
Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:
* Update external systems with the latest state from React.
* Subscribe for updates from some external system, calling setState in a callback function when external state changes.
Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/CompetenceBentoGrid.tsx:53:5
51 |
52 | useEffect(() => {
> 53 | setIsMounted(true);
| ^^^^^^^^^^^^ Avoid calling setState() directly within an effect
54 | }, []);
55 |
56 | const badge = props.badge || data?.badge || 'Leistungsspektrum'; react-hooks/set-state-in-effect
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/HeroVideo.tsx
5:18 warning 'AnimatePresence' is defined but never used @typescript-eslint/no-unused-vars
6:10 warning 'useState' is defined but never used @typescript-eslint/no-unused-vars
6:20 warning 'useEffect' is defined but never used @typescript-eslint/no-unused-vars
45:12 warning 'e' is defined but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/InteractiveGermanyMap.tsx
5:18 warning 'Factory' is defined but never used @typescript-eslint/no-unused-vars
5:27 warning 'Zap' is defined but never used @typescript-eslint/no-unused-vars
56:9 warning 'hq' is assigned a value but never used @typescript-eslint/no-unused-vars
57:9 warning 'branch' is assigned a value but never used @typescript-eslint/no-unused-vars
58:9 warning 'projects' is assigned a value but never used @typescript-eslint/no-unused-vars
59:9 warning 'minorNodes' is assigned a value but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/ReferencesSlider.test.tsx
20:12 warning Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element @next/next/no-img-element
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/SubCompanyTiles.tsx
92:19 warning 'CardWrapper' is assigned a value but never used @typescript-eslint/no-unused-vars
93:19 warning 'wrapperProps' is assigned a value but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/TeamGridBlock.tsx
20:39 warning 'title' is defined but never used. Allowed unused args must match /^_/u @typescript-eslint/no-unused-vars
20:46 warning 'department' is defined but never used. Allowed unused args must match /^_/u @typescript-eslint/no-unused-vars
20:58 warning 'showContact' is assigned a value but never used. Allowed unused args must match /^_/u @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/components/decorations/CorporateBackground.tsx
36:13 warning 'distance' is assigned a value but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/components/home/Hero.tsx
9:39 warning 'useCallback' is defined but never used @typescript-eslint/no-unused-vars
77:6 warning React Hook useEffect has missing dependencies: 'HERO_PLACEHOLDERS' and 't'. Either include them or remove the dependency array react-hooks/exhaustive-deps
/Volumes/Alpha SSD/Coding/e-tib.com/components/home/MeetTheTeam.tsx
8:9 warning 'teamT' is assigned a value but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/components/layout/Footer.tsx
4:35 warning 'Accessibility' is defined but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/components/providers/InitialLoader.tsx
5:8 warning 'Image' is defined but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/components/providers/PageTransitionShutter.tsx
6:8 warning 'Image' is defined but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/components/search/AIOrb.tsx
153:13 warning 'breathe' is assigned a value but never used @typescript-eslint/no-unused-vars
212:15 warning 'targetExcite' is assigned a value but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/components/search/AISearchResults.tsx
100:6 warning React Hook useEffect has missing dependencies: 'handleSearch' and 'initialQuery'. Either include them or remove the dependency array react-hooks/exhaustive-deps
/Volumes/Alpha SSD/Coding/e-tib.com/components/ui/AnimatedCounter.tsx
3:28 warning 'useState' is defined but never used @typescript-eslint/no-unused-vars
/Volumes/Alpha SSD/Coding/e-tib.com/lib/blog.ts
6:7 warning 'BLOG_DIR' is assigned a value but never used @typescript-eslint/no-unused-vars
94:7 warning 'next' is never reassigned. Use 'const' instead prefer-const
95:7 warning 'prev' is never reassigned. Use 'const' instead prefer-const
/Volumes/Alpha SSD/Coding/e-tib.com/lib/standorte-data.ts
1:10 warning 'LucideIcon' is defined but never used @typescript-eslint/no-unused-vars
1:22 warning 'MapPin' is defined but never used @typescript-eslint/no-unused-vars
1:30 warning 'Building2' is defined but never used @typescript-eslint/no-unused-vars
1:41 warning 'HardHat' is defined but never used @typescript-eslint/no-unused-vars
1:50 warning 'Phone' is defined but never used @typescript-eslint/no-unused-vars
1:57 warning 'Mail' is defined but never used @typescript-eslint/no-unused-vars
1:63 warning 'Navigation' is defined but never used @typescript-eslint/no-unused-vars
✖ 56 problems (0 errors, 56 warnings)
0 errors and 2 warnings potentially fixable with the `--fix` option.
ELIFECYCLE Command failed.

View File

@@ -5,33 +5,51 @@
 RUN  v4.1.2 /Volumes/Alpha SSD/Coding/e-tib.com
(node:74132) [DEP0205] DeprecationWarning: `module.register()` is deprecated. Use `module.registerHooks()` instead.
(node:64961) [DEP0205] DeprecationWarning: `module.register()` is deprecated. Use `module.registerHooks()` instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
✓ tests/homepage-and-competence-content.test.ts (4 tests) 10ms
✓ tests/task-12-links.test.ts (2 tests) 5ms
✓ tests/mdx-links.test.ts (1 test) 11ms
✓ tests/legal-pages.test.ts (2 tests) 15ms
✓ tests/messen-content.test.ts (2 tests) 30ms
✓ lib/mail/mailer.test.ts (1 test) 4ms
✓ components/search/AISearchResults.test.tsx (1 test) 25ms
✓ tests/mdx-links.test.ts (1 test) 29ms
✓ tests/homepage-and-competence-content.test.ts (4 tests) 14ms
 tests/legal-pages.test.ts (2 tests | 1 failed) 9ms
✓ should contain highly professional B2B sections in German AGB 5ms
 × should contain professional corresponding B2B sections in English Terms 2ms
✓ tests/task-12-links.test.ts (2 tests) 8ms
✓ tests/messen-content.test.ts (2 tests) 8ms
✓ lib/mail/mailer.test.ts (1 test) 7ms
stderr | components/layout/LanguageSwitcher.test.tsx > LanguageSwitcher TDD > translates /en/trade-fairs to /de/messen when switching to German
React does not recognize the `transitionMessage` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `transitionmessage` instead. If you accidentally passed it from a parent component, remove it from the DOM element.
✓ components/layout/LanguageSwitcher.test.tsx (5 tests) 26ms
✓ lib/env.test.ts (6 tests) 3ms
✓ components/layout/LanguageSwitcher.test.tsx (5 tests) 25ms
✓ components/search/AISearchResults.test.tsx (1 test) 52ms
stderr | components/blocks/ReferencesSlider.test.tsx > ReferencesSlider TDD > renders reference tiles correctly
Received `true` for a non-boolean attribute `fill`.
If you want to write it to the DOM, pass a string instead: fill="true" or fill={value.toString()}.
✓ components/blocks/ReferencesSlider.test.tsx (2 tests) 43ms
✓ lib/env.test.ts (6 tests) 4ms
stdout | app/[locale]/referenzen/[slug]/page.test.tsx
[Config] Initializing Toggles: { feedbackEnabled: false }
✓ app/[locale]/referenzen/[slug]/page.test.tsx (1 test) 7ms
✓ app/[locale]/referenzen/[slug]/page.test.tsx (1 test) 26ms
 Test Files  11 passed (11)
 Tests  27 passed (27)
 Start at  22:40:02
 Duration  2.69s (transform 2.09s, setup 0ms, import 4.45s, tests 179ms, environment 8.10s)
⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯
 FAIL  tests/legal-pages.test.ts > Legal Pages Content Validation > should contain professional corresponding B2B sections in English Terms
Error: ENOENT: no such file or directory, open '/Volumes/Alpha SSD/Coding/e-tib.com/content/en/terms.mdx'
  tests/legal-pages.test.ts:25:24
 23|
 24| it('should contain professional corresponding B2B sections in Englis…
 25| const content = fs.readFileSync(enTermsPath, 'utf8');
 | ^
 26|
 27| expect(content).toContain('title: "Terms and Conditions"');
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯
 Test Files  1 failed | 10 passed (11)
 Tests  1 failed | 26 passed (27)
 Start at  14:54:33
 Duration  5.94s (transform 5.27s, setup 0ms, import 9.43s, tests 222ms, environment 13.80s)
ELIFECYCLE Test failed. See above for more details.

View File

@@ -2,3 +2,4 @@
> e-tib-nextjs@2.2.12 typecheck /Volumes/Alpha SSD/Coding/e-tib.com
> tsc --noEmit
ELIFECYCLE Command failed.

25
INSTRUCTIONS.md Normal file
View File

@@ -0,0 +1,25 @@
# Antigravity Instructions & Project Rules
This document contains critical project-specific rules for the e-tib.com codebase. Antigravity must read and follow these rules at all times.
## 1. Bilingual Site (German & English) - STRICT
- **Always update BOTH languages!** The website is bilingual.
- When changing content, adding pages, or updating text, you MUST always check and update both `content/de/` and `content/en/` simultaneously.
- When adding new components with text, ensure they are built to support both languages or update the respective translation files/mechanisms. Do NOT just hardcode German text and forget the English version.
## 2. No Dummy Data / No Hallucinations
- Do not invent or hallucinate placeholder text (e.g., "Nachweis liegt vor" for certificates that don't exist).
- Only implement what is explicitly requested or what matches provided assets/data.
- If data is missing, ask the user instead of inventing placeholders.
## 3. Git Workflow & RC Tagging
- When instructed to "commit and tag" (or similar), always follow this process:
1. Add and commit the changes with conventional commits (`feat:`, `fix:`, `chore:`, etc.).
2. Check the latest tag using `git describe --tags --abbrev=0`.
3. Increment the RC (Release Candidate) number of the current version (e.g., if latest is `v2.2.13-rc19`, the new tag is `v2.2.13-rc20`).
4. Create the tag: `git tag vX.Y.Z-rcN`.
5. Push the commit and the tag: `git push origin main --tags`.
## 4. Work Exclusively on the Correct Branch
- Follow the `USER_GLOBAL` directive: If on `main`, create a branch unless explicitly told to work on `main`.
- For e-tib.com, often small fixes are done on `main` if the user commands it ("auf main arbeiten"), but always verify context.

View File

@@ -186,7 +186,7 @@ export default async function Page(props: { params: Promise<{ locale: string; sl
<div className={`flex flex-col min-h-screen ${isFullBleed ? '' : 'bg-white'}`}>
{/* Generic Hero Section (only for standard pages) */}
{!isFullBleed && (
<section className="bg-primary-dark text-white pt-40 pb-12 md:pt-56 md:pb-16 min-h-[40vh] md:min-h-[45vh] flex flex-col justify-end relative overflow-hidden">
<section key={`hero-section-${slug}`} className="bg-primary-dark text-white pt-40 pb-12 md:pt-56 md:pb-16 min-h-[40vh] md:min-h-[45vh] flex flex-col justify-end relative overflow-hidden">
<div className="absolute inset-0 opacity-20 pointer-events-none">
<div className="absolute top-0 left-0 w-full h-full bg-[radial-gradient(circle_at_center,_var(--tw-gradient-stops))] from-accent/50 via-transparent to-transparent" />
</div>

View File

@@ -19,7 +19,6 @@ import { TransitionProvider } from '@/components/providers/TransitionProvider';
import { PageTransitionShutter } from '@/components/providers/PageTransitionShutter';
import { InitialLoader } from '@/components/providers/InitialLoader';
import { CorporateBackground } from '@/components/decorations/CorporateBackground';
const inter = Inter({
subsets: ['latin'],
display: 'swap',

View File

@@ -79,6 +79,11 @@ export default async function ReferenzenOverview(props: { params: Promise<{ loca
title={locale === 'en' ? 'Successfully realized projects.' : 'Erfolgreich umgesetzte Projekte.'}
description={locale === 'en' ? 'From broadband expansion to complex 110kV lines: A selection of our nationwide projects where we have created infrastructure for the future.' : 'Vom Breitbandausbau bis zur komplexen 110kV-Trasse: Ein Auszug unserer bundesweiten Projekte, bei denen wir Infrastruktur für die Zukunft geschaffen haben.'}
locations={enrichedLocations}
hideStandorte={true}
stats={[
{ value: '100', suffix: '%', label: locale === 'en' ? 'Nationwide Reach' : 'Überregionale Reichweite' },
{ value: enrichedLocations.length.toString(), suffix: '+', label: locale === 'en' ? 'Completed Projects' : 'Abgeschlossene Projekte' }
]}
/>
{/* Main Content Area */}

View File

@@ -65,7 +65,7 @@ export default async function StandortDetail(props: { params: Promise<{ locale:
return (
<div className="flex flex-col min-h-screen bg-white">
{/* Generic Hero Section to match standard pages */}
<section className="bg-primary-dark text-white pt-40 pb-12 md:pt-56 md:pb-16 min-h-[40vh] md:min-h-[45vh] flex flex-col justify-end relative overflow-hidden">
<section key={`standort-hero-${slug}`} className="bg-primary-dark text-white pt-40 pb-12 md:pt-56 md:pb-16 min-h-[40vh] md:min-h-[45vh] flex flex-col justify-end relative overflow-hidden">
<div className="absolute inset-0 opacity-20 pointer-events-none">
<div className="absolute top-0 left-0 w-full h-full bg-[radial-gradient(circle_at_center,_var(--tw-gradient-stops))] from-accent/50 via-transparent to-transparent" />
</div>

View File

@@ -10,11 +10,13 @@
}
.hide-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none !important; /* IE and Edge */
scrollbar-width: none !important; /* Firefox */
}
.hide-scrollbar::-webkit-scrollbar {
display: none; /* Chrome, Safari and Opera */
display: none !important; /* Chrome, Safari and Opera */
width: 0 !important;
height: 0 !important;
}
@keyframes bg-pulse-15 {

View File

@@ -68,31 +68,7 @@ const defaultCertificates: Certificate[] = [
type: 'tax',
date: '13.02.2025',
},
{
title: 'Unbedenklichkeit IHK',
description: 'Industrie- und Handelskammer',
type: 'general',
},
{
title: 'Unbedenklichkeit HWK',
description: 'Handwerkskammer',
type: 'general',
},
{
title: 'Handelsregisterauszug',
description: 'Amtsgericht Cottbus',
type: 'general',
},
{
title: 'Gewerbe-Anmeldung',
description: 'Stadt Guben',
type: 'general',
},
{
title: 'Gewerbezentralregister',
description: 'Auskunft aus dem Register',
type: 'general',
},
];
export function CertificatesBlock({ badge, title, description, certificates = defaultCertificates, hideHeader = false }: CertificatesBlockProps) {

View File

@@ -2,6 +2,7 @@
import React from 'react';
import Image from 'next/image';
import { usePathname } from 'next/navigation';
import { motion } from 'framer-motion';
import { Badge, Container, Heading } from '@/components/ui';
import { Button } from '@/components/ui/Button';
@@ -39,13 +40,15 @@ const itemVariants = {
export const HeroSection: React.FC<HeroSectionProps> = (props) => {
const { title, badge, subtitle, backgroundImage, alignment, ctaLabel, ctaHref } = props;
const bgSrc = backgroundImage?.sizes?.card?.url || backgroundImage?.url;
const pathname = usePathname();
return (
<section
className={`relative min-h-[45vh] md:min-h-[55vh] flex items-center pt-32 pb-20 md:pt-36 md:pb-24 overflow-hidden bg-neutral-dark ${alignment === 'center' ? 'justify-center text-center' : ''}`}
className={`relative min-h-[45vh] md:min-h-[55vh] flex items-center pt-24 pb-16 md:pt-36 md:pb-24 overflow-hidden bg-neutral-dark ${alignment === 'center' ? 'justify-center text-center' : ''}`}
>
{bgSrc && (
<motion.div
key={`hero-bg-${pathname}`}
className="absolute inset-0 z-0"
initial={{ scale: 1.05, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
@@ -75,6 +78,7 @@ export const HeroSection: React.FC<HeroSectionProps> = (props) => {
)}
<Container className={`relative z-10 ${alignment === 'center' ? 'max-w-5xl' : ''}`}>
<motion.div
key={`hero-content-${pathname}`}
className={`max-w-4xl ${alignment === 'center' ? 'mx-auto' : ''}`}
variants={containerVariants}
initial="hidden"

View File

@@ -4,6 +4,7 @@ import { Button } from '@/components/ui/Button';
import Image from 'next/image';
import { motion, AnimatePresence } from 'framer-motion';
import { useState, useEffect } from 'react';
import { usePathname } from 'next/navigation';
interface HeroVideoProps {
data?: any;
@@ -28,6 +29,7 @@ export function HeroVideo(props: HeroVideoProps) {
const subtitle = props.subtitle || props.description || data?.subtitle || 'Wir verbinden Infrastruktur mit Präzision. Von Horizontalbohrungen bis zu komplexen Leitungsnetzen.';
const explicitNoVideo = props.videoUrl === 'none' || props.videoUrl === '';
const videoUrl = explicitNoVideo ? null : (props.videoUrl || data?.videoUrl || '/assets/dummy-hero.mp4');
const pathname = usePathname();
const posterSrc = props.backgroundImage?.url || props.posterImage?.url || data?.posterImage?.url || "/assets/photos/DJI_0048.JPG";
const posterAlt = props.backgroundImage?.alt || data?.posterImage?.alt || "E-TIB Gruppe Baustelle";
@@ -35,19 +37,10 @@ export function HeroVideo(props: HeroVideoProps) {
const ctaLabel = props.ctaLabel || props.linkText || data?.ctaLabel || 'Unternehmen entdecken';
const ctaHref = props.ctaHref || props.linkHref || data?.ctaHref || '#unternehmen';
let currentLocale = 'de';
try {
// We can't unconditionally call hooks if they might fail outside context, but HeroVideo is usually in context.
// However, to be safe and avoid adding new imports, we can use window.location or default to 'de' if not available.
if (typeof window !== 'undefined') {
currentLocale = window.location.pathname.startsWith('/en') ? 'en' : 'de';
}
} catch (e) {
// Fallback to default locale if window/location access fails
}
const currentLocale = pathname?.startsWith('/en') ? 'en' : 'de';
const secondaryCtaLabel = props.secondaryCtaLabel || data?.secondaryCtaLabel || (currentLocale === 'de' ? 'Projekt anfragen' : 'Inquire Project');
const secondaryCtaHref = props.secondaryCtaHref || data?.secondaryCtaHref || `/${currentLocale}/${currentLocale === 'de' ? 'contact' : 'contact'}`;
const secondaryCtaHref = props.secondaryCtaHref || data?.secondaryCtaHref || `/${currentLocale}/contact`;
return (
<div className="relative w-full h-[100svh] flex items-center justify-center overflow-hidden bg-neutral-dark">
@@ -56,7 +49,7 @@ export function HeroVideo(props: HeroVideoProps) {
{videoUrl ? (
<video
key={videoUrl}
key={`${pathname}-${videoUrl}`}
className="absolute inset-0 w-full h-full object-cover z-1 pointer-events-none filter contrast-125 saturate-110 brightness-90"
src={videoUrl}
autoPlay
@@ -67,6 +60,7 @@ export function HeroVideo(props: HeroVideoProps) {
/>
) : (
<Image
key={`img-${pathname}-${posterSrc}`}
src={posterSrc}
alt={posterAlt}
fill
@@ -88,13 +82,14 @@ export function HeroVideo(props: HeroVideoProps) {
<div className="container relative z-[4] text-center px-4">
<motion.div
key={`hero-content-${pathname}`}
initial={{ opacity: 0, y: 40 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 1.2, ease: [0.16, 1, 0.3, 1] }}
>
<h1
className="font-heading font-bold text-4xl md:text-6xl lg:text-8xl text-white mb-6 uppercase tracking-tight drop-shadow-lg"
dangerouslySetInnerHTML={{ __html: title.replace('KABELTIEFBAU', '<span class="text-primary-light">KABELTIEFBAU</span>').replace(/\\n|\n/g, '<br />') }}
dangerouslySetInnerHTML={{ __html: title.replace(/KABELTIEFBAU|Kabeltiefbau/g, '<span class="text-primary-light">Kabeltiefbau</span>').replace(/KABELNETZBAU|Kabelnetzbau/g, '<span class="text-primary-light">Kabelnetzbau</span>').replace(/\\n|\n/g, '<br />') }}
/>
<p className="text-lg md:text-xl lg:text-2xl text-white/90 max-w-3xl mx-auto mb-12 drop-shadow">

View File

@@ -4,7 +4,7 @@ import React, { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { MapPin, Factory, Zap, CheckCircle2, ArrowUpRight } from 'lucide-react';
import Image from 'next/image';
import { useRouter } from 'next/navigation';
import { useRouter, usePathname } from 'next/navigation';
import Link from 'next/link';
import { AnimatedGlossyBorder } from '@/components/ui/AnimatedGlossyBorder';
import { Location, defaultLocations, minorLocations, projectLocations } from '@/lib/map-data';
@@ -25,6 +25,7 @@ interface InteractiveGermanyMapProps {
stats?: Stat[];
locations?: Location[];
isHero?: boolean;
hideStandorte?: boolean;
}
export function InteractiveGermanyMap({
@@ -33,10 +34,12 @@ export function InteractiveGermanyMap({
description,
stats,
locations = projectLocations,
isHero = false
isHero = false,
hideStandorte = false
}: InteractiveGermanyMapProps) {
const [activeLocation, setActiveLocation] = useState<Location | null>(null);
const router = useRouter();
const pathname = usePathname();
const locale = useLocale();
const t = useTranslations('InteractiveGermanyMap');
const tStandard = useTranslations('StandardPage');
@@ -51,13 +54,21 @@ export function InteractiveGermanyMap({
const finalTitle = title || (locale === 'en' ? <>Nationwide<br/>in operation for you.</> : <>Deutschlandweit<br/>für Sie im Einsatz.</>);
const finalDescription = description || (locale === 'en' ? 'From our strategic locations in Guben, Kirchheilingen and Bülstedt, we control and implement complex infrastructure projects nationwide.' : 'Von unseren strategischen Standorten in Guben, Kirchheilingen und Bülstedt steuern und realisieren wir komplexe Infrastrukturprojekte im gesamten Bundesgebiet.');
const hq = locations.find((l) => l.type === 'hq');
const branch = locations.find((l) => l.type === 'branch');
const projects = locations.filter((l) => l.type === 'project');
const minorNodes = locations.filter((l) => l.type === 'minor_node');
const finalLocations = React.useMemo(() => {
if (hideStandorte) return locations;
// Ensure the 3 standorte are always included, without duplicating if already present by ID
const base = [...locations];
standorteLocations.forEach(sl => {
if (!base.some(l => l.id === sl.id)) {
base.push(sl as Location);
}
});
return base;
}, [locations, hideStandorte]);
return (
<div className={isHero ? "relative w-full" : "relative w-full max-w-7xl mx-auto py-16 md:py-24 px-4 sm:px-6 mt-16 md:mt-20"}>
<div key={isHero ? `hero-map-${pathname}` : undefined} className={isHero ? "relative w-full" : "relative w-full max-w-7xl mx-auto py-16 md:py-24 px-4 sm:px-6 mt-16 md:mt-20"}>
<div className={`bg-[#050B14] ${isHero ? 'pt-32 pb-16 md:pt-40 md:pb-24' : 'rounded-[2.5rem] md:rounded-[3.5rem] shadow-2xl border border-white/5'} overflow-visible relative group/map`}>
{/* Animated Border Glow */}
{!isHero && <AnimatedGlossyBorder opacity={0.7} className="z-30" />}
@@ -137,7 +148,7 @@ export function InteractiveGermanyMap({
</div>
{/* Minor Location Markers (The 100+ generic projects) */}
{locations.filter(l => l.type === 'minor_node').map((loc, idx) => (
{finalLocations.filter(l => l.type === 'minor_node').map((loc, idx) => (
<div
key={`minor-${idx}`}
className="absolute z-10 group/minor cursor-pointer w-10 h-10 flex items-center justify-center"
@@ -154,8 +165,8 @@ export function InteractiveGermanyMap({
</div>
))}
{/* Major & Reference Location Markers (HQ, Branch, Project) */}
{locations.filter(l => l.type !== 'minor_node').map((loc, idx) => {
{/* Major Location Markers (HQ, Branch, Project) */}
{finalLocations.filter(l => l.type !== 'minor_node').map((loc, idx) => {
const isHQ = loc.type === 'hq';
const isBranch = loc.type === 'branch';
const isActive = activeLocation?.id === loc.id;
@@ -272,7 +283,7 @@ export function InteractiveGermanyMap({
</ul>
)}
{activeLocation.href && (
{activeLocation.href && (activeLocation.type === 'hq' || activeLocation.type === 'branch') && (
<div className="inline-flex items-center text-xs font-bold text-primary">
{t('learnMore')}
<ArrowUpRight className="w-3.5 h-3.5 ml-1" />

View File

@@ -133,14 +133,17 @@ export function ReferencesSlider(props: ReferencesSliderProps) {
<Link
href={`/${locale}/referenzen/${ref.slug}`}
data-testid="reference-tile"
draggable={false}
onClick={(e) => {
if (dragDistanceRef.current > 5) {
if (dragDistanceRef.current > 15) {
e.preventDefault();
}
dragDistanceRef.current = 0;
}}
className="block relative aspect-[16/10] bg-neutral-800 rounded-2xl overflow-hidden mb-5 border border-white/5 shadow-2xl"
className="block relative select-none aspect-[16/10] bg-neutral-800 rounded-2xl overflow-hidden mb-5 border border-white/5 shadow-2xl"
>
<Image
draggable={false}
src={imgSrc}
alt={ref.title}
fill

View File

@@ -84,19 +84,19 @@ export function ScaleOfImpact() {
{/* Static Data Grid (No jumping text) */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-8 md:gap-12 w-full max-w-5xl mt-12">
<div className="flex flex-col items-center">
<div className="font-mono text-4xl md:text-5xl font-black text-white tracking-tighter mb-2">200<span className="text-primary">+</span></div>
<div className="font-mono text-4xl md:text-5xl font-black text-white tracking-tighter mb-2">200 <span className="text-primary">+</span></div>
<div className="text-xs font-bold uppercase tracking-widest text-white/50">{locale === 'en' ? 'Projects' : 'Projekte'}</div>
</div>
<div className="flex flex-col items-center">
<div className="font-mono text-4xl md:text-5xl font-black text-white tracking-tighter mb-2">974<span className="text-primary text-2xl">km</span></div>
<div className="font-mono text-4xl md:text-5xl font-black text-white tracking-tighter mb-2">974 <span className="text-primary text-2xl">km</span></div>
<div className="text-xs font-bold uppercase tracking-widest text-white/50">{locale === 'en' ? 'Cable Laying' : 'Kabelverlegung'}</div>
</div>
<div className="flex flex-col items-center">
<div className="font-mono text-4xl md:text-5xl font-black text-white tracking-tighter mb-2">300<span className="text-primary text-2xl">km</span></div>
<div className="font-mono text-4xl md:text-5xl font-black text-white tracking-tighter mb-2">300 <span className="text-primary text-2xl">km</span></div>
<div className="text-xs font-bold uppercase tracking-widest text-white/50">{locale === 'en' ? 'Open Trenching' : 'Offener Tiefbau'}</div>
</div>
<div className="flex flex-col items-center">
<div className="font-mono text-4xl md:text-5xl font-black text-white tracking-tighter mb-2">160<span className="text-primary text-2xl">km</span></div>
<div className="font-mono text-4xl md:text-5xl font-black text-white tracking-tighter mb-2">160 <span className="text-primary text-2xl">km</span></div>
<div className="text-xs font-bold uppercase tracking-widest text-white/50">{locale === 'en' ? 'HDD Drilling' : 'Spülbohrung'}</div>
</div>
</div>

View File

@@ -79,7 +79,7 @@ export function SubCompanyTiles(props: SubCompanyTilesProps) {
)}
<motion.div
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"
className="flex overflow-x-auto md:overflow-visible snap-x snap-mandatory pb-6 md:pb-0 md:grid md:grid-cols-2 lg:grid-cols-4 gap-4 md:gap-6 hide-scrollbar -mx-4 px-4 md:mx-0 md:px-0"
variants={containerVariants}
initial="hidden"
whileInView="visible"
@@ -236,7 +236,7 @@ export function SubCompanyTiles(props: SubCompanyTilesProps) {
<motion.div
key={index}
variants={itemVariants}
className="h-full"
className="h-full flex-shrink-0 snap-center w-[85%] sm:w-[70%] md:w-full"
>
{hasUrl ? (
isExternal ? (

View File

@@ -78,7 +78,7 @@ export function CorporateBackground() {
const y5 = useTransform(scrollYProgress, [0, 1], [0, -500]);
return (
<div className="absolute inset-0 z-[50] overflow-hidden pointer-events-none" aria-hidden="true">
<div className="absolute inset-0 z-[50] overflow-hidden pointer-events-none hidden md:block" aria-hidden="true">
{/* 1. Top Right - Medium, rotating moderately */}
<motion.div
style={{

View File

@@ -0,0 +1,41 @@
'use client';
import { motion } from 'framer-motion';
import Image from 'next/image';
export function EUFundingBadge() {
return (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 1.5, ease: [0.16, 1, 0.3, 1] }}
className="absolute top-0 right-0 w-[260px] md:w-[380px] h-[260px] md:h-[380px] z-0 pointer-events-none select-none overflow-hidden"
style={{
// Perfekter weicher Fade, der sicherstellt, dass harte Kanten komplett unsichtbar werden
maskImage: 'radial-gradient(100% 100% at top right, black 10%, rgba(0,0,0,0.8) 30%, transparent 70%)',
WebkitMaskImage: 'radial-gradient(100% 100% at top right, black 10%, rgba(0,0,0,0.8) 30%, transparent 70%)',
}}
>
{/* Background Flag */}
<div className="absolute inset-0 w-full h-full opacity-95">
<Image
src="/assets/eu-flag.webp"
alt="European Union Background"
fill
className="object-cover object-top"
priority
/>
</div>
{/* Text overlaid on the flag */}
<div className="absolute top-0 right-0 p-5 md:p-8 flex flex-col items-end text-right z-10 drop-shadow-[0_2px_8px_rgba(0,0,0,0.9)]">
<span className="block text-[9px] md:text-[11px] font-bold text-white/90 tracking-wide leading-snug drop-shadow-md">
Kofinanziert von der
</span>
<span className="block text-[11px] md:text-[13px] font-extrabold text-white tracking-wider leading-snug uppercase drop-shadow-md">
Europäischen Union
</span>
</div>
</motion.div>
);
}

View File

@@ -8,6 +8,7 @@ import { useAnalytics } from '../analytics/useAnalytics';
import { AnalyticsEvents } from '../analytics/analytics-events';
import { useState, useEffect, useRef, useCallback } from 'react';
import { ChevronRight } from 'lucide-react';
import { usePathname } from 'next/navigation';
import { AISearchResults } from '../search/AISearchResults';
const HeroIllustration = dynamic(() => import('./HeroIllustration'), { ssr: false });
const AIOrb = dynamic(() => import('../search/AIOrb'), { ssr: false });
@@ -15,6 +16,7 @@ const AIOrb = dynamic(() => import('../search/AIOrb'), { ssr: false });
export default function Hero({ data }: { data?: any }) {
const t = useTranslations('Home.hero');
const locale = useLocale();
const pathname = usePathname();
const { trackEvent } = useAnalytics();
const [searchQuery, setSearchQuery] = useState('');
@@ -85,7 +87,7 @@ export default function Hero({ data }: { data?: any }) {
return (
<>
<Section className="relative min-h-[85vh] md:h-[90vh] flex flex-col items-center justify-center overflow-hidden bg-primary py-12 md:py-0 lg:py-0">
<Section key={`home-hero-${pathname}`} className="relative min-h-[85vh] md:h-[90vh] flex flex-col items-center justify-center overflow-hidden bg-primary py-12 md:py-0 lg:py-0">
<Container className="relative z-10 text-center md:text-left text-white w-full order-2 md:order-none">
<div className="max-w-5xl mx-auto md:mx-0">
<div>

View File

@@ -4,6 +4,7 @@ import { useLocale } from 'next-intl';
import { ShieldCheck, Leaf, Lock, Accessibility, Zap, Mail, Phone } from 'lucide-react';
import { LanguageSwitcher } from './LanguageSwitcher';
import { Tooltip } from '@/components/ui/Tooltip';
import { EUFundingBadge } from '@/components/decorations/EUFundingBadge';
interface CompanyInfo {
contactEmail: string;
contactPhone: string;
@@ -18,7 +19,7 @@ export function Footer({ companyInfo }: FooterProps) {
const locale = useLocale();
return (
<footer className="bg-[#050B14] text-neutral-light py-10 md:py-16 relative overflow-hidden border-t border-white/5">
<footer className="bg-[#050B14] text-neutral-light pt-10 pb-28 md:py-16 relative overflow-hidden border-t border-white/5">
{/* Subtle background tech grid */}
<div className="absolute inset-0 bg-[linear-gradient(to_right,#8080800a_1px,transparent_1px),linear-gradient(to_bottom,#8080800a_1px,transparent_1px)] bg-[size:32px_32px] [mask-image:radial-gradient(ellipse_80%_50%_at_50%_0%,#000_70%,transparent_100%)] pointer-events-none" />
@@ -26,9 +27,11 @@ export function Footer({ companyInfo }: FooterProps) {
<div className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-primary/40 to-transparent" />
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-1/3 h-[200px] bg-primary/20 blur-[100px] rounded-full pointer-events-none opacity-50" />
<EUFundingBadge />
<div className="container relative z-10 grid grid-cols-1 md:grid-cols-4 lg:grid-cols-12 gap-4 md:gap-6 lg:gap-8 mb-8 md:mb-12">
{/* Brand Column Bento */}
<div className="col-span-1 md:col-span-4 lg:col-span-5 flex flex-col justify-between bg-white/[0.02] border border-white/5 rounded-3xl p-6 md:p-8 lg:p-10 backdrop-blur-md relative group overflow-hidden">
<div className="col-span-1 md:col-span-4 lg:col-span-5 flex flex-col justify-between bg-white/[0.02] border border-white/5 rounded-3xl p-5 md:p-8 lg:p-10 backdrop-blur-md relative group overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-br from-white/[0.04] to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-700" />
<div className="space-y-4 md:space-y-6 relative z-10">
@@ -96,7 +99,7 @@ export function Footer({ companyInfo }: FooterProps) {
<div className="col-span-1 md:col-span-4 lg:col-span-7 grid grid-cols-1 sm:grid-cols-2 gap-4 md:gap-6 lg:gap-8">
{/* Company Column */}
<div className="bg-white/[0.02] border border-white/5 rounded-3xl p-6 md:p-8 lg:p-10 backdrop-blur-md relative group overflow-hidden flex flex-col">
<div className="bg-white/[0.02] border border-white/5 rounded-3xl p-5 md:p-8 lg:p-10 backdrop-blur-md relative group overflow-hidden flex flex-col">
<div className="absolute inset-0 bg-gradient-to-bl from-white/[0.04] to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-700 pointer-events-none" />
<h4 className="font-heading font-bold uppercase tracking-widest text-sm mb-6 md:mb-8 text-white">
{locale === 'de' ? 'Unternehmen' : 'Company'}
@@ -124,7 +127,7 @@ export function Footer({ companyInfo }: FooterProps) {
</div>
{/* Legal Column */}
<div className="bg-white/[0.02] border border-white/5 rounded-3xl p-6 md:p-8 lg:p-10 backdrop-blur-md relative group overflow-hidden flex flex-col">
<div className="bg-white/[0.02] border border-white/5 rounded-3xl p-5 md:p-8 lg:p-10 backdrop-blur-md relative group overflow-hidden flex flex-col">
<div className="absolute inset-0 bg-gradient-to-tr from-white/[0.04] to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-700 pointer-events-none" />
<h4 className="font-heading font-bold uppercase tracking-widest text-sm mb-6 md:mb-8 text-white">
{locale === 'de' ? 'Rechtliches' : 'Legal'}

View File

@@ -72,7 +72,7 @@ export function Header({ navLinks }: HeaderProps) {
className={`fixed top-0 left-0 right-0 z-50 flex justify-center transition-all duration-700 ease-[cubic-bezier(0.16,1,0.3,1)] ${
isStandard
? 'bg-[#050B14]/95 backdrop-blur-xl border-b border-white/10'
: (isSolidMode ? 'pt-4 px-4' : 'pt-0 px-0')
: (isSolidMode ? 'pt-4 px-4 sm:px-6' : 'pt-0 px-0')
}`}
>
<div
@@ -80,7 +80,7 @@ export function Header({ navLinks }: HeaderProps) {
isStandard
? 'py-4 px-6 md:px-8'
: isSolidMode
? 'rounded-full bg-white/50 backdrop-blur-xl shadow-[0_8px_32px_rgba(0,0,0,0.08)] border border-white/40 py-2.5 px-6 md:px-8'
? 'rounded-full bg-white/50 backdrop-blur-xl shadow-[0_8px_32px_rgba(0,0,0,0.08)] border border-white/40 py-2.5 px-8 md:px-10'
: 'rounded-none bg-transparent py-6 px-4 md:px-8 border border-transparent'
}`}
>
@@ -165,6 +165,20 @@ export function Header({ navLinks }: HeaderProps) {
function NavItem({ link, currentLocale, pathname, isSolidMode }: { link: NavLink, currentLocale: string, pathname: string, isSolidMode: boolean }) {
const [isHovered, setIsHovered] = React.useState(false);
// Close dropdown on navigation
React.useEffect(() => {
setIsHovered(false);
}, [pathname]);
// Close dropdown on scroll
React.useEffect(() => {
const handleScroll = () => {
if (isHovered) setIsHovered(false);
};
window.addEventListener('scroll', handleScroll, { passive: true });
return () => window.removeEventListener('scroll', handleScroll);
}, [isHovered]);
const mappedUrl = link.url.startsWith('/') && !link.url.match(/^\/(en|de)/)
? `/${currentLocale}${link.url}`
: link.url;
@@ -237,6 +251,7 @@ function NavItem({ link, currentLocale, pathname, isSolidMode }: { link: NavLink
<TransitionLink
key={child.url}
href={childUrl}
onClick={() => setIsHovered(false)}
className={`group/dropitem relative block px-4 py-3.5 rounded-2xl text-sm font-medium transition-all duration-300 overflow-hidden ${
isSolidMode
? isChildActive ? 'bg-primary/10 text-primary' : 'text-neutral-600 hover:text-primary hover:bg-neutral-50/80'

View File

@@ -9,7 +9,7 @@ layout: "fullBleed"
badge="Kernkompetenz"
title="Bohrtechnik"
subtitle="Grabenlose Leitungsverlegung, Horizontalspülbohrungen und Erdraketen"
backgroundImage={{ url: '/assets/photos/DSC08653.JPG' }}
backgroundImage={{ url: '/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-47.jpg' }}
alignment="center"
ctaLabel="Projekt anfragen"
ctaHref="/de/kontakt"

View File

@@ -5,7 +5,7 @@ description: "Die E-TIB GmbH ist Ihr zuverlässiger Partner für komplexe Kabelt
<HomeHero
title={"Die Experten für\nKabeltiefbau"}
title={"Die Experten für\nKabelnetzbau"}
description="Wir realisieren komplexe Versorgungsleitungen für eine moderne Gesellschaft. Verlässlich, innovativ und mit höchster Präzision im Kabeltiefbau und der Bohrtechnik."
videoUrl="/assets/videos/web/hero-kabelpflug.mp4"
linkText="Unsere Leistungen"
@@ -21,14 +21,14 @@ description: "Die E-TIB GmbH ist Ihr zuverlässiger Partner für komplexe Kabelt
description: "Das komplette Leistungsspektrum zur Errichtung von Kabeltrassen aus einer Hand.",
icon: "M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",
url: "/de/standorte/guben",
backgroundImage: "/assets/photos/DJI_0243.JPG"
backgroundImage: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-54.jpg"
},
{
title: "E-TIB Ingenieurgesellschaft mbH",
description: "Unsere Ingenieure planen für Sie die Energie- und Telekommunikationsnetze der Zukunft - Vermessung und Dokumentation inklusive.",
icon: "M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4",
url: "https://www.etib-ing.com/",
backgroundImage: "/assets/photos/DSC01137.JPG"
backgroundImage: "/assets/photos/etib_ingenieure_tiefbau_solar_pv_planung_vermessung_gis-298.jpg"
},
{
title: "E-TIB Verwaltung GmbH",
@@ -122,7 +122,7 @@ description: "Die E-TIB GmbH ist Ihr zuverlässiger Partner für komplexe Kabelt
tag: "Energie",
size: "large",
href: "/de/kabeltiefbau",
image: { url: "/assets/photos/DSC01123.JPG", alt: "Kabelleitungstiefbau" }
image: { url: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-54.jpg", alt: "Kabelleitungstiefbau" }
},
{
title: "Bohrtechnik",
@@ -130,7 +130,7 @@ description: "Die E-TIB GmbH ist Ihr zuverlässiger Partner für komplexe Kabelt
tag: "Innovation",
size: "medium",
href: "/de/bohrtechnik",
image: { url: "/assets/photos/DSC08653.JPG", alt: "Bohrtechnik" }
image: { url: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-47.jpg", alt: "Bohrtechnik" }
},
{
title: "Planung",
@@ -138,14 +138,15 @@ description: "Die E-TIB GmbH ist Ihr zuverlässiger Partner für komplexe Kabelt
tag: "Präzision",
size: "small",
href: "/de/planung",
image: { url: "/assets/photos/DJI_0048.JPG", alt: "Planung" }
image: { url: "/assets/photos/etib_ingenieure_tiefbau_solar_pv_planung_vermessung_gis-298.jpg", alt: "Planung" }
},
{
title: "Vermessung",
description: "Digitale Bestandsdokumentation",
tag: "Digital",
size: "accent",
href: "/de/vermessung"
href: "/de/vermessung",
image: { url: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie_Vermessung_(26_von_99).jpg", alt: "Vermessung" }
}
]}
/>

View File

@@ -5,13 +5,14 @@ excerpt: "Werden Sie Teil eines dynamischen Teams und bauen Sie mit uns die Infr
layout: "fullBleed"
---
<HomeHero
<HeroSection
badge="Karriere"
title="Zukunft bauen"
description="Suchen Sie eine neue Herausforderung in einem zukunftssicheren Markt? Bei E-TIB arbeiten wir täglich daran, Deutschland zu vernetzen und die Energiewende voranzutreiben."
videoUrl="/assets/videos/web/hero-kabelpflug.mp4"
linkText="Offene Stellen"
linkHref="#stellen"
subtitle="Suchen Sie eine neue Herausforderung in einem zukunftssicheren Markt? Bei E-TIB arbeiten wir täglich daran, Deutschland zu vernetzen und die Energiewende voranzutreiben."
backgroundImage={{ url: '/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-28.jpg' }}
alignment="center"
ctaLabel="Offene Stellen"
ctaHref="#stellen"
/>
<JobListingBlock showFairs={false} showJobs={true} />

View File

@@ -5,13 +5,14 @@ excerpt: "Treffen Sie das Team der E-TIB Gruppe persönlich auf Fachmessen und B
layout: "fullBleed"
---
<HomeHero
<HeroSection
badge="Messen & Events"
title="Treffen Sie uns persönlich"
description="Lernen Sie die E-TIB Gruppe auf den führenden Branchenmessen kennen."
videoUrl="/assets/videos/web/hero-bahnkreuzung.mp4"
linkText="Kontakt aufnehmen"
linkHref="/de/kontakt"
subtitle="Lernen Sie die E-TIB Gruppe auf den führenden Branchenmessen kennen."
backgroundImage={{ url: '/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-100.jpg' }}
alignment="center"
ctaLabel="Kontakt aufnehmen"
ctaHref="/de/kontakt"
/>
<div id="termine">

View File

@@ -9,7 +9,7 @@ layout: "fullBleed"
badge="Kernkompetenz"
title="Planung & Beratung"
subtitle="Kompetente Begleitung für Energie- und Telekommunikationsnetze"
backgroundImage={{ url: '/assets/photos/DJI_0048.JPG' }}
backgroundImage={{ url: '/assets/photos/etib_ingenieure_tiefbau_solar_pv_planung_vermessung_gis-298.jpg' }}
alignment="center"
ctaLabel="Projekt anfragen"
ctaHref="/de/kontakt"

View File

@@ -27,13 +27,13 @@ layout: "fullBleed"
Seit unserer Gründung im Jahr 2015 in Guben haben wir es uns zur Aufgabe gemacht, den Ausbau der kritischen Infrastruktur in Deutschland aktiv mitzugestalten.
</div>
<div>
Mit 100+ engagierten Mitarbeitenden und einem hochmodernen Maschinenpark meistern wir selbst anspruchsvollste Projekte im Kabelnetzbau, der Spülbohrtechnik und der Netzmontage. Verlässlichkeit, Termintreue und höchste Qualitätsstandards sind dabei unser Fundament.
Mit über 100 Experten für Ihr Projekt (darunter Spezialisten der E-TIB GmbH, E-TIB Bohrtechnik und E-TIB Ingenieurgesellschaft) und einem hochmodernen Maschinenpark meistern wir selbst anspruchsvollste Projekte im Kabelnetzbau, der Spülbohrtechnik und der Netzmontage. Verlässlichkeit, Termintreue und höchste Qualitätsstandards sind dabei unser Fundament.
</div>
</div>
<div className="grid grid-cols-2 gap-6">
<div className="bg-white p-8 rounded-2xl shadow-sm border border-neutral-100">
<div className="text-4xl font-extrabold text-primary mb-2">100+</div>
<div className="text-neutral-dark font-semibold">Mitarbeiter</div>
<div className="text-neutral-dark font-semibold">Mitarbeitende</div>
</div>
<div className="bg-white p-8 rounded-2xl shadow-sm border border-neutral-100">
<div className="text-4xl font-extrabold text-primary mb-2">2015</div>
@@ -52,7 +52,20 @@ layout: "fullBleed"
</div>
</div>
<InteractiveGermanyMap isHero={true} badge="Bundesweite Präsenz" title="Infrastruktur für ein ganzes Land" description="Seit 2016 haben wir in über 200 Projekten quer durch Deutschland bewiesen, dass wir Infrastrukturprojekte jeder Größenordnung verlässlich umsetzen." />
<div className="bg-[#050B14] py-24 md:py-32 text-white relative overflow-hidden group my-16 md:my-24 rounded-[2.5rem] md:rounded-[3.5rem] mx-4 md:mx-auto max-w-7xl">
<div className="absolute inset-0 bg-[url('/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-54.jpg')] opacity-20 bg-cover bg-center mix-blend-overlay group-hover:scale-105 transition-transform duration-1000"></div>
<div className="absolute inset-0 bg-gradient-to-br from-[#050B14] via-[#0A1322]/90 to-[#050B14]"></div>
<div className="container max-w-4xl mx-auto px-4 relative z-10 text-center">
<div className="inline-block px-4 py-1.5 rounded-full bg-primary/10 text-primary border border-primary/20 text-xs font-bold uppercase tracking-wider mb-8">
Bundesweite Präsenz
</div>
<h2 className="font-heading text-4xl md:text-5xl lg:text-6xl font-extrabold mb-6 leading-tight text-transparent bg-clip-text bg-gradient-to-r from-white to-white/70">Infrastruktur für<br />ein ganzes Land</h2>
<p className="text-lg md:text-xl text-white/60 mb-12 max-w-2xl mx-auto leading-relaxed">Seit 2016 haben wir in über 200 Projekten quer durch Deutschland bewiesen, dass wir Infrastrukturprojekte jeder Größenordnung verlässlich umsetzen.</p>
<a href="/de/referenzen" className="inline-flex items-center gap-3 bg-primary text-[#050B14] px-8 py-4 rounded-xl font-bold uppercase tracking-wider hover:bg-white hover:-translate-y-1 transition-all duration-300 shadow-[0_0_20px_rgba(130,237,32,0.3)]">
Zu unseren Referenzen <span className="text-xl leading-none">&rarr;</span>
</a>
</div>
</div>
<CompanyTimeline />
@@ -66,14 +79,14 @@ layout: "fullBleed"
description: "Das komplette Leistungsspektrum zur Errichtung von Kabeltrassen aus einer Hand.",
icon: "M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",
url: "/de/standorte/guben",
backgroundImage: "/assets/photos/DJI_0243.JPG"
backgroundImage: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-54.jpg"
},
{
title: "E-TIB Ingenieurgesellschaft mbH",
description: "Unsere Ingenieure planen für Sie die Energie- und Telekommunikationsnetze der Zukunft - Vermessung und Dokumentation inklusive.",
icon: "M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4",
url: "https://www.etib-ing.com/",
backgroundImage: "/assets/photos/DSC01137.JPG"
backgroundImage: "/assets/photos/etib_ingenieure_tiefbau_solar_pv_planung_vermessung_gis-298.jpg"
},
{
title: "E-TIB Verwaltung GmbH",
@@ -82,43 +95,17 @@ layout: "fullBleed"
url: "/de/standorte/buelstedt",
backgroundImage: "/assets/photos/DJI_0048.JPG"
},
{
title: "E-TIB Bohrtechnik GmbH",
description: "Präzise Horizontalspülbohrungen in allen Bodenklassen für eine oberflächenschonende und grabenlose Leitungsverlegung.",
icon: "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z",
url: "/de/standorte/kirchheilingen",
backgroundImage: "/assets/photos/DSC08653.JPG"
}
{
title: "E-TIB Bohrtechnik GmbH",
description: "Präzise Horizontalspülbohrungen in allen Bodenklassen für eine oberflächenschonende und grabenlose Leitungsverlegung.",
icon: "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z",
url: "/de/bohrtechnik",
backgroundImage: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-47.jpg"
}
]}
/>
</div>
<div className="bg-white py-24 border-b border-neutral-100">
<div className="container max-w-6xl mx-auto px-4">
<div className="text-center mb-16">
<div className="text-primary font-bold tracking-wider uppercase text-sm mb-4">Unser Team</div>
<h2 className="font-heading text-4xl md:text-5xl font-extrabold text-neutral-dark mb-6">Über 100 Experten für Ihr Projekt</h2>
<div className="w-20 h-2 bg-primary mx-auto"></div>
</div>
<div className="grid grid-cols-2 md:grid-cols-4 gap-8">
<div className="text-center">
<div className="text-5xl font-extrabold text-primary mb-2">72</div>
<div className="text-neutral-dark font-bold text-lg">E-TIB GmbH</div>
</div>
<div className="text-center">
<div className="text-5xl font-extrabold text-primary mb-2">10</div>
<div className="text-neutral-dark font-bold text-lg">E-TIB Bohrtechnik</div>
</div>
<div className="text-center">
<div className="text-5xl font-extrabold text-primary mb-2">8</div>
<div className="text-neutral-dark font-bold text-lg">E-TIB ING</div>
</div>
<div className="text-center">
<div className="text-5xl font-extrabold text-primary mb-2">10</div>
<div className="text-neutral-dark font-bold text-lg">Niedersachsen</div>
</div>
</div>
</div>
</div>
<CallToAction />

View File

@@ -8,8 +8,8 @@ layout: "fullBleed"
<HeroSection
badge="Kernkompetenz"
title="Vermessung & Dokumentation"
subtitle="Lückenlose und rechtssichere Erfassung aller Bauphasen"
backgroundImage={{ url: '/assets/photos/DSC08653.JPG' }}
subtitle="Hochpräzise digitale Bestandsdokumentation, 3D-Scans und Drohnenvermessung für Ihre Leitungstrassen und Anlagen."
backgroundImage={{ url: '/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie_Vermessung_(24_von_99)_groß2.jpg' }}
alignment="center"
ctaLabel="Projekt anfragen"
ctaHref="/de/kontakt"

View File

@@ -9,7 +9,7 @@ layout: "fullBleed"
badge="Core Competency"
title="Drilling Technology"
subtitle="Trenchless Laying, horizontal directional drilling and earth rockets"
backgroundImage={{ url: '/assets/photos/DSC08653.JPG' }}
backgroundImage={{ url: '/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-47.jpg' }}
alignment="center"
ctaLabel="Request a project"
ctaHref="/en/contact"

View File

@@ -21,14 +21,14 @@ description: "E-TIB GmbH is your reliable partner for complex cable routes, hori
description: "The complete range of services for the construction of cable routes from a single source.",
icon: "M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",
url: "/en/standorte/guben",
backgroundImage: "/assets/photos/DJI_0243.JPG"
backgroundImage: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-54.jpg"
},
{
title: "E-TIB Ingenieurgesellschaft mbH",
description: "Our engineers plan the energy and telecommunications networks of the future for you - surveying and documentation included.",
icon: "M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4",
url: "https://www.etib-ing.com/",
backgroundImage: "/assets/photos/DSC01137.JPG"
backgroundImage: "/assets/photos/etib_ingenieure_tiefbau_solar_pv_planung_vermessung_gis-298.jpg"
},
{
title: "E-TIB Verwaltung GmbH",
@@ -122,7 +122,7 @@ description: "E-TIB GmbH is your reliable partner for complex cable routes, hori
tag: "Energy",
size: "large",
href: "/en/cable-civil-engineering",
image: { url: "/assets/photos/DSC01123.JPG", alt: "Cable Civil Engineering" }
image: { url: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-54.jpg", alt: "Cable Civil Engineering" }
},
{
title: "Drilling Technology",
@@ -130,7 +130,7 @@ description: "E-TIB GmbH is your reliable partner for complex cable routes, hori
tag: "Innovation",
size: "medium",
href: "/en/drilling-technology",
image: { url: "/assets/photos/DSC08653.JPG", alt: "Drilling Technology" }
image: { url: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-47.jpg", alt: "Drilling Technology" }
},
{
title: "Planning",
@@ -138,14 +138,15 @@ description: "E-TIB GmbH is your reliable partner for complex cable routes, hori
tag: "Precision",
size: "small",
href: "/en/planning",
image: { url: "/assets/photos/DJI_0048.JPG", alt: "Planning" }
image: { url: "/assets/photos/etib_ingenieure_tiefbau_solar_pv_planung_vermessung_gis-298.jpg", alt: "Planning" }
},
{
title: "Surveying",
description: "Digital as-built documentation",
tag: "Digital",
size: "accent",
href: "/en/surveying"
href: "/en/surveying",
image: { url: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie_Vermessung_(26_von_99).jpg", alt: "Surveying" }
}
]}
/>

View File

@@ -5,13 +5,14 @@ excerpt: "Become part of a dynamic team and help us build the infrastructure of
layout: "fullBleed"
---
<HomeHero
<HeroSection
badge="Careers"
title="Build the Future"
description="Are you looking for a new challenge in a future-proof market? At E-TIB, we work daily to network Germany and drive the energy transition forward."
videoUrl="/assets/videos/web/hero-kabelpflug.mp4"
linkText="Open Positions"
linkHref="#stellen"
subtitle="Are you looking for a new challenge in a future-proof market? At E-TIB, we work daily to network Germany and drive the energy transition forward."
backgroundImage={{ url: '/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-28.jpg' }}
alignment="center"
ctaLabel="Open Positions"
ctaHref="#stellen"
/>
<JobListingBlock showFairs={false} showJobs={true} />

View File

@@ -5,13 +5,14 @@ excerpt: "Meet the team of the E-TIB Group personally at trade fairs and industr
layout: "fullBleed"
---
<HomeHero
<HeroSection
badge="Fairs & Events"
title="Meet us personally"
description="Get to know the E-TIB Group at the leading industry trade fairs."
videoUrl="/assets/videos/web/hero-bahnkreuzung.mp4"
linkText="Get in Touch"
linkHref="/en/contact"
subtitle="Get to know the E-TIB Group at the leading industry trade fairs."
backgroundImage={{ url: '/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-100.jpg' }}
alignment="center"
ctaLabel="Get in Touch"
ctaHref="/en/contact"
/>
<div id="termine">

View File

@@ -9,7 +9,7 @@ layout: "fullBleed"
badge="Core Competency"
title="Planning & Consulting"
subtitle="Competent support for energy and telecommunications networks"
backgroundImage={{ url: '/assets/photos/DJI_0048.JPG' }}
backgroundImage={{ url: '/assets/photos/etib_ingenieure_tiefbau_solar_pv_planung_vermessung_gis-298.jpg' }}
alignment="center"
ctaLabel="Request a project"
ctaHref="/en/contact"

View File

@@ -27,7 +27,7 @@ layout: "fullBleed"
Since our foundation in 2015 in Guben, we have made it our mission to actively shape the expansion of critical infrastructure.
</div>
<div>
With 100+ dedicated employees and a state-of-the-art machinery park, we master even the most demanding projects in cable network construction, directional drilling, and grid assembly. Reliability, adherence to schedules, and the highest quality standards are our foundation.
With over 100 experts for your project (including specialists from E-TIB GmbH, E-TIB Bohrtechnik and E-TIB Ingenieurgesellschaft) and a state-of-the-art machinery park, we master even the most demanding projects in cable network construction, directional drilling, and grid assembly. Reliability, adherence to schedules, and the highest quality standards are our foundation.
</div>
</div>
<div className="grid grid-cols-2 gap-6">
@@ -52,7 +52,20 @@ layout: "fullBleed"
</div>
</div>
<InteractiveGermanyMap isHero={true} badge="Nationwide Presence" title="Infrastructure for an entire country" description="Since 2016, we have proven in over 200 projects across Germany that we reliably implement infrastructure projects of any scale." />
<div className="bg-[#050B14] py-24 md:py-32 text-white relative overflow-hidden group my-16 md:my-24 rounded-[2.5rem] md:rounded-[3.5rem] mx-4 md:mx-auto max-w-7xl">
<div className="absolute inset-0 bg-[url('/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-54.jpg')] opacity-20 bg-cover bg-center mix-blend-overlay group-hover:scale-105 transition-transform duration-1000"></div>
<div className="absolute inset-0 bg-gradient-to-br from-[#050B14] via-[#0A1322]/90 to-[#050B14]"></div>
<div className="container max-w-4xl mx-auto px-4 relative z-10 text-center">
<div className="inline-block px-4 py-1.5 rounded-full bg-primary/10 text-primary border border-primary/20 text-xs font-bold uppercase tracking-wider mb-8">
Nationwide Presence
</div>
<h2 className="font-heading text-4xl md:text-5xl lg:text-6xl font-extrabold mb-6 leading-tight text-transparent bg-clip-text bg-gradient-to-r from-white to-white/70">Infrastructure for<br />an entire country</h2>
<p className="text-lg md:text-xl text-white/60 mb-12 max-w-2xl mx-auto leading-relaxed">Since 2016, we have proven in over 200 projects across Germany that we reliably implement infrastructure projects of any scale.</p>
<a href="/en/referenzen" className="inline-flex items-center gap-3 bg-primary text-[#050B14] px-8 py-4 rounded-xl font-bold uppercase tracking-wider hover:bg-white hover:-translate-y-1 transition-all duration-300 shadow-[0_0_20px_rgba(130,237,32,0.3)]">
View our references <span className="text-xl leading-none">&rarr;</span>
</a>
</div>
</div>
<CompanyTimeline />
@@ -66,14 +79,14 @@ layout: "fullBleed"
description: "The complete range of services for the construction of cable routes from a single source.",
icon: "M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",
url: "/en/standorte/guben",
backgroundImage: "/assets/photos/DJI_0243.JPG"
backgroundImage: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-54.jpg"
},
{
title: "E-TIB Ingenieurgesellschaft mbH",
description: "Our engineers plan the energy and telecommunications networks of the future for you - surveying and documentation included.",
icon: "M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4",
url: "https://www.etib-ing.com/",
backgroundImage: "/assets/photos/DSC01137.JPG"
backgroundImage: "/assets/photos/etib_ingenieure_tiefbau_solar_pv_planung_vermessung_gis-298.jpg"
},
{
title: "E-TIB Verwaltung GmbH",
@@ -86,39 +99,13 @@ layout: "fullBleed"
title: "E-TIB Bohrtechnik GmbH",
description: "Precise horizontal directional drilling in all soil classes for surface-friendly and trenchless pipe laying.",
icon: "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z",
url: "/en/standorte/kirchheilingen",
backgroundImage: "/assets/photos/DSC08653.JPG"
url: "/en/bohrtechnik",
backgroundImage: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-47.jpg"
}
]}
/>
</div>
<div className="bg-white py-24 border-b border-neutral-100">
<div className="container max-w-6xl mx-auto px-4">
<div className="text-center mb-16">
<div className="text-primary font-bold tracking-wider uppercase text-sm mb-4">Our Team</div>
<h2 className="font-heading text-4xl md:text-5xl font-extrabold text-neutral-dark mb-6">Over 100 Experts for Your Project</h2>
<div className="w-20 h-2 bg-primary mx-auto"></div>
</div>
<div className="grid grid-cols-2 md:grid-cols-4 gap-8">
<div className="text-center">
<div className="text-5xl font-extrabold text-primary mb-2">72</div>
<div className="text-neutral-dark font-bold text-lg">E-TIB GmbH</div>
</div>
<div className="text-center">
<div className="text-5xl font-extrabold text-primary mb-2">10</div>
<div className="text-neutral-dark font-bold text-lg">E-TIB Bohrtechnik</div>
</div>
<div className="text-center">
<div className="text-5xl font-extrabold text-primary mb-2">8</div>
<div className="text-neutral-dark font-bold text-lg">E-TIB ING</div>
</div>
<div className="text-center">
<div className="text-5xl font-extrabold text-primary mb-2">10</div>
<div className="text-neutral-dark font-bold text-lg">Lower Saxony</div>
</div>
</div>
</div>
</div>
<CallToAction />

View File

@@ -8,8 +8,8 @@ layout: "fullBleed"
<HeroSection
badge="Core Competency"
title="Surveying & Documentation"
subtitle="Seamless and legally compliant recording of all construction phases"
backgroundImage={{ url: '/assets/photos/DSC08653.JPG' }}
subtitle="High-precision digital as-built documentation, 3D scans, and drone surveying for your line routes and facilities."
backgroundImage={{ url: '/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie_Vermessung_(24_von_99)_groß2.jpg' }}
alignment="center"
ctaLabel="Request a project"
ctaHref="/en/contact"

View File

@@ -60,30 +60,6 @@ layout: "fullBleed"
type: 'tax',
date: '13.02.2025',
},
{
title: 'IHK Clearance Certificate',
description: 'Chamber of Industry and Commerce',
type: 'general',
},
{
title: 'HWK Clearance Certificate',
description: 'Chamber of Crafts',
type: 'general',
},
{
title: 'Commercial Register Extract',
description: 'District Court Cottbus',
type: 'general',
},
{
title: 'Trade Registration',
description: 'City of Guben',
type: 'general',
},
{
title: 'Central Trade Register',
description: 'Information from the Register',
type: 'general',
}
]}
/>

View File

@@ -45,19 +45,19 @@ export const defaultLocations: Location[] = [
},
{
id: 'ketzin',
name: 'Ketzin (Wind)',
name: 'Ketzin (Netzausbau)',
type: 'project',
x: 72,
y: 34,
description: 'Netzanbindung Windpark',
description: 'Netzausbau Gewerbegebiet',
},
{
id: 'jevenstedt',
name: 'Jevenstedt (Wind)',
name: 'Jevenstedt (Kabeltrasse)',
type: 'project',
x: 43,
y: 9,
description: 'Netzanbindung Windpark',
description: '110 kV Kabeltrasse',
}
];

View File

@@ -143,7 +143,7 @@
"prepare": "husky",
"preinstall": "npx only-allow pnpm"
},
"version": "2.2.12",
"version": "2.2.13-rc.2",
"pnpm": {
"onlyBuiltDependencies": [
"@parcel/watcher",

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 KiB

BIN
public/assets/eu-flag.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
public/assets/photos/DSC00010.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 MiB

After

Width:  |  Height:  |  Size: 447 KiB

BIN
public/assets/photos/DSC00033.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 MiB

After

Width:  |  Height:  |  Size: 570 KiB

BIN
public/assets/photos/DSC00808.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 MiB

After

Width:  |  Height:  |  Size: 434 KiB

BIN
public/assets/photos/DSC00830.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 MiB

After

Width:  |  Height:  |  Size: 336 KiB

BIN
public/assets/photos/DSC00850.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 MiB

After

Width:  |  Height:  |  Size: 422 KiB

BIN
public/assets/photos/DSC01021.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 MiB

After

Width:  |  Height:  |  Size: 702 KiB

BIN
public/assets/photos/DSC01022.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 MiB

After

Width:  |  Height:  |  Size: 380 KiB

BIN
public/assets/photos/DSC01103.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 MiB

After

Width:  |  Height:  |  Size: 406 KiB

BIN
public/assets/photos/DSC01119.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 MiB

After

Width:  |  Height:  |  Size: 664 KiB

BIN
public/assets/photos/DSC01122.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 MiB

After

Width:  |  Height:  |  Size: 546 KiB

BIN
public/assets/photos/DSC01123.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 MiB

After

Width:  |  Height:  |  Size: 636 KiB

BIN
public/assets/photos/DSC01129.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 MiB

After

Width:  |  Height:  |  Size: 877 KiB

BIN
public/assets/photos/DSC01137.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 MiB

After

Width:  |  Height:  |  Size: 894 KiB

BIN
public/assets/photos/DSC01163.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 MiB

After

Width:  |  Height:  |  Size: 402 KiB

BIN
public/assets/photos/DSC01168.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 MiB

After

Width:  |  Height:  |  Size: 755 KiB

BIN
public/assets/photos/DSC01174.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 MiB

After

Width:  |  Height:  |  Size: 306 KiB

BIN
public/assets/photos/DSC01178.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 MiB

After

Width:  |  Height:  |  Size: 686 KiB

BIN
public/assets/photos/DSC01200.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 MiB

After

Width:  |  Height:  |  Size: 660 KiB

BIN
public/assets/photos/DSC01567.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 MiB

After

Width:  |  Height:  |  Size: 606 KiB

BIN
public/assets/photos/DSC01572.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 MiB

After

Width:  |  Height:  |  Size: 432 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 919 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 KiB

BIN
public/assets/photos/DSC03612.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 MiB

After

Width:  |  Height:  |  Size: 895 KiB

BIN
public/assets/photos/DSC08626.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 MiB

After

Width:  |  Height:  |  Size: 315 KiB

BIN
public/assets/photos/DSC08641.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 MiB

After

Width:  |  Height:  |  Size: 346 KiB

BIN
public/assets/photos/DSC08645.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 MiB

After

Width:  |  Height:  |  Size: 404 KiB

BIN
public/assets/photos/DSC08649.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 MiB

After

Width:  |  Height:  |  Size: 248 KiB

BIN
public/assets/photos/DSC08653.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 MiB

After

Width:  |  Height:  |  Size: 664 KiB

BIN
public/assets/photos/DSC08744.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 MiB

After

Width:  |  Height:  |  Size: 633 KiB

BIN
public/assets/photos/DSC08753.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 MiB

After

Width:  |  Height:  |  Size: 543 KiB

BIN
public/assets/photos/DSC09945.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 MiB

After

Width:  |  Height:  |  Size: 468 KiB

BIN
public/assets/photos/DSC09951.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 MiB

After

Width:  |  Height:  |  Size: 492 KiB

BIN
public/assets/photos/DSC09953.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 MiB

After

Width:  |  Height:  |  Size: 384 KiB

BIN
public/assets/photos/DSC09955.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 MiB

After

Width:  |  Height:  |  Size: 317 KiB

BIN
public/assets/photos/DSC09960.JPG Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 MiB

After

Width:  |  Height:  |  Size: 328 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1018 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1018 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

84
scripts/priority-gate.sh Executable file
View File

@@ -0,0 +1,84 @@
#!/bin/bash
set -e
if [ -z "$GITEA_PAT" ]; then
echo "No GITEA_PAT provided, skipping priority gate."
exit 0
fi
if [ -z "$CURRENT_RUN_ID" ] || [ -z "$CURRENT_TARGET" ] || [ -z "$GITHUB_REPOSITORY" ]; then
echo "Missing required environment variables."
exit 1
fi
declare -A PRIO=( ["production"]=40 ["staging"]=30 ["testing"]=20 ["branch"]=10 )
CURRENT_PRIO=${PRIO[$CURRENT_TARGET]:-0}
echo "Current Run: $CURRENT_RUN_ID, Target: $CURRENT_TARGET, Priority: $CURRENT_PRIO"
API_BASE="https://git.infra.mintel.me/api/v1/repos/$GITHUB_REPOSITORY/actions/runs"
# Fetch running and waiting workflows
LIMIT=50
RESPONSE=$(curl -s -H "Authorization: token $GITEA_PAT" "$API_BASE?limit=$LIMIT")
# Verify response is valid JSON
if ! echo "$RESPONSE" | jq empty 2>/dev/null; then
echo "Failed to parse API response from Gitea."
echo "$RESPONSE"
exit 1
fi
# Use jq to extract running or waiting jobs that are NOT the current one
RUNS=$(echo "$RESPONSE" | jq -c '.[] | select(.id != '"$CURRENT_RUN_ID"') | select(.status == "running" or .status == "waiting")')
if [ -z "$RUNS" ]; then
echo "No other running/waiting workflows found."
exit 0
fi
while IFS= read -r run; do
if [ -z "$run" ]; then continue; fi
RUN_ID=$(echo "$run" | jq -r '.id')
REF=$(echo "$run" | jq -r '.ref')
REF_NAME=${REF#refs/tags/}
REF_NAME=${REF_NAME#refs/heads/}
# Determine target of the running workflow
TARGET="branch"
if [ "$REF" == "refs/heads/main" ] || [ "$REF_NAME" == "main" ]; then
TARGET="testing"
elif [[ "$REF" == refs/tags/* ]] || [[ "$REF" == refs/heads/v* ]]; then
if [[ "$REF_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
TARGET="production"
else
TARGET="staging"
fi
fi
RUN_PRIO=${PRIO[$TARGET]:-0}
echo "Found running workflow ID: $RUN_ID (Target: $TARGET, Priority: $RUN_PRIO)"
if [ "$CURRENT_PRIO" -gt "$RUN_PRIO" ]; then
echo "Current workflow has HIGHER priority ($CURRENT_PRIO > $RUN_PRIO). Canceling run $RUN_ID..."
curl -s -X POST -H "Authorization: token $GITEA_PAT" "$API_BASE/$RUN_ID/cancel"
elif [ "$CURRENT_PRIO" -lt "$RUN_PRIO" ]; then
echo "Current workflow has LOWER priority ($CURRENT_PRIO < $RUN_PRIO). Aborting self."
curl -s -X POST -H "Authorization: token $GITEA_PAT" "$API_BASE/$CURRENT_RUN_ID/cancel"
exit 1
else
# Equal priority: Newer wins
if [ "$CURRENT_RUN_ID" -gt "$RUN_ID" ]; then
echo "Equal priority, but current is newer. Canceling run $RUN_ID..."
curl -s -X POST -H "Authorization: token $GITEA_PAT" "$API_BASE/$RUN_ID/cancel"
else
echo "Equal priority, but current is older. Aborting self."
curl -s -X POST -H "Authorization: token $GITEA_PAT" "$API_BASE/$CURRENT_RUN_ID/cancel"
exit 1
fi
fi
done <<< "$RUNS"
echo "Priority gate cleared. Continuing deployment."

View File

@@ -75,12 +75,12 @@ describe('Task 6 Content Updates', () => {
// DE Ueber uns
expect(deContent).toContain('100+');
expect(deContent).toContain('100+ engagierten');
expect(deContent).toContain('Mitarbeitende');
expect(deContent).toContain('Seit 2016 haben wir in über 200 Projekten quer');
// EN Ueber uns
expect(enContent).toContain('100+');
expect(enContent).toContain('100+ dedicated');
expect(enContent).toContain('Employees');
expect(enContent).toContain('Since 2016, we have proven in over 200 projects across');
});
});

View File

@@ -4,7 +4,7 @@ import path from 'path';
describe('Legal Pages Content Validation', () => {
const deAgbPath = path.join(process.cwd(), 'content', 'de', 'agb.mdx');
const enTermsPath = path.join(process.cwd(), 'content', 'en', 'terms.mdx');
const enTermsPath = path.join(process.cwd(), 'content', 'en', 'agb.mdx');
it('should contain highly professional B2B sections in German AGB', () => {
const content = fs.readFileSync(deAgbPath, 'utf8');