diff --git a/src/main/java/org/olat/modules/portfolio/CategoryToElement.java b/src/main/java/org/olat/modules/portfolio/CategoryToElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..e5c18f2104bcd54f090eb49bb4e4763347a2ed76
--- /dev/null
+++ b/src/main/java/org/olat/modules/portfolio/CategoryToElement.java
@@ -0,0 +1,36 @@
+/**
+ * <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.modules.portfolio;
+
+import org.olat.core.id.OLATResourceable;
+
+/**
+ * 
+ * Initial date: 29.06.2016<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public interface CategoryToElement {
+	
+	public Category getCategory();
+	
+	public OLATResourceable getCategorizedResource();
+
+}
diff --git a/src/main/java/org/olat/modules/portfolio/Page.java b/src/main/java/org/olat/modules/portfolio/Page.java
index 674b60d918b2d48e0d2b7ac395f9951ece30e6d2..336e2782bb8713ab8e22be4fd8c0ca31ac89c657 100644
--- a/src/main/java/org/olat/modules/portfolio/Page.java
+++ b/src/main/java/org/olat/modules/portfolio/Page.java
@@ -33,6 +33,10 @@ public interface Page extends PortfolioElement {
 	
 	public PageStatus getPageStatus();
 	
+	public Date getInitialPublicationDate();
+	
+	public Date getLastPublicationDate();
+	
 	public void setTitle(String title);
 	
 	public String getSummary();
diff --git a/src/main/java/org/olat/modules/portfolio/PortfolioElement.java b/src/main/java/org/olat/modules/portfolio/PortfolioElement.java
index 093acb329d1e0a8630da5b675ef24b9bf32759e6..08717659186e913dee70b40f7706899dc1521618 100644
--- a/src/main/java/org/olat/modules/portfolio/PortfolioElement.java
+++ b/src/main/java/org/olat/modules/portfolio/PortfolioElement.java
@@ -40,5 +40,6 @@ public interface PortfolioElement {
 	public Group getBaseGroup();
 	
 	public PortfolioElementType getType();
+	
 
 }
diff --git a/src/main/java/org/olat/modules/portfolio/PortfolioService.java b/src/main/java/org/olat/modules/portfolio/PortfolioService.java
index b54745d764e734266cea8ceca5313b8b1fc2e11d..8c06067303ea611e75d3775dec27ef2770ceb2c8 100644
--- a/src/main/java/org/olat/modules/portfolio/PortfolioService.java
+++ b/src/main/java/org/olat/modules/portfolio/PortfolioService.java
@@ -130,6 +130,7 @@ public interface PortfolioService {
 	
 	/**
 	 * Check if this template is used, has some copies.
+	 * 
 	 * @param template
 	 * @param courseEntry
 	 * @param subIdent
@@ -143,6 +144,7 @@ public interface PortfolioService {
 	
 	/**
 	 * The list of owners of the binder.
+	 * 
 	 * @param binder
 	 * @param roles At least a role need to be specified
 	 * @return
@@ -157,9 +159,34 @@ public interface PortfolioService {
 	
 	public void changeAccessRights(List<Identity> identities, List<AccessRightChange> changes);
 	
-	public List<Category> getCategories(Binder binder);
+	public List<Category> getCategories(PortfolioElement element);
+	
+	/**
+	 * Get the categories of the sections and pages under the specified binder.
+	 * 
+	 * @param binder
+	 * @return
+	 */
+	public List<CategoryToElement> getCategorizedSectionsAndPages(BinderRef binder);
+	
+	/**
+	 * Get the categories of the section and the pages under the specified section.
+	 * 
+	 * @param section
+	 * @return
+	 */
+	public List<CategoryToElement> getCategorizedSectionAndPages(SectionRef section);
+
+	/**
+	 * Get the categories of the pages that the specified user owned.
+	 * 
+	 * @param owner
+	 * @return
+	 */
+	public List<CategoryToElement> getCategorizedOwnedPages(IdentityRef owner);
+	
 
-	public void updateCategories(Binder binder, List<String> categories);
+	public void updateCategories(PortfolioElement element, List<String> categories);
 	
 	public File getPosterImageFile(BinderLight binder);
 	
diff --git a/src/main/java/org/olat/modules/portfolio/handler/TextHandler.java b/src/main/java/org/olat/modules/portfolio/handler/TextHandler.java
index 96c3dd41c16b8821460f151c19b90a3db37bec62..2aa8d0db682a73206b6586280d9f1da529ba9a27 100644
--- a/src/main/java/org/olat/modules/portfolio/handler/TextHandler.java
+++ b/src/main/java/org/olat/modules/portfolio/handler/TextHandler.java
@@ -24,12 +24,14 @@ import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.id.Identity;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.modules.portfolio.Media;
 import org.olat.modules.portfolio.MediaInformations;
 import org.olat.modules.portfolio.MediaLight;
 import org.olat.modules.portfolio.manager.MediaDAO;
 import org.olat.modules.portfolio.ui.media.TextMediaController;
