Course website boilerplate

I’m planning to transition a course website from Documenter to Franklin.jl, which I think will help with a number of things. In particular, I have a bunch of boilerplate that needs to be added to each lesson, assignment, lecture etc, a lot of which is duplicated, and I’m trying to sort out the best way to do this. As an example, here’s a lesson page, which as you can see has a number of badges with links to different components (lecture, assignment, repository / description) plus things like due dates. Then it has learning objectives and other metadata about the lesson, etc

A lot of this information is repeated on the assignment page, and furthermore each lesson has a very similar structure with a number of features that could be minimally specified in a toml file or something.

My hope is to have some series of components where I could specify most of the structure once and swap out variables for each lesson, and in the ideal scenario, have something generic where I could just change a few things and specify different parameters for different course runs. One example of a configuration:

author = "Kevin Bonham, PhD"

[lessons]

[lessons.lesson1]
title = "Getting Started"
lecture_links = ["lecture01", "lecture02"]
lecture_dates = [2021-06-09, 2021-06-11]
assignment_link = "assignment01"
assignment_due = 2021-06-14

[lessons.lesson2]
title = "Data Types and Functions"
# ... etc

[assignments]

[assignments.assignment01]
# ... etc

So I feel like I can accomplish this either with a couple of different html templates, a couple of hfuns, or both. And I’m wondering what folks think makes the most sense. I think I’ll end up feeling more comfortable just writing functions since I don’t have much experience making webpages, but are there some advantages to using page templates instead?

4 Likes

I guess that @tlienart will know the best solution.

My idea would be to convert output from a Franklin code block from Markdown to HTML if possible. With that, I would create a function in the website’s package and call that from within the webpages. The great thing about this is that you can “encode” the configuration in Julia syntax, that is, a full generic programming language in contrast to TOML or YAML.

2 Likes

Yes Franklin can definitely help, here’s one way to do this which I think should address what you’re hoping to do, (1) have a standard outer layout defined in _layout as per usual and then for pages do something like

(page path/to/page.md):

+++
lessons = [
  Lesson(title="Getting Started", lecture_links=...)
  Lesson(...)
]
assignments = [
  Assignment(...)
]
+++

# Page title

{{include_lessons}}

{{include_assignments}}

In utils.jl you’d define the Lesson and Assignment struct and how the include should work

using Parameters
@with_kw struct Lesson
    title::String = ""
    lecture_links::Vector{String} = String[]
end
# ...

function hfun_include_lessons()
    lessons = locvar(:lessons)::Vector{Lesson}
    io = IOBuffer()
    for lesson in lessons
        write(io, ...)
    end
    return String(take!(io))
end
# same for hfun_include_assignments

in the write you can write raw HTML that would correspond to how you want things to look when they’re included. You can also use fd2html(s, internal=true) to convert a markdown string s to HTML so you don’t have to bother with it.
Specifically you can do fd2html(read(other_file, String), internal=true) to incorporate the HTML corresponding to specific files (e.g. if the lectures_xxx.md are separate files).

Maybe give this a shot and ping me from your repo for questions/fine tuning?

2 Likes

Fantastic, thanks! This is a great starting point - I’ll give it a go.

1 Like