Enhanced documentation with troubleshooting, developer guides, and more details

This commit is contained in:
MD. PARVEJ HOSSAIN 2025-12-06 00:51:25 +06:00
parent 3b4298f9ed
commit 30faf64256
8 changed files with 1858 additions and 60 deletions

380
developer/api-reference.mdx Normal file
View File

@ -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 |

310
developer/architecture.mdx Normal file
View File

@ -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 (
<AuthContext.Provider value={{ user, loading, checkUser }}>
{children}
</AuthContext.Provider>
);
}
export const useAuth = () => useContext(AuthContext);
```
## Routing Structure
```javascript
// src/App.jsx
<Routes>
{/* Public Routes */}
<Route path="/" element={<HomePage />} />
<Route path="/blogs" element={<BlogsPage />} />
<Route path="/blog/:slug" element={<BlogPage />} />
<Route path="/projects" element={<ProjectsPage />} />
<Route path="/project/:slug" element={<ProjectPage />} />
<Route path="/shop" element={<ShopPage />} />
{/* Shortlink Redirect */}
<Route path="/:path" element={<ShortlinkRedirect />} />
{/* Admin Routes (Protected) */}
<Route path="/admin" element={<AdminLayout />}>
<Route index element={<Dashboard />} />
<Route path="blogs" element={<BlogManagement />} />
<Route path="projects" element={<ProjectManagement />} />
<Route path="shortlinks" element={<ShortlinkManagement />} />
{/* ... more admin routes */}
</Route>
</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: []
};
```

389
developer/customization.mdx Normal file
View File

@ -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
<button className="bg-primary hover:bg-primary-dark text-white">
Click Me
</button>
<div className="text-primary-light border-primary">
Content
</div>
```
### 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
<Steps>
<Step title="Create Component">
Create `src/pages/NewPage.jsx`:
```jsx
export default function NewPage() {
return (
<div className="container mx-auto px-4 py-8">
<h1 className="text-3xl font-bold">New Page</h1>
{/* Your content */}
</div>
);
}
```
</Step>
<Step title="Add Route">
In `src/App.jsx`:
```jsx
import NewPage from './pages/NewPage';
// In Routes
<Route path="/new-page" element={<NewPage />} />
```
</Step>
<Step title="Add to Navigation">
Update menu settings in admin or edit `Header.jsx`
</Step>
</Steps>
### Admin Page
<Steps>
<Step title="Create Component">
Create `src/pages/Admin/NewFeature/NewFeature.jsx`:
```jsx
export default function NewFeature() {
return (
<div className="p-6">
<h1 className="text-2xl font-bold mb-6">New Feature</h1>
{/* Admin content */}
</div>
);
}
```
</Step>
<Step title="Add Route">
In `src/App.jsx` under admin routes:
```jsx
<Route path="new-feature" element={<NewFeature />} />
```
</Step>
<Step title="Add to Sidebar">
Edit `src/pages/Admin/AdminLayout.jsx` to add menu item
</Step>
</Steps>
## 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
<FontSelector
value={titleFont}
onChange={setTitleFont}
label="Title Font"
previewText="Preview Text Here"
/>
```
## Customizing Rich Text Editor
### Add New Toolbar Button
Edit `src/components/RichTextEditor/RichTextEditor.jsx`:
```jsx
// Add to toolbar
<button
onClick={() => handleCustomAction()}
className="p-2 hover:bg-gray-100 rounded"
title="Custom Action"
>
<CustomIcon className="w-4 h-4" />
</button>
// 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 (
<div
className={`bg-white rounded-lg shadow-md overflow-hidden
hover:shadow-lg transition-shadow cursor-pointer ${className}`}
onClick={onClick}
>
{image && (
<img src={image} alt={title} className="w-full h-48 object-cover" />
)}
<div className="p-4">
<h3 className="font-bold text-lg mb-2">{title}</h3>
<p className="text-gray-600 text-sm">{description}</p>
</div>
</div>
);
}
```
### 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 (
<div className={`${sizes[size]} animate-spin rounded-full
border-2 border-gray-300 border-t-primary`} />
);
}
```
## 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
<!-- index.html -->
<script async src="https://www.googletagmanager.com/gtag/js?id=GA_ID"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'GA_ID');
</script>
```
### 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
<Tip>
Keep components small and focused. If a component exceeds 200 lines, consider splitting it.
</Tip>
<Tip>
Use TypeScript for better type safety and IDE support in larger projects.
</Tip>
<Tip>
Create a `constants.js` file for magic strings and configuration values.
</Tip>
<Warning>
Never hardcode API keys or secrets. Always use environment variables.
</Warning>
<Warning>
Test thoroughly after customizations, especially database schema changes.
</Warning>

240
features/photo-grids.mdx Normal file
View File

@ -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
<Steps>
<Step title="Open Editor">
Go to any content editor (Blog, Project, Product)
</Step>
<Step title="Click Grid Button">
Click the **Grid** icon (Grid3x3) in the toolbar
</Step>
<Step title="Choose Layout">
Browse 24 layout options and click your preferred one
</Step>
<Step title="Add Images">
For each cell:
1. Click the empty cell
2. Choose **URL** or **Upload**
3. Add your image
4. Click **Add Image**
</Step>
<Step title="Insert">
Click **Insert Grid** when all cells are filled
</Step>
</Steps>
## 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
<Tip>
Use images with similar color tones for a cohesive look.
</Tip>
<Tip>
Keep file sizes under 500KB per image for faster loading.
</Tip>
<Tip>
Use consistent aspect ratios within the same grid when possible.
</Tip>
<Warning>
Very large images (>2MB) will slow down page loading. Compress before uploading.
</Warning>
## 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 |
<Note>
Complex layouts may simplify on mobile devices for better viewing experience.
</Note>
## 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

View File

@ -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?
<CardGroup cols={3}>
<Card title="No Coding Required" icon="wand-magic-sparkles">
Manage all content through an intuitive admin panel
</Card>
<Card title="Fully Customizable" icon="palette">
Change fonts, colors, and layouts without touching code
</Card>
<Card title="Production Ready" icon="rocket">
Optimized for performance, SEO, and accessibility
</Card>
</CardGroup>
## 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
<CardGroup cols={2}>
<Card title="Blog System" icon="newspaper">
Full-featured blog with categories, multiple authors, and rich text editing
<Card title="Blog System" icon="newspaper" href="/features/blog-system">
Full-featured blog with categories, multiple authors, rich text editing, and SEO-friendly URLs
</Card>
<Card title="Project Gallery" icon="folder">
Showcase projects with custom URLs, galleries, and detailed descriptions
<Card title="Project Gallery" icon="folder" href="/features/project-gallery">
Showcase projects with custom URLs, image galleries, and detailed descriptions
</Card>
<Card title="Shortlink System" icon="link">
URL shortener with analytics, custom domains, and preview images
<Card title="Shortlink System" icon="link" href="/features/shortlink-system">
URL shortener with click analytics, geographic tracking, and custom domain support
</Card>
<Card title="Shop & Orders" icon="shopping-cart">
E-commerce with PayPal integration, order tracking, and secure file delivery
<Card title="Shop & Orders" icon="shopping-cart" href="/features/shop-system">
E-commerce with PayPal integration, order tracking, coupons, and secure file delivery
</Card>
<Card title="Font Management" icon="font">
70+ Google Fonts plus custom font uploads with Bangla support
<Card title="Font Management" icon="font" href="/features/font-management">
70+ Google Fonts plus custom font uploads with full Bangla language support
</Card>
<Card title="Rich Text Editor" icon="pen">
Advanced editor with embeds, photo grids, tables, and full formatting
<Card title="Rich Text Editor" icon="pen" href="/features/rich-text-editor">
Advanced editor with embeds, photo grids, tables, and complete formatting options
</Card>
</CardGroup>
## 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
<CardGroup cols={2}>
<Card title="Quick Start" icon="play" href="/quick-start">
Get up and running in 10 minutes
</Card>
<Card title="Appwrite Setup" icon="database" href="/appwrite/overview">
Configure your backend services
</Card>
<Card title="Deployment" icon="cloud-arrow-up" href="/deployment">
Deploy to Vercel or other platforms
</Card>
<Card title="Troubleshooting" icon="wrench" href="/troubleshooting">
Common issues and solutions
</Card>
</CardGroup>
## 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/)
<Note>
Appwrite Cloud offers a generous free tier that's sufficient for most portfolio sites. You can also self-host Appwrite if preferred.
</Note>

View File

@ -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": {

View File

@ -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
<Steps>
<Step title="Clone & Install">
<Step title="Clone the Repository">
```bash
git clone <your-repo-url>
cd portfolio
```
</Step>
<Step title="Install Dependencies">
```bash
npm install
```
This installs all required packages including React, Vite, Tailwind, and Appwrite SDK.
</Step>
<Step title="Create Appwrite Project">
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**
</Step>
<Step title="Configure Environment">
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
```
<Warning>
Never commit `.env` to version control. It's already in `.gitignore`.
</Warning>
</Step>
<Step title="Add Platform in Appwrite">
1. In Appwrite Console, go to **Settings** → **Platforms**
2. Click **Add Platform** → **Web**
3. Enter hostname: `localhost`
4. Click **Create**
<Note>
Get these values from your Appwrite Console after creating a project.
This allows your local development server to communicate with Appwrite.
</Note>
</Step>
@ -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).
</Step>
</Steps>
## 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
<Steps>
<Step title="Access Admin Panel">
Go to [http://localhost:5173/admin](http://localhost:5173/admin)
</Step>
<Step title="Create Account">
Click **Sign Up** and create an account with your email.
</Step>
<Step title="Verify Email (Optional)">
If email verification is enabled in Appwrite, check your inbox and verify.
</Step>
<Step title="Add Content">
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 |
</Step>
</Steps>
## Quick Content Checklist
After setup, add content in this order:
<Steps>
<Step title="Header Section">
`/admin/header` - Your name, rotating roles, description
</Step>
<Step title="About Section">
`/admin/about` - Bio, skills, profile image
</Step>
<Step title="Project Categories">
`/admin/project-categories` - Create 2-3 categories
</Step>
<Step title="First Project">
`/admin/projects` - Add your best project
</Step>
<Step title="Blog Category">
`/admin/blog-categories` - Create a category
</Step>
<Step title="First Blog Post">
`/admin/blogs` - Write your first post
</Step>
</Steps>
## 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
<AccordionGroup>
<Accordion title="Site shows empty/no data">
- Check `.env` file exists with correct values
- Verify Appwrite project ID is correct
- Ensure `localhost` is added to Appwrite platforms
</Accordion>
<Accordion title="CORS error in console">
Add `localhost` to Appwrite Console → Settings → Platforms
</Accordion>
<Accordion title="npm install fails">
- Delete `node_modules` and `package-lock.json`
- Run `npm install` again
- Ensure Node.js 18+ is installed
</Accordion>
</AccordionGroup>
See [Troubleshooting](/troubleshooting) for more solutions.
## Next Steps
<CardGroup cols={2}>
<Card title="Appwrite Setup" icon="database" href="/appwrite/overview">
Complete database and storage configuration
<Card title="Complete Appwrite Setup" icon="database" href="/appwrite/overview">
Set up all collections and storage buckets
</Card>
<Card title="Deployment" icon="rocket" href="/deployment">
Deploy to Vercel or other platforms
<Card title="Deploy to Vercel" icon="rocket" href="/deployment">
Make your portfolio live
</Card>
<Card title="Customize Theme" icon="palette" href="/developer/customization">
Change colors, fonts, and styles
</Card>
<Card title="Explore Features" icon="sparkles" href="/features/blog-system">
Learn about all available features
</Card>
</CardGroup>

281
troubleshooting.mdx Normal file
View File

@ -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
<AccordionGroup>
<Accordion title="Site shows empty/basic mode">
**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
```
</Accordion>
<Accordion title="CORS Error in Console">
**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
</Accordion>
<Accordion title="Collection Not Found (404)">
**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`
</Accordion>
<Accordion title="Permission Denied (401/403)">
**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)
</Accordion>
</AccordionGroup>
## Image & Storage Issues
<AccordionGroup>
<Accordion title="Images Not Uploading">
**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
</Accordion>
<Accordion title="Images Not Displaying">
**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
</Accordion>
<Accordion title="Font Upload Fails">
**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
</Accordion>
</AccordionGroup>
## Deployment Issues
<AccordionGroup>
<Accordion title="Vercel Build Fails">
**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
</Accordion>
<Accordion title="404 on Page Refresh">
**Cause:** SPA routing not configured
**Solution:** Add `vercel.json` to project root:
```json
{
"rewrites": [{ "source": "/(.*)", "destination": "/" }]
}
```
</Accordion>
<Accordion title="Environment Variables Not Working">
**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
</Accordion>
</AccordionGroup>
## Admin Panel Issues
<AccordionGroup>
<Accordion title="Can't Login to Admin">
**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
</Accordion>
<Accordion title="Changes Not Saving">
**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
</Accordion>
<Accordion title="Rich Text Editor Not Working">
**Solution:**
1. Clear browser cache
2. Try a different browser
3. Check for JavaScript errors in console
4. Ensure all dependencies are installed
</Accordion>
</AccordionGroup>
## Shortlink Issues
<AccordionGroup>
<Accordion title="Shortlink Not Redirecting">
**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
</Accordion>
<Accordion title="Custom Domain Not Verifying">
**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)
</Accordion>
<Accordion title="Analytics Not Recording">
**Solution:**
1. Check `shortlink_analytics` collection exists
2. Verify collection permissions
3. Test with incognito/private browsing
4. Check browser console for errors
</Accordion>
</AccordionGroup>
## Shop & Payment Issues
<AccordionGroup>
<Accordion title="PayPal Not Loading">
**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
</Accordion>
<Accordion title="Order Not Creating">
**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
</Accordion>
<Accordion title="Download Links Not Working">
**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)
</Accordion>
</AccordionGroup>
## Performance Issues
<AccordionGroup>
<Accordion title="Site Loading Slowly">
**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
</Accordion>
<Accordion title="Admin Panel Laggy">
**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
</Accordion>
</AccordionGroup>
## Quick Diagnostic Steps
When something isn't working:
<Steps>
<Step title="Check Browser Console">
Press `F12` → Console tab. Look for red error messages.
</Step>
<Step title="Check Network Tab">
Press `F12` → Network tab. Look for failed requests (red).
</Step>
<Step title="Verify Environment">
Ensure `.env` file exists and has correct values.
</Step>
<Step title="Check Appwrite Console">
Verify collections, buckets, and permissions are set up.
</Step>
<Step title="Clear Cache">
Hard refresh: `Ctrl+Shift+R` (Windows) or `Cmd+Shift+R` (Mac)
</Step>
</Steps>
## 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
<Note>
Most issues are caused by missing environment variables, incorrect permissions, or CORS configuration. Always check these first!
</Note>