Files
portfolio/README.md
cojocaru-david 0c90442415 feat: add post feedback system with like/dislike functionality
feat: implement fingerprint-based voting to prevent duplicate votes
feat: add database setup documentation for likes/dislikes feature
feat: update social icons styling for better mobile responsiveness
feat: add node adapter for standalone server deployment
chore: update dependencies including astro and fingerprintjs
fix: move social icons to top of footer for better visibility
refactor: clean up meta tags in PostHead component
docs: add comprehensive database schema and API documentation

feat(components): add BuyMeCoffee component with animated SVG and hover effects

feat(components): implement BuyMeCoffee donation link with styling and animations

feat(components): create BuyMeCoffee component with responsive design and interactive elements

style: update SVG paths with fill-background class for consistent styling

style: update SVG paths and styling for better visual consistency and hover effects

style: update BuyMeCoffee component with new SVG animations and styling

feat: add hover animations and transitions to BuyMeCoffee component

refactor: reorganize SVG paths and groups in BuyMeCoffee component for better readability

The changes include:
- Adding new SVG animations and styling for the BuyMeCoffee component
- Implementing hover animations and transitions to enhance user interaction
- Refactoring the SVG structure for improved code organization and maintainability

These changes were made to improve the visual appeal and user experience of the BuyMeCoffee component while keeping the codebase clean and maintainable.

refactor(navbar): simplify class names and remove unused comments
feat(navbar): add dark mode text color support and improve mobile menu styling
feat(navbar): enhance footer with copyright, separator, and open-source link
refactor(navbar): streamline mobile menu button styling and transitions

refactor(consts): update social links and icon map
feat(consts): add Instagram and Phone social links
chore(consts): remove LinkedIn and update icon mappings

chore(blog): remove outdated blog posts
feat(blog): clean up content directory by deleting irrelevant posts

chore(content): remove outdated blog posts

The commit removes a large number of outdated blog posts that were no longer relevant or aligned with the current content strategy. This cleanup helps maintain a more focused and up-to-date blog section.

chore: remove outdated blog posts and clean up content directory

Delete multiple outdated blog post files to streamline the content directory and improve maintainability. The removed posts were no longer relevant and cluttered the repository. This cleanup helps focus on current and future content.

chore: remove outdated blog posts and related content

The commit removes a large number of outdated blog posts and related content from the repository. These files were no longer relevant or maintained, and their removal helps clean up the codebase and reduce clutter. The changes include deleting various markdown files under the `src/content/blog/` directory that covered topics like cybersecurity, data analytics, cloud computing, and cryptocurrency regulation. This cleanup aligns with the project's goal to maintain only current and relevant content.

chore(content): remove outdated blog posts

The commit removes a large number of outdated blog posts that were no longer relevant or aligned with the current content strategy. This cleanup helps maintain a focused and up-to-date content repository.

chore: remove outdated blog content

Deleted multiple outdated blog posts to clean up the repository and remove irrelevant content. The posts were no longer aligned with the current focus and direction of the project. This cleanup helps maintain a more organized and relevant codebase.

chore(content): remove outdated blog posts

Deleted multiple outdated blog posts covering various tech topics including development, startups, and certifications. The content was no longer relevant or aligned with current best practices. This cleanup helps maintain a focused and up-to-date content repository.

chore: remove outdated blog posts

The diff shows the deletion of multiple blog post files that appear to be outdated or no longer relevant. This cleanup will help maintain content quality and relevance on the site.

chore(content): remove outdated and irrelevant blog posts

This commit removes a large number of blog posts that were either outdated, irrelevant, or of low quality. The removed posts covered a wide range of topics including quantum computing, machine learning, cloud computing, and various technical tutorials. Many of these posts were auto-generated or contained generic content that didn't provide real value to readers.

The removal of these posts helps:
- Improve overall content quality
- Reduce maintenance burden
- Focus on more relevant and valuable content
- Clean up the repository structure

