diff --git a/src/main/java/org/olat/search/_spring/searchContext.xml b/src/main/java/org/olat/search/_spring/searchContext.xml
index f4e20de3c925d4466a96a7812981a42bba079291..089522d6c026b02cd2ae61805dcb71b300a16eb5 100644
--- a/src/main/java/org/olat/search/_spring/searchContext.xml
+++ b/src/main/java/org/olat/search/_spring/searchContext.xml
@@ -172,6 +172,7 @@
 		<property name="indexerList">
 			<list>
 				<ref bean="spCourseNodeIndexer" />
+				<ref bean="documentCourseNodeIndexer" />
 				<ref bean="foCourseNodeIndexer"	/>
 				<ref bean="stCourseNodeIndexer"	/>
 				<ref bean="bcCourseNodeIndexer"	/>
@@ -228,6 +229,7 @@
 	<bean id="pfCourseNodeIndexer" class="org.olat.search.service.indexer.repository.course.PFCourseNodeIndexer" />
 	<bean id="openMeetingsCourseNodeIndexer" class="org.olat.search.service.indexer.repository.course.OpenMeetingsCourseNodeIndexer" />
 	<bean id="spCourseNodeIndexer" class="org.olat.search.service.indexer.repository.course.SPCourseNodeIndexer" />
+	<bean id="documentCourseNodeIndexer" class="org.olat.search.service.indexer.repository.course.DocumentCourseNodeIndexer" />
 	<bean id="foCourseNodeIndexer"	   class="org.olat.search.service.indexer.repository.course.FOCourseNodeIndexer" />
 	<bean id="stCourseNodeIndexer"	   class="org.olat.search.service.indexer.repository.course.STCourseNodeIndexer" />
 	<bean id="bcCourseNodeIndexer"	   class="org.olat.search.service.indexer.repository.course.BCCourseNodeIndexer" />
