Skip to content

Commit

Permalink
Merge branch 'v3' into feature/add-localize-to-shared
Browse files Browse the repository at this point in the history
  • Loading branch information
christinaroise committed Sep 11, 2024
2 parents dd7d4b1 + 6ca523d commit dd286a3
Show file tree
Hide file tree
Showing 81 changed files with 1,943 additions and 376 deletions.
1 change: 1 addition & 0 deletions .env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NEXT_PUBLIC_URL=http://localhost:3000
1 change: 1 addition & 0 deletions .env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NEXT_PUBLIC_URL=https://$NEXT_PUBLIC_VERCEL_URL
81 changes: 76 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,24 +101,24 @@ This project includes a customized Sanity Studio desk structure to enhance conte

## Managing Content

### Site Settings
### Company Information

The `Site Settings` menu allows you to configure global settings for your site, including brand assets, tracking codes, and default SEO settings.
The `Company Information` menu allows you to configure global settings for your site, including brand assets, tracking codes, and default SEO settings.

#### Social Media Profiles
### Social Media Profiles

- **Adding Social Media Links**: Editors can manage social media links under the `Social Media Profiles` menu. This allows visitors to connect with the website on various social platforms.
- **Supported Platforms**: The 9 supported platforms include Facebook, Instagram, and LinkedIn, but more can be added to `SoMePlatforms` if needed.

#### Navigation Management
### Navigation Management

- **Setting the Landing Page**: The `Navigation Manager` allows editors to set the landing page for the site, which is crucial for determining the primary page visitors see upon arrival.
- **Adding Menu Items**: Within the `Navigation Manager`, editors can add items to various pre-defined menus:
- **Main Menu**: Add links and a single Call to Action (if needed) to the main menu, which appears at the top of the website. This helps visitors navigate to important sections.
- **Footer Menu**: Add items to the footer menu, which consists of different sections. Each section can contain either social media links, custom links, text, or images (e.g., logos).
- **Sidebar Menu**: Add links to the sidebar menu, which will appear on smaller screens to aid mobile navigation.

#### Pages
### Pages

- **Creating Pages**: Content editors can create and manage pages under the `Pages` menu in the Sanity Studio.
- **Adding Sections**: Each page can be customized with structured content that includes various predefined sections such as hero, article, testimonials, features, callToAction, grid, and callout.
Expand Down Expand Up @@ -181,6 +181,77 @@ export default MyCustomComponent;

By using fetchWithToken, you ensure that all data fetching happens securely, with the server-side API route handling the sensitive token.

### OpenGraph image customization

