diff --git a/opentech/public/funds/migrations/0011_opencallindexpage.py b/opentech/public/funds/migrations/0011_opencallindexpage.py
new file mode 100644
index 0000000000000000000000000000000000000000..98889d43d209adf912a30660d3e1a356d55a5748
--- /dev/null
+++ b/opentech/public/funds/migrations/0011_opencallindexpage.py
@@ -0,0 +1,33 @@
+# Generated by Django 2.0.9 on 2019-03-26 12:12
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('images', '0003_customimage_drupal_id'),
+        ('wagtailcore', '0040_page_draft_title'),
+        ('public_funds', '0010_correct_related_page_required'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='OpenCallIndexPage',
+            fields=[
+                ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
+                ('social_text', models.CharField(blank=True, max_length=255)),
+                ('listing_title', models.CharField(blank=True, help_text='Override the page title used when this page appears in listings', max_length=255)),
+                ('listing_summary', models.CharField(blank=True, help_text="The text summary used when this page appears in listings. It's also used as the description for search engines if the 'Search description' field above is not defined.", max_length=255)),
+                ('introduction', models.TextField(blank=True)),
+                ('header_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='images.CustomImage')),
+                ('listing_image', models.ForeignKey(blank=True, help_text='Choose the image you wish to be displayed when this page appears in listings', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='images.CustomImage')),
+                ('social_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='images.CustomImage')),
+            ],
+            options={
+                'abstract': False,
+            },
+            bases=('wagtailcore.page', models.Model),
+        ),
+    ]
diff --git a/opentech/public/funds/models.py b/opentech/public/funds/models.py
index 0b1f212eb1abad8bba7634a1aa12888d1836db39..71045bf8ba649d28881c267082a69389595a6878 100644
--- a/opentech/public/funds/models.py
+++ b/opentech/public/funds/models.py
@@ -20,6 +20,8 @@ from wagtail.core.fields import StreamField
 from wagtail.images.edit_handlers import ImageChooserPanel
 from wagtail.search import index
 
+from opentech.apply.funds.models import ApplicationSubmission
+from opentech.apply.funds.workflow import OPEN_CALL_PHASES
 from opentech.public.utils.models import (
     BasePage,
     RelatedPage,
@@ -237,3 +239,36 @@ class LabIndex(BasePage):
         context = super().get_context(request, *args, **kwargs)
         context.update(subpages=labs)
         return context
+
+
+class OpenCallIndexPage(BasePage):
+    subpage_types = []
+    parent_page_types = ['home.HomePage']
+
+    introduction = models.TextField(blank=True)
+
+    content_panels = BasePage.content_panels + [
+        FieldPanel('introduction'),
+    ]
+
+    search_fields = BasePage.search_fields + [
+        index.SearchField('introduction'),
+    ]
+
+    def get_context(self, request, *args, **kwargs):
+        context = super().get_context(request, *args, **kwargs)
+        open_call_submissions = ApplicationSubmission.objects.filter(status__in=OPEN_CALL_PHASES)
+        per_page = settings.DEFAULT_PER_PAGE
+        page_number = request.GET.get('page')
+        paginator = Paginator(open_call_submissions, per_page)
+
+        try:
+            open_call_submissions = paginator.page(page_number)
+        except PageNotAnInteger:
+            open_call_submissions = paginator.page(1)
+        except EmptyPage:
+            open_call_submissions = paginator.page(paginator.num_pages)
+
+        context['open_call_submissions'] = open_call_submissions
+
+        return context
diff --git a/opentech/public/funds/templates/public_funds/open_call_index_page.html b/opentech/public/funds/templates/public_funds/open_call_index_page.html
new file mode 100644
index 0000000000000000000000000000000000000000..16cd611da8f6a489221423eff08d9d5680fabee7
--- /dev/null
+++ b/opentech/public/funds/templates/public_funds/open_call_index_page.html
@@ -0,0 +1,29 @@
+{% extends "base.html" %}
+{% load wagtailcore_tags wagtailimages_tags %}
+
+{% block content %}
+<div class="wrapper wrapper--small wrapper--inner-space-medium">
+    {% if page.introduction %}
+        <h4 class="heading heading--listings-introduction">{{ page.introduction }}</h4>
+    {% endif %}
+
+    <div class="wrapper wrapper--listings">
+
+        {% if open_call_submissions %}
+            {% for submission in open_call_submissions %}
+                <div class="listing listing--not-a-link">
+                    <h4 class="listing__title">{{ submission.title }}</h4>
+                    <a class="listing__button" href="{% pageurl submission.page %}">Build it</a>
+                </div>
+
+            {% endfor %}
+
+            {% include "includes/pagination.html" with paginator_page=open_call_submissions %}
+
+        {% else %}
+            {# no items on this page #}
+        {% endif %}
+    </div>
+</div>
+
+{% endblock %}