尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證sell scrap baby
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗Skrappily is a free remnant-metal board for machine shops. A shop lists leftover plate, bar, tube, angle, or mixed scrap. Nearby shops search by metal type (6061, 7075, 5052, mild steel, 304, 316, copper, brass, bronze, titanium, and others), form, thickness, length, price, distance from a ZIP code, and whether the seller can deliver. They message the seller in the app. A map shows each shop as a pin. Nothing is charged on the site. A delivery fee or a material-cert note is information for the buyer. Sellers choose buyer pickup or that they can deliver. A future $1 Verified Seller badge is shown from a shop flag and is not for sale yet. Posting and browsing stay free.
Example listings around San Diego are seeded so the board is usable on first run. They are marked Example and are not live inventory.
Requires Node.js 22 or newer.
npm install
npm run dev
Open http://127.0.0.1:3847.
No environment variables are required. Listings are stored in data/skrappily.db (SQLite via libSQL). Uploaded photos go in data/uploads/ and are served from /uploads/....
npm test
npm run lint
npm run build
Delete data/skrappily.db and restart to load the example listings again. Set SEED_EXAMPLE_DATA=false before the first boot if you want an empty board.
The codespace only has the files that are on GitHub. Open the scrapyard repo and confirm you see package.json, app/, and this README. An empty repo, or one that only has GitHub’s starter README, needs this project pushed to main first.
On the repo page, click Code, then the Codespaces tab, then Create codespace on main.
When the editor finishes loading, open the terminal and run:
npm install
npm run dev
Open the Ports tab. Port 3847 shows up once Next.js is ready. Click the globe on that row to open the app.
No environment variables are required. Sign in as [email protected] with password skrappily-demo, or create your own shop.
Stop the codespace from github.com/codespaces when you are done. The free plan counts the hours it stays running.
Every seeded shop uses the password skrappily-demo.
| Shop | ZIP | |
|---|---|---|
| Kearny Mesa Tool & Die | [email protected] | 92111 |
| Mira Mesa Aero Cuts | [email protected] | 92126 |
| Harbor Stainless | [email protected] | 91910 |
| National City Marine Fab | [email protected] | 91950 |
| El Cajon Job Shop | [email protected] | 92020 |
| Santee Weldments | [email protected] | 92071 |
| North County Titanium | [email protected] | 92054 |
| Carlsbad Screw Machine | [email protected] | 92008 |
| Escondido Metals | [email protected] | 92025 |
| Sorrento Plastics | [email protected] | 92121 |
| Lemon Grove Chassis | [email protected] | 91945 |
| Vista Sheet Metal | [email protected] | 92083 |
| Barrio Logan Drops | [email protected] | 92113 |
| Old Town Precision | [email protected] | 92110 |
Sign in as one of those shops to mark an example listing sold or to read a message you sent it. Create your own account for real listings.
Copy .env.example to .env.local only when you need something other than the defaults.
| Variable | Required | Purpose |
|---|---|---|
LIBSQL_URL | On Vercel | libSQL URL. Turso URLs look like libsql://your-db.turso.io. TURSO_DATABASE_URL and DATABASE_URL are aliases. DATABASE_URL must be libsql:// or file:, not Postgres. |
LIBSQL_AUTH_TOKEN | With a remote URL | Database token. TURSO_AUTH_TOKEN is an alias. |
SEED_EXAMPLE_DATA | No | Set to false before the first request to skip the San Diego examples. |
STORAGE_PROVIDER | No | local (default) or blob. |
BLOB_READ_WRITE_TOKEN | For blob photos | Vercel Blob token. If this is set and STORAGE_PROVIDER is empty, photos use Blob. |
When LIBSQL_URL is unset, the app uses file:./data/skrappily.db. A file: URL is also accepted for a different local path.
The app is a Next.js App Router project and stays on the Node.js runtime. The Hobby (free) plan is enough. You still need a remote database because Vercel’s filesystem is ephemeral, so the local SQLite file will not keep listings.
Push this project to a Git host and import it in Vercel.
Create a free Turso database:
turso db create skrappily
turso db show skrappily --url
turso db tokens create skrappily
In the Vercel project, set:
LIBSQL_URL to the libsql:// URLLIBSQL_AUTH_TOKEN to the tokenOptional photos that persist: create a Blob store in the Vercel dashboard (included on the free tier) and set STORAGE_PROVIDER=blob plus BLOB_READ_WRITE_TOKEN. Without Blob, listings still work, but photo upload is refused on Vercel so files are not written to a disk that disappears.
Optional: set SEED_EXAMPLE_DATA=false if the production board should start empty. If you leave it unset, the first request seeds the example San Diego listings into the empty Turso database.
Deploy. npm run build is the build command and Next.js is the framework preset.
Distance search does not call a geocoding API. Centroids for US ZIP codes ship in data/zip-centroids.csv. The map uses Leaflet with OpenStreetMap tiles and does not need an API key. Shop pins sit on the shop ZIP. A pin opens the shop name and active listing count, and links to that shop's page.
Accounts are email plus password. Passwords are hashed with bcrypt. The session cookie is HTTP-only and only the hash of the session token is stored. No magic-link email is sent, so the app does not need an email provider.
“Message seller” writes into the in-app inbox. Reports are stored on the listing. There is no admin console and no payment flow.
data/zip-centroids.csv comes from the GeoNames postal code dataset and is used under CC BY 4.0. See data/ZIP_SOURCE.txt.
Payments are limited to RFQs for now: once an RFQ owner accepts a quote, they
see Pay for this quote with a breakdown (quote price, card processing fee,
total). Checkout uses a Stripe Checkout Session as a destination charge to
the supplier's Connect account (Express dashboard; the platform controls fees
and losses), with application_fee_amount. Suppliers turn on payouts from
Account → Get paid. Orders live at /orders; suppliers mark them shipped
or completed. Webhooks land at /api/stripe/webhook (raw-body signature check,
idempotent via stripe_events).
Fee economics. Stripe charges about 2.9% + 30¢ per card payment, and on a
destination charge that cost comes out of the platform's balance. A small
platform fee alone would lose money on every sale, so by default
(STRIPE_PASS_THROUGH_CARD_FEES=true) the buyer's total is grossed up:
total = ceil((price + 30¢) / (1 − 2.9%)). The supplier receives
price − 1%, and the platform keeps the 1% after Stripe's cut. Example:
a $1,000 quote → buyer pays $1,030.18 ($30.18 card fee), supplier receives
$990.00, Skrappily nets ≈ $10. Invoices and net terms come later.