Skip to main content

System Architecture

Platzi Viewer is a client-server application that streams Platzi course content from Google Drive. The architecture consists of:
  • Python Backend: HTTP server with Drive API integration
  • JavaScript Frontend: Single-page application with modular routing
  • Google Drive: Content storage and streaming source
  • Local Storage: Progress tracking and state persistence

Architecture Diagram

Technology Stack

Backend

ComponentTechnologyPurpose
HTTP ServerPython http.server.ThreadingHTTPServerMulti-threaded request handling
Drive IntegrationGoogle API Python ClientFile listing and streaming
AuthenticationOAuth2 Service AccountDrive API access
CachingJSON file + in-memory cacheCourse metadata
Video ProcessingFFmpeg (optional)Compatibility streaming
The server supports Range Requests (HTTP 206) for video seeking and efficient bandwidth usage.

Frontend

ComponentTechnologyPurpose
ApplicationVanilla JavaScript (ES6 Modules)No framework dependencies
RoutingHash-based SPA routerClient-side navigation
State ManagementCentralized state serviceData + progress tracking
API CommunicationFetch API with retry logicBackend integration
StorageLocalStorage + Server syncProgress persistence

Data Flow

Application Bootstrap

1

Initial Load

Frontend requests /api/bootstrap for lightweight course catalog (no class details)
2

Progress Sync

Load progress from localStorage and merge with server data from /api/progress
3

Render UI

Display categories, routes, and courses with progress indicators
4

Lazy Loading

Course details (modules/classes) loaded on-demand via /api/course-detail

Video Streaming Flow

Component Communication

API Endpoints

The backend exposes RESTful endpoints:
EndpointMethodPurpose
/api/bootstrapGETLightweight course catalog
/api/coursesGETFull course data with all details
/api/course-detail/{cat}/{route}/{course}GETOn-demand course detail loading
/api/progressGET/POSTUser progress sync
/api/healthGETSystem health check
/drive/files/{fileId}GETStream Drive file with Range support
/api/video-compatible/{fileId}GETFFmpeg-remuxed video stream

Frontend Services

// State Service - Centralized data management
state.init()              // Load bootstrap data + progress
state.getCourse(...)      // Navigate course hierarchy
state.markClassComplete() // Update progress
state.saveProgress()      // Persist to localStorage + server
// API Service - Backend communication
ApiService.getBootstrap()        // Fetch course catalog
ApiService.getCourseDetail(...)  // Load course details
ApiService.getVideoUrl(fileId)   // Build Drive streaming URL

Cache Architecture

The system uses a two-tier caching strategy:

File-Based Cache (courses_cache.json)

# server.py:583
def init_cache():
    """Inicializa el caché cargando courses_cache.json."""
    # Loads and validates cache file
    # Pre-compresses JSON with gzip for fast API responses
    # Stores in global memory for multi-threaded access
Generated by rebuild_cache_drive.py, contains:
  • Category/route/course hierarchy
  • Drive file IDs for all content
  • Module and class structure
  • Metadata (match types, presentation flags)

In-Memory Cache

# server.py:38-54
courses_cache = None           # Full course data
bootstrap_cache = None         # Lightweight summary
full_cache_json_bytes = b""    # Pre-serialized JSON
full_cache_json_gzip_bytes = b"" # Pre-compressed
cache_lock = threading.Lock()  # Thread-safe access
The server pre-serializes and pre-compresses JSON payloads to minimize response latency. Gzip compression is used for responses over 1KB.

Thread Safety

The backend handles concurrent requests safely:
# server.py:730
class PlatziHandler(SimpleHTTPRequestHandler):
    # Each request handled in separate thread
    # ThreadingHTTPServer creates thread pool
    
# Thread-safe cache access
with cache_lock:
    data = courses_cache  # Protected read
# drive_service.py:102
def _get_session(self):
    # Shared AuthorizedSession with lock
    # Avoids per-thread authentication overhead
    with self._shared_session_lock:
        if self._shared_session is None:
            self._shared_session = AuthorizedSession(self.creds)

Deployment Modes

Platzi Viewer supports multiple deployment configurations:

Local Development

python server.py
# Binds to 127.0.0.1:8080
# CORS allowed for localhost only

Environment Variables

VariableDefaultPurpose
PORT8080Server port
HOST127.0.0.1Bind address
PLATZI_VIEWER_PATHCurrent dirStatic files location
PLATZI_DATA_PATHViewer pathData storage (cache, progress)
GOOGLE_SERVICE_ACCOUNT_FILEservice_account.jsonDrive credentials path
GOOGLE_SERVICE_ACCOUNT_JSON-Inline credentials (JSON string)

Performance Optimizations

The /api/bootstrap endpoint returns a lightweight payload (class counts instead of full class arrays), enabling fast initial page load. Full course details are loaded on-demand.
Server pre-compresses JSON responses and serves gzipped data when Accept-Encoding: gzip is present, reducing bandwidth by ~70-80%.
Video files support HTTP Range requests (status 206), allowing efficient seeking and reduced bandwidth when users skip through content.
A single authenticated AuthorizedSession is reused across threads to avoid per-request OAuth token overhead.
# server.py:1185
for chunk in resp.iter_content(chunk_size=1024 * 1024):
    # Larger chunks reduce overhead and improve A/V sync

Error Handling

Backend

# server.py:297-312
def _load_cache_file(path):
    # Validates JSON schema
    # Returns (data, mtime, error)
    # Invalid caches marked to avoid retry loops

Frontend

// api.js:13-28
static async _fetchWithTimeout(url, options = {}, timeoutMs = DEFAULT_TIMEOUT_MS) {
    const controller = new AbortController();
    const timer = window.setTimeout(() => controller.abort(), timeoutMs);
    // Timeout protection + structured error codes
}
All API errors include structured error codes (e.g., bootstrap_http_500, course_detail_not_found) for precise debugging.

Next Steps

Frontend Architecture

Dive into JavaScript modules, routing, and state management

Backend Architecture

Explore Python server internals and request handling

Google Drive Integration

Learn about Drive API, authentication, and file streaming

Build docs developers (and LLMs) love