homepage: typography upgrade + ArticleFeed polish
- layout.tsx: load Lora (serif) + Inter (sans) via next/font/google, self-hosted at build time, exposed as --font-serif / --font-sans CSS variables on <html>. No CDN fetch, no FOIT, no GDPR concern. - tailwind.css: --font-heading and --font-body now reference the next/font variables with Georgia / -apple-system fallbacks for the brief window before the self-hosted face is ready. --font-mono upgraded to IBM Plex Mono → ui-monospace → Courier New fallback (DoubleTicker chips already specify IBM Plex Mono directly). - ArticleFeed: drop the FEATURED filter chip (duplicates the Staff Editorial section above), add publish date alongside the byline on every card, lift the homepage feed cap from 200 → 5000. - api/public/posts: lift MAX_LIMIT to 10000 so client-side pagination + infinite-scroll see the full archive.
This commit is contained in:
@@ -3,7 +3,10 @@ import { getLatestImportedArticles } from "@/lib/articles/legacy-source";
|
||||
|
||||
export const revalidate = 300;
|
||||
|
||||
const MAX_LIMIT = 200;
|
||||
// Homepage feed now renders every imported post; pagination + infinite-
|
||||
// scroll happen client-side over the full set. Keep an absolute ceiling
|
||||
// only as a safety valve, not a UX cap.
|
||||
const MAX_LIMIT = 10000;
|
||||
const DEFAULT_LIMIT = 100;
|
||||
|
||||
export async function GET(request: Request) {
|
||||
|
||||
@@ -26,7 +26,7 @@ interface ArticleItem {
|
||||
|
||||
|
||||
|
||||
const ALL_CATEGORIES = ["All", "BROADCAST", "FEATURED", "POST PRODUCTION", "ANIMATION"];
|
||||
const ALL_CATEGORIES = ["All", "BROADCAST", "POST PRODUCTION", "ANIMATION"];
|
||||
const SOURCE_FILTERS = ["All", "Live", "Imported"] as const;
|
||||
type SourceFilter = typeof SOURCE_FILTERS[number];
|
||||
type FeedMode = "pagination" | "infinite";
|
||||
@@ -94,7 +94,7 @@ export default function ArticleFeed() {
|
||||
let cancelled = false;
|
||||
(async () => {
|
||||
try {
|
||||
const res = await fetch("/api/public/posts?limit=200", { cache: "no-store" });
|
||||
const res = await fetch("/api/public/posts?limit=5000", { cache: "no-store" });
|
||||
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||
const json = await res.json();
|
||||
const items = Array.isArray(json?.items) ? (json.items as ArticleItem[]) : [];
|
||||
@@ -613,11 +613,19 @@ export default function ArticleFeed() {
|
||||
{article?.excerpt}
|
||||
</p>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<div className="flex items-center gap-1 hidden sm:flex">
|
||||
<div className="hidden sm:flex items-center gap-2 text-xs text-[#666] min-w-0">
|
||||
<PersonIcon size={11} className="text-[#666] flex-shrink-0" />
|
||||
<span className="font-body text-xs text-[#666]">
|
||||
<span className="font-body truncate">
|
||||
By {article?.author}
|
||||
</span>
|
||||
{article?.date && (
|
||||
<>
|
||||
<span aria-hidden="true" className="text-[#333]">·</span>
|
||||
<time className="font-body whitespace-nowrap" dateTime={article.date}>
|
||||
{article.date}
|
||||
</time>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<Link
|
||||
href={articleHref}
|
||||
|
||||
@@ -1,6 +1,25 @@
|
||||
import React, { Suspense } from 'react';
|
||||
import type { Metadata, Viewport } from 'next';
|
||||
import { Lora, Inter } from 'next/font/google';
|
||||
import '../styles/tailwind.css';
|
||||
|
||||
// Self-hosted at build time by next/font — no runtime CDN fetch, no FOIT,
|
||||
// no GDPR concern. The two variables are consumed by --font-heading and
|
||||
// --font-body in src/styles/tailwind.css with Georgia/Arial fallbacks.
|
||||
const lora = Lora({
|
||||
subsets: ['latin'],
|
||||
weight: ['400', '500', '600', '700'],
|
||||
style: ['normal', 'italic'],
|
||||
variable: '--font-serif',
|
||||
display: 'swap',
|
||||
});
|
||||
|
||||
const inter = Inter({
|
||||
subsets: ['latin'],
|
||||
weight: ['300', '400', '500', '600', '700', '800'],
|
||||
variable: '--font-sans',
|
||||
display: 'swap',
|
||||
});
|
||||
// SystemStatusBar removed — the "articles indexed / events tracked / [v2.0.0]"
|
||||
// strip was eating vertical space without serving readers.
|
||||
import AskBBAI from '@/components/AskBBAI';
|
||||
@@ -81,7 +100,7 @@ export default function RootLayout({
|
||||
|
||||
}: Readonly<{children: React.ReactNode;}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<html lang="en" className={`${lora.variable} ${inter.variable}`}>
|
||||
<head>
|
||||
{/* hreflang entries removed pending real i18n routes (Phase D). */}
|
||||
|
||||
|
||||
@@ -17,9 +17,12 @@
|
||||
--color-border: #2a2a2a;
|
||||
--color-top-bar: #1a2535;
|
||||
--color-sub-nav: #161c28;
|
||||
--font-heading: Georgia, 'Times New Roman', serif;
|
||||
--font-body: Arial, Helvetica, sans-serif;
|
||||
--font-mono: 'Courier New', Courier, monospace;
|
||||
/* --font-serif and --font-sans are injected on <html> by next/font/google
|
||||
(Lora + Inter) in src/app/layout.tsx. The system-font tails are real
|
||||
fallbacks for the brief window before the self-hosted face is ready. */
|
||||
--font-heading: var(--font-serif), Georgia, 'Times New Roman', serif;
|
||||
--font-body: var(--font-sans), -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
|
||||
--font-mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, Consolas, 'Courier New', monospace;
|
||||
--transition-fast: 0.18s ease;
|
||||
--transition-base: 0.25s ease;
|
||||
--transition-slow: 0.4s ease;
|
||||
|
||||
Reference in New Issue
Block a user