Browse Source

feat: design improvements, page org, images, homepage

fix/enable-imgix
Thomas Osmonson 4 years ago
parent
commit
66b1a5a9cd
  1. 160
      lib/remark-custom-blocks.js
  2. 4
      lib/remark-plugins.js
  3. 3
      package.json
  4. 10
      public/images/pages/authentication-sm.svg
  5. 5
      public/images/pages/authentication.svg
  6. 9
      public/images/pages/build-an-app-sm.svg
  7. 9
      public/images/pages/build-an-app.svg
  8. 7
      public/images/pages/connect-sm.svg
  9. 12
      public/images/pages/connect.svg
  10. 14
      public/images/pages/counter-tutorial-sm.svg
  11. 11
      public/images/pages/counter-tutorial.svg
  12. 12
      public/images/pages/data-storage-sm.svg
  13. 6
      public/images/pages/data-storage.svg
  14. 13
      public/images/pages/hello-world-sm.svg
  15. 8
      public/images/pages/hello-world.svg
  16. 10
      public/images/pages/mining-sm.svg
  17. 5
      public/images/pages/mining.svg
  18. 13
      public/images/pages/radiks-sm.svg
  19. 8
      public/images/pages/radiks.svg
  20. 24
      public/images/pages/smart-contracts-sm.svg
  21. 14
      public/images/pages/smart-contracts.svg
  22. 18
      public/images/pages/todo-app-sm.svg
  23. 13
      public/images/pages/todo-app.svg
  24. 17
      src/common/config.ts
  25. 3
      src/common/constants.ts
  26. 9
      src/common/data/clarity-ref.ts
  27. 0
      src/common/data/hydrate-mdx.ts
  28. 20
      src/common/navigation.yaml
  29. 11
      src/common/utils/index.ts
  30. 12
      src/components/clarity-ref.tsx
  31. 2
      src/components/cli-reference.tsx
  32. 1
      src/components/content-wrapper.tsx
  33. 109
      src/components/custom-blocks/page-reference.tsx
  34. 2
      src/components/faq.tsx
  35. 2
      src/components/glossary.tsx
  36. 109
      src/components/header.tsx
  37. 6
      src/components/layouts/base-layout.tsx
  38. 21
      src/components/layouts/markdown-wrapper.tsx
  39. 72
      src/components/mdx/components/code.tsx
  40. 18
      src/components/mdx/components/heading.tsx
  41. 18
      src/components/mdx/md-contents.tsx
  42. 55
      src/components/mdx/styles.tsx
  43. 96
      src/components/mdx/typography.ts
  44. 131
      src/components/pagination.tsx
  45. 2
      src/components/search.tsx
  46. 123
      src/components/side-nav.tsx
  47. 7
      src/components/toc.tsx
  48. 30
      src/components/typography.tsx
  49. 8
      src/pages/_document.tsx
  50. 3
      src/pages/authentication/building-todo-app.md
  51. 21
      src/pages/authentication/connect.md
  52. 3
      src/pages/authentication/overview.md
  53. 2
      src/pages/authentication/profiles.md
  54. 19
      src/pages/build-an-app.md
  55. 5
      src/pages/data-indexing/overview.md
  56. 5
      src/pages/data-storage/overview.md
  57. 19
      src/pages/index.md
  58. 3
      src/pages/mining.md
  59. 2
      src/pages/references/blockstack-cli.md
  60. 3
      src/pages/references/clarity-language.md
  61. 3
      src/pages/references/faqs.md
  62. 2
      src/pages/references/glossary.md
  63. 2
      src/pages/references/stacks-blockchain.md
  64. 3
      src/pages/references/stacks-rpc-api.md
  65. 5
      src/pages/smart-contracts/counter-tutorial.md
  66. 9
      src/pages/smart-contracts/hello-world-tutorial.md
  67. 10
      src/pages/smart-contracts/overview.md
  68. 0
      src/pages/smart-contracts/running-a-testnet-node.md
  69. 16
      src/pages/smart-contracts/testing-contracts.md
  70. 25
      yarn.lock

160
lib/remark-custom-blocks.js

@ -0,0 +1,160 @@
const spaceSeparated = require('space-separated-tokens');
function escapeRegExp(str) {
return str.replace(new RegExp(`[-[\\]{}()*+?.\\\\^$|/]`, 'g'), '\\$&');
}
const C_NEWLINE = '\n';
const C_FENCE = '|';
function compilerFactory(nodeType) {
let text;
let title;
return {
blockHeading(node) {
title = this.all(node).join('');
return '';
},
blockBody(node) {
text = this.all(node)
.map(s => s.replace(/\n/g, '\n| '))
.join('\n|\n| ');
return text;
},
block(node) {
text = '';
title = '';
this.all(node);
if (title) {
return `[[${nodeType} | ${title}]]\n| ${text}`;
} else {
return `[[${nodeType}]]\n| ${text}`;
}
},
};
}
module.exports = function blockPlugin(availableBlocks = {}) {
const pattern = Object.keys(availableBlocks).map(escapeRegExp).join('|');
if (!pattern) {
throw new Error('remark-custom-blocks needs to be passed a configuration object as option');
}
const regex = new RegExp(`\\[\@(${pattern})(?: *\\| *(.*))?\]\n`);
function blockTokenizer(eat, value, silent) {
const now = eat.now();
const keep = regex.exec(value);
if (!keep) return;
if (keep.index !== 0) return;
const [eaten, blockType, blockTitle] = keep;
/* istanbul ignore if - never used (yet) */
if (silent) return true;
const linesToEat = [];
const content = [];
let idx = 0;
while ((idx = value.indexOf(C_NEWLINE)) !== -1) {
const next = value.indexOf(C_NEWLINE, idx + 1);
// either slice until next NEWLINE or slice until end of string
const lineToEat = next !== -1 ? value.slice(idx + 1, next) : value.slice(idx + 1);
if (lineToEat[0] !== C_FENCE) break;
// remove leading `FENCE ` or leading `FENCE`
const line = lineToEat.slice(lineToEat.startsWith(`${C_FENCE} `) ? 2 : 1);
linesToEat.push(lineToEat);
content.push(line);
value = value.slice(idx + 1);
}
const contentString = content.join(C_NEWLINE);
const stringToEat = eaten + linesToEat.join(C_NEWLINE);
const potentialBlock = availableBlocks[blockType];
const titleAllowed =
potentialBlock.title && ['optional', 'required'].includes(potentialBlock.title);
const titleRequired = potentialBlock.title && potentialBlock.title === 'required';
if (titleRequired && !blockTitle) return;
if (!titleAllowed && blockTitle) return;
const add = eat(stringToEat);
if (potentialBlock.details) {
potentialBlock.containerElement = 'details';
potentialBlock.titleElement = 'summary';
}
const exit = this.enterBlock();
const contents = {
type: `${blockType}CustomBlockBody`,
data: {
hName: potentialBlock.contentsElement ? potentialBlock.contentsElement : 'div',
hProperties: {
className: 'custom-block-body',
},
},
children: this.tokenizeBlock(contentString, now),
};
exit();
const blockChildren = [contents];
if (titleAllowed && blockTitle) {
const titleElement = potentialBlock.titleElement ? potentialBlock.titleElement : 'div';
const titleNode = {
type: `${blockType}CustomBlockHeading`,
data: {
hName: titleElement,
hProperties: {
className: 'custom-block-heading',
},
},
children: this.tokenizeInline(blockTitle, now),
};
blockChildren.unshift(titleNode);
}
const classList = spaceSeparated.parse(potentialBlock.classes || '');
return add({
type: `${blockType}CustomBlock`,
children: blockChildren,
data: {
hName: potentialBlock.containerElement ? potentialBlock.containerElement : 'div',
hProperties: {
className: ['custom-block', ...classList],
},
},
});
}
const Parser = this.Parser;
// Inject blockTokenizer
const blockTokenizers = Parser.prototype.blockTokenizers;
const blockMethods = Parser.prototype.blockMethods;
blockTokenizers.customBlocks = blockTokenizer;
blockMethods.splice(blockMethods.indexOf('fencedCode') + 1, 0, 'customBlocks');
const Compiler = this.Compiler;
if (Compiler) {
const visitors = Compiler.prototype.visitors;
if (!visitors) return;
Object.keys(availableBlocks).forEach(key => {
const compiler = compilerFactory(key);
visitors[`${key}CustomBlock`] = compiler.block;
visitors[`${key}CustomBlockHeading`] = compiler.blockHeading;
visitors[`${key}CustomBlockBody`] = compiler.blockBody;
});
}
// Inject into interrupt rules
const interruptParagraph = Parser.prototype.interruptParagraph;
const interruptList = Parser.prototype.interruptList;
const interruptBlockquote = Parser.prototype.interruptBlockquote;
interruptParagraph.splice(interruptParagraph.indexOf('fencedCode') + 1, 0, ['customBlocks']);
interruptList.splice(interruptList.indexOf('fencedCode') + 1, 0, ['customBlocks']);
interruptBlockquote.splice(interruptBlockquote.indexOf('fencedCode') + 1, 0, ['customBlocks']);
};

4
lib/remark-plugins.js

