Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Blog #21

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 72 additions & 6 deletions apps/mkt/app/(default)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,83 @@
import "../css/style.css";

import { Inter, Inter_Tight } from "next/font/google";
import dynamic, { Loader } from "next/dynamic";
import Script from "next/script";
import { Metadata } from "next";
import Header from "@/components/ui/header";
import Footer from "@/components/ui/footer";

export default function DefaultLayout({
const inter = Inter({
subsets: ["latin"],
variable: "--font-inter",
display: "swap",
});

const inter_tight = Inter_Tight({
weight: ["500", "600", "700"],
style: ["normal", "italic"],
subsets: ["latin"],
variable: "--font-inter-tight",
display: "swap",
});

export const metadata: Metadata = {
title: "sweetr.dev",
description:
"The dev-first platform for continuous improvement. Enable your software engineering teams to optimize and speed up development while improving developer experience.",
openGraph: {
title: "Sweetr - The dev-first platform for continuous improvement",
description:
"Enable your software engineering teams to optimize and speed up development while improving developer experience. Self-host for free or try a 14-day trial.",
url: "https://sweetr.dev",
siteName: "sweetr.dev",
images: [
{
url: "https://sweetr.dev/images/og-image.png",
width: 1200,
height: 630,
alt: "sweetr.dev",
},
],
locale: "en_US",
type: "website",
},
twitter: {
card: "summary_large_image",
title: "sweetr.dev",
description: "The dev-first platform for continuous improvement",
images: ["https://sweetr.dev/images/og-image.png"],
},
};

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const CrispChat = dynamic(() => import("../../components/crisp-chat"));
const analyticsId = process.env.NEXT_PUBLIC_ANALYTICS_ID;

return (
<>
<Header />
<html lang="en">
{analyticsId && (
<Script
async
src="https://analytics.umami.is/script.js"
data-website-id={analyticsId}
/>
)}
<CrispChat />
<body
className={`${inter.variable} ${inter_tight.variable} font-inter antialiased bg-white text-zinc-900 tracking-tight`}
>
<div className="flex flex-col min-h-screen overflow-hidden supports-[overflow:clip]:overflow-clip">
<Header />

<main className="grow">{children}</main>
<Footer />
</>
<main className="grow">{children}</main>
<Footer />
</div>
</body>
</html>
);
}
3 changes: 3 additions & 0 deletions apps/mkt/app/blog/(posts)/test/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Test() {
return <div>Test</div>;
}
3 changes: 3 additions & 0 deletions apps/mkt/app/blog/(posts)/welcome/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Welcome to my MDX page!

This is some **bold** and _italics_ text.
101 changes: 101 additions & 0 deletions apps/mkt/app/blog/components/category-nav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"use client";

import {
IconUsersGroup,
IconHeartCode,
IconRocket,
IconCompass,
IconBoxMultiple,
IconCode,
} from "@tabler/icons-react";
import Link from "next/link";
import { useSearchParams } from "next/navigation";
import React, { useEffect } from "react";

export const CategoryNav = () => {
const [selectedCategory, setSelectedCategory] = React.useState<string>("");

const searchParams = useSearchParams();

useEffect(() => {
setSelectedCategory(searchParams.get("category") || "");
}, [searchParams]);

return (
<div className="mt-8 bg-dark-800 p-1 flex w-fit mx-auto text-dark-100 gap-3 border border-dark-400 rounded-md flex-wrap justify-center">
<CategoryNavItem
category=""
active={selectedCategory === ""}
icon={IconBoxMultiple}
>
All
</CategoryNavItem>
<CategoryNavItem
category="leadership"
active={selectedCategory === "leadership"}
icon={IconCompass}
>
Leadership
</CategoryNavItem>
<CategoryNavItem
category="culture"
active={selectedCategory === "culture"}
icon={IconUsersGroup}
>
Culture
</CategoryNavItem>
<CategoryNavItem
category="performance"
active={selectedCategory === "performance"}
icon={IconRocket}
>
Performance
</CategoryNavItem>
<CategoryNavItem
category="developer-experience"
active={selectedCategory === "developer-experience"}
icon={IconHeartCode}
>
Developer Experience
</CategoryNavItem>
<CategoryNavItem
category="tech"
active={selectedCategory === "tech"}
icon={IconCode}
>
Tech
</CategoryNavItem>
</div>
);
};

interface CategoryNavItemProps extends React.HTMLAttributes<HTMLDivElement> {
active: boolean;
icon: React.ComponentType<{
stroke: number;
size: number;
}>;
category: string;
}

const CategoryNavItem = ({
children,
icon: Icon,
active,
category,
...props
}: CategoryNavItemProps) => {
return (
<Link href={category ? `?category=${category}` : "/blog"} scroll={false}>
<div
{...props}
className={`font-medium hover:text-green-400 transition-all p-2 rounded-md cursor-pointer ${active ? "bg-green-400/10 text-green-400 " : "hover:scale-105 "}`}
>
<div className="flex items-center justify-between gap-2">
<Icon size={20} stroke={1.5} />
{children}
</div>
</div>
</Link>
);
};
44 changes: 44 additions & 0 deletions apps/mkt/app/blog/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Header from "@/components/ui/header";
import "../css/style.css";
import Footer from "@/components/ui/footer";
import { Inter, Inter_Tight } from "next/font/google";

const inter = Inter({
subsets: ["latin"],
variable: "--font-inter",
display: "swap",
});

const inter_tight = Inter_Tight({
weight: ["500", "600", "700"],
style: ["normal", "italic"],
subsets: ["latin"],
variable: "--font-inter-tight",
display: "swap",
});

export const metadata = {
title: "Sweetr Blog",
description: "How to improve engineering teams",
};

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body
className={`${inter.variable} ${inter_tight.variable} bg-dark-800 font-inter antialiased text-zinc-900 tracking-tight`}
>
<div className="flex flex-col min-h-screen overflow-hidden supports-[overflow:clip]:overflow-clip">
<Header />

<main className="grow pt-[56px]">{children}</main>
<Footer />
</div>
</body>
</html>
);
}
108 changes: 108 additions & 0 deletions apps/mkt/app/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { IconRobot, IconRobotFace } from "@tabler/icons-react";
import { CategoryNav } from "./components/category-nav";
import { NextRequest } from "next/server";

