Compare commits

..

2 Commits

Author SHA1 Message Date
Flatlogic Bot
de96e0cfc2 Autosave: 20260328-091022 2026-03-28 09:10:22 +00:00
Flatlogic Bot
b60f4a1c0e Alemdesta design1 2026-03-28 05:06:12 +00:00
28 changed files with 2215 additions and 156 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 960 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

View File

@ -6,7 +6,6 @@ const passport = require('passport');
const path = require('path'); const path = require('path');
const fs = require('fs'); const fs = require('fs');
const bodyParser = require('body-parser'); const bodyParser = require('body-parser');
const db = require('./db/models');
const config = require('./config'); const config = require('./config');
const swaggerUI = require('swagger-ui-express'); const swaggerUI = require('swagger-ui-express');
const swaggerJsDoc = require('swagger-jsdoc'); const swaggerJsDoc = require('swagger-jsdoc');
@ -16,6 +15,7 @@ const fileRoutes = require('./routes/file');
const searchRoutes = require('./routes/search'); const searchRoutes = require('./routes/search');
const sqlRoutes = require('./routes/sql'); const sqlRoutes = require('./routes/sql');
const pexelsRoutes = require('./routes/pexels'); const pexelsRoutes = require('./routes/pexels');
const contactFormRoutes = require('./routes/contactForm');
const openaiRoutes = require('./routes/openai'); const openaiRoutes = require('./routes/openai');
@ -116,6 +116,7 @@ app.use(bodyParser.json());
app.use('/api/auth', authRoutes); app.use('/api/auth', authRoutes);
app.use('/api/file', fileRoutes); app.use('/api/file', fileRoutes);
app.use('/api/pexels', pexelsRoutes); app.use('/api/pexels', pexelsRoutes);
app.use('/api/contact-form', contactFormRoutes);
app.enable('trust proxy'); app.enable('trust proxy');

View File

@ -0,0 +1,108 @@
const express = require('express');
const InquiriesService = require('../services/inquiries');
const NewsletterSubscribersService = require('../services/newsletter_subscribers');
const wrapAsync = require('../helpers').wrapAsync;
const router = express.Router();
const inquiryTypes = new Set(['contact_message', 'request_samples', 'get_a_quote', 'partner_with_us']);
const buyerTypes = new Set(['roaster', 'importer', 'distributor', 'specialty_buyer', 'wholesaler', 'other']);
const incoterms = new Set(['fob', 'cif', 'cfr', 'exw', 'dap', 'other']);
const contactMethods = new Set(['email', 'phone', 'whatsapp']);
const newsletterSources = new Set(['home_footer', 'home_cta', 'contact_page', 'popup', 'other']);
const isValidEmail = (value) => /\S+@\S+\.\S+/.test(value || '');
const badRequest = (message) => {
const error = new Error(message);
error.code = 400;
return error;
};
router.post(
'/inquiry',
wrapAsync(async (req, res) => {
const data = req.body && req.body.data ? req.body.data : {};
if (!data.full_name || !data.email || !data.company_name || !data.country || !data.message) {
throw badRequest('Full name, email, company name, country, and message are required.');
}
if (!isValidEmail(data.email)) {
throw badRequest('A valid email address is required.');
}
if (data.inquiry_type && !inquiryTypes.has(data.inquiry_type)) {
throw badRequest('Invalid inquiry type.');
}
if (data.buyer_type && !buyerTypes.has(data.buyer_type)) {
throw badRequest('Invalid buyer type.');
}
if (data.incoterm && !incoterms.has(data.incoterm)) {
throw badRequest('Invalid incoterm.');
}
if (data.preferred_contact_method && !contactMethods.has(data.preferred_contact_method)) {
throw badRequest('Invalid preferred contact method.');
}
if (data.target_volume_kg !== undefined && data.target_volume_kg !== null && Number.isNaN(Number(data.target_volume_kg))) {
throw badRequest('Target volume must be a number.');
}
await InquiriesService.create({
inquiry_type: data.inquiry_type || 'contact_message',
status: 'new',
full_name: data.full_name,
email: data.email,
phone: data.phone || null,
company_name: data.company_name,
country: data.country,
buyer_type: data.buyer_type || 'other',
message: data.message,
target_volume_kg:
data.target_volume_kg !== undefined && data.target_volume_kg !== null && data.target_volume_kg !== ''
? Number(data.target_volume_kg)
: null,
incoterm: data.incoterm || 'fob',
preferred_contact_method: data.preferred_contact_method || 'email',
submitted_at: new Date(),
});
res.status(200).send({ success: true });
}),
);
router.post(
'/newsletter',
wrapAsync(async (req, res) => {
const data = req.body && req.body.data ? req.body.data : {};
if (!data.email || !isValidEmail(data.email)) {
throw badRequest('A valid email address is required.');
}
if (data.source && !newsletterSources.has(data.source)) {
throw badRequest('Invalid newsletter source.');
}
await NewsletterSubscribersService.create({
email: data.email,
full_name: data.full_name || null,
company_name: data.company_name || null,
country: data.country || null,
source: data.source || 'other',
is_confirmed: false,
subscribed_at: new Date(),
});
res.status(200).send({ success: true });
}),
);
router.use('/', require('../helpers').commonErrorHandler);
module.exports = router;

Binary file not shown.

After

Width:  |  Height:  |  Size: 664 KiB

View File

@ -1,6 +1,5 @@
import React, {useEffect, useRef} from 'react' import React, { useEffect, useRef, useState } from 'react'
import Link from 'next/link' import Link from 'next/link'
import { useState } from 'react'
import { mdiChevronUp, mdiChevronDown } from '@mdi/js' import { mdiChevronUp, mdiChevronDown } from '@mdi/js'
import BaseDivider from './BaseDivider' import BaseDivider from './BaseDivider'
import BaseIcon from './BaseIcon' import BaseIcon from './BaseIcon'

View File

@ -0,0 +1,230 @@
import axios from 'axios';
import React, { useEffect, useMemo, useState } from 'react';
import MarketingButton from './MarketingButton';
import { buyerTypes, contactMethods, incoterms, inquiryTypes } from './marketingData';
type InquiryType = 'request_samples' | 'get_a_quote' | 'partner_with_us' | 'contact_message';
type BuyerType = 'roaster' | 'importer' | 'distributor' | 'specialty_buyer' | 'wholesaler' | 'other';
type ContactMethod = 'email' | 'phone' | 'whatsapp';
type Incoterm = 'fob' | 'cif' | 'cfr' | 'exw' | 'dap' | 'other';
type Props = {
initialInquiryType?: string;
};
type InquiryState = {
inquiry_type: InquiryType;
full_name: string;
email: string;
phone: string;
company_name: string;
country: string;
buyer_type: BuyerType;
message: string;
target_volume_kg: string;
incoterm: Incoterm;
preferred_contact_method: ContactMethod;
};
const defaultState: InquiryState = {
inquiry_type: 'request_samples',
full_name: '',
email: '',
phone: '',
company_name: '',
country: '',
buyer_type: 'importer',
message: '',
target_volume_kg: '',
incoterm: 'fob',
preferred_contact_method: 'email',
};
const allowedInquiryTypes = new Set(['request_samples', 'get_a_quote', 'partner_with_us', 'contact_message']);
export default function InquiryForm({ initialInquiryType }: Props) {
const [form, setForm] = useState<InquiryState>(defaultState);
const [errorMessage, setErrorMessage] = useState('');
const [successMessage, setSuccessMessage] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
useEffect(() => {
if (initialInquiryType && allowedInquiryTypes.has(initialInquiryType)) {
setForm((current) => ({
...current,
inquiry_type: initialInquiryType as InquiryType,
}));
}
}, [initialInquiryType]);
const title = useMemo(() => {
const currentType = inquiryTypes.find((item) => item.value === form.inquiry_type);
return currentType ? currentType.label : 'Inquiry';
}, [form.inquiry_type]);
const onChange = (
event: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
) => {
setForm((current) => ({
...current,
[event.target.name]: event.target.value,
}));
};
const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
setErrorMessage('');
setSuccessMessage('');
if (!form.full_name.trim() || !form.email.trim() || !form.company_name.trim() || !form.country.trim() || !form.message.trim()) {
setErrorMessage('Please complete name, email, company, country, and message.');
return;
}
setIsSubmitting(true);
try {
await axios.post('/contact-form/inquiry', {
data: {
...form,
target_volume_kg: form.target_volume_kg ? Number(form.target_volume_kg) : null,
},
});
setSuccessMessage(`Thank you. Your ${title.toLowerCase()} request has been received and our team will respond shortly.`);
setForm((current) => ({
...defaultState,
inquiry_type: current.inquiry_type,
}));
} catch (error) {
console.error('Inquiry submission failed', error);
setErrorMessage('Your request could not be submitted right now. Please try again or email info@alemdesta.com.');
} finally {
setIsSubmitting(false);
}
};
return (
<div className="rounded-[2rem] border border-[#1F3A2D]/10 bg-white p-6 shadow-[0_24px_80px_rgba(20,38,29,0.08)] md:p-8">
<div className="mb-6">
<p className="text-sm font-semibold uppercase tracking-[0.35em] text-[#9FB06F]">Buyer inquiry</p>
<h3 className="font-brand-display mt-3 text-3xl text-[#1F3A2D]">{title}</h3>
<p className="mt-3 max-w-2xl text-sm leading-7 text-[#556257]">
Share your sourcing goals and we will tailor a response around origins, order size, process, and export handling.
</p>
</div>
<form className="space-y-4" onSubmit={onSubmit}>
<div className="grid gap-4 md:grid-cols-2">
<label className="space-y-2 text-sm font-medium text-[#1F3A2D]">
Inquiry type
<select className="coffee-input" name="inquiry_type" value={form.inquiry_type} onChange={onChange}>
{inquiryTypes.map((item) => (
<option key={item.value} value={item.value}>
{item.label}
</option>
))}
</select>
</label>
<label className="space-y-2 text-sm font-medium text-[#1F3A2D]">
Buyer type
<select className="coffee-input" name="buyer_type" value={form.buyer_type} onChange={onChange}>
{buyerTypes.map((item) => (
<option key={item.value} value={item.value}>
{item.label}
</option>
))}
</select>
</label>
</div>
<div className="grid gap-4 md:grid-cols-2">
<label className="space-y-2 text-sm font-medium text-[#1F3A2D]">
Full name
<input className="coffee-input" name="full_name" placeholder="Your name" value={form.full_name} onChange={onChange} />
</label>
<label className="space-y-2 text-sm font-medium text-[#1F3A2D]">
Email
<input className="coffee-input" name="email" type="email" placeholder="you@company.com" value={form.email} onChange={onChange} />
</label>
</div>
<div className="grid gap-4 md:grid-cols-2">
<label className="space-y-2 text-sm font-medium text-[#1F3A2D]">
Phone / WhatsApp
<input className="coffee-input" name="phone" placeholder="Contact number" value={form.phone} onChange={onChange} />
</label>
<label className="space-y-2 text-sm font-medium text-[#1F3A2D]">
Preferred contact method
<select className="coffee-input" name="preferred_contact_method" value={form.preferred_contact_method} onChange={onChange}>
{contactMethods.map((item) => (
<option key={item.value} value={item.value}>
{item.label}
</option>
))}
</select>
</label>
</div>
<div className="grid gap-4 md:grid-cols-2">
<label className="space-y-2 text-sm font-medium text-[#1F3A2D]">
Company name
<input className="coffee-input" name="company_name" placeholder="Company" value={form.company_name} onChange={onChange} />
</label>
<label className="space-y-2 text-sm font-medium text-[#1F3A2D]">
Country
<input className="coffee-input" name="country" placeholder="Country" value={form.country} onChange={onChange} />
</label>
</div>
<div className="grid gap-4 md:grid-cols-2">
<label className="space-y-2 text-sm font-medium text-[#1F3A2D]">
Target volume (kg)
<input
className="coffee-input"
min="0"
name="target_volume_kg"
placeholder="Optional"
type="number"
value={form.target_volume_kg}
onChange={onChange}
/>
</label>
<label className="space-y-2 text-sm font-medium text-[#1F3A2D]">
Preferred Incoterm
<select className="coffee-input" name="incoterm" value={form.incoterm} onChange={onChange}>
{incoterms.map((item) => (
<option key={item.value} value={item.value}>
{item.label}
</option>
))}
</select>
</label>
</div>
<label className="space-y-2 text-sm font-medium text-[#1F3A2D]">
Message
<textarea
className="coffee-input min-h-[160px] resize-y pt-3"
name="message"
placeholder="Tell us the origins, process style, order timing, or partnership goals you are exploring."
value={form.message}
onChange={onChange}
/>
</label>
<div className="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
<p className="text-sm text-[#667367]">Submissions are routed to the admin inquiry queue for follow-up.</p>
<MarketingButton className="w-full md:w-auto" type="submit">
{isSubmitting ? 'Sending request...' : 'Submit inquiry'}
</MarketingButton>
</div>
{errorMessage ? <p className="text-sm text-red-600">{errorMessage}</p> : null}
{successMessage ? (
<div className="rounded-2xl border border-[#9FB06F]/30 bg-[#EEF3E7] px-4 py-3 text-sm text-[#1F3A2D]">{successMessage}</div>
) : null}
</form>
</div>
);
}

