unblock cms draft mode (#38409)
* remove port from cms start script * address cors * 30s revalidation on blog index * fix types * remove duplicate cache strategy * disable graphql * fix cms build * fix ProductDropdown crash * fix env var turbo
This commit is contained in:
committed by
GitHub
parent
10cc742349
commit
b4922199cd
@@ -47,10 +47,6 @@ const nextConfig = {
|
||||
// We are already running linting via GH action, this will skip linting during production build on Vercel
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
experimental: {
|
||||
// Ensure compatibility with Turbopack and Sharp
|
||||
serverComponentsExternalPackages: ['sharp'],
|
||||
},
|
||||
// Configure Sharp as an external package for server-side rendering
|
||||
serverExternalPackages: ['sharp'],
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"lint": "cross-env NODE_OPTIONS=--no-deprecation next lint",
|
||||
"migrate": "cross-env NODE_OPTIONS=--no-deprecation tsx scripts/migrate.ts",
|
||||
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
|
||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start --port 3030",
|
||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start",
|
||||
"vercel-build": "pnpm migrate && pnpm build",
|
||||
"typecheck_IGNORED": "tsc --noEmit"
|
||||
},
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import config from '@payload-config'
|
||||
import '@payloadcms/next/css'
|
||||
import { GRAPHQL_PLAYGROUND_GET } from '@payloadcms/next/routes'
|
||||
|
||||
export const GET = GRAPHQL_PLAYGROUND_GET(config)
|
||||
@@ -1,8 +0,0 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import config from '@payload-config'
|
||||
import { GRAPHQL_POST, REST_OPTIONS } from '@payloadcms/next/routes'
|
||||
|
||||
export const POST = GRAPHQL_POST(config)
|
||||
|
||||
export const OPTIONS = REST_OPTIONS(config)
|
||||
@@ -102,7 +102,7 @@ export default buildConfig({
|
||||
// Global configuration for better performance
|
||||
globals: [],
|
||||
graphQL: {
|
||||
disable: process.env.NODE_ENV !== 'development', // Disable GraphQL in production for better performance
|
||||
disable: true,
|
||||
},
|
||||
// Reduce payload init overhead
|
||||
telemetry: false,
|
||||
|
||||
@@ -6,6 +6,12 @@ import { generateReadingTime } from '~/lib/helpers'
|
||||
// Lightweight runtime for better performance
|
||||
export const runtime = 'edge'
|
||||
|
||||
// CORS headers for cross-origin requests
|
||||
const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
|
||||
}
|
||||
|
||||
// Lightweight TOC generation for edge runtime
|
||||
type TocItem = { content: string; slug: string; lvl: number }
|
||||
|
||||
@@ -115,6 +121,14 @@ function convertRichTextToMarkdown(content: any): string {
|
||||
.join('\n\n')
|
||||
}
|
||||
|
||||
// Handle preflight requests
|
||||
export async function OPTIONS() {
|
||||
return new Response(null, {
|
||||
status: 200,
|
||||
headers: corsHeaders,
|
||||
})
|
||||
}
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(request.url)
|
||||
@@ -212,12 +226,15 @@ export async function GET(request: NextRequest) {
|
||||
_status: latestVersion._status,
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
post: processedPost,
|
||||
mode,
|
||||
isDraft: shouldFetchDraft,
|
||||
})
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
post: processedPost,
|
||||
mode,
|
||||
isDraft: shouldFetchDraft,
|
||||
},
|
||||
{ headers: corsHeaders }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -289,12 +306,15 @@ export async function GET(request: NextRequest) {
|
||||
_status: post._status,
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
post: processedPost,
|
||||
mode,
|
||||
isDraft: shouldFetchDraft,
|
||||
})
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
post: processedPost,
|
||||
mode,
|
||||
isDraft: shouldFetchDraft,
|
||||
},
|
||||
{ headers: corsHeaders }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,12 +384,15 @@ export async function GET(request: NextRequest) {
|
||||
_status: post._status,
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
post: processedPost,
|
||||
mode,
|
||||
isDraft: shouldFetchDraft,
|
||||
})
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
post: processedPost,
|
||||
mode,
|
||||
isDraft: shouldFetchDraft,
|
||||
},
|
||||
{ headers: corsHeaders }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -452,16 +475,21 @@ export async function GET(request: NextRequest) {
|
||||
toc_depth: post.toc_depth || 3,
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
post: processedPost,
|
||||
mode,
|
||||
source: 'versions-api',
|
||||
})
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
post: processedPost,
|
||||
mode,
|
||||
source: 'versions-api',
|
||||
},
|
||||
{ headers: corsHeaders }
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log('[cms-posts] Versions API failed, response:', await versionsResponse.text())
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.log('[cms-posts] Versions API failed, response:', await versionsResponse.text())
|
||||
}
|
||||
}
|
||||
|
||||
// Strategy 2: If versions API didn't work, try finding the parent post first, then get its latest published version
|
||||
@@ -556,12 +584,15 @@ export async function GET(request: NextRequest) {
|
||||
richContent: mode === 'full' ? post.content : undefined,
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
post: processedPost,
|
||||
mode,
|
||||
source: 'versions-by-parent-api',
|
||||
})
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
post: processedPost,
|
||||
mode,
|
||||
source: 'versions-by-parent-api',
|
||||
},
|
||||
{ headers: corsHeaders }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -590,6 +621,12 @@ export async function GET(request: NextRequest) {
|
||||
// For individual post requests, don't cache to ensure fresh data
|
||||
cache: slug ? 'no-store' : 'default',
|
||||
next: slug ? undefined : { revalidate: 300 },
|
||||
// Add SSL configuration for production
|
||||
...(process.env.NODE_ENV === 'production' && {
|
||||
// Allow self-signed certificates in development, but use proper SSL in production
|
||||
// This helps with Vercel's internal networking
|
||||
agent: false,
|
||||
}),
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -600,7 +637,7 @@ export async function GET(request: NextRequest) {
|
||||
error: 'Failed to fetch posts from CMS',
|
||||
status: response.status,
|
||||
},
|
||||
{ status: response.status }
|
||||
{ status: response.status, headers: corsHeaders }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -613,7 +650,7 @@ export async function GET(request: NextRequest) {
|
||||
error: 'CMS returned non-JSON response',
|
||||
contentType,
|
||||
},
|
||||
{ status: 502 }
|
||||
{ status: 502, headers: corsHeaders }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -695,20 +732,26 @@ export async function GET(request: NextRequest) {
|
||||
|
||||
// For single post requests, return the post directly
|
||||
if (slug && posts.length > 0) {
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
post: posts[0],
|
||||
mode,
|
||||
})
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
post: posts[0],
|
||||
mode,
|
||||
},
|
||||
{ headers: corsHeaders }
|
||||
)
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
posts,
|
||||
total: posts.length,
|
||||
mode,
|
||||
cached: true,
|
||||
})
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
posts,
|
||||
total: posts.length,
|
||||
mode,
|
||||
cached: true,
|
||||
},
|
||||
{ headers: corsHeaders }
|
||||
)
|
||||
} catch (error) {
|
||||
console.error('[cms-posts] Error:', error)
|
||||
return NextResponse.json(
|
||||
@@ -717,7 +760,7 @@ export async function GET(request: NextRequest) {
|
||||
error: 'Internal server error',
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
},
|
||||
{ status: 500 }
|
||||
{ status: 500, headers: corsHeaders }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,32 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
// Check for secret to confirm this is a valid request
|
||||
if (req.query.secret !== process.env.CMS_PREVIEW_SECRET) {
|
||||
return res.status(401).json({ message: 'Invalid token' })
|
||||
}
|
||||
|
||||
const { path } = req.query
|
||||
|
||||
if (!path) {
|
||||
return res.status(400).json({ message: 'Missing path parameter' })
|
||||
}
|
||||
import { revalidatePath } from 'next/cache'
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
// This will revalidate the specific page
|
||||
await res.revalidate(String(path))
|
||||
const body = await request.json()
|
||||
const { secret, path } = body
|
||||
|
||||
return res.json({ revalidated: true, path })
|
||||
// Check for secret to confirm this is a valid request
|
||||
if (secret !== process.env.CMS_PREVIEW_SECRET) {
|
||||
return NextResponse.json({ message: 'Invalid token' }, { status: 401 })
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
return NextResponse.json({ message: 'Missing path parameter' }, { status: 400 })
|
||||
}
|
||||
|
||||
// This will revalidate the specific page
|
||||
revalidatePath(path)
|
||||
|
||||
return NextResponse.json({ revalidated: true, path })
|
||||
} catch (error) {
|
||||
console.error('[Revalidate API] Error during revalidation:', error)
|
||||
return res.status(500).json({
|
||||
message: 'Error revalidating',
|
||||
error: error instanceof Error ? error.message : 'Unknown error',
|
||||
})
|
||||
return NextResponse.json(
|
||||
{
|
||||
message: 'Error revalidating',
|
||||
error: error instanceof Error ? error.message : 'Unknown error',
|
||||
},
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ const FONT_URLS = {
|
||||
const LW_TABLE = 'tickets'
|
||||
const LW_MATERIALIZED_VIEW = 'tickets_view'
|
||||
|
||||
export async function GET(req: Request, res: Response) {
|
||||
export async function GET(req: Request) {
|
||||
const url = new URL(req.url)
|
||||
|
||||
// Just here to silence snyk false positives
|
||||
|
||||
@@ -28,7 +28,7 @@ async function getCMSPostFromAPI(
|
||||
const fetchOptions = isDraft
|
||||
? {
|
||||
// For draft mode: always fresh data, no caching
|
||||
cache: 'no-store' as const,
|
||||
// cache: 'no-store' as const,
|
||||
next: { revalidate: 0 },
|
||||
}
|
||||
: {
|
||||
|
||||
@@ -15,6 +15,7 @@ export async function generateStaticParams() {
|
||||
return categories.map((category: string) => ({ category }))
|
||||
}
|
||||
|
||||
export const revalidate = 30
|
||||
export const dynamic = 'force-static'
|
||||
|
||||
export async function generateMetadata({ params }: { params: Params }): Promise<Metadata> {
|
||||
|
||||
@@ -15,6 +15,7 @@ export async function generateStaticParams() {
|
||||
return tags.map((tag: string) => ({ tag }))
|
||||
}
|
||||
|
||||
export const revalidate = 30
|
||||
export const dynamic = 'force-static'
|
||||
|
||||
export async function generateMetadata({ params }: { params: Params }): Promise<Metadata> {
|
||||
|
||||
@@ -14,10 +14,8 @@ import ComparisonsData from 'data/Comparisons'
|
||||
import CustomersData from 'data/CustomerStories'
|
||||
import MainProductsData from 'data/MainProducts'
|
||||
import ProductModulesData from 'data/ProductModules'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export const ProductDropdown = () => {
|
||||
const { basePath } = useRouter()
|
||||
const isTablet = useBreakpoint(1279)
|
||||
|
||||
return (
|
||||
|
||||
@@ -34,8 +34,8 @@ export const SITE_ORIGIN =
|
||||
|
||||
export const CMS_SITE_ORIGIN =
|
||||
process.env.NEXT_PUBLIC_VERCEL_ENV === 'production'
|
||||
? // In production, require env or fall back to localhost to avoid hitting supabase.com
|
||||
'http://localhost:3030'
|
||||
? // In production, use the actual CMS domain
|
||||
process.env.CMS_SITE_ORIGIN || 'https://cms.supabase.com'
|
||||
: process.env.NEXT_PUBLIC_VERCEL_BRANCH_URL &&
|
||||
typeof process.env.NEXT_PUBLIC_VERCEL_BRANCH_URL === 'string'
|
||||
? `https://${process.env.NEXT_PUBLIC_VERCEL_BRANCH_URL.replace('zone-www-dot-com-git-', 'cms-git-')}`
|
||||
|
||||
@@ -288,7 +288,7 @@ export async function getCMSPostBySlug(slug: string, preview = false) {
|
||||
'Content-Type': 'application/json',
|
||||
...(CMS_API_KEY && { Authorization: `Bearer ${CMS_API_KEY}` }),
|
||||
},
|
||||
cache: 'no-store',
|
||||
// cache: 'no-store',
|
||||
next: { revalidate: 0 },
|
||||
})
|
||||
|
||||
@@ -300,7 +300,7 @@ export async function getCMSPostBySlug(slug: string, preview = false) {
|
||||
'Content-Type': 'application/json',
|
||||
...(CMS_API_KEY && { Authorization: `Bearer ${CMS_API_KEY}` }),
|
||||
},
|
||||
cache: 'no-store',
|
||||
// cache: 'no-store',
|
||||
next: { revalidate: 0 },
|
||||
})
|
||||
}
|
||||
@@ -490,8 +490,8 @@ export async function getAllCMSPosts({
|
||||
'Content-Type': 'application/json',
|
||||
...(CMS_API_KEY && { Authorization: `Bearer ${CMS_API_KEY}` }),
|
||||
},
|
||||
cache: 'no-store', // Ensure we always get fresh data
|
||||
next: { revalidate: 0 }, // Disable caching for this fetch
|
||||
// cache: 'no-store', // Ensure we always get fresh data
|
||||
next: { revalidate: 30 }, // Disable caching for this fetch
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { useRouter } from 'next/router'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Accordion, Badge } from 'ui'
|
||||
import { SITE_ORIGIN } from '~/lib/constants'
|
||||
import { WeekDayProps } from './types6'
|
||||
import type { WeekDayProps } from '~/types/launch-week-6'
|
||||
|
||||
import styles from './styles/launchWeek6.module.css'
|
||||
import styleUtils from './styles/utils6.module.css'
|
||||
|
||||
@@ -116,6 +116,7 @@
|
||||
"ANALYZE",
|
||||
"CMS_API_KEY",
|
||||
"CMS_PREVIEW_SECRET",
|
||||
"CMS_SITE_ORIGIN",
|
||||
"NEXT_PUBLIC_MISC_USE_URL",
|
||||
"NEXT_PUBLIC_MISC_USE_ANON_KEY",
|
||||
"NEXT_PUBLIC_STUDIO_URL",
|
||||
|
||||
Reference in New Issue
Block a user