diff --git a/lms/envs/common.py b/lms/envs/common.py
index 3bd1614a5a..e2478fd8a5 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -2360,6 +2360,7 @@ INSTALLED_APPS = [
'openedx.features.enterprise_support.apps.EnterpriseSupportConfig',
'openedx.features.learner_profile',
'openedx.features.learner_analytics',
+ 'openedx.features.portfolio_project',
'experiments',
diff --git a/lms/urls.py b/lms/urls.py
index d3a56c9d7f..dd6f9dd0c9 100644
--- a/lms/urls.py
+++ b/lms/urls.py
@@ -676,6 +676,14 @@ urlpatterns += [
),
include('openedx.features.learner_analytics.urls'),
),
+
+ # Portfolio project experiment
+ url(
+ r'^courses/{}/xfeature/portfolio/'.format(
+ settings.COURSE_ID_PATTERN,
+ ),
+ include('openedx.features.portfolio_project.urls'),
+ ),
]
if settings.FEATURES['ENABLE_TEAMS']:
diff --git a/openedx/features/portfolio_project/__init__.py b/openedx/features/portfolio_project/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/openedx/features/portfolio_project/templates/portfolio_project/generic_tab.html b/openedx/features/portfolio_project/templates/portfolio_project/generic_tab.html
new file mode 100644
index 0000000000..01f5c73176
--- /dev/null
+++ b/openedx/features/portfolio_project/templates/portfolio_project/generic_tab.html
@@ -0,0 +1,10 @@
+## mako
+<%page expression_filter="h"/>
+
+<%namespace name='static' file='../static_content.html'/>
+
+<%block name="content">
+
+
+%block>
+<%namespace name='static' file='../static_content.html'/>
diff --git a/openedx/features/portfolio_project/urls.py b/openedx/features/portfolio_project/urls.py
new file mode 100644
index 0000000000..7b42b8a654
--- /dev/null
+++ b/openedx/features/portfolio_project/urls.py
@@ -0,0 +1,15 @@
+"""
+Url setup for portfolio project.
+"""
+from django.conf.urls import url
+
+from views import GenericTabView
+
+
+urlpatterns = [
+ url(
+ r'^$',
+ GenericTabView.as_view(),
+ name='openedx.portfolio.generic_tab',
+ ),
+]
diff --git a/openedx/features/portfolio_project/views.py b/openedx/features/portfolio_project/views.py
new file mode 100644
index 0000000000..ea3f5770f3
--- /dev/null
+++ b/openedx/features/portfolio_project/views.py
@@ -0,0 +1,39 @@
+"""
+Portfolio views.
+"""
+
+from django.template.loader import render_to_string
+from django.utils.decorators import method_decorator
+from django.views.decorators.cache import cache_control
+
+from lms.djangoapps.courseware.views.views import CourseTabView
+
+from util.views import ensure_valid_course_key
+
+from web_fragments.fragment import Fragment
+
+
+class GenericTabView(CourseTabView):
+ """
+ Provides a blank page that acts as its own tab in courseware for displaying content.
+ """
+ @method_decorator(cache_control(no_cache=True, no_store=True, must_revalidate=True))
+ @method_decorator(ensure_valid_course_key)
+ def get(self, request, course_id, **kwargs):
+ """
+ Displays a generic tab for the specified course.
+ """
+ return super(GenericTabView, self).get(request, course_id, 'courseware', **kwargs)
+
+ def render_to_fragment(self, request, course=None, tab=None, **kwargs):
+ """
+ Render out the bootstrap page.
+ """
+ context = {
+ 'course': course,
+ 'user': request.user,
+ 'uses_bootstrap': True,
+ 'tab_name': tab,
+ }
+ html = render_to_string('portfolio_project/generic_tab.html', context)
+ return Fragment(html)