View File

@ -0,0 +1,48 @@
import Link from 'next/link';
import React from 'react';
type Props = {
href?: string;
onClick?: () => void;
type?: 'button' | 'submit';
variant?: 'primary' | 'secondary' | 'ghost';
className?: string;
children: React.ReactNode;
};
const baseClassName =
'inline-flex items-center justify-center rounded-full px-5 py-3 text-sm font-semibold transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-[#9FB06F] focus:ring-offset-2';
const variantMap = {
primary:
'bg-[#9FB06F] text-[#18271F] shadow-[0_16px_40px_rgba(159,176,111,0.25)] hover:-translate-y-0.5 hover:bg-[#B0C482]',
secondary:
'border border-[#B9C88D]/55 bg-white/12 text-white backdrop-blur hover:border-[#C5D39A] hover:bg-white/24',
ghost:
'border border-[#1F3A2D]/15 bg-white text-[#1F3A2D] hover:border-[#1F3A2D]/30 hover:bg-[#F4F1E6]',
};
export default function MarketingButton({
href,
onClick,
type = 'button',
variant = 'primary',
className = '',
children,
}: Props) {
const classes = `${baseClassName} ${variantMap[variant]} ${className}`;
if (href) {
return (
<Link href={href} className={classes}>
{children}
</Link>
);
}
return (
<button className={classes} onClick={onClick} type={type}>
{children}
</button>
);
}

View File

@ -0,0 +1,348 @@
import { mdiArrowRight, mdiChevronDown, mdiClose, mdiMenu } from '@mdi/js';
import Link from 'next/link';
import { useRouter } from 'next/router';
import React, { useEffect, useMemo, useState } from 'react';
import BaseIcon from '../BaseIcon';
import MarketingButton from './MarketingButton';
import NewsletterForm from './NewsletterForm';
import { brand, exportServiceItems, navigationItems } from './marketingData';
type Props = {
children: React.ReactNode;
};
type NavigationItem = (typeof navigationItems)[number];
type NavigationChild = (typeof exportServiceItems)[number];
const isActivePath = (pathname: string, href: string) => {
if (href === '/') {
return pathname === '/';
}
return pathname === href;
};
const isNavItemActive = (pathname: string, item: NavigationItem) => {
if (isActivePath(pathname, item.href)) {
return true;
}
return item.children?.some((child) => isActivePath(pathname, child.href)) ?? false;
};
const getCurrentLabel = (pathname: string) => {
const currentChild = exportServiceItems.find((item) => item.href === pathname);
if (currentChild) {
return currentChild.label;
}
const currentItem = navigationItems.find((item) => item.href === pathname);
return currentItem ? currentItem.label : 'Discover';
};
const getDesktopNavClasses = (isActive: boolean, isHomeHeroMode: boolean) => {
if (isHomeHeroMode) {
return isActive
? 'border border-white/15 bg-white/16 text-white shadow-[0_16px_45px_rgba(0,0,0,0.18)] backdrop-blur-md'
: 'border border-white/10 bg-[#173125]/58 text-[#F4F1E6] shadow-[0_14px_35px_rgba(0,0,0,0.18)] backdrop-blur-md hover:bg-[#224032]/74 hover:text-white';
}
return isActive ? 'bg-[#1F3A2D] text-[#F4F1E6]' : 'text-[#32453A] hover:bg-[#F4F1E6]';
};
const getDesktopDropdownClasses = (isHomeHeroMode: boolean) => {
return isHomeHeroMode
? 'border-white/10 bg-[#14261D]/96 text-white shadow-[0_26px_80px_rgba(0,0,0,0.32)]'
: 'border-[#1F3A2D]/10 bg-white text-[#22332B] shadow-[0_26px_80px_rgba(20,38,29,0.14)]';
};
const getDesktopDropdownItemClasses = (pathname: string, item: NavigationChild, isHomeHeroMode: boolean) => {
const isActive = isActivePath(pathname, item.href);
if (isHomeHeroMode) {
return isActive
? 'bg-white/12 text-white'
: 'text-white/78 hover:bg-white/8 hover:text-white';
}
return isActive ? 'bg-[#F4F1E6] text-[#1F3A2D]' : 'text-[#32453A] hover:bg-[#F4F1E6]/70';
};
export default function MarketingLayout({ children }: Props) {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [isExportMenuOpen, setIsExportMenuOpen] = useState(false);
const [isScrolled, setIsScrolled] = useState(false);
const router = useRouter();
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 24);
};
handleScroll();
window.addEventListener('scroll', handleScroll, { passive: true });
return () => window.removeEventListener('scroll', handleScroll);
}, []);
useEffect(() => {
setIsMenuOpen(false);
setIsExportMenuOpen(false);
}, [router.pathname]);
const currentLabel = useMemo(() => getCurrentLabel(router.pathname), [router.pathname]);
const isHomeHeroMode = router.pathname === '/' && !isScrolled && !isMenuOpen;
return (
<div className="font-brand-body min-h-screen bg-[#FBF9F1] text-[#22332B]">
<header
className={`sticky top-0 z-50 transition-all duration-300 ${
isHomeHeroMode
? 'border-b border-white/10 bg-[#102118]/62 shadow-[0_18px_50px_rgba(0,0,0,0.18)] backdrop-blur-xl'
: 'border-b border-[#1F3A2D]/10 bg-[#FBF9F1]/92 shadow-[0_18px_50px_rgba(20,38,29,0.08)] backdrop-blur-xl'
}`}
>
<div className="mx-auto flex max-w-7xl items-center justify-between gap-4 px-5 py-4 lg:px-8">
<Link href="/" className="flex items-center gap-3">
<div
className={`flex h-12 w-12 items-center justify-center rounded-full border text-sm font-semibold shadow-lg transition-colors duration-300 ${
isHomeHeroMode
? 'border-white/28 bg-white/12 text-[#F4F1E6] backdrop-blur-md'
: 'border-[#9FB06F]/50 bg-[#1F3A2D] text-[#F4F1E6]'
}`}
>
AD
</div>
<div>
<p className={`font-brand-display text-lg font-bold transition-colors duration-300 ${isHomeHeroMode ? 'text-[#F4F1E6]' : 'text-[#1F3A2D]'}`}>
Alem Desta
</p>
<p className={`text-xs uppercase tracking-[0.28em] transition-colors duration-300 ${isHomeHeroMode ? 'text-white/60' : 'text-[#72816F]'}`}>
Coffee Export
</p>
</div>
</Link>
<nav className="hidden items-center gap-1 xl:flex">
{navigationItems.map((item) => {
const isActive = isNavItemActive(router.pathname, item);
const classes = getDesktopNavClasses(isActive, isHomeHeroMode);
if (!item.children) {
return (
<Link key={item.href} href={item.href} className={`rounded-full px-4 py-2 text-sm font-medium transition-all duration-300 ${classes}`}>
{item.label}
</Link>
);
}
return (
<div key={item.href} className="group relative">
<Link href={item.href} className={`inline-flex items-center gap-2 rounded-full px-4 py-2 text-sm font-medium transition-all duration-300 ${classes}`}>
{item.label}
<BaseIcon path={mdiChevronDown} className="transition-transform duration-300 group-hover:rotate-180 group-focus-within:rotate-180" />
</Link>
<div
className={`invisible absolute left-0 top-full mt-3 w-[22rem] translate-y-2 rounded-[1.75rem] border p-3 opacity-0 transition-all duration-300 group-hover:visible group-hover:translate-y-0 group-hover:opacity-100 group-hover:pointer-events-auto group-focus-within:visible group-focus-within:translate-y-0 group-focus-within:opacity-100 ${getDesktopDropdownClasses(
isHomeHeroMode,
)}`}
>
{item.children.map((child) => (
<Link
key={child.href}
href={child.href}
className={`block rounded-[1.25rem] px-4 py-3 transition-all duration-300 ${getDesktopDropdownItemClasses(
router.pathname,
child,
isHomeHeroMode,
)}`}
>
<p className="text-sm font-semibold">{child.label}</p>
<p className={`mt-1 text-xs leading-6 ${isHomeHeroMode ? 'text-white/58' : 'text-[#68766A]'}`}>{child.description}</p>
</Link>
))}
</div>
</div>
);
})}
</nav>
<div className="hidden items-center gap-3 xl:flex">
<MarketingButton href="/login" variant={isHomeHeroMode ? 'secondary' : 'ghost'}>
Admin Login
</MarketingButton>
<MarketingButton href="/contact?type=get_a_quote">Get a Quote</MarketingButton>
</div>
<button
type="button"
onClick={() => setIsMenuOpen((current) => !current)}
className={`inline-flex h-12 w-12 items-center justify-center rounded-full border transition-all duration-300 xl:hidden ${
isHomeHeroMode
? 'border-white/20 bg-white/10 text-[#F4F1E6] backdrop-blur-md'
: 'border-[#1F3A2D]/10 bg-white text-[#1F3A2D]'
}`}
aria-label="Toggle navigation"
>
<BaseIcon path={isMenuOpen ? mdiClose : mdiMenu} />
</button>
</div>
{isMenuOpen ? (
<div className="border-t border-[#1F3A2D]/10 bg-[#FBF9F1] px-5 py-4 xl:hidden">
<div className="mb-4 rounded-2xl border border-[#9FB06F]/30 bg-[#F4F1E6] px-4 py-3 text-sm text-[#5F6C61]">
Currently viewing: <span className="font-semibold text-[#1F3A2D]">{currentLabel}</span>
</div>
<div className="flex flex-col gap-2">
{navigationItems.map((item) => {
if (!item.children) {
return (
<Link
key={item.href}
href={item.href}
className={`rounded-2xl px-4 py-3 text-sm font-medium ${
isNavItemActive(router.pathname, item) ? 'bg-[#1F3A2D] text-[#F4F1E6]' : 'bg-white text-[#1F3A2D]'
}`}
onClick={() => setIsMenuOpen(false)}
>
{item.label}
</Link>
);
}
return (
<div key={item.href} className="overflow-hidden rounded-[1.5rem] border border-[#1F3A2D]/10 bg-white">
<div className="flex items-center">
<Link
href={item.href}
className={`flex-1 px-4 py-3 text-sm font-medium ${
isNavItemActive(router.pathname, item) ? 'text-[#1F3A2D]' : 'text-[#32453A]'
}`}
onClick={() => setIsMenuOpen(false)}
>
{item.label}
</Link>
<button
type="button"
onClick={() => setIsExportMenuOpen((current) => !current)}
className="px-4 py-3 text-[#1F3A2D]"
aria-label="Toggle export services submenu"
>
<BaseIcon
path={mdiChevronDown}
className={`transition-transform duration-300 ${isExportMenuOpen ? 'rotate-180' : ''}`}
/>
</button>
</div>
{isExportMenuOpen ? (
<div className="border-t border-[#1F3A2D]/10 bg-[#FBF9F1] p-2">
{item.children.map((child) => (
<Link
key={child.href}
href={child.href}
className={`block rounded-2xl px-4 py-3 ${
isActivePath(router.pathname, child.href) ? 'bg-[#1F3A2D] text-[#F4F1E6]' : 'text-[#1F3A2D]'
}`}
onClick={() => setIsMenuOpen(false)}
>
<p className="text-sm font-medium">{child.label}</p>
<p className={`mt-1 text-xs leading-6 ${isActivePath(router.pathname, child.href) ? 'text-white/70' : 'text-[#68766A]'}`}>
{child.description}
</p>
</Link>
))}
</div>
) : null}
</div>
);
})}
</div>
<div className="mt-4 grid gap-3 sm:grid-cols-2">
<MarketingButton href="/login" variant="ghost">
Admin Login
</MarketingButton>
<MarketingButton href="/contact?type=request_samples">Request Samples</MarketingButton>
</div>
</div>
) : null}
</header>
<main>{children}</main>
<section className="border-y border-[#1F3A2D]/10 bg-[#1F3A2D] px-5 py-16 text-white lg:px-8">
<div className="mx-auto flex max-w-7xl flex-col gap-10 lg:flex-row lg:items-center lg:justify-between">
<div className="max-w-3xl">
<p className="text-sm uppercase tracking-[0.35em] text-[#B7C78B]">Ready to source with confidence?</p>
<h2 className="font-brand-display mt-4 text-4xl leading-tight text-[#F4F1E6] md:text-5xl">
Discover Ethiopian coffee backed by heritage, clear communication, and export discipline.
</h2>
</div>
<div className="flex flex-col gap-3 sm:flex-row">
<MarketingButton href="/contact?type=request_samples">Request Samples</MarketingButton>
<MarketingButton href="/contact?type=get_a_quote" variant="secondary">
Get a Quote
</MarketingButton>
</div>
</div>
</section>
<footer className="bg-[#14261D] px-5 py-16 text-white lg:px-8">
<div className="mx-auto grid max-w-7xl gap-10 lg:grid-cols-[1.1fr_0.7fr_0.95fr_1fr]">
<div>
<p className="font-brand-display text-3xl text-[#F4F1E6]">{brand.name}</p>
<p className="mt-4 max-w-xl text-sm leading-7 text-white/72">{brand.tagline}</p>
<div className="mt-8 flex flex-wrap gap-3">
<MarketingButton href="/contact?type=partner_with_us">Partner With Us</MarketingButton>
<MarketingButton href="/login" variant="secondary">
Admin Interface
</MarketingButton>
</div>
</div>
<div>
<p className="text-sm font-semibold uppercase tracking-[0.28em] text-[#9FB06F]">Main pages</p>
<div className="mt-5 grid gap-3">
{navigationItems.map((item) => (
<Link key={item.href} href={item.href} className="inline-flex items-center gap-2 text-sm text-white/75 transition hover:text-white">
<BaseIcon path={mdiArrowRight} className="text-[#9FB06F]" />
{item.label}
</Link>
))}
</div>
</div>
<div>
<p className="text-sm font-semibold uppercase tracking-[0.28em] text-[#9FB06F]">Export services</p>
<div className="mt-5 grid gap-3">
{exportServiceItems.map((item) => (
<Link key={item.href} href={item.href} className="inline-flex items-center gap-2 text-sm text-white/75 transition hover:text-white">
<BaseIcon path={mdiArrowRight} className="text-[#9FB06F]" />
{item.label}
</Link>
))}
</div>
<div className="mt-8 space-y-2 text-sm text-white/75">
<p>{brand.address}</p>
<p>{brand.email}</p>
{brand.phones.map((phone) => (
<p key={phone}>{phone}</p>
))}
</div>
</div>
<div>
<p className="text-sm font-semibold uppercase tracking-[0.28em] text-[#9FB06F]">Newsletter subscription</p>
<p className="mt-4 text-sm leading-7 text-white/72">
Receive market-ready updates, sourcing availability, and company news tailored for international buyers.
</p>
<div className="mt-5">
<NewsletterForm compact source="home_footer" />
</div>
</div>
</div>
</footer>
</div>
);
}

