GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com โ€” GitHub - mfarim/spring-elearning-react: E-Learning for online examination at Junior high school

BranchesTags
Open more actions menu

Latest commit

 

History

56 Commits
56 Commits

Folders and files

NameName
Last commit message
Last commit date
.github
.github
 
 
backend
backend
 
 
docs
docs
 
 
frontend
frontend
 
 
screenshots
screenshots
 
 
.env.example
.env.example
 
 
.gitignore
.gitignore
 
 
CONTRIBUTING.md
CONTRIBUTING.md
 
 
LICENSE
LICENSE
 
 
README.id.md
README.id.md
 
 
README.md
README.md
 
 
deploy.sh
deploy.sh
 
 
docker-compose.prod.yml
docker-compose.prod.yml
 
 
docker-compose.yml
docker-compose.yml
 
 

Repository files navigation

๐Ÿ“š Spring E-Learning & CBT Platform

Java 21 Spring Boot React 19 Tailwind CSS v4 PostgreSQL Redis Laravel Edition License

๐Ÿ‡ฎ๐Ÿ‡ฉ Baca dalam Bahasa Indonesia

๐Ÿ˜ Looking for the Laravel & Livewire edition? A companion monolithic edition built with Laravel 13, Livewire 3, and Laravel Reverb is available at: https://github.com/mfarim/laravel-elearning

A full-featured web-based E-Learning and Computer Based Test (CBT) platform for managing modern academic learning activities between Admin, Teacher, and Student. Built as a containerized modular monolith with a decoupled SPA frontend: Java 21 LTS, Spring Boot 3.5+, React 19, and Tailwind CSS v4, featuring stateless JWT authentication with Redis-backed refresh-token rotation and impersonation, WebSocket STOMP real-time candidate proctoring, and Apache POI Excel batch processing.


โœจ Key Features

๐Ÿ‘จโ€๐Ÿ’ผ Admin Panel

Feature Description
Dashboard Real-time statistics overview: teachers, students, classrooms, subjects, CBT metrics
Teachers Full CRUD with automatic user account provisioning & NIP validation
Students CRUD + classroom filtering + ๐Ÿ“ฅ Excel Batch Import (.xlsx) + Exam Cards Print
Classrooms CRUD + homeroom teacher assignment + capacity & academic year management
Subjects CRUD + subject code + credit units + assigned teacher mapping
Announcements CRUD + multi-target broadcasting (All / Teacher / Student) + publish toggle
Impersonation Instant one-click login as teacher or student for administrative debugging
Security Spring Security 6 stateless JWT tokens, BCrypt hashing, and method-level @PreAuthorize

๐Ÿ‘จโ€๐Ÿซ Teacher Panel

Feature Description
Dashboard Teaching metrics, scheduled examinations, active assignments, and recent activity
Learning Materials CRUD + multi-type content (Document, Video, Text, Link, Audio) + student view tracking
Assignments CRUD + deadline dates + instructions + submission grading with feedback
CBT Examinations CRUD + duration timer + passing grade (KKM) + randomize questions/options + retry toggles
Question Builder Multiple Choice (A-E), True/False, Essay + points allocation + ๐Ÿ“ฅ Excel Import
Live Telemetry Monitor Real-time WebSocket candidate status, question progress bar, and anti-cheat flag alerts
Exam Hall Tickets Print ready-to-use official CBT student candidate cards with NIS barcodes

๐Ÿ‘จโ€๐ŸŽ“ Student Panel โ€” Mobile-First Design

Feature Description
Home Dashboard Responsive mobile drawer, upcoming exams countdown, active assignments, announcements
Learning Modules Browse, read, and download structured course materials per enrolled subject
Assignment Hub View assignment instructions + file upload dropzone + feedback review
CBT Exam Room Fullscreen examination runner with countdown timer, anti-cheat detection, and auto-submit
Grades & GPA Summary Subject average breakdown, progress bars, and passing grade pass/fail status

๐Ÿ–ฅ๏ธ CBT Exam System Workflow

Exam List โ†’ Confirmation & Instructions โ†’ Secure Exam Runner
                                           โ”œโ”€โ”€ โฑ๏ธ Synchronized Timer (auto-submit on expiry)
                                           โ”œโ”€โ”€ ๐Ÿ”’ Anti-Cheat Proctoring (fullscreen & tab change alerts)
                                           โ”œโ”€โ”€ ๐Ÿ“ Color-Coded Question Palette (answered / remaining)
                                           โ”œโ”€โ”€ ๐Ÿ’พ Instant Auto-Save (on every option selection)
                                           โ””โ”€โ”€ ๐Ÿ“Š Real-Time Proctor Telemetry (WebSocket push to teacher)