As part of providing the basic metadata for the [OpenGraph Protocol](https://ogp.me), a fallback image is generated if no other is specified. Fonts and background can be customized as shown below.

#### Custom fonts

The following font utils file can be defined:

> fonts must be placed in `/public/fonts`
```tsx
import { readFile } from "fs/promises";
import { join } from "path";

type Weight = 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
type FontStyle = "normal" | "italic";
interface FontOptions {
data: Buffer | ArrayBuffer;
name: string;
weight?: Weight;
style?: FontStyle;
lang?: string;
}

function readFont(filename: string) {
return readFile(join(process.cwd(), "public/fonts", filename));
}

export async function getFonts(): Promise<FontOptions[]> {
return [
{
data: await readFont("graphik_regular.woff"),
name: "Graphik",
weight: 400,
style: "normal",
},
{
data: await readFont("graphik_medium.woff"),
name: "Graphik",
weight: 600,
style: "normal",
},
{
data: await readFont("recoleta.ttf"),
name: "Recoleta",
weight: 600,
style: "normal",
},
];
}
```

followed by a modification of the image route response:

```tsx
(<OpenGraphImage title={title} description={description ?? undefined} />),
{
width: 1200,
height: 630,
fonts: await getFonts(), // add this line
};
```

#### Custom background

Simply use the CSS background property on the root element with a base64-encoded data url

```css
background: url("data:image/png;base64,...");
```

### Troubleshooting

- Sanity Preview: While the Sanity preview functionality is not fully optimized, it currently meets the essential requirements.
Expand Down
4 changes: 4 additions & 0 deletions public/arrow-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/sharedStudioIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/studioIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions sanity.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* This configuration is used to for the Sanity Studio that’s mounted on the routes:
* - `/app/studio/[[...index]]/page.tsx`
* - `/app/studioShared/[[...index]]/page.tsx`
*/

import { defineConfig } from "sanity";
import sharedStudioConfig from "./studioShared/studioConfig";
import studioConfig from "./studio/studioConfig";

export default defineConfig([studioConfig, sharedStudioConfig]);
106 changes: 56 additions & 50 deletions src/app/(main)/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import { Metadata } from "next";
import { redirect } from "next/navigation";
import { Blog } from "src/blog/Blog";
import BlogPreview from "src/blog/BlogPreview";
import SalaryAndBenefits from "src/salaryAndBenefits/SalaryAndBenefits";
import Compensations from "src/compensations/Compensations";
import { getDraftModeInfo } from "src/utils/draftmode";
import SectionRenderer from "src/utils/renderSection";
import { fetchSeoData, generateMetadataFromSeo } from "src/utils/seo";
import { BlogPage, PageBuilder, Post } from "studio/lib/payloads/pages";
import { SalaryAndBenefitsPage } from "studio/lib/payloads/salaryAndBenefits";
import { CompensationsPage } from "studio/lib/payloads/compensations";
import {
BLOG_PAGE_QUERY,
POSTS_QUERY,
SALARY_AND_BENEFITS_PAGE_QUERY,
COMPENSATIONS_PAGE_QUERY,
SEO_SLUG_QUERY,
SLUG_QUERY,
} from "studio/lib/queries/pages";
import { loadQuery } from "studio/lib/store";
import SalaryAndBenefitsPreview from "src/salaryAndBenefits/SalaryAndBenefitsPreview";
import CompensationsPreview from "src/compensations/CompensationsPreview";
import { homeLink } from "../../../blog/components/utils/linkTypes";
import CustomErrorMessage from "../../../blog/components/customErrorMessage/CustomErrorMessage";
import { CompanyLocation } from "studio/lib/payloads/companyDetails";
import { COMPANY_LOCATIONS_QUERY } from "studio/lib/queries/companyDetails";

export const dynamic = "force-dynamic";

Expand All @@ -32,42 +35,60 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
return generateMetadataFromSeo(seo);
}

const Page404 = (
<CustomErrorMessage
title="404 — Something went wrong"
body="The page you are looking for does not exist. There may be an error in the URL, or the page may have been moved or deleted."
link={homeLink}
/>
);

