Template integration

Rendering your own output inside course and lesson pages.

How the templates are chosen

POM LMS supplies the single templates for both post types: a course template for course and a lesson template for lesson. They are applied through WordPress's single-template filter.

A theme can replace them the way it replaces any single template, by filtering the template later. Before you do, consider whether a hook does what you need — a replaced template stops receiving the plugin's improvements, and it becomes your job to apply the access checks the original performs.

The hooks inside the pages

Both templates fire the theme's standard post-single actions, so anything already written against POM Theme post singles works on courses and lessons:

Action Fires
pom_before_post_single_content Before the course content
pom_after_post_single_content After the course content
pom_before_lesson_single_content Before the lesson content
pom_after_lesson_single_content After the lesson content
pom_after_post_single_footer After the post footer
pom_after_post_single_author After the author area
pom_after_post_single_nav After the previous/next navigation
pom_after_post_single_comments After the comments

The two lesson-specific actions are the ones to use for lesson features — a downloads list under the video, a notes panel, a call to action after the content.

Content hooks fire inside the accessible branch

The lesson content actions run where the lesson content is rendered, which is the branch reached by students who have access.

Do not rely on that for security. If your callback outputs anything derived from lesson content, check access yourself:

add_action( 'pom_after_lesson_single_content', function () {
    $lesson_id = get_the_ID();

    if ( ! pom_lms_user_can_access_lesson( $lesson_id ) ) {
        return;
    }

    // Safe to render.
} );

A hook that fires in a template you did not write is not an access check. See The access control contract.

The subheader

Lesson pages print the course title in the subheader, through the theme's subheader hook. Course and lesson subheaders are otherwise the theme's, configured by the plugin's settings.

If you are adding to the subheader, do it through the theme's subheader hooks, and check the post type — a callback that assumes a lesson will fatally misbehave on a course.

The outline

The course outline — the progress bar, the sections, the lesson list, the back link — is rendered by the plugin. It is not a hookable structure: there is no action for "before a lesson row" or "after a section".

If you need a different outline, build your own from the queries in Queries and URL helpers, and apply the access helpers per lesson so disabled rows stay disabled.

Lessons load without a full page reload

Opening a lesson from the outline replaces the content rather than reloading the page, with a configurable overlay covering the transition.

That has one consequence for integrators: JavaScript bound on page load will not bind to content that arrives afterwards. Use delegated event handling on a stable ancestor rather than binding directly to elements inside the lesson content.

Styling

The course sidebar uses POM Theme's p-1 helper for 1rem padding. Custom template copies should use the theme's rem helper scale rather than retired pixel-named classes. Update the plugin and theme together; review saved content separately with wp pom migrate-spacing-helpers --dry-run when upgrading an older site.

Course and lesson pages are theme pages, so they inherit the theme's styles. Add your styles through the normal enqueue mechanism, conditioned on the post type:

if ( is_singular( [ 'course', 'lesson' ] ) ) {
    // Enqueue.
}

What not to hook

Do not filter the rendered no-access output to substitute your own message. Site owners configure those texts per course, and an integration that overrides them creates a message nobody can find in the administration.

If a course needs different wording, that is a course field, not code.