๐Ÿ“ธ Screenshots

๐Ÿ” Login Page

Login Page

๐Ÿ‘จโ€๐Ÿ’ผ Admin Panel

Dashboard Teachers Management
Admin Dashboard Teachers
Students Management Classrooms Management
Students Classrooms
Subjects Management Announcements
Subjects Announcements

๐Ÿ‘จโ€๐Ÿซ Teacher Panel

Dashboard Learning Materials
Teacher Dashboard Materials
Assignments Management CBT Examinations
Assignments Exams
Question Builder & Bank
Question Bank

๐Ÿ‘จโ€๐ŸŽ“ Student Panel (Mobile-First Design)

Home Dashboard Learning Materials Assignments Hub
Student Dashboard Materials Assignments
Examination Room Grades & Report Card
Student Exams Student Grades

๐Ÿ› ๏ธ Tech Stack

Layer Technology
Backend Core Java 21 LTS, Spring Boot 3.5.7
Security & Auth Spring Security 6, JJWT 0.12.6, Method Security (@PreAuthorize), Impersonation Engine
Persistence PostgreSQL 16, Spring Data JPA, Hibernate 6, HikariCP, Flyway Migrations
Token Store & Realtime Redis 7 (refresh-token rotation, optional shared rate limits and cross-instance events), Spring WebSocket + STOMP (in-memory simple broker), SockJS
File Storage Local Docker volume or S3-compatible object storage (AWS S3, MinIO)
Batch Processing Apache POI (Excel .xlsx batch parsing for Students & Question Banks)
API Documentation Springdoc OpenAPI 3 / Swagger UI (/swagger-ui/index.html)
Frontend Core React 19, TypeScript 5+, Vite 6
Styling Tailwind CSS v4 (Native CSS engine with @tailwindcss/vite)
State Management Zustand 5, Axios with JWT interceptors
Icons & UI Lucide React
Deployment Docker Compose, Multi-stage Dockerfiles (OpenJDK 21 Alpine & Node 22 Alpine), Nginx 1.28

๐Ÿ›๏ธ High-Level System Architecture

The platform is a modular monolith (one Spring Boot service split into domain modules) with a separate React SPA, deployed as Docker containers on a VPS behind Cloudflare, with defense-in-depth at every layer. Data model, request flows, design decisions, and scaling limits are documented in docs/ARCHITECTURE.md.

graph TD
    Client["๐ŸŒ Clients / Web Browsers<br/>(Admin, Teacher, Student)"]
    
    subgraph Edge ["๐Ÿ›ก๏ธ Perimeter & Edge Layer"]
        CF["Cloudflare Edge Proxy<br/>โ€ข WAF & DDoS Shield<br/>โ€ข SSL/TLS Termination<br/>โ€ข CF-Connecting-IP Passthrough"]
    end

    subgraph Host ["๐Ÿ–ฅ๏ธ VPS Host Server"]
        Nginx["Host Reverse Proxy / Nginx<br/>โ€ข Port 80/443 Loopback (127.0.0.1)<br/>โ€ข Security Headers (nosniff, SAMEORIGIN)<br/>โ€ข Actuator Endpoints Blocked (404)"]
        
        subgraph DockerNet ["Docker Network (elearning-network)"]
            Frontend["๐Ÿ“ฆ elearning-frontend<br/>React 19 SPA + Vite + Tailwind v4"]
            
            Backend["โ˜• elearning-backend<br/>Java 21 LTS + Spring Boot 3.5.7<br/>โ€ข Spring Security 6 (Stateless JWT)<br/>โ€ข Bucket4j Login Rate Limiting (A07)<br/>โ€ข STOMP WebSocket (in-memory simple broker)<br/>โ€ข Apache POI with Batch Guards"]
            
            Postgres[("๐Ÿ˜ elearning-postgres<br/>PostgreSQL 16 Relational DB<br/>โ€ข Flyway Automated Migrations<br/>โ€ข HikariCP Connection Pool")]
            
            Redis[("โšก elearning-redis<br/>Redis 7<br/>โ€ข Refresh-token store<br/>โ€ข Rotation & revocation by jti")]
            
            Storage[("๐Ÿ“ backend_storage<br/>Persistent Docker Volume<br/>โ€ข Uploads (/app/storage/uploads)<br/>โ€ข File Extension Whitelisting")]
        end
    end

    Client -->|HTTPS / WSS| CF
    CF -->|Proxied Traffic| Nginx
    Nginx -->|Static Assets| Frontend
    Nginx -->|/api/ & /ws| Backend
    Backend -->|HikariCP / JPA| Postgres
    Backend -->|Refresh tokens| Redis
    Backend -->|Safe File I/O| Storage
