Compare commits

..

5 Commits
main ... dev

Author SHA1 Message Date
Tocho Tochev 0aa45b4514 Add license 2024-10-08 20:58:10 +03:00
Vencislav Atanasov cbd213da21 Fix incorrect filename of NavBar component 2024-09-27 17:52:35 +03:00
DanieII 0f2e1373c2 Add new hero banner 2024-09-16 01:00:59 +03:00
DanieII d668093240 Add new home page 2024-09-14 20:25:54 +03:00
Iliyan Georgiev 9b090d212a New version for 2024 2024-09-10 10:23:43 +03:00
49 changed files with 4642 additions and 1518 deletions

10
.prettierrc.json Normal file
View File

@ -0,0 +1,10 @@
{
"trailingComma": "es5",
"semi": true,
"tabWidth": 2,
"singleQuote": true,
"jsxSingleQuote": true,
"plugins": [
"prettier-plugin-tailwindcss"
]
}

View File

@ -1,11 +1,11 @@
import "server-only";
import type { Locale } from "./i18n-config";
import 'server-only';
import type { Locale } from './i18n-config';
// We enumerate all dictionaries here for better linting and typescript support
// We also get the default import for cleaner types
const dictionaries = {
en: () => import("./dictionaries/en.json").then((module) => module.default),
bg: () => import("./dictionaries/bg.json").then((module) => module.default),
en: () => import('./dictionaries/en.json').then((module) => module.default),
bg: () => import('./dictionaries/bg.json').then((module) => module.default),
};
export const getDictionary = async (locale: Locale) =>

View File

@ -1,5 +1,46 @@
{
"nav": {
"home": "Начало",
"about": "За нас",
"partners": "Партньори",
"archive": "Архив",
"contact": "Контакти"
},
"main": {
"hello": "Добре дошли"
"date": "2 - 3 ноември 2024",
"titleLocation": "София Тех Парк",
"countdownTimer": {
"title": "До OpenFest остават",
"days": "Дни",
"hours": "Часа",
"minutes": "Минути"
},
"description": {
"title": "Какво е OpenFest?",
"text": "OpenFest е най-голямата българска конференция, посветена на свободната култура, свободното споделяне на знание, свободния и отворен софтуер. Събитието се организира от доброволци и е безплатно за посещение. OpenFest се провежда годишно в София, България."
},
"cfp": {
"title": "Как можете да участвате в OpenFest 2024?",
"lecture": "Участвайте с лекция, работилница или щанд",
"volunteers": "Присъединете се като доброволец",
"partners": "Подкрепете събитието като партньор"
},
"news": {
"title": "Новини",
"cardButton": "Прочети",
"button": "Виж всички"
},
"partners": {
"sponsors": "Sponsors",
"media": "Media partners"
}
},
"footer": {
"description": "OpenFest е събитие, посветена на свободната култура, свободния софтуер и софтуера с отворен код, свободното споделяне на знания.",
"eventDate": "2-ри и 3-ти ноември 2024г.",
"eventLocation": "София Тех Парк",
"contactTeam": "Свържете се с екипа",
"contactDirections": "Ако имате въпроси, предложения или желаете да се включите в OpenFest 2024, пишете ни:",
"copyright": "Някои права запазени."
}
}

View File

@ -1,5 +1,46 @@
{
"nav": {
"home": "Home",
"about": "About us",
"partners": "Partners",
"archive": "Archive",
"contact": "Contact"
},
"main": {
"hello": "Welcome"
"date": "2 - 3 november 2024",
"titleLocation": "Sofia Tech Park",
"countdownTimer": {
"title": "OpenFest starts in",
"days": "Days",
"hours": "Hours",
"minutes": "Minutes"
},
"description": {
"title": "What is OpenFest...",
"text": "OpenFest is the biggest Bulgarian conference dedicated to the free culture, free knowledge sharing, free and open-source software. The event is organized by volunteers and is free to attend. OpenFest is held annually in Sofia, Bulgaria."
},
"cfp": {
"title": "How to participate in OpenFest 2024?",
"lecture": "Take part with a lecture, a workshop or a booth",
"volunteers": "Join us as a volunteer",
"partners": "Support the event as a partner"
},
"news": {
"title": "News",
"cardButton": "Read",
"button": "See all"
},
"partners": {
"sponsors": "Sponsors",
"media": "Media partners"
}
},
"footer": {
"description": "OpenFest is a event dedicated to free culture, free and open-source software, and free sharing of knowledge.",
"eventDate": "2-3 November 2024",
"eventLocation": "Sofia Tech Park",
"contactTeam": "Connect with the team",
"contactDirections": "If you have any questions and suggestions or if you would like to participate in OpenFest 2024, get in touch with us:",
"copyright": "Some rights reserved."
}
}

View File

@ -1,6 +1,7 @@
export const i18n = {
defaultLocale: "en",
locales: ["en", "bg"],
locales: ['bg', 'en'],
defaultLocale: 'bg',
localeDetection: true,
} as const;
export type Locale = (typeof i18n)["locales"][number];
export type Locale = (typeof i18n)['locales'][number];

View File

@ -12,8 +12,8 @@ const nextConfig = {
destination: '/news/1',
permanent: true,
},
]
];
},
}
};
export default nextConfig
export default nextConfig;

