mirror of
https://github.com/logos-co/logos-web.git
synced 2026-08-31 06:01:26 +00:00
* fix(sitemap): remove FAQ route from static indexable routes * feat(web): markdown-managed legal pages + Testnet FAQ & Terms Introduce a markdown-based system for legal/info documents and add the two testnet pages on the same docs route pattern. - Add getLegalDoc loader (gray-matter frontmatter + zod validation) and LegalMarkdown renderer (react-markdown + remark-gfm) mapped to Logos design tokens; render legal pages as a server component. - Refactor docs-page-factory to source content from content/legal/<slug>.md instead of next-intl namespaces; migrate terms, privacy, and security from messages/en.json to markdown. - Add /testnet-v01-faqs and /testnet-terms-and-conditions pages with content mirrored from logos.co; link the FAQ's testnet-terms references to the internal route. - Add Testnet FAQ and Testnet Terms to the docs ToC (remove the dead FAQ entry); register both routes in the sitemap. - Align docs content to the standard page gutter by removing the redundant px-3 on the docs page shell. * chore: optimise page imagery * feat(web): link Logos Devs X account in community section * chore(web): hide 'What you can build today' section on get-started and builders-hub * refactor: reuse builders hub start sections * feat(builders-hub): source RFPs from GitHub API at build time Fetch and parse RFPs from the logos-co/rfp repo (markdown + YAML frontmatter) at build time instead of local content, so the /rfps listing and [slug] detail pages render from a single live source. - add rfps-github lib: GitHub contents fetch, gray-matter frontmatter parse, stable slug from filename, draft/template exclusion - detail page renders frontmatter-stripped markdown via LegalMarkdown, with Apply + View on GitHub CTAs - widen RFP card/row/listing props to RfpListItem so GitHub data (no reward/image) and local Rfp both satisfy the UI - add optional markdown body to BuildersHubDetailLayout * refactor: share get started sections
88 lines
2.3 KiB
TypeScript
88 lines
2.3 KiB
TypeScript
import { getTranslations } from 'next-intl/server'
|
|
|
|
import { ROUTES } from '@/constants/routes'
|
|
import { Link } from '@/i18n/navigation'
|
|
|
|
/**
|
|
* Shared left-side ToC used by FAQ, Terms, Privacy, Security
|
|
* (and any future docs / legal pages that share the secondary nav).
|
|
*
|
|
* Figma desktop nodes: 40009046:22319 (FAQ frame),
|
|
* mobile node: 40009046:22278 (FAQ frame).
|
|
*
|
|
* Layout matches Figma exactly:
|
|
* - w-[226px], py-20, gap-1 (4px in Figma)
|
|
* - text-mono-s (Fira Mono Regular 10px) for inactive items
|
|
* - dot (h-2 w-3 rounded-full) + text-eyebrow for the active item
|
|
* - sticky top-0 from xl upward (matches the gap-122 desktop frame)
|
|
*/
|
|
|
|
export type DocsTocKey =
|
|
| 'brandKit'
|
|
| 'terms'
|
|
| 'privacy'
|
|
| 'security'
|
|
| 'faq'
|
|
| 'testnetFaqs'
|
|
| 'testnetTerms'
|
|
|
|
interface DocsTocItem {
|
|
key: DocsTocKey
|
|
href: string
|
|
}
|
|
|
|
const ITEMS: ReadonlyArray<DocsTocItem> = [
|
|
{ key: 'brandKit', href: ROUTES.brandKit },
|
|
{ key: 'terms', href: ROUTES.terms },
|
|
{ key: 'privacy', href: ROUTES.privacy },
|
|
{ key: 'security', href: ROUTES.security },
|
|
{ key: 'testnetFaqs', href: ROUTES.testnetV01Faqs },
|
|
{ key: 'testnetTerms', href: ROUTES.testnetTermsAndConditions },
|
|
]
|
|
|
|
interface DocsTocProps {
|
|
activeKey: DocsTocKey
|
|
}
|
|
|
|
export async function DocsToc({ activeKey }: DocsTocProps) {
|
|
const t = await getTranslations('common.docsNav')
|
|
|
|
return (
|
|
<nav
|
|
aria-label="Docs navigation"
|
|
className="flex w-56.5 shrink-0 flex-col items-start gap-1 self-start py-20 xl:sticky xl:top-0"
|
|
>
|
|
{ITEMS.map((item) => {
|
|
const isActive = item.key === activeKey
|
|
|
|
if (isActive) {
|
|
return (
|
|
<span
|
|
key={item.key}
|
|
aria-current="page"
|
|
className="flex items-center gap-1"
|
|
>
|
|
<span
|
|
aria-hidden="true"
|
|
className="h-2 w-3 shrink-0 rounded-full bg-brand-dark-green"
|
|
/>
|
|
<span className="text-eyebrow text-brand-dark-green">
|
|
{t(item.key)}
|
|
</span>
|
|
</span>
|
|
)
|
|
}
|
|
|
|
const className =
|
|
'text-mono-s cursor-pointer text-brand-dark-green transition-opacity hover:opacity-60'
|
|
|
|
return (
|
|
<Link key={item.key} href={item.href} className={className}>
|
|
{t(item.key)}
|
|
</Link>
|
|
)
|
|
})}
|
|
</nav>
|
|
)
|
|
}
|