Loading

๐Ÿ”’ Security & OWASP Top 10 Mapping

OWASP Standard Mitigation in this Platform
A01: Broken Access Control Method-level security (@PreAuthorize) on all administrative and user directory endpoints; classroom ownership validation preventing IDOR on assignments and discussions; STOMP WebSocket ChannelInterceptor verifying teacher/admin privileges.
A02: Cryptographic Failures BCrypt password hashing; HMAC-SHA256 JWT tokens with mandatory 256-bit+ secret key validation on application boot; automated fail-fast if JWT_SECRET is missing.
A03: Injection 100% parameterized Spring Data JPA queries eliminating SQL Injection; no OS command execution; strict input DTO @Valid constraints.
A04: Insecure Design Examination answer keys and explanations strictly stripped (null) from student payloads; examination duration deadlines enforced on the server-side, not trusting client clocks.
A05: Security Misconfiguration Spring Boot Actuator endpoints strictly blocked (404) from public Nginx reverse proxy; all Docker service ports bound to loopback 127.0.0.1; security headers (X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN) enforced.
A06: Vulnerable Components Java 21 LTS, Spring Boot 3.5.7, PostgreSQL 16, Redis 7, React 19. Multi-stage Docker containers running under non-root spring:spring user.
A07: Identification Failures Bucket4j Login Rate Limiter: 5 attempts per minute per IP address (CF-Connecting-IP / X-Forwarded-For) and per account email, returning 429 Too Many Requests with Retry-After header.
A08: Software & Data Integrity Strict file upload extension whitelist (.pdf, .docx, .xlsx, .jpg, .png, etc.); executable and scriptable types (.html, .svg, .exe, .sh) explicitly rejected to prevent Stored XSS; safe download Content-Disposition.
A09: Logging & Monitoring Anti-cheat proctoring violation alerts logged with student NIS; internal /actuator/health probe available for container healthchecks.
A10: SSRF Zero user-controlled outbound HTTP requests from backend services.

๐Ÿ—๏ธ Real-Time Telemetry & WebSocket Architecture

The live examination monitoring feature uses Spring WebSocket with STOMP and Spring's in-memory simple broker to push candidate progress to the teacher in real time. Answers and attempts are persisted in PostgreSQL first, then an event is broadcast. Moving to a Redis/RabbitMQ broker relay for multi-instance deployments is on the roadmap (see docs/ARCHITECTURE.md).

Message Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Candidate in   โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚   Spring Controller  โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚   PostgreSQL        โ”‚       โ”‚                  โ”‚
โ”‚  Exam Runner    โ”‚       โ”‚  /api/v1/exams/...   โ”‚       โ”‚ (attempts, answers) โ”‚       โ”‚   Spring STOMP   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ”‚  Message Broker  โ”‚
                                     โ”‚                                                 โ”‚  (/ws/cbt)       โ”‚
                                     โ”‚  messagingTemplate.convertAndSend()             โ”‚                  โ”‚
                                     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚                  โ”‚
                                                                                       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                                                                                โ”‚
                                                                       Real-time Telemetry Push โ”‚
                                                                                                โ–ผ
                                                                                   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                                                                   โ”‚  Teacher Proctoring    โ”‚
                                                                                   โ”‚  Monitor Dashboard     โ”‚
                                                                                   โ”‚  โ†’ Instant auto-update โ”‚
                                                                                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Key Components

File / Component Purpose
backend/.../WebSocketConfig.java Configures STOMP endpoints (/ws/cbt) and message broker destinations (/topic, /app)
backend/.../ExamTelemetryMessage.java DTO representing real-time candidate heartbeat, progress, and anti-cheat violations
backend/.../ExamService.java Broadcasts telemetry updates upon student answers, time alerts, and submission events
frontend/src/pages/exams/ExamMonitor.tsx Proctoring dashboard with STOMP/SockJS client listener and candidate progress cards
frontend/src/pages/exams/ExamRunner.tsx Secure candidate runner detecting window blur, tab switching, and fullscreen lock

