{"_id":"@crashnaut/sveltekit-firebase-blog","_rev":"3-848f3f270401536fc74d5f1e5c84631c","name":"@crashnaut/sveltekit-firebase-blog","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"name":"@crashnaut/sveltekit-firebase-blog","version":"1.0.0","keywords":["svelte","sveltekit","blog","firebase","comments","cms","typescript"],"author":{"name":"Crashnaut"},"license":"MIT","_id":"@crashnaut/sveltekit-firebase-blog@1.0.0","maintainers":[{"name":"crashnaut","email":"mikesell404@gmail.com"}],"homepage":"https://github.com/crashnaut/sveltekit-firebase-blog#readme","bugs":{"url":"https://github.com/crashnaut/sveltekit-firebase-blog/issues"},"bin":{"blog-manager":"bin/blog-manager.js","migrate-blogs":"bin/migrate-blogs.js"},"dist":{"shasum":"a4c7b21ed86e62c4d5a19876cb32d7a2909d28e8","tarball":"https://registry.npmjs.org/@crashnaut/sveltekit-firebase-blog/-/sveltekit-firebase-blog-1.0.0.tgz","fileCount":40,"integrity":"sha512-9sqe/CDKwSd6yO+bxH1mUEvMqsmDrSJx3W61nCM2QdDURmnM7vc5sA26bXYY0xgSL6YdxZ/a8TMweAXFH2qWtw==","signatures":[{"sig":"MEYCIQCGLADBCx0HexkQHHl3WzKlYm4mIrlIDcFNANAHSqOc1wIhAO6eFF3RRnWgR2yKHLrwfBMK5Ms8da6aimcbHtyhTltH","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":86311},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","svelte":"./dist/index.js"},"./types":{"types":"./dist/types/index.d.ts","default":"./dist/types/index.js"},"./utils":{"types":"./dist/utils/index.d.ts","default":"./dist/utils/index.js"},"./stores":{"types":"./dist/stores/index.d.ts","default":"./dist/stores/index.js"},"./firebase":{"types":"./dist/firebase/index.d.ts","default":"./dist/firebase/index.js"},"./components":{"types":"./dist/components/index.d.ts","svelte":"./dist/components/index.js"}},"scripts":{"dev":"vite dev","lint":"prettier --check . && eslint .","build":"vite build && npm run package","check":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json","format":"prettier --write .","package":"svelte-kit sync && svelte-package && publint","preview":"vite preview","check:watch":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch","prepublishOnly":"npm run package"},"_npmUser":{"name":"crashnaut","email":"mikesell404@gmail.com"},"repository":{"url":"git+https://github.com/crashnaut/sveltekit-firebase-blog.git","type":"git"},"_npmVersion":"10.9.2","description":"A comprehensive SvelteKit blog system with Firebase backend, comments, likes, and admin interface","directories":{},"_nodeVersion":"22.11.0","dependencies":{"marked":"^9.0.0","inquirer":"^9.0.0","gray-matter":"^4.0.3"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^5.0.11","tslib":"^2.4.1","eslint":"^9.0.0","svelte":"^4.2.7","globals":"^15.0.0","publint":"^0.1.9","prettier":"^3.1.1","typescript":"^5.0.0","svelte-check":"^3.6.0","@sveltejs/kit":"^2.0.0","@types/eslint":"^9.6.0","@types/inquirer":"^9.0.8","@sveltejs/package":"^2.0.0","typescript-eslint":"^8.0.0","eslint-plugin-svelte":"^2.36.0","@sveltejs/adapter-auto":"^3.0.0","eslint-config-prettier":"^9.1.0","prettier-plugin-svelte":"^3.1.2","@sveltejs/vite-plugin-svelte":"^3.0.0"},"peerDependencies":{"svelte":"^4.0.0","firebase":"^10.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sveltekit-firebase-blog_1.0.0_1749416867949_0.5935147051440322","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@crashnaut/sveltekit-firebase-blog","version":"1.0.1","keywords":["svelte","sveltekit","blog","firebase","comments","cms","typescript"],"author":{"name":"Crashnaut"},"license":"MIT","_id":"@crashnaut/sveltekit-firebase-blog@1.0.1","maintainers":[{"name":"crashnaut","email":"mikesell404@gmail.com"}],"homepage":"https://github.com/crashnaut/sveltekit-firebase-blog#readme","bugs":{"url":"https://github.com/crashnaut/sveltekit-firebase-blog/issues"},"bin":{"blog-manager":"bin/blog-manager.js","migrate-blogs":"bin/migrate-blogs.js"},"dist":{"shasum":"4847cdbce7da66e4464602ba6cbb8888999aecbb","tarball":"https://registry.npmjs.org/@crashnaut/sveltekit-firebase-blog/-/sveltekit-firebase-blog-1.0.1.tgz","fileCount":42,"integrity":"sha512-IcXE1SMBvDryvNc2qLtmX8zkc7LS2VQmZGt6W5ugz9Z/wAoWmPqzZlYwCKa6YjZcFxy9x8ehfeWS1L2ybffayA==","signatures":[{"sig":"MEUCIQDYabfpYxBvQ5rtc3pdSRMvheySHZ5xzZ+UwDDysed9+wIgenISr9PfUSHDGfGxBo3nReCkfm9xDuAgR7jAZLgqlXQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":114995},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","svelte":"./dist/index.js"},"./types":{"types":"./dist/types/index.d.ts","default":"./dist/types/index.js"},"./utils":{"types":"./dist/utils/index.d.ts","default":"./dist/utils/index.js"},"./stores":{"types":"./dist/stores/index.d.ts","default":"./dist/stores/index.js"},"./firebase":{"types":"./dist/firebase/index.d.ts","default":"./dist/firebase/index.js"},"./components":{"types":"./dist/components/index.d.ts","svelte":"./dist/components/index.js"}},"gitHead":"31e975b1d43d8577e42512c3842f6e83ba3c2a96","scripts":{"dev":"vite dev","lint":"prettier --check . && eslint .","build":"vite build && npm run package","check":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json","format":"prettier --write .","package":"svelte-kit sync && svelte-package && publint","preview":"vite preview","check:watch":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch","prepublishOnly":"npm run package"},"_npmUser":{"name":"crashnaut","email":"mikesell404@gmail.com"},"repository":{"url":"git+https://github.com/crashnaut/sveltekit-firebase-blog.git","type":"git"},"_npmVersion":"10.9.2","description":"A comprehensive SvelteKit blog system with Firebase backend, comments, likes, and admin interface","directories":{},"_nodeVersion":"22.11.0","dependencies":{"marked":"^9.0.0","inquirer":"^9.0.0","gray-matter":"^4.0.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^5.0.11","tslib":"^2.4.1","eslint":"^9.0.0","svelte":"^4.2.7","globals":"^15.0.0","publint":"^0.1.9","prettier":"^3.1.1","typescript":"^5.0.0","svelte-check":"^3.6.0","@sveltejs/kit":"^2.0.0","@types/eslint":"^9.6.0","@types/inquirer":"^9.0.8","@sveltejs/package":"^2.0.0","typescript-eslint":"^8.0.0","eslint-plugin-svelte":"^2.36.0","@sveltejs/adapter-auto":"^3.0.0","eslint-config-prettier":"^9.1.0","prettier-plugin-svelte":"^3.1.2","@sveltejs/vite-plugin-svelte":"^3.0.0"},"peerDependencies":{"svelte":"^4.0.0","firebase":"^10.0.0","tailwindcss":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sveltekit-firebase-blog_1.0.1_1749599325076_0.5885117924128056","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@crashnaut/sveltekit-firebase-blog","version":"1.0.2","description":"A comprehensive SvelteKit blog system with Firebase backend, comments, likes, and admin interface","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","svelte":"./dist/index.js","default":"./dist/index.js"},"./components":{"types":"./dist/components/index.d.ts","svelte":"./dist/components/index.js"},"./firebase":{"types":"./dist/firebase/index.d.ts","default":"./dist/firebase/index.js"},"./types":{"types":"./dist/types/index.d.ts","default":"./dist/types/index.js"},"./utils":{"types":"./dist/utils/index.d.ts","default":"./dist/utils/index.js"},"./stores":{"types":"./dist/stores/index.d.ts","default":"./dist/stores/index.js"},"./package.json":"./package.json"},"bin":{"blog-manager":"bin/blog-manager.js","migrate-blogs":"bin/migrate-blogs.js"},"scripts":{"dev":"vite dev","build":"vite build && npm run package","preview":"vite preview","package":"svelte-kit sync && svelte-package && publint","prepublishOnly":"npm run package","check":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json","check:watch":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch","lint":"prettier --check . && eslint .","format":"prettier --write ."},"devDependencies":{"@sveltejs/adapter-auto":"^3.0.0","@sveltejs/kit":"^2.0.0","@sveltejs/package":"^2.0.0","@sveltejs/vite-plugin-svelte":"^3.0.0","@types/eslint":"^9.6.0","@types/inquirer":"^9.0.8","eslint":"^9.0.0","eslint-config-prettier":"^9.1.0","eslint-plugin-svelte":"^2.36.0","globals":"^15.0.0","prettier":"^3.1.1","prettier-plugin-svelte":"^3.1.2","publint":"^0.1.9","svelte":"^4.2.7","svelte-check":"^3.6.0","tslib":"^2.4.1","typescript":"^5.0.0","typescript-eslint":"^8.0.0","vite":"^5.0.11"},"peerDependencies":{"firebase":"^10.0.0 || ^11.0.0","svelte":"^4.0.0 || ^5.0.0","tailwindcss":"^3.0.0"},"dependencies":{"gray-matter":"^4.0.3","inquirer":"^9.0.0","marked":"^9.0.0"},"keywords":["svelte","sveltekit","blog","firebase","comments","cms","typescript"],"author":{"name":"Crashnaut"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/crashnaut/sveltekit-firebase-blog.git"},"publishConfig":{"access":"public"},"_id":"@crashnaut/sveltekit-firebase-blog@1.0.2","gitHead":"31e975b1d43d8577e42512c3842f6e83ba3c2a96","bugs":{"url":"https://github.com/crashnaut/sveltekit-firebase-blog/issues"},"homepage":"https://github.com/crashnaut/sveltekit-firebase-blog#readme","_nodeVersion":"22.11.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-ar7bLZVoaYTBNaHd7UAzK/zHqtFcixf+JvaHFof5UTkbCkp+f8A/qA3iMEgoybRff4xmdGvEnlOjrSXyXaT9yg==","shasum":"4fe5cf5564cf712bd52148daf5e1b17fabae1fdf","tarball":"https://registry.npmjs.org/@crashnaut/sveltekit-firebase-blog/-/sveltekit-firebase-blog-1.0.2.tgz","fileCount":42,"unpackedSize":115092,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGcBM10Wh6mM+m+O0Jv363gp3cdkZWzdm/6cXGwDU6UEAiEArak57+q/hTmr0vo+HyrMwoyyPnP73ZK1G14AxL4l550="}]},"_npmUser":{"name":"crashnaut","email":"mikesell404@gmail.com"},"directories":{},"maintainers":[{"name":"crashnaut","email":"mikesell404@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sveltekit-firebase-blog_1.0.2_1749600554678_0.03041539981127528"},"_hasShrinkwrap":false}},"time":{"created":"2025-06-08T21:07:47.839Z","modified":"2025-06-11T00:09:15.142Z","1.0.0":"2025-06-08T21:07:48.118Z","1.0.1":"2025-06-10T23:48:45.259Z","1.0.2":"2025-06-11T00:09:14.935Z"},"bugs":{"url":"https://github.com/crashnaut/sveltekit-firebase-blog/issues"},"author":{"name":"Crashnaut"},"license":"MIT","homepage":"https://github.com/crashnaut/sveltekit-firebase-blog#readme","keywords":["svelte","sveltekit","blog","firebase","comments","cms","typescript"],"repository":{"type":"git","url":"git+https://github.com/crashnaut/sveltekit-firebase-blog.git"},"description":"A comprehensive SvelteKit blog system with Firebase backend, comments, likes, and admin interface","maintainers":[{"name":"crashnaut","email":"mikesell404@gmail.com"}],"readme":"# SvelteKit Firebase Blog Library\n\nA comprehensive, reusable SvelteKit blog system with Firebase backend, featuring comments, likes, authentication, and admin tools.\n\n## Features\n\n- 🔥 **Firebase Integration**: Complete Firestore backend with authentication\n- 📝 **Blog Management**: Create, edit, delete blog posts with markdown support\n- 💬 **Comments System**: Threaded comments with like/dislike functionality\n- ❤️ **Like System**: Post and comment likes with real-time updates\n- 🔐 **Authentication**: Firebase Auth integration\n- 🎨 **Responsive Design**: Mobile-first Tailwind CSS components\n- 📦 **TypeScript**: Full type safety throughout\n- 🛠️ **CLI Tools**: Blog management and migration utilities\n\n## Installation\n\n```bash\nnpm install @crashnaut/sveltekit-firebase-blog firebase\n```\n\n## Quick Setup\n\n### 1. Initialize Firebase in your SvelteKit app\n\n```typescript\n// src/lib/firebase.ts\nimport { initializeBlogFirebase } from '@crashnaut/sveltekit-firebase-blog/firebase';\n\nconst firebaseConfig = {\n  apiKey: \"your-api-key\",\n  authDomain: \"your-project.firebaseapp.com\",\n  projectId: \"your-project-id\",\n  storageBucket: \"your-project.appspot.com\",\n  messagingSenderId: \"123456789\",\n  appId: \"your-app-id\"\n};\n\n// Initialize the blog library with your Firebase config\ninitializeBlogFirebase(firebaseConfig);\n```\n\n### 2. Use in your routes\n\n```svelte\n<!-- src/routes/blog/+page.svelte -->\n<script lang=\"ts\">\n  import { BlogList } from '@crashnaut/sveltekit-firebase-blog';\n  import { getBlogPosts } from '@crashnaut/sveltekit-firebase-blog/firebase';\n  import { onMount } from 'svelte';\n  \n  let posts = [];\n  let loading = true;\n\n  onMount(async () => {\n    try {\n      const result = await getBlogPosts();\n      posts = result.posts;\n    } catch (error) {\n      console.error('Error loading posts:', error);\n    } finally {\n      loading = false;\n    }\n  });\n\n  function handleAuthModal(returnUrl: string) {\n    // Implement your auth modal logic\n    console.log('Open auth modal, return to:', returnUrl);\n  }\n</script>\n\n<div class=\"container mx-auto px-4 py-8\">\n  <h1 class=\"text-4xl font-bold mb-8\">Blog</h1>\n  \n  {#if loading}\n    <div class=\"flex justify-center py-8\">\n      <div class=\"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600\"></div>\n    </div>\n  {:else}\n    <BlogList {posts} {handleAuthModal} />\n  {/if}\n</div>\n```\n\n```svelte\n<!-- src/routes/blog/[slug]/+page.svelte -->\n<script lang=\"ts\">\n  import { page } from '$app/stores';\n  import { BlogPost, Comments, LikeButton } from '@crashnaut/sveltekit-firebase-blog';\n  import { getBlogPost } from '@crashnaut/sveltekit-firebase-blog/firebase';\n  import { onMount } from 'svelte';\n  \n  let post = null;\n  let loading = true;\n\n  onMount(async () => {\n    try {\n      const slug = $page.params.slug;\n      post = await getBlogPost(slug);\n    } catch (error) {\n      console.error('Error loading post:', error);\n    } finally {\n      loading = false;\n    }\n  });\n\n  function handleAuthModal(returnUrl: string) {\n    // Implement your auth modal logic\n  }\n</script>\n\n<div class=\"container mx-auto px-4 py-8\">\n  {#if loading}\n    <div class=\"flex justify-center py-8\">\n      <div class=\"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600\"></div>\n    </div>\n  {:else if post}\n    <BlogPost {post}>\n      <svelte:fragment slot=\"comments\">\n        <div class=\"flex items-center justify-between mb-6\">\n          <h3 class=\"text-xl font-semibold\">Comments</h3>\n          <LikeButton postId={post.id} initialLikeCount={post.likeCount} {handleAuthModal} />\n        </div>\n        <Comments postId={post.id} {handleAuthModal} />\n      </svelte:fragment>\n    </BlogPost>\n  {:else}\n    <div class=\"text-center py-8\">\n      <h1 class=\"text-2xl font-bold text-gray-900\">Post not found</h1>\n      <p class=\"text-gray-600 mt-2\">The blog post you're looking for doesn't exist.</p>\n    </div>\n  {/if}\n</div>\n```\n\n### 3. Set up authentication state (optional)\n\n```typescript\n// src/lib/stores/auth.ts\nimport { user } from '@crashnaut/sveltekit-firebase-blog/stores';\nimport { initializeAuth } from '@crashnaut/sveltekit-firebase-blog/firebase';\n\n// Initialize auth state management\ninitializeAuth();\n\n// Export the user store to use in your app\nexport { user };\n```\n\n## Firebase Setup\n\n### 1. Create Firestore Collections\n\nYour Firebase project needs these collections:\n\n- `posts` - Blog posts\n- `comments` - Comments on posts\n- `postLikes` - Post likes\n- `commentLikes` - Comment likes/dislikes\n\n### 2. Firestore Security Rules\n\n```javascript\nrules_version = '2';\nservice cloud.firestore {\n  match /databases/{database}/documents {\n    // Blog posts - public read, authenticated write\n    match /posts/{postId} {\n      allow read: if true;\n      allow write: if request.auth != null;\n    }\n    \n    // Comments - public read, authenticated write\n    match /comments/{commentId} {\n      allow read: if true;\n      allow create: if request.auth != null;\n      allow update, delete: if request.auth != null && \n        (request.auth.uid == resource.data.userId);\n    }\n    \n    // Post likes - authenticated users only\n    match /postLikes/{likeId} {\n      allow read, write: if request.auth != null;\n    }\n    \n    // Comment likes - authenticated users only\n    match /commentLikes/{likeId} {\n      allow read, write: if request.auth != null;\n    }\n  }\n}\n```\n\n## API Reference\n\n### Firebase Functions\n\n```typescript\n// Blog management\nimport { \n  getBlogPosts, \n  getBlogPost, \n  createBlogPost, \n  updateBlogPost, \n  deleteBlogPost,\n  likePost,\n  unlikePost,\n  hasUserLikedPost\n} from '@crashnaut/sveltekit-firebase-blog/firebase';\n\n// Comments\nimport { \n  getComments, \n  addComment, \n  deleteComment,\n  likeComment,\n  dislikeComment,\n  hasUserLikedComment,\n  hasUserDislikedComment\n} from '@crashnaut/sveltekit-firebase-blog/firebase';\n\n// Auth\nimport { \n  getCurrentUser, \n  signIn, \n  signOut, \n  isAuthenticated \n} from '@crashnaut/sveltekit-firebase-blog/firebase';\n```\n\n### Components\n\n```typescript\n// Main components\nimport { \n  BlogList,     // Display list of blog posts\n  BlogPost,     // Display single blog post\n  Comments,     // Comments section\n  LikeButton    // Like/unlike button\n} from '@crashnaut/sveltekit-firebase-blog';\n```\n\n### Types\n\n```typescript\nimport type { \n  BlogPost, \n  Comment, \n  NewComment,\n  BlogPostsResult \n} from '@crashnaut/sveltekit-firebase-blog/types';\n```\n\n## CLI Tools\n\n### Blog Manager\n\nCreate and manage blog posts from the command line:\n\n```bash\nnpx blog-manager\n```\n\nFeatures:\n- Create new blog posts\n- Interactive prompts for metadata\n- Markdown content editing\n- Preview functionality\n\n### Migration Tool\n\nMigrate existing markdown files to Firebase:\n\n```bash\nnpx migrate-blogs --verbose\nnpx migrate-blogs --no-dry-run  # Actually migrate\nnpx migrate-blogs --validate    # Validate posts only\n```\n\n## Styling\n\nThe library uses Tailwind CSS classes. Make sure your project has Tailwind configured:\n\n```javascript\n// tailwind.config.js\nexport default {\n  content: [\n    './src/**/*.{html,js,svelte,ts}',\n    './node_modules/@crashnaut/sveltekit-firebase-blog/**/*.{js,svelte,ts}'\n  ],\n  // ... your other config\n}\n```\n\n## Advanced Usage\n\n### Custom Authentication Modal\n\n```svelte\n<script lang=\"ts\">\n  import { Modal } from 'your-ui-library';\n  import { signIn } from '@crashnaut/sveltekit-firebase-blog/firebase';\n  \n  let showAuthModal = false;\n  let returnUrl = '';\n\n  function handleAuthModal(url: string) {\n    returnUrl = url;\n    showAuthModal = true;\n  }\n  \n  async function handleSignIn() {\n    try {\n      await signIn();\n      showAuthModal = false;\n      // Optionally redirect to returnUrl\n    } catch (error) {\n      console.error('Sign in failed:', error);\n    }\n  }\n</script>\n\n<BlogList posts={posts} openAuthModal={handleAuthModal} />\n\n<Modal bind:open={showAuthModal}>\n  <h2>Sign In Required</h2>\n  <p>Please sign in to interact with posts.</p>\n  <button on:click={handleSignIn}>Sign In with Google</button>\n</Modal>\n```\n\n### Admin Interface\n\n```svelte\n<script lang=\"ts\">\n  import { user } from '@crashnaut/sveltekit-firebase-blog/stores';\n  import { createBlogPost, updateBlogPost, deleteBlogPost } from '@crashnaut/sveltekit-firebase-blog/firebase';\n  \n  // Only show admin interface to authenticated users\n  $: isAdmin = $user && $user.email === 'admin@yourdomain.com';\n</script>\n\n{#if isAdmin}\n  <div class=\"admin-panel\">\n    <!-- Your admin interface here -->\n  </div>\n{/if}\n```\n\n## Development\n\nTo contribute to this library:\n\n```bash\ngit clone https://github.com/crashnaut/sveltekit-firebase-blog\ncd sveltekit-firebase-blog\nnpm install\nnpm run dev\n```\n\n## License\n\nMIT © Crashnaut\n","readmeFilename":"README.md"}