This repository contains the course website for AEM 4510, built with Hugo and the Wowchemy Academic theme.
-
Clone the repository:
git clone https://github.com/irudik/aem4510.git cd aem4510 -
Start the development server:
Rscript -e "blogdown::serve_site()" -
Open http://localhost:1313 in your browser
The site will automatically reload when you make changes to content files.
The lecture notes in content/lecture-notes/ are written as .Rmd files. To render them to HTML:
Rscript -e "
library(rmarkdown)
library(blogdown)
rmd_files = list.files('content/lecture-notes', pattern = '\\\\.Rmd$', full.names = TRUE)
for (rmd_file in rmd_files) {
html_file = sub('\\\\.Rmd$', '.html', rmd_file)
# Read the Rmd file and extract YAML frontmatter
lines = readLines(rmd_file)
yaml_start = which(lines == '---')[1]
yaml_end = which(lines == '---')[2]
yaml_content = lines[yaml_start:yaml_end]
# Render the Rmd to HTML
rmarkdown::render(rmd_file, output_format = 'html_document', output_file = basename(html_file), quiet = TRUE)
# Read rendered HTML and extract body content
html_lines = readLines(html_file)
body_start = grep('<body>', html_lines)[1]
body_end = grep('</body>', html_lines)[1]
if (!is.na(body_start) && !is.na(body_end)) {
body_content = html_lines[(body_start + 1):(body_end - 1)]
body_content = body_content[!grepl('class=\"container-fluid main-container\"', body_content)]
body_content = body_content[body_content != '</div>'][1:(length(body_content) - 1)]
} else {
body_content = html_lines
}
# Write final HTML with YAML frontmatter preserved
final_content = c(yaml_content, '', body_content)
writeLines(final_content, html_file)
message('Rendered: ', basename(rmd_file))
}
"Alternatively, render a single file:
Rscript -e "rmarkdown::render('content/lecture-notes/01-introduction.Rmd')"Note: After rendering, you may need to manually ensure the YAML frontmatter is preserved in the output HTML file for Hugo to process it correctly.
Slides are in slides/ and use xaringan. To render slides to HTML:
Rscript -e "rmarkdown::render('slides/01-slides-intro.Rmd')"To view rendered slides locally (recommended for embedded media like YouTube), serve the slides/ directory over HTTP:
Rscript -e "servr::httw('slides')"Then open http://127.0.0.1:4321/01-slides-intro.html (or the slide file you rendered).
To generate PDF versions of slides, use the slides/make-pdf.R script with pagedown.
The site is automatically deployed via Netlify.
- Push changes to the
mainbranch on GitHub - Netlify automatically detects the push and rebuilds the site
- The site is published at the configured domain
- The
public/directory is ignored and not tracked in git. Netlify builds the site from source. - Make sure to render
.Rmdfiles to.htmlbefore pushing if you've made changes to lecture notes. - The Hugo version used by Netlify is specified in
netlify.toml.
If you need to manually trigger a deployment:
- Go to the Netlify dashboard
- Navigate to the site's Deploys section
- Click "Trigger deploy" > "Deploy site"
.
├── config.yaml # Main Hugo configuration
├── content/ # Site content
│ ├── home/ # Homepage widgets
│ ├── lecture-notes/ # Lecture notes (Rmd and HTML)
│ ├── assignments/ # Assignment pages
│ └── games/ # In-class games
├── slides/ # Xaringan slide decks
├── static/ # Static assets (images, PDFs, etc.)
├── themes/ # Hugo themes (Wowchemy)
└── netlify.toml # Netlify deployment configuration
Make sure you're using Hugo extended version 0.139.0 or later. Check your version with:
hugo versionEnsure you have the required R packages installed:
install.packages(c("rmarkdown", "blogdown", "xaringan"))Some slides use the Lato font. Install it locally or view slides in a browser with internet access.
Slides use locally-hosted MP4 files instead of YouTube embeds for reliable offline playback in classrooms.
Install video download tools (one-time):
brew install yt-dlp ffmpegDownload all videos listed in the manifest:
cd slides/scripts && ./download_videos.shThe script skips already-downloaded files, so it's safe to re-run.
-
Add entry to
slides/video_manifest.csv:VIDEO_ID,NN-descriptive-name.mp4,NN-slides-name.Rmd,LINE,Description
VIDEO_ID: The YouTube video ID (fromyoutube.com/watch?v=VIDEO_ID)- Filename: Use format
NN-topic-description.mp4matching slide file number - LINE: Approximate line number in the Rmd (for reference)
-
Update the Rmd slide file:
In the setup chunk, ensure you have:
source("R/video_helpers.R")Where you want the video, add:
```{r, echo = FALSE} local_video("videos/NN-descriptive-name.mp4")
-
Download the new video:
cd slides/scripts && ./download_videos.sh
-
Test: Knit the slide deck and verify playback works offline.
Check that all videos in the manifest exist:
setwd("slides")
source("R/video_helpers.R")
validate_videos()slides/video_manifest.csv- Master list of all videosslides/videos/- Downloaded MP4 files (git-ignored)slides/scripts/download_videos.sh- Download scriptslides/R/video_helpers.R-local_video()andvalidate_videos()functions