Files
HomeVibes/lib/api.ts
2025-05-06 23:09:47 +02:00

584 lines
13 KiB
TypeScript

"use client"
import fs from "fs"
import path from "path"
import matter from "gray-matter"
const postsDirectory = path.join(process.cwd(), "posts")
export interface PostMetadata {
title: string
date: string
excerpt: string
[key: string]: any
}
export interface Post {
slug: string
content: string
metadata: PostMetadata
}
// Create posts directory if it doesn't exist
try {
if (!fs.existsSync(postsDirectory)) {
fs.mkdirSync(postsDirectory, { recursive: true })
createSamplePosts()
}
} catch (error) {
console.error("Error checking or creating posts directory:", error)
}
// Changed to synchronous to avoid suspense issues
export function getAllPosts(): Post[] {
try {
const filenames = fs.readdirSync(postsDirectory)
const posts = filenames
.filter((filename) => filename.endsWith(".md"))
.map((filename) => {
const slug = filename.replace(/\.md$/, "")
const fullPath = path.join(postsDirectory, filename)
const fileContents = fs.readFileSync(fullPath, "utf8")
const { data, content } = matter(fileContents)
return {
slug,
content,
metadata: data as PostMetadata,
}
})
return posts
} catch (error) {
console.error("Error getting all posts:", error)
return []
}
}
// Changed to synchronous to avoid suspense issues
export function getPostBySlug(slug: string): Post | null {
try {
const fullPath = path.join(postsDirectory, `${slug}.md`)
const fileContents = fs.readFileSync(fullPath, "utf8")
const { data, content } = matter(fileContents)
return {
slug,
content,
metadata: data as PostMetadata,
}
} catch (error) {
console.error(`Error getting post by slug ${slug}:`, error)
return null
}
}
function createSamplePosts() {
const samplePosts = [
{
filename: "getting-started-with-nextjs.md",
content: `---
title: "Getting Started with Next.js"
date: "2023-05-15"
excerpt: "Learn how to build modern web applications with Next.js"
---
# Getting Started with Next.js
Next.js is a React framework that enables functionality such as server-side rendering and static site generation.
## Why Next.js?
- **Server-side Rendering**: Improves performance and SEO
- **Static Site Generation**: Pre-renders pages at build time
- **API Routes**: Build API endpoints as part of your Next.js app
- **File-based Routing**: Create routes based on your file structure
## Getting Started
To create a new Next.js app, run:
\`\`\`bash
npx create-next-app@latest my-app
\`\`\`
This will set up everything automatically for you.`,
},
{
filename: "markdown-styling-guide.md",
content: `---
title: "Markdown Styling Guide"
date: "2023-06-22"
excerpt: "Learn how to style your markdown content for better readability"
---
# Markdown Styling Guide
Markdown is a lightweight markup language that you can use to add formatting elements to plaintext text documents.
## Basic Syntax
### Headers
# H1
## H2
### H3
### Emphasis
*This text will be italic*
_This will also be italic_
**This text will be bold**
__This will also be bold__
### Lists
Unordered:
- Item 1
- Item 2
- Item 2a
- Item 2b
Ordered:
1. Item 1
2. Item 2
3. Item 3
### Links
[GitHub](http://github.com)
### Images
![Alt Text](https://via.placeholder.com/150)
### Code
Inline \`code\` has \`back-ticks around\` it.
\`\`\`javascript
var s = "JavaScript syntax highlighting";
alert(s);
\`\`\``,
},
{
filename: "building-accessible-websites.md",
content: `---
title: "Building Accessible Websites"
date: "2023-07-10"
excerpt: "Learn how to make your websites accessible to everyone"
---
# Building Accessible Websites
Web accessibility means that websites, tools, and technologies are designed and developed so that people with disabilities can use them.
## Why Accessibility Matters
- **Inclusivity**: Everyone should be able to access and use web content
- **Legal Requirements**: Many countries have laws requiring web accessibility
- **Better UX**: Accessible sites often provide better user experience for everyone
- **SEO Benefits**: Many accessibility practices improve SEO
## Key Accessibility Practices
### Semantic HTML
Use the right HTML elements for their intended purpose:
\`\`\`html
<!-- Bad -->
<div class="button" onclick="submit()">Submit</div>
<!-- Good -->
<button onclick="submit()">Submit</button>
\`\`\`
### Keyboard Navigation
Ensure all interactive elements are keyboard accessible:
- Use proper focus states
- Maintain a logical tab order
- Provide skip links
### Alternative Text
Always provide alt text for images:
\`\`\`html
<img src="chart.png" alt="Bar chart showing sales data for Q1 2023">
\`\`\``,
},
// Adding 5 more dummy posts
{
filename: "modern-css-techniques.md",
content: `---
title: "Modern CSS Techniques for 2023"
date: "2023-08-05"
excerpt: "Explore the latest CSS features and techniques that are changing web development"
---
# Modern CSS Techniques for 2023
CSS has evolved significantly in recent years, with powerful new features that make complex layouts and effects easier than ever.
## CSS Grid
CSS Grid has revolutionized web layouts:
\`\`\`css
.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1rem;
}
\`\`\`
## CSS Custom Properties (Variables)
Variables make your CSS more maintainable:
\`\`\`css
:root {
--primary-color: #3490dc;
--secondary-color: #ffed4a;
}
.button {
background-color: var(--primary-color);
}
\`\`\`
## Container Queries
Container queries allow you to style elements based on their parent container's size:
\`\`\`css
@container (min-width: 700px) {
.card {
display: grid;
grid-template-columns: 2fr 1fr;
}
}
\`\`\`
## Logical Properties
Logical properties make internationalization easier:
\`\`\`css
.element {
margin-inline: 1rem;
padding-block: 0.5rem;
}
\`\`\`
## Conclusion
Modern CSS is more powerful than ever, enabling developers to create complex layouts and effects with less code and greater flexibility.`,
},
{
filename: "typescript-best-practices.md",
content: `---
title: "TypeScript Best Practices for Large Projects"
date: "2023-08-12"
excerpt: "Learn how to effectively use TypeScript in large-scale applications"
---
# TypeScript Best Practices for Large Projects
TypeScript has become the standard for large-scale JavaScript applications. Here are some best practices to keep your codebase maintainable.
## Type Everything
Always define types for your data structures:
\`\`\`typescript
interface User {
id: string;
name: string;
email: string;
role: 'admin' | 'user' | 'guest';
preferences?: UserPreferences;
}
// Instead of:
// const user = { id: '123', name: 'John' };
\`\`\`
## Use Discriminated Unions
Discriminated unions make your code more type-safe:
\`\`\`typescript
type Success = {
status: 'success';
data: User[];
};
type Error = {
status: 'error';
message: string;
};
type ApiResponse = Success | Error;
function handleResponse(response: ApiResponse) {
if (response.status === 'success') {
// TypeScript knows response.data exists
return response.data;
} else {
// TypeScript knows response.message exists
throw new Error(response.message);
}
}
\`\`\`
## Avoid Any
The \`any\` type defeats the purpose of TypeScript. Use \`unknown\` instead when necessary:
\`\`\`typescript
// Bad
function parseData(data: any) {
return data.items;
}
// Good
function parseData(data: unknown) {
if (typeof data === 'object' && data !== null && 'items' in data) {
return (data as { items: unknown[] }).items;
}
throw new Error('Invalid data format');
}
\`\`\`
## Conclusion
Following these best practices will help you build more maintainable and robust TypeScript applications.`,
},
{
filename: "serverless-architecture.md",
content: `---
title: "Introduction to Serverless Architecture"
date: "2023-08-20"
excerpt: "Understand the benefits and challenges of serverless computing"
---
# Introduction to Serverless Architecture
Serverless computing allows developers to build and run applications without thinking about servers.
## What is Serverless?
Despite the name, serverless doesn't mean there are no servers. It means you don't have to manage them:
- No provisioning servers
- No worrying about scaling
- Pay only for what you use
- Focus on code, not infrastructure
## Key Serverless Services
### AWS Lambda
\`\`\`javascript
exports.handler = async (event) => {
const result = await processData(event.data);
return {
statusCode: 200,
body: JSON.stringify(result)
};
};
\`\`\`
### Azure Functions
\`\`\`javascript
module.exports = async function (context, req) {
const result = await processData(req.body);
context.res = {
status: 200,
body: result
};
};
\`\`\`
## Challenges
Serverless isn't perfect for every use case:
- Cold starts can impact performance
- Long-running processes aren't ideal
- Debugging can be more difficult
- Vendor lock-in concerns
## Conclusion
Serverless architecture can significantly reduce operational complexity and cost for many applications, but it's important to understand its limitations and use cases.`,
},
{
filename: "react-performance-optimization.md",
content: `---
title: "React Performance Optimization Techniques"
date: "2023-08-25"
excerpt: "Learn how to make your React applications faster and more efficient"
---
# React Performance Optimization Techniques
Performance optimization is crucial for providing a good user experience in React applications.
## Use React.memo for Component Memoization
Prevent unnecessary re-renders with React.memo:
\`\`\`jsx
const ExpensiveComponent = React.memo(({ data }) => {
// Render using data
return <div>{/* ... */}</div>;
});
\`\`\`
## Virtualize Long Lists
Use virtualization for long lists:
\`\`\`jsx
import { FixedSizeList } from 'react-window';
function VirtualizedList({ items }) {
const Row = ({ index, style }) => (
<div style={style}>
{items[index].name}
</div>
);
return (
<FixedSizeList
height={500}
width={300}
itemCount={items.length}
itemSize={35}
>
{Row}
</FixedSizeList>
);
}
\`\`\`
## Code Splitting
Split your code to load only what's needed:
\`\`\`jsx
import React, { Suspense, lazy } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
);
}
\`\`\`
## Avoid Inline Functions in Renders
Inline functions cause unnecessary re-renders:
\`\`\`jsx
// Bad
return <button onClick={() => handleClick(id)}>Click me</button>;
// Good
const handleButtonClick = useCallback(() => {
handleClick(id);
}, [id, handleClick]);
return <button onClick={handleButtonClick}>Click me</button>;
\`\`\`
## Conclusion
By implementing these optimization techniques, you can significantly improve the performance of your React applications.`,
},
{
filename: "docker-for-developers.md",
content: `---
title: "Docker for Frontend Developers"
date: "2023-09-01"
excerpt: "A practical guide to using Docker in frontend development workflows"
---
# Docker for Frontend Developers
Docker can streamline your frontend development workflow and ensure consistency across environments.
## Why Use Docker for Frontend?
- **Consistency**: Same environment for all developers
- **Isolation**: Dependencies don't conflict with your system
- **CI/CD Integration**: Easier testing and deployment
- **Microservices**: Better for modern architecture
## Basic Dockerfile for a React App
\`\`\`dockerfile
# Build stage
FROM node:16-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Production stage
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
\`\`\`
## Docker Compose for Development
\`\`\`yaml
version: '3'
services:
frontend:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- ./src:/app/src
ports:
- "3000:3000"
environment:
- NODE_ENV=development
\`\`\`
## Tips for Frontend Docker Setups
1. Use multi-stage builds to keep images small
2. Mount volumes for hot reloading in development
3. Consider using Docker for your API during development
4. Use environment variables for configuration
## Conclusion
Docker can significantly improve your frontend development workflow, especially for complex applications or teams with multiple developers.`,
},
]
samplePosts.forEach((post) => {
fs.writeFileSync(path.join(postsDirectory, post.filename), post.content)
})
}