diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index a634c85c..00000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.env.example b/.env.example deleted file mode 100644 index 93fcbc16..00000000 --- a/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -APPLICATION_ID= -API_KEY= diff --git a/.env.local.example b/.env.local.example new file mode 100644 index 00000000..84443aee --- /dev/null +++ b/.env.local.example @@ -0,0 +1,18 @@ +# ─── terp-docs local development environment ───────────────────── +# Copy to .env.local and fill in values for local chain testing. +# +# Usage: +# cp .env.local.example .env.local +# # edit values, then: +# pnpm dev + +# Chain environment: "local" for local devnet, unset for mainnet (morocco-1) +NEXT_PUBLIC_CHAIN_ENV=local + +# Contract address overrides (deployed by local-test-env.sh) +# terp721-account billboard contract +NEXT_PUBLIC_TERP721_ACCOUNT= + +# DAO calendar contract (leave empty to resolve at runtime via billboard text records) +NEXT_PUBLIC_CALENDAR= +NEXT_PUBLIC_INFUSER= diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index cd6da0eb..00000000 --- a/.eslintignore +++ /dev/null @@ -1,5 +0,0 @@ -build -node_modules -*.cjs - -sidebars-*.js diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index efd1a26c..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "env": { - "browser": true, - "es2021": true, - "node": true - }, - "settings": { - "react": { - "version": "detect" - } - }, - "extends": ["eslint:recommended", "plugin:react/recommended"], - "parserOptions": { - "ecmaFeatures": { - "jsx": true - }, - "ecmaVersion": "latest", - "sourceType": "module" - }, - "plugins": ["react"], - "rules": { - "react/prop-types": "off", - "no-unused-vars": "warn" - } -} diff --git a/.gitignore b/.gitignore index 592206aa..df4f3a66 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,30 @@ -# Dependencies +# deps /node_modules -# Production -/build -.env +# generated content +.source +.vocs +/dist +# synced product docs (source of truth lives next to the code; see scripts/sync-product-docs.py) +src/pages/guides/validators/frost-privval.mdx -# Generated files -.docusaurus -.cache-loader +# test & build +/coverage +/.next/ +/out/ +/build +*.tsbuildinfo -# Misc +# misc .DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - +*.pem +/.pnp +.pnp.js npm-debug.log* yarn-debug.log* yarn-error.log* + +# others +.env*.local +.vercel +next-env.d.ts \ No newline at end of file diff --git a/.gitpod.yml b/.gitpod.yml deleted file mode 100644 index f2bf4259..00000000 --- a/.gitpod.yml +++ /dev/null @@ -1,11 +0,0 @@ -# This configuration file was automatically generated by Gitpod. -# Please adjust to your needs (see https://www.gitpod.io/docs/introduction/learn-gitpod/gitpod-yaml) -# and commit this file to your remote git repository to share the goodness with others. - -# Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart - -tasks: - - init: yarn install && yarn run build - command: yarn run start - - diff --git a/.husky/commit-msg b/.husky/commit-msg deleted file mode 100755 index fe4c17a2..00000000 --- a/.husky/commit-msg +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npx --no-install commitlint --edit "" diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index 6d395b88..00000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npm run lint:fix diff --git a/.husky/prepare-commit-msg b/.husky/prepare-commit-msg deleted file mode 100755 index 847dd3e7..00000000 --- a/.husky/prepare-commit-msg +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -exec < /dev/tty && npx git-cz --hook || true diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc new file mode 100644 index 00000000..d97428cb --- /dev/null +++ b/.markdownlint-cli2.jsonc @@ -0,0 +1,38 @@ +{ + "config": { + "default": true, + "MD013": false, + "MD033": false, + "MD041": false, + "MD024": false, + "MD025": false, + "MD026": false, + "MD029": false, + "MD034": false, + "MD036": false, + "MD040": true, + "MD001": true, + "MD022": true, + "MD031": true, + "MD032": false, + "MD012": false, + "MD060": false, + "MD046": false, + "MD047": false, + "MD009": false, + "MD010": false, + "MD018": true, + "MD019": true, + "MD023": true, + "MD045": false, + "MD051": false, + "MD052": false, + "MD053": false, + "MD055": false, + "MD056": false, + "MD028": false, + "MD042": false + }, + "globs": ["content/docs/**/*.{md,mdx}"], + "ignores": ["**/node_modules/**"] +} diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 00000000..d9fdfb57 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,41 @@ +{ + "default": true, + "MD001": true, + "MD003": false, + "MD004": false, + "MD007": false, + "MD009": false, + "MD010": false, + "MD012": false, + "MD013": false, + "MD014": false, + "MD022": false, + "MD024": false, + "MD025": false, + "MD026": false, + "MD028": false, + "MD029": false, + "MD030": false, + "MD031": false, + "MD032": false, + "MD033": false, + "MD034": false, + "MD035": false, + "MD036": false, + "MD037": false, + "MD039": false, + "MD040": true, + "MD041": false, + "MD042": false, + "MD045": false, + "MD046": false, + "MD047": false, + "MD051": false, + "MD052": false, + "MD053": false, + "MD055": false, + "MD056": false, + "MD058": false, + "MD059": false, + "MD060": false +} diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 97186f4a..00000000 --- a/.prettierignore +++ /dev/null @@ -1,2 +0,0 @@ -# autogenerated files -docs/*ui-kit/reference/**/*.md diff --git a/.releaserc.js b/.releaserc.js deleted file mode 100644 index 46f74d25..00000000 --- a/.releaserc.js +++ /dev/null @@ -1,35 +0,0 @@ -const mainConfig = { - branches: ['main'], - plugins: [ - '@semantic-release/commit-analyzer', - '@semantic-release/release-notes-generator', - '@semantic-release/changelog', - [ - '@semantic-release/npm', - { - npmPublish: false, - tarballDir: 'dist' - } - ], - [ - '@semantic-release/git', - { - assets: [ - 'package.json', - 'package-lock.json', - 'CHANGELOG.md' - ], - message: 'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}\n\n\nskip-checks: true' - } - ], - [ - '@semantic-release/github', - { - assets: 'dist/*.tgz' - } - ] - ], - repositoryUrl: 'https://github.com/terpnetwork/docs' -}; - -module.exports = mainConfig; diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 8f19618b..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "emmet.includeLanguages": { - "mdx": "javascriptreact" - } -} diff --git a/CHANGELOG.md b/ADDING_TO_ECO.md similarity index 100% rename from CHANGELOG.md rename to ADDING_TO_ECO.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 14c49b48..304fce2c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,86 +1,199 @@ # Contributing -The following is a set of guidelines for contributing. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. +We are thankful for you helping build the Terp Network docs. This guide covers the project layout, how to add things, and what we expect from contributions. -## Table of Contents -1. [Styleguides](#styleguides) -2. [What should I know before I get started?](#what-should-i-know-before-i-get-started) -3. [How Can I contribute?](#how-can-i-contribute) -4. [Code Contribution](#code-contribution) +## Requirements -# Guidelines +Be respectful. With our documentation, comes the relance on a stable, veriiable basis. If we are inaccurate or unorganized, we are not being respectful of our users time. -The following are the guidelines we request you to follow in order to contribute to this project. +## Expectations -## Styleguides +- Run `pnpm dev` and check your changes render before opening a PR. +- Every MDX file needs valid frontmatter. At minimum: `title` (string). Empty files or null fields break the build. +- Interactive components must be `'use client'` and wrapped in `not-prose` when used inside MDX. +- Keep PRs focused. One feature or fix per branch. -### Commit Messages +## Page status and completeness -The commit messages should follow the following pattern: +Frontmatter `status` tells readers (and CI) how ready a page is: + +| Value | Meaning | +|-------|---------| +| `complete` | Runnable steps or full reference; links work | +| `partial` | Real prose but gaps, TODOs, or scaffold markers | +| `stub` | Heading outline only — **required** if the body is headings without substantive content | + +```yaml +--- +title: Example +description: One-line expectation for the reader +status: complete +--- +``` + +**Every non-stub page should include:** + +- Accurate `description` (sets expectations; no “10 minutes” if empty) +- `## Related Concepts` and/or `## Further Reading` with **real** links (siblings + cross-section when relevant) +- For on-chain operations: a short verify habit — build/compare/decide (see trustlessness guides) + +**Heading-only pages** must set `status: stub`. Prefer linking the front door to complete pages instead of promising depth that does not exist. + +```bash +# Detect unlabeled heading-only pages (exit 1 if any) +bash scripts/check-stubs.sh + +# Frontmatter-only empties +pnpm check-empty +``` + +### Scaffold markers (interactive TODOs) + +When a diagram/demo is planned but not built, use **exactly** this line form (machine-scanned): + +```markdown +> **Scaffold:** `diagram` · id:`stable-kebab-id` · P2 · one-line purpose +``` + +| Field | Values | +|-------|--------| +| type | `diagram`, `flow`, `visualizer`, `demo`, `chart`, `other` | +| id | unique kebab-case (`scf-…` auto-ids are fine) | +| priority | `P1` front-door, `P2` core, `P3` polish | + +| Type | When | Prefer | +|------|------|--------| +| `diagram` | Static structure | Mermaid / `DynamicMermaidDiagram` | +| `flow` | Ordered steps over time | Mermaid sequence/flowchart | +| `visualizer` | User-tweaked inputs → outputs | `components/diagrams/` | +| `demo` | Live chain/API interaction | Client component + query hooks | +| `chart` | Distribution / timeline | Chart component or static SVG | ```bash -feat: Description # if a new feature is added -fix: Description # if a bug is fixed -refactor: Description # if code is refactored -docs: Description # if documentation is added -lint: Description # if a lint issue is fixed +# List / fail on unlabeled scaffolds +pnpm check-scaffolds + +# Auto-label + regenerate inventory page +pnpm check-scaffolds --label --write +# → content/docs/resources/scaffolds.md +# → scripts/scaffold-inventory.json +``` + +Do not invent product behavior on stub pages. Fill content only from source of truth (chain params, shipped tools, existing complete guides). + +## Project Layout + ``` +app/ + layout.tsx — root layout (QueryProvider + RootProvider only — no wallet) + global.css — all CSS: Tailwind imports, fumadocs + shadcn vars, brand theme + docs/ — Next.js route for doc pages + +lib/ + queries/ — TanStack Query client, fetchers, provider (see its README) + hooks/ — React Query hooks, one file per domain (see its README) + openapi.ts — OpenAPI spec config and source generation + source.ts — fumadocs source loader (MDX + OpenAPI combined) + utils.ts — cn() via clsx + twMerge (used by shadcn components) + cn.ts — cn() via twMerge only (older code) + +components/ + ui/ — shadcn primitives, managed by CLI (don't hand-edit) + calendar/ — community calendar feature + ai/ — AI page actions (copy, open-in-Claude, etc.) + +content/docs/ — MDX documentation pages +static/api/ — OpenAPI YAML specs +``` + +Each `lib/` subfolder has its own README with usage examples and conventions. Start there when working on data fetching or hooks. + +## Adding Things + +### New hook + +Create `lib/hooks/use-.ts`. See `lib/hooks/README.md` for the pattern. + +### New interactive component -### Issues +1. Create a folder under `components/` for your feature. +2. Use shadcn primitives from `components/ui/` for common UI. +3. Export a composite component from `index.tsx`. +4. Register it in `mdx-components.tsx` so MDX pages can use ``. +5. Wrap the outermost element in `not-prose` to prevent fumadocs prose styles from bleeding in. + +**Keep the root layout light.** Do not mount wallet (`@goblinhunt/cosmes`, ~77MB), calendar, or tree demos on `app/layout.tsx`. Patterns: + +- Diagrams / trees → import a **per-demo** file, e.g. `@/components/diagrams/dynamic/merkle-proof` (not the barrel `dynamic.tsx`, or one page compiles every visualizer) +- **No nested wallets / dApps in MDX** — do not mount `ConnectCalendar`, `WalletProvider`, Keplr connect buttons, or similar on docs pages. Wallet content is **written guides** under `/docs/guides/authentication/wallets` only. Users open extensions themselves. +- OpenAPI UI → lazy `import()` only on API doc routes +- Never put cosmes / wallet / calendar on `app/layout.tsx` + +### New shadcn primitive ```bash -update: Description # if an update is required for a feature -bug: Description # if there is a bug in a particular feature -suggestion: Description # if you want to suggest a better way to implement a feature +pnpm dlx shadcn@latest add ``` -### Code Styleguide +Config lives in `components.json` (style: new-york, icons: lucide). + +### New docs page + +Add a `.mdx` file under `content/docs/
/`. Update the section's `meta.json` to include the new slug. -The code should satisfy the following: +### New API spec -- Have meaningful variable names, either in `snake_case` or `camelCase`. -- Have no `lint` issues. -- Have meaningful file names, directory names and directory structure. -- Have a scope for easy fixing, refactoring and scaling. +1. Drop the YAML file in `static/api/`. +2. Add entries to `OPENAPI_INPUT` and `OPENAPI_SPECS` in `lib/openapi.ts`. +3. Pages generate at `/docs/api/` on next build. -## What should I know before I get started +## Brand & Styles -You can contribute to any of the features you want, here's what you need to know: +### Two color systems -- How the project works. -- The technology stack used for the project. -- A brief idea about writing documentation. +Both live in `app/global.css` and are branded to the same Terp palette: -## How Can I Contribute +| System | Prefix | Used by | +|--------|--------|---------| +| Fumadocs | `--color-fd-*` | Docs chrome: sidebar, nav, page layout | +| shadcn | `--background`, `--primary`, etc. | Interactive components: buttons, cards, selects | -You can contribute by: +If you change a color, update both sets. -- Reporting Bugs -- Suggesting Enhancements -- Code Contribution -- Pull Requests +### Terp palette -## Code Contribution +| Role | Light | Dark | +|------|-------|------| +| Primary (purple) | `hsl(265, 50%, 45%)` | `#bd93f9` | +| Accent (lavender) | `hsla(265, 45%, 40%, 0.2)` | `hsla(265, 50%, 55%, 0.25)` | +| Destructive (coral) | `#FA5757` | `#fe7d7d` | +| Green (neon lime) | `#cfffcf` | `#cfffcf` | +| Green (mint) | `#98e8c1` | `#98e8c1` | -1. Checkout the latest `main` branch to make sure the feature hasn't been implemented or the bug hasn't been fixed yet. -2. Check the issue tracker to make sure someone already hasn't requested it and/or contributed to it. -3. Fork it! -4. Create your feature branch: `git checkout -b feature/my-new-feature` -5. Add your changes: `git add .` -6. Commit your changes: `git commit -am 'feat: Add some feature'` -7. Push to the branch: `git push -u origin feature/my-new-feature` -8. Submit a pull request :sunglasses: +### Dark mode -### Pull Requests +Fumadocs handles the toggle via `.dark` on ``. Both variable systems define dark overrides in `global.css`. Always check both modes. -Make sure to document the contributions well in the pull request. -Pull requests should have: +### Two `cn()` utilities -- A concise commit message. -- A description of what was changed/added. +- `lib/utils.ts` — `clsx` + `twMerge`. Preferred for new code. +- `lib/cn.ts` — re-exports `twMerge` directly. Used by older code. + +## Quick Reference + +```bash +pnpm dev # start dev server +pnpm build # production build (catches frontmatter + type errors) +pnpm dlx shadcn@latest add # add a shadcn component +``` -Others will give constructive feedback. -This is a time for discussion and improvements, -and making the necessary changes will be required before we can -merge the contribution. +| Task | Where | +|------|-------| +| Add a query hook | `lib/hooks/use-.ts` | +| Add query infra | `lib/queries/` | +| Add a shadcn primitive | `pnpm dlx shadcn@latest add ` | +| Add an interactive feature | `components//index.tsx` + `mdx-components.tsx` | +| Add a docs page | `content/docs/
/.mdx` + `meta.json` | +| Add an API spec | `static/api/.yaml` + `lib/openapi.ts` | +| Change brand colors | both `--color-fd-*` and `--*` in `app/global.css` | diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 36358ee2..00000000 --- a/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM node:16-alpine as builder -# Set the working directory to /app inside the container -WORKDIR /app -# Copy app files -COPY . . -# Install dependencies (npm ci makes sure the exact versions in the lockfile gets installed) -RUN rm -rf node_modules && yarn install --frozen-lockfile -# Build the app -RUN yarn run build - -# Bundle static assets with nginx -FROM nginx:1.21.0-alpine as production -ENV NODE_ENV production -# Copy built assets from `builder` image -COPY --from=builder /app/build /usr/share/nginx/html -# Add your nginx.conf -COPY nginx.conf /etc/nginx/conf.d/default.conf -# Expose port -EXPOSE 80 -# Start nginx -CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/README.md b/README.md index 62cf83ab..b266e355 100644 --- a/README.md +++ b/README.md @@ -7,16 +7,16 @@

Terp-Core Docs

- Terp-Core' documentation portal, built with Docusaurus and inspired bye Dyte's configuration and template. + Terp-Core' documentation portal,
Explore the docs »

View Demo · - Report Bug + Report Bug · - Request Feature + Request Feature

@@ -39,24 +39,8 @@ -## TODO -- add table for available statesync, wasm, & snapshot endpoints -- add initial cryptography concepts -- make automatic update to latest versions -- reference docker images - ## About The Project -[Docusaurus](https://docusaurus.io/) is a static site generator that helps you ship beautiful, accessible docs. For building our [documentation](https://docs.terp.network) portal, we have made certain modifications over the template generated by [Docusaurus](https://docusaurus.io) to be able to properly showcase Terp-core, Cosmwasm and Javascript SDKs - -### Built With - -- [Docusaurus](https://docusaurus.io/) -- [React](https://reactjs.org/) -- [Tailwind](https://tailwindcss.com/) - - - ## Getting Started This section describes how you can get our documentation portal up and running on your machine. @@ -68,82 +52,29 @@ This section describes how you can get our documentation portal up and running o ### Installation -1. Clone the repo +This site is built with [Vocs](https://vocs.dev) (Vite + Waku). Pages live in `content/docs` and are mounted as `src/pages`. ```sh -git clone https://github.com/terpnetworkcommunity/docs.git +# 1. Clone the repo +git clone https://github.com/terpnetwork/docs.git +# 2. Install NPM packages +pnpm install +# 3. Run the app (http://localhost:5173) +pnpm run dev ``` -2. Install NPM packages - -```sh -npm install -``` - -3. Run the app - -```sh -npm start -``` +Production build: `pnpm build`. Preview: `pnpm preview`. The previous Next/Fumadocs app is still in the tree (`pnpm next:dev`) while the migration finishes. ## Usage - - ### Writing Documentation -To just edit older documentation, go to the specified versioned folder for a section, for example, you want to edit documentation for React SDK v0.25.x, open up [react_versioned_docs/version-0.25.x](./react_versioned_docs/version-0.25.x) and edit the required files there. - -To create a new version inside a section, for example, flutter. Make your changes in [docs/flutter](./docs/flutter). The `./docs` folder consists of the `next` version, which is unpublished, and is where you add your newer or _next_ version of documentation. - -After your changes are done, to create a version, run the following command: - -```sh -npm run docusaurus docs:version:flutter 1.2.3 -``` - -This will create a new version `1.2.3` for flutter. - -Reference: https://docusaurus.io/docs/versioning - ### To add new sections -Create a new section in docusaurus by adding a new plugin entry in [docusaurus.config.js](./docusaurus.config.js). - -If you're adding a new section, just add new section to `SECTIONS[]` array with the `defineSection()` utility easily. - -Now, run `npm start` and you can access your Go docs at http://localhost:3000/go/introduction - -Then, you can create versions and edit older versions as mentioned above. - ### Adding new docs to the Context Switcher -To add a newly created section to the Sections Menu, edit [./src/sections.js](src/sections.js). - -For example, for a section go, you will add: - -```jsx -import { GoIcon } from '../assets/icons'; - -const SECTIONS = [ - // ... - { - id: 'go', - name: 'Go', - icon: GoIcon, - section: false, // if it shouldn't have a sections menu - }, -] -``` - -You'll need to create a GoIcon component too. - -That is it! - - - ## Contributing @@ -155,12 +86,11 @@ Contributions are what make the open source community such an amazing place to b Contributions, issues, and feature requests are welcome! Give a ⭐️ if you like this project! - - To build the docker image: + ```sh -``` +``` diff --git a/TODO.md b/TODO.md new file mode 100644 index 00000000..93916f2b --- /dev/null +++ b/TODO.md @@ -0,0 +1,19 @@ +# TODO + +## Docs +- acutal documentation +- ~~openapi integration~~ +- ~~tanstack query design~~ +- [chain registry support] +- ~~ibc-channel support~~ (partial: guides/ibc/* including hooks) +- docker container support +- wasm & circuit support +- ~~test network faucet support~~ (guides/network/faucet.md) +- ~~connect to terp network~~ (overview/quickstart + guides) +- deployed contract page: display information about all deployed contracts: inspo by ) { + return {children}; +} diff --git a/app/(home)/page.tsx b/app/(home)/page.tsx new file mode 100644 index 00000000..c936084d --- /dev/null +++ b/app/(home)/page.tsx @@ -0,0 +1,16 @@ +import Link from 'next/link'; + +export default function HomePage() { + return ( +
+

