Skip to content

Commit b3ae7e4

Browse files
draft: blog
1 parent 9fdae47 commit b3ae7e4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2799
-365
lines changed

apps/blog/.gitignore

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.*
7+
.yarn/*
8+
!.yarn/patches
9+
!.yarn/plugins
10+
!.yarn/releases
11+
!.yarn/versions
12+
13+
# testing
14+
/coverage
15+
16+
# next.js
17+
/.next/
18+
/out/
19+
20+
# production
21+
/build
22+
23+
# misc
24+
.DS_Store
25+
*.pem
26+
27+
# debug
28+
npm-debug.log*
29+
yarn-debug.log*
30+
yarn-error.log*
31+
.pnpm-debug.log*
32+
33+
# env files (can opt-in for committing if needed)
34+
.env*
35+
36+
# vercel
37+
.vercel
38+
39+
# typescript
40+
*.tsbuildinfo
41+
next-env.d.ts

apps/blog/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
2+
3+
## Getting Started
4+
5+
First, run the development server:
6+
7+
```bash
8+
npm run dev
9+
# or
10+
yarn dev
11+
# or
12+
pnpm dev
13+
# or
14+
bun dev
15+
```
16+
17+
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
18+
19+
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
20+
21+
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
22+
23+
## Learn More
24+
25+
To learn more about Next.js, take a look at the following resources:
26+
27+
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28+
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29+
30+
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
31+
32+
## Deploy on Vercel
33+
34+
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
35+
36+
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

apps/blog/components.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"$schema": "https://ui.shadcn.com/schema.json",
3+
"style": "default",
4+
"rsc": true,
5+
"tsx": true,
6+
"tailwind": {
7+
"config": "tailwind.config.ts",
8+
"css": "src/app/globals.css",
9+
"baseColor": "neutral",
10+
"cssVariables": true,
11+
"prefix": ""
12+
},
13+
"aliases": {
14+
"components": "@/components",
15+
"utils": "@/lib/utils",
16+
"ui": "@/components/ui",
17+
"lib": "@/lib",
18+
"hooks": "@/hooks"
19+
},
20+
"iconLibrary": "lucide"
21+
}

apps/blog/eslint.config.mjs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { dirname } from "path";
2+
import { fileURLToPath } from "url";
3+
import { FlatCompat } from "@eslint/eslintrc";
4+
5+
const __filename = fileURLToPath(import.meta.url);
6+
const __dirname = dirname(__filename);
7+
8+
const compat = new FlatCompat({
9+
baseDirectory: __dirname,
10+
});
11+
12+
const eslintConfig = [
13+
...compat.extends("next/core-web-vitals", "next/typescript"),
14+
];
15+
16+
export default eslintConfig;

apps/blog/next.config.mjs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { rewrites as getAnalyticsRewrites } from '@ds-project/services/analytics/rewrites.mjs';
2+
3+
/** @type {import('next').NextConfig} */
4+
const nextConfig = {
5+
transpilePackages: ['next-mdx-remote'],
6+
rewrites: getAnalyticsRewrites,
7+
};
8+
9+
export default nextConfig;

apps/blog/package.json

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"name": "blog",
3+
"version": "0.1.0",
4+
"private": true,
5+
"scripts": {
6+
"dev": "next dev",
7+
"build": "next build",
8+
"start": "next start",
9+
"lint": "next lint"
10+
},
11+
"dependencies": {
12+
"@ds-project/services": "workspace:*",
13+
"@radix-ui/react-slot": "^1.1.0",
14+
"@t3-oss/env-core": "catalog:",
15+
"@t3-oss/env-nextjs": "catalog:",
16+
"@tailwindcss/typography": "^0.5.15",
17+
"class-variance-authority": "^0.7.0",
18+
"clsx": "^2.1.1",
19+
"lucide-react": "^0.408.0",
20+
"next": "catalog:",
21+
"next-mdx-remote": "^5.0.0",
22+
"next-themes": "^0.4.4",
23+
"react": "catalog:",
24+
"react-dom": "catalog:",
25+
"sonner": "^1.7.2",
26+
"tailwind-merge": "^2.4.0",
27+
"tailwindcss-animate": "^1.0.7",
28+
"zod": "catalog:"
29+
},
30+
"devDependencies": {
31+
"@eslint/eslintrc": "^3",
32+
"@types/node": "catalog:",
33+
"@types/react": "catalog:",
34+
"@types/react-dom": "catalog:",
35+
"eslint": "catalog:",
36+
"eslint-config-next": "15.1.5",
37+
"postcss": "catalog:",
38+
"tailwindcss": "catalog:",
39+
"typescript": "catalog:"
40+
}
41+
}

