├── .changeset └── config.json ├── .github ├── CONTRIBUTING.md ├── actions │ └── install-dependencies │ │ └── action.yml ├── dependabot.yml ├── vocs-logo-dark.svg ├── vocs-logo-light.svg └── workflows │ ├── canary.yml │ ├── changesets.yml │ ├── on-pull-request.yml │ ├── on-push-to-main.yml │ ├── prune-tags.yml │ └── verify.yml ├── .gitignore ├── .npmrc ├── .vscode ├── extensions.json └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── api └── og.tsx ├── biome.json ├── create-vocs ├── CHANGELOG.md ├── bin.ts ├── index.ts ├── init.ts ├── package.json ├── templates │ └── default │ │ ├── .gitignore │ │ ├── README.md │ │ ├── docs │ │ └── pages │ │ │ ├── example.mdx │ │ │ ├── getting-started.mdx │ │ │ └── index.mdx │ │ ├── package.json │ │ ├── tsconfig.json │ │ └── vocs.config.ts └── tsconfig.build.json ├── package.json ├── playgrounds ├── config-json │ ├── docs │ │ └── pages │ │ │ └── index.mdx │ ├── package.json │ └── vocs.config.json ├── config-toml │ ├── Vocs.toml │ ├── docs │ │ └── pages │ │ │ └── index.mdx │ └── package.json ├── custom-layout │ ├── docs │ │ ├── layout.tsx │ │ ├── pages │ │ │ ├── index.mdx │ │ │ └── subpage.mdx │ │ └── styles.css │ ├── package.json │ └── vocs.config.ts ├── default │ ├── docs │ │ └── pages │ │ │ └── index.mdx │ ├── package.json │ └── vocs.config.ts └── tailwind │ ├── docs │ ├── pages │ │ └── index.mdx │ └── styles.css │ └── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── scripts ├── postbuild.ts ├── preconstruct.ts └── prepublish.ts ├── site ├── components │ ├── Example.tsx │ └── MyButton.tsx ├── footer.tsx ├── pages │ ├── blank.mdx │ ├── blog │ │ ├── gm.mdx │ │ └── index.mdx │ ├── docs │ │ ├── api │ │ │ ├── config.mdx │ │ │ └── frontmatter.mdx │ │ ├── guides │ │ │ ├── blog.mdx │ │ │ ├── code-snippets.mdx │ │ │ ├── components.mdx │ │ │ ├── layouts.mdx │ │ │ ├── markdown-snippets.mdx │ │ │ ├── navigation.mdx │ │ │ ├── og-images.mdx │ │ │ ├── styling.mdx │ │ │ ├── theming.mdx │ │ │ └── twoslash.mdx │ │ ├── index.mdx │ │ ├── kitchen-sink.mdx │ │ ├── markdown.mdx │ │ └── structure.mdx │ └── index.mdx ├── public │ ├── og.png │ ├── vocs-icon-dark.svg │ ├── vocs-icon-light.svg │ ├── vocs-logo-dark.svg │ └── vocs-logo-light.svg ├── snippets │ └── example.ts └── styles.css ├── src ├── CHANGELOG.md ├── LICENSE ├── README.md ├── app │ ├── components │ │ ├── AiCtaDropdown.css.ts │ │ ├── AiCtaDropdown.tsx │ │ ├── Authors.css.ts │ │ ├── Authors.tsx │ │ ├── Banner.css.ts │ │ ├── Banner.tsx │ │ ├── BlogPosts.css.ts │ │ ├── BlogPosts.tsx │ │ ├── Button.css.ts │ │ ├── Button.tsx │ │ ├── Callout.css.ts │ │ ├── Callout.tsx │ │ ├── Content.css.ts │ │ ├── Content.tsx │ │ ├── CopyButton.css.ts │ │ ├── CopyButton.tsx │ │ ├── DesktopSearch.css.ts │ │ ├── DesktopSearch.tsx │ │ ├── DesktopTopNav.css.ts │ │ ├── DesktopTopNav.tsx │ │ ├── ExternalLink.css.ts │ │ ├── ExternalLink.tsx │ │ ├── Footer.css.ts │ │ ├── Footer.tsx │ │ ├── HomePage.css.ts │ │ ├── HomePage.tsx │ │ ├── Icon.css.ts │ │ ├── Icon.tsx │ │ ├── KeyboardShortcut.css.ts │ │ ├── KeyboardShortcut.tsx │ │ ├── Link.css.ts │ │ ├── Link.tsx │ │ ├── Logo.css.ts │ │ ├── Logo.tsx │ │ ├── MobileSearch.css.ts │ │ ├── MobileSearch.tsx │ │ ├── MobileTopNav.css.ts │ │ ├── MobileTopNav.tsx │ │ ├── NavLogo.css.ts │ │ ├── NavLogo.tsx │ │ ├── NavigationMenu.css.ts │ │ ├── NavigationMenu.tsx │ │ ├── NotFound.css.ts │ │ ├── NotFound.tsx │ │ ├── Outline.css.ts │ │ ├── Outline.tsx │ │ ├── Popover.css.ts │ │ ├── Popover.tsx │ │ ├── Raw.tsx │ │ ├── RouterLink.tsx │ │ ├── SearchDialog.css.ts │ │ ├── SearchDialog.tsx │ │ ├── Sidebar.css.ts │ │ ├── Sidebar.tsx │ │ ├── SkipLink.css.ts │ │ ├── SkipLink.tsx │ │ ├── Socials.css.ts │ │ ├── Socials.tsx │ │ ├── Sponsors.css.ts │ │ ├── Sponsors.tsx │ │ ├── Step.css.ts │ │ ├── Step.tsx │ │ ├── Steps.css.ts │ │ ├── Steps.tsx │ │ ├── Tabs.css.ts │ │ ├── Tabs.tsx │ │ ├── ThemeToggle.css.ts │ │ ├── ThemeToggle.tsx │ │ ├── icons │ │ │ ├── ArrowDiagonal.tsx │ │ │ ├── ArrowLeft.tsx │ │ │ ├── ArrowRight.tsx │ │ │ ├── CheckCircle.tsx │ │ │ ├── Checkmark.tsx │ │ │ ├── ChevronDown.tsx │ │ │ ├── ChevronRight.tsx │ │ │ ├── ChevronUp.tsx │ │ │ ├── Copy.tsx │ │ │ ├── Discord.tsx │ │ │ ├── ExclamationTriangle.tsx │ │ │ ├── File.tsx │ │ │ ├── GitHub.tsx │ │ │ ├── InfoCircled.tsx │ │ │ ├── LightningBolt.tsx │ │ │ ├── Link.tsx │ │ │ ├── Menu.tsx │ │ │ ├── Moon.tsx │ │ │ ├── OpenAi.tsx │ │ │ ├── Sun.tsx │ │ │ ├── Telegram.tsx │ │ │ ├── Terminal.tsx │ │ │ ├── Warpcast.tsx │ │ │ └── X.tsx │ │ └── mdx │ │ │ ├── Anchor.css.ts │ │ │ ├── Anchor.tsx │ │ │ ├── Aside.css.ts │ │ │ ├── Aside.tsx │ │ │ ├── Autolink.css.ts │ │ │ ├── Autolink.tsx │ │ │ ├── AutolinkIcon.css.ts │ │ │ ├── AutolinkIcon.tsx │ │ │ ├── Blockquote.css.ts │ │ │ ├── Blockquote.tsx │ │ │ ├── Code.css.ts │ │ │ ├── Code.tsx │ │ │ ├── CodeBlock.css.ts │ │ │ ├── CodeBlock.tsx │ │ │ ├── CodeGroup.css.ts │ │ │ ├── CodeGroup.tsx │ │ │ ├── CodeTitle.css.ts │ │ │ ├── CodeTitle.tsx │ │ │ ├── Details.css.ts │ │ │ ├── Details.tsx │ │ │ ├── Div.css.ts │ │ │ ├── Div.tsx │ │ │ ├── Figcaption.css.ts │ │ │ ├── Figcaption.tsx │ │ │ ├── Figure.css.ts │ │ │ ├── Figure.tsx │ │ │ ├── Footnotes.css.ts │ │ │ ├── Footnotes.tsx │ │ │ ├── H1.css.ts │ │ │ ├── H1.tsx │ │ │ ├── H2.css.ts │ │ │ ├── H2.tsx │ │ │ ├── H3.css.ts │ │ │ ├── H3.tsx │ │ │ ├── H4.css.ts │ │ │ ├── H4.tsx │ │ │ ├── H5.css.ts │ │ │ ├── H5.tsx │ │ │ ├── H6.css.ts │ │ │ ├── H6.tsx │ │ │ ├── Header.css.ts │ │ │ ├── Header.tsx │ │ │ ├── Heading.css.ts │ │ │ ├── Heading.tsx │ │ │ ├── HorizontalRule.css.ts │ │ │ ├── HorizontalRule.tsx │ │ │ ├── Kbd.css.ts │ │ │ ├── Kbd.tsx │ │ │ ├── List.css.ts │ │ │ ├── List.tsx │ │ │ ├── ListItem.css.ts │ │ │ ├── ListItem.tsx │ │ │ ├── Paragraph.css.ts │ │ │ ├── Paragraph.tsx │ │ │ ├── Pre.css.ts │ │ │ ├── Pre.tsx │ │ │ ├── Section.css.ts │ │ │ ├── Section.tsx │ │ │ ├── Span.css.ts │ │ │ ├── Span.tsx │ │ │ ├── Steps.tsx │ │ │ ├── Strong.css.ts │ │ │ ├── Strong.tsx │ │ │ ├── Subtitle.css.ts │ │ │ ├── Subtitle.tsx │ │ │ ├── Summary.css.ts │ │ │ ├── Summary.tsx │ │ │ ├── Table.css.ts │ │ │ ├── Table.tsx │ │ │ ├── TableCell.css.ts │ │ │ ├── TableCell.tsx │ │ │ ├── TableHeader.css.ts │ │ │ ├── TableHeader.tsx │ │ │ ├── TableRow.css.ts │ │ │ ├── TableRow.tsx │ │ │ ├── TwoslashPopover.tsx │ │ │ └── index.tsx │ ├── dom.d.ts │ ├── hooks │ │ ├── useActiveNavIds.ts │ │ ├── useConfig.tsx │ │ ├── useCopyCode.ts │ │ ├── useDebounce.ts │ │ ├── useEditLink.ts │ │ ├── useLayout.tsx │ │ ├── useLocalStorage.ts │ │ ├── useMounted.ts │ │ ├── useOgImageUrl.ts │ │ ├── usePageData.ts │ │ ├── useSearchIndex.ts │ │ ├── useSidebar.ts │ │ └── useTheme.ts │ ├── index.client.tsx │ ├── index.server.tsx │ ├── layouts │ │ ├── DocsLayout.css.ts │ │ └── DocsLayout.tsx │ ├── public │ │ └── .vocs │ │ │ └── icons │ │ │ ├── arrow-diagonal.svg │ │ │ ├── chevron-down.svg │ │ │ ├── chevron-up.svg │ │ │ └── link.svg │ ├── root.tsx │ ├── routes.tsx │ ├── styles │ │ ├── base.css.ts │ │ ├── global.css.ts │ │ ├── index.css.ts │ │ ├── reset.css.ts │ │ ├── twoslash.css.ts │ │ ├── utils.css.ts │ │ └── vars.css.ts │ ├── types.ts │ ├── utils │ │ ├── createFetchRequest.ts │ │ ├── debounce.ts │ │ ├── deserializeElement.ts │ │ ├── hydrateLazyRoutes.ts │ │ ├── initializeTheme.ts │ │ ├── mergeRefs.ts │ │ └── removeTempStyles.ts │ └── vite-env.d.ts ├── cli │ ├── commands │ │ ├── build.ts │ │ ├── dev.ts │ │ ├── preview.ts │ │ ├── search-index.ts │ │ └── twoslash.ts │ ├── index.ts │ └── version.ts ├── components.ts ├── config.ts ├── index.ts ├── mdx-react.ts ├── package.json └── vite │ ├── build.ts │ ├── buildSearchIndex.ts │ ├── buildTwoslash.ts │ ├── devServer.ts │ ├── index.html │ ├── plugins │ ├── css.ts │ ├── dev.tsx │ ├── llms.ts │ ├── mdx.ts │ ├── postbuild.ts │ ├── rehype │ │ ├── display-shiki-notation.ts │ │ └── inline-shiki.ts │ ├── remark │ │ ├── authors.ts │ │ ├── blog-posts.ts │ │ ├── callout.ts │ │ ├── code-group.ts │ │ ├── code.ts │ │ ├── details.ts │ │ ├── filename.ts │ │ ├── inferred-frontmatter.ts │ │ ├── links.ts │ │ ├── sponsors.ts │ │ ├── steps.ts │ │ ├── strong-block.ts │ │ ├── subheading.ts │ │ └── twoslash.ts │ ├── resolve-vocs-modules.ts │ ├── search.ts │ ├── shiki │ │ ├── transformerEmptyLine.ts │ │ ├── transformerLineNumbers.ts │ │ ├── transformerNotationInclude.ts │ │ ├── transformerShrinkIndent.ts │ │ ├── transformerSplitIdentifiers.ts │ │ ├── transformerTagLine.ts │ │ ├── transformerTitle.ts │ │ ├── twoslashRenderer.ts │ │ ├── twoslasher.ts │ │ └── utils.ts │ ├── virtual-blog.ts │ ├── virtual-config.ts │ ├── virtual-consumer-components.ts │ ├── virtual-routes.ts │ └── virtual-styles.ts │ ├── prerender.tsx │ ├── preview.ts │ ├── utils │ ├── cache.ts │ ├── getGitTimestamp.ts │ ├── hash.ts │ ├── html.tsx │ ├── resolveOutDir.ts │ ├── resolveVocsConfig.ts │ ├── search.ts │ ├── serveStatic.ts │ ├── slash.ts │ └── vercel.ts │ └── vite.config.ts ├── tsconfig.base.json ├── tsconfig.build.json ├── tsconfig.json ├── vercel.json └── vocs.config.tsx /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.1.0/schema.json", 3 | "changelog": [ 4 | "@changesets/changelog-github", 5 | { 6 | "repo": "wagmi-dev/vocs" 7 | } 8 | ], 9 | "commit": false, 10 | "access": "public", 11 | "baseBranch": "main", 12 | "updateInternalDependencies": "patch", 13 | "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { 14 | "onlyUpdatePeerDependentsWhenOutOfRange": true 15 | }, 16 | "ignore": ["playgrounds-*"] 17 | } 18 | -------------------------------------------------------------------------------- /.github/actions/install-dependencies/action.yml: -------------------------------------------------------------------------------- 1 | name: "Install dependencies" 2 | description: "Prepare repository and all dependencies" 3 | 4 | runs: 5 | using: "composite" 6 | steps: 7 | - name: Set up pnpm 8 | uses: wevm/actions/.github/actions/pnpm@main 9 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: 'npm' 4 | directory: '/' 5 | schedule: 6 | interval: 'monthly' 7 | open-pull-requests-limit: 0 8 | 9 | - package-ecosystem: 'github-actions' 10 | directory: '/' 11 | schedule: 12 | interval: 'monthly' 13 | -------------------------------------------------------------------------------- /.github/workflows/canary.yml: -------------------------------------------------------------------------------- 1 | name: Release (Canary) 2 | on: 3 | push: 4 | branches: [main] 5 | workflow_dispatch: 6 | 7 | jobs: 8 | canary: 9 | name: Release canary 10 | runs-on: ubuntu-latest 11 | timeout-minutes: 5 12 | 13 | steps: 14 | - name: Clone repository 15 | uses: actions/checkout@v4 16 | 17 | - name: Install dependencies 18 | uses: ./.github/actions/install-dependencies 19 | 20 | - name: Setup .npmrc file 21 | uses: actions/setup-node@v4 22 | with: 23 | registry-url: 'https://registry.npmjs.org' 24 | 25 | - name: Set version 26 | run: | 27 | jq --arg prop "workspaces" 'del(.[$prop])' package.json > package.tmp.json && rm package.json && cp package.tmp.json package.json && rm package.tmp.json 28 | cd src 29 | npm --no-git-tag-version version $(npm pkg get version | sed 's/"//g')-$(git branch --show-current | tr -cs '[:alnum:]-' '-' | tr '[:upper:]' '[:lower:]' | sed 's/-$//').$(date +'%Y%m%dT%H%M%S') 30 | cd ../create-vocs 31 | npm --no-git-tag-version version $(npm pkg get version | sed 's/"//g')-$(git branch --show-current | tr -cs '[:alnum:]-' '-' | tr '[:upper:]' '[:lower:]' | sed 's/-$//').$(date +'%Y%m%dT%H%M%S') 32 | 33 | - name: Build 34 | run: pnpm build 35 | 36 | - name: Publish to npm 37 | run: | 38 | pnpx tsx ./scripts/prepublish.ts 39 | cd src 40 | npm publish --tag $(git branch --show-current | tr -cs '[:alnum:]-' '-' | tr '[:upper:]' '[:lower:]' | sed 's/-$//') 41 | cd ../create-vocs 42 | sed -i -e 's/workspace:\*/main/g' package.json 43 | npm publish --tag $(git branch --show-current | tr -cs '[:alnum:]-' '-' | tr '[:upper:]' '[:lower:]' | sed 's/-$//') 44 | env: 45 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 46 | -------------------------------------------------------------------------------- /.github/workflows/on-pull-request.yml: -------------------------------------------------------------------------------- 1 | name: Pull request 2 | on: 3 | pull_request: 4 | types: [opened, reopened, synchronize, ready_for_review] 5 | 6 | concurrency: 7 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 8 | cancel-in-progress: true 9 | 10 | jobs: 11 | verify: 12 | name: Verify 13 | uses: ./.github/workflows/verify.yml 14 | secrets: inherit -------------------------------------------------------------------------------- /.github/workflows/on-push-to-main.yml: -------------------------------------------------------------------------------- 1 | name: Main 2 | on: 3 | push: 4 | branches: [main] 5 | workflow_dispatch: 6 | 7 | concurrency: 8 | group: ${{ github.workflow }}-${{ github.ref }} 9 | cancel-in-progress: true 10 | 11 | jobs: 12 | verify: 13 | name: Verify 14 | uses: ./.github/workflows/verify.yml 15 | secrets: inherit -------------------------------------------------------------------------------- /.github/workflows/prune-tags.yml: -------------------------------------------------------------------------------- 1 | name: Prune NPM tags 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | 7 | jobs: 8 | prune: 9 | name: Prune NPM tags 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Clone repository 13 | uses: actions/checkout@v4 14 | 15 | - name: Setup .npmrc file 16 | uses: actions/setup-node@v4 17 | with: 18 | registry-url: 'https://registry.npmjs.org' 19 | 20 | - name: Prune tags (vocs) 21 | run: cd src && npm view --json | jq -r '.["dist-tags"] | to_entries | .[] | select(.key != "latest") | select(.key != "main") | select(.key != "alpha") | select(.key != "next") | .key' | xargs -I % npm dist-tag rm vocs % 22 | env: 23 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 24 | 25 | - name: Prune tags (create-vocs) 26 | run: cd create-vocs && npm view --json | jq -r '.["dist-tags"] | to_entries | .[] | select(.key != "latest") | select(.key != "main") | select(.key != "alpha") | select(.key != "next") | .key' | xargs -I % npm dist-tag rm create-vocs % 27 | env: 28 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 29 | -------------------------------------------------------------------------------- /.github/workflows/verify.yml: -------------------------------------------------------------------------------- 1 | name: Verify 2 | on: 3 | workflow_call: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | check: 8 | name: Check 9 | runs-on: ubuntu-latest 10 | timeout-minutes: 5 11 | 12 | steps: 13 | - name: Clone repository 14 | uses: actions/checkout@v4 15 | 16 | - name: Install dependencies 17 | uses: ./.github/actions/install-dependencies 18 | 19 | - name: Check code 20 | run: pnpm check 21 | 22 | - uses: stefanzweifel/git-auto-commit-action@v5 23 | env: 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | with: 26 | commit_message: 'chore: format' 27 | commit_user_name: 'github-actions[bot]' 28 | commit_user_email: 'github-actions[bot]@users.noreply.github.com' 29 | 30 | build: 31 | name: Build 32 | runs-on: ubuntu-latest 33 | timeout-minutes: 5 34 | 35 | steps: 36 | - name: Clone repository 37 | uses: actions/checkout@v4 38 | 39 | - name: Install dependencies 40 | uses: ./.github/actions/install-dependencies 41 | 42 | - name: Build 43 | run: pnpm build 44 | 45 | types: 46 | name: Check types 47 | runs-on: ubuntu-latest 48 | 49 | steps: 50 | - name: Clone repository 51 | uses: actions/checkout@v4 52 | 53 | - name: Install dependencies 54 | uses: ./.github/actions/install-dependencies 55 | 56 | - name: Check 57 | run: pnpm check:types -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | dist 3 | node_modules 4 | _lib 5 | tsconfig.tsbuildinfo 6 | tsconfig.*.tsbuildinfo 7 | vocs.config.ts.timestamp-* 8 | .vercel 9 | .vocs -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["biomejs.biome", "vunguyentuan.vscode-css-variables"] 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "biomejs.biome", 3 | "typescript.tsdk": "node_modules/typescript/lib", 4 | "typescript.enablePromptUseWorkspaceTsdk": true, 5 | "[json]": { 6 | "editor.defaultFormatter": "biomejs.biome" 7 | }, 8 | "[javascript]": { 9 | "editor.defaultFormatter": "biomejs.biome" 10 | }, 11 | "[javascriptreact]": { 12 | "editor.defaultFormatter": "biomejs.biome" 13 | }, 14 | "[typescript]": { 15 | "editor.defaultFormatter": "biomejs.biome" 16 | }, 17 | "[typescriptreact]": { 18 | "editor.defaultFormatter": "biomejs.biome" 19 | }, 20 | "css.validate": false 21 | } 22 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | src/CHANGELOG.md -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | src/LICENSE -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | src/README.md -------------------------------------------------------------------------------- /api/og.tsx: -------------------------------------------------------------------------------- 1 | import { ImageResponse } from '@vercel/og' 2 | import * as React from 'react' 3 | 4 | export const config = { 5 | runtime: 'edge', 6 | } 7 | 8 | // https://og-playground.vercel.app/?share=bVLBbtswDP0VQcPQi5O4blYEQtrD2n3BCuySiyzRslpZNCQ5mRfk30c5FdYNO4l8pN6jnnjmCjVwwffaHg-esZhmBw_nc44Z68GaPgl2c1vXn2-qK3iyOvX_YNrG0cmZ0M7Bz4Lm-NkGUMmip5pCNw2-VF-nmGw3P6FP4LOIogNCKbdSvZmAk9dP6DBQ_VNz1zTNl9JAbAt86m2CAo5Sa-sNwbt6fB_kcjn4xxzs7WBYDOrhwPuUxig2myOquNZwXIKVQ4MrLcPbOh7Ngb-_n9rviYzy4g4bZDDWv-Ao2HZHAmxzFSAX_zR19LLv9hfQMHf3eZgF-VE8bdFpwv6iKulXTAkHwVa3DbE_kkedNfsN0f9HB0epbCLz6zURfFBttovqB4Vmm-meobMemHHYSscGSFLLJOlmYDNOgWlU00CfIfO_FdXrySuOY4YjF2e-rAIXu7qu-NUrLrY50dBOhotOuggVhwFf7cs85kVLpyUjnjzot6EFzUUKE1wqnmRLHT04hycMTvPLbw 9 | export default async function handler(request: Request) { 10 | const { searchParams } = new URL(request.url) 11 | 12 | const logo = searchParams.get('logo') 13 | const title = searchParams.get('title') 14 | const description = searchParams.get('description') 15 | 16 | return new ImageResponse( 17 |
29 | {/* biome-ignore lint/a11y/useAltText: */} 30 | {logo && } 31 |
32 | {title} 33 |
34 | {description && ( 35 |
{description}
36 | )} 37 |
, 38 | { 39 | width: 1200, 40 | height: 630, 41 | }, 42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", 3 | "files": { 4 | "ignore": [ 5 | "_lib", 6 | "dist", 7 | "**/node_modules", 8 | "tsconfig.json", 9 | "tsconfig.*.json", 10 | ".vercel", 11 | ".vocs" 12 | ] 13 | }, 14 | "formatter": { 15 | "enabled": true, 16 | "formatWithErrors": false, 17 | "indentStyle": "space", 18 | "indentWidth": 2, 19 | "lineWidth": 100 20 | }, 21 | "linter": { 22 | "enabled": true, 23 | "rules": { 24 | "style": { 25 | "noNonNullAssertion": "off" 26 | }, 27 | "suspicious": { 28 | "noAssignInExpressions": "off", 29 | "noExplicitAny": "off", 30 | "noArrayIndexKey": "off" 31 | } 32 | } 33 | }, 34 | "javascript": { 35 | "formatter": { 36 | "quoteStyle": "single", 37 | "trailingCommas": "all", 38 | "semicolons": "asNeeded" 39 | } 40 | }, 41 | "organizeImports": { 42 | "enabled": true 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /create-vocs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # create-vocs 2 | 3 | ## 1.0.0-alpha.5 4 | 5 | ### Patch Changes 6 | 7 | - [`7815f60`](https://github.com/wevm/vocs/commit/7815f60a3f89bdc991383aed42cd04e19e3e0db7) Thanks [@jxom](https://github.com/jxom)! - Added `typescript` & `@types/react` as dependencies. 8 | 9 | ## 1.0.0-alpha.4 10 | 11 | ### Patch Changes 12 | 13 | - [`957d228`](https://github.com/wevm/vocs/commit/957d228dc2723a63e302374f780e2d26b4c73aff) Thanks [@jxom](https://github.com/jxom)! - Fixed \`.gitignore\` dist directory. 14 | 15 | ## 1.0.0-alpha.3 16 | 17 | ### Patch Changes 18 | 19 | - [`28d09f1`](https://github.com/wevm/vocs/commit/28d09f13e629562f2627f7d6c2cddcc64d6834de) Thanks [@jxom](https://github.com/jxom)! - Fixed top nav styling. 20 | 21 | ## 1.0.0-alpha.2 22 | 23 | ### Patch Changes 24 | 25 | - [`3e717c5`](https://github.com/wevm/vocs/commit/3e717c5288c2d58b37970d64bc57a868f72b6741) Thanks [@jxom](https://github.com/jxom)! - Modified template to include landing page. 26 | 27 | ## 1.0.0-alpha.1 28 | 29 | ### Patch Changes 30 | 31 | - Initial release 32 | 33 | ## 1.0.0-alpha.0 34 | 35 | ### Major Changes 36 | 37 | - [`4226240`](https://github.com/wevm/vocs/commit/4226240f0e70fefb2059cb599bda478bb8eb268c) Thanks [@jxom](https://github.com/jxom)! - Initial release 38 | -------------------------------------------------------------------------------- /create-vocs/bin.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import { createRequire } from 'node:module' 3 | import { cac } from 'cac' 4 | import { type InitParameters, init } from './init.js' 5 | 6 | const require = createRequire(import.meta.url) 7 | const pkg = require('../package.json') 8 | 9 | const cli = cac('create-vocs') 10 | 11 | cli.usage('[options]').option('-n, --name [name]', 'Name of project') 12 | 13 | cli.help() 14 | cli.version(pkg.version) 15 | 16 | const { options } = cli.parse() 17 | 18 | if (!options.help) init(options as InitParameters) 19 | -------------------------------------------------------------------------------- /create-vocs/index.ts: -------------------------------------------------------------------------------- 1 | export { init, type InitParameters } from './init.js' 2 | -------------------------------------------------------------------------------- /create-vocs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-vocs", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "bin": { 6 | "create-vocs": "./_lib/bin.js" 7 | }, 8 | "main": "./_lib/index.js", 9 | "exports": { 10 | ".": "./_lib/index.js" 11 | }, 12 | "dependencies": { 13 | "@clack/prompts": "^0.7.0", 14 | "cac": "^6.7.14", 15 | "detect-package-manager": "^3.0.2", 16 | "fs-extra": "^11.3.0", 17 | "picocolors": "^1.1.1" 18 | }, 19 | "repository": "wevm/vocs" 20 | } 21 | -------------------------------------------------------------------------------- /create-vocs/templates/default/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # production 9 | /docs/dist 10 | 11 | # misc 12 | .DS_Store 13 | *.pem 14 | 15 | # debug 16 | npm-debug.log* 17 | yarn-debug.log* 18 | yarn-error.log* 19 | 20 | # typescript 21 | *.tsbuildinfo 22 | -------------------------------------------------------------------------------- /create-vocs/templates/default/README.md: -------------------------------------------------------------------------------- 1 | This is a [Vocs](https://vocs.dev) project bootstrapped with the Vocs CLI. 2 | -------------------------------------------------------------------------------- /create-vocs/templates/default/docs/pages/example.mdx: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | This is an example page. -------------------------------------------------------------------------------- /create-vocs/templates/default/docs/pages/getting-started.mdx: -------------------------------------------------------------------------------- 1 | # Get started 2 | 3 | Hello world! -------------------------------------------------------------------------------- /create-vocs/templates/default/docs/pages/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | layout: landing 3 | --- 4 | 5 | import { HomePage } from 'vocs/components' 6 | 7 | 8 | 9 | My Awesome Docs 10 | 11 | This is a description of my documentation website. 12 | 13 | Get started 14 | GitHub 15 | 16 | -------------------------------------------------------------------------------- /create-vocs/templates/default/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Docs", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vocs dev", 8 | "build": "vocs build", 9 | "preview": "vocs preview" 10 | }, 11 | "dependencies": { 12 | "react": "latest", 13 | "react-dom": "latest", 14 | "vocs": "latest" 15 | }, 16 | "devDependencies": { 17 | "@types/react": "latest", 18 | "typescript": "latest" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /create-vocs/templates/default/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["**/*.ts", "**/*.tsx"] 24 | } 25 | -------------------------------------------------------------------------------- /create-vocs/templates/default/vocs.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vocs' 2 | 3 | export default defineConfig({ 4 | title: 'Docs', 5 | sidebar: [ 6 | { 7 | text: 'Getting Started', 8 | link: '/getting-started', 9 | }, 10 | { 11 | text: 'Example', 12 | link: '/example', 13 | }, 14 | ], 15 | }) 16 | -------------------------------------------------------------------------------- /create-vocs/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is used to compile the for cjs and esm (see package.json build scripts). It should exclude all test files. 3 | "extends": "../tsconfig.base.json", 4 | "exclude": ["_lib", "node_modules"], 5 | "include": ["*"], 6 | "compilerOptions": { 7 | "declaration": true, 8 | "declarationMap": true, 9 | "outDir": "./_lib", 10 | "sourceMap": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /playgrounds/config-json/docs/pages/index.mdx: -------------------------------------------------------------------------------- 1 | # Hello world -------------------------------------------------------------------------------- /playgrounds/config-json/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playgrounds-default", 3 | "version": "0.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "node --import tsx/esm ../../src/cli/index.ts dev", 8 | "build": "NODE_ENV=production node --import tsx/esm ../../src/cli/index.ts build", 9 | "preview": "node --import tsx/esm ../../src/cli/index.ts preview", 10 | "dist:dev": "vocs dev", 11 | "dist:build": "NODE_ENV=production vocs build", 12 | "dist:preview": "vocs preview" 13 | }, 14 | "dependencies": { 15 | "react": "catalog:", 16 | "react-dom": "catalog:", 17 | "vocs": "workspace:*" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /playgrounds/config-json/vocs.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "sidebar": [ 3 | { 4 | "text": "Getting Started", 5 | "link": "/" 6 | }, 7 | { 8 | "text": "Migration Guide", 9 | "link": "/migration-guide" 10 | } 11 | ], 12 | "title": "JSON Config Example" 13 | } 14 | -------------------------------------------------------------------------------- /playgrounds/config-toml/Vocs.toml: -------------------------------------------------------------------------------- 1 | theme = { accent-color = "red" } 2 | 3 | title = "TOML Config Example" 4 | 5 | sidebar = [ 6 | { text = "Getting Started", link = "/" }, 7 | { text = "Migration Guide", link = "/migration-guide" } 8 | ] 9 | 10 | [[top-nav]] 11 | text = "Home" 12 | link = "/" -------------------------------------------------------------------------------- /playgrounds/config-toml/docs/pages/index.mdx: -------------------------------------------------------------------------------- 1 | # Hello world -------------------------------------------------------------------------------- /playgrounds/config-toml/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playgrounds-default", 3 | "version": "0.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "node --import tsx/esm ../../src/cli/index.ts dev", 8 | "build": "NODE_ENV=production node --import tsx/esm ../../src/cli/index.ts build", 9 | "preview": "node --import tsx/esm ../../src/cli/index.ts preview", 10 | "dist:dev": "vocs dev", 11 | "dist:build": "NODE_ENV=production vocs build", 12 | "dist:preview": "vocs preview" 13 | }, 14 | "dependencies": { 15 | "react": "catalog:", 16 | "react-dom": "catalog:", 17 | "vocs": "workspace:*" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /playgrounds/custom-layout/docs/layout.tsx: -------------------------------------------------------------------------------- 1 | export default function Layout({ children }: { children: React.ReactNode }) { 2 | return
{children}
3 | } 4 | 5 | export function TopNavEnd() { 6 | return
TopNavEnd
7 | } 8 | -------------------------------------------------------------------------------- /playgrounds/custom-layout/docs/pages/index.mdx: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | Example overview page with custome layout. 4 | 5 | ## Example Section 6 | 7 | Hello there. -------------------------------------------------------------------------------- /playgrounds/custom-layout/docs/pages/subpage.mdx: -------------------------------------------------------------------------------- 1 | # Subpage 2 | 3 | Here is an example of a subpage. 4 | 5 | ## Example Section 6 | 7 | Hello there. -------------------------------------------------------------------------------- /playgrounds/custom-layout/docs/styles.css: -------------------------------------------------------------------------------- 1 | .custom_fullwidth .vocs_DocsLayout_gutterLeft { 2 | justify-content: normal; 3 | width: auto; 4 | } 5 | 6 | @media screen and (width > 1080px) { 7 | .custom_fullwidth .vocs_DocsLayout_gutterTop_offsetLeftGutter { 8 | padding-left: max(var(--vocs-sidebar_width), calc(1.5rem + var(--vocs-sidebar_width))); 9 | padding-right: 1.5rem; 10 | } 11 | 12 | .custom_fullwidth .vocs_DocsLayout_content_withSidebar { 13 | margin-left: max(var(--vocs-sidebar_width), calc(1.5rem + var(--vocs-sidebar_width))); 14 | } 15 | 16 | .vocs_Content, 17 | .vocs_Footer { 18 | max-width: 70ch; 19 | padding-left: 0px; 20 | padding-right: 0px; 21 | } 22 | } 23 | 24 | .custom_fullwidth .vocs_DocsLayout_gutterTop_offsetLeftGutter .vocs_DesktopTopNav { 25 | padding: 0; 26 | } 27 | -------------------------------------------------------------------------------- /playgrounds/custom-layout/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playgrounds-custom-layout", 3 | "version": "0.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "node --import tsx/esm ../../src/cli/index.ts dev", 8 | "build": "NODE_ENV=production node --import tsx/esm ../../src/cli/index.ts build", 9 | "preview": "node --import tsx/esm ../../src/cli/index.ts preview", 10 | "dist:dev": "vocs dev", 11 | "dist:build": "NODE_ENV=production vocs build", 12 | "dist:preview": "vocs preview" 13 | }, 14 | "dependencies": { 15 | "react": "catalog:", 16 | "react-dom": "catalog:", 17 | "vocs": "workspace:*" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /playgrounds/custom-layout/vocs.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '../../src/index.js' 2 | 3 | export default defineConfig({ 4 | sidebar: [ 5 | { 6 | text: 'Overview', 7 | link: '/', 8 | }, 9 | { 10 | text: 'Subpage', 11 | link: '/subpage', 12 | }, 13 | ], 14 | title: 'Custom Layout', 15 | topNav: [ 16 | { 17 | text: 'Overview', 18 | link: '/', 19 | }, 20 | { 21 | text: 'Subpage', 22 | link: '/subpage', 23 | }, 24 | ], 25 | }) 26 | -------------------------------------------------------------------------------- /playgrounds/default/docs/pages/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | layout: minimal 3 | showLogo: false 4 | --- 5 | 6 | import { HomePage } from 'vocs/components' 7 | 8 | 9 | 10 | 11 | 12 | Documentation Framework powered by Vite and React 13 | 14 | Vocs is a minimalistic documentation generator designed to supercharge your documentation workflow, built with modern web technologies. 15 | 16 | Get started 17 | GitHub 18 | 19 | 20 | -------------------------------------------------------------------------------- /playgrounds/default/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playgrounds-default", 3 | "version": "0.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "node --import tsx/esm ../../src/cli/index.ts dev", 8 | "build": "NODE_ENV=production node --import tsx/esm ../../src/cli/index.ts build", 9 | "preview": "node --import tsx/esm ../../src/cli/index.ts preview", 10 | "dist:dev": "vocs dev", 11 | "dist:build": "NODE_ENV=production vocs build", 12 | "dist:preview": "vocs preview" 13 | }, 14 | "dependencies": { 15 | "react": "catalog:", 16 | "react-dom": "catalog:", 17 | "vocs": "workspace:*" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /playgrounds/default/vocs.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '../../src/index.js' 2 | 3 | export default defineConfig({ 4 | sidebar: [ 5 | { 6 | text: 'Introduction', 7 | }, 8 | ], 9 | theme: { 10 | accentColor: 'red', 11 | }, 12 | title: 'Awesome Docs', 13 | }) 14 | -------------------------------------------------------------------------------- /playgrounds/tailwind/docs/pages/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tailwind 3 | --- 4 | 5 | # Tailwind 6 | 7 |

