From 0153faa90022c2cb11a90fd89a8f4ba7578505e7 Mon Sep 17 00:00:00 2001 From: Thomas Osmonson Date: Fri, 7 Aug 2020 15:45:59 -0500 Subject: [PATCH] feat: copy button, formatting, link previews --- lib/mdx-frontmatter-loader.js | 2 +- lib/mdx-loader.js | 70 ---- package.json | 16 +- public/images/todo-list-app.png | Bin 0 -> 26307 bytes src/common/navigation.yaml | 4 +- .../custom-blocks/page-reference.tsx | 75 +++- src/components/feedback.tsx | 6 +- src/components/icons/clipboard-check.tsx | 11 + src/components/icons/clipboard.tsx | 10 + src/components/icons/copy.tsx | 10 + src/components/icons/sitemap.tsx | 13 + src/components/layouts/markdown-wrapper.tsx | 99 ------ src/components/mdx/components/code.tsx | 140 +++++--- src/components/mdx/components/link.tsx | 131 ++++++- src/components/mdx/markdown-wrapper.tsx | 34 ++ src/components/mdx/md-contents.tsx | 12 +- src/components/mdx/mdx-components.tsx | 5 +- src/components/mdx/overrides.tsx | 21 -- src/components/page-meta.tsx | 51 +++ src/components/page-top.tsx | 44 +++ src/components/search.tsx | 8 +- src/components/tooltip.tsx | 4 +- src/pages/authentication/building-todo-app.md | 38 ++- src/pages/authentication/connect.md | 3 +- src/pages/authentication/overview.md | 5 - src/pages/authentication/profiles.md | 8 +- src/pages/build-an-app.md | 2 +- src/pages/data-indexing/collaborate.md | 2 +- src/pages/data-indexing/integrate.md | 2 +- src/pages/data-indexing/models.md | 2 +- src/pages/data-indexing/overview.md | 2 +- src/pages/data-indexing/server-extras.md | 4 - src/pages/data-storage/authentication.md | 2 +- src/pages/data-storage/collection-type.md | 2 +- src/pages/data-storage/collections.md | 13 +- src/pages/data-storage/overview.md | 2 +- src/pages/data-storage/storage-guide.md | 2 +- src/pages/data-storage/storage-write-read.md | 2 +- src/pages/ecosystem/address-confirmation.md | 5 +- src/pages/ecosystem/contributing.md | 2 +- src/pages/ecosystem/faq.md | 16 - src/pages/ecosystem/overview.md | 1 + src/pages/ecosystem/stacks-token-holders.md | 25 +- src/pages/ecosystem/stacks-token.md | 1 + src/pages/index.md | 2 +- src/pages/mining.md | 2 +- src/pages/naming-services/architecture.md | 2 +- .../build-profile-search-index.md | 6 +- src/pages/naming-services/choose-name.md | 4 - src/pages/naming-services/comparison.md | 2 +- src/pages/naming-services/create-namespace.md | 2 +- src/pages/naming-services/did.md | 2 +- src/pages/naming-services/forks.md | 2 +- src/pages/naming-services/manage-names.md | 4 - src/pages/naming-services/namespaces.md | 2 +- src/pages/naming-services/overview.md | 2 +- src/pages/naming-services/register-name.md | 5 - src/pages/naming-services/resolve-name.md | 5 - .../naming-services/subdomains-tutorial.md | 9 +- src/pages/naming-services/subdomains.md | 13 +- src/pages/references/blockstack-cli.md | 5 +- src/pages/references/clarity-language.md | 4 - src/pages/references/deploy-tips.md | 9 +- src/pages/references/faqs.md | 54 --- src/pages/references/glossary.md | 3 +- src/pages/references/stacks-blockchain.md | 4 +- src/pages/references/stacks-rpc-api.md | 2 +- .../smart-contracts/cli-wallet-quickstart.md | 8 +- src/pages/smart-contracts/counter-tutorial.md | 3 +- .../smart-contracts/hello-world-tutorial.md | 13 +- src/pages/smart-contracts/install-source.md | 3 +- src/pages/smart-contracts/overview.md | 38 ++- src/pages/smart-contracts/principals.md | 3 +- .../smart-contracts/running-a-testnet-node.md | 6 + .../smart-contracts/signing-transactions.md | 5 +- .../smart-contracts/testing-contracts.md | 6 +- .../atlas/how-atlas-works.md | 2 +- src/pages/stacks-blockchain/atlas/overview.md | 2 +- src/pages/stacks-blockchain/atlas/usage.md | 2 - src/pages/stacks-blockchain/best-practices.md | 3 +- src/pages/stacks-blockchain/install-api.md | 12 +- .../stacks-blockchain/installing-memcached.md | 5 +- src/pages/stacks-blockchain/overview.md | 2 +- src/pages/stacks-blockchain/wire-format.md | 7 +- src/pages/stacks-wallet/install.md | 5 +- src/pages/stacks-wallet/overview.md | 5 +- src/pages/stacks-wallet/security.md | 7 +- src/pages/stacks-wallet/troubleshooting.md | 65 ---- src/pages/stacks-wallet/usage.md | 12 +- src/pages/storage-hubs/amazon-s3-deploy.md | 17 +- src/pages/storage-hubs/config-schema.md | 3 +- .../storage-hubs/digital-ocean-deploy.md | 3 +- src/pages/storage-hubs/gaia-admin.md | 2 +- src/pages/storage-hubs/hello-hub-choice.md | 3 +- src/pages/storage-hubs/overview.md | 4 - yarn.lock | 322 +++++++++++------- 96 files changed, 872 insertions(+), 748 deletions(-) delete mode 100644 lib/mdx-loader.js create mode 100644 public/images/todo-list-app.png create mode 100644 src/components/icons/clipboard-check.tsx create mode 100644 src/components/icons/clipboard.tsx create mode 100644 src/components/icons/copy.tsx create mode 100644 src/components/icons/sitemap.tsx delete mode 100644 src/components/layouts/markdown-wrapper.tsx create mode 100644 src/components/mdx/markdown-wrapper.tsx create mode 100644 src/components/page-meta.tsx create mode 100644 src/components/page-top.tsx delete mode 100644 src/pages/ecosystem/faq.md delete mode 100644 src/pages/references/faqs.md delete mode 100644 src/pages/stacks-wallet/troubleshooting.md diff --git a/lib/mdx-frontmatter-loader.js b/lib/mdx-frontmatter-loader.js index f93d104e..41fb9b39 100644 --- a/lib/mdx-frontmatter-loader.js +++ b/lib/mdx-frontmatter-loader.js @@ -34,7 +34,7 @@ async function mdxFrontmatterLoader(src) { const headings = getHeadings(content); const duration = getReadingTime(content).text; const code = - `import { MDWrapper } from '@components/layouts/markdown-wrapper'; + `import { MDWrapper } from '@components/mdx/markdown-wrapper'; export default function Layout({ children, ...props }){ return ( readingTime(mdxContent); - -const getHeadings = mdxContent => { - const regex = /\n(#+)(.*)/gm; - const found = mdxContent.match(regex); - const getLevel = string => string.split('#'); - const headings = - found && found.length - ? found.map(f => { - const md = f.split('# ')[1]; - let content = md; - remark() - .use(strip) - .process(md, (err, file) => { - if (err) throw err; - content = file.contents.toString().trim(); - }); - const level = getLevel(f).length; - return { content, level }; - }) - : []; - return headings; -}; - -const layoutPropsString = `const layoutProps = {`; -const newLayoutPropsString = frontmatter => `const layoutProps = { - frontmatter: ${frontmatter},\n`; - -const withFrontmatter = (code, frontmatter) => - code.replace(layoutPropsString, newLayoutPropsString(frontmatter)); - -const loader = async function (src) { - const callback = this.async(); - const options = Object.assign({}, getOptions(this), { - filepath: this.resourcePath, - }); - - const { content, data } = fm(src); - const headings = getHeadings(content); - const duration = getReadingTime(content).text; - const frontmatter = JSON.stringify({ duration, ...data, headings }); - - let result; - - try { - result = await mdx(content, options); - } catch (err) { - return callback(err); - } - - const { renderer = DEFAULT_RENDERER } = options; - - const code = withFrontmatter(`${renderer}\n${result}`, frontmatter); - - return callback(null, code); -}; - -module.exports = loader; diff --git a/package.json b/package.json index b8044b45..e7103f27 100755 --- a/package.json +++ b/package.json @@ -2,10 +2,10 @@ "name": "@blockstack/docs", "version": "1.0.0", "dependencies": { - "@blockstack/ui": "2.12.2-beta.0", - "@docsearch/react": "^1.0.0-alpha.26", + "@blockstack/ui": "file:.yalc/@blockstack/ui", + "@docsearch/react": "^1.0.0-alpha.27", "@hashicorp/remark-plugins": "^3.0.0", - "@mdx-js/loader": "1.6.15", + "@mdx-js/loader": "1.6.16", "@mdx-js/mdx": "^1.6.16", "@mdx-js/react": "^1.6.16", "@next/mdx": "^9.4.4", @@ -16,7 +16,7 @@ "@types/node": "^14.0.27", "@types/nprogress": "^0.2.0", "@types/reach__tooltip": "^0.2.0", - "algoliasearch": "^4.3.1", + "algoliasearch": "^4.4.0", "babel-plugin-macros": "^2.8.0", "cache-manager": "^3.3.0", "cache-manager-fs-hash": "^0.0.9", @@ -34,15 +34,15 @@ "lodash.debounce": "^4.0.8", "mdi-react": "7.3.0", "micro-memoize": "^4.0.9", - "next": "^9.5.2-canary.7", + "next": "^9.5.2-canary.9", "next-fonts": "^1.4.0", "next-google-fonts": "^1.1.0", "next-mdx-remote": "^0.6.0", "nprogress": "^0.2.0", "p-all": "^3.0.0", - "preact": "^10.4.4", + "preact": "^10.4.7", "preact-render-to-string": "^5.1.4", - "preact-ssr-prepass": "^1.1.0", + "preact-ssr-prepass": "^1.1.1", "prettier": "^2.0.5", "preval.macro": "^5.0.0", "react-gesture-responder": "^2.1.0", @@ -63,7 +63,7 @@ "remark-unwrap-images": "2.0.0", "remark-vscode": "^1.0.0-beta.2", "strip-markdown": "^3.1.2", - "swr": "^0.2.3", + "swr": "^0.3.0", "turndown": "^6.0.0", "typescript": "^3.9.7", "unified-vscode": "^1.0.0-beta.1", diff --git a/public/images/todo-list-app.png b/public/images/todo-list-app.png new file mode 100644 index 0000000000000000000000000000000000000000..87a0b0f8ed2239f8fb92ea1d925ebf80ce33a9e9 GIT binary patch literal 26307 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ⅇgqh_(eMyV4qrA{0C{cFUgugUrhW7| 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 { = R ) ); -const GridCardDetails: React.FC = React.memo( +const GridItemDetails: React.FC = React.memo( ({ isHovered, page, ...props }) => ( <> @@ -192,11 +195,63 @@ const GridCard: React.FC = React.memo(({ page, ...res {...bind} > - + ); }); +const getIcon = (icon: string) => { + switch (icon) { + case 'BlockstackIcon': + return (p: BoxProps) => ; + case 'StacksIcon': + return (p: BoxProps) => ( + + + + ); + case 'TestnetIcon': + return (p: BoxProps) => ( + + + + ); + default: + return (p: BoxProps) => ; + } +}; +const GridSmallItem: React.FC = ({ page, ...rest }) => { + const { hover, active, bind } = useTouchable({ + behavior: 'link', + }); + const Icon = getIcon(page.icon); + return ( + + {page.icon ? : null} + + + ); +}; + +const getComponent = (type: 'default' | 'inline' | 'grid' | 'grid-small') => { + switch (type) { + case 'inline': + return InlineCard; + case 'grid': + return GridCard; + case 'grid-small': + return GridSmallItem; + default: + return GridCard; + } +}; + export const PageReference: React.FC = React.memo(({ children }) => { const content = onlyText(children).trim(); const [variant, _paths] = content.includes('\n') ? content.split('\n') : ['default', content]; @@ -206,6 +261,8 @@ export const PageReference: React.FC = React.memo(({ children }) => { if (!routes) return null; const pages = paths.map(path => routes?.find(route => route.path === path)).filter(page => page); + + const Comp = getComponent(variant as any); return ( = React.memo(({ children }) => { `repeat(${pages.length === 1 ? 1 : 3}, 1fr)`, ]} > - {pages.map((page, key) => - variant === 'inline' ? ( - - ) : ( - - ) - )} + {pages.map((page, key) => ( + + ))} ); }); diff --git a/src/components/feedback.tsx b/src/components/feedback.tsx index 39530e18..bb6a6765 100644 --- a/src/components/feedback.tsx +++ b/src/components/feedback.tsx @@ -19,10 +19,12 @@ import { useRouter } from 'next/router'; import { getHeadingStyles } from '@components/mdx/typography'; import { css } from '@styled-system/css'; import { StatusCheck } from '@components/status-check'; +import { useColorMode } from '@common/hooks/use-color-mode'; const Icon: React.FC }> = ({ icon: IconComponent, ...props }) => { const { bind, hover, active } = useTouchable(); const isHovered = hover || active; + const [mode] = useColorMode(); return ( }> = ({ icon: IconComponen {...props} {...bind} > - + ); }; diff --git a/src/components/icons/clipboard-check.tsx b/src/components/icons/clipboard-check.tsx new file mode 100644 index 00000000..c8693746 --- /dev/null +++ b/src/components/icons/clipboard-check.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { BaseSvg, SvgProps } from '@components/icons/_base'; + +export const ClipboardCheckIcon: SvgProps = props => ( + + + + + + +); diff --git a/src/components/icons/clipboard.tsx b/src/components/icons/clipboard.tsx new file mode 100644 index 00000000..05380ead --- /dev/null +++ b/src/components/icons/clipboard.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { BaseSvg, SvgProps } from '@components/icons/_base'; + +export const ClipboardIcon: SvgProps = props => ( + + + + + +); diff --git a/src/components/icons/copy.tsx b/src/components/icons/copy.tsx new file mode 100644 index 00000000..9ebbc6fa --- /dev/null +++ b/src/components/icons/copy.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { BaseSvg, SvgProps } from '@components/icons/_base'; + +export const CopyIcon: SvgProps = props => ( + + + + + +); diff --git a/src/components/icons/sitemap.tsx b/src/components/icons/sitemap.tsx new file mode 100644 index 00000000..ab56f0e3 --- /dev/null +++ b/src/components/icons/sitemap.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { BaseSvg, SvgProps } from '@components/icons/_base'; + +export const SitemapIcon: SvgProps = props => ( + + + + + + + + +); diff --git a/src/components/layouts/markdown-wrapper.tsx b/src/components/layouts/markdown-wrapper.tsx deleted file mode 100644 index 2c12a2ce..00000000 --- a/src/components/layouts/markdown-wrapper.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import React from 'react'; -import { Box, Flex, Stack, space, BoxProps, color } from '@blockstack/ui'; -import { MDContents } from '@components/mdx/md-contents'; -import { H1 } from '@components/mdx'; -import Head from 'next/head'; -import { Text } from '@components/typography'; -import { useRouter } from 'next/router'; -import dynamic from 'next/dynamic'; -import { getTitle } from '@common/utils'; -import { css } from '@styled-system/css'; -import { getHeadingStyles } from '@components/mdx/typography'; -import { ToolsIcon } from '@components/icons/tools'; -import { ClockIcon } from '@components/icons/clock'; -const Search = dynamic(() => import('@components/search')); - -const Experience: React.FC = ({ - level, - ...rest -}) => ( - - - - - {level} - -); -const Duration: React.FC = ({ value, ...rest }) => ( - - - - - {value} - -); - -const PageTop: React.FC = props => { - const router = useRouter(); - const isHome = router?.pathname === '/'; - return ( - - -

{getTitle(props)}

- {isHome ? ( - - - - ) : null} -
- {props.description ? ( - - - {props.description} - {' '} - - ) : null} - - - {props.experience ? : null} - {!isHome && props.duration ? : null} - -
- ); -}; - -const defaultFrontmatter = { - headings: [], - description: - 'Blockstack is an open-source and developer-friendly network for building decentralized apps and smart contracts.', -}; - -export const MDWrapper: React.FC = React.memo( - ({ frontmatter = defaultFrontmatter, dynamicHeadings = [], ...props }) => { - const { headings, description } = frontmatter; - - return ( - <> - - {getTitle(frontmatter)} | Blockstack - - - } - headings={[...headings, ...dynamicHeadings]} - > - {props.children} - - - ); - } -); - -export default MDWrapper; diff --git a/src/components/mdx/components/code.tsx b/src/components/mdx/components/code.tsx index ea10942d..bd9ca2d3 100644 --- a/src/components/mdx/components/code.tsx +++ b/src/components/mdx/components/code.tsx @@ -1,9 +1,13 @@ -import React from 'react'; +import React, { Children } from 'react'; -import { Box, BoxProps, color, space, themeColor } from '@blockstack/ui'; -import { border } from '@common/utils'; +import { Box, Flex, BoxProps, color, space, useClipboard, themeColor } from '@blockstack/ui'; +import { ClipboardCheckIcon } from '@components/icons/clipboard-check'; +import { border, onlyText } from '@common/utils'; import { css } from '@styled-system/css'; import { Text } from '@components/typography'; +import { useHover } from 'use-events'; +import { IconButton } from '@components/icon-button'; +import { CopyIcon as BaseCopyIcon } from '@components/icons/copy'; const LINE_MINIMUM = 4; @@ -39,55 +43,95 @@ export const Code: React.FC< BoxProps & { highlight?: string; lang?: string; lines: number } > = React.memo( React.forwardRef(({ children, highlight, lang, lines, ...rest }, ref) => { + const [hover, bind] = useHover(); + const numbers = getHighlightLineNumbers(highlight); + + const convertSingleChildToString = child => onlyText(child).replace(/\n/g, ''); + const tokenLines = Children.toArray(children).map(convertSingleChildToString); + const codeString = tokenLines.join('\n'); + + const { hasCopied, onCopy } = useClipboard(codeString); + + const CopyIcon = hasCopied ? ClipboardCheckIcon : BaseCopyIcon; + return ( - - + + LINE_MINIMUM && lang !== 'bash' - ? { - counterIncrement: 'line', - content: 'counter(line, decimal-leading-zero)', - display: 'grid', - placeItems: 'center', - color: themeColor('ink.400'), - mr: '16px', - width: '42px', - fontSize: '12px', - borderRight: '1px solid rgb(39,41,46)', - } - : {}, - }, - pr: space(['base-loose', 'base-loose', 'extra-loose', 'extra-loose']), - pl: - lines <= LINE_MINIMUM || lang === 'bash' - ? space(['extra-loose', 'extra-loose', 'base-loose', 'base-loose']) - : 'unset', - })} - {...rest} - > - - {children} - + flexDirection: 'column', + minWidth: 'fit-content', + '.token-line': { + display: 'inline-block', + ...generateCssStylesForHighlightedLines(numbers), + }, + counterReset: 'line', + '& .token-line': { + '.comment': { + color: 'rgba(255,255,255,0.5) !important', + }, + display: 'flex', + fontSize: '14px', + '&::before': + lines > LINE_MINIMUM && lang !== 'bash' + ? { + counterIncrement: 'line', + content: 'counter(line, decimal-leading-zero)', + display: 'grid', + placeItems: 'center', + color: themeColor('ink.400'), + mr: '16px', + width: '42px', + fontSize: '12px', + borderRight: '1px solid rgb(39,41,46)', + } + : {}, + }, + pr: space(['base-loose', 'base-loose', 'extra-loose', 'extra-loose']), + pl: + lines <= LINE_MINIMUM || lang === 'bash' + ? space(['extra-loose', 'extra-loose', 'base-loose', 'base-loose']) + : 'unset', + })} + {...rest} + > + + {children} + + + {hover ? ( + + + + + + ) : null} ); }) diff --git a/src/components/mdx/components/link.tsx b/src/components/mdx/components/link.tsx index a6fbe36a..0249b394 100644 --- a/src/components/mdx/components/link.tsx +++ b/src/components/mdx/components/link.tsx @@ -1,6 +1,26 @@ -import { Box, BoxProps } from '@blockstack/ui'; +import { Box, BoxProps, color, space, Fade } from '@blockstack/ui'; import NextLink from 'next/link'; import React, { forwardRef, Ref } from 'react'; +import { useAppState } from '@common/hooks/use-app-state'; +import { border, transition } from '@common/utils'; +import { Text } from '@components/typography'; +import { useTouchable } from '@common/hooks/use-touchable'; +import { css } from '@styled-system/css'; +import { getHeadingStyles } from '@components/mdx/typography'; +import { PageMeta } from '@components/page-meta'; + +export const MarkdownLink = ({ href, ...rest }: { href: string }) => { + const isExternal = !href || href?.includes('http') || href?.includes('mailto'); + const link = ; + + return isExternal ? ( + link + ) : ( + + {link} + + ); +}; export const SmartLink = ({ href, ...rest }: { href: string }) => { const isExternal = !href || href?.includes('http') || href?.includes('mailto'); @@ -15,21 +35,104 @@ export const SmartLink = ({ href, ...rest }: { href: string }) => { ); }; +const Card = ({ route, styles, ...rest }) => { + const { description } = route; + return ( + + + + + {description} + + + + + + ); +}; + +export const LinkWithHover = forwardRef( + ( + props: { href?: string; target?: string; rel?: string } & BoxProps, + ref: Ref + ) => { + const { bind, hover } = useTouchable(); + + const { routes } = useAppState(); + const isExternal = + props.href && (props.href?.includes('http') || props.href?.includes('mailto')); + + const previewData = + !isExternal && props.href && props.href.startsWith('/') + ? routes.find(r => r.path.endsWith(props.href)) + : undefined; + + return ( + + + {previewData ? ( + + {styles => ( + + )} + + ) : null} + + ); + } +); + export const Link = forwardRef( ( props: { href?: string; target?: string; rel?: string } & BoxProps, ref: Ref - ) => ( - - ) + ) => { + return ( + + ); + } ); diff --git a/src/components/mdx/markdown-wrapper.tsx b/src/components/mdx/markdown-wrapper.tsx new file mode 100644 index 00000000..f258efb4 --- /dev/null +++ b/src/components/mdx/markdown-wrapper.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { MDContents } from '@components/mdx/md-contents'; +import Head from 'next/head'; +import { getTitle } from '@common/utils'; +import { PageTop } from '@components/page-top'; + +const defaultFrontmatter = { + headings: [], + description: + 'Blockstack is an open-source and developer-friendly network for building decentralized apps and smart contracts.', +}; + +export const MDWrapper: React.FC = React.memo( + ({ frontmatter = defaultFrontmatter, dynamicHeadings = [], ...props }) => { + const { headings, description } = frontmatter; + + return ( + <> + + {getTitle(frontmatter)} | Blockstack + + + } + headings={[...headings, ...dynamicHeadings]} + > + {props.children} + + + ); + } +); + +export default MDWrapper; diff --git a/src/components/mdx/md-contents.tsx b/src/components/mdx/md-contents.tsx index 798db769..85bfbd62 100644 --- a/src/components/mdx/md-contents.tsx +++ b/src/components/mdx/md-contents.tsx @@ -11,10 +11,14 @@ import { border } from '@common/utils'; import { getCapsizeStyles } from '@components/mdx/typography'; export const styleOverwrites = { - section: { - '&:first-child > h2:first-child': { - mt: 0, + '& > section': { + '&:nth-child(2)': { + '& > *:first-child': { + mt: 0, + }, }, + }, + section: { '& > *:not(pre):not(ul):not(ol):not(img):not([data-reach-accordion]):not(section):not(hr)': { px: space(['extra-loose', 'extra-loose', 'none', 'none']), }, @@ -48,7 +52,7 @@ export const styleOverwrites = { borderRadius: [0, 0, '12px'], bg: themeColor('ink'), }, - '& > div > code': { + '& > div > div > code': { whiteSpace: 'pre', overflowX: 'auto', maxWidth: '100%', diff --git a/src/components/mdx/mdx-components.tsx b/src/components/mdx/mdx-components.tsx index 4f17921e..4f77181d 100644 --- a/src/components/mdx/mdx-components.tsx +++ b/src/components/mdx/mdx-components.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { Pre, THead, - SmartLink, + MarkdownLink, TData, Table, InlineCode, @@ -24,7 +24,6 @@ import { import { Img } from '@components/mdx/image'; import { Code } from '@components/mdx/components'; import { PageReference } from '@components/custom-blocks/page-reference'; -import { MDWrapper } from '@components/layouts/markdown-wrapper'; export const Components = { h1: () => null, @@ -41,7 +40,7 @@ export const Components = { table: Table, th: THead, td: TData, - a: SmartLink, + a: MarkdownLink, p: P, ul: Ul, ol: Ol, diff --git a/src/components/mdx/overrides.tsx b/src/components/mdx/overrides.tsx index 28609eea..867536fe 100644 --- a/src/components/mdx/overrides.tsx +++ b/src/components/mdx/overrides.tsx @@ -16,27 +16,6 @@ img{ image-rendering: crisp-edges; will-change: transform; } -.headroom { - top: 0; - left: 0; - right: 0; - zIndex: 1; -} -.headroom--unfixed { - position: relative; - transform: translateY(0); -} -.headroom--scrolled { - transition: transform 200ms ease-in-out; -} -.headroom--unpinned { - position: fixed; - transform: translateY(-100%); -} -.headroom--pinned { - position: fixed; - transform: translateY(0%); -} :root{ --docsearch-modal-background: ${color('bg')}; --docsearch-text-color: ${color('text-title')}; diff --git a/src/components/page-meta.tsx b/src/components/page-meta.tsx new file mode 100644 index 00000000..f4c3159b --- /dev/null +++ b/src/components/page-meta.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { Box, Flex, space, Stack, BoxProps, color, StackProps } from '@blockstack/ui'; + +import { Text } from '@components/typography'; + +import { ToolsIcon } from '@components/icons/tools'; +import { ClockIcon } from '@components/icons/clock'; +import { css } from '@styled-system/css'; +import { getCapsizeStyles } from '@components/mdx/typography'; +const Experience: React.FC< + BoxProps & { level?: 'beginner' | 'intermediate' | 'advanced'; small?: boolean } +> = ({ level, small, ...rest }) => ( + + + + + + {level} + + +); +const Duration: React.FC = ({ + value, + small, + ...rest +}) => ( + + + + + + {value} + + +); + +export const PageMeta: React.FC = ({ experience, duration, isHome, small }) => ( + + {experience ? : null} + {!isHome && duration ? : null} + +); diff --git a/src/components/page-top.tsx b/src/components/page-top.tsx new file mode 100644 index 00000000..14c63c59 --- /dev/null +++ b/src/components/page-top.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { Box, Flex, Stack, space, BoxProps } from '@blockstack/ui'; +import { H1 } from '@components/mdx/index'; +import { Text } from '@components/typography'; +import { useRouter } from 'next/router'; +import dynamic from 'next/dynamic'; +import { getTitle } from '@common/utils'; +import { css } from '@styled-system/css'; +import { getHeadingStyles } from '@components/mdx/typography'; +const Search = dynamic(() => import('@components/search')); +import { PageMeta } from '@components/page-meta'; + +export const PageTop: React.FC = props => { + const router = useRouter(); + const isHome = router?.pathname === '/'; + return ( + + +

{getTitle(props)}

+ {isHome ? ( + + + + ) : null} +
+ {props.description ? ( + + + {props.description} + {' '} + + ) : null} + +
+ ); +}; diff --git a/src/components/search.tsx b/src/components/search.tsx index 05f46058..c4b904ce 100644 --- a/src/components/search.tsx +++ b/src/components/search.tsx @@ -52,16 +52,14 @@ const Key: React.FC = React.memo(({ children, ...rest }) => ( placeItems: 'center', }} size="18px" - bg={color('bg')} - border={border()} + bg={'rgba(0,0,0,0.11)'} borderRadius="3px" - boxShadow="low" - opacity={0.75} + opacity={0.65} {...rest} > { }; }; -export const Tooltip = ({ children, label, 'aria-label': ariaLabel }: any) => { +export const Tooltip = ({ children, label, 'aria-label': ariaLabel, style = {}, ...rest }: any) => { const [trigger, tooltip] = useTooltip(); const { onMouseDown, ...triggerProps } = trigger; @@ -33,8 +33,10 @@ export const Tooltip = ({ children, label, 'aria-label': ariaLabel }: any) => { borderRadius: '3px', padding: '0.5em 1em', fontSize: '12px', + ...style, }} position={centered} + {...rest} /> ); diff --git a/src/pages/authentication/building-todo-app.md b/src/pages/authentication/building-todo-app.md index 4f6230f0..2386ac28 100644 --- a/src/pages/authentication/building-todo-app.md +++ b/src/pages/authentication/building-todo-app.md @@ -1,6 +1,8 @@ --- title: Building a Todo app description: Learn how to integrate authentication and data storage. +experience: beginners +duration: 30 minutes tags: - tutorial images: @@ -13,6 +15,10 @@ redirect_from: # Building a Todo app +![What you'll be creating in this tutorial](/images/todo-list-app.png) + +## Introduction + In this tutorial, you will learn about Blockstack authentication and storage by installing, running and reviewing the code for a "Todos" web app built with Blockstack and [React](https://reactjs.org/). @@ -49,21 +55,21 @@ $ npm run start You should see output similar to the following: ```bash - Compiled successfully! +Compiled successfully! - You can now view bs-todo in the browser. +You can now view bs-todo in the browser. http://localhost:3000/ - Note that the development build is not optimized. - To create a production build, use npm run build. +Note that the development build is not optimized. +To create a production build, use npm run build. ``` ### Step 3: Open your local browser to [`http://localhost:3000`](http://localhost:3000) if it doesn't open automatically. You should see the app's landing page: -![](/images/todos-home.png) +![The homepage of the todos app](/images/todos-home.png) ## Onboard into your first Blockstack app @@ -73,7 +79,7 @@ The app displays a standardized introductory modal using [Blockstack Connect](https://github.com/blockstack/ux/tree/master/packages/connect), a JavaScript library that makes it easy to integrate Blockstack into the UI of any web app. -![](/images/todos-intro.png) +![The Blockstack Connect Modal](/images/todos-intro.png) Below, you can see the relevant parts of the [React component](https://reactjs.org/docs/react-component.html) that triggers this modal in [`src/components/Signin.jsx`](https://github.com/blockstack/blockstack-todos/blob/master/src/components/Signin.jsx): @@ -179,7 +185,7 @@ componentDidMount() { The app triggers a popup window in which [the Blockstack App](https://github.com/blockstack/ux/tree/master/packages/app) is loaded from [`app.blockstack.org`](http://app.blockstack.org/) and begins generating a new _Secret Key_. -![](/images/todos-generation.svg) +![What the UI looks like when a new ID is generated](/images/todos-generation.svg) ### Step 3: Choose **Copy Secret Key** to copy your _Secret Key_ to the clipboard. @@ -190,11 +196,11 @@ all of the private data they create and manage with Blockstack apps. _Secret Keys_ are like strong passwords. However, they can never be recovered if lost or reset if stolen. As such, it's paramount that users handle them with great care. -![](/images/todos-copy-secret-key.svg) +![An example of a secret key](/images/todos-copy-secret-key.svg) ### Step 4: Choose **I've saved it** to confirm you've secured your _Secret Key_ in a suitable place. -![](/images/todos-ive-saved-it.svg) +![An example of the I've saved it screen](/images/todos-ive-saved-it.svg) ### Step 5: Enter a username value and choose **Continue** @@ -203,7 +209,7 @@ The username will be used by the app to generate a URL for sharing your todos, s It is registered on the Stacks blockchain with the [Blockstack Naming System (BNS)](/core/naming/introduction) and associated with your _Secret Key_. -![](/images/todos-username.svg) +![Choosing a user name example](/images/todos-username.svg) ### Done: You've now completed onboarding into the app! @@ -212,13 +218,13 @@ and associated with your _Secret Key_. Once you've authenticated the app, you can can start adding todos by entering values into the "Write your to do" field and hitting "Enter". -![](/images/todos-home-authenticated.svg) +![The authenticated view of the todos app](/images/todos-home-authenticated.svg) The data for all todos are saved as JSON to the Gaia hub linked to your Secret Key using the [`putFile`](http://blockstack.github.io/blockstack.js/globals.html#putfile) method of the `userSession` object in the [`src/assets/data-store.js`](https://github.com/blockstack/blockstack-todos/blob/master/src/assets/data-store.js#L26) module: -```js +```jsx export const saveTasks = async (userSession, tasks, isPublic) => { await userSession.putFile(TASKS_FILENAME, JSON.stringify({ tasks, isPublic }), { encrypt: !isPublic, @@ -229,7 +235,7 @@ export const saveTasks = async (userSession, tasks, isPublic) => { These todos are subsequently loaded using the [`getFile`](http://blockstack.github.io/blockstack.js/globals.html#getfile) method of the same object in the same module: -```js +```jsx export const fetchTasks = async (userSession, username) => { const tasksJSON = await userSession.getFile(TASKS_FILENAME, { decrypt: false, @@ -248,7 +254,7 @@ When deleting a todo, the same `putFile` method is used to save a new JSON array Select "Make public" to make your todos accessible to the public for sharing via URL. -![](/images/todos-public.svg) +![Public todos view](/images/todos-public.svg) This will call `saveTasks` with the `isPublic` parameter set to `true`, which is used to disable encryption when using `putFile`. @@ -280,14 +286,14 @@ Once signed out, select "Sign in" to sign back in with your _Secret Key_. If you've previously deauthenticated the Blockstack app, you'll see a prompt to enter your _Secret Key_: -![](/images/todos-sign-in.svg) +![An example of a sign in screen](/images/todos-sign-in.svg) The above screen will be ommitted if you have an active session with the Blockstack app already. Then you'll be presented with the option to select an existing username associated with your _Secret Key_ or create a new one if you wish to authenticate the app with a different identity and data set: -![](/images/todos-choose-account.svg) +![An example of the choose an account screen](/images/todos-choose-account.svg) You'll now see your todos as an authenticated user for the username you've chosen. diff --git a/src/pages/authentication/connect.md b/src/pages/authentication/connect.md index e4617691..98af29fa 100644 --- a/src/pages/authentication/connect.md +++ b/src/pages/authentication/connect.md @@ -2,10 +2,9 @@ title: Blockstack Connect description: Learn what Connect is and how to integrate it into an app. experience: beginners +duration: 15 minutes --- -# Guide to Blockstack Connect - ## Introduction Blockstack Connect is a JavaScript library for integrating Blockstack authentication and smart contracts into your app. diff --git a/src/pages/authentication/overview.md b/src/pages/authentication/overview.md index e5e9a4a0..ac542488 100644 --- a/src/pages/authentication/overview.md +++ b/src/pages/authentication/overview.md @@ -6,11 +6,6 @@ images: sm: /images/pages/authentication-sm.svg --- -# Authentication protocol - -Blockstack Auth provides single sign on and authentication without third parties or remote servers. -On this page, you'll get an overview of authentication from a developer perspective. - ## Authentication flow For an application developer, the application flow is similar to the typical client-server flow used by centralized sign in services (e.g., OAuth). However, with Blockstack, the authentication flow happens entirely client-side. diff --git a/src/pages/authentication/profiles.md b/src/pages/authentication/profiles.md index 81f93128..f06aab2a 100644 --- a/src/pages/authentication/profiles.md +++ b/src/pages/authentication/profiles.md @@ -1,12 +1,8 @@ --- -title: Guide to Blockstack Profiles +title: Guide to Profiles +description: Learn about profiles on the Blockstack network --- -# Guide to Blockstack Profiles - -You can use `blockstack.js` to create and register a Blockstack username on the Stacks blockchain. -This section describes the `Profile` object and contains the following topics: - ## About profiles Profile data is stored using Gaia on the user's selected storage provider. An example of a `profile.json` file URL using diff --git a/src/pages/build-an-app.md b/src/pages/build-an-app.md index bff3caf4..efee584e 100644 --- a/src/pages/build-an-app.md +++ b/src/pages/build-an-app.md @@ -6,7 +6,7 @@ images: sm: /images/pages/build-an-app-sm.svg --- -# Building decentralized apps +## Introduction Prefer to jump right in? Get started with this tutorial where you’ll create a decentralized to-do list app. diff --git a/src/pages/data-indexing/collaborate.md b/src/pages/data-indexing/collaborate.md index 9e92f0e7..a3f338be 100644 --- a/src/pages/data-indexing/collaborate.md +++ b/src/pages/data-indexing/collaborate.md @@ -3,7 +3,7 @@ title: Collaborate with groups description: A key feature of Radiks is support for private collaboration between multiple users. --- -# Collaborate with groups +## Introduction A key feature of Radiks is support for private collaboration between multiple users. Supporting collaboration with client-side encryption and user-owned storage can be complicated, but the patterns to implement it are generally the diff --git a/src/pages/data-indexing/integrate.md b/src/pages/data-indexing/integrate.md index 85360139..59c47b26 100644 --- a/src/pages/data-indexing/integrate.md +++ b/src/pages/data-indexing/integrate.md @@ -3,7 +3,7 @@ title: Integrate Radiks description: Learn how to setup Radiks with your application. --- -# Integrate Radiks +## Introduction Using Radiks with your application requires a Radiks server and a client application constructed to use the server. In this article, you learn how to install, setup, and run a pre-packaged Radiks server that connects to MongoDB. diff --git a/src/pages/data-indexing/models.md b/src/pages/data-indexing/models.md index 08739ab8..c86a59de 100644 --- a/src/pages/data-indexing/models.md +++ b/src/pages/data-indexing/models.md @@ -3,7 +3,7 @@ title: Create and use models description: Model and query application data with Radiks. --- -# Create and use models +## Introduction Radiks allows you to model your client data. You can then query this data and display it for a user in multi-player applications. A social application where users want to see the comments of diff --git a/src/pages/data-indexing/overview.md b/src/pages/data-indexing/overview.md index 0a4182c3..d130b021 100644 --- a/src/pages/data-indexing/overview.md +++ b/src/pages/data-indexing/overview.md @@ -6,7 +6,7 @@ images: sm: /images/pages/radiks-sm.svg --- -# Radiks the data indexer +## Introduction The Blockstack Radiks feature enables Blockstack decentralized applications (DApps) to index and store across data belonging to multiple users. Radiks works with Blockstack's Gaia Storage System. Using Radiks, you can build diff --git a/src/pages/data-indexing/server-extras.md b/src/pages/data-indexing/server-extras.md index 12cc774e..537ddde0 100644 --- a/src/pages/data-indexing/server-extras.md +++ b/src/pages/data-indexing/server-extras.md @@ -3,10 +3,6 @@ title: Radiks server tips and tricks description: Some tips and tricks for working with a Radiks server. --- -# Radiks server tips and tricks - -In this section, you'll find some tips and tricks you can use to work with a Radiks server. - ## Access the MongoDB collection Radiks-server keeps all models inside of a collection. You can use the `getDB` function to access this collection from inside your application. diff --git a/src/pages/data-storage/authentication.md b/src/pages/data-storage/authentication.md index 0abdbb1e..5f061ee5 100644 --- a/src/pages/data-storage/authentication.md +++ b/src/pages/data-storage/authentication.md @@ -2,7 +2,7 @@ description: 'Storing user data with Blockstack' --- -# Authentication and Gaia +## Introduction Blockstack authentication is a bearer token-based authentication system. From an app user's perspective, login similar to third-party authentication techniques that they're familiar with. For an app developer, diff --git a/src/pages/data-storage/collection-type.md b/src/pages/data-storage/collection-type.md index 85562dc1..5854ea61 100644 --- a/src/pages/data-storage/collection-type.md +++ b/src/pages/data-storage/collection-type.md @@ -2,7 +2,7 @@ title: Create a Collection type --- -# How to create a Collection type +## Introduction Collections support data portability between applications. Blockstack supplies a `Contact` collection for use by Blockstack applications. Developers can create additional collection types, use them in their own applications, and publish them so other developers can make use of them too. diff --git a/src/pages/data-storage/collections.md b/src/pages/data-storage/collections.md index 8d079c3d..62986e63 100644 --- a/src/pages/data-storage/collections.md +++ b/src/pages/data-storage/collections.md @@ -1,8 +1,9 @@ --- title: Collections (Preview) +description: Learn about the beta release of Collections and how you can start using it. --- -# Work with Collections (Preview) +## Introduction Collections is the feature designed to make data portable among Blockstack applications. Sharing is accomplished by storing a user's data in a standardized format at a known, Gaia storage location. Collections associate user data with @@ -11,13 +12,9 @@ a user's decentralized ID. When users move among apps, the same data is availabl On this page, you learn what collections are and how to use them. You'll learn about the `Contact` collection in particular. The following topics are covered: -> #### Preview release -> -> This is a preview release of the `Contact` collections. This release allows developers to try out the new collections -> functionality and we are interested in collecting feedback. Please feel free to report issues or request enhancements -> with collections or `Contacts` themselves on the [blockstack-collections repository](https://github.com/blockstack/blockstack-collections/issues/new). -> -> If you encounter problems with `blockstack.js` you can [file issues or request enhancements on its repo](https://github.com/blockstack/blockstack.js/issues/new). +-> This is a preview release of the `Contact` collections. This release allows developers to try out the new collections functionality and we are interested in collecting feedback. Please feel free to report issues or request enhancements with collections or `Contacts` themselves on the [blockstack-collections repository](https://github.com/blockstack/blockstack-collections/issues/new). + +~> If you encounter problems with `blockstack.js` you can [file issues or request enhancements on its repo](https://github.com/blockstack/blockstack.js/issues/new). ## Understand how collections work diff --git a/src/pages/data-storage/overview.md b/src/pages/data-storage/overview.md index ac24f10c..411ef77c 100644 --- a/src/pages/data-storage/overview.md +++ b/src/pages/data-storage/overview.md @@ -6,7 +6,7 @@ images: sm: /images/pages/data-storage-sm.svg --- -# A decentralized storage architecture +## Introduction The Blockstack Network stores application data using a storage system called Gaia. Transactional metadata is stored on the Blockstack blockchain and user diff --git a/src/pages/data-storage/storage-guide.md b/src/pages/data-storage/storage-guide.md index 67689077..eb5b460f 100644 --- a/src/pages/data-storage/storage-guide.md +++ b/src/pages/data-storage/storage-guide.md @@ -2,7 +2,7 @@ title: Guide to Blockstack Storage --- -# Guide to Blockstack Storage +## Introduction The Blockstack Platform stores application data in the Gaia Storage System. Transactional metadata is stored on the Blockstack blockchain and user application data is stored in Gaia storage. Storing data off of the blockchain ensures diff --git a/src/pages/data-storage/storage-write-read.md b/src/pages/data-storage/storage-write-read.md index 956dd0fc..26fc3888 100644 --- a/src/pages/data-storage/storage-write-read.md +++ b/src/pages/data-storage/storage-write-read.md @@ -2,7 +2,7 @@ description: 'Storing user data with Blockstack' --- -# Storage write and read +## Introduction Once a user authenticates and a DApp obtains authentication, the application interacts with Gaia through the blockstack.js library. There are two simple methods for working with data in Gaia hub: the `putFile()` and `getFile()` diff --git a/src/pages/ecosystem/address-confirmation.md b/src/pages/ecosystem/address-confirmation.md index 92706afd..f0ae7b6c 100644 --- a/src/pages/ecosystem/address-confirmation.md +++ b/src/pages/ecosystem/address-confirmation.md @@ -1,8 +1,9 @@ --- -description: 'Blockstack Network documentation' +title: Confirm your address +description: Learn how to confirm a Stacks address --- -# Check your address +## Introduction We recommend that you confirm your address is correct by going through the following steps in the Stacks Wallet: diff --git a/src/pages/ecosystem/contributing.md b/src/pages/ecosystem/contributing.md index 04bf9384..f06e8de9 100644 --- a/src/pages/ecosystem/contributing.md +++ b/src/pages/ecosystem/contributing.md @@ -3,7 +3,7 @@ title: How to contribute description: Learn how this site is built, and how you could contribute to it. --- -# How to contribute +## Introduction Welcome! Thank you for your interest in contributing and helping make these docs as good as they can be! This page will outline how this site is built, its general structure, getting it running locally, and some helpful tips for using all of its features. diff --git a/src/pages/ecosystem/faq.md b/src/pages/ecosystem/faq.md deleted file mode 100644 index a67291de..00000000 --- a/src/pages/ecosystem/faq.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -description: 'Blockstack Network documentation' ---- - -export { convertFaqAnswersToMDX as getStaticProps } from '@common/data/faq' -import { FAQs } from '@components/faq' - -# FAQs about Stacks tokens and wallet - -## Stacks tokens - - - -## Stacks Wallet - - diff --git a/src/pages/ecosystem/overview.md b/src/pages/ecosystem/overview.md index 56fb45f8..6f4d7133 100644 --- a/src/pages/ecosystem/overview.md +++ b/src/pages/ecosystem/overview.md @@ -1,5 +1,6 @@ --- description: Learn about Blockstack and decentralization +icon: BlockstackIcon --- # Overview of Blockstack diff --git a/src/pages/ecosystem/stacks-token-holders.md b/src/pages/ecosystem/stacks-token-holders.md index cc48d483..ccfb13cb 100644 --- a/src/pages/ecosystem/stacks-token-holders.md +++ b/src/pages/ecosystem/stacks-token-holders.md @@ -1,8 +1,9 @@ --- +title: Stacks token holders description: 'Blockstack token holder documentation' --- -# Information for current token holders +## Introduction The information on this page is intended for **current Stacks (STX) token holders** during Blockstack’s token sale through early 2018. @@ -18,28 +19,6 @@ address directly to Blockstack, you can either use the **Restore from Seed Phrase** feature on the Stacks Wallet or contact us at for help. - - - - - - - - - - - - - - - - - - - - - - You should see a report detailing the tokens allocated to your address and when they unlock: ![](/images/unlocking-address.png) diff --git a/src/pages/ecosystem/stacks-token.md b/src/pages/ecosystem/stacks-token.md index d16280b8..e3d3da19 100644 --- a/src/pages/ecosystem/stacks-token.md +++ b/src/pages/ecosystem/stacks-token.md @@ -1,6 +1,7 @@ --- title: Stacks token description: Learn about the native token of Blockstack +icon: StacksIcon --- # Learn more about the Stacks token diff --git a/src/pages/index.md b/src/pages/index.md index 03b43f4d..27ed8cf6 100644 --- a/src/pages/index.md +++ b/src/pages/index.md @@ -18,4 +18,4 @@ description: All you need to build decentralized apps and smart contracts. ## Explore [@page-reference | grid-small] -| /ecosystem/overview, /ecosystem/stacks-token +| /ecosystem/overview, /ecosystem/stacks-token, /smart-contracts/running-a-testnet-node diff --git a/src/pages/mining.md b/src/pages/mining.md index 62e57717..cf902347 100644 --- a/src/pages/mining.md +++ b/src/pages/mining.md @@ -6,4 +6,4 @@ images: sm: /images/pages/mining-sm.svg --- -# Mine Stacks Token +## Introduction diff --git a/src/pages/naming-services/architecture.md b/src/pages/naming-services/architecture.md index a075cab8..17ec171d 100644 --- a/src/pages/naming-services/architecture.md +++ b/src/pages/naming-services/architecture.md @@ -3,7 +3,7 @@ title: Blockstack naming service (BNS) description: The BNS node is the heart of the system. It is responsible for building up and replicating global name state. --- -# Understand the Architecture +## Understand the Architecture The BNS node is the heart of the system. It is responsible for building up and replicating global name state. diff --git a/src/pages/naming-services/build-profile-search-index.md b/src/pages/naming-services/build-profile-search-index.md index 4b243152..e15089c6 100644 --- a/src/pages/naming-services/build-profile-search-index.md +++ b/src/pages/naming-services/build-profile-search-index.md @@ -2,7 +2,7 @@ description: Blockstack naming service (BNS) --- -# How to build a Profile Search Index +## Introduction The search subsystem for Stacks Blockchain creates an index for data associated with registered names in namespaces and makes that data searchable. @@ -26,7 +26,7 @@ http://localhost:5000/search?query= This document describes how to setup the search subsystem to respond at that endpoint. -# Installation +## Installation - **Step 1:** First, make sure you have [virtualenv installed](http://docs.python-guide.org/en/latest/dev/virtualenvs/). Then, setup the API and search subsystem: @@ -67,7 +67,7 @@ python -m search.basic_index --refresh $ sed -i 's/SEARCH_API_ENDPOINT_ENABLED \= False/SEARCH_API_ENDPOINT_ENABLED \= True/' config.py ``` -# Usage +## Usage You can quickly test the search index from the command line: diff --git a/src/pages/naming-services/choose-name.md b/src/pages/naming-services/choose-name.md index e6db518d..268c7c90 100644 --- a/src/pages/naming-services/choose-name.md +++ b/src/pages/naming-services/choose-name.md @@ -3,10 +3,6 @@ title: Choose a name description: This section explains how to choose and create a namespace. --- -# Choose a name - -This section explains how to choose and create a namespace. - ## Intended uses for a namespace The intention is that each application can create its own BNS diff --git a/src/pages/naming-services/comparison.md b/src/pages/naming-services/comparison.md index a6e2bd9b..73b6f081 100644 --- a/src/pages/naming-services/comparison.md +++ b/src/pages/naming-services/comparison.md @@ -3,7 +3,7 @@ title: Feature comparison description: This page describes some other naming systems in comparison to Blockstack. --- -# Naming system feature comparison +## Introduction BNS is not the only naming system in wide-spread use, nor is it the only decentralized naming system that implements human-readable, globally-unique, and diff --git a/src/pages/naming-services/create-namespace.md b/src/pages/naming-services/create-namespace.md index f3558b36..89eba66c 100644 --- a/src/pages/naming-services/create-namespace.md +++ b/src/pages/naming-services/create-namespace.md @@ -3,7 +3,7 @@ title: Creating a Namespace description: Learn how to create a namespace in the Blockstack Naming Service. --- -# Creating a Namespace +## Introduction Making a namespace is very expensive. Given the large amount of cryptocurrency at stake in name creation, developers wanting to create their own namespaces should read [Understand Namespaces](/core/naming/namespaces) first. You should diff --git a/src/pages/naming-services/did.md b/src/pages/naming-services/did.md index 8fe80744..824d90a2 100644 --- a/src/pages/naming-services/did.md +++ b/src/pages/naming-services/did.md @@ -3,7 +3,7 @@ title: Decentralized Identifiers (DIDs) description: BNS nodes are compliant with the emerging Decentralized Identity Foundation protocol specification for decentralized identifiers. --- -# Decentralized Identifiers (DIDs) +## Introduction BNS nodes are compliant with the emerging [Decentralized Identity Foundation](http://identity.foundation) protocol diff --git a/src/pages/naming-services/forks.md b/src/pages/naming-services/forks.md index d21f4528..c0df74e3 100644 --- a/src/pages/naming-services/forks.md +++ b/src/pages/naming-services/forks.md @@ -3,7 +3,7 @@ title: BNS forks description: Learn about forks within the context of the BNS. --- -# BNS Forks +## Introduction BNS effectively uses a public blockchain to store a database log. A BNS peer bootstraps itself by downloading and replaying the database log from the diff --git a/src/pages/naming-services/manage-names.md b/src/pages/naming-services/manage-names.md index cd00d45f..cf44e88c 100644 --- a/src/pages/naming-services/manage-names.md +++ b/src/pages/naming-services/manage-names.md @@ -3,10 +3,6 @@ title: Manage BNS Names description: This section teaches you how to manage your namespace. --- -# Manage BNS Names - -This section teaches you how to manage your namespace. - ## Overview of management Once you register a BNS name, you have the power to change its zone file hash, diff --git a/src/pages/naming-services/namespaces.md b/src/pages/naming-services/namespaces.md index 9da19ac9..cdf7b9ea 100644 --- a/src/pages/naming-services/namespaces.md +++ b/src/pages/naming-services/namespaces.md @@ -3,7 +3,7 @@ title: Understand Namespaces description: Namespaces are the top-level naming objects in BNS. --- -# Understand Namespaces +## Introduction Namespaces are the top-level naming objects in BNS. diff --git a/src/pages/naming-services/overview.md b/src/pages/naming-services/overview.md index 8048450f..287132f5 100644 --- a/src/pages/naming-services/overview.md +++ b/src/pages/naming-services/overview.md @@ -97,7 +97,7 @@ can do the following and more: - Build public-key infrastructure where it's easy for users to discover and remember each other's keys. -# Organization of BNS +## Organization of BNS BNS names are organized into a global name hierarchy. There are three different layers in this hierarchy related to naming: diff --git a/src/pages/naming-services/register-name.md b/src/pages/naming-services/register-name.md index 05a36edf..8fd18bfc 100644 --- a/src/pages/naming-services/register-name.md +++ b/src/pages/naming-services/register-name.md @@ -3,11 +3,6 @@ title: Register a name description: This section explains registering BNS names and provides instructions for methods you can use to understand the cost of namespace registration. --- -# Register a name - -This section explains registering BNS names and provides instructions for methods -you can use to understand the cost of namespace registration. - ## Understand registration Registering a BNS name costs cryptocurrency. This cost comes from two sources: diff --git a/src/pages/naming-services/resolve-name.md b/src/pages/naming-services/resolve-name.md index e7304b50..a59e7296 100644 --- a/src/pages/naming-services/resolve-name.md +++ b/src/pages/naming-services/resolve-name.md @@ -3,11 +3,6 @@ title: Resolve a name description: This section explains resolving BNS names and provides instructions for methods you can use to accomplish namespace resolution. --- -## Resolve a name - -This section explains resolving BNS names and provides instructions for methods -you can use to accomplish namespace resolution. - ## Understand resolution BNS names are bound to both public keys and to about 40Kb of off-chain state. diff --git a/src/pages/naming-services/subdomains-tutorial.md b/src/pages/naming-services/subdomains-tutorial.md index 8fd8ac32..a3a75863 100644 --- a/src/pages/naming-services/subdomains-tutorial.md +++ b/src/pages/naming-services/subdomains-tutorial.md @@ -1,12 +1,11 @@ --- -description: 'Blockstack naming service (BNS)' +title: Subdomain registrar +description: Learn how to create, register, and run a subdomain registrar. --- -# Subdomain Design and Implementation +## Introduction -Subdomains allow us to provide names to end users cheaply (and quickly). This -tutorial explains you how to create, register, and run a subdomain register, it -contains the following sections: +Subdomains allow us to provide names to end users cheaply (and quickly). ## Strong subdomain ownership diff --git a/src/pages/naming-services/subdomains.md b/src/pages/naming-services/subdomains.md index 3037f906..a961c616 100644 --- a/src/pages/naming-services/subdomains.md +++ b/src/pages/naming-services/subdomains.md @@ -1,13 +1,9 @@ --- -description: 'Blockstack naming service (BNS)' +title: Subdomains +description: This section explains BNS subdomains and provides instructions for methods you can use to work with them. --- -# BNS Subdomains - -This section explains BNS subdomains and provides instructions for methods -you can use to work with them. The following topics are included: - -# Overview of subdomains +## Overview of subdomains BNS names are strongly-owned because the owner of its private key can generate valid transactions that update its zone file hash and owner. However, this comes at the @@ -236,8 +232,7 @@ subdomain registrars on behalf of their applications. For example, the name `personal.id` is used to register Blockstack application users without requiring them to spend any Bitcoin. -We supply a reference -implementation of a [BNS Subdomain Registrar](https://github.com/blockstack/subdomain-registrar) +We supply a reference implementation of a [BNS Subdomain Registrar](https://github.com/blockstack/subdomain-registrar) to help developers broadcast subdomain operations. Users would still own their subdomain names; the registrar simply gives developers a convenient way for them to register and manage them in the context of a particular application. diff --git a/src/pages/references/blockstack-cli.md b/src/pages/references/blockstack-cli.md index 170cc7bb..6adeb37a 100644 --- a/src/pages/references/blockstack-cli.md +++ b/src/pages/references/blockstack-cli.md @@ -5,7 +5,7 @@ title: Blockstack CLI export { convertBlockstackCLIUsageToMdx as getStaticProps } from '@common/data/cli-ref' import { CLIReferenceTable } from '@components/cli-reference' -# Blockstack CLI reference +## Introduction The command line is intended for developers only. Developers can use the command line to test and debug Blockstack applications in ways that the Blockstack @@ -17,8 +17,7 @@ Browser does not yet support. Using the command line, developers can: - Query Stacks Nodes - Implement a minimum viable authentication flow -!> Many of the commands operate on unencrypted private keys. For this reason, -DO NOT use this tool for day-to-day tasks as you risk the security of your keys. +!> Many of the commands operate on unencrypted private keys. For this reason, **DO NOT** use this tool for day-to-day tasks as you risk the security of your keys. You must install the command line before you can use the commands. diff --git a/src/pages/references/clarity-language.md b/src/pages/references/clarity-language.md index 81eae845..fe22c6c1 100644 --- a/src/pages/references/clarity-language.md +++ b/src/pages/references/clarity-language.md @@ -6,10 +6,6 @@ description: See a detailed list of all keywords and functions for the Clarity l export { convertClarityRefToMdx as getStaticProps } from '@common/data/clarity-ref' import { ClarityKeywordReference, ClarityFunctionReference } from '@components/clarity-ref' -# Clarity Language Reference - -This file contains the reference for the Clarity language. - ## Clarity Type System The Clarity language uses a strong static type system. Function arguments diff --git a/src/pages/references/deploy-tips.md b/src/pages/references/deploy-tips.md index 6fdd957b..d86c86f4 100644 --- a/src/pages/references/deploy-tips.md +++ b/src/pages/references/deploy-tips.md @@ -1,10 +1,13 @@ --- -description: Blockstack dApp documentation +title: Deploy tips +description: Learn some common methods for deploying your application. --- -# Deployment +## Introduction -Blockstack applications are web applications that authenticate users with Blockstack Auth and store data with Gaia. Both of these technologies can be accessed on the client side. As such, Blockstack apps tend to be simple in design and operation, since in many cases, they don’t have to host anything besides the application’s assets. +Blockstack applications are web applications that authenticate users with Blockstack Auth and store data with Gaia. +Both of these technologies can be accessed on the client side. As such, Blockstack apps tend to be simple in design and +operation, since in many cases, they don’t have to host anything besides the application’s assets. ## Where to deploy your application diff --git a/src/pages/references/faqs.md b/src/pages/references/faqs.md deleted file mode 100644 index 697befa4..00000000 --- a/src/pages/references/faqs.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: FAQs -description: This is a comprehensive list of all the Blockstack FAQs. -redirect_from: /org/voucherholder ---- - -export { convertFaqAnswersToMDX as getStaticProps } from '@common/data/faq' -import { FAQs } from '@components/faq' - -# Blockstack FAQs - -This is a comprehensive list of all the Blockstack FAQs. - -## General questions - - - -## Application user questions - - - -## Stacks Token questions - - - -## Stacks Wallet questions - - - -## DApp developers questions - - - -## Core developer questions - - - -## Open source developer questions - - - -## Miscellaneous questions - - - -## Important disclaimer - -_The Securities and Exchange Commission (SEC) has qualified the offering statement that we have filed with the SEC under Regulation A for our offering of certain of our Stacks Tokens. The information in that offering statement is more complete than the information we are providing now, and could differ in important ways. You must read the documents filed with the SEC before investing. The offering is being made only by means of its offering statement. This document shall not constitute an offer to sell or the solicitation of an offer to buy, nor shall there be any sale of these securities in any state or jurisdiction in which such offer, solicitation or sale would be unlawful prior to registration or qualification under the securities laws of any such state or jurisdiction._ - -_An indication of interest involves no obligation or commitment of any kind. Any person interested in investing in any offering of Stacks Tokens should review our disclosures and the publicly filed offering statement and the ffinal offering circular that is part of that offering statement. Blockstack is not registered, licensed or supervised as a broker dealer or investment adviser by the SEC, the Financial Industry Regulatory Authority (FINRA) or any other financial regulatory authority or licensed to provide any financial advice or services._ - -## Forward-looking statements - -_This communication contains forward-looking statements that are based on our beliefs and assumptions and on information currently available to us. In some cases, you can identify forward-looking statements by the following words: “will,” “expect,” “would,” “intend,” “believe,” or other comparable terminology. Forward-looking statements in this document include, but are not limited to, statements about our plans for developing the platform and future utility for the Stacks Token, our Clarity smart contracting language, and potential mining operations. These statements involve risks, uncertainties, assumptions and other factors that may cause actual results or performance to be materially different. More information on the factors, risks and uncertainties that could cause or contribute to such differences is included in our filings with the SEC, including in the “Risk Factors” and “Management’s Discussion & Analysis” sections of our offering statement on Form 1-A. We cannot assure you that the forward-looking statements will prove to be accurate. These forward-looking statements speak only as of the date hereof. We disclaim any obligation to update these forward-looking statements._ diff --git a/src/pages/references/glossary.md b/src/pages/references/glossary.md index 7aacdceb..3ccfa481 100644 --- a/src/pages/references/glossary.md +++ b/src/pages/references/glossary.md @@ -1,10 +1,9 @@ --- +title: Glossary description: A comprehensive list of terms used within the ecosystem. --- export { convertGlossaryToJson as getStaticProps } from '@common/data/glossary' import { Glossary } from '@components/glossary' -# Glossary - diff --git a/src/pages/references/stacks-blockchain.md b/src/pages/references/stacks-blockchain.md index 55733bfe..a30fac09 100644 --- a/src/pages/references/stacks-blockchain.md +++ b/src/pages/references/stacks-blockchain.md @@ -3,7 +3,7 @@ title: Stacks Blockchain APIs description: Interacting with the Stacks 2.0 Blockchain --- -# Stacks Blockchain APIs +## Introduction With the launch of Stacks 2.0, a new version of the Blockstack blockchain was released. There are two ways of interacting with the blockchain, either using the Stacks Blockchain API or by making RPC calls to a Stacks Core directly. @@ -15,6 +15,6 @@ The Stacks 2.0 blockchain's Rust implementation exposes RPC endpoints (in JSON f The Stacks Blockchain API was built to maintain pageable materialized views of the Stacks 2.0 Blockchain. It is a server that exposes a RESTful JSON API, hosted by PBC. It introduces aidditonal functionality (e.g. get all transactions), as well as proxies calls directly to Stacks Node. [You can find the OpenAPI specification and documentation here](https://blockstack.github.io/stacks-blockchain-sidecar/). -_Note: Using this API requires you to trust the server, but provides a faster onboarding experience. It also addresses performance issues for which querying a node itself would be too slow or difficult._ +~> Note: Using this API requires you to trust the server, but provides a faster onboarding experience. It also addresses performance issues for which querying a node itself would be too slow or difficult -> If you are looking for the Stacks 1.0 RPC endpoint references, please follow [this link](https://core.blockstack.org/). diff --git a/src/pages/references/stacks-rpc-api.md b/src/pages/references/stacks-rpc-api.md index d7714647..2a537877 100644 --- a/src/pages/references/stacks-rpc-api.md +++ b/src/pages/references/stacks-rpc-api.md @@ -3,7 +3,7 @@ title: Stacks Node RPC API description: Every running Stacks node exposes an RPC API, which allows you to interact with the underlying blockchain. --- -# RPC API Reference +## Introduction Every running Stacks node exposes an RPC API, which allows you to interact with the underlying blockchain. diff --git a/src/pages/smart-contracts/cli-wallet-quickstart.md b/src/pages/smart-contracts/cli-wallet-quickstart.md index 5f60a399..fe8e34a3 100644 --- a/src/pages/smart-contracts/cli-wallet-quickstart.md +++ b/src/pages/smart-contracts/cli-wallet-quickstart.md @@ -1,10 +1,12 @@ --- -description: 'Blockstack CLI Wallet Quickstart' +title: CLI Wallet quickstart +description: Learn how to set up a wallet via the CLI and send/receive STX on the Testnet. --- -# Send/Receive Stacks on Testnet +## Introduction -This quickstart guide will show you how to setup a Stacks wallet using the Blockstack JavaScript CLI and use it to send/receive Stacks tokens on Testnet. This wallet is intended for developer experimentation with Testnet only, do not use this wallet to store your tokens. +This quickstart guide will show you how to setup a Stacks wallet using the Blockstack JavaScript CLI and use it to +send/receive Stacks tokens on Testnet. This wallet is intended for developer experimentation with Testnet only, do not use this wallet to store your tokens. ## Prerequisites diff --git a/src/pages/smart-contracts/counter-tutorial.md b/src/pages/smart-contracts/counter-tutorial.md index 7d528bf4..31aa6736 100644 --- a/src/pages/smart-contracts/counter-tutorial.md +++ b/src/pages/smart-contracts/counter-tutorial.md @@ -1,4 +1,5 @@ --- +title: Counter tutorial description: Learn how to write a simple smart contract in the Clarity language. experience: intermediate duration: 30 minutes @@ -9,7 +10,7 @@ images: sm: /images/pages/counter-tutorial-sm.svg --- -# Counter smart contract +## Introduction In this tutorial, you learn how to implement a smart contract that stores and manipulates an integer value on the Stacks 2.0 blockchain. By the end of this tutorial, you will ... diff --git a/src/pages/smart-contracts/hello-world-tutorial.md b/src/pages/smart-contracts/hello-world-tutorial.md index f961dfbb..4f6f5c59 100644 --- a/src/pages/smart-contracts/hello-world-tutorial.md +++ b/src/pages/smart-contracts/hello-world-tutorial.md @@ -1,6 +1,6 @@ --- title: Hello, World! -description: Get Started Writing Smart Contracts with Clarity +description: Learn the basics of Clarity and write a simple Hello World smart contract. duration: 18 minutes experience: beginners images: @@ -8,9 +8,7 @@ images: sm: /images/pages/hello-world-sm.svg --- -# Hello, World! - -## Overview +## Introduction In the world of smart contracts, everything is a blockchain transaction. You use tokens in your wallet to deploy a smart contract in a transaction, and each call to that contract after it's published is a transaction, too. That means that at each step, tokens are being exchanged as transaction fees. This tutorial introduces you to this mode of programming, which transforms blockchains into powerful state machines capable of executing complex logic. @@ -149,8 +147,6 @@ Locate the `(echo-number)` method, provide any integer for the `val` argument an **Congratulations! You just deployed your smart contract and called a public function on the Testnet.** ---- - With the completion of this tutorial, you now: - Have a working Clarity starter project and local dev environment @@ -207,8 +203,3 @@ blockstack call_contract_func hello-world echo-number 2000 1 Next tutorial: Writing a counter smart contract -- Tutorial: Testing contracts with JavaScript and Mocha diff --git a/src/pages/smart-contracts/install-source.md b/src/pages/smart-contracts/install-source.md index b0e823a9..4536723e 100644 --- a/src/pages/smart-contracts/install-source.md +++ b/src/pages/smart-contracts/install-source.md @@ -1,8 +1,9 @@ --- +title: Install Clarity from source description: 'Blockstack smart contracting language' --- -# Install Clarity from Source +## Installation Build using `rust` and `cargo`: diff --git a/src/pages/smart-contracts/overview.md b/src/pages/smart-contracts/overview.md index 0bc2f66b..59d54648 100644 --- a/src/pages/smart-contracts/overview.md +++ b/src/pages/smart-contracts/overview.md @@ -6,21 +6,28 @@ images: sm: /images/pages/smart-contracts-sm.svg --- -# Write smart contracts +## Introduction -Clarity is a programming language for writing smart contracts on the Stacks 2.0 blockchain. It supports programmatic control over digital assets. +Clarity is a programming language for writing smart contracts on the Stacks 2.0 blockchain. It supports programmatic +control over digital assets. ## Smart contracts -Smart contracts encode and enforce rules for modifying a particular set of data that is shared among people and entities who don't necessarily trust each other. For example, a smart contract can hold funds in escrow until multiple parties agree to release them, create its own ledger and keep track of its own novel tokens (fungible or non-fungible), and even help make supply chains more transparent. +Smart contracts encode and enforce rules for modifying a particular set of data that is shared among people and entities +who don't necessarily trust each other. For example, a smart contract can hold funds in escrow until multiple parties +agree to release them, create its own ledger and keep track of its own novel tokens (fungible or non-fungible), and +even help make supply chains more transparent. -Because smart contracts are programs that exist in a blockchain, anyone can query them, and anyone can submit transactions to execute them. A smart contract execution can result in new transactions being written to the blockchain. +Because smart contracts are programs that exist in a blockchain, anyone can query them, and anyone can submit transactions +to execute them. A smart contract execution can result in new transactions being written to the blockchain. -Apps can take advantage of smart contracts to manage a global state that is visible to the public. Anyone can audit the blockchain in order to independently verify that an app's global shared state has been managed correctly according to the smart contract's rules. +Apps can take advantage of smart contracts to manage a global state that is visible to the public. Anyone can audit the +blockchain in order to independently verify that an app's global shared state has been managed correctly according to the smart contract's rules. ## Use cases -Not every decentralized application requires smart contracts, but Clarity unlocks interesting capabilities for decentralized applications. Examples of use cases include, but are not limited to: +Not every decentralized application requires smart contracts, but Clarity unlocks interesting capabilities for +decentralized applications. Examples of use cases include, but are not limited to: - Access control (e.g. pay to access) - Non-fungible (e.g. collectibles) and fungible tokens (e.g. stablecoins) @@ -35,20 +42,29 @@ Clarity differs from most other smart contract languages in two essential ways: - The language is interpreted and broadcast on the blockchain as is (not compiled) - The language is decidable (not Turing complete) -Using an interpreted language ensures that the executed code is human-readable and auditable. A decidable language like Clarity makes it possible to determine precisely which code is going to be executed, for any function. +Using an interpreted language ensures that the executed code is human-readable and auditable. A decidable language +like Clarity makes it possible to determine precisely which code is going to be executed, for any function. -A Clarity smart contract is composed of two parts — a data space and a set of functions. Only the associated smart contract may modify its corresponding data space on the blockchain. Functions may be private and thus callable only from within the smart contract, or public and thus callable from other contracts. Users call smart contracts' public functions by broadcasting a transaction on the blockchain which invokes the public function. Contracts can also call public functions from other smart contracts. +A Clarity smart contract is composed of two parts — a data space and a set of functions. Only the associated +smart contract may modify its corresponding data space on the blockchain. Functions may be private and thus callable +only from within the smart contract, or public and thus callable from other contracts. Users call smart contracts' +public functions by broadcasting a transaction on the blockchain which invokes the public function. Contracts +can also call public functions from other smart contracts. Note some of the key Clarity language rules and limitations. - The only primitive types are booleans, integers, buffers, and principals - Recursion is illegal and there are no anonymous functions. - Looping may only be performed via `map`, `filter`, or `fold` -- There is support for lists, however, the only variable length lists in the language appear as function inputs; There is no support for list operations like append or join. +- There is support for lists, however, the only variable length lists in the language appear as function inputs; + There is no support for list operations like append or join. - Variables are immutable. ## Learning Clarity -The tutorials are ordered from "beginner" to "advanced." Start with the [Hello World tutorial](tutorial), then learn how to construct [a counter](tutorial-counter), and finally, learn how to [test your smart contracts](tutorial-test) using Mocha. +The tutorials are ordered from "beginner" to "advanced." Start with the [Hello World tutorial](/smart-contracts/hello-world-tutorial), +then learn how to construct [a counter](/smart-contracts/counter-tutorial), and finally, learn how to +[test your smart contracts](/smart-contracts/testing-contracts) using Mocha. -Once you've got the hang of the general workflow, environment, and language syntax, you should be ready to start writing contracts, referring to the [Clarity language reference](clarityRef) as you go. +Once you've got the hang of the general workflow, environment, and language syntax, you should be ready to start writing +contracts, referring to the [Clarity language reference](/references/clarity-language) as you go. diff --git a/src/pages/smart-contracts/principals.md b/src/pages/smart-contracts/principals.md index b6e2bf91..1a650bb7 100644 --- a/src/pages/smart-contracts/principals.md +++ b/src/pages/smart-contracts/principals.md @@ -1,8 +1,9 @@ --- +title: Principals description: 'Clarity: Understanding Principals' --- -# Understanding Principals +## Introduction _Principals_ are a Clarity native type that represents an entity that can have a token balance. This section discusses principals and how they are used in the Clarity. diff --git a/src/pages/smart-contracts/running-a-testnet-node.md b/src/pages/smart-contracts/running-a-testnet-node.md index 5afd1f3e..6f51d422 100644 --- a/src/pages/smart-contracts/running-a-testnet-node.md +++ b/src/pages/smart-contracts/running-a-testnet-node.md @@ -1,3 +1,9 @@ +--- +title: Testnet +description: Run the latest builds of a Stacks Testnet node +icon: TestnetIcon +--- + # Running a Testnet Node The Stacks 2.0 testnet is currently in development. As part of the testnet, you can run a node and connect it to a public network. This guide will walk you through downloading and running your own node in the testnet network. diff --git a/src/pages/smart-contracts/signing-transactions.md b/src/pages/smart-contracts/signing-transactions.md index fd964abe..2cbf3037 100644 --- a/src/pages/smart-contracts/signing-transactions.md +++ b/src/pages/smart-contracts/signing-transactions.md @@ -1,8 +1,11 @@ --- title: Signing transactions +description: Learn how to sign transactions using Blockstack Connect. +experience: advanced +duration: 30 minutes --- -# Signing transactions +## Introduction With Connect, you can interact with the Stacks 2.0 blockchain. You can allow your users to send transactions and interact with smart contracts. diff --git a/src/pages/smart-contracts/testing-contracts.md b/src/pages/smart-contracts/testing-contracts.md index 84caf00b..dea8f0e3 100644 --- a/src/pages/smart-contracts/testing-contracts.md +++ b/src/pages/smart-contracts/testing-contracts.md @@ -1,13 +1,11 @@ --- title: Testing Clarity code -description: Learn to Test Clarity Contract Code with JavaScript and Mocha +description: Learn to Test Clarity Contract Code with JavaScript and Mocha. experience: advanced duration: 15 minutes --- -# Testing Clarity code - -## Overview +## Introduction Clarity, Blockstack's smart contracting language, is based on [LISP](). Clarity is an interpreted language, and [decidable](https://en.wikipedia.org/wiki/Recursive_language). In this tutorial, you will learn how to test Clarity and how use [Mocha](https://mochajs.org/) to test Clarity contracts while you develop them. diff --git a/src/pages/stacks-blockchain/atlas/how-atlas-works.md b/src/pages/stacks-blockchain/atlas/how-atlas-works.md index 42cae118..b9b87b23 100644 --- a/src/pages/stacks-blockchain/atlas/how-atlas-works.md +++ b/src/pages/stacks-blockchain/atlas/how-atlas-works.md @@ -3,7 +3,7 @@ title: How Atlas works description: Atlas was designed to overcome the structural weaknesses inherent to all distributed hash tables. --- -# How Atlas Works +## Introduction Atlas was designed to overcome the structural weaknesses inherent to all distributed hash tables. In particular, it uses an unstructured peer network to diff --git a/src/pages/stacks-blockchain/atlas/overview.md b/src/pages/stacks-blockchain/atlas/overview.md index 6df5f0ae..0cd06ea6 100644 --- a/src/pages/stacks-blockchain/atlas/overview.md +++ b/src/pages/stacks-blockchain/atlas/overview.md @@ -3,7 +3,7 @@ title: Overview of the Atlas network description: This document describes the Atlas network, a peer-to-peer content-addressed storage system whose chunks' hashes are announced on a public blockchain. --- -# Overview of the Atlas network +## Introduction This document describes the Atlas network, a peer-to-peer content-addressed storage system whose chunks' hashes are announced on a public blockchain. Atlas diff --git a/src/pages/stacks-blockchain/atlas/usage.md b/src/pages/stacks-blockchain/atlas/usage.md index 1204b3d8..69edf77e 100644 --- a/src/pages/stacks-blockchain/atlas/usage.md +++ b/src/pages/stacks-blockchain/atlas/usage.md @@ -3,8 +3,6 @@ title: How to use the Atlas network description: This section teaches you how to use the Atlas network. --- -# How to Use the Atlas Network - ## The API While the Blockstack software stack expects that Atlas-hosted data is made up of diff --git a/src/pages/stacks-blockchain/best-practices.md b/src/pages/stacks-blockchain/best-practices.md index a31ca7d0..299fc270 100644 --- a/src/pages/stacks-blockchain/best-practices.md +++ b/src/pages/stacks-blockchain/best-practices.md @@ -1,9 +1,8 @@ --- title: Best practices +descriptions: Helpful tips for getting a core node up and running. --- -# Best practices - ## Hardware and OS requirements - A 64-bit CPU running at at least 1 GHz is _highly_ recommended (but not strictly required) diff --git a/src/pages/stacks-blockchain/install-api.md b/src/pages/stacks-blockchain/install-api.md index 02a7af27..afe6f2c7 100644 --- a/src/pages/stacks-blockchain/install-api.md +++ b/src/pages/stacks-blockchain/install-api.md @@ -1,6 +1,12 @@ -# Blockstack API +--- +title: Blockstack API +description: Step-by-step instructions for deploying a Blockstack API node on Debian or Ubuntu are below. +duration: 30 minutes +tags: + - tutorial +--- -Step-by-step instructions for deploying a Blockstack API node on Debian or Ubuntu are below. +## Introduction - **Step 1:** Make sure you have a Stacks Node running locally (see [instructions](https://github.com/blockstack/blockstack-core/blob/master/README.md#quick-start)). @@ -82,5 +88,5 @@ sudo systemctl restart blockstack_api sudo systemctl restart nginx ``` -If you run into any issues, please [submit a Github issue](https://github.com/blockstack/blockstack-core/issues) and we'll update these +If you run into any issues, please [submit a Github issue](https://github.com/blockstack/stacks-blockchain/issues) and we'll update these instructions. diff --git a/src/pages/stacks-blockchain/installing-memcached.md b/src/pages/stacks-blockchain/installing-memcached.md index 6f66a017..3e615676 100644 --- a/src/pages/stacks-blockchain/installing-memcached.md +++ b/src/pages/stacks-blockchain/installing-memcached.md @@ -1,4 +1,7 @@ -# Installing Memcached +--- +title: Installing Memcached +description: Learn how to install Memcached to improve performance of a local Blockstack API instance. +--- The Blockstack API optionally uses memcached and pylibmc for scaling read-only calls. If you want to enable this functionality then you should have memcached diff --git a/src/pages/stacks-blockchain/overview.md b/src/pages/stacks-blockchain/overview.md index 3e2a4fbe..3b26fc2d 100644 --- a/src/pages/stacks-blockchain/overview.md +++ b/src/pages/stacks-blockchain/overview.md @@ -2,4 +2,4 @@ title: Overview --- -# Overview +## Introduction diff --git a/src/pages/stacks-blockchain/wire-format.md b/src/pages/stacks-blockchain/wire-format.md index fefec275..b0fcfff0 100644 --- a/src/pages/stacks-blockchain/wire-format.md +++ b/src/pages/stacks-blockchain/wire-format.md @@ -1,4 +1,9 @@ -# Bitcoin wire format +--- +title: Bitcoin wire format +description: Learn about the format of transactions used for name operations in the Blockstack network. +--- + +## Introduction This page is for organizations who want to be able to create and send name operation transactions to the blockchain(s) Blockstack supports. It describes the transaction formats for the Bitcoin blockchain. diff --git a/src/pages/stacks-wallet/install.md b/src/pages/stacks-wallet/install.md index 884664e7..baaddf8c 100644 --- a/src/pages/stacks-wallet/install.md +++ b/src/pages/stacks-wallet/install.md @@ -1,8 +1,9 @@ --- -description: 'How to use the Blockstack Software' +title: Install the Stacks wallet +description: Learn how to install the Stacks wallet --- -# Install the Stacks Wallet software +## Introduction You use the Stacks Wallet software client alone or with a hardware wallet to send and receive Stacks (STX) tokens. On this page, you learn how to install the Stacks Wallet software. diff --git a/src/pages/stacks-wallet/overview.md b/src/pages/stacks-wallet/overview.md index 33e1d93b..b646b948 100644 --- a/src/pages/stacks-wallet/overview.md +++ b/src/pages/stacks-wallet/overview.md @@ -1,8 +1,9 @@ --- -description: 'How to use the Blockstack Software' +title: Stacks wallet overview +description: Learn about cryptocurrency wallets, STX, and the Stacks wallet. --- -# Understand cryptocurrency wallets +## Introduction If you are, or plan to be a Stacks token holder, you need to think about how you can manage your Stacks (STX) tokens. How can you review your token balance? How can send or diff --git a/src/pages/stacks-wallet/security.md b/src/pages/stacks-wallet/security.md index c666f484..55a274c4 100644 --- a/src/pages/stacks-wallet/security.md +++ b/src/pages/stacks-wallet/security.md @@ -1,8 +1,9 @@ --- -description: 'Blockstack Network documentation' +title: Wallet security +description: Best practices for keeping your wallet(s) secure. --- -# Wallet and identity security +## Introduction It is important that you understand how to keep good security for your Stacks Wallet software and your Blockstack identity. @@ -12,7 +13,7 @@ Both your wallet seed phrase and your Secret Recovery Code are cryptographic key Stacks Wallet software. A **Secret Recovery Code** gives you access to your Blockstack identity. You need to use the strictest security available to you for both of these keys. -The CrtypoCurrency Security Standard publishes [guidelines for key storage](https://cryptoconsortium.github.io/CCSS/Details/#1.03). +The Cryptocurrency Security Standard publishes [guidelines for key storage](https://cryptoconsortium.github.io/CCSS/Details/#1.03). These guidelines are presented from least (Level I) to most secure (Level III). We recommend you store your keys with at least Level II security. This level states that you should: diff --git a/src/pages/stacks-wallet/troubleshooting.md b/src/pages/stacks-wallet/troubleshooting.md deleted file mode 100644 index 05f64c0a..00000000 --- a/src/pages/stacks-wallet/troubleshooting.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -description: 'How to use the Blockstack Software' ---- - -export { convertFaqAnswersToMDX as getStaticProps } from '@common/data/faq' -import { FAQs } from '@components/faq' - - - -# Wallet FAQs and Troubleshooting - -This page contains frequently asked questions and troubleshooting related to the wallet. - -## Frequently asked questions - - - -## Change from a software-only wallet to a hardware wallet - -To change from a software-only wallet to a hardware wallet, do the following: - -1. Purchase and set up your hardware wallet according to the manufacturer's instructions. -2. **Reset** the Blockstack Software wallet according to the instructions. -3. Choose the hardware wallet option to setup the Blockstack Software wallet. -4. Use the **Receive** button to display the Stacks address. -5. Login into your Coinlist account. -6. Change your Stacks wallet address. - -## View or change your Stacks wallet address on Coinlist - -If you purchased Stacks via Coinlist during in the token sale, your Stacks address is located at this URL: - -``` -https://sale.stackstoken.com/stacks-token-sale/YOUR_COINLIST_USERNAME/wallet_address -``` - -For example, if your Coinlist user name is `Eleven`, the URL you would use is: - -``` -https://sale.stackstoken.com/stacks-token-sale/Eleven/wallet_address -``` - -To view or change your Stacks address on Coinlist, do the following: - -1. Log into your Coinlist account. -2. Enter a URL in this format: - - ``` - https://sale.stackstoken.com/stacks-token-sale/YOUR_COINLIST_USERNAME/wallet_address - ``` - -3. Change your address if necessary. - -## I tried to login to CoinList with my AngelList account. Now, I can’t sign in. How do I access my account? - -If you previously set up your CoinList account by logging in with your AngelList credentials and you are having issues signing into your account, you must create a separate password for Coinlist. To do this: - -1. Go to stackstoken.net. -2. Select **Forgot your Password?**. -3. Enter the email associated with your AngelList account. -4. Select **Send recovery email**. -5. Locate the recovery email in your email software. -6. Use the instructions in the recovery email to create a unique password for your CoinList account. - -Going forward, you can access your CoinList account by logging in with your email and new password. diff --git a/src/pages/stacks-wallet/usage.md b/src/pages/stacks-wallet/usage.md index 4c7afc10..089c20d9 100644 --- a/src/pages/stacks-wallet/usage.md +++ b/src/pages/stacks-wallet/usage.md @@ -1,10 +1,11 @@ --- -description: 'Blockstack Network documentation' +title: Using the Stacks wallet +description: Learn how to use the Stacks wallet --- -# Use the Stacks Wallet software +## Introduction -This page describes how to use the Stacks Wallet software to manager your Stacks (STX) tokens. This page contains the following topics: +This page describes how to use the Stacks Wallet software to manager your Stacks (STX) tokens. The Stacks Wallet software is installed on your computer, it is not a web application. You should have already [downloaded, verified, and installed the wallet software](wallet-install). @@ -270,8 +271,7 @@ They are maintained. Once you reset the wallet, you have to start over from the _Terms of Use_. If you do not restart the wallet, you can simple close it. -1. Click the - (settings icon) in the upper right corner of the wallet. +1. Click the settings icon in the upper right corner of the wallet. The system opens the **Settings** dialog. @@ -280,7 +280,7 @@ you do not restart the wallet, you can simple close it. 2. Select **Reset Wallet**. System asks for confirmation. If, for some reason, you want to stop the reset - you would press (right corner) or **Close**. + you would press close icon in the right corner or **Close**. 3. Select **Are you sure?** to complete the reset. diff --git a/src/pages/storage-hubs/amazon-s3-deploy.md b/src/pages/storage-hubs/amazon-s3-deploy.md index 4b4bf441..64738662 100644 --- a/src/pages/storage-hubs/amazon-s3-deploy.md +++ b/src/pages/storage-hubs/amazon-s3-deploy.md @@ -1,20 +1,19 @@ --- -description: 'Storing user data with Blockstack' +title: Configure a hub on Amazon EC2 +description: Learn how to run a Gaia hub on Amazon EC2. --- -# Configure a hub on Amazon EC2 +## Introduction This teaches you how to run a Gaia hub on Amazon EC2. Amazon EC2 is an affordable and convenient cloud computing provider. This example uses Amazon EC2 instance together with an [EBS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonEBS.html) disk for file storage. -> #### Is this tutorial for you? -> -> This documentation is appropriate for advanced power users who are familiar with command line tools, `ssh`, and -> basic editing configuration files. -> -> If you are planning on running an _open-membership hub_ or an _application-specific hub_, see -> [the section on Hub Operation](hub-operation). +#### Is this tutorial for you? + +-> This documentation is appropriate for advanced power users who are familiar with command line tools, `ssh`, and basic editing configuration files. + +-> If you are planning on running an _open-membership hub_ or an _application-specific hub_, see [the section on Hub Operation](hub-operation). ## Prerequisites you need diff --git a/src/pages/storage-hubs/config-schema.md b/src/pages/storage-hubs/config-schema.md index e7b5550f..d9bc7fb7 100644 --- a/src/pages/storage-hubs/config-schema.md +++ b/src/pages/storage-hubs/config-schema.md @@ -1,8 +1,9 @@ --- +title: Hub configuration description: 'Storing user data with Blockstack' --- -# Hub configuration parameters +## Schema The following JSON schema details the possible parameters for a hub configuration: diff --git a/src/pages/storage-hubs/digital-ocean-deploy.md b/src/pages/storage-hubs/digital-ocean-deploy.md index 947d81d8..d202ea53 100644 --- a/src/pages/storage-hubs/digital-ocean-deploy.md +++ b/src/pages/storage-hubs/digital-ocean-deploy.md @@ -1,8 +1,9 @@ --- +title: Configure a hub on DigitalOcean description: 'Storing user data with Blockstack' --- -# Configure a hub on DigitalOcean +## Introduction This teaches you how to run a Gaia storage hub on DigitalOcean (DO). DigitalOcean is an affordable and convenient cloud computing provider. This example uses DigitalOcean Spaces for file storage. A space is equivalent to AWS's S3 file storage solution. diff --git a/src/pages/storage-hubs/gaia-admin.md b/src/pages/storage-hubs/gaia-admin.md index b1a57d09..f976cf46 100644 --- a/src/pages/storage-hubs/gaia-admin.md +++ b/src/pages/storage-hubs/gaia-admin.md @@ -3,7 +3,7 @@ title: Gaia admin description: 'Storing user data with Blockstack' --- -# Use the admin service +## Introduction A Gaia service can run a simple administrative service co-located with your Gaia hub. This service allows you to administer the Gaia hub with the help of an API key. Gaia hubs installed using the Gaia Amazon Machine Image (AMI) have this service integrated automatically. diff --git a/src/pages/storage-hubs/hello-hub-choice.md b/src/pages/storage-hubs/hello-hub-choice.md index aa6de79e..3212174d 100644 --- a/src/pages/storage-hubs/hello-hub-choice.md +++ b/src/pages/storage-hubs/hello-hub-choice.md @@ -1,8 +1,9 @@ --- +title: Hello world hub choice description: 'Storing user data with Blockstack' --- -# Hello hub choice tutorial +## Introduction -> The functionality described in this tutorial has been deprecated with the Blockstack Browser. It will continue working only for apps that have not yet upgraded to Blockstack Connect. diff --git a/src/pages/storage-hubs/overview.md b/src/pages/storage-hubs/overview.md index 4379f028..91d73c8c 100644 --- a/src/pages/storage-hubs/overview.md +++ b/src/pages/storage-hubs/overview.md @@ -4,10 +4,6 @@ redirect_from: - /storage/hello-hub-choice.html --- -# Understand hub operation - -This page describes the considerations hub operators must take into account when creating and operating a Gaia storage hub. - ## Configuration files You should store a JSON configuration file either in the top-level directory of diff --git a/yarn.lock b/yarn.lock index 414fc793..da898a64 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,11 +9,23 @@ dependencies: "@algolia/cache-common" "4.3.1" +"@algolia/cache-browser-local-storage@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.4.0.tgz#f58055bdf798d7b31b6d5f86e465cb0fc7dd6694" + integrity sha512-2AiKgN7DpFypkRCRkpqH7waXXyFdcnsPWzmN8sLHrB/FfXqgmsQb3pGft+9YHZIDQ0vAnfgMxSGgMhMGW+0Qnw== + dependencies: + "@algolia/cache-common" "4.4.0" + "@algolia/cache-common@4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.3.1.tgz#2470fd0a358ae5a66119851d77cdf12969b53591" integrity sha512-BgZVQKfQ3rYSKHDbEuYeIHgQ7cIqbDVUe8gPib/YI6hB2FWdt3hQyDqKslulBt65MxZ5CLSrWg8mq/qL077Bog== +"@algolia/cache-common@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.4.0.tgz#bfe84790230f5d2de495238b29e9397c5ed2b26e" + integrity sha512-PrIgoMnXaDWUfwOekahro543pgcJfgRu/nd/ZQS5ffem3+Ow725eZY6HDpPaQ1k3cvLii9JH6V2sNJConjqUKA== + "@algolia/cache-in-memory@4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.3.1.tgz#905a27ab5f1303b1e0fea719bc808784e9415169" @@ -21,6 +33,13 @@ dependencies: "@algolia/cache-common" "4.3.1" +"@algolia/cache-in-memory@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.4.0.tgz#54a089094c2afa5b9cacab4b60a5f1ba29013a7c" + integrity sha512-9+XlUB0baDU/Dp9URRHPp6Q37YmTO0QmgPWt9+n+wqZrRL0jR3Jezr4jCT7RemqGMxBiR+YpnqaUv0orpb0ptw== + dependencies: + "@algolia/cache-common" "4.4.0" + "@algolia/client-account@4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.3.1.tgz#e84f93e2c3375a9defc690e4c24b2e2d9a28824f" @@ -30,6 +49,15 @@ "@algolia/client-search" "4.3.1" "@algolia/transporter" "4.3.1" +"@algolia/client-account@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.4.0.tgz#7dbeff83e1c85d853b3ad224674a924e02b94d1b" + integrity sha512-Kynu3cMEs0clTLf674rtrCF+FWR/JwlQxKlIWsPzvLBRmNXdvYej9YBcNaOr4OTQFCCZn9JVE8ib91Z7J4IL1Q== + dependencies: + "@algolia/client-common" "4.4.0" + "@algolia/client-search" "4.4.0" + "@algolia/transporter" "4.4.0" + "@algolia/client-analytics@4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.3.1.tgz#391227f0e2cc1a7fefedbab06f4b2b78f59579a5" @@ -40,6 +68,16 @@ "@algolia/requester-common" "4.3.1" "@algolia/transporter" "4.3.1" +"@algolia/client-analytics@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.4.0.tgz#50dde68b067c615fc91434c98db9b5ca429be33d" + integrity sha512-GQyjQimKAc9sZbafxln9Wk7j4pEYiORv28MZkZ+0Bjt7WNXIeO7OgOOECVpQHm9buyV6hCKpNtJcbb5/syRzdQ== + dependencies: + "@algolia/client-common" "4.4.0" + "@algolia/client-search" "4.4.0" + "@algolia/requester-common" "4.4.0" + "@algolia/transporter" "4.4.0" + "@algolia/client-common@4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.3.1.tgz#053580c0c2ed982eb2f65c7d728238f3da67db4e" @@ -48,6 +86,14 @@ "@algolia/requester-common" "4.3.1" "@algolia/transporter" "4.3.1" +"@algolia/client-common@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.4.0.tgz#b9fa987bc7a148f9756da59ada51fe2494a4aa9a" + integrity sha512-a3yr6UhzjWPHDG/8iGp9UvrDOm1aeHVWJIf0Nj/cIvqX5tNCEIo4IMe59ovApkDgLOIpt/cLsyhn9/FiPXRhJA== + dependencies: + "@algolia/requester-common" "4.4.0" + "@algolia/transporter" "4.4.0" + "@algolia/client-recommendation@4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@algolia/client-recommendation/-/client-recommendation-4.3.1.tgz#e693b16cdf6ec7fa532f9ab39143c8dabed5cc76" @@ -57,6 +103,15 @@ "@algolia/requester-common" "4.3.1" "@algolia/transporter" "4.3.1" +"@algolia/client-recommendation@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@algolia/client-recommendation/-/client-recommendation-4.4.0.tgz#82410f7a346ed8518b8dcd28bc47571e850ab74f" + integrity sha512-sBszbQH46rko6w2fdEG77ma8+fAg0SDkLZGxWhv4trgcnYGUBFl2dcpEPt/6koto9b4XYlf+eh+qi6iGvYqRPg== + dependencies: + "@algolia/client-common" "4.4.0" + "@algolia/requester-common" "4.4.0" + "@algolia/transporter" "4.4.0" + "@algolia/client-search@4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.3.1.tgz#e0a3d9b757855901a185d3d918b27af28d520a5b" @@ -66,11 +121,25 @@ "@algolia/requester-common" "4.3.1" "@algolia/transporter" "4.3.1" +"@algolia/client-search@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.4.0.tgz#c1e107206f3ae719cd3a9877889eea5e5cbcdc62" + integrity sha512-jqWcxCUyPPHnHreoMb2PnN9iHTP+V/nL62R84XuTRDE3VgTnhm4ZnqyuRdzZQqaz+gNy5znav64TmQ9FN9WW5g== + dependencies: + "@algolia/client-common" "4.4.0" + "@algolia/requester-common" "4.4.0" + "@algolia/transporter" "4.4.0" + "@algolia/logger-common@4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.3.1.tgz#31d2ff5f81a3e2424cfb4b205e64cfd7b1acfba5" integrity sha512-HOY89EkxFFR0LjeqE+fqaF3EeQUAYFdVdrAXsnrWhm/OsAlXiy+vsoHL4EaJLXvTQlJRBbgNyyQv8ZPAN9JLCw== +"@algolia/logger-common@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.4.0.tgz#8115d95d5f6227f0127d33130a9c4622cde64f6f" + integrity sha512-2vjmSENLaKNuF+ytRDysfWxxgFG95WXCHwHbueThdPMCK3hskkwqJ0Y/pugKfzl+54mZxegb4BYfgcCeuaHVUw== + "@algolia/logger-console@4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.3.1.tgz#f61f2e0ed67ae92556d7e1b1cb4f08e270b2734b" @@ -78,6 +147,13 @@ dependencies: "@algolia/logger-common" "4.3.1" +"@algolia/logger-console@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.4.0.tgz#1e0eaaf0879f152f9a1fa333c4cd8cb55e071552" + integrity sha512-st/GUWyKvr6YM72OOfF+RmpdVGda3BPXbQ+chpntUq1WyVkyZXGjSmH1IcBVlua27GzxabwOUYON39cF3x10/g== + dependencies: + "@algolia/logger-common" "4.4.0" + "@algolia/requester-browser-xhr@4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.3.1.tgz#c664be05dbdddbd63cb66c4e32b598b563ab83d1" @@ -85,11 +161,23 @@ dependencies: "@algolia/requester-common" "4.3.1" +"@algolia/requester-browser-xhr@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.4.0.tgz#f5877397ed92d2d64d08846ea969aeb559a5efb6" + integrity sha512-V3a4hXlNch355GnWaT1f5QfXhROpsjT6sd0Znq29gAhwLqfBExhLW6Khdkv5pENC0Qy7ClVhdXFrBL9QCQer1g== + dependencies: + "@algolia/requester-common" "4.4.0" + "@algolia/requester-common@4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.3.1.tgz#215084aa1ea025b1f2f73eb03b437de89c7c6c39" integrity sha512-2lu0gOB2Rt4mn9gKDxjB8rY2IvU4usDA8bZVGl5tf/E81kRovtDZcgZjuKQ5zMyJ/xuIYXjx+ECXAxjUnNhieA== +"@algolia/requester-common@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.4.0.tgz#0e977939aae32ff81a6d27480a71771a65db6051" + integrity sha512-jPinHlFJEFokxQ5b3JWyjQKKn+FMy0hH99PApzOgQAYOSiFRXiPEZp6LeIexDeLLu7Y3eRt/3nHvjPKa6PmRRw== + "@algolia/requester-node-http@4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.3.1.tgz#8ffaeef57c1410e32d59565fbd2db6705bffaa92" @@ -97,6 +185,13 @@ dependencies: "@algolia/requester-common" "4.3.1" +"@algolia/requester-node-http@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.4.0.tgz#6ffba93d54eeadf64cb1be67fae5c4e3f7c8f390" + integrity sha512-b7HC9C/GHxiV4+0GpCRTtjscvwarPr3dGm4CAhb6AkNjgjRcFUNr1NfsF75w3WVmzmt79/7QZihddztDdVMGjw== + dependencies: + "@algolia/requester-common" "4.4.0" + "@algolia/transporter@4.3.1": version "4.3.1" resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.3.1.tgz#8320b29cabf54a1486435bea51d1c562952337ce" @@ -106,6 +201,15 @@ "@algolia/logger-common" "4.3.1" "@algolia/requester-common" "4.3.1" +"@algolia/transporter@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.4.0.tgz#6ec79aac43bc515c8e4f6d6e27dc8d8cd7112f7e" + integrity sha512-Xxzq91DEEeKIzT3DU46n4LEyTGAKZNtSHc2H9wvIY5MYwhZwEribmXXZ6k8W1FvBvzggv3juu0SP+xwGoR7F0w== + dependencies: + "@algolia/cache-common" "4.4.0" + "@algolia/logger-common" "4.4.0" + "@algolia/requester-common" "4.4.0" + "@ampproject/toolbox-core@^2.5.4": version "2.5.4" resolved "https://registry.yarnpkg.com/@ampproject/toolbox-core/-/toolbox-core-2.5.4.tgz#8554c5398b6d65d240085a6b0abb94f9a3276dce" @@ -1375,19 +1479,48 @@ use-events "^1.4.1" use-onclickoutside "^0.3.1" -"@docsearch/css@^1.0.0-alpha.26": - version "1.0.0-alpha.26" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-1.0.0-alpha.26.tgz#a2f9b61168d527600b0e3f31c0f04998002f3aa2" - integrity sha512-YAa7R6O2MMdRtxTaMB3TTfeelhpf01J1xtnGZEQa7LNA64QO8BErceQIMQq5/ZMXnGViK/eUjqSVyCu7uzYE5w== +"@blockstack/ui@file:.yalc/@blockstack/ui": + version "2.12.4" + dependencies: + "@popperjs/core" "^2.4.0" + "@reach/alert" "^0.10.2" + "@reach/auto-id" "^0.10.0" + "@reach/rect" "^0.10.2" + "@styled-system/css" "5.1.5" + "@styled-system/should-forward-prop" "^5.1.5" + "@styled-system/theme-get" "^5.1.2" + "@types/react-transition-group" "^4.2.4" + "@types/styled-components" "^5.1.0" + "@types/styled-system" "^5.1.6" + "@types/styled-system__css" "^5.0.8" + "@types/styled-system__should-forward-prop" "^5.1.1" + "@types/styled-system__theme-get" "^5.0.0" + color "3.1.2" + flushable "^1.0.0" + prettier "^2.0.5" + prism-react-renderer "^1.0.2" + prismjs "^1.20.0" + prop-types "^15.7.2" + react-spring "8.0.27" + react-transition-group "^4.4.1" + styled-system "5.1.5" + type-fest "^0.15.1" + use-events "^1.4.1" + use-onclickoutside "^0.3.1" + +"@docsearch/css@^1.0.0-alpha.27": + version "1.0.0-alpha.27" + resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-1.0.0-alpha.27.tgz#7f50985869ebab10ffb901b94ed7545269a3393c" + integrity sha512-Kw6R/gAHMZW2tKZO2a0gd3I8Yf6bJgTk3Dp+L0ZFrvEHEh8v3yQKvoxVify3ML9YVyvCxxAPQQuF9u3JNUwvXw== -"@docsearch/react@^1.0.0-alpha.26": - version "1.0.0-alpha.26" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-1.0.0-alpha.26.tgz#98b736d7de951bfa55cf3d0eb3639f93c9dd1db2" - integrity sha512-2eKIcUXuWbGgz6/xF+p7kYyd1IVGcnB8r+oIkTD6Tqtq0VGzZmf9ZPCOX37G38pVIJXAAxmtAb7oPO311xGWNQ== +"@docsearch/react@^1.0.0-alpha.27": + version "1.0.0-alpha.27" + resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-1.0.0-alpha.27.tgz#eae61d648ddc3667c5dee82c4cd9d47bf35a3c85" + integrity sha512-jcgUHZsrNNRsaVsplqKhXWheh4VzRTCdhsPuVhJMRvfsFUqXEPo/7kVt5xIybtOj9u+/FVdeSO+APJEE2rakYA== dependencies: - "@docsearch/css" "^1.0.0-alpha.26" - "@francoischalifour/autocomplete-core" "^1.0.0-alpha.26" - "@francoischalifour/autocomplete-preset-algolia" "^1.0.0-alpha.26" + "@docsearch/css" "^1.0.0-alpha.27" + "@francoischalifour/autocomplete-core" "^1.0.0-alpha.27" + "@francoischalifour/autocomplete-preset-algolia" "^1.0.0-alpha.27" algoliasearch "^4.0.0" "@emotion/is-prop-valid@^0.8.1", "@emotion/is-prop-valid@^0.8.8": @@ -1412,15 +1545,15 @@ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== -"@francoischalifour/autocomplete-core@^1.0.0-alpha.26": - version "1.0.0-alpha.26" - resolved "https://registry.yarnpkg.com/@francoischalifour/autocomplete-core/-/autocomplete-core-1.0.0-alpha.26.tgz#fc9ec90a62f0665c7092d19a649c751fe3794de3" - integrity sha512-XUXAGVx0My9isShokR1QB/oPFQiaPYDCouoTZTN+DISQw5AK6kGZUCFFXJSRNHTxBq1/0e70DYEiQa8E+rT/Og== +"@francoischalifour/autocomplete-core@^1.0.0-alpha.27": + version "1.0.0-alpha.27" + resolved "https://registry.yarnpkg.com/@francoischalifour/autocomplete-core/-/autocomplete-core-1.0.0-alpha.27.tgz#bd85058bf0ef02e9f9a57c7973c705edc2a25c41" + integrity sha512-kpKbtrjMt9l1HIFFmmH0u88633/1oBD+mEjKg1EIRJ1zQCeOBxlQvIXZ3X6GEoud79QjLVoc8HD4HN1OMRt+OA== -"@francoischalifour/autocomplete-preset-algolia@^1.0.0-alpha.26": - version "1.0.0-alpha.26" - resolved "https://registry.yarnpkg.com/@francoischalifour/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.0.0-alpha.26.tgz#3e20315d43dfef6c676cab4267974de70c2f6ec2" - integrity sha512-RrayxZgvTzpwq+RqEIpVn2UOEFLwa+HADCr2I3UI05o/OGU7Wc6LltpQy54scR+FlAIk6qTJwp5Nw/ecJn6xXg== +"@francoischalifour/autocomplete-preset-algolia@^1.0.0-alpha.27": + version "1.0.0-alpha.27" + resolved "https://registry.yarnpkg.com/@francoischalifour/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.0.0-alpha.27.tgz#29de9939274887363f6e3f41078b2ee3e9c56493" + integrity sha512-Mp4lhlLd8vuLOCXtuw8UTUaJXGRrXYL7AN/ZmhaMwqyL9e9XSqLlcv82EWP0NAMcoz/I1E1C709h4jnbnN4llw== "@hashicorp/remark-plugins@^3.0.0": version "3.0.0" @@ -1435,41 +1568,16 @@ unist-util-map "^2.0.1" unist-util-visit "^2.0.2" -"@mdx-js/loader@1.6.15": - version "1.6.15" - resolved "https://registry.yarnpkg.com/@mdx-js/loader/-/loader-1.6.15.tgz#11d5ed30c7c0d3e5a5dbfa946f5e097ad547db03" - integrity sha512-ssDjQByfiZdBKaP8Hyti1KzFW3t4DsFMcGRbU+0CQjVQ0xjcnymswFSAL+7Q8Yh2kK1HkeUHsHpFP+8l/fSoUQ== +"@mdx-js/loader@1.6.16": + version "1.6.16" + resolved "https://registry.yarnpkg.com/@mdx-js/loader/-/loader-1.6.16.tgz#5a9c3b0ab41885cd2df85bcf360644ca63e44e88" + integrity sha512-jYIAav17lXmEvweO6bzbsqY9mRTm49UeXXSZPAB81uCX8j91Pgi50Z0NnEN777yQEgGm2Z5PMtnJdxGFQIAjJQ== dependencies: - "@mdx-js/mdx" "1.6.15" - "@mdx-js/react" "1.6.15" + "@mdx-js/mdx" "1.6.16" + "@mdx-js/react" "1.6.16" loader-utils "2.0.0" -"@mdx-js/mdx@1.6.15": - version "1.6.15" - resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.15.tgz#96e3db4e442008501ba7c4457382c02ff938f13a" - integrity sha512-jDp29ATBPliN8FlMpB11287x+MbpM/xj8uT5E7i1+2SoMgDNc/B1EqNd5eZLFYT0lyDk9IyKkcE0w0A0o616RA== - dependencies: - "@babel/core" "7.10.5" - "@babel/plugin-syntax-jsx" "7.10.4" - "@babel/plugin-syntax-object-rest-spread" "7.8.3" - "@mdx-js/util" "1.6.15" - babel-plugin-apply-mdx-type-prop "1.6.15" - babel-plugin-extract-import-names "1.6.15" - camelcase-css "2.0.1" - detab "2.0.3" - hast-util-raw "6.0.0" - lodash.uniq "4.5.0" - mdast-util-to-hast "9.1.0" - remark-footnotes "1.0.0" - remark-mdx "1.6.15" - remark-parse "8.0.3" - remark-squeeze-paragraphs "4.0.0" - style-to-object "0.3.0" - unified "9.1.0" - unist-builder "2.0.3" - unist-util-visit "2.0.3" - -"@mdx-js/mdx@^1.6.16", "@mdx-js/mdx@^1.6.8": +"@mdx-js/mdx@1.6.16", "@mdx-js/mdx@^1.6.16", "@mdx-js/mdx@^1.6.8": version "1.6.16" resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.16.tgz#f01af0140539c1ce043d246259d8becd2153b2bb" integrity sha512-jnYyJ0aCafCIehn3GjYcibIapaLBgs3YkoenNQBPcPFyyuUty7B3B07OE+pMllhJ6YkWeP/R5Ax19x0nqTzgJw== @@ -1494,21 +1602,11 @@ unist-builder "2.0.3" unist-util-visit "2.0.3" -"@mdx-js/react@1.6.15": - version "1.6.15" - resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.15.tgz#99a6061d0f74f2d01b95ad0314efba9ad6f19e81" - integrity sha512-C8yhsYZyFwL2kTa4Yw1zFIUxHcl225NrP75F6qgNbBum1APcsnl0WQ7N5V/l515gxnJmXSRQ6uL7pAFPZvdmzA== - -"@mdx-js/react@^1.6.16", "@mdx-js/react@^1.6.8": +"@mdx-js/react@1.6.16", "@mdx-js/react@^1.6.16", "@mdx-js/react@^1.6.8": version "1.6.16" resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.16.tgz#538eb14473194d0b3c54020cb230e426174315cd" integrity sha512-+FhuSVOPo7+4fZaRwWuCSRUcZkJOkZu0rfAbBKvoCg1LWb1Td8Vzi0DTLORdSvgWNbU6+EL40HIgwTOs00x2Jw== -"@mdx-js/util@1.6.15": - version "1.6.15" - resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.15.tgz#0e555fac778dfb1bd99ffedc00a22a26a26564f1" - integrity sha512-0JTd7as6t6sYiMfoOgGodNqD3hf/WlHPhZBNdZdyMWJDoqSq2uv12iNsBQP4jytvsREvEZyKjA944EAImxLz/w== - "@mdx-js/util@1.6.16": version "1.6.16" resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.16.tgz#07a7342f6b61ea1ecbfb31e6e23bf7a8c79b9b57" @@ -1526,10 +1624,10 @@ resolved "https://registry.yarnpkg.com/@next/mdx/-/mdx-9.5.1.tgz#c7e2fd457810b34e8ce598f57075b799ca48751b" integrity sha512-jmNKqEMWkCPQWWeoq6CiOShngGv99Cs+rQSLlU7BZMVCZzbcTVEkAsUqR4WfLA97K2ihjtNidY5jwbKFu4h83Q== -"@next/react-dev-overlay@9.5.2-canary.7": - version "9.5.2-canary.7" - resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-9.5.2-canary.7.tgz#41f1f4a2513a897b548620f6e45df030602c495d" - integrity sha512-lDFIorQQE55Z62XvouJ7XcRw5EzU6LiZjoeilpnfpCXMyhPvxXR/XZ2P5WwM/6/+8o5DjvXlsEhyY2T2C9RJLQ== +"@next/react-dev-overlay@9.5.2-canary.9": + version "9.5.2-canary.9" + resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-9.5.2-canary.9.tgz#c14c4490b72236886990b380ab1f563527ed7760" + integrity sha512-CG3vcw9ASxmGNETs6svNhIII0PE9DkFyceB1gglKMcyJGa5bsqOaKXNRa3gDur8DrotOk5fbiecfXg3AM0VglQ== dependencies: "@babel/code-frame" "7.8.3" ally.js "1.4.1" @@ -1542,10 +1640,10 @@ stacktrace-parser "0.1.10" strip-ansi "6.0.0" -"@next/react-refresh-utils@9.5.2-canary.7": - version "9.5.2-canary.7" - resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-9.5.2-canary.7.tgz#db801584c088a1a961c771eb5fbbbf91b5764e32" - integrity sha512-6Lk9eEhwaK+KYCaaIqbCBTexw9J3BCJn4xJq589aW0IghWYXTFuJB/w3W4ZHxUFC4jJWvw6Y/eOpNvDQh05Xww== +"@next/react-refresh-utils@9.5.2-canary.9": + version "9.5.2-canary.9" + resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-9.5.2-canary.9.tgz#6b922e1998e3d04c1a643347ff35632c417a43cc" + integrity sha512-VfC6dlsXQk3Ub2Sm8mL305Zb2uRpu2flEil+WGt2aDuJwQInII+/jQ9Yvz/wwoEV/QnmqZ4xuBY2FTL2Bfpq9w== "@popperjs/core@^2.4.0": version "2.4.4" @@ -2243,7 +2341,7 @@ algoliasearch@^3.24.5: semver "^5.1.0" tunnel-agent "^0.6.0" -algoliasearch@^4.0.0, algoliasearch@^4.3.1: +algoliasearch@^4.0.0: version "4.3.1" resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.3.1.tgz#dea6ad87705e0439855cf3e5a4406b74e794b874" integrity sha512-q8aIYgdZZWOMzmvlIwxcbktVa8+M5cyI8hIrgd/NcSz/XKHfVTKdNYbnsmPqmYrssAmepx8C8vHnJrPuumUnYA== @@ -2263,6 +2361,26 @@ algoliasearch@^4.0.0, algoliasearch@^4.3.1: "@algolia/requester-node-http" "4.3.1" "@algolia/transporter" "4.3.1" +algoliasearch@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.4.0.tgz#25c356d8bdcf7e3f941633f61e1ac111ddcba404" + integrity sha512-Ag3wxe/nSodNl/1KbHibtkh7TNLptKE300/wnGVtszRjXivaWD6333nUpCumrYObHym/fHMHyLcmQYezXbAIWQ== + dependencies: + "@algolia/cache-browser-local-storage" "4.4.0" + "@algolia/cache-common" "4.4.0" + "@algolia/cache-in-memory" "4.4.0" + "@algolia/client-account" "4.4.0" + "@algolia/client-analytics" "4.4.0" + "@algolia/client-common" "4.4.0" + "@algolia/client-recommendation" "4.4.0" + "@algolia/client-search" "4.4.0" + "@algolia/logger-common" "4.4.0" + "@algolia/logger-console" "4.4.0" + "@algolia/requester-browser-xhr" "4.4.0" + "@algolia/requester-common" "4.4.0" + "@algolia/requester-node-http" "4.4.0" + "@algolia/transporter" "4.4.0" + ally.js@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/ally.js/-/ally.js-1.4.1.tgz#9fb7e6ba58efac4ee9131cb29aa9ee3b540bcf1e" @@ -2489,14 +2607,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2" integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA== -babel-plugin-apply-mdx-type-prop@1.6.15: - version "1.6.15" - resolved "https://registry.yarnpkg.com/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.15.tgz#d970e46033e47259d330c5cb64bbcde74098ac92" - integrity sha512-viGIiG66GOJoID7kJZRrAh15e7y/Calfi5vDgkF6soxT6OO57rWH+rqrC2Uo0e26Cs/uhyOo4M5UKRKutbEPgg== - dependencies: - "@babel/helper-plugin-utils" "7.10.4" - "@mdx-js/util" "1.6.15" - babel-plugin-apply-mdx-type-prop@1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.16.tgz#4becd65b3aa108f15c524a0b125ca7c81f3443d8" @@ -2512,13 +2622,6 @@ babel-plugin-dynamic-import-node@^2.3.3: dependencies: object.assign "^4.1.0" -babel-plugin-extract-import-names@1.6.15: - version "1.6.15" - resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.15.tgz#03f98dc11f40ad261dbd9ad89d5ca0ebc83aeea0" - integrity sha512-t7EdzuBXMKKwRZbxe0EiFNRZGo4vhnSDKGCllBEgYnUs/PqDfGCPweg6ztPDEFWRJRZ0TCfNhlthslfyUPTOjA== - dependencies: - "@babel/helper-plugin-utils" "7.10.4" - babel-plugin-extract-import-names@1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.16.tgz#b964004e794bdd62534c525db67d9e890d5cc079" @@ -6357,10 +6460,10 @@ next-transpile-modules@^4.0.2: micromatch "^4.0.2" slash "^3.0.0" -next@^9.5.2-canary.7: - version "9.5.2-canary.7" - resolved "https://registry.yarnpkg.com/next/-/next-9.5.2-canary.7.tgz#4f753ba974e58c5f07a4d00eb484b3f4d38fc2cb" - integrity sha512-Alo6nQf5VMr3X9kZYXPLjQDlKUMapRuRqRpf9VqgFjE2mxXPGEpfSz6EHz4KuQpcCYflE2RxrHaWKeL8+DgaIw== +next@^9.5.2-canary.9: + version "9.5.2-canary.9" + resolved "https://registry.yarnpkg.com/next/-/next-9.5.2-canary.9.tgz#e8d3bdbcb8e72dbbb862b764b0e79632b3a09bdb" + integrity sha512-IcYGrJkmsdETJwwOSl+Hq8H1XktItBMxFqUNnfPh1QHroKMZ3MuPfpb+dhnmV1s9+PZWhq/FkJSuM4jx01xo6A== dependencies: "@ampproject/toolbox-optimizer" "2.5.14" "@babel/code-frame" "7.8.3" @@ -6381,8 +6484,8 @@ next@^9.5.2-canary.7: "@babel/preset-typescript" "7.9.0" "@babel/runtime" "7.9.6" "@babel/types" "7.9.6" - "@next/react-dev-overlay" "9.5.2-canary.7" - "@next/react-refresh-utils" "9.5.2-canary.7" + "@next/react-dev-overlay" "9.5.2-canary.9" + "@next/react-refresh-utils" "9.5.2-canary.9" ast-types "0.13.2" babel-plugin-syntax-jsx "6.18.0" babel-plugin-transform-define "2.0.0" @@ -7323,16 +7426,21 @@ preact-render-to-string@^5.1.4: dependencies: pretty-format "^3.8.0" -preact-ssr-prepass@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/preact-ssr-prepass/-/preact-ssr-prepass-1.1.0.tgz#62390309cfac3f7c1d3fe3708b63b828ab2ee9f9" - integrity sha512-NZMBkRDZKmflEhA5YRMeaBgcvYmqorbWjpoSQ3s1bG/5FN5tgnMCw8slLHndUEeFOEHX2OquhxFotmF1tkgGHg== +preact-ssr-prepass@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/preact-ssr-prepass/-/preact-ssr-prepass-1.1.1.tgz#1031e50c3b80cbdd8e155e520d0e97b9bc425faa" + integrity sha512-AszER25gPq8GMcUP+PruRCRg6FEgeoVfR8tlquz7QCPbRLSqkmHkTNwRiwx0zeRl0wd0CtFN4D9r6zCPeVo8Hg== preact@^10.4.4: version "10.4.6" resolved "https://registry.yarnpkg.com/preact/-/preact-10.4.6.tgz#86cc43396e4bdd755726a2b4b1f0529e78067cd3" integrity sha512-80WJfXH53yyINig5Wza/8MD9n4lMg9G6aN00ws0ptsAaY/Fu/M7xW4zICf7OLfocVltxS30wvNQ8oIbUyZS1tw== +preact@^10.4.7: + version "10.4.7" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.4.7.tgz#5a530d34b4ba45f38234be8b1b3fe910098a165f" + integrity sha512-DtnnPbOm7oxW7Sxf5Co+KSIOxo7bGm0vLfJN/wGey7G2sAGKnGP5+bFyE2YIgutMISQl6xFVTsOd6l/Au88VVw== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -7821,20 +7929,6 @@ remark-images@2.0.0: unist-util-is "^4.0.0" unist-util-visit-parents "^3.0.0" -remark-mdx@1.6.15: - version "1.6.15" - resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-1.6.15.tgz#8762b8ebda06d8d775908aed342852fa641df414" - integrity sha512-YrEB0Qm8/rkL9rverXuHq5kGgobFQnSKwiQy9SH8S9AXu592O+UnoMaw+TRLiycBIbLUM3wf9dxtg/2sRjc68Q== - dependencies: - "@babel/core" "7.10.5" - "@babel/helper-plugin-utils" "7.10.4" - "@babel/plugin-proposal-object-rest-spread" "7.10.4" - "@babel/plugin-syntax-jsx" "7.10.4" - "@mdx-js/util" "1.6.15" - is-alphabetical "1.0.4" - remark-parse "8.0.3" - unified "9.1.0" - remark-mdx@1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-1.6.16.tgz#13ee40ad0614a1cc179aca3604d7f1b79e498a2f" @@ -8895,10 +8989,10 @@ svgo@^1.0.0: unquote "~1.1.1" util.promisify "~1.0.0" -swr@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/swr/-/swr-0.2.3.tgz#e0fb260d27f12fafa2388312083368f45127480d" - integrity sha512-JhuuD5ojqgjAQpZAhoPBd8Di0Mr1+ykByVKuRJdtKaxkUX/y8kMACWKkLgLQc8pcDOKEAnbIreNjU7HfqI9nHQ== +swr@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/swr/-/swr-0.3.0.tgz#69602953dd50ab07fe60c920fd63199256645675" + integrity sha512-3p0p5TWH0qiaKAph5wBkMwqe2WjNseITfjmdVoNzjqRZGn/gnpRi6whMDjhMVb/vp/yyDtKWPlyjid8QZH+UhA== dependencies: fast-deep-equal "2.0.1"