Bygga
제품명을 박스에 입력하면 Bygga가 3D로 모든 조립 단계와 부품·스크류·도구를 보여주고 음성으로 안내합니다
저장소 정보는 아직 수집하지 않았습니다.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A booking marketplace for verified vehicle rentals (motorcycles, scooters, self-drive cars, self-drive SUVs) in Manali, Himachal Pradesh. Built with Next.js 16 (App Router), Drizzle ORM, and a Neon Postgres database.
This is an MVP implementation of the full specification in the project brief. See
docs/known-limitations.md for what is not yet production-ready,
and docs/compliance-register.md for legal/regulatory open items.
docs/test-report.md records what was actually run and its results.
drizzle-orm + @neondatabase/serverlessrender prop, not asChild)sessions table) — no third-party auth providervitest 5 + vite 8's config loader need
require(esm) support, stable since Node 22.12). The app itself (next dev/next build/next start)
runs fine on Node ≥ 20.18, but this project was developed and primarily tested in an
environment where the system Node was 20.16 — too old for npm test. If you hit
ERR_REQUIRE_ESM or SyntaxError: ... does not provide an export named 'isAgent' running tests,
upgrade Node; there is no workaround in package.json for this, it's a real Node-version floor.pg_version: 18 and gen_random_uuid().npm install
cp .env.example .env.local # fill in DATABASE_URL at minimum — see below
npm run db:migrate # applies drizzle/*.sql, including the booking-overlap guard
npm run db:seed # creates an admin user, a demo customer, 2 demo partners, 5 vehicles
npm run dev
neon.tech → New Project)..env.local as DATABASE_URL.npm run db:migrate runs everything in drizzle/, in order:
0000_*.sql — generated from src/db/schema/*.ts via drizzle-kit generate0001_booking_overlap_guard.sql — hand-written, not generated. It adds a
btree_gist-backed, partial EXCLUDE constraint on bookings(vehicle_id, tstzrange(starts_at, ends_at)),
scoped to the statuses that occupy a vehicle's calendar (see
src/server/services/availability.ts#OCCUPYING_STATUSES — keep the two in sync if you change
either). This is the actual mechanism that makes double-booking impossible, verified under
real concurrency in tests/booking-flow.integration.test.ts. Because drizzle-kit can't
express EXCLUDE constraints, this migration is tracked in drizzle/meta/_journal.json
with a duplicated snapshot (0001_snapshot.json = a copy of 0000_snapshot.json), so future
drizzle-kit generate runs continue to work for ordinary schema changes.src/db/schema/*.ts, run npm run db:generate to create a new numbered
migration, then npm run db:migrate.npm run db:studio opens Drizzle Studio against the same DATABASE_URL.npm run db:seed creates a super_admin user from ADMIN_BOOTSTRAP_EMAIL /
ADMIN_BOOTSTRAP_PASSWORD in .env.local (defaults: [email protected] /
ChangeMe123! if unset). Change this password immediately in a real deployment — the seed
script is meant for development, not for provisioning a production admin account. For
production, insert the first admin directly via SQL with a properly generated bcrypt hash, or
build a one-time CLI bootstrap script before going live (not included here).
The seed script also creates:
[email protected] / Passw0rd!123[email protected], [email protected], both Passw0rd!123The payment integration is a provider interface (src/server/services/paymentProvider.ts) with
two implementations:
RAZORPAY_KEY_ID / RAZORPAY_KEY_SECRET /
RAZORPAY_WEBHOOK_SECRET are not all set). Checkout shows explicit "Simulate: Pay now
(success)" / "Simulate: Payment fails" buttons — nothing here is presented as a real payment.
/api/payments/sandbox-confirm only responds while the sandbox adapter is active; it 404s the
instant real keys are configured, so it can never be hit in a real-money deployment by mistake.orders.create on the platform's own merchant
account; it does not use Razorpay Route/split-settlement, which needs its own marketplace
onboarding and KYC with Razorpay that this project has not gone through. Partner payout stays an
internal ledger entry (partner_ledger_entries) rather than an automatic transfer — see
docs/known-limitations.md.To go live:
RAZORPAY_KEY_ID, RAZORPAY_KEY_SECRET, RAZORPAY_WEBHOOK_SECRET, NEXT_PUBLIC_RAZORPAY_KEY_ID.https://<your-domain>/api/payments/webhook for at least
payment.captured and payment.failed events.Checkout.js with the order from
createPaymentOrderAction (the current sandbox UI's "pay now" buttons are replaced by that
flow — see the isSandbox branch in src/components/checkout/CheckoutPanel.tsx).Not implemented. partner_documents and vehicle_documents tables exist in the schema with a
file_key column, but there is no upload UI or Vercel Blob wiring yet — see
docs/known-limitations.md. BLOB_READ_WRITE_TOKEN is reserved in .env.example for this.
Not implemented. The notifications table exists; nothing currently writes to it or calls an
email/SMS provider. RESEND_API_KEY is reserved in .env.example.
npm test # vitest run — needs Node >=22.12, see "Requirements"
npm run build # production build + typecheck
npm run lint # eslint
tests/pricing.test.ts is pure unit tests for the pricing engine (no database).
tests/booking-flow.integration.test.ts runs against the real database in DATABASE_URL —
it creates its own test partner/vehicles/customers, exercises hold creation, a genuine concurrent
double-booking race (Promise.allSettled on two simultaneous holds for the same slot), payment
capture + idempotent webhook replay, ledger posting, and cancellation refund math, then deletes
everything it created in afterAll. See docs/test-report.md for the actual run output.
vercel link, then vercel env add for every variable in .env.example (or vercel env pull
after setting them in the dashboard).NEXT_PUBLIC_APP_URL to the real deployment URL (used in the sitemap and for absolute links).npm run db:migrate against the production DATABASE_URL as a one-off step before the
first deploy (it is not run automatically on deploy in this setup).vercel deploy --prod.next build) was verified locally; see docs/test-report.md.Standard Vercel instant-rollback to a previous deployment. The one thing rollback does not
undo is a database migration — drizzle/0001_booking_overlap_guard.sql added a constraint, which
would need its own down-migration (not written) if you needed to revert it after data relying on
it existed.
*_paise columns), never floats.Asia/Kolkata (no DST), handled with a fixed +05:30
offset rather than a timezone library — see src/lib/format.ts and the IST-parsing comments in
src/server/actions/booking.ts and src/components/vehicles/VehicleResultsPage.tsx.src/server/services/bookingStateMachine.ts is the only place
bookings.status is allowed to change from application code; it enforces the transition table
and writes an immutable booking_status_events row for every change. Admins can force an
off-table transition, but only with a reason, which gets logged as "admin override".src/server/services/pricing.ts, and snapshotted
into booking_price_snapshots at hold-creation time — a later edit to a vehicle's price never
changes an existing booking's agreed total.src/lib/auth.ts#requireRole() is called at the top of every protected
Server Action and page — not just gated by src/proxy.ts, which only does a coarse
cookie-presence redirect before a protected page renders (see the comment in proxy.ts for why
that's intentionally not the real security boundary).