<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Usman</title>
    <description>The latest articles on DEV Community by Usman (@maxixo).</description>
    <link>https://dev.to/maxixo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1144192%2Fe7e3d929-77a2-41a4-a4d1-1573e58e2ded.png</url>
      <title>DEV Community: Usman</title>
      <link>https://dev.to/maxixo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maxixo"/>
    <language>en</language>
    <item>
      <title>From Frontend to Full-Stack: Building a Real Estate Marketplace and Learning Backend Development</title>
      <dc:creator>Usman</dc:creator>
      <pubDate>Sat, 14 Feb 2026 20:56:12 +0000</pubDate>
      <link>https://dev.to/maxixo/from-frontend-to-full-stack-building-a-real-estate-marketplace-and-learning-backend-development-2258</link>
      <guid>https://dev.to/maxixo/from-frontend-to-full-stack-building-a-real-estate-marketplace-and-learning-backend-development-2258</guid>
      <description>&lt;p&gt;What is the best career advice I can give to any frontend developer right now? Learn backend development. So I took my own advice and jumped straight into servers, databases, and APIs. Coming from a React background, I already had JavaScript in my toolkit, which made picking up Express.js quite smooth. But knowing the syntax is one thing, understanding how to architect a real application is another entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Project: Soul Estate
&lt;/h3&gt;

&lt;p&gt;I built a production-ready real estate marketplace with complete authentication, profile management, and CRUD operations for listings. Here’s what users can do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sign up with email/password or use Google OAuth for easy access&lt;/li&gt;
&lt;li&gt;Profile Management: Update user details and upload custom avatars&lt;/li&gt;
&lt;li&gt;Listing Management: Create, update, delete, and browse property listings&lt;/li&gt;
&lt;li&gt;Image Uploads: Multi-image upload with Appwrite Storage (URLs stored in MongoDB)&lt;/li&gt;
&lt;li&gt;Real-time Validation: Inline form validation with comprehensive error handling&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Tech Stack:
&lt;/h4&gt;

&lt;p&gt;Frontend: React + Vite, Redux Toolkit for state management, Tailwind CSS for styling&lt;br&gt;
Backend: Node.js + Express.js with Mongoose ODM&lt;br&gt;
Authentication: JWT cookies + Firebase Google OAuth&lt;br&gt;
Storage: Appwrite for image hosting&lt;br&gt;
Database: MongoDB Atlas&lt;/p&gt;

&lt;p&gt;The project follows a monorepo structure with separate api/ and client/ directories, making it easy to manage both frontend and backend in a single repository.&lt;/p&gt;
&lt;h3&gt;
  
  
  Database Design and API Foundation
&lt;/h3&gt;

&lt;p&gt;The first week was all about laying the foundation. I started by designing my MongoDB schemas, focusing on the Listing model, which was the core of the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  name: String,
  description: String,
  address: String,
  type: 'rent' | 'sale',
  offer: Boolean,
  regularPrice: Number,
  discountedPrice: Number,
  bedrooms: Number,
  bathrooms: Number,
  parking: Boolean,
  furnished: Boolean,
  imageUrls: [String],  // Appwrite URLs
  userRef: ObjectId     // Reference to owner
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I proceeded to implement a comprehensive REST API with clear, RESTful endpoints:&lt;/p&gt;

&lt;p&gt;Auth Routes:&lt;br&gt;
POST /api/auth/signup - Email/password registration&lt;br&gt;
POST /api/auth/signin - User login&lt;br&gt;
POST /api/auth/google - Google OAuth flow&lt;br&gt;
GET /api/auth/signout - Session termination&lt;/p&gt;

&lt;p&gt;User Routes:&lt;br&gt;
POST /api/user/update/:id - Update profile and avatar&lt;br&gt;
DELETE /api/user/delete/:id - Account deletion&lt;br&gt;
GET /api/user/listings/:id - Fetch user’s listings&lt;/p&gt;

&lt;p&gt;Listing Routes:&lt;br&gt;
POST /api/listing/create - Create new listing&lt;br&gt;
POST /api/listing/update/:id - Update existing listing&lt;br&gt;
DELETE /api/listing/delete/:id - Remove listing&lt;br&gt;
GET /api/listing/:id - Fetch single listing details&lt;/p&gt;
&lt;h3&gt;
  
  
  The Image Upload Challenge
&lt;/h3&gt;