4270
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -7,13 +7,16 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"format": "prettier --check --ignore-path .gitignore .",
"format:fix": "prettier --write --ignore-path .gitignore ."
},
"dependencies": {
"@formatjs/intl-localematcher": "^0.5.4",
"@headlessui/react": "^2.1.5",
"gray-matter": "^4.0.3",
"negotiator": "^0.6.3",
"next": "14.2.3",
"next": "^14.2.8",
"react": "^18",
"react-dom": "^18",
"remark": "^15.0.1",
@ -22,14 +25,19 @@
"strip-markdown": "^6.0.0"
},
"devDependencies": {
"@heroicons/react": "^2.1.5",
"@types/negotiator": "^0.6.3",
"@types/node": "^20",
"@types/react": "^18",
"@types/node": "^22.5.4",
"@types/react": "^18.3.5",
"@types/react-dom": "^18",
"eslint": "^8",
"eslint-config-next": "14.2.3",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"typescript": "^5"
"autoprefixer": "^10.4.20",
"eslint": "^9.10.0",
"eslint-config-next": "^14.2.8",
"install": "^0.13.0",
"npm": "^10.8.3",
"postcss": "^8.4.45",
"prettier-plugin-tailwindcss": "^0.6.6",
"tailwindcss": "^3.4.10",
"typescript": "^5.5.4"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1001 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
public/posts/post-1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
public/posts/post-2.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
public/posts/post-3.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@ -1,8 +0,0 @@
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css');
@tailwind base;
@tailwind components;
@tailwind utilities;
.container {
@apply mx-auto px-6;
}

31
src/app/[lang]/layout.jsx Normal file
View File

@ -0,0 +1,31 @@
import { i18n } from '../../../i18n-config';
import NavBar from '../../components/NavBar';
import Footer from '@/components/Footer';
import '@/styles/globals.css';
export async function generateStaticParams() {
return i18n.locales.map((locale) => ({ lang: locale }));
}
export const metadata = {
title: 'OpenFest 2024',
description: 'Да се видим на OpenFest 2024!',
};
export default function RootLayout({ children, params }) {
return (
<html lang={params.lang}>
<body
className={`flex min-h-screen flex-col font-openSans text-white md:text-lg lg:text-xl`}
>
<header>
<NavBar lang={params.lang} />
</header>
<main>{children}</main>
<Footer lang={params.lang} />
</body>
</html>
);
}

View File

@ -1,37 +0,0 @@
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
import { i18n, type Locale } from '../../../i18n-config'
import NavBar from '../../components/NavBar'
import Footer from '../../components/Footer'
export async function generateStaticParams() {
return i18n.locales.map((locale) => ({ lang: locale }))
}
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({
children,
params,
}: Readonly<{
children: React.ReactNode
params: { lang: Locale }
}>) {
return (
<html lang={params.lang}>
<body
className={`${inter.className}, flex flex-col text-white md:text-lg lg:text-xl min-h-screen`}
>
<NavBar lang={params.lang} />
{children}
<Footer />
</body>
</html>
)
}

View File

@ -0,0 +1,22 @@
// import { getSortedPostsData } from '../../lib/posts';
// import { getDictionary } from '../../../dictionaries';
export default async function PageNovini({ params }) {
const { lang } = params;
// const dictionary = await getDictionary(lang);
// const { posts } = await getSortedPostsData(lang);
return (
<>
<main>
<div className='container flex flex-col py-8 lg:py-16 gap-8 lg:gap-16 text-black'>
<div className='flex flex-col'>
<h2 className='text-xl lg:text-3xl font-extrabold text-center mb-6 lg:mb-10'>
news
</h2>
</div>
</div>
</main>
</>
);
}

90
src/app/[lang]/page.jsx Normal file
View File

@ -0,0 +1,90 @@
import CountDownTimer from '@/components/CountDownTimer';
import NewsFeed from '@/components/NewsFeed';
import Partners from '@/components/Partners';
import Image from 'next/image';
import { getDictionary } from '@/dictionaries';
export default async function Home({ params }) {
const { lang } = params;
const dictionary = await getDictionary(lang);
return (
<>
<section className='h-[65vh] bg-home-bg bg-cover bg-bottom sm:h-[75vh]'>
<div className='container flex h-full flex-col justify-center gap-10 text-black sm:gap-16'>
<div className='text-center'>
<p className='font-semibold uppercase tracking-[0.2em] text-white sm:text-xl'>
{dictionary.main.date}
</p>
<h1 className='text-6xl font-bold text-white sm:text-7xl'>
OpenFest <br /> 2024
</h1>
</div>
<div className='text-center'>
<p className='pb-2 text-2xl font-semibold text-white sm:pb-4 sm:text-5xl'>
Lets share the freedom!
</p>
<p className='text-xl text-white sm:text-3xl'>
{dictionary.main.titleLocation}
</p>
</div>
</div>
</section>
<CountDownTimer props={dictionary.main.countdownTimer} />
<section className='bg-blue-8'>
<div className='container flex flex-col gap-4 sm:gap-8'>
<h2 className='text-center text-2xl text-blue-2 sm:text-4xl'>
{dictionary.main.description.title}
</h2>
<div className='flex flex-col gap-6 sm:flex-row'>
<div className='flex-1'>
<p> {dictionary.main.description.text}</p>
</div>
<div className='flex-1'>
<Image
src='/images/openfest-2.webp'
width='620'
height='380'
></Image>
</div>
</div>
</div>
</section>
<section>
<div className='container'>
<h2 className='pb-4 text-center text-2xl text-blue-2 sm:pb-8 sm:text-4xl'>
{dictionary.main.cfp.title}
</h2>
<div className='flex flex-col gap-4 sm:flex-row sm:gap-8'>
<div className='flex basis-1/3 flex-col items-center justify-center gap-3 rounded-xl bg-blue-2 p-6 sm:gap-6'>
<div className='flex h-20 w-20 items-center justify-center rounded-full bg-blue-8 text-4xl text-blue-2 shadow-md shadow-black sm:h-24 sm:w-24 sm:text-5xl'>
<i className='fa-solid fa-lightbulb'></i>
</div>
<p className='text-center text-white'>
{dictionary.main.cfp.lecture}
</p>
</div>
<div className='flex basis-1/3 flex-col items-center justify-center gap-3 rounded-xl bg-blue-2 p-6 sm:gap-6'>
<div className='flex h-20 w-20 items-center justify-center rounded-full bg-blue-8 text-4xl text-blue-2 shadow-md shadow-black sm:h-24 sm:w-24 sm:text-5xl'>
<i className='fa-solid fa-helmet-safety'></i>
</div>
<p className='text-center text-white'>
{dictionary.main.cfp.volunteers}
</p>
</div>
<div className='flex basis-1/3 flex-col items-center justify-center gap-3 rounded-xl bg-blue-2 p-6 sm:gap-6'>
<div className='flex h-20 w-20 items-center justify-center rounded-full bg-blue-8 text-4xl text-blue-2 shadow-md shadow-black sm:h-24 sm:w-24 sm:text-5xl'>
<i className='fa-solid fa-handshake-angle'></i>
</div>
<p className='text-center text-white'>
{dictionary.main.cfp.partners}
</p>
</div>
</div>
</div>
</section>
<NewsFeed lang={lang} />
<Partners lang={lang} />
</>
);
}

View File

@ -1,36 +0,0 @@
import Header from '../../components/Header'
import Info from '../../components/Info'
import JoinUs from '../../components/JoinUs'
import Social from '../../components/Social'
import News from '../../components/News'
import { getSortedPostsData } from '../../lib/posts'
import { getDictionary } from '../../../dictionaries'
import { Locale } from '../../../i18n-config'
export default async function Home({
params: { lang },
}: {
params: { lang: Locale }
}) {
const dictionary = await getDictionary(lang)
const { posts } = await getSortedPostsData(lang)
return (
<>
<Header />
<main>
<Info />
<JoinUs />
<div className='container flex flex-col py-8 lg:py-16 gap-8 lg:gap-16 text-black'>
<div className='flex flex-col'>
<h2 className='text-xl lg:text-3xl font-extrabold text-center mb-6 lg:mb-10'>
Новини
</h2>
<News posts={posts} />
</div>
</div>
<Social />
</main>
</>
)
}

View File

@ -0,0 +1,97 @@
'use client';
import React, { useState, useEffect } from 'react';
const CountDownTimer = ({ props }) => {
const [days, setDays] = useState(0);
const [hours, setHours] = useState(0);
const [minutes, setMinutes] = useState(0);
useEffect(() => {
const targetDate = new Date('2024-11-02T09:30:00+03:00');
const countDownIntervalTime = 1000;
const updateCountDown = () => {
const now = new Date();
const diff = targetDate.getTime() - now.getTime();
const d = Math.floor(diff / (1000 * 60 * 60 * 24));
setDays(d);
const h = Math.floor((diff / (1000 * 60 * 60)) % 24);
setHours(h);
const m = Math.floor((diff / (1000 * 60)) % 60);
setMinutes(m);
};
// Set time
updateCountDown();
// Set interval
const interval = setInterval(updateCountDown, countDownIntervalTime);
return () => clearInterval(interval);
}, []);
return (
<section>
<div className='container flex flex-col gap-4 sm:gap-8'>
<h2 className='text-center text-2xl text-blue-2 sm:text-start sm:text-4xl'>
{props.title}
</h2>
<div className='flex flex-col items-center justify-evenly gap-8 lg:flex-row'>
<div className='relative h-48 w-48 lg:h-64 lg:w-64'>
<div className='absolute inset-0 rotate-[-45deg] overflow-hidden rounded-full bg-[#A9CDF7]'>
<div className='absolute left-0 top-0 h-full w-1/2'></div>
<div className='absolute left-0 top-0 h-full w-1/2 bg-[#C8E0FC]'></div>
</div>
<div className='absolute inset-0 flex items-center justify-center'>
<span className='text-center font-bold'>
<p className='pb-1 pt-2 text-6xl text-white lg:pb-3 lg:pt-4 lg:text-8xl'>
{days}
</p>
<p className='text-2xl font-light text-white lg:text-5xl'>
{props.days}
</p>
</span>
</div>
</div>
<div className='relative h-48 w-48 lg:h-64 lg:w-64'>
<div className='absolute inset-0 rotate-[-45deg] overflow-hidden rounded-full bg-[#A9CDF7]'>
<div className='absolute left-0 top-0 h-full w-full'></div>
</div>
<div className='absolute inset-0 flex items-center justify-center'>
<span className='text-center font-bold text-gray-800'>
<p className='pb-1 pt-2 text-6xl text-white lg:pb-3 lg:pt-4 lg:text-8xl'>
{hours}
</p>
<p className='text-2xl font-light text-white lg:text-5xl'>
{props.hours}
</p>
</span>
</div>
</div>
<div className='relative h-48 w-48 lg:h-64 lg:w-64'>
<div className='absolute inset-0 rotate-[-45deg] overflow-hidden rounded-full bg-[#A9CDF7]'>
<div className='absolute left-0 top-0 h-full w-1/2'></div>
<div className='absolute right-0 top-0 h-full w-1/2 bg-[#C8E0FC]'></div>
</div>
<div className='absolute inset-0 flex items-center justify-center'>
<span className='text-center font-bold text-gray-800'>
<p className='pb-1 pt-2 text-6xl text-white lg:pb-3 lg:pt-4 lg:text-8xl'>
{minutes}
</p>
<p className='text-2xl font-light text-white lg:text-5xl'>
{props.minutes}
</p>
</span>
</div>
</div>
</div>
</div>
</section>
);
};
export default CountDownTimer;

View File

@ -1,155 +1,194 @@
import Link from 'next/link'
import Link from 'next/link';
import Image from 'next/image';
import { getDictionary } from '@/dictionaries';
import OpenFestLogoWithe from './openfest/openfest-logo-withe.svg';
const Footer = async ({ lang }) => {
const dictionary = await getDictionary(lang);
const currentYear = new Date().getFullYear();
const Footer = () => {
return (
<footer className='mt-auto'>
<div className='bg-dark-blue pt-8 lg:pt-16 pb-6'>
<div className='container'>
<div className='flex items-center gap-4 mb-3'>
<div className='bg-blue w-14 h-14 lg:w-16 lg:h-16 p-1 rounded-full'>
<svg
className='fill-deep-blue'
width='100%'
height='100%'
viewBox='0 0 293 182'
fill='none'
xmlns='http://www.w3.org/2000/svg'
<footer className='bg-[#002A5D] px-12 pt-12 lg:px-9'>
<div className='row-gap-6 m-auto mb-8 grid max-w-screen-xl gap-10 sm:grid-cols-2 lg:grid-cols-4'>
<div className='sm:col-span-2'>
<Image src={OpenFestLogoWithe} alt='OpenFest Logo' width={256} />
<div className='mt-6 lg:max-w-sm'>
<p className='text-[15px] text-base text-white'>
{dictionary.footer.description}
</p>
<div className='mt-3 flex flex-col'>
<div className='my-4 flex items-center'>
<div className='mr-3 flex h-10 w-10 items-center justify-center rounded-full bg-[#A9CDF7]'>
<i
className='fa-solid fa-calendar-days'
style={{ color: '#002A5D' }}
></i>
</div>
<p className='text-base text-white'>
{dictionary.footer.eventDate}
</p>
</div>
<div className='flex items-center'>
<div className='mr-3 flex h-10 w-10 items-center justify-center rounded-full bg-[#A9CDF7]'>
<i
className='fa-solid fa-location-dot'
style={{ color: '#002A5D' }}
></i>
</div>
<a
href='https://maps.app.goo.gl/XsAKbZh7mMR3T8Rk8'
target='_blank'
className='text-base text-white hover:underline hover:underline-offset-4'
>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M0 86.1918L18.5717 65.0594L66.4078 111.895C70.0214 108.957 74.1682 105.87 78.7001 102.753L48.1916 61.7055L65.8746 49.4475L93.4804 93.6119C101.863 89.0114 111.163 84.7374 121.353 81.4429L98.1307 8.48858L133.29 0L147.833 75.4772C153.401 74.8539 159 74.5274 164.627 74.5571L177.601 13.1484L203.104 19.0845L184.917 76.4566C204.2 79.9886 220.283 88.2397 233.168 98.5982L282.663 37.9315L293 47.7557L241.876 106.256C252.095 116.317 259.796 127.566 264.98 138.221L233.257 156.594C233.257 156.594 220.402 126.349 196.202 108.126C198.986 114.537 200.497 121.63 200.497 129.05C200.497 158.196 176.772 182 147.714 182C117.117 182 92.888 155.703 95.0206 125.34L122.004 128.605C118.361 142.05 128.55 155.941 142.916 155.941C154.764 155.941 164.598 146.205 164.598 134.215C164.598 102.308 128.402 94.5023 102.544 105.484C86.4605 112.34 73.5166 122.402 55.8039 136.084C37.7061 119.107 18.8679 102.783 0 86.1918Z'
/>
</svg>
{dictionary.footer.eventLocation}
</a>
</div>
</div>
</div>
</div>
<div className='space-y-2 text-sm'>
<p className='text-base font-bold tracking-wide text-gray-900'>
Contacts
</p>
<div className='mt-6 flex basis-1/4 flex-col gap-4'>
<a
href='mailto:info@openfest.org'
target='_blank'
className='hover:underline hover:underline-offset-4'
>
Свържете се
<i className='fa-solid fa-angle-right ml-1 text-neon-green'></i>
</a>
<a
href='https://cfp.openfest.org/'
target='_blank'
className='hover:underline hover:underline-offset-4'
>
Включете се
<i className='fa-solid fa-angle-right ml-1 text-neon-green'></i>
</a>
</div>
</div>
<div>
<p className='text-xl lg:text-3xl font-extrabold uppercase'>
OpenFest
<span className='text-base font-bold tracking-wide text-white'>
{dictionary.footer.contactTeam}
</span>
<p className='mt-4 text-[15px] text-base text-white'>
{dictionary.footer.contactDirections}
</p>
<p>2024</p>
<div className='mt-0 flex flex-col'>
<div className='my-4 flex items-center'>
<div className='mr-3 flex h-10 w-10 items-center justify-center rounded-full bg-[#A9CDF7]'>
<i
className='fa-solid fa-envelope'
style={{ color: '#002A5D' }}
></i>
</div>
</div>
<div className='flex flex-col lg:flex-row gap-6'>
<div className='basis-1/2'>
<p>
OpenFest е конференция, посветена на свободната култура,
свободния софтуер и софтуера с отворен код, свободното споделяне
на знания.
</p>
<div className='flex flex-col gap-4 my-4'>
<div className='flex items-center'>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full mr-3'>
<i className='fa-solid fa-calendar-days'></i>
</div>
2 и 3 ноември 2024 (събота и неделя)
<a
href='mailto:info@openfest.org'
target='_blank'
className='text-base hover:underline hover:underline-offset-4'
>
info@openfest.org
</a>
</div>
<div className='flex items-center'>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full mr-3'>
<i className='fa-solid fa-location-dot'></i>
<div className='mr-3 flex h-10 w-10 items-center justify-center rounded-full bg-[#A9CDF7]'>
<i
className='fa-solid fa-user-plus'
style={{ color: '#002A5D' }}
></i>
</div>
Sofia Tech Park
</div>
<div className='flex items-center'>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full mr-3'>
<i className='fa-solid fa-ticket'></i>
</div>
Вход свободен, без предварителна регистрация
<a
href='http://cfp.openfest.org/'
target='_blank'
className='text-base hover:underline hover:underline-offset-4'
>
Call for participation
</a>
</div>
</div>
</div>
<div className='basis-1/4'>
<p className='font-extrabold'>Свържете се</p>
<p>
Ако имате въпроси, предложения или желаете да се включите в
OpenFest 2024, пишете ни:
</p>
<div className='flex flex-col'>
<div className='flex items-center my-4'>
<div className='w-10 h-10 bg-neon-green text-black flex items-center justify-center rounded-full mr-3'>
<i className='fa-solid fa-envelope'></i>
</div>
<Link href='mailto:info@openfest.org'>info@openfest.org</Link>
</div>
</div>
</div>
<div className='flex flex-col gap-4 basis-1/4'>
<Link href='https://cfp.openfest.org/'>
<div className='flex items-center'>
<div className='w-10 h-10 bg-neon-green text-black flex items-center justify-center rounded-full mr-3'>
<i className='fa-solid fa-lightbulb'></i>
</div>
Call for Participation
</div>
</Link>
<Link href='https://cfp.openfest.org/'>
<div className='flex items-center'>
<div className='w-10 h-10 bg-neon-green text-black flex items-center justify-center rounded-full mr-3'>
<i className='fa-solid fa-helmet-safety'></i>
</div>
Call for Volunteers
</div>
</Link>
<Link href='https://cfp.openfest.org/'>
<div className='flex items-center'>
<div className='w-10 h-10 bg-neon-green text-black flex items-center justify-center rounded-full mr-3'>
<i className='fa-solid fa-handshake-angle'></i>
</div>
Партньорство и спонсорство
</div>
</Link>
</div>
</div>
<div className='flex justify-center gap-4 mt-4'>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full'>
<div className='mb-12 mt-14 flex justify-center gap-7'>
<a
href='https://www.youtube.com/@openfestbulgaria'
target='_blank'
className='cursor flex h-12 w-12 items-center justify-center rounded-full bg-[#A9CDF7] text-[#002A5D] hover:bg-white'
>
<i className='fa-brands fa-youtube'></i>
<i className='fa-brands fa-youtube fa-xl'></i>
</a>
</div>
<div className='text-blue text-4xl flex items-center justify-center rounded-full'>
<a
href='https://www.facebook.com/groups/6360369433'
href='https://www.facebook.com/OpenFestBulgaria'
target='_blank'
className='cursor flex h-12 w-12 items-center justify-center rounded-full bg-[#A9CDF7] text-[#002A5D] hover:bg-white'
>
<i className='fa-brands fa-facebook'></i>
<i className='fa-brands fa-facebook fa-xl'></i>
</a>
</div>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full'>
<a href='https://twitter.com/openfestbg' target='_blank'>
<i className='fa-brands fa-x-twitter'></i>
<a
href='https://twitter.com/openfestbg'
target='_blank'
className='cursor flex h-12 w-12 items-center justify-center rounded-full bg-[#A9CDF7] text-[#002A5D] hover:bg-white'
>
<i className='fa-brands fa-x-twitter fa-xl'></i>
</a>
</div>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full'>
<a href='https://mastodon.social/@openfest' target='_blank'>
<i className='fa-brands fa-mastodon'></i>
<a
href='https://mastodon.social/@openfest'
target='_blank'
className='cursor flex h-12 w-12 items-center justify-center rounded-full bg-[#A9CDF7] text-[#002A5D] hover:bg-white'
>
<i className='fa-brands fa-mastodon fa-xl'></i>
</a>
</div>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full'>
<a
href='https://www.instagram.com/openfestbulgaria'
target='_blank'
className='cursor flex h-12 w-12 items-center justify-center rounded-full bg-[#A9CDF7] text-[#002A5D] hover:bg-white'
>
<i className='fa-brands fa-instagram'></i>
<i className='fa-brands fa-instagram fa-xl'></i>
</a>
</div>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full'>
<a
href='https://www.linkedin.com/company/openfest-bulgaria/'
target='_blank'
className='cursor flex h-12 w-12 items-center justify-center rounded-full bg-[#A9CDF7] text-[#002A5D] hover:bg-white'
>
<i className='fa-brands fa-linkedin-in'></i>
<i className='fa-brands fa-linkedin-in fa-xl'></i>
</a>
</div>
</div>
<p className='text-center mt-5'>
&copy; 2024 OpenFest. Някои права са запазени.
<div className='m-auto flex max-w-screen-xl flex-col-reverse justify-between border-t border-[#F2F5F9] pb-10 pt-5 lg:flex-row'>
<p className='text-sm text-[#F2F5F9]'>
© {currentYear} OpenFest. {dictionary.footer.copyright}
</p>
</div>
<ul className='mb-3 flex flex-col space-y-2 sm:flex-row sm:space-x-5 sm:space-y-0 lg:mb-0'>
<li>
<a
href='/'
className='hover:text-deep-purple-accent-400 text-sm text-gray-600 transition-colors duration-300'
>
F.A.Q
</a>
</li>
<li>
<a
href='/'
className='hover:text-deep-purple-accent-400 text-sm text-gray-600 transition-colors duration-300'
>
Privacy Policy
</a>
</li>
<li>
<a
href='/'
className='hover:text-deep-purple-accent-400 text-sm text-gray-600 transition-colors duration-300'
>
Terms &amp; Conditions
</a>
</li>
</ul>
</div>
</footer>
)
}
);
};
export default Footer
export default Footer;

