diff --git a/developer/api-reference.mdx b/developer/api-reference.mdx
new file mode 100644
index 0000000..c663ed4
--- /dev/null
+++ b/developer/api-reference.mdx
@@ -0,0 +1,380 @@
+---
+title: "API Reference"
+description: "Service functions and Appwrite API usage"
+---
+
+# API Reference
+
+Reference for service functions and Appwrite operations.
+
+## Appwrite Client Setup
+
+```javascript
+import { Client, Databases, Storage, Account, ID, Query } from 'appwrite';
+
+const client = new Client()
+ .setEndpoint(import.meta.env.VITE_APPWRITE_ENDPOINT)
+ .setProject(import.meta.env.VITE_APPWRITE_PROJECT_ID);
+
+export const databases = new Databases(client);
+export const storage = new Storage(client);
+export const account = new Account(client);
+export { ID, Query };
+```
+
+## Database Operations
+
+### List Documents
+
+```javascript
+import { databases, Query } from './appwrite';
+
+// Basic list
+const blogs = await databases.listDocuments(
+ 'portfolio_db',
+ 'blogs'
+);
+
+// With queries
+const featuredBlogs = await databases.listDocuments(
+ 'portfolio_db',
+ 'blogs',
+ [
+ Query.equal('featured', true),
+ Query.orderDesc('publishDate'),
+ Query.limit(10)
+ ]
+);
+```
+
+### Get Single Document
+
+```javascript
+const blog = await databases.getDocument(
+ 'portfolio_db',
+ 'blogs',
+ 'document_id'
+);
+```
+
+### Create Document
+
+```javascript
+import { ID } from 'appwrite';
+
+const newBlog = await databases.createDocument(
+ 'portfolio_db',
+ 'blogs',
+ ID.unique(), // Auto-generate ID
+ {
+ title: 'My Blog Post',
+ category: 'Technology',
+ description: 'A great post...',
+ // ... other fields
+ }
+);
+```
+
+### Update Document
+
+```javascript
+const updated = await databases.updateDocument(
+ 'portfolio_db',
+ 'blogs',
+ 'document_id',
+ {
+ title: 'Updated Title',
+ // Only include fields to update
+ }
+);
+```
+
+### Delete Document
+
+```javascript
+await databases.deleteDocument(
+ 'portfolio_db',
+ 'blogs',
+ 'document_id'
+);
+```
+
+## Query Methods
+
+| Method | Description | Example |
+|--------|-------------|---------|
+| `Query.equal(attr, value)` | Exact match | `Query.equal('category', 'Tech')` |
+| `Query.notEqual(attr, value)` | Not equal | `Query.notEqual('status', 'draft')` |
+| `Query.lessThan(attr, value)` | Less than | `Query.lessThan('price', 100)` |
+| `Query.greaterThan(attr, value)` | Greater than | `Query.greaterThan('likes', 10)` |
+| `Query.search(attr, value)` | Full-text search | `Query.search('title', 'react')` |
+| `Query.orderAsc(attr)` | Sort ascending | `Query.orderAsc('createdAt')` |
+| `Query.orderDesc(attr)` | Sort descending | `Query.orderDesc('publishDate')` |
+| `Query.limit(n)` | Limit results | `Query.limit(10)` |
+| `Query.offset(n)` | Skip results | `Query.offset(20)` |
+| `Query.contains(attr, value)` | Array contains | `Query.contains('tags', 'react')` |
+
+### Complex Queries
+
+```javascript
+// Pagination
+const page2 = await databases.listDocuments(
+ 'portfolio_db',
+ 'blogs',
+ [
+ Query.orderDesc('publishDate'),
+ Query.limit(10),
+ Query.offset(10) // Skip first 10
+ ]
+);
+
+// Multiple conditions
+const filtered = await databases.listDocuments(
+ 'portfolio_db',
+ 'products',
+ [
+ Query.equal('category', 'Electronics'),
+ Query.equal('onSale', true),
+ Query.lessThan('price', 500),
+ Query.orderAsc('price')
+ ]
+);
+```
+
+## Storage Operations
+
+### Upload File
+
+```javascript
+import { storage, ID } from './appwrite';
+
+const file = await storage.createFile(
+ 'blog_images', // Bucket ID
+ ID.unique(), // File ID
+ document.getElementById('fileInput').files[0]
+);
+
+// Get file URL
+const fileUrl = storage.getFileView('blog_images', file.$id);
+```
+
+### Get File URL
+
+```javascript
+// View URL (for images)
+const viewUrl = storage.getFileView('bucket_id', 'file_id');
+
+// Download URL
+const downloadUrl = storage.getFileDownload('bucket_id', 'file_id');
+
+// Preview URL (with transformations)
+const previewUrl = storage.getFilePreview(
+ 'bucket_id',
+ 'file_id',
+ 400, // width
+ 300, // height
+ 'center', // gravity
+ 90 // quality
+);
+```
+
+### Delete File
+
+```javascript
+await storage.deleteFile('bucket_id', 'file_id');
+```
+
+## Authentication
+
+### Login
+
+```javascript
+import { account } from './appwrite';
+
+const session = await account.createEmailPasswordSession(
+ 'user@example.com',
+ 'password'
+);
+```
+
+### Get Current User
+
+```javascript
+try {
+ const user = await account.get();
+ console.log('Logged in as:', user.email);
+} catch (error) {
+ console.log('Not logged in');
+}
+```
+
+### Logout
+
+```javascript
+await account.deleteSession('current');
+```
+
+### Create Account
+
+```javascript
+const user = await account.create(
+ ID.unique(),
+ 'user@example.com',
+ 'password',
+ 'User Name' // Optional
+);
+```
+
+## Service Examples
+
+### Blog Service
+
+```javascript
+// src/lib/blogService.js
+export const blogService = {
+ async listAll() {
+ return await databases.listDocuments(
+ DATABASE_ID,
+ 'blogs',
+ [Query.orderDesc('publishDate')]
+ );
+ },
+
+ async listFeatured() {
+ return await databases.listDocuments(
+ DATABASE_ID,
+ 'blogs',
+ [
+ Query.equal('featured', true),
+ Query.orderDesc('publishDate'),
+ Query.limit(6)
+ ]
+ );
+ },
+
+ async getBySlug(slug) {
+ const result = await databases.listDocuments(
+ DATABASE_ID,
+ 'blogs',
+ [Query.equal('customSlug', slug)]
+ );
+ return result.documents[0] || null;
+ },
+
+ async listByCategory(category) {
+ return await databases.listDocuments(
+ DATABASE_ID,
+ 'blogs',
+ [
+ Query.equal('category', category),
+ Query.orderDesc('publishDate')
+ ]
+ );
+ }
+};
+```
+
+### Shortlink Service
+
+```javascript
+// src/lib/shortlinkService.js
+export const shortlinkService = {
+ async getByPath(path) {
+ const result = await databases.listDocuments(
+ DATABASE_ID,
+ 'shortlinks',
+ [
+ Query.equal('customPath', path.toLowerCase()),
+ Query.equal('isActive', true)
+ ]
+ );
+ return result.documents[0] || null;
+ },
+
+ async incrementClicks(id, currentCount) {
+ return await databases.updateDocument(
+ DATABASE_ID,
+ 'shortlinks',
+ id,
+ { clickCount: currentCount + 1 }
+ );
+ },
+
+ async recordAnalytics(shortlinkId, data) {
+ return await databases.createDocument(
+ DATABASE_ID,
+ 'shortlink_analytics',
+ ID.unique(),
+ {
+ shortlinkId,
+ timestamp: new Date().toISOString(),
+ ...data
+ }
+ );
+ }
+};
+```
+
+### Image Upload Helper
+
+```javascript
+// src/lib/imageService.js
+export const imageService = {
+ async upload(bucketId, file) {
+ const uploaded = await storage.createFile(
+ bucketId,
+ ID.unique(),
+ file
+ );
+
+ const url = storage.getFileView(bucketId, uploaded.$id);
+
+ return {
+ id: uploaded.$id,
+ url: url.href
+ };
+ },
+
+ async delete(bucketId, fileId) {
+ await storage.deleteFile(bucketId, fileId);
+ },
+
+ getPreviewUrl(bucketId, fileId, width = 400, height = 300) {
+ return storage.getFilePreview(
+ bucketId,
+ fileId,
+ width,
+ height
+ ).href;
+ }
+};
+```
+
+## Error Handling
+
+```javascript
+try {
+ const result = await databases.listDocuments(...);
+} catch (error) {
+ if (error.code === 404) {
+ console.log('Collection not found');
+ } else if (error.code === 401) {
+ console.log('Not authorized');
+ } else if (error.code === 403) {
+ console.log('Permission denied');
+ } else {
+ console.log('Error:', error.message);
+ }
+}
+```
+
+## Common Error Codes
+
+| Code | Meaning | Solution |
+|------|---------|----------|
+| 401 | Unauthorized | Check authentication |
+| 403 | Forbidden | Check permissions |
+| 404 | Not Found | Check collection/document ID |
+| 409 | Conflict | Duplicate unique value |
+| 413 | Payload Too Large | Reduce file/data size |
+| 429 | Rate Limited | Slow down requests |
diff --git a/developer/architecture.mdx b/developer/architecture.mdx
new file mode 100644
index 0000000..02eeb21
--- /dev/null
+++ b/developer/architecture.mdx
@@ -0,0 +1,310 @@
+---
+title: "Architecture"
+description: "Technical architecture and project structure overview"
+---
+
+# Project Architecture
+
+Understanding the technical structure of the portfolio website.
+
+## Tech Stack
+
+| Layer | Technology | Purpose |
+|-------|------------|---------|
+| Frontend | React 18 | UI components and state management |
+| Build Tool | Vite 5 | Fast development and optimized builds |
+| Styling | Tailwind CSS 3 | Utility-first CSS framework |
+| Backend | Appwrite | Database, storage, authentication |
+| Icons | Lucide React | Consistent icon library |
+| Deployment | Vercel | Hosting and CI/CD |
+
+## Project Structure
+
+```
+portfolio/
+├── public/ # Static assets
+├── src/
+│ ├── components/ # Reusable UI components
+│ │ ├── Header/
+│ │ ├── Footer/
+│ │ ├── FontSelector/
+│ │ ├── RichTextEditor/
+│ │ ├── PhotoGrid/
+│ │ └── ...
+│ ├── pages/
+│ │ ├── Admin/ # Admin dashboard pages
+│ │ │ ├── BlogManagement/
+│ │ │ ├── ProjectManagement/
+│ │ │ ├── ShortlinkManagement/
+│ │ │ ├── ShopManagement/
+│ │ │ └── Settings/
+│ │ ├── HomePage.jsx
+│ │ ├── BlogPage.jsx
+│ │ ├── ProjectPage.jsx
+│ │ ├── ShopPage.jsx
+│ │ └── ...
+│ ├── lib/ # Services and utilities
+│ │ ├── appwrite.js # Appwrite client config
+│ │ ├── shortlinkService.js
+│ │ ├── analyticsService.js
+│ │ └── ...
+│ ├── utils/ # Helper functions
+│ │ ├── googleFonts.js
+│ │ ├── fontLoader.js
+│ │ └── ...
+│ ├── context/ # React context providers
+│ │ ├── AuthContext.jsx
+│ │ ├── CartContext.jsx
+│ │ └── ...
+│ ├── App.jsx # Main app component
+│ ├── main.jsx # Entry point
+│ └── index.css # Global styles
+├── docs/ # Documentation (separate repo)
+├── .env # Environment variables
+├── vite.config.js # Vite configuration
+├── tailwind.config.js # Tailwind configuration
+└── package.json
+```
+
+## Data Flow
+
+```
+┌─────────────┐ ┌─────────────┐ ┌─────────────┐
+│ Browser │────▶│ React │────▶│ Appwrite │
+│ (User) │◀────│ App │◀────│ Backend │
+└─────────────┘ └─────────────┘ └─────────────┘
+ │
+ ┌──────┴──────┐
+ │ │
+ ┌─────▼─────┐ ┌─────▼─────┐
+ │ Components│ │ Context │
+ │ (UI) │ │ (State) │
+ └───────────┘ └───────────┘
+```
+
+## Key Components
+
+### Appwrite Client (`src/lib/appwrite.js`)
+
+Central configuration for Appwrite SDK:
+
+```javascript
+import { Client, Databases, Storage, Account } from 'appwrite';
+
+const client = new Client()
+ .setEndpoint(import.meta.env.VITE_APPWRITE_ENDPOINT)
+ .setProject(import.meta.env.VITE_APPWRITE_PROJECT_ID);
+
+export const databases = new Databases(client);
+export const storage = new Storage(client);
+export const account = new Account(client);
+```
+
+### Database Service Pattern
+
+Each feature has a dedicated service file:
+
+```javascript
+// src/lib/blogService.js
+import { databases, ID, Query } from './appwrite';
+
+const DATABASE_ID = import.meta.env.VITE_APPWRITE_DATABASE_ID;
+const COLLECTION_ID = 'blogs';
+
+export const blogService = {
+ async list(queries = []) {
+ return await databases.listDocuments(
+ DATABASE_ID,
+ COLLECTION_ID,
+ queries
+ );
+ },
+
+ async get(id) {
+ return await databases.getDocument(
+ DATABASE_ID,
+ COLLECTION_ID,
+ id
+ );
+ },
+
+ async create(data) {
+ return await databases.createDocument(
+ DATABASE_ID,
+ COLLECTION_ID,
+ ID.unique(),
+ data
+ );
+ },
+
+ async update(id, data) {
+ return await databases.updateDocument(
+ DATABASE_ID,
+ COLLECTION_ID,
+ id,
+ data
+ );
+ },
+
+ async delete(id) {
+ return await databases.deleteDocument(
+ DATABASE_ID,
+ COLLECTION_ID,
+ id
+ );
+ }
+};
+```
+
+### Context Providers
+
+Global state management using React Context:
+
+```javascript
+// src/context/AuthContext.jsx
+import { createContext, useContext, useState, useEffect } from 'react';
+import { account } from '../lib/appwrite';
+
+const AuthContext = createContext();
+
+export function AuthProvider({ children }) {
+ const [user, setUser] = useState(null);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ checkUser();
+ }, []);
+
+ async function checkUser() {
+ try {
+ const session = await account.get();
+ setUser(session);
+ } catch {
+ setUser(null);
+ }
+ setLoading(false);
+ }
+
+ return (
+
+ {children}
+
+ );
+}
+
+export const useAuth = () => useContext(AuthContext);
+```
+
+## Routing Structure
+
+```javascript
+// src/App.jsx
+
+ {/* Public Routes */}
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+ {/* Shortlink Redirect */}
+ } />
+
+ {/* Admin Routes (Protected) */}
+ }>
+ } />
+ } />
+ } />
+ } />
+ {/* ... more admin routes */}
+
+
+```
+
+## State Management
+
+| State Type | Solution | Use Case |
+|------------|----------|----------|
+| Server State | Direct Appwrite calls | Database operations |
+| Auth State | AuthContext | User session |
+| Cart State | CartContext + localStorage | Shopping cart |
+| UI State | useState/useReducer | Component-level state |
+
+## Performance Optimizations
+
+### Code Splitting
+
+```javascript
+// Lazy load admin pages
+const BlogManagement = lazy(() => import('./pages/Admin/BlogManagement'));
+const ProjectManagement = lazy(() => import('./pages/Admin/ProjectManagement'));
+```
+
+### Image Optimization
+
+- Lazy loading for images below the fold
+- WebP format support
+- Responsive image sizes
+
+### Font Loading
+
+```javascript
+// Dynamic Google Font loading
+const loadGoogleFont = (fontFamily) => {
+ const link = document.createElement('link');
+ link.href = `https://fonts.googleapis.com/css2?family=${fontFamily}&display=swap`;
+ link.rel = 'stylesheet';
+ document.head.appendChild(link);
+};
+```
+
+## Security Considerations
+
+| Concern | Solution |
+|---------|----------|
+| Authentication | Appwrite session management |
+| Authorization | Collection-level permissions |
+| XSS Prevention | DOMPurify for rich text |
+| CORS | Appwrite platform configuration |
+| Secrets | Environment variables (never in code) |
+
+## Build Configuration
+
+### Vite Config (`vite.config.js`)
+
+```javascript
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ rollupOptions: {
+ output: {
+ manualChunks: {
+ vendor: ['react', 'react-dom', 'react-router-dom'],
+ appwrite: ['appwrite'],
+ }
+ }
+ }
+ }
+});
+```
+
+### Tailwind Config (`tailwind.config.js`)
+
+```javascript
+export default {
+ content: ['./index.html', './src/**/*.{js,jsx}'],
+ theme: {
+ extend: {
+ colors: {
+ primary: '#1E8479',
+ secondary: '#105652',
+ }
+ }
+ },
+ plugins: []
+};
+```
diff --git a/developer/customization.mdx b/developer/customization.mdx
new file mode 100644
index 0000000..df82f0a
--- /dev/null
+++ b/developer/customization.mdx
@@ -0,0 +1,389 @@
+---
+title: "Customization"
+description: "How to customize and extend the portfolio website"
+---
+
+# Customization Guide
+
+Learn how to customize colors, fonts, components, and add new features.
+
+## Theme Customization
+
+### Colors
+
+Edit `tailwind.config.js` to change the color scheme:
+
+```javascript
+// tailwind.config.js
+export default {
+ theme: {
+ extend: {
+ colors: {
+ primary: {
+ DEFAULT: '#1E8479',
+ light: '#07C983',
+ dark: '#105652',
+ },
+ secondary: '#F59E0B',
+ accent: '#8B5CF6',
+ }
+ }
+ }
+};
+```
+
+### Using Custom Colors
+
+```jsx
+// In components
+
+
+
+ Content
+
+```
+
+### CSS Variables
+
+For dynamic theming, use CSS variables in `src/index.css`:
+
+```css
+:root {
+ --color-primary: #1E8479;
+ --color-primary-light: #07C983;
+ --color-primary-dark: #105652;
+ --color-background: #ffffff;
+ --color-text: #1f2937;
+}
+
+/* Dark mode */
+.dark {
+ --color-background: #1f2937;
+ --color-text: #f9fafb;
+}
+```
+
+## Adding New Pages
+
+### Public Page
+
+
+
+ Create `src/pages/NewPage.jsx`:
+
+ ```jsx
+ export default function NewPage() {
+ return (
+
+
New Page
+ {/* Your content */}
+
+ );
+ }
+ ```
+
+
+
+ In `src/App.jsx`:
+
+ ```jsx
+ import NewPage from './pages/NewPage';
+
+ // In Routes
+ } />
+ ```
+
+
+
+ Update menu settings in admin or edit `Header.jsx`
+
+
+
+### Admin Page
+
+
+
+ Create `src/pages/Admin/NewFeature/NewFeature.jsx`:
+
+ ```jsx
+ export default function NewFeature() {
+ return (
+
+
New Feature
+ {/* Admin content */}
+
+ );
+ }
+ ```
+
+
+
+ In `src/App.jsx` under admin routes:
+
+ ```jsx
+ } />
+ ```
+
+
+
+ Edit `src/pages/Admin/AdminLayout.jsx` to add menu item
+
+
+
+## Adding New Collections
+
+### 1. Create in Appwrite
+
+1. Go to Appwrite Console → Databases → portfolio_db
+2. Create new collection with attributes
+3. Set permissions
+
+### 2. Create Service
+
+```javascript
+// src/lib/newFeatureService.js
+import { databases, ID, Query } from './appwrite';
+
+const DATABASE_ID = import.meta.env.VITE_APPWRITE_DATABASE_ID;
+const COLLECTION_ID = 'new_collection';
+
+export const newFeatureService = {
+ async list() {
+ return await databases.listDocuments(DATABASE_ID, COLLECTION_ID);
+ },
+
+ async get(id) {
+ return await databases.getDocument(DATABASE_ID, COLLECTION_ID, id);
+ },
+
+ async create(data) {
+ return await databases.createDocument(
+ DATABASE_ID,
+ COLLECTION_ID,
+ ID.unique(),
+ data
+ );
+ },
+
+ async update(id, data) {
+ return await databases.updateDocument(
+ DATABASE_ID,
+ COLLECTION_ID,
+ id,
+ data
+ );
+ },
+
+ async delete(id) {
+ return await databases.deleteDocument(DATABASE_ID, COLLECTION_ID, id);
+ }
+};
+```
+
+### 3. Create Admin UI
+
+Use existing admin pages as templates. Key patterns:
+
+```jsx
+// List view with CRUD
+const [items, setItems] = useState([]);
+const [loading, setLoading] = useState(true);
+
+useEffect(() => {
+ loadItems();
+}, []);
+
+async function loadItems() {
+ setLoading(true);
+ const result = await newFeatureService.list();
+ setItems(result.documents);
+ setLoading(false);
+}
+
+async function handleDelete(id) {
+ if (confirm('Delete this item?')) {
+ await newFeatureService.delete(id);
+ loadItems();
+ }
+}
+```
+
+## Adding Font Selector to New Pages
+
+```jsx
+import FontSelector from '../../../components/FontSelector/FontSelector';
+
+const [titleFont, setTitleFont] = useState("'Open Sans', sans-serif");
+
+// In your form
+
+```
+
+## Customizing Rich Text Editor
+
+### Add New Toolbar Button
+
+Edit `src/components/RichTextEditor/RichTextEditor.jsx`:
+
+```jsx
+// Add to toolbar
+
+
+// Handler function
+const handleCustomAction = () => {
+ document.execCommand('customCommand', false, 'value');
+ // Or manipulate selection directly
+};
+```
+
+### Add New Embed Type
+
+```jsx
+// In embed handler
+const supportedEmbeds = {
+ youtube: /youtube\.com|youtu\.be/,
+ vimeo: /vimeo\.com/,
+ // Add new type
+ spotify: /spotify\.com/,
+};
+```
+
+## Custom Components
+
+### Reusable Card Component
+
+```jsx
+// src/components/Card/Card.jsx
+export default function Card({
+ title,
+ description,
+ image,
+ onClick,
+ className = ''
+}) {
+ return (
+
+ {image && (
+

+ )}
+
+
{title}
+
{description}
+
+
+ );
+}
+```
+
+### Loading Spinner
+
+```jsx
+// src/components/Spinner/Spinner.jsx
+export default function Spinner({ size = 'md' }) {
+ const sizes = {
+ sm: 'w-4 h-4',
+ md: 'w-8 h-8',
+ lg: 'w-12 h-12'
+ };
+
+ return (
+
+ );
+}
+```
+
+## Environment-Specific Config
+
+```javascript
+// src/config.js
+const config = {
+ development: {
+ apiUrl: 'http://localhost:5173',
+ debug: true,
+ },
+ production: {
+ apiUrl: 'https://yourdomain.com',
+ debug: false,
+ }
+};
+
+export default config[import.meta.env.MODE] || config.development;
+```
+
+## Adding Analytics
+
+### Google Analytics
+
+```html
+
+
+
+```
+
+### Track Page Views
+
+```jsx
+// src/App.jsx
+import { useEffect } from 'react';
+import { useLocation } from 'react-router-dom';
+
+function App() {
+ const location = useLocation();
+
+ useEffect(() => {
+ // Track page view
+ if (window.gtag) {
+ window.gtag('event', 'page_view', {
+ page_path: location.pathname,
+ });
+ }
+ }, [location]);
+
+ // ...
+}
+```
+
+## Best Practices
+
+
+ Keep components small and focused. If a component exceeds 200 lines, consider splitting it.
+
+
+
+ Use TypeScript for better type safety and IDE support in larger projects.
+
+
+
+ Create a `constants.js` file for magic strings and configuration values.
+
+
+
+ Never hardcode API keys or secrets. Always use environment variables.
+
+
+
+ Test thoroughly after customizations, especially database schema changes.
+
diff --git a/features/photo-grids.mdx b/features/photo-grids.mdx
new file mode 100644
index 0000000..0097e1f
--- /dev/null
+++ b/features/photo-grids.mdx
@@ -0,0 +1,240 @@
+---
+title: "Photo Grids"
+description: "Create beautiful image layouts with 24 pre-designed templates"
+---
+
+# Photo Grids
+
+Insert stunning image galleries with professional layouts directly in your content.
+
+## Overview
+
+Photo grids allow you to display multiple images in visually appealing arrangements. Choose from 24 pre-designed layouts to showcase your work.
+
+## Inserting a Photo Grid
+
+
+
+ Go to any content editor (Blog, Project, Product)
+
+
+ Click the **Grid** icon (Grid3x3) in the toolbar
+
+
+ Browse 24 layout options and click your preferred one
+
+
+ For each cell:
+ 1. Click the empty cell
+ 2. Choose **URL** or **Upload**
+ 3. Add your image
+ 4. Click **Add Image**
+
+
+ Click **Insert Grid** when all cells are filled
+
+
+
+## Available Layouts
+
+### Simple Grids (1-5)
+
+| Layout | Description | Images |
+|--------|-------------|--------|
+| 2 Columns | Side by side | 2 |
+| 3 Columns | Three in a row | 3 |
+| 4 Columns | Four in a row | 4 |
+| 2×2 Grid | Square grid | 4 |
+| 3×2 Grid | Two rows of three | 6 |
+
+**Best for:** Simple galleries, before/after comparisons, product showcases
+
+### Asymmetric Layouts (6-10)
+
+| Layout | Description | Images |
+|--------|-------------|--------|
+| Large Left + 2 Right | Featured image on left | 3 |
+| Large Right + 2 Left | Featured image on right | 3 |
+| 2 Top + 3 Bottom | Wide top, small bottom | 5 |
+| 3 Top + 2 Bottom | Small top, wide bottom | 5 |
+| Large Center + 4 Corners | Center focus | 5 |
+
+**Best for:** Highlighting a main image with supporting images
+
+### Creative Layouts (11-15)
+
+| Layout | Description | Images |
+|--------|-------------|--------|
+| Masonry 1 | Tall images on sides | 4-6 |
+| Masonry 2 | Alternating heights | 4-6 |
+| Featured + 3 | One large, three small | 4 |
+| Split + 4 | Two large top, 4 small bottom | 6 |
+| Showcase | Alternating sizes | 5 |
+
+**Best for:** Portfolio showcases, creative presentations
+
+### Gallery Layouts (16-20)
+
+| Layout | Description | Images |
+|--------|-------------|--------|
+| Gallery 1 | Tall left, wide right | 4 |
+| Gallery 2 | Large square with small images | 5 |
+| Portfolio 1 | Wide top, tall right | 4 |
+| Portfolio 2 | Mixed sizes | 5 |
+| Magazine | Editorial style | 5 |
+
+**Best for:** Professional portfolios, editorial content
+
+### Special Layouts (21-24)
+
+| Layout | Description | Images |
+|--------|-------------|--------|
+| Hero + Grid | Hero image with thumbnails | 5 |
+| Spotlight | Wide feature with small images | 4 |
+| Collage 1 | Artistic arrangement | 5 |
+| Collage 2 | Creative mixed layout | 6 |
+
+**Best for:** Hero sections, artistic presentations
+
+## Editing Photo Grids
+
+### Change Images
+
+1. Hover over the grid in the editor
+2. Click **Settings** icon (gear)
+3. Click on the image you want to change
+4. Upload or enter new image URL
+5. Click **Update Grid**
+
+### Change Layout
+
+1. Click **Settings** on the grid
+2. Click **Change Layout**
+3. Select new layout
+4. Rearrange images if needed
+5. Click **Update Grid**
+
+### Delete Grid
+
+1. Hover over the grid
+2. Click **Delete** icon (trash)
+3. Confirm deletion
+
+## Image Recommendations
+
+### Optimal Sizes
+
+| Use Case | Recommended Size |
+|----------|------------------|
+| Thumbnail cells | 400×400px |
+| Wide cells | 800×400px |
+| Tall cells | 400×800px |
+| Hero/Large cells | 1200×800px |
+
+### File Formats
+
+| Format | Best For |
+|--------|----------|
+| JPG | Photos, complex images |
+| PNG | Graphics, transparency |
+| WebP | Best compression (modern browsers) |
+
+### Tips for Best Results
+
+
+ Use images with similar color tones for a cohesive look.
+
+
+
+ Keep file sizes under 500KB per image for faster loading.
+
+
+
+ Use consistent aspect ratios within the same grid when possible.
+
+
+
+ Very large images (>2MB) will slow down page loading. Compress before uploading.
+
+
+## Use Cases
+
+### Portfolio Showcase
+
+Use **Gallery** or **Portfolio** layouts to display your best work with a featured piece.
+
+```
+┌─────────────────┬─────────┐
+│ │ 2 │
+│ 1 ├─────────┤
+│ (Featured) │ 3 │
+│ ├─────────┤
+│ │ 4 │
+└─────────────────┴─────────┘
+```
+
+### Product Gallery
+
+Use **2×2 Grid** or **3 Columns** for product photos from different angles.
+
+```
+┌─────────┬─────────┬─────────┐
+│ 1 │ 2 │ 3 │
+└─────────┴─────────┴─────────┘
+```
+
+### Before/After
+
+Use **2 Columns** for side-by-side comparisons.
+
+```
+┌─────────────┬─────────────┐
+│ Before │ After │
+└─────────────┴─────────────┘
+```
+
+### Photo Essay
+
+Use **Magazine** or **Collage** layouts for storytelling.
+
+```
+┌─────────────────────────────┐
+│ Hero │
+├─────────┬─────────┬─────────┤
+│ 2 │ 3 │ 4 │
+└─────────┴─────────┴─────────┘
+```
+
+## Responsive Behavior
+
+All photo grids are automatically responsive:
+
+| Screen Size | Behavior |
+|-------------|----------|
+| Desktop | Full grid layout |
+| Tablet | Adjusted spacing, some stacking |
+| Mobile | Stacked or simplified layout |
+
+
+ Complex layouts may simplify on mobile devices for better viewing experience.
+
+
+## Troubleshooting
+
+### Grid Not Appearing
+
+1. Ensure you clicked **Insert Grid** after adding images
+2. Check that all cells have images
+3. Refresh the editor
+
+### Images Not Loading
+
+1. Verify image URLs are correct and accessible
+2. Check file upload completed successfully
+3. Ensure images are publicly accessible
+
+### Layout Looks Wrong
+
+1. Check image aspect ratios match the cell shapes
+2. Try a different layout better suited to your images
+3. Ensure all cells are filled
diff --git a/introduction.mdx b/introduction.mdx
index 20d76e7..5b380db 100644
--- a/introduction.mdx
+++ b/introduction.mdx
@@ -5,55 +5,121 @@ description: "A modern portfolio website built with React, Vite, Tailwind CSS, a
# Portfolio Website
-A comprehensive, feature-rich portfolio website with an admin dashboard for complete content management.
+A comprehensive, feature-rich portfolio website with an admin dashboard for complete content management. Built for developers, designers, and creators who want full control over their online presence.
+
+## Why This Portfolio?
+
+
+
+ Manage all content through an intuitive admin panel
+
+
+ Change fonts, colors, and layouts without touching code
+
+
+ Optimized for performance, SEO, and accessibility
+
+
## Tech Stack
-| Technology | Purpose |
-|------------|---------|
-| React 18 | Frontend framework |
-| Vite 5 | Build tool & dev server |
-| Tailwind CSS 3 | Styling |
-| Appwrite | Backend, database & storage |
-| Lucide React | Icons |
+| Technology | Purpose | Why Chosen |
+|------------|---------|------------|
+| React 18 | Frontend framework | Component-based, large ecosystem |
+| Vite 5 | Build tool & dev server | Lightning fast HMR, optimized builds |
+| Tailwind CSS 3 | Styling | Utility-first, highly customizable |
+| Appwrite | Backend, database & storage | Open-source, self-hostable, generous free tier |
+| Lucide React | Icons | Consistent, lightweight, 1000+ icons |
## Key Features
-
- Full-featured blog with categories, multiple authors, and rich text editing
+
+ Full-featured blog with categories, multiple authors, rich text editing, and SEO-friendly URLs
-
- Showcase projects with custom URLs, galleries, and detailed descriptions
+
+ Showcase projects with custom URLs, image galleries, and detailed descriptions
-
- URL shortener with analytics, custom domains, and preview images
+
+ URL shortener with click analytics, geographic tracking, and custom domain support
-
- E-commerce with PayPal integration, order tracking, and secure file delivery
+
+ E-commerce with PayPal integration, order tracking, coupons, and secure file delivery
-
- 70+ Google Fonts plus custom font uploads with Bangla support
+
+ 70+ Google Fonts plus custom font uploads with full Bangla language support
-
- Advanced editor with embeds, photo grids, tables, and full formatting
+
+ Advanced editor with embeds, photo grids, tables, and complete formatting options
+## What's Included
+
+### Public Pages
+- **Homepage** - Hero section, featured content, about preview
+- **Blog** - List view, single post, category filtering
+- **Projects** - Gallery view, detailed project pages
+- **Shop** - Product catalog, cart, checkout
+- **Contact** - Contact form with validation
+
+### Admin Dashboard
+- **Content Management** - Header, about, experience, FAQ
+- **Blog Management** - Posts, categories, authors
+- **Project Management** - Projects, categories, galleries
+- **Shop Management** - Products, orders, coupons
+- **Shortlinks** - URL shortener, analytics, custom domains
+- **Settings** - Fonts, menu, social links
+
## Project Structure
```
-src/
-├── components/ # Reusable UI components
-├── pages/
-│ ├── Admin/ # Admin dashboard pages
-│ └── ... # Public pages
-├── lib/ # Appwrite services & utilities
-└── utils/ # Helper functions
+portfolio/
+├── src/
+│ ├── components/ # Reusable UI components
+│ │ ├── Header/
+│ │ ├── Footer/
+│ │ ├── RichTextEditor/
+│ │ └── ...
+│ ├── pages/
+│ │ ├── Admin/ # Admin dashboard (protected)
+│ │ ├── HomePage.jsx
+│ │ ├── BlogPage.jsx
+│ │ └── ...
+│ ├── lib/ # Appwrite services
+│ ├── utils/ # Helper functions
+│ └── context/ # React context providers
+├── public/ # Static assets
+├── docs/ # Documentation
+└── .env # Environment variables
```
## Quick Links
-- [Quick Start Guide](/quick-start) - Get up and running in 10 minutes
-- [Appwrite Setup](/appwrite/overview) - Configure your backend
-- [Deployment Guide](/deployment) - Deploy to Vercel
+
+
+ Get up and running in 10 minutes
+
+
+ Configure your backend services
+
+
+ Deploy to Vercel or other platforms
+
+
+ Common issues and solutions
+
+
+
+## Requirements
+
+Before you begin, ensure you have:
+
+- **Node.js 18+** - [Download](https://nodejs.org/)
+- **npm or yarn** - Comes with Node.js
+- **Appwrite Account** - [Sign up free](https://cloud.appwrite.io)
+- **Git** - [Download](https://git-scm.com/)
+
+
+ Appwrite Cloud offers a generous free tier that's sufficient for most portfolio sites. You can also self-host Appwrite if preferred.
+
diff --git a/mint.json b/mint.json
index 6d2ae1c..5908ad7 100644
--- a/mint.json
+++ b/mint.json
@@ -29,7 +29,7 @@
"navigation": [
{
"group": "Getting Started",
- "pages": ["introduction", "quick-start", "deployment"]
+ "pages": ["introduction", "quick-start", "deployment", "troubleshooting"]
},
{
"group": "Appwrite Setup",
@@ -48,7 +48,8 @@
"features/shortlink-system",
"features/shop-system",
"features/font-management",
- "features/rich-text-editor"
+ "features/rich-text-editor",
+ "features/photo-grids"
]
},
{
@@ -58,6 +59,14 @@
"admin/content-management",
"admin/settings"
]
+ },
+ {
+ "group": "Developer Guide",
+ "pages": [
+ "developer/architecture",
+ "developer/api-reference",
+ "developer/customization"
+ ]
}
],
"footerSocials": {
diff --git a/quick-start.mdx b/quick-start.mdx
index ba87dad..8555b79 100644
--- a/quick-start.mdx
+++ b/quick-start.mdx
@@ -5,35 +5,72 @@ description: "Get your portfolio website running in 10 minutes"
# Quick Start Guide
+Get your portfolio website up and running quickly with this step-by-step guide.
+
## Prerequisites
-- Node.js 18+ installed
-- Appwrite account ([cloud.appwrite.io](https://cloud.appwrite.io))
-- Git installed
+Before starting, make sure you have:
+
+| Requirement | Version | Check Command |
+|-------------|---------|---------------|
+| Node.js | 18+ | `node --version` |
+| npm | 9+ | `npm --version` |
+| Git | Any | `git --version` |
+
+You'll also need an [Appwrite Cloud](https://cloud.appwrite.io) account (free).
## Installation
-
+
```bash
git clone
cd portfolio
+ ```
+
+
+
+ ```bash
npm install
```
+
+ This installs all required packages including React, Vite, Tailwind, and Appwrite SDK.
+
+
+
+ 1. Go to [cloud.appwrite.io](https://cloud.appwrite.io)
+ 2. Click **Create Project**
+ 3. Name it (e.g., "Portfolio")
+ 4. Copy your **Project ID**
Create a `.env` file in the root directory:
```env
+ # Appwrite Configuration
VITE_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
- VITE_APPWRITE_PROJECT_ID=your_project_id
+ VITE_APPWRITE_PROJECT_ID=your_project_id_here
VITE_APPWRITE_DATABASE_ID=portfolio_db
VITE_APPWRITE_STORAGE_ID=reactbucket
+
+ # Optional: PayPal (for shop)
+ VITE_PAYPAL_CLIENT_ID=your_paypal_client_id
```
+
+ Never commit `.env` to version control. It's already in `.gitignore`.
+
+
+
+
+ 1. In Appwrite Console, go to **Settings** → **Platforms**
+ 2. Click **Add Platform** → **Web**
+ 3. Enter hostname: `localhost`
+ 4. Click **Create**
+
- Get these values from your Appwrite Console after creating a project.
+ This allows your local development server to communicate with Appwrite.
@@ -43,47 +80,133 @@ description: "Get your portfolio website running in 10 minutes"
```
Open [http://localhost:5173](http://localhost:5173) in your browser.
+
+ You should see the portfolio homepage (with placeholder content until you set up the database).
-## First-Time Setup
+## Database Setup
-### 1. Create Admin Account
+Your site needs database collections to store content. You have two options:
-1. Go to `/admin` in your browser
-2. Sign up with your email
-3. Verify your email in Appwrite Console
+### Option A: Quick Setup (Recommended for Testing)
-### 2. Set Up Database
+Create the minimum required collections:
-Follow the [Appwrite Setup Guide](/appwrite/overview) to create:
-- Required collections (blogs, projects, products, etc.)
-- Storage buckets for images
-- Proper permissions
+1. Go to Appwrite Console → **Databases**
+2. Click **Create Database** → ID: `portfolio_db`
+3. Create these collections with basic attributes:
-### 3. Add Your First Content
+| Collection | Required Attributes |
+|------------|---------------------|
+| `header_section` | `name` (string), `roles` (string[]), `description` (string) |
+| `menubar_settings` | `showBlog` (boolean), `showProjects` (boolean) |
-| Section | Admin URL | What to Add |
-|---------|-----------|-------------|
-| Header | `/admin/header` | Name, roles, description |
-| About | `/admin/about` | Bio, skills, experience |
-| Projects | `/admin/projects` | Portfolio projects |
-| Blog | `/admin/blogs` | Blog posts |
+See [Database Setup](/appwrite/database-setup) for complete schema.
+
+### Option B: Full Setup
+
+Follow the complete [Appwrite Setup Guide](/appwrite/overview) to create all collections and storage buckets.
+
+## First-Time Admin Setup
+
+
+
+ Go to [http://localhost:5173/admin](http://localhost:5173/admin)
+
+
+
+ Click **Sign Up** and create an account with your email.
+
+
+
+ If email verification is enabled in Appwrite, check your inbox and verify.
+
+
+
+ Start adding your content:
+
+ | Section | What to Add |
+ |---------|-------------|
+ | Header | Your name, job titles, intro |
+ | About | Bio, skills, profile image |
+ | Projects | Your portfolio work |
+ | Blog | Articles and posts |
+
+
+
+## Quick Content Checklist
+
+After setup, add content in this order:
+
+
+
+ `/admin/header` - Your name, rotating roles, description
+
+
+ `/admin/about` - Bio, skills, profile image
+
+
+ `/admin/project-categories` - Create 2-3 categories
+
+
+ `/admin/projects` - Add your best project
+
+
+ `/admin/blog-categories` - Create a category
+
+
+ `/admin/blogs` - Write your first post
+
+
## Build for Production
```bash
+# Build optimized production bundle
npm run build
-npm run preview # Test production build locally
+
+# Preview production build locally
+npm run preview
```
+The build output is in the `dist/` folder, ready for deployment.
+
+## Common Issues
+
+
+
+ - Check `.env` file exists with correct values
+ - Verify Appwrite project ID is correct
+ - Ensure `localhost` is added to Appwrite platforms
+
+
+
+ Add `localhost` to Appwrite Console → Settings → Platforms
+
+
+
+ - Delete `node_modules` and `package-lock.json`
+ - Run `npm install` again
+ - Ensure Node.js 18+ is installed
+
+
+
+See [Troubleshooting](/troubleshooting) for more solutions.
+
## Next Steps
-
- Complete database and storage configuration
+
+ Set up all collections and storage buckets
-
- Deploy to Vercel or other platforms
+
+ Make your portfolio live
+
+
+ Change colors, fonts, and styles
+
+
+ Learn about all available features
diff --git a/troubleshooting.mdx b/troubleshooting.mdx
new file mode 100644
index 0000000..735b248
--- /dev/null
+++ b/troubleshooting.mdx
@@ -0,0 +1,281 @@
+---
+title: "Troubleshooting"
+description: "Common issues and solutions for your portfolio website"
+---
+
+# Troubleshooting Guide
+
+Quick solutions to common problems you might encounter.
+
+## Database & Backend Issues
+
+### Data Not Loading
+
+
+
+ **Cause:** Environment variables not configured or Appwrite connection failed.
+
+ **Solution:**
+ 1. Check `.env` file exists with correct values
+ 2. Verify Appwrite project ID is correct
+ 3. Check browser console for errors
+ 4. Ensure Appwrite platform includes your domain
+
+ ```env
+ VITE_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
+ VITE_APPWRITE_PROJECT_ID=your_project_id
+ VITE_APPWRITE_DATABASE_ID=portfolio_db
+ ```
+
+
+
+ **Error:** `Access to XMLHttpRequest blocked by CORS policy`
+
+ **Solution:**
+ 1. Go to Appwrite Console → Settings → Platforms
+ 2. Add your domain:
+ - `localhost` (for development)
+ - `your-site.vercel.app` (for production)
+ - `yourdomain.com` (custom domain)
+ 3. Wait 1-2 minutes for changes to propagate
+
+
+
+ **Error:** `Collection or database not found`
+
+ **Solution:**
+ 1. Verify collection exists in Appwrite Console
+ 2. Check collection ID matches exactly (case-sensitive)
+ 3. Ensure database ID is correct in `.env`
+
+
+
+ **Error:** `User is not authorized`
+
+ **Solution:**
+ 1. Check collection permissions in Appwrite
+ 2. For public content: Add "Any" with Read permission
+ 3. For admin content: Add "Users" with all permissions
+ 4. See [Permissions Guide](/appwrite/permissions)
+
+
+
+## Image & Storage Issues
+
+
+
+ **Possible Causes:**
+ - File too large (check bucket max size)
+ - Wrong file format
+ - Bucket permissions incorrect
+
+ **Solution:**
+ 1. Check file size (usually max 10MB)
+ 2. Use supported formats: jpg, png, gif, webp
+ 3. Verify bucket has "Users" create permission
+ 4. Check browser console for specific error
+
+
+
+ **Possible Causes:**
+ - Bucket doesn't have public read access
+ - Image URL is incorrect
+ - Image was deleted
+
+ **Solution:**
+ 1. Check bucket has "Any" read permission
+ 2. Test image URL directly in browser
+ 3. Re-upload the image if needed
+
+
+
+ **Solution:**
+ 1. Ensure file is `.ttf`, `.otf`, or `.woff` format
+ 2. Check file size < 5MB
+ 3. Verify `custom-fonts` bucket exists
+ 4. Check bucket permissions
+
+
+
+## Deployment Issues
+
+
+
+ **Common Causes:**
+ - Missing dependencies
+ - Environment variables not set
+ - Syntax errors in code
+
+ **Solution:**
+ 1. Check Vercel build logs for specific error
+ 2. Run `npm run build` locally to test
+ 3. Ensure all env variables are set in Vercel
+ 4. Check for TypeScript/ESLint errors
+
+
+
+ **Cause:** SPA routing not configured
+
+ **Solution:** Add `vercel.json` to project root:
+ ```json
+ {
+ "rewrites": [{ "source": "/(.*)", "destination": "/" }]
+ }
+ ```
+
+
+
+ **Solution:**
+ 1. Variables must start with `VITE_` prefix
+ 2. Redeploy after adding variables
+ 3. Check variables are set for correct environment (Production/Preview)
+ 4. Clear browser cache after redeploying
+
+
+
+## Admin Panel Issues
+
+
+
+ **Solution:**
+ 1. Verify Appwrite account exists
+ 2. Check email is verified in Appwrite
+ 3. Clear browser cookies and try again
+ 4. Check Appwrite Console for user status
+
+
+
+ **Possible Causes:**
+ - Network error
+ - Permission denied
+ - Validation error
+
+ **Solution:**
+ 1. Check browser console for errors
+ 2. Verify you're logged in
+ 3. Check all required fields are filled
+ 4. Try refreshing and re-saving
+
+
+
+ **Solution:**
+ 1. Clear browser cache
+ 2. Try a different browser
+ 3. Check for JavaScript errors in console
+ 4. Ensure all dependencies are installed
+
+
+
+## Shortlink Issues
+
+
+
+ **Solution:**
+ 1. Check shortlink is marked "Active"
+ 2. Verify path doesn't have typos
+ 3. Clear browser cache
+ 4. Check if path conflicts with existing routes
+
+
+
+ **Solution:**
+ 1. Wait 10-15 minutes for DNS propagation
+ 2. Verify DNS records are correct:
+ - CNAME pointing to your domain
+ - TXT record with verification token
+ 3. Check DNS with online tools (dnschecker.org)
+ 4. Ensure Cloudflare proxy is enabled (if using)
+
+
+
+ **Solution:**
+ 1. Check `shortlink_analytics` collection exists
+ 2. Verify collection permissions
+ 3. Test with incognito/private browsing
+ 4. Check browser console for errors
+
+
+
+## Shop & Payment Issues
+
+
+
+ **Solution:**
+ 1. Verify `VITE_PAYPAL_CLIENT_ID` is set
+ 2. Check PayPal Client ID is correct
+ 3. Ensure PayPal app is enabled
+ 4. Test with sandbox credentials first
+
+
+
+ **Solution:**
+ 1. Check `orders` collection exists with all attributes
+ 2. Verify collection permissions
+ 3. Check browser console for validation errors
+ 4. Ensure all required fields are provided
+
+
+
+ **Solution:**
+ 1. Check `order-files` bucket exists
+ 2. Verify user is logged in
+ 3. Ensure user email matches order email
+ 4. Check if download token expired (15 min limit)
+
+
+
+## Performance Issues
+
+
+
+ **Solutions:**
+ 1. Optimize images before uploading (compress, resize)
+ 2. Reduce number of embeds per page
+ 3. Use lazy loading for images
+ 4. Check network tab for slow requests
+ 5. Consider CDN for static assets
+
+
+
+ **Solutions:**
+ 1. Clear browser cache
+ 2. Close unused browser tabs
+ 3. Check for memory leaks in console
+ 4. Reduce number of items per page in lists
+
+
+
+## Quick Diagnostic Steps
+
+When something isn't working:
+
+
+
+ Press `F12` → Console tab. Look for red error messages.
+
+
+ Press `F12` → Network tab. Look for failed requests (red).
+
+
+ Ensure `.env` file exists and has correct values.
+
+
+ Verify collections, buckets, and permissions are set up.
+
+
+ Hard refresh: `Ctrl+Shift+R` (Windows) or `Cmd+Shift+R` (Mac)
+
+
+
+## Getting Help
+
+If you're still stuck:
+
+1. **Check the specific feature documentation** for detailed setup steps
+2. **Review Appwrite Console** for database/storage issues
+3. **Check Vercel logs** for deployment issues
+4. **Search error messages** online for common solutions
+
+
+ Most issues are caused by missing environment variables, incorrect permissions, or CORS configuration. Always check these first!
+