Conditionally add build identifier to <head />

This commit is contained in:
Sam Becker 2025-11-08 15:22:33 -06:00
parent 02f2d08e04
commit 667328b166
6 changed files with 48 additions and 4 deletions

View File

@ -203,6 +203,11 @@ Create Upstash Redis store from storage tab of Vercel dashboard and link to your
- urls must begin with 'https' - urls must begin with 'https'
- ⚠️ this will invoke arbitrary script execution on every page—use with caution - ⚠️ this will invoke arbitrary script execution on every page—use with caution
### Debugging
- `DISABLE_DEBUG_OUTPUTS = 1`
- removes build identifier in `<head />`
- disables `/admin/configuration/export.json`
## Alternate storage providers ## Alternate storage providers
Only one storage adapter—Vercel Blob, Cloudflare R2, AWS S3, or MinIO—can be used at a time. Ideally, this is configured before photos are uploaded (see [Issue #34](https://github.com/sambecker/exif-photo-blog/issues/34) for migration considerations). If you have multiple adapters, you can set one as preferred by storing `aws-s3`, `cloudflare-r2`, `minio`, or `vercel-blob` in `NEXT_PUBLIC_STORAGE_PREFERENCE`. See [FAQ](#will-there-be-support-for-image-storage-providers-beyond-vercel-aws-and-cloudflare) regarding unsupported providers. Only one storage adapter—Vercel Blob, Cloudflare R2, AWS S3, or MinIO—can be used at a time. Ideally, this is configured before photos are uploaded (see [Issue #34](https://github.com/sambecker/exif-photo-blog/issues/34) for migration considerations). If you have multiple adapters, you can set one as preferred by storing `aws-s3`, `cloudflare-r2`, `minio`, or `vercel-blob` in `NEXT_PUBLIC_STORAGE_PREFERENCE`. See [FAQ](#will-there-be-support-for-image-storage-providers-beyond-vercel-aws-and-cloudflare) regarding unsupported providers.

View File

@ -1,5 +1,7 @@
import { APP_CONFIGURATION } from '@/app/config'; import { APP_CONFIGURATION, DEBUG_OUTPUTS_ENABLED } from '@/app/config';
export async function GET() { export async function GET() {
return Response.json(APP_CONFIGURATION); return DEBUG_OUTPUTS_ENABLED
? Response.json(APP_CONFIGURATION)
: new Response('Debugging disabled', { status: 404 });
}; };

View File

@ -11,6 +11,8 @@ import {
SITE_FEEDS_ENABLED, SITE_FEEDS_ENABLED,
ADMIN_DEBUG_TOOLS_ENABLED, ADMIN_DEBUG_TOOLS_ENABLED,
PAGE_SCRIPT_URLS, PAGE_SCRIPT_URLS,
VERCEL_GIT_COMMIT_SHA_SHORT,
DEBUG_OUTPUTS_ENABLED,
} from '@/app/config'; } from '@/app/config';
import AppStateProvider from '@/app/AppStateProvider'; import AppStateProvider from '@/app/AppStateProvider';
import ToasterWithThemes from '@/toast/ToasterWithThemes'; import ToasterWithThemes from '@/toast/ToasterWithThemes';
@ -70,6 +72,11 @@ export const metadata: Metadata = {
type: 'image/png', type: 'image/png',
sizes: '180x180', sizes: '180x180',
}], }],
...DEBUG_OUTPUTS_ENABLED && {
other: {
'build': VERCEL_GIT_COMMIT_SHA_SHORT ?? 'unknown',
},
},
...SITE_FEEDS_ENABLED && { ...SITE_FEEDS_ENABLED && {
alternates: { alternates: {
types: { types: {

View File

@ -133,6 +133,8 @@ export default function AdminAppConfigurationClient({
// Scripts & Analytics // Scripts & Analytics
hasPageScriptUrls, hasPageScriptUrls,
pageScriptUrls, pageScriptUrls,
// Debugging
isDebuggingEnabled,
// Internal // Internal
areInternalToolsEnabled, areInternalToolsEnabled,
areAdminDebugToolsEnabled, areAdminDebugToolsEnabled,
@ -972,6 +974,18 @@ export default function AdminAppConfigurationClient({
{renderEnvVars(['PAGE_SCRIPT_URLS'])} {renderEnvVars(['PAGE_SCRIPT_URLS'])}
</ChecklistRow> </ChecklistRow>
</>; </>;
case 'Debugging':
return <>
<ChecklistRow
title="Debug outputs"
status={isDebuggingEnabled}
optional
>
Set environment variable to {'"1"'} to disable build identifier
and admin configuration export:
{renderEnvVars(['DISABLE_DEBUG_OUTPUTS'])}
</ChecklistRow>
</>;
case 'Internal': case 'Internal':
return <> return <>
<ChecklistRow <ChecklistRow

View File

@ -3,7 +3,7 @@ import { BiData, BiGlobe, BiHide, BiLockAlt, BiPencil } from 'react-icons/bi';
import { CgDebug } from 'react-icons/cg'; import { CgDebug } from 'react-icons/cg';
import { FaRegFolderClosed } from 'react-icons/fa6'; import { FaRegFolderClosed } from 'react-icons/fa6';
import { HiOutlineCog, HiSparkles } from 'react-icons/hi'; import { HiOutlineCog, HiSparkles } from 'react-icons/hi';
import { IoMdGrid } from 'react-icons/io'; import { IoMdGrid, IoMdPower } from 'react-icons/io';
import { PiPaintBrushHousehold } from 'react-icons/pi'; import { PiPaintBrushHousehold } from 'react-icons/pi';
import { RiSpeedMiniLine } from 'react-icons/ri'; import { RiSpeedMiniLine } from 'react-icons/ri';
import { TbBrandGoogleAnalytics } from 'react-icons/tb'; import { TbBrandGoogleAnalytics } from 'react-icons/tb';
@ -68,10 +68,20 @@ const ADMIN_CONFIG_SECTIONS = [{
title: 'Scripts & Analytics', title: 'Scripts & Analytics',
required: false, required: false,
icon: <TbBrandGoogleAnalytics size={18} className="translate-y-[1px]" />, icon: <TbBrandGoogleAnalytics size={18} className="translate-y-[1px]" />,
}, {
title: 'Debugging',
required: false,
icon: <CgDebug
size={18}
className="translate-x-[-2px] translate-y-[0.5px]"
/>,
}, { }, {
title: 'Internal', title: 'Internal',
required: false, required: false,
icon: <CgDebug size={18} className="translate-y-[1px]" />, icon: <IoMdPower
size={16}
className="translate-x-[-1px] translate-y-[1px]"
/>,
}] as const satisfies AdminConfigSection[]; }] as const satisfies AdminConfigSection[];
export type ConfigSectionKey = typeof ADMIN_CONFIG_SECTIONS[number]['title']; export type ConfigSectionKey = typeof ADMIN_CONFIG_SECTIONS[number]['title'];

View File

@ -386,6 +386,10 @@ export const PAGE_SCRIPT_URLS = process.env.PAGE_SCRIPT_URLS
.filter(url => url.startsWith('https://')) .filter(url => url.startsWith('https://'))
: []; : [];
// DEBUGGING
export const DEBUG_OUTPUTS_ENABLED = process.env.DISABLE_DEBUG_OUTPUTS !== '1';
// INTERNAL // INTERNAL
export const ADMIN_DEBUG_TOOLS_ENABLED = process.env.ADMIN_DEBUG_TOOLS === '1'; export const ADMIN_DEBUG_TOOLS_ENABLED = process.env.ADMIN_DEBUG_TOOLS === '1';
@ -510,6 +514,8 @@ export const APP_CONFIGURATION = {
// Scripts & Analytics // Scripts & Analytics
hasPageScriptUrls: PAGE_SCRIPT_URLS.length > 0, hasPageScriptUrls: PAGE_SCRIPT_URLS.length > 0,
pageScriptUrls: PAGE_SCRIPT_URLS, pageScriptUrls: PAGE_SCRIPT_URLS,
// Debugging
isDebuggingEnabled: DEBUG_OUTPUTS_ENABLED,
// Internal // Internal
areInternalToolsEnabled: ( areInternalToolsEnabled: (
ADMIN_DEBUG_TOOLS_ENABLED || ADMIN_DEBUG_TOOLS_ENABLED ||