chore: added TOC to blog post

This commit is contained in:
Jonathan Summers-Muir
2021-02-18 15:09:32 +08:00
parent 60a2eab880
commit e5f2c4471e
11 changed files with 554 additions and 18 deletions

3
package-lock.json generated Normal file
View File

@@ -0,0 +1,3 @@
{
"lockfileVersion": 1
}

View File

@@ -7,6 +7,7 @@ author_url: https://github.com/roryw10
author_image_url: https://github.com/roryw10.png
authorURL: https://github.com/roryw10
image: supabase-xendit.png
thumb: supabase-xendit-thumb.jpg
tags:
- case-study
- fintech

View File

@@ -1,7 +1,7 @@
---
title: Supabase Beta December 2020
description: Ten months of building.
author: Paul Copplestone
author: paul_copplestone
author_title: Supabase
author_url: https://github.com/kiwicopple
author_image_url: https://github.com/kiwicopple.png

View File

@@ -1,7 +1,7 @@
---
title: Supabase Beta January 2021
description: Eleven months of building.
author: Paul Copplestone
author: paul_copplestone
author_title: Supabase
author_url: https://github.com/kiwicopple
author_image_url: https://github.com/kiwicopple.png

View File

@@ -20,13 +20,13 @@ Learn how Brad and Roboflow used Supabase to launch [Paint.wtf](https://paint.wt
![Supabase and Strive are partnering up to teach OSS.](/new/images/blog/roboflow-website.png)
**From idea to a launch in a weekend**
## From idea to a launch in a weekend
Brad and a friend ([Erik Dunteman](https://twitter.com/erikdoingthings)) wanted to experiment with OpenAI's new [CLIP](https://openai.com/blog/clip/) model through a side project they could build in a weekend. CLIP classifies a wide range of images by flipping image classification into a text similarity task. Current image classifiers are limited because they are trained on a fixed number of categories. In contrast, CLIP learns from the raw text describing the images meaning the classifier isn't limited by labels and supervised learning. The team recognised that CLIP opens up a vast range of use cases that have been difficult previously due to the time required to collect images and train the model.
Roboflow settled on a straightforward concept: they prompt users to draw an image which is then fed into CLIP. The AI then judges how close the drawing is to the given prompt and assigns it a score. Users' performance is tracked on a leaderboard for each prompt and users can see how well they performed against their peers according to the model.
**Leaderboards that Count**
## Leaderboards that Count
Brad and the team needed a leaderboard to make this idea work. While their first intuition was to use Firebase, it lacks the built-in functionality for counting the number of documents in a collection - a critical function for implementing their leaderboard design.
@@ -34,7 +34,7 @@ Brad and the team needed a leaderboard to make this idea work. While their first
You might export data to BigQuery, or implement an increment function on collection change, however PostgreSQL has great built in support for counting and Brad felt like this would be the perfect opportunity to test out Supabase and get the functionality he needed for the leaderboards to work reliably and without implementing add-ons.
**One weekend to break the internet**
## One weekend to break the internet
Brad and the team built the product overnight and launched it on Hacker News. Paint.wtf went on to make it to Hacker News and Reddit's first page, and getting traction on Product Hunt. As a result, they had to handle serious user volumes; at its peak, users were submitting over 2 new drawings every second.
@@ -54,6 +54,6 @@ Paint.Wtf has continued to get sustained coverage in the media and has continued
![Supabase and Strive are partnering up to teach OSS.](/new/images/blog/roboflow-quote.png)
**Ship fast, and carry on scaling**
## Ship fast, and carry on scaling
Thanks to Supabase, Roboflow could launch quickly and keep scaling despite the huge user volumes their innovative project generated overnight.

396
www/package-lock.json generated
View File

@@ -1016,6 +1016,14 @@
"resolved": "https://registry.npmjs.org/anser/-/anser-1.4.9.tgz",
"integrity": "sha512-AI+BjTeGt2+WFk4eWcqbQ7snZpDBt8SaLlj0RT2h5xfdWaiy51OjYvqwMrNzJLGy8iOAL6nKDITWO+rd4MkYEA=="
},
"ansi-red": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz",
"integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=",
"requires": {
"ansi-wrap": "0.1.0"
}
},
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
@@ -1029,6 +1037,11 @@
"color-convert": "^1.9.0"
}
},
"ansi-wrap": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
"integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768="
},
"anymatch": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
@@ -1153,6 +1166,14 @@
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
"dev": true
},
"autolinker": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/autolinker/-/autolinker-0.28.1.tgz",
"integrity": "sha1-BlK0kYgYefB3XazgzcoyM5QqTkc=",
"requires": {
"gulp-header": "^1.7.1"
}
},
"autoprefixer": {
"version": "9.8.6",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz",
@@ -1370,6 +1391,11 @@
"ieee754": "^1.1.4"
}
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
},
"buffer-xor": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
@@ -1493,6 +1519,11 @@
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
"optional": true
},
"coffee-script": {
"version": "1.12.7",
"resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz",
"integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw=="
},
"collapse-white-space": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz",
@@ -1550,6 +1581,54 @@
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
"requires": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^2.2.2",
"typedarray": "^0.0.6"
},
"dependencies": {
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
}
}
},
"concat-with-sourcemaps": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz",
"integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==",
"requires": {
"source-map": "^0.6.1"
}
},
"console-browserify": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
@@ -1902,6 +1981,11 @@
"minimist": "^1.1.1"
}
},
"diacritics-map": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/diacritics-map/-/diacritics-map-0.1.0.tgz",
"integrity": "sha1-bfwP+dAQAKLt8oZTccrDFulJd68="
},
"didyoumean": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.1.tgz",
@@ -2053,6 +2137,49 @@
"safe-buffer": "^5.1.1"
}
},
"expand-range": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
"integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
"requires": {
"fill-range": "^2.1.0"
},
"dependencies": {
"fill-range": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz",
"integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==",
"requires": {
"is-number": "^2.1.0",
"isobject": "^2.0.0",
"randomatic": "^3.0.0",
"repeat-element": "^1.1.2",
"repeat-string": "^1.5.2"
}
},
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"is-number": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
"integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
"requires": {
"kind-of": "^3.0.2"
}
},
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"requires": {
"is-buffer": "^1.1.5"
}
}
}
},
"expand-template": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
@@ -2148,6 +2275,11 @@
"integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==",
"dev": true
},
"for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
"integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
},
"format": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
@@ -2289,6 +2421,16 @@
"strip-bom-string": "^1.0.0"
}
},
"gulp-header": {
"version": "1.8.12",
"resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz",
"integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==",
"requires": {
"concat-with-sourcemaps": "*",
"lodash.template": "^4.4.0",
"through2": "^2.0.0"
}
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@@ -2693,6 +2835,21 @@
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA=="
},
"is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
"requires": {
"isobject": "^3.0.1"
},
"dependencies": {
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
}
}
},
"is-whitespace-character": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz",
@@ -2850,6 +3007,14 @@
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
},
"lazy-cache": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz",
"integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=",
"requires": {
"set-getter": "^0.1.0"
}
},
"line-column": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/line-column/-/line-column-1.0.2.tgz",
@@ -2859,6 +3024,40 @@
"isobject": "^2.0.0"
}
},
"list-item": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/list-item/-/list-item-1.1.1.tgz",
"integrity": "sha1-DGXQDih8tmPMs8s4Sad+iewmilY=",
"requires": {
"expand-range": "^1.8.1",
"extend-shallow": "^2.0.1",
"is-number": "^2.1.0",
"repeat-string": "^1.5.2"
},
"dependencies": {
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"is-number": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
"integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
"requires": {
"kind-of": "^3.0.2"
}
},
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"requires": {
"is-buffer": "^1.1.5"
}
}
}
},
"loader-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
@@ -2885,8 +3084,7 @@
"lodash._reinterpolate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
"dev": true
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
},
"lodash.camelcase": {
"version": "4.3.0",
@@ -2902,7 +3100,6 @@
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz",
"integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==",
"dev": true,
"requires": {
"lodash._reinterpolate": "^3.0.0",
"lodash.templatesettings": "^4.0.0"
@@ -2912,7 +3109,6 @@
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz",
"integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==",
"dev": true,
"requires": {
"lodash._reinterpolate": "^3.0.0"
}
@@ -2972,11 +3168,54 @@
"resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz",
"integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg=="
},
"markdown-link": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/markdown-link/-/markdown-link-0.1.1.tgz",
"integrity": "sha1-MsXGUZmmRXMWMi0eQinRNAfIx88="
},
"markdown-table": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz",
"integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q=="
},
"markdown-toc": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/markdown-toc/-/markdown-toc-1.2.0.tgz",
"integrity": "sha512-eOsq7EGd3asV0oBfmyqngeEIhrbkc7XVP63OwcJBIhH2EpG2PzFcbZdhy1jutXSlRBBVMNXHvMtSr5LAxSUvUg==",
"requires": {
"concat-stream": "^1.5.2",
"diacritics-map": "^0.1.0",
"gray-matter": "^2.1.0",
"lazy-cache": "^2.0.2",
"list-item": "^1.1.1",
"markdown-link": "^0.1.1",
"minimist": "^1.2.0",
"mixin-deep": "^1.1.3",
"object.pick": "^1.2.0",
"remarkable": "^1.7.1",
"repeat-string": "^1.6.1",
"strip-color": "^0.1.0"
},
"dependencies": {
"gray-matter": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-2.1.1.tgz",
"integrity": "sha1-MELZrewqHe1qdwep7SOA+KF6Qw4=",
"requires": {
"ansi-red": "^0.1.1",
"coffee-script": "^1.12.4",
"extend-shallow": "^2.0.1",
"js-yaml": "^3.8.1",
"toml": "^2.3.2"
}
}
}
},
"math-random": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz",
"integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A=="
},
"md5.js": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@@ -3156,6 +3395,25 @@
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"mixin-deep": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
"integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
"requires": {
"for-in": "^1.0.2",
"is-extendable": "^1.0.1"
},
"dependencies": {
"is-extendable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
"integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
"requires": {
"is-plain-object": "^2.0.4"
}
}
}
},
"mkdirp-classic": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
@@ -3458,6 +3716,21 @@
"integrity": "sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg==",
"dev": true
},
"object.pick": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
"integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
"requires": {
"isobject": "^3.0.1"
},
"dependencies": {
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
}
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -4666,6 +4939,23 @@
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz",
"integrity": "sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw=="
},
"randomatic": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz",
"integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==",
"requires": {
"is-number": "^4.0.0",
"kind-of": "^6.0.0",
"math-random": "^1.0.1"
},
"dependencies": {
"is-number": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
"integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ=="
}
}
},
"randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -5094,6 +5384,20 @@
"xtend": "^4.0.1"
}
},
"remarkable": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/remarkable/-/remarkable-1.7.4.tgz",
"integrity": "sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg==",
"requires": {
"argparse": "^1.0.10",
"autolinker": "~0.28.0"
}
},
"repeat-element": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
"integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g=="
},
"repeat-string": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
@@ -5167,6 +5471,14 @@
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
"optional": true
},
"set-getter": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz",
"integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=",
"requires": {
"to-object-path": "^0.3.0"
}
},
"setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
@@ -5417,6 +5729,11 @@
"resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz",
"integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI="
},
"strip-color": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz",
"integrity": "sha1-EG9l09PmotlAHKwOsM6LinArT3s="
},
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
@@ -5598,6 +5915,44 @@
"readable-stream": "^3.1.1"
}
},
"through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"requires": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
},
"dependencies": {
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
}
}
},
"timers-browserify": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz",
@@ -5622,6 +5977,29 @@
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
},
"to-object-path": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
"integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
"requires": {
"kind-of": "^3.0.2"
},
"dependencies": {
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"requires": {
"is-buffer": "^1.1.5"
}
}
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -5640,6 +6018,11 @@
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
},
"toml": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/toml/-/toml-2.3.6.tgz",
"integrity": "sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ=="
},
"tr46": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
@@ -5692,6 +6075,11 @@
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz",
"integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg=="
},
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
"typescript": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.2.tgz",