&lt;p&gt;One of the most interesting technical challenges was implementing image uploads. Instead of using Firebase Storage, I opted for Appwrite because payment was required for Firebase usage, which clearly wasn’t going to scale. This turned out to be a valuable learning experience. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4x6a96kw1t1sgmy60xu2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4x6a96kw1t1sgmy60xu2.png" alt="image upload interface in the listing creation form" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;image upload interface in the listing creation form&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here’s how the flow works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User Selects Multiple Images (React Frontend): The frontend uses a standard React state pattern to capture multiple files from a file input. The multiple attribute is essential here to allow users to select more than one property image at once
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Representative frontend component logic
const [files, setFiles] = useState([]);

const handleFileSelection = (e) =&amp;gt; {
  // Capturing multiple files into state
  setFiles(e.target.files);
};

return (
  &amp;lt;input 
    type="file" 
    id="images" 
    accept="image/*" 
    multiple 
    onChange={handleFileSelection} 
    className="p-3 border border-gray-300 rounded w-full"
  /&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;2.&amp;amp; 3. Upload to Appwrite and Retrieve Public URLs: The application uses the Appwrite Storage service to host images. The frontend iterates over the selected files, uploads them to the configured bucket using VITE_APPWRITE_BUCKET_ID, and generates public URLs for each file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Representative logic for uploading and URL generation
import { Storage, ID } from 'appwrite';

const storage = new Storage(client);

const uploadToAppwrite = async () =&amp;gt; {
  const uploadPromises = Array.from(files).map((file) =&amp;gt; {
    return storage.createFile(
      import.meta.env.VITE_APPWRITE_BUCKET_ID,
      ID.unique(),
      file
    );
  });

  const fileResponses = await Promise.all(uploadPromises);

  // Generating public URLs for the imageUrls array
  return fileResponses.map(file =&amp;gt; 
    storage.getFileView(import.meta.env.VITE_APPWRITE_BUCKET_ID, file.$id).href
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Store URLs in MongoDB's imageUrls Array: Once the URLs are retrieved, they are included in the listing data and sent to the backend via the POST /api/listing/create route. The backend then saves these strings into the imageUrls array field defined in the Listing Mongoose model
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Backend Controller: api/controllers/listing.controller.js
export const createListing = async (req, res, next) =&amp;gt; {
  try {
    // req.body contains the imageUrls array of Appwrite URLs
    const listing = await Listing.create({
      ...req.body,
      userRef:req.user.id, // Authenticated owner ID
    });
    return res.status(201).json(listing);
  } catch (error) {
    next(error); // Global error handling
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Frontend Fetches and Displays Images. Finally, the application retrieves the listing data. The frontend renders the images by mapping over the imageUrls array, permitting efficient display of high-quality property visuals hosted on Appwrite.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// client/src/pages/Listing.jsx

{listing.imageUrls &amp;amp;&amp;amp; listing.imageUrls.map((url, index) =&amp;gt; (
  &amp;lt;div 
    key={index} 
    className="h-[500px]" 
    style={{ background: `url(${url}) center no-repeat`, backgroundSize: 'cover' }}
  &amp;gt;
    {/* Displaying property images in a slider or gallery */}
  &amp;lt;/div&amp;gt;
)}e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1qllwmgqn0iicr7tbyy3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1qllwmgqn0iicr7tbyy3.png" alt="Property images displayed in an interactive gallery, sourced from Appwrite URLs" width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Property images displayed in an interactive gallery, sourced from Appwrite URLs&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Using MongoDB for metadata and Appwrite for binary storage made querying the database fast and kept the backend light.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication: JWT + OAuth
&lt;/h3&gt;

&lt;p&gt;I implemented a dual authentication system to balance security together with user convenience. Users can choose between traditional email/password registration or streamlined Google sign-in, making sure the application accommodates different privacy preferences and use cases.&lt;/p&gt;

&lt;p&gt;Here’s how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Traditional Email/Password:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Passwords hashed with bcrypt&lt;/li&gt;
&lt;li&gt;JWT tokens are stored in httpOnly cookies for security&lt;/li&gt;
&lt;li&gt;Server-side validation with Mongoose schemas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2 Google OAuth (via Firebase):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; One-click sign-in with Google accounts&lt;/li&gt;
&lt;li&gt; Perfect integration with Firebase Authentication&lt;/li&gt;
&lt;li&gt; Automatic user creation on first login&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The JWT cookie strategy prevents XSS attacks since JavaScript can’t access httpOnly cookies, while Firebase handles the OAuth complexity on the client side.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Implementation
&lt;/h3&gt;

&lt;p&gt;Security wasn't an afterthought as I applied my cybersecurity knowledge to implement multiple layers of protection from day one. Modern web applications encounter constant threats, so I focused on three critical attack vectors: Cross-Site Scripting (XSS), Cross-Site Request Forgery (CSRF), and unauthorised cross-origin requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  CSRF Protection for State-Changing Requests
&lt;/h3&gt;

&lt;p&gt;Since the application uses cookie-based JWT authentication, browsers automatically include these cookies in every request—even malicious cross-site ones. To prevent CSRF attacks, I implemented token-based verification on all state-changing operations (creating, updating, or deleting listings and profiles).&lt;/p&gt;

&lt;p&gt;Here's the security middleware stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import cookieParser from 'cookie-parser';
import csrf from 'csurf';
import cors from 'cors';

const app = express();

app.use(express.json());
app.use(cookieParser()); // Required for reading JWT and CSRF cookies

// CORS configuration - strict origin control
app.use(cors({
  origin: 'http://localhost:5173', // Vite dev server (update for production)
  credentials: true // Allow cookies to be sent cross-origin
}));

// CSRF protection for all API routes
const csrfProtection = csrf({ cookie: true });
app.use('/api', csrfProtection, (req, res, next) =&amp;gt; {
  // CSRF token available to frontend via cookie
  res.cookie('XSRF-TOKEN', req.csrfToken());
  next();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How CSRF Protection Works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The server generates a unique CSRF token for each session.&lt;/li&gt;
&lt;li&gt;Token is sent to the client via a cookie (XSRF-TOKEN)&lt;/li&gt;
&lt;li&gt;The frontend includes this token in the request headers for state-changing operations.&lt;/li&gt;
&lt;li&gt;The server validates that the token matches before processing the request.&lt;/li&gt;
&lt;li&gt;Malicious sites can't access the token due to the same-origin policy.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Configuration: Controlled Cross-Origin Access
&lt;/h2&gt;

&lt;p&gt;CORS (Cross-Origin Resource Sharing) controls which domains can access the API. The configuration above restricts API access to the legitimate frontend origin only, preventing unauthorised websites from making requests to the backend—even if they somehow obtain a valid JWT&lt;/p&gt;

&lt;p&gt;Production Considerations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In production, the origin is set to the deployed frontend domain (not localhost)&lt;/li&gt;
&lt;li&gt;credentials: true ensures cookies are sent with cross-origin requests&lt;/li&gt;
&lt;li&gt;Additional headers can be restricted using allowedHeaders and exposedHeaders&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;State Management with Redux Toolkit&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I used Redux Toolkit to manage global state, particularly for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User authentication status&lt;/li&gt;
&lt;li&gt;Current user profile data&lt;/li&gt;
&lt;li&gt;Listing creation/editing state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code snippet represents a standard userSlice.js implementation for this project, handling user authentication, profile updates, and state persistence.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createSlice } from '@reduxjs/toolkit';

const initialState = {
  currentUser: null, // Stores user data including avatar and ID for userRef
  error: null,
  loading: false,
};

const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    // Auth: Email/Password and Google OAuth login flow
    signInStart: (state) =&amp;gt; {
      state.loading = true;
    },
    signInSuccess: (state, action) =&amp;gt; {
      state.currentUser = action.payload;
      state.loading = false;
      state.error = null;
    },
    signInFailure: (state, action) =&amp;gt; {
      state.error = action.payload;
      state.loading = false;
    },
    // Profile Management: Handling avatar and detail updates
    updateUserSuccess: (state, action) =&amp;gt; {
      state.currentUser = action.payload;
      state.loading = false;
      state.error = null;
    },
    // Sign out logic to clear global state
    signOutUserSuccess: (state) =&amp;gt; {
      state.currentUser = null;
      state.loading = false;
      state.error = null;
    },
  },
});

export const { 
  signInStart, signInSuccess, signInFailure, 
  updateUserSuccess, signOutUserSuccess 
} = userSlice.actions;

export default userSlice.reducer;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A key takeaway from building this project and a basic fact about backend development is that it's not only about writing code that works; it's about writing code that's secure and scalable. The jump from frontend to full-stack requires a change in mindset. You're no longer just concerned with UI state and user actions (though these still matter); you're now responsible for data validity, authentication and security, API design, and server architecture. &lt;/p&gt;

&lt;p&gt;Every decision has implications: choosing between SQL and NoSQL, deciding where to store images, implementing proper error handling, and securing sensitive routes. What surprised me most was how much these backend concerns influenced my frontend decisions. Understanding how data flows from the database to the API, then to Redux, and finally to React components gave me a holistic view of the application architecture that I couldn't grasp as a frontend-only developer. If you're on the fence about learning backend development, my advice is straightforward: start building&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Resources &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;livelink:  &lt;a href="https://soul-estate.up.railway.app/" rel="noopener noreferrer"&gt;https://soul-estate.up.railway.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;github repo: &lt;a href="https://github.com/maxixo/mern-estate" rel="noopener noreferrer"&gt;https://github.com/maxixo/mern-estate&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/usman-oshodi-28326b307/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/usman-oshodi-28326b307/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>backend</category>
      <category>fullstack</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Usman</dc:creator>
      <pubDate>Thu, 29 Jan 2026 07:29:30 +0000</pubDate>
      <link>https://dev.to/maxixo/-44cf</link>
      <guid>https://dev.to/maxixo/-44cf</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/maxixo" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1144192%2Fe7e3d929-77a2-41a4-a4d1-1573e58e2ded.png" alt="maxixo"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/maxixo/building-a-data-visualization-and-note-taking-web-app-4inb" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Building a Data Visualization and Note-Taking Web App&lt;/h2&gt;
      &lt;h3&gt;Usman ・ Jan 28&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#analysis&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#encryption&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#fullstack&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>analysis</category>
      <category>encryption</category>
      <category>fullstack</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building a Data Visualization and Note-Taking Web App</title>
      <dc:creator>Usman</dc:creator>
      <pubDate>Wed, 28 Jan 2026 11:21:26 +0000</pubDate>
      <link>https://dev.to/maxixo/building-a-data-visualization-and-note-taking-web-app-4inb</link>
      <guid>https://dev.to/maxixo/building-a-data-visualization-and-note-taking-web-app-4inb</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Have you ever found yourself switching between multiple tabs while analysing data and taking notes at the same time? If yes, then this tool is for you, eliminating the friction of fragmented workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Thought Process
&lt;/h2&gt;

&lt;p&gt;I built an all-in-one web application that combines data visualization and secure note-taking. This tool is designed to streamline the process of analysing datasets and recording insights, all within a single, easy-to-use interface.&lt;/p&gt;

&lt;p&gt;Here is a rundown and my inspiration for building this tool.&lt;/p&gt;

&lt;p&gt;During my HNG internship, we were given a list of projects to choose from, and this one immediately stood out to me. I was immediately drawn to the concept of visualizing data in charts and bringing numbers to life. With a background in chemistry and extensive experience working with data in qualitative analysis, I saw an opportunity to build something that resonated with my expertise and could benefit anyone working with data.&lt;/p&gt;

&lt;p&gt;In the course of building this, I noticed that while viewing the data, users would want to take notes on findings and insights. This prompted me to add the draft section of the web app. I took this a step further by adding a feature to encrypt your drafts and datasets with military-grade AES-256, securely protecting the data with a password, salt, IV, and buffers before storing it in the MongoDB database. Users can decrypt their notes or datasets on demand using their password, leveraging privacy for their data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ssi1z28keli7hth7yta.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ssi1z28keli7hth7yta.png" alt="dashboard page" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Data Visualization
&lt;/h3&gt;

&lt;p&gt;Once logged in, datasets can be viewed by uploading a CSV or Excel file. You can then select the type of chart you intend to use. Chart options include bar, line, and pie charts. Here is how a typical chart will look once a dataset is uploaded.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkz5fnt9q3cqx46ji2191.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkz5fnt9q3cqx46ji2191.png" alt="barchart " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of product sales chart.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Futx1sol1f7c30l28up9k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Futx1sol1f7c30l28up9k.png" alt="barchart" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[This image shows how filtering specific data (e.g., mouse products) provides focused insights within the visualization.]&lt;/p&gt;

&lt;p&gt;Taking a close look at the first picture, we see the entire array of products sold displayed by their sales volume. You can filter for specific data and compare it with another option in the dataset. This helps to narrow down specific niches. The second picture shows exactly how this works. The sales of mouse products were specifically filtered out from the rest of the products and displayed on the chart.&lt;/p&gt;

&lt;p&gt;When dealing with large datasets, it is common to want to take notes and make sure key details are recorded. I created a drafts section in the web app that lets users create, edit, delete, and securely store drafts. Implementing encryption was insightful for me. I learned about array buffering, which is key to how the server receives the encrypted data before storing it on MongoDB. Here is how an encrypted file looks in the backend.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm4l2sbk34sl10le23iqn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm4l2sbk34sl10le23iqn.png" alt="MongoDB data preview" width="800" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of encrypted draft file as stored in the MongoDB backend. This highlights end-to-end encryption and secure data storage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Export Options
&lt;/h3&gt;

&lt;p&gt;To retrieve and download the encrypted file from the backend, the user needs the password used during encryption. If the password is forgotten, the document is lost forever. Always use a password you can remember. You can also export your viewed charts in PNG, PDF, or JSON format. The pictures above were exported from the app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fppozr19b0gtq5hub8vgo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fppozr19b0gtq5hub8vgo.png" alt="export details" width="800" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot showing exported charts in PNG, PDF, and JSON formats, demonstrating flexible export options for analysis or sharing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secure Note-Taking
&lt;/h3&gt;

&lt;p&gt;The note-taking portion of the app features drafts, encrypted drafts, and trash. Encrypted drafts can be easily accessed with the password created when a user encrypts a draft. Note: The password must not be forgotten unless the draft is lost forever and cannot be unlocked&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj9yh9v01jtoa88e003ed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj9yh9v01jtoa88e003ed.png" alt="draft section" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[Screenshot of the note-taking interface, displaying drafts, encrypted drafts, and the trash section for managing notes securely.]&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Features
&lt;/h3&gt;

&lt;p&gt;Other notable features include a light/dark theme toggle, an FAQ, and a user profile page for a seamless experience. The landing page is enhanced with Framer Motion animations. Authentication is streamlined with Google sign-in and robust validation for strong password protection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security &amp;amp; Best Practices
&lt;/h2&gt;

&lt;p&gt;I prioritized security throughout the development process. Key practices include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Sanitizing inputs to prevent injection attacks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hashing passwords securely&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Authenticating cookies with appropriate expiration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rate-limiting API calls&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Applying proper CORS and CSP configurations&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tech Stack
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Frontend:&lt;/strong&gt; React, Framer Motion&lt;br&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Node.js, Express&lt;br&gt;
&lt;strong&gt;Database:&lt;/strong&gt; MongoDB&lt;br&gt;
&lt;strong&gt;Security:&lt;/strong&gt; AES-256 encryption, bcrypt&lt;br&gt;
&lt;strong&gt;Deployment:&lt;/strong&gt; Railway&lt;/p&gt;

&lt;p&gt;Here is a live link to the project. You can test it out, play around with it, or star the repo.&lt;/p&gt;

&lt;p&gt;Resources&lt;/p&gt;

&lt;p&gt;sample data to test: download file &lt;br&gt;
live link: &lt;a href="https://dataworld-production.up.railway.app/" rel="noopener noreferrer"&gt;https://dataworld-production.up.railway.app/&lt;/a&gt;&lt;br&gt;
github repo: &lt;a href="https://github.com/maxixo/dataworld-" rel="noopener noreferrer"&gt;https://github.com/maxixo/dataworld-&lt;/a&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/usman-oshodi-28326b307/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/usman-oshodi-28326b307/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Give me a follow on GitHub as well; I enjoy connecting with other developers in this space.&lt;/p&gt;

</description>
      <category>analysis</category>
      <category>encryption</category>
      <category>fullstack</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to fetch images with Unsplash API using Javascript</title>
      <dc:creator>Usman</dc:creator>
      <pubDate>Sat, 09 Sep 2023 14:20:11 +0000</pubDate>
      <link>https://dev.to/maxixo/how-to-fetch-images-with-unsplash-api-with-javascript-5gf0</link>
      <guid>https://dev.to/maxixo/how-to-fetch-images-with-unsplash-api-with-javascript-5gf0</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;It's common in programming to find ourselves in situations where we have to upload images to hosting services to use in our projects, which can take up valuable time and slow down the coding process. In this tutorial, I'm going to guide you on how to easily request images from an API to be directly used in your projects, using the Unsplash API as a primary example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A basic understanding of HTML, CSS and Javascript is needed for this example below.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An Editor/IDE is also recommended, If you don’t have a setup IDE you can use an online editor such as &lt;a href="https://codepen.io/pen/" rel="noopener noreferrer"&gt;Codepen&lt;/a&gt; or &lt;a href="https://jsfiddle.net/" rel="noopener noreferrer"&gt;JSFiddle&lt;/a&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up the API
&lt;/h2&gt;

&lt;p&gt;To begin, we need to create a developer account with the API provider. In this case, we are using the Unsplash API. Now, head over to the &lt;a href="https://unsplash.com/documentation#creating-a-developer-account" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; link. You should see the page below. Head over to 'Create a developer account' and click 'Join' follow the provided instructions, and accept the terms for API use.&lt;/p&gt;

&lt;p&gt;Note: You should create an account with Unsplash first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0tg7yv335kgsntb3lcf1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0tg7yv335kgsntb3lcf1.png" alt="'Unslpash developers page '" width="800" height="458"&gt;&lt;/a&gt;&lt;br&gt;
After setting up your demo app, You should have your API key like this below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgenwwuvjdt26q1fkdnkw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgenwwuvjdt26q1fkdnkw.png" alt="'Unsplash API key'" width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s also important to know that you can only make &lt;strong&gt;50 requests&lt;/strong&gt; per hour for Demo apps and apps in production have access to &lt;strong&gt;5,000 requests&lt;/strong&gt; per hour. If you need to make more requests you can upgrade your limits or contact the support team. For our tutorial, we’re only fetching images for our simple gallery.&lt;/p&gt;

&lt;p&gt;Let's get into the coding aspect.&lt;/p&gt;
&lt;h2&gt;
  
  
  Coding &amp;amp; Explanation
&lt;/h2&gt;

&lt;p&gt;First, we start with our HTLM part of the code which should look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt; &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"gallery"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;img&lt;/span&gt;  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;img&lt;/span&gt;  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;img&lt;/span&gt;  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;img&lt;/span&gt;  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;img&lt;/span&gt;  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;img&lt;/span&gt;  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;img&lt;/span&gt;  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;img&lt;/span&gt;  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;img&lt;/span&gt;  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;img&lt;/span&gt;  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code block, we have a section that contains 10 div elements, each of which holds an image element. These image elements are currently empty, but we will be adding the source files for the images later in the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Styling our Gallery
&lt;/h3&gt;

&lt;p&gt;Now we need to style our images to make them look more appropriate. Paste the following code in the CSS part in your codepen&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Portfolio */&lt;/span&gt;
&lt;span class="nf"&gt;#gallery&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;1200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auto-fit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;104&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;104&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;104&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;#gallery&lt;/span&gt; &lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;104&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;104&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;104&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this CSS block, we style our gallery with a width of 1200 pixels and a 30-pixel left margin for horizontal centering. We use a responsive grid layout that adapts to a minimum column width of 200 pixels with a 20-pixel gap between the image-containing divs. Lastly, we apply a box shadow to both the image and div elements for visibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetching the images
&lt;/h3&gt;

&lt;p&gt;Our code wouldn't be complete without the Javascript aspect to interact with our API and fetch the images. Our JS code block should look like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="c1"&gt;// Unsplash Images API request&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Your API Key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://api.unsplash.com/photos/random?query=restaurant&amp;amp;count=10&amp;amp;client_id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;regular&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here should be the Output of all the codes put together&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxkhhy2peul4nra44jh00.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxkhhy2peul4nra44jh00.png" alt="'A simple gallery of 10 images'" width="800" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can take it a step further by wrapping our request into a function 'getImages', Now we can set this function to request images at different intervals, for example :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="c1"&gt;//getImages Function&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getImages&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://api.unsplash.com/photos/random?query=food&amp;amp;count=10&amp;amp;client_id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
     &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;regular&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Set interval&lt;/span&gt;
&lt;span class="nf"&gt;getImages&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getImages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are requesting new images at a 10-second interval (10,000 milliseconds).&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We have covered the basic aspects of fetching images, This can apply to other APIs aside from Unslpash, It's the same method involved, All you need is an API key to request the server. Now you can begin to implement this in your upcoming projects or apps.&lt;/p&gt;

&lt;p&gt;If you enjoyed the article, give me a follow here and on my &lt;a href="https://github.com/maxixo" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>api</category>
      <category>webdev</category>
      <category>unsplash</category>
    </item>
    <item>
      <title>How To Implement GridView Class in Flutter</title>
      <dc:creator>Usman</dc:creator>
      <pubDate>Sat, 02 Sep 2023 01:41:42 +0000</pubDate>
      <link>https://dev.to/maxixo/how-to-implement-gridview-class-in-flutter-10c4</link>
      <guid>https://dev.to/maxixo/how-to-implement-gridview-class-in-flutter-10c4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In Flutter development we often encounter different forms of designs which require specific elements to help facilitate a better user experience. One of these elements can come in the form of Grids and we need a 'GridView' class to implement that. There are other various widgets in Flutter but we will be talking about the 'GridView' class and its various constructors today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;p&gt;To get the most out of this guide, You should have a basic understanding of Flutter and have it installed on your device. If you’re unfamiliar with this I recommend visiting the original Flutter &lt;a href="https://docs.flutter.dev/get-started/install" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; to set up your device. You can also use an online Flutter editor (&lt;a href="https://flutlab.io/editor" rel="noopener noreferrer"&gt;Flutlab&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the GridView class
&lt;/h2&gt;

&lt;p&gt;As the name implies the GridView class is usually used when we want to implement a grid-like design. For example, if we want to design the user interface of a chessboard, we have the white and black squares across the whole board, another good example is photos in the gallery. These square boxes are grid-like designs. I will go in-depth on the various methods that are associated with this class and its constructors.  The GridView class has the main GridView builder,  GridView.count, GridView .custom and  GridView.extent. You have to note that there are certain limitations and benefits to each of the constructors, I will be discussing them in the sections below. Let's get into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use the GridView Class
&lt;/h2&gt;

&lt;p&gt;To utilize the most out of the GridView class, You need to have an idea of the items you intend to display on the screen. You must also be familiar with the terminologies used in this section of the article. Common terms and properties associated with the GridView class are :&lt;/p&gt;

&lt;p&gt;1 - itemCount: It determines the total number of items within the grid.&lt;/p&gt;

&lt;p&gt;2 - gridDelegate: It plays a pivotal role in defining the layout and appearance of the grid. This takes in two parameters which are :&lt;/p&gt;

&lt;p&gt;I.  SliverGridDelegateWithFixedCrossAxisCount: This creates grid layouts with a fixed number of tiles in the cross-axis.&lt;/p&gt;

&lt;p&gt;II.  SliverGridDelegateWithMaxCrossAxisExtent: This creates grid layouts with tiles that each have a maximum cross-axis extent.&lt;/p&gt;

&lt;p&gt;3 - crossAxisCount: This property defines the number of columns (or rows, depending on the scrolling direction) in the grid layout.&lt;/p&gt;

&lt;p&gt;4 - mainAxisSpacing: This property defines the spacing between items along the main axis (vertical spacing if the grid scrolls vertically, and horizontal spacing if the grid scrolls horizontally).&lt;/p&gt;

&lt;p&gt;5 - maxCrossAxisExtent: This property defines the spacing between items along the cross-axis (horizontal spacing if the grid scrolls vertically, and vertical spacing if the grid scrolls horizontally).&lt;/p&gt;

&lt;p&gt;Now it's time to jump into the coding aspect by analyzing each of the constructors under the GridView class below.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use GridView.count
&lt;/h2&gt;

&lt;p&gt;GridView.count constructor is a convenient way to create grid layouts with a fixed number of tiles across the cross-axis. It allows you to specify the number of columns in the grid, and Flutter automatically adjusts the layout based on the available space. It is the most basic way to invoke the GridView class and it uses the crossAxisCount parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GridViewCount&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;GridView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;crossAxisCount:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;Padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;padding:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;8.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;Padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;padding:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;8.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;yellow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;Padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;padding:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;8.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;yellow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;Padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;padding:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;8.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you run this code in your editor this is going to be the output :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1693497591158%2F1067f9e2-f0d9-4e66-a801-bacb17967baa.png%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1693497591158%2F1067f9e2-f0d9-4e66-a801-bacb17967baa.png%2520align%3D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To explain better, we are displaying a grid with four containers (2 blue, 2 yellow), We specified our grid to have two columns by using the crossAxisCount property and added some padding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of GridView.count
&lt;/h3&gt;

&lt;p&gt;It allows you to have precise control over the number of columns which in turn allows you to have complete control over the whole layout and it adapts automatically based on the available space, ensuring a responsive design.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations of GridView.count
&lt;/h3&gt;

&lt;p&gt;It is suitable for scenarios where you need a fixed number of columns and it's not advisable to use when you want a more dynamic layout over the design.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to use GridView.builder
&lt;/h2&gt;

&lt;p&gt;The GridView.builder constructor is a powerful tool that enables you to create dynamic grid layouts in Flutter. It's different from the basic GridView constructor, which requires you to provide a fixed number of items. It's best to use when working with large datasets or data generated on the go.&lt;/p&gt;

&lt;h3&gt;
  
  
  Components of GridView.builder
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;itemBuilder Function: This function is responsible for creating separate grid items, It takes two arguments (context, index) and should return a widget representing the content of the item at a given index&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;itemCount Property: This is a necessary property that specifies the total number of items in the Grid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;scrollDirection : This property is used to set the direction of scrolling the grid items, It can be set to vertical or horizontal.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's how to use it :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GridViewBuilder&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;GridView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;gridDelegate:&lt;/span&gt;
           &lt;span class="n"&gt;SliverGridDelegateWithFixedCrossAxisCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;crossAxisCount:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nl"&gt;itemCount:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;scrollDirection:&lt;/span&gt; &lt;span class="n"&gt;Axis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;vertical&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;itemBuilder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;padding:&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;8.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xff6c5f5f&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'My item'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;textAlign:&lt;/span&gt; &lt;span class="n"&gt;TextAlign&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;center&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt; 
          &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1693497715048%2Fa39ac619-de98-4ce3-bc41-32c571349a34.png%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1693497715048%2Fa39ac619-de98-4ce3-bc41-32c571349a34.png%2520align%3D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the code above, You will notice some properties that were added after the GridView.builder constructor was introduced. Properties added were the “ItemCount”, “itemBuilder”, "scrollDirection". Now in our example, we’re using the constructor to create a GridView that has a gridDelegate with a fixed cross-axis count (2 columns), while setting the itemcount to 32 to produce a total of 32 containers as children with some padding and finally we set the scrollDirection to vertical. These new properties introduced are the main components of using the GridView.builder constructor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of using GridView.builder
&lt;/h3&gt;

&lt;p&gt;GridView.builder generates items when they are needed and you can work with data sources of varying length without needing to modify the layout code. It provides smooth scrolling even with a significant number of items.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to use GridView.extent
&lt;/h2&gt;

&lt;p&gt;The  GridView.extent constructor is suitable for producing grid layouts where each size of each grid item is determined by the maximum extent it can occupy along the cross axis. It's mostly useful when you want a specific size for each item regardless of the screen size.  You always have to specify the maximum cross-axis extent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GridViewExtent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;GridView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;extent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;maxCrossAxisExtent:&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;padding:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;8.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;purple&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Item &lt;/span&gt;&lt;span class="si"&gt;${index + 1}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1693517557095%2F57cb395c-b86d-469b-bc27-9dac83916f13.png%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1693517557095%2F57cb395c-b86d-469b-bc27-9dac83916f13.png%2520align%3D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the example above, We are displaying a grid with a maxCrossAxisExtent of 150, and the grid is to display a list of 12 generated items across the whole layout with some padding on each item.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of GridView.extent
&lt;/h3&gt;

&lt;p&gt;It ensures each grid has consistent sizes regardless of screen size, layout is automatically managed which makes the interface more responsive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations of GridView.extent
&lt;/h3&gt;

&lt;p&gt;It is suitable for scenarios where you want a consistent item size, but it may not be the best choice if you need more dynamic control over item generation or layout.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to use GridView.custom
&lt;/h2&gt;

&lt;p&gt;The GridView.custom constructor is the most flexible one out of all the constructors as it allows you to control every aspect of the widget, making it suitable for complex scenarios where the arrangements need to meet specific requirements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GridViewCustom&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;GridView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;custom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;gridDelegate:&lt;/span&gt; &lt;span class="n"&gt;SliverGridDelegateWithFixedCrossAxisCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;crossAxisCount:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;mainAxisSpacing:&lt;/span&gt; &lt;span class="mf"&gt;16.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;crossAxisSpacing:&lt;/span&gt; &lt;span class="mf"&gt;16.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;childrenDelegate:&lt;/span&gt; &lt;span class="n"&gt;SliverChildBuilderDelegate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;color:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Item &lt;/span&gt;&lt;span class="si"&gt;${index + 1}&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="nl"&gt;childCount:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1693526937442%2F0003817a-d2d1-4928-aafb-b8faabc2522a.png%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1693526937442%2F0003817a-d2d1-4928-aafb-b8faabc2522a.png%2520align%3D" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of GridView.custom
&lt;/h3&gt;

&lt;p&gt;This constructor allows you to control the layout and is very adaptive when working with a large set of complex data that depends on complex logic such as data manipulation. The constructor also recycles items off the screen for optimal performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations of GridView.custom
&lt;/h3&gt;

&lt;p&gt;It is more intricate and complex to set up. It is only used when custom item generation and or complex layouts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Now that you know the various methods of incorporating the GridView class, the benefits, and the limitations involved, You can begin to apply it in your next project, and fully implement its constructors when needed to optimize your designs and to give a better user experience.&lt;/p&gt;

&lt;p&gt;If you enjoyed the article, You can give me a follow on &lt;a href="https://github.com/maxixo" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>webdev</category>
      <category>web</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