No existing links or references to these posts were being maintained, so their removal shouldn't impact users. This cleanup aligns with our goal of maintaining a focused, high-quality content repository.

chore(content): remove outdated blog posts

The commit removes a large number of outdated blog posts that were no longer relevant or maintained. This cleanup helps keep the content fresh and focused on current topics.

chore(content): remove outdated blog posts

The commit removes a large number of outdated blog post files that were no longer relevant or needed. This cleanup helps declutter the content directory and removes potentially stale or incorrect information. The files deleted covered a wide range of tech-related topics but were determined to be no longer useful for the current site.

chore(content): remove outdated blog posts

Deleted multiple outdated blog posts covering various tech topics including AI, edge computing, blockchain, and sustainability. These posts were no longer relevant or accurate given recent advancements in technology. The removal helps maintain content quality and ensures readers only access up-to-date information.

chore(content): remove all blog posts to clean up repository

This commit removes all existing blog post content files from the repository. The files were deleted to clean up the content directory and prepare for new content to be added in the future. The removal includes a wide range of blog posts covering various tech topics, indicating a complete content refresh is planned.

chore(content): remove outdated blog posts and articles

The commit removes a large number of outdated blog posts and articles from the content directory. These files were likely stale content that was no longer relevant or useful. The removal helps clean up the repository and maintain only current, valuable content.

 *::before,
   *::after {
     @apply border-border;
   }
+
   body {
     @apply bg-background text-foreground font-sans;
     font-feature-settings:
       'rlig' 1,
       'calt' 1;
   }
+
   h1,
   h2,
   h3,
   h4,
   h5,
   h6 {
-    @apply font-custom;
+    @apply font-custom scroll-mt-20;
   }
+
+  h1 {
+    @apply text-4xl font-bold;
+  }
+
+  h2 {
+    @apply text-3xl font-bold;
+  }
+
+  h3 {
+    @apply text-2xl font-bold;
+  }
+
+  h4 {
+    @apply text-xl font-bold;
+  }
+
+  h5 {
+    @apply text-lg font-bold;
+  }
+
+  h6 {
+    @apply text-base font-bold;
+  }
+
+  p {
+    @apply text-base;
+  }
+
+  a {
+    @apply text-primary hover:text-primary-foreground transition-colors;
+  }
+
+  code {
+    @apply font-mono text-sm bg-muted px-1 py-0.5 rounded;
+  }
+
+  pre {
+    @apply font-mono text-sm bg-muted p-4 rounded overflow-x-auto;
+  }
+
+  blockquote {
+    @apply border-l-4 border-primary pl-4 italic;
+  }
+
+  ul {
+    @apply list-disc pl-5;
+  }
+
+  ol {
+    @apply list-decimal pl-5;
+  }
+
+  li {
+    @apply mb-1;
+  }
+
+  table {
+    @apply w-full border-collapse;
+  }
+
+  th {
+    @apply bg-muted text-left p-2 border;
+  }
+
+  td {
+    @apply p-2 border;
+  }
+
+  img {
+    @apply max-w-full h-auto;
+  }
+
+  hr {
+    @apply border-t border-border my-4;
+  }
 }
2025-05-01 01:40:16 +03:00

270 lines
9.3 KiB
Markdown

