diff --git a/client/modules/_hooks/src/datafiles/projects/types.ts b/client/modules/_hooks/src/datafiles/projects/types.ts
index 7b8f0bc483..2ffb9337c8 100644
--- a/client/modules/_hooks/src/datafiles/projects/types.ts
+++ b/client/modules/_hooks/src/datafiles/projects/types.ts
@@ -5,6 +5,7 @@ export type TProjectUser = {
   inst: string;
   role: 'pi' | 'co_pi' | 'team_member' | 'guest';
   username?: string;
+  authorship?: boolean;
 };
 
 export type TProjectAward = {
@@ -92,6 +93,8 @@ export type TBaseProjectValue = {
   fileObjs: TFileObj[];
   fileTags: TFileTag[];
 
+  hazmapperMaps?: THazmapperMap[];
+
   license?: string;
 };
 
@@ -102,6 +105,23 @@ export type TEntityValue = {
   authors?: TProjectUser[];
   fileObjs?: TFileObj[];
   fileTags: TFileTag[];
+  dateStart?: string;
+  dateEnd?: string;
+  location?: string;
+  event?: string;
+  facility?: TDropdownValue;
+  latitude?: string;
+  longitude?: string;
+  dois?: string[];
+  referencedData: TReferencedWork[];
+  relatedWork: TAssociatedProject[];
+
+  experimentType?: TDropdownValue;
+  equipmentType?: TDropdownValue;
+  procedureStart?: string;
+  procedureEnd?: string;
+
+  simulationType?: TDropdownValue;
 };
 
 export type TProjectMeta = {
@@ -126,6 +146,7 @@ export type TPreviewTreeData = {
   uuid: string;
   value: TEntityValue;
   order: number;
+  publicationDate?: string;
   children: TPreviewTreeData[];
 };
 
diff --git a/client/modules/_hooks/src/datafiles/projects/useProjectListing.ts b/client/modules/_hooks/src/datafiles/projects/useProjectListing.ts
index 5d7aabe895..f4cbd83fe1 100644
--- a/client/modules/_hooks/src/datafiles/projects/useProjectListing.ts
+++ b/client/modules/_hooks/src/datafiles/projects/useProjectListing.ts
@@ -1,4 +1,5 @@
 import { useQuery } from '@tanstack/react-query';
+import { useSearchParams } from 'react-router-dom';
 import apiClient from '../../apiClient';
 import { TBaseProject } from './types';
 
@@ -10,25 +11,37 @@ export type TProjectListingResponse = {
 async function getProjectListing({
   page = 1,
   limit = 100,
+  queryString,
   signal,
 }: {
   page: number;
   limit: number;
+  queryString?: string;
   signal: AbortSignal;
 }) {
   const resp = await apiClient.get<TProjectListingResponse>(
     '/api/projects/v2',
     {
       signal,
-      params: { offset: (page - 1) * limit, limit },
+      params: { offset: (page - 1) * limit, limit, q: queryString },
     }
   );
   return resp.data;
 }
 
 export function useProjectListing(page: number, limit: number) {
+  const [searchParams] = useSearchParams();
+  const queryString = searchParams.get('q') ?? undefined;
   return useQuery({
-    queryKey: ['datafiles', 'projects', 'listing', page, limit],
-    queryFn: ({ signal }) => getProjectListing({ page, limit, signal }),
+    queryKey: [
+      'datafiles',
+      'projects',
+      'listing',
+      page,
+      limit,
+      queryString ?? '',
+    ],
+    queryFn: ({ signal }) =>
+      getProjectListing({ page, limit, queryString, signal }),
   });
 }
diff --git a/client/modules/_hooks/src/datafiles/useFileListing.ts b/client/modules/_hooks/src/datafiles/useFileListing.ts
index a556e38668..3faa862e4d 100644
--- a/client/modules/_hooks/src/datafiles/useFileListing.ts
+++ b/client/modules/_hooks/src/datafiles/useFileListing.ts
@@ -1,6 +1,7 @@
 import { useInfiniteQuery } from '@tanstack/react-query';
 import apiClient from '../apiClient';
 import { AxiosError } from 'axios';
+import { useSearchParams } from 'react-router-dom';
 
 export type TFileListing = {
   system: string;
@@ -28,13 +29,14 @@ async function getFileListing(
   limit: number = 100,
   page: number = 0,
   nextPageToken: string | undefined,
+  queryString: string | undefined,
   { signal }: { signal: AbortSignal }
 ) {
   const offset = page * limit;
 
   const res = await apiClient.get<FileListingResponse>(
     `/api/datafiles/${api}/${scheme}/listing/${system}/${path}`,
-    { signal, params: { offset, limit, nextPageToken } }
+    { signal, params: { offset, limit, nextPageToken, q: queryString } }
   );
   return res.data;
 }
@@ -61,12 +63,21 @@ function useFileListing({
   pageSize = 100,
   disabled = false,
 }: TFileListingHookArgs) {
+  const [searchParams] = useSearchParams();
+  const queryString = searchParams.get('q');
   return useInfiniteQuery<
     FileListingResponse,
     AxiosError<{ message?: string }>
   >({
     initialPageParam: 0,
-    queryKey: ['datafiles', 'fileListing', api, system, path],
+    queryKey: [
+      'datafiles',
+      'fileListing',
+      api,
+      system,
+      path,
+      queryString ?? '',
+    ],
     queryFn: ({ pageParam, signal }) =>
       getFileListing(
         api,
@@ -76,6 +87,7 @@ function useFileListing({
         pageSize,
         (pageParam as TFileListingPageParam).page,
         (pageParam as TFileListingPageParam).nextPageToken,
+        queryString ?? undefined,
         {
           signal,
         }
diff --git a/client/modules/datafiles/src/DatafilesToolbar/DatafilesToolbar.tsx b/client/modules/datafiles/src/DatafilesToolbar/DatafilesToolbar.tsx
index 1280f4f436..31b6341d67 100644
--- a/client/modules/datafiles/src/DatafilesToolbar/DatafilesToolbar.tsx
+++ b/client/modules/datafiles/src/DatafilesToolbar/DatafilesToolbar.tsx
@@ -24,7 +24,9 @@ const ToolbarButton: React.FC<ButtonProps> = (props) => {
   );
 };
 
-export const DatafilesToolbar: React.FC = () => {
+export const DatafilesToolbar: React.FC<{ searchInput?: React.ReactNode }> = ({
+  searchInput,
+}) => {
   const { api, system, scheme, path } = useFileListingRouteParams();
   const { selectedFiles } = useSelectedFiles(api, system, path);
   const { user } = useAuthenticatedUser();
@@ -45,7 +47,7 @@ export const DatafilesToolbar: React.FC = () => {
 
   return (
     <div className={styles.toolbarRoot}>
-      <span>(search bar goes here)</span>
+      <div style={{ marginLeft: '12px' }}>{searchInput ?? null}</div>
 
       <div className={styles.toolbarButtonContainer}>
         <DatafilesModal.Rename api={api} system={system} path={path}>
diff --git a/client/modules/datafiles/src/FileListing/FileListing.tsx b/client/modules/datafiles/src/FileListing/FileListing.tsx
index 252286e60d..07a1e22a4f 100644
--- a/client/modules/datafiles/src/FileListing/FileListing.tsx
+++ b/client/modules/datafiles/src/FileListing/FileListing.tsx
@@ -24,8 +24,16 @@ export const FileListing: React.FC<
     system: string;
     path?: string;
     scheme?: string;
+    baseRoute?: string;
   } & Omit<TableProps, 'columns'>
-> = ({ api, system, path = '', scheme = 'private', ...tableProps }) => {
+> = ({
+  api,
+  system,
+  path = '',
+  scheme = 'private',
+  baseRoute,
+  ...tableProps
+}) => {
   // Base file listing for use with My Data/Community Data
   const [previewModalState, setPreviewModalState] = useState<{
     isOpen: boolean;
@@ -43,7 +51,7 @@ export const FileListing: React.FC<
           record.type === 'dir' ? (
             <NavLink
               className="listing-nav-link"
-              to={`../${encodeURIComponent(record.path)}`}
+              to={`${baseRoute ?? '..'}/${encodeURIComponent(record.path)}`}
               replace={false}
             >
               <i
@@ -85,7 +93,7 @@ export const FileListing: React.FC<
         render: (d) => new Date(d).toLocaleString(),
       },
     ],
-    [setPreviewModalState]
+    [setPreviewModalState, baseRoute]
   );
 
   return (
diff --git a/client/modules/datafiles/src/projects/BaseProjectDetails.module.css b/client/modules/datafiles/src/projects/BaseProjectDetails.module.css
index 10737750ae..8a66681587 100644
--- a/client/modules/datafiles/src/projects/BaseProjectDetails.module.css
+++ b/client/modules/datafiles/src/projects/BaseProjectDetails.module.css
@@ -10,3 +10,7 @@
   -webkit-box-orient: vertical;
   overflow: hidden;
 }
+
+.prj-row td {
+  padding: 2px 0px;
+}
diff --git a/client/modules/datafiles/src/projects/BaseProjectDetails.tsx b/client/modules/datafiles/src/projects/BaseProjectDetails.tsx
index 2de96ae8a1..8020e940d5 100644
--- a/client/modules/datafiles/src/projects/BaseProjectDetails.tsx
+++ b/client/modules/datafiles/src/projects/BaseProjectDetails.tsx
@@ -1,8 +1,8 @@
 import React, { useEffect, useState, useCallback } from 'react';
-import { TBaseProjectValue } from '@client/hooks';
+import { TBaseProjectValue, TProjectUser } from '@client/hooks';
 
 import styles from './BaseProjectDetails.module.css';
-import { Button } from 'antd';
+import { Button, Col, Popover, Row, Tooltip } from 'antd';
 
 export const DescriptionExpander: React.FC<React.PropsWithChildren> = ({
   children,
@@ -49,49 +49,173 @@ export const DescriptionExpander: React.FC<React.PropsWithChildren> = ({
   );
 };
 
+export const LicenseDisplay: React.FC<{ licenseType: string }> = ({
+  licenseType,
+}) => {
+  const ENTITY_ICON_MAP: Record<string, string> = {
+    'GNU General Public License': 'curation-gpl',
+    'Open Data Commons Attribution': 'curation-odc',
+    'Open Data Commons Public Domain Dedication': 'curation-odc',
+    'Creative Commons Attribution': 'curation-cc-share',
+    'Creative Commons Public Domain Dedication': 'curation-cc-zero',
+    '3-Clause BSD License': 'curation-3bsd',
+  };
+  return (
+    <div style={{ display: 'flex', alignItems: 'center' }}>
+      <i className={ENTITY_ICON_MAP[licenseType]} />
+      &nbsp;
+      {licenseType}
+    </div>
+  );
+};
+
+export const UsernamePopover: React.FC<{ user: TProjectUser }> = ({ user }) => {
+  const content = (
+    <article
+      style={{
+        width: '500px',
+        display: 'flex',
+        flexDirection: 'column',
+        gap: '10px',
+      }}
+    >
+      <Row>
+        <Col span={8}>Name</Col>
+        <Col offset={4} span={12}>
+          <strong>
+            {user.fname} {user.lname}
+          </strong>
+        </Col>
+      </Row>
+      <Row gutter={[0, 40]}>
+        <Col span={8}>Email</Col>
+        <Col offset={4} span={12}>
+          <strong>{user.email}</strong>
+        </Col>
+      </Row>
+      <Row gutter={[0, 40]}>
+        <Col span={8}>Institution</Col>
+        <Col offset={4} span={12}>
+          <strong>{user.inst}</strong>
+        </Col>
+      </Row>
+    </article>
+  );
+  return (
+    <Popover
+      trigger="click"
+      content={content}
+      title={
+        <h3 style={{ marginTop: '0px' }}>{`${user.lname}, ${user.fname}`}</h3>
+      }
+    >
+      <Button type="link" style={{ userSelect: 'text' }}>
+        <strong>
+          {user.lname}, {user.fname}
+        </strong>
+      </Button>
+    </Popover>
+  );
+};
+
+const projectTypeMapping = {
+  field_recon: 'Field research',
+  other: 'Other',
+  experimental: 'Experimental',
+  simulation: 'Simulation',
+  hybrid_simulation: 'Hybrid Simulation',
+  field_reconnaissance: 'Field Reconaissance',
+  None: 'None',
+};
+
 export const BaseProjectDetails: React.FC<{
   projectValue: TBaseProjectValue;
-}> = ({ projectValue }) => {
+  publicationDate?: string;
+}> = ({ projectValue, publicationDate }) => {
   const pi = projectValue.users.find((u) => u.role === 'pi');
   const coPis = projectValue.users.filter((u) => u.role === 'co_pi');
+  const projectType = [
+    projectTypeMapping[projectValue.projectType],
+    ...(projectValue.frTypes?.map((t) => t.name) ?? []),
+  ].join(' | ');
 
   return (
     <section style={{ marginBottom: '20px' }}>
-      <table style={{ width: '100%', marginBottom: '20px' }}>
+      <table
+        style={{ width: '100%', marginBottom: '20px', borderSpacing: '200px' }}
+      >
         <colgroup>
           <col style={{ width: '200px' }} />
           <col />
         </colgroup>
         <tbody>
-          <tr className="prj-row">
-            <td>PI</td>
-            <td
-              style={{ fontWeight: 'bold' }}
-            >{`${pi?.lname}, ${pi?.fname}`}</td>
-          </tr>
-          <tr className="prj-row">
-            <td>Co-PIs</td>
-            <td style={{ fontWeight: 'bold' }}>
-              {coPis.map((u) => `${u.lname}, ${u.fname}`).join(', ')}
-            </td>
-          </tr>
-          <tr className="prj-row">
-            <td>Project Type</td>
-            <td style={{ fontWeight: 'bold' }}>{projectValue.projectType}</td>
-          </tr>
-          <tr className="prj-row">
-            <td>Data Types</td>
-            <td style={{ fontWeight: 'bold' }}>
-              {projectValue.dataTypes?.map((d) => d.name).join(', ')}
-            </td>
-          </tr>
-          <tr className="prj-row">
-            <td>Natural Hazard Type</td>
+          {pi && projectValue.projectType !== 'other' && (
+            <tr className={styles['prj-row']}>
+              <td>PI</td>
+              <td style={{ fontWeight: 'bold' }}>
+                <UsernamePopover user={pi} />
+              </td>
+            </tr>
+          )}
+          {coPis.length > 0 && projectValue.projectType !== 'other' && (
+            <tr className={styles['prj-row']}>
+              <td>Co-PIs</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {coPis.map((u, i) => (
+                  <>
+                    <UsernamePopover user={u} />
+                    {i !== coPis.length - 1 && '; '}
+                  </>
+                ))}
+              </td>
+            </tr>
+          )}
+          {projectValue.authors.length > 0 &&
+            projectValue.projectType === 'other' && (
+              <tr className={styles['prj-row']}>
+                <td>Authors</td>
+                <td style={{ fontWeight: 'bold' }}>
+                  {projectValue.authors.map((u, i) => (
+                    <>
+                      <UsernamePopover user={u} />
+                      {i !== projectValue.authors.length - 1 && '; '}
+                    </>
+                  ))}
+                </td>
+              </tr>
+            )}
+          {projectValue.projectType !== 'other' && (
+            <tr className={styles['prj-row']}>
+              <td>Project Type</td>
+              <td style={{ fontWeight: 'bold' }}>{projectType}</td>
+            </tr>
+          )}
+          {(projectValue.dataTypes?.length ?? 0) > 0 && (
+            <tr className={styles['prj-row']}>
+              <td>Data Type(s)</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {projectValue.dataTypes?.map((d) => d.name).join(', ')}
+              </td>
+            </tr>
+          )}
+          <tr className={styles['prj-row']}>
+            <td>Natural Hazard Type(s)</td>
             <td style={{ fontWeight: 'bold' }}>{`${projectValue.nhTypes
               .map((t) => t.name)
               .join(', ')}`}</td>
           </tr>
-          <tr className="prj-row" hidden={!projectValue.facilities.length}>
+          {publicationDate && (
+            <tr className={styles['prj-row']}>
+              <td>Date of Publication</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {new Date(publicationDate).toISOString().split('T')[0]}
+              </td>
+            </tr>
+          )}
+          <tr
+            className={styles['prj-row']}
+            hidden={!projectValue.facilities.length}
+          >
             <td>Facilities</td>
             <td style={{ fontWeight: 'bold' }}>
               {projectValue.facilities.map((t) => (
@@ -99,35 +223,101 @@ export const BaseProjectDetails: React.FC<{
               ))}
             </td>
           </tr>
-          <tr>
-            <td>Events</td>
-            <td style={{ fontWeight: 'bold' }}>
-              {projectValue.nhEvents.map((evt) => (
-                <div key={JSON.stringify(evt)}>
-                  {evt.eventName} | {evt.location} {evt.eventStart}-
-                  {evt.eventEnd} | Lat {evt.latitude} long {evt.longitude}
-                </div>
-              ))}
-            </td>
-          </tr>
-          <tr className="prj-row">
-            <td>Awards</td>
-            <td style={{ fontWeight: 'bold' }}>
-              {projectValue.awardNumbers.map((t) => (
-                <div key={JSON.stringify(t)}>
-                  {[t.name, t.number, t.fundingSource]
-                    .filter((v) => !!v)
-                    .join(' | ')}{' '}
-                </div>
-              ))}
-            </td>
-          </tr>
-          <tr className="prj-row">
+          {(projectValue.nhEvents?.length ?? 0) > 0 && (
+            <tr>
+              <td>Event(s)</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {projectValue.nhEvents.map((evt) => (
+                  <div key={JSON.stringify(evt)}>
+                    {evt.eventName} | {evt.location} |{' '}
+                    {new Date(evt.eventStart).toISOString().split('T')[0]}
+                    {' ― '}
+                    {
+                      new Date(evt.eventEnd ?? evt.eventStart)
+                        .toISOString()
+                        .split('T')[0]
+                    }{' '}
+                    |{' '}
+                    <a
+                      href={`https://www.google.com/maps/place/${evt.latitude},${evt.longitude}`}
+                      rel="noopener noreferrer"
+                      target="_blank"
+                    >
+                      Lat {evt.latitude} long {evt.longitude}
+                    </a>
+                  </div>
+                ))}
+              </td>
+            </tr>
+          )}
+          {(projectValue.awardNumbers?.length ?? 0) > 0 && (
+            <tr className={styles['prj-row']}>
+              <td>Awards</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {projectValue.awardNumbers.map((t) => (
+                  <div key={JSON.stringify(t)}>
+                    {[t.name, t.number, t.fundingSource]
+                      .filter((v) => !!v)
+                      .join(' | ')}{' '}
+                  </div>
+                ))}
+              </td>
+            </tr>
+          )}
+          {(projectValue.associatedProjects?.length ?? 0) > 0 && (
+            <tr className={styles['prj-row']}>
+              <td>Related Work</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {projectValue.associatedProjects.map((assoc) => (
+                  <div key={JSON.stringify(assoc)}>
+                    <a
+                      href={assoc.href}
+                      rel="noopener noreferrer"
+                      target="_blank"
+                    >
+                      {assoc.title}
+                    </a>
+                  </div>
+                ))}
+              </td>
+            </tr>
+          )}
+          <tr className={styles['prj-row']}>
             <td>Keywords</td>
             <td style={{ fontWeight: 'bold' }}>
               {projectValue.keywords.join(', ')}
             </td>
           </tr>
+          {(projectValue.hazmapperMaps?.length ?? 0) > 0 && (
+            <tr className={styles['prj-row']}>
+              <td>Hazmapper Maps</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {(projectValue.hazmapperMaps ?? []).map((m) => (
+                  <div key={m.uuid}>
+                    {m.name}&nbsp;
+                    <Tooltip title="Open in HazMapper">
+                      <a
+                        href={`https://hazmapper.tacc.utexas.edu/hazmapper/project-public/${m.uuid}`}
+                        rel="noopener noreferrer"
+                        target="_blank"
+                      >
+                        <i role="none" className="fa fa-external-link"></i>
+                      </a>
+                    </Tooltip>
+                  </div>
+                ))}
+              </td>
+            </tr>
+          )}
+
+          {projectValue.projectType === 'other' && projectValue.license && (
+            <tr className={styles['prj-row']}>
+              <td>License</td>
+              <td style={{ fontWeight: 'bold' }}>
+                <LicenseDisplay licenseType={projectValue.license} />
+              </td>
+            </tr>
+          )}
         </tbody>
       </table>
       <DescriptionExpander>
diff --git a/client/modules/datafiles/src/projects/ProjectCitation/ProjectCitation.tsx b/client/modules/datafiles/src/projects/ProjectCitation/ProjectCitation.tsx
index df43e754d9..f4fd8dc9d4 100644
--- a/client/modules/datafiles/src/projects/ProjectCitation/ProjectCitation.tsx
+++ b/client/modules/datafiles/src/projects/ProjectCitation/ProjectCitation.tsx
@@ -43,9 +43,10 @@ export const PublishedCitation: React.FC<{
             ? `${author.lname}, ${author.fname[0]}.`
             : `${author.fname[0]}. ${author.lname}`
         )
-        .join(', ')}
-      . "{entityDetails.value.title}", in <i>{data.baseProject.title}</i>.
-      DesignSafe-CI. (DOI will appear after publication)
+        .join(', ')}{' '}
+      ({new Date(entityDetails.publicationDate).getFullYear()}). "
+      {entityDetails.value.title}", in <i>{data.baseProject.title}</i>.
+      DesignSafe-CI. ({entityDetails.value.dois && entityDetails.value.dois[0]})
     </div>
   );
 };
diff --git a/client/modules/datafiles/src/projects/ProjectListing.tsx b/client/modules/datafiles/src/projects/ProjectListing.tsx
index 4e009b4012..ab01a2a5f6 100644
--- a/client/modules/datafiles/src/projects/ProjectListing.tsx
+++ b/client/modules/datafiles/src/projects/ProjectListing.tsx
@@ -23,7 +23,10 @@ const columns: TableColumnsType<TBaseProject> = [
     },
     title: 'Principal Investigator',
   },
-  { render: (_, record) => record.lastUpdated, title: 'Last Modified' },
+  {
+    render: (_, record) => new Date(record.lastUpdated).toLocaleString(),
+    title: 'Last Modified',
+  },
 ];
 
 export const ProjectListing: React.FC = () => {
diff --git a/client/modules/datafiles/src/projects/ProjectPreview/ProjectPreview.tsx b/client/modules/datafiles/src/projects/ProjectPreview/ProjectPreview.tsx
index 09208952cd..947b98ed8a 100644
--- a/client/modules/datafiles/src/projects/ProjectPreview/ProjectPreview.tsx
+++ b/client/modules/datafiles/src/projects/ProjectPreview/ProjectPreview.tsx
@@ -18,6 +18,7 @@ import {
   TFileListingColumns,
 } from '../../FileListing/FileListingTable/FileListingTable';
 import { NavLink } from 'react-router-dom';
+import { PublishedEntityDetails } from '../PublishedEntityDetails';
 
 const columns: TFileListingColumns = [
   {
@@ -97,6 +98,7 @@ function RecursiveTree({
 export const PublishedEntityDisplay: React.FC<{
   projectId: string;
   preview?: boolean;
+  license?: string;
   treeData: TPreviewTreeData;
   defaultOpen?: boolean;
   defaultOpenChildren?: boolean;
@@ -104,6 +106,7 @@ export const PublishedEntityDisplay: React.FC<{
   projectId,
   preview,
   treeData,
+  license,
   defaultOpen = false,
   defaultOpenChildren = false,
 }) => {
@@ -159,13 +162,33 @@ export const PublishedEntityDisplay: React.FC<{
                 )}
               </div>
             ),
-            children: (sortedChildren ?? []).map((child) => (
-              <RecursiveTree
-                treeData={child}
-                key={child.id}
-                defaultOpen={defaultOpenChildren}
-              />
-            )),
+            children: (
+              <>
+                <PublishedEntityDetails
+                  entityValue={treeData.value}
+                  license={license}
+                  publicationDate={treeData.publicationDate}
+                />
+                {(treeData.value.fileObjs?.length ?? 0) > 0 && (
+                  <FileListingTable
+                    api="tapis"
+                    system="designsafe.storage.published"
+                    path={treeData.uuid}
+                    scheme="public"
+                    columns={columns}
+                    dataSource={treeData.value.fileObjs}
+                    disabled
+                  />
+                )}
+                {(sortedChildren ?? []).map((child) => (
+                  <RecursiveTree
+                    treeData={child}
+                    key={child.id}
+                    defaultOpen={defaultOpenChildren}
+                  />
+                ))}
+              </>
+            ),
           },
         ]}
       />
@@ -187,15 +210,17 @@ export const ProjectPreview: React.FC<{ projectId: string }> = ({
 
   return (
     <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}>
-      {sortedChildren.map((child, idx) => (
-        <PublishedEntityDisplay
-          preview
-          projectId={projectId}
-          treeData={child}
-          defaultOpen={idx === 0}
-          key={child.id}
-        />
-      ))}
+      {sortedChildren
+        .filter((child) => child.name !== 'designsafe.project')
+        .map((child, idx) => (
+          <PublishedEntityDisplay
+            preview
+            projectId={projectId}
+            treeData={child}
+            defaultOpen={idx === 0}
+            key={child.id}
+          />
+        ))}
     </div>
   );
 };
@@ -219,9 +244,13 @@ export const PublicationView: React.FC<{
   return (
     <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}>
       {sortedChildren
-        .filter((child) => child.version === version)
+        .filter(
+          (child) =>
+            child.version === version && child.name !== 'designsafe.project'
+        )
         .map((child, idx) => (
           <PublishedEntityDisplay
+            license={data.baseProject.license}
             projectId={projectId}
             treeData={child}
             defaultOpen={idx === 0}
diff --git a/client/modules/datafiles/src/projects/PublishedEntityDetails.tsx b/client/modules/datafiles/src/projects/PublishedEntityDetails.tsx
new file mode 100644
index 0000000000..f0e36add8b
--- /dev/null
+++ b/client/modules/datafiles/src/projects/PublishedEntityDetails.tsx
@@ -0,0 +1,208 @@
+import React from 'react';
+import { TEntityValue } from '@client/hooks';
+
+import styles from './BaseProjectDetails.module.css';
+import {
+  DescriptionExpander,
+  LicenseDisplay,
+  UsernamePopover,
+} from './BaseProjectDetails';
+
+export const PublishedEntityDetails: React.FC<{
+  entityValue: TEntityValue;
+  publicationDate?: string;
+  license?: string;
+}> = ({ entityValue, publicationDate, license }) => {
+  return (
+    <section style={{ marginBottom: '20px' }}>
+      <table
+        style={{ width: '100%', marginBottom: '20px', borderSpacing: '200px' }}
+      >
+        <colgroup>
+          <col style={{ width: '200px' }} />
+          <col />
+        </colgroup>
+        <tbody>
+          {entityValue.event && (
+            <tr className={styles['prj-row']}>
+              <td>Event</td>
+              <td style={{ fontWeight: 'bold' }}>{entityValue.event}</td>
+            </tr>
+          )}
+
+          {entityValue.dateStart && (
+            <tr className={styles['prj-row']}>
+              <td>Date(s)</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {new Date(entityValue.dateStart).toISOString().split('T')[0]}
+                {entityValue.dateEnd && (
+                  <span>
+                    {' ― '}
+                    {new Date(entityValue.dateEnd).toISOString().split('T')[0]}
+                  </span>
+                )}
+              </td>
+            </tr>
+          )}
+
+          {entityValue.simulationType && (
+            <tr className={styles['prj-row']}>
+              <td>Facility</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {entityValue.simulationType?.name}
+              </td>
+            </tr>
+          )}
+
+          {(entityValue.authors ?? []).length > 0 && (
+            <tr className={styles['prj-row']}>
+              <td>Authors</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {entityValue.authors
+                  ?.filter((a) => a.authorship !== false)
+                  .map((u, i) => (
+                    <>
+                      <UsernamePopover user={u} />
+                      {i !==
+                        (entityValue.authors?.filter(
+                          (a) => a.authorship !== false
+                        ).length ?? 0) -
+                          1 && '; '}
+                    </>
+                  ))}
+              </td>
+            </tr>
+          )}
+
+          {entityValue.facility && (
+            <tr className={styles['prj-row']}>
+              <td>Experiment Type</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {entityValue.facility?.name}
+              </td>
+            </tr>
+          )}
+
+          {entityValue.experimentType && (
+            <tr className={styles['prj-row']}>
+              <td>Facility</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {entityValue.experimentType?.name}
+              </td>
+            </tr>
+          )}
+
+          {entityValue.equipmentType && (
+            <tr className={styles['prj-row']}>
+              <td>Equipment Type</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {entityValue.equipmentType?.name}
+              </td>
+            </tr>
+          )}
+
+          {entityValue.procedureStart && (
+            <tr className={styles['prj-row']}>
+              <td>Date of Experiment</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {
+                  new Date(entityValue.procedureStart)
+                    .toISOString()
+                    .split('T')[0]
+                }
+                {entityValue.procedureEnd && (
+                  <span>
+                    {' ― '}
+                    {
+                      new Date(entityValue.procedureEnd)
+                        .toISOString()
+                        .split('T')[0]
+                    }
+                  </span>
+                )}
+              </td>
+            </tr>
+          )}
+          {entityValue.location && (
+            <tr className={styles['prj-row']}>
+              <td>Site Location</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {entityValue.location} |{' '}
+                <a
+                  href={`https://www.google.com/maps/place/${entityValue.latitude},${entityValue.longitude}`}
+                  rel="noopener noreferrer"
+                  target="_blank"
+                >
+                  Lat {entityValue.latitude} long {entityValue.longitude}
+                </a>
+              </td>
+            </tr>
+          )}
+
+          {(entityValue.relatedWork?.length ?? 0) > 0 && (
+            <tr className={styles['prj-row']}>
+              <td>Related Work</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {entityValue.relatedWork.map((assoc) => (
+                  <div key={JSON.stringify(assoc)}>
+                    <a
+                      href={assoc.href}
+                      rel="noopener noreferrer"
+                      target="_blank"
+                    >
+                      {assoc.title}
+                    </a>
+                  </div>
+                ))}
+              </td>
+            </tr>
+          )}
+          {(entityValue.referencedData?.length ?? 0) > 0 && (
+            <tr className={styles['prj-row']}>
+              <td>Related Work</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {entityValue.referencedData.map((ref) => (
+                  <div key={JSON.stringify(ref)}>
+                    {ref.hrefType && `${ref.hrefType} | `}
+                    <a href={ref.doi} rel="noopener noreferrer" target="_blank">
+                      {ref.title}
+                    </a>
+                  </div>
+                ))}
+              </td>
+            </tr>
+          )}
+
+          {publicationDate && (
+            <tr className={styles['prj-row']}>
+              <td>Date Published</td>
+              <td style={{ fontWeight: 'bold' }}>
+                {new Date(publicationDate).toISOString().split('T')[0]}
+              </td>
+            </tr>
+          )}
+
+          {entityValue.dois && entityValue.dois[0] && (
+            <tr className={styles['prj-row']}>
+              <td>DOI</td>
+              <td style={{ fontWeight: 'bold' }}>{entityValue.dois[0]}</td>
+            </tr>
+          )}
+
+          {license && (
+            <tr className={styles['prj-row']}>
+              <td>License</td>
+              <td style={{ fontWeight: 'bold' }}>
+                <LicenseDisplay licenseType={license} />
+              </td>
+            </tr>
+          )}
+        </tbody>
+      </table>
+      <DescriptionExpander>
+        <strong>Description: </strong>
+        {entityValue.description}
+      </DescriptionExpander>
+    </section>
+  );
+};
diff --git a/client/modules/datafiles/src/publications/PublicationSearchSidebar/PublicationSearchSidebar.module.css b/client/modules/datafiles/src/publications/PublicationSearchSidebar/PublicationSearchSidebar.module.css
new file mode 100644
index 0000000000..04ea748c60
--- /dev/null
+++ b/client/modules/datafiles/src/publications/PublicationSearchSidebar/PublicationSearchSidebar.module.css
@@ -0,0 +1,16 @@
+.projectTypeOptions {
+  border: 1px solid #dddddd;
+  padding: 15px 10px;
+}
+
+.sidebarLabel {
+  font-weight: normal;
+}
+
+.checkboxRow {
+  margin-bottom: 10px;
+}
+
+.sidebarSelect {
+  width: 100%;
+}
diff --git a/client/modules/datafiles/src/publications/PublicationSearchSidebar/PublicationSearchSidebar.tsx b/client/modules/datafiles/src/publications/PublicationSearchSidebar/PublicationSearchSidebar.tsx
new file mode 100644
index 0000000000..a307cdf699
--- /dev/null
+++ b/client/modules/datafiles/src/publications/PublicationSearchSidebar/PublicationSearchSidebar.tsx
@@ -0,0 +1,217 @@
+import { Checkbox, Select } from 'antd';
+import React from 'react';
+import * as dropdownOptions from '../../projects/forms/ProjectFormDropdowns';
+import styles from './PublicationSearchSidebar.module.css';
+import { useSearchParams } from 'react-router-dom';
+export const PublicationSearchSidebar: React.FC = () => {
+  const [searchParams, setSearchParams] = useSearchParams();
+
+  const toggleProjectTypeFilter = (projectType: string) => {
+    const selectedTypes = searchParams.getAll('project-type');
+    const newSearchParams = new URLSearchParams(searchParams);
+
+    if (selectedTypes.includes(projectType)) {
+      newSearchParams.delete('project-type', projectType);
+      setSearchParams(newSearchParams, { replace: true });
+    } else {
+      newSearchParams.append('project-type', projectType);
+      setSearchParams(newSearchParams, { replace: true });
+    }
+  };
+
+  const setSearchParam = (key: string, value?: string) => {
+    const newSearchParams = new URLSearchParams(searchParams);
+    if (value) {
+      newSearchParams.set(key, value);
+    } else {
+      newSearchParams.delete(key);
+    }
+    if (key === 'facility') {
+      newSearchParams.delete('experiment-type');
+    }
+    setSearchParams(newSearchParams);
+  };
+
+  const currentYear = new Date(Date.now()).getUTCFullYear();
+  //Show events going back to 2015
+  const datesInRange = [];
+  for (let i = currentYear; i >= 2015; i--) {
+    datesInRange.push(i);
+  }
+  const yearOptions = datesInRange.map((y) => ({ label: y, value: y }));
+
+  return (
+    <section style={{ backgroundColor: '#fafafa' }}>
+      <article className={styles.projectTypeOptions}>
+        <label htmlFor="facility-select">Facility</label>
+
+        <Select
+          id="facility-select"
+          allowClear
+          virtual={false}
+          value={searchParams.get('facility')}
+          onChange={(v) => {
+            setSearchParam('facility', v);
+          }}
+          options={dropdownOptions.facilityOptions}
+          popupMatchSelectWidth={false}
+          style={{ width: '100%' }}
+          placeholder="All Facilities"
+        />
+      </article>
+
+      <article className={styles.projectTypeOptions}>
+        <div className={styles.checkboxRow}>
+          <Checkbox
+            checked={searchParams
+              .getAll('project-type')
+              .includes('experimental')}
+            onChange={() => toggleProjectTypeFilter('experimental')}
+          />
+          &nbsp;
+          <strong>Experimental</strong>
+        </div>
+        <div>
+          <label
+            className={styles.sidebarLabel}
+            htmlFor="experiment-type-select"
+          >
+            Experiment Type
+          </label>
+          <Select
+            id="experiment-type-select"
+            virtual={false}
+            allowClear
+            disabled={
+              !Object.keys(dropdownOptions.experimentTypeOptions).includes(
+                searchParams.get('facility') ?? ''
+              )
+            }
+            value={searchParams.get('experiment-type')}
+            onChange={(v) => setSearchParam('experiment-type', v)}
+            options={
+              searchParams.get('facility')
+                ? dropdownOptions.experimentTypeOptions[
+                    searchParams.get('facility') ?? ''
+                  ]
+                : []
+            }
+            style={{ width: '100%' }}
+            placeholder="All Types"
+          />
+        </div>
+      </article>
+      <article className={styles.projectTypeOptions}>
+        <div className={styles.checkboxRow}>
+          <Checkbox
+            checked={searchParams.getAll('project-type').includes('simulation')}
+            onChange={() => toggleProjectTypeFilter('simulation')}
+          />
+          &nbsp;
+          <strong>Simulation</strong>
+        </div>
+        <label className={styles.sidebarLabel} htmlFor="simulation-type-select">
+          Simulation Type
+        </label>
+
+        <Select
+          id="simulation-type-select"
+          options={dropdownOptions.simulationTypeOptions}
+          value={searchParams.get('sim-type')}
+          onChange={(v) => setSearchParam('sim-type', v)}
+          allowClear
+          style={{ width: '100%' }}
+          placeholder="All Types"
+        />
+      </article>
+      <article className={styles.projectTypeOptions}>
+        <div className={styles.checkboxRow}>
+          <Checkbox
+            checked={searchParams
+              .getAll('project-type')
+              .includes('field-research')}
+            onChange={() => toggleProjectTypeFilter('field-research')}
+          />
+          &nbsp;
+          <strong>Field Research</strong>
+        </div>
+        <div>
+          <label className={styles.sidebarLabel} htmlFor="fr-type-select">
+            Field Research Type
+          </label>
+          <Select
+            id="fr-type-select"
+            allowClear
+            options={dropdownOptions.frTypeOptions}
+            value={searchParams.get('fr-type')}
+            onChange={(v) => setSearchParam('fr-type', v)}
+            style={{ width: '100%', marginBottom: '5px' }}
+            placeholder="All Types"
+          />
+        </div>
+        <div>
+          <label className={styles.sidebarLabel} htmlFor="nh-year-select">
+            Natural Hazard Year
+          </label>
+          <Select
+            id="nh-year-select"
+            options={yearOptions}
+            value={searchParams.get('nh-year')}
+            onChange={(v) => setSearchParam('nh-year', v)}
+            allowClear
+            style={{ width: '100%' }}
+            placeholder="All Years"
+          />
+        </div>
+      </article>
+      <article className={styles.projectTypeOptions}>
+        <div className={styles.checkboxRow}>
+          <Checkbox
+            checked={searchParams.getAll('project-type').includes('hybrid-sim')}
+            onChange={() => toggleProjectTypeFilter('hybrid-sim')}
+          />
+          &nbsp;
+          <strong>Hybrid Simulation</strong>
+        </div>
+        <div>
+          <label className={styles.sidebarLabel} htmlFor="hybsim-type-select">
+            Hybrid Simulation Type
+          </label>
+          <Select
+            id="hybsim-type-select"
+            options={dropdownOptions.HybridSimTypeOptions}
+            value={searchParams.get('hyb-sim-type')}
+            onChange={(v) => setSearchParam('hyb-sim-type', v)}
+            allowClear
+            style={{ width: '100%' }}
+            placeholder="All Types"
+          />
+        </div>
+      </article>
+      <article className={styles.projectTypeOptions}>
+        {' '}
+        <div className={styles.checkboxRow}>
+          <Checkbox
+            checked={searchParams.getAll('project-type').includes('other')}
+            onChange={() => toggleProjectTypeFilter('other')}
+          />
+          &nbsp;
+          <strong>Other</strong>
+        </div>
+        <div>
+          <label className={styles.sidebarLabel} htmlFor="data-type-select">
+            Data Type
+          </label>
+          <Select
+            options={dropdownOptions.dataTypeOptions}
+            value={searchParams.get('data-type')}
+            onChange={(v) => setSearchParam('data-type', v)}
+            allowClear
+            style={{ width: '100%' }}
+            placeholder="All Types"
+          />
+        </div>
+      </article>
+    </section>
+  );
+};
diff --git a/client/modules/datafiles/src/publications/PublicationSearchToolbar/PublicationSearchToolbar.tsx b/client/modules/datafiles/src/publications/PublicationSearchToolbar/PublicationSearchToolbar.tsx
new file mode 100644
index 0000000000..50e7ccb189
--- /dev/null
+++ b/client/modules/datafiles/src/publications/PublicationSearchToolbar/PublicationSearchToolbar.tsx
@@ -0,0 +1,94 @@
+import { Button, Form, Input, Select } from 'antd';
+import React from 'react';
+import { useSearchParams } from 'react-router-dom';
+import * as dropdownOptions from '../../projects/forms/ProjectFormDropdowns';
+export const PublicationSearchToolbar: React.FC = () => {
+  const [searchParams, setSearchParams] = useSearchParams();
+  const setSearchParam = (key: string, value?: string) => {
+    const newSearchParams = new URLSearchParams(searchParams);
+    if (value) {
+      newSearchParams.set(key, value);
+    } else {
+      newSearchParams.delete(key);
+    }
+    if (key === 'facility') {
+      newSearchParams.delete('experiment-type');
+    }
+    setSearchParams(newSearchParams);
+  };
+
+  const currentYear = new Date(Date.now()).getUTCFullYear();
+  //Show events going back to 2015
+  const datesInRange = [];
+  for (let i = currentYear; i >= 2015; i--) {
+    datesInRange.push(i);
+  }
+  const yearOptions = [...datesInRange.map((y) => ({ label: y, value: y }))];
+
+  return (
+    <div
+      style={{
+        display: 'flex',
+        alignItems: 'center',
+        gap: '10px',
+        justifyContent: 'space-between',
+        flexWrap: 'wrap',
+      }}
+    >
+      <Form
+        onFinish={(data) => setSearchParam('q', data.query)}
+        style={{ display: 'inline-flex', flex: 1, minWidth: '250px' }}
+      >
+        <Button htmlType="submit" type="primary" className="success-button">
+          <i className="fa fa-search" />
+          &nbsp;Search
+        </Button>
+        <Form.Item name="query" style={{ marginBottom: 0, flex: 1 }}>
+          <Input
+            placeholder="Author, Title, Keyword, Description, Natural Hazard Event, or Project ID"
+            style={{ flex: 1 }}
+          />
+        </Form.Item>
+      </Form>
+      <div>
+        <label htmlFor="nh-type-select" style={{ margin: 0 }}>
+          Natural Hazard Type
+        </label>
+        &nbsp;
+        <Select
+          style={{ width: '150px' }}
+          virtual={false}
+          allowClear
+          id="nh-type-select"
+          placeholder="All Types"
+          options={dropdownOptions.nhTypeOptions}
+          popupMatchSelectWidth={false}
+          value={searchParams.get('nh-type')}
+          onChange={(v) => setSearchParam('nh-type', v)}
+        />
+      </div>
+
+      <div>
+        <label htmlFor="publication-year-select" style={{ margin: 0 }}>
+          Year Published
+        </label>
+        &nbsp;
+        <Select
+          style={{ width: '150px' }}
+          id="publication-year-select"
+          options={yearOptions}
+          allowClear
+          placeholder="All Years"
+          popupMatchSelectWidth={false}
+          virtual={false}
+          value={searchParams.get('pub-year')}
+          onChange={(v) => setSearchParam('pub-year', v)}
+        />
+      </div>
+
+      <Button type="link" onClick={() => setSearchParams(undefined)}>
+        Clear Filters
+      </Button>
+    </div>
+  );
+};
diff --git a/client/modules/datafiles/src/publications/PublishedListing/PublishedListing.tsx b/client/modules/datafiles/src/publications/PublishedListing/PublishedListing.tsx
index 011da2940d..7afed2d55d 100644
--- a/client/modules/datafiles/src/publications/PublishedListing/PublishedListing.tsx
+++ b/client/modules/datafiles/src/publications/PublishedListing/PublishedListing.tsx
@@ -7,7 +7,7 @@ const columns: TableColumnsType<TPublicationListingItem> = [
   {
     render: (_, record) => record.projectId,
     title: 'Project ID',
-    width: '10%',
+    width: '100px',
   },
   {
     render: (_, record) => <Link to={record.projectId}>{record.title}</Link>,
@@ -19,8 +19,13 @@ const columns: TableColumnsType<TPublicationListingItem> = [
       return `${record.pi?.fname} ${record.pi?.lname}`;
     },
     title: 'Principal Investigator',
+    ellipsis: true,
+  },
+  {
+    title: 'Publication Date',
+    ellipsis: true,
+    render: (_, record) => new Date(record.created).toLocaleDateString(),
   },
-  { render: (_, record) => record.created, title: 'Publication Date' },
 ];
 
 export const PublishedListing: React.FC = () => {
@@ -34,7 +39,7 @@ export const PublishedListing: React.FC = () => {
       loading={isLoading}
       columns={columns}
       style={{ height: '100%' }}
-      scroll={{ y: '100%' }}
+      scroll={{ y: '100%', x: 500 }}
       rowKey={(row) => row.projectId}
       pagination={{
         total: data?.total,
diff --git a/client/modules/datafiles/src/publications/index.ts b/client/modules/datafiles/src/publications/index.ts
index d4808b5e8c..796ceebc9f 100644
--- a/client/modules/datafiles/src/publications/index.ts
+++ b/client/modules/datafiles/src/publications/index.ts
@@ -1 +1,3 @@
 export { PublishedListing } from './PublishedListing/PublishedListing';
+export { PublicationSearchSidebar } from './PublicationSearchSidebar/PublicationSearchSidebar';
+export { PublicationSearchToolbar } from './PublicationSearchToolbar/PublicationSearchToolbar';
diff --git a/client/src/datafiles/layouts/FileListingLayout.tsx b/client/src/datafiles/layouts/FileListingLayout.tsx
index 4dbcc432d5..ec873cce61 100644
--- a/client/src/datafiles/layouts/FileListingLayout.tsx
+++ b/client/src/datafiles/layouts/FileListingLayout.tsx
@@ -4,11 +4,38 @@ import {
   FileListing,
 } from '@client/datafiles';
 import { useAuthenticatedUser, useFileListingRouteParams } from '@client/hooks';
-import { Layout } from 'antd';
+import { Button, Form, Input, Layout } from 'antd';
 import React from 'react';
-import { Link, Navigate } from 'react-router-dom';
+import { Link, Navigate, useSearchParams } from 'react-router-dom';
 import styles from './layout.module.css';
 
+const FileListingSearchBar = () => {
+  const [searchParams, setSearchParams] = useSearchParams();
+  const onSubmit = (queryString: string) => {
+    const newSearchParams = searchParams;
+    if (queryString) {
+      newSearchParams.set('q', queryString);
+    } else {
+      newSearchParams.delete('q');
+    }
+
+    setSearchParams(newSearchParams);
+  };
+  return (
+    <Form
+      onFinish={(data) => onSubmit(data.query)}
+      style={{ display: 'inline-flex' }}
+    >
+      <Form.Item name="query" style={{ marginBottom: 0 }}>
+        <Input placeholder="Search Data Files" style={{ width: '250px' }} />
+      </Form.Item>
+      <Button htmlType="submit">
+        <i className="fa fa-search"></i>
+      </Button>
+    </Form>
+  );
+};
+
 export const FileListingLayout: React.FC = () => {
   const { api, path, scheme, system } = useFileListingRouteParams();
   const { user } = useAuthenticatedUser();
@@ -22,7 +49,7 @@ export const FileListingLayout: React.FC = () => {
     user?.username && !path && api === 'tapis' && isUserHomeSystem;
   return (
     <Layout style={{ gap: '5px', minWidth: '500px' }}>
-      <DatafilesToolbar />
+      <DatafilesToolbar searchInput={<FileListingSearchBar />} />
       {true && (
         <BaseFileListingBreadcrumb
           api={api}
diff --git a/client/src/datafiles/layouts/projects/ProjectCurationLayout.tsx b/client/src/datafiles/layouts/projects/ProjectCurationLayout.tsx
index 534c016d6f..8b0b06f4a8 100644
--- a/client/src/datafiles/layouts/projects/ProjectCurationLayout.tsx
+++ b/client/src/datafiles/layouts/projects/ProjectCurationLayout.tsx
@@ -1,4 +1,5 @@
 import {
+  DatafilesBreadcrumb,
   ManageCategoryModal,
   ManagePublishableEntityModal,
   ProjectCurationFileListing,
@@ -9,7 +10,7 @@ import { useProjectDetail } from '@client/hooks';
 import { Button } from 'antd';
 
 import React from 'react';
-import { useParams } from 'react-router-dom';
+import { Link, useParams } from 'react-router-dom';
 
 const PublishableEntityButton: React.FC<{ projectId: string }> = ({
   projectId,
@@ -124,7 +125,9 @@ const PublishableEntityButton: React.FC<{ projectId: string }> = ({
 
 export const ProjectCurationLayout: React.FC = () => {
   const { projectId, path } = useParams();
+  const { data } = useProjectDetail(projectId ?? '');
   if (!projectId) return null;
+  if (!data) return <div>loading...</div>;
   return (
     <div style={{ paddingBottom: '50px' }}>
       <div style={{ display: 'flex', alignItems: 'center', gap: '3rem' }}>
@@ -163,6 +166,20 @@ export const ProjectCurationLayout: React.FC = () => {
           </RelateDataModal>
         </span>
       </div>
+      <DatafilesBreadcrumb
+        initialBreadcrumbs={[]}
+        path={path ?? ''}
+        baseRoute={`/projects/${projectId}/curation`}
+        systemRootAlias={data.baseProject.value.projectId}
+        systemRoot=""
+        itemRender={(obj) => {
+          return (
+            <Link className="breadcrumb-link" to={obj.path ?? '/'}>
+              {obj.title}
+            </Link>
+          );
+        }}
+      />
       <ProjectCurationFileListing projectId={projectId} path={path ?? ''} />
     </div>
   );
diff --git a/client/src/datafiles/layouts/projects/ProjectDetailLayout.tsx b/client/src/datafiles/layouts/projects/ProjectDetailLayout.tsx
index 627fe0a488..95ac9ddbfb 100644
--- a/client/src/datafiles/layouts/projects/ProjectDetailLayout.tsx
+++ b/client/src/datafiles/layouts/projects/ProjectDetailLayout.tsx
@@ -1,8 +1,40 @@
 import React from 'react';
-import { Outlet, useParams } from 'react-router-dom';
-import { BaseProjectDetails, ProjectTitleHeader } from '@client/datafiles';
+import { Outlet, useParams, useSearchParams } from 'react-router-dom';
+import {
+  BaseProjectDetails,
+  DatafilesToolbar,
+  ProjectTitleHeader,
+} from '@client/datafiles';
+import { Button, Form, Input } from 'antd';
 import { useProjectDetail } from '@client/hooks';
 
+const FileListingSearchBar = () => {
+  const [searchParams, setSearchParams] = useSearchParams();
+  const onSubmit = (queryString: string) => {
+    const newSearchParams = searchParams;
+    if (queryString) {
+      newSearchParams.set('q', queryString);
+    } else {
+      newSearchParams.delete('q');
+    }
+
+    setSearchParams(newSearchParams);
+  };
+  return (
+    <Form
+      onFinish={(data) => onSubmit(data.query)}
+      style={{ display: 'inline-flex' }}
+    >
+      <Form.Item name="query" style={{ marginBottom: 0 }}>
+        <Input placeholder="Search Data Files" style={{ width: '250px' }} />
+      </Form.Item>
+      <Button htmlType="submit">
+        <i className="fa fa-search"></i>
+      </Button>
+    </Form>
+  );
+};
+
 export const ProjectDetailLayout: React.FC = () => {
   const { projectId } = useParams();
   const { data } = useProjectDetail(projectId ?? '');
@@ -10,6 +42,7 @@ export const ProjectDetailLayout: React.FC = () => {
 
   return (
     <section>
+      <DatafilesToolbar searchInput={<FileListingSearchBar />} />
       <ProjectTitleHeader projectId={projectId} />
       <BaseProjectDetails projectValue={data.baseProject.value} />
       <Outlet />
diff --git a/client/src/datafiles/layouts/projects/ProjectListingLayout.tsx b/client/src/datafiles/layouts/projects/ProjectListingLayout.tsx
index 5cf9ab8304..807ec42ffe 100644
--- a/client/src/datafiles/layouts/projects/ProjectListingLayout.tsx
+++ b/client/src/datafiles/layouts/projects/ProjectListingLayout.tsx
@@ -1,11 +1,40 @@
-import { ProjectListing } from '@client/datafiles';
-import { Layout } from 'antd';
+import { DatafilesToolbar, ProjectListing } from '@client/datafiles';
+import { Button, Form, Input, Layout } from 'antd';
 import React from 'react';
 
+import { useSearchParams } from 'react-router-dom';
+
+const ProjectListingSearchBar = () => {
+  const [searchParams, setSearchParams] = useSearchParams();
+  const onSubmit = (queryString: string) => {
+    const newSearchParams = searchParams;
+    if (queryString) {
+      newSearchParams.set('q', queryString);
+    } else {
+      newSearchParams.delete('q');
+    }
+
+    setSearchParams(newSearchParams);
+  };
+  return (
+    <Form
+      onFinish={(data) => onSubmit(data.query)}
+      style={{ display: 'inline-flex' }}
+    >
+      <Form.Item name="query" style={{ marginBottom: 0 }}>
+        <Input placeholder="Find in My Projects" style={{ width: '300px' }} />
+      </Form.Item>
+      <Button htmlType="submit">
+        <i className="fa fa-search"></i>
+      </Button>
+    </Form>
+  );
+};
+
 export const ProjectListingLayout: React.FC = () => {
   return (
     <Layout>
-      <div>Placeholder for the project listing searchbar</div>
+      <DatafilesToolbar searchInput={<ProjectListingSearchBar />} />
       <div style={{ flex: '1 0 0 ', height: '100%', overflow: 'auto' }}>
         <ProjectListing />
       </div>
diff --git a/client/src/datafiles/layouts/projects/ProjectWorkdirLayout.tsx b/client/src/datafiles/layouts/projects/ProjectWorkdirLayout.tsx
index 4f64796dca..0fd579cca7 100644
--- a/client/src/datafiles/layouts/projects/ProjectWorkdirLayout.tsx
+++ b/client/src/datafiles/layouts/projects/ProjectWorkdirLayout.tsx
@@ -19,7 +19,7 @@ export const ProjectWorkdirLayout: React.FC = () => {
         initialBreadcrumbs={[]}
         path={path ?? ''}
         baseRoute={`/projects/${projectId}/workdir`}
-        systemRootAlias={projectId}
+        systemRootAlias={data.baseProject.value.projectId}
         systemRoot=""
         itemRender={(obj) => {
           return (
diff --git a/client/src/datafiles/layouts/published/PublishedDetailLayout.tsx b/client/src/datafiles/layouts/published/PublishedDetailLayout.tsx
index 26c1b9ec5a..dbbf61ad24 100644
--- a/client/src/datafiles/layouts/published/PublishedDetailLayout.tsx
+++ b/client/src/datafiles/layouts/published/PublishedDetailLayout.tsx
@@ -1,10 +1,38 @@
-import { BaseProjectDetails } from '@client/datafiles';
+import { BaseProjectDetails, DatafilesToolbar } from '@client/datafiles';
 import { usePublicationDetail } from '@client/hooks';
 import React, { useEffect } from 'react';
-import { Outlet, useParams, useSearchParams } from 'react-router-dom';
+import { Button, Form, Input } from 'antd';
+import { Navigate, Outlet, useParams, useSearchParams } from 'react-router-dom';
+
+const FileListingSearchBar = () => {
+  const [searchParams, setSearchParams] = useSearchParams();
+  const onSubmit = (queryString: string) => {
+    const newSearchParams = searchParams;
+    if (queryString) {
+      newSearchParams.set('q', queryString);
+    } else {
+      newSearchParams.delete('q');
+    }
+
+    setSearchParams(newSearchParams);
+  };
+  return (
+    <Form
+      onFinish={(data) => onSubmit(data.query)}
+      style={{ display: 'inline-flex' }}
+    >
+      <Form.Item name="query" style={{ marginBottom: 0 }}>
+        <Input placeholder="Search Data Files" style={{ width: '250px' }} />
+      </Form.Item>
+      <Button htmlType="submit">
+        <i className="fa fa-search"></i>
+      </Button>
+    </Form>
+  );
+};
 
 export const PublishedDetailLayout: React.FC = () => {
-  const { projectId } = useParams();
+  const { projectId, path } = useParams();
   const [searchParams, setSearchParams] = useSearchParams();
   const { data } = usePublicationDetail(projectId ?? '');
 
@@ -19,13 +47,34 @@ export const PublishedDetailLayout: React.FC = () => {
 
   if (!projectId || !data) return null;
 
+  if (searchParams.get('q') && !path) {
+    return (
+      <Navigate
+        to={`/public/designsafe.storage.published/${projectId}/${projectId}?q=${searchParams.get(
+          'q'
+        )}`}
+      />
+    );
+  }
+
+  const publicationDate = data.tree.children.find(
+    (c) => c.value.projectId === projectId
+  )?.publicationDate;
+
   return (
     <div style={{ width: '100%', paddingBottom: '100px' }}>
-      <div className="prj-head-title" style={{ marginBottom: '20px' }}>
+      <DatafilesToolbar searchInput={<FileListingSearchBar />} />
+      <div
+        className="prj-head-title"
+        style={{ marginTop: '20px', marginBottom: '20px' }}
+      >
         <strong>{data.baseProject.projectId}</strong>&nbsp;|&nbsp;
         {data.baseProject.title}
       </div>
-      <BaseProjectDetails projectValue={data?.baseProject} />
+      <BaseProjectDetails
+        projectValue={data?.baseProject}
+        publicationDate={publicationDate}
+      />
       <Outlet />
     </div>
   );
diff --git a/client/src/datafiles/layouts/published/PublishedEntityListingLayout.tsx b/client/src/datafiles/layouts/published/PublishedEntityListingLayout.tsx
index 527707554e..46298a5fa5 100644
--- a/client/src/datafiles/layouts/published/PublishedEntityListingLayout.tsx
+++ b/client/src/datafiles/layouts/published/PublishedEntityListingLayout.tsx
@@ -1,4 +1,4 @@
-import { PublicationView } from '@client/datafiles';
+import { FileListing, PublicationView } from '@client/datafiles';
 import { usePublicationDetail } from '@client/hooks';
 import React from 'react';
 import { useParams } from 'react-router-dom';
@@ -12,6 +12,17 @@ export const PublishedEntityListingLayout: React.FC = () => {
   return (
     <div style={{ width: '100%' }}>
       <PublicationView projectId={projectId} />
+      {['other', 'field_reconnaissance'].includes(
+        data.baseProject.projectType
+      ) && (
+        <FileListing
+          scroll={{ y: 500 }}
+          api="tapis"
+          system="designsafe.storage.published"
+          path={data.baseProject.projectId}
+          baseRoute="."
+        />
+      )}
     </div>
   );
 };
diff --git a/client/src/datafiles/layouts/published/PublishedListingLayout.tsx b/client/src/datafiles/layouts/published/PublishedListingLayout.tsx
index d334db3e2a..c53a02719c 100644
--- a/client/src/datafiles/layouts/published/PublishedListingLayout.tsx
+++ b/client/src/datafiles/layouts/published/PublishedListingLayout.tsx
@@ -1,14 +1,40 @@
-import { PublishedListing } from '@client/datafiles';
+import {
+  PublicationSearchSidebar,
+  PublicationSearchToolbar,
+  PublishedListing,
+} from '@client/datafiles';
 import { Layout } from 'antd';
 import React from 'react';
 
 export const PublishedListingLayout: React.FC = () => {
   return (
-    <Layout>
-      <div>Placeholder for the publication listing searchbar</div>
-      <div style={{ flex: '1 0 0 ', height: '100%', overflow: 'auto' }}>
-        <PublishedListing />
+    <Layout style={{ paddingBottom: '20px' }}>
+      <div
+        style={{
+          backgroundColor: 'transparent',
+          padding: 0,
+          marginBottom: '20px',
+        }}
+      >
+        <PublicationSearchToolbar />
       </div>
+      <Layout style={{ gap: '10px' }}>
+        <Layout.Content
+          style={{
+            display: 'flex',
+            flexDirection: 'column',
+            flex: '1 0 0',
+            overflow: 'auto',
+          }}
+        >
+          <div style={{ flex: '1 0 0', height: '100%', overflow: 'auto' }}>
+            <PublishedListing />
+          </div>
+        </Layout.Content>
+        <Layout.Sider width={200} style={{ backgroundColor: 'transparent' }}>
+          <PublicationSearchSidebar />
+        </Layout.Sider>
+      </Layout>
     </Layout>
   );
 };
diff --git a/designsafe/apps/api/projects_v2/migration_utils/project_db_ingest.py b/designsafe/apps/api/projects_v2/migration_utils/project_db_ingest.py
index 90ead81c4d..6d968fed4e 100644
--- a/designsafe/apps/api/projects_v2/migration_utils/project_db_ingest.py
+++ b/designsafe/apps/api/projects_v2/migration_utils/project_db_ingest.py
@@ -2,6 +2,7 @@
 
 from datetime import datetime, timezone
 from pydantic import ValidationError
+from elasticsearch_dsl import Q
 import networkx as nx
 from designsafe.apps.api.projects_v2.models.project_metadata import ProjectMetadata
 from designsafe.apps.api.projects_v2.migration_utils.graph_constructor import (
@@ -172,7 +173,6 @@ def ingest_publications():
     """Ingest Elasticsearch-based publications into the db"""
     all_pubs = iterate_pubs()
     for pub in all_pubs:
-        print(pub["projectId"])
         try:
             pub_graph = combine_pub_versions(pub["projectId"])
             latest_version: int = IndexedPublication.max_revision(pub["projectId"]) or 1
@@ -204,3 +204,45 @@ def ingest_publications():
         except ValidationError as exc:
             print(pub["projectId"])
             print(exc)
+
+
+def ingest_tombstones():
+    """Ingest Elasticsearch tombstones into the db"""
+
+    all_pubs = (
+        IndexedPublication.search().filter(Q("term", status="tombstone")).execute().hits
+    )
+    print(all_pubs)
+    for pub in all_pubs:
+        try:
+            pub_graph = combine_pub_versions(pub["projectId"])
+            latest_version: int = IndexedPublication.max_revision(pub["projectId"]) or 1
+            pub_base = next(
+                (
+                    pub_graph.nodes[node_id]["value"]
+                    for node_id in pub_graph
+                    if (
+                        pub_graph.nodes[node_id]["uuid"] == pub["project"]["uuid"]
+                        and pub_graph.nodes[node_id].get("version", latest_version)
+                        == latest_version
+                    )
+                ),
+                None,
+            )
+            if not pub_base:
+                raise ValueError("No pub base")
+            pub_graph_json = nx.node_link_data(pub_graph)
+            Publication.objects.update_or_create(
+                project_id=pub["projectId"],
+                defaults={
+                    "is_published": False,
+                    "created": datetime.fromisoformat(pub["created"]).replace(
+                        tzinfo=timezone.utc
+                    ),
+                    "tree": pub_graph_json,
+                    "value": pub_base,
+                },
+            )
+        except ValidationError as exc:
+            print(pub["projectId"])
+            print(exc)
diff --git a/designsafe/apps/api/projects_v2/migration_utils/publication_transforms.py b/designsafe/apps/api/projects_v2/migration_utils/publication_transforms.py
index ce57fc86f0..0f794dfa12 100644
--- a/designsafe/apps/api/projects_v2/migration_utils/publication_transforms.py
+++ b/designsafe/apps/api/projects_v2/migration_utils/publication_transforms.py
@@ -287,6 +287,13 @@ def transform_entity(entity: dict, base_pub_meta: dict, base_path: str):
         fixed_authors = list(map(convert_v2_user, entity["authors"]))
         entity["value"]["authors"] = sorted(fixed_authors, key=lambda a: a["order"])
 
+    tombstone_uuids = base_pub_meta.get("tombstone", [])
+    if entity["uuid"] in tombstone_uuids:
+        entity["value"]["tombstone"] = True
+    tombstone_message = base_pub_meta.get("tombstoneMessage", None)
+    if tombstone_message:
+        entity["value"]["tombstoneMessage"] = tombstone_message
+
     old_tags = entity["value"].get("tags", None)
     if old_tags:
         new_style_tags = convert_legacy_tags(entity)
@@ -316,6 +323,20 @@ def transform_entity(entity: dict, base_pub_meta: dict, base_path: str):
         entity["value"]["fileObjs"] = new_file_objs
     else:
         path_mapping = {}
-
     validated_model = model.model_validate(entity["value"])
+
+    if getattr(validated_model, "project_type", None) == "other":
+        # Type Other doesn't include emails/institutions in team order
+        for author in validated_model.authors:
+            user = next(
+                (u for u in validated_model.users if u.username == author.name), None
+            )
+            if user:
+                author.email = user.email
+                author.inst = user.inst
+        if schema_version == 1:
+            validated_model.authors = [
+                u for u in validated_model.users if u.fname != "N/A"
+            ]
+
     return validated_model.model_dump(), path_mapping
diff --git a/designsafe/apps/api/projects_v2/schema_models/base.py b/designsafe/apps/api/projects_v2/schema_models/base.py
index c6a96cd43a..ad39660b79 100644
--- a/designsafe/apps/api/projects_v2/schema_models/base.py
+++ b/designsafe/apps/api/projects_v2/schema_models/base.py
@@ -131,6 +131,9 @@ class BaseProject(MetadataModel):
     coverage_temporal: Optional[str] = None
     lat_long_name: Optional[str] = None
 
+    tombstone: bool = False
+    tombstone_message: Optional[str] = None
+
     def construct_users(self) -> list[ProjectUser]:
         """Fill in missing user information from the database."""
         users = []
diff --git a/designsafe/apps/api/projects_v2/schema_models/experimental.py b/designsafe/apps/api/projects_v2/schema_models/experimental.py
index 9b457ae70d..491ef6ce48 100644
--- a/designsafe/apps/api/projects_v2/schema_models/experimental.py
+++ b/designsafe/apps/api/projects_v2/schema_models/experimental.py
@@ -64,6 +64,8 @@ class Experiment(MetadataModel):
     project: list[str] = []
     dois: list[str] = []
 
+    tombstone: bool = False
+
     @model_validator(mode="after")
     def handle_other(self):
         """Use values of XXX_other fields to fill in dropdown values."""
diff --git a/designsafe/apps/api/projects_v2/schema_models/field_recon.py b/designsafe/apps/api/projects_v2/schema_models/field_recon.py
index b8b62b6af3..f4e48fa646 100644
--- a/designsafe/apps/api/projects_v2/schema_models/field_recon.py
+++ b/designsafe/apps/api/projects_v2/schema_models/field_recon.py
@@ -44,6 +44,7 @@ class Mission(MetadataModel):
     authors: Annotated[list[ProjectUser], BeforeValidator(handle_legacy_authors)] = []
     project: list[str] = []
     dois: list[str] = []
+    tombstone: bool = False
 
     # Deprecate these later
     facility: Optional[DropdownValue] = None
@@ -76,6 +77,8 @@ class FieldReconReport(MetadataModel):
     missions: list[str] = Field(default=[], exclude=True)
     referenced_datas: list[ReferencedWork] = Field(default=[], exclude=True)
 
+    tombstone: bool = False
+
 
 class Instrument(MetadataModel):
     """model for instruments used in field recon projects."""
diff --git a/designsafe/apps/api/projects_v2/schema_models/hybrid_sim.py b/designsafe/apps/api/projects_v2/schema_models/hybrid_sim.py
index 6affbb6757..99f1f024ed 100644
--- a/designsafe/apps/api/projects_v2/schema_models/hybrid_sim.py
+++ b/designsafe/apps/api/projects_v2/schema_models/hybrid_sim.py
@@ -39,6 +39,8 @@ class HybridSimulation(MetadataModel):
 
     facility: Optional[DropdownValue] = None
 
+    tombstone: bool = False
+
     @model_validator(mode="after")
     def handle_other(self):
         """Use values of XXX_other fields to fill in dropdown values."""
diff --git a/designsafe/apps/api/projects_v2/schema_models/simulation.py b/designsafe/apps/api/projects_v2/schema_models/simulation.py
index 3d2a3b6bb7..a937afb3f0 100644
--- a/designsafe/apps/api/projects_v2/schema_models/simulation.py
+++ b/designsafe/apps/api/projects_v2/schema_models/simulation.py
@@ -37,6 +37,7 @@ class Simulation(MetadataModel):
     dois: list[str] = []
 
     facility: Optional[DropdownValue] = None
+    tombstone: bool = False
 
     @model_validator(mode="after")
     def handle_other(self):
diff --git a/designsafe/apps/api/projects_v2/views.py b/designsafe/apps/api/projects_v2/views.py
index ca6f2422bd..0008aadb8a 100644
--- a/designsafe/apps/api/projects_v2/views.py
+++ b/designsafe/apps/api/projects_v2/views.py
@@ -29,6 +29,14 @@
 logger = logging.getLogger(__name__)
 
 
+def get_search_filter(query_string):
+    id_filter = models.Q(value__projectId__icontains=query_string)
+    title_filter = models.Q(value__title__icontains=query_string)
+    desc_filter = models.Q(value__description__icontains=query_string)
+    user_filter = models.Q(value__users__icontains=query_string)
+    return id_filter | title_filter | desc_filter | user_filter
+
+
 class ProjectsView(BaseApiView):
     """View for listing and creating projects"""
 
@@ -36,17 +44,22 @@ def get(self, request: HttpRequest):
         """Return the list of projects for a given user."""
         offset = int(request.GET.get("offset", 0))
         limit = int(request.GET.get("limit", 100))
+        query_string = request.GET.get("q", None)
         # user = get_user_model().objects.get(username="ds_admin")
         user = request.user
 
         if not request.user.is_authenticated:
             raise ApiException("Unauthenticated user", status=401)
 
-        projects = user.projects.order_by("last_updated")[offset : offset + limit]
+        projects = user.projects.order_by("last_updated")
+        if query_string:
+            projects = projects.filter(get_search_filter(query_string))
         total = user.projects.count()
 
         project_json = {
-            "result": [project.to_dict() for project in projects],
+            "result": [
+                project.to_dict() for project in projects[offset : offset + limit]
+            ],
             "total": total,
         }
 
@@ -101,7 +114,7 @@ def put(self, request: HttpRequest, project_id: str):
             ) from exc
 
         # Get the new value from the request data
-        new_value = request.data.get('new_value')
+        new_value = request.data.get("new_value")
 
         # Call the change_project_type function to update the project type
         updated_project = change_project_type(project_id, new_value)
@@ -116,7 +129,7 @@ def put(self, request: HttpRequest, project_id: str):
                 ),
             }
         )
-    
+
     def patch(self, request: HttpRequest, project_id: str):
         """Update a project's root metadata"""
         user = request.user
diff --git a/designsafe/apps/api/publications_v2/migrations/0002_publication_is_published.py b/designsafe/apps/api/publications_v2/migrations/0002_publication_is_published.py
new file mode 100644
index 0000000000..e22cd8c3fa
--- /dev/null
+++ b/designsafe/apps/api/publications_v2/migrations/0002_publication_is_published.py
@@ -0,0 +1,17 @@
+# Generated by Django 4.2.6 on 2024-04-22 21:24
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("publications_v2_api", "0001_initial"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="publication",
+            name="is_published",
+            field=models.BooleanField(default=True),
+        ),
+    ]
diff --git a/designsafe/apps/api/publications_v2/models.py b/designsafe/apps/api/publications_v2/models.py
index 0919164c70..8c42413e8f 100644
--- a/designsafe/apps/api/publications_v2/models.py
+++ b/designsafe/apps/api/publications_v2/models.py
@@ -13,6 +13,7 @@ class Publication(models.Model):
 
     project_id = models.CharField(max_length=100, primary_key=True, editable=False)
     created = models.DateTimeField(default=timezone.now)
+    is_published = models.BooleanField(default=True)
     last_updated = models.DateTimeField(auto_now=True)
     value = models.JSONField(
         encoder=DjangoJSONEncoder,