@profullstack/builtindie 0.0.0-stage → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/LICENSE +21 -0
  2. package/OpenStack.md +74 -0
  3. package/README.md +63 -2
  4. package/bin/builtindie +3 -0
  5. package/package.json +35 -4
  6. package/public/app.js +35 -0
  7. package/public/favicon.svg +1 -0
  8. package/public/icon-192.png +0 -0
  9. package/public/icon-512.png +0 -0
  10. package/public/icons/openicon.json +574 -0
  11. package/public/icons/svg/apple.svg +1 -0
  12. package/public/icons/svg/arrow-up.svg +1 -0
  13. package/public/icons/svg/bluesky.svg +1 -0
  14. package/public/icons/svg/check.svg +1 -0
  15. package/public/icons/svg/chrome.svg +1 -0
  16. package/public/icons/svg/code.svg +1 -0
  17. package/public/icons/svg/discord.svg +1 -0
  18. package/public/icons/svg/dollar.svg +1 -0
  19. package/public/icons/svg/external-link.svg +1 -0
  20. package/public/icons/svg/github.svg +1 -0
  21. package/public/icons/svg/globe.svg +1 -0
  22. package/public/icons/svg/instagram.svg +1 -0
  23. package/public/icons/svg/layers.svg +1 -0
  24. package/public/icons/svg/link.svg +1 -0
  25. package/public/icons/svg/linkedin.svg +1 -0
  26. package/public/icons/svg/mail.svg +1 -0
  27. package/public/icons/svg/product-hunt.svg +1 -0
  28. package/public/icons/svg/reddit.svg +1 -0
  29. package/public/icons/svg/rocket.svg +1 -0
  30. package/public/icons/svg/search.svg +1 -0
  31. package/public/icons/svg/share.svg +1 -0
  32. package/public/icons/svg/star.svg +1 -0
  33. package/public/icons/svg/tag.svg +1 -0
  34. package/public/icons/svg/telegram.svg +1 -0
  35. package/public/icons/svg/terminal.svg +1 -0
  36. package/public/icons/svg/tiktok.svg +1 -0
  37. package/public/icons/svg/trophy.svg +1 -0
  38. package/public/icons/svg/user.svg +1 -0
  39. package/public/icons/svg/x.svg +1 -0
  40. package/public/icons/svg/youtube.svg +1 -0
  41. package/public/install.sh +44 -0
  42. package/public/manifest.webmanifest +20 -0
  43. package/public/moshpit-root-ca.crt +11 -0
  44. package/public/style.css +162 -0
  45. package/public/sw.js +30 -0
  46. package/src/auth.ts +96 -0
  47. package/src/cli.ts +203 -0
  48. package/src/client.ts +115 -0
  49. package/src/db.ts +412 -0
  50. package/src/fetch.ts +708 -0
  51. package/src/html.ts +525 -0
  52. package/src/icons.ts +56 -0
  53. package/src/mcp.ts +79 -0
  54. package/src/media.ts +160 -0
  55. package/src/ring.ts +86 -0
  56. package/src/server.ts +655 -0
  57. package/src/service.ts +369 -0
  58. package/src/tui.ts +127 -0
  59. package/src/version.ts +1 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Profullstack, Inc. (moshcoder)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/OpenStack.md ADDED
