diff --git a/src/actions/auth.js b/src/actions/auth.js
deleted file mode 100644
index 18e177a..0000000
--- a/src/actions/auth.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { createActions } from "redux-actions";
-import service from "../services/lookup";
-
-async function getMemberGroups() {}
-
-export default createActions({
-  GET_MEMBER_GROUPS: getMemberGroups,
-});
diff --git a/src/actions/challenges.js b/src/actions/challenges.js
index 304fa5c..4f4914c 100644
--- a/src/actions/challenges.js
+++ b/src/actions/challenges.js
@@ -7,28 +7,71 @@ async function doGetChallenges(filter) {
   return service.getChallenges(filter);
 }
 
-async function getActiveChallenges(filter) {
-  const activeFilter = {
+async function getAllActiveChallenges(filter) {
+  const BUCKET_ALL_ACTIVE_CHALLENGES = constants.FILTER_BUCKETS[0];
+  let page;
+
+  if (util.isDisplayingBucket(filter, BUCKET_ALL_ACTIVE_CHALLENGES)) {
+    page = filter.page;
+  } else {
+    page = 1;
+  }
+
+  const allActiveFilter = {
     ...util.createChallengeCriteria(filter),
-    ...util.createActiveChallengeCriteria(),
+    ...util.createAllActiveChallengeCriteria(),
+    page,
   };
-  return doGetChallenges(activeFilter);
+  return doGetChallenges(allActiveFilter);
 }
 
 async function getOpenForRegistrationChallenges(filter) {
+  const BUCKET_OPEN_FOR_REGISTRATION = constants.FILTER_BUCKETS[1];
+  let page;
+
+  if (util.isDisplayingBucket(filter, BUCKET_OPEN_FOR_REGISTRATION)) {
+    page = filter.page;
+  } else {
+    page = 1;
+  }
+
   const openForRegistrationFilter = {
     ...util.createChallengeCriteria(filter),
     ...util.createOpenForRegistrationChallengeCriteria(),
+    page,
   };
   return doGetChallenges(openForRegistrationFilter);
 }
 
-async function getPastChallenges(filter) {
-  const pastFilter = {
+async function getClosedChallenges(filter) {
+  const BUCKET_CLOSED_CHALLENGES = constants.FILTER_BUCKETS[1];
+  let page;
+
+  if (util.isDisplayingBucket(filter, BUCKET_CLOSED_CHALLENGES)) {
+    page = filter.page;
+  } else {
+    page = 1;
+  }
+
+  const closedFilter = {
     ...util.createChallengeCriteria(filter),
-    ...util.createPastChallengeCriteria(),
+    ...util.createClosedChallengeCriteria(),
+    page,
   };
-  return doGetChallenges(pastFilter);
+  return doGetChallenges(closedFilter);
+}
+
+async function getRecommendedChallenges(filter) {
+  let result = [];
+  result.meta = { total: 0 };
+
+  if (result.length === 0) {
+    const failbackFilter = { ...filter };
+    result = await getOpenForRegistrationChallenges(failbackFilter);
+    result.loadingRecommendedChallengesError = true;
+  }
+
+  return result;
 }
 
 function doFilterBySubSommunities(challenges) {
@@ -43,46 +86,113 @@ function doFilterByPrizeTo(challenges) {
 
 async function getChallenges(filter, change) {
   const FILTER_BUCKETS = constants.FILTER_BUCKETS;
-  let challenges;
-  let challengesFiltered;
-  let total;
-  let filterChange = change;
-
-  const getChallengesByBucket = async (f) => {
-    switch (f.bucket) {
-      case FILTER_BUCKETS[0]:
-        return getActiveChallenges(f);
-      case FILTER_BUCKETS[1]:
-        return getOpenForRegistrationChallenges(f);
-      case FILTER_BUCKETS[2]:
-        return getPastChallenges(f);
-      default:
-        return [];
-    }
+  const BUCKET_ALL_ACTIVE_CHALLENGES = FILTER_BUCKETS[0];
+  const BUCKET_OPEN_FOR_REGISTRATION = FILTER_BUCKETS[1];
+  const BUCKET_CLOSED_CHALLENGES = FILTER_BUCKETS[2];
+  const filterChange = change;
+  const bucket = filter.bucket;
+
+  const getChallengesByBuckets = async (f) => {
+    return FILTER_BUCKETS.includes(f.bucket)
+      ? Promise.all([
+          getAllActiveChallenges(f),
+          f.recommended
+            ? getRecommendedChallenges(f)
+            : getOpenForRegistrationChallenges(f),
+          getClosedChallenges(f),
+        ])
+      : [[], [], []];
   };
 
+  if (!filterChange) {
+    let [
+      allActiveChallenges,
+      openForRegistrationChallenges,
+      closedChallenges,
+    ] = await getChallengesByBuckets(filter);
+    let challenges;
+    let openForRegistrationCount;
+    let total;
+    let loadingRecommendedChallengesError;
+
+    switch (bucket) {
+      case BUCKET_ALL_ACTIVE_CHALLENGES:
+        challenges = allActiveChallenges;
+        break;
+      case BUCKET_OPEN_FOR_REGISTRATION:
+        challenges = openForRegistrationChallenges;
+        break;
+      case BUCKET_CLOSED_CHALLENGES:
+        challenges = closedChallenges;
+        break;
+    }
+    openForRegistrationCount = openForRegistrationChallenges.meta.total;
+    total = challenges.meta.total;
+    loadingRecommendedChallengesError =
+      challenges.loadingRecommendedChallengesError;
+
+    return {
+      challenges,
+      total,
+      openForRegistrationCount,
+      loadingRecommendedChallengesError,
+      allActiveChallenges,
+      openForRegistrationChallenges,
+      closedChallenges,
+    };
+  }
+
   if (!util.checkRequiredFilterAttributes(filter)) {
     return { challenges: [], challengesFiltered: [], total: 0 };
   }
 
-  if (!filterChange) {
-    const chs = await getChallengesByBucket(filter);
-    return { challenges: chs, challengesFiltered: chs, total: chs.meta.total };
-  }
+  let allActiveChallenges;
+  let openForRegistrationChallenges;
+  let closedChallenges;
+  let challenges;
+  let openForRegistrationCount;
+  let total;
+  let loadingRecommendedChallengesError;
 
   if (util.shouldFetchChallenges(filterChange)) {
-    challenges = await getChallengesByBucket(filter);
+    [
+      allActiveChallenges,
+      openForRegistrationChallenges,
+      closedChallenges,
+    ] = await getChallengesByBuckets(filter);
+    switch (bucket) {
+      case BUCKET_ALL_ACTIVE_CHALLENGES:
+        challenges = allActiveChallenges;
+        break;
+      case BUCKET_OPEN_FOR_REGISTRATION:
+        challenges = openForRegistrationChallenges;
+        break;
+      case BUCKET_CLOSED_CHALLENGES:
+        challenges = closedChallenges;
+        break;
+    }
   }
 
-  challengesFiltered = challenges;
+  openForRegistrationCount = openForRegistrationChallenges.meta.total;
   total = challenges.meta.total;
+  loadingRecommendedChallengesError =
+    challenges.loadingRecommendedChallengesError;
+
   if (util.shouldFilterChallenges(filterChange)) {
-    challengesFiltered = doFilterBySubSommunities(challengesFiltered);
-    challengesFiltered = doFilterByPrizeFrom(challengesFiltered);
-    challengesFiltered = doFilterByPrizeTo(challengesFiltered);
+    challenges = doFilterBySubSommunities(challenges);
+    challenges = doFilterByPrizeFrom(challenges);
+    challenges = doFilterByPrizeTo(challenges);
   }
 
-  return { challenges, challengesFiltered, total };
+  return {
+    challenges,
+    total,
+    openForRegistrationCount,
+    loadingRecommendedChallengesError,
+    allActiveChallenges,
+    openForRegistrationChallenges,
+    closedChallenges,
+  };
 }
 
 export default createActions({
diff --git a/src/actions/filter.js b/src/actions/filter.js
index 5d3944b..d24ba3e 100644
--- a/src/actions/filter.js
+++ b/src/actions/filter.js
@@ -1,9 +1,14 @@
 import { createActions } from "redux-actions";
 
+function restoreFilter(filter) {
+  return filter;
+}
+
 function updateFilter(partialUpdate) {
   return partialUpdate;
 }
 
 export default createActions({
+  RESTORE_FILTER: restoreFilter,
   UPDATE_FILTER: updateFilter,
 });
diff --git a/src/assets/icons/card-view.svg b/src/assets/icons/card-view.svg
new file mode 100644
index 0000000..a25ef80
--- /dev/null
+++ b/src/assets/icons/card-view.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="03_2_My-Challenges" transform="translate(-1315.000000, -123.000000)">
+            <g id="icons/grid" transform="translate(1315.000000, 123.000000)">
+              <path fill="#7F7F7F" d="M6,9 C6.6,9 7,9.4 7,10 L7,10 L7,15 C7,15.6 6.6,16 6,16 L6,16 L1,16 C0.4,16 0,15.6 0,15 L0,15 L0,10 C0,9.4 0.4,9 1,9 L1,9 Z M15,9 C15.6,9 16,9.4 16,10 L16,10 L16,15 C16,15.6 15.6,16 15,16 L15,16 L10,16 C9.4,16 9,15.6 9,15 L9,15 L9,10 C9,9.4 9.4,9 10,9 L10,9 Z M6,0 C6.6,0 7,0.4 7,1 L7,1 L7,6 C7,6.6 6.6,7 6,7 L6,7 L1,7 C0.4,7 0,6.6 0,6 L0,6 L0,1 C0,0.4 0.4,0 1,0 L1,0 Z M15,0 C15.6,0 16,0.4 16,1 L16,1 L16,6 C16,6.6 15.6,7 15,7 L15,7 L10,7 C9.4,7 9,6.6 9,6 L9,6 L9,1 C9,0.4 9.4,0 10,0 L10,0 Z"></path>
+        </g>
+        </g>
+    </g>
+</svg>
\ No newline at end of file
diff --git a/src/assets/icons/list-view.svg b/src/assets/icons/list-view.svg
new file mode 100644
index 0000000..ea5bd21
--- /dev/null
+++ b/src/assets/icons/list-view.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16px" height="14px" viewBox="0 0 16 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g transform="translate(-1279.000000, -124.000000)">
+            <g transform="translate(1279.000000, 124.000000)">
+                <path fill="#7F7F7F" d="M15,12 C15.5125714,12 15.9354694,12.3862857 15.9932682,12.8834315 L16,13 C16,13.552 15.552,14 15,14 L1,14 C0.487428571,14 0.0645306122,13.6137143 0.00673177843,13.1165685 L0,13 C0,12.448 0.448,12 1,12 L15,12 Z M15,7 C15.5125714,7 15.9354694,7.38628571 15.9932682,7.88343149 L16,8 C16,8.552 15.552,9 15,9 L1,9 C0.487428571,9 0.0645306122,8.61371429 0.00673177843,8.11656851 L0,8 C0,7.448 0.448,7 1,7 L15,7 Z M15,0 C15.552,0 16,0.448 16,1 L16,3 C16,3.552 15.552,4 15,4 L1,4 C0.448,4 0,3.552 0,3 L0,1 C0,0.448 0.448,0 1,0 L15,0 Z"></path>
+            </g>
+        </g>
+    </g>
+</svg>
\ No newline at end of file
diff --git a/src/assets/icons/not-found-recommended.png b/src/assets/icons/not-found-recommended.png
new file mode 100644
index 0000000..728a77b
Binary files /dev/null and b/src/assets/icons/not-found-recommended.png differ
diff --git a/src/components/Button/index.jsx b/src/components/Button/index.jsx
index 2d28836..f30e79e 100644
--- a/src/components/Button/index.jsx
+++ b/src/components/Button/index.jsx
@@ -4,7 +4,7 @@ import PT from "prop-types";
 import "./styles.scss";
 
 const Button = ({ children, onClick }) => (
-  <button styleName="button" onClick={onClick}>
+  <button styleName="button" onClick={onClick} type="button">
     {children}
   </button>
 );
@@ -14,4 +14,17 @@ Button.propTypes = {
   onClick: PT.func,
 };
 
+const ButtonIcon = ({ children, onClick }) => (
+  <button styleName="button-icon" onClick={onClick} type="button">
+    {children}
+  </button>
+);
+
+ButtonIcon.propTypes = {
+  children: PT.node,
+  onClick: PT.func,
+};
+
+export { Button, ButtonIcon };
+
 export default Button;
diff --git a/src/components/Button/styles.scss b/src/components/Button/styles.scss
index 88f1d74..608f1ec 100644
--- a/src/components/Button/styles.scss
+++ b/src/components/Button/styles.scss
@@ -22,5 +22,15 @@
   background-color: $green;
 }
 
-.button-lg {}
-.button-sm {}
+.button-icon {
+  width: 32px;
+  height: 32px;
+  padding: 0;
+  line-height: 0;
+  text-align: center;
+  vertical-align: middle;
+  appearance: none;
+  background: none;
+  border: 0;
+  border-radius: 50%;
+}
diff --git a/src/components/Checkbox/index.jsx b/src/components/Checkbox/index.jsx
index 10343de..3ad7a08 100644
--- a/src/components/Checkbox/index.jsx
+++ b/src/components/Checkbox/index.jsx
@@ -1,7 +1,7 @@
 /**
  * Checkbox component.
  */
-import React, { useRef, useState } from "react";
+import React, { useRef, useState, useEffect } from "react";
 import PT from "prop-types";
 import _ from "lodash";
 import "./styles.scss";
@@ -22,6 +22,10 @@ function Checkbox({ checked, onChange, size, errorMsg }) {
     _.debounce((q, cb) => cb(q), process.env.GUIKIT.DEBOUNCE_ON_CHANGE_TIME) // eslint-disable-line no-undef
   ).current;
 
+  useEffect(() => {
+    setCheckedInternal(checked);
+  }, [checked]);
+
   return (
     <label styleName={`container ${sizeStyle}`}>
       <input
diff --git a/src/components/DateRangePicker/DateInput/index.jsx b/src/components/DateRangePicker/DateInput/index.jsx
index 83fbd8b..6141ffc 100644
--- a/src/components/DateRangePicker/DateInput/index.jsx
+++ b/src/components/DateRangePicker/DateInput/index.jsx
@@ -1,15 +1,153 @@
-import React from "react";
+import React, { useRef, useEffect, useState } from "react";
 import PT from "prop-types";
 import TextInput from "../../TextInput";
+import CalendarIcon from "assets/icons/icon-calendar.svg";
 
 import "./styles.scss";
 
-const DateInput = ({ value, onClick }) => (
-  <div onClick={onClick} styleName="date-range-input">
-    <TextInput label="From" size="xs" value={value} readonly />
-  </div>
-);
+const DateInput = ({
+  id,
+  isStartDateActive,
+  startDateString,
+  onStartDateChange,
+  onStartDateFocus,
+  isEndDateActive,
+  endDateString,
+  onEndDateChange,
+  onEndDateFocus,
+  error,
+  onClickCalendarIcon,
+  onStartEndDateChange,
+}) => {
+  const ref = useRef(null);
+  const [focused, setFocused] = useState(false);
 
-DateInput.propTypes = {};
+  let rangeText;
+  if (startDateString && endDateString) {
+    rangeText = `${startDateString} - ${endDateString}`;
+  } else {
+    rangeText = `${startDateString}${endDateString}`;
+  }
+
+  useEffect(() => {
+    const inputElement = ref.current.querySelector("input");
+    const onFocus = () => setFocused(true);
+    const onBlur = () => setFocused(false);
+
+    inputElement.addEventListener("focus", onFocus);
+    inputElement.addEventListener("blur", onBlur);
+
+    return () => {
+      inputElement.removeEventListener("focus", onFocus);
+      inputElement.removeEventListener("blur", onBlur);
+    };
+  }, []);
+
+  useEffect(() => {
+    const inputElement = ref.current.querySelector("input");
+
+    let caretPosition;
+    if (inputElement.selectionDirection === "forward") {
+      caretPosition = inputElement.selectionEnd;
+    } else {
+      caretPosition = inputElement.selectionStart;
+    }
+
+    if (caretPosition < 14) {
+      onStartDateFocus();
+    } else {
+      onEndDateFocus();
+    }
+  }, [focused]);
+
+  const onChangeRangeText = (value) => {
+    let [newStartDateString = "", newEndDateString = ""] = value
+      .trim()
+      .split("-");
+    newStartDateString = newStartDateString.trim();
+    newEndDateString = newEndDateString.trim();
+
+    if (
+      newStartDateString !== startDateString &&
+      newEndDateString !== endDateString
+    ) {
+      const event = {
+        startDateString: newStartDateString,
+        endDateString: newEndDateString,
+      };
+      onStartEndDateChange(event);
+      onStartDateFocus();
+    } else if (newStartDateString !== startDateString) {
+      onStartDateFocus();
+      onStartDateChange(newStartDateString);
+    } else if (newEndDateString !== endDateString) {
+      onEndDateFocus();
+      onEndDateChange(newEndDateString);
+      if (newEndDateString === "") {
+        onStartDateFocus();
+      }
+    }
+  };
+
+  const onChangeRangeTextDebounced = useRef(_.debounce((f) => f(), 150));
+
+  const onClickIcon = () => {
+    const inputElement = ref.current.querySelector("input");
+
+    let caretPosition;
+    if (inputElement.selectionDirection === "forward") {
+      caretPosition = inputElement.selectionEnd;
+    } else {
+      caretPosition = inputElement.selectionStart;
+    }
+
+    if (caretPosition < 14) {
+      onClickCalendarIcon("start");
+    } else {
+      onClickCalendarIcon("end");
+    }
+  };
+
+  const label = startDateString ? "From" : endDateString ? "To" : "From";
+
+  return (
+    <div styleName={`container ${error ? "isError" : ""}`}>
+      <div styleName="date-range-input input-group" ref={ref}>
+        <TextInput
+          label={label}
+          size="xs"
+          value={rangeText}
+          onChange={(value) => {
+            onChangeRangeTextDebounced.current(() => onChangeRangeText(value));
+          }}
+        />
+        <div
+          id={id}
+          styleName="icon"
+          role="button"
+          onClick={onClickIcon}
+        >
+          <CalendarIcon />
+        </div>
+      </div>
+      <div styleName="errorHint">{error}</div>
+    </div>
+  );
+};
+
+DateInput.propTypes = {
+  id: PT.string,
+  isStartDateActive: PT.bool,
+  startDateString: PT.string,
+  onStartDateChange: PT.func,
+  onStartDateFocus: PT.func,
+  isEndDateActive: PT.bool,
+  endDateString: PT.string,
+  onEndDateChange: PT.func,
+  onEndDateFocus: PT.func,
+  error: PT.string,
+  onClickCalendarIcon: PT.func,
+  onStartEndDateChange: PT.func,
+};
 
 export default DateInput;
diff --git a/src/components/DateRangePicker/DateInput/styles.scss b/src/components/DateRangePicker/DateInput/styles.scss
index b6c4514..7afad43 100644
--- a/src/components/DateRangePicker/DateInput/styles.scss
+++ b/src/components/DateRangePicker/DateInput/styles.scss
@@ -1,11 +1,44 @@
 @import "styles/variables";
 
+.container {
+  &.isError {
+    input {
+      border: 1px solid $tc-level-5;
+    }
+
+    .errorHint {
+      display: block;
+      color: $tc-level-5;
+      font-size: 12px;
+      padding: 4px 0;
+      height: 20px;
+    }
+  }
+}
+
 .date-range-input {
   width: 230px;
+  margin-top: -12px;
   font-size: $font-size-sm;
+}
+
+.input-group {
+  position: relative;
+
+  .icon {
+    position: absolute;
+    top: 22px;
+    right: 14px;
+    z-index: 1;
+    display: block;
+    cursor: pointer;
+  }
 
   input {
-    color: $body-color !important;
-    border-color: $tc-gray-30 !important;
+    padding-right: 46px !important;
   }
 }
+
+.errorHint {
+  display: none;
+}
diff --git a/src/components/DateRangePicker/helpers.js b/src/components/DateRangePicker/helpers.js
index cc6dab1..cef8582 100644
--- a/src/components/DateRangePicker/helpers.js
+++ b/src/components/DateRangePicker/helpers.js
@@ -50,11 +50,11 @@ const staticRangeHandler = {
  * @return {object[]} list of defined ranges
  */
 export function createStaticRanges() {
-  const now = moment();
-  const pastWeek = moment().subtract(1, "week");
-  const pastMonth = moment().subtract(1, "month");
-  const past6Months = moment().subtract(6, "month");
-  const pastYear = moment().subtract(1, "year");
+  const now = moment().utcOffset(0);
+  const pastWeek = now.clone().subtract(1, "week");
+  const pastMonth = now.clone().subtract(1, "month");
+  const past6Months = now.clone().subtract(6, "month");
+  const pastYear = now.clone().subtract(1, "year");
 
   const ranges = [
     {
diff --git a/src/components/DateRangePicker/index.jsx b/src/components/DateRangePicker/index.jsx
index b838904..4e8fe55 100644
--- a/src/components/DateRangePicker/index.jsx
+++ b/src/components/DateRangePicker/index.jsx
@@ -16,13 +16,7 @@ import {
 } from "./helpers";
 
 function DateRangePicker(props) {
-  const {
-    readOnly,
-    startDatePlaceholder,
-    endDatePlaceholder,
-    range,
-    onChange,
-  } = props;
+  const { id, range, onChange } = props;
 
   const [rangeString, setRangeString] = useState({
     startDateString: "",
@@ -45,15 +39,33 @@ function DateRangePicker(props) {
   const isStartDateFocused = focusedRange[1] === 0;
   const isEndDateFocused = focusedRange[1] === 1;
 
+  useEffect(() => {
+    setRangeString({
+      startDateString: range.startDate
+        ? moment(range.startDate).format("MMM D, YYYY")
+        : "",
+      endDateString: range.endDate
+        ? moment(range.endDate).format("MMM D, YYYY")
+        : "",
+    });
+  }, [range]);
+
   /**
    * Handle end date change on user input
    * After user input the end date via keyboard, validate it then update the range state
    * @param {Object} e Input Event.
    */
-  const onEndDateChange = (e) => {
-    const endDateString = e.target.value;
-    const endDate = moment(endDateString, "MM/DD/YYYY", true);
-    if (endDate.isValid()) {
+  const onEndDateChange = (value) => {
+    const endDateString = value;
+    const endDate = moment(endDateString, "MMM D, YYYY", true);
+    const startDate = moment(rangeString.startDateString, "MMM D, YYYY", true);
+
+    if (endDate.isValid() && isBeforeDay(endDate, startDate)) {
+      setErrors({
+        ...errors,
+        endDate: "Range Error",
+      });
+    } else if (endDate.isValid()) {
       onChange({
         endDate: endDate.toDate(),
         startDate: range.startDate,
@@ -66,15 +78,23 @@ function DateRangePicker(props) {
 
       setRangeString({
         ...rangeString,
-        endDateString: endDate.format("MM/DD/YYYY"),
+        endDateString: endDate.format("MMM D, YYYY"),
+      });
+    } else if (endDateString === "") {
+      onChange({
+        endDate: null,
+        startDate: range.startDate,
+      });
+
+      setErrors({
+        ...errors,
+        endDate: "",
       });
     } else {
-      if (endDateString && endDateString !== "mm/dd/yyyy") {
-        setErrors({
-          ...errors,
-          endDate: "Invalid Format",
-        });
-      }
+      setErrors({
+        ...errors,
+        endDate: "Invalid End Date Format",
+      });
 
       setRangeString({
         ...rangeString,
@@ -88,10 +108,21 @@ function DateRangePicker(props) {
    * After user input the start date via keyboard, validate it then update the range state
    * @param {Object} e Input Event.
    */
-  const onStartDateChange = (e) => {
-    const startDateString = e.target.value;
-    const startDate = moment(startDateString, "MM/DD/YYYY", true);
-    if (startDate.isValid()) {
+  const onStartDateChange = (value) => {
+    const startDateString = value;
+    const startDate = moment(startDateString, "MMM D, YYYY", true);
+    const endDate = moment(rangeString.endDateString, "MMM D, YYYY", true);
+
+    if (
+      startDate.isValid() &&
+      endDate.isValid() &&
+      isAfterDay(startDate, endDate)
+    ) {
+      setErrors({
+        ...errors,
+        startDate: "Range Error",
+      });
+    } else if (startDate.isValid()) {
       onChange({
         endDate: range.endDate,
         startDate: startDate.toDate(),
@@ -104,15 +135,23 @@ function DateRangePicker(props) {
 
       setRangeString({
         ...rangeString,
-        startDateString: startDate.format("MM/DD/YYYY"),
+        startDateString: startDate.format("MMM D, YYYY"),
+      });
+    } else if (startDateString === "") {
+      onChange({
+        endDate: range.endDate,
+        startDate: null,
+      });
+
+      setErrors({
+        ...errors,
+        startDate: "",
       });
     } else {
-      if (startDateString && startDateString !== "mm/dd/yyyy") {
-        setErrors({
-          ...errors,
-          startDate: "Invalid Format",
-        });
-      }
+      setErrors({
+        ...errors,
+        startDate: "Invalid Start Date Format",
+      });
 
       setRangeString({
         ...rangeString,
@@ -121,13 +160,92 @@ function DateRangePicker(props) {
     }
   };
 
+  const onStartEndDateChange = ({ startDateString, endDateString }) => {
+    const startDate = moment(startDateString, "MMM D, YYYY", true);
+    const endDate = moment(endDateString, "MMM D, YYYY", true);
+
+    if (
+      startDate.isValid() &&
+      endDate.isValid() &&
+      isBeforeDay(endDate, startDate)
+    ) {
+      setErrors({
+        ...errors,
+        endDate: "Range Error",
+      });
+    } else if (startDate.isValid() && endDate.isValid()) {
+      onChange({
+        endDate: endDate.toDate(),
+        startDate: startDate.toDate(),
+      });
+      setErrors({
+        startDate: "",
+        endDate: "",
+      });
+    } else if (startDate.isValid()) {
+      onChange({
+        endDate: null,
+        startDate: startDate.toDate(),
+      });
+      setErrors({
+        ...errors,
+        endDate: "Invalid End Date Format",
+      });
+    } else if (endDate.isValid()) {
+      onChange({
+        endDate: endDate.toDate(),
+        startDate: null,
+      });
+      setErrors({
+        ...errors,
+        startDate: "Invalid Start Date Format",
+      });
+    } else if (startDateString === "" && endDateString === "") {
+      onChange({
+        endDate: null,
+        startDate: null,
+      });
+      setErrors({
+        startDate: "",
+        endDate: "",
+      });
+    } else if (startDateString === "") {
+      onChange({
+        endDate: endDate.toDate(),
+        startDate: null,
+      });
+
+      setErrors({
+        ...errors,
+        startDate: "",
+      });
+    } else if (endDateString === "") {
+      onChange({
+        endDate: null,
+        startDate: startDate.toDate(),
+      });
+
+      setErrors({
+        ...errors,
+        endDate: "",
+      });
+    } else {
+      onChange({
+        endDate: null,
+        startDate: null,
+      });
+      setErrors({
+        startDate: "Invalid Start Date Format",
+        endDate: "Invalid End Date Format",
+      });
+    }
+  };
+
   /**
    * Trigger to open calendar modal on calendar icon in start date input
    */
   const onIconClickStartDate = () => {
-    const calendarIcon = document.querySelector(
-      "#input-start-date-range-calendar-icon"
-    );
+    const calendarIcon = document.querySelector(id);
     if (calendarIcon) {
       calendarIcon.blur();
     }
@@ -141,9 +259,7 @@ function DateRangePicker(props) {
    * Trigger to open calendar modal on calendar icon in end date input
    */
   const onIconClickEndDate = () => {
-    const calendarIcon = document.querySelector(
-      "#input-end-date-range-calendar-icon"
-    );
+    const calendarIcon = document.querySelector(id);
     if (calendarIcon) {
       calendarIcon.blur();
     }
@@ -205,9 +321,9 @@ function DateRangePicker(props) {
 
     setRangeString({
       startDateString: newStartDate
-        ? moment(newStartDate).format("MM/DD/YYYY")
+        ? moment(newStartDate).format("MMM D, YYYY")
         : "",
-      endDateString: newEndDate ? moment(newEndDate).format("MM/DD/YYYY") : "",
+      endDateString: newEndDate ? moment(newEndDate).format("MMM D, YYYY") : "",
     });
 
     onChange({
@@ -405,22 +521,24 @@ function DateRangePicker(props) {
     ${(errors.startDate || errors.endDate) && styles.isErrorInput}
   `;
 
-  let rangeText;
-  if (rangeString.startDateString && rangeString.endDateString) {
-    rangeText = `${rangeString.startDateString} - ${rangeString.endDateString}`;
-  } else {
-    rangeText = `${rangeString.startDateString}${rangeString.endDateString}`;
-  }
-
   return (
     <div styleName="dateRangePicker" className={className}>
       <div styleName="dateInputWrapper">
         <DateInput
-          onClick={() => {
-            onIconClickStartDate();
-            setFocusedRange([0, 0]);
+          id={id}
+          isStartDateActive={focusedRange[1] === 0 && isComponentVisible}
+          startDateString={rangeString.startDateString}
+          onStartDateChange={onStartDateChange}
+          onStartDateFocus={() => setFocusedRange([0, 0])}
+          isEndDateActive={focusedRange[1] === 1 && isComponentVisible}
+          endDateString={rangeString.endDateString}
+          onEndDateChange={onEndDateChange}
+          onEndDateFocus={() => setFocusedRange([0, 1])}
+          error={errors.startDate || errors.endDate}
+          onClickCalendarIcon={(event) => {
+            event === "start" ? onIconClickStartDate() : onIconClickEndDate();
           }}
-          value={rangeText}
+          onStartEndDateChange={onStartEndDateChange}
         />
       </div>
       <div ref={calendarRef}>
@@ -453,18 +571,14 @@ function DateRangePicker(props) {
 // It use https://www.npmjs.com/package/react-date-range internally
 // Check the docs for further options
 
+DateRangePicker.defaultProps = {
+  id: "input-date-range-calendar-icon"
+}
+
 DateRangePicker.propTypes = {
-  readOnly: PropTypes.bool,
-  startDatePlaceholder: PropTypes.string,
-  endDatePlaceholder: PropTypes.string,
+  id: PropTypes.string,
   range: PropTypes.object.isRequired,
   onChange: PropTypes.func.isRequired,
 };
 
-DateRangePicker.defaultProps = {
-  readOnly: false,
-  startDatePlaceholder: "Start Date",
-  endDatePlaceholder: "End Date",
-};
-
 export default DateRangePicker;
diff --git a/src/components/DateRangePicker/style.scss b/src/components/DateRangePicker/style.scss
index 4f863ce..8c36d00 100644
--- a/src/components/DateRangePicker/style.scss
+++ b/src/components/DateRangePicker/style.scss
@@ -166,7 +166,21 @@
     }
 
     .rdrMonthAndYearPickers select {
-      background: url("data:image/svg+xml;utf8,<svg width='9px' height='6px' viewBox='0 0 9 6' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><g id='Artboard' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd' transform='translate(-636.000000, -171.000000)'><g id='input' transform='translate(172.000000, 37.000000)' fill='%230B71E6' fill-rule='nonzero'><g id='Group-9' transform='translate(323.000000, 127.000000)'><path d='M142.280245,7.23952813 C141.987305,6.92353472 141.512432,6.92361662 141.219585,7.23971106 C140.926739,7.5558055 140.926815,8.06821394 141.219755,8.38420735 L145.498801,13 L149.780245,8.38162071 C150.073185,8.0656273 150.073261,7.55321886 149.780415,7.23712442 C149.487568,6.92102998 149.012695,6.92094808 148.719755,7.23694149 L145.498801,10.7113732 L142.280245,7.23952813 Z' id='arrow'></path></g></g></g></svg>") no-repeat right 8px center;
+      background: url("data:image/svg+xml;utf8,<svg width='9px' height='6px' viewBox='0 0 9 6' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><g id='Artboard' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd' transform='translate(-636.000000, -171.000000)'><g id='input' transform='translate(172.000000, 37.000000)' fill='%23137D60' fill-rule='nonzero'><g id='Group-9' transform='translate(323.000000, 127.000000)'><path d='M142.280245,7.23952813 C141.987305,6.92353472 141.512432,6.92361662 141.219585,7.23971106 C140.926739,7.5558055 140.926815,8.06821394 141.219755,8.38420735 L145.498801,13 L149.780245,8.38162071 C150.073185,8.0656273 150.073261,7.55321886 149.780415,7.23712442 C149.487568,6.92102998 149.012695,6.92094808 148.719755,7.23694149 L145.498801,10.7113732 L142.280245,7.23952813 Z' id='arrow'></path></g></g></g></svg>") no-repeat right 8px center;
+
+      option {
+        background: $white;
+
+        &:checked {
+          font-weight: bold;
+          color: $white;
+          background-color: $green;
+        }
+      }
+    }
+
+    rdrMonthAndYearPickers option:hover {
+      background-color: yellow !important;
     }
 
     .rdrMonths {
@@ -336,6 +350,11 @@
             z-index: 0;
           }
         }
+
+        .rdrDayNumber {
+          top: 0;
+          bottom: 0;
+        }
       }
 
       .rdrDayStartOfWeek,
diff --git a/src/components/DropdownTerms/index.jsx b/src/components/DropdownTerms/index.jsx
index b2fa746..a90e716 100644
--- a/src/components/DropdownTerms/index.jsx
+++ b/src/components/DropdownTerms/index.jsx
@@ -16,6 +16,7 @@ function DropdownTerms({
   onChange,
   errorMsg,
   addNewOptionPlaceholder,
+  size,
 }) {
   const [internalTerms, setInternalTerms] = useState(terms);
   const selectedOption = _.filter(internalTerms, { selected: true }).map(
@@ -87,7 +88,9 @@ function DropdownTerms({
         selectedOption && !!selectedOption.length ? "haveValue" : ""
       } ${errorMsg ? "haveError" : ""} ${
         _.every(internalTerms, { selected: true }) ? "isEmptySelectList" : ""
-      } ${focused ? "isFocused" : ""}`}
+      } ${focused ? "isFocused" : ""} ${
+        size === "lg" ? "term-lgSize" : "term-xsSize"
+      }`}
     >
       <div styleName="relative">
         <Creatable
@@ -179,6 +182,7 @@ DropdownTerms.defaultProps = {
   onChange: () => {},
   errorMsg: "",
   addNewOptionPlaceholder: "",
+  size: "lg",
 };
 
 DropdownTerms.propTypes = {
@@ -194,6 +198,7 @@ DropdownTerms.propTypes = {
   onChange: PT.func,
   errorMsg: PT.string,
   addNewOptionPlaceholder: PT.string,
+  size: PT.oneOf(["xs", "lg"]),
 };
 
 export default DropdownTerms;
diff --git a/src/components/DropdownTerms/styles.scss b/src/components/DropdownTerms/styles.scss
index c8bdae4..773068a 100644
--- a/src/components/DropdownTerms/styles.scss
+++ b/src/components/DropdownTerms/styles.scss
@@ -85,7 +85,7 @@
       left: 0;
       right: 0;
       background: transparent;
-      height: 100% !important;
+      min-height: 100% !important;
       z-index: 5;
       margin: 0 !important;
       cursor: pointer;
@@ -153,6 +153,39 @@
       }
     }
   }
+
+  &.term-lgSize {
+  }
+
+  &.term-xsSize {
+    :global {
+      .Select-control {
+        min-height: 40px;
+      }
+
+      .Select-placeholder {
+        font-size: 14px;
+      }
+
+      .Select--multi .Select-multi-value-wrapper {
+        max-height: 90px;
+      }
+
+      .Select.is-open  .Select-multi-value-wrapper {
+        overflow: hidden;
+      }
+
+      .Select--multi .Select-value {
+        line-height: 38px;
+        margin-top: 10px;
+        font-size: 14px;
+      }
+    }
+
+    .errorMessage {
+      @include errorMessageXs;
+    }
+  }
 }
 
 .addAnotherSkill {
diff --git a/src/components/Menu/index.jsx b/src/components/Menu/index.jsx
index 261604b..328788f 100644
--- a/src/components/Menu/index.jsx
+++ b/src/components/Menu/index.jsx
@@ -31,6 +31,7 @@ const Menu = ({ menu, icons, selected, onSelect }) => {
     if (!submenu[key]) {
       return null;
     }
+
     const subSubmenu = submenu[key];
     return (
       <ul styleName="sub-submenu">
@@ -52,6 +53,7 @@ const Menu = ({ menu, icons, selected, onSelect }) => {
     if (!menu[key]) {
       return null;
     }
+
     const subMenu = menu[key];
     return (
       <ul styleName="sub-menu">
diff --git a/src/components/Menu/styles.scss b/src/components/Menu/styles.scss
index 46acfb1..679db70 100644
--- a/src/components/Menu/styles.scss
+++ b/src/components/Menu/styles.scss
@@ -5,16 +5,16 @@ $menu-padding-y: 20px;
 
 .menu {
   padding: $menu-padding-y $menu-padding-x (3 * $base-unit);
-  line-height: 21px;
 }
 
 .menu-item {
-  padding: 7px 0;
+  padding: 4px 0;
   cursor: pointer;
 
   a {
     display: flex;
     align-items: center;
+    line-height: 26px;
   }
 
   .icon {
@@ -45,10 +45,21 @@ $menu-padding-y: 20px;
   }
 
   &.selected > a {
-    color: $green;
+    color: $lightGreen;
   }
 }
 
+.menu-item-main > a {
+  margin-left: -20px;
+  margin-right: -20px;
+  padding-left: 20px;
+  padding-right: 20px;
+}
+
+.menu-item-main.active > a {
+  box-shadow: inset 4px 0 #06D6A0;
+}
+
 .menu-item-main > a + ul,
 .menu-item-secondary > a + ul {
   display: none;
@@ -60,7 +71,7 @@ $menu-padding-y: 20px;
 }
 
 .menu-item-secondary.active.collapsed {
-  color: $green;
+  color: $lightGreen;
 }
 
 .sub-menu {
diff --git a/src/components/Pagination/index.jsx b/src/components/Pagination/index.jsx
index aceda01..de245ef 100644
--- a/src/components/Pagination/index.jsx
+++ b/src/components/Pagination/index.jsx
@@ -39,7 +39,7 @@ const Pagination = ({ length, pageIndex, pageSize, onChange }) => {
   const onChangePageSize = (options) => {
     const selectedOption = utils.getSelectedDropdownOption(options);
     const newPageSize = +selectedOption.label;
-    onChange({ pageIndex, pageSize: newPageSize });
+    onChange({ pageIndex: 0, pageSize: newPageSize });
   };
 
   const onChangePageIndex = (newPageIndex) => {
@@ -106,7 +106,11 @@ const Pagination = ({ length, pageIndex, pageSize, onChange }) => {
             </button>
           </li>
         ))}
-        <li styleName={`page next ${pageIndex === total - 1 ? "hidden" : ""}`}>
+        <li
+          styleName={`page next ${
+            pageIndex === total - 1 || length === 0 ? "hidden" : ""
+          }`}
+        >
           <button onClick={next}>NEXT</button>
         </li>
       </ul>
diff --git a/src/components/Pagination/styles.scss b/src/components/Pagination/styles.scss
index edbcfa6..c7401fd 100644
--- a/src/components/Pagination/styles.scss
+++ b/src/components/Pagination/styles.scss
@@ -12,8 +12,7 @@
 
   :global {
     .Select-value-label::after {
-      content: 'per page';
-      margin-left: 0.15em;
+      content: ' per page';
     }
   }
 }
diff --git a/src/components/Toggle/index.jsx b/src/components/Toggle/index.jsx
index 61dd77a..a4fd9f5 100644
--- a/src/components/Toggle/index.jsx
+++ b/src/components/Toggle/index.jsx
@@ -1,7 +1,7 @@
 /**
  * Toggles component.
  */
-import React, { useRef, useState } from "react";
+import React, { useRef, useState, useEffect } from "react";
 import PT from "prop-types";
 import _ from "lodash";
 import "./style.scss";
@@ -17,6 +17,10 @@ function Toggles({ checked, onChange, size }) {
     sizeStyle = size === "xs" ? "xsSize" : "smSize";
   }
 
+  useEffect(() => {
+    setInternalChecked(checked);
+  }, [checked]);
+
   return (
     <label styleName={`container ${sizeStyle}`}>
       <input
diff --git a/src/constants/index.js b/src/constants/index.js
index a30d9bf..5115e6b 100644
--- a/src/constants/index.js
+++ b/src/constants/index.js
@@ -25,7 +25,7 @@ export const NAV_MENU_ICONS = {
 export const FILTER_BUCKETS = [
   "All Active Challenges",
   "Open for Registration",
-  "Past Challenges",
+  "Closed Challenges",
 ];
 
 export const FILTER_CHALLENGE_TYPES = ["Challenge", "First2Finish", "Task"];
@@ -40,14 +40,14 @@ export const FILTER_CHALLENGE_TRACKS = [
   "Design",
   "Development",
   "Data Science",
-  "Quality Assurance",
+  "QA",
 ];
 
 export const FILTER_CHALLENGE_TRACK_ABBREVIATIONS = {
   Design: "DES",
   Development: "DEV",
   "Data Science": "DS",
-  "Quality Assurance": "QA",
+  QA: "QA",
 };
 
 export const CHALLENGE_SORT_BY = {
@@ -57,6 +57,15 @@ export const CHALLENGE_SORT_BY = {
   Title: "name",
 };
 
+export const CHALLENGE_SORT_BY_RECOMMENDED = "bestMatch";
+export const CHALLENGE_SORT_BY_RECOMMENDED_LABEL = "Best Match";
+export const CHALLENGE_SORT_BY_DEFAULT = "updated";
+
+export const SORT_ORDER = {
+  DESC: "desc",
+  ASC: "asc",
+};
+
 export const TRACK_COLOR = {
   Design: "#2984BD",
   Development: "#35AC35",
diff --git a/src/containers/Challenges/Listing/ChallengeError/index.jsx b/src/containers/Challenges/Listing/ChallengeError/index.jsx
index f0b62c8..31611a1 100644
--- a/src/containers/Challenges/Listing/ChallengeError/index.jsx
+++ b/src/containers/Challenges/Listing/ChallengeError/index.jsx
@@ -1,6 +1,5 @@
 import React from "react";
 import IconNotFound from "assets/icons/not-found.png";
-
 import "./styles.scss";
 
 const ChallengeError = () => (
@@ -9,7 +8,7 @@ const ChallengeError = () => (
       <img src={IconNotFound} alt="not found" />
     </h1>
     <p>
-      No challenges were found. You can try changing your search perimeters.
+      No challenges were found. You can try changing your search parameters.
     </p>
   </div>
 );
diff --git a/src/containers/Challenges/Listing/ChallengeItem/NumRegistrants/styles.scss b/src/containers/Challenges/Listing/ChallengeItem/NumRegistrants/styles.scss
index 376bd0d..98627d8 100644
--- a/src/containers/Challenges/Listing/ChallengeItem/NumRegistrants/styles.scss
+++ b/src/containers/Challenges/Listing/ChallengeItem/NumRegistrants/styles.scss
@@ -9,7 +9,7 @@
     display: inline-block;
     width: 14px;
     height: 16px;
-    margin-right: 7px;
+    margin-right: 14px;
     vertical-align: middle;
   }
 }
diff --git a/src/containers/Challenges/Listing/ChallengeItem/NumSubmissions/styles.scss b/src/containers/Challenges/Listing/ChallengeItem/NumSubmissions/styles.scss
index 62bd69f..95eda50 100644
--- a/src/containers/Challenges/Listing/ChallengeItem/NumSubmissions/styles.scss
+++ b/src/containers/Challenges/Listing/ChallengeItem/NumSubmissions/styles.scss
@@ -9,7 +9,7 @@
     display: inline-block;
     width: 14px;
     height: 16px;
-    margin-right: 7px;
+    margin-right: 14px;
     vertical-align: middle;
   }
 }
diff --git a/src/containers/Challenges/Listing/ChallengeItem/PhaseEndDate/index.jsx b/src/containers/Challenges/Listing/ChallengeItem/PhaseEndDate/index.jsx
index ef1a959..6bb02ef 100644
--- a/src/containers/Challenges/Listing/ChallengeItem/PhaseEndDate/index.jsx
+++ b/src/containers/Challenges/Listing/ChallengeItem/PhaseEndDate/index.jsx
@@ -15,7 +15,13 @@ const PhaseEndDate = ({ challenge }) => {
   );
   const timeLeftColor = timeLeft.time < 12 * 60 * 60 * 1000 ? "#EF476F" : "";
   const timeLeftMessage = timeLeft.late ? (
-    <span>{`Late by ${timeLeft.text}`}</span>
+    <span>
+      Late by
+      <span
+        style={{ color: "#EF476F" }}
+        styleName="uppercase"
+      >{` ${timeLeft.text}`}</span>
+    </span>
   ) : (
     <span style={{ color: timeLeftColor }}>
       <span
@@ -29,7 +35,7 @@ const PhaseEndDate = ({ challenge }) => {
     <span>
       <span styleName="phase-message">
         {`${phaseMessage}`} {`${status}`}:
-      </span>
+      </span>{" "}
       <span styleName="time-left">{timeLeftMessage}</span>
     </span>
   );
diff --git a/src/containers/Challenges/Listing/ChallengeItem/Prize/styles.scss b/src/containers/Challenges/Listing/ChallengeItem/Prize/styles.scss
index b558dd7..5b64e44 100644
--- a/src/containers/Challenges/Listing/ChallengeItem/Prize/styles.scss
+++ b/src/containers/Challenges/Listing/ChallengeItem/Prize/styles.scss
@@ -17,4 +17,8 @@
 
   font-size: 24px;
   line-height: 26px;
+
+  &::first-letter {
+    margin-right: -0.125em;
+  }
 }
diff --git a/src/containers/Challenges/Listing/ChallengeItem/Tags/index.jsx b/src/containers/Challenges/Listing/ChallengeItem/Tags/index.jsx
index 889e82f..58dfc8c 100644
--- a/src/containers/Challenges/Listing/ChallengeItem/Tags/index.jsx
+++ b/src/containers/Challenges/Listing/ChallengeItem/Tags/index.jsx
@@ -23,6 +23,10 @@ const Tags = ({ tags, onClickTag }) => {
   );
 };
 
+Tags.defaultProps = {
+  tags: [],
+};
+
 Tags.propTypes = {
   tags: PT.arrayOf(PT.string),
   onClickTag: PT.func,
diff --git a/src/containers/Challenges/Listing/ChallengeItem/TrackIcon/styles.scss b/src/containers/Challenges/Listing/ChallengeItem/TrackIcon/styles.scss
index 3ab927c..5135e80 100644
--- a/src/containers/Challenges/Listing/ChallengeItem/TrackIcon/styles.scss
+++ b/src/containers/Challenges/Listing/ChallengeItem/TrackIcon/styles.scss
@@ -2,6 +2,8 @@
   .track-icon {
     position: relative;
     display: inline-block;
+    width: 42px;
+    height: 46px;
     vertical-align: middle;
     line-height: 1;
 
diff --git a/src/containers/Challenges/Listing/ChallengeItem/index.jsx b/src/containers/Challenges/Listing/ChallengeItem/index.jsx
index a5325a0..9a2f8bb 100644
--- a/src/containers/Challenges/Listing/ChallengeItem/index.jsx
+++ b/src/containers/Challenges/Listing/ChallengeItem/index.jsx
@@ -15,7 +15,7 @@ const ChallengeItem = ({ challenge, onClickTag, onClickTrack }) => {
   let purse = challenge.prizeSets
     ? utils.challenge.getChallengePurse(challenge.prizeSets)
     : "";
-  purse = purse && utils.formatMoneyValue(purse);
+  purse = typeof purse === "number" && utils.formatMoneyValue(purse);
 
   return (
     <div styleName="challenge-item">
diff --git a/src/containers/Challenges/Listing/ChallengeItem/styles.scss b/src/containers/Challenges/Listing/ChallengeItem/styles.scss
index 693f532..bc53fbc 100644
--- a/src/containers/Challenges/Listing/ChallengeItem/styles.scss
+++ b/src/containers/Challenges/Listing/ChallengeItem/styles.scss
@@ -1,4 +1,5 @@
 @import "styles/variables";
+@import "styles/mixins";
 
 .challenge-item {
   display: flex;
@@ -35,8 +36,14 @@
   }
 
   .tags {
-    max-width: calc(50% - 32px);
+    max-width: calc(50% - 84px);
+    min-width: calc(50% - 84px);
     flex: 1 1 auto;
+
+    @media (min-width: $screen-xxl + 1px) {
+      min-width: 294px;
+      max-width: 25%;
+    }
   }
 
   .nums {
@@ -44,7 +51,15 @@
     white-space: nowrap;
 
     > * {
-      margin: 0 16px;
+      margin: 0 20px;
+
+      &:first-child {
+        margin-left: 0;
+      }
+
+      &:last-child {
+        margin-right: 0;
+      }
     }
   }
 }
diff --git a/src/containers/Challenges/Listing/ChallengeRecommendedError/index.jsx b/src/containers/Challenges/Listing/ChallengeRecommendedError/index.jsx
new file mode 100644
index 0000000..bc7fa3e
--- /dev/null
+++ b/src/containers/Challenges/Listing/ChallengeRecommendedError/index.jsx
@@ -0,0 +1,18 @@
+import React from "react";
+import IconNotFound from "assets/icons/not-found-recommended.png";
+import "./styles.scss";
+
+const ChallengeRecommendedError = () => (
+  <div styleName="challenge-recommended-error">
+    <h1>
+      <img src={IconNotFound} alt="not found" />
+    </h1>
+    <p>
+      Looks like there are no <strong>Recommended Challenges</strong> that best
+      match your skills at this point. But you can try to join other challenges
+      that work for you.
+    </p>
+  </div>
+);
+
+export default ChallengeRecommendedError;
diff --git a/src/containers/Challenges/Listing/ChallengeRecommendedError/styles.scss b/src/containers/Challenges/Listing/ChallengeRecommendedError/styles.scss
new file mode 100644
index 0000000..a1efc68
--- /dev/null
+++ b/src/containers/Challenges/Listing/ChallengeRecommendedError/styles.scss
@@ -0,0 +1,24 @@
+@import "styles/variables";
+
+.challenge-recommended-error {
+  padding: 16px 24px;
+  min-height: 136px;
+  margin-bottom: 35px;
+  font-size: $font-size-sm;
+  line-height: 22px;
+  text-align: center;
+  background: $white;
+  border-radius: $border-radius-lg;
+
+  h1 {
+    padding: 15px 0 10px;
+  }
+
+  p {
+    margin-bottom: 20px;
+  }
+
+  strong {
+    font-weight: bold;
+  }
+}
diff --git a/src/containers/Challenges/Listing/index.jsx b/src/containers/Challenges/Listing/index.jsx
index 7c18893..eb4ec76 100644
--- a/src/containers/Challenges/Listing/index.jsx
+++ b/src/containers/Challenges/Listing/index.jsx
@@ -16,6 +16,7 @@ import "./styles.scss";
 
 const Listing = ({
   challenges,
+  search,
   page,
   perPage,
   sortBy,
@@ -25,9 +26,10 @@ const Listing = ({
   updateFilter,
   bucket,
   getChallenges,
+  challengeSortBys,
 }) => {
   const sortByOptions = utils.createDropdownOptions(
-    Object.keys(constants.CHALLENGE_SORT_BY),
+    challengeSortBys,
     utils.getSortByLabel(constants.CHALLENGE_SORT_BY, sortBy)
   );
 
@@ -42,6 +44,7 @@ const Listing = ({
               <img src={IconSearch} alt="search" />
             </span>
             <TextInput
+              value={search}
               placeholder="Search for challenges"
               size="xs"
               onChange={(value) => {
@@ -64,11 +67,11 @@ const Listing = ({
               options={sortByOptions}
               size="xs"
               onChange={(newSortByOptions) => {
-                const selectOption = utils.getSelectedDropdownOption(
+                const selectedOption = utils.getSelectedDropdownOption(
                   newSortByOptions
                 );
                 const filterChange = {
-                  sortBy: constants.CHALLENGE_SORT_BY[selectOption.label],
+                  sortBy: constants.CHALLENGE_SORT_BY[selectedOption.label],
                 };
                 updateFilter(filterChange);
                 getChallenges(filterChange);
@@ -140,6 +143,7 @@ const Listing = ({
 
 Listing.propTypes = {
   challenges: PT.arrayOf(PT.shape()),
+  search: PT.string,
   page: PT.number,
   perPage: PT.number,
   sortBy: PT.string,
@@ -149,6 +153,7 @@ Listing.propTypes = {
   getChallenges: PT.func,
   updateFilter: PT.func,
   bucket: PT.string,
+  challengeSortBys: PT.arrayOf(PT.string),
 };
 
 export default Listing;
diff --git a/src/containers/Challenges/index.jsx b/src/containers/Challenges/index.jsx
index 9a890c0..9ff80e3 100644
--- a/src/containers/Challenges/index.jsx
+++ b/src/containers/Challenges/index.jsx
@@ -4,10 +4,17 @@ import { connect } from "react-redux";
 import Listing from "./Listing";
 import actions from "../../actions";
 import ChallengeError from "./Listing/ChallengeError";
+import ChallengeRecommendedError from "./Listing/ChallengeRecommendedError";
+import IconListView from "../../assets/icons/list-view.svg";
+import IconCardView from "../../assets/icons/card-view.svg";
+import { ButtonIcon } from "../../components/Button";
+import * as constants from "../../constants";
+
 import "./styles.scss";
 
 const Challenges = ({
   challenges,
+  search,
   page,
   perPage,
   sortBy,
@@ -17,6 +24,8 @@ const Challenges = ({
   getChallenges,
   updateFilter,
   bucket,
+  recommended,
+  loadingRecommendedChallengesError,
 }) => {
   const [initialized, setInitialized] = useState(false);
 
@@ -24,23 +33,56 @@ const Challenges = ({
     getChallenges().finally(() => setInitialized(true));
   }, []);
 
+  const BUCKET_OPEN_FOR_REGISTRATION = constants.FILTER_BUCKETS[1];
+  const isRecommended = recommended && bucket === BUCKET_OPEN_FOR_REGISTRATION;
+  const sortByValue = isRecommended
+    ? sortBy
+    : sortBy === constants.CHALLENGE_SORT_BY_RECOMMENDED
+    ? constants.CHALLENGE_SORT_BY_DEFAULT
+    : sortBy;
+  const sortByLabels = isRecommended
+    ? Object.keys(constants.CHALLENGE_SORT_BY)
+    : Object.keys(constants.CHALLENGE_SORT_BY).filter(
+        (label) => label !== constants.CHALLENGE_SORT_BY_RECOMMENDED_LABEL
+      );
+
+  const isNoRecommendedChallenges =
+    bucket === BUCKET_OPEN_FOR_REGISTRATION &&
+    recommended &&
+    loadingRecommendedChallengesError;
+
   return (
     <div styleName="page">
-      <h1 styleName="title">CHALLENGES</h1>
-      {challenges.length === 0 ? (
-        initialized && <ChallengeError />
-      ) : (
+      <h1 styleName="title">
+        <span>CHALLENGES</span>
+        <span styleName="view-mode">
+          <ButtonIcon>
+            <IconListView />
+          </ButtonIcon>
+          <ButtonIcon>
+            <IconCardView />
+          </ButtonIcon>
+        </span>
+      </h1>
+
+      {isNoRecommendedChallenges && initialized && (
+        <ChallengeRecommendedError />
+      )}
+      {challenges.length === 0 && initialized && <ChallengeError />}
+      {challenges.length > 0 && (
         <Listing
           challenges={challenges}
+          search={search}
           page={page}
           perPage={perPage}
-          sortBy={sortBy}
+          sortBy={sortByValue}
           total={total}
           endDateStart={endDateStart}
           startDateEnd={startDateEnd}
           updateFilter={updateFilter}
           bucket={bucket}
           getChallenges={getChallenges}
+          challengeSortBys={sortByLabels}
         />
       )}
     </div>
@@ -49,6 +91,7 @@ const Challenges = ({
 
 Challenges.propTypes = {
   challenges: PT.arrayOf(PT.shape()),
+  search: PT.string,
   page: PT.number,
   perPage: PT.number,
   sortBy: PT.string,
@@ -58,18 +101,24 @@ Challenges.propTypes = {
   getChallenges: PT.func,
   updateFilter: PT.func,
   bucket: PT.string,
+  recommended: PT.bool,
+  loadingRecommendedChallengesError: PT.bool,
 };
 
 const mapStateToProps = (state) => ({
   state: state,
+  search: state.filter.challenge.search,
   page: state.filter.challenge.page,
   perPage: state.filter.challenge.perPage,
   sortBy: state.filter.challenge.sortBy,
   total: state.challenges.total,
   endDateStart: state.filter.challenge.endDateStart,
   startDateEnd: state.filter.challenge.startDateEnd,
-  challenges: state.challenges.challengesFiltered,
+  challenges: state.challenges.challenges,
   bucket: state.filter.challenge.bucket,
+  recommended: state.filter.challenge.recommended,
+  loadingRecommendedChallengesError:
+    state.challenges.loadingRecommendedChallengesError,
 });
 
 const mapDispatchToProps = {
diff --git a/src/containers/Challenges/styles.scss b/src/containers/Challenges/styles.scss
index b43a724..046abe5 100644
--- a/src/containers/Challenges/styles.scss
+++ b/src/containers/Challenges/styles.scss
@@ -9,3 +9,11 @@
   @include barlow-condensed-medium;
   margin-bottom: 22px;
 }
+
+.view-mode {
+  float: right;
+
+  > * {
+    margin: 0 2px;
+  }
+}
diff --git a/src/containers/Filter/ChallengeFilter/index.jsx b/src/containers/Filter/ChallengeFilter/index.jsx
index 0575912..7764915 100644
--- a/src/containers/Filter/ChallengeFilter/index.jsx
+++ b/src/containers/Filter/ChallengeFilter/index.jsx
@@ -1,4 +1,4 @@
-import React, { useState } from "react";
+import React, { useState, useEffect, useRef } from "react";
 import PT from "prop-types";
 import _ from "lodash";
 import RadioButton from "../../../components/RadioButton";
@@ -8,6 +8,7 @@ import Toggle from "../../../components/Toggle";
 import Button from "../../../components/Button";
 import TextInput from "../../../components/TextInput";
 import * as utils from "../../../utils";
+import * as constants from "../../../constants";
 
 import "./styles.scss";
 
@@ -18,6 +19,7 @@ const ChallengeFilter = ({
   tags,
   prizeFrom,
   prizeTo,
+  recommended,
   subCommunities,
   challengeBuckets,
   challengeTypes,
@@ -26,7 +28,10 @@ const ChallengeFilter = ({
   challengeSubCommunities,
   saveFilter,
   clearFilter,
+  switchBucket,
+  openForRegistrationCount,
 }) => {
+  const BUCKET_OPEN_FOR_REGISTRATION = constants.FILTER_BUCKETS[1];
   const tagOptions = utils.createDropdownTermOptions(challengeTags);
   const bucketOptions = utils.createRadioOptions(challengeBuckets, bucket);
 
@@ -39,26 +44,66 @@ const ChallengeFilter = ({
       prizeFrom,
       prizeTo,
       subCommunities,
+      recommended,
     })
   );
 
   utils.setSelectedDropdownTermOptions(tagOptions, filter.tags);
 
+  useEffect(() => {
+    const newFilter = _.cloneDeep({
+      bucket,
+      types,
+      tracks,
+      tags,
+      prizeFrom,
+      prizeTo,
+      subCommunities,
+      recommended,
+    });
+    setFilter(newFilter);
+  }, [
+    bucket,
+    types,
+    tracks,
+    tags,
+    prizeFrom,
+    prizeTo,
+    subCommunities,
+    recommended,
+  ]);
+
+  const ref = useRef(null);
+
+  useEffect(() => {
+    if (!ref.current) {
+      return;
+    }
+
+    const openForRegistrationElement = ref.current.children[0].children[1];
+    const badgeElement = utils.icon.createBadgeElement(
+      openForRegistrationElement,
+      `${openForRegistrationCount}`
+    );
+
+    return () => {
+      badgeElement.parentElement.removeChild(badgeElement);
+    };
+  }, [ref.current, openForRegistrationCount]);
+
   return (
     <div styleName="filter">
-      <div styleName="buckets vertical-list">
+      <div styleName="buckets vertical-list" ref={ref}>
         <RadioButton
           options={bucketOptions}
           onChange={(newBucketOptions) => {
-            const filterChange = {
-              ...filter,
-              bucket: utils.getSelectedRadioOption(newBucketOptions).label,
-            };
-            setFilter(filterChange);
-            saveFilter(filterChange);
+            const selectedBucket = utils.getSelectedRadioOption(
+              newBucketOptions
+            ).label;
+            setFilter({ ...filter, bucket: selectedBucket });
+            switchBucket(selectedBucket);
           }}
         />
-        <span></span>
       </div>
 
       <div styleName="challenge-types">
@@ -115,14 +160,43 @@ const ChallengeFilter = ({
               tags: selectedTagOptions.map((tagOption) => tagOption.label),
             });
           }}
+          size="xs"
         />
       </div>
 
       <div styleName="prize">
         <h3>Prize Amount</h3>
-        <TextInput size="xs" label="From" value={`${prizeFrom}`} />
+        <div styleName="input-group">
+          <TextInput
+            value={filter.prizeFrom}
+            size="xs"
+            label="From"
+            value={`${utils.formatPrizeAmount(prizeFrom)}`}
+            onChange={(value) => {
+              setFilter({
+                ...filter,
+                prizeFrom: utils.parsePrizeAmountText(value),
+              });
+            }}
+          />
+          <span styleName="suffix">USD</span>
+        </div>
         <span styleName="separator" />
-        <TextInput size="xs" label="To" value={`${prizeTo}`} />
+        <div styleName="input-group">
+          <TextInput
+            value={filter.prizeTo}
+            size="xs"
+            label="To"
+            value={`${utils.formatPrizeAmount(prizeTo)}`}
+            onChange={(value) => {
+              setFilter({
+                ...filter,
+                prizeTo: utils.parsePrizeAmountText(value),
+              });
+            }}
+          />
+          <span styleName="suffix">USD</span>
+        </div>
       </div>
 
       {challengeSubCommunities.length > 0 && (
@@ -145,12 +219,26 @@ const ChallengeFilter = ({
           </div>
         </div>
       )}
-      <div styleName="recommended-challenges">
-        <span styleName="toggle">
-          <Toggle />
-        </span>
-        <span>Recommended Challenges</span>
-      </div>
+
+      {bucket === BUCKET_OPEN_FOR_REGISTRATION && (
+        <div styleName="recommended-challenges">
+          <span styleName="toggle">
+            <Toggle
+              checked={filter.recommended}
+              onChange={(checked) => {
+                setFilter({
+                  ...filter,
+                  recommended: checked,
+                  sortBy: checked
+                    ? constants.CHALLENGE_SORT_BY_RECOMMENDED
+                    : constants.CHALLENGE_SORT_BY_DEFAULT,
+                });
+              }}
+            />
+          </span>
+          <span>Recommended Challenges</span>
+        </div>
+      )}
 
       <div styleName="footer">
         <Button onClick={clearFilter}>CLEAR FILTER</Button>
@@ -175,6 +263,8 @@ ChallengeFilter.propTypes = {
   challengeSubCommunities: PT.arrayOf(PT.string),
   saveFilter: PT.func,
   clearFilter: PT.func,
+  switchBucket: PT.func,
+  openForRegistrationCount: PT.number,
 };
 
 export default ChallengeFilter;
diff --git a/src/containers/Filter/ChallengeFilter/styles.scss b/src/containers/Filter/ChallengeFilter/styles.scss
index 1af3174..7d1c7fc 100644
--- a/src/containers/Filter/ChallengeFilter/styles.scss
+++ b/src/containers/Filter/ChallengeFilter/styles.scss
@@ -17,7 +17,7 @@ $filter-padding-y: 3 * $base-unit;
   margin-bottom: 18px;
 
   > h3 {
-    margin-bottom: 12px;
+    margin-bottom: 15px;
     font-size: inherit;
     line-height: 19px;
   }
@@ -29,6 +29,18 @@ $filter-padding-y: 3 * $base-unit;
       margin: $base-unit 0;
     }
   }
+
+  :global(.badge) {
+    display: inline-block;
+    margin-left: $base-unit;
+    padding: 0 5px;
+    font-weight: bold;
+    font-size: 11px;
+    line-height: 16px;
+    color: white;
+    background: red;
+    border-radius: 13px;
+  }
 }
 
 .challenge-types,
@@ -51,6 +63,7 @@ $filter-padding-y: 3 * $base-unit;
 
 .skills {
   margin-bottom: 34px;
+  max-width: 230px;
 }
 
 .prize {
@@ -74,6 +87,27 @@ $filter-padding-y: 3 * $base-unit;
   margin-top: -12px;
 }
 
+.input-group {
+  position: relative;
+  margin-top: -12px;
+
+  input {
+    padding-right: 36px !important;
+  }
+
+  .suffix {
+    @include roboto-medium;
+
+    position: absolute;
+    top: 22px;
+    right: 10px;
+    font-size: 13px;
+    line-height: 22px;
+    color: $tc-gray-30;
+    pointer-events: none;
+  }
+}
+
 .recommended-challenges {
   margin: 20px 0 25px;
   font-size: $font-size-sm;
@@ -98,3 +132,4 @@ $filter-padding-y: 3 * $base-unit;
     margin-left: 9px;
   }
 }
+
diff --git a/src/containers/Filter/index.jsx b/src/containers/Filter/index.jsx
index e4717f2..13fdf4d 100644
--- a/src/containers/Filter/index.jsx
+++ b/src/containers/Filter/index.jsx
@@ -11,6 +11,7 @@ const Filter = ({
   tags,
   prizeFrom,
   prizeTo,
+  recommended,
   subCommunities,
   challengeBuckets,
   challengeTypes,
@@ -21,6 +22,7 @@ const Filter = ({
   getChallenges,
   getTags,
   getSubCommunities,
+  openForRegistrationCount,
 }) => {
   useEffect(() => {
     getTags();
@@ -32,6 +34,10 @@ const Filter = ({
     getChallenges(filter);
   };
 
+  const onSwitchBucket = (bucket) => {
+    updateFilter({ bucket });
+  };
+
   return (
     <ChallengeFilter
       bucket={bucket}
@@ -40,6 +46,7 @@ const Filter = ({
       tags={tags}
       prizeFrom={prizeFrom}
       prizeTo={prizeTo}
+      recommended={recommended}
       subCommunities={subCommunities}
       challengeBuckets={challengeBuckets}
       challengeTypes={challengeTypes}
@@ -48,6 +55,8 @@ const Filter = ({
       challengeSubCommunities={challengeSubCommunities}
       saveFilter={onSaveFilter}
       clearFilter={() => {}}
+      switchBucket={onSwitchBucket}
+      openForRegistrationCount={openForRegistrationCount}
     />
   );
 };
@@ -59,6 +68,7 @@ Filter.propTypes = {
   tags: PT.arrayOf(PT.string),
   prizeFrom: PT.number,
   prizeTo: PT.number,
+  recommended: PT.bool,
   subCommunities: PT.arrayOf(PT.string),
   challengeBuckets: PT.arrayOf(PT.string),
   challengeTypes: PT.arrayOf(PT.string),
@@ -69,6 +79,7 @@ Filter.propTypes = {
   getChallenges: PT.func,
   getTags: PT.func,
   getSubCommunities: PT.func,
+  openForRegistrationCount: PT.number,
 };
 
 const mapStateToProps = (state) => ({
@@ -79,12 +90,14 @@ const mapStateToProps = (state) => ({
   tags: state.filter.challenge.tags,
   prizeFrom: state.filter.challenge.prizeFrom,
   prizeTo: state.filter.challenge.prizeTo,
+  recommended: state.filter.challenge.recommended,
   subCommunities: state.filter.challenge.subCommunities,
   challengeBuckets: state.lookup.buckets,
   challengeTypes: state.lookup.types,
   challengeTracks: state.lookup.tracks,
   challengeTags: state.lookup.tags,
   challengeSubCommunities: state.lookup.subCommunities,
+  openForRegistrationCount: state.challenges.openForRegistrationCount,
 });
 
 const mapDispatchToProps = {
diff --git a/src/reducers/challenges.js b/src/reducers/challenges.js
index 827b06f..055d9aa 100644
--- a/src/reducers/challenges.js
+++ b/src/reducers/challenges.js
@@ -1,15 +1,26 @@
 import { handleActions } from "redux-actions";
+import * as util from "../utils/challenge";
+import * as constants from "../constants";
 
 const defaultState = {
   loadingChallenges: false,
   loadingChallengesError: null,
+  loadingRecommendedChallengesError: false,
   challenges: [],
-  challengesFiltered: [],
+  allActiveChallenges: [],
+  openForRegistrationChallenges: [],
+  closedChallenges: [],
+  openForRegistrationCount: 0,
   total: 0,
 };
 
 function onGetChallengesInit(state) {
-  return { ...state, loadingChallenges: true, loadingChallengesError: null };
+  return {
+    ...state,
+    loadingChallenges: true,
+    loadingChallengesError: null,
+    loadingRecommendedChallengesError: false,
+  };
 }
 
 function onGetChallengesDone(state, { payload }) {
@@ -17,8 +28,13 @@ function onGetChallengesDone(state, { payload }) {
     ...state,
     loadingChallenges: false,
     loadingChallengesError: null,
+    loadingRecommendedChallengesError:
+      payload.loadingRecommendedChallengesError,
     challenges: payload.challenges,
-    challengesFiltered: payload.challengesFiltered,
+    allActiveChallenges: payload.allActiveChallenges,
+    openForRegistrationChallenges: payload.openForRegistrationChallenges,
+    closedChallenges: payload.closedChallenges,
+    openForRegistrationCount: payload.openForRegistrationCount,
     total: payload.total,
   };
 }
@@ -29,16 +45,55 @@ function onGetChallengesFailure(state, { payload }) {
     loadingChallenges: false,
     loadingChallengesError: payload,
     challenges: [],
-    challengesFiltered: [],
+    allActiveChallenges: [],
+    openForRegistrationChallenges: [],
+    closedChallenges: [],
+    openForRegistrationCount: 0,
     total: 0,
   };
 }
 
+function onUpdateFilter(state, { payload }) {
+  const FILTER_BUCKETS = constants.FILTER_BUCKETS;
+  const BUCKET_ALL_ACTIVE_CHALLENGES = FILTER_BUCKETS[0];
+  const BUCKET_OPEN_FOR_REGISTRATION = FILTER_BUCKETS[1];
+  const BUCKET_CLOSED_CHALLENGES = FILTER_BUCKETS[2];
+  const filterChange = payload;
+  const {
+    allActiveChallenges,
+    openForRegistrationChallenges,
+    closedChallenges,
+  } = state;
+
+  let challenges;
+  let total;
+
+  if (util.isSwitchingBucket(filterChange)) {
+    switch (filterChange.bucket) {
+      case BUCKET_ALL_ACTIVE_CHALLENGES:
+        challenges = allActiveChallenges;
+        break;
+      case BUCKET_OPEN_FOR_REGISTRATION:
+        challenges = openForRegistrationChallenges;
+        break;
+      case BUCKET_CLOSED_CHALLENGES:
+        challenges = closedChallenges;
+        break;
+    }
+    total = challenges.meta.total;
+
+    return { ...state, challenges, total };
+  }
+
+  return { ...state };
+}
+
 export default handleActions(
   {
     GET_CHALLENGE_INIT: onGetChallengesInit,
     GET_CHALLENGES_DONE: onGetChallengesDone,
     GET_CHALLENGES_FAILURE: onGetChallengesFailure,
+    UPDATE_FILTER: onUpdateFilter,
   },
   defaultState
 );
diff --git a/src/reducers/filter.js b/src/reducers/filter.js
index 6346dce..073fef5 100644
--- a/src/reducers/filter.js
+++ b/src/reducers/filter.js
@@ -1,19 +1,20 @@
 import { handleActions } from "redux-actions";
 import * as constants from "../constants";
+import moment from "moment";
 
 const defaultState = {
   challenge: {
     types: constants.FILTER_CHALLENGE_TYPES,
-    tracks: constants.FILTER_CHALLENGE_TRACKS,
+    tracks: constants.FILTER_CHALLENGE_TRACKS.filter((track) => track !== "QA"),
     search: "",
     tags: [],
     groups: [],
-    startDateEnd: null,
-    endDateStart: null,
+    endDateStart: moment().subtract(99, "year").toDate().toISOString(),
+    startDateEnd: moment().add(1, "year").toDate().toISOString(),
     page: 1,
     perPage: constants.PAGINATION_PER_PAGE[0],
     sortBy: constants.CHALLENGE_SORT_BY["Most recent"],
-    sortOrder: null,
+    sortOrder: constants.SORT_ORDER.ASC,
 
     // ---
 
@@ -21,15 +22,21 @@ const defaultState = {
     prizeFrom: 0,
     prizeTo: 10000,
     subCommunities: [],
+    recommended: false,
   },
 };
 
+function onRestoreFilter(state, { payload }) {
+  return { ...state, ...payload };
+}
+
 function onUpdateFilter(state, { payload }) {
   return { ...state, challenge: { ...state.challenge, ...payload } };
 }
 
 export default handleActions(
   {
+    RESTORE_FILTER: onRestoreFilter,
     UPDATE_FILTER: onUpdateFilter,
   },
   defaultState
diff --git a/src/root.component.js b/src/root.component.js
index a49494c..4eb8c1c 100644
--- a/src/root.component.js
+++ b/src/root.component.js
@@ -5,6 +5,8 @@ import { createHistory, LocationProvider } from "@reach/router";
 import { Provider } from "react-redux";
 import store from "./store";
 import App from "./App";
+import * as util from "./utils/session";
+import actions from "./actions";
 
 // History for location provider
 const history = createHistory(window);
@@ -13,6 +15,13 @@ export default function Root() {
   useEffect(() => {
     // when app starts it should set its side menu structure
     setAppMenu("/earn", appMenu);
+
+    const unsubscribe = store.subscribe(() =>
+      util.persistFilter(util.selectFilter(store.getState()))
+    );
+    return () => {
+      unsubscribe();
+    };
   }, []);
 
   return (
diff --git a/src/services/challenges.js b/src/services/challenges.js
index 1889d9c..b93a5dd 100644
--- a/src/services/challenges.js
+++ b/src/services/challenges.js
@@ -11,6 +11,12 @@ async function getChallenges(filter) {
   return api.get(`/challenges/${challengeQuery}`);
 }
 
+async function getRecommendedChallenges(filter, handle) {
+  const challengeQuery = util.buildQueryString(filter);
+  return api.get(`/recommender-api/${handle}/${challengeQuery}`);
+}
+
 export default {
   getChallenges,
+  getRecommendedChallenges,
 };
diff --git a/src/store.js b/src/store.js
index 0852395..4e2867f 100644
--- a/src/store.js
+++ b/src/store.js
@@ -4,6 +4,8 @@
 import { createStore, compose, applyMiddleware } from "redux";
 import { createPromise } from "redux-promise-middleware";
 import root from "./reducers";
+import actions from "./actions";
+import * as util from "./utils/session";
 
 const middlewares = [
   createPromise({ promiseTypeSuffixes: ["INIT", "DONE", "FAILURE"] }),
@@ -15,4 +17,8 @@ if (process.env.APPMODE === "development") {
   middlewares.push(logger);
 }
 
-export default createStore(root, compose(applyMiddleware(...middlewares)));
+const store = createStore(root, compose(applyMiddleware(...middlewares)));
+
+store.dispatch(actions.filter.restoreFilter(util.restoreFilter()));
+
+export default store;
diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss
index 433ec8b..fde2cc4 100644
--- a/src/styles/_variables.scss
+++ b/src/styles/_variables.scss
@@ -127,6 +127,9 @@ $font-size-sm: 14px;
 $font-size-xs: 12px;
 
 /// APP
+
+$screen-xxl: 1366px;
+
 $base-unit: 5px;
 
 $body-color: $tc-gray-90;
diff --git a/src/utils/challenge.js b/src/utils/challenge.js
index 158f9ea..dceacf3 100644
--- a/src/utils/challenge.js
+++ b/src/utils/challenge.js
@@ -34,7 +34,9 @@ export function createChallengeCriteria(filter) {
     startDateEnd: filter.startDateEnd,
     endDateStart: filter.endDateStart,
     endDateEnd: filter.endDateEnd,
-    sortBy: filter.sortBy,
+    sortBy: isValidCriteriaSortBy(filter.sortBy)
+      ? filter.sortBy
+      : constants.CHALLENGE_SORT_BY_DEFAULT,
     sortOrder: filter.sortOrder,
     groups: filter.groups,
   };
@@ -44,18 +46,22 @@ export function createOpenForRegistrationChallengeCriteria() {
   return {
     status: "Active",
     currentPhaseName: "Registration",
+    endDateStart: null,
+    startDateEnd: null,
   };
 }
 
-export function createActiveChallengeCriteria() {
+export function createAllActiveChallengeCriteria() {
   return {
     status: "Active",
     currentPhaseName: "Submission",
     registrationEndDateEnd: new Date().toISOString(),
+    endDateStart: null,
+    startDateEnd: null,
   };
 }
 
-export function createPastChallengeCriteria() {
+export function createClosedChallengeCriteria() {
   return {
     status: "Completed",
   };
@@ -102,6 +108,19 @@ export function checkRequiredFilterAttributes(filter) {
   return valid;
 }
 
+export function isSwitchingBucket(filterChange) {
+  const keys = Object.keys(filterChange);
+  return keys.length === 1 && keys[0] === "bucket";
+}
+
+export function isDisplayingBucket(filter, bucket) {
+  return filter.bucket === bucket;
+}
+
+export function isValidCriteriaSortBy(sortBy) {
+  return ["updated", "overview.totalPrizes", "name"].includes(sortBy);
+}
+
 /**
  * Returns phase's end date.
  * @param {Object} phase
diff --git a/src/utils/icon.js b/src/utils/icon.js
index 5cc61ff..759360e 100644
--- a/src/utils/icon.js
+++ b/src/utils/icon.js
@@ -119,7 +119,7 @@ function createTCOEventIcon (color) {
           <g id="01_3_Find-Work-Challenges-Non-Logged-In-Hover" transform="translate(-346.000000, -264.000000)">
               <g id="Group-17" transform="translate(329.000000, 245.000000)">
                   <g id="icon-/-challenge-/-track-copy" transform="translate(17.000000, 19.531250)">
-                      <text id="TCO" fontFamily="Helvetica" fontSize="11" fontWeight="normal" lineSpacing="12" fill={color}>
+                      <text id="TCO" fontFamily="Helvetica" fontSize="11" fontWeight="normal" linespacing="12" fill={color}>
                           <tspan x="0" y="44.8854167">TCO</tspan>
                       </text>
                       <g id="icon-/-track-/-design" transform="translate(22.000000, 23.177083)">
@@ -136,3 +136,13 @@ function createTCOEventIcon (color) {
     </svg>
   );
 }
+
+export function createBadgeElement(htmlElement, content) {
+  const badgeElement = document.createElement('span');
+
+  badgeElement.classList.add('badge');
+  badgeElement.textContent = content;
+  htmlElement.appendChild(badgeElement);
+
+  return badgeElement;
+}
diff --git a/src/utils/index.js b/src/utils/index.js
index 62d01b8..5df8191 100644
--- a/src/utils/index.js
+++ b/src/utils/index.js
@@ -122,14 +122,51 @@ export function formatMoneyValue(value) {
   }
 
   if (val.startsWith("-")) {
-    val = `-$${val.slice(1)}`;
+    val = `-\uFF04${val.slice(1)}`;
   } else {
-    val = `$${val}`;
+    val = `\uFF04${val}`;
   }
 
   return val;
 }
 
+/**
+ * Format a number value into the integer text of amount.
+ * Ex: 0 -> 0, greater than 10000 -> 10,000+
+ */
+export function formatPrizeAmount(value) {
+  let val = value || 0;
+  let greaterThan10000 = val >= 10000;
+
+  val = val.toLocaleString("en-US");
+
+  const i = val.indexOf(".");
+  if (i !== -1) {
+    val = val.slice(0, i);
+  }
+
+  val = greaterThan10000 ? "10,000+" : val;
+
+  return val;
+}
+
+export function parsePrizeAmountText(s) {
+  let val = s;
+  if (val.endsWith("+")) {
+    val = val.slice(0, val.length - 1);
+  }
+
+  const i = val.indexOf(".");
+  if (i !== -1) {
+    val = val.slice(0, i);
+  }
+
+  val = val.replace("/,/g", "");
+  val = parseInt(val);
+
+  return isNaN(val) ? 0 : val;
+}
+
 export function clamp(value, min, max) {
   return Math.min(Math.max(value, min), max);
 }
diff --git a/src/utils/menu.js b/src/utils/menu.js
index b060439..b388ee6 100644
--- a/src/utils/menu.js
+++ b/src/utils/menu.js
@@ -9,7 +9,7 @@ export class MenuSelection {
   }
 
   travel(root) {
-    Object.keys(root).forEach((key) => {
+    this.getMenuItems(root).forEach((key) => {
       if (_.isObject(root[key])) {
         root[key].expanded = false;
         root[key].branch = true;
@@ -24,35 +24,37 @@ export class MenuSelection {
     });
   }
 
+  getMenuItems(menu) {
+    return Object.keys(_.omit(menu, "expanded", "active", "branch", "leaf"));
+  }
+
   select(name) {
     let found = false;
 
     const selectInternal = (root) => {
-      Object.keys(_.omit(root, "expanded", "active", "branch", "leaf")).forEach(
-        (key) => {
-          if (found) {
-            return;
-          }
+      this.getMenuItems(root).forEach((key) => {
+        if (found) {
+          return;
+        }
 
-          if (key !== name) {
-            if (root[key].branch) {
-              selectInternal(root[key]);
-            } else {
-              root[key].active = false;
-            }
+        if (key !== name) {
+          if (root[key].branch) {
+            selectInternal(root[key]);
           } else {
-            if (root[key].leaf) {
-              root[key].active = true;
-              this.selectedMenuItem = name;
-            } else {
-              root[key].expanded = !root[key].expanded;
-            }
-
-            found = true;
-            this.emitSelectionEvent();
+            root[key].active = false;
           }
+        } else {
+          if (root[key].leaf) {
+            root[key].active = true;
+            this.selectedMenuItem = name;
+          } else {
+            root[key].expanded = !root[key].expanded;
+          }
+
+          found = true;
+          this.emitSelectionEvent();
         }
-      );
+      });
     };
 
     selectInternal(this.menu);
@@ -62,17 +64,15 @@ export class MenuSelection {
     let leaf = false;
 
     const isLeafInternal = (root) => {
-      Object.keys(_.omit(root, "expanded", "active", "branch", "leaf")).forEach(
-        (key) => {
-          if (key !== name) {
-            if (root[key].branch) {
-              isLeafInternal(root[key]);
-            }
-          } else if (root[key].leaf) {
-            leaf = true;
+      this.getMenuItems(root).forEach((key) => {
+        if (key !== name) {
+          if (root[key].branch) {
+            isLeafInternal(root[key]);
           }
+        } else if (root[key].leaf) {
+          leaf = true;
         }
-      );
+      });
     };
 
     isLeafInternal(this.menu);
@@ -85,20 +85,18 @@ export class MenuSelection {
   }
 
   isExpanded(name) {
-    let expanded = false;
+    let expanded;
 
     const isExpandedInternal = (root) => {
-      Object.keys(_.omit(root, "expanded", "active", "branch", "leaf")).forEach(
-        (key) => {
-          if (key !== name) {
-            if (root[key].branch) {
-              isExpandedInternal(root[key]);
-            }
-          } else if (root[key].branch) {
-            expanded = root[key].expanded;
+      this.getMenuItems(root).forEach((key) => {
+        if (key !== name) {
+          if (root[key].branch) {
+            isExpandedInternal(root[key]);
           }
+        } else if (root[key].branch) {
+          expanded = root[key].expanded;
         }
-      );
+      });
     };
 
     isExpandedInternal(this.menu);
@@ -123,20 +121,18 @@ export class MenuSelection {
     }
 
     const isActiveInternal = (root) => {
-      Object.keys(_.omit(root, "expanded", "active", "branch", "leaf")).forEach(
-        (key) => {
-          if (key !== this.selectedMenuItem) {
-            if (root[key].branch) {
-              stack.push(key);
-              isActiveInternal(root[key]);
-              stack.pop(key);
-            }
-          } else {
+      this.getMenuItems(root).forEach((key) => {
+        if (key !== this.selectedMenuItem) {
+          if (root[key].branch) {
             stack.push(key);
-            path = [...stack.arr];
+            isActiveInternal(root[key]);
+            stack.pop(key);
           }
+        } else {
+          stack.push(key);
+          path = [...stack.arr];
         }
-      );
+      });
     };
 
     isActiveInternal(this.menu);
diff --git a/src/utils/pagination.js b/src/utils/pagination.js
index 8f0adf6..292d7fe 100644
--- a/src/utils/pagination.js
+++ b/src/utils/pagination.js
@@ -10,11 +10,11 @@ export function pageIndexToPage(pageIndex) {
  * @param {any} response Web APIs Response
  * @return {Object} pagination data
  */
-export function getResponseHeaders(reponse) {
+export function getResponseHeaders(response) {
   return {
-    page: +(reponse.headers.get("X-Page") || 0),
-    perPage: +(reponse.headers.get("X-Per-Page") || 0),
-    total: +(reponse.headers.get("X-Total") || 0),
-    totalPages: +(reponse.headers.get("X-Total-Pages") || 0),
+    page: +(response.headers.get("X-Page") || 0),
+    perPage: +(response.headers.get("X-Per-Page") || 0),
+    total: +(response.headers.get("X-Total") || 0),
+    totalPages: +(response.headers.get("X-Total-Pages") || 0),
   };
 }
diff --git a/src/utils/session.js b/src/utils/session.js
new file mode 100644
index 0000000..ef396f6
--- /dev/null
+++ b/src/utils/session.js
@@ -0,0 +1,29 @@
+function selectFilter(state) {
+  return state.filter;
+}
+
+let currentFilterValue;
+function persistFilter(filter) {
+  let previousFilterValue = currentFilterValue;
+  currentFilterValue = filter;
+
+  if (previousFilterValue !== currentFilterValue) {
+    try {
+      sessionStorage.setItem("filter", JSON.stringify(filter));
+    } catch (e) {
+      console.error(e);
+    }
+  }
+}
+
+function restoreFilter() {
+  let filter;
+  try {
+    filter = JSON.parse(sessionStorage.getItem("filter"));
+  } catch (e) {
+    filter = {};
+  }
+  return filter;
+}
+
+export { selectFilter, persistFilter, restoreFilter };
diff --git a/src/utils/tag.js b/src/utils/tag.js
index 39bea25..2b4418a 100644
--- a/src/utils/tag.js
+++ b/src/utils/tag.js
@@ -6,7 +6,7 @@ export function calculateNumberOfVisibleTags(tags) {
   let n = tags.length;
   if (tagsString.length > MAX_LEN) {
     let ss = "";
-    for (n = 0; n < tags.length && ss.length < 20; n += 1) {
+    for (n = 0; n < tags.length && ss.length < MAX_LEN; n += 1) {
       ss = ss.concat(tags[n]);
     }
   }
diff --git a/src/utils/url.js b/src/utils/url.js
index bffc6d1..80fb7d3 100644
--- a/src/utils/url.js
+++ b/src/utils/url.js
@@ -8,7 +8,7 @@ import qs from "qs";
  * `{ p: undefined }` => ""
  * `{ p: value }`     => "p=value"
  * `{ p: [] }`        => ""
- * `{ p: ['Challenge', 'First2Finish', 'Task'] } => "p[]=Challenge&p[]=First2Finish&p[]=Taks`
+ * `{ p: ['Challenge', 'First2Finish', 'Task'] } => "p[]=Challenge&p[]=First2Finish&p[]=Task`
  * `{ p: ['Design', 'Development', 'Data Science', 'Quality Assurance'] }` => "p[]=Design&p[]=Development&p=Data%20Science&p[]=Quality%20Assurance"
  * `{ p: { Des: true, Dev: true, DS: false, QA: false } }` => "p[Des]=true&p[Dev]=true&p[DS]=false&p[QA]=false"
  *