Before/after photos, completed project highlights, public-facing portfolio showcase, and performance analytics
Showcase your best work to attract homeowners and win more bids
Get a free estimate from Mike Johnson Contracting
General Renovation
Plumbing
Carpentry
contractorPortfolio — title, description, category, photos[], beforePhotos[], afterPhotos[], projectCost, completionDate, jobId, isPublic, displayOrdercontractorProfile — avatar, bio, services[], serviceArea, ratingcontractorUsers — auth identity, name, email, phonejobs — linked via jobId for completed project referencesuseQuery(api.contractor.portfolio.list) — paginated portfolio items by contractoruseQuery(api.contractor.portfolio.get) — single item detailuseQuery(api.contractor.portfolio.getStats) — totalItems, publicItems, categories, totalPhotosuseContractorProjects() — completed jobs for Projects tabuseContractorActiveJobs() — in-progress jobsuseMyBids() — pending/lost bidsapi.contractor.portfolio.add — create portfolio item with photos, before/after, categoryapi.contractor.portfolio.update — edit title, description, photos, categoryapi.contractor.portfolio.remove — delete item (rate-limited)api.contractor.portfolio.reorder — update displayOrderapi.features.storage.generateUploadUrl — get Convex upload URLapi.features.storage.storeFile — store reference, return URL