From 9b3586a5a41c6ed6f2d00e57f0ea78cfcb8753a5 Mon Sep 17 00:00:00 2001 From: b5 Date: Mon, 18 Dec 2023 13:22:17 -0500 Subject: [PATCH 1/4] sendme page --- package-lock.json | 8 +- package.json | 2 +- public/img/sendme/sendme_hero_1.svg | 201 ++++++++++++++++++++++++++++ src/app/sendme/PageIcon.jsx | 16 +++ src/app/sendme/bg.jsx | 48 +++++++ src/app/sendme/page.mdx | 126 +++++++++++++++++ src/lib/mdx/recma.mjs | 3 + src/lib/mdx/rehype.mjs | 124 +++++++++++++++++ src/lib/mdx/remark.mjs | 4 + src/lib/mdx/search.mjs | 135 +++++++++++++++++++ tailwind.config.js | 6 + 11 files changed, 668 insertions(+), 5 deletions(-) create mode 100644 public/img/sendme/sendme_hero_1.svg create mode 100644 src/app/sendme/PageIcon.jsx create mode 100644 src/app/sendme/bg.jsx create mode 100644 src/app/sendme/page.mdx create mode 100644 src/lib/mdx/recma.mjs create mode 100644 src/lib/mdx/rehype.mjs create mode 100644 src/lib/mdx/remark.mjs create mode 100644 src/lib/mdx/search.mjs diff --git a/package-lock.json b/package-lock.json index 1101efcb..15b7947c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@algolia/autocomplete-core": "^1.11.1", "@headlessui/react": "^1.7.17", "@headlessui/tailwindcss": "^0.2.0", - "@heroicons/react": "^2.0.18", + "@heroicons/react": "^2.1.1", "@lottiefiles/lottie-interactivity": "^1.6.2", "@lottiefiles/lottie-player": "^2.0.2", "@lottiefiles/react-lottie-player": "^3.5.3", @@ -518,9 +518,9 @@ } }, "node_modules/@heroicons/react": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.0.18.tgz", - "integrity": "sha512-7TyMjRrZZMBPa+/5Y8lN0iyvUU/01PeMGX2+RE7cQWpEUIcb4QotzUObFkJDejj/HUH4qjP/eQ0gzzKs2f+6Yw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.1.1.tgz", + "integrity": "sha512-JyyN9Lo66kirbCMuMMRPtJxtKJoIsXKS569ebHGGRKbl8s4CtUfLnyKJxteA+vIKySocO4s1SkTkGS4xtG/yEA==", "peerDependencies": { "react": ">= 16" } diff --git a/package.json b/package.json index a6e5eaab..946fbb84 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "@algolia/autocomplete-core": "^1.11.1", "@headlessui/react": "^1.7.17", "@headlessui/tailwindcss": "^0.2.0", - "@heroicons/react": "^2.0.18", + "@heroicons/react": "^2.1.1", "@lottiefiles/lottie-interactivity": "^1.6.2", "@lottiefiles/lottie-player": "^2.0.2", "@lottiefiles/react-lottie-player": "^3.5.3", diff --git a/public/img/sendme/sendme_hero_1.svg b/public/img/sendme/sendme_hero_1.svg new file mode 100644 index 00000000..052fdf08 --- /dev/null +++ b/public/img/sendme/sendme_hero_1.svg @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/sendme/PageIcon.jsx b/src/app/sendme/PageIcon.jsx new file mode 100644 index 00000000..64593b80 --- /dev/null +++ b/src/app/sendme/PageIcon.jsx @@ -0,0 +1,16 @@ +import React from "react"; + +export function PageIcon() { + return ( + + + + + + + + + + + ) +} \ No newline at end of file diff --git a/src/app/sendme/bg.jsx b/src/app/sendme/bg.jsx new file mode 100644 index 00000000..8cccca72 --- /dev/null +++ b/src/app/sendme/bg.jsx @@ -0,0 +1,48 @@ +import React from 'react' + +export default function Background() { + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ) +} \ No newline at end of file diff --git a/src/app/sendme/page.mdx b/src/app/sendme/page.mdx new file mode 100644 index 00000000..fb633c60 --- /dev/null +++ b/src/app/sendme/page.mdx @@ -0,0 +1,126 @@ +import React from 'react' +import Image from 'next/image' +import { + ChatBubbleLeftIcon +} from '@heroicons/react/24/outline' + +export const metadata = { + title: 'Sendme', + description: + 'send files over the internet', +} + +export const sections = [ + {title: 'Guides', id: 'guides'}, + {title: 'Resources', id: 'resources'}, +] + +
+
+
+

