Using your own LMS

If you already run a learning management system, Academia reads its courses and maps its fields onto the same cards. There is nothing to migrate and nothing to configure.

Plugin Post type read Subjects from Fields mapped
Tutor LMS courses course-category level, duration, price, free/paid, instructor
LifterLMS course course_cat price, length, difficulty, instructor
Sensei LMS course course-category instructor
LearnDash sfwd-courses ld_course_category instructor

Sensei and LearnDash record less that maps cleanly onto a card, so those two show the title, excerpt, image, subject and instructor. A card only ever shows the facts it actually has, so a thinner source produces a shorter card rather than a row of empty labels.

How the source is chosen

One source is resolved per request, highest priority first: Academia Library, then Tutor, LifterLMS, Sensei, LearnDash, then plain posts. Detection prefers a registered post type over a class name, because plugins move their namespaces between versions and the post type does not.

LifterLMS and Sensei both register a post type called course, so where the post type alone is ambiguous a class check breaks the tie.

If you run two LMS plugins at once, the priority order decides. To force a particular one:

add_filter( 'academia_course_source', function ( $source ) {
	return array_merge( $source, array(
		'slug'      => 'lifter',
		'post_type' => 'course',
		'taxonomy'  => 'course_cat',
		'level_tax' => 'course_difficulty',
		'map'       => 'academia_map_course_lifter',
	) );
} );

Adding a source of your own

Register it with academia_course_sources and supply a mapping callback that fills in whatever your plugin records:

add_filter( 'academia_course_sources', function ( $sources ) {
	return array( 'mine' => array(
		'post_type' => 'my_course',
		'taxonomy'  => 'my_course_cat',
		'level_tax' => '',
		'map'       => 'my_course_mapper',
		'label'     => 'My LMS',
	) ) + $sources;
} );

function my_course_mapper( $course, $post ) {
	$course['duration'] = get_post_meta( $post->ID, '_my_length', true );
	$course['price']    = get_post_meta( $post->ID, '_my_price', true );
	$course['free']     = '' === $course['price'];

	return $course;
}

The normalised shape a mapper receives and must return: id, title, permalink, excerpt, thumbnail_id, level, duration, lessons, price, sale_price, free, instructor, rating, reviews, categories.

Styling an LMS's own pages

Academia styles the course archive and single views it renders itself. An LMS's lesson, quiz, and student-dashboard screens are that plugin's own templates, and Academia inherits rather than restyles them. The theme's typography, colours and form styling apply, but the layout of those screens belongs to the plugin.