Chat about this codebase

AI-powered code exploration

Online

Project Overview

SC-ITWEB delivers a complete, static front-end for Federal University Dutse’s IT Department. It combines responsive layout, client-side interactivity, and local credential handling to support students, faculty, and administrators without requiring a backend.

Goals

• Offer a deployable template for departmental websites
• Enable students to register, view, filter, and remove courses entirely on the client
• Provide a simple login flow for students and admins with immediate dashboard redirects
• Ensure a responsive experience on desktop and mobile through a mobile menu toggle

Main Features

• Responsive Navigation
– HTML/CSS layout with a JavaScript toggle for mobile menus
• Login Interface
– Local credential validation in login.html
– Redirects to student or admin dashboard on success; inline error messages on failure
• Course Registration Module
– Uses localStorage to persist courses
– Supports adding, filtering, viewing, and removing entries without a server
• Department Content Sections
– News, faculty profiles, image gallery, courses overview, and contact form

Typical Use Cases

• Student Course Management
– A student opens index.html → logs in → registers courses → views or filters registered courses
• Admin Dashboard Access
– An administrator logs in → accesses the admin dashboard for departmental data updates
• Department Website Deployment
– IT staff clone the repo, host static files on any HTTP server, and update content by editing HTML/CSS

By combining static content with client-side logic, SC-ITWEB provides a lightweight, maintainable foundation for departmental portals.

Quick Start & Development Setup

Get a local copy of SC-ITWEB up and running in minutes. Follow these steps to clone the repo, launch a static server, and reach your first working dashboard.

Prerequisites

• Git
• Node.js (for npm) or Python 3.x
• VS Code (optional, for Live Server)

1. Clone the Repository

Run:

git clone https://github.com/AbuJulaybeeb/SC-ITWEB.git
cd SC-ITWEB

2. Serve the Site Locally

a) Using npm http-server

  1. Install globally (if not already):
    npm install -g http-server
    
  2. Start the server from the project root:
    http-server ./ -p 8080
    
  3. Open http://localhost:8080/index.html

b) Using Python 3

From the project root, run:

python -m http.server 8000

Then visit http://localhost:8000/index.html

c) Using VS Code Live Server

  1. Open the SC-ITWEB folder in VS Code.
  2. Install and enable the Live Server extension.
  3. Right-click on index.htmlOpen with Live Server.
  4. Your browser opens at http://127.0.0.1:5500/index.html

3. Reach the First Working Dashboard

  1. On the homepage (index.html), click Login in the nav.
  2. Use the default admin credentials:
    • Username: Admin@IT
    • Password: InfoTech
  3. You’ll redirect to Admin_dashboard.html.
  4. For student views, register via localStorage (see Users section in README) or manually inject a user:
// In browser console on index.html
const users = JSON.parse(localStorage.getItem('users')) || [];
users.push({ username: 'jsmith', email: 'jsmith@fud.edu.ng', password: 'Password123' });
localStorage.setItem('users', JSON.stringify(users));
  1. Log in as jsmith / Password123 to reach Student_dashboard.html.

Next Steps

• Explore index.html’s layout, styles, and mobile menu toggle in assets/js.
• Review login.html logic for authentication flow.
• Customize or extend dashboards under Admin_dashboard.html and Student_dashboard.html.

Project Structure & Core Concepts

This section breaks down the repository into three layers—HTML views, JavaScript modules, and CSS themes—and explains how they interact to deliver a modular, maintainable web application.

Directory Layout

SC-ITWEB/
├─ index.html
├─ courses.html
├─student_profile.html
├─ admin_dashboard.html
├─ css/
│   ├─ tailwind.css
│   ├─ theme-default.css
│   ├─ theme-dark.css
│   └─ admin_dashboard.css
├─ js/
│   ├─ courseRegistration.js
│   ├─ studentProfile.js
│   └─ adminDashboard.js
└─ assets/
    ├─ images/
    └─ fonts/

HTML Views

