diff --git a/frontend/docs/docs/user-guide/org-settings.md b/frontend/docs/docs/user-guide/org-settings.md
index 5c5f50d37a..a2a6a46b86 100644
--- a/frontend/docs/docs/user-guide/org-settings.md
+++ b/frontend/docs/docs/user-guide/org-settings.md
@@ -4,17 +4,20 @@ Settings that apply to the entire organization are found in the **Settings** pag
 
 ## General
 
-### Name and URL
+### Name, URL, and other basic information
 
-Choose a display name for your org that's unique and memorable, like the name of your company, organization, or personal project. This name will be visible in the org's [public profile](#profile), if that page is enabled.
+Your org name appears throughout the web application and in email notifications. Choose a display name for your org that's unique and memorable, like the name of your company, organization, or personal project.
 
-The org URL is where you and other org members will go to view the dashboard, configure org settings, and manage all other org-related activities. Changing this URL will also update the URL of your org's public profile, if enabled.
+The org URL is where you and other org members will go to view the dashboard, configure org settings, and manage all other org-related activities. If your org has a [public collections gallery](#public-collections-gallery) enabled, changing this will also update the URL to the gallery.
 
-Org name and URLs are unique to each Browsertrix instance (for example, on `app.browsertrix.com`) and you may be prompted to change the org name or URL identifier if either are already in use by another org.
+Org name and URLs are unique to each Browsertrix instance (for example, on `app.browsertrix.com`) and you may be prompted to change the org name or URL if either are already in use by another org.
 
-### Profile
+??? info "What information will be visible to the public?"
+    All org information is private until you make the org visible. Once your org is made visible to the public, the org name, description, and website will appear on the org's public gallery page. You can preview how information appears to the public by clicking **View as public**.
 
-Enable and configure a public profile page for your org. Once enabled, anyone on the internet with a link to your org's profile page will be able to view public information like the org name, description, and public collections.
+### Public Collections Gallery
+
+Enable a homepage for your public collections to easily share all public collections in your org. Once enabled, anyone on the internet with a link to your org's public collections gallery will be able to browse public collections and view general information like the org name, description, and website.
 
 ## Billing
 
diff --git a/frontend/src/decorators/needLogin.test.ts b/frontend/src/decorators/needLogin.test.ts
index 79a1fa940c..66047fa70a 100644
--- a/frontend/src/decorators/needLogin.test.ts
+++ b/frontend/src/decorators/needLogin.test.ts
@@ -19,6 +19,7 @@ describe("needLogin", () => {
     }
 
     const Element = needLogin(
+      // @ts-expect-error not stubbing full BtrixElement
       class TestElement extends LiteElementMock {
         appState = appState;
       } as unknown as {
diff --git a/frontend/src/features/collections/collection-metadata-dialog.ts b/frontend/src/features/collections/collection-metadata-dialog.ts
index cd54308c1d..7c3d4ae012 100644
--- a/frontend/src/features/collections/collection-metadata-dialog.ts
+++ b/frontend/src/features/collections/collection-metadata-dialog.ts
@@ -16,6 +16,7 @@ import { DEFAULT_THUMBNAIL } from "./collection-thumbnail";
 import { BtrixElement } from "@/classes/BtrixElement";
 import type { Dialog } from "@/components/ui/dialog";
 import type { SelectCollectionAccess } from "@/features/collections/select-collection-access";
+import { alerts } from "@/strings/collections/alerts";
 import { CollectionAccess, type Collection } from "@/types/collection";
 import { isApiError } from "@/utils/api";
 import { maxLengthValidator } from "@/utils/form";
@@ -170,12 +171,10 @@ export class CollectionMetadataDialog extends BtrixElement {
             <btrix-alert variant="warning" class="mt-2">
               ${org.enablePublicProfile
                 ? msg(
-                    "This collection will be visible on the org public profile, even without archived items. You may want to set visibility to 'Unlisted' until archived items have been added.",
+                    "This collection will be visible in the org public collection gallery, even without archived items. You may want to set visibility to 'Unlisted' until archived items have been added.",
                   )
                 : html`
-                    ${msg(
-                      "This collection will be visible on the org profile page, which isn't public yet. To make the org profile and this collection visible to the public, update org profile settings.",
-                    )}
+                    ${alerts.orgNotPublicWarning}
                     <a
                       class="ml-auto flex items-center gap-1.5 font-medium underline hover:no-underline"
                       href=${`${this.navigate.orgBasePath}/settings`}
diff --git a/frontend/src/features/collections/collections-grid.ts b/frontend/src/features/collections/collections-grid.ts
index fb241e92f5..8f14f845cb 100644
--- a/frontend/src/features/collections/collections-grid.ts
+++ b/frontend/src/features/collections/collections-grid.ts
@@ -108,7 +108,7 @@ export class CollectionsGrid extends BtrixElement {
           html`<btrix-collection-edit-dialog
             .collectionId=${this.collectionBeingEdited ?? undefined}
             ?open=${!!this.collectionBeingEdited}
-            @sl-hide=${() => {
+            @sl-after-hide=${() => {
               this.collectionBeingEdited = null;
               // TODO propagate an event back up & refresh collections
               // void this.fetchCollection();
@@ -121,22 +121,15 @@ export class CollectionsGrid extends BtrixElement {
   private readonly renderActions = (collection: PublicCollection) => html`
     <div class="pointer-events-none absolute left-0 right-0 top-0 aspect-video">
       <div class="pointer-events-auto absolute bottom-2 right-2">
-        <btrix-overflow-dropdown raised>
-          <sl-menu>
-            <sl-menu-item
-              @click=${() => (this.collectionBeingEdited = collection.id)}
-            >
-              <sl-icon name="pencil" slot="prefix"></sl-icon>
-              ${msg("Edit Collection")}
-            </sl-menu-item>
-            <btrix-menu-item-link
-              href=${`/${RouteNamespace.PublicOrgs}/${this.orgSlugState}/collections/${collection.slug}`}
-            >
-              <sl-icon slot="prefix" name="globe2"></sl-icon>
-              ${msg("Visit Public Page")}
-            </btrix-menu-item-link>
-          </sl-menu>
-        </btrix-overflow-dropdown>
+        <btrix-button raised>
+          <sl-icon
+            label=${msg("Edit Collection")}
+            name="pencil"
+            @click=${() => {
+              this.collectionBeingEdited = collection.id;
+            }}
+          ></sl-icon>
+        </btrix-button>
       </div>
     </div>
   `;
diff --git a/frontend/src/features/collections/edit-dialog/sharing-section.ts b/frontend/src/features/collections/edit-dialog/sharing-section.ts
index 7d29f02d31..1de86ab733 100644
--- a/frontend/src/features/collections/edit-dialog/sharing-section.ts
+++ b/frontend/src/features/collections/edit-dialog/sharing-section.ts
@@ -10,11 +10,11 @@ import { customElement, property } from "lit/decorators.js";
 import { ifDefined } from "lit/directives/if-defined.js";
 import { when } from "lit/directives/when.js";
 
+import { collectionShareLink } from "../helpers/share-link";
 import { type SelectCollectionAccess } from "../select-collection-access";
 
 import { BtrixElement } from "@/classes/BtrixElement";
 import { viewStateContext, type ViewStateContext } from "@/context/view-state";
-import { RouteNamespace } from "@/routes";
 import { CollectionAccess, type Collection } from "@/types/collection";
 
 @customElement("btrix-collection-share-settings")
@@ -39,15 +39,11 @@ export class CollectionShareSettings extends BtrixElement {
   }
 
   private get shareLink() {
-    const baseUrl = `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ""}`;
-    if (this.collection) {
-      return `${baseUrl}/${
-        this.collection.access === CollectionAccess.Private
-          ? `${RouteNamespace.PrivateOrgs}/${this.orgSlugState}/collections/view/${this.collection.id}`
-          : `${RouteNamespace.PublicOrgs}/${this.viewState?.params.slug || ""}/collections/${this.collection.slug}`
-      }`;
-    }
-    return "";
+    return collectionShareLink(
+      this.collection,
+      this.orgSlugState,
+      this.viewState?.params.slug || "",
+    );
   }
 
   private get publicReplaySrc() {
diff --git a/frontend/src/features/collections/helpers/share-link.ts b/frontend/src/features/collections/helpers/share-link.ts
new file mode 100644
index 0000000000..2f6dceb8a0
--- /dev/null
+++ b/frontend/src/features/collections/helpers/share-link.ts
@@ -0,0 +1,20 @@
+import { RouteNamespace } from "@/routes";
+import { CollectionAccess, type Collection } from "@/types/collection";
+
+export function collectionShareLink(
+  collection:
+    | (Pick<Collection, "id" | "slug"> & Partial<Pick<Collection, "access">>)
+    | undefined,
+  privateSlug: string | null,
+  publicSlug: string | null,
+) {
+  const baseUrl = `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ""}`;
+  if (collection) {
+    return `${baseUrl}/${
+      collection.access === CollectionAccess.Private
+        ? `${RouteNamespace.PrivateOrgs}/${privateSlug}/collections/view/${collection.id}`
+        : `${RouteNamespace.PublicOrgs}/${publicSlug}/collections/${collection.slug}`
+    }`;
+  }
+  return "";
+}
diff --git a/frontend/src/features/collections/select-collection-access.ts b/frontend/src/features/collections/select-collection-access.ts
index 7547298ca2..2e8c9d5df9 100644
--- a/frontend/src/features/collections/select-collection-access.ts
+++ b/frontend/src/features/collections/select-collection-access.ts
@@ -28,7 +28,7 @@ export class SelectCollectionAccess extends BtrixElement {
     [CollectionAccess.Public]: {
       label: msg("Public"),
       icon: "globe2",
-      detail: msg("Anyone can view on the org's public profile"),
+      detail: msg("Anyone can view from the org public collections gallery"),
     },
   };
 
diff --git a/frontend/src/features/collections/share-collection.ts b/frontend/src/features/collections/share-collection.ts
index 1e97db062f..962c3b55fc 100644
--- a/frontend/src/features/collections/share-collection.ts
+++ b/frontend/src/features/collections/share-collection.ts
@@ -15,11 +15,12 @@ import {
   DEFAULT_THUMBNAIL_VARIANT,
   Thumbnail,
 } from "./collection-thumbnail";
-import { SelectCollectionAccess } from "./select-collection-access";
+import { collectionShareLink } from "./helpers/share-link";
+import { type SelectCollectionAccess } from "./select-collection-access";
 
 import { BtrixElement } from "@/classes/BtrixElement";
 import { ClipboardController } from "@/controllers/clipboard";
-import { RouteNamespace } from "@/routes";
+import { alerts } from "@/strings/collections/alerts";
 import { AnalyticsTrackEvent } from "@/trackEvents";
 import {
   CollectionAccess,
@@ -33,6 +34,12 @@ enum Tab {
   Embed = "embed",
 }
 
+function isFullCollection(
+  collection: PublicCollection | Collection | undefined,
+): collection is Collection {
+  return !!collection && "access" in collection;
+}
+
 /**
  * @fires btrix-change
  */
@@ -46,7 +53,7 @@ export class ShareCollection extends BtrixElement {
   collectionId = "";
 
   @property({ type: Object })
-  collection?: Partial<Collection>;
+  collection?: Collection | PublicCollection;
 
   @state()
   private showDialog = false;
@@ -57,15 +64,11 @@ export class ShareCollection extends BtrixElement {
   private readonly clipboardController = new ClipboardController(this);
 
   private get shareLink() {
-    const baseUrl = `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ""}`;
-    if (this.collection) {
-      return `${baseUrl}/${
-        this.collection.access === CollectionAccess.Private
-          ? `${RouteNamespace.PrivateOrgs}/${this.orgSlugState}/collections/view/${this.collectionId}`
-          : `${RouteNamespace.PublicOrgs}/${this.orgSlug}/collections/${this.collection.slug}`
-      }`;
-    }
-    return "";
+    return collectionShareLink(
+      this.collection,
+      this.orgSlugState,
+      this.orgSlug,
+    );
   }
 
   private get publicReplaySrc() {
@@ -93,7 +96,10 @@ export class ShareCollection extends BtrixElement {
       `;
     }
 
-    if (this.collection.access === CollectionAccess.Private) {
+    if (
+      isFullCollection(this.collection) &&
+      this.collection.access === CollectionAccess.Private
+    ) {
       return html`
         <sl-button
           variant=${this.collection.crawlCount ? "primary" : "default"}
@@ -107,129 +113,64 @@ export class ShareCollection extends BtrixElement {
     }
 
     return html`
-      <sl-button-group>
-        <sl-tooltip
-          content=${this.clipboardController.isCopied
-            ? ClipboardController.text.copied
-            : msg("Copy shareable link")}
-        >
-          <sl-button
-            variant=${this.collection.crawlCount ? "primary" : "default"}
-            size="small"
-            ?disabled=${!this.shareLink}
+      <div class="flex items-center gap-2">
+        <btrix-copy-button
+          .getValue=${() => this.shareLink}
+          content=${msg("Copy Link")}
+          @click=${() => {
+            void this.clipboardController.copy(this.shareLink);
+
+            if (
+              isFullCollection(this.collection) &&
+              this.collection.access === CollectionAccess.Public
+            ) {
+              track(AnalyticsTrackEvent.CopyShareCollectionLink, {
+                org_slug: this.orgSlug,
+                collection_slug: this.collection.slug,
+                logged_in: !!this.authState,
+              });
+            }
+          }}
+        ></btrix-copy-button>
+        <sl-tooltip content=${msg("View Embed Code")}>
+          <sl-icon-button
+            class="text-base"
+            name="code-slash"
             @click=${() => {
-              void this.clipboardController.copy(this.shareLink);
-
-              if (this.collection?.access === CollectionAccess.Public) {
-                track(AnalyticsTrackEvent.CopyShareCollectionLink, {
-                  org_slug: this.orgSlug,
-                  collection_slug: this.collection.slug,
-                  logged_in: !!this.authState,
-                });
-              }
+              this.tabGroup?.show(Tab.Embed);
+              this.showDialog = true;
             }}
           >
-            <sl-icon
-              name=${this.clipboardController.isCopied
-                ? "check-lg"
-                : "link-45deg"}
-            >
-            </sl-icon>
-            ${msg("Copy Link")}
-          </sl-button>
+          </sl-icon-button>
         </sl-tooltip>
-        <sl-dropdown distance="4" placement="bottom-end">
-          <sl-button
-            slot="trigger"
-            size="small"
-            variant=${this.collection.crawlCount ? "primary" : "default"}
-            caret
-          >
-          </sl-button>
-          <sl-menu>
-            <sl-menu-item
-              @click=${() => {
-                this.tabGroup?.show(Tab.Embed);
-                this.showDialog = true;
-              }}
-            >
-              <sl-icon slot="prefix" name="code-slash"></sl-icon>
-              ${msg("View Embed Code")}
-            </sl-menu-item>
-            ${when(
-              this.authState && !this.navigate.isPublicPage,
-              () => html`
-                <btrix-menu-item-link
-                  href=${this.shareLink}
-                  ?disabled=${!this.shareLink}
+        ${when(this.orgSlug && this.collection, (collection) =>
+          isFullCollection(collection) &&
+          collection.access === CollectionAccess.Public &&
+          collection.allowPublicDownload
+            ? html`
+                <sl-tooltip
+                  content=${msg("Download Collection: ") +
+                  this.localize.bytes(collection.totalSize || 0)}
                 >
-                  ${this.collection?.access === CollectionAccess.Unlisted
-                    ? html`
-                        <sl-icon
-                          slot="prefix"
-                          name=${SelectCollectionAccess.Options.unlisted.icon}
-                        ></sl-icon>
-                        ${msg("Visit Unlisted Page")}
-                      `
-                    : html`
-                        <sl-icon
-                          slot="prefix"
-                          name=${SelectCollectionAccess.Options.public.icon}
-                        ></sl-icon>
-                        ${msg("Visit Public Page")}
-                      `}
-                </btrix-menu-item-link>
-                ${this.appState.isCrawler
-                  ? html`
-                      <sl-divider></sl-divider>
-                      <sl-menu-item
-                        @click=${() => {
-                          this.showDialog = true;
-                        }}
-                      >
-                        <sl-icon slot="prefix" name="box-arrow-up"></sl-icon>
-                        ${msg("Link Settings")}
-                      </sl-menu-item>
-                    `
-                  : nothing}
-              `,
-            )}
-            ${when(this.orgSlug && this.collection, (collection) =>
-              collection.access === CollectionAccess.Public &&
-              collection.allowPublicDownload
-                ? html`
-                    <btrix-menu-item-link
-                      href=${`/api/public/orgs/${this.orgSlug}/collections/${this.collectionId}/download`}
-                      download
-                      ?disabled=${!this.collection?.totalSize}
-                      @click=${() => {
-                        track(AnalyticsTrackEvent.DownloadPublicCollection, {
-                          org_slug: this.orgSlug,
-                          collection_slug: this.collection?.slug,
-                        });
-                      }}
-                    >
-                      <sl-icon name="cloud-download" slot="prefix"></sl-icon>
-                      ${msg("Download Collection")}
-                      ${when(
-                        this.collection,
-                        (collection) => html`
-                          <btrix-badge
-                            slot="suffix"
-                            class="font-monostyle text-xs text-neutral-500"
-                            >${this.localize.bytes(
-                              collection.totalSize || 0,
-                            )}</btrix-badge
-                          >
-                        `,
-                      )}
-                    </btrix-menu-item-link>
-                  `
-                : nothing,
-            )}
-          </sl-menu>
-        </sl-dropdown>
-      </sl-button-group>
+                  <sl-icon-button
+                    class="text-base"
+                    name="cloud-download"
+                    href=${`/api/public/orgs/${this.orgSlug}/collections/${this.collectionId}/download`}
+                    download="true"
+                    ?disabled=${!this.collection?.totalSize}
+                    @click=${() => {
+                      track(AnalyticsTrackEvent.DownloadPublicCollection, {
+                        org_slug: this.orgSlug,
+                        collection_slug: this.collection?.slug,
+                      });
+                    }}
+                  >
+                  </sl-icon-button>
+                </sl-tooltip>
+              `
+            : nothing,
+        )}
+      </div>
     `;
   }
 
@@ -293,27 +234,25 @@ export class ShareCollection extends BtrixElement {
         ${when(
           this.org &&
             !this.org.enablePublicProfile &&
-            this.collection?.access === CollectionAccess.Public,
+            isFullCollection(this.collection) &&
+            this.collection.access === CollectionAccess.Public,
           () => html`
             <btrix-alert variant="warning" class="mt-3">
-              ${msg(
-                "The org profile page isn't public yet. To make the org profile and this collection visible to the public, update profile visibility in org settings.",
-              )}
+              ${alerts.orgNotPublicWarning}
             </btrix-alert>
           `,
         )}
       </div>
       ${when(
-        this.collection?.access != CollectionAccess.Private,
+        isFullCollection(this.collection) &&
+          this.collection.access != CollectionAccess.Private,
         () => html`<div class="mb-7">${this.renderShareLink()}</div>`,
       )}
       <div class="mb-7">
         <div class="form-label flex items-center gap-1.5">
           ${msg("Thumbnail")}
           <sl-tooltip
-            content=${msg(
-              "Choose a thumbnail to represent this collection in the org dashboard and profile page.",
-            )}
+            content=${msg("Choose a thumbnail to represent this collection.")}
           >
             <sl-icon name="info-circle"></sl-icon>
           </sl-tooltip>
@@ -446,7 +385,8 @@ export class ShareCollection extends BtrixElement {
 
     return html`
       ${when(
-        this.collection?.access === CollectionAccess.Private,
+        isFullCollection(this.collection) &&
+          this.collection.access === CollectionAccess.Private,
         () => html`
           <btrix-alert variant="warning" class="mb-3">
             ${msg("Change the visibility setting to embed this collection.")}
@@ -504,12 +444,11 @@ export class ShareCollection extends BtrixElement {
   };
 
   private async updateVisibility(access: CollectionAccess) {
-    const prevValue = this.collection?.access;
+    if (!isFullCollection(this.collection)) return;
+    const prevValue = this.collection.access;
 
     // Optimistic update
-    if (this.collection) {
-      this.collection = { ...this.collection, access };
-    }
+    this.collection = { ...this.collection, access };
 
     try {
       await this.api.fetch<{ updated: boolean }>(
@@ -532,7 +471,7 @@ export class ShareCollection extends BtrixElement {
       console.debug(err);
 
       // Revert optimistic update
-      if (this.collection && prevValue !== undefined) {
+      if (isFullCollection(this.collection)) {
         this.collection = { ...this.collection, access: prevValue };
       }
 
diff --git a/frontend/src/index.ts b/frontend/src/index.ts
index e1d2dbce6d..dfc1693359 100644
--- a/frontend/src/index.ts
+++ b/frontend/src/index.ts
@@ -820,11 +820,11 @@ export class App extends BtrixElement {
         ></btrix-org>`;
       }
 
-      case "publicOrgProfile":
-        return html`<btrix-org-profile
+      case "publicOrg":
+        return html`<btrix-public-org
           class="w-full"
           orgSlug=${this.viewState.params.slug}
-        ></btrix-org-profile>`;
+        ></btrix-public-org>`;
 
       case "publicCollection": {
         const { collectionSlug, collectionTab } = this.viewState.params;
diff --git a/frontend/src/layouts/pageHeader.ts b/frontend/src/layouts/pageHeader.ts
index 028f92c684..0cdf83c064 100644
--- a/frontend/src/layouts/pageHeader.ts
+++ b/frontend/src/layouts/pageHeader.ts
@@ -136,7 +136,7 @@ export function pageHeader({
       </div>
 
       ${actions
-        ? html`<div class="ml-auto flex flex-shrink-0 items-center gap-2">
+        ? html`<div class="ml-auto flex flex-shrink-0 items-end gap-2">
             ${actions}
           </div>`
         : nothing}
diff --git a/frontend/src/pages/collections/collection.ts b/frontend/src/pages/collections/collection.ts
index 5d51379e83..dfa32a8247 100644
--- a/frontend/src/pages/collections/collection.ts
+++ b/frontend/src/pages/collections/collection.ts
@@ -104,26 +104,26 @@ export class Collection extends BtrixElement {
           : [],
       title: collection.name || "",
       actions: html`
-        ${when(
-          this.canEditCollection,
-          () => html`
-            <sl-tooltip content=${msg("Edit collection")}>
-              <sl-icon-button
-                href="${this.navigate
-                  .orgBasePath}/collections/view/${collection.id}"
-                class="size-8 text-base"
-                name="pencil"
-                @click=${this.navigate.link}
-              ></sl-icon-button>
-            </sl-tooltip>
-          `,
-        )}
-
         <btrix-share-collection
           orgSlug=${this.orgSlug || ""}
           collectionId=${collection.id}
           .collection=${collection}
         ></btrix-share-collection>
+        ${when(
+          this.canEditCollection,
+          () => html`
+            <sl-button
+              href="${this.navigate
+                .orgBasePath}/collections/view/${collection.id}"
+              size="small"
+              variant="primary"
+              @click=${this.navigate.link}
+            >
+              <sl-icon slot="prefix" name="gear"></sl-icon>
+              ${msg("Edit Collection")}
+            </sl-button>
+          `,
+        )}
       `,
     };
 
diff --git a/frontend/src/pages/index.ts b/frontend/src/pages/index.ts
index 142bce53f1..bf3410b96a 100644
--- a/frontend/src/pages/index.ts
+++ b/frontend/src/pages/index.ts
@@ -11,3 +11,4 @@ import(/* webpackChunkName: "users-invite" */ "./users-invite");
 import(/* webpackChunkName: "accept-invite" */ "./invite/accept");
 import(/* webpackChunkName: "account-settings" */ "./account-settings");
 import(/* webpackChunkName: "collections" */ "./collections");
+import(/* webpackChunkName: "public" */ "./public");
diff --git a/frontend/src/pages/org/collection-detail.ts b/frontend/src/pages/org/collection-detail.ts
index 1242aa36d5..216c74dfe4 100644
--- a/frontend/src/pages/org/collection-detail.ts
+++ b/frontend/src/pages/org/collection-detail.ts
@@ -1,3 +1,4 @@
+import { consume } from "@lit/context";
 import { localized, msg, str } from "@lit/localize";
 import clsx from "clsx";
 import { html, nothing, type PropertyValues, type TemplateResult } from "lit";
@@ -12,7 +13,9 @@ import type { Embed as ReplayWebPage } from "replaywebpage";
 import { BtrixElement } from "@/classes/BtrixElement";
 import type { MarkdownEditor } from "@/components/ui/markdown-editor";
 import type { PageChangeEvent } from "@/components/ui/pagination";
+import { viewStateContext, type ViewStateContext } from "@/context/view-state";
 import type { EditDialogTab } from "@/features/collections/collection-edit-dialog";
+import { collectionShareLink } from "@/features/collections/helpers/share-link";
 import { SelectCollectionAccess } from "@/features/collections/select-collection-access";
 import type { ShareCollection } from "@/features/collections/share-collection";
 import {
@@ -72,6 +75,9 @@ export class CollectionDetail extends BtrixElement {
   @state()
   private isRwpLoaded = false;
 
+  @consume({ context: viewStateContext })
+  viewState?: ViewStateContext;
+
   @query("replay-web-page")
   private readonly replayEmbed?: ReplayWebPage | null;
 
@@ -102,6 +108,14 @@ export class CollectionDetail extends BtrixElement {
     },
   };
 
+  private get shareLink() {
+    return collectionShareLink(
+      this.collection,
+      this.orgSlugState,
+      this.viewState?.params.slug || "",
+    );
+  }
+
   private get isCrawler() {
     return this.appState.isCrawler;
   }
@@ -136,7 +150,29 @@ export class CollectionDetail extends BtrixElement {
 
   render() {
     return html`
-      <div class="mb-7">${this.renderBreadcrumbs()}</div>
+      <div class="mb-7 flex justify-between">
+        ${this.renderBreadcrumbs()}
+        ${this.collection &&
+        (this.collection.access === CollectionAccess.Unlisted ||
+          this.collection.access === CollectionAccess.Public)
+          ? html`
+              <a
+                href=${this.shareLink}
+                class="flex h-5 items-center gap-1 truncate whitespace-nowrap font-medium leading-5 text-primary"
+              >
+                <sl-icon
+                  slot="prefix"
+                  name=${this.collection.access === CollectionAccess.Unlisted
+                    ? SelectCollectionAccess.Options.unlisted.icon
+                    : SelectCollectionAccess.Options.public.icon}
+                ></sl-icon>
+                ${this.collection.access === CollectionAccess.Unlisted
+                  ? msg("Visit Unlisted Page")
+                  : msg("Visit Public Page")}
+              </a>
+            `
+          : nothing}
+      </div>
       <header class=${clsx(tw`mt-5 flex flex-col gap-3 lg:flex-row`)}>
         <div
           class="-mb-2 -ml-2 -mr-1 -mt-1 flex flex-none flex-col gap-2 self-start rounded-lg pb-2 pl-2 pr-1 pt-1 transition-colors has-[sl-icon-button:hover]:bg-primary-50"
@@ -413,27 +449,22 @@ export class CollectionDetail extends BtrixElement {
     const authToken = this.authState?.headers.Authorization.split(" ")[1];
 
     return html`
-      <sl-button-group>
-        <sl-button
-          variant="primary"
-          size="small"
-          @click=${() => {
-            this.openDialogName = "edit";
-          }}
-        >
-          <sl-icon name="pencil" slot="prefix"></sl-icon>
-          ${msg("Edit Collection")}
-        </sl-button>
-      </sl-button-group>
+      <sl-button
+        size="small"
+        variant="primary"
+        @click=${() => {
+          this.openDialogName = "edit";
+          this.editTab = "general";
+        }}
+      >
+        <sl-icon slot="prefix" name="pencil"></sl-icon>
+        ${msg("Edit Collection")}
+      </sl-button>
       <sl-dropdown distance="4">
         <sl-button slot="trigger" size="small" caret
           >${msg("Actions")}</sl-button
         >
         <sl-menu>
-          <sl-menu-item @click=${() => (this.openDialogName = "edit")}>
-            <sl-icon name="pencil" slot="prefix"></sl-icon>
-            ${msg("Edit Collection")}
-          </sl-menu-item>
           <sl-menu-item
             @click=${async () => {
               // replay-web-page needs to be available in order to configure start page
@@ -449,32 +480,13 @@ export class CollectionDetail extends BtrixElement {
             ?disabled=${!this.collection?.crawlCount}
           >
             <sl-icon name="gear" slot="prefix"></sl-icon>
-            ${msg("Configure Replay View")}
-          </sl-menu-item>
-          <sl-menu-item
-            @click=${async () => {
-              if (this.collectionTab !== Tab.About) {
-                this.navigate.to(
-                  `${this.navigate.orgBasePath}/collections/view/${this.collectionId}/${Tab.About}`,
-                );
-                await this.updateComplete;
-              }
-
-              this.isEditingDescription = true;
-            }}
-          >
-            <sl-icon name="pencil-square" slot="prefix"></sl-icon>
-            ${msg("Edit About Section")}
+            ${msg("Edit Collection")}
           </sl-menu-item>
           <sl-menu-item @click=${() => (this.openDialogName = "editItems")}>
             <sl-icon name="ui-checks" slot="prefix"></sl-icon>
             ${msg("Select Archived Items")}
           </sl-menu-item>
           <sl-divider></sl-divider>
-          <sl-menu-item @click=${() => this.shareCollection?.show()}>
-            <sl-icon slot="prefix" name="box-arrow-up"></sl-icon>
-            ${msg("Share Collection")}
-          </sl-menu-item>
           <btrix-menu-item-link
             href=${`/api/orgs/${this.orgId}/collections/${this.collectionId}/download?auth_bearer=${authToken}`}
             download
diff --git a/frontend/src/pages/org/dashboard.ts b/frontend/src/pages/org/dashboard.ts
index 2d3b06f762..7c9338d2a0 100644
--- a/frontend/src/pages/org/dashboard.ts
+++ b/frontend/src/pages/org/dashboard.ts
@@ -89,11 +89,59 @@ export class Dashboard extends BtrixElement {
     return html`
       ${pageHeader({
         title: this.userOrg?.name,
+        secondary: html`
+          ${when(
+            this.org?.publicDescription,
+            (publicDescription) => html`
+              <div class="text-pretty text-stone-600">${publicDescription}</div>
+            `,
+          )}
+          ${when(this.org?.publicUrl, (urlStr) => {
+            let url: URL;
+            try {
+              url = new URL(urlStr);
+            } catch {
+              return nothing;
+            }
+
+            return html`
+              <div
+                class="flex items-center gap-1.5 text-pretty text-neutral-700"
+              >
+                <sl-icon
+                  name="globe2"
+                  class="size-4 text-stone-400"
+                  label=${msg("Website")}
+                ></sl-icon>
+                <a
+                  class="font-medium leading-none text-stone-500 transition-colors hover:text-stone-600"
+                  href="${url.href}"
+                  target="_blank"
+                  rel="noopener noreferrer nofollow"
+                >
+                  ${url.href.split("//")[1].replace(/\/$/, "")}
+                </a>
+              </div>
+            `;
+          })}
+        `,
         actions: html`
+          <sl-tooltip
+            content=${this.org?.enablePublicProfile
+              ? msg("Visit Public Collections Gallery")
+              : msg("Preview Public Collections Gallery")}
+          >
+            <sl-icon-button
+              href=${`/${RouteNamespace.PublicOrgs}/${this.orgSlugState}`}
+              class="size-8 text-base"
+              name="globe2"
+              @click=${this.navigate.link}
+            ></sl-icon-button>
+          </sl-tooltip>
           ${when(
             this.appState.isAdmin,
             () =>
-              html`<sl-tooltip content=${msg("Manage org settings")}>
+              html`<sl-tooltip content=${msg("Change Org Settings")}>
                 <sl-icon-button
                   href=${`${this.navigate.orgBasePath}/settings`}
                   class="size-8 text-base"
@@ -304,14 +352,6 @@ export class Dashboard extends BtrixElement {
                       <sl-icon slot="prefix" name="collection-fill"></sl-icon>
                       ${msg("Manage Collections")}
                     </btrix-menu-item-link>
-                    <btrix-menu-item-link
-                      href=${`/${RouteNamespace.PublicOrgs}/${this.orgSlugState}`}
-                    >
-                      <sl-icon slot="prefix" name="globe2"></sl-icon>
-                      ${this.org?.enablePublicProfile
-                        ? msg("Visit Public Profile")
-                        : msg("Preview Public Profile")}
-                    </btrix-menu-item-link>
                     ${when(this.org, (org) =>
                       org.enablePublicProfile
                         ? html`
@@ -330,7 +370,7 @@ export class Dashboard extends BtrixElement {
                               }}
                             >
                               <sl-icon name="copy" slot="prefix"></sl-icon>
-                              ${msg("Copy Link to Profile")}
+                              ${msg("Copy Link to Public Gallery")}
                             </sl-menu-item>
                           `
                         : this.appState.isAdmin
diff --git a/frontend/src/pages/org/index.ts b/frontend/src/pages/org/index.ts
index e27e4d09d6..cc68523188 100644
--- a/frontend/src/pages/org/index.ts
+++ b/frontend/src/pages/org/index.ts
@@ -12,6 +12,7 @@ import type { Tab as CollectionTab } from "./collection-detail";
 import type {
   Member,
   OrgRemoveMemberEvent,
+  UpdateOrgDetail,
   UserRoleChangeEvent,
 } from "./settings/settings";
 
@@ -41,7 +42,6 @@ import "./browser-profiles-detail";
 import "./browser-profiles-list";
 import "./settings/settings";
 import "./dashboard";
-import "./profile";
 
 import(/* webpackChunkName: "org" */ "./archived-item-qa/archived-item-qa");
 import(/* webpackChunkName: "org" */ "./workflows-new");
@@ -628,6 +628,17 @@ export class Org extends BtrixElement {
     return html`<btrix-org-settings
       activePanel=${activePanel}
       ?isAddingMember=${isAddingMember}
+      @btrix-update-org=${(e: CustomEvent<UpdateOrgDetail>) => {
+        e.stopPropagation();
+
+        // Optimistic update
+        AppStateService.partialUpdateOrg({
+          id: this.orgId,
+          ...e.detail,
+        });
+
+        void this.updateOrg();
+      }}
       @org-user-role-change=${this.onUserRoleChange}
       @org-remove-member=${this.onOrgRemoveMember}
     ></btrix-org-settings>`;
diff --git a/frontend/src/pages/org/settings/components/profile.ts b/frontend/src/pages/org/settings/components/profile.ts
deleted file mode 100644
index fc1708fb3c..0000000000
--- a/frontend/src/pages/org/settings/components/profile.ts
+++ /dev/null
@@ -1,158 +0,0 @@
-import { localized, msg } from "@lit/localize";
-import { serialize } from "@shoelace-style/shoelace/dist/utilities/form.js";
-import { html } from "lit";
-import { customElement } from "lit/decorators.js";
-
-import { BtrixElement } from "@/classes/BtrixElement";
-import { columns, type Cols } from "@/layouts/columns";
-import { RouteNamespace } from "@/routes";
-import { formValidator, maxLengthValidator } from "@/utils/form";
-
-@localized()
-@customElement("btrix-org-settings-profile")
-export class OrgSettingsProfile extends BtrixElement {
-  private readonly validateDescriptionMax = maxLengthValidator(150);
-
-  render() {
-    const orgBaseUrl = `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ""}`;
-
-    const cols: Cols = [
-      [
-        html`
-          <label for="orgVisibility" class="form-label text-xs">
-            ${msg("Visibility")}
-          </label>
-          <div>
-            <sl-switch
-              id="orgVisibility"
-              name="enablePublicProfile"
-              size="small"
-              ?checked=${this.org?.enablePublicProfile}
-            >
-              ${msg("Allow anyone to view org")}
-            </sl-switch>
-          </div>
-        `,
-        msg(
-          "If enabled, anyone will be able to view your org's profile page and public collections.",
-        ),
-      ],
-      [
-        html`
-          <sl-textarea
-            class="with-max-help-text"
-            name="publicDescription"
-            size="small"
-            label=${msg("Description")}
-            autocomplete="off"
-            value=${this.org?.publicDescription || ""}
-            minlength="2"
-            rows="2"
-            help-text=${this.validateDescriptionMax.helpText}
-            @sl-input=${this.validateDescriptionMax.validate}
-          ></sl-textarea>
-        `,
-        msg("Write a short description to introduce your organization."),
-      ],
-      [
-        html`
-          <btrix-url-input
-            class="mb-2"
-            name="publicUrl"
-            size="small"
-            label=${msg("Website")}
-            value=${this.org?.publicUrl || ""}
-          ></btrix-url-input>
-        `,
-        msg("Link to your organization's (or your personal) website."),
-      ],
-      [
-        html`
-          <div class="mb-2">
-            <btrix-copy-field
-              label=${msg("Profile Page")}
-              value=${`${orgBaseUrl}/${RouteNamespace.PublicOrgs}/${this.orgSlugState}`}
-              .monostyle=${false}
-            ></btrix-copy-field>
-          </div>
-        `,
-        html`
-          ${msg(
-            html`To customize this URL,
-              <a
-                href=${`${location.pathname}#org-url`}
-                class="text-cyan-500 underline decoration-cyan-500/30 transition hover:text-cyan-600 hover:decoration-cyan-500/50"
-                >${msg("update your Org URL in General settings")}</a
-              >.`,
-          )}
-        `,
-      ],
-    ];
-
-    return html`
-      <h2 class="mb-2 mt-7 text-lg font-medium">${msg("Profile")}</h2>
-
-      <section class="rounded-lg border">
-        <form @submit=${this.onSubmit}>
-          <div class="p-5">${columns(cols)}</div>
-          <footer class="flex items-center justify-between border-t px-4 py-3">
-            <btrix-link
-              href=${`/${RouteNamespace.PublicOrgs}/${this.orgSlugState}`}
-              target="_blank"
-            >
-              ${msg("Preview public profile page")}
-            </btrix-link>
-            <sl-button type="submit" size="small" variant="primary">
-              ${msg("Save")}
-            </sl-button>
-          </footer>
-        </form>
-      </section>
-    `;
-  }
-
-  private readonly checkFormValidity = formValidator(this);
-
-  private async onSubmit(e: SubmitEvent) {
-    e.preventDefault();
-
-    const form = e.currentTarget as HTMLFormElement;
-
-    if (!(await this.checkFormValidity(form))) return;
-
-    const { enablePublicProfile, publicDescription, publicUrl } =
-      serialize(form);
-
-    try {
-      const data = await this.api.fetch<{ updated: boolean }>(
-        `/orgs/${this.orgId}/public-profile`,
-        {
-          method: "POST",
-          body: JSON.stringify({
-            enablePublicProfile: enablePublicProfile === "on",
-            publicDescription,
-            publicUrl,
-          }),
-        },
-      );
-
-      if (!data.updated) {
-        throw new Error();
-      }
-
-      this.notify.toast({
-        message: msg("Org profile has been updated."),
-        variant: "success",
-        icon: "check2-circle",
-      });
-    } catch (err) {
-      console.debug(err);
-
-      this.notify.toast({
-        message: msg("Sorry, couldn't update org at this time."),
-        variant: "danger",
-        icon: "exclamation-octagon",
-      });
-    }
-  }
-}
diff --git a/frontend/src/pages/org/settings/components/visibility.ts b/frontend/src/pages/org/settings/components/visibility.ts
new file mode 100644
index 0000000000..aadbbd0216
--- /dev/null
+++ b/frontend/src/pages/org/settings/components/visibility.ts
@@ -0,0 +1,128 @@
+import { localized, msg } from "@lit/localize";
+import type { SlChangeEvent, SlSwitch } from "@shoelace-style/shoelace";
+import { html } from "lit";
+import { customElement } from "lit/decorators.js";
+
+import { UPDATED_STATUS_TOAST_ID, type UpdateOrgDetail } from "../settings";
+
+import { BtrixElement } from "@/classes/BtrixElement";
+import { columns, type Cols } from "@/layouts/columns";
+import { RouteNamespace } from "@/routes";
+import { alerts } from "@/strings/orgs/alerts";
+
+/**
+ * @fires btrix-update-org
+ */
+@localized()
+@customElement("btrix-org-settings-visibility")
+export class OrgSettingsVisibility extends BtrixElement {
+  render() {
+    const orgBaseUrl = `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ""}`;
+
+    const cols: Cols = [
+      [
+        html`
+          <label for="orgVisibility" class="form-label text-xs">
+            ${msg("Gallery Visibility")}
+          </label>
+          <div>
+            <sl-switch
+              id="orgVisibility"
+              name="enablePublicProfile"
+              size="small"
+              @sl-change=${this.onVisibilityChange}
+              ?checked=${this.org?.enablePublicProfile}
+              ?disabled=${!this.org}
+            >
+              ${msg("Enable gallery of public collections")}
+            </sl-switch>
+          </div>
+        `,
+        msg(
+          "If enabled, anyone on the Internet will be able to browse this org's public collections and view general org information.",
+        ),
+      ],
+      [
+        html`
+          <div class="mb-2">
+            <btrix-copy-field
+              label=${msg("Public Gallery URL")}
+              value=${`${orgBaseUrl}/${RouteNamespace.PublicOrgs}/${this.orgSlugState}`}
+              .monostyle=${false}
+            ></btrix-copy-field>
+          </div>
+        `,
+        html`
+          ${msg(
+            html`To customize this URL,
+              <a
+                href=${`${location.pathname}#org-url`}
+                class="text-cyan-500 underline decoration-cyan-500/30 transition hover:text-cyan-600 hover:decoration-cyan-500/50"
+                >${msg("update your Org URL in General settings")}</a
+              >.`,
+          )}
+        `,
+      ],
+    ];
+
+    return html`
+      <h2 class="mb-2 mt-7 text-lg font-medium">
+        ${msg("Public Collections Gallery")}
+      </h2>
+
+      <section class="rounded-lg border">
+        <div class="p-5">${columns(cols)}</div>
+      </section>
+    `;
+  }
+
+  private readonly onVisibilityChange = async (e: SlChangeEvent) => {
+    const checked = (e.target as SlSwitch).checked;
+
+    if (checked === this.org?.enablePublicProfile) {
+      return;
+    }
+
+    try {
+      const data = await this.api.fetch<{ updated: boolean }>(
+        `/orgs/${this.orgId}/public-profile`,
+        {
+          method: "POST",
+          body: JSON.stringify({
+            enablePublicProfile: checked,
+          }),
+        },
+      );
+
+      if (!data.updated) {
+        throw new Error("`data.updated` is not true");
+      }
+
+      this.dispatchEvent(
+        new CustomEvent<UpdateOrgDetail>("btrix-update-org", {
+          detail: {
+            enablePublicProfile: checked,
+          },
+          bubbles: true,
+          composed: true,
+        }),
+      );
+
+      this.notify.toast({
+        message: msg("Updated public collections gallery visibility."),
+        variant: "success",
+        icon: "check2-circle",
+        id: UPDATED_STATUS_TOAST_ID,
+      });
+    } catch (err) {
+      console.debug(err);
+
+      this.notify.toast({
+        message: alerts.settingsUpdateFailure,
+        variant: "danger",
+        icon: "exclamation-octagon",
+        id: UPDATED_STATUS_TOAST_ID,
+      });
+    }
+  };
+}
diff --git a/frontend/src/pages/org/settings/settings.ts b/frontend/src/pages/org/settings/settings.ts
index f0b744bb21..ea5c6ef625 100644
--- a/frontend/src/pages/org/settings/settings.ts
+++ b/frontend/src/pages/org/settings/settings.ts
@@ -20,10 +20,11 @@ import type { APIUser } from "@/index";
 import { columns } from "@/layouts/columns";
 import { pageHeader } from "@/layouts/pageHeader";
 import { RouteNamespace } from "@/routes";
+import { alerts } from "@/strings/orgs/alerts";
 import type { APIPaginatedList } from "@/types/api";
 import { isApiError } from "@/utils/api";
 import { formValidator, maxLengthValidator } from "@/utils/form";
-import { AccessCode, isAdmin, isCrawler } from "@/utils/orgs";
+import { AccessCode, isAdmin, isCrawler, type OrgData } from "@/utils/orgs";
 import slugifyStrict from "@/utils/slugify";
 import { AppStateService } from "@/utils/state";
 import { tw } from "@/utils/tailwind";
@@ -31,7 +32,7 @@ import { formatAPIUser } from "@/utils/user";
 
 import "./components/billing";
 import "./components/crawling-defaults";
-import "./components/profile";
+import "./components/visibility";
 
 const styles = unsafeCSS(stylesheet);
 
@@ -55,6 +56,10 @@ export type OrgRemoveMemberEvent = CustomEvent<{
   member: Member;
 }>;
 
+export type UpdateOrgDetail = Partial<OrgData>;
+
+export const UPDATED_STATUS_TOAST_ID = "org-updated-status" as const;
+
 /**
  * Usage:
  * ```ts
@@ -64,6 +69,7 @@ export type OrgRemoveMemberEvent = CustomEvent<{
  * ></btrix-org-settings>
  * ```
  *
+ * @fires btrix-update-org
  * @fires org-user-role-change
  * @fires org-remove-member
  */
@@ -103,6 +109,7 @@ export class OrgSettings extends BtrixElement {
   }
 
   private readonly validateOrgNameMax = maxLengthValidator(40);
+  private readonly validateDescriptionMax = maxLengthValidator(150);
 
   async willUpdate(changedProperties: PropertyValues<this>) {
     if (changedProperties.has("isAddingMember") && this.isAddingMember) {
@@ -171,7 +178,7 @@ export class OrgSettings extends BtrixElement {
         <btrix-tab-group-panel name="information">
           ${this.renderPanelHeader({ title: msg("General") })}
           ${this.renderInformation()}
-          <btrix-org-settings-profile></btrix-org-settings-profile>
+          <btrix-org-settings-visibility></btrix-org-settings-visibility>
           ${this.renderApi()}
         </btrix-tab-group-panel>
         <btrix-tab-group-panel name="members">
@@ -294,7 +301,7 @@ export class OrgSettings extends BtrixElement {
               html`
                 <sl-input
                   id="org-url"
-                  class="hide-required-content mb-2 part-[input]:pl-0"
+                  class="hide-required-content mb-2 part-[input]:pl-px"
                   name="orgSlug"
                   size="small"
                   label=${msg("Org URL")}
@@ -306,20 +313,56 @@ export class OrgSettings extends BtrixElement {
                   required
                   @sl-input=${this.handleSlugInput}
                 >
-                  <div slot="prefix" class="font-light text-neutral-400">
-                    ${window.location.hostname}${window.location.port
-                      ? `:${window.location.port}`
-                      : ""}/${RouteNamespace.PrivateOrgs}/
-                  </div>
+                  <div slot="prefix" class="font-light text-neutral-500">/</div>
                 </sl-input>
               `,
-              msg(
-                "Customize your org's Browsertrix URL. This will also apply to the URL to your org's public profile page, if you've enabled it.",
-              ),
+              msg("Customize your org's Browsertrix URL."),
+            ],
+            [
+              html`
+                <sl-textarea
+                  class="with-max-help-text"
+                  name="publicDescription"
+                  size="small"
+                  label=${msg("Description")}
+                  autocomplete="off"
+                  value=${this.org?.publicDescription || ""}
+                  minlength="2"
+                  rows="2"
+                  help-text=${this.validateDescriptionMax.helpText}
+                  @sl-input=${this.validateDescriptionMax.validate}
+                ></sl-textarea>
+              `,
+              msg("Write a short description to introduce your organization."),
+            ],
+            [
+              html`
+                <btrix-url-input
+                  class="mb-2"
+                  name="publicUrl"
+                  size="small"
+                  label=${msg("Website")}
+                  value=${this.org?.publicUrl || ""}
+                ></btrix-url-input>
+              `,
+              msg("Link to your organization's (or your personal) website."),
             ],
           ])}
         </div>
-        <footer class="flex justify-end border-t px-4 py-3">
+        <footer class="flex items-center justify-between border-t px-4 py-3">
+          <btrix-link
+            href=${`/${RouteNamespace.PublicOrgs}/${this.orgSlugState}`}
+            target="_blank"
+          >
+            ${when(
+              this.org,
+              (org) =>
+                org.enablePublicProfile
+                  ? msg("View as public")
+                  : msg("Preview how information appears to the public"),
+              () => html` <sl-skeleton class="w-36"></sl-skeleton> `,
+            )}
+          </btrix-link>
           <sl-button
             type="submit"
             size="small"
@@ -668,24 +711,81 @@ export class OrgSettings extends BtrixElement {
     e.preventDefault();
 
     const formEl = e.target as HTMLFormElement;
-    if (!(await this.checkFormValidity(formEl))) return;
-
-    const { orgName } = serialize(formEl) as { orgName: string };
+    if (!(await this.checkFormValidity(formEl)) || !this.org) return;
 
-    const params = {
-      name: orgName,
-      slug: this.orgSlugState!,
+    const { orgName, publicDescription, publicUrl } = serialize(formEl) as {
+      orgName: string;
+      publicDescription: string;
+      publicUrl: string;
     };
 
-    if (this.slugValue) {
-      params.slug = slugifyStrict(this.slugValue);
+    // TODO See if backend can combine into one endpoint
+    const requests: Promise<unknown>[] = [];
+
+    if (orgName !== this.org.name || this.slugValue) {
+      const params = {
+        name: orgName,
+        slug: this.orgSlugState!,
+      };
+
+      if (this.slugValue) {
+        params.slug = slugifyStrict(this.slugValue);
+      }
+
+      requests.push(this.renameOrg(params));
     }
 
-    this.isSavingOrgName = true;
+    if (
+      publicDescription !== (this.org.publicDescription ?? "") ||
+      publicUrl !== (this.org.publicUrl ?? "")
+    ) {
+      requests.push(
+        this.updateOrgProfile({
+          publicDescription: publicDescription || this.org.publicDescription,
+          publicUrl: publicUrl || this.org.publicUrl,
+        }),
+      );
+    }
+
+    if (requests.length) {
+      this.isSavingOrgName = true;
+
+      try {
+        await Promise.all(requests);
+
+        this.notify.toast({
+          message: alerts.settingsUpdateSuccess,
+          variant: "success",
+          icon: "check2-circle",
+          id: UPDATED_STATUS_TOAST_ID,
+        });
+      } catch (err) {
+        console.debug(err);
+
+        let message = alerts.settingsUpdateFailure;
+
+        if (isApiError(err)) {
+          if (err.details === "duplicate_org_name") {
+            message = msg("This org name is already taken, try another one.");
+          } else if (err.details === "duplicate_org_slug") {
+            message = msg("This org URL is already taken, try another one.");
+          } else if (err.details === "invalid_slug") {
+            message = msg(
+              "This org URL is invalid. Please use alphanumeric characters and dashes (-) only.",
+            );
+          }
+        }
 
-    await this.renameOrg(params);
+        this.notify.toast({
+          message,
+          variant: "danger",
+          icon: "exclamation-octagon",
+          id: UPDATED_STATUS_TOAST_ID,
+        });
+      }
 
-    this.isSavingOrgName = false;
+      this.isSavingOrgName = false;
+    }
   }
 
   private readonly selectUserRole = (user: User) => (e: Event) => {
@@ -777,52 +877,50 @@ export class OrgSettings extends BtrixElement {
   }
 
   private async renameOrg({ name, slug }: { name: string; slug: string }) {
-    try {
-      await this.api.fetch(`/orgs/${this.orgId}/rename`, {
-        method: "POST",
-        body: JSON.stringify({ name, slug }),
-      });
-
-      const user = await this.getCurrentUser();
-
-      AppStateService.updateUser(formatAPIUser(user), slug);
+    await this.api.fetch(`/orgs/${this.orgId}/rename`, {
+      method: "POST",
+      body: JSON.stringify({ name, slug }),
+    });
 
-      this.navigate.to(`${this.navigate.orgBasePath}/settings`);
+    const user = await this.getCurrentUser();
 
-      this.notify.toast({
-        message: msg("Org successfully updated."),
-        variant: "success",
-        icon: "check2-circle",
-        id: "org-update-status",
-      });
-    } catch (e) {
-      console.debug(e);
+    AppStateService.updateUser(formatAPIUser(user), slug);
 
-      let message = msg(
-        "Sorry, couldn't rename organization at this time. Try again later from org settings.",
-      );
+    this.navigate.to(`${this.navigate.orgBasePath}/settings`);
+  }
 
-      if (isApiError(e)) {
-        if (e.details === "duplicate_org_name") {
-          message = msg("This org name is already taken, try another one.");
-        } else if (e.details === "duplicate_org_slug") {
-          message = msg(
-            "This org URL identifier is already taken, try another one.",
-          );
-        } else if (e.details === "invalid_slug") {
-          message = msg(
-            "This org URL identifier is invalid. Please use alphanumeric characters and dashes (-) only.",
-          );
-        }
-      }
+  private async updateOrgProfile({
+    publicDescription,
+    publicUrl,
+  }: {
+    publicDescription: string | null;
+    publicUrl: string | null;
+  }) {
+    const data = await this.api.fetch<{ updated: boolean }>(
+      `/orgs/${this.orgId}/public-profile`,
+      {
+        method: "POST",
+        body: JSON.stringify({
+          publicDescription,
+          publicUrl,
+        }),
+      },
+    );
 
-      this.notify.toast({
-        message: message,
-        variant: "danger",
-        icon: "exclamation-octagon",
-        id: "org-update-status",
-      });
+    if (!data.updated) {
+      throw new Error("`data.updated` is not true");
     }
+
+    this.dispatchEvent(
+      new CustomEvent<UpdateOrgDetail>("btrix-update-org", {
+        detail: {
+          publicDescription,
+          publicUrl,
+        },
+        bubbles: true,
+        composed: true,
+      }),
+    );
   }
 
   private async getCurrentUser(): Promise<APIUser> {
diff --git a/frontend/src/pages/public/index.ts b/frontend/src/pages/public/index.ts
new file mode 100644
index 0000000000..afaa511903
--- /dev/null
+++ b/frontend/src/pages/public/index.ts
@@ -0,0 +1 @@
+import "./org";
diff --git a/frontend/src/pages/org/profile.ts b/frontend/src/pages/public/org.ts
similarity index 90%
rename from frontend/src/pages/org/profile.ts
rename to frontend/src/pages/public/org.ts
index 7dc9936fb0..372b220cdc 100644
--- a/frontend/src/pages/org/profile.ts
+++ b/frontend/src/pages/public/org.ts
@@ -13,8 +13,8 @@ import type { OrgData, PublicOrgCollections } from "@/types/org";
 import { SortDirection } from "@/types/utils";
 
 @localized()
-@customElement("btrix-org-profile")
-export class OrgProfile extends BtrixElement {
+@customElement("btrix-public-org")
+export class PublicOrg extends BtrixElement {
   @property({ type: String })
   orgSlug?: string;
 
@@ -91,11 +91,13 @@ export class OrgProfile extends BtrixElement {
           <sl-alert variant="primary" open>
             <sl-icon slot="icon" name="eye-fill"></sl-icon>
             <strong class="font-semibold">
-              ${msg("This is a private preview of your org's profile page")}
+              ${msg(
+                "This is a private preview of the public collections gallery",
+              )}
             </strong>
             <p>
               ${msg(
-                "Update your org's profile settings to make this page visible to anyone on the internet.",
+                "Update your org's public collections gallery settings to make this page visible to anyone on the internet.",
               )}
               ${this.appState.isAdmin
                 ? html`
@@ -127,15 +129,24 @@ export class OrgProfile extends BtrixElement {
             : nothing,
           actions: when(
             this.canEditOrg,
-            () =>
-              html`<sl-tooltip content=${msg("Edit org profile")}>
+            () => html`
+              <sl-tooltip content=${msg("Go to Dashboard")}>
+                <sl-icon-button
+                  href="${this.navigate.orgBasePath}/dashboard"
+                  class="size-8 text-base"
+                  name="speedometer"
+                  @click=${this.navigate.link}
+                ></sl-icon-button>
+              </sl-tooltip>
+              <sl-tooltip content=${msg("Change Org Settings")}>
                 <sl-icon-button
                   href="${this.navigate.orgBasePath}/settings"
                   class="size-8 text-base"
-                  name="pencil"
+                  name="gear"
                   @click=${this.navigate.link}
                 ></sl-icon-button>
-              </sl-tooltip>`,
+              </sl-tooltip>
+            `,
           ),
           secondary: html`
             ${when(
@@ -188,11 +199,11 @@ export class OrgProfile extends BtrixElement {
         ${when(
           this.canEditOrg,
           () =>
-            html`<sl-tooltip content=${msg("Manage collections")}>
+            html`<sl-tooltip content=${msg("Manage Collections")}>
               <sl-icon-button
                 href=${`${this.navigate.orgBasePath}/collections`}
                 class="size-8 text-base"
-                name="gear"
+                name="collection"
                 @click=${this.navigate.link}
               ></sl-icon-button>
             </sl-tooltip>`,
diff --git a/frontend/src/routes.ts b/frontend/src/routes.ts
index a6b20cde1a..dd38ef8adf 100644
--- a/frontend/src/routes.ts
+++ b/frontend/src/routes.ts
@@ -9,7 +9,7 @@ export enum OrgTab {
 
 export enum RouteNamespace {
   PrivateOrgs = "orgs",
-  PublicOrgs = "profile",
+  PublicOrgs = "explore",
 }
 
 export const ROUTES = {
@@ -35,7 +35,7 @@ export const ROUTES = {
     `(/${OrgTab.Settings}(/:settingsTab))`,
   ].join(""),
   publicOrgs: `/${RouteNamespace.PublicOrgs}(/)`,
-  publicOrgProfile: `/${RouteNamespace.PublicOrgs}/:slug(/)`,
+  publicOrg: `/${RouteNamespace.PublicOrgs}/:slug(/)`,
   publicCollection: `/${RouteNamespace.PublicOrgs}/:slug/collections/:collectionSlug(/:collectionTab)`,
   users: "/users",
   usersInvite: "/users/invite",
diff --git a/frontend/src/strings/collections/alerts.ts b/frontend/src/strings/collections/alerts.ts
new file mode 100644
index 0000000000..ba9301b753
--- /dev/null
+++ b/frontend/src/strings/collections/alerts.ts
@@ -0,0 +1,7 @@
+import { msg } from "@lit/localize";
+
+export const alerts = {
+  orgNotPublicWarning: msg(
+    "This doesn't have a public collections gallery enabled yet. To make this collection and basic org information public, update the org's gallery visibility setting.",
+  ),
+};
diff --git a/frontend/src/strings/orgs/alerts.ts b/frontend/src/strings/orgs/alerts.ts
new file mode 100644
index 0000000000..a5753130e1
--- /dev/null
+++ b/frontend/src/strings/orgs/alerts.ts
@@ -0,0 +1,6 @@
+import { msg } from "@lit/localize";
+
+export const alerts = {
+  settingsUpdateSuccess: msg("Updated org settings."),
+  settingsUpdateFailure: msg("Sorry, couldn't update org at this time."),
+};