A static, drop-in website for displaying EECS182 Extra Credit posts for Special Participation D (Muon & MuP updates) — Red Team.
- Full-text search over titles, authors, content, and extracted links
- Filters by author, topic, attachments, and external links
- Topic grouping using keyword heuristics (Lion, SOAP, Muon, etc.)
- TL;DR generation (≤240 chars) using text heuristics
- Detail view with full content, attachments, and extracted links
- Statistics panel showing total posts, unique authors, and topic counts
- Performance optimized with debounced search and pagination ("Load more")
- Open VS Code in this directory
- Install the "Live Server" extension if not already installed
- Right-click on
index.htmland select "Open with Live Server" - The website will open in your browser at
http://127.0.0.1:5500/(or similar)
- Open a terminal in this directory
- Run:
python -m http.server 8000 - Open your browser and navigate to:
http://localhost:8000
- Install
http-serverglobally:npm install -g http-server - Run:
http-server -p 8000 - Open your browser and navigate to:
http://localhost:8000
To deploy as a subdirectory on eecs182.org:
- Upload the entire
special_participation_d_redteam/folder to your server - Ensure it's accessible as a subdirectory (e.g.,
https://eecs182.org/special_participation_d_redteam/) - All paths are relative, so it will work correctly under any subpath
- The website will automatically load
export_ed_filtered.jsonfrom the same directory
special_participation_d_redteam/
├── index.html # Main HTML file
├── styles.css # Stylesheet
├── app.js # JavaScript application logic
├── export_ed_filtered.json # Post data (JSON array)
└── README.md # This file
The website expects export_ed_filtered.json to be a top-level JSON array of post objects. Each post object should have the following structure:
id(number): Unique post identifiertitle(string): Post titleuser_id(number): User IDcreated_at(string): ISO 8601 timestamp (e.g., "2025-12-11T17:37:21.05447+11:00")
user(object): User object withnamefield for author namecontent(string): XML-formatted content with:<file url="..." filename="..."/>tags for attachments<link href="...">...</link>tags for external links
document(string): Plain text version of content (used as fallback)course_id(number): Course identifier for building Ed Discussion URLs
The normalizePost() function in app.js handles the normalization:
- id: Uses
idor falls back tonumber - title: Uses
titleor defaults to "Untitled" - author: Uses
user.nameor falls back touser_idor "Unknown" - created_at: Uses
created_atorcreatedAt - bodyText: Prefers
documentfield, otherwise extracts text from XMLcontent - attachments: Parsed from
<file>tags in XMLcontent - links: Extracted from
<link>tags in XMLcontentand also from plain text URLs - edUrl: Ed Discussion URL (see Ed URL Extraction section below)
Each post includes an "Open on Ed" link that points to the original Ed Discussion post. The URL is obtained as follows:
-
Direct URL fields (checked first): The normalization function checks for direct URL fields in the JSON:
url,permalink,link,web_url,html_url,ed_url- If found and valid (starts with
http), it is used directly
-
Constructed URL (fallback): If no direct URL field exists, the URL is constructed from:
course_id(e.g., 84647)id(thread/post ID, e.g., 7451971)- Pattern:
https://edstem.org/us/courses/<course_id>/discussion/<thread_id> - Example:
https://edstem.org/us/courses/84647/discussion/7451971
-
Unavailable: If neither
course_idnoridis available,edUrlis set tonulland "Ed link unavailable" is displayed.
The "Open on Ed" link appears:
- In the modal detail view (meta section, styled as a button)
- On each post card in the results list (small link in the meta area)
All Ed links open in a new tab with target="_blank" rel="noopener noreferrer" for security.
- HTML Sanitization: All user-generated content is sanitized to prevent XSS attacks
- Input Validation: Safety check warns if JSON appears unfiltered
- Error Handling: Detailed error messages show requested path, resolved URL, and status code
- 404 Detection: Helpful message if JSON file is missing
Topics are assigned using keyword heuristics:
- Lion: Contains "lion" (may combine with SOAP)
- SOAP: Contains "soap"
- Muon: Contains "muon" (may combine with Lion/Adam)
- Optimizers: Contains "optimizer"
- Homework: Contains "homework" or "hw"
- Hyperparameter Tuning: Contains "hyperparameter" or "sweep"
- Other: Default category
- In-memory index: All posts are indexed once on page load
- Debounced search: Search input is debounced (250ms) to avoid excessive filtering
- Pagination: Initial display shows 50 results, with "Load more" for additional posts
- Efficient filtering: Filters are applied in a single pass
Works in all modern browsers that support:
- ES6 JavaScript (fetch API, arrow functions, etc.)
- CSS Grid and Flexbox
- CSS Custom Properties (variables)
Tested in Chrome, Firefox, Safari, and Edge.
- The website assumes the JSON file is already filtered for Special Participation D posts
- No backend or database required — everything runs client-side
- All paths are relative (e.g.,
./export_ed_filtered.json) for subdirectory compatibility - External links open in new tabs with
target="_blank" rel="noopener"for security