feat: redesign page heroes, implement organic markers, and streamline contact flow
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 6s
Build & Deploy / 🧪 QA (push) Failing after 1m24s
Build & Deploy / 🏗️ Build (push) Failing after 4m3s
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🩺 Health Check (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 5s

- Refined hero sections for About, Blog, Websites, and Case Studies for a bespoke industrial entry point.
- Redesigned Marker component using layered SVG paths for an organic, hand-drawn highlighter effect.
- Restored technical precision in ArchitectureVisualizer with refined line thickness.
- Streamlined contact page by removing generic headers and prioritizing the configurator/gateway.
- Updated technical references to reflect self-hosted Gitea infrastructure.
- Cleaned up unused imports and addressed linting warnings across modified pages.
This commit is contained in:
2026-02-16 19:34:08 +01:00
parent cb32b9d62f
commit 9cfe7ee9e5
58 changed files with 3231 additions and 1592 deletions

View File

@@ -99,13 +99,27 @@ export function getDefaultAnalytics(): AnalyticsService {
websiteId: env.NEXT_PUBLIC_UMAMI_WEBSITE_ID || "",
hostUrl: env.UMAMI_API_ENDPOINT,
});
} else {
} else if (provider === "plausible") {
defaultAnalytics = createPlausibleAnalytics({
domain: env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN,
scriptUrl:
env.NEXT_PUBLIC_PLAUSIBLE_SCRIPT_URL ||
"https://plausible.yourdomain.com/js/script.js",
scriptUrl: env.NEXT_PUBLIC_PLAUSIBLE_SCRIPT_URL,
});
} else {
// No analytics provider configured
return {
getAdapter: () => ({
track: async () => {},
page: async () => {},
getScriptTag: () => null,
}),
track: async () => {},
page: async () => {},
identify: async () => {},
trackEvent: async () => {},
trackOutboundLink: async () => {},
trackSearch: async () => {},
trackPageLoad: async () => {},
} as any;
}
}
return defaultAnalytics;

View File

@@ -3,36 +3,40 @@
* Decoupled implementation
*/
import type { AnalyticsAdapter, AnalyticsEvent, AnalyticsConfig } from './interfaces';
import type {
AnalyticsAdapter,
AnalyticsEvent,
AnalyticsConfig,
} from "./interfaces";
export class PlausibleAdapter implements AnalyticsAdapter {
private domain: string;
private scriptUrl: string;
constructor(config: AnalyticsConfig) {
this.domain = config.domain || 'mintel.me';
this.scriptUrl = config.scriptUrl || 'https://plausible.yourdomain.com/js/script.js';
this.domain = config.domain || "";
this.scriptUrl = config.scriptUrl || "";
}
async track(event: AnalyticsEvent): Promise<void> {
if (typeof window === 'undefined') return;
if (typeof window === "undefined") return;
const w = window as any;
if (w.plausible) {
w.plausible(event.name, {
props: event.props
props: event.props,
});
}
}
async page(path: string, props?: Record<string, any>): Promise<void> {
await this.track({
name: 'Pageview',
props: { path, ...props }
name: "Pageview",
props: { path, ...props },
});
}
getScriptTag(): string {
return `<script defer data-domain="${this.domain}" src="${this.scriptUrl}"></script>`;
}
}
}

View File

@@ -46,14 +46,31 @@ export function getImgproxyUrl(
// Handle local paths or relative URLs
let absoluteSrc = src;
if (src.startsWith("/")) {
const baseUrl =
const baseUrlForSrc =
process.env.NEXT_PUBLIC_BASE_URL ||
(typeof window !== "undefined" ? window.location.origin : "");
if (baseUrl) {
absoluteSrc = `${baseUrl}${src}`;
if (baseUrlForSrc) {
absoluteSrc = `${baseUrlForSrc}${src}`;
}
}
// Development mapping: Map local domains to internal Docker hostnames
// so imgproxy can fetch images without SSL issues or external routing
if (process.env.NODE_ENV === "development") {
if (absoluteSrc.includes("mintel.localhost")) {
absoluteSrc = absoluteSrc.replace(
/^https?:\/\/mintel\.localhost/,
"http://app:3000",
);
} else if (absoluteSrc.includes("cms.mintel.localhost")) {
absoluteSrc = absoluteSrc.replace(
/^https?:\/\/cms\.mintel\.localhost/,
"http://directus:8055",
);
}
console.log(`[imgproxy] ${src} -> ${absoluteSrc}`);
}
const {
width = 0,
height = 0,