Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import code, {
ImageOptions,
PageMetadata,
StructuredDataOptions,
BrandingOptions,
} from "./code";
import "./styles.css";

Expand Down Expand Up @@ -141,6 +142,11 @@ export default function App() {
organizationName: "",
logoUrl: "",
});
const [branding, setBranding] = useState<BrandingOptions>({
siteName: "",
brandReplacement: "",
twitterHandle: "",
});
const [slugMetadataExpanded, setSlugMetadataExpanded] = useState<
Record<number, boolean>
>({});
Expand Down Expand Up @@ -231,6 +237,17 @@ export default function App() {
setCopied(false);
}

function handleBrandingChange(
field: keyof BrandingOptions,
value: string,
): void {
setBranding({
...branding,
[field]: value,
});
setCopied(false);
}

function toggleSlugMetadata(index: number): void {
setSlugMetadataExpanded({
...slugMetadataExpanded,
Expand Down Expand Up @@ -292,6 +309,7 @@ export default function App() {
optionImage,
pageMetadata,
structuredData,
branding,
};

const script = noError ? code(codeData) : undefined;
Expand Down Expand Up @@ -711,6 +729,55 @@ export default function App() {
size="small"
/>

<Box sx={{ mt: 3, pt: 2, borderTop: 1, borderColor: "grey.300" }}>
<Typography
variant="subtitle2"
color="text.secondary"
gutterBottom
>
Branding & Social
</Typography>
<TextField
fullWidth
label="Site Name"
margin="dense"
placeholder="My Awesome Site"
helperText="Used for og:site_name meta tag"
onChange={(e) =>
handleBrandingChange("siteName", e.target.value)
}
value={branding.siteName}
variant="outlined"
size="small"
/>
<TextField
fullWidth
label="Brand Replacement"
margin="dense"
placeholder="My Brand"
helperText="Replaces 'Notion' text in meta tags (optional)"
onChange={(e) =>
handleBrandingChange("brandReplacement", e.target.value)
}
value={branding.brandReplacement}
variant="outlined"
size="small"
/>
<TextField
fullWidth
label="Twitter/X Handle"
margin="dense"
placeholder="@username"
helperText="For twitter:site and twitter:creator meta tags"
onChange={(e) =>
handleBrandingChange("twitterHandle", e.target.value)
}
value={branding.twitterHandle}
variant="outlined"
size="small"
/>
</Box>

<Box sx={{ mt: 3, pt: 2, borderTop: 1, borderColor: "grey.300" }}>
<Stack
direction="row"
Expand Down
36 changes: 34 additions & 2 deletions src/code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ export interface StructuredDataOptions {
logoUrl?: string;
}

export interface BrandingOptions {
siteName?: string;
brandReplacement?: string;
twitterHandle?: string;
}

export interface CodeData {
myDomain: string;
notionUrl: string;
Expand All @@ -35,6 +41,7 @@ export interface CodeData {
optionImage: ImageOptions;
pageMetadata: Record<string, PageMetadata>;
structuredData: StructuredDataOptions;
branding: BrandingOptions;
}

function getId(url: string): string {
Expand All @@ -60,6 +67,7 @@ export default function code(data: CodeData): string {
optionImage,
pageMetadata,
structuredData,
branding,
} = data;
let url = myDomain.replace("https://", "").replace("http://", "");
if (url.slice(-1) === "/") url = url.slice(0, url.length - 1);
Expand Down Expand Up @@ -103,6 +111,14 @@ ${slugs
const ORGANIZATION_NAME = '${structuredData?.organizationName || ""}';
const LOGO_URL = '${structuredData?.logoUrl || ""}';

/*
* Step 3.3: branding configuration (optional)
* Replace Notion branding with your own and add social media handles
*/
const SITE_NAME = '${branding?.siteName || ""}';
const BRAND_REPLACEMENT = '${branding?.brandReplacement || ""}';
const TWITTER_HANDLE = '${branding?.twitterHandle || ""}';

/* Step 4: enter a Google Font name, you can choose from https://fonts.google.com */
const GOOGLE_FONT = '${googleFont || ""}';

Expand Down Expand Up @@ -355,11 +371,21 @@ ${slugs
return;
}
}
if (MY_DOMAIN !== '') {
if (element.getAttribute('property') === 'og:site_name') {
// Set og:site_name - use SITE_NAME if configured, otherwise MY_DOMAIN (Issue #18)
if (element.getAttribute('property') === 'og:site_name') {
if (SITE_NAME !== '') {
element.setAttribute('content', SITE_NAME);
} else if (MY_DOMAIN !== '') {
element.setAttribute('content', MY_DOMAIN);
}
}
// Replace 'Notion' branding in meta content (Issue #18)
if (BRAND_REPLACEMENT !== '') {
const content = element.getAttribute('content');
if (content && content.includes('Notion')) {
element.setAttribute('content', content.replace(/Notion/g, BRAND_REPLACEMENT));
}
}
if (pageTitle !== '') {
if (element.getAttribute('property') === 'og:title'
|| element.getAttribute('name') === 'twitter:title') {
Expand Down Expand Up @@ -405,6 +431,12 @@ ${slugs
element.append(\`<link rel="canonical" href="\${canonicalUrl}">\`, { html: true });
element.append(\`<meta name="robots" content="index, follow">\`, { html: true });

// Add Twitter/X meta tags for social cards (Issue #19)
if (TWITTER_HANDLE !== '') {
element.append(\`<meta name="twitter:site" content="\${TWITTER_HANDLE}">\`, { html: true });
element.append(\`<meta name="twitter:creator" content="\${TWITTER_HANDLE}">\`, { html: true });
}

// Add JSON-LD structured data for rich search results (Issue #10)
if (STRUCTURED_DATA_ENABLED) {
const pageTitle = this.metadata.title || PAGE_TITLE;
Expand Down
Loading