Each .html file represents a distinct section of the app. They share a common layout but load only the scripts and styles they need.

Common Template Snippet

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>SC-ITWEB – {{ PageTitle }}</title>
  <link rel="stylesheet" href="css/tailwind.css">
  <link rel="stylesheet" href="css/theme-default.css">
  <!-- Page-specific CSS -->
  {{#if AdminDashboard}}<link rel="stylesheet" href="css/admin_dashboard.css">{{/if}}
</head>
<body>
  <!-- Header, navigation, footer included via partials or server includes -->
  {{> header }}
  
  <main>
    <!-- page-specific content -->
  </main>

  <!-- Common JS -->
  <script src="js/courseRegistration.js"></script>
  <script src="js/studentProfile.js"></script>
  {{#if AdminDashboard}}<script src="js/adminDashboard.js"></script>{{/if}}
</body>
</html>

JavaScript Logic Modules

All scripts live in /js and attach behavior to elements in their corresponding view.

1. courseRegistration.js

• Manages “Register Courses” / “View Courses” tabs
• Persists course list in localStorage under key registeredCourses
• Provides add, remove, search, and render functions

Import in courses.html:

<script src="js/courseRegistration.js"></script>

2. studentProfile.js

• Populates LGA dropdown based on selected state
• Uses a hard-coded lookup object for Nigerian states→LGAs
• Exposes populateLGA() to pre-select values in edit forms

Import in student_profile.html:

<script src="js/studentProfile.js"></script>

3. adminDashboard.js

• Toggles .active class on .sidebar-menu via the hamburger button
• Enables responsive sidebar show/hide at ≤699px

Import in admin_dashboard.html:

<script src="js/adminDashboard.js"></script>

CSS Themes

All styles reside in /css. The project uses Tailwind for utility classes plus custom theme files.

1. Tailwind Base

css/tailwind.css
Provides core utility classes.

2. Theme Files

  • css/theme-default.css
    Applies color palette, typography, and spacing rules.
  • css/theme-dark.css
    Overrides default colors for dark mode.

Switch themes by swapping the <link> tag or toggling via JavaScript:

<!-- Default -->
<link id="themeStylesheet" rel="stylesheet" href="css/theme-default.css">

<script>
  // Toggle dark mode
  document.getElementById('darkModeToggle').addEventListener('click', () => {
    const link = document.getElementById('themeStylesheet');
    link.href = link.href.includes('default')
      ? 'css/theme-dark.css'
      : 'css/theme-default.css';
  });
</script>

3. Page-Specific CSS

css/admin_dashboard.css
Contains sidebar layout, media queries, and styles specific to the admin dashboard.

Core Concepts & Best Practices

  • Separation of concerns: HTML for structure, CSS for styling, JS for behavior.
  • Lazy loading of page assets ensures each view only loads what it needs.
  • Utility-first styling via Tailwind speeds up layout and responsive design.
  • LocalStorage simplifies client-side persistence without a backend.
  • Modular JS files improve maintainability and scope isolation.

Use this structure as a blueprint when adding new pages or features:

  1. Create new_page.html in the root.
  2. Add page-specific <link> and <script> includes.
  3. Implement logic in /js/newPage.js and styles in /css/new_page.css.
  4. Register any new UI components (tabs, forms, menus) with clear separation of HTML, CSS, and JS.

Core Features & Workflows

Step-by-step guides for end-to-end workflows in the Student and Admin areas.

Client-Side Course Registration (Course_registration.html)

Purpose
Enable students to add, view, search and remove courses entirely in the browser using localStorage.

Key Concepts

  • Data model: array of { code, title } stored under registeredCourses.
  • Two tabs: Register Courses (form) and View Courses (table with search & remove).
  • Core functions: renderCourses(), form submit handler, remove handler, search handler.
  1. Initialization
// On page load
let courses = JSON.parse(localStorage.getItem('registeredCourses') || '[]');
renderCourses();
  1. Rendering Courses
function renderCourses(filter = '') {
  const tbody = document.getElementById('courseList');
  tbody.innerHTML = '';
  courses
    .filter(c =>
      c.code.toLowerCase().includes(filter.toLowerCase()) ||
      c.title.toLowerCase().includes(filter.toLowerCase())
    )
    .forEach((course, idx) => {
      const tr = document.createElement('tr');
      tr.innerHTML = `
        <td class="p-2">${course.code}</td>
        <td class="p-2">${course.title}</td>
        <td class="p-2">
          <button class="bg-red-500 text-white px-3 py-1 rounded" data-idx="${idx}">
            Remove
          </button>
        </td>`;
      tbody.appendChild(tr);
    });
}
  1. Registering a Course
document.querySelector('#registerTab form').addEventListener('submit', e => {
  e.preventDefault();
  const [codeInput, titleInput] = e.target.querySelectorAll('input[type="text"]');
  const code = codeInput.value.trim();
  const title = titleInput.value.trim();
  if (!code || !title) return alert('Both fields are required.');
  courses.push({ code, title });
  localStorage.setItem('registeredCourses', JSON.stringify(courses));
  e.target.reset();
  alert('Course added!');
});
  1. Removing a Course
document.getElementById('viewTab').addEventListener('click', e => {
  if (!e.target.matches('button[data-idx]')) return;
  const idx = +e.target.dataset.idx;
  courses.splice(idx, 1);
  localStorage.setItem('registeredCourses', JSON.stringify(courses));
  renderCourses(document.getElementById('searchCourse').value);
});
  1. Searching Courses
document.getElementById('searchCourse').addEventListener('input', e => {
  renderCourses(e.target.value);
});
  1. Tab Switching
registerTabBtn.onclick = () => {
  registerTab.style.display = ''; viewTab.style.display = 'none';
  registerTabBtn.classList.add('active');
  viewTabBtn.classList.remove('active');
};
viewTabBtn.onclick = () => {
  registerTab.style.display = 'none'; viewTab.style.display = '';
  viewTabBtn.classList.add('active');
  registerTabBtn.classList.remove('active');
  renderCourses();
};

Practical Tips

  • Ensure unique course codes or handle duplicates.
  • Persist active tab in localStorage if needed.
  • Replace alert() with custom toasts for better UX.
  • To preload courses, fetch from an API and merge before first renderCourses().

Persisting Uploaded Courses in localStorage

Purpose
Enable admins to add new courses via a form and persist them across page reloads in localStorage.

How It Works

  • Store all uploaded courses under adminUploadedCourses as a JSON-encoded array.
  • On load, retrieve and render the array.
  • On form submit, append new course, save, and re-render.
  1. Retrieve stored courses
function getUploadedCourses() {
  return JSON.parse(localStorage.getItem('adminUploadedCourses') || '[]');
}
  1. Save courses to storage
function saveUploadedCourses(courses) {
  localStorage.setItem('adminUploadedCourses', JSON.stringify(courses));
}
  1. Render courses into the table
function renderCourses() {
  const courses = getUploadedCourses();
  const tbody = document.getElementById('uploaded-courses-body');
  tbody.innerHTML = '';
  courses.forEach(({ code, name, credits }) => {
    const tr = document.createElement('tr');
    tr.innerHTML = `
      <td>${code}</td>
      <td>${name}</td>
      <td>${credits}</td>`;
    tbody.appendChild(tr);
  });
}
  1. Handle the upload form
document.getElementById('upload-course-form').addEventListener('submit', function(e) {
  e.preventDefault();
  const code    = document.getElementById('course-code').value.trim();
  const name    = document.getElementById('course-name').value.trim();
  const credits = parseInt(document.getElementById('course-credits').value, 10);
  if (!code || !name || credits < 0) return;
  const courses = getUploadedCourses();
  courses.push({ code, name, credits });
  saveUploadedCourses(courses);
  renderCourses();
  this.reset();
});
  1. Initial rendering on page load
document.addEventListener('DOMContentLoaded', renderCourses);

Practical Tips

  • Prevent duplicates by checking courses.find(c => c.code === code).
  • Migrate to a backend for large data sets.
  • Always validate and sanitize inputs if exposing data via APIs.

Lecture Slides Management (Admin Upload & Student View)

Purpose
Manage lecture slides end-to-end: admins upload slides via NoteSlide, storing them in localStorage; students view and download them on their dashboard.

Essential Details

  • Storage key: lectureSlides (array of slide objects).
  • Slide object shape:
    • id: unique timestamp-based ID
    • title: slide title
    • fileDataUrl: Base64-encoded file
    • fileName: original filename

Admin: Uploading, Listing & Deleting Slides

HTML (NoteSlide page)

<form id="upload-form">
  <input id="slide-title" placeholder="Slide Title" required>
  <input id="slide-file" type="file" required>
  <button type="submit">Upload</button>
</form>
<div id="slides-list"></div>

Core Logic (noteslide.js)

function loadSlides() {
  return JSON.parse(localStorage.getItem('lectureSlides')) || [];
}
function saveSlides(slides) {
  localStorage.setItem('lectureSlides', JSON.stringify(slides));
}

function renderAdminSlides() {
  const slides = loadSlides();
  const container = document.getElementById('slides-list');
  container.innerHTML = slides.length
    ? slides.map(s => `
        <div class="uploaded-slide-item">
          <h4>${s.title}</h4>
          <a href="${s.fileDataUrl}" download="${s.fileName}">Download</a>
          <button class="delete-slide-btn" data-id="${s.id}">Delete</button>
        </div>`).join('')
    : '<p>No lecture slides uploaded yet.</p>';

  container.querySelectorAll('.delete-slide-btn').forEach(btn => {
    btn.addEventListener('click', e => {
      const id = e.target.dataset.id;
      const updated = loadSlides().filter(sl => sl.id !== id);
      saveSlides(updated);
      renderAdminSlides();
    });
  });
}

document.getElementById('upload-form').addEventListener('submit', e => {
  e.preventDefault();
  const title = document.getElementById('slide-title').value.trim();
  const file  = document.getElementById('slide-file').files[0];
  if (!title || !file) return alert('Fill all fields.');

  const reader = new FileReader();
  reader.onload = evt => {
    const slides = loadSlides();
    slides.push({
      id: Date.now().toString(),
      title,
      fileDataUrl: evt.target.result,
      fileName: file.name
    });
    saveSlides(slides);
    alert('Lecture slide uploaded!');
    e.target.reset();
    renderAdminSlides();
  };
  reader.readAsDataURL(file);
});

renderAdminSlides();

Student: Viewing & Downloading Slides

HTML (Student Dashboard)

<a id="noteslide-nav-link" href="#">Lecture Slides</a>
<section id="noteslide-section" class="hidden">
  <div id="slides-list"></div>
</section>

Core Logic (Student_dashboard.js)

function loadLectureSlides() {
  return JSON.parse(localStorage.getItem('lectureSlides')) || [];
}

function renderLectureSlides() {
  const container = document.getElementById('slides-list');
  const slides = loadLectureSlides();
  container.innerHTML = slides.length
    ? slides.map(s => `
        <div class="bg-white p-6 rounded shadow">
          <h3 class="text-xl font-semibold">${s.title}</h3>
          <a href="${s.fileDataUrl}"
             download="${s.fileName}"
             class="btn btn-primary mt-2">Download</a>
        </div>`).join('')
    : '<p class="text-gray-600">No lecture slides available yet.</p>';
}

document.getElementById('noteslide-nav-link').addEventListener('click', e => {
  e.preventDefault();
  const section = document.getElementById('noteslide-section');
  section.classList.toggle('hidden');
  renderLectureSlides();
});

Practical Guidance

  • Use consistent IDs across admin and student pages (upload-form, slide-title, slide-file, slides-list, noteslide-nav-link, noteslide-section).
  • Base64 files can quickly fill localStorage; consider server‐side storage for large slide decks.
  • Each action re-renders the list to reflect updates immediately.
  • Customize markup and CSS to fit your design system.

Extending & Contributing

This section guides you through customizing pages, adding new features, wiring a real backend, and submitting pull requests to SC-ITWEB.


1. Modifying Existing Pages

Every HTML page lives at the project root (e.g., Admin_dashboard.html, Student_dashboard.html). Shared components (sidebar, header, footer) use consistent IDs and classes.

Steps

  1. Open the target HTML file.
  2. Locate the sidebar <ul> and add or update <li><a> entries.
  3. Mirror any new IDs in your JS handlers.

Example: Add “Reports” to Admin Sidebar

<!-- Admin_dashboard.html -->
<div class="sidebar-menu">
  <button id="sidebarHamburger" class="hamburger-btn">☰</button>
  <ul>
    <li><a href="Admin_dashboard.html" class="active">Dashboard</a></li>
    <!-- New item -->
    <li><a href="Admin_reports.html" id="admin-reports-link">Reports</a></li>
  </ul>
</div>
<script src="js/Admin_dashboard.js"></script>
// js/Admin_dashboard.js
document.getElementById('admin-reports-link')
  .addEventListener('click', e => {
    e.preventDefault();
    // insert report-view logic here
    window.location.href = 'Admin_reports.html';
  });

2. Adding New Modules

Organize new features under js/modules/. Each module pairs an HTML page with a JS file.

File Structure

js/
  modules/
    reports/
      reports.html
      reports.js
  services/
  utils/

Steps

  1. Create reports.html under js/modules/reports/.
  2. Reference shared CSS/JS from root.
  3. Implement interaction in reports.js.
  4. Add a sidebar link in your main layout.

Example: Reports Module

reports.html:

<link rel="stylesheet" href="../css/main.css">
<script defer src="../js/modules/reports/reports.js"></script>

<main>
  <h1>Reports</h1>
  <div id="reports-list"></div>
</main>

reports.js:

import { api } from '../../services/api.js';

async function loadReports() {
  const reports = await api.getReports();
  const container = document.getElementById('reports-list');
  container.innerHTML = reports.map(r =>
    `<div class="card">
       <h2>${r.title}</h2>
       <p>${r.summary}</p>
     </div>`
  ).join('') || '<p>No reports found.</p>';
}

document.addEventListener('DOMContentLoaded', loadReports);

3. Integrating a Real Backend

Replace localStorage mocks with HTTP calls via a centralized service.

Setup services/api.js

// js/services/api.js
const BASE_URL = 'https://api.example.com'; // update per environment

async function request(path, options = {}) {
  const res = await fetch(`${BASE_URL}${path}`, {
    headers: { 'Content-Type': 'application/json' },
    ...options
  });
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}

export const api = {
  getSlides: ()    => request('/slides'),
  postSlide: data  => request('/slides', { method: 'POST', body: JSON.stringify(data) }),
  getReports: ()   => request('/reports'),
  // add more endpoints here
};

Migrate loadLectureSlides()

// Before: localStorage
function loadLectureSlides() {
  const raw = localStorage.getItem('lectureSlides');
  return raw ? JSON.parse(raw) : [];
}

// After: HTTP
import { api } from '../services/api.js';
async function loadLectureSlides() {
  try {
    return await api.getSlides();
  } catch (e) {
    console.error('Failed fetching slides', e);
    return [];
  }
}

Environment Configuration

  • Store BASE_URL in config.js and ignore via .gitignore.
  • Use a simple proxy in development (e.g., vite.config.js or http-proxy-middleware).

4. Contributing Pull Requests

Follow these conventions to streamline reviews.

Workflow

  1. Fork the repo and clone your fork.
  2. Create a feature branch: git checkout -b feat/noteslide-enhancement.
  3. Implement changes; run lint and manual tests.
  4. Commit with [Conventional Commits]:
    • feat(noteslide): support file size display
    • fix(api): handle 401 unauthorized
  5. Push and open a PR against main.
  6. Link any related issue, describe your changes, and request reviewers.

Guidelines

  • Target main branch.
  • Write clear PR descriptions and reference issue IDs.
  • Ensure no ESLint or console errors.
  • Add or update documentation under docs/.
  • Squash or rebase commits before merge.

5. Coding Standards

  • Follow ESLint rules in .eslintrc.js.
  • Use Prettier for consistent formatting.
  • Name modules and files in kebab-case.
  • Write modern ES modules (import/export).

6. Testing & QA

  • Perform manual smoke tests on all pages.
  • Verify mobile responsiveness (sidebar toggle, menu collapse).
  • Check API error handling (network failures, empty data).
  • Run browser devtools console to catch uncaught exceptions.

By following these guidelines, you ensure that new features integrate smoothly, maintain code quality, and align with SC-ITWEB’s architecture.

\n \n {{#if AdminDashboard}}{{/if}}\n\n\n```\n\n### JavaScript Logic Modules\n\nAll scripts live in `/js` and attach behavior to elements in their corresponding view.\n\n#### 1. courseRegistration.js\n\n• Manages “Register Courses” / “View Courses” tabs \n• Persists course list in `localStorage` under key `registeredCourses` \n• Provides add, remove, search, and render functions \n\nImport in `courses.html`:\n\n```html\n\n```\n\n#### 2. studentProfile.js\n\n• Populates LGA dropdown based on selected state \n• Uses a hard-coded lookup object for Nigerian states→LGAs \n• Exposes `populateLGA()` to pre-select values in edit forms \n\nImport in `student_profile.html`:\n\n```html\n\n```\n\n#### 3. adminDashboard.js\n\n• Toggles `.active` class on `.sidebar-menu` via the hamburger button \n• Enables responsive sidebar show/hide at ≤699px \n\nImport in `admin_dashboard.html`:\n\n```html\n\n```\n\n### CSS Themes\n\nAll styles reside in `/css`. The project uses Tailwind for utility classes plus custom theme files.\n\n#### 1. Tailwind Base\n\n`css/tailwind.css` \nProvides core utility classes.\n\n#### 2. Theme Files\n\n- `css/theme-default.css` \n Applies color palette, typography, and spacing rules.\n- `css/theme-dark.css` \n Overrides default colors for dark mode.\n\nSwitch themes by swapping the `` tag or toggling via JavaScript:\n\n```html\n\n\n\n\n```\n\n#### 3. Page-Specific CSS\n\n`css/admin_dashboard.css` \nContains sidebar layout, media queries, and styles specific to the admin dashboard.\n\n### Core Concepts & Best Practices\n\n- Separation of concerns: HTML for structure, CSS for styling, JS for behavior. \n- Lazy loading of page assets ensures each view only loads what it needs. \n- Utility-first styling via Tailwind speeds up layout and responsive design. \n- LocalStorage simplifies client-side persistence without a backend. \n- Modular JS files improve maintainability and scope isolation. \n\nUse this structure as a blueprint when adding new pages or features:\n\n1. Create `new_page.html` in the root. \n2. Add page-specific `` and `\n```\n```js\n// js/Admin_dashboard.js\ndocument.getElementById('admin-reports-link')\n .addEventListener('click', e => {\n e.preventDefault();\n // insert report-view logic here\n window.location.href = 'Admin_reports.html';\n });\n```\n\n---\n\n### 2. Adding New Modules\n\nOrganize new features under `js/modules/`. Each module pairs an HTML page with a JS file.\n\n#### File Structure\n```\njs/\n modules/\n reports/\n reports.html\n reports.js\n services/\n utils/\n```\n\n#### Steps\n1. Create `reports.html` under `js/modules/reports/`.\n2. Reference shared CSS/JS from root.\n3. Implement interaction in `reports.js`.\n4. Add a sidebar link in your main layout.\n\n#### Example: Reports Module\nreports.html:\n```html\n\n\n\n
\n

Reports

\n
\n
\n```\nreports.js:\n```js\nimport { api } from '../../services/api.js';\n\nasync function loadReports() {\n const reports = await api.getReports();\n const container = document.getElementById('reports-list');\n container.innerHTML = reports.map(r =>\n `
\n

${r.title}

\n

${r.summary}

\n
`\n ).join('') || '

No reports found.

';\n}\n\ndocument.addEventListener('DOMContentLoaded', loadReports);\n```\n\n---\n\n### 3. Integrating a Real Backend\n\nReplace `localStorage` mocks with HTTP calls via a centralized service.\n\n#### Setup `services/api.js`\n```js\n// js/services/api.js\nconst BASE_URL = 'https://api.example.com'; // update per environment\n\nasync function request(path, options = {}) {\n const res = await fetch(`${BASE_URL}${path}`, {\n headers: { 'Content-Type': 'application/json' },\n ...options\n });\n if (!res.ok) throw new Error(await res.text());\n return res.json();\n}\n\nexport const api = {\n getSlides: () => request('/slides'),\n postSlide: data => request('/slides', { method: 'POST', body: JSON.stringify(data) }),\n getReports: () => request('/reports'),\n // add more endpoints here\n};\n```\n\n#### Migrate `loadLectureSlides()`\n```js\n// Before: localStorage\nfunction loadLectureSlides() {\n const raw = localStorage.getItem('lectureSlides');\n return raw ? JSON.parse(raw) : [];\n}\n\n// After: HTTP\nimport { api } from '../services/api.js';\nasync function loadLectureSlides() {\n try {\n return await api.getSlides();\n } catch (e) {\n console.error('Failed fetching slides', e);\n return [];\n }\n}\n```\n\n#### Environment Configuration\n- Store `BASE_URL` in `config.js` and ignore via `.gitignore`.\n- Use a simple proxy in development (e.g., `vite.config.js` or `http-proxy-middleware`).\n\n---\n\n### 4. Contributing Pull Requests\n\nFollow these conventions to streamline reviews.\n\n#### Workflow\n1. **Fork** the repo and clone your fork.\n2. Create a feature branch: `git checkout -b feat/noteslide-enhancement`.\n3. Implement changes; run lint and manual tests.\n4. Commit with [Conventional Commits]:\n - `feat(noteslide): support file size display`\n - `fix(api): handle 401 unauthorized`\n5. Push and open a PR against `main`.\n6. Link any related issue, describe your changes, and request reviewers.\n\n#### Guidelines\n- Target `main` branch.\n- Write clear PR descriptions and reference issue IDs.\n- Ensure no ESLint or console errors.\n- Add or update documentation under `docs/`.\n- Squash or rebase commits before merge.\n\n---\n\n### 5. Coding Standards\n\n- Follow **ESLint** rules in `.eslintrc.js`.\n- Use **Prettier** for consistent formatting.\n- Name modules and files in `kebab-case`.\n- Write modern ES modules (`import`/`export`).\n\n---\n\n### 6. Testing & QA\n\n- Perform manual smoke tests on all pages.\n- Verify mobile responsiveness (sidebar toggle, menu collapse).\n- Check API error handling (network failures, empty data).\n- Run browser devtools console to catch uncaught exceptions.\n\nBy following these guidelines, you ensure that new features integrate smoothly, maintain code quality, and align with SC-ITWEB’s architecture."; document.addEventListener('DOMContentLoaded', function() { const contentDiv = AppUtils.dom.query('#documentation-content'); const tocNav = AppUtils.dom.query('#toc-nav'); const tocNavMobile = AppUtils.dom.query('#toc-nav-mobile'); // Initialize mobile menu functionality MobileMenu.init(); // Apply content styling and initialize TOC if (contentDiv) { ContentStyling.applyProseStyles(contentDiv); TableOfContents.init(contentDiv, tocNav, tocNavMobile); } // Setup quick actions QuickActions.init(tocNav, contentDiv); });