View File

@ -0,0 +1,27 @@
import React from 'react';
type Props = {
eyebrow: string;
title: string;
description: string;
image: string;
};
export default function MarketingPageHero({ eyebrow, title, description, image }: Props) {
return (
<section className="px-5 pb-8 pt-12 lg:px-8 lg:pb-12 lg:pt-16">
<div className="mx-auto grid max-w-7xl gap-8 overflow-hidden rounded-[2rem] bg-[#F4F1E6] p-6 shadow-[0_28px_90px_rgba(31,58,45,0.08)] lg:grid-cols-[1.05fr_0.95fr] lg:p-10">
<div className="flex flex-col justify-center">
<p className="text-sm font-semibold uppercase tracking-[0.35em] text-[#9FB06F]">{eyebrow}</p>
<h1 className="font-brand-display mt-4 text-4xl leading-tight text-[#1F3A2D] md:text-6xl">{title}</h1>
<p className="mt-6 max-w-2xl text-base leading-8 text-[#556257]">{description}</p>
</div>
<div className="relative min-h-[320px] overflow-hidden rounded-[1.75rem]">
<img className="absolute inset-0 h-full w-full object-cover saturate-[0.88]" loading="eager" src={image} alt={title} />
<div className="absolute inset-0 bg-[linear-gradient(160deg,rgba(16,33,24,0.08),rgba(36,63,48,0.22),rgba(16,33,24,0.42))]" />
<div className="absolute inset-0 bg-gradient-to-t from-[#102118]/54 via-transparent to-transparent" />
</div>
</div>
</section>
);
}

View File

@ -0,0 +1,32 @@
import React from 'react';
type Props = {
eyebrow?: string;
title: string;
description?: string;
children?: React.ReactNode;
className?: string;
centered?: boolean;
};
export default function MarketingSection({
eyebrow,
title,
description,
children,
className = '',
centered = false,
}: Props) {
return (
<section className={`px-5 py-16 lg:px-8 lg:py-24 ${className}`}>
<div className="mx-auto max-w-7xl">
<div className={centered ? 'mx-auto max-w-3xl text-center' : 'max-w-3xl'}>
{eyebrow ? <p className="text-sm font-semibold uppercase tracking-[0.35em] text-[#9FB06F]">{eyebrow}</p> : null}
<h2 className="font-brand-display mt-4 text-4xl leading-tight text-[#1F3A2D] md:text-5xl">{title}</h2>
{description ? <p className="mt-5 text-base leading-8 text-[#556257]">{description}</p> : null}
</div>
{children ? <div className="mt-12">{children}</div> : null}
</div>
</section>
);
}

View File

@ -0,0 +1,25 @@
import Head from 'next/head';
import React from 'react';
import { brand } from './marketingData';
type Props = {
title: string;
description: string;
keywords?: string;
};
export default function MarketingSeo({ title, description, keywords }: Props) {
const fullTitle = `${title} | ${brand.name}`;
return (
<Head>
<title>{fullTitle}</title>
<meta name="description" content={description} />
<meta
name="keywords"
content={keywords || 'Ethiopian coffee export, specialty coffee, green coffee beans, single origin coffee'}
/>
</Head>
);
}

View File

@ -0,0 +1,119 @@
import axios from 'axios';
import React, { useState } from 'react';
import MarketingButton from './MarketingButton';
type Props = {
source?: string;
compact?: boolean;
};
type NewsletterState = {
email: string;
full_name: string;
company_name: string;
country: string;
};
const initialState: NewsletterState = {
email: '',
full_name: '',
company_name: '',
country: '',
};
export default function NewsletterForm({ source = 'home_footer', compact = false }: Props) {
const [form, setForm] = useState<NewsletterState>(initialState);
const [errorMessage, setErrorMessage] = useState('');
const [successMessage, setSuccessMessage] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setForm((current) => ({
...current,
[event.target.name]: event.target.value,
}));
};
const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
setErrorMessage('');
setSuccessMessage('');
if (!form.email.trim()) {
setErrorMessage('Email is required.');
return;
}
setIsSubmitting(true);
try {
await axios.post('/contact-form/newsletter', {
data: {
...form,
source,
},
});
setSuccessMessage('Thank you. You have been added to our coffee export updates list.');
setForm(initialState);
} catch (error) {
console.error('Newsletter subscription failed', error);
setErrorMessage('Subscription could not be completed right now. Please try again shortly.');
} finally {
setIsSubmitting(false);
}
};
return (
<form className="space-y-3" onSubmit={onSubmit}>
{!compact && (
<div className="grid gap-3 md:grid-cols-2">
<input
className="h-12 rounded-2xl border border-white/15 bg-white/10 px-4 text-sm text-white placeholder:text-white/55 focus:outline-none focus:ring-2 focus:ring-[#9FB06F]"
name="full_name"
placeholder="Name"
value={form.full_name}
onChange={onChange}
/>
<input
className="h-12 rounded-2xl border border-white/15 bg-white/10 px-4 text-sm text-white placeholder:text-white/55 focus:outline-none focus:ring-2 focus:ring-[#9FB06F]"
name="company_name"
placeholder="Company"
value={form.company_name}
onChange={onChange}
/>
</div>
)}
<div className={`grid gap-3 ${compact ? 'md:grid-cols-[minmax(0,1fr)_auto]' : 'md:grid-cols-[minmax(0,1fr)_minmax(0,1fr)]'}`}>
<input
className="h-12 rounded-2xl border border-white/15 bg-white/10 px-4 text-sm text-white placeholder:text-white/55 focus:outline-none focus:ring-2 focus:ring-[#9FB06F]"
name="email"
placeholder="Email address"
type="email"
value={form.email}
onChange={onChange}
/>
{compact ? (
<MarketingButton className="w-full md:w-auto" type="submit">
{isSubmitting ? 'Subscribing...' : 'Subscribe'}
</MarketingButton>
) : (
<input
className="h-12 rounded-2xl border border-white/15 bg-white/10 px-4 text-sm text-white placeholder:text-white/55 focus:outline-none focus:ring-2 focus:ring-[#9FB06F]"
name="country"
placeholder="Country"
value={form.country}
onChange={onChange}
/>
)}
</div>
{!compact && (
<MarketingButton className="w-full md:w-auto" type="submit">
{isSubmitting ? 'Subscribing...' : 'Subscribe to updates'}
</MarketingButton>
)}
{errorMessage ? <p className="text-sm text-[#f8caca]">{errorMessage}</p> : null}
{successMessage ? <p className="text-sm text-[#d9c08e]">{successMessage}</p> : null}
</form>
);
}