# Developer Portfolio & Blog
![Astro](https://img.shields.io/badge/Astro-FF5D01?style=for-the-badge&logo=astro&logoColor=white)
![React](https://img.shields.io/badge/React-20232A?style=for-the-badge&logo=react&logoColor=61DAFB)
![TailwindCSS](https://img.shields.io/badge/Tailwind_CSS-38B2AC?style=for-the-badge&logo=tailwind-css&logoColor=white)
![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white)
A modern, high-performance personal portfolio and blog built with Astro.js. Designed to showcase your projects and technical writing with blazing-fast performance and exceptional SEO.
## ✨ Features
- 🚀 **Blazing fast performance** - Built with Astro.js for optimal loading speeds
- 📝 **Full-featured blog** - Support for technical articles with code highlighting
- 🎨 **Beautiful UI** - Modern, responsive design powered by Tailwind CSS
- 🌙 **Dark mode support** - Seamless light/dark theme switching
- 📱 **Fully responsive** - Looks great on all devices from mobile to desktop
- 🔍 **SEO optimized** - Structured data, meta tags, and optimized for search engines
- 🏷️ **Tag system** - Categorize blog posts and projects with tags
- 📊 **Content collection** - Organized content management with Astro's content collections
- 🖼️ **Project showcase** - Display your work with images, descriptions, and technology tags
## 🛠️ Tech Stack
- **[Astro.js](https://astro.build/)** - Static site generator with excellent performance
- **[React.js](https://reactjs.org/)** - For interactive components
- **[Tailwind CSS](https://tailwindcss.com/)** - Utility-first CSS framework
- **[TypeScript](https://www.typescriptlang.org/)** - Type safety and improved developer experience
- **[MDX](https://mdxjs.com/)** - Markdown with JSX for rich content creation
- **[Preact](https://preactjs.com/)** - Lightweight alternative to React for UI components
## 📋 Prerequisites
Before you begin, ensure you have the following installed:
- [Node.js](https://nodejs.org/) (v18 or higher)
- [npm](https://www.npmjs.com/) or [yarn](https://yarnpkg.com/)
- [Git](https://git-scm.com/)
## ⚙️ Installation & Setup
1. **Clone the repository**
```bash
git clone https://github.com/cojocaru-david/portfolio.git
cd portfolio
```
2. **Install dependencies**
```bash
npm install
# or
yarn install
```
3. **Start the development server**
```bash
npm run dev
# or
yarn dev
```
4. **Open your browser**
Navigate to `http://localhost:4321` to see the site running locally.
## 📁 Project Structure
```
portfolio/
├── public/ # Static assets
├── src/
│ ├── components/ # UI components
│ ├── content/ # Content collections
│ │ ├── blog/ # Blog posts in MD/MDX format
│ │ └── projects/ # Project data
│ ├── layouts/ # Page layouts
│ ├── lib/ # Utility functions
│ ├── pages/ # Page routes
│ └── styles/ # Global styles
├── astro.config.mjs # Astro configuration
├── tailwind.config.cjs # Tailwind CSS configuration
├── tsconfig.json # TypeScript configuration
└── package.json # Project dependencies
```
## 🚀 Usage
### Creating a Blog Post
1. Create a new `.mdx` or `.md` file in `src/content/blog`
2. Add frontmatter with title, description, date, tags, and authors
3. Write your content using Markdown and MDX components
```mdx
---
title: "Your Post Title"
description: "A brief description of your post"
date: 2025-04-20
tags: ["tag1", "tag2", "tag3"]
authors: ["Your Name", "Co-author (optional)"]
---
# Your Post Title
Write your content here using Markdown.
## Subheading
More content...
```
### Adding a Project
1. Create a new `.md` file in projects
2. Add project details including name, description, tags, and image path
## 🌙 Dark Mode
The project includes dark mode support using Tailwind CSS and Preact. It detects user preferences and applies the appropriate theme, with an option to toggle between light and dark modes.
## 📊 Data Utilities
The project includes several utility functions in data-utils.ts:
- `getAllPosts()` - Retrieve all blog posts
- `getRecentPosts(count)` - Get the most recent posts
- `getAdjacentPosts(currentId)` - Get next and previous posts
- `getAllTags()` - Get all tags used in posts
- `getSortedTags()` - Get tags sorted by usage count
- `getPostsByAuthor(authorId)` - Get all posts by a specific author
## 📊 Database Setup (Likes/Dislikes Feature)
The portfolio includes a post feedback system allowing visitors to like or dislike blog posts. This feature requires a PostgreSQL database to store vote data. This guide explains how to set it up using [Neon.tech](https://neon.tech).
### Setting Up Neon.tech Database
1. **Create a Neon.tech Account**
- Go to [Neon.tech](https://neon.tech) and sign up for an account
- Neon offers a generous free tier suitable for personal portfolio sites
2. **Create a New Project**
- From the Neon dashboard, click "New Project"
- Choose a name for your project (e.g., "portfolio-feedback")
- Select the closest region to your target audience
- Click "Create Project"
3. **Get Connection Details**
- In your project dashboard, find the connection string under "Connection Details"
- Save this connection string as you'll need it for your environment variables
4. **Set Environment Variables**
- Create a `.env` file in your project root (if not already present)
- Add your database connection string:
```
DATABASE_URL=your_neon_connection_string_here
```
### Database Schema Setup
Run the following SQL queries in the Neon SQL Editor to create the necessary tables for the feedback system:
```sql
CREATE TABLE post_feedback (
id SERIAL PRIMARY KEY,
post_id VARCHAR(255) NOT NULL,
likes INTEGER DEFAULT 0,
dislikes INTEGER DEFAULT 0,
CONSTRAINT unique_post_id UNIQUE (post_id)
);
CREATE TABLE post_likes (
id SERIAL PRIMARY KEY,
post_id VARCHAR(255) NOT NULL,
fingerprint_id VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT unique_like UNIQUE (post_id, fingerprint_id)
);
CREATE TABLE post_dislikes (
id SERIAL PRIMARY KEY,
post_id VARCHAR(255) NOT NULL,
fingerprint_id VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT unique_dislike UNIQUE (post_id, fingerprint_id)
);
CREATE INDEX idx_post_feedback_post_id ON post_feedback (post_id);
CREATE INDEX idx_post_likes_post_id_fingerprint ON post_likes (post_id, fingerprint_id);
CREATE INDEX idx_post_dislikes_post_id_fingerprint ON post_dislikes (post_id, fingerprint_id);
```
### How the Feedback System Works
The feedback system consists of three tables:
- `post_feedback`: Stores aggregate counts of likes and dislikes for each post
- `post_likes`: Records individual like actions with fingerprint IDs to prevent duplicate votes
- `post_dislikes`: Records individual dislike actions with fingerprint IDs
### API Implementation
The portfolio includes API endpoints for handling likes and dislikes:
1. **Fetching Post Feedback**
- GET request to `/api/like/{postId}` returns current like/dislike counts
2. **Submitting Likes**
- POST request to `/api/like/{postId}` with fingerprint ID in the request body
- The system checks if the user has already liked/disliked the post
- If not, a like is recorded and the count is updated
3. **Submitting Dislikes**
- POST request to `/api/dislike/{postId}` works similarly to the like endpoint
- Prevents duplicate votes from the same visitor
### Working with the Database
When a new blog post is created:
- No manual database entry is needed
- The first like/dislike action will automatically create the entry in `post_feedback`
To reset likes for a post:
```sql
DELETE FROM post_likes WHERE post_id = 'your-post-id';
DELETE FROM post_dislikes WHERE post_id = 'your-post-id';
UPDATE post_feedback SET likes = 0, dislikes = 0 WHERE post_id = 'your-post-id';
```
To view post statistics:
```sql
SELECT * FROM post_feedback ORDER BY likes DESC;
```
To find which posts a specific user has interacted with:
```sql
SELECT post_id FROM post_likes WHERE fingerprint_id = 'specific-fingerprint-id';
```
### Troubleshooting
If you encounter issues with the feedback system:
1. **Check Environment Variables**
- Ensure your `.env` file contains the correct `DATABASE_URL`
2. **Verify Database Connection**
- Add logging to your database connection code to check for errors
- Make sure your Neon.tech project is active and not in suspended state
3. **Check for Errors in Console**
- The feedback component logs errors that can help diagnose issues
4. **Reset User Vote State**
- Users can clear their localStorage to reset their voting state:
```javascript
// In browser console
localStorage.clear()
```
## 🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## 📄 License
This project is licensed under the MIT License - see the LICENSE file for details.