View File

@ -1,18 +0,0 @@
import Chicken from './icons/Chicken'
const Header = () => {
return (
<header className='relative overflow-hidden pt-10 pb-16 sm:pt-16 sm:pb-24 lg:pt-16 lg:pb-44 bg-deep-blue'>
<div className='container flex flex-col gap-2 lg:gap-4 text-center'>
<p className='uppercase tracking-widest lg:tracking-max text-xl lg:text3xl z-10'>
2 - 3 Ноември 2024
</p>
<p className='font-extrabold text-4xl lg:text-8xl z-10'>OpenFest</p>
<p className='font-extrabold text-4xl lg:text-8xl z-10'>2024</p>
</div>
<Chicken className='fill-blue absolute inset-0 scale-1.3 -translate-y-10 sm:scale-125 lg:-translate-y-16' />
</header>
)
}
export default Header

View File

@ -1,59 +0,0 @@
import Circle from './icons/Circle'
import Eye from './icons/Eye'
const Info = () => {
return (
<div className='bg-deep-blue'>
<div className='container'>
<div className='flex flex-col-reverse lg:flex-row gap-6 items-center py-8 lg:py-16'>
<div className='flex justify-center relative flex-1'>
<Circle className='w-2/5 md:w-1/2' />
<Eye className='absolute inset-0 translate-x-full w-2/5 md:translate-x-3/4 md:w-1/2' />
</div>
<div className='flex-1'>
<h2 className='font-extrabold text-xl lg:text-3xl'>
{' '}
Повече за OpenFest
</h2>
<p className='mt-4 mb-2'>
OpenFest e най-голямата българска конференция, посветена на
свободната култура, свободния софтуер и софтуера с отворен код,
свободното споделяне на знания фестивал на свободното
творчество.
</p>
<p>
Организаторите всякога се стараят да дадат поле за изява и на
свободното изкуство и свободното разпространение на знания.
</p>
</div>
</div>
</div>
<div className='bg-blue'>
<div className='container flex flex-col gap-2 items-center lg:gap-0 lg:flex-row lg:justify-between p-2'>
<p>
<i className='fa-solid fa-angle-right text-neon-pink'></i>
1500+ посетители годишно
</p>
<p>
<i className='fa-solid fa-angle-right text-neon-pink'></i>
40+ Лектора
</p>
<p>
<i className='fa-solid fa-angle-right text-neon-pink'></i>
20+ Лекции
</p>
<p>
<i className='fa-solid fa-angle-right text-neon-pink'></i>
20+ Работилници
</p>
<p>
<i className='fa-solid fa-angle-right text-neon-pink'></i>
70+ Доброволеца
</p>
</div>
</div>
</div>
)
}
export default Info