View File

@ -0,0 +1,276 @@
export const brand = {
name: 'Alem Desta Coffee Export',
tagline: 'Premium Ethiopian green coffee sourced with heritage, integrity, and export discipline.',
email: 'info@alemdesta.com',
phones: ['+251 930105914', '+251 904186868'],
address: 'Kirkos Sub-city, Wereda 01, Addis Ababa, Ethiopia',
};
export const exportServiceItems = [
{
href: '/coffee-origins',
label: 'Coffee Origins',
description: 'Single-origin coffees from iconic Ethiopian regions with distinct altitude, profile, and terroir.',
},
{
href: '/quality-control',
label: 'Quality Control',
description: 'Disciplined cherry selection, moisture monitoring, and cupping protocols before export.',
},
{
href: '/sustainability',
label: 'Sustainability',
description: 'Long-term sourcing built around farmer respect, environmental care, and transparent relationships.',
},
{
href: '/logistics-export',
label: 'Logistics & Export',
description: 'Documentation, shipment coordination, and responsive communication from Addis Ababa to destination.',
},
];
export const navigationItems = [
{ href: '/', label: 'Home' },
{ href: '/about', label: 'About' },
{ href: '/export-services', label: 'Export Services', children: exportServiceItems },
{ href: '/contact', label: 'Contact' },
];
export const featureHighlights = [
{
title: 'Traceability & Transparency',
description:
'Every shipment is sourced with documented origin details, responsible handling, and buyer-ready clarity from farm gate to export.',
},
{
title: 'Premium Quality Control',
description:
'Careful cherry selection, moisture monitoring, cupping review, and export preparation protect cup quality at every stage.',
},
{
title: 'Direct Farmer Partnerships',
description:
'We build relationships with skilled producers and washing stations to secure consistency, trust, and long-term value.',
},
{
title: 'Sustainable Sourcing',
description:
'Commercial success is paired with responsible sourcing practices that respect communities, land, and future harvests.',
},
];
export const galleryItems = [
{
title: 'Green coffee landscapes',
caption: 'Highland farms and careful cultivation create the foundation for exceptional green coffee lots.',
image:
'https://images.unsplash.com/photo-1447933601403-0c6688de566e?auto=format&fit=crop&w=1200&q=80',
},
{
title: 'Washing station discipline',
caption: 'Lot separation, drying control, and station handling protect specialty green coffee quality before export.',
image:
'https://images.unsplash.com/photo-1495474472287-4d71bcdd2085?auto=format&fit=crop&w=1200&q=80',
},
{
title: 'Lot evaluation',
caption: 'Cupping, moisture review, and sample assessment help buyers select green coffee with confidence.',
image:
'https://images.unsplash.com/photo-1511920170033-f8396924c348?auto=format&fit=crop&w=1200&q=80',
},
{
title: 'Export-ready preparation',
caption: 'Packaging, documentation, and shipment coordination move export-ready green coffee toward global buyers.',
image:
'https://images.unsplash.com/photo-1520607162513-77705c0f0d4a?auto=format&fit=crop&w=1200&q=80',
},
];
export const founderStory = [
'Alem Desta Coffee Export was shaped by a life rooted in Ethiopian coffee culture, where coffee is more than a crop; it is hospitality, identity, and daily ritual. Growing up with that tradition created a deep respect for the people, landscapes, and craftsmanship behind every cup.',
'Family tradition made coffee familiar from an early age, but global experience expanded the vision. Time spent in the United States — including Chicago, San Francisco, and the DMV area — offered a firsthand understanding of how international buyers evaluate quality, consistency, communication, and professionalism.',
'Returning to Ethiopia brought that perspective back to origin. It also created the opportunity to learn closely from a brother already active in coffee exporting, translating heritage into disciplined export practice, relationship building, and an appreciation for what buyers genuinely need from a trusted supplier.',
'Today the business stands at the intersection of culture, global exposure, and commercial responsibility: honoring Ethiopian roots while delivering premium coffee with clear communication, traceability, and long-term partnership in mind.',
];
export const philosophyPillars = [
{
title: 'Altitude',
description: 'High-altitude growing environments support clarity, floral aromatics, and refined complexity.',
},
{
title: 'Soil',
description: 'Rich natural soils nourish coffee trees slowly and help create layered flavor expression.',
},
{
title: 'Climate',
description: 'Balanced rainfall, sunlight, and cool nights allow cherries to mature with patience.',
},
{
title: 'Human Craftsmanship',
description: 'Excellence depends on farmers, processors, cuppers, and exporters applying skill at every step.',
},
];
export const values = [
{
title: 'Integrity',
description: 'We communicate honestly, document carefully, and build trust through dependable execution.',
},
{
title: 'Culture & Heritage',
description: 'Our work is grounded in Ethiopian coffee tradition and respect for origin.',
},
{
title: 'Quality Excellence',
description: 'We pursue careful selection, disciplined processing, and export readiness without compromise.',
},
{
title: 'Partnership',
description: 'We value long-term relationships with farmers, washing stations, and international buyers.',
},
{
title: 'Responsibility',
description: 'Commercial growth should strengthen communities and support ethical business practices.',
},
{
title: 'Sustainability',
description: 'Responsible sourcing protects both the environment and the future of coffee farming.',
},
];
export const principles = [
'Direct sourcing',
'Full traceability',
'Compliance with international standards',
'Long-term relationships',
'Continuous improvement',
];
export const origins = [
{
name: 'Yirgacheffe',
profile: 'Floral, citrus, bright acidity',
altitude: '19002200 MASL',
rainfall: 'Balanced seasonal rainfall',
image:
'https://images.unsplash.com/photo-1461988320302-91bde64fc8e4?auto=format&fit=crop&w=900&q=80',
},
{
name: 'Guji',
profile: 'Fruity, vibrant sweetness',
altitude: '18002200 MASL',
rainfall: 'Reliable mountain rainfall',
image:
'https://images.unsplash.com/photo-1509042239860-f550ce710b93?auto=format&fit=crop&w=900&q=80',
},
{
name: 'Sidama',
profile: 'Balanced, complex flavor',
altitude: '17002200 MASL',
rainfall: 'Rich rainfall with cool nights',
image:
'https://images.unsplash.com/photo-1442512595331-e89e73853f31?auto=format&fit=crop&w=900&q=80',
},
{
name: 'Harrar',
profile: 'Bold, winey, spicy',
altitude: '15002100 MASL',
rainfall: 'Drier climate with intense character',
image:
'https://images.unsplash.com/photo-1455470956270-4cbb357f60f6?auto=format&fit=crop&w=900&q=80',
},
{
name: 'Limu & Jimma',
profile: 'Chocolatey, smooth',
altitude: '14002100 MASL',
rainfall: 'Steady seasonal rainfall',
image:
'https://images.unsplash.com/photo-1494314671902-399b18174975?auto=format&fit=crop&w=900&q=80',
},
];
export const qualityProcesses = [
{
title: 'Washed Process',
highlight: 'Clean, bright coffee profile',
steps: ['Selective harvesting', 'Pulping', 'Fermentation', 'Washing', 'Drying', 'Milling'],
},
{
title: 'Natural Process',
highlight: 'Sun-dried cherries develop fruity, bold flavors with patient drying.',
steps: ['Selective harvesting', 'Whole cherry drying', 'Slow turning', 'Moisture stabilization', 'Hulling'],
},
{
title: 'Honey Process',
highlight: 'A semi-washed style balancing sweetness, texture, and acidity.',
steps: ['Selective harvesting', 'Depulping', 'Mucilage retention', 'Controlled drying', 'Milling'],
},
];
export const qualityMetrics = [
'Moisture control: 1012%',
'Cupping evaluation of aroma',
'Body and mouthfeel review',
'Acidity balance and clarity',
'Aftertaste consistency',
];
export const exportServices = [
'FOB Djibouti export system managed with professional coordination',
'Documentation handled internally for smoother buyer communication',
'Reliable logistics chain from Addis Ababa to Djibouti and onward to global markets',
'Flexible order volumes for specialty buyers, roasters, and wholesale partners',
'Timely delivery expectations supported by strong communication and planning',
];
export const sustainabilityPoints = [
'Fair payment practices that respect producer effort and quality',
'Ethical sourcing grounded in long-term supplier relationships',
'Environmental responsibility in cultivation and processing decisions',
'Community development engagement where coffee value begins',
];
export const testimonials = [
{
quote:
'A disciplined, origin-driven Ethiopian exporter with the kind of communication international buyers appreciate.',
author: 'Testimonial placeholder — Specialty roasting partner',
},
{
quote:
'The combination of traceability, cup quality, and professionalism signals strong export potential.',
author: 'Testimonial placeholder — Green coffee importer',
},
];
export const buyerTypes = [
{ value: 'roaster', label: 'Roaster' },
{ value: 'importer', label: 'Importer' },
{ value: 'distributor', label: 'Distributor' },
{ value: 'specialty_buyer', label: 'Specialty buyer' },
{ value: 'wholesaler', label: 'Wholesaler' },
{ value: 'other', label: 'Other' },
];
export const inquiryTypes = [
{ value: 'request_samples', label: 'Request Samples' },
{ value: 'get_a_quote', label: 'Get a Quote' },
{ value: 'partner_with_us', label: 'Partner With Us' },
{ value: 'contact_message', label: 'General Inquiry' },
];
export const incoterms = [
{ value: 'fob', label: 'FOB' },
{ value: 'cif', label: 'CIF' },
{ value: 'cfr', label: 'CFR' },
{ value: 'exw', label: 'EXW' },
{ value: 'dap', label: 'DAP' },
{ value: 'other', label: 'Other' },
];
export const contactMethods = [
{ value: 'email', label: 'Email' },
{ value: 'phone', label: 'Phone' },
{ value: 'whatsapp', label: 'WhatsApp' },
];

View File