diff --git a/src/main/java/org/olat/search/service/indexer/repository/CourseIndexer.java b/src/main/java/org/olat/search/service/indexer/repository/CourseIndexer.java
index 762c76b79139b80bb8d9fa77347fb247b23b2f98..58b5c98ce2e2d35894786ada60ebc7fa0b2d45f6 100644
--- a/src/main/java/org/olat/search/service/indexer/repository/CourseIndexer.java
+++ b/src/main/java/org/olat/search/service/indexer/repository/CourseIndexer.java
@@ -84,11 +84,11 @@ public class CourseIndexer extends AbstractHierarchicalIndexer {
 	@Override
 	public void doIndex(SearchResourceContext parentResourceContext, Object parentObject, OlatFullIndexer indexWriter) {
 		RepositoryEntry repositoryEntry = (RepositoryEntry) parentObject;
-		if (log.isDebugEnabled()) log.debug("Analyse Course... repositoryEntry=" + repositoryEntry);
+		if (log.isDebugEnabled()) log.debug("Analyse Course... repositoryEntry={}", repositoryEntry);
 		try {
 			RepositoryEntryStatusEnum status = repositoryEntry.getEntryStatus();
 			if(status.decommissioned()) {
-				if(log.isDebugEnabled()) log.debug("Course not indexed because it's " + status + ": repositoryEntry=" + repositoryEntry);
+				if(log.isDebugEnabled()) log.debug("Course not indexed because it's {}: repositoryEntry={}", status, repositoryEntry);
 				return;
 			}
 
@@ -98,9 +98,9 @@ public class CourseIndexer extends AbstractHierarchicalIndexer {
 			parentResourceContext.setParentContextName(course.getCourseTitle());
 			doIndexCourse( parentResourceContext, course,  course.getRunStructure().getRootNode(), indexWriter);			
 		} catch(CorruptedCourseException ex) {
-			log.warn("Can not index repositoryEntry (" + repositoryEntry.getKey() + ")", ex);
+			log.warn("Can not index repositoryEntry ({})", repositoryEntry.getKey(), ex);
 		} catch (Exception ex) {
-			log.warn("Can not index repositoryEntry=" + repositoryEntry,ex);
+			log.warn("Can not index repositoryEntry={}", repositoryEntry,ex);
 		}
 	}
 
@@ -117,19 +117,19 @@ public class CourseIndexer extends AbstractHierarchicalIndexer {
 	throws IOException,InterruptedException  {
 		//try to index the course node
 		if(node instanceof CourseNode) {
-			if (log.isDebugEnabled()) log.debug("Analyse CourseNode child ... childCourseNode=" + node);
+			if (log.isDebugEnabled()) log.debug("Analyse CourseNode child ... childCourseNode={}", node);
 			// go further with resource
 			CourseNode childCourseNode = (CourseNode)node;
 			CourseNodeIndexer courseNodeIndexer = getCourseNodeIndexer(childCourseNode);
 			if (courseNodeIndexer != null) {
 				if (log.isDebugEnabled()) {
-					log.debug("courseNodeIndexer=" + courseNodeIndexer);
+					log.debug("courseNodeIndexer={}", courseNodeIndexer);
 				}
 				
  				try {
 					courseNodeIndexer.doIndex(repositoryResourceContext, course, childCourseNode, indexWriter);
 				} catch (Exception e) {
-					log.warn("Can not index course node=" + childCourseNode.getIdent(), e);
+					log.warn("Can not index course node={}", childCourseNode.getIdent(), e);
 				}
 			}
 		}
@@ -164,28 +164,30 @@ public class CourseIndexer extends AbstractHierarchicalIndexer {
 			// not a course node of course we have access to the course metadata
 			return true;
 		}
-		if (log.isDebugEnabled()) log.debug("Start identity=" + identity + "  roles=" + roles);
+		
+		boolean debug = log.isDebugEnabled();
+		if (debug) log.debug("Start identity={} roles={}", identity, roles);
 		Long repositoryKey = contextEntry.getOLATResourceable().getResourceableId();
 		RepositoryEntry repositoryEntry = repositoryManager.lookupRepositoryEntry(repositoryKey);
-		if (log.isDebugEnabled()) log.debug("repositoryEntry=" + repositoryEntry );
+		if (debug) log.debug("repositoryEntry={}", repositoryEntry);
 
 		if(roles.isGuestOnly() && repositoryEntry.isGuests()) {
 			return false;
 		}
 		
 		Long nodeId = bcContextEntry.getOLATResourceable().getResourceableId();
-		if (log.isDebugEnabled()) log.debug("nodeId=" + nodeId );
+		if (debug) log.debug("nodeId={}", nodeId);
 		ICourse course = CourseFactory.loadCourse(repositoryEntry);
 		
 		IdentityEnvironment ienv = new IdentityEnvironment();
 		ienv.setIdentity(identity);
 		ienv.setRoles(roles);
 		UserCourseEnvironment userCourseEnv = new UserCourseEnvironmentImpl(ienv, course.getCourseEnvironment());
-		if (log.isDebugEnabled()) log.debug("userCourseEnv=" + userCourseEnv + "ienv=" + ienv );
+		if (debug) log.debug("userCourseEnv={} ienv={}", userCourseEnv, ienv );
 		
 		String nodeIdS = nodeId.toString();
 		CourseNode courseNode = course.getRunStructure().getNode(nodeIdS);
-		if (log.isDebugEnabled()) log.debug("courseNode=" + courseNode );
+		if (debug) log.debug("courseNode={}", courseNode);
 		
 		TreeNode treeNode = CoreSpringFactory.getImpl(NodeAccessService.class)
 				.getCourseTreeModelBuilder(userCourseEnv)
diff --git a/src/main/java/org/olat/search/service/indexer/repository/course/CPCourseNodeIndexer.java b/src/main/java/org/olat/search/service/indexer/repository/course/CPCourseNodeIndexer.java
index 8e72cd2afc220afe358497093267322506141e20..fe0ecf212dbe8cfe3bd45774df93b9d456c93032 100644
--- a/src/main/java/org/olat/search/service/indexer/repository/course/CPCourseNodeIndexer.java
+++ b/src/main/java/org/olat/search/service/indexer/repository/course/CPCourseNodeIndexer.java
@@ -50,9 +50,9 @@ public class CPCourseNodeIndexer extends FolderIndexer implements CourseNodeInde
 
 	// Must correspond with LocalString_xx.properties
 	// Do not use '_' because we want to seach for certain documenttype and lucene haev problems with '_' 
-	public final static String TYPE = "type.course.node.cp";
+	public static final String TYPE = "type.course.node.cp";
 
-	private final static String SUPPORTED_TYPE_NAME = "org.olat.course.nodes.CPCourseNode";
+	private static final String SUPPORTED_TYPE_NAME = "org.olat.course.nodes.CPCourseNode";
 	
 	@Override
 	public void doIndex(SearchResourceContext repositoryResourceContext, ICourse course, CourseNode courseNode, OlatFullIndexer indexWriter)
diff --git a/src/main/java/org/olat/search/service/indexer/repository/course/DocumentCourseNodeIndexer.java b/src/main/java/org/olat/search/service/indexer/repository/course/DocumentCourseNodeIndexer.java
new file mode 100644
index 0000000000000000000000000000000000000000..94ea6d0401b34a8768d6698d7ac850a8a0547029
--- /dev/null
+++ b/src/main/java/org/olat/search/service/indexer/repository/course/DocumentCourseNodeIndexer.java
@@ -0,0 +1,69 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.search.service.indexer.repository.course;
+
+import java.io.IOException;
+
+import org.apache.lucene.document.Document;
+import org.olat.core.util.vfs.VFSContainer;
+import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.course.ICourse;
+import org.olat.course.folder.CourseContainerOptions;
+import org.olat.course.nodes.CourseNode;
+import org.olat.course.nodes.DocumentCourseNode;
+import org.olat.search.service.SearchResourceContext;
+import org.olat.search.service.document.CourseNodeDocument;
+import org.olat.search.service.indexer.LeafIndexer;
+import org.olat.search.service.indexer.OlatFullIndexer;
+
+/**
+ * 
+ * Initial date: 15 janv. 2021<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class DocumentCourseNodeIndexer extends LeafIndexer implements CourseNodeIndexer {
+
+	private static final String SUPPORTED_TYPE_NAME = "org.olat.course.nodes.DocumentCourseNode";
+	public static final String TYPE = "type.course.node.document";
+	
+	@Override
+	public String getSupportedTypeName() {
+		return SUPPORTED_TYPE_NAME;
+	}
+
+	@Override
+	public void doIndex(SearchResourceContext courseResourceContext, ICourse course, CourseNode node,
+			OlatFullIndexer indexWriter) throws IOException, InterruptedException {
+		DocumentCourseNode docNode = (DocumentCourseNode)node;
+		
+		SearchResourceContext courseNodeResourceContext = createSearchResourceContext(courseResourceContext, docNode, TYPE);
+		Document nodeDocument = CourseNodeDocument.createDocument(courseNodeResourceContext, docNode);
+		indexWriter.addDocument(nodeDocument);
+		
+		VFSContainer courseFolderCont = course.getCourseEnvironment()
+				.getCourseFolderContainer(CourseContainerOptions.withoutElements());
+		VFSLeaf vfsLeaf = docNode.getDocumentSource(courseFolderCont).getVfsLeaf();
+		if(vfsLeaf != null) {
+			SearchResourceContext fileContext = new SearchResourceContext(courseNodeResourceContext);
+			doIndexVFSLeafByMySelf(fileContext, vfsLeaf, indexWriter, SUPPORTED_TYPE_NAME);
+		}
+	}
+}