Skip to main content

Building

With every module we build, we are moving toward a clear picture of how content will be managed in our learning management system (LMS).

Currently, this documentation uses Module 101 as an example. In the weeks to come, this documentation will be updated as we continue to iterate on Lesson components and content structures.

Getting Started

Clone the PPBL Front End Template 2023

git clone https://gitlab.com/gimbalabs/ppbl-2023/ppbl-front-end-template-2023
git branch -la

Look for a module-[number]-plannning branch and use git checkout <branch name>. If the branch you need does not exist, create it, and then push updates to GitLab. For example:

git checkout -b module-101-planning
git push --set-upstream origin module-101-planning

Make updates to these files:

Data

In slts-english.json, each Module includes some identifying data, a list of slts and a list of lessons.

When you are building a Module, please only make changes to the list of lessons for that Module.

Example:

"lessons": [
{
"slug": "slts",
"name": "Student Learning Targets",
"video": ""
},
{
"slug": "1011",
"name": "Lesson 1: Compiling Plutus Scripts",
"video": ""
},
...
]
  • slug is used in the page route, as in plutuspbl.io/modules/101/slts or plutuspbl.io/modules/101/1011
  • name is used to populate the Sidebar in each Module. Make changes here to update the lesson names listed in the Sidebar.
  • video is not yet implemented. Stay tuned!

After a module is complete, lessons arrays can be copied from a source slts-language.json file into those of the other languages and translated.

Pages

For each module, you'll find two files: [lesson].tsx and index.tsx, located in the corresponding directory:

/src/pages/modules/[module_id]

You might not have to change these files at all.

[lesson].tsx includes all imports of lesson components. If a new component is added (for example, a 'Summary' component), it can be added to [lesson].tsx. See Module 101 for an example.

In [lesson].tsx you will find another lessons list. Each key must have a corresponding lesson slug in the slts-language.json (mentioned earlier).

Example:

const lessons = [
{ key:"slts", component:<SLTs101 />},
{ key:"1011", component:<Lesson1011 />},
{ key:"1012", component:<Lesson1012 />},
{ key:"1013", component:<Lesson1013 />},
{ key:"1014", component:<Lesson1014 />},
{ key:"1015", component:<Lesson1015 />},
{ key:"1016", component:<Lesson1016 />},
{ key:"summary", component:<Summary101 />},
]

The lessons list defines which routes are valid in site navigation. Each component defines a Lesson component from src/components/course-modules as imported at the top of [lesson].tsx. If you want to add new page routes, do so here.

Components

Most of the Module content will be added to the src/components/course-modules/ directory. For example, take a look at /src/components/course-modules/101.

You will find three types of files:

  • .tsx files
  • .mdx files
  • module.json

Component Details

Let's take an in-depth look at each of the file types in course-modules/[module_id]:

.tsx files:

Each .tsx file is imported into /src/pages/modules/[module_id]/[lesson].tsx as described above. See example.

Here is an example of a Lesson-[slug].tsx component:

import LessonLayout from "@/src/components/lms/Lesson/LessonLayout";
import LessonIntroAndVideo from "@/src/components/lms/Lesson/LessonIntroAndVideo";
import YouWillKnowYouAreSuccessfulIf from "@/src/components/lms/Lesson/YouWillKnowYouAreSuccessfulIf";

import Docs1014 from "@/src/components/course-modules/101/Docs1014.mdx";
import module from "./module101.json";

export default function Lesson1014() {
const slug = "1014";
const lessonDetails = module.lessons.find((lesson) => lesson.slug === slug);

return (
<LessonLayout moduleNumber={101} sltId="101.4" slug="1014">
<LessonIntroAndVideo lessonData={lessonDetails} />
{lessonDetails?.success && (
<YouWillKnowYouAreSuccessfulIf criteria={lessonDetails?.success?.criteria} text={lessonDetails?.success.text} />
)}
<Docs1014 />
</LessonLayout>
);
}

🎉 Note that in this example, there is no lesson text! 🎉

We are moving toward the design of a full-fledged content-management system, and by separating content from components, we make it easier for everyone who is translating the course. However, there are still exceptions to this goal, for example see Lesson 101.1. With each iteration, we get closer to our CMS.

Note the imports at the top of each Lesson-[slug].tsx file.

  • First, we import the LessonLayout, LessonIntroAndVideo and YouWillKnowYouAreSuccesfulIf components. Please review each of these files to get familiar with the current project architecture.
  • Then, we import Docs1014 and module101.json. Keep reading to learn more.

.mdx files:

Docs1014 is a .mdx file. Learn more about .mdx here. In each .mdx file, we can include documentation and embedded React components.

Whenever we need to embed extended documentation, we can follow this approach. Note how each .mdx file is imported into its corresponding .tsx file. Hopefully, this approach makes it easier for translation - let's test it.

module.json

To the extent possible, each .tsx file should be populated by data from slts-language.json and module.json. The module.json file consists of a list of lessons. Each object in lessons looks like this:

 {
"slug": "1011",
"introduction": [
"In this course, you will learn how to write smart contracts that can be used on the Cardano blockchain. In this module, we will take our first look at some of the smart contract languages on Cardano.",
"All of these languages share some basic design patterns, even though each language looks a little different.",
"All of these languages compile to Untyped Plutus Core (UPLC). UPLC can be encoded in Concise Binary Object Representation (CBOR), and this CBOR can be used on the blockchain.",
"To see what this CBOR looks like, watch this video."
],
"links": [
{ "url": "https://well-typed.com/blog/2022/08/plutus-cores/", "linkText": "Well-Typed Blog: The Plutus Compilation Pipeline" },
{ "url": "https://cbor.io/", "linkText": "About CBOR" }
],
"videoHeading": "What does it mean to \"compile a Plutus script\"?",
"youtubeId": "dDkAdzvzrbg",
"successComponent": false,
"success": {
"criteria": "you can compile a contract to UPLC from the language of your choice.",
"text": "To master this learning target, you must attempt at least one of the approaches suggested in Lessons 101.3 through 101.6. Are you ready? If so, move on to Lesson 2."
},
"assignmentComponent": true,
"markdownComponent": false
},

Let's take a look at each:

  • slug: matches the slug in slts-langugage.json
  • introduction: a list of strings. Each maps to a <Text> element in /src/components/lms/Lesson/LessonIntroAndVideo.tsx
  • links: a list of objects with url and linkText params. Each maps to a <ListItem> in /src/components/lms/Lesson/LessonIntroAndVideo.tsx
  • videoHeading: a string. The <Heading> in /src/components/lms/Lesson/VideoComponent.tsx
  • youtubeId: string. The Youtube id passed to <LiteYouTubeEmbed> in /src/components/lms/Lesson/VideoComponent.tsx
  • successComponent: boolean - not yet used
  • success: object with criteria and text params used in /src/components/lms/Lesson/YouWillKnowYouAreSuccessfulIf.tsx. This component is used when there is no automated mastery check.
  • assignmentComponent: boolean - not yet used
  • markdownComponent: boolean - not yet used

Next Steps:

  • add documentation for component in /src/components/lms/ - if you are looking at this now, please get to know each of these. There is some good work ahead in fine tuning each, and creating new ones as needed. See Abstraction

Creating new subdirectories:

When you build lesson-specific demo components, you can create new subdirectories as needed. It was unnecessary to create any such components (yet?) in Module 101. Instead, see ContributorMinter in Module 100