Firebase Portfolio Storage
March 19, 2025 · AI Conversations
And then also fetch all portfolio
### **1. Set Up Firebase**
– Create a Firebase project in the [Firebase Console](https://console.firebase.google.com/).
– Add Firebase to your web app.
– Install Firebase SDK:
npm install firebase
– Initialize Firebase in your project:
import { initializeApp } from "firebase/app";
import { getStorage } from "firebase/storage";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_AUTH_DOMAIN",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_STORAGE_BUCKET",
messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
appId: "YOUR_APP_ID"
};
const app = initializeApp(firebaseConfig);
export const storage = getStorage(app);
export const db = getFirestore(app);
—
### **2. Upload Portfolio Item (Title, Technologies, Image, Description)**
– Use Firestore for storing metadata and Firebase Storage for images.
import { getFirestore, collection, addDoc } from "firebase/firestore";
import { getStorage, ref, uploadBytes, getDownloadURL } from "firebase/storage";
const db = getFirestore();
const storage = getStorage();
const uploadPortfolioItem = async (title, technologies, imageFile, description) => {
try {
// Upload image to Firebase Storage
const imageRef = ref(storage, `portfolio/${imageFile.name}`);
const snapshot = await uploadBytes(imageRef, imageFile);
const imageUrl = await getDownloadURL(snapshot.ref);
// Store metadata in Firestore
await addDoc(collection(db, "portfolio"), {
title,
technologies,
image: imageUrl,
description,
createdAt: new Date(),
});
console.log("Portfolio item added successfully!");
} catch (error) {
console.error("Error adding portfolio item: ", error);
}
};
**Usage Example:**
const fileInput = document.querySelector("#fileInput");
const title = "My Portfolio Project";
const technologies = ["Vue.js", "Laravel", "Firebase"];
const description = "A great portfolio project.";
fileInput.addEventListener("change", (event) => {
const file = event.target.files[0];
if (file) {
uploadPortfolioItem(title, technologies, file, description);
}
});
—
### **3. Fetch All Portfolio Items**
import { collection, getDocs } from "firebase/firestore";
const fetchPortfolioItems = async () => {
const querySnapshot = await getDocs(collection(db, "portfolio"));
const portfolioItems = [];
querySnapshot.forEach((doc) => {
portfolioItems.push({ id: doc.id, ...doc.data() });
});
return portfolioItems;
};
// Usage Example
fetchPortfolioItems().then((items) => console.log(items));
—
### **4. Display Portfolio Items in Vue.js**
If you're using Vue.js, you can integrate the fetch function like this:
<template>
<div>
<h2>My Portfolio</h2>
<div v-for="item in portfolioItems" :key="item.id">
<h3>{{ item.title }}</h3>
<p>{{ item.technologies.join(', ') }}</p>
<img :src="item.image" alt="Portfolio Image" width="200">
<p>{{ item.description }}</p>
</div>
</div>
</template>
<script>
import { fetchPortfolioItems } from "@/firebase"; // Adjust path accordingly
export default {
data() {
return {
portfolioItems: [],
};
},
async mounted() {
this.portfolioItems = await fetchPortfolioItems();
},
};
</script>
—
### **Summary**
– **Firebase Storage**: Stores images.
– **Firestore Database**: Stores metadata (title, technologies, description, image URL).
– **Vue.js Component**: Fetches and displays the portfolio.
Let me know if you need further customization!
—
### **1. Set Up Firebase**
Install Firebase SDK if you haven't:
npm install firebase
Initialize Firebase in a separate file (`firebase.js`):
import { initializeApp } from "firebase/app";
import { getStorage } from "firebase/storage";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_AUTH_DOMAIN",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_STORAGE_BUCKET",
messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
appId: "YOUR_APP_ID"
};
const app = initializeApp(firebaseConfig);
export const storage = getStorage(app);
export const db = getFirestore(app);
—
### **2. Upload Portfolio Item (Using Composition API)**
Create a **Firebase Composable** (`usePortfolio.js`):
import { ref as storageRef, uploadBytes, getDownloadURL } from "firebase/storage";
import { collection, addDoc, getDocs } from "firebase/firestore";
import { ref } from "vue";
import { db, storage } from "@/firebase";
export function usePortfolio() {
const portfolioItems = ref([]);
// Upload Portfolio Item
const uploadPortfolioItem = async (title, technologies, imageFile, description) => {
try {
// Upload image to Firebase Storage
const imgRef = storageRef(storage, `portfolio/${imageFile.name}`);
const snapshot = await uploadBytes(imgRef, imageFile);
const imageUrl = await getDownloadURL(snapshot.ref);
// Store metadata in Firestore
await addDoc(collection(db, "portfolio"), {
title,
technologies,
image: imageUrl,
description,
createdAt: new Date(),
});
console.log("Portfolio item added successfully!");
} catch (error) {
console.error("Error adding portfolio item:", error);
}
};
// Fetch Portfolio Items
const fetchPortfolioItems = async () => {
try {
const querySnapshot = await getDocs(collection(db, "portfolio"));
portfolioItems.value = querySnapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
} catch (error) {
console.error("Error fetching portfolio items:", error);
}
};
return { portfolioItems, uploadPortfolioItem, fetchPortfolioItems };
}
—
### **3. Portfolio Upload Component (Composition API)**
Create `PortfolioUploader.vue`:
<template>
<div>
<h2>Upload Portfolio Item</h2>
<form @submit.prevent="handleSubmit">
<input type="text" v-model="title" placeholder="Title" required />
<input type="text" v-model="technologies" placeholder="Technologies (comma separated)" required />
<input type="file" @change="handleFileChange" required />
<textarea v-model="description" placeholder="Description"></textarea>
<button type="submit">Upload</button>
</form>
</div>
</template>
<script>
import { ref } from "vue";
import { usePortfolio } from "@/composables/usePortfolio";
export default {
setup() {
const { uploadPortfolioItem } = usePortfolio();
const title = ref("");
const technologies = ref("");
const imageFile = ref(null);
const description = ref("");
const handleFileChange = (event) => {
imageFile.value = event.target.files[0];
};
const handleSubmit = async () => {
if (!imageFile.value) {
alert("Please select an image.");
return;
}
const techArray = technologies.value.split(",").map((tech) => tech.trim());
await uploadPortfolioItem(title.value, techArray, imageFile.value, description.value);
// Reset form
title.value = "";
technologies.value = "";
imageFile.value = null;
description.value = "";
};
return { title, technologies, imageFile, description, handleFileChange, handleSubmit };
},
};
</script>
—
### **4. Portfolio List Component (Composition API)**
Create `PortfolioList.vue`:
<template>
<div>
<h2>Portfolio Items</h2>
<button @click="fetchPortfolioItems">Load Portfolio</button>
<div v-if="loading">Loading...</div>
<div v-else>
<div v-for="item in portfolioItems" :key="item.id">
<h3>{{ item.title }}</h3>
<p>Technologies: {{ item.technologies.join(', ') }}</p>
<img :src="item.image" alt="Portfolio Image" width="200" />
<p>{{ item.description }}</p>
</div>
</div>
</div>
</template>
<script>
import { onMounted, ref } from "vue";
import { usePortfolio } from "@/composables/usePortfolio";
export default {
setup() {
const { portfolioItems, fetchPortfolioItems } = usePortfolio();
const loading = ref(true);
onMounted(async () => {
await fetchPortfolioItems();
loading.value = false;
});
return { portfolioItems, fetchPortfolioItems, loading };
},
};
</script>
—
### **5. Use Components in `App.vue`**
<template>
<PortfolioUploader />
<PortfolioList />
</template>
<script>
import PortfolioUploader from "@/components/PortfolioUploader.vue";
import PortfolioList from "@/components/PortfolioList.vue";
export default {
components: {
PortfolioUploader,
PortfolioList,
},
};
</script>
—
### **Summary**
✅ **Firebase Storage** → Stores images
✅ **Firestore** → Stores title, technologies, description, image URL
✅ **Composition API** → Manages state & logic
✅ **Reusable Composables (`usePortfolio.js`)** → Fetch & upload portfolio items
✅ **Vue Components (`PortfolioUploader.vue` & `PortfolioList.vue`)** → UI
This setup ensures a **structured and reusable** way to handle portfolio items in Vue 3 with Firebase. Let me know if you need any modifications! 🚀