8 | Hello world 9 |

-------------------------------------------------------------------------------- /playgrounds/tailwind/docs/styles.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | -------------------------------------------------------------------------------- /playgrounds/tailwind/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playgrounds-tailwind", 3 | "version": "0.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "node --import tsx/esm ../../src/cli/index.ts dev", 8 | "build": "NODE_ENV=production node --import tsx/esm ../../src/cli/index.ts build", 9 | "preview": "node --import tsx/esm ../../src/cli/index.ts preview" 10 | }, 11 | "dependencies": { 12 | "react": "catalog:", 13 | "react-dom": "catalog:" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'create-vocs' 3 | - 'og' 4 | - 'playgrounds/*' 5 | - 'site' 6 | - 'src' 7 | 8 | catalog: 9 | '@types/react': ^19 10 | '@types/react-dom': ^19 11 | react: ^19 12 | react-dom: ^19 13 | typescript: ^5.7.3 -------------------------------------------------------------------------------- /scripts/postbuild.ts: -------------------------------------------------------------------------------- 1 | // TODO: Probably don't do this? 2 | 3 | import { readdirSync } from 'node:fs' 4 | import { resolve } from 'node:path' 5 | import { default as fs } from 'fs-extra' 6 | 7 | // Copy index.html 8 | fs.copyFileSync( 9 | resolve(import.meta.dirname, '../src/vite/index.html'), 10 | resolve(import.meta.dirname, '../src/_lib/vite/index.html'), 11 | ) 12 | 13 | // Copy public folder 14 | fs.copy( 15 | resolve(import.meta.dirname, '../src/app/public'), 16 | resolve(import.meta.dirname, '../src/_lib/app/public'), 17 | ) 18 | 19 | // Copy create-vocs templates 20 | fs.copy( 21 | resolve(import.meta.dirname, '../create-vocs/templates'), 22 | resolve(import.meta.dirname, '../create-vocs/_lib/templates'), 23 | ) 24 | 25 | rewriteExtensions(resolve(import.meta.dirname, '../src/_lib')) 26 | rewriteMdxPlugin() 27 | 28 | //////////////////////////////////////////////////////////////////// 29 | 30 | function rewriteExtensions(dir: string) { 31 | const files = readdirSync(dir) 32 | for (const file of files) { 33 | const path = resolve(dir, file) 34 | if (isDir(path)) { 35 | rewriteExtensions(path) 36 | continue 37 | } 38 | if (path.endsWith('.map')) continue 39 | if (path.endsWith('root.js')) continue 40 | if (path.endsWith('vocs-config.js')) continue 41 | if (path.endsWith('virtual-consumer-components.js')) continue 42 | const fileContent = fs.readFileSync(path, 'utf-8') 43 | fs.writeFileSync(path, fileContent.replace(/\.(tsx|ts)/g, '.js')) 44 | } 45 | } 46 | 47 | function rewriteMdxPlugin() { 48 | const path = resolve(import.meta.dirname, '../src/_lib/vite/plugins/mdx.js') 49 | const content = fs.readFileSync(path, 'utf-8') 50 | fs.writeFileSync(path, content.replace('@mdx-js/react', 'vocs/mdx-react')) 51 | } 52 | 53 | function isDir(dir: string) { 54 | try { 55 | readdirSync(dir) 56 | return true 57 | } catch { 58 | return false 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /scripts/prepublish.ts: -------------------------------------------------------------------------------- 1 | import { join } from 'node:path' 2 | import { default as fs } from 'fs-extra' 3 | 4 | // Writes the current package.json version to `./src/cli/version.ts`. 5 | const versionFilePath = join(import.meta.dirname, '../src/cli/version.ts') 6 | const packageJsonPath = join(import.meta.dirname, '../src/package.json') 7 | const packageVersion = fs.readJsonSync(packageJsonPath).version 8 | 9 | fs.writeFileSync(versionFilePath, `export const version = '${packageVersion}'\n`) 10 | -------------------------------------------------------------------------------- /site/components/Example.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export function Example() { 4 | return
Hello world.
5 | } 6 | -------------------------------------------------------------------------------- /site/components/MyButton.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx' 2 | import type * as React from 'react' 3 | import { Button } from 'vocs/components' 4 | 5 | type ButtonProps = { 6 | children: React.ReactNode 7 | className?: string 8 | href?: string 9 | variant?: 'accent' 10 | } 11 | 12 | export function Large({ children, className, ...rest }: ButtonProps) { 13 | return ( 14 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /site/footer.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | export default function Footer() { 4 | return ( 5 |
6 |
© {new Date().getFullYear()} weth, LLC.
7 |
8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /site/pages/blank.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | showOutline: false 3 | showSidebar: false 4 | --- 5 | 6 | # Blank page 7 | 8 | This is a blank page. 9 | 10 | ```ts 11 | const a = 1 // [\!code --] 12 | const b = 2 // [\!code ++] 13 | const c = 3 14 | ``` 15 | -------------------------------------------------------------------------------- /site/pages/blog/gm.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | layout: minimal 3 | date: 2023-11-25 4 | --- 5 | 6 | # gm 7 | 8 | ::authors 9 | 10 | we're so back. -------------------------------------------------------------------------------- /site/pages/blog/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | layout: minimal 3 | --- 4 | 5 | # Blog 6 | 7 | ::blog-posts -------------------------------------------------------------------------------- /site/pages/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Vocs – React Documentation Framework 3 | layout: landing 4 | showLogo: false 5 | --- 6 | 7 | import { HomePage } from '../../src/components' 8 | 9 | 10 | 11 | Minimal Documentation Framework, powered by React + Vite. 12 | 13 | Vocs is a minimal static documentation generator designed to supercharge your documentation workflow, built with modern web technologies. 14 | 15 | Get started 16 | GitHub 17 | 18 | 19 | 20 | # Sponsors 21 | 22 | ::sponsors 23 | 24 | -------------------------------------------------------------------------------- /site/public/og.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wevm/vocs/ee0179c47147a5fe161c7f758eb50d8168892d1d/site/public/og.png -------------------------------------------------------------------------------- /site/public/vocs-icon-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /site/public/vocs-icon-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /site/snippets/example.ts: -------------------------------------------------------------------------------- 1 | // [!region import] 2 | import { http, createPublicClient } from 'viem' 3 | import { mainnet } from 'viem/chains' 4 | // [!endregion import] 5 | 6 | // [!region setup] 7 | const client = createPublicClient({ 8 | chain: mainnet, 9 | transport: http(), 10 | }) 11 | // [!endregion setup] 12 | 13 | // [!region usage-1] 14 | const blockNumber_$1 = await client.getBlockNumber() 15 | // [!endregion usage-1] 16 | 17 | // [!region usage-2-docs] 18 | const blockNumber_$2 = await client.getBlockNumber() // [\!code hl] // [!code focus] 19 | // [!endregion usage-2-docs] 20 | 21 | // [!region usage-2] 22 | const blockNumber_$3 = await client.getBlockNumber() // [!code hl] 23 | // [!endregion usage-2] 24 | 25 | // [!region usage-3-docs] 26 | // [\!code word:getBlockNumber] // [!code focus] 27 | const blockNumber_$4 = await client.getBlockNumber() 28 | // [!endregion usage-3-docs] 29 | 30 | // [!region usage-3] 31 | // [!code word:getBlockNumber] 32 | const blockNumber_$5 = await client.getBlockNumber() 33 | // [!endregion usage-3] 34 | 35 | // [!region usage-4] 36 | const blockNumber_$6 = await client.getBlockNumber() 37 | // ^? 38 | // [!endregion usage-4] 39 | -------------------------------------------------------------------------------- /site/styles.css: -------------------------------------------------------------------------------- 1 | .vocs_NavLogo_logoImage { 2 | height: 30% !important; 3 | } 4 | 5 | .footer { 6 | align-items: center; 7 | color: var(--vocs-color_text3); 8 | display: flex; 9 | flex-direction: column; 10 | font-size: 14px; 11 | line-height: 1.5em; 12 | width: 100%; 13 | } 14 | 15 | .vocs_Button_button.text-xl { 16 | font-size: var(--vocs-fontSize_32); 17 | height: var(--vocs-fontSize_64); 18 | } 19 | -------------------------------------------------------------------------------- /src/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024-present weth, LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/app/components/Authors.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | import { fontSizeVars, primitiveColorVars } from '../styles/vars.css.js' 3 | 4 | export const root = style({ 5 | color: primitiveColorVars.text3, 6 | fontSize: fontSizeVars[14], 7 | }) 8 | 9 | export const authors = style( 10 | { 11 | color: primitiveColorVars.text, 12 | }, 13 | 'authors', 14 | ) 15 | 16 | export const link = style( 17 | { 18 | textDecoration: 'underline', 19 | textUnderlineOffset: '2px', 20 | ':hover': { 21 | color: primitiveColorVars.text2, 22 | }, 23 | }, 24 | 'link', 25 | ) 26 | 27 | export const separator = style( 28 | { 29 | color: primitiveColorVars.text3, 30 | }, 31 | 'separator', 32 | ) 33 | -------------------------------------------------------------------------------- /src/app/components/Banner.tsx: -------------------------------------------------------------------------------- 1 | import { runSync } from '@mdx-js/mdx' 2 | import { Cross1Icon } from '@radix-ui/react-icons' 3 | import { assignInlineVars } from '@vanilla-extract/dynamic' 4 | import clsx from 'clsx' 5 | import { Fragment, useMemo } from 'react' 6 | import * as runtime from 'react/jsx-runtime' 7 | 8 | import { useConfig } from '../hooks/useConfig.js' 9 | import { deserializeElement } from '../utils/deserializeElement.js' 10 | import * as styles from './Banner.css.js' 11 | 12 | export type BannerProps = { 13 | hide?: () => void 14 | } 15 | 16 | export function Banner({ hide }: BannerProps) { 17 | const { banner } = useConfig() 18 | const ConsumerBanner = useMemo(() => { 19 | const content = banner?.content ?? '' 20 | if (!content) return null 21 | if (typeof content !== 'string') return () => deserializeElement(content) 22 | const { default: MDXBanner } = runSync(content, { ...runtime, Fragment } as never) 23 | return MDXBanner 24 | }, [banner]) 25 | 26 | if (!ConsumerBanner) return null 27 | return ( 28 |
35 |
36 |
37 | 38 |
39 | {banner?.dismissable !== ('false' as unknown as boolean) && ( 40 | 43 | )} 44 |
45 |
46 | ) 47 | } 48 | -------------------------------------------------------------------------------- /src/app/components/BlogPosts.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | import { fontSizeVars, fontWeightVars, primitiveColorVars, spaceVars } from '../styles/vars.css.js' 3 | 4 | export const root = style({ 5 | display: 'flex', 6 | flexDirection: 'column', 7 | gap: spaceVars['32'], 8 | }) 9 | 10 | export const description = style( 11 | { 12 | marginTop: spaceVars['16'], 13 | }, 14 | 'description', 15 | ) 16 | 17 | export const divider = style( 18 | { 19 | borderColor: primitiveColorVars.background4, 20 | }, 21 | 'divider', 22 | ) 23 | 24 | export const post = style({}, 'post') 25 | 26 | export const readMore = style( 27 | { 28 | selectors: { 29 | [`${post}:hover &`]: { 30 | color: primitiveColorVars.textAccent, 31 | }, 32 | }, 33 | }, 34 | 'readMore', 35 | ) 36 | 37 | export const title = style( 38 | { 39 | color: primitiveColorVars.heading, 40 | fontSize: fontSizeVars.h2, 41 | fontWeight: fontWeightVars.semibold, 42 | }, 43 | 'title', 44 | ) 45 | -------------------------------------------------------------------------------- /src/app/components/BlogPosts.tsx: -------------------------------------------------------------------------------- 1 | import { posts } from 'virtual:blog' 2 | import { Fragment } from 'react' 3 | 4 | import { Authors } from './Authors.js' 5 | import * as styles from './BlogPosts.css.js' 6 | import { RouterLink } from './RouterLink.js' 7 | 8 | export function BlogPosts() { 9 | return ( 10 |
11 | {posts.map((post, index) => ( 12 | 13 |
14 | 15 |

{post.title}

16 | 17 |

18 | {post.description} [→] 19 |

20 |
21 |
22 | {index < posts.length - 1 &&
} 23 |
24 | ))} 25 |
26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /src/app/components/Button.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | import { 3 | borderRadiusVars, 4 | fontSizeVars, 5 | fontWeightVars, 6 | primitiveColorVars, 7 | spaceVars, 8 | } from '../styles/vars.css.js' 9 | 10 | export const button = style( 11 | { 12 | alignItems: 'center', 13 | background: primitiveColorVars.background3, 14 | border: `1px solid ${primitiveColorVars.border}`, 15 | borderRadius: borderRadiusVars.round, 16 | color: primitiveColorVars.text, 17 | display: 'flex', 18 | fontSize: fontSizeVars['14'], 19 | fontWeight: fontWeightVars.medium, 20 | height: '40px', 21 | padding: `0 ${spaceVars['18']}`, 22 | transition: 'background 0.1s', 23 | selectors: { 24 | '&:hover': { 25 | background: primitiveColorVars.background4, 26 | }, 27 | }, 28 | whiteSpace: 'pre', 29 | width: 'fit-content', 30 | }, 31 | 'button', 32 | ) 33 | 34 | export const button_accent = style( 35 | { 36 | background: primitiveColorVars.backgroundAccent, 37 | border: `1px solid ${primitiveColorVars.borderAccent}`, 38 | color: primitiveColorVars.backgroundAccentText, 39 | selectors: { 40 | '&:hover': { 41 | background: primitiveColorVars.backgroundAccentHover, 42 | }, 43 | }, 44 | }, 45 | 'button_accent', 46 | ) 47 | -------------------------------------------------------------------------------- /src/app/components/Button.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx' 2 | import type { ReactNode } from 'react' 3 | 4 | import * as styles from './Button.css.js' 5 | import { Link } from './Link.js' 6 | 7 | export type ButtonProps = { 8 | children: ReactNode 9 | className?: string 10 | href?: string 11 | variant?: 'accent' 12 | } 13 | 14 | export function Button({ children, className, href, variant }: ButtonProps) { 15 | return ( 16 | 21 | {children} 22 | 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /src/app/components/Callout.tsx: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from 'clsx' 2 | import type { ReactNode } from 'react' 3 | 4 | import * as styles from './Callout.css.js' 5 | import { CheckCircle } from './icons/CheckCircle.js' 6 | import { ExclamationTriangle } from './icons/ExclamationTriangle.js' 7 | import { InfoCircled } from './icons/InfoCircled.js' 8 | import { LightningBolt } from './icons/LightningBolt.js' 9 | 10 | export type CalloutProps = { 11 | className: ClassValue 12 | children: ReactNode 13 | type: 'note' | 'info' | 'warning' | 'danger' | 'tip' | 'success' 14 | } 15 | 16 | export function Callout({ className, children, type }: CalloutProps) { 17 | return ( 18 | 29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /src/app/components/Content.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | import { contentVars, primitiveColorVars } from '../styles/vars.css.js' 3 | 4 | export const root = style({ 5 | backgroundColor: primitiveColorVars.background, 6 | flex: 1, 7 | maxWidth: contentVars.width, 8 | padding: `${contentVars.verticalPadding} ${contentVars.horizontalPadding}`, 9 | position: 'relative', 10 | width: '100%', 11 | }) 12 | -------------------------------------------------------------------------------- /src/app/components/Content.tsx: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from 'clsx' 2 | 3 | import * as styles from './Content.css.js' 4 | 5 | export function Content({ 6 | children, 7 | className, 8 | }: { children: React.ReactNode; className?: ClassValue }) { 9 | return
{children}
10 | } 11 | -------------------------------------------------------------------------------- /src/app/components/CopyButton.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | 3 | import { borderRadiusVars, primitiveColorVars, spaceVars, zIndexVars } from '../styles/vars.css.js' 4 | import { root as Pre } from './mdx/Pre.css.js' 5 | 6 | export const root = style({ 7 | alignItems: 'center', 8 | backgroundColor: `color-mix(in srgb, ${primitiveColorVars.background2} 75%, transparent)`, 9 | backdropFilter: 'blur(1px)', 10 | border: `1px solid ${primitiveColorVars.border}`, 11 | borderRadius: borderRadiusVars['4'], 12 | color: primitiveColorVars.text3, 13 | display: 'flex', 14 | justifyContent: 'center', 15 | position: 'absolute', 16 | right: spaceVars['18'], 17 | top: spaceVars['18'], 18 | opacity: 0, 19 | height: '32px', 20 | width: '32px', 21 | transition: 'background-color 0.15s, opacity 0.15s', 22 | zIndex: zIndexVars.surface, 23 | selectors: { 24 | '&:hover': { 25 | backgroundColor: primitiveColorVars.background4, 26 | transition: 'background-color 0.05s', 27 | }, 28 | '&:focus-visible': { 29 | backgroundColor: primitiveColorVars.background4, 30 | opacity: 1, 31 | transition: 'background-color 0.05s', 32 | }, 33 | '&:hover:active': { 34 | backgroundColor: primitiveColorVars.background2, 35 | }, 36 | '&[data-copied="true"]:hover:active': { 37 | backgroundColor: primitiveColorVars.background4, 38 | }, 39 | [`${Pre}:hover &`]: { 40 | opacity: 1, 41 | }, 42 | }, 43 | }) 44 | 45 | export const copied = style( 46 | { 47 | height: '12px', 48 | width: '12px', 49 | }, 50 | 'copied', 51 | ) 52 | -------------------------------------------------------------------------------- /src/app/components/CopyButton.tsx: -------------------------------------------------------------------------------- 1 | import * as styles from './CopyButton.css.js' 2 | import { Icon } from './Icon.js' 3 | import { Checkmark } from './icons/Checkmark.js' 4 | import { Copy } from './icons/Copy.js' 5 | 6 | export function CopyButton({ copy, copied }: { copy: () => void; copied: boolean }) { 7 | return ( 8 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /src/app/components/DesktopSearch.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | 3 | import { 4 | borderRadiusVars, 5 | fontSizeVars, 6 | fontWeightVars, 7 | primitiveColorVars, 8 | spaceVars, 9 | } from '../styles/vars.css.js' 10 | 11 | export const search = style( 12 | { 13 | alignItems: 'center', 14 | backgroundColor: primitiveColorVars.background3, 15 | border: `1px solid ${primitiveColorVars.border}`, 16 | borderRadius: borderRadiusVars[8], 17 | color: primitiveColorVars.text3, 18 | display: 'flex', 19 | fontSize: fontSizeVars[14], 20 | fontWeight: fontWeightVars.regular, 21 | gap: spaceVars[6], 22 | height: spaceVars[40], 23 | maxWidth: '15.5rem', 24 | paddingLeft: spaceVars[12], 25 | paddingRight: spaceVars[12], 26 | position: 'relative', 27 | width: '100%', 28 | transition: 'color 0.1s, border-color 0.1s', 29 | selectors: { 30 | '&:hover': { 31 | color: primitiveColorVars.text, 32 | borderColor: primitiveColorVars.border2, 33 | }, 34 | }, 35 | }, 36 | 'search', 37 | ) 38 | 39 | export const searchCommand = style( 40 | { 41 | alignItems: 'center', 42 | border: `1.5px solid ${primitiveColorVars.text3}`, 43 | borderRadius: borderRadiusVars[4], 44 | color: primitiveColorVars.text3, 45 | display: 'flex', 46 | height: spaceVars[12], 47 | justifyContent: 'center', 48 | marginLeft: 'auto', 49 | marginTop: spaceVars[1], 50 | padding: spaceVars[1], 51 | width: spaceVars[12], 52 | }, 53 | 'searchCommand', 54 | ) 55 | -------------------------------------------------------------------------------- /src/app/components/ExternalLink.css.ts: -------------------------------------------------------------------------------- 1 | import { createVar, style } from '@vanilla-extract/css' 2 | 3 | export const arrowColor = createVar('arrowColor') 4 | export const iconUrl = createVar('iconUrl') 5 | 6 | export const root = style({ 7 | selectors: { 8 | '&::after': { 9 | backgroundColor: 'currentColor', 10 | content: '', 11 | color: arrowColor, 12 | display: 'inline-block', 13 | height: '0.5em', 14 | marginBottom: '0.1em', 15 | marginLeft: '0.325em', 16 | marginRight: '0.25em', 17 | width: '0.5em', 18 | mask: `${iconUrl} no-repeat center / contain`, 19 | }, 20 | }, 21 | }) 22 | -------------------------------------------------------------------------------- /src/app/components/ExternalLink.tsx: -------------------------------------------------------------------------------- 1 | import { clsx } from 'clsx' 2 | 3 | import { assignInlineVars } from '@vanilla-extract/dynamic' 4 | import { forwardRef } from 'react' 5 | import { useConfig } from '../hooks/useConfig.js' 6 | import * as styles from './ExternalLink.css.js' 7 | 8 | export type ExternalLinkProps = React.DetailedHTMLProps< 9 | React.AnchorHTMLAttributes, 10 | HTMLAnchorElement 11 | > & { hideExternalIcon?: boolean } 12 | 13 | export const ExternalLink = forwardRef( 14 | ({ className, children, hideExternalIcon, href, ...props }: ExternalLinkProps, ref) => { 15 | const { basePath } = useConfig() 16 | const assetBasePath = import.meta.env.PROD ? basePath : '' 17 | return ( 18 | 32 | {children} 33 | 34 | ) 35 | }, 36 | ) 37 | -------------------------------------------------------------------------------- /src/app/components/Icon.css.ts: -------------------------------------------------------------------------------- 1 | import { createVar, style } from '@vanilla-extract/css' 2 | 3 | export const sizeVar = createVar('size') 4 | export const srcVar = createVar('src') 5 | 6 | export const root = style({ 7 | alignItems: 'center', 8 | display: 'flex', 9 | height: sizeVar, 10 | width: sizeVar, 11 | }) 12 | -------------------------------------------------------------------------------- /src/app/components/Icon.tsx: -------------------------------------------------------------------------------- 1 | import { assignInlineVars } from '@vanilla-extract/dynamic' 2 | 3 | import clsx from 'clsx' 4 | import * as styles from './Icon.css.js' 5 | 6 | export type IconProps = { 7 | className?: string 8 | label: string 9 | icon: React.ElementType 10 | size?: string 11 | style?: React.CSSProperties 12 | } 13 | 14 | export function Icon({ className, label, icon: Icon, size, style }: IconProps) { 15 | return ( 16 |
25 | 26 |
27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /src/app/components/KeyboardShortcut.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | 3 | import { fontSizeVars, spaceVars, viewportVars } from '../styles/vars.css.js' 4 | 5 | export const root = style({ 6 | alignItems: 'center', 7 | display: 'inline-flex', 8 | gap: spaceVars[6], 9 | fontSize: fontSizeVars[12], 10 | '@media': { 11 | [viewportVars['max-720px']]: { 12 | display: 'none', 13 | }, 14 | }, 15 | }) 16 | 17 | export const kbdGroup = style( 18 | { 19 | alignItems: 'center', 20 | display: 'inline-flex', 21 | gap: spaceVars[3], 22 | }, 23 | 'kbdGroup', 24 | ) 25 | -------------------------------------------------------------------------------- /src/app/components/KeyboardShortcut.tsx: -------------------------------------------------------------------------------- 1 | import { Kbd } from './mdx/Kbd.js' 2 | 3 | import * as styles from './KeyboardShortcut.css.js' 4 | 5 | export function KeyboardShortcut(props: { 6 | description: string 7 | keys: string[] 8 | }) { 9 | const { description, keys } = props 10 | return ( 11 | 12 | {description} 13 | 14 | 15 | {keys.map((key) => ( 16 | {key} 17 | ))} 18 | 19 | 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /src/app/components/Link.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | 3 | import { 4 | fontWeightVars, 5 | primitiveColorVars, 6 | semanticColorVars, 7 | spaceVars, 8 | } from '../styles/vars.css.js' 9 | import { arrowColor } from './ExternalLink.css.js' 10 | 11 | export const root = style({}) 12 | 13 | export const accent = style( 14 | { 15 | color: semanticColorVars.link, 16 | fontWeight: fontWeightVars.medium, 17 | textUnderlineOffset: spaceVars['2'], 18 | textDecoration: 'underline', 19 | transition: 'color 0.1s', 20 | selectors: { 21 | '&:hover': { 22 | color: semanticColorVars.linkHover, 23 | }, 24 | }, 25 | }, 26 | 'accent', 27 | ) 28 | 29 | export const styleless = style( 30 | { 31 | vars: { 32 | [arrowColor]: primitiveColorVars.text3, 33 | }, 34 | }, 35 | 'styleless', 36 | ) 37 | -------------------------------------------------------------------------------- /src/app/components/Link.tsx: -------------------------------------------------------------------------------- 1 | import { clsx } from 'clsx' 2 | import { forwardRef } from 'react' 3 | 4 | import { useLocation } from 'react-router' 5 | import { ExternalLink } from './ExternalLink.js' 6 | import * as styles from './Link.css.js' 7 | import { RouterLink, type RouterLinkProps } from './RouterLink.js' 8 | 9 | type LinkProps = { 10 | children: React.ReactNode 11 | className?: string 12 | hideExternalIcon?: boolean 13 | onClick?: (e: React.MouseEvent) => void 14 | href?: string 15 | variant?: 'accent' | 'styleless' 16 | } 17 | 18 | export const Link = forwardRef((props: LinkProps, ref) => { 19 | const { hideExternalIcon, href, variant = 'accent' } = props 20 | 21 | const { pathname } = useLocation() 22 | 23 | // External links 24 | if (href?.match(/^(www|https?)/)) 25 | return ( 26 | 37 | ) 38 | 39 | // Internal links 40 | const [before, after] = (href || '').split('#') 41 | const to = `${before ? before : pathname}${after ? `#${after}` : ''}` 42 | return ( 43 | 54 | ) 55 | }) 56 | -------------------------------------------------------------------------------- /src/app/components/Logo.css.ts: -------------------------------------------------------------------------------- 1 | import { globalStyle, style } from '@vanilla-extract/css' 2 | 3 | export const root = style({}) 4 | 5 | export const logoDark = style({}, 'logoDark') 6 | globalStyle(`:root:not(.dark) ${logoDark}`, { 7 | display: 'none', 8 | }) 9 | 10 | export const logoLight = style({}, 'logoLight') 11 | globalStyle(`:root.dark ${logoLight}`, { 12 | display: 'none', 13 | }) 14 | -------------------------------------------------------------------------------- /src/app/components/Logo.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx' 2 | 3 | import { useConfig } from '../hooks/useConfig.js' 4 | import * as styles from './Logo.css.js' 5 | 6 | export function Logo({ className }: { className?: string }) { 7 | const { logoUrl } = useConfig() 8 | 9 | if (!logoUrl) return null 10 | return ( 11 | <> 12 | {typeof logoUrl === 'string' ? ( 13 | Logo 14 | ) : ( 15 | <> 16 | Logo 21 | Logo 26 | 27 | )} 28 | 29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /src/app/components/MobileSearch.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | 3 | import { primitiveColorVars, spaceVars } from '../styles/vars.css.js' 4 | 5 | export const searchButton = style( 6 | { 7 | alignItems: 'center', 8 | display: 'flex', 9 | color: primitiveColorVars.text, 10 | height: spaceVars[28], 11 | justifyContent: 'center', 12 | width: spaceVars[28], 13 | }, 14 | 'searchButton', 15 | ) 16 | -------------------------------------------------------------------------------- /src/app/components/MobileSearch.tsx: -------------------------------------------------------------------------------- 1 | import * as Dialog from '@radix-ui/react-dialog' 2 | import { MagnifyingGlassIcon } from '@radix-ui/react-icons' 3 | import { useState } from 'react' 4 | 5 | import * as styles from './MobileSearch.css.js' 6 | import { SearchDialog } from './SearchDialog.js' 7 | 8 | export function MobileSearch() { 9 | const [open, setOpen] = useState(false) 10 | 11 | return ( 12 | 13 | 14 | 17 | 18 | 19 | setOpen(false)} /> 20 | 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /src/app/components/NavLogo.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | import { fontSizeVars, fontWeightVars, lineHeightVars } from '../styles/vars.css.js' 3 | 4 | export const logoImage = style( 5 | { 6 | height: '50%', 7 | width: 'auto', 8 | }, 9 | 'logoImage', 10 | ) 11 | 12 | export const title = style( 13 | { 14 | fontSize: fontSizeVars['18'], 15 | fontWeight: fontWeightVars.semibold, 16 | lineHeight: lineHeightVars.heading, 17 | }, 18 | 'title', 19 | ) 20 | -------------------------------------------------------------------------------- /src/app/components/NavLogo.tsx: -------------------------------------------------------------------------------- 1 | import { useConfig } from '../hooks/useConfig.js' 2 | import { Logo } from './Logo.js' 3 | import * as styles from './NavLogo.css.js' 4 | 5 | export function NavLogo() { 6 | const config = useConfig() 7 | 8 | if (config.logoUrl) return 9 | return
{config.title}
10 | } 11 | -------------------------------------------------------------------------------- /src/app/components/NotFound.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | import { primitiveColorVars, spaceVars } from '../styles/vars.css.js' 3 | 4 | export const root = style({ 5 | alignItems: 'center', 6 | display: 'flex', 7 | flexDirection: 'column', 8 | maxWidth: '400px', 9 | margin: '0 auto', 10 | paddingTop: spaceVars['64'], 11 | }) 12 | 13 | export const divider = style( 14 | { 15 | borderColor: primitiveColorVars.border, 16 | width: '50%', 17 | }, 18 | 'divider', 19 | ) 20 | -------------------------------------------------------------------------------- /src/app/components/NotFound.tsx: -------------------------------------------------------------------------------- 1 | import { spaceVars } from '../styles/vars.css.js' 2 | import { Link } from './Link.js' 3 | import * as styles from './NotFound.css.js' 4 | import { H1 } from './mdx/H1.js' 5 | import { Paragraph } from './mdx/Paragraph.js' 6 | 7 | export function NotFound() { 8 | return ( 9 |
10 |

Page Not Found

11 |
12 |
13 |
14 | The page you were looking for could not be found. 15 |
16 | Go to Home Page 17 |
18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/app/components/Popover.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | import { borderRadiusVars, primitiveColorVars, spaceVars, zIndexVars } from '../styles/vars.css.js' 3 | 4 | export const root = style({ 5 | backgroundColor: primitiveColorVars.background, 6 | border: `1px solid ${primitiveColorVars.border}`, 7 | borderRadius: borderRadiusVars[4], 8 | margin: `0 ${spaceVars[6]}`, 9 | zIndex: zIndexVars.popover, 10 | }) 11 | -------------------------------------------------------------------------------- /src/app/components/Popover.tsx: -------------------------------------------------------------------------------- 1 | import * as Popover_ from '@radix-ui/react-popover' 2 | import type { ReactNode } from 'react' 3 | 4 | import clsx from 'clsx' 5 | import * as styles from './Popover.css.js' 6 | 7 | Popover.Root = Popover_.Root 8 | Popover.Trigger = Popover_.Trigger 9 | 10 | export function Popover({ children, className }: { children: ReactNode; className?: string }) { 11 | return ( 12 | 13 | 14 | {children} 15 | 16 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /src/app/components/Raw.tsx: -------------------------------------------------------------------------------- 1 | import { MDXProvider } from '@mdx-js/react' 2 | import type { ReactNode } from 'react' 3 | 4 | export function Raw({ children }: { children: ReactNode }) { 5 | return {children} 6 | } 7 | -------------------------------------------------------------------------------- /src/app/components/RouterLink.tsx: -------------------------------------------------------------------------------- 1 | import { routes } from 'virtual:routes' 2 | import { forwardRef, useEffect } from 'react' 3 | import { useInView } from 'react-intersection-observer' 4 | import { Link, type LinkProps } from 'react-router' 5 | 6 | import { mergeRefs } from '../utils/mergeRefs.js' 7 | 8 | export type RouterLinkProps = LinkProps 9 | 10 | export const RouterLink = forwardRef((props: RouterLinkProps, ref) => { 11 | const loadRoute = () => routes.find((route) => route.path === props.to)?.lazy() 12 | 13 | const { ref: intersectionRef, inView } = useInView() 14 | // biome-ignore lint/correctness/useExhaustiveDependencies: 15 | useEffect(() => { 16 | if (inView) loadRoute() 17 | }, [inView]) 18 | 19 | return 20 | }) 21 | -------------------------------------------------------------------------------- /src/app/components/SkipLink.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | import { 3 | borderRadiusVars, 4 | fontSizeVars, 5 | fontWeightVars, 6 | primitiveColorVars, 7 | semanticColorVars, 8 | spaceVars, 9 | } from '../styles/vars.css.js' 10 | 11 | export const root = style({ 12 | background: primitiveColorVars.background, 13 | borderRadius: borderRadiusVars['4'], 14 | color: semanticColorVars.link, 15 | fontSize: fontSizeVars['14'], 16 | fontWeight: fontWeightVars.semibold, 17 | left: spaceVars[8], 18 | padding: `${spaceVars['8']} ${spaceVars['16']}`, 19 | position: 'fixed', 20 | textDecoration: 'none', 21 | top: spaceVars[8], 22 | zIndex: 999, 23 | ':focus': { 24 | clip: 'auto', 25 | clipPath: 'none', 26 | height: 'auto', 27 | width: 'auto', 28 | }, 29 | }) 30 | -------------------------------------------------------------------------------- /src/app/components/SkipLink.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx' 2 | import { useLocation } from 'react-router' 3 | import { visuallyHidden } from '../styles/utils.css.js' 4 | import * as styles from './SkipLink.css.js' 5 | 6 | export const skipLinkId = 'vocs-content' 7 | 8 | export function SkipLink() { 9 | const { pathname } = useLocation() 10 | return ( 11 | 12 | Skip to content 13 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /src/app/components/Socials.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | import { primitiveColorVars, spaceVars } from '../styles/vars.css.js' 3 | 4 | export const root = style({ display: 'flex', flexDirection: 'row', gap: spaceVars[8] }) 5 | 6 | export const button = style( 7 | { 8 | alignItems: 'center', 9 | display: 'flex', 10 | padding: spaceVars[4], 11 | }, 12 | 'button', 13 | ) 14 | 15 | export const icon = style( 16 | { 17 | color: primitiveColorVars.text3, 18 | transition: 'color 0.1s', 19 | selectors: { 20 | [`${button}:hover &`]: { 21 | color: primitiveColorVars.textHover, 22 | }, 23 | }, 24 | }, 25 | 'icon', 26 | ) 27 | -------------------------------------------------------------------------------- /src/app/components/Sponsors.tsx: -------------------------------------------------------------------------------- 1 | import { assignInlineVars } from '@vanilla-extract/dynamic' 2 | import clsx from 'clsx' 3 | import { Fragment } from 'react' 4 | import { useConfig } from '../hooks/useConfig.js' 5 | import { Link } from './Link.js' 6 | import * as styles from './Sponsors.css.js' 7 | 8 | export function Sponsors() { 9 | const { sponsors } = useConfig() 10 | return ( 11 |
12 | {sponsors?.map((sponsorSet, i) => ( 13 | 14 |
{sponsorSet.name}
15 | {sponsorSet.items.map((sponsorRow, i) => ( 16 |
24 | {sponsorRow.map((sponsor, i) => ( 25 | 32 | {sponsor?.image && ( 33 | {sponsor?.name} 34 | )} 35 | 36 | ))} 37 |
38 | ))} 39 |
40 | ))} 41 |
42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /src/app/components/Step.tsx: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from 'clsx' 2 | import type { ReactNode } from 'react' 3 | 4 | import * as styles from './Step.css.js' 5 | import { H2 } from './mdx/H2.js' 6 | import { H3 } from './mdx/H3.js' 7 | import { H4 } from './mdx/H4.js' 8 | import { H5 } from './mdx/H5.js' 9 | import { H6 } from './mdx/H6.js' 10 | 11 | export type StepProps = { 12 | children: ReactNode 13 | className?: ClassValue 14 | title: ReactNode | string 15 | titleLevel?: 2 | 3 | 4 | 5 | 6 16 | } 17 | 18 | export function Step({ children, className, title, titleLevel = 2 }: StepProps) { 19 | const Element = (() => { 20 | if (titleLevel === 2) return H2 21 | if (titleLevel === 3) return H3 22 | if (titleLevel === 4) return H4 23 | if (titleLevel === 5) return H5 24 | if (titleLevel === 6) return H6 25 | throw new Error('Invalid.') 26 | })() 27 | 28 | return ( 29 |
30 | {typeof title === 'string' ? {title} : title} 31 |
{children}
32 |
33 | ) 34 | } 35 | -------------------------------------------------------------------------------- /src/app/components/Steps.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | 3 | import { primitiveColorVars, spaceVars, viewportVars } from '../styles/vars.css.js' 4 | 5 | export const root = style({ 6 | borderLeft: `1.5px solid ${primitiveColorVars.border}`, 7 | counterReset: 'step', 8 | paddingLeft: spaceVars['24'], 9 | marginLeft: spaceVars['12'], 10 | marginTop: spaceVars['24'], 11 | '@media': { 12 | [viewportVars['max-720px']]: { 13 | marginLeft: spaceVars['4'], 14 | }, 15 | }, 16 | }) 17 | -------------------------------------------------------------------------------- /src/app/components/Steps.tsx: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from 'clsx' 2 | import type { ReactNode } from 'react' 3 | 4 | import * as styles from './Steps.css.js' 5 | 6 | export type StepsProps = { 7 | children: ReactNode 8 | className?: ClassValue 9 | } 10 | 11 | export function Steps({ children, className }: StepsProps) { 12 | return
{children}
13 | } 14 | -------------------------------------------------------------------------------- /src/app/components/Tabs.tsx: -------------------------------------------------------------------------------- 1 | import * as Tabs from '@radix-ui/react-tabs' 2 | import clsx from 'clsx' 3 | 4 | import * as styles from './Tabs.css.js' 5 | 6 | export function Root(props: Tabs.TabsProps) { 7 | return 8 | } 9 | 10 | export function List(props: Tabs.TabsListProps) { 11 | return 12 | } 13 | 14 | export function Trigger(props: Tabs.TabsTriggerProps) { 15 | return 16 | } 17 | 18 | export function Content(props: Tabs.TabsContentProps) { 19 | return 20 | } 21 | -------------------------------------------------------------------------------- /src/app/components/ThemeToggle.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | import { borderRadiusVars, primitiveColorVars, spaceVars } from '../styles/vars.css.js' 3 | 4 | export const root = style({ 5 | border: `1px solid ${primitiveColorVars.border}`, 6 | borderRadius: borderRadiusVars.round, 7 | display: 'flex', 8 | gap: spaceVars['8'], 9 | padding: spaceVars['4'], 10 | }) 11 | 12 | export const themeToggleButton = style( 13 | { 14 | color: primitiveColorVars.text4, 15 | selectors: { 16 | '&:hover': { 17 | color: primitiveColorVars.textHover, 18 | }, 19 | '&[data-active="true"]': { 20 | color: primitiveColorVars.textHover, 21 | }, 22 | }, 23 | }, 24 | 'themeToggleButton', 25 | ) 26 | -------------------------------------------------------------------------------- /src/app/components/ThemeToggle.tsx: -------------------------------------------------------------------------------- 1 | import { useMounted } from '../hooks/useMounted.js' 2 | import { useTheme } from '../hooks/useTheme.js' 3 | import { Icon } from './Icon.js' 4 | import * as styles from './ThemeToggle.css.js' 5 | import { Moon } from './icons/Moon.js' 6 | import { Sun } from './icons/Sun.js' 7 | 8 | export function ThemeToggle() { 9 | const { theme, setTheme } = useTheme() 10 | const mounted = useMounted() 11 | if (!mounted) return null 12 | if (!theme) return null 13 | return ( 14 |
15 | 23 | 31 |
32 | ) 33 | } 34 | -------------------------------------------------------------------------------- /src/app/components/icons/ArrowDiagonal.tsx: -------------------------------------------------------------------------------- 1 | export function ArrowDiagonal() { 2 | return ( 3 | 10 | Arrow Diagonal 11 | 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /src/app/components/icons/ArrowLeft.tsx: -------------------------------------------------------------------------------- 1 | export function ArrowLeft() { 2 | return ( 3 | 10 | Arrow Left 11 | 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /src/app/components/icons/ArrowRight.tsx: -------------------------------------------------------------------------------- 1 | export function ArrowRight() { 2 | return ( 3 | 10 | Arrow Right 11 | 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /src/app/components/icons/CheckCircle.tsx: -------------------------------------------------------------------------------- 1 | export function CheckCircle() { 2 | return ( 3 | 10 | Check 11 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/app/components/icons/Checkmark.tsx: -------------------------------------------------------------------------------- 1 | export function Checkmark() { 2 | return ( 3 | 10 | Checkmark 11 | 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /src/app/components/icons/ChevronDown.tsx: -------------------------------------------------------------------------------- 1 | export function ChevronDown() { 2 | return ( 3 | 10 | Chevron Down 11 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/app/components/icons/ChevronRight.tsx: -------------------------------------------------------------------------------- 1 | export function ChevronRight() { 2 | return ( 3 | 10 | Chevron Right 11 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/app/components/icons/ChevronUp.tsx: -------------------------------------------------------------------------------- 1 | export function ChevronUp() { 2 | return ( 3 | 10 | Chevron Up 11 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/app/components/icons/Discord.tsx: -------------------------------------------------------------------------------- 1 | export function Discord() { 2 | return ( 3 | 4 | Discord 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /src/app/components/icons/ExclamationTriangle.tsx: -------------------------------------------------------------------------------- 1 | export function ExclamationTriangle() { 2 | return ( 3 | 10 | Exclamation 11 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/app/components/icons/GitHub.tsx: -------------------------------------------------------------------------------- 1 | export function GitHub() { 2 | return ( 3 | 4 | GitHub 5 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /src/app/components/icons/InfoCircled.tsx: -------------------------------------------------------------------------------- 1 | export function InfoCircled() { 2 | return ( 3 | 10 | Info 11 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/app/components/icons/LightningBolt.tsx: -------------------------------------------------------------------------------- 1 | export function LightningBolt() { 2 | return ( 3 | 10 | Lightning Bolt 11 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/app/components/icons/Link.tsx: -------------------------------------------------------------------------------- 1 | export function Link() { 2 | return ( 3 | 10 | Link 11 | 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /src/app/components/icons/Menu.tsx: -------------------------------------------------------------------------------- 1 | export function Menu() { 2 | return ( 3 | 10 | Menu 11 | 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /src/app/components/icons/OpenAi.tsx: -------------------------------------------------------------------------------- 1 | export function OpenAi() { 2 | return ( 3 | 4 | OpenAI 5 | 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /src/app/components/icons/Telegram.tsx: -------------------------------------------------------------------------------- 1 | export function Telegram() { 2 | return ( 3 | 4 | Telegram 5 | 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /src/app/components/icons/Terminal.tsx: -------------------------------------------------------------------------------- 1 | export function Terminal() { 2 | return ( 3 | 10 | Terminal 11 | 15 | 16 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /src/app/components/icons/Warpcast.tsx: -------------------------------------------------------------------------------- 1 | export function Warpcast() { 2 | return ( 3 | 4 | Warpcast 5 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /src/app/components/icons/X.tsx: -------------------------------------------------------------------------------- 1 | export function X() { 2 | return ( 3 | 10 | X 11 | 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /src/app/components/mdx/Anchor.css.ts: -------------------------------------------------------------------------------- 1 | import { globalStyle, style } from '@vanilla-extract/css' 2 | 3 | import { fontWeightVars, semanticColorVars, spaceVars } from '../../styles/vars.css.js' 4 | import { danger, info, success, tip, warning } from '../Callout.css.js' 5 | import { root as Section } from './Section.css.js' 6 | 7 | export const root = style({ 8 | color: semanticColorVars.link, 9 | fontWeight: fontWeightVars.medium, 10 | textUnderlineOffset: spaceVars['2'], 11 | textDecoration: 'underline', 12 | transition: 'color 0.1s', 13 | selectors: { 14 | [`${danger} &`]: { 15 | color: semanticColorVars.dangerText, 16 | }, 17 | [`${danger} &:hover`]: { 18 | color: semanticColorVars.dangerTextHover, 19 | }, 20 | [`${info} &`]: { 21 | color: semanticColorVars.infoText, 22 | }, 23 | [`${info} &:hover`]: { 24 | color: semanticColorVars.infoTextHover, 25 | }, 26 | [`${success} &`]: { 27 | color: semanticColorVars.successText, 28 | }, 29 | [`${success} &:hover`]: { 30 | color: semanticColorVars.successTextHover, 31 | }, 32 | [`${tip} &`]: { 33 | color: semanticColorVars.tipText, 34 | }, 35 | [`${tip} &:hover`]: { 36 | color: semanticColorVars.tipTextHover, 37 | }, 38 | [`${warning} &`]: { 39 | color: semanticColorVars.warningText, 40 | }, 41 | [`${warning} &:hover`]: { 42 | color: semanticColorVars.warningTextHover, 43 | }, 44 | '&:hover': { 45 | color: semanticColorVars.linkHover, 46 | }, 47 | }, 48 | }) 49 | 50 | globalStyle(`${Section} a.data-footnote-backref`, { 51 | color: semanticColorVars.link, 52 | fontWeight: fontWeightVars.medium, 53 | textUnderlineOffset: spaceVars['2'], 54 | textDecoration: 'underline', 55 | }) 56 | 57 | globalStyle(`${Section} a.data-footnote-backref:hover`, { 58 | color: semanticColorVars.linkHover, 59 | }) 60 | -------------------------------------------------------------------------------- /src/app/components/mdx/Anchor.tsx: -------------------------------------------------------------------------------- 1 | import { clsx } from 'clsx' 2 | import type { ReactNode } from 'react' 3 | import { useLocation } from 'react-router' 4 | 5 | import { Link } from '../Link.js' 6 | import * as styles from './Anchor.css.js' 7 | import { Autolink } from './Autolink.js' 8 | 9 | type AnchorProps = { 10 | children: ReactNode 11 | className?: string 12 | href?: string 13 | } 14 | 15 | export function Anchor(props: AnchorProps) { 16 | const { children, href } = props 17 | const { pathname } = useLocation() 18 | 19 | // Heading slug links 20 | if ( 21 | children && 22 | typeof children === 'object' && 23 | 'props' in children && 24 | (children.props as { 'data-autolink-icon'?: boolean })['data-autolink-icon'] 25 | ) 26 | return 27 | 28 | // ID links 29 | if (href?.match(/^#/)) 30 | return ( 31 | 32 | ) 33 | 34 | return 35 | } 36 | -------------------------------------------------------------------------------- /src/app/components/mdx/Aside.css.ts: -------------------------------------------------------------------------------- 1 | import { style } from '@vanilla-extract/css' 2 | 3 | export const root = style({}) 4 | -------------------------------------------------------------------------------- /src/app/components/mdx/Aside.tsx: -------------------------------------------------------------------------------- 1 | import { clsx } from 'clsx' 2 | import type { DetailedHTMLProps, HTMLAttributes } from 'react' 3 | 4 | import { Callout, type CalloutProps } from '../Callout.js' 5 | import * as styles from './Aside.css.js' 6 | 7 | export function Aside(props: DetailedHTMLProps, HTMLElement>) { 8 | const className = clsx(props.className, styles.root) 9 | if ('data-callout' in props) 10 | return ( 11 | 12 | {props.children} 13 | 14 | ) 15 | return