๐Ÿš€ Installation & Quick Setup

Prerequisites

  • Docker & Docker Compose
  • Java 21 LTS (for local backend development)
  • Node.js 22+ (for local frontend development)

Quick Setup (Docker Compose โ€” Recommended)

# Clone the repository
git clone https://github.com/mfarim/spring-elearning-react.git
cd spring-elearning-react

# Generate a JWT signing secret (required, no default)
echo "JWT_SECRET=$(openssl rand -base64 32)" > .env

# Launch full stack (PostgreSQL 16, Redis 7, Spring Boot backend, and React frontend)
docker compose up -d

# (Optional) Seed realistic demo data (teachers, classrooms, subjects, exams)
docker exec -i elearning-postgres psql -U postgres -d elearning < backend/src/main/resources/db/migration/seed_demo_data.sql

Access the services:

  • Frontend Web Portal: http://localhost:3000
  • Spring Boot Backend API: http://localhost:8080
  • Actuator Health Probe: http://localhost:8080/actuator/health
  • Interactive Swagger UI Documentation: http://localhost:8080/swagger-ui/index.html

For contribution guidelines and coding standards, see CONTRIBUTING.md.


Manual Setup (Local Development)

1. Start Infrastructure

docker compose up -d postgres redis

2. Start Backend (Spring Boot)

cd backend
# JWT_SECRET must be set (same value as in .env)
export $(grep JWT_SECRET ../.env)
./mvnw clean spring-boot:run

3. Start Frontend (React + Vite)

cd frontend
npm install
npm run dev

๐Ÿ”‘ Demo Accounts

The database comes pre-seeded with ready-to-test accounts for each academic role:

Role Email Password Portal URL
Admin [email protected] (or [email protected]) password /dashboard
Guru (Teacher) [email protected] (or [email protected]) password /dashboard
Siswa (Student) [email protected] (or [email protected]) password /dashboard

Quick Demo Login buttons are also available directly on the login screen for instant one-click access.


๐Ÿ“ฅ Student Excel Import Format

The student batch importer accepts standard .xlsx spreadsheets with the following columns:

Column Header Required Example Value Description
Name โœ… Andi Pratama Student's full registered name
Email โœ… [email protected] Unique login credential email
NIS โœ… 20250001 Student identification number (unique barcode identifier)
Classroom โœ… X IPA 1 Target classroom name
NISN โž– 0012345678 National student identification number
Gender โž– L / P (or M / F) Gender identification
Address โž– Jl. Merdeka No. 45 Residential home address

๐Ÿงช Testing & Validation

Backend Tests

cd backend
./mvnw test

Frontend Build & Lint Check

cd frontend
npm run build

๐Ÿ“‚ Project Structure