View File

@ -1,155 +0,0 @@
import Link from 'next/link'
import BackToTheSource from './icons/BackToTheSource'
export default function JoinUs() {
return (
<div className='container flex flex-col pt-8 lg:pt-16 gap-8 lg:gap-16'>
<div className='flex flex-col-reverse text-black lg:flex-row gap-6 items-center'>
<div className='flex-1'>
<h2 className='font-extrabold text-xl lg:text-3xl'>
Станете част от OpenFest 2024
</h2>
<p className='mt-4 mb-2'>
Фестът е оживен двудневен празник на всичко с отворен код, който
събира ентусиасти, разработчици и новатори. Независимо дали сте
опитен професионалист или начинаещ, OpenFest предлага уникална
възможност да се потопите в света на отворените технологии и
съвместното творчество във всички измерения.
</p>
<div className='flex flex-col gap-2 mt-4'>
<div className='flex items-center'>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full mr-3 text-white min-w-10'>
<i className='fa-solid fa-calendar-days'></i>
</div>
2 и 3 ноември 2024 (събота и неделя)
</div>
<div className='flex items-center'>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full mr-3 text-white min-w-10'>
<i className='fa-solid fa-location-dot'></i>
</div>
Sofia Tech Park
</div>
<div className='flex items-center'>
<div className='w-10 h-10 bg-blue flex items-center justify-center rounded-full mr-3 min-w-10 text-blue'>
<i className='fa-solid fa-location-dot'></i>
</div>
Вход свободен, без предварителна регистрация
</div>
</div>
</div>
<div className='flex justify-center relative flex-1'>
<BackToTheSource />
</div>
</div>
<div className='flex flex-col text-black lg:flex-row gap-6 items-center'>
<div className='flex flex-col gap-4 items-center center relative flex-1'>
<div className='flex items-center justify-center bg-blue rounded-full p-4 text-5xl w-24 h-24 lg:text-7xl lg:w-36 lg:h-36'>
<i className='fa-regular fa-lightbulb text-neon-pink'></i>
</div>
<h2 className='font-extrabold text-3xl text-center'>
Предложете
<br />
идея
</h2>
</div>
<div className='flex-1'>
<p className='mb-2'>
Представете лекция, уъркшоп или щанд. Приемаме предложения до 1
септември 2024 г
</p>
<p>Тази година направленията са:</p>
<ul>
<li>
<strong>Advanced Technical</strong> За технически лекции с
по-голяма сложност.
</li>
<li>
<strong>Technical</strong> Това е мястото да разкажете какво
ново сте открили през годината, което би било полезно и разбираемо
и за начинаещи.
</li>
<li>
<strong>OpenArt</strong> Свободата да твориш под Creative
Commons и свободното изкуство във всичките му форми.
</li>
<li>
<strong>Общност и социален</strong> Отворени общности,
образование и управление, свободни лицензи, как човек може да се
изхранва с хобито си и др.
</li>
</ul>
<div className='flex justify-center mt-4'>
<Link
href='https://cfp.openfest.org/'
className='bg-neon-green px-16 py-4 rounded-md'
>
Предложете идея
</Link>
</div>
</div>
</div>
<div className='flex flex-col-reverse text-black lg:flex-row gap-6 items-center'>
<div className='flex-1'>
<p>
OpenFest се организира и провежда изцяло от доброволци. Тази година
отново се надяваме да срещнем нови съмишленици и приятели, да
създадем вълнуващо събитие. Можете да се включите в екипите: Мрежа;
Логистика; Аудио и видео; Медия, уебсайт и дизайн; Хералди;
Рецепция.
</p>
<p className='mt-4'>
Повече за тях можете да прочетете във формата за кандидатстване.
</p>
<div className='flex justify-center mt-4'>
<Link
href='https://cfp.openfest.org/'
className='bg-neon-green px-16 py-4 rounded-md'
>
Кандидатствайте
</Link>
</div>
</div>
<div className='flex flex-col gap-4 items-center center relative flex-1'>
<div className='flex items-center justify-center bg-blue rounded-full p-4 text-5xl w-24 h-24 lg:text-7xl lg:w-36 lg:h-36'>
<i className='fa-solid fa-helmet-safety text-neon-pink'></i>
</div>
<h2 className='font-extrabold text-3xl text-center'>
Станете
<br />
доброволец
</h2>
</div>
</div>
<div className='flex flex-col text-black lg:flex-row gap-6 items-center'>
<div className='flex flex-col gap-4 items-center center relative flex-1'>
<div className='flex items-center justify-center bg-blue rounded-full p-4 text-5xl w-24 h-24 lg:text-7xl lg:w-36 lg:h-36'>
<i className='fa-solid fa-handshake-angle text-neon-pink'></i>
</div>
<h2 className='font-extrabold text-3xl text-center'>
Подкрепете <br /> събитието като <br /> партньор
</h2>
</div>
<div className='flex-1'>
<p>
OpenFest се организира и провежда изцяло от доброволци. Тази година
отново се надяваме да срещнем нови съмишленици и приятели, да
създадем вълнуващо събитие. Можете да се включите в екипите: Мрежа;
Логистика; Аудио и видео; Медия, уебсайт и дизайн; Хералди;
Рецепция.
</p>
<p className='mt-4'>
Повече за тях можете да прочетете във формата за кандидатстване.
</p>
<div className='flex justify-center mt-4'>
<Link
href='https://cfp.openfest.org/'
className='bg-neon-green px-16 py-4 rounded-md'
>
Кандидатствайте
</Link>
</div>
</div>
</div>
</div>
)
}

View File

@ -1,30 +1,30 @@
'use client'
import Link from 'next/link'
import { i18n } from '../../i18n-config'
import { usePathname } from 'next/navigation'
'use client';
import { usePathname } from 'next/navigation';
import Link from 'next/link';
import { i18n } from '../../i18n-config';
export default function LocaleSwitcher({ lang }) {
const pathName = usePathname()
const pathName = usePathname();
const { locales } = i18n
const otherLocale = locales?.find((cur) => cur !== lang)
const { locales } = i18n;
const otherLocale = locales?.find((cur) => cur !== lang);
function getRedirectPathName() {
if (!pathName) return '/'
const segments = pathName.split('/')
segments[1] = otherLocale
if (!pathName) return '/';
const segments = pathName.split('/');
segments[1] = otherLocale;
return segments.join('/')
return segments.join('/');
}
return (
<Link
href={getRedirectPathName()}
locale={otherLocale}
className='flex justify-center items-center'
className='flex items-center justify-center'
>
<i className='fa-solid fa-globe'></i>
<i className='fa-solid fa-globe text-black'></i>
<div className='pl-2'>{lang === 'en' ? 'БГ' : 'EN'}</div>
</Link>
)
);
}

View File