Send files

+

For free. No account required.

+
+ + +
+
+
+
+

File transfer
doesn't need to be complicated

+

It's like scp without needing to know the IP address.

+
+ +
+

Install

+
$ curl -fsSL https://iroh.computer/sendme.sh | sh
+
+
+
+ +
+
+
+

USING SENDME:

+
+
+
+
+
+
+
+
+
+

> $ sendme provide ~/great_photos

+

content added

+

run iroh get blobQmFoo...

+
+

1. Setup send

+

pass a file or folder you want to share to sendme. It'll spit out a ticket.

+
+
+
+ +
+ hey here have some great photos: + blobQmFoo... +
+
+

2. Paste the ticket

+

copy-paste the ticket to your friend.

+
+
+
+
+
+
+
+
+

> $ sendme get blobQmFoo...

+

fetched to my_photos

+
+

3. Download

+

run get to fetch data directly from your friend.

+
+
+
+ +
+
+
+
+

Free, for files & folders of any size

+

sendme works by connecting sender and receiver directly, so there's no need to upload to a server, which means no cost!

+
+
+
+

Fast.

+

Sendme can saturate a 4Gbps connection.

+
+
+

Resumable fetching

+

Interrupted downloads pick up where they left off.

+
+
+

Integrity checks

+

Data is automatically verified for correctness on both send and receive.

+
+
+
+ +
+
+

Coming Soon

+

Sendme Mobile

+

Send files to your iOS device!

+
+
+ +
+

Sendme is built on iroh blobs & connections

+

Just like Dumb pipe, sendme is built on iroh. Sendme uses iroh blobs to send and verfiy your files, and connections to establish direct links between devices for data transfer

