This is the source code for my personal website and blog at shovanch.com. Built with Astro 5, it features a modern architecture with dual content systems, Obsidian integration, and performance optimizations.
Note: All content, posts, and notes in this repository are my personal work. Feel free to use the codebase as a template, but please replace all content with your own.
- Modern Stack: Built with Astro 5, React 19, TypeScript, and Tailwind CSS v4
- Dual Content System: Blog posts and Obsidian notes managed as separate git submodules
- Interactive Code Editors: Embedded Sandpack code playgrounds for live coding examples
- Obsidian Integration: Seamless wikilink support and automatic image syncing from Obsidian vault
- Dynamic OG Images: Auto-generated social media previews using
@vercel/og - Search: Full-text search powered by Pagefind
- Dark Mode: Persistent theme switching with system preference detection
- Performance: Optimized with code splitting, image optimization, and lazy loading
- RSS & Sitemap: Auto-generated feeds and sitemaps
- Code Highlighting: Syntax highlighting with Expressive Code
- Typography: Beautiful typography with custom fonts and responsive design
- Node.js 22+
- pnpm (recommended) or npm
# Clone the repository
git clone https://github.com/shovanch/shovanch.com.git
cd shovanch.com
# Install dependencies
pnpm install
# Initialize git submodules (for Obsidian notes and blog posts)
pnpm run submodule-init
# Start development server
pnpm run devThe site will be available at http://localhost:4321
To adapt this codebase for your own website, you'll need to update several configuration files:
export const siteConfig = {
url: 'https://yoursite.com', // Your domain
title: 'Your Name', // Your name/site title
description: 'Your site description', // SEO description
author: 'Your Name', // Author name
email: 'your@email.com', // Your email
} as const;
export const navigationConfig = {
mainMenu: [
{ label: 'home', url: '/' },
{ label: 'posts', url: '/posts' },
{ label: 'notes', url: '/notes' }, // Remove if not using Obsidian
{ label: 'about', url: '/about' },
],
socialLinks: [
{ label: 'email', url: `mailto:your@email.com` },
{ label: 'github', url: 'https://github.com/yourusername' },
{ label: 'linkedin', url: 'https://www.linkedin.com/in/yourusername' },
{ label: 'twitter', url: 'https://x.com/yourusername' },
{ label: 'rss', url: `https://yoursite.com/rss.xml` },
],
} as const;export default defineConfig({
site: 'https://yoursite.com', // Update to your domain
// ... rest of config
});{
"name": "your-site-name"
// Update name, description, repository, etc.
}- Replace blog posts: Both content collections are git submodules:
src/content/posts/- Replace with your own blog posts repositorysrc/content/notes/- Replace with your Obsidian vault (or remove if not needed)
- Update submodule URLs: Modify
.gitmodulesto point to your repositories - Update about page: Modify
src/pages/about.astrowith your information - Replace images: Update images in
public/images/with your own - Update fonts: Replace custom fonts in
public/fonts/if desired
- Colors: Modify Tailwind configuration for your color scheme
- Fonts: Update font references in CSS files if changing fonts
- Layout: Customize components in
src/components/and layouts insrc/layouts/
To remove content collections you don't need:
For Obsidian notes (if not using):
- Remove the notes collection from
src/content.config.ts - Delete notes-related pages in
src/pages/notes/ - Remove Obsidian scripts from
package.json - Update navigation to remove notes links
- Remove git submodule:
git submodule deinit src/content/notes
For blog posts submodule (if using inline content):
- Remove git submodule:
git submodule deinit src/content/posts - Create
src/content/posts/directory and add your MDX files directly
To add your own submodules:
- Remove existing submodules:
git submodule deinit --all - Add your repositories:
git submodule add <your-repo-url> src/content/posts - Update
.gitmoduleswith your repository URLs - Configure authentication in Vercel for private repositories
| Command | Description |
|---|---|
pnpm run dev |
Start development server (syncs Obsidian images first) |
pnpm run build |
Build for production |
pnpm run preview |
Preview production build locally |
pnpm run prod |
Build and preview in one command |
pnpm run type-check |
Run TypeScript type checking |
pnpm run format |
Format code with Prettier |
pnpm run test |
Run tests with Vitest |
src/
├── components/ # Reusable Astro and React components
├── content/
│ ├── posts/ # Blog posts in MDX format (git submodule)
│ └── notes/ # Obsidian notes (git submodule)
├── layouts/ # Page layouts
├── pages/ # Route pages
├── utils/ # Utility functions
├── styles/ # Global CSS styles
└── config/ # Configuration files
public/
├── fonts/ # Custom web fonts
├── images/ # Static images
└── notes/assets/ # Synced Obsidian images
Interactive Code Examples:
You can embed live code editors using Sandpack for interactive examples:
import { CodePlayground } from '~/components/code-playground';
<CodePlayground
files={{
'/App.js': `
import React, { useState } from 'react';
export default function App() {
const [count, setCount] = useState(0);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
`,
}}
template="react"
/>;The project supports Obsidian-style markdown with automatic processing:
- Wikilinks:
[[Page Name]]→ converted to proper links - Image embeds:
![[image.jpg]]→ automatically processed - Highlighting:
==highlighted text==→<mark>tags - Smart captions: Intelligent caption detection for images
Place Obsidian images in src/content/notes/assets/ and they'll be automatically synced to the public directory.
The project uses Tailwind CSS v4 with:
- Custom fonts (Source Serif 4, Uncut Sans, Fira Code)
- Dark mode support
- Typography plugin for prose styling
- Custom component styles
Key configuration files:
astro.config.mjs- Astro configurationsrc/config/site.ts- Site metadata and settingstailwind.config.js- Tailwind CSS configurationtsconfig.json- TypeScript configuration
The project is optimized for Vercel deployment with enhanced submodule support:
- Connect your repository to Vercel
- Set environment variables:
GITHUB_PAT- GitHub Personal Access Token for private submodules
- Configure build settings:
- Build Command:
pnpm run build(uses customscripts/vercel-build.sh) - The build script automatically handles authentication for both public and private submodules
- Build Command:
- Deploy automatically on push
Private Submodule Authentication:
The custom Vercel build script (scripts/vercel-build.sh) automatically configures authentication for private GitHub repositories using your GITHUB_PAT environment variable. This allows seamless deployment of sites using private content repositories.
The project generates static files and can be deployed to any static hosting service:
pnpm run build
# Deploy the dist/ folderSocial media previews are automatically generated for each blog post using @vercel/og. Images are created at build time and served from /posts/[slug]/og.png.
Full-text search is powered by Pagefind, which indexes all content at build time and provides fast, client-side search.
An RSS feed is automatically generated at /rss.xml including all published blog posts.
- Built-in Astro analytics support
- Optimized images with
sharp - Code splitting and lazy loading
- Performance monitoring ready
The project uses Prettier with:
- Double quotes and semicolons
- Auto-import organization
- Tailwind class sorting
Format code: pnpm run format
Tests are written with Vitest:
pnpm run test # Run tests in watch mode
pnpm run test:run # Run tests oncepnpm run type-check # Check TypeScript types- Framework: Astro 5
- UI Library: React 19
- Styling: Tailwind CSS v4
- Language: TypeScript
- Content: MDX with content collections
- Deployment: Vercel
- Search: Pagefind
- Code Highlighting: Expressive Code
- Interactive Code: Sandpack for embedded code playgrounds
- OG Images: @vercel/og
This project is open source and available under the MIT License.
Content License: All blog posts, notes, and personal content in this repository are copyrighted by Shovan Chatterjee. The code and structure are freely available, but please replace all content with your own.
This is primarily a personal website, but contributions to improve the codebase are welcome! Please feel free to submit a Pull Request for:
- Bug fixes
- Performance improvements
- New features that would benefit the template
- Documentation improvements
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests if applicable
- Run the quality checks:
pnpm run type-check pnpm run lint pnpm run format pnpm run test - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Submit a pull request
- Website: shovanch.com
- GitHub: @shovanch
- Email: hi@shovanch.com
Built with ❤️ using Astro and modern web technologies.