Ecommerce Template
Next.js·React 등으로 만든 최신 전자상거래 템플릿
기계 공장을 위한 무료 잔여물 보드. 남은 바, 판, 튜브, 드롭을 목록화해 인근 공장이 폐기물 대신 구매하도록 합니다
A free remnant board for machine shops. List leftover bar, plate, tube, and drops so a nearby shop can buy them instead of the scrap bin.
커머스TypeScript · CSSGitHub @jmwilson92온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기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.