+
+
+
+
+
\ No newline at end of file diff --git a/src/lib/mdx/recma.mjs b/src/lib/mdx/recma.mjs new file mode 100644 index 00000000..195ff746 --- /dev/null +++ b/src/lib/mdx/recma.mjs @@ -0,0 +1,3 @@ +import {mdxAnnotations} from 'mdx-annotations'; + +export const recmaPlugins = [mdxAnnotations.recma]; diff --git a/src/lib/mdx/rehype.mjs b/src/lib/mdx/rehype.mjs new file mode 100644 index 00000000..643bef86 --- /dev/null +++ b/src/lib/mdx/rehype.mjs @@ -0,0 +1,124 @@ +import {slugifyWithCounter} from '@sindresorhus/slugify'; +import * as acorn from 'acorn'; +import {toString} from 'mdast-util-to-string'; +import {mdxAnnotations} from 'mdx-annotations'; +import shiki from 'shiki'; +import {visit} from 'unist-util-visit'; + +function rehypeParseCodeBlocks() { + return (tree) => { + visit(tree, 'element', (node, _nodeIndex, parentNode) => { + if (node.tagName === 'code' && node.properties.className) { + parentNode.properties.language = node.properties.className[0]?.replace( + /^language-/, + '', + ); + } + }); + }; +} + +let highlighter; + +function rehypeShiki() { + return async (tree) => { + highlighter = + highlighter ?? (await shiki.getHighlighter({theme: 'css-variables'})); + + visit(tree, 'element', (node) => { + if (node.tagName === 'pre' && node.children[0]?.tagName === 'code') { + const codeNode = node.children[0]; + const textNode = codeNode.children[0]; + + node.properties.code = textNode.value; + + if (node.properties.language) { + const tokens = highlighter.codeToThemedTokens( + textNode.value, + node.properties.language, + ); + + textNode.value = shiki.renderToHtml(tokens, { + elements: { + pre: ({children}) => children, + code: ({children}) => children, + line: ({children}) => `${children}`, + }, + }); + } + } + }); + }; +} + +function rehypeSlugify() { + return (tree) => { + const slugify = slugifyWithCounter(); + visit(tree, 'element', (node) => { + if (node.tagName === 'h2' && !node.properties.id) { + node.properties.id = slugify(toString(node)); + } + }); + }; +} + +function rehypeAddMDXExports(getExports) { + return (tree) => { + const exports = Object.entries(getExports(tree)); + + for (const [name, value] of exports) { + for (const node of tree.children) { + if ( + node.type === 'mdxjsEsm' && + new RegExp(`export\\s+const\\s+${name}\\s*=`).test(node.value) + ) { + return; + } + } + + const exportStr = `export const ${name} = ${value}`; + + tree.children.push({ + type: 'mdxjsEsm', + value: exportStr, + data: { + estree: acorn.parse(exportStr, { + sourceType: 'module', + ecmaVersion: 'latest', + }), + }, + }); + } + }; +} + +function getSections(node) { + const sections = []; + + for (const child of node.children ?? []) { + if (child.type === 'element' && child.tagName === 'h2') { + sections.push(`{ + title: ${JSON.stringify(toString(child))}, + id: ${JSON.stringify(child.properties.id)}, + ...${child.properties.annotation} + }`); + } else if (child.children) { + sections.push(...getSections(child)); + } + } + + return sections; +} + +export const rehypePlugins = [ + mdxAnnotations.rehype, + rehypeParseCodeBlocks, + rehypeShiki, + rehypeSlugify, + [ + rehypeAddMDXExports, + (tree) => ({ + sections: `[${getSections(tree).join()}]`, + }), + ], +]; diff --git a/src/lib/mdx/remark.mjs b/src/lib/mdx/remark.mjs new file mode 100644 index 00000000..3178fe86 --- /dev/null +++ b/src/lib/mdx/remark.mjs @@ -0,0 +1,4 @@ +import {mdxAnnotations} from 'mdx-annotations'; +import remarkGfm from 'remark-gfm'; + +export const remarkPlugins = [mdxAnnotations.remark, remarkGfm]; diff --git a/src/lib/mdx/search.mjs b/src/lib/mdx/search.mjs new file mode 100644 index 00000000..0408c5ff --- /dev/null +++ b/src/lib/mdx/search.mjs @@ -0,0 +1,135 @@ +import {slugifyWithCounter} from '@sindresorhus/slugify'; +import glob from 'fast-glob'; +import * as fs from 'fs'; +import {toString} from 'mdast-util-to-string'; +import * as path from 'path'; +import {remark} from 'remark'; +import remarkMdx from 'remark-mdx'; +import {createLoader} from 'simple-functional-loader'; +import {filter} from 'unist-util-filter'; +import {SKIP, visit} from 'unist-util-visit'; +import * as url from 'url'; + +const __filename = url.fileURLToPath(import.meta.url); +const processor = remark().use(remarkMdx).use(extractSections); +const slugify = slugifyWithCounter(); + +function isObjectExpression(node) { + return ( + node.type === 'mdxTextExpression' && + node.data?.estree?.body?.[0]?.expression?.type === 'ObjectExpression' + ); +} + +function excludeObjectExpressions(tree) { + return filter(tree, (node) => !isObjectExpression(node)); +} + +function extractSections() { + return (tree, {sections}) => { + slugify.reset(); + + visit(tree, (node) => { + if (node.type === 'heading' || node.type === 'paragraph') { + const content = toString(excludeObjectExpressions(node)); + if (node.type === 'heading' && node.depth <= 2) { + const hash = node.depth === 1 ? null : slugify(content); + sections.push([content, hash, []]); + } else { + sections.at(-1)?.[2].push(content); + } + return SKIP; + } + }); + }; +} + +export default function search(nextConfig = {}) { + const cache = new Map(); + + return Object.assign({}, nextConfig, { + webpack(config, options) { + config.module.rules.push({ + test: __filename, + use: [ + createLoader(function() { + const appDir = path.resolve('./src/app'); + this.addContextDependency(appDir); + + const files = glob.sync('**/*.mdx', {cwd: appDir}); + const data = files.map((file) => { + const url = '/' + file.replace(/(^|\/)page\.mdx$/, ''); + const mdx = fs.readFileSync(path.join(appDir, file), 'utf8'); + + let sections = []; + + if (cache.get(file)?.[0] === mdx) { + sections = cache.get(file)[1]; + } else { + const vfile = {value: mdx, sections}; + processor.runSync(processor.parse(vfile), vfile); + cache.set(file, [mdx, sections]); + } + + return {url, sections}; + }); + + // When this file is imported within the application + // the following module is loaded: + return ` + import FlexSearch from 'flexsearch' + + let sectionIndex = new FlexSearch.Document({ + tokenize: 'full', + document: { + id: 'url', + index: 'content', + store: ['title', 'pageTitle'], + }, + context: { + resolution: 9, + depth: 2, + bidirectional: true + } + }) + + let data = ${JSON.stringify(data)} + + for (let { url, sections } of data) { + for (let [title, hash, content] of sections) { + sectionIndex.add({ + url: url + (hash ? ('#' + hash) : ''), + title, + content: [title, ...content].join('\\n'), + pageTitle: hash ? sections[0][0] : undefined, + }) + } + } + + export function search(query, options = {}) { + let result = sectionIndex.search(query, { + ...options, + enrich: true, + }) + if (result.length === 0) { + return [] + } + return result[0].result.map((item) => ({ + url: item.id, + title: item.doc.title, + pageTitle: item.doc.pageTitle, + })) + } + `; + }), + ], + }); + + if (typeof nextConfig.webpack === 'function') { + return nextConfig.webpack(config, options); + } + + return config; + }, + }); +} diff --git a/tailwind.config.js b/tailwind.config.js index dd890f1e..9c2c4dd3 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -21,6 +21,12 @@ module.exports = { }, typography: require('./typography'), extend: { + dropShadow: { + glow: [ + // "0 0px 20px rgba(255,255, 255, 0.2)", + "0 0px 15px rgba(255, 255,255, 0.25)" + ] + }, fontFamily: { 'space': ['Space Grotesk', 'sans-serif'], 'spaceMono': ['Space Mono', 'sans-serif'] From cfeaaaba4c43ad768854ebbaa33b1ff450214dc1 Mon Sep 17 00:00:00 2001 From: b5 Date: Wed, 20 Dec 2023 10:34:43 -0500 Subject: [PATCH 2/4] sendme page tweaks --- public/sendme.sh | 30 +++++++ src/app/sendme/page.mdx | 116 +------------------------ src/components/SendmePage.jsx | 146 ++++++++++++++++++++++++++++++++ src/components/icons/Github.jsx | 2 +- src/fonts/Koulen-Regular.ttf | Bin 0 -> 55724 bytes tailwind.config.js | 3 +- 6 files changed, 181 insertions(+), 116 deletions(-) create mode 100644 public/sendme.sh create mode 100644 src/components/SendmePage.jsx create mode 100644 src/fonts/Koulen-Regular.ttf diff --git a/public/sendme.sh b/public/sendme.sh new file mode 100644 index 00000000..88d50fe2 --- /dev/null +++ b/public/sendme.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# Copyright 2023 n0. All rights reserved. Dual MIT/Apache license. + +set -e + +repo="n0-computer/sendme" +release_url="https://api.github.com/repos/$repo/releases/latest" + +if [ "$OS" = "Windows_NT" ]; then + echo "Error: this installer only works on linux & macOS." 1>&2 + exit 1 +else + case $(uname -sm) in + "Darwin x86_64") target="darwin-x86_64" ;; + "Darwin arm64") target="darwin-aarch64" ;; + "Linux x86_64") target="linux-x86_64" ;; + "Linux arm64"|"Linux aarch64") target="linux-aarch64" ;; + *) target="linux-x86_64" ;; + esac +fi + +echo "Downloading $repo for $target" +release_target_url=$( + curl -s "$release_url" | + grep "browser_download_url" | + grep "$target" | + sed -re 's/.*: "([^"]+)".*/\1/' \ +) + +curl -sL "$release_target_url" | tar xz \ No newline at end of file diff --git a/src/app/sendme/page.mdx b/src/app/sendme/page.mdx index fb633c60..9440e5c1 100644 --- a/src/app/sendme/page.mdx +++ b/src/app/sendme/page.mdx @@ -1,8 +1,4 @@ -import React from 'react' -import Image from 'next/image' -import { - ChatBubbleLeftIcon -} from '@heroicons/react/24/outline' +import SendmePage from '@/components/SendmePage' export const metadata = { title: 'Sendme', @@ -15,112 +11,4 @@ export const sections = [ {title: 'Resources', id: 'resources'}, ] -
-
-
-

Send files

-

For free. No account required.

-
- - -
-
-
-
-

File transfer
doesn't need to be complicated

-

It's like scp without needing to know the IP address.

-
- -
-

Install

-
$ curl -fsSL https://iroh.computer/sendme.sh | sh
-
-
-
- -
-
-
-

USING SENDME:

-
-
-
-
-
-
-
-
-
-

> $ sendme provide ~/great_photos

-

content added

-

run iroh get blobQmFoo...

-
-

1. Setup send

-

pass a file or folder you want to share to sendme. It'll spit out a ticket.

-
-
-
- -
- hey here have some great photos: - blobQmFoo... -
-
-

2. Paste the ticket

-

copy-paste the ticket to your friend.

-
-
-
-
-
-
-
-
-

> $ sendme get blobQmFoo...

-

fetched to my_photos

-
-

3. Download

-

run get to fetch data directly from your friend.

-
-
-
- -
-
-
-
-

Free, for files & folders of any size

-

sendme works by connecting sender and receiver directly, so there's no need to upload to a server, which means no cost!

-
-
-
-

Fast.

-

Sendme can saturate a 4Gbps connection.

-
-
-

Resumable fetching

-

Interrupted downloads pick up where they left off.

-
-
-

Integrity checks

-

Data is automatically verified for correctness on both send and receive.

-
-
-
- -
-
-

Coming Soon

-

Sendme Mobile

-

Send files to your iOS device!

-
-
- -
-

Sendme is built on iroh blobs & connections

-

Just like Dumb pipe, sendme is built on iroh. Sendme uses iroh blobs to send and verfiy your files, and connections to establish direct links between devices for data transfer

-
-
-
-
-
\ No newline at end of file + \ No newline at end of file diff --git a/src/components/SendmePage.jsx b/src/components/SendmePage.jsx new file mode 100644 index 00000000..abc8613f --- /dev/null +++ b/src/components/SendmePage.jsx @@ -0,0 +1,146 @@ +'use client'; + +import React from 'react' +import Image from 'next/image' +import localFont from 'next/font/local' +import clsx from 'clsx' +import { + ChatBubbleLeftIcon, + ClipboardDocumentIcon, + ClipboardDocumentCheckIcon +} from '@heroicons/react/24/outline' +import { Button } from './Button' + +const koulen = localFont({ + src: '../fonts/Koulen-Regular.ttf', + display: 'swap', + variable: '--font-koulen-regular', + weight: '200 900', +}) + +export default function SendmePage() { + const install = `curl -fsSL https://iroh.computer/sendme.sh | sh` + const [copied, setCopied] = React.useState(false) + + const handleCopy = () => { + navigator.clipboard.writeText(install); + setCopied(true); + setTimeout(() => { + setCopied(false); + }, 1300); + } + + return ( +
+
+
+

Send files

+

For free. No account required.

+
+ one computer sending files to another computer through a pipe + +
+
+
+
+

File transfer
doesn't need to be complicated

+

It's like scp without needing to know the IP address. Add some files to sendme, and it will give you a pastable ticket that you can give to anyone who needs your files. Sendme will connect your devices directly & transfer the data without any accounts or configuration.

+
+ +
+

Install

+

Add sendme to your machine using shell:

+ +
+
+
+ +
+
+
+

USING SENDME:

+
+
+
+
+
+
+
+
+
+

{'>'} $ sendme provide ~/great_photos

+

content added

+

run iroh get blobQmFoo...

+
+

1. Setup

+

pass a file or folder you want to share to sendme. It'll spit out a ticket.

+
+
+
+ +
+ hey here have some great photos: + blobQmFoo... +
+
+

2. Paste

+

copy-paste the ticket to your friend.

+
+
+
+
+
+
+
+
+

{'>'} $ sendme get blobQmFoo...

+

fetched to my_photos

+
+

3. Download

+

run get to fetch data directly from your friend.

+
+
+
+ +
+
+
+
+

Free, for files & folders of any size

+

sendme works by connecting sender and receiver directly, so there's no need to upload to a server, which means no cost!

+
+
+
+

Fast

+

Sendme can saturate a 4Gbps connection.

+
+
+

Resumable fetching

+

Interrupted downloads pick up where they left off.

+
+
+

Integrity checks

+

Data is automatically verified for correctness on both send and receive.

+
+
+
+ +
+

Sendme is built on iroh

+

Just like Dumb pipe, sendme is built on iroh. Sendme uses iroh blobs to send and verfiy your files, and connections to establish direct links between devices for data transfer

+ +
+
+
+
+
+ ) +} \ No newline at end of file diff --git a/src/components/icons/Github.jsx b/src/components/icons/Github.jsx index 28b8b970..3565ac22 100644 --- a/src/components/icons/Github.jsx +++ b/src/components/icons/Github.jsx @@ -3,7 +3,7 @@ export function GithubIcon(props) { return ( ) diff --git a/src/fonts/Koulen-Regular.ttf b/src/fonts/Koulen-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1729525e78b32ae875536c62bd8e687f3ee44344 GIT binary patch literal 55724 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 literal 0 HcmV?d00001 diff --git a/tailwind.config.js b/tailwind.config.js index 9c2c4dd3..6a6045ed 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -29,7 +29,8 @@ module.exports = { }, fontFamily: { 'space': ['Space Grotesk', 'sans-serif'], - 'spaceMono': ['Space Mono', 'sans-serif'] + 'spaceMono': ['Space Mono', 'sans-serif'], + 'koulen': 'var(--font-koulen-regular)' }, boxShadow: { glow: '0 0 4px rgb(0 0 0 / 0.1)', From e326f5f14b3c95b138d9930c6ef3effa2861113c Mon Sep 17 00:00:00 2001 From: b5 Date: Wed, 20 Dec 2023 23:17:59 -0500 Subject: [PATCH 3/4] incorporate review --- src/components/GithubStars.jsx | 2 +- src/components/SendmePage.jsx | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/GithubStars.jsx b/src/components/GithubStars.jsx index d7d7bc30..83e6bf90 100644 --- a/src/components/GithubStars.jsx +++ b/src/components/GithubStars.jsx @@ -7,7 +7,7 @@ export default function GithubStars(props) { return ( - 1k + 1.1k ) } \ No newline at end of file diff --git a/src/components/SendmePage.jsx b/src/components/SendmePage.jsx index abc8613f..74c9e7d3 100644 --- a/src/components/SendmePage.jsx +++ b/src/components/SendmePage.jsx @@ -34,8 +34,9 @@ export default function SendmePage() {
-

Send files

-

For free. No account required.

+

New to send files? Try

+

Sendme

+

Unlimited file size. Free. No account required.

one computer sending files to another computer through a pipe @@ -78,7 +79,7 @@ export default function SendmePage() {

{'>'} $ sendme provide ~/great_photos

content added

-

run iroh get blobQmFoo...

+

run sendme get blobQmFoo...

1. Setup

pass a file or folder you want to share to sendme. It'll spit out a ticket.

@@ -102,7 +103,7 @@ export default function SendmePage() {

{'>'} $ sendme get blobQmFoo...

-

fetched to my_photos

+

fetched to great_photos

3. Download

run get to fetch data directly from your friend.

@@ -135,7 +136,7 @@ export default function SendmePage() {

Sendme is built on iroh

-

Just like Dumb pipe, sendme is built on iroh. Sendme uses iroh blobs to send and verfiy your files, and connections to establish direct links between devices for data transfer

+

Just like dumbpipe, sendme is built on iroh. Sendme uses iroh blobs to send and verfiy your files, and connections to establish direct links between devices for data transfer

From 8136654c277eb140fc9319a2613315d1aa4ea5fa Mon Sep 17 00:00:00 2001 From: b5 Date: Thu, 21 Dec 2023 08:28:12 -0500 Subject: [PATCH 4/4] add dumbpipe & sendme links to the footer --- src/components/FooterMarketing.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/FooterMarketing.jsx b/src/components/FooterMarketing.jsx index 06f5bc15..adf265c9 100644 --- a/src/components/FooterMarketing.jsx +++ b/src/components/FooterMarketing.jsx @@ -12,6 +12,8 @@ const navigation = { learn: [ { name: 'Blog', href: '/blog' }, { name: 'Examples', href: '/docs/examples' }, + { name: "dumbpipe", href: 'https://dumbpipe.dev'}, + { name: "sendme", href: '/sendme'}, ], connect: [ { name: 'Discord', href: 'https://iroh.computer/discord' },