@@ -0,0 +1,74 @@
1
+ # built.indie
2
+
3
+ - **Kind**: product
4
+ - **Web**: https://built.indie.pit.world
5
+ - **Repo**: https://github.com/moshcoder/built.indie
6
+ - **Operator**: https://built.indie.pit.world/.well-known/openprofile.md
7
+ - **License**: MIT
8
+ - **Updated**: 2026-10-19
9
+
10
+ Launch your indie product with one URL: we read the homepage and the LogicSRC files it serves, keep the pictures, and put it on a daily upvote board.
11
+
12
+ ## Languages
13
+
14
+ - TypeScript 5: everything, ES modules
15
+
16
+ ## Runtimes
17
+
18
+ - Bun 1.4: the server, the CLI, the TUI and the MCP server
19
+ - Browser: the PWA (service worker, manifest)
20
+
21
+ ## Interfaces
22
+
23
+ ### Web
24
+
25
+ - Hono 4: server-rendered pages, no client framework
26
+ - public/app.js: votes, copy buttons, progress, service worker
27
+
28
+ ### API
29
+
30
+ - Hono 4: JSON under /api/v1, OpenSite index calls under /api/v1/sites
31
+
32
+ ### CLI
33
+
34
+ - @profullstack/builtindie: `builtindie`
35
+
36
+ ### TUI
37
+
38
+ - @profullstack/hqtui: the board in a terminal
39
+
40
+ ### MCP
41
+
42
+ - @modelcontextprotocol/sdk 1: stdio, zod 3 schemas
43
+
44
+ ## Data
45
+
46
+ - SQLite (bun:sqlite): one file, WAL
47
+ - Files: pictures beside the database, checked by their first bytes
48
+
49
+ ## Services
50
+
51
+ - CoinPay: crypto payments for Featured
52
+ - Resend: sign-in links
53
+ - crawlproof: analytics and ads
54
+ - Headless Chrome: homepage screenshots, run as nobody
55
+ - pit.world relay: the address everyone without Moshpit DNS uses
56
+
57
+ ## Specs
58
+
59
+ - OpenSite 0.1: every product is a record; we are a reader and an index
60
+ - OpenProfile 0.4: products are organizations, makers are people
61
+ - OpenStack.md 0.1: read from products, served about ourselves
62
+ - OpenSaaS 0.1: plans and the cancel page, read from products
63
+ - OpenIcon 0.1: the reference set, a vendored subset
64
+
65
+ ## Hosting
66
+
67
+ - dev2 (bare metal): systemd unit built-indie, nginx, OpenInstall bin/install.sh
68
+ - Moshpit name built.indie, certificate from the Moshpit registry
69
+
70
+ ## Never
71
+
72
+ - No Stripe: payments are CoinPay
73
+ - No client-side framework, no bundler
74
+ - No secrets in .env files: app.env is written from the vault
package/README.md CHANGED
@@ -1,3 +1,64 @@
1
- # Temporary Holding Version
1
+ # built.indie
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Launch your indie product with one URL. **https://built.indie.pit.world** (on Moshpit DNS: https://built.indie)
4
+
5
+ Paste a URL and built.indie reads the homepage the way a careful person would: the name, tagline and description, the logo, the card image, screenshots from the page plus one we take ourselves with headless Chrome, YouTube/Vimeo/Loom/mp4 videos, social accounts, `llms.txt`, the web manifest and JSON-LD. It also reads the [LogicSRC](https://logicsrc.com/specs) files a site may serve about itself:
6
+
7
+ | file | spec | we show |
8
+ | --- | --- | --- |
9
+ | `/.well-known/opensite.json` | [OpenSite](https://logicsrc.com/docs/opensite) | what the site says it is; wins over what we scrape; `index.allow: false` is honoured |
10
+ | `/.well-known/openprofile.md` | [OpenProfile](https://logicsrc.com/docs/openprofile) | the company (`Kind: organization`) and its accounts |
11
+ | `/.well-known/openstack.md` | [OpenStack.md](https://logicsrc.com/docs/openstack) | "Built with" |
12
+ | `/.well-known/opensaas.json` | [OpenSaaS](https://logicsrc.com/docs/opensaas) | plans, trial, and the cancel page |
13
+ | `/.well-known/openicon.json` | [OpenIcon](https://logicsrc.com/docs/openicon) | that it publishes an icon set |
14
+
15
+ Then it goes on today's board. People upvote (one per visitor). The board resets at midnight UTC; yesterday's winners get "#1 Product of the day" on their page and badge.
16
+
17
+ **Free to launch, no account.** Anyone can launch any site. To edit a listing, sign in (an emailed link) and **claim** it by adding a DNS TXT record, `_built-indie.<domain>` → `built-indie-verify=<token>`. A signed-in submitter can edit until the owner claims it.
18
+
19
+ Viral bits: a live badge with the upvote count (`/badge/<slug>.svg`) that turns a link back into a followed link and a ✓ once we see it on the homepage, share buttons, an OG card per product, RSS, and an optional crypto-paid **Featured** slot (CoinPay).
20
+
21
+ Every product is published back as an OpenSite record (`/p/<slug>/opensite.json`) and an OpenProfile (`/p/<slug>/openprofile.md`); makers are OpenProfiles too (`/makers/<id>/openprofile.md`). Icons are the [OpenIcon](https://github.com/profullstack/openicon) reference set.
22
+
23
+ ## Surfaces
24
+
25
+ ```sh
26
+ curl -fsSL https://built.indie.pit.world/install.sh | sh
27
+
28
+ builtindie # TUI: today's board, ←/→ boards, v upvote, l launch
29
+ builtindie launch yourproduct.com
30
+ builtindie top week
31
+ builtindie show linear
32
+ builtindie vote linear
33
+ builtindie preview any.site --json
34
+ BUILTINDIE_KEY=bi_… builtindie claim linear # prints the TXT record, then checks it
35
+ BUILTINDIE_KEY=bi_… builtindie edit linear --tagline "…"
36
+
37
+ claude mcp add builtindie -- bunx @profullstack/builtindie mcp
38
+ ```
39
+
40
+ The web app is a PWA (manifest + service worker). The JSON API is under `/api/v1` and documented at `/help`; the OpenSite index calls are `GET /api/v1/sites?url=` and `POST /api/v1/sites`.
41
+
42
+ ## Run your own
43
+
44
+ ```sh
45
+ bun install
46
+ BUILTINDIE_KEY=$(openssl rand -hex 32) bun src/server.ts # http://127.0.0.1:8798
47
+ bun test
48
+ ```
49
+
50
+ | env | |
51
+ | --- | --- |
52
+ | `BUILTINDIE_KEY` | required: keys vote hashes and claim tokens |
53
+ | `BUILTINDIE_ORIGIN` | public address (default https://built.indie.pit.world) |
54
+ | `BUILTINDIE_DATA` | where the database and pictures live (default ~/.local/share/built-indie) |
55
+ | `BUILTINDIE_ADMIN_KEY` | bearer that may take a listing down |
56
+ | `RESEND_API_KEY`, `MAIL_FROM` | sign-in mail; without them the link is logged |
57
+ | `COINPAY_API_KEY`, `COINPAY_BUSINESS_ID`, `COINPAY_WEBHOOK_SECRET` | Featured payments |
58
+ | `FEATURE_USD`, `FEATURE_DAYS` | price and length of Featured (19, 7) |
59
+ | `BUILTINDIE_CHROME` | Chrome path, or `off`; `BUILTINDIE_SCREENSHOTS=off` skips screenshots |
60
+ | `CRAWLPROOF_SITE`, `CRAWLPROOF_AD_SLOT` | analytics and ads; `off` turns either off |
61
+
62
+ Production runs on dev2 under `bin/install.sh` (OpenInstall); every merge to main deploys. See `OpenStack.md`.
63
+
64
+ MIT. Part of the [Moshpit ring](https://pit.world/ring).
package/bin/builtindie ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bun
2
+ import { main } from '../src/cli.ts'
3
+ process.exitCode = await main()
package/package.json CHANGED
@@ -1,6 +1,37 @@
1
1
  {
2
2
  "name": "@profullstack/builtindie",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.3",
4
+ "description": "built.indie: launch your indie product with one URL. We fetch the logo, screenshots, videos, llms.txt, OpenSite and OpenProfile from your homepage; people upvote; you get a badge. Web (PWA), API, CLI, TUI and MCP.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "homepage": "https://built.indie.pit.world",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/moshcoder/built.indie.git"
11
+ },
12
+ "bin": {
13
+ "builtindie": "bin/builtindie"
14
+ },
15
+ "files": ["bin/builtindie", "src", "public", "OpenStack.md", "README.md", "LICENSE"],
16
+ "engines": {
17
+ "bun": ">=1.1"
18
+ },
19
+ "scripts": {
20
+ "start": "bun src/server.ts",
21
+ "dev": "bun --watch src/server.ts",
22
+ "test": "bun test",
23
+ "typecheck": "tsc --noEmit"
24
+ },
25
+ "dependencies": {
26
+ "@modelcontextprotocol/sdk": "^1.17.0",
27
+ "@profullstack/coinpay-onboard": "^0.1.1",
28
+ "@profullstack/hqtui": "^0.10.3",
29
+ "@profullstack/openprofile": "^0.2.0",
30
+ "hono": "^4.13.13",
31
+ "zod": "^3.25.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/bun": "^1.4.3",
35
+ "typescript": "^7.0.2"
36
+ }
37
+ }
package/public/app.js ADDED
@@ -0,0 +1,35 @@
1
+ // built.indie: vote without a page load, copy buttons, progress while we read a site, the service worker.
2
+ document.addEventListener('click', async (e) => {
3
+ const copy = e.target.closest('[data-copy]')
4
+ if (copy) {
5
+ e.preventDefault()
6
+ navigator.clipboard?.writeText(copy.dataset.copy).then(() => {
7
+ const was = copy.textContent
8
+ copy.textContent = 'Copied'
9
+ setTimeout(() => { copy.textContent = was }, 1500)
10
+ })
11
+ return
12
+ }
13
+ const vote = e.target.closest('[data-vote]')
14
+ if (!vote) return
15
+ e.preventDefault()
16
+ if (vote.classList.contains('voted')) return
17
+ vote.classList.add('voted', 'bump')
18
+ const count = vote.querySelector('.count')
19
+ count.textContent = String(Number(count.textContent) + 1)
20
+ try {
21
+ const r = await fetch('/p/' + encodeURIComponent(vote.dataset.vote) + '/vote', { method: 'POST', headers: { accept: 'application/json' } })
22
+ if (r.ok) count.textContent = String((await r.json()).votes)
23
+ } catch {}
24
+ })
25
+ document.addEventListener('submit', (e) => {
26
+ const form = e.target
27
+ if (form.dataset.confirm && !confirm(form.dataset.confirm)) return e.preventDefault()
28
+ if (!form.dataset.busy || form.classList.contains('busy')) return
29
+ form.classList.add('busy')
30
+ const note = document.createElement('p')
31
+ note.className = 'busy-note'
32
+ note.textContent = form.dataset.busy
33
+ form.append(note)
34
+ })
35
+ if ('serviceWorker' in navigator) navigator.serviceWorker.register('/sw.js').catch(() => {})
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" rx="14" fill="#0b0a10"/><path d="M32 9 11 35h14v20h14V35h14z" fill="#ff5c39"/></svg>
Binary file
Binary file