export default function Blog() {
return (
<div
style={{
backgroundImage: `
linear-gradient(to bottom,
#141517 0%,
#141517 30%,
rgba(20, 21, 23, 0.7) 40%,
rgba(20, 21, 23, 0.4) 60%,
rgba(20, 21, 23, 0.1) 80%,
transparent 100%
),
url('/images/blog/bg.svg')
`,
Comment on lines +9 to +19
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds a gradient on top of the image to give a vignette effect.

backgroundRepeat: "no-repeat",
backgroundSize: "cover",
backgroundPosition: "top center",
backgroundAttachment: "fixed",
}}
>
<div className="max-w-6xl mx-auto px-4 sm:px-6 md:px-0">
<div className="pt-20 text-center">
<h1 className="text-white text-4xl font-bold">
The Sweetr <span className="text-green-400">Blog</span>
</h1>
<p className="text-dark-100 text-lg mt-4">
Read our latest articles and insights on how to improve your
engineering organization.
</p>
</div>

<CategoryNav />

<div className="pt-16 pb-32 grid grid-cols-1 gap-6">
{/* Placeholder content for the grid items */}
{[...Array(3)].map((_, index) => (
<a
href="#"
key={index}
className="hover:scale-105 transition-all border border-dark-400 rounded-md bg-dark-800 mx-auto"
>
<div className="p-4 flex flex-row justify-between items-center gap-12 flex-wrap">
<div>
<div className="relative w-full md:w-[400px]">
<img
src="https://images.pexels.com/photos/3183153/pexels-photo-3183153.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
className="rounded w-full h-full object-cover"
alt="Blog post image"
/>
<div
className="absolute inset-0 rounded"
style={{
backgroundImage: `
radial-gradient(
circle at center,
rgba(0, 0, 0, 0) 0%,
rgba(0, 0, 0, 0.3) 70%,
rgba(0, 0, 0, 0.7) 100%
)
`,
}}
></div>
</div>
</div>

<div className="max-w-[400px]">
<div className="flex items-center gap-2">
<div className="bg-dark-800 text-green-400 text-sm font-semibold uppercase tracking-[3px]">
Leadership
</div>
</div>
<h3 className="text-zinc-300 text-lg font-semibold mt-4">
Lorem Ipsum is simply dummy text of the printing and
typesetting
</h3>
<div className="text-dark-100 text-sm mt-2 line-clamp-3">
Lorem Ipsum is simply dummy text of the printing and
typesetting industry. Lorem Ipsum has been the industry's
standard dummy text ever since the 1500s, when an unknown
printer took a galley of type and scrambled it to make a
type specimen book.
</div>
<div className="flex mt-6 items-center gap-2">
<img
src="https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png?20150327203541"
className="rounded-full"
height={48}
width={48}
/>
<div className="flex flex-col text-zinc-400 font-semibold">
<div className="text-sm">Walter Galvão</div>
<div className="text-xs">September 14th, 2024</div>
</div>
</div>
</div>
</div>
</a>
))}
</div>
</div>
</div>
);
}
Loading