Add Drupal headless stack with Next.js frontend

- Add Next.js frontend service (nextjs) with Dockerfile and source
- Update docker-compose.yml: image names, Drupal 11.3.3, nextjs service
- Add docker-compose.override.yml.disabled for dev hot-reload
- Add install-headless-modules.sh for OAuth/JSON:API module setup
- Add README.md with full setup and configuration guide
- Update nginx/Dockerfile and nginx.conf.template for cms. subdomain
- Update drupal/Dockerfile PHP-FPM build args
- Gitignore **/.vscode/ to prevent IDE workspace files from being tracked
This commit is contained in:
rnsrk 2026-03-30 11:14:17 +02:00
parent 71a8dac389
commit f8b8f53d54
85 changed files with 7802 additions and 17 deletions

View file

@ -0,0 +1,253 @@
import type { Metadata } from "next"
import Image from "next/image"
import { Source_Sans_3 } from "next/font/google"
import {
LayoutGrid,
FileText,
Database,
Scale,
} from "lucide-react"
import { MainNav } from "@/components/main-nav"
import { CookieBanner } from "@/components/cookie-banner"
import "./globals.css"
const sourceSans3 = Source_Sans_3({
subsets: ["latin"],
display: "swap",
})
export const metadata: Metadata = {
title: {
default: "nasarek.dev",
template: "%s | nasarek.dev",
},
description: "Powered by Drupal and Next.js",
}
export default async function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" suppressHydrationWarning>
<body
className={`layout-body ${sourceSans3.className} flex min-h-screen flex-col bg-slate-50 text-slate-900 antialiased`}
>
<a
href="#main-content"
className="sr-only focus:not-sr-only focus:absolute focus:left-6 focus:top-4 focus:z-100 focus:rounded-md focus:bg-slate-800 focus:px-4 focus:py-2 focus:text-white focus:outline-none focus:ring-2 focus:ring-emerald-400"
>
Skip to main content
</a>
<header className="layout-header sticky top-0 z-50 border-b border-slate-700/50 bg-slate-800/95 backdrop-blur-sm">
<div className="layout-header-inner mx-auto flex max-w-7xl items-center justify-between px-4 py-4 lg:px-6">
<a
href="/"
className="layout-logo flex items-center gap-3 rounded-sm text-2xl font-bold tracking-tight text-emerald-500 outline-none transition-colors duration-200 ease-out hover:text-emerald-500 focus-visible:ring-2 focus-visible:ring-emerald-500 focus-visible:ring-offset-2 focus-visible:ring-offset-slate-800 sm:text-3xl"
aria-label="nasarek.dev home"
>
<Image
src="/icon.svg"
alt=""
width={40}
height={40}
className="size-9 shrink-0 sm:size-10"
/>
Nasarek Data Engineering
</a>
<MainNav />
</div>
</header>
<main id="main-content" className="layout-main flex flex-1 flex-col overflow-x-hidden bg-white">
<div className="layout-main-content mx-auto flex min-h-full w-full max-w-full flex-1 flex-col px-4 py-4 pb-16 lg:px-6">
{children}
</div>
</main>
<footer className="layout-footer mt-12 border-t border-slate-200 bg-slate-50">
<div className="layout-footer-inner mx-auto max-w-7xl px-6 py-12">
<div className="layout-footer-grid grid grid-cols-2 gap-8 text-center sm:text-left lg:grid-cols-4">
<div className="layout-footer-section">
<h3 className="layout-footer-heading mb-3 text-left text-sm font-semibold uppercase tracking-wider text-slate-500">
Legal
</h3>
<ul className="space-y-2">
<li className="text-left">
<a
href="/imprint"
className="inline-flex items-center gap-2 text-slate-600 outline-none transition-colors hover:text-emerald-600 focus-visible:ring-2 focus-visible:ring-emerald-500 focus-visible:ring-offset-2"
>
<Scale className="size-4 shrink-0" aria-hidden />
Imprint
</a>
</li>
</ul>
</div>
<div className="layout-footer-section">
<h3 className="layout-footer-heading mb-3 text-left text-sm font-semibold uppercase tracking-wider text-slate-500">
Social
</h3>
<ul className="space-y-2">
<li className="text-left">
<a
href="https://github.com/rnsrk"
className="group inline-flex items-center gap-2 text-slate-600 outline-none transition-colors hover:text-emerald-600 focus-visible:ring-2 focus-visible:ring-emerald-500 focus-visible:ring-offset-2"
target="_blank"
rel="noopener noreferrer"
>
<Image src="/assets/icons/github.svg" alt="" width={16} height={16} className="footer-icon-hover-emerald size-4 shrink-0 transition-[filter] duration-200" unoptimized />
GitHub
</a>
</li>
<li className="text-left">
<a
href="https://www.drupal.org/u/rnsrk"
className="group inline-flex items-center gap-2 text-slate-600 outline-none transition-colors hover:text-emerald-600 focus-visible:ring-2 focus-visible:ring-emerald-500 focus-visible:ring-offset-2"
target="_blank"
rel="noopener noreferrer"
>
<Image
src="/assets/icons/drupal.svg"
alt=""
width={16}
height={16}
className="footer-icon-hover-emerald size-4 shrink-0 transition-[filter] duration-200"
unoptimized
/>
Drupal
</a>
</li>
<li className="text-left">
<a
rel="me"
href="https://fedihum.org/@rnsrk"
className="group inline-flex items-center gap-2 text-slate-600 outline-none transition-colors hover:text-emerald-600 focus-visible:ring-2 focus-visible:ring-emerald-500 focus-visible:ring-offset-2"
target="_blank"
>
<Image
src="/assets/icons/mastodon.svg"
alt=""
width={16}
height={16}
className="footer-icon-hover-emerald size-4 shrink-0 transition-[filter] duration-200"
unoptimized
/>
Mastodon
</a>
</li>
</ul>
</div>
<div className="layout-footer-section">
<h3 className="layout-footer-heading mb-3 text-left text-sm font-semibold uppercase tracking-wider text-slate-500">
Powered by
</h3>
<ul className="space-y-2">
<li className="text-left">
<a
href="https://www.drupal.org"
className="group inline-flex items-center gap-2 text-slate-600 outline-none transition-colors duration-200 ease-out hover:text-emerald-600 focus-visible:ring-2 focus-visible:ring-emerald-500 focus-visible:ring-offset-2"
target="_blank"
rel="noopener noreferrer"
>
<Image
src="/assets/icons/drupal.svg"
alt=""
width={16}
height={16}
className="footer-icon-hover-emerald size-4 shrink-0 transition-[filter] duration-200"
unoptimized
/>
Drupal
</a>
</li>
<li className="text-left">
<a
href="https://nextjs.org"
className="group inline-flex items-center gap-2 text-slate-600 outline-none transition-colors duration-200 ease-out hover:text-emerald-600 focus-visible:ring-2 focus-visible:ring-emerald-500 focus-visible:ring-offset-2"
target="_blank"
rel="noopener noreferrer"
>
<Image
src="/assets/icons/nextjs.svg"
alt=""
width={16}
height={16}
className="footer-icon-hover-emerald size-4 shrink-0 transition-[filter] duration-200"
unoptimized
/>
Next.js
</a>
</li>
</ul>
</div>
<div className="layout-footer-section">
<h3 className="layout-footer-heading mb-3 text-left text-sm font-semibold uppercase tracking-wider text-slate-500">Media</h3>
<ul className="space-y-2">
<li className="text-left">
<a
href="https://www.youtube.com/watch?v=MGOHzreEU38"
className="group inline-flex items-center gap-2 text-slate-600 outline-none transition-colors duration-200 ease-out hover:text-emerald-600 focus-visible:ring-2 focus-visible:ring-emerald-500 focus-visible:ring-offset-2"
target="_blank"
rel="noopener noreferrer"
>
<Image
src="/assets/icons/youtube.svg"
alt=""
width={16}
height={16}
className="footer-icon-hover-emerald size-4 shrink-0 transition-[filter] duration-200"
unoptimized
/>
YouTube
</a>
</li>
<li className="text-left">
<a
href="https://open.spotify.com/episode/40v8fdhk4WcXJYu1oIF1oe"
className="group inline-flex items-center gap-2 text-slate-600 outline-none transition-colors duration-200 ease-out hover:text-emerald-600 focus-visible:ring-2 focus-visible:ring-emerald-500 focus-visible:ring-offset-2"
target="_blank"
rel="noopener noreferrer"
>
<Image
src="/assets/icons/spotify.svg"
alt=""
width={16}
height={16}
className="footer-icon-hover-emerald size-4 shrink-0 transition-[filter] duration-200"
unoptimized
/>
Spotify
</a>
</li>
<li className="text-left">
<a
href="https://zenodo.org/search?q=metadata.creators.person_or_org.name%3A%22Nasarek%2C%20Robert%22&l=list&p=1&s=10&sort=bestmatch"
className="group inline-flex items-center gap-2 text-slate-600 outline-none transition-colors hover:text-emerald-600 focus-visible:ring-2 focus-visible:ring-emerald-500 focus-visible:ring-offset-2"
target="_blank"
rel="noopener noreferrer"
>
<Image
src="/assets/icons/zenodo.svg"
alt=""
width={16}
height={16}
className="footer-icon-hover-emerald size-4 shrink-0 transition-[filter] duration-200"
unoptimized
/>
Zenodo
</a>
</li>
</ul>
</div>
</div>
<div className="layout-footer-copyright mt-10 border-t border-slate-200 pt-8 text-center text-sm text-slate-500">
&copy; {new Date().getFullYear()} nasarek.dev
</div>
</div>
</footer>
<CookieBanner />
</body>
</html>
)
}