diff --git a/src/customizations/volto/components/theme/View/Readme.md b/src/customizations/volto/components/theme/View/Readme.md
new file mode 100644
index 0000000..0a2502b
--- /dev/null
+++ b/src/customizations/volto/components/theme/View/Readme.md
@@ -0,0 +1 @@
+This cusomization needs to be removed in volto 17.
diff --git a/src/customizations/volto/components/theme/View/View.jsx b/src/customizations/volto/components/theme/View/View.jsx
new file mode 100644
index 0000000..e836e45
--- /dev/null
+++ b/src/customizations/volto/components/theme/View/View.jsx
@@ -0,0 +1,299 @@
+/**
+ * View container.
+ * @module components/theme/View/View
+ */
+
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import { compose } from 'redux';
+import { Redirect } from 'react-router-dom';
+import { Portal } from 'react-portal';
+import { injectIntl } from 'react-intl';
+import qs from 'query-string';
+
+import {
+ ContentMetadataTags,
+ Comments,
+ Tags,
+ Toolbar,
+} from '@plone/volto/components';
+import { listActions, getContent } from '@plone/volto/actions';
+import {
+ BodyClass,
+ getBaseUrl,
+ flattenToAppURL,
+ getLayoutFieldname,
+ hasApiExpander,
+} from '@plone/volto/helpers';
+
+import config from '@plone/volto/registry';
+
+/**
+ * View container class.
+ * @class View
+ * @extends Component
+ */
+class View extends Component {
+ /**
+ * Property types.
+ * @property {Object} propTypes Property types.
+ * @static
+ */
+ static propTypes = {
+ actions: PropTypes.shape({
+ object: PropTypes.arrayOf(PropTypes.object),
+ object_buttons: PropTypes.arrayOf(PropTypes.object),
+ user: PropTypes.arrayOf(PropTypes.object),
+ }),
+ listActions: PropTypes.func.isRequired,
+ /**
+ * Action to get the content
+ */
+ getContent: PropTypes.func.isRequired,
+ /**
+ * Pathname of the object
+ */
+ pathname: PropTypes.string.isRequired,
+ location: PropTypes.shape({
+ search: PropTypes.string,
+ pathname: PropTypes.string,
+ }).isRequired,
+ /**
+ * Version id of the object
+ */
+ versionId: PropTypes.string,
+ /**
+ * Content of the object
+ */
+ content: PropTypes.shape({
+ /**
+ * Layout of the object
+ */
+ layout: PropTypes.string,
+ /**
+ * Allow discussion of the object
+ */
+ allow_discussion: PropTypes.bool,
+ /**
+ * Title of the object
+ */
+ title: PropTypes.string,
+ /**
+ * Description of the object
+ */
+ description: PropTypes.string,
+ /**
+ * Type of the object
+ */
+ '@type': PropTypes.string,
+ /**
+ * Subjects of the object
+ */
+ subjects: PropTypes.arrayOf(PropTypes.string),
+ is_folderish: PropTypes.bool,
+ }),
+ error: PropTypes.shape({
+ /**
+ * Error type
+ */
+ status: PropTypes.number,
+ }),
+ };
+
+ /**
+ * Default properties.
+ * @property {Object} defaultProps Default properties.
+ * @static
+ */
+ static defaultProps = {
+ actions: null,
+ content: null,
+ versionId: null,
+ error: null,
+ };
+
+ state = {
+ hasObjectButtons: null,
+ isClient: false,
+ };
+
+ componentDidMount() {
+ // Do not trigger the actions action if the expander is present
+ if (!hasApiExpander('actions', getBaseUrl(this.props.pathname))) {
+ this.props.listActions(getBaseUrl(this.props.pathname));
+ }
+
+ this.props.getContent(
+ getBaseUrl(this.props.pathname),
+ this.props.versionId,
+ );
+ this.setState({ isClient: true });
+ }
+
+ /**
+ * Component will receive props
+ * @method componentWillReceiveProps
+ * @param {Object} nextProps Next properties
+ * @returns {undefined}
+ */
+ UNSAFE_componentWillReceiveProps(nextProps) {
+ if (nextProps.pathname !== this.props.pathname) {
+ // Do not trigger the actions action if the expander is present
+ if (!hasApiExpander('actions', getBaseUrl(nextProps.pathname))) {
+ this.props.listActions(getBaseUrl(nextProps.pathname));
+ }
+
+ this.props.getContent(
+ getBaseUrl(nextProps.pathname),
+ this.props.versionId,
+ );
+ }
+
+ if (nextProps.actions.object_buttons) {
+ const objectButtons = nextProps.actions.object_buttons;
+ this.setState({
+ hasObjectButtons: !!objectButtons.length,
+ });
+ }
+ }
+
+ /**
+ * Default fallback view
+ * @method getViewDefault
+ * @returns {string} Markup for component.
+ */
+ getViewDefault = () => config.views.defaultView;
+
+ /**
+ * Get view by content type
+ * @method getViewByType
+ * @returns {string} Markup for component.
+ */
+ getViewByType = () =>
+ config.views.contentTypesViews[this.props.content['@type']] || null;
+
+ /**
+ * Get view by content layout property
+ * @method getViewByLayout
+ * @returns {string} Markup for component.
+ */
+ getViewByLayout = () =>
+ config.views.layoutViews[
+ this.props.content[getLayoutFieldname(this.props.content)]
+ ] || null;
+
+ /**
+ * Cleans the component displayName (specially for connected components)
+ * which have the Connect(componentDisplayName)
+ * @method cleanViewName
+ * @param {string} dirtyDisplayName The displayName
+ * @returns {string} Clean displayName (no Connect(...)).
+ */
+ cleanViewName = (dirtyDisplayName) =>
+ dirtyDisplayName
+ .replace('Connect(', '')
+ .replace('injectIntl(', '')
+ .replace(')', '')
+ .replace('connect(', '')
+ .toLowerCase();
+
+ /**
+ * Render method.
+ * @method render
+ * @returns {string} Markup for the component.
+ */
+ render() {
+ const { views } = config;
+ if (this.props.error && this.props.error.code === 301) {
+ const redirect = flattenToAppURL(this.props.error.url).split('?')[0];
+ return