@ -62,3 +62,62 @@ font-family: 'Ubuntu', sans-serif !important;
.introjs-prevbutton{ .introjs-prevbutton{
@apply bg-transparent border border-pastelBrownTheme-buttonColor text-pastelBrownTheme-buttonColor !important; @apply bg-transparent border border-pastelBrownTheme-buttonColor text-pastelBrownTheme-buttonColor !important;
} }
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Playfair+Display:wght@600;700;800&display=swap');
:root {
--coffee-brown: #1F3A2D;
--coffee-beige: #F4F1E6;
--coffee-gold: #9FB06F;
}
html {
scroll-behavior: smooth;
}
.font-brand-display {
font-family: 'Playfair Display', Georgia, serif;
}
.font-brand-body {
font-family: 'Inter', 'Ubuntu', sans-serif;
}
.coffee-input {
width: 100%;
height: 3.25rem;
border-radius: 1rem;
border: 1px solid rgba(31, 58, 45, 0.14);
background: #F8FAF4;
padding: 0 1rem;
font-size: 0.95rem;
color: #22332B;
transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
}
.coffee-input:focus {
outline: none;
border-color: rgba(159, 176, 111, 0.82);
box-shadow: 0 0 0 3px rgba(159, 176, 111, 0.18);
background: #ffffff;
}
.coffee-input::placeholder {
color: #869488;
}
@keyframes coffeeFadeIn {
from {
opacity: 0;
transform: translateY(14px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.coffee-fade-in {
animation: coffeeFadeIn 0.8s ease both;
}

View File

@ -1,5 +1,4 @@
import React, { ReactNode, useEffect } from 'react' import React, { ReactNode, useEffect, useState } from 'react'
import { useState } from 'react'
import jwt from 'jsonwebtoken'; import jwt from 'jsonwebtoken';
import { mdiForwardburger, mdiBackburger, mdiMenu } from '@mdi/js' import { mdiForwardburger, mdiBackburger, mdiMenu } from '@mdi/js'
import menuAside from '../menuAside' import menuAside from '../menuAside'

View File

@ -0,0 +1,58 @@
import type { ReactElement } from 'react';
import React from 'react';
import MarketingLayout from '../components/marketing/MarketingLayout';
import MarketingPageHero from '../components/marketing/MarketingPageHero';
import MarketingSeo from '../components/marketing/MarketingSeo';
import MarketingSection from '../components/marketing/MarketingSection';
import { founderStory } from '../components/marketing/marketingData';
import LayoutGuest from '../layouts/Guest';
export default function AboutPage() {
return (
<>
<MarketingSeo
title="About Alem Desta Coffee Export"
description="Founder story, Ethiopian coffee heritage, U.S. market exposure, and the roots behind Alem Desta Coffee Export."
/>
<MarketingLayout>
<MarketingPageHero
eyebrow="About us"
title="A heritage-led coffee export business shaped by global perspective"
description="Our story combines Ethiopian coffee culture, family tradition, U.S. market exposure, and practical export learning grounded in real relationships."
image="https://images.unsplash.com/photo-1495474472287-4d71bcdd2085?auto=format&fit=crop&w=1400&q=80"
/>
<MarketingSection
eyebrow="Founder story"
title="From Ethiopian coffee culture to global buyer understanding"
description="The company story is personal, emotional, and practical — exactly the mix international buyers often trust most when choosing who to work with."
>
<div className="grid gap-6 lg:grid-cols-[0.8fr_1.2fr]">
<div className="rounded-[2rem] bg-[#1F3A2D] p-8 text-white shadow-[0_24px_80px_rgba(20,38,29,0.14)]">
<p className="text-sm uppercase tracking-[0.32em] text-[#B7C78B]">What shapes the company</p>
<ul className="mt-6 space-y-4 text-sm leading-7 text-white/78">
<li> Ethiopian coffee culture upbringing</li>
<li> Family coffee tradition</li>
<li> U.S. experience in Chicago, San Francisco, and the DMV</li>
<li> Return to Ethiopia with renewed business purpose</li>
<li> Export learning through close family mentorship</li>
</ul>
</div>
<div className="space-y-6">
{founderStory.map((paragraph) => (
<div key={paragraph} className="rounded-[1.75rem] border border-[#1F3A2D]/8 bg-white p-7 shadow-[0_18px_60px_rgba(20,38,29,0.06)]">
<p className="text-base leading-8 text-[#556257]">{paragraph}</p>
</div>
))}
</div>
</div>
</MarketingSection>
</MarketingLayout>
</>
);
}
AboutPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};

View File

@ -0,0 +1,55 @@
import type { ReactElement } from 'react';
import React from 'react';
import MarketingLayout from '../components/marketing/MarketingLayout';
import MarketingPageHero from '../components/marketing/MarketingPageHero';
import MarketingSeo from '../components/marketing/MarketingSeo';
import MarketingSection from '../components/marketing/MarketingSection';
import { origins } from '../components/marketing/marketingData';
import LayoutGuest from '../layouts/Guest';
export default function CoffeeOriginsPage() {
return (
<>
<MarketingSeo
title="Coffee Origins"
description="Explore Ethiopian coffee regions including Yirgacheffe, Guji, Sidama, Harrar, Limu, and Jimma."
/>
<MarketingLayout>
<MarketingPageHero
eyebrow="Coffee origins"
title="Regional character that gives Ethiopian coffee its global distinction"
description="Each origin tells a different flavor story, giving international buyers a practical way to align sourcing decisions with roast goals and customer preferences."
image="https://images.unsplash.com/photo-1455470956270-4cbb357f60f6?auto=format&fit=crop&w=1400&q=80"
/>
<MarketingSection
eyebrow="Origin portfolio"
title="A curated overview of key coffee-producing regions"
description="These region cards provide a premium, buyer-friendly snapshot of profile, altitude, and growing context."
>
<div className="grid gap-6 lg:grid-cols-2 xl:grid-cols-3">
{origins.map((item) => (
<article key={item.name} className="overflow-hidden rounded-[2rem] bg-white shadow-[0_24px_70px_rgba(20,38,29,0.08)]">
<div className="relative">
<img className="h-64 w-full object-cover saturate-[0.9]" loading="lazy" src={item.image} alt={item.name} />
<div className="absolute inset-0 bg-[linear-gradient(180deg,rgba(18,38,29,0.05),rgba(18,38,29,0),rgba(18,38,29,0.25))]" />
</div>
<div className="p-6">
<p className="text-sm uppercase tracking-[0.28em] text-[#9FB06F]">{item.altitude}</p>
<h2 className="font-brand-display mt-3 text-3xl text-[#1F3A2D]">{item.name}</h2>
<p className="mt-4 text-sm leading-7 text-[#556257]">{item.profile}</p>
<div className="mt-5 rounded-2xl bg-[#F4F1E6] px-4 py-3 text-sm text-[#556257]">Rainfall: {item.rainfall}</div>
</div>
</article>
))}
</div>
</MarketingSection>
</MarketingLayout>
</>
);
}
CoffeeOriginsPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};

View File

@ -0,0 +1,55 @@
import { mdiTerrain, mdiWeatherPartlyCloudy, mdiSprout, mdiHumanGreeting } from '@mdi/js';
import type { ReactElement } from 'react';
import React from 'react';
import BaseIcon from '../components/BaseIcon';
import MarketingLayout from '../components/marketing/MarketingLayout';
import MarketingPageHero from '../components/marketing/MarketingPageHero';
import MarketingSeo from '../components/marketing/MarketingSeo';
import MarketingSection from '../components/marketing/MarketingSection';
import { philosophyPillars } from '../components/marketing/marketingData';
import LayoutGuest from '../layouts/Guest';
const icons = [mdiTerrain, mdiSprout, mdiWeatherPartlyCloudy, mdiHumanGreeting];
export default function CoffeePhilosophyPage() {
return (
<>
<MarketingSeo
title="Coffee Philosophy"
description="Coffee excellence begins at origin — patience, altitude, climate, soil, and craftsmanship define premium Ethiopian coffee."
/>
<MarketingLayout>
<MarketingPageHero
eyebrow="Coffee philosophy"
title="Coffee Excellence Begins at Origin"
description="Coffee is not industrial. It is crafted — by land, weather, skilled hands, and the patience required to let quality mature naturally."
image="https://images.unsplash.com/photo-1509042239860-f550ce710b93?auto=format&fit=crop&w=1400&q=80"
/>
<MarketingSection
eyebrow="Our belief"
title="Great coffee is the result of nature and human discipline working together"
description="This page articulates a premium sourcing philosophy buyers can feel: Ethiopian coffee is a crafted product, not a commodity shortcut."
centered
>
<div className="grid gap-6 md:grid-cols-2 xl:grid-cols-4">
{philosophyPillars.map((item, index) => (
<div key={item.title} className="rounded-[1.75rem] border border-[#1F3A2D]/8 bg-white p-7 shadow-[0_20px_65px_rgba(20,38,29,0.06)]">
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#F4F1E6] text-[#1F3A2D]">
<BaseIcon path={icons[index]} />
</div>
<h3 className="font-brand-display mt-5 text-2xl text-[#1F3A2D]">{item.title}</h3>
<p className="mt-4 text-sm leading-7 text-[#556257]">{item.description}</p>
</div>
))}
</div>
</MarketingSection>
</MarketingLayout>
</>
);
}
CoffeePhilosophyPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};

View File

@ -0,0 +1,102 @@
import { mdiEmailOutline, mdiMapMarkerOutline, mdiPhoneOutline } from '@mdi/js';
import type { ReactElement } from 'react';
import { useRouter } from 'next/router';
import React from 'react';
import BaseIcon from '../components/BaseIcon';
import InquiryForm from '../components/marketing/InquiryForm';
import MarketingButton from '../components/marketing/MarketingButton';
import MarketingLayout from '../components/marketing/MarketingLayout';
import MarketingPageHero from '../components/marketing/MarketingPageHero';
import MarketingSeo from '../components/marketing/MarketingSeo';
import MarketingSection from '../components/marketing/MarketingSection';
import { brand } from '../components/marketing/marketingData';
import LayoutGuest from '../layouts/Guest';
const inquiryLinks = [
{ href: '/contact?type=request_samples', label: 'Request Samples' },
{ href: '/contact?type=get_a_quote', label: 'Get a Quote' },
{ href: '/contact?type=partner_with_us', label: 'Partner With Us' },
];
export default function ContactPage() {
const router = useRouter();
const initialType = typeof router.query.type === 'string' ? router.query.type : undefined;
return (
<>
<MarketingSeo
title="Contact"
description="Contact Alem Desta Coffee Export in Addis Ababa and submit sample requests, quote requests, or partnership inquiries."
/>
<MarketingLayout>
<MarketingPageHero
eyebrow="Contact"
title="Start a confident buying conversation"
description="The contact experience is designed as a real workflow: choose your inquiry type, submit details, and route the request directly into the admin inquiry queue."
image="https://images.unsplash.com/photo-1494314671902-399b18174975?auto=format&fit=crop&w=1400&q=80"
/>
<MarketingSection
eyebrow="How to engage"
title="Choose the right buyer action and share your needs"
description="Sample requests, quotes, and partnership conversations all flow through one elegant form so your team can respond quickly and consistently."
>
<div className="flex flex-wrap gap-3">
{inquiryLinks.map((item) => (
<MarketingButton key={item.href} href={item.href} variant={initialType === item.href.split('=')[1] ? 'primary' : 'ghost'}>
{item.label}
</MarketingButton>
))}
</div>
<div className="mt-10 grid gap-8 lg:grid-cols-[0.75fr_1.25fr]">
<div className="space-y-5">
<div className="rounded-[1.75rem] border border-[#1F3A2D]/8 bg-white p-6 shadow-[0_20px_65px_rgba(20,38,29,0.06)]">
<div className="flex items-start gap-4">
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#F4F1E6] text-[#1F3A2D]">
<BaseIcon path={mdiMapMarkerOutline} />
</div>
<div>
<p className="text-sm font-semibold uppercase tracking-[0.28em] text-[#9FB06F]">Location</p>
<p className="mt-3 text-sm leading-7 text-[#556257]">{brand.address}</p>
</div>
</div>
</div>
<div className="rounded-[1.75rem] border border-[#1F3A2D]/8 bg-white p-6 shadow-[0_20px_65px_rgba(20,38,29,0.06)]">
<div className="flex items-start gap-4">
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#F4F1E6] text-[#1F3A2D]">
<BaseIcon path={mdiEmailOutline} />
</div>
<div>
<p className="text-sm font-semibold uppercase tracking-[0.28em] text-[#9FB06F]">Email</p>
<p className="mt-3 text-sm leading-7 text-[#556257]">{brand.email}</p>
</div>
</div>
</div>
<div className="rounded-[1.75rem] border border-[#1F3A2D]/8 bg-white p-6 shadow-[0_20px_65px_rgba(20,38,29,0.06)]">
<div className="flex items-start gap-4">
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#F4F1E6] text-[#1F3A2D]">
<BaseIcon path={mdiPhoneOutline} />
</div>
<div>
<p className="text-sm font-semibold uppercase tracking-[0.28em] text-[#9FB06F]">Phone</p>
<div className="mt-3 space-y-1 text-sm leading-7 text-[#556257]">
{brand.phones.map((phone) => (
<p key={phone}>{phone}</p>
))}
</div>
</div>
</div>
</div>
</div>
<InquiryForm initialInquiryType={initialType} />
</div>
</MarketingSection>
</MarketingLayout>
</>
);
}
ContactPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};

