Skip to main content

Project Architecture

Understanding the technical structure of the portfolio website.

Tech Stack

LayerTechnologyPurpose
FrontendReact 18UI components and state management
Build ToolVite 5Fast development and optimized builds
StylingTailwind CSS 3Utility-first CSS framework
BackendAppwriteDatabase, storage, authentication
IconsLucide ReactConsistent icon library
DeploymentVercelHosting 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:
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:
// 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:
// 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

// 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 TypeSolutionUse Case
Server StateDirect Appwrite callsDatabase operations
Auth StateAuthContextUser session
Cart StateCartContext + localStorageShopping cart
UI StateuseState/useReducerComponent-level state

Performance Optimizations

Code Splitting

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

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

ConcernSolution
AuthenticationAppwrite session management
AuthorizationCollection-level permissions
XSS PreventionDOMPurify for rich text
CORSAppwrite platform configuration
SecretsEnvironment variables (never in code)

Build Configuration

Vite Config (vite.config.js)

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)

export default {
  content: ['./index.html', './src/**/*.{js,jsx}'],
  theme: {
    extend: {
      colors: {
        primary: '#1E8479',
        secondary: '#105652',
      }
    }
  },
  plugins: []
};