@ -1,31 +1,90 @@
import Logo from './icons/Logo'
import LanguageSwitcher from './LanguageSwitcher'
import Link from 'next/link'
// import Logo from './icons/Logo'
import LanguageSwitcher from './LanguageSwitcher';
import Link from 'next/link';
import Image from 'next/image';
// import {
// DisclosureButton,
// Menu,
// MenuButton,
// MenuItem,
// MenuItems,
// Transition,
// } from '@headlessui/react';
// import { BookmarkIcon } from '@heroicons/react';
import { getDictionary } from '@/dictionaries';
import OpenFestLogo from './openfest/openfest-logo.svg';
// const navigation = [
// { name: 'Dashboard', href: '#', current: true },
// { name: 'Team', href: '#', current: false },
// { name: 'Projects', href: '#', current: false },
// { name: 'Calendar', href: '#', current: false },
// ];
// function classNames(...classes) {
// return classes.filter(Boolean).join(' ')
// }
const open = true;
const NavBar = async ({ lang }) => {
const dictionary = await getDictionary(lang);
const Navbar = ({ lang }) => {
return (
<nav className='bg-deep-blue'>
<div className='container flex flex-col items-center gap-6 lg:flex-row lg:justify-between py-6'>
<Link href='/' className='flex items-center gap-4'>
<div className='bg-blue w-14 h-14 lg:w-16 lg:h-16 p-1 rounded-full'>
<Logo className='fill-deep-blue' />
</div>
<>
<nav className='container flex flex-col items-center justify-between gap-4 bg-white text-black sm:flex-row'>
<div>
<p className='text-xl lg:text-3xl font-extrabold uppercase'>
OpenFest
</p>
<p>2024</p>
<a href='https://openfest.org/' className='flex items-center'>
<Image src={OpenFestLogo} alt='OpenFest Logo' width={256} />
</a>
</div>
</Link>
<div className='flex w-full flex-wrap justify-center sm:justify-around lg:justify-end gap-6 gap-y-4 items-center font-semibold'>
<Link href='/news'>Новини</Link>
<Link href='https://cfp.openfest.org/'>Call for participation</Link>
<Link href='mailto:info@openfest.org'>Пишете ни</Link>
<div className='flex items-center justify-center'>
<ul className='flex flex-wrap items-center justify-center gap-4 sm:gap-8'>
<li>
<a href='#' className='' aria-current='page'>
{dictionary.nav.home}
</a>
</li>
<li>
<a href='#' className=''>
{dictionary.nav.about}
</a>
</li>
<li>
<a href='#' className=''>
{dictionary.nav.partners}
</a>
</li>
<li>
<a href='#' className=''>
{dictionary.nav.archive}
</a>
</li>
<li>
<a href='#' className=''>
{dictionary.nav.contact}
</a>
</li>
<li>
<LanguageSwitcher lang={lang} />
</li>
</ul>
</div>
</div>
{
//<div className='mx-auto flex max-w-screen-xl flex-wrap items-center justify-between p-4'>
// <div
// className='hidden w-full md:block md:w-auto'
// id='navbar-default'
// >
// // </div>
//</div>
}
</nav>
)
}
</>
);
};
export default Navbar
export default NavBar;

View File

@ -1,21 +0,0 @@
import Link from 'next/link'
export default function News({ posts }) {
return (
<div className='flex flex-wrap text-center gap-6 lg:text-left lg:gap-4 lg:gap-y-8'>
{posts.map((post) => (
<div key={post.id} className='flex flex-col gap-2 basis-24 flex-1'>
<p className='text-xl font-extrabold'>{post.title}</p>
<p>{post.date}</p>
<p>{post.truncatedContent}</p>
<Link href={`/news/post/${post.id}`}>
<p className='underline decoration-2 underline-offset-4 decoration-neon-green mt-auto'>
Прочетете
<i className='fa-solid fa-angle-right text-neon-green ml-1'></i>
</p>
</Link>
</div>
))}
</div>
)
}

View File

@ -0,0 +1,51 @@
import Image from 'next/image';
import { getDictionary } from '@/dictionaries';
import { getSortedPostsData } from '@/lib/posts';
const NewsFeed = async ({ lang }) => {
const dictionary = await getDictionary(lang);
const posts = await getSortedPostsData(lang);
return (
<section className='bg-blue-8'>
<div className='container flex flex-col gap-4 sm:gap-8'>
<h2 className='text-center text-2xl text-blue-2 sm:text-start sm:text-4xl'>
{dictionary.main.news.title}
</h2>
<div className='flex flex-col gap-4 sm:flex-row sm:gap-8'>
{posts.map((post) => {
return (
<div
key={post.title}
className='flex basis-1/3 flex-col overflow-hidden rounded-xl drop-shadow-2xl'
>
<div>
<Image src={post.imageUrl} width='400' height='190'></Image>
</div>
<div className='flex h-full flex-1 flex-col gap-2 bg-white p-6 text-center sm:gap-4'>
<p className='text-blue-2'>{post.title}</p>
<p className='text-sm opacity-50'>{post.date}</p>
<a
href='#'
className='mx-auto mt-auto self-baseline rounded-3xl bg-blue-2 px-12 py-2'
>
{dictionary.main.news.cardButton}
</a>
</div>
</div>
);
})}
</div>
<a
href='#'
className='mt-4 flex items-center justify-center gap-4 self-center rounded-3xl bg-blue-2 px-12 py-2 sm:self-baseline'
>
{dictionary.main.news.button}
<i className='fa-solid fa-arrow-right'></i>
</a>
</div>
</section>
);
};
export default NewsFeed;

View File

@ -0,0 +1,61 @@
import Image from 'next/image';
import { getDictionary } from '@/dictionaries';
const Partners = async ({ lang }) => {
const dictionary = await getDictionary(lang);
const sponsorLogos = ['logo-1', 'logo-2', 'logo-3', 'logo-4', 'logo-5'];
const mediaPartnerLogos = ['logo-1', 'logo-2', 'logo-3', 'logo-4', 'logo-5'];
const getShuffledLogos = (logos) => {
for (let i = logos.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[logos[i], logos[j]] = [logos[j], logos[i]];
}
return logos;
};
return (
<section>
<div className='container flex flex-col gap-10 !py-16 sm:gap-16'>
<div>
<h2 className='pb-4 text-center text-2xl text-blue-2 sm:pb-8 sm:text-4xl'>
{dictionary.main.partners.sponsors}
</h2>
<div className='flex flex-wrap justify-evenly gap-6'>
{getShuffledLogos(sponsorLogos).map((logo) => {
return (
<div
key={logo}
className='cursor-pointer opacity-50 hover:opacity-100'
>
<p>{logo}</p>
</div>
);
})}
</div>
</div>
<div>
<h2 className='pb-4 text-center text-2xl text-blue-2 sm:pb-8 sm:text-4xl'>
{dictionary.main.partners.media}
</h2>
<div className='flex flex-wrap justify-evenly gap-6'>
{getShuffledLogos(mediaPartnerLogos).map((logo) => {
return (
<div
key={logo}
className='cursor-pointer opacity-50 hover:opacity-100'
>
<p>{logo}</p>
</div>
);
})}
</div>
</div>
</div>
</section>
);
};
export default Partners;

View File

@ -1,57 +0,0 @@
const Social = () => {
return (
<div id='social' className='py-8 lg:pb-16 bg-deep-blue'>
<div className='container'>
<h2 className='font-extrabold text-center text-xl lg:text-3xl mb-6 lg:mb-12'>
Продължете разговора
</h2>
<div className='flex flex-wrap justify-center gap-10 md:gap-20 md:gap-y-12'>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-neon-green w-12 h-12 md:w-16 md:h-16 rounded-full text-black text-3xl'>
<i className='fa-brands fa-youtube'></i>
</div>
@openfestbulgaria
</div>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-black w-12 h-12 md:w-16 md:h-16 rounded-full text-neon-green text-5xl md:text-6xl'>
<i className='fa-brands fa-facebook '></i>
</div>
@openfestbulgaria
</div>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-neon-green w-12 h-12 md:w-16 md:h-16 rounded-full text-black text-3xl'>
<i className='fa-brands fa-x-twitter'></i>
</div>
OpenFestBG
</div>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-neon-green w-12 h-12 md:w-16 md:h-16 rounded-full text-black text-3xl'>
<i className='fa-brands fa-instagram'></i>
</div>
openfestbulgaria
</div>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-neon-green w-12 h-12 md:w-16 md:h-16 rounded-full text-black text-3xl'>
<i className='fa-brands fa-mastodon'></i>
</div>
@openfest
</div>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-neon-green w-12 h-12 md:w-16 md:h-16 rounded-full text-black text-3xl'>
<i className='fa-brands fa-facebook-f'></i>
</div>
Facebook група: OpenFest
</div>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-neon-green w-12 h-12 md:w-16 md:h-16 rounded-full text-black text-3xl'>
<i className='fa-brands fa-linkedin-in'></i>
</div>
openfest-bulgaria
</div>
</div>
</div>
</div>
)
}
export default Social

View File

