Agree on the partnership before you commit to it
파트너와 실제 합의 내용을 확인하고 각자 답변을 비교해 차이를 파악한 뒤 변호사에게 전달할 공동 요약을 작성합니다
SwiftScope는 현장 중심 소프트웨어로 1~10인 팀이 바로 견적을 작성·전송하고, 주택 소유자는 지역 장인에게 무료 견적을 받습니다
Quoting software built site-first for trade teams of 1-10. Scope, quote and send before you leave the driveway. Homeowners get free quotes from local tradies.
비즈니스TypeScript · PLpgSQLGitHub @Brencovered온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗AU trade quoting SaaS: build a live quote on site, send it, win the job, run the crew day, push a draft invoice to Xero.
Do not treat supabase/schema.sql as the full live schema. Production evolves through dated files in supabase/migrations/ (apply in order on new environments).
schema.sql is a historical bootstrap snapshot only. Prefer:
If you must bootstrap from SQL editor, run migrations after any base schema, then verify with the latest migration timestamps.
supabase/migrations/ (see above).env.example to .env.local and fill in Supabase keysnpm install && npm run devSign up at resend.com, verify a sending domain, add RESEND_API_KEY and RESEND_FROM_EMAIL. Without these, save still works; send fails with a clear error.
Register a developer app at developer.xero.com. Redirect URI: <deployed-url>/api/xero/callback. Set XERO_CLIENT_ID, XERO_CLIENT_SECRET, XERO_REDIRECT_URI.
Each business connects their own org from Settings. On quote accept, SwiftScope pushes a draft invoice (scope lines when available, otherwise the quote total). Payment status does not sync back from Xero yet - mark jobs paid in SwiftScope when money clears. Variations do not auto-update the Xero invoice yet.
$45/mo or annual (~2 months free), unlimited users, 7-day free trial, no per-seat pricing.
STRIPE_PRICE_MONTHLY, STRIPE_PRICE_ANNUAL, STRIPE_SECRET_KEY/api/stripe/webhook for subscription + checkout events → STRIPE_WEBHOOK_SECRETSUPABASE_SERVICE_ROLE_KEY for webhook writesNEXT_PUBLIC_APP_URL for Checkout redirectsAccess is gated in middleware.ts via trial/subscription status (lib/requireActiveAccess.ts).
npm run dev
npm run build
npm run lint
npm test # vitest unit tests (quote grouping, Xero line builder, trade normalize)
npm run directory:merge # dry-run duplicate plan; add -- --apply to write
npm run directory:abn # free ABN ingest + enrich + MX/ABN verify (local)
npm run directory:verify # re-check ABN status and email MX only
directory_listing feeds SEO pages and outreach. Phone numbers are stored as E.164 (+61…) in phone_e164, websites as a bare hostname in website_domain, and ABNs as 11 digits. Shared call-centre numbers (13 / 1300 / 1800 / 1900) and directory hosts (Facebook, Yellow Pages, supplier sites) are not used as unique identity.
Apply order on an existing database (do this yourself; nothing in CI mutates production):
supabase/migrations/20261021120000_directory_listing_identity.sql. It adds abn, phone_e164, website_domain, verified_at, verification_source, email_valid, and the shared-key flags. It also relabels historical source = 'scraper' rows that have a place_id to google_places. Deploy the app only after this migration: outreach export and claim-invite select email_valid.npx tsx scripts/merge-directory-duplicates.ts (or npm run directory:merge). Read the MERGE, SUPPRESS, and REVIEW lines.npx tsx scripts/merge-directory-duplicates.ts --apply. Same-suburb rows that are the same business are merged (claimed or richer row wins; the loser is snapshotted in directory_listing_merge_log). Different businesses that share a phone or domain keep both rows; the extra row drops the normalised key so the unique index can exist. The displayed phone and website stay. A group with two claimed profiles is left for a person to resolve.supabase/migrations/20261021130000_directory_listing_unique_identity.sql. It refuses to create the unique indexes while any duplicate phone, domain, or ABN group remains in one suburb.Secrets for the weekly GitHub Action .github/workflows/abn-directory.yml (Settings → Secrets and variables → Actions). Do not commit values.
| Name | Where |
|---|---|
SUPABASE_URL | same as NEXT_PUBLIC_SUPABASE_URL |
SUPABASE_SERVICE_ROLE_KEY | Supabase → Project Settings → API |
ABN_LOOKUP_GUID | free registration at https://abr.business.gov.au/Tools/WebServices |
Optional variables: ABN_ENRICH_LIMIT (default 800), DIRECTORY_VERIFY_LIMIT (default 2000). The workflow runs Sundays at 16:00 UTC, or on demand with phase all, ingest, enrich, or verify. It downloads each ABR zip once, stream-parses it, bulk-inserts trade candidates, guesses websites in parallel, then re-checks ABNs (ABN Lookup) and email DNS MX records. It never sends email and it deletes GOOGLE_PLACES_API_KEY from the job environment before it starts. Google Places stays on the manual admin scrape, directory-page scrape, and listing-create screens. The paused expand-directory cron stays out of vercel.json.
ABN bulk ingest from the admin UI returns 409 and points at this workflow. A small enrich batch can still be started from the admin screen; that path does not call Google.
Push to GitHub, import in Vercel, set the env vars above. Standard Next.js app.