View File

@ -0,0 +1,119 @@
import {
mdiCompassOutline,
mdiLeaf,
mdiShieldCheckOutline,
mdiTruckFastOutline,
} from '@mdi/js';
import type { ReactElement } from 'react';
import React from 'react';
import BaseIcon from '../components/BaseIcon';
import MarketingButton from '../components/marketing/MarketingButton';
import MarketingLayout from '../components/marketing/MarketingLayout';
import MarketingPageHero from '../components/marketing/MarketingPageHero';
import MarketingSeo from '../components/marketing/MarketingSeo';
import MarketingSection from '../components/marketing/MarketingSection';
import { exportServiceItems } from '../components/marketing/marketingData';
import LayoutGuest from '../layouts/Guest';
const iconByHref = {
'/coffee-origins': mdiCompassOutline,
'/quality-control': mdiShieldCheckOutline,
'/sustainability': mdiLeaf,
'/logistics-export': mdiTruckFastOutline,
};
const workflowSteps = [
{
title: 'Origin matching',
description:
'We align buyer taste goals, processing preferences, and market needs with the most suitable Ethiopian origins.',
},
{
title: 'Quality verification',
description:
'Lots move through disciplined selection, moisture review, and cupping evaluation before they are prepared for export.',
},
{
title: 'Shipment coordination',
description:
'Documentation, communication, and logistics are handled with clarity from Addis Ababa through Djibouti to destination.',
},
];
export default function ExportServicesPage() {
return (
<>
<MarketingSeo
title="Export Services"
description="Explore Alem Desta Coffee Export's service hub covering coffee origins, quality control, sustainability, and logistics coordination for global buyers."
/>
<MarketingLayout>
<MarketingPageHero
eyebrow="Export services"
title="A premium export hub designed for serious international coffee buyers"
description="The Export Services page brings every key decision area into one elegant overview — origin selection, quality assurance, sustainability expectations, and shipment coordination."
image="https://images.unsplash.com/photo-1520607162513-77705c0f0d4a?auto=format&fit=crop&w=1400&q=80"
/>
<MarketingSection
eyebrow="Service hub"
title="Explore the four pillars behind our export offer"
description="Rather than overcrowding the main navigation, the website groups our detailed export capabilities here in one clear buyer-focused hub."
>
<div className="grid gap-6 md:grid-cols-2">
{exportServiceItems.map((item) => (
<article
key={item.href}
className="rounded-[2rem] border border-[#1F3A2D]/8 bg-white p-7 shadow-[0_20px_65px_rgba(20,38,29,0.06)]"
>
<div className="flex h-14 w-14 items-center justify-center rounded-2xl bg-[#F4F1E6] text-[#1F3A2D]">
<BaseIcon path={iconByHref[item.href as keyof typeof iconByHref]} />
</div>
<h2 className="font-brand-display mt-6 text-3xl text-[#1F3A2D]">{item.label}</h2>
<p className="mt-4 text-sm leading-7 text-[#556257]">{item.description}</p>
<div className="mt-6">
<MarketingButton href={item.href} variant="ghost">
View details
</MarketingButton>
</div>
</article>
))}
</div>
</MarketingSection>
<MarketingSection
eyebrow="Buyer workflow"
title="How the export relationship is structured"
description="International buyers need more than storytelling. They need a process that feels organized, transparent, and commercially dependable."
className="bg-[#F8FAF4]"
>
<div className="grid gap-6 lg:grid-cols-3">
{workflowSteps.map((step, index) => (
<div
key={step.title}
className="rounded-[1.75rem] border border-[#1F3A2D]/8 bg-white p-7 shadow-[0_18px_55px_rgba(20,38,29,0.05)]"
>
<div className="flex h-11 w-11 items-center justify-center rounded-full bg-[#1F3A2D] text-sm font-semibold text-[#F4F1E6]">
{index + 1}
</div>
<h3 className="font-brand-display mt-6 text-2xl text-[#1F3A2D]">{step.title}</h3>
<p className="mt-4 text-sm leading-7 text-[#556257]">{step.description}</p>
</div>
))}
</div>
<div className="mt-10 flex flex-col gap-4 sm:flex-row">
<MarketingButton href="/contact?type=request_samples">Request Samples</MarketingButton>
<MarketingButton href="/contact?type=get_a_quote" variant="ghost">
Request a tailored quote
</MarketingButton>
</div>
</MarketingSection>
</MarketingLayout>
</>
);
}
ExportServicesPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};

View File