@ -1,196 +0,0 @@
export default function BackToTheSource({ className }) {
return (
<svg
className={className}
width='100%'
fill='none'
viewBox='0 0 710 319'
xmlns='http://www.w3.org/2000/svg'
>
<path
d='M563.902 292.433C502.395 305.069 425.252 313.559 342.093 313.559C144.143 313.559 5.02502 265.455 5.02502 227.837'
stroke='#D92ACE'
strokeLinecap='round'
strokeWidth='10'
/>
<path
d='M703.912 227.837C703.912 241.271 683.012 256.043 647.124 269.484'
stroke='#D92ACE'
strokeLinecap='round'
strokeWidth='10'
/>
<path
d='M636.889 268.756L626.209 281.882C628.085 283.785 629.533 285.587 630.453 286.816C630.536 286.931 630.628 287.061 630.725 287.198C630.867 287.402 631.022 287.626 631.178 287.853C631.332 288.078 631.486 288.307 631.634 288.526C631.649 288.55 631.661 288.573 631.674 288.596C631.679 288.609 631.685 288.621 631.688 288.633C631.732 288.747 631.734 288.87 631.699 288.982C631.692 289.001 631.686 289.022 631.678 289.042C631.67 289.054 631.664 289.067 631.656 289.08C631.648 289.096 631.638 289.111 631.628 289.126C631.591 289.179 631.543 289.227 631.485 289.265L629.694 290.449L629.68 290.458L623.253 294.709C623.008 294.871 622.679 294.804 622.518 294.56L621.658 293.266C621.494 293.021 621.561 292.691 621.806 292.528L624.068 291.031C623.285 289.698 620.987 286.121 617.506 283.534C617.438 283.483 617.347 283.543 617.361 283.623C618.161 288.135 616.542 292.934 612.724 296.014C607.14 300.52 598.966 299.641 594.462 294.054C593.781 293.214 593.222 292.314 592.785 291.375C592.638 291.056 592.841 290.684 593.188 290.631L599.924 289.594C600.099 289.566 600.276 289.631 600.396 289.761C602.406 291.942 605.793 292.222 608.138 290.33C610.576 288.355 610.96 284.781 608.994 282.333C608.985 282.324 608.979 282.316 608.972 282.307C607.981 281.103 606.463 280.598 604.898 280.627C601.804 280.687 597.733 281.872 593.885 283.917C590.477 285.727 587.219 288.392 585.177 290.21C584.548 290.772 584.031 291.256 583.668 291.607C583.45 291.817 583.099 291.802 582.901 291.574L578.791 286.866L571.092 279.166C570.953 279.026 570.903 278.821 570.961 278.634L572.776 272.738C572.895 272.356 573.375 272.235 573.658 272.518L583.049 281.913C583.961 281.215 584.974 280.482 586.069 279.752L582.143 273.801C582.056 273.67 582.032 273.505 582.08 273.354L583.627 268.323C583.759 267.895 584.328 267.812 584.576 268.185L590.523 277.102C591.092 276.804 591.672 276.518 592.262 276.244C593.543 275.651 594.802 275.152 596.03 274.734L593.265 262.643C593.227 262.474 593.274 262.298 593.388 262.17L599.412 255.488C599.699 255.169 600.226 255.306 600.323 255.726L604.268 272.975C605.441 272.869 606.542 272.833 607.558 272.847L611.097 259.71C611.204 259.309 611.715 259.182 611.998 259.487L615.478 263.24C615.601 263.374 615.648 263.561 615.6 263.738L612.982 273.504C612.998 273.508 613.015 273.513 613.031 273.517C617.189 274.63 620.878 277.071 623.851 279.661L635.523 265.422C635.807 265.076 636.364 265.213 636.454 265.652C636.682 266.758 636.997 268.315 636.997 268.315C637.028 268.471 636.989 268.633 636.889 268.756Z'
fill='#D92ACE'
/>
<path
d='M631.634 288.526C631.486 288.307 631.332 288.078 631.178 287.853C631.023 287.626 630.867 287.401 630.725 287.198C630.735 287.209 630.743 287.22 630.751 287.232C631.029 287.63 631.347 288.098 631.634 288.526Z'
fill='#D92ACE'
/>
<path
d='M631.634 288.526C631.65 288.55 631.662 288.573 631.674 288.596C631.661 288.573 631.649 288.55 631.634 288.526Z'
fill='#D92ACE'
/>
<path
d='M631.7 288.981C631.734 288.869 631.732 288.747 631.689 288.633C631.734 288.747 631.736 288.869 631.7 288.981Z'
fill='#D92ACE'
/>
<path
d='M4.26318 179.068V173.831L40.1095 198.998V209.139L33.1999 207.054L40.1095 214.671V224.813L8.75892 202.802V182.225L4.26318 179.068ZM16.6344 192.806L26.2898 199.584L32.2339 200.586V198.705L16.6339 187.753L16.6344 192.806ZM16.6344 203.094L32.2345 214.047V212.166L26.2903 204.822L16.635 198.043L16.6344 203.094Z'
fill='#2F1B5D'
/>
<path
d='M44.8984 226.151L53.3013 208.784L49.0308 207.152V201.915L72.9646 211.059L83.4333 240.874L74.1351 237.321L71.5177 229.867L56.8481 224.263L54.2306 229.716L44.8984 226.151ZM58.983 219.843L69.3827 223.816L65.7323 213.534L62.6329 212.35L58.983 219.843Z'
fill='#2F1B5D'
/>
<path
d='M83.4746 220.236V214.999L125.788 226.289V235.804L116.492 231.995V229.045L98.0778 224.132V239.473L116.492 244.386V241.436L125.788 242.589V252.104L88.7817 242.229V221.652L83.4746 220.236Z'
fill='#2F1B5D'
/>
<path
d='M130.03 248.834V242.233L135.427 241.779V228.281L144.88 230.069V240.949L163.389 239.361V233.57L172.842 235.359V245.169L158.644 246.391L166.794 254.498L173.06 255.683V261.215L161.179 258.967L149.263 247.162L144.88 247.55V255.884L135.427 254.095V248.38L130.03 248.834Z'
fill='#2F1B5D'
/>
<path
d='M190.567 248.341V238.016L231.526 242.899V253.224L221.973 250.758V246.996L215.823 246.263V266.841L206.27 265.702V245.125L200.12 244.391V248.153L190.567 248.341Z'
fill='#2F1B5D'
/>
<path
d='M236.663 269.16V243.346L274.856 246.205V272.02L236.663 269.16ZM246.257 264.642L265.262 266.064V250.723L246.257 249.3V264.642Z'
fill='#2F1B5D'
/>
<path
d='M292.153 257.404V247.077L333.389 248.083V258.409L323.771 256.847V253.085L317.58 252.934V273.512L307.962 273.277V252.7L301.771 252.549V256.31L292.153 257.404Z'
fill='#2F1B5D'
/>
<path
d='M336.884 253.391V248.154L351.995 247.926V258.142L371.014 257.854V247.639L380.634 247.494V273.308L371.014 273.453V263.09L351.995 263.378V273.74L342.376 273.886V253.308L336.884 253.391Z'
fill='#2F1B5D'
/>
<path
d='M385.287 252.636V247.399L429.052 245.016V254.53L419.445 253.725V250.775L400.414 251.812V256.864L416.058 256.012V261.249L400.414 262.101V267.153L419.445 266.116V263.166L429.052 261.315V270.829L390.809 272.912V252.334L385.287 252.636Z'
fill='#2F1B5D'
/>
<path
d='M449.991 269.131V260.649L459.559 261.036V262.88L478.108 260.916V257.67L449.991 256.187V243.316L487.675 239.325V248.287L478.107 247.825V245.575L459.559 247.54V251.044L487.675 252.528V265.14L449.991 269.131Z'
fill='#2F1B5D'
/>
<path
d='M493.776 264.387V238.573L531.666 232.986V258.802L493.776 264.387ZM503.293 257.748L522.148 254.967V239.626L503.293 242.406V257.748Z'
fill='#2F1B5D'
/>
<path
d='M536.277 237.581V232.345L551.098 229.383V247.453L555.725 249.035L569.75 246.232V225.655L579.185 223.77V249.584L553.194 254.778L541.663 250.813V236.505L536.277 237.581Z'
fill='#2F1B5D'
/>
<path
d='M583.769 242.965V237.248L589.071 234.891V221.468L626.041 211.457V224.143L615.295 228.933L627.5 236.876L614.655 240.354L604.514 233.734L598.358 236.47V244.767L589.071 247.282V240.608L583.769 242.965ZM598.358 230.68L616.754 222.49V219.207L598.358 224.19V230.68Z'
fill='#2F1B5D'
/>
<path
d='M630.358 215.744V210.508L671.111 194.471V203.985L662.157 206.181V203.231L644.422 210.209V225.55L662.157 218.572V215.621L671.111 210.77V220.285L635.469 234.31V213.732L630.358 215.744Z'
fill='#2F1B5D'
/>
<path
d='M676.633 199.679V194.443L709.429 165.354V174.868L702.23 179.926V176.976L687.969 189.624V194.677L699.692 184.279V189.515L687.969 199.913V204.966L702.23 192.317V189.367L709.429 181.653V191.168L680.77 216.587V196.009L676.633 199.679Z'
fill='#2F1B5D'
/>
<path
d='M9.02502 88.5303V62.7158L41.509 42.4174V68.2319L9.02502 88.5303ZM17.1851 78.195L33.3485 68.0942V52.7533L17.1851 62.8535V78.195Z'
fill='#2F1B5D'
/>
<path
d='M46.16 61.7082V55.9184L51.3779 53.2808V39.2672L87.7623 27.3013V40.6512L60.5178 54.4421V62.0759L51.3779 65.0817V59.0706L46.16 61.7082ZM60.5178 48.6522L78.6224 39.4899V35.5441L60.5178 41.4979V48.6522Z'
fill='#2F1B5D'
/>
<path
d='M91.6941 31.5751V26.3386L134.507 16.9479V26.4623L125.109 27.1961V24.246L106.494 28.329V33.3815L121.796 30.025V35.2616L106.494 38.6185V43.6705L125.109 39.5875V36.6374L134.507 33.2484V42.7629L97.0955 50.9691V30.3912L91.6941 31.5751Z'
fill='#2F1B5D'
/>
<path
d='M140.397 41.7753V14.9285L168.735 26.5561V16.7833L165.639 17.2655V12.0289L178.242 10.0658V35.8803L170.192 37.1344L149.905 28.494V35.0583L153 34.5757V39.8122L140.397 41.7753Z'
fill='#2F1B5D'
/>
<path
d='M182.864 14.6865V9.44997L223.359 5.04932V14.3792L213.794 14.0909V11.3249L197.89 13.0534V19.9127L213.794 18.1842V23.4208L197.89 25.1493V33.6314L188.325 34.6704V14.093L182.864 14.6865Z'
fill='#2F1B5D'
/>
<path
d='M226.822 9.93122V4.69468L270.551 1.72705V11.2415L260.952 10.5655V7.61539L241.938 8.90557V13.958L257.569 12.8968V18.1333L241.938 19.194V24.2465L260.952 22.9563V20.0062L270.551 18.0271V27.5416L232.339 30.1348V9.55685L226.822 9.93122Z'
fill='#2F1B5D'
/>
<path
d='M276.363 27.2867V18.8052L285.978 19.8886V21.7326L304.62 21.1158V17.8708L276.363 14.3431V1.47275L314.237 0.220215V9.18137L304.621 8.02423V5.7744L285.979 6.39113V9.89453L314.237 13.4222V26.0342L276.363 27.2867Z'
fill='#2F1B5D'
/>
<path
d='M319.207 10.4932V0.167588L360.456 0V10.3256L350.834 9.03696V5.27521L344.642 5.30048V25.8784L335.02 25.9176V5.33967L328.827 5.36493V9.12669L319.207 10.4932Z'
fill='#2F1B5D'
/>
<path
d='M379.62 26.2487V13.747L408.609 10.3076V6.80416L389.234 6.04666V8.29597L379.62 9.39536V0.434204L418.223 1.94354V14.8139L389.234 18.2534V21.3881L408.609 22.1456V20.3016L418.223 19.2759V27.7581L379.62 26.2487Z'
fill='#2F1B5D'
/>
<path
d='M424.366 28.0948V2.28027L462.202 4.9612V30.7757L424.366 28.0948ZM433.963 19.5188L448.598 9.23448L433.963 8.19749V19.5188ZM437.971 23.822L452.606 24.859V13.5377L437.971 23.822Z'
fill='#2F1B5D'
/>
<path
d='M468.333 31.2975V18.7959L497.185 17.2582V13.7548L477.901 11.7261V13.9755L468.333 14.4442V5.48303L506.753 9.52478V22.3952L477.901 23.9324V27.0671L497.184 29.0957V27.2517L506.753 26.8567V35.3383L468.333 31.2975Z'
fill='#2F1B5D'
/>
<path
d='M511.534 32.4187V27.1451L546.994 13.6234V32.3203L552.612 33.1345V38.371L546.994 37.5568V41.0236L537.472 39.6437V36.1774L511.534 32.4187ZM523.791 28.9581L537.472 30.9409V23.7128L523.791 28.9581Z'
fill='#2F1B5D'
/>
<path
d='M10.4181 143.275V130.774L34.7318 142.034V138.531L18.4813 127.949V130.198L10.4176 126.423V117.461L42.7944 138.545V151.416L18.4807 140.156V143.29L34.7313 153.872V152.029L42.7944 155.878V164.36L10.4181 143.275Z'
fill='#2F1B5D'
/>
<path
d='M61.6609 161.07V155.833L85.6112 164.178V169.415L61.6609 161.07Z'
fill='#2F1B5D'
/>
<path
d='M104.358 185.272V176.311L113.724 179.986V182.235L132.241 186.585V184.703L125.207 179.88L116.989 177.95V172.713L125.207 174.644L132.241 173.124V171.244L113.724 166.894V169.143L104.358 168.419V159.458L141.608 168.206V178.348L133.39 179.183L141.608 183.879V194.02L104.358 185.272Z'
fill='#2F1B5D'
/>
<path
d='M162.992 198.026V171.179L191.346 191.526V181.754L188.248 181.284V176.048L200.858 177.962V203.777L192.804 202.553L172.504 187.671V194.235L175.602 194.705V199.942L162.992 198.026Z'
fill='#2F1B5D'
/>
<path
d='M207.132 204.55V178.736L245.229 182.681V208.495L207.132 204.55ZM216.702 200.304L235.659 202.267V186.926L216.702 184.963V200.304Z'
fill='#2F1B5D'
/>
<path
d='M249.683 188.319V183.083L262.194 183.841L272.643 201.55L283.019 185.104L293.138 185.718L277.242 210.569L267.897 210.001L255.166 188.652L249.683 188.319Z'
fill='#2F1B5D'
/>
<path
d='M326.036 212.885L334.629 200.477L335.095 199.804L334.524 199.216L323.852 188.271L328.549 187.878L339.79 199.409L330.734 212.493L326.036 212.885ZM324.031 214.051L331.283 213.443L341.072 199.302L328.931 186.848L321.925 187.435L321.81 187.601L333.812 199.911L324.025 214.046L324.031 214.051Z'
fill='#D92ACE'
/>
<path
d='M352.882 213.922L361.474 201.513L361.939 200.839L361.368 200.253L350.697 189.307L355.394 188.914L366.637 200.446L357.579 213.529L352.882 213.922ZM350.875 215.088L358.128 214.478L367.919 200.338L355.777 187.885L348.771 188.473L348.657 188.638L360.656 200.946L350.872 215.083L350.875 215.088Z'
fill='#D92ACE'
/>
<path
d='M378.256 214.32L386.847 201.911L387.313 201.238L386.742 200.651L376.07 189.704L380.767 189.312L392.01 200.843L382.953 213.925L378.256 214.32ZM376.248 215.485L383.502 214.877L393.292 200.736L381.15 188.284L374.144 188.87L374.03 189.035L386.031 201.345L376.244 215.481L376.248 215.485Z'
fill='#D92ACE'
/>
<path
d='M395.038 188.216L394.924 188.381L406.925 200.691L397.138 214.827L397.144 214.831L404.395 214.224L414.185 200.083L402.044 187.629L395.038 188.216Z'
fill='#D92ACE'
/>
<path
d='M414.462 186.724L414.347 186.89L426.348 199.199L416.561 213.336L416.566 213.34L423.817 212.732L433.607 198.591L421.466 186.139L414.462 186.724Z'
fill='#D92ACE'
/>
<path
d='M432.272 184.561L432.159 184.726L444.16 197.036L434.373 211.171L434.378 211.176L441.631 210.568L451.422 196.428L439.279 183.974L432.272 184.561Z'
fill='#D92ACE'
/>
</svg>
)
}

