Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
38 changes: 37 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,37 @@
# sheikhcoders.github.io
# Sheikh Coders Blog

A bilingual (English & Bangla) static blog hosted on GitHub Pages. The homepage highlights each post with English and Bangla summaries, "Continue reading" links, and an SEO-ready banner. Individual posts live under `/posts/<slug>/` with matching meta tags and structured data.

## Project structure

```
assets/
posts.json # Post metadata used to render homepage cards
site.js # Shared scripts (year + homepage population)
styles.css # Global styles for homepage + posts
posts/
<slug>/index.html # Full bilingual article
index.html # Homepage with hero banner and auto-loaded posts
```

## Adding a new post

1. **Duplicate a folder** in `posts/` (for example `posts/portfolio-landing/`) and rename it to your new slug.
2. **Update meta tags and copy** inside the new `index.html`. Keep both English and Bangla sections, and refresh the JSON-LD block.
3. **List the post** in `assets/posts.json` with the same slug, title, date, excerpts, and topics. The homepage automatically refreshes the cards using this file.

## Local preview

You can open the HTML files directly in a browser or serve the repo locally with any static server, e.g.

```bash
python3 -m http.server 8000
```

Then visit `http://localhost:8000` to check responsive layouts and "Continue reading" links.

## SEO checklist

- Canonical URLs and language alternates are configured for every page.
- Structured data (`Blog`, `BlogPosting`, and `FAQPage`) is embedded for richer search snippets.
- Mobile-first design with fluid typography and accessible language attributes for English and Bangla.
57 changes: 57 additions & 0 deletions assets/posts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
[
{
"slug": "nextjs-github-actions",
"title": "Deploy Next.js with GitHub Actions",
"date": "2024-06-02",
"displayDate": "02 Jun 2024",
"readTime": "6 min read",
"excerpt_en": "Automate build, test, and deployment steps for a Next.js app using reusable workflow jobs and Vercel or static hosting.",
"excerpt_bn": "গিটহাব অ্যাকশন্স দিয়ে কীভাবে নেক্সট.জেএস অ্যাপের বিল্ড, টেস্ট ও ডিপ্লয়মেন্ট সম্পূর্ণ স্বয়ংক্রিয় করবেন তার ধাপসমূহ।",
"topics": ["GitHub Actions", "Next.js Deploy", "CI/CD"],
"url": "/posts/nextjs-github-actions/"
},
{
"slug": "query-string-seo",
"title": "Mastering URL Query Strings for Focused SEO",
"date": "2024-05-18",
"displayDate": "18 May 2024",
"readTime": "5 min read",
"excerpt_en": "Decode how query parameters shape personalized content, campaign tracking, and crawlable experiences with clear naming logic.",
"excerpt_bn": "কুয়েরি প্যারামিটার দিয়ে কীভাবে ব্যক্তিকৃত কন্টেন্ট, ক্যাম্পেইন ট্র্যাকিং এবং এসইও পারফরমেন্স উন্নত করা যায় তা ধাপে ধাপে জানুন।",
"topics": ["URL Query String", "SEO Logic", "Analytics"],
"url": "/posts/query-string-seo/"
},
{
"slug": "portfolio-landing",
"title": "Build a Clean Portfolio Landing Page",
"date": "2024-05-10",
"displayDate": "10 May 2024",
"readTime": "4 min read",
"excerpt_en": "Learn the layout, typography, and SEO checklist for a one-page portfolio that loads fast on every screen size.",
"excerpt_bn": "প্রতিটি ডিভাইসে দ্রুত লোড হওয়ার জন্য কীভাবে এক-পেইজের পরিচিতিমূলক ওয়েবসাইটকে সুন্দর ও কার্যকরী রাখা যায় তার টিপস।",
"topics": ["Responsive HTML", "Minimal CSS", "SEO Basics"],
"url": "/posts/portfolio-landing/"
},
{
"slug": "nextjs-performance",
"title": "Starter Guide to Next.js Performance",
"date": "2024-04-28",
"displayDate": "28 Apr 2024",
"readTime": "5 min read",
"excerpt_en": "A short list of essentials: dynamic metadata, image optimization, and how to measure Core Web Vitals before launch.",
"excerpt_bn": "নেক্সট.জেএস অ্যাপ লাইভ করার আগে কোন মেটাডাটা, ইমেজ অপ্টিমাইজেশন ও পারফরমেন্স পরীক্ষাগুলো জরুরি তা সহজ ভাষায়।",
"topics": ["Next.js", "Core Web Vitals", "Meta Tags"],
"url": "/posts/nextjs-performance/"
},
{
"slug": "ai-writing",
"title": "AI Writing Workflow for Developers",
"date": "2024-04-12",
"displayDate": "12 Apr 2024",
"readTime": "4 min read",
"excerpt_en": "Keep documentation clear: prompt planning, review loops, and tone control to make AI your writing teammate.",
"excerpt_bn": "ডকুমেন্টেশন পরিষ্কার রাখতে প্রম্পট পরিকল্পনা, পুনঃমূল্যায়ন, ও টোন নিয়ন্ত্রণের মাধ্যমে কীভাবে এআই-কে সহলেখক বানাবেন।",
"topics": ["AI Workflow", "Technical Writing", "Productivity"],
"url": "/posts/ai-writing/"
}
]
70 changes: 70 additions & 0 deletions assets/site.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
(function () {
const yearTarget = document.querySelector('[data-current-year]');
if (yearTarget) {
yearTarget.textContent = new Date().getFullYear();
}

const escapeHtml = (value = '') =>
String(value)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');

const postsGrid = document.querySelector('[data-posts-grid]');
if (!postsGrid) return;

fetch('/assets/posts.json')
.then((response) => {
if (!response.ok) throw new Error('Failed to load posts');
return response.json();
})
.then((posts) => {
if (!Array.isArray(posts) || posts.length === 0) {
return;
}

const sortedPosts = posts.slice().sort((a, b) => new Date(b.date) - new Date(a.date));
const fragment = document.createDocumentFragment();

sortedPosts.forEach((post) => {
const article = document.createElement('article');
article.className = 'post-card';

const topics = Array.isArray(post.topics) ? post.topics : [];
const topicsMarkup = topics
.map((topic) => `<li>${escapeHtml(topic)}</li>`)
.join('');

const url = escapeHtml(post.url);
const title = escapeHtml(post.title);

article.innerHTML = `
<time datetime="${escapeHtml(post.date)}">${escapeHtml(post.displayDate ?? post.date)}</time>
${post.readTime ? `<p class="reading-time">${escapeHtml(post.readTime)}</p>` : ''}
<h3><a href="${url}">${title}</a></h3>
<p lang="en">${escapeHtml(post.excerpt_en)}</p>
<p class="bangla" lang="bn">${escapeHtml(post.excerpt_bn)}</p>
${topicsMarkup ? `<ul class="topic-list" aria-label="Topics">${topicsMarkup}</ul>` : ''}
<a class="read-more" href="${url}" aria-label="Continue reading ${title}">
<span>Continue reading</span>
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M5 12h14M13 6l6 6-6 6" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</a>
`;

fragment.appendChild(article);
});

postsGrid.replaceChildren(fragment);
})
.catch(() => {
const status = document.createElement('p');
status.className = 'bangla';
status.setAttribute('role', 'status');
status.textContent = 'পোস্ট তালিকা লোড করা যাচ্ছে না। অনুগ্রহ করে পরে চেষ্টা করুন।';
postsGrid.appendChild(status);
});
})();
Loading