@ -1,166 +1,258 @@
import {
import React, { useEffect, useState } from 'react'; mdiEarth,
mdiLeaf,
mdiMapMarker,
mdiShieldCheck,
mdiTruckFastOutline,
} from '@mdi/js';
import type { ReactElement } from 'react'; import type { ReactElement } from 'react';
import Head from 'next/head'; import React from 'react';
import Link from 'next/link';
import BaseButton from '../components/BaseButton'; import BaseIcon from '../components/BaseIcon';
import CardBox from '../components/CardBox'; import MarketingButton from '../components/marketing/MarketingButton';
import SectionFullScreen from '../components/SectionFullScreen'; import MarketingLayout from '../components/marketing/MarketingLayout';
import MarketingSection from '../components/marketing/MarketingSection';
import MarketingSeo from '../components/marketing/MarketingSeo';
import NewsletterForm from '../components/marketing/NewsletterForm';
import {
brand,
exportServices,
featureHighlights,
galleryItems,
origins,
testimonials,
} from '../components/marketing/marketingData';
import LayoutGuest from '../layouts/Guest'; import LayoutGuest from '../layouts/Guest';
import BaseDivider from '../components/BaseDivider';
import BaseButtons from '../components/BaseButtons';
import { getPageTitle } from '../config';
import { useAppSelector } from '../stores/hooks';
import CardBoxComponentTitle from "../components/CardBoxComponentTitle";
import { getPexelsImage, getPexelsVideo } from '../helpers/pexels';
const statItems = [
{ label: 'Origin-driven sourcing', value: 'Ethiopia first' },
{ label: 'Export route', value: 'Addis Ababa → Djibouti → Global markets' },
{ label: 'Buyer focus', value: 'Roasters, importers, distributors, wholesalers' },
];
export default function Starter() { const trustPillars = [
const [illustrationImage, setIllustrationImage] = useState({ {
src: undefined, icon: mdiShieldCheck,
photographer: undefined, title: 'Trust & transparency',
photographer_url: undefined, description: 'Clear communication, honest documentation, and disciplined follow-through for international buyers.',
}) },
const [illustrationVideo, setIllustrationVideo] = useState({video_files: []}) {
const [contentType, setContentType] = useState('video'); icon: mdiMapMarker,
const [contentPosition, setContentPosition] = useState('right'); title: 'Origin expertise',
const textColor = useAppSelector((state) => state.style.linkColor); description: 'Regional understanding supports lot selection aligned with buyer taste profiles and sourcing goals.',
},
const title = 'Alem Desta Coffee Export Site' {
icon: mdiTruckFastOutline,
// Fetch Pexels image/video title: 'Export reliability',
useEffect(() => { description: 'A structured logistics chain supports timely movement from origin to destination.',
async function fetchData() { },
const image = await getPexelsImage(); {
const video = await getPexelsVideo(); icon: mdiLeaf,
setIllustrationImage(image); title: 'Responsible sourcing',
setIllustrationVideo(video); description: 'Sustainability is treated as a business responsibility, not a campaign message.',
} },
fetchData(); ];
}, []);
const imageBlock = (image) => (
<div
className='hidden md:flex flex-col justify-end relative flex-grow-0 flex-shrink-0 w-1/3'
style={{
backgroundImage: `${
image
? `url(${image?.src?.original})`
: 'linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5))'
}`,
backgroundSize: 'cover',
backgroundPosition: 'left center',
backgroundRepeat: 'no-repeat',
}}
>
<div className='flex justify-center w-full bg-blue-300/20'>
<a
className='text-[8px]'
href={image?.photographer_url}
target='_blank'
rel='noreferrer'
>
Photo by {image?.photographer} on Pexels
</a>
</div>
</div>
);
const videoBlock = (video) => {
if (video?.video_files?.length > 0) {
return (
<div className='hidden md:flex flex-col justify-end relative flex-grow-0 flex-shrink-0 w-1/3'>
<video
className='absolute top-0 left-0 w-full h-full object-cover'
autoPlay
loop
muted
>
<source src={video?.video_files[0]?.link} type='video/mp4'/>
Your browser does not support the video tag.
</video>
<div className='flex justify-center w-full bg-blue-300/20 z-10'>
<a
className='text-[8px]'
href={video?.user?.url}
target='_blank'
rel='noreferrer'
>
Video by {video.user.name} on Pexels
</a>
</div>
</div>)
}
};
export default function HomePage() {
return ( return (
<div <>
style={ <MarketingSeo
contentPosition === 'background' title="Ethiopian Premium Coffee Export"
? { description="Premium Ethiopian coffee exporter connecting origin, traceability, and global buyer confidence with elegant, professional service."
backgroundImage: `${ />
illustrationImage <MarketingLayout>
? `url(${illustrationImage.src?.original})` <section className="relative -mt-[88px] overflow-hidden bg-[#16271F] px-5 pb-16 pt-36 text-white lg:px-8 lg:pb-24 lg:pt-44">
: 'linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5))' <div className="absolute inset-0">
}`, <img
backgroundSize: 'cover', className="h-full w-full scale-[1.02] object-cover opacity-32 saturate-[0.82]"
backgroundPosition: 'left center', loading="eager"
backgroundRepeat: 'no-repeat', src="https://images.unsplash.com/photo-1447933601403-0c6688de566e?auto=format&fit=crop&w=1600&q=80"
} alt="Ethiopian coffee farm"
: {} />
} <div className="absolute inset-0 bg-[linear-gradient(135deg,rgba(18,38,29,0.88),rgba(31,58,45,0.72),rgba(18,38,29,0.9))]" />
> </div>
<Head>
<title>{getPageTitle('Starter Page')}</title>
</Head>
<SectionFullScreen bg='violet'> <div className="coffee-fade-in relative mx-auto grid max-w-7xl gap-10 lg:grid-cols-[1.05fr_0.95fr] lg:items-end">
<div <div>
className={`flex ${ <p className="text-sm font-semibold uppercase tracking-[0.38em] text-[#B7C78B]">Specialty green coffee export</p>
contentPosition === 'right' ? 'flex-row-reverse' : 'flex-row' <h1 className="font-brand-display mt-6 max-w-4xl text-5xl leading-[1.05] text-[#F4F1E6] md:text-7xl">
} min-h-screen w-full`} Ethiopian Premium Coffee Sourced with Experience, Exported with Integrity
> </h1>
{contentType === 'image' && contentPosition !== 'background' <p className="mt-6 max-w-3xl text-lg leading-8 text-white/78">
? imageBlock(illustrationImage) Achieving premium coffee excellence from its origin.
: null} </p>
{contentType === 'video' && contentPosition !== 'background' <p className="mt-6 max-w-3xl text-base leading-8 text-white/72">
? videoBlock(illustrationVideo) {brand.name} bridges Ethiopian premium coffee producers with global buyers, focusing on traceability,
: null} single-origin green coffee sourcing, export-ready preparation, and uncompromising quality.
<div className='flex items-center justify-center flex-col space-y-4 w-full lg:w-full'> </p>
<CardBox className='w-full md:w-3/5 lg:w-2/3'> <div className="mt-10 flex flex-col gap-4 sm:flex-row">
<CardBoxComponentTitle title="Welcome to your Alem Desta Coffee Export Site app!"/> <MarketingButton href="/contact?type=request_samples">Request Samples</MarketingButton>
<MarketingButton href="/contact?type=get_a_quote" variant="secondary">
<div className="space-y-3"> Get a Quote
<p className='text-center text-gray-500'>This is a React.js/Node.js app generated by the <a className={`${textColor}`} href="https://flatlogic.com/generator">Flatlogic Web App Generator</a></p> </MarketingButton>
<p className='text-center text-gray-500'>For guides and documentation please check </div>
your local README.md and the <a className={`${textColor}`} href="https://flatlogic.com/documentation">Flatlogic documentation</a></p>
</div> </div>
<BaseButtons>
<BaseButton
href='/login'
label='Login'
color='info'
className='w-full'
/>
</BaseButtons> <div className="rounded-[2rem] border border-white/10 bg-white/10 p-6 backdrop-blur-md shadow-[0_30px_80px_rgba(0,0,0,0.25)] md:p-8">
</CardBox> <p className="text-sm font-semibold uppercase tracking-[0.28em] text-[#B7C78B]">Why buyers trust us</p>
</div> <div className="mt-8 space-y-5">
</div> {statItems.map((item) => (
</SectionFullScreen> <div key={item.label} className="border-b border-white/10 pb-5 last:border-b-0 last:pb-0">
<div className='bg-black text-white flex flex-col text-center justify-center md:flex-row'> <p className="text-sm uppercase tracking-[0.28em] text-white/48">{item.label}</p>
<p className='py-6 text-sm'>© 2026 <span>{title}</span>. All rights reserved</p> <p className="mt-2 text-lg font-medium text-white">{item.value}</p>
<Link className='py-6 ml-4 text-sm' href='/privacy-policy/'> </div>
Privacy Policy ))}
</Link> </div>
</div> </div>
</div>
</section>
</div> <MarketingSection
eyebrow="Immediate confidence"
title="A refined sourcing experience for global coffee buyers"
description="The first impression international buyers need is clarity: where coffee comes from, how quality is protected, and whether export communication will be dependable. This website presents that trust story with elegance and precision."
>
<div className="grid gap-6 md:grid-cols-2 xl:grid-cols-4">
{trustPillars.map((item) => (
<div key={item.title} className="rounded-[1.75rem] border border-[#1F3A2D]/8 bg-white p-6 shadow-[0_20px_65px_rgba(20,38,29,0.06)]">
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#F4F1E6] text-[#1F3A2D]">
<BaseIcon path={item.icon} />
</div>
<h3 className="font-brand-display mt-5 text-2xl text-[#1F3A2D]">{item.title}</h3>
<p className="mt-3 text-sm leading-7 text-[#556257]">{item.description}</p>
</div>
))}
</div>
</MarketingSection>
<MarketingSection
eyebrow="Feature highlights"
title="Built around traceability, premium handling, and long-term export partnerships"
description="Each highlight below mirrors the core buying questions of roasters, green coffee importers, and wholesale partners evaluating a supplier relationship."
centered
className="bg-[#F8FAF4]"
>
<div className="grid gap-6 lg:grid-cols-2 xl:grid-cols-4">
{featureHighlights.map((item) => (
<div key={item.title} className="rounded-[1.75rem] border border-[#1F3A2D]/8 bg-white p-7 shadow-[0_20px_70px_rgba(20,38,29,0.07)]">
<h3 className="font-brand-display text-2xl text-[#1F3A2D]">{item.title}</h3>
<p className="mt-4 text-sm leading-7 text-[#556257]">{item.description}</p>
</div>
))}
</div>
</MarketingSection>
<MarketingSection
eyebrow="Visual origin story"
title="From farms to cupping tables to export readiness"
description="The buyer journey starts with visual confidence: clean origin imagery, disciplined processing, and a clear sense of how coffee moves professionally toward shipment."
>
<div className="grid gap-6 md:grid-cols-2">
{galleryItems.map((item) => (
<article key={item.title} className="group overflow-hidden rounded-[2rem] bg-white shadow-[0_24px_70px_rgba(20,38,29,0.08)]">
<div className="relative h-72 overflow-hidden">
<img
className="h-full w-full object-cover saturate-[0.88] transition duration-700 group-hover:scale-105"
loading="lazy"
src={item.image}
alt={item.title}
/>
<div className="absolute inset-0 bg-[linear-gradient(180deg,rgba(18,38,29,0.08),rgba(18,38,29,0),rgba(18,38,29,0.28))]" />
</div>
<div className="p-6">
<h3 className="font-brand-display text-2xl text-[#1F3A2D]">{item.title}</h3>
<p className="mt-3 text-sm leading-7 text-[#556257]">{item.caption}</p>
</div>
</article>
))}
</div>
</MarketingSection>
<MarketingSection
eyebrow="Origin snapshots"
title="Distinctive Ethiopian regions, each with its own flavor narrative"
description="A quick regional preview gives buyers a sense of sourcing depth before they request samples or a tailored quote."
className="bg-[#F4F1E6]/45"
>
<div className="grid gap-6 lg:grid-cols-3">
{origins.slice(0, 3).map((item) => (
<div key={item.name} className="overflow-hidden rounded-[2rem] bg-white shadow-[0_24px_70px_rgba(20,38,29,0.08)]">
<div className="relative">
<img className="h-56 w-full object-cover saturate-[0.9]" loading="lazy" src={item.image} alt={item.name} />
<div className="absolute inset-0 bg-[linear-gradient(180deg,rgba(18,38,29,0.05),rgba(18,38,29,0),rgba(18,38,29,0.24))]" />
</div>
<div className="p-6">
<p className="text-sm uppercase tracking-[0.28em] text-[#9FB06F]">{item.altitude}</p>
<h3 className="font-brand-display mt-3 text-2xl text-[#1F3A2D]">{item.name}</h3>
<p className="mt-3 text-sm leading-7 text-[#556257]">{item.profile}</p>
</div>
</div>
))}
</div>
<div className="mt-8">
<MarketingButton href="/coffee-origins" variant="ghost">
Explore all origins
</MarketingButton>
</div>
</MarketingSection>
<MarketingSection
eyebrow="Export capability"
title="Professional export services built for international buyers"
description="Reliable logistics, internal documentation handling, and strong communication help create a premium corporate buying experience."
>
<div className="grid gap-4 md:grid-cols-2">
{exportServices.slice(0, 4).map((item) => (
<div key={item} className="flex gap-4 rounded-[1.5rem] border border-[#1F3A2D]/8 bg-white p-5 shadow-[0_18px_60px_rgba(20,38,29,0.06)]">
<div className="mt-1 text-[#9FB06F]">
<BaseIcon path={mdiEarth} />
</div>
<p className="text-sm leading-7 text-[#556257]">{item}</p>
</div>
))}
</div>
</MarketingSection>
<MarketingSection
eyebrow="Testimonials"
title="Commercial credibility, with room to grow into buyer proof"
description="These premium placeholders establish the intended testimonial zone so future buyer feedback can be added without redesigning the site."
centered
className="bg-[#F8FAF4]"
>
<div className="grid gap-6 lg:grid-cols-2">
{testimonials.map((item) => (
<blockquote key={item.author} className="rounded-[1.75rem] border border-[#1F3A2D]/8 bg-white p-7 shadow-[0_18px_60px_rgba(20,38,29,0.06)]">
<p className="font-brand-display text-2xl leading-10 text-[#1F3A2D]">{item.quote}</p>
<footer className="mt-6 text-sm font-medium uppercase tracking-[0.24em] text-[#72816F]">{item.author}</footer>
</blockquote>
))}
</div>
</MarketingSection>
<MarketingSection
eyebrow="Stay informed"
title="Subscribe for sourcing updates"
description="Newsletter sign-up is already connected to the admin subscriber list, giving your team a real conversion path from day one."
className="bg-[#1F3A2D] text-white"
>
<div className="grid gap-10 lg:grid-cols-[1fr_0.9fr] lg:items-center">
<div>
<h3 className="font-brand-display text-4xl text-[#F4F1E6]">Receive buyer-focused green coffee updates</h3>
<p className="mt-5 max-w-2xl text-base leading-8 text-white/72">
Join the list for availability updates, new origin highlights, and company announcements shaped for professional buyers.
</p>
</div>
<div className="rounded-[2rem] border border-white/10 bg-white/10 p-6 backdrop-blur-md">
<NewsletterForm source="home_cta" />
</div>
</div>
</MarketingSection>
</MarketingLayout>
</>
); );
} }
Starter.getLayout = function getLayout(page: ReactElement) { HomePage.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>; return <LayoutGuest>{page}</LayoutGuest>;
}; };

View File