Hello World

+

+ You can open{' '} + + /docs + {' '} + and see the documentation. +

+
+ ); +} diff --git a/app/api/page.tsx b/app/api/page.tsx new file mode 100644 index 00000000..0cfd9749 --- /dev/null +++ b/app/api/page.tsx @@ -0,0 +1,18 @@ +import { getOpenAPISlug, resolveOpenAPIDocument } from '@/lib/openapi'; +import { redirect } from 'next/navigation'; + +type SearchParams = { + v?: string; +}; + +export default async function LegacyAPIPage({ + searchParams, +}: { + searchParams: Promise; +}) { + const params = await searchParams; + const document = resolveOpenAPIDocument(params.v); + const slug = getOpenAPISlug(document); + + redirect(`/docs/api/${slug}`); +} diff --git a/app/api/search/route.ts b/app/api/search/route.ts new file mode 100644 index 00000000..7ba7e823 --- /dev/null +++ b/app/api/search/route.ts @@ -0,0 +1,7 @@ +import { source } from '@/lib/source'; +import { createFromSource } from 'fumadocs-core/search/server'; + +export const { GET } = createFromSource(source, { + // https://docs.orama.com/docs/orama-js/supported-languages + language: 'english', +}); diff --git a/app/brain/page.tsx b/app/brain/page.tsx new file mode 100644 index 00000000..da211912 --- /dev/null +++ b/app/brain/page.tsx @@ -0,0 +1,7 @@ +export default function BrainPage() { + return ( +
+

Brain graph coming soon.

+
+ ); +} diff --git a/app/docs/[[...slug]]/page.tsx b/app/docs/[[...slug]]/page.tsx new file mode 100644 index 00000000..292d2e9b --- /dev/null +++ b/app/docs/[[...slug]]/page.tsx @@ -0,0 +1,99 @@ +import { getPageImage, source } from '@/lib/source'; +import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page'; +import { notFound } from 'next/navigation'; +import { getMDXComponents } from '@/mdx-components'; +import type { Metadata } from 'next'; +import { createRelativeLink } from 'fumadocs-ui/mdx'; +import { LLMCopyButton, ViewOptions } from '@/components/ai/page-actions'; +import { gitConfig } from '@/lib/layout.shared'; + +export default async function Page(props: PageProps<'/docs/[[...slug]]'>) { + const params = await props.params; + const page = source.getPage(params.slug); + if (!page) notFound(); + + // Support async mode for lazy-loaded community/external MDX docs + const data = 'load' in page.data && typeof page.data.load === 'function' + ? await page.data.load() + : page.data; + + if ('getAPIPageProps' in data && typeof data.getAPIPageProps === 'function') { + // Lazy-load OpenAPI UI only for API routes — not every MDX doc page + const { APIPage } = await import('@/lib/openapi'); + const apiPageProps = data.getAPIPageProps(); + const operations = apiPageProps.operations ?? []; + const webhooks = apiPageProps.webhooks ?? []; + const toc = 'toc' in data ? data.toc : []; + const full = 'full' in data ? data.full : false; + // Type guard: check for a property that only exists in the extended type + if (!('title' in data)) { + notFound(); // or handle fallback + } + + + if (operations.length === 0 && webhooks.length === 0) { + return ( + + {data.title} + {data.description} + +