File diff suppressed because one or more lines are too long

View File

@ -1,59 +0,0 @@
export default function Circle({ className }) {
return (
<svg
className={className}
height='100%'
viewBox='0 0 473 472'
fill='none'
xmlns='http://www.w3.org/2000/svg'
>
<g filter='url(#filter0_d_181_191)'>
<circle
cx='236.5'
cy='236'
r='166'
stroke='#2F1B5D'
strokeWidth='40'
shapeRendering='crispEdges'
/>
</g>
<defs>
<filter
id='filter0_d_181_191'
x='0.5'
y='0'
width='472'
height='472'
filterUnits='userSpaceOnUse'
colorInterpolationFilters='sRGB'
>
<feFlood floodOpacity='0' result='BackgroundImageFix' />
<feColorMatrix
in='SourceAlpha'
type='matrix'
values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'
result='hardAlpha'
/>
<feOffset />
<feGaussianBlur stdDeviation='25' />
<feComposite in2='hardAlpha' operator='out' />
<feColorMatrix
type='matrix'
values='0 0 0 0 0.773556 0 0 0 0 0.327778 0 0 0 0 0.983333 0 0 0 0.2 0'
/>
<feBlend
mode='normal'
in2='BackgroundImageFix'
result='effect1_dropShadow_181_191'
/>
<feBlend
mode='normal'
in='SourceGraphic'
in2='effect1_dropShadow_181_191'
result='shape'
/>
</filter>
</defs>
</svg>
)
}

View File