async function Page({ params }: Props) {
const { slug } = params;
const { perspective, isDraftMode } = getDraftModeInfo();

const [initialPage, initialBlogPage, initialSalaryAndBenefitsPage] =
await Promise.all([
loadQuery<PageBuilder>(SLUG_QUERY, { slug }, { perspective }),
loadQuery<BlogPage>(BLOG_PAGE_QUERY, { slug }, { perspective }),
loadQuery<SalaryAndBenefitsPage>(
SALARY_AND_BENEFITS_PAGE_QUERY,
{ slug },
{ perspective },
),
]);
const [
initialPage,
initialBlogPage,
initialCompensationsPage,
initialLocationsData,
] = await Promise.all([
loadQuery<PageBuilder>(SLUG_QUERY, { slug }, { perspective }),
loadQuery<BlogPage>(BLOG_PAGE_QUERY, { slug }, { perspective }),
loadQuery<CompensationsPage>(
COMPENSATIONS_PAGE_QUERY,
{ slug },
{ perspective },
),
loadQuery<CompanyLocation[]>(COMPANY_LOCATIONS_QUERY, {}, { perspective }),
]);

if (
!initialPage.data &&
!initialBlogPage.data &&
!initialSalaryAndBenefitsPage.data
) {
console.log(`Page ${slug} not found`);
// TODO: add error snackbar
redirect("/");
if (initialPage.data) {
return (
<>
{initialPage.data?.sections?.map((section, index) => (
<SectionRenderer
key={section._key}
section={section}
isDraftMode={isDraftMode}
initialData={initialPage}
isLandingPage={false}
sectionIndex={index}
/>
))}
</>
);
}

// TODO: fix error for when initialBlogPage.data is empty (say slug doesn't exists)
if (!initialPage.data && initialBlogPage.data) {
if (initialBlogPage.data) {
const initialPosts = await loadQuery<Post[]>(
POSTS_QUERY,
{ slug },
{ perspective },
);

if (!initialPosts) {
console.log(`Posts for page: ${slug} not found`);
// TODO: ADD ERROR PAGE
return Page404;
}

return isDraftMode ? (
Expand All @@ -85,36 +106,21 @@ async function Page({ params }: Props) {
);
}

if (initialBlogPage.data && !initialBlogPage.data) {
return (
<>
{initialPage.data?.sections?.map((section, index) => (
<SectionRenderer
key={section._key}
section={section}
isDraftMode={isDraftMode}
initialData={initialPage}
isLandingPage={false}
sectionIndex={index}
/>
))}
</>
);
}

if (initialSalaryAndBenefitsPage.data) {
if (initialCompensationsPage.data && initialLocationsData.data) {
return isDraftMode ? (
<SalaryAndBenefitsPreview
initialSalaryAndBenefits={initialSalaryAndBenefitsPage}
<CompensationsPreview
initialCompensations={initialCompensationsPage}
initialLocations={initialLocationsData}
/>
) : (
<SalaryAndBenefits
salaryAndBenefits={initialSalaryAndBenefitsPage.data}
<Compensations
compensations={initialCompensationsPage.data}
locations={initialLocationsData.data}
/>
);
}

return null;
return Page404;
}

export default Page;
20 changes: 10 additions & 10 deletions src/app/(main)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Footer from "src/components/navigation/footer/Footer";
import { NAV_QUERY } from "studio/lib/queries/navigation";
import { SITESETTINGS_QUERY } from "studio/lib/queries/siteSettings";
import { COMPANY_INFO_QUERY } from "studio/lib/queries/companyDetails";
import { Header } from "src/components/navigation/header/Header";
import { Navigation } from "studio/lib/payloads/navigation";
import { SiteSettings } from "studio/lib/payloads/siteSettings";
import { CompanyInfo } from "studio/lib/payloads/companyDetails";
import { loadQuery } from "studio/lib/store";
import HeaderPreview from "src/components/navigation/header/HeaderPreview";
import FooterPreview from "src/components/navigation/footer/FooterPreview";
Expand All @@ -24,22 +24,22 @@ export default async function Layout({
}>) {
const { perspective, isDraftMode } = getDraftModeInfo();

const [initialNav, initialSiteSettings, initialSoMe, initialLegal] =
const [initialNav, initialCompanyInfo, initialSoMe, initialLegal] =
await Promise.all([
loadQuery<Navigation>(NAV_QUERY, {}, { perspective }),
loadQuery<SiteSettings>(SITESETTINGS_QUERY, {}, { perspective }),
loadQuery<CompanyInfo>(COMPANY_INFO_QUERY, {}, { perspective }),
loadQuery<SocialMediaProfiles>(SOMEPROFILES_QUERY, {}, { perspective }),
loadQuery<LegalDocument[]>(LEGAL_DOCUMENTS_QUERY, {}, { perspective }),
]);

const hasNavData = hasValidData(initialNav.data);
const hasSiteSettingsData = hasValidData(initialSiteSettings.data);
const hasCompanyInfoData = hasValidData(initialCompanyInfo.data);

const hasHeaderData =
hasNavData && (initialNav.data.main || initialNav.data.sidebar);

const hasFooterData = hasNavData && initialNav.data.footer;
const hasMenuData = hasSiteSettingsData && (hasHeaderData || hasFooterData);
const hasMenuData = hasCompanyInfoData && (hasHeaderData || hasFooterData);

if (!hasMenuData) {
return (
Expand All @@ -55,12 +55,12 @@ export default async function Layout({
{hasHeaderData && isDraftMode ? (
<HeaderPreview
initialNav={initialNav}
initialSiteSetting={initialSiteSettings}
initialCompanyInfo={initialCompanyInfo}
/>
) : (
<Header
data={initialNav.data}
assets={initialSiteSettings.data?.brandAssets}
assets={initialCompanyInfo.data?.brandAssets}
/>
)}
<main id="main" tabIndex={-1}>
Expand All @@ -69,14 +69,14 @@ export default async function Layout({
{hasFooterData && isDraftMode ? (
<FooterPreview
initialNav={initialNav}
initialSiteSetting={initialSiteSettings}
initialCompanyInfo={initialCompanyInfo}
initialSoMe={initialSoMe}
/>
) : (
<Footer
navigationData={initialNav.data}
legalData={initialLegal.data}
siteSettings={initialSiteSettings.data}
companyInfo={initialCompanyInfo.data}
soMeData={initialSoMe.data}
/>
)}
Expand Down
Loading

0 comments on commit dd286a3

Please sign in to comment.