View File

@@ -18,6 +18,7 @@
"classnames": "2.2.6",
"date-fns": "2.10.0",
"gray-matter": "^4.0.2",
"markdown-toc": "^1.2.0",
"next": "latest",
"react": "^16.13.0",
"react-copy-to-clipboard": "^5.0.2",

View File

@@ -64,10 +64,10 @@ function Blog(props: any) {
</div>
</div>
</div>
<div className="container mx-auto px-8 sm:px-16 xl:px-20 mt-16">
<div className="container mx-auto px-8 sm:px-16 xl:px-20 mt-32">
<div className=" mx-auto max-w-7xl">
<Typography.Title level={2}>More posts from the team</Typography.Title>
<div className="mt-5 max-w-lg mx-auto grid lg:grid-cols-1 lg:max-w-none">
<div className="mt-12 max-w-lg mx-auto grid lg:grid-cols-1 lg:max-w-none">
{/* <ul> */}
{props.blogs.slice(2).map((blog: any, idx: any) => {
return BlogListItem(blog)

View File

@@ -0,0 +1,51 @@
.toc a {
text-decoration: none !important;
font-weight: 400 !important;
}
.toc > ul > li {
padding-left: 0 !important;
}
.toc li {
@apply text-sm !important;
padding-left: 1rem !important;
}
/* .toc ul,
.toc ol,
.toc li {
list-style: none !important;
list-style-type: none !important;
}
.toc ul li::marker,
.toc ol li::marker {
color: red !important;
font-size: 1.5em !important;
} */
.toc ul > li:before {
content: '';
position: absolute;
background-color: none;
border-radius: 50%;
width: 0 !important;
height: 0 !important;
top: 0.6875em;
left: 0.25em;
/* content: "";
position: absolute;
background-color: #bbb;
border-radius: 50%;
width: .375em;
height: .375em;
top: .6875em;
left: .25em; */
}
.header:hover svg,
.header svg:hover {
display: inline-block;
}

View File

@@ -1,24 +1,77 @@
// file: pages/blog/[slug].js
import React from 'react'
import { Typography } from '@supabase/ui'
import { IconHash, IconLink, Space, Typography } from '@supabase/ui'
import ReactMarkdown from 'react-markdown'
import DefaultLayout from '~/components/Layouts/Default'
import authors from 'lib/authors.json'
import blogStyles from './[slug].module.css'
const toc = require('markdown-toc')
function BlogPostPage(props: any) {
// @ts-ignore
const author = props.blog.author ? authors[props.blog.author] : authors['supabase']
return (
<DefaultLayout>
<div className="bg-white dark:bg-dark-700 overflow-hidden py-12">
<div className="container mx-auto px-8 sm:px-16 xl:px-20 mt-16">
<div className="mx-auto max-w-7xl">
<div className="max-w-3xl">
<Space className="mb-4">
<Typography.Text type="secondary">{props.blog.date}</Typography.Text>
<Typography.Text type="secondary"></Typography.Text>
<Typography.Text type="secondary">5 min read</Typography.Text>
</Space>
<Typography.Title>{props.blog.title}</Typography.Title>
{author && (
<div className="mt-6">
<Space size={4}>
{author.author_image_url && (
<img src={author.author_image_url} className="rounded-full w-10" />
)}
<Space direction="vertical" size={0}>
<Typography.Text>{author.author}</Typography.Text>
<Typography.Text type="secondary" small>
{author.position}
</Typography.Text>
</Space>
</Space>
</div>
)}
</div>
</div>
</div>
<div className="overflow-hidden py-12">
<div className="py-12">
<div className="container mx-auto px-8 sm:px-16 xl:px-10 mb-16 -mt-16">
<div className="max-w-4xl">
<img
src={'/new/images/blog/' + props.blog.thumb}
className="object-cover"
style={{ maxHeight: '520px', width: '100%' }}
/>
</div>
</div>
<div className="container mx-auto px-8 sm:px-16 xl:px-20 mb-16">
{/* <div className="max-w-7xl">
<Typography.Text className=" block mb-4">Table of contents</Typography.Text>
<ol>
{props.blog.toc.json.map((item: any) => {
return <li className="underline mb-2">{item.content}</li>
})}
</ol>
</div> */}
<Typography.Text className="block mb-4 underline">Table of contents</Typography.Text>
<Typography>
<div className={blogStyles['toc']}>
<ReactMarkdown>{props.blog.toc.content}</ReactMarkdown>
</div>
</Typography>
</div>
<div className="container mx-auto px-8 sm:px-16 xl:px-20">
<div className="mx-auto max-w-7xl">
<div className="max-w-7xl">
<Typography>
<ReactMarkdown>{props.blog.content}</ReactMarkdown>
<ReactMarkdown renderers={{ heading: HeadingRenderer }}>
{props.blog.content}
</ReactMarkdown>
</Typography>
</div>
</div>
@@ -50,11 +103,16 @@ export async function getStaticProps(context: any) {
// .use(markdown)
// .use(highlight) // highlight code block
// .use(html)
// .process(content) // pass content to process
// .process(content) // pass content to process)
console.log(toc(content))
console.log(typeof content)
return {
props: {
blog: {
toc: toc(content),
...data,
// content: result.toString(),
content: content,
@@ -86,4 +144,38 @@ export async function getStaticPaths(context: any) {
}
}
// Heading renderer solution
// https://github.com/remarkjs/react-markdown/issues/404
const flatten = (text: string, child: any) => {
const result: any =
typeof child === 'string'
? text + child
: React.Children.toArray(child.props.children).reduce(flatten, text)
return result
}
/**
* HeadingRenderer is a custom renderer
* It parses the heading and attaches an id to it to be used as an anchor
*/
const HeadingRenderer = (props: any) => {
const children = React.Children.toArray(props.children)
const text = children.reduce(flatten, '')
const slug = text.toLowerCase().replace(/\W/g, '-')
return (
<a href={'#' + slug} style={{ textDecoration: 'none' }}>
<Space>
<span className={blogStyles['header']}>
{React.createElement('h' + props.level, { id: slug }, [
props.children,
<IconLink size="small" className="ml-2 hidden" />,
])}
</span>
</Space>
</a>
)
}
export default BlogPostPage

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB