feat: add Dream Home Template project and improve SEO

feat: improve recent posts to show random posts

refactor: improve image sizes for project details page

chore(package.json): upgrade dependencies
This commit is contained in:
cojocaru-david
2025-05-29 15:24:12 +03:00
parent e22d9296e9
commit 5e0055ab69
7 changed files with 674 additions and 1042 deletions

View File

@@ -0,0 +1,72 @@
---
name: 'Dream Home Template'
description: 'A modern, responsive real estate platform built with React, Vite, and Tailwind CSS. Find your dream home with intuitive search, detailed property listings, and seamless user experience.'
tags: ['react', 'vite', 'tailwindcss']
image: '../../../public/static/dream-home-template.png'
link: 'https://dreamhome.cojocarudavid.me'
startDate: '2025-04-16'
endDate: '2025-05-29'
---
> **Find your perfect home with ease** - A modern, responsive real estate platform with advanced SEO optimization
> If you like this template, consider you can buy it from **[Ko-fi](https://ko-fi.com/c/11ea4e5155)** to support my work!
## ✨ Features
- 📱 **Fully Responsive** - Perfect experience on all devices
- 🎨 **Modern UI/UX** - Beautiful design with smooth animations
- 🏠 **Property Listings** - Detailed property information and galleries
- 👥 **User Authentication** - A basic (non-full-featured) authentication system
- 📞 **Contact & Support** - Easy ways to get in touch
-**Fast Performance** - Built with Vite for lightning-fast development
- 🚀 **SEO Optimized** - Complete SEO implementation with structured data
## 🔍 SEO Features
### Meta Tags & Open Graph
- ✅ Dynamic page titles for each route
- ✅ Unique meta descriptions for all pages
- ✅ Open Graph tags for social media sharing
- ✅ Twitter Card optimization
- ✅ Canonical URLs for duplicate content prevention
### Structured Data (JSON-LD)
- ✅ Organization schema for company information
- ✅ LocalBusiness schema for local SEO
- ✅ RealEstateListing schema for properties
- ✅ BreadcrumbList for navigation
- ✅ Property-specific structured data
### Technical SEO
- ✅ Sitemap.xml generation
- ✅ Robots.txt optimization
- ✅ Web manifest for PWA features
- ✅ Performance optimization with code splitting
- ✅ Mobile-first responsive design
- ✅ Fast loading times with Vite optimization
### Page-Specific SEO
#### Home Page (`/`)
- **Focus:** Brand awareness, service overview, featured properties
- **Keywords:** real estate, luxury homes, property search, dream home
#### Browse Properties (`/browse`)
- **Focus:** Property listings, search functionality
- **Keywords:** browse properties, luxury homes for sale, property finder
#### About Us (`/about`)
- **Focus:** Company information, team, expertise
- **Keywords:** real estate company, expert agents, professional service
#### List Property (`/list`)
- **Focus:** Property listing services, selling homes
- **Keywords:** sell home, list property, home selling, property marketing
#### Contact (`/contact`)
- **Focus:** Contact information, consultation services
- **Keywords:** contact real estate agent, property consultation
#### Property Details (`/property/:id`)
- **Focus:** Individual property information
- **Keywords:** Location-specific, property type, features

View File

@@ -7,11 +7,32 @@ export async function getAllPosts(): Promise<CollectionEntry<'blog'>[]> {
.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf())
}
function getDayKey(date: string | Date): string {
const d = new Date(date)
return d.toISOString().split('T')[0]
}
export async function getRecentPosts(
count: number,
): Promise<CollectionEntry<'blog'>[]> {
const posts = await getAllPosts()
return posts.slice(0, count)
const postsByDay = posts.reduce<Record<string, CollectionEntry<'blog'>[]>>((acc, post) => {
const key = getDayKey(post.data.date)
if (!acc[key]) {
acc[key] = []
}
acc[key].push(post)
return acc
}, {})
const randomPostsPerDay = Object.values(postsByDay).map(postsForDay => {
const randomIndex = Math.floor(Math.random() * postsForDay.length)
return postsForDay[randomIndex]
})
const shuffled = randomPostsPerDay.sort(() => Math.random() - 0.5)
return shuffled.slice(0, count)
}
export async function getAdjacentPosts(currentId: string): Promise<{

View File

@@ -91,8 +91,8 @@ const currentUrl = Astro.url;
class="col-start-2 mb-8 h-auto w-full rounded-3xl object-cover"
loading="lazy"
fetchpriority="low"
width={800}
height={600}
width={1800}
height={1600}
/>
{headings.length > 0 && <TableOfContents headings={headings} />}