diff --git a/actions/categoryActions.ts b/actions/categoryActions.ts new file mode 100644 index 0000000..028bc9d --- /dev/null +++ b/actions/categoryActions.ts @@ -0,0 +1,13 @@ +import { Category } from "@/types/articles"; +import client from "@/utils/client"; +import { cache } from "react"; + +export const getCategories = cache(async function (): Promise { + const query = ` +*[_type=='category']{ + title, + _id +} +`; + return await client.fetch(query); +}); diff --git a/utils/newsletter.ts b/actions/newsLetterActions.ts similarity index 56% rename from utils/newsletter.ts rename to actions/newsLetterActions.ts index 4bee10e..db35ae4 100644 --- a/utils/newsletter.ts +++ b/actions/newsLetterActions.ts @@ -1,4 +1,5 @@ "use server"; +import { redirect } from "next/navigation"; import { db, QueryResult, QueryResultRow } from "@vercel/postgres"; export interface User { @@ -8,7 +9,7 @@ export interface User { } export async function queryDb( - query: string + query: string, ): Promise | null> { const client = await db.connect(); try { @@ -20,17 +21,20 @@ export async function queryDb( } } -export const unsubscribe= async (mail: string) => { +export const unsubscribe = async (mail: string) => { "use server"; const exists = await user_exists(mail); if (exists) { - const res = await queryDb(`DELETE FROM mailing_list WHERE email = '${mail}'`); - console.log(res) + const res = await queryDb( + `DELETE FROM mailing_list WHERE email = '${mail}'`, + ); + console.log(res); } }; + export async function user_exists(email: string): Promise { const result = await queryDb( - `SELECT * FROM mailing_list WHERE email='${email}'` + `SELECT * FROM mailing_list WHERE email='${email}'`, ); if (result && result.rowCount > 0) { return true; @@ -39,11 +43,11 @@ export async function user_exists(email: string): Promise { export async function add_user( email: string, - name: string + name: string, ): Promise { try { const result = await queryDb( - `INSERT INTO mailing_list (name, email) VALUES ('${name}', '${email}') RETURNING *` + `INSERT INTO mailing_list (name, email) VALUES ('${name}', '${email}') RETURNING *`, ); if (result && result.rowCount > 0) { return result.rows[0]; @@ -53,3 +57,19 @@ export async function add_user( return null; } } + +export async function handleSubmit(formData: FormData) { + const email = formData.get("email"); + const name = formData.get("name"); + if (email) { + const exists = await user_exists(email as string); + if (!exists) { + const response = await add_user(email as string, name as string); + if (response !== null) { + redirect("/newsletter/thank-you"); + } + } else { + redirect("/newsletter/already-with-me"); + } + } +} diff --git a/actions/postAcions.ts b/actions/postAcions.ts new file mode 100644 index 0000000..70414ea --- /dev/null +++ b/actions/postAcions.ts @@ -0,0 +1,100 @@ +"use server"; +import client from "@/utils/client"; +import { cache } from "react"; +import type { ArticlCardType, ArticleDetailType } from "@/types/articles"; +import type { Serie } from "@/types/series"; + +export const getLatestHomePosts = cache(async function (): Promise< + ArticlCardType[] +> { + const query = `*[_type == "article"] | order(releasedAt desc) [0..4] { + title, + 'slug':slug.current, + releasedAt, + description, + 'categories':categories[]->title, +}`; + return await client.fetch(query); +}); + +export const getArticleSeries = cache(async function (): Promise { + const query = ` +*[_type=='serie'] { + _id, + title, + description, + 'articles':articles[]->{ + title, + 'categories':categories[]->title, + 'slug':slug.current, + releasedAt, + }, +}`; + return await client.fetch(query); +}); + +export const getArticles = cache(async function (): Promise { + let query = ` + *[_type=='article'] | order(releasedAt desc) { + 'slug':slug.current, + title, + releasedat, + description, + mainImage, + 'categories':categories[]->title, + } +`; + return await client.fetch(query); +}); + +export const getArticleBySlug = cache(async function ( + slug?: string, +): Promise { + const query = ` +*[_type == "article" && slug.current == $slug][0]{ + title, + 'slug':slug.current, + releasedAt, + description, + 'categories':categories[]->title, + body[]{ + ..., + asset->{ + metadata, + "_type":"reference", + "_ref": _id + } + }, + "related": *[_type == "article" && _id != ^._id && count(categories[@._ref in ^.^.categories[]._ref]) > 0] | order(releasedAt desc, _createdAt desc) [0..2] { + title, + _id, + "mainImage":{ + "asset":{ + ...mainImage.asset, + "metadata":mainImage.asset->metadata + }, + }, + "slug": slug.current, + description + } +}`; + return await client.fetch(query, { + slug: slug, + }); +}); + +export const getArticleSEOContentBySlug = cache(async function ( + slug?: string, +): Promise { + const seoQuery = ` +*[_type == "article" && slug.current == $slug][0]{ + title, + 'slug':slug.current, + description, + 'categories':categories[]->title, + 'mainImage':mainImage.asset->{url}.url +}`; + return await client.fetch(seoQuery, { + slug: slug, + }); +}); diff --git a/actions/projectActions.ts b/actions/projectActions.ts new file mode 100644 index 0000000..8121cfe --- /dev/null +++ b/actions/projectActions.ts @@ -0,0 +1,18 @@ +"use server"; + +import client from "@/utils/client"; +import type { Project } from "@/types/projects"; +import { cache } from "react"; + +export const getHomeProjects = cache( + async function (): Promise { + const query = ` + *[_type=='project' && pinned==true][0..6]{ + ..., + "slug": slug.current + } +`; + + return await client.fetch(query); + }, +); diff --git a/actions/snippetActions.ts b/actions/snippetActions.ts new file mode 100644 index 0000000..4389fe4 --- /dev/null +++ b/actions/snippetActions.ts @@ -0,0 +1,18 @@ +"use server"; + +import { ArticlCardType } from "@/types/articles"; +import client from "@/utils/client"; +import { cache } from "react"; + +export const getSnippets = cache(async function (): Promise { + let query = ` +*[_type=='snippet'] | order(releasedAt desc) { + title, + 'slug':slug.current, + 'categories':categories[]->title, + description, + releasedAt +} +`; + return await client.fetch(query); +}); diff --git a/app/(web)/about/page.tsx b/app/(web)/about/page.tsx index 2bee019..91db3ca 100644 --- a/app/(web)/about/page.tsx +++ b/app/(web)/about/page.tsx @@ -4,18 +4,19 @@ import Image from "next/image"; import Hero from "@/components/pages/hero"; import { getOpenGraph, getTwitterCard, metaData } from "@/utils/metadata"; import type { Metadata } from "next"; + const ComputerModel = dynamic(() => import("@/components/common/model"), { ssr: false, }); const hero = { title: "About", - subtitle: "Arkar", + subtitle: "Arkar Myat", description: "", }; export const metadata: Metadata = { - title: "About | Arkar", + title: "About | Arkar Myat", openGraph: getOpenGraph( "/images/arkar.png", "About | " + metaData.title, @@ -31,8 +32,8 @@ export const metadata: Metadata = { function AboutPage() { return ( -
-
+
+
title, - body[]{ - ..., - asset->{ - metadata, - "_type":"reference", - "_ref": _id - } - }, - "related": *[_type == "article" && _id != ^._id && count(categories[@._ref in ^.^.categories[]._ref]) > 0] | order(releasedAt desc, _createdAt desc) [0..2] { - title, - _id, - "mainImage":{ - "asset":{ - ...mainImage.asset, - "metadata":mainImage.asset->metadata - }, - }, - "slug": slug.current, - description - } -}`; export async function generateMetadata({ params, }: { params: { slug: string }; }) { - const seoQuery = ` -*[_type == "article" && slug.current == $slug][0]{ - title, - 'slug':slug.current, - description, - 'categories':categories[]->title, - 'mainImage':mainImage.asset->{url}.url -}`; - - const data: ArticleDetailType = await client.fetch(seoQuery, { - slug: params?.slug, - }); - + const data: ArticleDetailType = await getArticleSEOContentBySlug(params.slug); return { title: data?.title, description: data?.description, @@ -64,6 +28,7 @@ export async function generateMetadata({ data?.title, data.description, new URL(`/snippets/${data?.slug}`, metaData?.url), + "article", ), twitter: getTwitterCard(data?.mainImage, data.title, data.description), }; @@ -71,10 +36,8 @@ export async function generateMetadata({ async function ArticleDetailPage(props: DetailPageParamTypes) { const { params } = props; - const data: ArticleDetailType = await client.fetch(query, { - slug: params?.slug, - }); - if (data === null) return
404
; + const data = await getArticleBySlug(params?.slug); + if (data === null) return <>; return (
diff --git a/app/(web)/articles/page.tsx b/app/(web)/articles/page.tsx index 8efb0d3..15835ca 100644 --- a/app/(web)/articles/page.tsx +++ b/app/(web)/articles/page.tsx @@ -1,11 +1,11 @@ export const revalidate = 60; -import { getOpenGraph, getTwitterCard, metaData } from "@/utils/metadata"; -import { Categories } from "@/components/pages/article/categories"; import { ArticleTimeLine } from "@/components/pages/article/timeline"; import { Banner } from "@/components/pages/banner"; +import { Categories } from "@/components/pages/article/categories"; import { Metadata } from "next"; -import client from "@/utils/client"; +import { getCategories } from "@/actions/categoryActions"; +import { getOpenGraph, getTwitterCard, metaData } from "@/utils/metadata"; export const metadata: Metadata = { title: "Articles | Arkar", @@ -22,18 +22,11 @@ export const metadata: Metadata = { ), }; -const categoryQuery = ` -*[_type=='category']{ - title, - _id -} -`; - export default async function ArticlePage(props: { - searchParams?: { [key: string]: string | undefined }; + searchParams?: { category: string | undefined }; }) { const { searchParams } = props; - const categories = await client.fetch(categoryQuery); + const categories = await getCategories(); return (
diff --git a/app/(web)/layout.tsx b/app/(web)/layout.tsx index 6be48fd..99d2b21 100644 --- a/app/(web)/layout.tsx +++ b/app/(web)/layout.tsx @@ -23,8 +23,7 @@ export const metadata: Metadata = { keywords: metaData.keywords, authors: [ { name: metaData.title, url: metaData.url }, - { name: "Arkar", url: "https://arkar.space" }, - { name: "Arkar", url: "https://arkar.space" }, + { name: "Arkar Myat", url: "https://arkar.space" }, ], creator: metaData.title, publisher: metaData.title, diff --git a/app/(web)/newsletter/sorry-to-see-you-go/[email]/page.tsx b/app/(web)/newsletter/sorry-to-see-you-go/[email]/page.tsx index 1010e4a..a49e60c 100644 --- a/app/(web)/newsletter/sorry-to-see-you-go/[email]/page.tsx +++ b/app/(web)/newsletter/sorry-to-see-you-go/[email]/page.tsx @@ -1,9 +1,10 @@ "use client"; -import React, { useState } from "react"; -import Link from "next/link"; import Image from "next/image"; -import { unsubscribe } from "@/utils/newsletter"; +import Link from "next/link"; +import React, { useState } from "react"; +import { unsubscribe } from "@/actions/newsLetterActions"; import { useTransition } from "react"; + export default function ByeBye({ params }: any) { const [message, setMessage] = useState("Unsubscribe"); const { email } = params; diff --git a/app/(web)/page.tsx b/app/(web)/page.tsx index 02193f7..5496ac5 100644 --- a/app/(web)/page.tsx +++ b/app/(web)/page.tsx @@ -1,4 +1,4 @@ -export const revalidate = 60; +export const revalidate = 3600; import type { Metadata } from "next"; import { Intro } from "@/components/pages/home/intro"; @@ -7,9 +7,8 @@ import { Projects } from "@/components/pages/home/projects"; import { HomeLatestPost } from "@/components/pages/home/latest-blogs"; import { ArticleSeries } from "@/components/common/article-series/ArticleSeries"; - export const metadata: Metadata = { - title: "Arkar", + title: "Arkar Myat | An Inspiring Developer", }; export default async function Home() { diff --git a/app/(web)/snippets/[slug]/page.tsx b/app/(web)/snippets/[slug]/page.tsx index 3b4d14e..8dc6ad6 100644 --- a/app/(web)/snippets/[slug]/page.tsx +++ b/app/(web)/snippets/[slug]/page.tsx @@ -43,17 +43,19 @@ export async function generateMetadata({ data?.mainImage, data.title, data.description, - new URL(`/snippets/${data?.slug}`, metaData?.url) + new URL(`/snippets/${data?.slug}`, metaData?.url), + 'article' ), twitter: getTwitterCard(data?.mainImage, data.title, data.description), }; } + async function SnippetDetailPage(props: DetailPageParamTypes) { const { params } = props; const data: SnippetDetailType = await client.fetch(query, { slug: params?.slug, }); - if (data === null) return
404
; + if (data === null) return <>; return (
diff --git a/app/(web)/snippets/page.tsx b/app/(web)/snippets/page.tsx index d7ab623..b641f3a 100644 --- a/app/(web)/snippets/page.tsx +++ b/app/(web)/snippets/page.tsx @@ -1,11 +1,10 @@ export const revalidate = 60; import Hero from "@/components/pages/hero"; -import SnippetTimeLine from "@/components/pages/snippets/timeline"; import { Metadata } from "next"; -import client from "@/utils/client"; -import type { ArticlCardType } from "@/types/articles"; +import { SnippetTimeLine } from "@/components/pages/snippets/timeline"; import { getOpenGraph, getTwitterCard, metaData } from "@/utils/metadata"; +import { getSnippets } from "@/actions/snippetActions"; const hero = { title: "Snippets", @@ -15,31 +14,23 @@ const hero = { }; export const metadata: Metadata = { - title: "Snippets | Arkar", + title: "Snippets | Arkar Myat", openGraph: getOpenGraph( "/images/snippets.png", "Snippets | " + metaData.title, metaData.description, - new URL("/snippets", metaData.url) + new URL("/snippets", metaData.url), + "article", ), twitter: getTwitterCard( "/images/snippets.png", "Snippets | " + metaData.title, - metaData.description + metaData.description, ), }; -async function ArticlePage() { - let query = ` -*[_type=='snippet'] | order(releasedAt desc) { - title, - 'slug':slug.current, - 'categories':categories[]->title, - description, - releasedAt -} -`; - const raw_data: ArticlCardType[] = await client.fetch(query); +async function ArticlePage() { + const snippets = await getSnippets(); return (
@@ -48,9 +39,10 @@ async function ArticlePage() { description={hero.description} subtitle={hero.subtitle} /> - +
); } + export default ArticlePage; diff --git a/app/(web)/videos/page.tsx b/app/(web)/videos/page.tsx index 6369f4d..111bfae 100644 --- a/app/(web)/videos/page.tsx +++ b/app/(web)/videos/page.tsx @@ -23,6 +23,7 @@ export const metadata: Metadata = { metaData.description, ), }; + function VideoPage() { return (
@@ -33,7 +34,7 @@ function VideoPage() { subtitle={hero.subtitle} /> - +
); diff --git a/components/common/article-serie-card/ArticleSerieCard.tsx b/components/common/article-serie-card/index.tsx similarity index 100% rename from components/common/article-serie-card/ArticleSerieCard.tsx rename to components/common/article-serie-card/index.tsx diff --git a/components/common/article-series/ArticleSeries.tsx b/components/common/article-series/ArticleSeries.tsx index 438a5f1..5adc538 100644 --- a/components/common/article-series/ArticleSeries.tsx +++ b/components/common/article-series/ArticleSeries.tsx @@ -1,26 +1,11 @@ import React from "react"; import type { Serie } from "@/types/series"; -import client from "@/utils/client"; import { ArticlCardType } from "@/types/articles"; -import { ArticleSerieCard } from "../article-serie-card/ArticleSerieCard"; +import { ArticleSerieCard } from "@/components/common/article-serie-card"; +import { getArticleSeries } from "@/actions/postAcions"; -type Props = {}; - -const query = ` -*[_type=='serie'] { - _id, - title, - description, - 'articles':articles[]->{ - title, - 'categories':categories[]->title, - 'slug':slug.current, - releasedAt, - }, -}`; - -export async function ArticleSeries({}: Props) { - const series: Serie[] = await client.fetch(query); +export async function ArticleSeries() { + const series: Serie[] = await getArticleSeries(); return (
{!!series && diff --git a/components/common/header/index.tsx b/components/common/header/index.tsx index f9295c5..e405534 100644 --- a/components/common/header/index.tsx +++ b/components/common/header/index.tsx @@ -16,7 +16,7 @@ const Header = () => { absolute top-0 left-0 h-[3.5em] z-[99999] w-full" > - Arkar + Arkar Myat diff --git a/components/common/newsletter/index.tsx b/components/common/newsletter/index.tsx index c2d811a..7e988c6 100644 --- a/components/common/newsletter/index.tsx +++ b/components/common/newsletter/index.tsx @@ -1,28 +1,8 @@ import React from "react"; -import { redirect } from "next/navigation"; import cx from "classnames"; -import { user_exists, add_user } from "@/utils/newsletter"; - -type Props = {}; - -export function NewsLetter({}: Props) { - async function handleSubmit(formData: FormData) { - "use server"; - const email = formData.get("email"); - const name = formData.get("name"); - if (email) { - const exists = await user_exists(email as string); - if (!exists) { - const response = await add_user(email as string, name as string); - if (response !== null) { - redirect("/newsletter/thank-you"); - } - } else { - redirect("/newsletter/already-with-me"); - } - } - } +import { handleSubmit } from "@/actions/newsLetterActions"; +export function NewsLetter() { return (
@@ -48,7 +27,7 @@ export function NewsLetter({}: Props) { type="text" name="name" spellCheck={false} - placeholder="Enter your name! " + placeholder="Your Name ! " className="w-full px-4 py-2 border border-theme-primary-opaque bg-transparent rounded-md outline-none hover:bg-gradient-to-r hover:from-theme-accent-opaque " required={true} /> @@ -57,14 +36,14 @@ export function NewsLetter({}: Props) { name="email" required={true} spellCheck={false} - placeholder="Enter your email! " + placeholder="Your email ! " className="w-full px-4 py-2 border border-theme-primary-opaque bg-transparent rounded-md outline-none hover:bg-gradient-to-r hover:from-theme-accent-opaque " /> + {lines > 15 && ( + + )}
); } diff --git a/components/pages/article/timeline/index.tsx b/components/pages/article/timeline/index.tsx index 4b79635..cff996f 100644 --- a/components/pages/article/timeline/index.tsx +++ b/components/pages/article/timeline/index.tsx @@ -1,32 +1,27 @@ import ArticleCard from "../card"; import Link from "next/link"; -import client from "@/utils/client"; import type { ArticlCardType } from "@/types/articles"; - -let query = ` - *[_type=='article'] | order(releasedAt desc) { - title, - 'slug':slug.current, - releasedAt, - description, - 'mainImage':mainImage, - 'categories':categories[]->title, - } -`; +import { getArticles } from "@/actions/postAcions"; interface Props { current: string | undefined; } -export async function ArticleTimeLine(props: Props) { - const { current } = props; - const data: ArticlCardType[] = await client.fetch(query); - const filteredArticles = data.filter((article) => { - if (current) { + +function filterArticlesByParam(data: ArticlCardType[], param?: string) { + return data.filter((article) => { + if (param) { if (!article.categories) return false; - return article.categories.includes(current); + return article.categories.includes(param); } return true; }); +} + +export async function ArticleTimeLine(props: Props) { + const { current } = props; + const data = await getArticles(); + const filteredArticles = filterArticlesByParam(data, current); + return (
{filteredArticles.length > 0 ? ( diff --git a/components/pages/home/intro/index.tsx b/components/pages/home/intro/index.tsx index 347158f..4afbaf3 100644 --- a/components/pages/home/intro/index.tsx +++ b/components/pages/home/intro/index.tsx @@ -2,10 +2,10 @@ export function Intro() { return (

- Hello, I'm Arkar 👋 + Hello, I'm Arkar Myat 👋

- An inspiring programmer{" "} + An inspiring softare engineer{" "} title, -}} -`; +import { getLatestHomePosts } from "@/actions/postAcions"; export async function HomeLatestPost() { - const data: Props = await client.fetch(query); + const posts= await getLatestHomePosts(); return (

- Here are the latest posts I have written and published on my site. + Checkout my latest articles

- {data.posts.map((article, index) => { + {posts.map((article, index) => { return (

diff --git a/components/pages/snippets/timeline/index.tsx b/components/pages/snippets/timeline/index.tsx index 94ec472..8e2daba 100644 --- a/components/pages/snippets/timeline/index.tsx +++ b/components/pages/snippets/timeline/index.tsx @@ -7,7 +7,8 @@ import { ArticlCardType } from "@/types/articles"; interface Props { data: ArticlCardType[]; } -function SnippetTimeLine({ data }: Props) { + +export function SnippetTimeLine({ data }: Props) { const { filteredData, handleChange, searchTerm } = useSearchByTitle(data); return (

@@ -38,5 +39,3 @@ function SnippetTimeLine({ data }: Props) {
); } - -export default SnippetTimeLine; diff --git a/components/pages/videos/video-list/index.tsx b/components/pages/videos/video-list/index.tsx index 9bab9d3..25af638 100644 --- a/components/pages/videos/video-list/index.tsx +++ b/components/pages/videos/video-list/index.tsx @@ -1,14 +1,18 @@ import VideoCard from "@/components/pages/videos/video-card"; import type { VideoAPIType } from "@/types/videos"; -export async function VideoTimeline() { - const data: VideoAPIType = await fetch( +async function getVideos(): Promise { + return await fetch( `https://youtube.googleapis.com/youtube/v3/playlists?part=snippet&part=id&channelId=UC_RfEQCC3gL2AzsFFAABikg&maxResults=20&key=AIzaSyAtWf4t83KhLS48fEgqwPKDTDWLZrTBbds`, { //@ts-ignore Authorization: `Bearer ${process.env.NEXT_PUBLIC_YT_API}`, }, ).then((res) => res.json()); +} + +export async function VideoTimeline() { + const data = await getVideos(); return (
{ query, { slug: url, - } + }, ); const mailgun = new Mailgun(formData); @@ -39,7 +39,7 @@ const mail_handler = async (req: NextApiRequest, res: NextApiResponse) => { }); const object = recipent_vars.reduce( (acc, obj) => ({ ...acc, ...obj }), - {} + {}, ); const data = { from: "Arkar ", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9f77cd0..b7d4408 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -141,14 +141,14 @@ importers: specifier: ^1.0.2 version: 1.0.2 next: - specifier: 14.2.3 - version: 14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 14.2.4 + version: 14.2.4(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-sanity: specifier: ^9.0.13 - version: 9.0.14(@sanity/client@6.17.2)(@sanity/icons@2.11.8(react@18.3.1))(@sanity/types@3.37.2)(@sanity/ui@2.1.3(react-dom@18.3.1(react@18.3.1))(react-is@18.2.0)(react@18.3.1)(styled-components@6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(sanity@3.40.0(@types/node@20.11.19)(@types/react@18.2.57)(bufferutil@4.0.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.27.2)(utf-8-validate@6.0.3))(styled-components@6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + version: 9.0.14(@sanity/client@6.17.2)(@sanity/icons@2.11.8(react@18.3.1))(@sanity/types@3.37.2)(@sanity/ui@2.1.3(react-dom@18.3.1(react@18.3.1))(react-is@18.2.0)(react@18.3.1)(styled-components@6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(next@14.2.4(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(sanity@3.40.0(@types/node@20.11.19)(@types/react@18.2.57)(bufferutil@4.0.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.27.2)(utf-8-validate@6.0.3))(styled-components@6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) next-sanity-image: specifier: ^6.1.1 - version: 6.1.1(@sanity/client@6.17.2)(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 6.1.1(@sanity/client@6.17.2)(next@14.2.4(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) octokit: specifier: ^2.1.0 version: 2.1.0 @@ -1846,62 +1846,62 @@ packages: '@neondatabase/serverless@0.4.15': resolution: {integrity: sha512-fTTcnfj6z4gpOREF3fbzPYltt5vJKB3G9OdfV4diiO45mBAi//0n/ViOirYm4bGxi0luzszf9jGe3BP6hsQ7Ig==} - '@next/env@14.2.3': - resolution: {integrity: sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==} + '@next/env@14.2.4': + resolution: {integrity: sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg==} '@next/eslint-plugin-next@14.2.3': resolution: {integrity: sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw==} - '@next/swc-darwin-arm64@14.2.3': - resolution: {integrity: sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==} + '@next/swc-darwin-arm64@14.2.4': + resolution: {integrity: sha512-AH3mO4JlFUqsYcwFUHb1wAKlebHU/Hv2u2kb1pAuRanDZ7pD/A/KPD98RHZmwsJpdHQwfEc/06mgpSzwrJYnNg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@14.2.3': - resolution: {integrity: sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==} + '@next/swc-darwin-x64@14.2.4': + resolution: {integrity: sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@14.2.3': - resolution: {integrity: sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==} + '@next/swc-linux-arm64-gnu@14.2.4': + resolution: {integrity: sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@14.2.3': - resolution: {integrity: sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==} + '@next/swc-linux-arm64-musl@14.2.4': + resolution: {integrity: sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@14.2.3': - resolution: {integrity: sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==} + '@next/swc-linux-x64-gnu@14.2.4': + resolution: {integrity: sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@14.2.3': - resolution: {integrity: sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==} + '@next/swc-linux-x64-musl@14.2.4': + resolution: {integrity: sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@14.2.3': - resolution: {integrity: sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==} + '@next/swc-win32-arm64-msvc@14.2.4': + resolution: {integrity: sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-ia32-msvc@14.2.3': - resolution: {integrity: sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==} + '@next/swc-win32-ia32-msvc@14.2.4': + resolution: {integrity: sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] - '@next/swc-win32-x64-msvc@14.2.3': - resolution: {integrity: sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==} + '@next/swc-win32-x64-msvc@14.2.4': + resolution: {integrity: sha512-tkLrjBzqFTP8DVrAAQmZelEahfR9OxWpFR++vAI9FBhCiIxtwHwBHC23SBHCTURBtwB4kc/x44imVOnkKGNVGg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -6236,8 +6236,8 @@ packages: next-tick@1.1.0: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} - next@14.2.3: - resolution: {integrity: sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==} + next@14.2.4: + resolution: {integrity: sha512-R8/V7vugY+822rsQGQCjoLhMuC9oFj9SOi4Cl4b2wjDrseD0LRZ10W7R6Czo4w9ZznVSshKjuIomsRjvm9EKJQ==} engines: {node: '>=18.17.0'} hasBin: true peerDependencies: @@ -10335,37 +10335,37 @@ snapshots: dependencies: '@types/pg': 8.6.6 - '@next/env@14.2.3': {} + '@next/env@14.2.4': {} '@next/eslint-plugin-next@14.2.3': dependencies: glob: 10.3.10 - '@next/swc-darwin-arm64@14.2.3': + '@next/swc-darwin-arm64@14.2.4': optional: true - '@next/swc-darwin-x64@14.2.3': + '@next/swc-darwin-x64@14.2.4': optional: true - '@next/swc-linux-arm64-gnu@14.2.3': + '@next/swc-linux-arm64-gnu@14.2.4': optional: true - '@next/swc-linux-arm64-musl@14.2.3': + '@next/swc-linux-arm64-musl@14.2.4': optional: true - '@next/swc-linux-x64-gnu@14.2.3': + '@next/swc-linux-x64-gnu@14.2.4': optional: true - '@next/swc-linux-x64-musl@14.2.3': + '@next/swc-linux-x64-musl@14.2.4': optional: true - '@next/swc-win32-arm64-msvc@14.2.3': + '@next/swc-win32-arm64-msvc@14.2.4': optional: true - '@next/swc-win32-ia32-msvc@14.2.3': + '@next/swc-win32-ia32-msvc@14.2.4': optional: true - '@next/swc-win32-x64-msvc@14.2.3': + '@next/swc-win32-x64-msvc@14.2.4': optional: true '@nodelib/fs.scandir@2.1.5': @@ -11601,7 +11601,7 @@ snapshots: - react-dom - react-is - '@sanity/visual-editing@1.8.18(@sanity/client@6.17.2)(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))': + '@sanity/visual-editing@1.8.18(@sanity/client@6.17.2)(next@14.2.4(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))': dependencies: '@sanity/preview-url-secret': 1.6.12(@sanity/client@6.17.2) '@vercel/stega': 0.1.2 @@ -11612,7 +11612,7 @@ snapshots: valibot: 0.30.0 optionalDependencies: '@sanity/client': 6.17.2 - next: 14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@selderee/plugin-htmlparser2@0.11.0': dependencies: @@ -15850,14 +15850,14 @@ snapshots: new-array@1.0.0: {} - next-sanity-image@6.1.1(@sanity/client@6.17.2)(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): + next-sanity-image@6.1.1(@sanity/client@6.17.2)(next@14.2.4(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): dependencies: '@sanity/client': 6.17.2 '@sanity/image-url': 1.0.2 - next: 14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 - next-sanity@9.0.14(@sanity/client@6.17.2)(@sanity/icons@2.11.8(react@18.3.1))(@sanity/types@3.37.2)(@sanity/ui@2.1.3(react-dom@18.3.1(react@18.3.1))(react-is@18.2.0)(react@18.3.1)(styled-components@6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(sanity@3.40.0(@types/node@20.11.19)(@types/react@18.2.57)(bufferutil@4.0.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.27.2)(utf-8-validate@6.0.3))(styled-components@6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)): + next-sanity@9.0.14(@sanity/client@6.17.2)(@sanity/icons@2.11.8(react@18.3.1))(@sanity/types@3.37.2)(@sanity/ui@2.1.3(react-dom@18.3.1(react@18.3.1))(react-is@18.2.0)(react@18.3.1)(styled-components@6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(next@14.2.4(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(sanity@3.40.0(@types/node@20.11.19)(@types/react@18.2.57)(bufferutil@4.0.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.27.2)(utf-8-validate@6.0.3))(styled-components@6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)): dependencies: '@portabletext/react': 3.0.18(react@18.3.1) '@sanity/client': 6.17.2 @@ -15865,10 +15865,10 @@ snapshots: '@sanity/preview-kit': 5.0.53(@sanity/client@6.17.2)(react@18.3.1) '@sanity/types': 3.37.2 '@sanity/ui': 2.1.3(react-dom@18.3.1(react@18.3.1))(react-is@18.2.0)(react@18.3.1)(styled-components@6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) - '@sanity/visual-editing': 1.8.18(@sanity/client@6.17.2)(next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + '@sanity/visual-editing': 1.8.18(@sanity/client@6.17.2)(next@14.2.4(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) groq: 3.40.0 history: 5.3.0 - next: 14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 sanity: 3.40.0(@types/node@20.11.19)(@types/react@18.2.57)(bufferutil@4.0.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.27.2)(utf-8-validate@6.0.3) styled-components: 6.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -15879,9 +15879,9 @@ snapshots: next-tick@1.1.0: {} - next@14.2.3(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@14.2.4(@babel/core@7.24.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@next/env': 14.2.3 + '@next/env': 14.2.4 '@swc/helpers': 0.5.5 busboy: 1.6.0 caniuse-lite: 1.0.30001609 @@ -15891,15 +15891,15 @@ snapshots: react-dom: 18.3.1(react@18.3.1) styled-jsx: 5.1.1(@babel/core@7.24.4)(react@18.3.1) optionalDependencies: - '@next/swc-darwin-arm64': 14.2.3 - '@next/swc-darwin-x64': 14.2.3 - '@next/swc-linux-arm64-gnu': 14.2.3 - '@next/swc-linux-arm64-musl': 14.2.3 - '@next/swc-linux-x64-gnu': 14.2.3 - '@next/swc-linux-x64-musl': 14.2.3 - '@next/swc-win32-arm64-msvc': 14.2.3 - '@next/swc-win32-ia32-msvc': 14.2.3 - '@next/swc-win32-x64-msvc': 14.2.3 + '@next/swc-darwin-arm64': 14.2.4 + '@next/swc-darwin-x64': 14.2.4 + '@next/swc-linux-arm64-gnu': 14.2.4 + '@next/swc-linux-arm64-musl': 14.2.4 + '@next/swc-linux-x64-gnu': 14.2.4 + '@next/swc-linux-x64-musl': 14.2.4 + '@next/swc-win32-arm64-msvc': 14.2.4 + '@next/swc-win32-ia32-msvc': 14.2.4 + '@next/swc-win32-x64-msvc': 14.2.4 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros diff --git a/public/images/snippets.png b/public/images/snippets.png index f12e6aa..d2bf185 100644 Binary files a/public/images/snippets.png and b/public/images/snippets.png differ diff --git a/utils/metadata.ts b/utils/metadata.ts index 71d546a..3e04f52 100644 --- a/utils/metadata.ts +++ b/utils/metadata.ts @@ -1,17 +1,29 @@ - export const metaData = { - title: "Arkar", - siteName: "Arkar", + title: "Arkar Myat", + siteName: "Arkar Myat", description: "An inspiring engineer who loves coding, problem-solving and design", url: new URL("https://arkar.space"), - keywords: ["Next.js", "React", "JavaScript", "ArkarDev", "Arkar Myat","Arkar", "Arkar Kaung Myat"], + keywords: [ + "Next.js", + "React", + "JavaScript", + "ArkarDev", + "Arkar Myat", + "Arkar", + "Arkar Kaung Myat", + ], }; - -export const getOpenGraph = (image: string,title: string,description:string,url:URL) => ({ +export const getOpenGraph = ( + image: string, + title: string, + description: string, + url: URL, + type = "website", +) => ({ title: title, - description:description, + description: description, url: url, siteName: "ArkarDev", images: [ @@ -22,15 +34,19 @@ export const getOpenGraph = (image: string,title: string,description:string,url: }, ], locale: "en-US", - type: "website", + type: type, }); -export const getTwitterCard = (image: string,title:string,description:string) => ( { - card: 'summary_large_image', - title: title, - description:description, - siteId: '1127263021007396864', - creator: '@arkardev', - creatorId: '1127263021007396864', - images: [image], - }) +export const getTwitterCard = ( + image: string, + title: string, + description: string, +) => ({ + card: "summary_large_image", + title: title, + description: description, + siteId: "1127263021007396864", + creator: "@arkardev", + creatorId: "1127263021007396864", + images: [image], +});