@ -1,57 +0,0 @@
export default function Eye({ className }) {
return (
<svg
className={className}
height='100%'
viewBox='0 0 485 337'
fill='none'
xmlns='http://www.w3.org/2000/svg'
>
<g filter='url(#filter0_d_181_192)'>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M50.5 142.239L74.8397 114.72L137.533 175.709C142.269 171.883 147.703 167.864 153.643 163.805L113.659 110.353L136.834 94.3904L173.014 151.901C183.999 145.91 196.189 140.345 209.542 136.055L179.108 41.0538L225.187 30L244.247 128.286C251.545 127.475 258.882 127.049 266.257 127.088L283.26 47.1218L316.684 54.8518L292.849 129.562C318.12 134.161 339.199 144.906 356.085 158.394L420.952 79.3943L434.5 92.1874L367.498 168.366C380.891 181.468 390.984 196.116 397.777 209.992L356.202 233.916C356.202 233.916 339.354 194.532 307.639 170.801C311.288 179.149 313.267 188.387 313.267 198.049C313.267 236.003 282.173 267 244.092 267C203.991 267 172.237 232.756 175.032 193.218L210.396 197.469C205.622 214.978 218.976 233.066 237.803 233.066C253.331 233.066 266.219 220.388 266.219 204.774C266.219 163.226 218.781 153.061 184.892 167.361C163.813 176.289 146.849 189.391 123.635 207.209C99.9169 185.101 75.2279 163.844 50.5 142.239Z'
fill='#5C46B2'
/>
</g>
<defs>
<filter
id='filter0_d_181_192'
x='0.5'
y='0'
width='484'
height='337'
filterUnits='userSpaceOnUse'
colorInterpolationFilters='sRGB'
>
<feFlood floodOpacity='0' result='BackgroundImageFix' />
<feColorMatrix
in='SourceAlpha'
type='matrix'
values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'
result='hardAlpha'
/>
<feOffset dy='20' />
<feGaussianBlur stdDeviation='25' />
<feComposite in2='hardAlpha' operator='out' />
<feColorMatrix
type='matrix'
values='0 0 0 0 0.546065 0 0 0 0 0.5375 0 0 0 0 1 0 0 0 0.2 0'
/>
<feBlend
mode='normal'
in2='BackgroundImageFix'
result='effect1_dropShadow_181_192'
/>
<feBlend
mode='normal'
in='SourceGraphic'
in2='effect1_dropShadow_181_192'
result='shape'
/>
</filter>
</defs>
</svg>
)
}

View File

@ -1,18 +0,0 @@
export default function Logo({ className }) {
return (
<svg
className={className}
width='100%'
height='100%'
viewBox='0 0 293 182'
fill='none'
xmlns='http://www.w3.org/2000/svg'
>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M0 86.1918L18.5717 65.0594L66.4078 111.895C70.0214 108.957 74.1682 105.87 78.7001 102.753L48.1916 61.7055L65.8746 49.4475L93.4804 93.6119C101.863 89.0114 111.163 84.7374 121.353 81.4429L98.1307 8.48858L133.29 0L147.833 75.4772C153.401 74.8539 159 74.5274 164.627 74.5571L177.601 13.1484L203.104 19.0845L184.917 76.4566C204.2 79.9886 220.283 88.2397 233.168 98.5982L282.663 37.9315L293 47.7557L241.876 106.256C252.095 116.317 259.796 127.566 264.98 138.221L233.257 156.594C233.257 156.594 220.402 126.349 196.202 108.126C198.986 114.537 200.497 121.63 200.497 129.05C200.497 158.196 176.772 182 147.714 182C117.117 182 92.888 155.703 95.0206 125.34L122.004 128.605C118.361 142.05 128.55 155.941 142.916 155.941C154.764 155.941 164.598 146.205 164.598 134.215C164.598 102.308 128.402 94.5023 102.544 105.484C86.4605 112.34 73.5166 122.402 55.8039 136.084C37.7061 119.107 18.8679 102.783 0 86.1918Z'
/>
</svg>
)
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -1,15 +1,15 @@
import { remark } from 'remark'
import html from 'remark-html'
import strip from 'strip-markdown'
import { remark } from 'remark';
import html from 'remark-html';
import strip from 'strip-markdown';
export async function markdownToHtml(markdown) {
const result = await remark().use(html).process(markdown)
const result = await remark().use(html).process(markdown);
return result.toString()
return result.toString();
}
export async function markdownToText(markdown) {
const result = await remark().use(strip).process(markdown)
const result = await remark().use(strip).process(markdown);
return result.toString()
return result.toString();
}

View File

@ -1,66 +1,67 @@
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import { markdownToHtml, markdownToText } from './markdown'
import { cache } from 'react'
import { i18n } from '../../i18n-config'
import { cache } from 'react';
import { markdownToHtml, markdownToText } from './markdown';
import { i18n } from '../../i18n-config';
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import process from 'process';
async function getTruncatedPostContent(content) {
const words = content.split(' ')
const truncatedWords = 9
const words = content.split(' ');
const truncatedWords = 9;
const truncatedContent =
words.length > truncatedWords
? words.slice(0, truncatedWords).join(' ') + '...'
: content
const truncatedContentAsText = await markdownToText(truncatedContent)
: content;
const truncatedContentAsText = await markdownToText(truncatedContent);
return truncatedContentAsText
return truncatedContentAsText;
}
export const getSortedPostsData = cache(async (locale) => {
const postsDirectory = path.join(process.cwd(), `src/posts/${locale}`)
const fileNames = fs.readdirSync(postsDirectory)
const postsDirectory = path.join(process.cwd(), `src/posts/${locale}`);
const fileNames = fs.readdirSync(postsDirectory);
const allPostsDataPromises = fileNames.map(async (fileName) => {
const id = fileName.replace(/\.md$/, '')
const id = fileName.replace(/\.md$/, '');
const fullPath = path.join(postsDirectory, fileName)
const fileContents = fs.readFileSync(fullPath, 'utf8')
const fullPath = path.join(postsDirectory, fileName);
const fileContents = fs.readFileSync(fullPath, 'utf8');
const matterResult = matter(fileContents)
const content = matterResult.content
const truncatedContent = await getTruncatedPostContent(content)
const contentAsHtml = await markdownToHtml(content)
const matterResult = matter(fileContents);
const content = matterResult.content;
const truncatedContent = await getTruncatedPostContent(content);
const contentAsHtml = await markdownToHtml(content);
return {
id,
content: contentAsHtml,
truncatedContent,
...matterResult.data,
}
})
const allPostsData = await Promise.all(allPostsDataPromises)
};
});
const allPostsData = await Promise.all(allPostsDataPromises);
const sortedPostsData = allPostsData.sort((a, b) => {
if (a.date < b.date) {
return -1
return -1;
} else {
return 1
return 1;
}
})
});
return {
posts: sortedPostsData,
}
})
return sortedPostsData;
});
export const getAllPosts = cache(async () => {
const allPosts = {}
const allPosts = {};
for (const locale of i18n.locales) {
const { posts } = await getSortedPostsData(locale)
allPosts[locale] = posts
const { posts } = await getSortedPostsData(locale);
allPosts[locale] = posts;
}
return allPosts
})
return allPosts;
});

View File

@ -1,10 +1,10 @@
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { i18n } from "../i18n-config";
import { i18n } from '../i18n-config';
import { match as matchLocale } from "@formatjs/intl-localematcher";
import Negotiator from "negotiator";
import { match as matchLocale } from '@formatjs/intl-localematcher';
import Negotiator from 'negotiator';
function getLocale(request: NextRequest): string | undefined {
// Negotiator expects plain object so we need to transform headers
@ -28,16 +28,17 @@ export function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname;
// `/_next/` and `/api/` are ignored by the watcher, but we need to ignore files in `public` manually.
// If you have one
if (
[
const paths = [
'/manifest.json',
'/favicon.ico',
'/next.svg',
'/vercel.svg',
// Your other files in `public`
].includes(pathname)
)
return
];
const dirs = ['/images/', '/posts/'];
if (paths.includes(pathname) || dirs.some((dir) => pathname.startsWith(dir)))
return;
// Check if there is any supported locale in the pathname
const pathnameIsMissingLocale = i18n.locales.every(
@ -52,7 +53,7 @@ export function middleware(request: NextRequest) {
// The new URL is now /en-US/products
return NextResponse.redirect(
new URL(
`/${locale}${pathname.startsWith("/") ? "" : "/"}${pathname}`,
`/${locale}${pathname.startsWith('/') ? '' : '/'}${pathname}`,
request.url
)
);
@ -61,5 +62,5 @@ export function middleware(request: NextRequest) {
export const config = {
// Matcher ignoring `/_next/` and `/api/`
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};

View File

@ -1,6 +1,7 @@
---
title: 'Bulgarian'
date: '08-06-2024'
imageUrl: '/posts/post-1.webp'
---
**Some** description

View File

@ -1,6 +1,7 @@
---
title: 'English'
date: '08-06-2024'
imageUrl: '/posts/post-1.webp'
---
**Some** description

24
src/styles/globals.css Normal file
View File

@ -0,0 +1,24 @@
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css');
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap');
@tailwind base;
@tailwind components;
@tailwind utilities;
.container {
@apply mx-auto w-full max-w-screen-xl px-6 py-8 sm:px-12 sm:py-10;
}
@layer base {
p {
@apply text-black;
}
}
@layer components {
.fa-color-custom {
color: #000;
}
.fa-color-custom:hover {
color: red;
}
}

View File

@ -1,24 +1,26 @@
import type { Config } from 'tailwindcss'
import type { Config } from 'tailwindcss';
const config: Config = {
content: [
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
],
content: ['./src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {
fontFamily: {
openSans: ['Open Sans', 'sans-serif'],
},
backgroundImage: {
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
'gradient-conic':
'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
'home-bg': "url('/images/openfest-1.png')",
},
colors: {
'dark-blue': '#09021B',
'deep-blue': '#0F0429',
blue: '#2F1B5D',
'neon-green': '#34EAD8',
'neon-pink': '#D92ACE',
'blue-2': '#004394',
'blue-8': '#E2EFFE',
//'dark-blue': '#09021B',
//'deep-blue': '#0F0429',
//blue: '#2F1B5D',
//'neon-green': '#34EAD8',
//'neon-pink': '#D92ACE',
},
letterSpacing: {
max: '0.3em',
@ -32,5 +34,6 @@ const config: Config = {
},
},
plugins: [],
}
export default config
};
export default config;

View File

@ -18,7 +18,8 @@
}
],
"paths": {
"@/*": ["./src/*"]
"@/*": ["./src/*"],
"@/dictionaries": ["./dictionaries"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],