+import org.olat.portfolio.manager.EPFrontendManager;
 import org.olat.portfolio.model.artefacts.AbstractArtefact;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -47,6 +49,8 @@ public class TextHandler extends AbstractMediaHandler {
 	
 	@Autowired
 	private MediaDAO mediaDao;
+	@Autowired
+	private EPFrontendManager oldPortfolioManager;
 
 	public TextHandler() {
 		super(TEXT_MEDIA);
@@ -78,6 +82,10 @@ public class TextHandler extends AbstractMediaHandler {
 		String title = artefact.getTitle();
 		String description = artefact.getDescription();
 		String content = artefact.getFulltextContent();
+		if(!StringHelper.containsNonWhitespace(content)) {
+			content = oldPortfolioManager.getArtefactFullTextContent(artefact);
+		}
+		
 		String businessPath = artefact.getBusinessPath();
 		if(businessPath == null) {
 			businessPath = "[PortfolioV2:0][MediaCenter:0]";
diff --git a/src/main/java/org/olat/modules/portfolio/manager/BinderDAO.java b/src/main/java/org/olat/modules/portfolio/manager/BinderDAO.java
index 4f5ef667657e29fae608cb18abaed9ca4ad0fd20..8257fd3a009cd7740ec3a5626edf1dbb6c287e94 100644
--- a/src/main/java/org/olat/modules/portfolio/manager/BinderDAO.java
+++ b/src/main/java/org/olat/modules/portfolio/manager/BinderDAO.java
@@ -195,6 +195,11 @@ public class BinderDAO {
 			.getResultList();
 	}
 	
+	/**
+	 * The same type of query is user for the categories
+	 * @param owner
+	 * @return
+	 */
 	public List<BinderRow> searchOwnedBinders(IdentityRef owner) {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select binder.key, binder.title, binder.imagePath, binder.lastModified, binder.status,")
diff --git a/src/main/java/org/olat/modules/portfolio/manager/CategoryDAO.java b/src/main/java/org/olat/modules/portfolio/manager/CategoryDAO.java
index 60f750acb3692f782febc61c42caf8c54365535d..fab4b9deb049bef765842d7aba169a066fc7fa60 100644
--- a/src/main/java/org/olat/modules/portfolio/manager/CategoryDAO.java
+++ b/src/main/java/org/olat/modules/portfolio/manager/CategoryDAO.java
@@ -22,9 +22,14 @@ package org.olat.modules.portfolio.manager;
 import java.util.Date;
 import java.util.List;
 
+import org.olat.basesecurity.GroupRoles;
+import org.olat.basesecurity.IdentityRef;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.OLATResourceable;
+import org.olat.modules.portfolio.BinderRef;
 import org.olat.modules.portfolio.Category;
+import org.olat.modules.portfolio.CategoryToElement;
+import org.olat.modules.portfolio.SectionRef;
 import org.olat.modules.portfolio.model.CategoryImpl;
 import org.olat.modules.portfolio.model.CategoryToElementImpl;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -87,5 +92,53 @@ public class CategoryDAO {
 			.setParameter("resId", ores.getResourceableId())
 			.getResultList();
 	}
+	
+	public List<CategoryToElement> getCategorizedSectionsAndPages(BinderRef binder) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("select rel from pfcategoryrelation as rel")
+		  .append(" inner join fetch rel.category as category")
+		  .append(" where exists (select binder from pfbinder as binder")
+		  .append("   inner join binder.sections as section")
+		  .append("   inner join section.pages as page")
+		  .append("   where binder.key=:binderKey")
+		  .append("   and ((rel.resId=page.key and rel.resName='Page') or (rel.resId=section.key and rel.resName='Section'))")
+		  .append(" )");
+		return dbInstance.getCurrentEntityManager()
+			.createQuery(sb.toString(), CategoryToElement.class)
+			.setParameter("binderKey", binder.getKey())
+			.getResultList();
+	}
+	
+	public List<CategoryToElement> getCategorizedSectionAndPages(SectionRef section) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("select rel from pfcategoryrelation as rel")
+		  .append(" inner join fetch rel.category as category")
+		  .append(" where exists (select section from pfsection as section")
+		  .append("   inner join section.pages as page")
+		  .append("   where section.key=:sectionKey")
+		  .append("   and ((rel.resId=page.key and rel.resName='Page') or (rel.resId=section.key and rel.resName='Section'))")
+		  .append(" )");
+		return dbInstance.getCurrentEntityManager()
+			.createQuery(sb.toString(), CategoryToElement.class)
+			.setParameter("sectionKey", section.getKey())
+			.getResultList();
+	}
+	
+	public List<CategoryToElement> getCategorizedOwnedPages(IdentityRef identity) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("select rel from pfcategoryrelation as rel")
+		  .append(" inner join fetch rel.category as category")
+		  .append(" inner join pfpage as page on (rel.resId=page.key and rel.resName='Page')")
+		  .append(" left join pfsection as section on (section.key = page.section.key)")
+		  .append(" left join pfbinder as binder on (binder.key=section.binder.key)")
+		  .append(" where exists (select pageMember from bgroupmember as pageMember")
+		  .append("   inner join pageMember.identity as ident on (ident.key=:ownerKey and pageMember.role='").append(GroupRoles.owner.name()).append("')")
+		  .append("   where pageMember.group.key=page.baseGroup.key or pageMember.group.key=binder.baseGroup.key")
+		  .append(" )");
+		return dbInstance.getCurrentEntityManager()
+			.createQuery(sb.toString(), CategoryToElement.class)
+			.setParameter("ownerKey", identity.getKey())
+			.getResultList();
+	}
 
 }
diff --git a/src/main/java/org/olat/modules/portfolio/manager/PageDAO.java b/src/main/java/org/olat/modules/portfolio/manager/PageDAO.java
index f2aef4fb6c62e450d0ef8a62436e465661ddf371..99e52da416981d4405166391d77874650787de53 100644
--- a/src/main/java/org/olat/modules/portfolio/manager/PageDAO.java
+++ b/src/main/java/org/olat/modules/portfolio/manager/PageDAO.java
@@ -147,7 +147,7 @@ public class PageDAO {
 		  .append(" left join section.binder as binder")
 		  .append(" where exists (select pageMember from bgroupmember as pageMember")
 		  .append("     inner join pageMember.identity as ident on (ident.key=:ownerKey and pageMember.role='").append(GroupRoles.owner.name()).append("')")
-		  .append("  	where pageMember.group.key=page.baseGroup.key or pageMember.group.key=binder.baseGroup.key or pageMember.group.key=page.baseGroup.key")
+		  .append("  	where pageMember.group.key=page.baseGroup.key or pageMember.group.key=binder.baseGroup.key")
 		  .append(" )");
 		
 		List<Page> pages = dbInstance.getCurrentEntityManager()
diff --git a/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java b/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java
index b3a658cc62a2b3f8e35742a9526fac8f2175708f..57f968b785f9ed09638236f7229ffb68b11608f1 100644
--- a/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java
+++ b/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java
@@ -59,6 +59,7 @@ import org.olat.modules.portfolio.Binder;
 import org.olat.modules.portfolio.BinderLight;
 import org.olat.modules.portfolio.BinderRef;
 import org.olat.modules.portfolio.Category;
+import org.olat.modules.portfolio.CategoryToElement;
 import org.olat.modules.portfolio.Media;
 import org.olat.modules.portfolio.MediaHandler;
 import org.olat.modules.portfolio.MediaLight;
@@ -330,16 +331,40 @@ public class PortfolioServiceImpl implements PortfolioService {
 	}
 
 	@Override
-	public List<Category> getCategories(Binder binder) {
-		OLATResourceable ores = OresHelper.createOLATResourceableInstance(Binder.class, binder.getKey());
+	public List<Category> getCategories(PortfolioElement element) {
+		OLATResourceable ores = getOLATResoucreable(element);
 		return categoryDao.getCategories(ores);
 	}
 
 	@Override
-	public void updateCategories(Binder binder, List<String> categories) {
-		OLATResourceable ores = OresHelper.createOLATResourceableInstance(Binder.class, binder.getKey());
+	public List<CategoryToElement> getCategorizedSectionsAndPages(BinderRef binder) {
+		return categoryDao.getCategorizedSectionsAndPages(binder);
+	}
+
+	@Override
+	public List<CategoryToElement> getCategorizedSectionAndPages(SectionRef section) {
+		return categoryDao.getCategorizedSectionAndPages(section);
+	}
+
+	@Override
+	public List<CategoryToElement> getCategorizedOwnedPages(IdentityRef owner) {
+		return categoryDao.getCategorizedOwnedPages(owner);
+	}
+
+	@Override
+	public void updateCategories(PortfolioElement element, List<String> categories) {
+		OLATResourceable ores = getOLATResoucreable(element);
 		updateCategories(ores, categories);
 	}
+	
+	private OLATResourceable getOLATResoucreable(PortfolioElement element) {
+		switch(element.getType()) {
+			case binder: return OresHelper.createOLATResourceableInstance(Binder.class, element.getKey());
+			case section: return OresHelper.createOLATResourceableInstance(Section.class, element.getKey());
+			case page: return OresHelper.createOLATResourceableInstance(Page.class, element.getKey());
+			default: return null;
+		}
+	}
 
 	private void updateCategories(OLATResourceable oresource, List<String> categories) {
 		List<Category> currentCategories = categoryDao.getCategories(oresource);
@@ -536,6 +561,13 @@ public class PortfolioServiceImpl implements PortfolioService {
 	public Page changePageStatus(Page page, PageStatus status) {
 		Page reloadedPage = pageDao.loadByKey(page.getKey());
 		((PageImpl)reloadedPage).setPageStatus(status);
+		if(status == PageStatus.published) {
+			Date now = new Date();
+			if(reloadedPage.getInitialPublicationDate() == null) {
+				((PageImpl)reloadedPage).setInitialPublicationDate(now);
+			}
+			((PageImpl)reloadedPage).setLastPublicationDate(now);
+		}
 		return pageDao.updatePage(reloadedPage);
 	}
 
diff --git a/src/main/java/org/olat/modules/portfolio/model/CategoryToElementImpl.java b/src/main/java/org/olat/modules/portfolio/model/CategoryToElementImpl.java
index 8bc403094087292bc50f2c1ce5c6e5e4847a97b8..f77dadf10ba9b0b02a7b5ad0d9092002bddf71d1 100644
--- a/src/main/java/org/olat/modules/portfolio/model/CategoryToElementImpl.java
+++ b/src/main/java/org/olat/modules/portfolio/model/CategoryToElementImpl.java
@@ -32,10 +32,14 @@ import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
+import javax.persistence.Transient;
 
 import org.olat.core.id.CreateInfo;
+import org.olat.core.id.OLATResourceable;
 import org.olat.core.id.Persistable;
+import org.olat.core.util.resource.OresHelper;
 import org.olat.modules.portfolio.Category;
+import org.olat.modules.portfolio.CategoryToElement;
 
 /**
  * 
@@ -47,7 +51,7 @@ import org.olat.modules.portfolio.Category;
  */
 @Entity(name="pfcategoryrelation")
 @Table(name="o_pf_category_relation")
-public class CategoryToElementImpl implements Persistable, CreateInfo {
+public class CategoryToElementImpl implements CategoryToElement, Persistable, CreateInfo {
 
 	private static final long serialVersionUID = -5196328449832113662L;
 
@@ -104,6 +108,7 @@ public class CategoryToElementImpl implements Persistable, CreateInfo {
 		this.resId = resId;
 	}
 
+	@Override
 	public Category getCategory() {
 		return category;
 	}
@@ -111,6 +116,12 @@ public class CategoryToElementImpl implements Persistable, CreateInfo {
 	public void setCategory(Category category) {
 		this.category = category;
 	}
+	
+	@Override
+	@Transient
+	public OLATResourceable getCategorizedResource() {
+		return OresHelper.createOLATResourceableInstance(resName, resId);
+	}
 
 	@Override
 	public int hashCode() {
diff --git a/src/main/java/org/olat/modules/portfolio/model/PageImpl.java b/src/main/java/org/olat/modules/portfolio/model/PageImpl.java
index e8670ba2435f4be5b2eb4777a421fefee647d6ea..71db3a5536cafd23e698bd588bce78a8facb399a 100644
--- a/src/main/java/org/olat/modules/portfolio/model/PageImpl.java
+++ b/src/main/java/org/olat/modules/portfolio/model/PageImpl.java
@@ -69,7 +69,7 @@ public class PageImpl implements Persistable, ModifiedInfo, CreateInfo, Page {
 	@Temporal(TemporalType.TIMESTAMP)
 	@Column(name="lastmodified", nullable=false, insertable=true, updatable=true)
 	private Date lastModified;
-	
+
 	/** Only used for order by */
 	@GeneratedValue
 	@Column(name="pos")
@@ -161,6 +161,24 @@ public class PageImpl implements Persistable, ModifiedInfo, CreateInfo, Page {
 	public void setStatus(String status) {
 		this.status = status;
 	}
+	
+	@Override
+	public Date getInitialPublicationDate() {
+		return initialPublicationDate;
+	}
+
+	public void setInitialPublicationDate(Date initialPublicationDate) {
+		this.initialPublicationDate = initialPublicationDate;
+	}
+
+	@Override
+	public Date getLastPublicationDate() {
+		return lastPublicationDate;
+	}
+
+	public void setLastPublicationDate(Date lastPublicationDate) {
+		this.lastPublicationDate = lastPublicationDate;
+	}
 
 	@Override
 	public String getTitle() {
diff --git a/src/main/java/org/olat/modules/portfolio/model/PageRow.java b/src/main/java/org/olat/modules/portfolio/model/PageRow.java
index e8189febdb60783101d0673cc79f5a801be6540b..433ba7100da4800325867a157bc022bef55e905b 100644
--- a/src/main/java/org/olat/modules/portfolio/model/PageRow.java
+++ b/src/main/java/org/olat/modules/portfolio/model/PageRow.java
@@ -19,6 +19,7 @@
  */
 package org.olat.modules.portfolio.model;
 
+import java.util.Collection;
 import java.util.Date;
 
 import org.olat.core.gui.components.form.flexible.elements.FormLink;
@@ -44,6 +45,9 @@ public class PageRow {
 	private boolean firstPageOfSection;
 	private final AssessmentSection assessmentSection;
 	
+	private Collection<String> pageCategories;
+	private Collection<String> sectionCategories;
+	
 	private Link openLink;
 	private FormLink openFormLink;
 	private FormLink newEntryLink;
@@ -81,6 +85,14 @@ public class PageRow {
 		return page.getLastModified();
 	}
 	
+	public boolean hasLastPublicationDate() {
+		return page != null && page.getLastPublicationDate() != null;
+	}
+	
+	public Date getLastPublicationDate() {
+		return page.getLastPublicationDate();
+	}
+	
 	public String getCssClassStatus() {
 		return page.getPageStatus() == null
 				? PageStatus.draft.cssClass() : page.getPageStatus().cssClass();
@@ -133,6 +145,30 @@ public class PageRow {
 		this.firstPageOfSection = firstPageOfSection;
 	}
 	
+	public boolean hasPageCategories() {
+		return pageCategories != null && pageCategories.size() > 0;
+	}
+	
+	public Collection<String> getPageCategories() {
+		return pageCategories;
+	}
+
+	public void setPageCategories(Collection<String> pageCategories) {
+		this.pageCategories = pageCategories;
+	}
+	
+	public boolean hasSectionCategories() {
+		return sectionCategories != null && sectionCategories.size() > 0;
+	}
+
+	public Collection<String> getSectionCategories() {
+		return sectionCategories;
+	}
+
+	public void setSectionCategories(Collection<String> sectionCategories) {
+		this.sectionCategories = sectionCategories;
+	}
+
 	public boolean isAssessable() {
 		return assessable;
 	}
diff --git a/src/main/java/org/olat/modules/portfolio/ui/AbstractPageListController.java b/src/main/java/org/olat/modules/portfolio/ui/AbstractPageListController.java
index 7eed82582d9a9714e46380d9d573a6af1eaaa1a6..702c2c34beee439bae268e20454c0dd699c12dfe 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/AbstractPageListController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/AbstractPageListController.java
@@ -19,7 +19,9 @@
  */
 package org.olat.modules.portfolio.ui;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
@@ -44,12 +46,15 @@ import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
 import org.olat.core.gui.control.generic.dtabs.Activateable2;
+import org.olat.core.id.OLATResourceable;
 import org.olat.core.id.context.ContextEntry;
 import org.olat.core.id.context.StateEntry;
 import org.olat.core.util.StringHelper;
+import org.olat.core.util.resource.OresHelper;
 import org.olat.modules.portfolio.AssessmentSection;
 import org.olat.modules.portfolio.BinderConfiguration;
 import org.olat.modules.portfolio.BinderSecurityCallback;
+import org.olat.modules.portfolio.Category;
 import org.olat.modules.portfolio.Page;
 import org.olat.modules.portfolio.PortfolioService;
 import org.olat.modules.portfolio.Section;
@@ -133,7 +138,9 @@ implements Activateable2, TooledController, FlexiTableComponentDelegate {
 	
 	protected abstract void loadModel();
 	
-	protected PageRow forgeRow(Page page, AssessmentSection assessmentSection, boolean firstOfSection) {
+	protected PageRow forgeRow(Page page, AssessmentSection assessmentSection, boolean firstOfSection,
+			Map<OLATResourceable,List<Category>> categorizedElementMap) {
+
 		PageRow row = new PageRow(page, page.getSection(), assessmentSection, firstOfSection, config.isAssessable());
 		String openLinkId = "open_" + (++counter);
 		FormLink openLink = uifactory.addFormLink(openLinkId, "open.full", "open.full.page", null, flc, Link.BUTTON_SMALL);
@@ -141,10 +148,13 @@ implements Activateable2, TooledController, FlexiTableComponentDelegate {
 		openLink.setPrimary(true);
 		row.setOpenFormLink(openLink);
 		openLink.setUserObject(row);
+		addCategoriesToRow(row, categorizedElementMap);
 		return row;
 	}
 	
-	protected PageRow forgeRow(Section section, AssessmentSection assessmentSection, boolean firstOfSection) {
+	protected PageRow forgeRow(Section section, AssessmentSection assessmentSection, boolean firstOfSection,
+			Map<OLATResourceable,List<Category>> categorizedElementMap) {
+		
 		PageRow row = new PageRow(null, section, assessmentSection, firstOfSection, config.isAssessable());
 		String openLinkId = "open_" + (++counter);
 		FormLink openLink = uifactory.addFormLink(openLinkId, "open.full", "open.full.page", null, flc, Link.BUTTON_SMALL);
@@ -152,9 +162,33 @@ implements Activateable2, TooledController, FlexiTableComponentDelegate {
 		openLink.setPrimary(true);
 		row.setOpenFormLink(openLink);
 		openLink.setUserObject(row);
+		addCategoriesToRow(row, categorizedElementMap);
 		return row;
 	}
 	
+	private void addCategoriesToRow(PageRow row, Map<OLATResourceable,List<Category>> categorizedElementMap) {
+		if(categorizedElementMap != null) {
+			if(row.getPage() != null) {
+				OLATResourceable ores = OresHelper.createOLATResourceableInstance(Page.class, row.getPage().getKey());
+				row.setPageCategories(getCategories(ores, categorizedElementMap));
+			}
+		}
+	}
+	
+	private List<String> getCategories(OLATResourceable ores, Map<OLATResourceable,List<Category>> categorizedElementMap) {
+		List<String> strings = null;
+		List<Category> categories = categorizedElementMap.get(ores);
+		if(categories != null && categories.size() > 0) {
+			strings = new ArrayList<>(categories.size());
+			for(Category category:categories) {
+				strings.add(category.getName());
+			}
+		}
+		return strings;
+	}
+	
+	
+	
 	@Override
 	public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
 		//
diff --git a/src/main/java/org/olat/modules/portfolio/ui/BinderPageListController.java b/src/main/java/org/olat/modules/portfolio/ui/BinderPageListController.java
index 7ffc5c788e12756d0a0aad0ff30ef60dbe38bc41..d90121326dc753b3b1f9a2573d81b41ce2e06e9b 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/BinderPageListController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/BinderPageListController.java
@@ -21,8 +21,10 @@ package org.olat.modules.portfolio.ui;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.olat.core.commons.persistence.SortKey;
 import org.olat.core.gui.UserRequest;
@@ -40,10 +42,13 @@ import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
+import org.olat.core.id.OLATResourceable;
 import org.olat.modules.portfolio.AssessmentSection;
 import org.olat.modules.portfolio.Binder;
 import org.olat.modules.portfolio.BinderConfiguration;
 import org.olat.modules.portfolio.BinderSecurityCallback;
+import org.olat.modules.portfolio.Category;
+import org.olat.modules.portfolio.CategoryToElement;
 import org.olat.modules.portfolio.Page;
 import org.olat.modules.portfolio.Section;
 import org.olat.modules.portfolio.SectionStatus;
@@ -96,6 +101,18 @@ public class BinderPageListController extends AbstractPageListController  {
 	protected void loadModel() {
 		List<Section> sections = portfolioService.getSections(binder);
 		
+		List<CategoryToElement> categorizedElements = portfolioService.getCategorizedSectionsAndPages(binder);
+		Map<OLATResourceable,List<Category>> categorizedElementMap = new HashMap<>();
+		Map<Section,Set<String>> sectionAggregatedCategoriesMap = new HashMap<>();
+		for(CategoryToElement categorizedElement:categorizedElements) {
+			List<Category> categories = categorizedElementMap.get(categorizedElement.getCategorizedResource());
+			if(categories == null) {
+				categories = new ArrayList<>();
+				categorizedElementMap.put(categorizedElement.getCategorizedResource(), categories);
+			}
+			categories.add(categorizedElement.getCategory());
+		}
+		
 		List<AssessmentSection> assessmentSections = portfolioService.getAssessmentSections(binder, getIdentity());
 		Map<Section,AssessmentSection> sectionToAssessmentSectionMap = new HashMap<>();
 		for(AssessmentSection assessmentSection:assessmentSections) {
@@ -110,7 +127,7 @@ public class BinderPageListController extends AbstractPageListController  {
 			if (sections.remove(section)) {
 				first = true;
 			}
-			PageRow pageRow = forgeRow(page, sectionToAssessmentSectionMap.get(section), first);
+			PageRow pageRow = forgeRow(page, sectionToAssessmentSectionMap.get(section), first, categorizedElementMap);
 			rows.add(pageRow);
 			if(secCallback.canAddPage() && section != null
 					&& section.getSectionStatus() != SectionStatus.closed
@@ -120,10 +137,24 @@ public class BinderPageListController extends AbstractPageListController  {
 				newEntryButton.setUserObject(pageRow);
 				pageRow.setNewEntryLink(newEntryButton);
 			}
+			
+			if(section != null) {
+				Set<String> categories = sectionAggregatedCategoriesMap.get(section);
+				if(categories == null) {
+					categories = new HashSet<>();
+					sectionAggregatedCategoriesMap.put(section, categories);
+				}
+				if(pageRow.hasPageCategories()) {
+					categories.addAll(pageRow.getPageCategories());
+				}
+				
+				pageRow.setSectionCategories(categories);
+			}
 		}
 		
+		//sections without pages
 		for(Section section:sections) {
-			PageRow pageRow = forgeRow(section, sectionToAssessmentSectionMap.get(section), true);
+			PageRow pageRow = forgeRow(section, sectionToAssessmentSectionMap.get(section), true, categorizedElementMap);
 			rows.add(pageRow);
 			if(secCallback.canAddPage() && section != null
 					&& section.getSectionStatus() != SectionStatus.closed
diff --git a/src/main/java/org/olat/modules/portfolio/ui/MyPageListController.java b/src/main/java/org/olat/modules/portfolio/ui/MyPageListController.java
index 94f708d8876ed4ac9ad3b00722cc43ce3b7ec828..3b1b8b271b416451b7dea82677313f6e30ede047 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/MyPageListController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/MyPageListController.java
@@ -20,7 +20,9 @@
 package org.olat.modules.portfolio.ui;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
@@ -32,8 +34,11 @@ import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
+import org.olat.core.id.OLATResourceable;
 import org.olat.modules.portfolio.BinderConfiguration;
 import org.olat.modules.portfolio.BinderSecurityCallback;
+import org.olat.modules.portfolio.Category;
+import org.olat.modules.portfolio.CategoryToElement;
 import org.olat.modules.portfolio.Page;
 import org.olat.modules.portfolio.model.PageRow;
 
@@ -67,10 +72,21 @@ public class MyPageListController extends AbstractPageListController {
 
 	@Override
 	protected void loadModel() {
+		List<CategoryToElement> categorizedElements = portfolioService.getCategorizedOwnedPages(getIdentity());
+		Map<OLATResourceable,List<Category>> categorizedElementMap = new HashMap<>();
+		for(CategoryToElement categorizedElement:categorizedElements) {
+			List<Category> categories = categorizedElementMap.get(categorizedElement.getCategorizedResource());
+			if(categories == null) {
+				categories = new ArrayList<>();
+				categorizedElementMap.put(categorizedElement.getCategorizedResource(), categories);
+			}
+			categories.add(categorizedElement.getCategory());
+		}
+		
 		List<Page> pages = portfolioService.searchOwnedPages(getIdentity());
 		List<PageRow> rows = new ArrayList<>(pages.size());
 		for (Page page : pages) {
-			rows.add(forgeRow(page, null, false));
+			rows.add(forgeRow(page, null, false, categorizedElementMap));
 		}
 		model.setObjects(rows);
 		tableEl.reset();
diff --git a/src/main/java/org/olat/modules/portfolio/ui/PageController.java b/src/main/java/org/olat/modules/portfolio/ui/PageController.java
index 432b20df6ccadb07b9410dbf000e7b909f720b7b..a621d2ac3d1c5d1c9eb9aed35ee88c74978651d9 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/PageController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/PageController.java
@@ -154,6 +154,7 @@ public class PageController extends BasicController implements TooledController
 		} else if(editMetadataCtrl == source) {
 			if(event == Event.DONE_EVENT) {
 				loadModel(ureq);
+				fireEvent(ureq, Event.CHANGED_EVENT);
 			}
 			cmc.deactivate();
 			cleanUp();
diff --git a/src/main/java/org/olat/modules/portfolio/ui/PageMetadataEditController.java b/src/main/java/org/olat/modules/portfolio/ui/PageMetadataEditController.java
index 28f9e8d2f7f513d1fc1e94e2d67189222f6be11d..597cd285642aa59c3f9fe1f68c0904525f1daa42 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/PageMetadataEditController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/PageMetadataEditController.java
@@ -20,8 +20,10 @@
 package org.olat.modules.portfolio.ui;
 
 import java.io.File;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import org.olat.core.gui.UserRequest;
@@ -29,6 +31,7 @@ import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FileElement;
 import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
+import org.olat.core.gui.components.form.flexible.elements.TextBoxListElement;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
 import org.olat.core.gui.components.form.flexible.impl.FormEvent;
@@ -39,6 +42,7 @@ import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.util.StringHelper;
 import org.olat.modules.portfolio.Binder;
+import org.olat.modules.portfolio.Category;
 import org.olat.modules.portfolio.Page;
 import org.olat.modules.portfolio.PortfolioService;
 import org.olat.modules.portfolio.Section;
@@ -64,6 +68,7 @@ public class PageMetadataEditController extends FormBasicController {
 	
 	private TextElement titleEl, summaryEl;
 	private SingleSelection bindersEl, sectionsEl;
+	private TextBoxListElement categoriesEl;
 	
 	private FileElement fileUpload;
 	private static final int picUploadlimitKB = 5120;
@@ -74,6 +79,9 @@ public class PageMetadataEditController extends FormBasicController {
 	
 	private final boolean chooseBinder;
 	private final boolean chooseSection;
+
+	private Map<String,String> categories = new HashMap<>();
+	private Map<String,Category> categoriesMap = new HashMap<>();
 	
 	@Autowired
 	private PortfolioService portfolioService;
@@ -104,6 +112,14 @@ public class PageMetadataEditController extends FormBasicController {
 		this.chooseBinder = chooseBinder;
 		this.chooseSection = chooseSection;
 		
+		if(page != null) {
+			List<Category> tags = portfolioService.getCategories(page);
+			for(Category tag:tags) {
+				categories.put(tag.getName(), tag.getName());
+				categoriesMap.put(tag.getName(), tag);
+			}
+		}
+		
 		initForm(ureq);
 	}
 
@@ -176,6 +192,10 @@ public class PageMetadataEditController extends FormBasicController {
 			bindersEl.setEnabled(false);
 		}
 
+		categoriesEl = uifactory.addTextBoxListElement("categories", "categories", "categories.hint", categories, formLayout, getTranslator());
+		categoriesEl.setElementCssClass("o_sel_ep_tagsinput");
+		categoriesEl.setAllowDuplicates(false);
+
 		//list of sections
 		if(chooseSection) {
 			retrieveSections(formLayout, true);
@@ -272,7 +292,7 @@ public class PageMetadataEditController extends FormBasicController {
 				imagePath = portfolioService.addPosterImageForPage(fileUpload.getUploadFile(),
 						fileUpload.getUploadFileName());
 			}
-			portfolioService.appendNewPage(getIdentity(), title, summary, imagePath, selectSection);
+			page = portfolioService.appendNewPage(getIdentity(), title, summary, imagePath, selectSection);
 		} else {
 			page.setTitle(titleEl.getValue());
 			page.setSummary(summaryEl.getValue());
@@ -294,6 +314,9 @@ public class PageMetadataEditController extends FormBasicController {
 			}
 			page = portfolioService.updatePage(page, newParent);
 		}
+		
+		List<String> updatedCategories = categoriesEl.getValueList();
+		portfolioService.updateCategories(page, updatedCategories);
 
 		fireEvent(ureq, Event.DONE_EVENT);
 	}
diff --git a/src/main/java/org/olat/modules/portfolio/ui/SectionEditController.java b/src/main/java/org/olat/modules/portfolio/ui/SectionEditController.java
index 96ecbd70635ce2c329b4cb41fa44a202c6fd6305..1bb773c574f4a43bf052ac63d49b2c7141bbe501 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/SectionEditController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/SectionEditController.java
@@ -129,6 +129,7 @@ public class SectionEditController extends FormBasicController {
 			reloadedSection.setEndDate(endDateEl.getDate());
 			section = portfolioService.updateSection(reloadedSection);
 		}
+		
 		fireEvent(ureq, Event.DONE_EVENT);
 	}
 
diff --git a/src/main/java/org/olat/modules/portfolio/ui/SectionPageListController.java b/src/main/java/org/olat/modules/portfolio/ui/SectionPageListController.java
index ea0ff1461025efe60531f62225e0a57fbbf496c2..2a56976099bf857710348bb04225fc608a71b391 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/SectionPageListController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/SectionPageListController.java
@@ -20,7 +20,11 @@
 package org.olat.modules.portfolio.ui;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
@@ -32,10 +36,13 @@ import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
+import org.olat.core.id.OLATResourceable;
 import org.olat.modules.portfolio.AssessmentSection;
 import org.olat.modules.portfolio.Binder;
 import org.olat.modules.portfolio.BinderConfiguration;
 import org.olat.modules.portfolio.BinderSecurityCallback;
+import org.olat.modules.portfolio.Category;
+import org.olat.modules.portfolio.CategoryToElement;
 import org.olat.modules.portfolio.Page;
 import org.olat.modules.portfolio.Section;
 import org.olat.modules.portfolio.model.PageRow;
@@ -76,6 +83,19 @@ public class SectionPageListController extends AbstractPageListController  {
 
 	@Override
 	protected void loadModel() {
+		List<CategoryToElement> categorizedElements = portfolioService.getCategorizedSectionAndPages(section);
+		Map<OLATResourceable,List<Category>> categorizedElementMap = new HashMap<>();
+		Set<String> sectionAggregatedCategories = new HashSet<>();
+		for(CategoryToElement categorizedElement:categorizedElements) {
+			List<Category> categories = categorizedElementMap.get(categorizedElement.getCategorizedResource());
+			if(categories == null) {
+				categories = new ArrayList<>();
+				categorizedElementMap.put(categorizedElement.getCategorizedResource(), categories);
+			}
+			categories.add(categorizedElement.getCategory());
+			sectionAggregatedCategories.add(categorizedElement.getCategory().getName());
+		}
+		
 		AssessmentSection assessmentSection = null;
 		List<AssessmentSection> assessmentSections = portfolioService.getAssessmentSections(binder, getIdentity());
 		for(AssessmentSection aSection:assessmentSections) {
@@ -88,7 +108,9 @@ public class SectionPageListController extends AbstractPageListController  {
 		List<PageRow> rows = new ArrayList<>();
 		boolean first = true;
 		for (Page page : pages) {
-			rows.add(forgeRow(page, assessmentSection, first));
+			PageRow row = forgeRow(page, assessmentSection, first, categorizedElementMap);
+			row.setSectionCategories(sectionAggregatedCategories);
+			rows.add(row);
 			first = false;
 		}
 		model.setObjects(rows);
diff --git a/src/main/java/org/olat/modules/portfolio/ui/_content/page_row.html b/src/main/java/org/olat/modules/portfolio/ui/_content/page_row.html
index c53ba61c12b53f3367a3ac28876a5ac94181eeb5..ad4a905185b04b86b3cc814b42fd36a0daa2dc03 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/_content/page_row.html
+++ b/src/main/java/org/olat/modules/portfolio/ui/_content/page_row.html
@@ -19,6 +19,18 @@
 		<div class="o_section_lead o_block_large_bottom">
 			<p>$r.xssScan($row.sectionDescription)</p>
 		</div>
+		
+		#if(${row.hasSectionCategories()})
+		<div class="o_block_large_bottom">
+			<div class="o_portfolio_page_meta text-muted o_small">
+				$r.translate("meta.section.categories") <i class="o_icon o_icon_tags"> </i>
+			 	#foreach($category in $row.sectionCategories)
+			 		#if(${foreach.count} > 1), #end
+			 		$category
+			 	#end
+			</div>
+		</div>
+		#end
 	</div>
 	
 	#if(${row.hasNewEntryLink()})
@@ -42,9 +54,23 @@
 		<i class="o_icon ${row.getCssClassStatus()} o_icon-fw"> </i>
 		$r.escapeHtml($row.title)
 	</h4>
-	<div class="o_portfolio_page_meta text-muted o_small">
+	#if(${row.hasLastPublicationDate()})
+	<span class="o_portfolio_page_meta text-muted o_small">
+		 $r.translate("meta.last.publication", $r.formatDateAndTime($row.lastPublicationDate))
+	</span>
+	#end
+	#if(${row.hasPageCategories()})
+	<span class="o_portfolio_page_meta text-muted o_small">
+		 $r.translate("meta.categories") <i class="o_icon o_icon_tags"> </i>
+		 #foreach($category in $row.pageCategories)
+		 	#if(${foreach.count} > 1), #end
+		 	$category
+		 #end
+	</span>
+	#end
+	<span class="o_portfolio_page_meta text-muted o_small">
 		 $r.translate("meta.last.modified", $r.formatDateAndTime($row.lastModified))
-	</div>
+	</span>
 	<div class="o_portfolio_page_summary o_block">
 		$r.xssScan($row.summary)
 	</div>
diff --git a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_de.properties
index c07bdb81b00ce5c3faec62d048631ca3c73a35d3..00ba8391ce9dc1589e418b95b3d324f1cc013cd4 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_de.properties
@@ -44,6 +44,7 @@ create.new.binder.descr=Erstellen Sie eine portfolio Mappe um Ihre Eintr\u00E4ge
 create.new.binder.title=Neue Mappe erstellen
 create.new.page=Neuer Eintrag erstellen
 create.new.page.tite=Neuer Eintrag erstellen
+create.new.page.descr=Neuer Eintrag erstellen
 create.new.section=Neuer Bereich erstellen
 create.new.section.text=Erstellen Sie einen neuen Bereich in der Portfolio Mappe um Ihre Eintr\u00E4ge zu organisieren.
 create.new.section.title=Neuer Bereich hinzuf\u00FCgen
@@ -83,7 +84,10 @@ map.passed=$org.olat.course.assessment\:map.passed
 map.returnDate=$org.olat.course.nodes.portfolio\:map.returnDate
 media.center=Mediencenter
 media.center.text=Hier k\u00F6nnen Sie Mediendateien, Dokumente oder andere Artefakte hinzuf\u00FCgen. Verwenden Sie die Medien um Ihre Eintr\u00E4ge zu illustrieren und zu erg\u00E4nzen.
+meta.categories=Kategorien
 meta.last.modified=zuletzt bearbeitet am {0}
+meta.last.publication=ver\u00F6ffentlich am {0}
+meta.section.categories=<strong>Kategorien</strong> in diesem Bereich
 my.entries=Meine Beitr\u00E4ge
 my.entries.text=Liste aller Beitr\u00E4ge in chronologischer Reihenfolge unabh\u00E4ngig von ihrem Kontext. Dies ist das Herzst\u00FCck Ihrer Portfolioarbeit.
 my.portfolio.binders=Meine Portfolio Mappen
diff --git a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties
index 20bc48097e77fdc0d0f77f5d5e59e841ccbba253..4377beef4a1b37cb107a9104de7ae28c8b31e406 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/portfolio/ui/_i18n/LocalStrings_en.properties
@@ -71,8 +71,6 @@ invitation.mail.subject=Invitation to a binder already released
 invitation.mail.body=You have been invited by {1} to have a look at a binder in OpenOLAT. Please go to\: {0}
 invitation.mail.success=The persons invited have been notified successfully via e-mail.
 invitation.mail.failure=Error while sending your e-mail. The persons invited could not be notified. Please try again later or contact your support team.
-
-
 lastName=Last name
 mail=E-Mail
 map.available=$org.olat.course.nodes.portfolio\:map.available
@@ -85,9 +83,12 @@ map.not.passed=$org.olat.course.assessment\:map.not.passed
 map.not.rated.yet=$org.olat.course.assessment\:map.not.rated.yet
 map.passed=$org.olat.course.assessment\:map.passed
 map.returnDate=$org.olat.course.nodes.portfolio\:map.returnDate
+meta.categories=Categories
 media.center=Media center
 media.center.text=Search, create, add media files or other artefacts that you want to use within your entries for illustration purpose.
 meta.last.modified=last modified {0}
+meta.last.publication=published at {0}
+meta.section.categories=<strong>Categories</strong> in this section
 my.entries=My entries
 my.entries.text=List all your portfolio entries regardless of their context. This is the heart of your portfolio work.
 my.portfolio.binders=My portfolio binders