diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx
new file mode 100644
index 0000000000..d4db2b0e63
--- /dev/null
+++ b/packages/app/src/components/catalog/EntityPage.tsx
@@ -0,0 +1,494 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { ReactNode, useMemo, useState } from 'react';
+import BadgeIcon from '@material-ui/icons/CallToAction';
+import { EmptyState } from '@backstage/core';
+import {
+ EntityApiDefinitionCard,
+ EntityConsumingComponentsCard,
+ EntityHasApisCard,
+ EntityProvidingComponentsCard,
+ EntityProvidedApisCard,
+ EntityConsumedApisCard,
+} from '@backstage/plugin-api-docs';
+import { EntityBadgesDialog } from '@backstage/plugin-badges';
+import {
+ EntityAboutCard,
+ EntityHasComponentsCard,
+ EntityHasSubcomponentsCard,
+ EntityHasSystemsCard,
+ EntityLayout,
+ EntityLinksCard,
+ EntitySystemDiagramCard,
+ EntitySwitch,
+ isComponentType,
+ isKind,
+} from '@backstage/plugin-catalog';
+import {
+ EntityCircleCIContent,
+ isCircleCIAvailable,
+} from '@backstage/plugin-circleci';
+import {
+ EntityCloudbuildContent,
+ isCloudbuildAvailable,
+} from '@backstage/plugin-cloudbuild';
+import {
+ EntityGithubActionsContent,
+ EntityRecentGithubActionsRunsCard,
+ isGithubActionsAvailable,
+} from '@backstage/plugin-github-actions';
+import {
+ EntityJenkinsContent,
+ EntityLatestJenkinsRunCard,
+ isJenkinsAvailable,
+} from '@backstage/plugin-jenkins';
+import { EntityKafkaContent } from '@backstage/plugin-kafka';
+import { EntityKubernetesContent } from '@backstage/plugin-kubernetes';
+import {
+ EntityLastLighthouseAuditCard,
+ EntityLighthouseContent,
+ isLighthouseAvailable,
+} from '@backstage/plugin-lighthouse';
+import {
+ EntityGroupProfileCard,
+ EntityMembersListCard,
+ EntityOwnershipCard,
+ EntityUserProfileCard,
+} from '@backstage/plugin-org';
+import {
+ EntityPagerDutyCard,
+ isPagerDutyAvailable,
+} from '@backstage/plugin-pagerduty';
+import {
+ EntityRollbarContent,
+ isRollbarAvailable,
+} from '@backstage/plugin-rollbar';
+import { EntitySentryContent } from '@backstage/plugin-sentry';
+import { EntityTechdocsContent } from '@backstage/plugin-techdocs';
+import { EntityTodoContent } from '@backstage/plugin-todo';
+import { Button, Grid } from '@material-ui/core';
+import {
+ EntityBuildkiteContent,
+ isBuildkiteAvailable,
+} from '@roadiehq/backstage-plugin-buildkite';
+import {
+ EntityGithubInsightsContent,
+ EntityGithubInsightsLanguagesCard,
+ EntityGithubInsightsReadmeCard,
+ EntityGithubInsightsReleasesCard,
+ isGithubInsightsAvailable,
+} from '@roadiehq/backstage-plugin-github-insights';
+import {
+ EntityGithubPullRequestsContent,
+ EntityGithubPullRequestsOverviewCard,
+ isGithubPullRequestsAvailable,
+} from '@roadiehq/backstage-plugin-github-pull-requests';
+import {
+ EntityTravisCIContent,
+ EntityTravisCIOverviewCard,
+ isTravisciAvailable,
+} from '@roadiehq/backstage-plugin-travis-ci';
+
+const EntityLayoutWrapper = (props: { children?: ReactNode }) => {
+ const [badgesDialogOpen, setBadgesDialogOpen] = useState(false);
+
+ const extraMenuItems = useMemo(() => {
+ return [
+ {
+ title: 'Badges',
+ Icon: BadgeIcon,
+ onClick: () => setBadgesDialogOpen(true),
+ },
+ ];
+ }, []);
+
+ return (
+ <>
+
+ {props.children}
+
+ setBadgesDialogOpen(false)}
+ />
+ >
+ );
+};
+
+export const cicdContent = (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Read more
+
+ }
+ />
+
+
+);
+
+const cicdCard = (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
+
+const errorsContent = (
+
+
+
+
+
+
+
+
+
+);
+
+const overviewContent = (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {cicdCard}
+
+
+ Boolean(isGithubInsightsAvailable(e))}>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Boolean(isGithubPullRequestsAvailable(e))}>
+
+
+
+
+
+
+
+
+
+
+);
+
+const serviceEntityPage = (
+
+
+ {overviewContent}
+
+
+
+ {cicdContent}
+
+
+
+ {errorsContent}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
+
+const websiteEntityPage = (
+
+
+ {overviewContent}
+
+
+
+ {cicdContent}
+
+
+
+
+
+
+
+ {errorsContent}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
+
+const defaultEntityPage = (
+
+
+ {overviewContent}
+
+
+
+
+
+
+
+
+
+
+);
+
+const componentPage = (
+
+
+ {serviceEntityPage}
+
+
+
+ {websiteEntityPage}
+
+
+ {defaultEntityPage}
+
+);
+
+const apiPage = (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
+
+const userPage = (
+
+
+
+
+
+
+
+
+
+
+
+
+);
+
+const groupPage = (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
+
+const systemPage = (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
+
+const domainPage = (
+
+
+
+
+
+
+
+
+
+
+
+
+);
+
+export const entityPage = (
+
+
+
+
+
+
+
+
+ {defaultEntityPage}
+
+);