apps/blog/postcss.config.mjs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/** @type {import('postcss-load-config').Config} */
2+
const config = {
3+
plugins: {
4+
tailwindcss: {},
5+
},
6+
};
7+
8+
export default config;

apps/blog/public/file.svg

Lines changed: 1 addition & 0 deletions
Loading

apps/blog/public/globe.svg

Lines changed: 1 addition & 0 deletions
Loading

apps/blog/public/next.svg

Lines changed: 1 addition & 0 deletions
Loading

apps/blog/public/vercel.svg

Lines changed: 1 addition & 0 deletions
Loading

apps/blog/public/window.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { getPost, getAllPosts } from '@/utils/mdx';
2+
3+
export async function generateStaticParams() {
4+
const posts = await getAllPosts();
5+
return posts.map((post) => ({
6+
slug: post.slug,
7+
}));
8+
}
9+
10+
export default async function BlogPost({
11+
params,
12+
}: {
13+
params: { slug: string };
14+
}) {
15+
const post = await getPost(params.slug);
16+
17+
return (
18+
<>
19+
<div className="mx-auto max-w-3xl">
20+
<article className="prose prose-sm sm:prose lg:prose-lg">
21+
<h1 className="mb-8 text-4xl font-bold">{post.title}</h1>
22+
<div className="text-gray-600 mb-8">
23+
{new Date(post.date).toLocaleDateString('en-US', {
24+
year: 'numeric',
25+
month: 'long',
26+
day: 'numeric',
27+
})}
28+
</div>
29+
{post.content}
30+
</article>
31+
</div>
32+
</>
33+
);
34+
}

apps/blog/src/app/favicon.ico

25.3 KB
Binary file not shown.

apps/blog/src/app/globals.css

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;
4+
5+
body {
6+
font-family: Arial, Helvetica, sans-serif;
7+
}
8+
9+
@layer base {
10+
:root {
11+
--background: 0 0% 100%;
12+
--foreground: 0 0% 3.9%;
13+
--card: 0 0% 100%;
14+
--card-foreground: 0 0% 3.9%;
15+
--popover: 0 0% 100%;
16+
--popover-foreground: 0 0% 3.9%;
17+
--primary: 0 0% 9%;
18+
--primary-foreground: 0 0% 98%;
19+
--secondary: 0 0% 96.1%;
20+
--secondary-foreground: 0 0% 9%;
21+
--muted: 0 0% 96.1%;
22+
--muted-foreground: 0 0% 45.1%;
23+
--accent: 0 0% 96.1%;
24+
--accent-foreground: 0 0% 9%;
25+
--destructive: 0 84.2% 60.2%;
26+
--destructive-foreground: 0 0% 98%;
27+
--border: 0 0% 89.8%;
28+
--input: 0 0% 89.8%;
29+
--ring: 0 0% 3.9%;
30+
--chart-1: 12 76% 61%;
31+
--chart-2: 173 58% 39%;
32+
--chart-3: 197 37% 24%;
33+
--chart-4: 43 74% 66%;
34+
--chart-5: 27 87% 67%;
35+
--radius: 0.5rem;
36+
}
37+
.dark {
38+
--background: 0 0% 3.9%;
39+
--foreground: 0 0% 98%;
40+
--card: 0 0% 3.9%;
41+
--card-foreground: 0 0% 98%;
42+
--popover: 0 0% 3.9%;
43+
--popover-foreground: 0 0% 98%;
44+
--primary: 0 0% 98%;
45+
--primary-foreground: 0 0% 9%;
46+
--secondary: 0 0% 14.9%;
47+
--secondary-foreground: 0 0% 98%;
48+
--muted: 0 0% 14.9%;
49+
--muted-foreground: 0 0% 63.9%;
50+
--accent: 0 0% 14.9%;
51+
--accent-foreground: 0 0% 98%;
52+
--destructive: 0 62.8% 30.6%;
53+
--destructive-foreground: 0 0% 98%;
54+
--border: 0 0% 14.9%;
55+
--input: 0 0% 14.9%;
56+
--ring: 0 0% 83.1%;
57+
--chart-1: 220 70% 50%;
58+
--chart-2: 160 60% 45%;
59+
--chart-3: 30 80% 55%;
60+
--chart-4: 280 65% 60%;
61+
--chart-5: 340 75% 55%;
62+
}
63+
}
64+
65+
@layer base {
66+
* {
67+
@apply border-border;
68+
}
69+
body {
70+
@apply bg-background text-foreground;
71+
}
72+
}