@ -0,0 +1,109 @@
import { mdiFileDocumentOutline, mdiMessageTextFastOutline, mdiPackageVariantClosed, mdiTruckFastOutline } from '@mdi/js';
import type { ReactElement } from 'react';
import React from 'react';
import BaseIcon from '../components/BaseIcon';
import MarketingLayout from '../components/marketing/MarketingLayout';
import MarketingPageHero from '../components/marketing/MarketingPageHero';
import MarketingSeo from '../components/marketing/MarketingSeo';
import MarketingSection from '../components/marketing/MarketingSection';
import LayoutGuest from '../layouts/Guest';
const logisticsPillars = [
{
icon: mdiFileDocumentOutline,
title: 'Documentation handling',
description:
'Export paperwork is managed with care to support smoother communication and reduce uncertainty for international buyers.',
},
{
icon: mdiPackageVariantClosed,
title: 'Shipment preparation',
description:
'Lots are prepared for export with disciplined packaging, timing coordination, and readiness checks before dispatch.',
},
{
icon: mdiTruckFastOutline,
title: 'Route coordination',
description:
'The logistics chain is organized from Addis Ababa to Djibouti and onward to destination markets with responsive updates.',
},
{
icon: mdiMessageTextFastOutline,
title: 'Buyer communication',
description:
'Prompt communication keeps importers, roasters, and distributors informed throughout the export workflow.',
},
];
const timeline = [
'Lot confirmation and shipment planning',
'Internal document preparation and export coordination',
'Movement from origin handling points toward Djibouti',
'Final export dispatch with clear buyer communication',
];
export default function LogisticsExportPage() {
return (
<>
<MarketingSeo
title="Logistics & Export"
description="Learn how Alem Desta Coffee Export coordinates documentation, shipment preparation, and export communication from Ethiopia to global markets."
/>
<MarketingLayout>
<MarketingPageHero
eyebrow="Logistics & export"
title="Export coordination that feels disciplined, responsive, and globally ready"
description="For premium buyers, logistics is part of trust. We present the export chain with the same clarity and professionalism expected from the coffee itself."
image="https://images.unsplash.com/photo-1520607162513-77705c0f0d4a?auto=format&fit=crop&w=1400&q=80"
/>
<MarketingSection
eyebrow="Operational confidence"
title="The logistics side of the business is built to reduce friction"
description="This page gives buyers a concise view of how coffee moves from Ethiopian origin into an organized export workflow."
>
<div className="grid gap-6 md:grid-cols-2 xl:grid-cols-4">
{logisticsPillars.map((item) => (
<div
key={item.title}
className="rounded-[1.75rem] border border-[#1F3A2D]/8 bg-white p-6 shadow-[0_20px_65px_rgba(20,38,29,0.06)]"
>
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#F4F1E6] text-[#1F3A2D]">
<BaseIcon path={item.icon} />
</div>
<h2 className="font-brand-display mt-5 text-2xl text-[#1F3A2D]">{item.title}</h2>
<p className="mt-4 text-sm leading-7 text-[#556257]">{item.description}</p>
</div>
))}
</div>
</MarketingSection>
<MarketingSection
eyebrow="Export flow"
title="A simple view of how the shipment process is organized"
description="The sequence below reinforces a premium message: disciplined coffee handling, timely coordination, and dependable communication."
className="bg-[#F8FAF4]"
>
<div className="grid gap-4 lg:grid-cols-2">
{timeline.map((step, index) => (
<div
key={step}
className="flex items-center gap-4 rounded-[1.5rem] border border-[#1F3A2D]/8 bg-white px-5 py-4 shadow-[0_18px_55px_rgba(20,38,29,0.05)]"
>
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#1F3A2D] text-sm font-semibold text-[#F4F1E6]">
{index + 1}
</div>
<p className="text-sm leading-7 text-[#556257]">{step}</p>
</div>
))}
</div>
</MarketingSection>
</MarketingLayout>
</>
);
}
LogisticsExportPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};

View File

@ -0,0 +1,79 @@
import { mdiChartWaterfall, mdiCupOutline, mdiWaterOutline } from '@mdi/js';
import type { ReactElement } from 'react';
import React from 'react';
import BaseIcon from '../components/BaseIcon';
import MarketingLayout from '../components/marketing/MarketingLayout';
import MarketingPageHero from '../components/marketing/MarketingPageHero';
import MarketingSeo from '../components/marketing/MarketingSeo';
import MarketingSection from '../components/marketing/MarketingSection';
import { qualityMetrics, qualityProcesses } from '../components/marketing/marketingData';
import LayoutGuest from '../layouts/Guest';
const processIcons = [mdiWaterOutline, mdiChartWaterfall, mdiCupOutline];
export default function QualityControlPage() {
return (
<>
<MarketingSeo
title="Quality Control"
description="Washed, natural, and honey processing workflows with moisture control and cupping evaluation standards."
/>
<MarketingLayout>
<MarketingPageHero
eyebrow="Quality control"
title="Structured processing and disciplined quality review"
description="This page turns processing detail into buyer confidence by showing how washed, natural, and honey methods are handled and evaluated."
image="https://images.unsplash.com/photo-1511920170033-f8396924c348?auto=format&fit=crop&w=1400&q=80"
/>
<MarketingSection
eyebrow="Processing systems"
title="Three process pathways, each explained with clarity"
description="The goal is simple: make process detail easy to read, visually elegant, and commercially reassuring."
>
<div className="grid gap-6 lg:grid-cols-3">
{qualityProcesses.map((item, index) => (
<div key={item.title} className="rounded-[1.85rem] border border-[#1F3A2D]/8 bg-white p-7 shadow-[0_24px_70px_rgba(20,38,29,0.06)]">
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#F4F1E6] text-[#1F3A2D]">
<BaseIcon path={processIcons[index]} />
</div>
<h3 className="font-brand-display mt-5 text-3xl text-[#1F3A2D]">{item.title}</h3>
<p className="mt-4 text-sm leading-7 text-[#556257]">{item.highlight}</p>
<div className="mt-6 space-y-3">
{item.steps.map((step, stepIndex) => (
<div key={step} className="flex items-center gap-3 rounded-2xl bg-[#EEF3E7] px-4 py-3 text-sm text-[#4F5E53]">
<span className="flex h-8 w-8 items-center justify-center rounded-full bg-[#1F3A2D] text-xs font-semibold text-[#F4F1E6]">
{stepIndex + 1}
</span>
{step}
</div>
))}
</div>
</div>
))}
</div>
</MarketingSection>
<MarketingSection
eyebrow="Quality system"
title="Measured, tasted, and reviewed before export"
description="Moisture control and cupping evaluation help translate process discipline into export confidence."
className="bg-[#F8FAF4]"
>
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
{qualityMetrics.map((item) => (
<div key={item} className="rounded-[1.5rem] border border-[#1F3A2D]/8 bg-white px-5 py-4 text-sm leading-7 text-[#556257] shadow-[0_18px_55px_rgba(20,38,29,0.05)]">
{item}
</div>
))}
</div>
</MarketingSection>
</MarketingLayout>
</>
);
}
QualityControlPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};

View File

@ -0,0 +1,47 @@
import type { ReactElement } from 'react';
import React from 'react';
import MarketingLayout from '../components/marketing/MarketingLayout';
import MarketingPageHero from '../components/marketing/MarketingPageHero';
import MarketingSeo from '../components/marketing/MarketingSeo';
import MarketingSection from '../components/marketing/MarketingSection';
import { sustainabilityPoints } from '../components/marketing/marketingData';
import LayoutGuest from '../layouts/Guest';
export default function SustainabilityPage() {
return (
<>
<MarketingSeo
title="Sustainability"
description="Fair payment, ethical sourcing, environmental care, and community development framed as a real business responsibility."
/>
<MarketingLayout>
<MarketingPageHero
eyebrow="Sustainability"
title="Sustainability is our responsibility, not a marketing claim"
description="This message anchors the brand in seriousness and credibility, especially for buyers evaluating long-term sourcing relationships."
image="https://images.unsplash.com/photo-1461988320302-91bde64fc8e4?auto=format&fit=crop&w=1400&q=80"
/>
<MarketingSection
eyebrow="Responsible sourcing"
title="A business approach that respects people, land, and long-term supply"
description="Sustainability should be visible in sourcing behavior, not only in headlines."
centered
>
<div className="grid gap-6 md:grid-cols-2">
{sustainabilityPoints.map((item) => (
<div key={item} className="rounded-[1.75rem] border border-[#1F3A2D]/8 bg-white p-7 text-sm leading-7 text-[#556257] shadow-[0_20px_65px_rgba(20,38,29,0.06)]">
{item}
</div>
))}
</div>
</MarketingSection>
</MarketingLayout>
</>
);
}
SustainabilityPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};

View File

@ -0,0 +1,72 @@
import { mdiHandshakeOutline, mdiLeaf, mdiMedalOutline, mdiScaleBalance, mdiSeedOutline, mdiShieldCheck } from '@mdi/js';
import type { ReactElement } from 'react';
import React from 'react';
import BaseIcon from '../components/BaseIcon';
import MarketingLayout from '../components/marketing/MarketingLayout';
import MarketingPageHero from '../components/marketing/MarketingPageHero';
import MarketingSeo from '../components/marketing/MarketingSeo';
import MarketingSection from '../components/marketing/MarketingSection';
import { principles, values } from '../components/marketing/marketingData';
import LayoutGuest from '../layouts/Guest';
const icons = [mdiShieldCheck, mdiSeedOutline, mdiMedalOutline, mdiHandshakeOutline, mdiScaleBalance, mdiLeaf];
export default function VisionMissionValuesPage() {
return (
<>
<MarketingSeo
title="Vision Mission and Values"
description="Vision, mission, values, and business principles that define Alem Desta Coffee Export."
/>
<MarketingLayout>
<MarketingPageHero
eyebrow="Vision, mission & values"
title="A long-term export business built on trust, quality, and partnership"
description="International buyers need more than attractive language. They need a clear statement of vision, mission, principles, and values that signal operational maturity."
image="https://images.unsplash.com/photo-1442512595331-e89e73853f31?auto=format&fit=crop&w=1400&q=80"
/>
<MarketingSection title="Vision" description="To become a globally trusted Ethiopian coffee exporter known for quality, traceability, and long-term partnerships." />
<MarketingSection title="Mission" description="To export premium Ethiopian coffee with strict quality control, transparency, and sustainable partnerships." className="pt-0" />
<MarketingSection
eyebrow="Core values"
title="The values that guide how we source, communicate, and deliver"
centered
className="bg-[#F8FAF4]"
>
<div className="grid gap-6 md:grid-cols-2 xl:grid-cols-3">
{values.map((item, index) => (
<div key={item.title} className="rounded-[1.75rem] border border-[#1F3A2D]/8 bg-white p-7 shadow-[0_20px_65px_rgba(20,38,29,0.06)]">
<div className="flex h-12 w-12 items-center justify-center rounded-2xl bg-[#F4F1E6] text-[#1F3A2D]">
<BaseIcon path={icons[index]} />
</div>
<h3 className="font-brand-display mt-5 text-2xl text-[#1F3A2D]">{item.title}</h3>
<p className="mt-4 text-sm leading-7 text-[#556257]">{item.description}</p>
</div>
))}
</div>
</MarketingSection>
<MarketingSection
eyebrow="Principles"
title="Execution principles buyers can recognize immediately"
description="These principles turn brand values into supplier behavior."
>
<div className="grid gap-4 md:grid-cols-2">
{principles.map((item) => (
<div key={item} className="rounded-[1.5rem] border border-[#1F3A2D]/8 bg-white px-5 py-4 text-sm font-medium text-[#1F3A2D] shadow-[0_18px_60px_rgba(20,38,29,0.05)]">
{item}
</div>
))}
</div>
</MarketingSection>
</MarketingLayout>
</>
);
}
VisionMissionValuesPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};