Files
v10/site/astro.config.mjs
T

163 lines
5.4 KiB
JavaScript

// @ts-check
import process from 'node:process';
import mdx from '@astrojs/mdx';
import netlify from '@astrojs/netlify';
import react from '@astrojs/react';
import sitemap from '@astrojs/sitemap';
import sentry from '@sentry/astro';
import tailwindcss from '@tailwindcss/vite';
import { defineConfig, envField, fontProviders } from 'astro/config';
import svgr from 'vite-plugin-svgr';
import llmsMarkdown from './integrations/llms-markdown';
import rehypePrepareCodeBlocks from './src/utils/rehypePrepareCodeBlocks';
import remarkConditionalHeadings from './src/utils/remarkConditionalHeadings';
import { remarkReadingTime } from './src/utils/remarkReadingTime.mjs';
import { shikiNotationTransformers } from './src/utils/shikiNotationTransformers';
import shikiTransformMetadata from './src/utils/shikiTransformMetadata';
// Netlify sets CONTEXT and BRANCH for each deploy. We use them to determine
// the correct site URL:
// - production (site/v10 branch) → https://videojs.org
// - branch-deploy (main branch) → https://next.videojs.org
// - deploy-preview (PR branches) → DEPLOY_PRIME_URL (Netlify subdomain)
//
// For URLs that must always point to production regardless of deploy context
// (e.g. canonical, JSON-LD), use PRODUCTION_URL from src/consts.ts instead.
const SITE_URL =
process.env.CONTEXT === 'production'
? 'https://videojs.org'
: process.env.BRANCH === 'main'
? 'https://next.videojs.org'
: process.env.DEPLOY_PRIME_URL || 'https://videojs.org';
// https://astro.build/config
export default defineConfig({
site: SITE_URL,
trailingSlash: 'never',
adapter: netlify({
devFeatures: { images: false, environmentVariables: true },
}),
// Server-only secrets read at runtime (not inlined at build time).
// All optional — the site degrades gracefully without auth/Mux configured.
// See site/CLAUDE.md "Environment Variables" for full documentation.
env: {
schema: {
// OAuth — powers the video uploader login flow
OAUTH_CLIENT_ID: envField.string({ context: 'server', access: 'secret', optional: true }),
OAUTH_CLIENT_SECRET: envField.string({ context: 'server', access: 'secret', optional: true }),
OAUTH_REDIRECT_URI: envField.string({ context: 'server', access: 'secret', optional: true }),
OAUTH_URL: envField.string({ context: 'server', access: 'secret', optional: true }),
SESSION_COOKIE_PASSWORD: envField.string({ context: 'server', access: 'secret', optional: true }),
MUX_API_URL: envField.string({
context: 'server',
access: 'secret',
optional: true,
default: 'https://api.mux.com',
}),
// Mux service account credentials — only used by the /api/health/mux endpoint
MUX_TOKEN_ID: envField.string({ context: 'server', access: 'secret', optional: true }),
MUX_TOKEN_SECRET: envField.string({ context: 'server', access: 'secret', optional: true }),
},
},
redirects: {
// Redirects are configured in netlify.toml
},
integrations: [
sentry({
project: 'videojsorg',
org: 'mux',
authToken: process.env.SENTRY_AUTH_TOKEN,
}),
mdx({ extendMarkdownConfig: true }),
sitemap({
// llms-markdown.ts auto-generates per-framework sub-indexes, but sitemap
// entries are hardcoded here. Add a new line when adding a framework.
customPages: [
`${SITE_URL}/llms.txt`,
`${SITE_URL}/blog/llms.txt`,
`${SITE_URL}/docs/framework/html/llms.txt`,
`${SITE_URL}/docs/framework/react/llms.txt`,
],
}),
llmsMarkdown(),
react({
babel: {
plugins: [['babel-plugin-react-compiler', { target: '19' }]],
},
}),
],
prefetch: {
prefetchAll: true,
},
markdown: {
// a lot of these are defaults but I'm setting them just to be explicit
smartypants: true,
gfm: true,
syntaxHighlight: 'shiki',
shikiConfig: {
themes: {
light: 'gruvbox-dark-hard',
dark: 'gruvbox-dark-soft',
},
transformers: [shikiTransformMetadata, ...shikiNotationTransformers],
},
remarkPlugins: [remarkConditionalHeadings, remarkReadingTime],
rehypePlugins: [rehypePrepareCodeBlocks],
},
image: {
domains: ['image.mux.com'],
remotePatterns: [
{
protocol: 'https',
hostname: '66.media.tumblr.com',
pathname: '/tumblr_mdgad5rr0S1qzc111.png',
},
],
},
vite: {
// SVG → React component transform. We use SVGR instead of Astro's
// experimental svg feature because: (1) React islands need React
// components, and (2) SVGR runs SVGO for automatic SVG optimization.
plugins: [tailwindcss(), svgr()],
optimizeDeps: {
exclude: ['@videojs/react', '@videojs/html'],
},
resolve: {
dedupe: ['react', 'react-dom'],
alias: {
'@': new URL('./src', import.meta.url).pathname,
},
},
},
fonts: [
{
provider: fontProviders.google(),
name: 'Instrument Sans',
cssVariable: '--font-instrument-sans',
weights: ['400 600'],
styles: ['normal', 'italic'],
subsets: ['latin'],
fallbacks: ['sans-serif'],
optimizedFallbacks: true,
display: 'swap',
},
{
provider: fontProviders.google(),
name: 'IBM Plex Mono',
cssVariable: '--font-ibm-plex-mono',
weights: ['600', '400'],
styles: ['normal'],
subsets: ['latin'],
fallbacks: ['monospace'],
optimizedFallbacks: true,
display: 'swap',
},
],
});