import { PrismaClient } from "@prisma/client"; import slugify from "slugify"; const prisma = new PrismaClient(); const CATEGORIES = [ "3D Modeling", "3D Animation", "CAD", "3D Sculpting", "AI Generated Content", "Video", "Photography", "Graphic Design", "Illustration", ]; function slug(s: string) { return slugify(s, { lower: true, strict: true }); } async function main() { console.log("Seeding categories…"); for (let i = 0; i < CATEGORIES.length; i++) { const name = CATEGORIES[i]; await prisma.category.upsert({ where: { slug: slug(name) }, create: { name, slug: slug(name), sortOrder: i }, update: { name, sortOrder: i }, }); } // Convenience slugs for URL filters (/portfolio/3d, /portfolio/ai, etc.) const aliases: Record = { "3d-modeling": "3d", "3d-animation": "animation", "ai-generated-content": "ai", "graphic-design": "design", }; // We keep canonical slugs; PortfolioView can use short names // Seed portfolio views only on a fresh DB. Do not re-create views after the admin deletes them. const viewCount = await prisma.portfolioView.count(); if (viewCount === 0) { console.log("Seeding default portfolio views (empty table)…"); const cats = await prisma.category.findMany(); const bySlug = Object.fromEntries(cats.map((c) => [c.slug, c])); async function createView( name: string, viewSlug: string, description: string, orderedSlugs: string[] ) { const view = await prisma.portfolioView.create({ data: { name, slug: viewSlug, description, showOthers: true }, }); for (let i = 0; i < orderedSlugs.length; i++) { const cat = bySlug[orderedSlugs[i]]; if (!cat) continue; await prisma.portfolioViewCategory.create({ data: { viewId: view.id, categoryId: cat.id, priority: i }, }); } } await createView( "3D", "3d", "All 3D work front and center.", ["3d-modeling", "3d-animation", "3d-sculpting", "cad"] ); await createView("Animation", "animation", "Animation-focused portfolio.", [ "3d-animation", "video", ]); await createView("CAD", "cad", "CAD and technical design.", ["cad", "3d-modeling"]); await createView("AI", "ai", "AI-generated creative work.", [ "ai-generated-content", "illustration", "graphic-design", ]); for (const [canonical, short] of Object.entries(aliases)) { if (short === "3d" || short === "animation" || short === "ai") continue; await createView(bySlug[canonical]?.name ?? short, short, `Filter: ${short}`, [ canonical, ]); } } else { console.log(`Skipping portfolio view seed (${viewCount} existing views).`); } const existingResume = await prisma.resume.findFirst({ where: { isActive: true } }); if (!existingResume) { console.log("Seeding sample resume…"); await prisma.resume.create({ data: { isActive: true, fullName: "J. Martin", title: "3D Artist · Designer · Creative Technologist", email: "contact@jmartgraphix.com", website: "https://jmartgraphix.com", location: "United States", summary: "Creative professional specializing in 3D modeling, CAD, animation, and visual design. Building polished digital experiences and production-ready assets for games, product visualization, and media.", sections: [ { type: "experience", title: "Experience", items: [ { title: "Independent Creative / jmartgraphix", organization: "Freelance", location: "Remote", startDate: "2018", endDate: "Present", description: "Delivered 3D models, animations, CAD designs, and graphic work for clients across game development, product design, and marketing.", highlights: [ "End-to-end 3D pipeline: modeling, sculpting, texturing, rendering", "CAD and product visualization for engineering collaborators", "Motion graphics and short-form video production", ], }, ], }, { type: "skills", title: "Software & Tools", items: [ { group: "3D & CAD", skills: [ "Blender", "Maya", "ZBrush", "SolidWorks", "Fusion 360", "Substance Painter", ], }, { group: "Design & Video", skills: [ "Photoshop", "Illustrator", "After Effects", "Premiere Pro", "DaVinci Resolve", ], }, { group: "Other", skills: ["AI image/video tools", "Git", "Web (HTML/CSS)"], }, ], }, { type: "links", title: "Links", items: [ { label: "Portfolio", url: "https://jmartgraphix.com" }, { label: "ArtStation", url: "https://jmartgraphix.artstation.com/" }, { label: "YouTube", url: "https://www.youtube.com/@samuraijkm" }, { label: "Vimeo", url: "https://vimeo.com/jmartgraphix" }, ], }, ], }, }); } await prisma.siteSetting.upsert({ where: { key: "site" }, create: { key: "site", value: { name: "jmartgraphix", tagline: "Creative Professional Portfolio", about: "I create 3D art, technical design, animation, and visual media — from concept through polished delivery.", social: { artstation: "https://jmartgraphix.artstation.com/", youtube: "https://www.youtube.com/@samuraijkm", vimeo: "https://vimeo.com/jmartgraphix", }, heroTitle: "", heroSubtitle: "3D · Design · Motion · Craft", }, }, update: {}, }); console.log("Seed complete."); } main() .catch((e) => { console.error(e); process.exit(1); }) .finally(() => prisma.$disconnect());