-[["Map",1,2,9,10],"meta::meta",["Map",3,4,5,6,7,8],"astro-version","5.1.2","content-config-digest","35234a24d48863ab","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"site\":\"https://johanwulf.github.io\",\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[]},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":\"shiki\",\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":true,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"responsiveImages\":false},\"legacy\":{\"collections\":false}}","blog",["Map",11,12,27,28],"migrating-to-astro",{"id":11,"data":13,"body":22,"filePath":23,"digest":24,"legacyId":25,"deferredRender":26},{"title":14,"date":15,"tags":16,"description":21},"Migrating to Astro",["Date","2024-06-08T00:00:00.000Z"],[17,18,19,20],"astro","web","migration","mdx","How I migrated my personal website from Vite + React to Astro","After struggling with complex MDX configurations and build tool conflicts, I decided to migrate my personal website to Astro.\n\n## The Problem\n\nI started with a Vite + React + MDX setup, which seemed like a good idea at first. But as I added more features, the complexity grew:\n\n- PostCSS and Tailwind CSS v4 conflicts\n- Complex MDX configuration with multiple plugins\n- Manual routing for blog posts\n- Heavy JavaScript bundle for a mostly static site\n\n## Enter Astro\n\nAstro is a modern static site generator that's perfect for content-focused websites. Here's what sold me:\n\n### Zero JavaScript by Default\n\nUnlike traditional React apps, Astro ships zero JavaScript by default. Your pages are fully rendered at build time.\n\n### Built-in MDX Support\n\n```js\n// astro.config.mjs\nimport mdx from '@astrojs/mdx'\n\nexport default defineConfig({\n integrations: [mdx()]\n})\n```\n\n### Content Collections\n\nAstro's content collections provide type-safe content management:\n\n```typescript\nimport { defineCollection, z } from 'astro:content'\n\nconst blogCollection = defineCollection({\n type: 'content',\n schema: z.object({\n title: z.string(),\n date: z.coerce.date(),\n tags: z.array(z.string()),\n description: z.string().optional(),\n }),\n})\n```\n\n## The Migration Process\n\nThe migration was surprisingly smooth:\n\n1. **Created Astro project structure**\n - Pages go in `src/pages/`\n - Layouts in `src/layouts/`\n - Blog posts in `src/content/blog/`\n\n2. **Converted React components to Astro**\n - Most components became `.astro` files\n - Kept React only for interactive components\n\n## The Results\n\nThe page you are looking at!\n\n## Code Example\n\nHere's how simple a blog post page is in Astro:\n\n```astro\n---\nimport BaseLayout from '../../layouts/BaseLayout.astro'\nimport { getCollection } from 'astro:content'\n\nexport async function getStaticPaths() {\n const posts = await getCollection('blog')\n return posts.map(post => ({\n params: { slug: post.slug },\n props: { post },\n }))\n}\n\nconst { post } = Astro.props\nconst { Content } = await post.render()\n---\n\n\u003CBaseLayout title={post.data.title}>\n \u003Carticle>\n \u003Ch1>{post.data.title}\u003C/h1>\n \u003CContent />\n \u003C/article>\n\u003C/BaseLayout>\n```","src/content/blog/migrating-to-astro.mdx","5c696a405a031b3c","migrating-to-astro.mdx",true,"building-shadecn",{"id":27,"data":29,"body":39,"filePath":40,"digest":41,"legacyId":42,"deferredRender":26},{"title":30,"date":31,"tags":32,"description":38},"Building Shadecn - A shadcn Theme-Aware SVG Tool",["Date","2024-12-08T00:00:00.000Z"],[33,34,35,36,37],"react","shadcn","svg","tools","typescript","How I built a tool to make SVGs work seamlessly with shadcn themes","I love using unDraw illustrations in my projects, but there was always this annoying problem: their colors never matched my shadcn themes. You'd grab a beautiful illustration, paste it in, and it would clash horribly with your carefully crafted design system.\n\nSo I built [Shadecn](https://github.com/johanwulf/shadecn) to fix exactly this problem (hehe, see what I did there?).\n\n## The Problem\n\nWhen you export SVGs from Figma or other design tools, you get something like this:\n\n```jsx\n\u003Csvg fill=\"#8b5cf6\" stroke=\"#3b82f6\">\n \u003Cpath d=\"...\" />\n\u003C/svg>\n```\n\nThose hex colors are baked in. They don't respond to theme changes, and they probably don't match your design system anyway.\n\n## The Solution\n\nShadecn lets you import your shadcn theme CSS and map those hard-coded colors to your theme variables. Instead of `fill=\"#8b5cf6\"`, you get `fill=\"hsl(var(--primary))\"`.\n\nHere's how it works:\n\n1. Paste your SVG\n2. Import your shadcn theme config (the CSS with all those OKLCH colors)\n3. Map which SVG colors should use which theme colors\n4. Export a React component that adapts to your theme\n\n## Why Themes Are Better Than Manual Color Changes\n\nBefore, you'd have to manually change each color in your SVG editor or code, hoping it looked decent in both light and dark modes. With theme integration, your SVGs automatically adapt to theme changes - no more broken designs when users switch themes.\n\n## Tech Stack\n\nBuilt with React, TypeScript, and of course shadcn/ui components. Using Tailwind CSS for styling and Vite for the build process. The color conversion magic happens with culori.\n\nIt's live at [wulf.gg/shadecn](https://wulf.gg/shadecn) and the code is on [GitHub](https://github.com/johanwulf/shadecn).\n\n## Why I Built This\n\nHonestly, I just got tired of manually editing SVG colors every time I wanted to use an icon in a project. Now I can paste an SVG, map it to my theme, and get a component that just works everywhere.\n\nPlus, the name was too good to pass up.","src/content/blog/building-shadecn.mdx","17ee70fed56330c4","building-shadecn.mdx"]
0 commit comments