@ -6,11 +6,10 @@ const emoji = require('remark-emoji');
const paragraphAlerts = require('./remark-paragraph-alerts');
const images = require('remark-images');
const unwrapImages = require('remark-unwrap-images');
const normalizeHeadings = require('remark-normalize-headings');
const slug = require('remark-slug');
const headingID = require('remark-heading-id');
const sectionize = require('remark-sectionize');
const customBlocks = require('remark-custom-blocks');
const customBlocks = require('./remark-custom-blocks');
const externalLinks = require('remark-external-links');
const remarkPlugins = [
@ -19,7 +18,6 @@ const remarkPlugins = [
memoize(emoji),
memoize(images),
memoize(unwrapImages),
memoize(normalizeHeadings),
memoize(slug),
memoize(headingID),
memoize(sectionize),

3
package.json

@ -20,6 +20,7 @@
"babel-plugin-macros": "^2.8.0",
"cache-manager": "^3.3.0",
"cache-manager-fs-hash": "^0.0.9",
"capsize": "^1.1.0",
"csvtojson": "^2.0.10",
"docsearch.js": "^2.6.3",
"fathom-client": "^3.0.0",
@ -64,7 +65,7 @@
"swr": "^0.2.3",
"turndown": "^6.0.0",
"typescript": "^3.9.7",
"unified-vscode": "^1.0.0-beta.0",
"unified-vscode": "^1.0.0-beta.1",
"unist-builder": "^2.0.3",
"unist-util-is": "^4.0.2",
"unist-util-select": "^3.0.1",

10
public/images/pages/authentication-sm.svg

@ -0,0 +1,10 @@
<svg width="65" height="65" viewBox="0 0 65 65" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="65" height="65">
<rect x="0.970947" y="0.439056" width="64" height="64" fill="#F0F0F5"/>
</mask>
<g mask="url(#mask0)">
<rect x="0.970947" y="0.439056" width="64" height="64" fill="#9985FF"/>
<ellipse cx="32.9708" cy="24.9807" rx="8.53326" ry="8.54167" fill="white"/>
<path opacity="0.64" d="M45.7707 35.6265C45.7707 37.3091 45.4396 38.9752 44.7964 40.5297C44.1531 42.0841 43.2103 43.4966 42.0217 44.6863C40.8331 45.8761 39.4221 46.8199 37.8691 47.4637C36.3161 48.1076 34.6517 48.439 32.9708 48.439C31.2899 48.439 29.6254 48.1076 28.0725 47.4637C26.5195 46.8199 25.1085 45.8761 23.9199 44.6863C22.7313 43.4966 21.7885 42.0841 21.1452 40.5297C20.502 38.9752 20.1709 37.3091 20.1709 35.6265L32.9708 35.6265H45.7707Z" fill="white"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 919 B

5
public/images/pages/authentication.svg

@ -0,0 +1,5 @@
<svg width="257" height="145" viewBox="0 0 257 145" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.394897" y="0.439056" width="256" height="144" fill="#9985FF"/>
<ellipse cx="128.395" cy="51.9287" rx="23.4665" ry="23.4896" fill="white"/>
<path opacity="0.64" d="M163.595 81.2046C163.595 85.8316 162.684 90.4134 160.915 94.6882C159.146 98.9631 156.553 102.847 153.285 106.119C150.016 109.391 146.136 111.986 141.865 113.757C137.595 115.528 133.017 116.439 128.395 116.439C123.772 116.439 119.195 115.528 114.925 113.757C110.654 111.986 106.774 109.391 103.505 106.119C100.236 102.847 97.6436 98.9631 95.8746 94.6882C94.1057 90.4134 93.1952 85.8316 93.1952 81.2046L128.395 81.2046H163.595Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 723 B

9
public/images/pages/build-an-app-sm.svg

@ -0,0 +1,9 @@
<svg width="65" height="65" viewBox="0 0 65 65" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.576431" y="0.439056" width="64" height="64" fill="#9985FF"/>
<path opacity="0.64" d="M12.8595 14.3444H43.1224V44.5018H12.8595V14.3444Z" fill="white"/>
<path d="M39.0873 26.4078L53.21 50.5338H24.9646L39.0873 26.4078Z" fill="white"/>
<path d="M54.2183 28.4182C54.2183 30.6389 52.4117 32.4392 50.1832 32.4392C47.9547 32.4392 46.1481 30.6389 46.1481 28.4182C46.1481 26.1974 47.9547 24.3972 50.1832 24.3972C52.4117 24.3972 54.2183 26.1974 54.2183 28.4182Z" fill="#DAD3FF" fill-opacity="0.55"/>
<path d="M19.627 26.2244L22.7653 23.2086L19.627 20.1929L18.7303 21.0545L20.972 23.2086L18.7303 25.3627L19.627 26.2244Z" fill="#9985FF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M43.1226 33.3719V44.7762H28.2664L39.0876 26.4078L43.1226 33.3719Z" fill="#9985FF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M43.1226 33.3719V44.7761H28.2664L39.0876 26.4078L43.1226 33.3719Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1004 B

9
public/images/pages/build-an-app.svg

@ -0,0 +1,9 @@
<svg width="256" height="145" viewBox="0 0 256 145" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect y="0.439056" width="256" height="144" fill="#9985FF"/>
<path opacity="0.64" d="M84.0003 33.9388H148.391V98.105H84.0003V33.9388Z" fill="white"/>
<path d="M139.805 59.6064L169.854 110.939H109.756L139.805 59.6064Z" fill="white"/>
<path d="M172 63.8838C172 68.6089 168.156 72.4393 163.414 72.4393C158.673 72.4393 154.829 68.6089 154.829 63.8838C154.829 59.1587 158.673 55.3283 163.414 55.3283C168.156 55.3283 172 59.1587 172 63.8838Z" fill="#BDB0FF"/>
<path d="M98.3995 59.216L105.077 52.7993L98.3995 46.3827L96.4916 48.216L101.261 52.7993L96.4916 57.3826L98.3995 59.216Z" fill="#9985FF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M148.391 74.4239V98.6889H116.782L139.806 59.6064L148.391 74.4239Z" fill="#9985FF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M148.391 74.4238V98.6888H116.782L139.806 59.6063L148.391 74.4238Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 963 B

7
public/images/pages/connect-sm.svg

@ -0,0 +1,7 @@
<svg width="65" height="65" viewBox="0 0 65 65" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.667969" y="0.439056" width="64" height="64" fill="#9985FF"/>
<path d="M46.668 32.4391C44.5668 32.4391 42.4862 32.0252 40.545 31.2211C38.6038 30.4171 36.84 29.2385 35.3543 27.7528C33.8685 26.267 32.69 24.5032 31.8859 22.562C31.0818 20.6208 30.668 18.5402 30.668 16.4391L46.668 16.4391L46.668 32.4391Z" fill="white" fill-opacity="0.64"/>
<path d="M18.668 32.4391C20.7691 32.4391 22.8497 32.0252 24.7909 31.2211C26.7321 30.4171 28.4959 29.2385 29.9817 27.7528C31.4674 26.267 32.646 24.5032 33.45 22.562C34.2541 20.6208 34.668 18.5402 34.668 16.4391L18.668 16.4391L18.668 32.4391Z" fill="white"/>
<path d="M18.668 32.4391C20.7691 32.4391 22.8497 32.8529 24.7909 33.657C26.7321 34.4611 28.4959 35.6396 29.9817 37.1253C31.4674 38.6111 32.646 40.3749 33.45 42.3161C34.2541 44.2573 34.668 46.3379 34.668 48.4391L18.668 48.4391L18.668 32.4391Z" fill="white" fill-opacity="0.64"/>
<path d="M46.668 32.4391C44.5668 32.4391 42.4862 32.8529 40.545 33.657C38.6038 34.4611 36.84 35.6396 35.3543 37.1253C33.8685 38.6111 32.69 40.3749 31.8859 42.3161C31.0818 44.2573 30.668 46.3379 30.668 48.4391L46.668 48.4391L46.668 32.4391Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

12
public/images/pages/connect.svg

@ -0,0 +1,12 @@
<svg width="257" height="145" viewBox="0 0 257 145" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.0919189" y="0.439056" width="256" height="144" fill="#9985FF"/>
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="257" height="145">
<rect x="0.0919189" y="0.439056" width="256" height="144" fill="#9985FF"/>
</mask>
<g mask="url(#mask0)">
<path d="M161.372 72.4391C156.445 72.4391 151.567 71.4687 147.015 69.5833C142.463 67.6979 138.328 64.9344 134.844 61.4507C131.36 57.9669 128.597 53.8311 126.711 49.2793C124.826 44.7276 123.855 39.8491 123.855 34.9223L161.372 34.9223V72.4391Z" fill="white" fill-opacity="0.64"/>
<path d="M95.718 72.4391C100.645 72.4391 105.523 71.4687 110.075 69.5833C114.627 67.6979 118.763 64.9344 122.246 61.4507C125.73 57.9669 128.494 53.8311 130.379 49.2793C132.264 44.7276 133.235 39.8491 133.235 34.9223L95.718 34.9223V72.4391Z" fill="white"/>
<path d="M95.7178 72.439C100.645 72.439 105.523 73.4094 110.075 75.2948C114.627 77.1802 118.762 79.9437 122.246 83.4275C125.73 86.9112 128.493 91.047 130.379 95.5988C132.264 100.151 133.235 105.029 133.235 109.956L95.7178 109.956V72.439Z" fill="white" fill-opacity="0.64"/>
<path d="M161.372 72.439C156.445 72.439 151.567 73.4094 147.015 75.2948C142.463 77.1802 138.328 79.9437 134.844 83.4275C131.36 86.9112 128.597 91.047 126.711 95.5988C124.826 100.151 123.855 105.029 123.855 109.956L161.372 109.956V72.439Z" fill="white"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

14
public/images/pages/counter-tutorial-sm.svg

@ -0,0 +1,14 @@
<svg width="65" height="65" viewBox="0 0 65 65" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="65" height="65">
<rect x="0.27417" y="0.0744896" width="64" height="64" fill="#F0F0F5"/>
</mask>
<g mask="url(#mask0)">
<rect x="0.27417" y="0.0744896" width="64" height="64" fill="#9985FF"/>
<g style="mix-blend-mode:multiply">
<rect x="0.27417" y="0.0744896" width="64" height="64" fill="#9985FF"/>
</g>
<rect opacity="0.64" x="12.2742" y="-9.92551" width="40" height="40" rx="4" fill="white"/>
<path d="M35.3335 12.6003V11.1894H28.6135V12.6003H35.3335Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.2742 34.9231C14.065 34.9231 12.2742 36.714 12.2742 38.9231V70.9231C12.2742 73.1323 14.065 74.9231 16.2742 74.9231H48.2742C50.4833 74.9231 52.2742 73.1323 52.2742 70.9231V38.9231C52.2742 36.714 50.4833 34.9231 48.2742 34.9231H16.2742ZM33.2098 55.2378H36.2061V56.7651H33.2098V59.7615H31.697V56.7651H28.7007V55.2378H31.697V52.2415H33.2098V55.2378Z" fill="white"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

11
public/images/pages/counter-tutorial.svg

@ -0,0 +1,11 @@
<svg width="257" height="145" viewBox="0 0 257 145" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.697876" y="0.0744896" width="256" height="144" fill="#9985FF"/>
<g style="mix-blend-mode:multiply">
<rect x="0.697876" y="0.0744896" width="256" height="144" fill="#9985FF"/>
</g>
<path d="M32.6979 40.0745C32.6979 35.6562 36.2796 32.0745 40.6979 32.0745H216.698C221.116 32.0745 224.698 35.6562 224.698 40.0745V144.074H32.6979V40.0745Z" fill="white"/>
<rect x="57.6979" y="57.0745" width="64" height="70" rx="3" fill="#F0F0F5" stroke="#F0F0F5" stroke-width="2"/>
<path d="M94.7459 96.2425V93.9145H83.6579V96.2425H94.7459Z" fill="#A1A7B3"/>
<rect x="135.698" y="57.0745" width="64" height="70" rx="3" fill="white" stroke="#F0F0F5" stroke-width="2"/>
<path d="M174.186 92.5945H169.242V87.6505H166.746V92.5945H161.802V95.1145H166.746V100.058H169.242V95.1145H174.186V92.5945Z" fill="#A1A7B3"/>
</svg>

After

Width:  |  Height:  |  Size: 907 B

12
public/images/pages/data-storage-sm.svg

@ -0,0 +1,12 @@
<svg width="65" height="65" viewBox="0 0 65 65" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="65" height="65">
<rect x="0.576431" y="0.71051" width="64" height="64" fill="#F0F0F5"/>
</mask>
<g mask="url(#mask0)">
<rect x="0.576431" y="0.71051" width="64" height="64" fill="#9985FF"/>
<rect x="0.576431" y="0.71051" width="64" height="64" fill="#9985FF"/>
<rect x="18.5764" y="20.7105" width="28" height="28" fill="white" fill-opacity="0.64"/>
<rect x="14.5764" y="18.7105" width="36" height="8" fill="white"/>
<rect x="26.5764" y="32.7105" width="12" height="2" fill="#9985FF"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 674 B

6
public/images/pages/data-storage.svg

@ -0,0 +1,6 @@
<svg width="256" height="145" viewBox="0 0 256 145" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect y="0.710495" width="256" height="144" fill="#9985FF"/>
<rect x="93.7778" y="40.9327" width="68.4444" height="68.4444" fill="white" fill-opacity="0.64"/>
<rect x="84" y="36.0438" width="88" height="19.5556" fill="white"/>
<rect x="113.333" y="70.2661" width="29.3333" height="4.88889" fill="#9985FF"/>
</svg>

After

Width:  |  Height:  |  Size: 414 B

13
public/images/pages/hello-world-sm.svg

@ -0,0 +1,13 @@
<svg width="65" height="65" viewBox="0 0 65 65" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="65" height="65">
<rect x="0.971924" y="0.0744896" width="64" height="64" fill="#F0F0F5"/>
</mask>
<g mask="url(#mask0)">
<rect x="0.971924" y="0.0744896" width="64" height="64" fill="#9985FF"/>
<g style="mix-blend-mode:multiply">
<rect x="0.971924" y="0.0744896" width="64" height="64" fill="#9985FF"/>
</g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M48.9719 16.0745H16.9719V38.0745H20.4819C20.8489 37.6162 21.2415 37.1775 21.6582 36.7608C23.144 35.275 24.9078 34.0965 26.849 33.2924C28.7902 32.4883 30.8708 32.0745 32.9719 32.0745C35.0731 32.0745 37.1536 32.4883 39.0949 33.2924C41.0361 34.0965 42.7999 35.275 44.2856 36.7608C44.7024 37.1775 45.095 37.6162 45.4619 38.0745H48.9719V16.0745Z" fill="white"/>
<path opacity="0.64" d="M48.9719 48.0745C48.9719 45.9733 48.5581 43.8928 47.754 41.9516C46.9499 40.0103 45.7714 38.2465 44.2856 36.7608C42.7999 35.275 41.0361 34.0965 39.0949 33.2924C37.1536 32.4883 35.0731 32.0745 32.9719 32.0745C30.8708 32.0745 28.7902 32.4883 26.849 33.2924C24.9078 34.0965 23.144 35.275 21.6582 36.7608C20.1725 38.2465 18.9939 40.0103 18.1899 41.9516C17.3858 43.8928 16.9719 45.9733 16.9719 48.0745L32.9719 48.0745H48.9719Z" fill="white"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

8
public/images/pages/hello-world.svg

@ -0,0 +1,8 @@
<svg width="257" height="145" viewBox="0 0 257 145" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.395874" y="0.0744896" width="256" height="144" fill="#9985FF"/>
<g style="mix-blend-mode:multiply">
<rect x="0.395874" y="0.0744896" width="256" height="144" fill="#9985FF"/>
</g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M167.758 34.7124H89.0338V88.8353H97.6689C98.5716 87.7078 99.5374 86.6287 100.563 85.6034C104.218 81.9483 108.557 79.0489 113.333 77.0708C118.108 75.0926 123.227 74.0745 128.396 74.0745C133.565 74.0745 138.684 75.0926 143.459 77.0708C148.235 79.0489 152.574 81.9483 156.229 85.6034C157.254 86.6287 158.22 87.7078 159.123 88.8353H167.758V34.7124Z" fill="white"/>
<path opacity="0.64" d="M167.758 113.437C167.758 108.268 166.74 103.149 164.762 98.3734C162.784 93.5978 159.884 89.2585 156.229 85.6034C152.574 81.9483 148.235 79.0489 143.459 77.0708C138.684 75.0926 133.565 74.0745 128.396 74.0745C123.227 74.0745 118.108 75.0926 113.333 77.0708C108.557 79.0489 104.218 81.9483 100.563 85.6034C96.9076 89.2585 94.0082 93.5978 92.0301 98.3734C90.0519 103.149 89.0338 108.268 89.0338 113.437L128.396 113.437H167.758Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

10
public/images/pages/mining-sm.svg

@ -0,0 +1,10 @@
<svg width="65" height="65" viewBox="0 0 65 65" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="65" height="65">
<rect x="0.970947" y="0.368134" width="64" height="64" fill="#F0F0F5"/>
</mask>
<g mask="url(#mask0)">
<rect x="0.970947" y="0.368134" width="64" height="64" fill="#9985FF"/>
<path opacity="0.64" d="M48.9709 32.3681C48.9709 34.4833 48.5571 36.5778 47.753 38.5321C46.9489 40.4863 45.7704 42.2619 44.2847 43.7576C42.7989 45.2533 41.0351 46.4397 39.0939 47.2492C37.1527 48.0586 35.0721 48.4753 32.9709 48.4753C30.8698 48.4753 28.7892 48.0586 26.848 47.2492C24.9068 46.4397 23.143 45.2533 21.6572 43.7576C20.1715 42.2619 18.9929 40.4863 18.1889 38.5321C17.3848 36.5778 16.9709 34.4833 16.9709 32.3681L32.9709 32.3681H48.9709Z" fill="white"/>
<ellipse rx="10.6667" ry="10.7381" transform="matrix(1 0 0 -1 32.7286 32.0683)" fill="white"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 939 B

5
public/images/pages/mining.svg

@ -0,0 +1,5 @@
<svg width="257" height="145" viewBox="0 0 257 145" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.394897" y="0.368164" width="256" height="144" fill="#9985FF"/>
<path opacity="0.64" d="M172.395 68.6628C172.395 74.4797 171.257 80.2396 169.046 85.6137C166.834 90.9878 163.593 95.8708 159.508 99.9839C155.422 104.097 150.571 107.36 145.233 109.586C139.895 111.812 134.173 112.958 128.395 112.958C122.617 112.958 116.895 111.812 111.557 109.586C106.218 107.36 101.368 104.097 97.2822 99.9839C93.1964 95.8708 89.9554 90.9878 87.7442 85.6137C85.533 80.2396 84.3949 74.4797 84.3949 68.6628L128.395 68.6628H172.395Z" fill="white"/>
<ellipse rx="29.3333" ry="29.5298" transform="matrix(1 0 0 -1 127.728 67.8384)" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 739 B

13
public/images/pages/radiks-sm.svg

@ -0,0 +1,13 @@
<svg width="65" height="65" viewBox="0 0 65 65" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="65" height="65">
<rect x="0.667969" y="0.0744896" width="64" height="64" fill="#F0F0F5"/>
</mask>
<g mask="url(#mask0)">
<rect x="0.667969" y="0.0744896" width="64" height="64" fill="#9985FF"/>
<path opacity="0.64" d="M20.668 12.0746L20.668 52.0746L41.5375 32.0745L20.668 12.0746Z" fill="white"/>
<path d="M44.668 12.0746L44.668 52.0746L23.7984 32.0745L44.668 12.0746Z" fill="white"/>
<g style="mix-blend-mode:multiply">
<path fill-rule="evenodd" clip-rule="evenodd" d="M32.668 40.5746L23.7985 32.0745L32.668 23.5745L41.5376 32.0745L32.668 40.5746Z" fill="#9985FF"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 761 B

8
public/images/pages/radiks.svg

@ -0,0 +1,8 @@
<svg width="257" height="145" viewBox="0 0 257 145" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.0938721" y="0.0744896" width="256" height="144" fill="#9985FF"/>
<path opacity="0.64" d="M101.694 28.0745L101.694 116.074L147.607 72.0745L101.694 28.0745Z" fill="white"/>
<path d="M154.494 28.0745L154.494 116.074L108.581 72.0745L154.494 28.0745Z" fill="white"/>
<g style="mix-blend-mode:multiply">
<path fill-rule="evenodd" clip-rule="evenodd" d="M128.094 90.7745L108.581 72.0745L128.094 53.3745L147.607 72.0745L128.094 90.7745Z" fill="#9985FF"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 570 B

24
public/images/pages/smart-contracts-sm.svg

@ -0,0 +1,24 @@
<svg width="65" height="65" viewBox="0 0 65 65" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="65" height="65">
<rect x="0.273865" y="0.439056" width="64" height="64" fill="#F0F0F5"/>
</mask>
<g mask="url(#mask0)">
<rect x="0.273865" y="0.439056" width="64" height="64" fill="#9985FF"/>
<rect x="-95.8773" y="-39.5609" width="256" height="144" fill="#9985FF"/>
<g style="mix-blend-mode:multiply">
<rect x="-95.8773" y="-39.5609" width="256" height="144" fill="#9985FF"/>
</g>
</g>
<g clip-path="url(#clip0)">
<path opacity="0.64" d="M32.2739 17.6567L52.2739 28.6057L32.2739 39.5548L12.2739 28.6057L32.2739 17.6567Z" fill="white"/>
<path d="M32.2739 29.3725L52.2739 40.3216L32.2739 51.2706L12.2739 40.3216L32.2739 29.3725Z" fill="white"/>
<g style="mix-blend-mode:multiply">
<path fill-rule="evenodd" clip-rule="evenodd" d="M41.5734 34.4637L32.2738 39.5548L22.9742 34.4637L32.2738 29.3726L41.5734 34.4637Z" fill="#9985FF"/>
</g>
</g>
<defs>
<clipPath id="clip0">
<rect width="40" height="36.6667" fill="white" transform="translate(12.2739 14.4391)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

14
public/images/pages/smart-contracts.svg

@ -0,0 +1,14 @@
<svg width="257" height="145" viewBox="0 0 257 145" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.697876" y="0.439056" width="256" height="144" fill="#9985FF"/>
<g style="mix-blend-mode:multiply">
<rect x="0.697876" y="0.439056" width="256" height="144" fill="#9985FF"/>
</g>
<path opacity="0.64" d="M128.698 32.1023L176.698 58.38L128.698 84.6577L80.6979 58.38L128.698 32.1023Z" fill="white"/>
<path d="M128.698 60.2204L176.698 86.4981L128.698 112.776L80.6979 86.4981L128.698 60.2204Z" fill="white"/>
<g style="mix-blend-mode:multiply">
<path fill-rule="evenodd" clip-rule="evenodd" d="M151.017 72.4391L128.698 84.6577L106.379 72.4391L128.698 60.2204L151.017 72.4391Z" fill="#9985FF"/>
</g>
<g style="mix-blend-mode:multiply">
<path fill-rule="evenodd" clip-rule="evenodd" d="M151.017 72.439L128.698 84.6576L106.379 72.439L128.698 60.2203L151.017 72.439Z" fill="#9985FF"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 898 B

18
public/images/pages/todo-app-sm.svg

@ -0,0 +1,18 @@
<svg width="65" height="65" viewBox="0 0 65 65" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="65" height="65">
<rect x="0.576431" y="0.0744896" width="64" height="64" fill="#F0F0F5"/>
</mask>
<g mask="url(#mask0)">
<rect x="0.576431" y="0.0744896" width="64" height="64" fill="#9985FF"/>
<path d="M12.5764 16.0745C12.5764 13.8654 14.3673 12.0745 16.5764 12.0745H104.576C106.786 12.0745 108.576 13.8654 108.576 16.0745V68.0745H12.5764V16.0745Z" fill="white"/>
<path d="M20.5764 26.0745C20.5764 24.9699 21.4719 24.0745 22.5764 24.0745H26.5764C27.681 24.0745 28.5764 24.9699 28.5764 26.0745V30.0745C28.5764 31.1791 27.681 32.0745 26.5764 32.0745H22.5764C21.4719 32.0745 20.5764 31.1791 20.5764 30.0745V26.0745Z" fill="#08018A"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M26.3382 26.806C26.4865 26.9506 26.4895 27.188 26.3449 27.3363L24.3949 29.3363C24.3244 29.4087 24.2275 29.4495 24.1264 29.4495C24.0253 29.4495 23.9285 29.4087 23.8579 29.3363L22.8079 28.2594C22.6634 28.1111 22.6664 27.8736 22.8146 27.7291C22.9629 27.5845 23.2004 27.5875 23.3449 27.7358L24.1264 28.5373L25.8079 26.8127C25.9525 26.6644 26.1899 26.6614 26.3382 26.806Z" fill="white"/>
<path opacity="0.32" d="M34.5764 26.5745C34.5764 26.0222 35.0241 25.5745 35.5764 25.5745H77.5764C78.1287 25.5745 78.5764 26.0222 78.5764 26.5745V30.0745C78.5764 30.6268 78.1287 31.0745 77.5764 31.0745H35.5764C35.0241 31.0745 34.5764 30.6268 34.5764 30.0745V26.5745Z" fill="#08018A"/>
<path opacity="0.2" d="M34.5764 40.5745C34.5764 40.0222 35.0241 39.5745 35.5764 39.5745H69.5764C70.1287 39.5745 70.5764 40.0222 70.5764 40.5745V44.0745C70.5764 44.6268 70.1287 45.0745 69.5764 45.0745H35.5764C35.0241 45.0745 34.5764 44.6268 34.5764 44.0745V40.5745Z" fill="#08018A"/>
<path opacity="0.12" d="M34.5764 54.5745C34.5764 54.0222 35.0241 53.5745 35.5764 53.5745H89.5764C90.1287 53.5745 90.5764 54.0222 90.5764 54.5745V58.0745C90.5764 58.6268 90.1287 59.0745 89.5764 59.0745H35.5764C35.0241 59.0745 34.5764 58.6268 34.5764 58.0745V54.5745Z" fill="#08018A"/>
<path d="M20.5764 40.0745C20.5764 38.9699 21.4719 38.0745 22.5764 38.0745H26.5764C27.681 38.0745 28.5764 38.9699 28.5764 40.0745V44.0745C28.5764 45.1791 27.681 46.0745 26.5764 46.0745H22.5764C21.4719 46.0745 20.5764 45.1791 20.5764 44.0745V40.0745Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M26.5764 39.0745H22.5764C22.0241 39.0745 21.5764 39.5222 21.5764 40.0745V44.0745C21.5764 44.6268 22.0241 45.0745 22.5764 45.0745H26.5764C27.1287 45.0745 27.5764 44.6268 27.5764 44.0745V40.0745C27.5764 39.5222 27.1287 39.0745 26.5764 39.0745ZM22.5764 38.0745C21.4719 38.0745 20.5764 38.9699 20.5764 40.0745V44.0745C20.5764 45.1791 21.4719 46.0745 22.5764 46.0745H26.5764C27.681 46.0745 28.5764 45.1791 28.5764 44.0745V40.0745C28.5764 38.9699 27.681 38.0745 26.5764 38.0745H22.5764Z" fill="#08018A" fill-opacity="0.2"/>
<path d="M20.5764 54.0745C20.5764 52.9699 21.4719 52.0745 22.5764 52.0745H26.5764C27.681 52.0745 28.5764 52.9699 28.5764 54.0745V58.0745C28.5764 59.1791 27.681 60.0745 26.5764 60.0745H22.5764C21.4719 60.0745 20.5764 59.1791 20.5764 58.0745V54.0745Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M26.5764 53.0745H22.5764C22.0241 53.0745 21.5764 53.5222 21.5764 54.0745V58.0745C21.5764 58.6268 22.0241 59.0745 22.5764 59.0745H26.5764C27.1287 59.0745 27.5764 58.6268 27.5764 58.0745V54.0745C27.5764 53.5222 27.1287 53.0745 26.5764 53.0745ZM22.5764 52.0745C21.4719 52.0745 20.5764 52.9699 20.5764 54.0745V58.0745C20.5764 59.1791 21.4719 60.0745 22.5764 60.0745H26.5764C27.681 60.0745 28.5764 59.1791 28.5764 58.0745V54.0745C28.5764 52.9699 27.681 52.0745 26.5764 52.0745H22.5764Z" fill="#08018A" fill-opacity="0.12"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

13
public/images/pages/todo-app.svg

@ -0,0 +1,13 @@
<svg width="256" height="145" viewBox="0 0 256 145" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect y="0.0744896" width="256" height="144" fill="#9985FF"/>
<path d="M32 40.0745C32 35.6562 35.5817 32.0745 40 32.0745H216C220.418 32.0745 224 35.6562 224 40.0745V144.074H32V40.0745Z" fill="white"/>
<path d="M48 60.0745C48 57.8654 49.7909 56.0745 52 56.0745H60C62.2091 56.0745 64 57.8654 64 60.0745V68.0745C64 70.2836 62.2091 72.0745 60 72.0745H52C49.7909 72.0745 48 70.2836 48 68.0745V60.0745Z" fill="#08018A"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M59.5236 61.5375C59.8202 61.8267 59.8262 62.3015 59.537 62.5981L55.637 66.5981C55.4958 66.7428 55.3022 66.8245 55.1 66.8245C54.8978 66.8245 54.7042 66.7428 54.563 66.5981L52.463 64.4442C52.1738 64.1476 52.1798 63.6728 52.4764 63.3836C52.773 63.0945 53.2478 63.1005 53.537 63.3971L55.1 65.0001L58.463 61.5509C58.7522 61.2543 59.227 61.2483 59.5236 61.5375Z" fill="white"/>
<path opacity="0.32" d="M76 61.0745C76 59.9699 76.8954 59.0745 78 59.0745H162C163.105 59.0745 164 59.9699 164 61.0745V68.0745C164 69.1791 163.105 70.0745 162 70.0745H78C76.8954 70.0745 76 69.1791 76 68.0745V61.0745Z" fill="#08018A"/>
<path opacity="0.2" d="M76 89.0745C76 87.9699 76.8954 87.0745 78 87.0745H146C147.105 87.0745 148 87.9699 148 89.0745V96.0745C148 97.1791 147.105 98.0745 146 98.0745H78C76.8954 98.0745 76 97.1791 76 96.0745V89.0745Z" fill="#08018A"/>
<path opacity="0.12" d="M76 117.074C76 115.97 76.8954 115.074 78 115.074H186C187.105 115.074 188 115.97 188 117.074V124.074C188 125.179 187.105 126.074 186 126.074H78C76.8954 126.074 76 125.179 76 124.074V117.074Z" fill="#08018A"/>
<path d="M48 88.0745C48 85.8654 49.7909 84.0745 52 84.0745H60C62.2091 84.0745 64 85.8654 64 88.0745V96.0745C64 98.2836 62.2091 100.074 60 100.074H52C49.7909 100.074 48 98.2836 48 96.0745V88.0745Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M60 86.0745H52C50.8954 86.0745 50 86.9699 50 88.0745V96.0745C50 97.1791 50.8954 98.0745 52 98.0745H60C61.1046 98.0745 62 97.1791 62 96.0745V88.0745C62 86.9699 61.1046 86.0745 60 86.0745ZM52 84.0745C49.7909 84.0745 48 85.8654 48 88.0745V96.0745C48 98.2836 49.7909 100.074 52 100.074H60C62.2091 100.074 64 98.2836 64 96.0745V88.0745C64 85.8654 62.2091 84.0745 60 84.0745H52Z" fill="#08018A" fill-opacity="0.2"/>
<path d="M48 116.074C48 113.865 49.7909 112.074 52 112.074H60C62.2091 112.074 64 113.865 64 116.074V124.074C64 126.284 62.2091 128.074 60 128.074H52C49.7909 128.074 48 126.284 48 124.074V116.074Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M60 114.074H52C50.8954 114.074 50 114.97 50 116.074V124.074C50 125.179 50.8954 126.074 52 126.074H60C61.1046 126.074 62 125.179 62 124.074V116.074C62 114.97 61.1046 114.074 60 114.074ZM52 112.074C49.7909 112.074 48 113.865 48 116.074V124.074C48 126.284 49.7909 128.074 52 128.074H60C62.2091 128.074 64 126.284 64 124.074V116.074C64 113.865 62.2091 112.074 60 112.074H52Z" fill="#08018A" fill-opacity="0.12"/>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

17
src/common/config.ts

@ -1,17 +0,0 @@
export const config = {
title: 'Blockstack',
description: 'Docs',
baseurl: '',
url: 'https://docs.blockstack.org',
repository: 'blockstack/docs.blockstack',
github_editme_path: 'blockstack/docs.blockstack/edit/master',
branch_url: 'master',
twitter: {
username: 'blockstack',
image: '/assets/img/twitter.png',
card: 'summary',
},
footer: {
copyright: 'Blockstack Public Benefit Corp.',
},
};

3
src/common/constants.ts

@ -1,6 +1,7 @@
export const SIDEBAR_WIDTH = 240;
export const TOC_WIDTH = 240;
export const TOC_WIDTH = 208;
export const CONTENT_MAX_WIDTH = 1104;
export const PAGE_WIDTH = 1216;
export const SHIKI_THEME = 'Material-Theme-Default';
export const THEME_STORAGE_KEY = 'theme';

9
src/common/data/clarity-ref.ts

@ -23,7 +23,8 @@ const generateMarkdown = () => {
let functions = '';
CLARITY_REFERENCE.functions.forEach(entry => {
functions += `### ${entry.name}
functions += `
### ${entry.name}
**Signature:** ${inlineCode(entry.signature)}\n
@ -37,12 +38,12 @@ ${entry.description}
#### Example {#${slugify(entry.name)}-example}
${wrapInClarityTicks(entry.example)}
${wrapInClarityTicks(entry.example)}\n
`;
});
CLARITY_REFERENCE.keywords.forEach(entry => {
keywords += `### ${entry.name}
keywords += `\n### ${entry.name}
**Output:** ${inlineCode(entry.output_type)}
@ -50,7 +51,7 @@ ${entry.description}
#### Example {#${slugify(entry.name)}-example}
${wrapInClarityTicks(entry.example)}
${wrapInClarityTicks(entry.example)}\n
`;
});

0
src/common/hydrate-mdx.ts → src/common/data/hydrate-mdx.ts

20
src/common/navigation.yaml

@ -5,14 +5,14 @@ sections:
- path: /smart-contracts
pages:
- path: /overview
- path: /testing-contracts
- path: /principals
- path: /running-testnet-node
- path: /running-a-testnet-node
sections:
- title: Tutorials
pages:
- path: /hello-world-tutorial
- path: /counter-tutorial
- path: /testing-contracts
- path: /signing-transactions
- path: /mining # is an overview page
@ -57,6 +57,13 @@ sections:
pages:
- path: /install-api
- path: /installing-memcached
- path: /stacks-wallet
pages:
- path: /overview
- path: /install
- path: /usage
- path: /security
- path: /troubleshooting
- path: /naming-services
pages:
- path: /overview
@ -92,11 +99,12 @@ sections:
- path: /contributing
- title: References
usePageTitles: true
pages:
- path: /clarity-reference
- path: /blockstack-cli-reference
- path: /stacks-blockchain-reference
- path: /stacks-rpc-api-reference
- path: /clarity-language
- path: /blockstack-cli
- path: /stacks-blockchain
- path: /stacks-rpc-api
- path: /faqs
- path: /glossary
- path: /deploy-tips

11
src/common/utils.ts → src/common/utils/index.ts

@ -9,7 +9,7 @@ const camelToKebab = (string: string) =>
.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2')
.toLowerCase();
export const slugify = (string: string) =>
export const slugify = (string: string): string =>
string
.toLowerCase()
.replace(/\s+/g, '-') // Replace spaces with -
@ -60,3 +60,12 @@ export const onlyText = (children: ReactNode): string => {
return text.concat(newText);
}, '') as string;
};
const getTitleFromHeading = (headings?: any[]) =>
headings?.length
? typeof headings[0] === 'string'
? headings[0]
: headings[0].content
: undefined;
export const getTitle = ({ title, headings }): string => title || getTitleFromHeading(headings);

12
src/components/clarity-ref.tsx

@ -1,19 +1,25 @@
import React from 'react';
import { MDXComponents } from '@components/mdx/mdx-components';
import { TableOfContents } from '@components/toc';
import { hydrate } from '@common/hydrate-mdx';
import { hydrate } from '@common/data/hydrate-mdx';
import { space } from '@blockstack/ui';
export const ClarityKeywordReference = ({ content, headings }) => {
return (
<>
<TableOfContents label="Contents" headings={headings} />
<TableOfContents mb={space('extra-loose')} label="Contents" headings={headings} />
{hydrate(content, MDXComponents)}
</>
);
};
export const ClarityFunctionReference = ({ content, headings }) => (
<>
<TableOfContents columns={[2, 2, 3]} label="Contents" headings={headings} />
<TableOfContents
mb={space('extra-loose')}
columns={[2, 2, 3]}
label="Contents"
headings={headings}
/>
{hydrate(content, MDXComponents)}
</>
);

2
src/components/cli-reference.tsx

@ -3,7 +3,7 @@ import { cliReferenceData } from '@common/../_data/cliRef';
import { MDXComponents } from '@components/mdx/mdx-components';
import { Grid, Box, color } from '@blockstack/ui';
import { border } from '@common/utils';
import { hydrate } from '@common/hydrate-mdx';
import { hydrate } from '@common/data/hydrate-mdx';
const styles = {
maxWidth: '100%',

1
src/components/content-wrapper.tsx

@ -4,7 +4,6 @@ import { Flex, FlexProps, space } from '@blockstack/ui';
const ContentWrapper: React.FC<FlexProps> = props => (
<Flex
flexShrink={0}
px={space(['none', 'none', 'extra-loose', 'extra-loose'])}
pt={space(['base', 'base', 'extra-loose'])}
mt={space('extra-loose')}
pb={[4, 4, 6]}

109
src/components/custom-blocks/page-reference.tsx

@ -5,14 +5,35 @@ import { useTouchable } from '@common/hooks/use-touchable';
import { Caption, Text } from '@components/typography';
import Link from 'next/link';
import routes from '@common/routes';
import { Img } from '@components/mdx/image';
const Image = (props: BoxProps) => (
const Image = ({
src,
isHovered,
size,
...rest
}: BoxProps & { src?: string; isHovered?: boolean }) => (
<Box
transition="all 0.75s cubic-bezier(0.23, 1, 0.32, 1)"
flexShrink={0}
bg="#9985FF"
{...props}
/>
style={{
willChange: 'transform',
}}
width="100%"
transition="all 0.2s cubic-bezier(0.23, 1, 0.32, 1)"
size={size}
{...rest}
>
<Img
flexShrink={0}
borderRadius="12px"
src={src}
width="100%"
minWidth={size}
size={size}
mx="0 !important"
my="0 !important"
/>
</Box>
);
const Title = ({ children, ...props }: BoxProps) => (
@ -39,6 +60,7 @@ const InlineCard = ({ page }) => {
return (
<Flex
border={border()}
flexDirection={['column', 'column', 'row']}
borderColor={hover ? '#9985FF' : color('border')}
p={space('base-loose')}
borderRadius="12px"
@ -48,14 +70,30 @@ const InlineCard = ({ page }) => {
position="relative"
{...bind}
>
<Image borderRadius={hover ? '100%' : '12px'} mr={space('base')} size="64px" />
<Flex flexDirection="column">
<Box flexShrink={0} size="64px" overflow="hidden" borderRadius={'12px'}>
<Image size="64px" src={page.images.sm} />
</Box>
<Flex
flexDirection="column"
ml={space(['none', 'none', 'base'])}
mt={space(['base', 'base', 'none'])}
textAlign={['center', 'center', 'left']}
>
<Flex align="baseline">
<Title color={hover ? color('accent') : color('text-title')} mb={space('extra-tight')}>
<Title
width={['100%', '100%', 'unset']}
color={hover ? color('accent') : color('text-title')}
mb={space('extra-tight')}
>
{page.title || page.headings[0]}
</Title>
{page.tags?.length
? page.tags.map(tag => (
{page.tags?.length ? (
<Flex
position={['absolute', 'absolute', 'static']}
top={space('base-loose')}
right={space('base-loose')}
>
{page.tags.map(tag => (
<Flex
ml={space('tight')}
borderRadius="18px"
@ -71,8 +109,9 @@ const InlineCard = ({ page }) => {
>
{tag}
</Flex>
))
: null}
))}
</Flex>
) : null}
</Flex>
<Description>{page.description}</Description>
</Flex>
@ -81,6 +120,31 @@ const InlineCard = ({ page }) => {
);
};
const GridCard: React.FC<BoxProps & { page?: any }> = ({ page, ...rest }) => {
const { hover, active, bind } = useTouchable({
behavior: 'link',
});
return (
<Box position="relative" {...rest} {...bind}>
<Box borderRadius="12px" overflow="hidden" mb={space('loose')}>
<Image
width="100%"
size="100%"
transform={hover || active ? 'scale(1.1)' : 'scale(1.02)'}
src={page?.images?.large}
/>
</Box>
<Flex alignItems="flex-start" justifyContent="flex-start" flexDirection="column">
<Title color={hover ? color('accent') : color('text-title')} mb={space('tight')}>
{page.title || page.headings[0]}
</Title>
<Description>{page.description}</Description>
</Flex>
<FloatingLink href={`${page.path}`} />
</Box>
);
};
export const PageReference = ({ children }) => {
const content = onlyText(children).trim();
const [variant, _paths] = content.includes('\n') ? content.split('\n') : ['default', content];
@ -90,23 +154,18 @@ export const PageReference = ({ children }) => {
const pages = paths.map(path => routes?.find(route => route.path === path)).filter(page => page);
return (
<Grid
width="100%"
mt={space('extra-loose')}
gridColumnGap={space('loose')}
gridTemplateColumns={`repeat(${pages.length === 1 ? 1 : 3}, 1fr)`}
gridRowGap={space('loose')}
gridTemplateColumns={[
`repeat(1, 1fr)`,
`repeat(1, 1fr)`,
`repeat(${pages.length === 1 ? 1 : 3}, 1fr)`,
]}
>
{pages.map(page =>
variant === 'inline' ? (
<InlineCard page={page} />
) : (
<Box position="relative">
<Image height="144px" borderRadius="12px" mb={space('loose')} />
<Flex alignItems="flex-start" justifyContent="flex-start" flexDirection="column">
<Title mb={space('tight')}>{page.title || page.headings[0]}</Title>
<Description>{page.description}</Description>
</Flex>
<FloatingLink href={`${page.path}`} />
</Box>
)
variant === 'inline' ? <InlineCard page={page} /> : <GridCard page={page} />
)}
</Grid>
);

2
src/components/faq.tsx

@ -1,7 +1,7 @@
import React from 'react';
import { MDXComponents } from '@components/mdx';
import { Box, Flex, ChevronIcon, space, color } from '@blockstack/ui';
import { hydrate } from '@common/hydrate-mdx';
import { hydrate } from '@common/data/hydrate-mdx';
import { Accordion, AccordionItem, AccordionButton, AccordionPanel } from '@reach/accordion';
import { border } from '@common/utils';
import { slugify } from '@common/utils';

2
src/components/glossary.tsx

@ -1,6 +1,6 @@
import React from 'react';
import { Box, space } from '@blockstack/ui';
import { hydrate } from '@common/hydrate-mdx';
import { hydrate } from '@common/data/hydrate-mdx';
import { MDXComponents } from '@components/mdx/mdx-components';
import { slugify } from '@common/utils';
import { css } from '@styled-system/css';

109
src/components/header.tsx

@ -1,25 +1,14 @@
import React from 'react';
import {
Flex,
Box,
BlockstackIcon,
Stack,
color,
space,
ChevronIcon,
BoxProps,
} from '@blockstack/ui';
import { Link, Text, LinkProps } from '@components/typography';
import { Flex, Box, BlockstackIcon, Stack, color, space, BoxProps } from '@blockstack/ui';
import { Link, Text } from '@components/typography';
import MenuIcon from 'mdi-react/MenuIcon';
import CloseIcon from 'mdi-react/CloseIcon';
import { useMobileMenuState } from '@common/hooks/use-mobile-menu';
import GithubIcon from 'mdi-react/GithubIcon';
import { IconButton } from '@components/icon-button';
import routes from '@common/routes';
import { css } from '@styled-system/css';
import NextLink from 'next/link';
import { useRouter } from 'next/router';
import { ColorModeButton } from '@components/color-mode-button';
import { PAGE_WIDTH } from '@common/constants';
const MenuButton = ({ ...rest }: any) => {
const { isOpen, handleOpen, handleClose } = useMobileMenuState();
@ -37,73 +26,6 @@ const MenuButton = ({ ...rest }: any) => {
);
};
const BreadCrumbs: React.FC<any> = props => {
const router = useRouter();
const [route, setRoute] = React.useState(undefined);
const [section, setSection] = React.useState(undefined);
React.useEffect(() => {
routes.forEach(_section => {
_section?.routes?.length &&
_section.routes.forEach(_route => {
if (router.route === `/${_route.path}`) {
setSection(_section);
setRoute(_route);
}
});
});
}, [router.route]);
return route && section ? (
<Flex align="center">
<Box>
<Text fontSize={['12px', '12px', '14px']} fontWeight="500">
Docs
</Text>
</Box>
<Box pt="3px" color={color('text-caption')}>
<ChevronIcon size="20px" />
</Box>
<Box>
<Text fontSize={['12px', '12px', '14px']} fontWeight="500">
{section?.title}
</Text>
</Box>
<Box pt="3px" color={color('text-caption')}>
<ChevronIcon size="20px" />
</Box>
<Box>
<Text fontSize={['12px', '12px', '14px']} fontWeight="500">
{route?.title || (route?.headings.length && route.headings[0])}
</Text>
</Box>
</Flex>
) : (
<Box />
);
};
const GithubButton = (props: LinkProps) => (
<IconButton
as="a"
href="https://github.com/blockstack/ux/tree/master/packages/ui#blockstack-ui"
target="_blank"
rel="nofollow noopener noreferrer"
title="Find us on GitHub"
position="relative"
overflow="hidden"
display="flex"
style={{
alignItems: 'center',
}}
{...props}
>
<Text position="absolute" opacity={0} as="label">
Find us on GitHub
</Text>
<GithubIcon size="20px" />
</IconButton>
);
const HeaderWrapper: React.FC<any> = React.forwardRef((props, ref) => (
<Box top={2} ref={ref} width="100%" {...props} />
));
@ -111,9 +33,23 @@ const HeaderWrapper: React.FC<any> = React.forwardRef((props, ref) => (
const nav = [
{
label: 'Developers',
chilren: [
{
label: 'Documentation',
},
{
label: 'GitHub',
},
{
label: 'Papers',
},
{
label: 'Discord',
},
],
},
{ label: 'Run a node' },
{ label: 'Build on Blockstack' },
{ label: 'Testnet' },
{ label: 'Discover apps' },
];
export const HEADER_HEIGHT = 132;
@ -158,7 +94,7 @@ const Header = ({ hideSubBar, ...rest }: any) => {
backdropFilter: 'blur(5px)',
}}
height="72px"
maxWidth="1280px"
maxWidth={`${PAGE_WIDTH}px`}
mx="auto"
px={space(['extra-loose', 'extra-loose', 'base', 'base'])}
{...rest}
@ -177,7 +113,7 @@ const Header = ({ hideSubBar, ...rest }: any) => {
</NextLink>
<Flex align="center">
<Box display={['none', 'none', 'block']}>
<Stack mr={space('base')} isInline spacing={space('base')}>
<Stack mr={space('base')} isInline spacing={space('extra-loose')}>
{nav.map(item => (
<Box>
<HeaderTextItem>{item.label}</HeaderTextItem>
@ -186,7 +122,6 @@ const Header = ({ hideSubBar, ...rest }: any) => {
</Stack>
</Box>
<ColorModeButton />
<GithubButton />
<MenuButton />
</Flex>
</Flex>

6
src/components/layouts/base-layout.tsx

@ -1,11 +1,11 @@
import React from 'react';
import { Flex, Box, FlexProps, color, space, CloseIcon, Fade, Transition } from '@blockstack/ui';
import { SideNav } from '../side-nav';
import { Header, HEADER_HEIGHT } from '../header';
import { Header } from '../header';
import { Main } from '../main';
import { Footer } from '../footer';
import NotFoundPage from '@pages/404';
import { SIDEBAR_WIDTH } from '@common/constants';
import { PAGE_WIDTH, SIDEBAR_WIDTH } from '@common/constants';
import { useWatchActiveHeadingChange } from '@common/hooks/use-active-heading';
import { useLockBodyScroll } from '@common/hooks/use-lock-body-scroll';
import { useMobileMenuState } from '@common/hooks/use-mobile-menu';
@ -144,7 +144,7 @@ const BaseLayout: React.FC<{ isHome?: boolean }> = ({ children }) => {
<Flex minHeight="100vh" flexDirection="column">
<MobileMenu />
<Header />
<Flex width="100%" flexGrow={1} maxWidth="1280px" mx="auto">
<Flex width="100%" flexGrow={1} maxWidth={`${PAGE_WIDTH}px`} mx="auto">
<SideNav display={['none', 'none', 'block']} />
<Flex
flexGrow={1}

21
src/components/layouts/markdown-wrapper.tsx

@ -1,15 +1,28 @@
import React from 'react';
import { Box, Stack, space } from '@blockstack/ui';
import { Box, Flex, Stack, space } from '@blockstack/ui';
import { MDContents } from '@components/mdx/md-contents';
import { H1 } from '@components/mdx';
import Head from 'next/head';
import { Caption, Text } from '@components/typography';
const getTitle = ({ title, headings }) => title || (headings?.length && headings[0].content);
import { useRouter } from 'next/router';
import dynamic from 'next/dynamic';
import { getTitle } from '@common/utils';
const Search = dynamic(() => import('@components/search'));
const PageTop = props => {
const router = useRouter();
const isHome = router.pathname === '/';
return (
<Box px={space('extra-loose')} mb="64px">
<H1 mb="0 !important">{getTitle(props)}</H1>
<Flex>
<H1 mb="0 !important">{getTitle(props)}</H1>
{isHome ? (
<Box width="100%" maxWidth="208px">
<Search />
</Box>
) : null}
</Flex>
{props.description ? (
<Box mt="24px !important">
<Text>{props.description}</Text>{' '}
@ -18,7 +31,7 @@ const PageTop = props => {
<Stack isInline spacing={space('base')} mt={space('base')}>
{props.experience ? <Caption textTransform="capitalize">{props.experience}</Caption> : null}
{props.duration ? <Caption>{props.duration}</Caption> : null}
{!isHome && props.duration ? <Caption>{props.duration}</Caption> : null}
</Stack>
</Box>
);

72
src/components/mdx/components/code.tsx

@ -1,10 +1,11 @@
import React from 'react';
import { Box, BoxProps, color, themeColor } from '@blockstack/ui';
import { Box, BoxProps, color, space, themeColor } from '@blockstack/ui';
import { border } from '@common/utils';
import { css } from '@styled-system/css';
import { Text } from '@components/typography';
import { useColorMode } from '@pages/_app';
const LINE_MINIMUM = 4;
const getHighlightLineNumbers = (str: string): number[] | undefined => {
if (!str) return;
@ -20,26 +21,27 @@ const getHighlightLineNumbers = (str: string): number[] | undefined => {
return numbers;
};
export const Code: React.FC<BoxProps & { highlight?: string }> = React.forwardRef(
({ children, highlight, ...rest }, ref) => {
const [mode] = useColorMode();
const numbers = getHighlightLineNumbers(highlight);
const generateCssStylesForHighlightedLines = (numbers: number[] = []) => {
const record = {};
const style = {
bg: 'var(--colors-highlight-line-bg)',
'&::before': {
borderRightColor: themeColor('ink.600'),
},
};
numbers.forEach(number => {
record[`&:nth-of-type(${number})`] = style;
});
return record;
};
const generateCssStylesForHighlightedLines = (numbers: number[] = []) => {
const record = {};
const style = {
bg: 'var(--colors-highlight-line-bg)',
'&::before': {
borderRightColor: themeColor('ink.600'),
},
};
numbers.forEach(number => {
record[`&:nth-of-type(${number})`] = style;
});
return record;
};
export const Code: React.FC<
BoxProps & { highlight?: string; lang?: string; lines: number }
> = React.memo(
React.forwardRef(({ children, highlight, lang, lines, ...rest }, ref) => {
const numbers = getHighlightLineNumbers(highlight);
return (
<Box ref={ref as any} overflowX="auto">
<Box className={lines <= 3 ? 'no-line-numbers' : ''} ref={ref as any} overflowX="auto">
<Box
as="code"
css={css({
@ -51,6 +53,34 @@ export const Code: React.FC<BoxProps & { highlight?: string }> = React.forwardRe
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(['base-loose', 'base-loose', 'base-loose', 'base-loose'])
: 'unset',
})}
{...rest}
>
@ -60,7 +90,7 @@ export const Code: React.FC<BoxProps & { highlight?: string }> = React.forwardRe
</Box>
</Box>
);
}
})
);
const preProps = {

18
src/components/mdx/components/heading.tsx

@ -1,4 +1,4 @@
import { Box, FlexProps, BoxProps, color, useClipboard, space } from '@blockstack/ui';
import { Box, Flex, FlexProps, BoxProps, color, useClipboard, space } from '@blockstack/ui';
import React from 'react';
import LinkIcon from 'mdi-react/LinkVariantIcon';
@ -10,7 +10,6 @@ import { Title } from '@components/typography';
import { css } from '@styled-system/css';
import { getHeadingStyles, baseTypeStyles } from '@components/mdx/typography';
import { useRouter } from 'next/router';
import { HEADER_HEIGHT } from '@components/header';
import { Link } from '@components/mdx/components/link';
const LinkButton = React.memo(({ link, onClick, ...rest }: BoxProps & { link: string }) => {
@ -63,9 +62,16 @@ const AnchorOffset = ({ id }: BoxProps) =>
) : null;
const Hashtag = () => (
<Box position="absolute" as="span" left="10px" color={color('text-caption')}>
<Flex
position="absolute"
as="span"
align="center"
size="1rem"
left="10px"
color={color('text-caption')}
>
<HashtagIcon size="1rem" />
</Box>
</Flex>
);
export const Heading = ({ as, children, id, ...rest }: FlexProps) => {
@ -107,9 +113,7 @@ export const Heading = ({ as, children, id, ...rest }: FlexProps) => {
})}
onClick={id && handleLinkClick}
>
<Box as="span" display="inline-block">
{children}
</Box>
{children}
<AnchorOffset id={id} />
{id && isActive && <Hashtag />}
{id && <LinkButton opacity={hover || active ? 1 : 0} link={link} />}

18
src/components/mdx/md-contents.tsx

@ -7,9 +7,9 @@ import { TableOfContents } from '@components/toc';
import { css } from '@styled-system/css';
import { TOC_WIDTH } from '@common/constants';
import { styleOverwrites } from '@components/mdx/styles';
import dynamic from 'next/dynamic';
import { border } from '@common/utils';
import { useRouter } from 'next/router';
import dynamic from 'next/dynamic';
const Search = dynamic(() => import('@components/search'));
@ -20,7 +20,11 @@ export const MDContents: React.FC<any> = React.memo(
return (
<>
<ContentWrapper
width={['100%', '100%', '100%', `calc(100% - ${isHome ? 0 : TOC_WIDTH}px)`]}
pl={space(['none', 'none', 'extra-loose', 'extra-loose'])}
pr={
isHome ? ['0px', '0px', 'base-loose'] : space(['0', '0', 'extra-loose', 'extra-loose'])
}
width={['100%', '100%', '100%', `calc(100% - ${isHome ? 0 : TOC_WIDTH + 20}px)`]}
mx="unset"
pt="unset"
css={css(styleOverwrites as any)}
@ -29,14 +33,18 @@ export const MDContents: React.FC<any> = React.memo(
{children}
</ContentWrapper>
{!isHome ? (
<Box>
<Box position="sticky" top={0} pt="64px" pl={space('extra-loose')}>
<Box
maxWidth={['100%', `${TOC_WIDTH + 20}px`, `${TOC_WIDTH + 20}px`]}
width="100%"
display={['none', 'none', 'none', 'block']}
pr="base-loose"
>
<Box position="sticky" top={0} pt="64px">
<Search mb={space('base')} />
{headings?.length > 1 ? (
<TableOfContents
pl={space('base')}
borderLeft={border()}
display={['none', 'none', 'none', 'block']}
headings={headings}
limit={2}
/>

55
src/components/mdx/styles.tsx

@ -3,6 +3,7 @@ import { color, space, themeColor } from '@blockstack/ui';
import { createGlobalStyle } from 'styled-components';
import { getHeadingStyles } from '@components/mdx/typography';
import { border } from '@common/utils';
import { getCapsizeStyles } from '@components/mdx/typography';
export const MdxOverrides = createGlobalStyle`
html, body {
@ -11,6 +12,11 @@ html, body {
@counter-style list {
pad: "0";
}
img{
//image-rendering: auto;
//image-rendering: crisp-edges;
//image-rendering: pixelated;
}
.headroom {
top: 0;
left: 0;
@ -98,9 +104,6 @@ html, body {
color: ${color('accent')};
}
pre, code{
font-family: "Soehne Mono", "Fira Code", monospace;
}
pre{
display: inline-block;
}
@ -159,26 +162,6 @@ export const styleOverwrites = {
'& + h4, & + h5, & + h6, & + blockquote, & + ul, & + ol': {
mt: 0,
},
counterReset: 'line',
'& .token-line': {
'.comment': {
color: 'rgba(255,255,255,0.5) !important',
},
display: 'flex',
fontSize: '14px',
'&::before': {
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']),
},
boxShadow: 'none',
},
},
@ -187,21 +170,7 @@ export const styleOverwrites = {
},
'p, li, a': {
display: 'inline-block',
fontSize: '16px',
lineHeight: '28px',
padding: '0.05px 0',
'::before': {
content: "''",
marginTop: '-0.5144886363636364em',
display: 'block',
height: 0,
},
'::after': {
content: "''",
marginBottom: '-0.5144886363636364em',
display: 'block',
height: 0,
},
...getCapsizeStyles(16, 28),
},
li: {
display: 'list-item',
@ -244,6 +213,16 @@ export const styleOverwrites = {
borderRadius: '12px',
},
},
'*:not(pre) code': {
fontFamily: '"Soehne Mono", "Fira Code", monospace',
// ...getCapsizeStyles(14, 24),
// padding: '3px 2px',
},
'pre code': {
fontFamily: '"Soehne Mono", "Fira Code", monospace',
fontSize: '14px',
lineHeight: '24px',
},
h2: {
mt: '64px',
'&, & > *': {

96
src/components/mdx/typography.ts

@ -1,94 +1,54 @@
import capsize from 'capsize';
const fontMetrics = {
capHeight: 718,
ascent: 1040,
descent: -234,
lineGap: 0,
unitsPerEm: 1000,
};
export const baseTypeStyles = {
letterSpacing: '-0.01em',
dispay: 'flex',
display: 'flex',
fontFeatureSettings: `'ss01' on`,
fontFamily: `'Soehne', Inter, sans-serif`,
};
export const getCapsizeStyles = (fontSize, leading) =>
capsize({
fontMetrics,
fontSize,
leading,
});
const h1 = {
fontWeight: 600,
fontSize: ['38px', '38px', '44px'],
lineHeight: '52px',
padding: '0.05px 0',
':before': {
content: "''",
marginTop: ['-0.32188995215311006em', '-0.32188995215311006em', '-0.2284090909090909em'],
display: 'block',
height: 0,
},
':after': {
content: "''",
marginBottom: ['-0.32188995215311006em', '-0.32188995215311006em', '-0.22840909090909092em'],
display: 'block',
height: 0,
},
...getCapsizeStyles(36, 48),
};
const h2 = {
fontWeight: 500,
fontSize: '27.5px',
lineHeight: '34px',
padding: '0.05px 0',
':before': {
content: "''",
marginTop: '-0.25636363636363635em',
display: 'block',
height: 0,
},
':after': {
content: "''",
marginBottom: '-0.2563636363636364em',
display: 'block',
height: 0,
},
fontWeight: 600,
...getCapsizeStyles(24, 36),
};
const h3 = {
fontWeight: 500,
fontSize: '22px',
lineHeight: '32px',
padding: '0.05px 0',
':before': {
content: "''",
marginTop: '-0.3659090909090909em',
display: 'block',
height: 0,
},
':after': {
content: "''",
marginBottom: '-0.3659090909090909em',
display: 'block',
height: 0,
},
fontWeight: 400,
...getCapsizeStyles(20, 32),
};
const h4 = {
fontWeight: 400,
fontSize: '19.25px',
lineHeight: '28px',
padding: '0.05px 0',
':before': {
content: "''",
marginTop: '-0.36623376623376624em',
display: 'block',
height: 0,
},
':after': {
content: "''",
marginBottom: '-0.36623376623376624em',
display: 'block',
height: 0,
},
fontWeight: 500,
...getCapsizeStyles(18, 32),
};
const h5 = {
fontWeight: 400,
fontSize: '16px',
lineHeight: '28px',
...getCapsizeStyles(16, 26),
};
const h6 = {
fontWeight: 400,
fontSize: '14px',
lineHeight: '28px',
...getCapsizeStyles(14, 20),
};
const headings = {

131
src/components/pagination.tsx

@ -2,69 +2,52 @@ import React from 'react';
import { Box, BoxProps, Flex, Grid, color, space, transition } from '@blockstack/ui';
import routes from '@common/routes';
import { useRouter } from 'next/router';
import { MDXComponents } from '@components/mdx';
import { border } from '@common/utils';
import { border, getTitle } from '@common/utils';
import NextLink from 'next/link';
import { Link } from '@components/typography';
import { Caption, Text, Link } from '@components/typography';
import { useTouchable } from '@common/hooks/use-touchable';
import { getHeadingStyles } from '@components/mdx/typography';
import { css } from '@styled-system/css';
const FloatingLink: React.FC<any> = ({ href }) => (
<NextLink href={`${href}`} passHref>
<Link position="absolute" size="100%" zIndex={2} as="a" />
</NextLink>
);
const getCategory = (pathname: string) => {
const arr = pathname.split('/');
if (arr.length > 1) {
return arr[1];
}
return undefined;
};
const usePaginateRoutes = () => {
const router = useRouter();
const getRoute = route => router.pathname === `/${route.path}`;
const getSection = _section => _section.routes.find(getRoute);
const findSectionByTitle = item => item.title === section.title;
const category = getCategory(router.pathname);
const getSection = route => getCategory(route.path) === category;
const findCurrentRouteInArray = item => item.path === router.pathname;
return {
next: undefined,
prev: undefined,
};
const sectionRoutes = routes.filter(getSection);
const section = routes.find(getSection);
if (!section)
if (!sectionRoutes)
return {
next: undefined,
prev: undefined,
};
const { routes: sectionRoutes } = section;
const sectionIndex: number = routes.findIndex(findSectionByTitle);
const nextSection = routes[sectionIndex + 1];
const prevSection = routes[sectionIndex - 1];
const isFirstSection = sectionIndex === 0;
const isLastSection = sectionIndex === routes.length - 1;
const routeIndex: number = sectionRoutes.findIndex(getRoute);
const isFirstRouteInSection = routeIndex === 0;
const isLastRouteInSection = routeIndex === sectionRoutes.length - 1;
const routeIndex: number = sectionRoutes.findIndex(findCurrentRouteInArray);
let next;
let prev;
if (!isLastRouteInSection) {
next = sectionRoutes[routeIndex + 1];
}
if (isLastRouteInSection && !isLastSection) {
next = nextSection?.routes?.length && nextSection?.routes[0];
}
if (!isFirstRouteInSection) {
prev = sectionRoutes[routeIndex - 1];
}
if (isFirstRouteInSection && !isFirstSection) {
prev = prevSection?.routes?.length && prevSection?.routes[0];
}
const next = sectionRoutes[routeIndex + 1];
const prev = sectionRoutes[routeIndex - 1];
return { next, prev };
};
const Description: React.FC<BoxProps> = props => (
<Box maxWidth="42ch" mt={space('extra-tight')}>
<MDXComponents.p {...props} />
</Box>
<Caption display="block" maxWidth="42ch" mt={space('extra-tight')} {...props} />
);
const Card: React.FC<any> = ({ children, ...rest }) => {
@ -93,6 +76,34 @@ const Card: React.FC<any> = ({ children, ...rest }) => {
);
};
const Pretitle: React.FC<BoxProps> = props => (
<Text
display="block"
color={color('text-caption')}
transition={transition}
mb={space('base')}
css={css({
...getHeadingStyles('h6'),
})}
{...props}
/>
);
const Title: React.FC<BoxProps & { isHovered?: boolean }> = ({ isHovered, ...props }) => (
<Text
display="block"
maxWidth="38ch"
width="100%"
transition={transition}
color={isHovered ? color('accent') : color('text-title')}
mb={space('tight')}
css={css({
...getHeadingStyles('h3'),
})}
{...props}
/>
);
const PrevCard: React.FC<any> = React.memo(props => {
const { prev } = usePaginateRoutes();
@ -100,17 +111,9 @@ const PrevCard: React.FC<any> = React.memo(props => {
<Card>
{({ hover, active }) => (
<>
<NextLink href={`/${prev.path}`} passHref>
<Link position="absolute" size="100%" zIndex={2} as="a" />
</NextLink>
<Box>
<MDXComponents.h5 mt={0} color={color('text-caption')}>
Previous
</MDXComponents.h5>
</Box>
<Box maxWidth="38ch">
<MDXComponents.h3 my={0}>{prev.title || prev.headings[0]}</MDXComponents.h3>
</Box>
<FloatingLink href={prev.path} />
<Pretitle>Previous</Pretitle>
<Title isHovered={hover || active}>{getTitle(prev)}</Title>
{prev.description && <Description>{prev.description}</Description>}
</>
)}
@ -126,21 +129,9 @@ const NextCard: React.FC<any> = React.memo(props => {
<Card textAlign="right" align="flex-end">
{({ hover, active }) => (
<>
<NextLink href={`/${next.path}`} passHref>
<Link position="absolute" size="100%" zIndex={2} as="a" />
</NextLink>
<MDXComponents.h5 mt={0} color={color('text-caption')} width="100%" display="block">
Next
</MDXComponents.h5>
<Box maxWidth="38ch">
<MDXComponents.h3
transition={transition}
color={hover ? color('accent') : color('text-title')}
my={0}
>
{next.title || next.headings[0]}
</MDXComponents.h3>
</Box>
<FloatingLink href={next.path} />
<Pretitle>Next</Pretitle>
<Title isHovered={hover || active}>{getTitle(next)}</Title>
{next.description && <Description>{next.description}</Description>}
</>
)}

2
src/components/search.tsx

@ -90,7 +90,7 @@ export const SearchBox: React.FC<BoxProps> = React.memo(props => {
</Portal>
<Box
bg={color('bg-alt')}
minWidth="200px"
width="100%"
borderRadius="12px"
display={['none', 'none', 'block', 'block']}
border="1px solid"

123
src/components/side-nav.tsx

@ -6,7 +6,8 @@ import { SIDEBAR_WIDTH } from '@common/constants';
// @ts-ignore
import nav from '@common/navigation.yaml';
import ArrowLeftIcon from 'mdi-react/ArrowLeftIcon';
import { slugify } from '@common/utils';
import { getTitle, slugify } from '@common/utils';
import { useRouter } from 'next/router';
const Wrapper: React.FC<BoxProps & { containerProps?: BoxProps }> = ({
width = `${SIDEBAR_WIDTH}px`,
@ -21,7 +22,6 @@ const Wrapper: React.FC<BoxProps & { containerProps?: BoxProps }> = ({
width={width}
maxHeight={`calc(100vh - 60px)`}
overflow="auto"
pb="62px"
px={space('base')}
top={0}
pt="64px"
@ -41,15 +41,15 @@ const capitalize = s => {
const convertToTitle = (path: string) =>
!path ? null : path === '/' ? 'Home' : capitalize(path.replace('/', '').replace(/-/g, ' '));
const PageItem = ({ isActive, ...props }: any) => (
const PageItem = ({ isActive, color: _color = color('text-caption'), ...props }: any) => (
<Flex
_hover={{
cursor: 'pointer',
color: color('text-title'),
}}
color={isActive ? color('accent') : color('text-caption')}
mb={space('tight')}
fontSize="14px"
fontSize="16px"
color={isActive ? color('accent') : _color}
{...props}
/>
);
@ -57,39 +57,56 @@ const PageItem = ({ isActive, ...props }: any) => (
const SectionTitle: React.FC<BoxProps> = props => (
<Box
color={color('text-title')}
fontSize="16px"
fontSize="18px"
mb={space('tight')}
fontWeight="400"
{...props}
/>
);
const getRoutePath = path => routes.find(route => route.path.endsWith(path));
const ChildPages = ({ items, handleClick }: any) =>
items.pages.map(page => {
const path = page.pages
? `${page.path}${page.pages[0].path}`
: items.path
? '/' + slugify(items.path) + page.path
: page.path;
items?.pages
? items?.pages?.map(page => {
const path = page.pages
? `${page.path}${page.pages[0].path}`
: items.path
? '/' + slugify(items.path) + page.path
: page.path;
const routePath = routes.find(route => route.path.endsWith(path));
const router = useRouter();
return (
<Box mb={space('extra-tight')}>
<Link href={routePath.path} passHref>
<PageItem onClick={page.pages ? () => handleClick(page) : undefined} as="a">
{convertToTitle(page.path)}
</PageItem>
</Link>
</Box>
);
});
const routePath = routes.find(route => route.path.endsWith(path));
return (
<Box mb={space('extra-tight')}>
<Link href={routePath.path} passHref>
<PageItem
isActive={router.pathname.endsWith(path)}
onClick={page.pages ? () => handleClick(page) : undefined}
as="a"
>
{convertToTitle(page.path)}
</PageItem>
</Link>
</Box>
);
})
: null;
const ChildSection = ({ sections }) =>
const ChildSection: React.FC<BoxProps & { sections?: any }> = ({ sections, ...rest }) =>
sections.map(section => {
return (
<Box mt={space('base-loose')}>
<SectionTitle>{section.title}</SectionTitle>
<Box {...rest}>
<SectionTitle
letterSpacing="0.06rem"
textTransform="uppercase"
fontSize="12px"
fontWeight={500}
>
{section.title}
</SectionTitle>
<ChildPages items={section} />
</Box>
);
@ -104,25 +121,48 @@ const BackItem = props => (
</PageItem>
);
const NewNav = () => {
const Navigation = () => {
const [selected, setSelected] = React.useState<any | undefined>({
type: 'default',
items: nav.sections,
selected: undefined,
});
const router = useRouter();
React.useEffect(() => {
let currentSection = selected.items;
nav.sections.forEach(section => {
section.pages.forEach(page => {
if (page.pages) {
const pagesFound = page.pages.find(_page => {
return router.pathname.endsWith(page.path + _page.path);
});
const sectionsFound = page?.sections?.find(_section => {
return _section.pages.find(_page => {
return router.pathname.endsWith(page.path + _page.path);
});
});
if (pagesFound || sectionsFound) {
currentSection = page;
}
} else {
return router.pathname.endsWith(page.path);
}
});
});
if (selected.items !== currentSection) {
setSelected({ type: 'page', items: currentSection });
}
}, []);
const handleClick = (page: any) => {
if (page.pages) {
setSelected({
type: 'page',
items: page,
});
} else {
setSelected({
type: 'default',
items: nav.sections,
selected: page.path,
});
}
};
@ -141,6 +181,7 @@ const NewNav = () => {
{selected.items ? <ChildPages handleClick={handleClick} items={selected.items} /> : null}
{selected.items?.sections ? (
<ChildSection
mt={space('extra-loose')}
sections={selected.items?.sections?.map(section => ({
...section,
path: selected.items.path,
@ -159,7 +200,7 @@ const NewNav = () => {
? {
color: color('text-title'),
mb: space('tight'),
fontSize: '16px',
fontSize: '18px',
_hover: {
color: color('accent'),
cursor: 'pointer',
@ -167,9 +208,9 @@ const NewNav = () => {
}
: {};
return (
<Box mb={space('base')}>
<Box mb="40px">
{section.title ? (
<Flex width="100%" align="center">
<Flex width="100%" align="center" mb={space('extra-tight')}>
<SectionTitle>{section.title}</SectionTitle>
<Box
transform="translateY(-3px)"
@ -185,9 +226,11 @@ const NewNav = () => {
const path = page.pages
? `${page.path}${page.pages[0].path}`
: section?.title
? '/' + slugify(section?.title) + page.path
? `/${slugify(section?.title)}${page.path}`
: page.path;
const route = getRoutePath(path);
return (
<Box mb={space('extra-tight')}>
<Link href={path}>
@ -195,10 +238,10 @@ const NewNav = () => {
as="a"
href={path}
{...itemProps}
isActive={selected.selected === page.path}
isActive={router.pathname.endsWith(path)}
onClick={() => handleClick(page)}
>
{convertToTitle(page.path)}
{section.usePageTitles ? getTitle(route) : convertToTitle(page.path)}
</PageItem>
</Link>
</Box>
@ -216,7 +259,7 @@ export const SideNav: React.FC<BoxProps & { containerProps?: BoxProps }> = ({
}) => {
return (
<Wrapper containerProps={containerProps} {...rest}>
<NewNav />
<Navigation />
</Wrapper>
);
};

7
src/components/toc.tsx

@ -63,12 +63,7 @@ export const TableOfContents = ({
} & BoxProps) => {
return (
<Box position="relative" display={display}>
<Box
flexShrink={0}
minWidth={['100%', `${TOC_WIDTH}px`, `${TOC_WIDTH}px`]}
pr={space('base')}
{...rest}
>
<Box flexShrink={0} width="100%" {...rest}>
{!noLabel && (
<Box mb={space('extra-tight')}>
<Text fontWeight="bold" fontSize="14px">

30
src/components/typography.tsx

@ -1,19 +1,17 @@
import * as React from 'react';
import { Text as BaseText, BoxProps, color, FlexProps } from '@blockstack/ui';
import { border } from '@common/utils';
import { Text as BaseText, BoxProps, color } from '@blockstack/ui';
import { getCapsizeStyles } from '@components/mdx/typography';
export const Text = React.forwardRef((props: BoxProps, ref) => (
<BaseText ref={ref} color={color('text-body')} {...props} />
<BaseText ref={ref} color={color('text-body')} {...getCapsizeStyles(16, 26)} {...props} />
));
export const Caption: React.FC<BoxProps> = props => (
<Text
style={{ userSelect: 'none' }}
color={color('text-caption')}
fontSize="12px"
lineHeight="16px"
display="inline-block"
fontFamily="body"
{...getCapsizeStyles(14, 22)}
{...props}
/>
);
@ -22,26 +20,6 @@ export const Title: React.FC<BoxProps> = React.forwardRef((props, ref) => (
<Text ref={ref} display="inline-block" color={color('text-title')} {...props} />
));
export const SectionTitle: React.FC<BoxProps> = props => (
<Title lineHeight="28px" fontSize="20px" fontWeight="500" {...props} />
);
export const Pre = React.forwardRef((props: BoxProps, ref) => (
<Text
fontFamily={`"Soehne Mono", "Fira Code", monospace`}
bg={color('bg-alt')}
borderRadius="3px"
px="extra-tight"
border={border()}
fontSize="12px"
ref={ref}
{...props}
style={{
whiteSpace: 'nowrap',
}}
/>
));
export type LinkProps = BoxProps & Partial<React.AnchorHTMLAttributes<HTMLAnchorElement>>;
export const Link = React.forwardRef(({ _hover = {}, ...props }: LinkProps, ref) => (

8
src/pages/_document.tsx

@ -41,28 +41,28 @@ export default class MyDocument extends Document<any> {
font-family: 'Soehne Mono';
src: url('/static/fonts/soehne-mono-web-buch.otf') format('opentype');
font-weight: 400;
font-display: auto;
font-display: swap;
font-style: normal;
}
@font-face {
font-family: 'Soehne';
src: url('/static/fonts/soehne-web-buch.otf') format('opentype');
font-weight: 400;
font-display: auto;
font-display: swap;
font-style: normal;
}
@font-face {
font-family: 'Soehne';
src: url('/static/fonts/soehne-web-kraftig_1.otf') format('opentype');
font-weight: 500;
font-display: auto;
font-display: swap;
font-style: normal;
}
@font-face {
font-family: 'Soehne';
src: url('/static/fonts/soehne-web-halbfett_1.otf') format('opentype');
font-weight: 600;
font-display: auto;
font-display: swap;
font-style: normal;
}
`,

3
src/pages/authentication/building-todo-app.md

@ -3,6 +3,9 @@ title: Building a Todo app
description: Learn how to integrate authentication and data storage.
tags:
- tutorial
images:
large: /images/pages/todo-app.svg
sm: /images/pages/todo-app-sm.svg
redirect_from:
- /develop/zero_to_dapp_1.html
- /browser/hello-blockstack.html

21
src/pages/authentication/connect.md

@ -1,10 +1,29 @@
---
description: 'Guide to Blockstack Connect'
title: Blockstack Connect
description: Learn what Connect is and how to integrate it into an app.
experience: beginners
---
# Guide to Blockstack Connect
## Introduction
Blockstack Connect is a JavaScript library for integrating Blockstack authentication and smart contracts into your app.
The library empowers you to:
- Register new users with a pre-built onboarding flow that quickly educates them as to the privacy benefits of using your app with Blockstack and provisions a "Secret Key" that secures their identity and data against the Stacks blockchain.
- Authenticate users when they return to your app using that same Secret Key.
- Prompt users to sign transactions with smart contracts as written in Clarity and published to the Stacks blockchain.
## How does this compare to `blockstack.js`?
Although [`blockstack.js`](https://github.com/blockstack/blockstack.js) can also be used to authenticate users, it implements the deprecated [Blockstack Browser](https://browser.blockstack.org/) and lacks any pre-built onboarding UI that educates users as to how your app is more secure for having implemented Blockstack. As such, we advise that you use `blockstack.js` for all other functionality apart from authentication, such as saving and retrieving user data with Gaia.
## Start building with Blockstack Connect
Head over to the [to-do app tutorial](/authentication/building-todo-app) to learn how to build apps with Blockstack Connect.
## Installation
With yarn:

3
src/pages/authentication/overview.md

@ -1,6 +1,9 @@
---
title: Authentication
description: Blockstack Auth provides single sign on and authentication without third parties or remote servers.
images:
large: /images/pages/authentication.svg
sm: /images/pages/authentication-sm.svg
---
# Authentication protocol

2
src/pages/authentication/profiles.md

@ -4,7 +4,7 @@ title: Guide to Blockstack Profiles
# Guide to Blockstack Profiles
You can use `blockstack.js` to create and register an Blockstack username on the Stacks blockchain.
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

19
src/pages/build-an-app.md

@ -1,13 +1,16 @@
---
title: Building decentralized apps
description: Overview and guides for getting started building decentralized applications.
images:
large: /images/pages/build-an-app.svg
sm: /images/pages/build-an-app-sm.svg
---
# Building decentralized apps
Prefer to jump right in? Get started with this tutorial where you’ll create a decentralized to-do list app.
[[page-reference | inline]]
[@page-reference | inline]
| /authentication/building-todo-app
## What are decentralized apps?
@ -44,13 +47,13 @@ To build your decentralized app, you’ll use authentication, data storage, data
Like a regular app, yours will require user authentication and data storage — but decentralized. Get started with the
documentation below or try the tutorial.
[[page-reference | inline]]
[@page-reference | inline]
| /authentication/overview
[[page-reference | inline]]
[@page-reference | inline]
| /data-storage/overview
[[page-reference | inline]]
[@page-reference | inline]
| /authentication/building-todo-app
### Data indexing
@ -58,7 +61,7 @@ documentation below or try the tutorial.
If you need to store and index data shared by multiple users, such as messages or a shared document, read the Radiks
documentation.
[[page-reference | inline]]
[@page-reference | inline]
| /data-indexing/overview
### Smart contracts
@ -66,11 +69,11 @@ documentation.
You can use smart contracts to decentralize your app’s backend logic, making it open and permissionless. Smart contracts
on Blockstack are written in the Clarity language. View the smart contracts documentation or get started with a tutorial.
[[page-reference | inline]]
[@page-reference | inline]
| /smart-contracts/overview
[[page-reference | inline]]
[@page-reference | inline]
| /smart-contracts/hello-world-tutorial
[[page-reference | inline]]
[@page-reference | inline]
| /smart-contracts/counter-tutorial

5
src/pages/data-indexing/overview.md

@ -1,6 +1,9 @@
---
title: Overview
title: Radiks
description: Using Radiks you can build multi-player apps that index, store, and query user data.
images:
large: /images/pages/radiks.svg
sm: /images/pages/radiks-sm.svg
---
# Radiks the data indexer

5
src/pages/data-storage/overview.md

@ -1,6 +1,9 @@
---
title: A decentralized storage architecture
description: 'Storing user data with Blockstack'
description: Storing user data with Blockstack
images:
large: /images/pages/data-storage.svg
sm: /images/pages/data-storage-sm.svg
---
# A decentralized storage architecture

19
src/pages/index.md

@ -1,28 +1,21 @@
---
title: 'Documentation'
title: Documentation
description: All you need to build decentralized apps and smart contracts.
---
# Documentation
All you need to build decentralized apps and smart contracts
## Get started
[[page-reference]]
[@page-reference | grid]
| /build-an-app, /smart-contracts/overview, /mining
## Tutorials
[[page-reference]]
| /authentication/building-todo-app, /smart-contracts/hello-world-tutorial, /smart-contracts/counter-tutorial
[@page-reference | grid]
| /authentication/building-todo-app, /smart-contracts/counter-tutorial
## Explore
[[page-reference]]
[@page-reference | grid-small]
| /ecosystem/overview, /ecosystem/stacks-token
## Sample projects
Showcase your sample project
[Submit on GitHub](https://github.com/blockstack/docs.blockstack)

3
src/pages/mining.md

@ -1,6 +1,9 @@
---
title: Mine Stacks Token
description: Run a node, earn STX, and learn how Proof of Transfer (PoX) works
images:
large: /images/pages/mining.svg
sm: /images/pages/mining-sm.svg
---
# Mine Stacks Token

2
src/pages/references/blockstack-cli-reference.md → src/pages/references/blockstack-cli.md

@ -1,5 +1,5 @@
---
title: Blockstack CLI Reference
title: Blockstack CLI
---
export { convertBlockstackCLIUsageToMdx as getStaticProps } from '@common/data/cli-ref'

3
src/pages/references/clarity-reference.md → src/pages/references/clarity-language.md

@ -1,5 +1,6 @@
---
description: 'See a detailed list of all keywords and functions for the Clarity language.'
title: Clarity Language
description: See a detailed list of all keywords and functions for the Clarity language.
---
export { convertClarityRefToMdx as getStaticProps } from '@common/data/clarity-ref'

3
src/pages/references/faqs.md

@ -1,5 +1,6 @@
---
description: 'Blockstack Network documentation'
title: FAQs
description: This is a comprehensive list of all the Blockstack FAQs.
redirect_from: /org/voucherholder
---

2
src/pages/references/glossary.md

@ -1,5 +1,5 @@
---
description: 'Blockstack Network documentation'
description: A comprehensive list of terms used within the ecosystem.
---
export { convertGlossaryToJson as getStaticProps } from '@common/data/glossary'

2
src/pages/references/stacks-blockchain-reference.md → src/pages/references/stacks-blockchain.md

@ -1,5 +1,5 @@
---
title: 'Stacks Blockchain APIs'
title: Stacks Blockchain APIs
description: Interacting with the Stacks 2.0 Blockchain
---

3
src/pages/references/stacks-rpc-api-reference.md → src/pages/references/stacks-rpc-api.md

@ -1,5 +1,6 @@
---
description: 'Stacks Node RPC API Reference'
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

5
src/pages/smart-contracts/counter-tutorial.md

@ -2,6 +2,11 @@
description: Learn how to write a simple smart contract in the Clarity language.
experience: intermediate
duration: 30 minutes
tags:
- tutorial
images:
large: /images/pages/counter-tutorial.svg
sm: /images/pages/counter-tutorial-sm.svg
---
# Counter smart contract

9
src/pages/smart-contracts/hello-world-tutorial.md

@ -1,14 +1,17 @@
---
title: Hello, World!
description: Get Started Writing Smart Contracts with Clarity
duration: 18 minutes
experience: beginners
images:
large: /images/pages/hello-world-app.svg
sm: /images/pages/hello-world-sm.svg
---
# Hello, World!
## Overview
| Experience | | **Beginner** |
| Duration | | **18 minutes** |
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.
Clarity, Blockstack's smart contracting language, is based on LISP and uses its parenthesized notation. Clarity is an [interpreted language](https://en.wikipedia.org/wiki/Interpreted_language), and [decidable](https://en.wikipedia.org/wiki/Recursive_language). To learn more basics about the language, see the [Introduction to Clarity](overview) topic.

10
src/pages/smart-contracts/overview.md

@ -1,8 +1,12 @@
---
description: 'Blockstack Clarity: Introduction'
title: Write smart contracts
description: Overview and guides for getting started with Clarity
images:
large: /images/pages/smart-contracts.svg
sm: /images/pages/smart-contracts-sm.svg
---
# Introduction to Clarity
# Write smart contracts
Clarity is a programming language for writing smart contracts on the Stacks 2.0 blockchain. It supports programmatic control over digital assets.
@ -28,7 +32,7 @@ Not every decentralized application requires smart contracts, but Clarity unlock
Clarity differs from most other smart contract languages in two essential ways:
- The language is interpreted and broadcasted on the blockchain as is (not compiled)
- 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.

0
src/pages/smart-contracts/running-testnet-node.md → src/pages/smart-contracts/running-a-testnet-node.md

16
src/pages/smart-contracts/testing-contracts.md

@ -1,14 +1,14 @@
---
title: Testing Clarity code
description: Learn to Test Clarity Contract Code with JavaScript and Mocha
experience: advanced
duration: 15 minutes
---
# Test Clarity Code
# Testing Clarity code
## Overview
| Experience | | **Advanced** |
| Duration | | **15 minutes** |
Clarity, Blockstack's smart contracting language, is based on [LISP](<https://en.wikipedia.org/wiki/Lisp_(programming_language)>). 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.
- Have a working Clarity starter project
@ -138,15 +138,9 @@ Now, review the last test `should echo number` on your own and try to understand
---
With the completion of this tutorial, you ...
With the completion of this tutorial, you:
- Created a working Clarity starter project
- Understood how to test Clarity contracts
Congratulations!
## Where to go next
- <a href="principals.html">Guide: Understanding principals</a>
- <a href="tutorial-counter.html">Next tutorial: Writing a counter smart contract</a>
- <a href="clarityRef.html">Clarity language reference</a>

25
yarn.lock

@ -2905,6 +2905,13 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001093:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001107.tgz#809360df7a5b3458f627aa46b0f6ed6d5239da9a"
integrity sha512-86rCH+G8onCmdN4VZzJet5uPELII59cUzDphko3thQFgAQG1RNa+sVLDoALIhRYmflo5iSIzWY3vu1XTWtNMQQ==
capsize@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/capsize/-/capsize-1.1.0.tgz#d70f918b5ecadc2390b2a3b3b672ced639907ed6"
integrity sha512-tV0weOXxQ9hsbqewiWfGQBXsGzSN/i/w9IGuH+JVySzGOhscTAzeK3N9ZAM3Kf89bWgYot80Za5fSXKi6ZynvA==
dependencies:
round-to "^4.1.0"
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
@ -8072,6 +8079,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^3.0.0"
inherits "^2.0.1"
round-to@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/round-to/-/round-to-4.1.0.tgz#148d768d18b2f127f78e6648cb8b0a5943c416bf"
integrity sha512-H/4z+4QdWS82iMZ23+5St302Mv2jJws0hUvEogrD6gC8NN6Z5TalDtbg51owCrVy4V/4c8ePvwVLNtlhEfPo5g==
run-queue@^1.0.0, run-queue@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
@ -9172,10 +9184,10 @@ unicode-property-aliases-ecmascript@^1.0.4:
resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4"
integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==
unified-vscode@^1.0.0-beta.0:
version "1.0.0-beta.0"
resolved "https://registry.yarnpkg.com/unified-vscode/-/unified-vscode-1.0.0-beta.0.tgz#d09a7375943094ac7b1a782e98b404405343a0ff"
integrity sha512-DsTZZqOx85ycgNKzemttRW2oBJN/7ZXZzJnvbaTQ594IH8L5zARrdWFqZxEiCgHM7rpYjnE52SbKMheH4VwBFQ==
unified-vscode@^1.0.0-beta.1:
version "1.0.0-beta.1"
resolved "https://registry.yarnpkg.com/unified-vscode/-/unified-vscode-1.0.0-beta.1.tgz#d80c220c119e77da60c81fea1e441a062507449d"
integrity sha512-YXjyTkJRCeePjFfz8HCZM0ZZmiuHMwb83B8jQZ922rrnMas77MSYT7S63MFA2vBTOxvEJzeKutuTjPvRYd/hfA==
dependencies:
cache-manager "^3.3.0"
cache-manager-fs-hash "^0.0.9"
@ -9576,6 +9588,11 @@ vm-browserify@^1.0.1:
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
"vscode-textmate@git+https://github.com/octref/vscode-textmate.git":
version "4.0.1"
uid e65aabe2227febda7beaad31dd0fca1228c5ddf3
resolved "git+https://github.com/octref/vscode-textmate.git#e65aabe2227febda7beaad31dd0fca1228c5ddf3"
"vscode-textmate@https://github.com/octref/vscode-textmate":
version "4.0.1"
resolved "https://github.com/octref/vscode-textmate#e65aabe2227febda7beaad31dd0fca1228c5ddf3"

Loading…
Cancel
Save