No routes are defined in this OpenAPI specification yet.

+
+
+ ); + } + + return ( + + + + + + ); + } + const full = 'full' in data ? data.full : false; + if (!('body' in data)) { + notFound(); + } + const MDX = data.body; + + return ( + + {page.data.title} + {page.data.description} +
+ + +
+ + + +
+ ); +} + +export async function generateStaticParams() { + return source.generateParams(); +} + +export async function generateMetadata(props: PageProps<'/docs/[[...slug]]'>): Promise { + const params = await props.params; + const page = source.getPage(params.slug); + if (!page) notFound(); + + return { + title: page.data.title, + description: page.data.description, + openGraph: { + images: getPageImage(page).url, + }, + }; +} diff --git a/app/docs/layout.tsx b/app/docs/layout.tsx new file mode 100644 index 00000000..fff5a1cd --- /dev/null +++ b/app/docs/layout.tsx @@ -0,0 +1,17 @@ +import { source } from '@/lib/source'; +import { DocsLayout } from 'fumadocs-ui/layouts/docs'; +import { baseOptions } from '@/lib/layout.shared'; + +export default function Layout({ children }: LayoutProps<'/docs'>) { + return ( + + {children} + + ); +} diff --git a/app/global.css b/app/global.css new file mode 100644 index 00000000..18f7fb61 --- /dev/null +++ b/app/global.css @@ -0,0 +1,291 @@ +@import 'tailwindcss'; +@import 'fumadocs-ui/css/neutral.css'; +@import 'fumadocs-ui/css/preset.css'; +@import 'fumadocs-openapi/css/preset.css'; +@import "tw-animate-css"; +@import "shadcn/tailwind.css"; + +@custom-variant dark (&:is(.dark *)); + +/* ── Terp Network brand theme ───────────────────────────────────── + Green: #cfffcf (neon lime) / #98e8c1 (mint) + Purple: #bd93f9 / #d3b3e9 + Coral: #FA5757 / #fe7d7d + Brown: #533b3b (light headings) + ──────────────────────────────────────────────────────────────── */ + +/* ── Light mode ────────────────────────────────────────────────── */ +@theme { + --color-fd-background: hsla(0, 0%, 97%, 0.82); + --color-fd-foreground: hsl(0, 5%, 12%); + --color-fd-muted: hsla(0, 0%, 93%, 0.88); + --color-fd-muted-foreground: hsl(0, 0%, 42%); + --color-fd-popover: hsl(0, 0%, 98%); + --color-fd-popover-foreground: hsl(0, 0%, 12%); + --color-fd-card: hsla(0, 0%, 95%, 0.75); + --color-fd-card-foreground: hsl(0, 5%, 12%); + --color-fd-border: hsla(0, 0%, 72%, 0.35); + --color-fd-primary: hsl(265, 50%, 45%); + --color-fd-primary-foreground: hsl(0, 0%, 98%); + --color-fd-secondary: hsla(0, 0%, 91%, 0.85); + --color-fd-secondary-foreground: hsl(0, 5%, 12%); + --color-fd-accent: hsla(265, 45%, 40%, 0.2); + --color-fd-accent-foreground: hsl(265, 45%, 25%); + --color-fd-ring: hsl(265, 45%, 50%); +} + +/* ── Dark mode ─────────────────────────────────────────────────── */ +.dark { + --color-fd-background: hsla(260, 8%, 5%, 0.82); + --color-fd-foreground: hsl(80, 100%, 95%); + --color-fd-muted: hsla(260, 6%, 10%, 0.88); + --color-fd-muted-foreground: hsla(0, 0%, 65%, 0.8); + --color-fd-popover: hsl(260, 8%, 7%); + --color-fd-popover-foreground: hsl(80, 40%, 90%); + --color-fd-card: hsla(260, 6%, 6.5%, 0.7); + --color-fd-card-foreground: hsl(80, 100%, 95%); + --color-fd-border: hsla(265, 25%, 40%, 0.18); + --color-fd-primary: hsl(265, 90%, 78%); + --color-fd-primary-foreground: hsl(260, 20%, 6%); + --color-fd-secondary: hsla(260, 6%, 12%, 0.85); + --color-fd-secondary-foreground: hsl(80, 40%, 90%); + --color-fd-accent: hsla(265, 50%, 55%, 0.25); + --color-fd-accent-foreground: hsl(265, 90%, 78%); + --color-fd-ring: hsl(265, 60%, 65%); + --background: hsl(260, 8%, 5%); + --foreground: hsl(80, 100%, 95%); + --card: hsla(260, 6%, 6.5%, 0.7); + --card-foreground: hsl(80, 100%, 95%); + --popover: hsl(260, 8%, 7%); + --popover-foreground: hsl(80, 40%, 90%); + --primary: hsl(265, 90%, 78%); + --primary-foreground: hsl(260, 20%, 6%); + --secondary: hsla(260, 6%, 12%, 0.85); + --secondary-foreground: hsl(80, 40%, 90%); + --muted: hsla(260, 6%, 10%, 0.88); + --muted-foreground: hsla(0, 0%, 65%, 0.8); + --accent: hsla(265, 50%, 55%, 0.25); + --accent-foreground: hsl(265, 90%, 78%); + --destructive: hsl(0, 93%, 74%); + --border: hsla(265, 25%, 40%, 0.18); + --input: hsla(265, 25%, 40%, 0.25); + --ring: hsl(265, 60%, 65%); + --chart-1: hsl(265, 90%, 78%); + --chart-2: hsl(150, 50%, 55%); + --chart-3: hsl(0, 93%, 74%); + --chart-4: hsl(265, 70%, 65%); + --chart-5: hsl(150, 70%, 70%); + --sidebar: hsl(260, 8%, 5%); + --sidebar-foreground: hsl(80, 100%, 95%); + --sidebar-primary: hsl(265, 90%, 78%); + --sidebar-primary-foreground: hsl(80, 100%, 95%); + --sidebar-accent: hsla(265, 50%, 55%, 0.25); + --sidebar-accent-foreground: hsl(265, 90%, 78%); + --sidebar-border: hsla(265, 25%, 40%, 0.18); + --sidebar-ring: hsl(265, 60%, 65%); +} + +/* ── Sidebar — frosted glass ──────────────────────────────────── */ +#nd-sidebar { + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); +} + +.dark #nd-sidebar { + --color-fd-muted: hsla(260, 5%, 8%, 0.7); + --color-fd-secondary: hsla(260, 5%, 10%, 0.7); + --color-fd-muted-foreground: hsl(0, 0%, 55%); +} + +/* ── Background ───────────────────────────────────────────────── */ +body { + background-color: hsl(0, 0%, 97%); +} + +.dark body { + background-color: hsl(260, 8%, 4%); +} + +/* Glyph watermark — single centered, SVG has its own neon glow */ +.glyph-bg { + position: fixed; + inset: 0; + z-index: 0; + background-image: url('/terp-glyph-light.svg'); + background-repeat: no-repeat; + background-position: center; + background-size: 80vmin; + filter: blur(12px); + opacity: 0.35; + pointer-events: none; +} + +.dark .glyph-bg { + background-image: url('/terp-glyph.svg'); + filter: blur(16px); + opacity: 0.2; +} + +body > *:not(.glyph-bg) { + position: relative; + z-index: 1; +} + +/* ── Prose overrides — headings & links via prose variables ───── */ +.prose { + --tw-prose-headings: hsl(265, 45%, 30%); + --tw-prose-links: #c94040; +} + +.dark .prose { + --tw-prose-headings: #d3b3e9; + --tw-prose-links: #fe7d7d; +} + +/* ── Active links — purple highlight ──────────────────────────── */ +a[data-active='true'], +[aria-current='page'] { + color: hsl(265, 50%, 45%); +} + +.dark a[data-active='true'], +.dark [aria-current='page'] { + color: #bd93f9; +} + +/* ── Content links — coral hover ───────────────────────────────── */ +.prose a:hover { + color: #FA5757; +} + +/* ── Code blocks — green tinted ───────────────────────────────── */ +.dark pre { + background: hsl(150, 8%, 6%) !important; + border: 1px solid hsla(150, 30%, 40%, 0.1); +} + +.dark code { + color: #cfffcf; +} + +/* ── Calendar widget — match fumadocs theme ──────────────────── */ +.calendar-widget { + --background: var(--color-fd-secondary); + --foreground: var(--color-fd-foreground); + --accent: var(--color-fd-accent); + --accent-foreground: var(--color-fd-accent-foreground); + --primary: var(--color-fd-primary); + --primary-foreground: var(--color-fd-primary-foreground); + --muted-foreground: var(--color-fd-muted-foreground); +} + +/* ── Calendar event dots ─────────────────────────────────────── */ +.calendar-has-events button::after { + content: ''; + display: block; + width: 4px; + height: 4px; + border-radius: 50%; + background: hsl(265, 50%, 45%); + margin: 2px auto 0; +} + +.dark .calendar-has-events button::after { + background: #bd93f9; +} + +/* ── Inline code — purple tint ────────────────────────────────── */ +:not(pre) > code { + background: hsla(265, 20%, 50%, 0.08); + color: hsl(265, 40%, 35%); + border: 1px solid hsla(265, 30%, 50%, 0.1); +} + +.dark :not(pre) > code { + background: hsla(268, 30%, 50%, 0.1); + color: #d3b3e9; + border: 1px solid hsla(268, 40%, 50%, 0.12); +} + +@theme inline { + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --radius-2xl: calc(var(--radius) + 8px); + --radius-3xl: calc(var(--radius) + 12px); + --radius-4xl: calc(var(--radius) + 16px); + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +/* ── shadcn vars — branded to Terp palette ───────────────────── */ +:root { + --radius: 0.625rem; + --background: hsl(0, 0%, 97%); + --foreground: hsl(0, 5%, 12%); + --card: hsla(0, 0%, 95%, 0.75); + --card-foreground: hsl(0, 5%, 12%); + --popover: hsl(0, 0%, 98%); + --popover-foreground: hsl(0, 0%, 12%); + --primary: hsl(265, 50%, 45%); + --primary-foreground: hsl(0, 0%, 98%); + --secondary: hsla(0, 0%, 91%, 0.85); + --secondary-foreground: hsl(0, 5%, 12%); + --muted: hsla(0, 0%, 93%, 0.88); + --muted-foreground: hsl(0, 0%, 42%); + --accent: hsla(265, 45%, 40%, 0.15); + --accent-foreground: hsl(265, 45%, 25%); + --destructive: hsl(0, 92%, 66%); + --border: hsla(0, 0%, 72%, 0.35); + --input: hsla(0, 0%, 72%, 0.35); + --ring: hsl(265, 45%, 50%); + --chart-1: hsl(265, 50%, 45%); + --chart-2: hsl(150, 50%, 55%); + --chart-3: hsl(0, 92%, 66%); + --chart-4: hsl(265, 70%, 65%); + --chart-5: hsl(150, 70%, 70%); + --sidebar: hsl(0, 0%, 97%); + --sidebar-foreground: hsl(0, 5%, 12%); + --sidebar-primary: hsl(265, 50%, 45%); + --sidebar-primary-foreground: hsl(0, 0%, 98%); + --sidebar-accent: hsla(265, 45%, 40%, 0.15); + --sidebar-accent-foreground: hsl(265, 45%, 25%); + --sidebar-border: hsla(0, 0%, 72%, 0.35); + --sidebar-ring: hsl(265, 45%, 50%); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } +} \ No newline at end of file diff --git a/app/icon.svg b/app/icon.svg new file mode 100644 index 00000000..d686a1c7 --- /dev/null +++ b/app/icon.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 00000000..eb78b8b3 --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,45 @@ +import { RootProvider } from 'fumadocs-ui/provider/next'; +import '@/public/global.css'; +import { Inter } from 'next/font/google'; +import type { Metadata } from 'next'; + +const inter = Inter({ + subsets: ['latin'], +}); + +export const metadata: Metadata = { + title: { + default: 'Terp Network Docs', + template: '%s | Terp Network Docs', + }, + description: 'Documentation for Terp Network — CosmWasm smart contracts, validators, governance, and developer guides.', + metadataBase: new URL('https://docs.terp.network'), + openGraph: { + type: 'website', + siteName: 'Terp Network Docs', + title: 'Terp Network Docs', + description: 'Documentation for Terp Network — CosmWasm smart contracts, validators, governance, and developer guides.', + images: [{ url: '/og-banner.svg', width: 1200, height: 630, alt: 'Terp Network' }], + }, + twitter: { + card: 'summary_large_image', + title: 'Terp Network Docs', + description: 'Documentation for Terp Network', + images: ['/og-banner.svg'], + }, +}; + +/** + * Docs-only root: no React Query, no wallet, no calendar. + * Wallet content is written guides under /docs/guides/authentication/wallets. + */ +export default function Layout({ children }: LayoutProps<'/'>) { + return ( + + +