spring-elearning-react/
โ”œโ”€โ”€ backend/
โ”‚   โ”œโ”€โ”€ src/main/java/com/elearning/
โ”‚   โ”‚   โ”œโ”€โ”€ config/              # Spring Security filter chain, WebSocket/STOMP config
โ”‚   โ”‚   โ”œโ”€โ”€ security/            # JWT provider & filter, refresh-token store, rate limiting
โ”‚   โ”‚   โ”œโ”€โ”€ common/              # Base entity, response wrappers, exception handler
โ”‚   โ”‚   โ””โ”€โ”€ modules/
โ”‚   โ”‚       โ”œโ”€โ”€ auth/            # Login, refresh, logout, password change, impersonation
โ”‚   โ”‚       โ”œโ”€โ”€ user/            # Users, Teachers, Students
โ”‚   โ”‚       โ”œโ”€โ”€ academic/        # Classrooms, Subjects
โ”‚   โ”‚       โ”œโ”€โ”€ announcement/    # Announcements
โ”‚   โ”‚       โ”œโ”€โ”€ material/        # Learning Materials & Material Views
โ”‚   โ”‚       โ”œโ”€โ”€ assignment/      # Assignments, Submissions, Discussions
โ”‚   โ”‚       โ”œโ”€โ”€ exam/            # CBT Exams, Question Bank, Attempts, Telemetry
โ”‚   โ”‚       โ””โ”€โ”€ grade/           # Grade summaries
โ”‚   โ””โ”€โ”€ src/main/resources/
โ”‚       โ”œโ”€โ”€ db/migration/        # Flyway SQL schema migrations & seeders
โ”‚       โ””โ”€โ”€ application.yml      # Spring Boot profile configurations
โ”œโ”€โ”€ frontend/
โ”‚   โ”œโ”€โ”€ public/                  # Favicons, App Logo, OG Banner image
โ”‚   โ”œโ”€โ”€ src/
โ”‚   โ”‚   โ”œโ”€โ”€ api/                 # Axios HTTP client with JWT auto-refresh interceptors
โ”‚   โ”‚   โ”œโ”€โ”€ components/          # Common Layout, Sidebar, Top Navbar, ProtectedRoute
โ”‚   โ”‚   โ”œโ”€โ”€ pages/               # Admin, Teacher, Student, CBT Runner, Exam Monitor
โ”‚   โ”‚   โ”œโ”€โ”€ store/               # Zustand authentication & state management
โ”‚   โ”‚   โ””โ”€โ”€ types/               # TypeScript interfaces & DTO schemas
โ”‚   โ”œโ”€โ”€ index.html               # Semantic HTML with complete OpenGraph & JSON-LD SEO
โ”‚   โ””โ”€โ”€ vite.config.ts           # Vite 6 config with Tailwind CSS v4 native plugin
โ”œโ”€โ”€ docs/ARCHITECTURE.md         # Data model, sequence diagrams, design decisions, scaling limits
โ”œโ”€โ”€ screenshots/                 # Application showcase captures across roles
โ””โ”€โ”€ docker-compose.yml           # Multi-container orchestration definition

๐Ÿšข Production Deployment

For production deployments:

  1. Use the optimized multi-stage backend/Dockerfile and frontend/Dockerfile.
  2. Configure external production PostgreSQL and Redis connection strings in environment variables (SPRING_DATASOURCE_URL, SPRING_DATA_REDIS_HOST).
  3. Set a strong JWT secret (JWT_SECRET) with a minimum of 256 bits.
  4. Deploy behind Nginx or Cloudflare with SSL/TLS termination and WebSocket header forwarding (Upgrade and Connection headers).
  5. Add your public domain to APP_CORS_ALLOWED_ORIGINS (also used as the allowed WebSocket origins).
  6. Default accounts must change their password on first login. Set APP_DEMO_MODE=true only on a public demo instance with shared demo accounts.
  7. Keep SPRINGDOC_ENABLED=false and APP_REGISTRATION_ENABLED=false unless you need them.
  8. The refresh token is an httpOnly Secure cookie, so serve the app over HTTPS. Set APP_REFRESH_COOKIE_SECURE=false only for plain-HTTP local runs (the local docker-compose.yml already does).
  9. The SPA sends a Content-Security-Policy. If you enable analytics, allow its hosts on the frontend container, e.g. CSP_SCRIPT_SRC_EXTRA="https://www.googletagmanager.com" and CSP_CONNECT_SRC_EXTRA="https://*.google-analytics.com".
  10. Several backend instances: set APP_REALTIME_MODE=redis, APP_RATE_LIMIT_STORE=redis, and APP_STORAGE_TYPE=s3 with APP_STORAGE_S3_BUCKET (plus APP_STORAGE_S3_ENDPOINT and APP_STORAGE_S3_PATH_STYLE=true for MinIO), and enable sticky sessions for /ws. Details in docs/ARCHITECTURE.md.
  11. Real client IP / rate limiting: the backend trusts X-Forwarded-For only from internal proxies (Docker network). If the site is behind Cloudflare, restore the visitor IP on the host Nginx, otherwise all users share Cloudflare's IPs for rate limiting:
# http {} block of the host nginx โ€” keep the list in sync with https://www.cloudflare.com/ips/
set_real_ip_from 173.245.48.0/20;   # ...add every Cloudflare IPv4/IPv6 range
real_ip_header CF-Connecting-IP;
# and in the proxied location:
proxy_set_header X-Forwarded-For $remote_addr;

๐Ÿ“„ License

This project is open-sourced software licensed under the MIT license.

About

E-Learning for online examination at Junior high school

spring-elearning.mfarim.com

Topics

elearning-platformjava-spring-boot-framework

Resources

Readme
MIT license

Contributing

Contributing
Activity

Stars

4 stars

Watchers

0 watching

Forks

0 forks
Report repository

Contributors

Languages

You are visitor 01402503 โ€” GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800ร—600. No cookies required.