apps/blog/src/app/layout.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type { Metadata } from 'next';
2+
import { Fira_Sans, Fira_Mono } from 'next/font/google';
3+
import './globals.css';
4+
import { Footer } from '@/components/footer';
5+
import { Toaster } from '@/components/ui/sonner';
6+
7+
const fontSans = Fira_Sans({
8+
variable: '--font-sans',
9+
subsets: ['latin'],
10+
weight: ['400', '700'],
11+
});
12+
13+
const fontMono = Fira_Mono({
14+
variable: '--font-mono',
15+
subsets: ['latin'],
16+
weight: ['400', '700'],
17+
});
18+
19+
export const metadata: Metadata = {
20+
title: 'DS Pro Blog',
21+
description: 'Insights about Design Systems and Frontend Development',
22+
};
23+
24+
export default function RootLayout({
25+
children,
26+
}: Readonly<{
27+
children: React.ReactNode;
28+
}>) {
29+
return (
30+
<html lang="en">
31+
<body
32+
className={`${fontSans.variable} ${fontMono.variable} antialiased font-[family-name:var(--font-sans)]`}
33+
>
34+
<main className="mx-auto max-w-2xl px-4 py-16">{children}</main>
35+
<Footer />
36+
<Toaster />
37+
</body>
38+
</html>
39+
);
40+
}

apps/blog/src/app/page.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Bio } from '@/components/bio';
2+
import { BlogPosts } from '@/components/blog-posts';
3+
import { Newsletter } from '@/components/newsletter';
4+
import { SocialLinks } from '@/components/social-links';
5+
6+
export default function Home() {
7+
return (
8+
<>
9+
<h1 className="mb-8 text-3xl font-bold">DS Pro</h1>
10+
<Bio />
11+
<BlogPosts />
12+
<Newsletter />
13+
<SocialLinks />
14+
</>
15+
);
16+
}

apps/blog/src/app/subscribe.action.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use server';
2+
3+
import { serverEnv } from '@/env/server-env';
4+
5+
export async function subscribeToNewsletter(formData: FormData) {
6+
const email = formData.get('email');
7+
8+
const { ok } = await fetch('https://api.useplunk.com/v1/track', {
9+
method: 'POST',
10+
headers: {
11+
'Content-Type': 'application/json',
12+
Authorization: `Bearer ${serverEnv.PLUNK_API_KEY}`,
13+
},
14+
body: JSON.stringify({
15+
event: 'subscribed',
16+
email,
17+
subscribed: false,
18+
}),
19+
});
20+
21+
if (!ok) {
22+
return {
23+
success: false,
24+
message: 'Something went wrong. Please try again.',
25+
};
26+
}
27+
28+
// This is where you'd typically integrate with your email service
29+
// For now, we'll just return a success message
30+
return {
31+
success: true,
32+
message:
33+
'Thanks for subscribing! Check your email to confirm your subscription.',
34+
};
35+
}

0 commit comments

Comments
 (0)