# Core Architecture Standards for Bulma
This document defines the core architecture standards for developing maintainable, performant, and scalable web applications with the Bulma CSS framework. It focuses on architectural patterns, project structure, and organization principles that should be adhered to by all developers. These standards aim to promote consistency, readability, and long-term maintainability of Bulma-based projects.
## 1. Project Structure and Organization
A well-defined project structure is crucial for managing complexity and ensuring that the codebase remains organized as the project grows.
### 1.1. Directory Structure
**Do This:**
* Adopt a modular and component-based project structure. Organize your files and dependencies into logical modules or feature areas.
* Maintain clear separation of concerns: HTML templates, CSS/Sass styles, and JavaScript logic should reside in distinct directories.
* Use a "src" directory to house all source code, separating it from build artifacts and configuration files.
**Don't Do This:**
* Avoid a flat directory structure where all files are placed in a single directory.
* Don't mix HTML, CSS/Sass, and JavaScript files within the same directory unless there is a specific valid reason and it concerns a single component.
**Why:**
* **Maintainability:** A modular structure makes it easier to locate, understand, and modify specific parts of the application.
* **Scalability:** Clear separation of concerns allows for independent scaling and modular testing of individual components of the application.
* **Collaboration:** A standardized directory structure facilitates collaboration among developers by providing a common ground for finding and contributing code.
**Example:**
"""
project-root/
├── src/
│ ├── assets/ # Static assets (images, fonts, etc.)
│ ├── components/ # Reusable Bulma components
│ │ ├── navbar/ # Example component: Navbar
│ │ │ ├── navbar.html
│ │ │ ├── navbar.scss
│ │ │ └── navbar.js
│ │ ├── button/ # Example Component: Button
│ │ │ ├── button.html
│ │ │ ├── button.scss
│ │ │ └── button.js
│ ├── styles/ # Global stylesheets and Bulma customizations
│ │ ├── main.scss # Main stylesheet importing all modules
│ │ └── _variables.scss # Custom Bulma variables
│ ├── scripts/ # Main JavaScript files
│ │ └── main.js
│ ├── index.html # Main HTML file
│ └── app.js # Main app javascript file
├── dist/ # Build artifacts
├── node_modules/ # Node modules
├── package.json
├── webpack.config.js
└── README.md
"""
### 1.2. Naming Conventions
**Do This:**
* Use consistent and descriptive names for files, directories, and variables. File names should clearly indicate the component or module they contain.
* Adopt a naming convention (e.g., BEM) for CSS classes to improve readability and avoid naming conflicts.
* Use lowercase and hyphens (-) for CSS class names (e.g., "navbar-item", "button-primary").
* Use camelCase for JavaScript variables and functions (e.g., "initNavbar", "handleButtonClick").
**Don't Do This:**
* Avoid cryptic or ambiguous names that don't convey the purpose of the element.
* Don't use inconsistent naming conventions across the project.
* Don't use underscores (_) in CSS class names.
**Why:**
* **Readability:** Consistent naming conventions make the codebase easier to read and understand.
* **Maintainability:** Descriptive names make it easier to locate and modify specific elements in the code.
* **Collaboration:** Standardized naming conventions ensure that all developers use the same language when referring to elements in the codebase.
**Example:**
"""html
Click me
"""
"""scss
/* styles/components/_button.scss */
.button {
padding: 10px 20px;
border: none;
cursor: pointer;
&.button-primary {
background-color: blue;
color: white;
}
}
"""
"""javascript
// scripts/components/button.js
function handleButtonClick() {
console.log('Button clicked!');
}
const primaryButtons = document.querySelectorAll(".button-primary");
primaryButtons.forEach(button => {
button.addEventListener('click', handleButtonClick);
});
"""
## 2. Bulma Customization and Extension
Bulma is designed to be easily customizable and extensible. Understanding how to properly modify Bulma's default styles and components is critical for building consistent and maintainable applications.
### 2.1. Using Bulma Variables
**Do This:**
* Leverage Bulma's Sass variables to customize the framework's appearance (colors, fonts, spacing, etc).
* Create a dedicated "_variables.scss" file in your "styles" directory to override the default variables.
* Import your "_variables.scss" file *before* importing the Bulma stylesheet.
**Don't Do This:**
* Avoid directly modifying the Bulma source files. Customizations should be done through variable overrides.
* Don't hardcode values in your CSS that conflict with Bulma's design system.
**Why:**
* **Maintainability:** Variable overrides allow you to update the look and feel of your application without modifying the Bulma source code. This makes it easier to upgrade to newer versions of Bulma.
* **Consistency:** Using variables ensures that styles are consistent across the application and follows the design system.
* **Theming:** Variable overrides allow you to easily create different themes for your application.
**Example:**
"""scss
/* styles/_variables.scss */
$primary: #209CEE;
$secondary: #7949d5;
$family-sans-serif: "Nunito", sans-serif;
"""
"""scss
/* styles/main.scss */
@import "variables"; // Import custom variables BEFORE bulma
@import "~bulma/sass/bulma";
"""
### 2.2. Extending Bulma with Custom Components
**Do This:**
* Create new components in separate files within the "components" directory.
* Use Bulma's existing classes as a foundation for your custom components.
* Leverage Sass mixins and functions to generate consistent styles.
**Don't Do This:**
* Don't apply inline styles directly to HTML elements unless absolutely necessary.
* Avoid overwriting Bulma's core styles unless there is a compelling reason to do so.
**Why:**
* **Reusability:** Custom components promote code reuse.
* **Consistency:** Leverages Bulma's styles for a consistent look and feel.
* **Maintainability:** Easier to update and maintain custom components when they are separate and well-defined.
**Example:**
"""scss
/* styles/components/_custom-card.scss */
.custom-card {
@extend .card; // Inheriting Bulma's card styles
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
.card-header {
background-color: $primary; // Use custom Bulma variable
color: white;
font-weight: bold;
}
.card-content {
padding: 1.5rem;
}
}
"""
"""html
<p>
Custom Card Title
</p>
<p>This is the content of the card. Uses a custom Bulma variable.</p>
"""
### 2.3. Using Bulma Modifiers and Helpers
**Do This:**
* Understand and utilize Bulma's modifier classes (e.g., ".is-primary", ".is-small") and helper classes (e.g., ".has-text-centered", ".is-hidden") to control element appearance and behavior.
* Use modifier classes to create variations of standard Bulma components (e.g., a primary-colored button). Use helper classes for utility purposes like text alignment and visibility control.
**Don't Do This:**
* Don't create custom CSS classes that duplicate the functionality of Bulma's modifier and helper classes.
* Avoid overusing custom styles when Bulma provides built-in options.
**Why:**
* **Efficiency:** Reduces the amount of custom CSS required.
* **Consistency:** Ensures that styles are consistent with Bulma's design system and provides a uniform look across the application.
* **Readability:** Makes the HTML code more concise and easier to understand.
**Example:**
"""html
Submit
<p>This text is centered.</p>
"""
## 3. JavaScript Integration
Bulma is primarily a CSS framework, but it often requires JavaScript for interactive components.
### 3.1. Decoupling JavaScript from HTML
**Do This:**
* Separate JavaScript logic from HTML markup. Place JavaScript code in separate ".js" files and use event listeners to attach behavior to DOM elements.
* Use data attributes ("data-*") to store component-specific data within HTML elements.
**Don't Do This:**
* Avoid inline JavaScript (e.g., "") as it pollutes the HTML and makes it harder to maintain.
* Don't directly manipulate the DOM without proper event handling and error checking.
**Why:**
* **Maintainability:** Separating JavaScript makes the code easier to read, understand, and debug.
* **Reusability:** JavaScript code can be reused across multiple components.
* **Testability:** Separated JavaScript logic is easier to test.
**Example:**
"""html
Home
Documentation
"""
"""javascript
// scripts/components/navbar.js
document.addEventListener('DOMContentLoaded', () => {
// Get all "navbar-burger" elements
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
// Add a click event on each of them
$navbarBurgers.forEach( el => {
el.addEventListener('click', () => {
// Get the "data-target" attribute from the "navbar-burger" element
const target = el.dataset.target;
const $target = document.getElementById(target);
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle('is-active');
$target.classList.toggle('is-active');
});
});
});
"""
### 3.2. Using a JavaScript Framework or Library
**Do This:**
* Consider using a JavaScript framework or library (e.g., React, Vue.js, Angular) to manage Bulma components and create complex user interfaces.
* Choose a framework that aligns with the complexity of your project and the skill set of your team.
**Don't Do This:**
* Avoid using a framework if it's not necessary for the project.
* Don't over-engineer simple interactions with complex JavaScript frameworks. Bulma's simplicity should be complemented, not complicated.
**Why:**
* **Componentization:** JavaScript frameworks provide a structured way to organize components and manage their state.
* **Data Binding:** Simplifies the process of updating the UI in response to data changes.
* **Rich Interactions:** Enables the creation of complex user interfaces and interactive components.
**Example (Vue.js):**
"""vue
// Navbar.vue
"""
## 4. Performance Optimization
Optimizing the performance of Bulma-based applications is essential for providing a smooth user experience.
### 4.1. Minifying and Compressing Assets
**Do This:**
* Minify CSS and JavaScript files to reduce their size. Use tools like CSSNano or Terser to remove unnecessary characters and whitespace from the code.
* Compress assets (images, fonts, etc.) to reduce their download time.
* Enable Gzip compression on your web server to further reduce the size of transferred assets.
**Don't Do This:**
* Don't deploy unminified and uncompressed assets to production.
* Don't use overly large images or unoptimized fonts.
**Why:**
* **Faster Load Times:** Reduces the amount of data that needs to be downloaded, resulting in faster page load times.
* **Improved User Experience:** Faster loading websites provide a better user experience.
**Example (Webpack Configuration):**
"""javascript
const TerserPlugin = require("terser-webpack-plugin");
const CSSMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
//... other config options
optimization: {
minimize: true,
minimizer: [
new TerserPlugin(),
new CSSMinimizerPlugin(),
],
},
};
"""
### 4.2. Code Splitting
**Do This:**
* Implement code splitting to break down JavaScript code into smaller chunks that can be loaded on demand.
* Use dynamic imports to load modules only when they are needed.
**Don't Do This:**
* Don't load all JavaScript code upfront, especially for large applications with many components.
* Avoid creating large monolithic JavaScript bundles.
**Why:**
* **Improved Initial Load Time:** Loads only the necessary code upfront, reducing initial load time.
* **Reduced Bandwidth Consumption:** Only downloads code that is actually used.
* **Better User Experience:** Results in a faster and more responsive user experience.
**Example:**
"""javascript
// scripts/main.js
async function loadComponent() {
const { MyComponent } = await import('./components/my-component');
// Use MyComponent
}
loadComponent();
"""
### 4.3. Lazy Loading Images
**Do This:**
* Implement lazy loading for images to defer the loading of images that are not initially visible in the viewport.
* Use the "loading="lazy"" attribute on "" tags to enable native lazy loading.
**Don't Do This:**
* Don't load all images upfront, especially for pages with many images.
* Avoid using very large images that are not properly optimized for the web.
**Why:**
* **Improved Initial Load Time:** Loads only the images that are visible in the viewport, reducing initial load time.
* **Reduced Bandwidth Consumption:** Only downloads images that are actually needed.
* **Better User Experience:** Results in a faster and more responsive user experience.
**Example:**
"""html
"""
## 5. Accessibility (A11y)
Accessibility is a crucial aspect of modern web development. Ensure your Bulma-based applications are usable by people with disabilities.
### 5.1. Semantic HTML
**Do This:**
* Use semantic HTML elements (e.g., "", "", "", "") to structure the content of your pages.
* Use proper heading levels ("" - "") to create a logical document outline.
* Use ARIA attributes to enhance the accessibility of interactive components.
**Don't Do This:**
* Avoid using generic "" and "" elements for everything.
* Don't rely solely on CSS for conveying meaning or structure.
**Why:**
* **Improved Screen Reader Compatibility:** Screen readers rely on semantic HTML to understand the structure and content of a page.
* **Better SEO:** Search engines also use semantic HTML to understand the content of a page.
* **Enhanced Usability:** Semantic HTML makes the code more readable and maintainable.
**Example:**
"""html
Home
About
Contact
Article Title
<p>Article content...</p>
"""
### 5.2. ARIA Attributes
**Do This:**
* Use ARIA attributes to provide additional information to assistive technologies about the role, state, and properties of interactive elements.
* Use "aria-label" to provide a descriptive label for elements that don't have visible text labels.
* Use "aria-live" to announce dynamic content updates to screen readers.
**Don't Do This:**
* Don't overuse ARIA attributes. Use semantic HTML whenever possible.
* Don't provide conflicting or inaccurate information with ARIA attributes. "role=button" on an "" tag that doesn't actually act like a button, for instance.
**Why:**
* **Improved Accessibility:** ARIA attributes fill the gaps in native HTML and provide additional information to assistive technologies.
* **Enhanced User Experience:** Makes the application more usable for people with disabilities.
**Example:**
"""html
×
"""
### 5.3. Color Contrast
**Do This:**
* Ensure sufficient color contrast between text and background colors to meet WCAG guidelines.
* Use a color contrast checker to verify that your color combinations meet accessibility standards.
**Don't Do This:**
* Don't use low-contrast color combinations that are difficult to read for people with visual impairments. Always test!
* Avoid relying solely on color to convey important information. Colors can not be the only indicator, as colorblind users will not be able to benefit.
**Why:**
* **Improved Readability:** High color contrast makes the text easier to read for everyone.
* **Accessibility for Visual Impairments:** Ensures that the application is usable for people with low vision.
* **Compliance:** Meeting WCAG guidelines is often a legal requirement.
**Example:**
"""scss
/* styles/_variables.scss */
$primary: #209CEE; //Primary Color
$primary-invert: #fff; //Invert Color
"""
## 6. Security Best Practices
Security is paramount in web development. Adopt these practices to protect your Bulma applications.
### 6.1. Input Validation
**Do This:**
* Validate all user inputs on both the client and server sides to prevent malicious data from being processed.
* Sanitize user inputs to remove potentially harmful characters or code.
**Don't Do This:**
* Don't trust user inputs without validation. Assume all user inputs are potentially malicious.
* Don't rely solely on client-side validation, as it can be easily bypassed.
**Why:**
* **Prevention of Cross-Site Scripting (XSS) Attacks:** Input validation can prevent attackers from injecting malicious scripts into your application.
* **Prevention of SQL Injection Attacks:** Input validation can prevent attackers from manipulating database queries.
* **Data Integrity:** Ensures that only valid data is stored in your database.
### 6.2. Cross-Site Scripting (XSS) Protection
**Do This:**
* Use a Content Security Policy (CSP) to control the sources from which the browser is allowed to load resources.
* Escape user-generated content when displaying it on the page to prevent XSS attacks.
* Avoid using "eval()" or other methods that execute arbitrary JavaScript code.
**Don't Do This:**
* Don't allow users to inject arbitrary HTML or JavaScript code into your application.
* Don't disable XSS protection features in your web server or framework.
**Why:**
* **Protection Against XSS Attacks:** CSP and output escaping can prevent attackers from injecting malicious scripts into your application.
* **Enhanced Security:** Reduces the attack surface of your application.
### 6.3. Dependencies Management
**Do This:**
* Keep your Bulma and other dependencies up to date to patch security vulnerabilities.
* Use a dependency management tool (e.g., npm, yarn) to manage your project's dependencies.
* Regularly audit your dependencies for known vulnerabilities.
**Don't Do This:**
* Don't use outdated versions of Bulma or other dependencies.
* Don't install dependencies from untrusted sources.
**Why:**
* **Security Vulnerability Patching:** Updating dependencies ensures that security vulnerabilities are patched.
* **Improved Stability:** Newer versions of dependencies often include bug fixes and performance improvements.
* **Reduced Risk of Attacks:** Using up-to-date dependencies reduces the attack surface of your application.
## 7. Testing
Thoroughly test your Bulma-based applications to ensure they function properly and provide a good user experience.
### 7.1. Unit Testing
**Do This:**
* Write unit tests for individual components and functions.
* Use a testing framework (e.g., Jest, Mocha) to automate the testing process.
* Aim for high code coverage to ensure that most of the code is tested.
**Don't Do This:**
* Don't skip unit testing, especially for critical components and functions.
* Don't write tests that are too tightly coupled to the implementation details.
**Why:**
* **Early Bug Detection:** Unit tests can detect bugs early in the development process.
* **Code Quality Assurance:** Ensures that individual components and functions work as expected.
* **Refactoring Safety:** Provides confidence when refactoring code.
### 7.2. End-to-End Testing
**Do This:**
* Write end-to-end tests to simulate user interactions with the application.
* Use a testing framework (e.g., Cypress, Selenium) to automate the testing process.
* Test critical user flows to ensure that the application functions correctly in a real-world environment.
**Don't Do This:**
* Don't rely solely on manual testing.
* Don't neglect end-to-end testing, especially for complex applications with many user interactions.
**Why:**
* **Real-World Testing:** Simulates user interactions and tests the application in a real-world environment.
* **Detection of Integration Issues:** Identifies issues that may arise when different components of the application interact.
* **User Experience Assurance:** Ensures that the application provides a good user experience.
### 7.3. Accessibility Testing
**Do This:**
* Test your applications for accessibility issues using automated tools and manual reviews.
* Use accessibility checkers to verify that your color combinations meet WCAG guidelines.
* Use screen readers to test the accessibility of your applications for people with visual impairments.
**Don't Do This:**
* Don't ignore accessibility testing.
* Don't rely solely on automated tools for accessibility testing.
**Why:**
* **Accessibility Compliance:** Ensures that the application meets accessibility standards.
* **Improved Usability:** Makes the application more usable for people with disabilities.
* **Ethical Responsibility:** Accessibility is often a legal and ethical requirement.
danielsogl
Created Mar 6, 2025
This guide explains how to effectively use .clinerules
with Cline, the AI-powered coding assistant.
The .clinerules
file is a powerful configuration file that helps Cline understand your project's requirements, coding standards, and constraints. When placed in your project's root directory, it automatically guides Cline's behavior and ensures consistency across your codebase.
Place the .clinerules
file in your project's root directory. Cline automatically detects and follows these rules for all files within the project.
# Project Overview project: name: 'Your Project Name' description: 'Brief project description' stack: - technology: 'Framework/Language' version: 'X.Y.Z' - technology: 'Database' version: 'X.Y.Z'
# Code Standards standards: style: - 'Use consistent indentation (2 spaces)' - 'Follow language-specific naming conventions' documentation: - 'Include JSDoc comments for all functions' - 'Maintain up-to-date README files' testing: - 'Write unit tests for all new features' - 'Maintain minimum 80% code coverage'
# Security Guidelines security: authentication: - 'Implement proper token validation' - 'Use environment variables for secrets' dataProtection: - 'Sanitize all user inputs' - 'Implement proper error handling'
Be Specific
Maintain Organization
Regular Updates
# Common Patterns Example patterns: components: - pattern: 'Use functional components by default' - pattern: 'Implement error boundaries for component trees' stateManagement: - pattern: 'Use React Query for server state' - pattern: 'Implement proper loading states'
Commit the Rules
.clinerules
in version controlTeam Collaboration
Rules Not Being Applied
Conflicting Rules
Performance Considerations
# Basic .clinerules Example project: name: 'Web Application' type: 'Next.js Frontend' standards: - 'Use TypeScript for all new code' - 'Follow React best practices' - 'Implement proper error handling' testing: unit: - 'Jest for unit tests' - 'React Testing Library for components' e2e: - 'Cypress for end-to-end testing' documentation: required: - 'README.md in each major directory' - 'JSDoc comments for public APIs' - 'Changelog updates for all changes'
# Advanced .clinerules Example project: name: 'Enterprise Application' compliance: - 'GDPR requirements' - 'WCAG 2.1 AA accessibility' architecture: patterns: - 'Clean Architecture principles' - 'Domain-Driven Design concepts' security: requirements: - 'OAuth 2.0 authentication' - 'Rate limiting on all APIs' - 'Input validation with Zod'
# State Management Standards for Bulma This document outlines best practices for managing application state within a Bulma-based project. Bulma, being a CSS framework, doesn't inherently handle state management. Therefore, we must rely on external JavaScript libraries and patterns to create dynamic and interactive user interfaces. The goal is to build maintainable, scalable, and performant applications. These standards apply specifically to how state management interacts with and enhances Bulma's styling and components. ## 1. Guiding Principles * **Unidirectional Data Flow:** Data flows in a single direction, making debugging and understanding data changes simpler. This is generally achieved with a component tree where data updates are passed down and events are notified up. * **Separation of Concerns:** Separate the presentation layer (Bulma's CSS & HTML structure) from the application logic and state management. This makes the application more modular and testable. * **Predictable State:** State changes should be predictable, using clearly defined actions. * **Immutability:** Favor immutability when managing state to prevent unexpected side effects and facilitate easier debugging. Immutable data structures ensure that once created, they cannot be changed. This is a core tenet of robust state management. * **Performance:** Avoid unnecessary re-renders by strategically managing state updates and leveraging component memoization techniques. Optimize data structures for efficient lookups and updates. How this impacts Bulma styling should be considered (e.g., avoid frequent class name changes that trigger style recalculations). ## 2. State Management Approaches Several state management libraries integrate well with Bulma. The choice depends on project complexity and team familiarity. ### 2.1. Component-Local State (React useState, Vue Ref, etc.) * **Description:** Each component manages its own state. Suitable for small, self-contained components with limited interactivity. * **Do This:** Use component-local state for simple interactions, such as toggling a Bulma modal's visibility or managing form input values directly within the component displaying the input. * **Don't Do This:** Overuse component-local state for data shared across multiple, unrelated components. This leads to prop drilling and difficult-to-manage state. **Example (React):** """jsx import React, { useState } from 'react'; function BulmaModal() { const [isActive, setIsActive] = useState(false); const toggleModal = () => { setIsActive(!isActive); }; return ( <div> <button className="button" onClick={toggleModal}> Toggle Modal </button> <div className={"modal ${isActive ? 'is-active' : ''}"}> <div className="modal-background"></div> <div className="modal-content"> <p>Modal content goes here.</p> </div> <button className="modal-close is-large" aria-label="close" onClick={toggleModal}></button> </div> </div> ); } export default BulmaModal; """ **Why:** Simplifies component logic for isolated UI elements. The CSS class updates in conjunction with user clicks is well handled in one component. ### 2.2. Context API (React) / Provide/Inject (Vue) * **Description:** Provides a way to pass data through the component tree without having to pass props down manually at every level. * **Do This:** Use for application-wide state that many components need access to, such as user authentication status, theme preferences, or language settings. For example, storing a "theme" object and updating Bulma class names based on the "theme" variables. * **Don't Do This:** Using context to store data that changes frequently, especially if components that consume the context are deeply nested. This can cause unnecessary re-renders. * **Performance Note:** Be mindful of the consumer components. When the context value changes, all components consuming the context will re-render. **Example (React):** """jsx import React, { createContext, useContext, useState } from 'react'; const ThemeContext = createContext(); function ThemeProvider({ children }) { const [theme, setTheme] = useState({ primaryColor: 'is-primary', textColor: 'has-text-dark', }); const toggleTheme = () => { setTheme((prevTheme) => ({ primaryColor: prevTheme.primaryColor === 'is-primary' ? 'is-info' : 'is-primary', textColor: prevTheme.textColor === 'has-text-dark' ? 'has-text-light' : 'has-text-dark', })); }; return ( <ThemeContext.Provider value={{ theme, toggleTheme }}> {children} </ThemeContext.Provider> ); } function ThemedButton() { const { theme, toggleTheme } = useContext(ThemeContext); return ( <button className={"button ${theme.primaryColor}"} onClick={toggleTheme}> Toggle Theme </button> ); } function ThemedText({ children }) { const { theme } = useContext(ThemeContext); return <p className={theme.textColor}>{children}</p>; } function App() { return ( <ThemeProvider> <div className="container"> <ThemedButton /> <ThemedText>This is some themed text.</ThemedText> </div> </ThemeProvider> ); } export default App; """ **Why:** Context API simplifies accessing shared state values across multiple components without prop drilling, leading to organized theming and styling. "ThemedButton" uses the "primaryColor" variable to update a Bulma button. "ThemedText" applies a text color. When the "ThemeContext" is updated via "toggleTheme" all consuming components (in this case "ThemedButton" and "ThemedText") will rerender. ### 2.3. Redux * **Description:** A predictable state container for JavaScript apps. Centralizes the application state in a single store, making it easier to manage and debug. * **Do This:** Use for complex applications with substantial state and data interactions across many views. Good for managing global application data (e.g., user profiles, shopping cart contents, complex filter states). * **Don't Do This:** Overuse Redux for small single-page applications where component-local state or Context API would suffice. Introduces boilerplate and complexity. **Example (React with Redux):** """jsx // actions.js export const SET_MODAL_ACTIVE = 'SET_MODAL_ACTIVE'; export const setModalActive = (isActive) => ({ type: SET_MODAL_ACTIVE, payload: isActive, }); // reducer.js const initialState = { isModalActive: false, }; function modalReducer(state = initialState, action) { switch (action.type) { case SET_MODAL_ACTIVE: return { ...state, isModalActive: action.payload, }; default: return state; } } export default modalReducer; // store.js import { configureStore } from '@reduxjs/toolkit'; import modalReducer from './reducer'; const store = configureStore({ reducer: { modal: modalReducer, }, }); export default store; // BulmaModal.jsx import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { setModalActive } from './actions'; function BulmaModal() { const dispatch = useDispatch(); const isModalActive = useSelector((state) => state.modal.isModalActive); const toggleModal = () => { dispatch(setModalActive(!isModalActive)); }; return ( <div> <button className="button" onClick={toggleModal}> Toggle Modal </button> <div className={"modal ${isModalActive ? 'is-active' : ''}"}> <div className="modal-background"></div> <div className="modal-content"> <p>Modal content goes here.</p> </div> <button className="modal-close is-large" aria-label="close" onClick={toggleModal}></button> </div> </div> ); } export default BulmaModal; // App.jsx import React from 'react'; import { Provider } from 'react-redux'; import store from './store'; import BulmaModal from './BulmaModal'; function App() { return ( <Provider store={store}> <BulmaModal /> </Provider> ); } export default App; """ **Why:** Redux centralizes state management allowing components across the application to access and modify the state in a predictable way. In this case, a centrally controlled "isModalActive" dictates the Bulma modal's open/close state. ### 2.4. Zustand * **Description:** A small, fast, and scalable bearbones state-management solution using simplified flux principles. Less boilerplate than Redux. * **Benefits:** Lightweight and easy to learn. Can integrate well with React and other frameworks. Improves productivity. **Example:** """jsx import React from 'react'; import { create } from 'zustand' const useStore = create((set) => ({ isModalActive: false, toggleModal: () => set((state) => ({ isModalActive: !state.isModalActive })), })) function BulmaModal() { const { isModalActive, toggleModal } = useStore() return ( <div> <button className="button" onClick={toggleModal}> Toggle Modal </button> <div className={"modal ${isModalActive ? 'is-active' : ''}"}> <div className="modal-background"></div> <div className="modal-content"> <p>Modal content goes here.</p> </div> <button className="modal-close is-large" aria-label="close" onClick={toggleModal}></button> </div> </div> ); } export default BulmaModal; """ **Why:** Zustand offers a simpler approach than Redux, reducing boilerplate and enabling easier state updates for Bulma components. The state definition and modifiers are colocated with the component, making the code more maintainable in certain cases. ### 2.5. MobX * **Description:** Uses reactive functions to automatically update relevant components when state changes. * **Do This:** Consider for applications requiring fine-grained reactivity and automatic dependency tracking. * **Don't Do This:** Avoid if you prefer more explicit control over state updates and data flow. Can be harder to debug initially due to its "magic". **Example (React with MobX):** """jsx import React from 'react'; import { makeObservable, observable, action } from 'mobx'; import { observer } from 'mobx-react-lite'; class ModalState { isModalActive = false; constructor() { makeObservable(this, { isModalActive: observable, toggleModal: action }); } toggleModal = () => { this.isModalActive = !this.isModalActive; } } const modalState = new ModalState(); const BulmaModal = observer(() => { return ( <div> <button className="button" onClick={modalState.toggleModal}> Toggle Modal </button> <div className={"modal ${modalState.isModalActive ? 'is-active' : ''}"}> <div className="modal-background"></div> <div className="modal-content"> <p>Modal content goes here.</p> </div> <button className="modal-close is-large" aria-label="close" onClick={modalState.toggleModal}></button> </div> </div> ); }); export default BulmaModal; """ **Why:** MobX enables reactive updates to Bulma style classes. Changes to "modalState.isModalActive" automatically trigger a re-render for the modal. ### 2.6. Vuex * **Description:** Vue’s official state management library. Follows the Flux pattern with a central store, mutations, actions, and getters. * **Do This:** Use for medium to large Vue applications that need a centralized and predictable state management solution especially useful in areas where Bulma components are being dynamically composed and styled. * **Don't Do This:** For small projects, the overhead of setting up Vuex might outweigh its benefits. **Example (Vue with Vuex):** """vue // store.js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { isModalActive: false }, mutations: { setModalActive (state, payload) { state.isModalActive = payload } }, actions: { toggleModal ({ commit, state }) { commit('setModalActive', !state.isModalActive) } }, getters: { isModalActive: state => state.isModalActive } }) // BulmaModal.vue <template> <div> <button class="button" @click="toggleModal"> Toggle Modal </button> <div class="modal" :class="{'is-active': isModalActive}"> <div class="modal-background"></div> <div class="modal-content"> <p>Modal content goes here.</p> </div> <button class="modal-close is-large" aria-label="close" @click="toggleModal"></button> </div> </div> </template> <script> import { mapGetters, mapActions } from 'vuex' export default { computed: { ...mapGetters(['isModalActive']) }, methods: { ...mapActions(['toggleModal']) } } </script> // App.vue <template> <div id="app"> <BulmaModal /> </div> </template> <script> import BulmaModal from './components/BulmaModal.vue' export default { components: { BulmaModal } } </script> """ **Why:** Vuex provides structured state management in Vue apps, allowing centralized control over "isModalActive", impacting Bulma's "is-active" class. ## 3. Data Fetching and Caching * **Description:** How your application retrieves and stores data from external sources (e.g., APIs). * **Do This:** * Use libraries like "axios", "fetch", or "swr" (for React) for network requests. * Implement caching strategies to reduce API calls. * Handle loading and error states gracefully using Bulma's progress bars, loading spinners, or notification components. * **Don't Do This:** Make direct API calls inside components without managing loading states, or error handling. Don't store sensitive data (e.g., API keys) directly in the client-side code. **Example (React with "swr" and Bulma loading state):** """jsx import React from 'react'; import useSWR from 'swr'; const fetcher = (...args) => fetch(...args).then((res) => res.json()); function UserProfile() { const { data, error } = useSWR('/api/user', fetcher); if (error) return <div>Failed to load</div>; if (!data) return <progress className="progress is-small is-primary" max="100">15%</progress>; // Bulma loading indicator return ( <div> <h1>{data.name}</h1> <p>{data.email}</p> </div> ); } export default UserProfile; """ **Why:** "swr" handles caching and revalidation, improving performance. Bulma's "progress" component provides visual feedback during data loading. Improves the UX. ## 4. Immutability * **Description:** Treating data as immutable ensures that it cannot be modified after creation. Instead, new copies are created with the required changes. * **Do This:** * Use immutable data structures from libraries like "Immutable.js". * When updating arrays or objects, make use of spread syntax ("...") or "Array.map()", "Array.filter()", "Object.assign()". * **Don't Do This:** Directly modifying existing objects or arrays. This leads to unpredictable behavior and difficulties in debugging. **Example (Array update using spread syntax):** """javascript const originalArray = [1, 2, 3]; const newArray = [...originalArray, 4]; // Creates a new array [1, 2, 3, 4] """ **Example (Object update using spread syntax):** """javascript const originalObject = { name: 'John', age: 30 }; const newObject = { ...originalObject, age: 31 }; // Creates a new object { name: 'John', age: 31 } """ **Why:** Improves predictability by clearly defining the impact of changes, especially when working with complex Bulma-styled components. Makes debugging easier as you can easily track where state changes occur. Enables easier state reconciliation in complex applications. ## 5. Integrating with Bulma * **Bulma's Responsiveness:** When managing state, consider Bulma's responsive design principles. Update state based on screen size or device orientation to adapt the layout dynamically. For example, managing visibility of elements for mobile vs. desktop. * **Bulma Components State:** Use state to control the "is-active", "is-loading", "is-disabled", and other modifiers that control Bulma component appearance and behavior. * **Custom Theming:** Manage theme variables in your state and dynamically apply the appropriate Bulma classes based on these variables. **Example (Managing visibility based on screen size):** """jsx import React, { useState, useEffect } from 'react'; function ResponsiveComponent() { const [isMobile, setIsMobile] = useState(window.innerWidth < 768); // Bulma's breakpoint below tablet useEffect(() => { const handleResize = () => { setIsMobile(window.innerWidth < 768); }; window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); }; }, []); return ( <div className={" ${isMobile ? 'is-hidden-desktop' : 'is-hidden-mobile'}"}> {isMobile ? 'This is visible on mobile' : 'This is visible on desktop'} </div> ); } export default ResponsiveComponent; """ **Why:** Provides responsive design adhering to the principles of mobile first, making the site usable at different screen sizes. The "is-hidden-desktop" and "is-hidden-mobile" are Bulma utility classes. ## 6. Testing * **Unit Tests:** Test individual components and state management logic (reducers, actions, etc.) in isolation. * **Integration Tests:** Test how components interact with each other and the state management system. * **End-to-End Tests:** Test the entire application flow from the user's perspective. **Example (Simple Unit Test - React with Jest):** """javascript // BulmaModal.test.js import React from 'react'; import { render, fireEvent } from '@testing-library/react'; import BulmaModal from './BulmaModal'; import { Provider } from 'react-redux'; import store from './store'; test('Toggles modal visibility on button click', () => { const { getByText, queryByRole } = render( <Provider store={store}> <BulmaModal /> </Provider> ); const button = getByText('Toggle Modal'); fireEvent.click(button); const modal = queryByRole('dialog'); //Assuming the modal has role="dialog" expect(modal).toBeInTheDocument(); fireEvent.click(button); expect(queryByRole('dialog')).not.toBeInTheDocument(); }); """ **Why:** Solid tests ensure the state management is behaving as expected; especially critical for toggling the state which affect Bulma CSS classes applied. ## 7. Performance Optimization * **Memoization:** Use "React.memo" to prevent unnecessary re-renders of Bulma components. * **Virtualization:** For large lists, use virtualization libraries like "react-window" to render only the visible items. * **Debouncing/Throttling:** Limit the frequency of state updates triggered by user input. * **Selective Updates:** Update only the specific parts of the state that need to be changed. Avoid unnecessary updates to application-wide context. **Example (Memoization with React.memo):** """jsx import React from 'react'; const BulmaButton = React.memo(function BulmaButton({ onClick, children }) { console.log('BulmaButton rendered'); // Check when it re-renders return ( <button className="button is-primary" onClick={onClick}> {children} </button> ); }); export default BulmaButton; """ **Why:** "React.memo" prevents re-renders if the Bulma button's props haven't changed, improving performance, especially useful when styled with many Bulma elements. Be careful to test performance optimizations and ensure they are providing the gains expected. ## 8. Security Considerations * **Never Store Sensitive Data in State:** Avoid storing passwords, API keys, or other sensitive information directly in the client-side state. * **Sanitize User Input:** When using user input to update Bulma components (e.g., dynamically adding classes), sanitize the input to prevent cross-site scripting (XSS) vulnerabilities. Use established sanitation libraries to properly sanitize data as it enters your application. * **Rate Limiting:** Implement rate limiting for API requests to prevent abuse. * **Authentication and Authorization:** Ensure proper authentication and authorization mechanisms are in place to protect sensitive data. **Example (Sanitizing user input before adding classes):** """javascript import DOMPurify from 'dompurify'; function sanitizeClass(className) { return DOMPurify.sanitize(className, {ALLOWED_TAGS: [], ALLOWED_ATTR: []}); } //Example usage const userInput = "<img src='x' onerror='alert(\"XSS\")' /> malicious-class"; const sanitizedInput = sanitizeClass(userInput); console.log(sanitizedInput); // malicious-class //When adding it to element const element = document.getElementById('myElement'); element.classList.add(sanitizedInput); """ **Why:** Prevents attackers from injecting malicious code that could compromise the application or user data. Preventing execution of JavaScript in class names is critical. By adhering to these guidelines, you can effectively manage application state in your Bulma projects, resulting in more maintainable, scalable, performant, and secure applications. Remember to choose the right state management solution based on the complexity of your project and team expertise. Also keep up-to-date on the latest Bulma versions.
# Component Design Standards for Bulma This document outlines the coding standards for designing components using Bulma, focusing on reusability, maintainability, and performance. Adhering to these standards will ensure consistency and quality across your projects. ## 1. Component Structure and Organization ### 1.1 Modularization **Do This:** * Break down complex UI into smaller, self-contained components. Each component should have a specific purpose ("Single Responsibility Principle"). * Use a consistent directory structure for organizing components. A common pattern is: """ components/ ├── MyComponent/ # Directory for each component │ ├── MyComponent.vue # Main component file (if using Vue.js) │ ├── MyComponent.js # Component logic (if not using a framework) │ ├── MyComponent.scss # Component-specific styles │ └── MyComponent.stories.js # Storybook stories for the component └── AnotherComponent/ ├── AnotherComponent.vue ├── AnotherComponent.js └── AnotherComponent.scss """ **Don't Do This:** * Create monolithic components that handle multiple unrelated functionalities. * Mix component-specific styles directly into global stylesheets. * Lack of a clear folder structure, making it difficult to locate and manage components. **Why:** Modular components are easier to understand, test, and reuse. Consistent structure improves maintainability and collaboration. **Example (Vue.js):** """vue <!-- components/Button/Button.vue --> <template> <button class="button" :class="typeClass" :disabled="disabled" @click="$emit('click')" > {{ label }} </button> </template> <script> export default { name: 'Button', props: { label: { type: String, required: true }, type: { type: String, default: 'primary', validator: (value) => ['primary', 'secondary', 'info', 'success', 'warning', 'danger'].includes(value) }, disabled: { type: Boolean, default: false } }, computed: { typeClass() { return "is-${this.type}"; } } }; </script> <style lang="scss" scoped> /* components/Button/Button.scss */ .button { &.is-primary { @extend .is-primary; // ... other style overrides if needed. Leverage Bulma's variables if desired. } &.is-secondary { @extend .is-info; // Example usage. Different Bulma Color } // Additional specific styling rules for the component } </style> """ ### 1.2 Using Bulma's CSS Classes **Do This:** * Leverage Bulma's built-in classes for common UI elements and layouts. This allows you to take advantage of the grid system, modifiers, and helpers that Bulma provides. * Customize Bulma's variables through a separate "_variables.scss" file to maintain a consistent branding across the application without modifying the Bulma core files. * Use Bulma's modifier classes (e.g., "is-primary", "is-success", "is-small") for consistent styling and theming. * Utilize Bulma's helper classes (e.g., "is-hidden", "is-pulled-left", "has-text-centered") for utility styling. **Don't Do This:** * Overly rely on custom CSS or JavaScript when Bulma provides built-in solutions. * Modify Bulma's core CSS files directly. * Ignore Bulma's semantic class names and create custom names that duplicate Bulma's functionality. **Why:** Using Bulma effectively reduces development time, ensures visual consistency, and simplifies maintenance by relying on a well-documented and established CSS framework. **Example:** """html <button class="button is-primary is-medium"> Click me </button> <div class="columns"> <div class="column is-half"> Column 1 </div> <div class="column is-half"> Column 2 </div> </div> """ **Example of using Bulma Variables (create a "_variables.scss" file and import before Bulma):** """scss // _variables.scss $primary: #ff385f; // Custom primary color, Airbnb style $family-sans-serif: "Nunito", sans-serif; // Import Bulma @import "~bulma/bulma"; """ ### 1.3 Component Communication **Do This:** * Use props to pass data from parent to child components. * Use events to communicate from child to parent components. * For complex state management, consider using a state management library like Vuex or Redux (especially within JS frameworks) **Don't Do This:** * Directly modify props within child components. * Rely on global variables or event buses for inter-component communication where props/events would suffice **Why:** Explicit data flow through props and events ensures predictable behavior and makes it easier to reason about the component's state and interactions. Centralized state management improves organization and simplifies debugging in larger applications. **Example (Vue.js):** """ vue <!-- ParentComponent.vue --> <template> <div> <ChildComponent :message="parentMessage" @customEvent="handleEvent" /> <p>Received event data: {{ receivedData }}</p> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { parentMessage: 'Hello from parent!', receivedData: '' }; }, methods: { handleEvent(data) { this.receivedData = data; } } }; </script> <!-- ChildComponent.vue --> <template> <button class="button is-primary" @click="emitEvent"> Click to emit event </button> </template> <script> export default { props: { message: { type: String, required: true } }, methods: { emitEvent() { this.$emit('customEvent', 'Data from child'); } } }; </script> """ ## 2. Styling and Theming ### 2.1 Bulma's Sass Structure **Do This:** * Take advantage of Bulma's Sass structure. Import the "bulma/bulma.sass" file into your project's main Sass file. * Override Bulma's variables before importing "bulma/bulma.sass" to customize its appearance without modifying the core files. * Use Sass mixins for sharing styling rules across components. * Organize your Sass files into logical sections (variables, mixins, base styles, components). **Don't Do This:** * Modify Bulma's core Sass files directly. This makes upgrading Bulma more difficult. * Overuse "!important" declarations. Use specificity or Sass variable overrides instead. * Write overly complex or deeply nested Sass rules that can negatively impact performance. **Why:** Bulma's Sass structure allows for easy customization and extension while maintaining a clear separation of concerns. Variables and mixins promote code reuse and consistency. **Example (Directory Structure):** """ assets/ ├── sass/ # Main Sass directory │ ├── main.scss # Main Sass file │ ├── _variables.scss # Customized Bulma variables │ ├── _mixins.scss # Custom Sass mixins │ ├── components/ # Component-specific styles │ │ └── _button.scss │ └── base/ # Base styles (e.g., typography, resets) │ └── _typography.scss """ **Example ("main.scss"):** """scss // main.scss @import "./_variables.scss"; // Override Bulma's variables @import "~bulma/bulma"; // Import Bulma // Optionally import your own styles *after* Bulma @import "./_mixins.scss"; @import "./base/_typography.scss"; @import "./components/_button.scss"; """ ### 2.2 Custom Styles and Overrides **Do This:** * Limit custom styles to component-specific styling and high-level theme customizations. Leverage Bulma's core classes as much as possible. * Use clear and descriptive class names for custom styles. Follow a consistent naming convention (BEM is a popular choice). * Ensure that custom styles are responsive and work well across different screen sizes. Use Bulma's responsive modifiers or implement your own media queries. **Don't Do This:** * Create highly specific CSS rules that are difficult to override or maintain. * Use inline styles unless absolutely necessary. * Neglect testing custom styles on different devices and browsers. **Why:** Limiting custom styles ensures that your application remains consistent with Bulma's design principles. Well-organized and responsive styles improve the user experience across all devices. **Example (BEM-style Custom Styling):** """scss /* components/Button/Button.scss */ .button { &.is-primary { @extend .is-primary; // Extend standard Bulma button first // Override further, being specific background-color: $primary; // Custom primary from _variables.scss border-color: darken($primary, 10%); &:hover { background-color: darken($primary, 5%); } } &--large { // BEM modifier block font-size: 1.25rem; padding: 0.75rem 1.5rem; } } """ ### 2.3 Theming **Do This:** * Use Bulma's Sass variables to define your application's theme (colors, fonts, spacing). * Create multiple theme files (e.g., "_theme-light.scss", "_theme-dark.scss") and switch between them using CSS classes or JavaScript. * Utilize CSS custom properties (variables) to store theme values and dynamically update them. **Don't Do This:** * Hardcode theme values directly in CSS rules. * Neglect accessibility considerations when designing your theme (e.g., sufficient contrast ratios). **Why:** Theming allows you to easily switch between different visual appearances and cater to user preferences. CSS custom properties enable dynamic theming without requiring a full page reload. **Example (Dark Theme):** """scss /* _theme-dark.scss */ $background: #222; $text: #fff; $primary: #1e88e5; body { background-color: $background; color: $text; } .button.is-primary { background-color: $primary; } """ ## 3. Component Composition and Patterns ### 3.1 Higher-Order Components (HOCs) or Render Props **Do This (When Using Frameworks):** * Employ Higher-Order Components (HOCs) or render props to share common functionality (e.g., authentication, data fetching) across multiple components where applicable. * Keep HOCs small and focused on a single responsibility. When using vue, functional components are also relevant. **Don't Do This:** * Overuse HOCs or render props, leading to deeply nested component structures. * Create HOCs that tightly couple components to specific implementation details. **Why:** HOCs and render props promote code reuse and separation of concerns. They allow you to inject functionality into components without modifying their core logic. **Example (React):** """jsx // withAuthentication.jsx (HOC) import React from 'react'; const withAuthentication = (WrappedComponent) => { return class extends React.Component { constructor(props) { super(props); this.state = { isAuthenticated: localStorage.getItem('token') !== null }; } render() { if (this.state.isAuthenticated) { return <WrappedComponent {...this.props} />; } else { return <div>Please log in to view this content.</div>; } } }; }; export default withAuthentication; // MyComponent.jsx import React from 'react'; import withAuthentication from './withAuthentication'; const MyComponent = (props) => { return <div>This component requires authentication.</div>; }; export default withAuthentication(MyComponent); """ ### 3.2 Compound Components **Do This (Where Frameworks allow):** * Use compound components to create more complex UI patterns with implicit state sharing. * Clearly document the interaction between the parent and child components. **Don't Do This:** * Make the relationship between compound components too implicit or confusing. * Overuse compound components when simpler composition techniques would suffice. **Why:** Compound components simplify complex UI patterns by encapsulating related components and their interactions. **Example (React):** """jsx // Tabs.jsx import React, { createContext, useState, useContext } from 'react'; const TabsContext = createContext(); const Tabs = ({ children, defaultIndex = 0 }) => { const [selectedIndex, setSelectedIndex] = useState(defaultIndex); return ( <TabsContext.Provider value={{ selectedIndex, setSelectedIndex }}> <div className="tabs"> <ul>{children}</ul> </div> </TabsContext.Provider> ); }; const Tab = ({ children, index }) => { const { selectedIndex, setSelectedIndex } = useContext(TabsContext); const isActive = selectedIndex === index; return ( <li className={isActive ? 'is-active' : ''}> <a onClick={() => setSelectedIndex(index)}>{children}</a> </li> ); }; export { Tabs, Tab }; // Usage <Tabs> <Tab index={0}>Tab 1</Tab> <Tab index={1}>Tab 2</Tab> </Tabs> """ ### 3.3 Mixins (for styling) **Do This:** * Create Sass mixins for common styling patterns or Bulma overrides. * Use descriptive names for your mixins. * Pass parameters to your mixins to make them flexible and reusable. **Don't Do This:** * Create overly complex mixins that are difficult to understand or maintain. * Duplicate code when a mixin could be used instead. **Why:** Sass mixins promote code reuse, reduce redundancy, and improve maintainability. **Example:** """scss // _mixins.scss @mixin box-shadow($shadow...) { box-shadow: $shadow; // Vendor prefixes if needed -webkit-box-shadow: $shadow; } .my-element { @include box-shadow(0 2px 4px rgba(0, 0, 0, 0.1)); } """ ## 4. Accessibility ### 4.1 Semantic HTML **Do This:** * Use semantic HTML elements (e.g., "<nav>", "<article>", "<aside>") to provide structure and meaning to your content. * Use proper heading levels (<h1> to <h6>) to create a logical document outline. * Use "<button>" elements for interactive elements that trigger actions, and "<a>" elements for navigation links. **Don't Do This:** * Use "<div>" or "<span>" elements for everything, without considering their semantic meaning. * Use heading levels purely for styling purposes. * Use "<a>" elements as buttons unless they navigate to a new page or section. **Why:** Semantic HTML improves accessibility for users with disabilities and helps search engines understand the content of your page. **Example:** """html <nav class="navbar" role="navigation" aria-label="main navigation"> <!-- Navbar content --> </nav> <article> <h1>Article Title</h1> <p>Article content...</p> </article> """ ### 4.2 ARIA Attributes **Do This:** * Use ARIA attributes to provide additional information about interactive elements and their state. * Use "aria-label" to provide a text alternative for elements that don't have visible text. * Use "aria-hidden="true"" to hide decorative elements from screen readers. * Test your components with screen readers (e.g., VoiceOver, NVDA) to ensure they are accessible. **Don't Do This:** * Overuse ARIA attributes or use them incorrectly. * Rely solely on ARIA attributes without providing semantic HTML. * Forget to update ARIA attributes when the state of an element changes dynamically. **Why:** ARIA attributes enhance accessibility for users with disabilities by providing assistive technologies with information about the role, state, and properties of UI elements. **Example:** """html <button class="button is-primary" aria-label="Close"> <span aria-hidden="true">×</span> </button> <div role="alert" aria-live="polite"> This is an alert message. </div> """ ### 4.3 Focus Management **Do This:** * Ensure that all interactive elements are focusable and have a clear focus indicator. * Manage focus programmatically to ensure that the user's focus remains within a specific region of the page (e.g., a modal dialog). * Avoid trapping the user's focus within a component. **Don't Do This:** * Remove the default focus indicator from interactive elements. * Create focus traps that prevent users from navigating to other parts of the page. **Why:** Proper focus management ensures that users can navigate your application using the keyboard or other assistive technologies. **Example (Focus Trap - Avoid this! Illustrative of what *not* to do)** """javascript // WARNING: This demonstrates an anti-pattern (focus trap). Do not implement this directly. // AVOID: Focus trapping! This is used for demonstration purposes only and should not be implemented in production. // This code sets focus to the first focusable element inside a modal and prevents the user from tabbing out of it. This is **extremely** bad for accessibility. // DO NOT SHIP CODE LIKE THIS """ ### 4.4 Color Contrast **Do This:** * Ensure that the contrast ratio between text and background colors meets the WCAG 2.1 AA or AAA standards (a minimum of 4.5:1 for normal text and 3:1 for large text). * Use a color contrast checker to verify that your color combinations are accessible. * Provide a high-contrast theme for users with visual impairments. **Don't Do This:** * Use color combinations that are difficult to read or distinguish. * Rely solely on color to convey information. **Why:** Sufficient color contrast ensures that your content is readable for users with visual impairments. **Example:** Use a tool like [WebAIM's Contrast Checker](https://webaim.org/resources/contrastchecker/) to ensure your color choices meet accessibility standards. ## 5. Performance ### 5.1 Optimize CSS **Do This:** * Minify and compress your CSS files to reduce their size. * Remove unused CSS rules. * Use CSS selectors efficiently to avoid performance bottlenecks. * Leverage browser caching to reduce the number of requests for CSS files. **Don't Do This:** * Write overly complex CSS selectors that are difficult for the browser to parse. * Include large, unused CSS frameworks in your project. * Load CSS files synchronously in the "<head>" section of your HTML document. **Why:** Optimized CSS files improve page load times and reduce the amount of data that needs to be transferred over the network. ### 5.2 Lazy Loading **Do This:** * Lazy load images and other non-critical resources to improve initial page load time. * Use the "loading="lazy"" attribute for images that are below the fold. * Consider using a JavaScript library for more advanced lazy loading techniques. **Don't Do This:** * Lazy load critical resources that are needed for the initial rendering of the page. **Why:** Lazy loading reduces initial page load time by deferring the loading of non-critical resources until they are needed. **Example:** """html <img src="my-image.jpg" alt="My Image" loading="lazy"> """ ### 5.3 Code Splitting **Do This (when applicable):** * Split your JavaScript and CSS code into smaller chunks that can be loaded on demand. * Use dynamic imports to load modules only when they are needed. * Leverage your bundler's code splitting capabilities. **Don't Do This:** * Load all of your JavaScript and CSS code in a single large file. * Neglect to analyze your bundle size and identify opportunities for code splitting. **Why:** Code splitting reduces initial page load time by loading only the code that is needed for the current view. These coding standards will ensure codebases are easier to maintain and scale.
# Deployment and DevOps Standards for Bulma This document outlines the coding standards for Bulma projects, focusing specifically on deployment and DevOps practices. It is intended to guide developers in building robust, maintainable, and performant Bulma-based applications. This document is also designed to provide context for AI coding assistants, enabling them to generate code that adheres to these standards. ## 1. Build Processes and CI/CD for Bulma ### 1.1. Standard: Use a Robust Build System **Do This:** Use a modern build system such as Webpack, Parcel, or esbuild. These tools allow for efficient bundling, minification, and optimization of CSS and JavaScript. **Don't Do This:** Rely on manual concatenation and minification. This is error-prone and difficult to maintain as the project grows. **Why:** Automating the build process with a build system ensures consistency across environments, reduces the risk of human error, and significantly improves performance by optimizing assets. **Code Example (Webpack):** """javascript // webpack.config.js const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); module.exports = { entry: './src/js/app.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), }, module: { rules: [ { test: /\.scss$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader', ], }, { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'], }, }, }, ], }, plugins: [ new MiniCssExtractPlugin({ filename: 'bundle.css', }), ], optimization: { minimizer: [ '...', // Use TerserPlugin for JavaScript new CssMinimizerPlugin(), ], }, }; """ ### 1.2. Standard: Implement CSS Purging **Do This:** Integrate CSS purging tools like PurgeCSS or UnCSS to remove unused Bulma styles and custom CSS. **Don't Do This:** Include the entire Bulma CSS file without purging unused styles, especially for small projects where only a subset of Bulma's components are used. **Why:** Bulma provides a large number of CSS classes. Purging unused styles significantly reduces the size of the CSS file, resulting in faster page load times. This is particularly important for mobile users. **Code Example (PurgeCSS with Webpack):** """javascript // webpack.config.js const path = require('path'); const glob = require('glob'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); const { PurgeCSSPlugin } = require('purgecss-webpack-plugin'); const PATHS = { src: path.join(__dirname, 'src') } module.exports = { entry: './src/js/app.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), }, module: { rules: [ { test: /\.scss$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader', ], }, { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'], }, }, }, ], }, plugins: [ new MiniCssExtractPlugin({ filename: 'bundle.css', }), new PurgeCSSPlugin({ paths: glob.sync("${PATHS.src}/**/*", { nodir: true }), // Consider using more explicit paths here safelist: { standard: [/^is-/, /^has-/, /^fa-/], // Bulma and FontAwesome modifiers deep: [/data-theme$/] }, }), ], optimization: { minimizer: [ '...', // Use TerserPlugin for JavaScript new CssMinimizerPlugin(), ], }, }; """ **Anti-Pattern:** Using a very broad selector for PurgeCSS paths (e.g., "/**/*") can inadvertently remove CSS classes that are dynamically added via JavaScript. Always refine paths to only include files that contain your HTML structure. ### 1.3. Standard: Implement Continuous Integration and Continuous Deployment (CI/CD) **Do This:** Set up a CI/CD pipeline using tools like GitHub Actions, GitLab CI, Jenkins, or CircleCI. The pipeline should automatically run tests, build the application, and deploy it to the target environment upon code changes. **Don't Do This:** Manually build and deploy the application. This is inefficient and increases the risk of introducing errors. **Why:** CI/CD automates the build, test, and deployment processes, ensuring rapid feedback, reducing errors, and enabling faster release cycles. **Code Example (GitHub Actions):** """yaml # .github/workflows/deploy.yml name: Deploy to Production on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18.x' - name: Install dependencies run: npm install - name: Build run: npm run build # Or yarn build, depending on your package manager - name: Deploy to Server uses: appleboy/scp-action@v0.1.10 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USERNAME }} key: ${{ secrets.SSH_PRIVATE_KEY }} source: dist/ target: /var/www/your-app/ - name: Restart Server uses: appleboy/ssh-action@v1.0.0 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USERNAME }} key: ${{ secrets.SSH_PRIVATE_KEY }} script: | pm2 restart your-app # Assuming you're using PM2 """ **Explanation:** This GitHub Actions workflow is triggered on pushes to the "main" branch. It checks out the code, sets up Node.js, installs dependencies, builds the application (using a "build" script defined in "package.json"), deploys the contents of the "dist" directory to a server using "scp", and then restarts the application using "pm2". Secrets like server host, username, and SSH key are stored in GitHub's secrets management. ### 1.4. Standard: Version Control for Bulma Customizations **Do This:** Use a version control system (e.g., Git) to track all Bulma customizations, including custom themes, extensions, and overrides. **Don't Do This:** Modify Bulma's core files directly. Keep customizations separate to facilitate easier updates. **Why:** Version control allows you to track changes, collaborate effectively, and easily revert to previous versions if necessary. Separating customizations avoids conflicts when upgrading Bulma. **Example:** Maintain a separate "src/sass/custom.scss" file to contain all your overrides, and import the Bulma library at the top: """scss // src/sass/custom.scss @import "~bulma/sass/bulma"; // Your customizations $primary: #ff0000; .my-custom-class { color: $primary; } """ ### 1.5. Standard: Automate Image Optimization **Do This:** Integrate image optimization tools into your build process. Tools like "imagemin-webpack-plugin" will automatically compress images during your build. Consider using modern image formats like WebP. **Don't Do This:** Deploy unoptimized images. Ensure that all images are properly compressed and sized for their intended display. **Why:** Optimized images drastically reduce page load times and improve the user experience, especially on mobile devices. **Code Example (imagemin-webpack-plugin):** """javascript // webpack.config.js const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin"); module.exports = { // ... other webpack configuration optimization: { minimizer: [ // ... other minimizers new ImageMinimizerPlugin({ minimizer: { implementation: ImageMinimizerPlugin.imageminMinify, options: { plugins: [ ["gifsicle", { interlaced: true }], ["jpegtran", { progressive: true }], ["optipng", { optimizationLevel: 5 }], [ "svgo", { plugins: [ { name: "preset-default", params: { overrides: { removeViewBox: false, addAttributesToSVGElement: { params: { attributes: [{ xmlns: "http://www.w3.org/2000/svg" }], }, }, }, }, }, ], }, ], ], }, }, }), ], }, plugins: [ //... other plugins ] }; """ ## 2. Production Considerations for Bulma ### 2.1. Standard: Enable Caching **Do This:** Configure your web server (e.g., Nginx, Apache, or CDN) to properly cache static assets, including CSS, JavaScript, images, and fonts. Use appropriate "Cache-Control" headers to control caching behavior. **Don't Do This:** Disable caching or use overly short cache durations. This forces browsers to re-download assets on every page load, significantly increasing latency. **Why:** Caching reduces server load and improves performance by allowing browsers to store static assets locally. **Code Example (Nginx Configuration):** """nginx location ~* \.(?:css|js|json|svg|eot|ttf|woff|woff2)$ { expires 30d; add_header Cache-Control "public, max-age=2592000"; } location ~* \.(?:png|jpg|jpeg|gif)$ { expires 7d; add_header Cache-Control "public, max-age=604800"; } """ **Explanation:** This Nginx configuration sets a 30-day cache expiration for CSS, JavaScript, JSON, SVG, and font files, and a 7-day expiration for image files. The "Cache-Control" header instructs browsers and CDNs to cache these assets publicly. ### 2.2. Standard: Utilize a Content Delivery Network (CDN) **Do This:** Host static assets (CSS, JavaScript, images, fonts) on a CDN to distribute content geographically closer to users. **Don't Do This:** Serve all assets from a single server, especially for applications with a global audience. **Why:** CDNs improve performance by reducing latency and providing highly available content delivery. **Example:** Services like Cloudflare, AWS CloudFront, or Google Cloud CDN can be used to host your Bulma-based application's static assets. ### 2.3. Standard: Monitor Application Performance **Do This:** Implement real-time monitoring of application performance using tools like Google Analytics, New Relic, or Sentry. Monitor key metrics such as page load times, error rates, and API response times. Also, consider using Lighthouse or PageSpeed Insights to get reports and suggestions. **Don't Do This:** Neglect performance monitoring. Proactively identify and address performance bottlenecks. **Why:** Monitoring allows you to identify and resolve performance issues quickly, ensuring a positive user experience. ### 2.4. Standard: Implement Error Tracking **Do This:** Integrate an error-tracking tool like Sentry or Bugsnag to capture and report JavaScript errors and server-side exceptions that may occur in production. **Don't Do This:** Rely solely on user reports for error detection. Proactively monitor and address errors to improve application stability. **Why:** Error tracking helps you identify and fix errors that users may encounter, improving application stability and reducing user frustration. ### 2.5. Standard: Security Hardening **Do This:** Implement security best practices, including: * Using HTTPS to encrypt all traffic. * Setting appropriate HTTP security headers (e.g., Content-Security-Policy, X-Frame-Options, Strict-Transport-Security). * Protecting against Cross-Site Scripting (XSS) attacks by sanitizing user input and encoding output. * Regularly updating dependencies to patch security vulnerabilities. * Auditing your Bulma customizations for potential security flaws. **Don't Do This:** Ignore security considerations. A security breach can have serious consequences for your application and users. **Why:** Security hardening protects your application and users from various attacks. **Example (Content Security Policy):** Setting a restrictive CSP can prevent many XSS attacks. The exact policy will depend on your applications needs. ### 2.6. Standard: Feature Flags and Rollouts **Do This:** Consider using feature flags to gradually roll out new features to a subset of users. This allows you to test new features in a production environment with minimal risk. **Don't Do This:** Deploy large, untested features directly to all users. **Why:** Feature flags reduce the risk associated with deploying new features by allowing you to test them with a smaller audience and quickly revert changes if necessary. ### 2.7. Bulma-Specific Considerations for Deployment * **Custom Themes:** When deploying custom Bulma themes, ensure that the custom theme files are loaded *after* the core Bulma CSS. CSS specificity and cascade rules apply! * **JavaScript Dependencies**: Ensure all Bulma JavaScript dependencies are included and loaded correctly, particularly when using Bulma extensions or custom components that rely on JavaScript. * **Accessibility**: Review your application's accessibility after deployment. Use tools like WAVE to identify and fix accessibility issues. Ensure color contrast ratios are sufficient and that all interactive elements are properly labeled. By following these Deployment and DevOps standards, developers can build and deploy robust, performant, and secure Bulma applications. These standards are intended to promote consistency, reduce errors, and enable faster release cycles. They also provide a clear guide for AI coding assistants, helping them to generate code that aligns with these best practices.
# Tooling and Ecosystem Standards for Bulma This document outlines the recommended tools, libraries, extensions, and practices for developing with Bulma effectively and efficiently. These standards are designed to promote maintainability, performance, and security within your Bulma projects. They also provide context to AI coding assistants on the proper methods of usage, enabling them to generate helpful and effective code. ## 1. Build Tools and Package Management ### 1.1. Package Manager Selection: npm or Yarn **Standard:** Use either npm or Yarn as your package manager. Yarn is often preferred for its speed and deterministic dependency resolution (using yarn.lock), while npm is widely adopted and integrated with Node.js. **Do This:** * Choose either npm or Yarn at the project's inception and consistently use it. * Include "package-lock.json" (for npm) or "yarn.lock" (for Yarn) in your Git repository to ensure consistent dependency versions across environments. **Don't Do This:** * Mix npm and Yarn in the same project. * Forget to commit the lock file to your repository. **Why:** Consistency in package management reduces dependency conflicts and ensures that all developers and environments use the same versions of packages, preventing unexpected behavior. **Example (npm):** """bash npm install bulma npm install node-sass --save-dev """ **Example (Yarn):** """bash yarn add bulma yarn add node-sass --dev """ ### 1.2. Task Runners and Build Systems: npm scripts, Gulp, or Webpack **Standard:** Use npm scripts, Gulp, or Webpack for build automation, Sass compilation, and other development tasks. Webpack, with its module bundling capabilities, is highly recommended for complex projects that utilize modern JavaScript modules or assets. Gulp is a good choice for simpler task automation workflows. npm scripts offer a lightweight and dependency-free approach. **Do This:** * Define build, test, and other utility commands in your "package.json" using npm scripts. * Use Gulp for more complex task automation, such as file minification and image optimization. * Use Webpack for bundling assets, especially when dealing with JavaScript modules and dependencies. **Don't Do This:** * Manually compile Sass or perform other build steps. * Overcomplicate build processes with unnecessary dependencies. **Why:** Automation streamlines development, reduces errors, and ensures consistent build processes. **Example (npm scripts in "package.json"):** """json { "scripts": { "build:sass": "node-sass sass/main.scss css/style.css", "watch:sass": "node-sass sass/main.scss css/style.css --watch", "start": "npm run watch:sass" }, "devDependencies": { "node-sass": "^7.0.0" } } """ **Example (Gulp):** """javascript // gulpfile.js const gulp = require('gulp'); const sass = require('gulp-sass')(require('node-sass')); const autoprefixer = require('gulp-autoprefixer'); const cleanCSS = require('gulp-clean-css'); function compileSass() { return gulp.src('sass/main.scss') .pipe(sass().on('error', sass.logError)) .pipe(autoprefixer({ cascade: false })) .pipe(cleanCSS({compatibility: 'ie8'})) .pipe(gulp.dest('css')); } function watch() { gulp.watch('sass/**/*.scss', compileSass); } exports.compileSass = compileSass; exports.watch = watch; exports.default = gulp.series(compileSass, watch); """ **Example (Webpack):** """javascript // webpack.config.js const path = require('path'); module.exports = { entry: './js/app.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js' }, module: { rules: [ { test: /\.scss$/, use: [ 'style-loader', // Creates "style" nodes from JS strings 'css-loader', // Translates CSS into CommonJS 'sass-loader' // Compiles Sass to CSS ] } ] } }; """ ### 1.3. Linting and Formatting: Stylelint and Prettier **Standard:** Use Stylelint for linting and Prettier for code formatting. Configure them to enforce consistent styling and formatting across your codebase. **Do This:** * Install Stylelint and Prettier as development dependencies. * Configure Stylelint with rules specific to Bulma and Sass standards. * Configure Prettier with consistent settings for indentation, line length, and other formatting options. * Integrate Stylelint and Prettier into your editor or IDE for real-time feedback. * Use Husky or similar tools to run linters and formatters before committing code. **Don't Do This:** * Ignore linting and formatting warnings. * Use inconsistent styling or formatting across files. **Why:** Consistent styling and formatting improve code readability and reduce cognitive load, making it easier for developers to understand and maintain the codebase. **Example (.stylelintrc.json):** """json { "extends": "stylelint-config-standard-scss", "rules": { "selector-class-pattern": null, // Allow Bulma's class naming convention "at-rule-no-unknown": null, // To avoid false positives with Sass directives "scss/at-rule-no-unknown": true } } """ **Example (.prettierrc.json):** """json { "semi": false, "singleQuote": true, "trailingComma": "es5", "tabWidth": 2 } """ **Example (Husky pre-commit hook):** """json // package.json { "husky": { "hooks": { "pre-commit": "lint-staged" } }, "lint-staged": { "*.{scss,css}": "stylelint --fix", "*.{js,json}": "prettier --write" } } """ ## 2. Bulma Extensions and Add-ons ### 2.1. Officially Supported Extensions **Standard:** Prioritize officially supported or widely used and maintained Bulma extensions. Check their documentation and contribution history when choosing which extensions to use. **Do This:** * Research extensions before using them in your project. * Ensure the extension is actively maintained and compatible with your Bulma version. **Don't Do This:** * Use unmaintained or abandoned extensions, as they might introduce security vulnerabilities or compatibility issues. **Why:** Stable and well-maintained extensions enhance Bulma's capabilities, providing more components and utilities without compromising project stability. ### 2.2. Bulma Customization Libraries **Standard:** Favor libraries that enhance Bulma itself through Sass variables or component composition rather than extensions requiring extensive JavaScript or CSS overrides. **Do This:** * Look for libraries offering Sass mixins or variables to customize Bulma's appearance. * Ensure that additional CSS integrates seamessly and follows Bulma's standards. **Don't Do This:** * Implement libraries that heavily change the core styling or markup, as this reduces the benefit of Bulma's pre-defined styles. **Why:** Simple customization libraries maintain Bulma's core structure, improving consistency and upgradeability. ### 2.3. JavaScript Integration **Standard:** When JavaScript integration is required, prefer native JavaScript over jQuery whenever possible. Use lightweight JavaScript libraries or frameworks strategically. **Do This:** * Use native JavaScript for DOM manipulation, event handling, and AJAX requests. * Consider using a lightweight framework when more advanced UI interactions are required. **Don't Do This:** * Rely heavily on jQuery for basic DOM manipulation tasks. * Introduce unnecessary dependencies for simple interactivity. **Why:** Native JavaScript is more performant and reduces the overall project size. Using lightweight libraries minimizes dependency bloat. **Example (Native JavaScript Toggle):** """html <button id="toggleButton">Toggle</button> <div id="content" class="is-hidden">Content to toggle</div> <script> const toggleButton = document.getElementById('toggleButton'); const content = document.getElementById('content'); toggleButton.addEventListener('click', () => { content.classList.toggle('is-hidden'); }); </script> """ ### 2.4. Accessibility Integration **Standard**: Ensure that extensions and integrations comply with accessibility (ARIA) standards. When integrating Javascript components, ensure these additions provide proper ARIA attributes and keyboard navigation. **Do This:** * Test any JavaScript-enhanced Bulma components for keyboard accessibility and screen reader compatibility. * Verify sufficient color contrast between text and background colors. **Don't Do This:** * Add extensions or JS components that break accessibility. **Why:** Accessibility ensures your Bulma-based applications are usable by everyone, including people with disabilities. ## 3. Debugging and Development Tools ### 3.1. Browser Developer Tools **Standard:** Utilize browser developer tools (Chrome DevTools, Firefox Developer Tools) for debugging CSS and JavaScript. **Do This:** * Use the "Inspect" tool to examine HTML elements and their applied CSS styles. * Use the "Console" to log messages and debug JavaScript code. * Use the "Network" tab to analyze network requests and identify performance bottlenecks. **Don't Do This:** * Rely solely on "console.log" statements for debugging. * Ignore browser warnings and errors. **Why:** Browser developer tools provide powerful debugging capabilities and performance insights, making it easier to diagnose and fix issues. ### 3.2. Responsive Design Testing **Standard:** Test your Bulma layouts on various screen sizes and devices using browser developer tools or dedicated testing tools. **Do This:** * Use the responsive design mode in browser developer tools to simulate different screen sizes and orientations. * Test on physical devices to ensure proper rendering and usability. * Consider using cross-browser testing tools like BrowserStack or Sauce Labs. **Don't Do This:** * Assume your layout will work perfectly on all devices without proper testing. **Why:** Responsive design testing ensures that your application provides a consistent and user-friendly experience across all devices. ### 3.3. Performance Analysis **Standard:** Use performance analysis tools to identify and address potential performance bottlenecks. **Do This:** * Use browser developer tools (e.g., Chrome DevTools' "Performance" tab) to profile your application's performance. * Identify slow-loading resources, inefficient JavaScript code, and excessive DOM manipulation. * Optimize images and other assets to reduce file sizes. **Don't Do This:** * Ignore performance issues until they become critical. **Why:** Performance analysis enables you to optimize your application for speed and responsiveness, improving the user experience. ## 4. Version Control and Collaboration ### 4.1. Git and GitHub/GitLab/Bitbucket **Standard:** Use Git for version control and a platform like GitHub, GitLab, or Bitbucket for collaboration. **Do This:** * Commit code frequently with clear and concise commit messages. * Use branching strategies (e.g., Gitflow) to manage feature development and releases. * Use pull requests for code review and collaboration. **Don't Do This:** * Commit large changes without proper testing. * Push code directly to the main branch. * Ignore code review feedback. **Why:** Version control enables you to track changes to your codebase, collaborate effectively with other developers, and revert to previous versions if necessary. ### 4.2. Code Reviews **Standard:** Conduct thorough code reviews before merging changes into the main branch. **Do This:** * Focus on code quality, maintainability, security, and performance during code reviews. * Provide constructive feedback and suggest improvements. * Ensure that all code adheres to these coding standards. **Don't Do This:** * Skip code reviews. * Approve code without thoroughly understanding it. **Why:** Code reviews help identify potential issues early, improve code quality, and promote knowledge sharing among team members. ## 5. Documentation Tools ### 5.1. Project README **Standard:** Maintain a comprehensive README file for your Bulma project. **Do This:** * Include a clear description of the project's purpose and features. * Provide instructions on how to set up the development environment, install dependencies, and run the application. * Document any project-specific coding standards or conventions. **Don't Do This:** * Leave the README file incomplete or outdated. **Why:** A well-maintained README file makes it easier for new developers to understand the project and get started quickly. ### 5.2. Inline Code Documentation **Standard:** Document your code using comments and documentation generators (e.g., JSDoc for JavaScript). Provide semantic HTML markup for better code understanding. **Do This:** * Use comments to explain complex logic, non-obvious code, and important design decisions. * Use documentation generators to create API documentation from your code comments. **Don't Do This:** * Over-comment code with obvious explanations. * Fail to document important code sections. **Why:** Code documentation makes it easier for developers to understand and maintain the codebase, especially in complex projects. By following these tooling and ecosystem standards, you can create robust, maintainable, and performant Bulma-based applications. This guidance, combined with AI coding assistants trained on these principles, will lead to significant improvements in code quality and development efficiency.
# Performance Optimization Standards for Bulma This document outlines coding standards focusing on performance optimization when developing with Bulma, the CSS framework. These standards provide guidance to developers to build fast, responsive, and resource-efficient web applications. The standards are tailored specifically for Bulma's ecosystem, emphasizing best practices relevant to the latest version. ## 1. CSS Performance Optimization ### 1.1. Reducing CSS File Size **Standard:** Minimize CSS file size by removing unused CSS and using features like PurgeCSS and CSS minification. **Why:** Smaller CSS files result in faster download times and improved page load speed. * **Do This:** * Use PurgeCSS (or similar tools) to remove unused CSS rules. * Minify the final CSS file for production environments. * Use the "cssnano" plugin along with "postcss" to optimize CSS. * **Don't Do This:** * Include the entire Bulma CSS if only a few components are used. * Leave unnecessary comments or whitespace in production CSS. **Code Example (PurgeCSS):** """bash npm install -D purgecss """ """javascript // postcss.config.js const purgecss = require('@fullhuman/postcss-purgecss') module.exports = { plugins: [ require('tailwindcss'), require('autoprefixer'), purgecss({ content: ['./**/*.html', './src/**/*.vue', './src/**/*.jsx'], defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || [] }) ] } """ **Common Anti-patterns:** * Manually deleting CSS rules (error-prone). * Not configuring PurgeCSS correctly, leading to essential styles being removed. ### 1.2. Efficient CSS Selectors **Standard:** Use efficient CSS selectors to improve rendering performance. **Why:** Complex CSS selectors can significantly slow down browser rendering. * **Do This:** * Use class-based selectors instead of tag-based selectors when possible. * Avoid overly specific selectors. * Limit the depth of nested selectors. * **Don't Do This:** * Use the universal selector ("*") excessively. * Overuse of attribute selectors. **Code Example (Efficient vs. Inefficient Selectors):** """css /* Efficient */ .button { /*Direct class selector */ color: white; } /* Inefficient */ div > ul > li a { /* Overly specific */ text-decoration: none; } """ **Common Anti-patterns:** * Using IDs for styling (high specificity). * Creating deeply nested selectors. ### 1.3. Leverage Bulma's Modular CSS **Standard:** Utilize Bulma's modularity to include only necessary components. **Why:** Reduces CSS overhead, leading to improved performance and faster load times. * **Do This:** * Consider alternatives if you use a minimal set of defaults, or combine it with something to remove unused classes (purgecss). * Import only needed Bulma modules via Sass. * **Don't Do This:** * Import the complete Bulma CSS if you only use a few components. **Code Example (Sass Import):** """scss // Import Bulma's core @import "../node_modules/bulma/sass/utilities/_all"; @import "../node_modules/bulma/sass/base/_all"; // Import only specific components @import "../node_modules/bulma/sass/elements/button"; @import "../node_modules/bulma/sass/components/navbar"; // Optionally include theme-specific customization @import "custom-styles"; """ **Common Anti-patterns:** * Not taking advantage of Bulma's Sass structure for targeted imports. * Loading the full Bulma CSS unnecessarily. ### 1.4. Use CSS Custom Properties (Variables) **Standard:** Use CSS custom properties (variables) to manage and reuse styles. **Why:** Improves maintainability and allows for easy theme customization, and can offer slight performance improvements by reducing redundant style declarations. * **Do This:** * Define custom properties at the ":root" level for global theming. * Use custom properties for frequently used values. * **Don't Do This:** * Hardcode values throughout your CSS when they could be managed with variables. **Code Example (CSS Variables):** """css :root { --primary-color: #007bff; --secondary-color: #6c757d; } .button { background-color: var(--primary-color); color: white; } .button-secondary { background-color: var(--secondary-color); color: white; } """ **Common Anti-patterns:** * Not using CSS variables for consistent styling. * Overusing CSS variables where static values are more appropriate. ### 1.5 Avoid Expensive CSS Properties **Standard:** Be mindful of CSS properties that trigger layout thrashing. **Why:** Layout thrashing occurs when JavaScript forces the browser to perform reflows repeatedly, causing performance bottlenecks. * **Do This:** * Avoid reading and writing layout properties (e.g., "offsetWidth", "scrollTop") in quick succession. * Use "transform" and "opacity" for animations as they often don't trigger reflows. * **Don't Do This:** * Animate properties like "width", "height", "top", or "left" if possible, without considering performance. **Code Example (Animation Optimization):** """css /* Preferred */ .animated-element { transform: translateX(100px); /*Uses hardware accelaration */ transition: transform 0.3s ease-in-out; } /* Avoid (Causes Reflow) */ .animated-element { left: 100px; /* Causes recalculation and reflow */ transition: left 0.3s ease-in-out; } """ **Common Anti-patterns:** * Frequent DOM manipulations that trigger layout recalculations. * Unnecessary use of layout-affecting CSS properties in animations. ## 2. JavaScript Performance Optimization ### 2.1. Minimize DOM Manipulations **Standard:** Reduce the number of DOM manipulations. **Why:** DOM manipulations are expensive operations that can significantly impact performance. * **Do This:** * Use document fragments to batch DOM updates. Create the structure in memory, and then append the entire fragment to the DOM at once. * Cache frequently accessed DOM elements. * **Don't Do This:** * Directly manipulate the DOM inside loops. * Query the DOM repeatedly for the same elements. **Code Example(Using DocumentFragments):** """javascript const data = ['Item 1', 'Item 2', 'Item 3']; const list = document.getElementById('myList'); const fragment = document.createDocumentFragment(); data.forEach(itemText => { const listItem = document.createElement('li'); listItem.textContent = itemText; fragment.appendChild(listItem); }); list.appendChild(fragment); // Append entire fragment to the DOM """ **Common Anti-patterns:** * Appending elements to the DOM one at a time in a loop. * Not caching DOM element references. ### 2.2. Event Delegation **Standard:** Use event delegation to handle events on dynamically added elements. **Why:** Avoids attaching event listeners to individual elements, reducing memory overhead and improving performance. * **Do This:** * Attach event listeners to a parent element that already exists. * Use the "event.target" property to determine which element triggered the event. * **Don't Do This:** * Attach event listeners to multiple similar elements individually. Especially not in a loop. **Code Example (Event Delegation):** """html <ul id="myList"> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> <script> document.getElementById('myList').addEventListener('click', function(event) { if (event.target && event.target.nodeName === 'LI') { console.log('List item clicked:', event.target.textContent); } }); </script> """ **Common Anti-patterns:** * Attaching event listeners to each list item individually. * Not utilizing event delegation for dynamically added elements. ### 2.3. Debouncing and Throttling **Standard:** Implement debouncing or throttling to limit the rate at which event handlers are executed. **Why:** Improves performance by preventing excessive function calls in response to events like scrolling or resizing. * **Do This:** * Use debouncing for events where you only care about the final state (e.g., auto-saving). * Use throttling for events where you need to execute the handler periodically (e.g., scroll events). * **Don't Do This:** * Execute computationally intensive tasks directly in event handlers without debouncing or throttling. **Code Example (Debouncing):** """javascript function debounce(func, delay) { let timeout; return function(...args) { const context = this; clearTimeout(timeout); timeout = setTimeout(() => func.apply(context, args), delay); }; } function handleInput() { console.log('Input processed'); } const debouncedInput = debounce(handleInput, 300); document.getElementById('myInput').addEventListener('input', debouncedInput); """ **Common Anti-patterns:** * Not using debouncing or throttling for performance-sensitive events. * Setting excessively long delays, resulting in poor user experience. ### 2.4. Optimize Images **Standard:** Optimize images to reduce file size without sacrificing quality. **Why:** Large images slow down page load times and consume excessive bandwidth. * **Do This:** * Use appropriate image formats (WebP, JPEG, PNG). * Compress images using tools like ImageOptim, TinyPNG, or equivalent. * Use responsive images with the "<picture>" element or "srcset" attribute. Consider lazy-loading images outside of the initial viewport. * **Don't Do This:** * Use unnecessarily large images. * Use incorrect image formats. * Fail to compress images before deploying to production. **Code Example (Responsive Images):** """html <picture> <source media="(max-width: 600px)" srcset="small.jpg"> <source media="(max-width: 1200px)" srcset="medium.jpg"> <img src="large.jpg" alt="My Image"> </picture> """ """html <img src="image.jpg" srcset="image-small.jpg 480w, image-medium.jpg 800w" sizes="(max-width: 600px) 480px, 800px" alt="My Image"> """ Lazy loading example: """html <img src="placeholder.jpg" data-src="image.jpg" alt="My Image" loading="lazy"> """ **Common Anti-patterns:** * Using large, unoptimized images. * Serving the same image size to all devices. * Not using lazy loading. ### 2.5. Asynchronous Loading **Standard:** Asynchronously load non-critical resources. **Why:** Improves the initial page load time by deferring the loading of less essential resources. * **Do This:** * Use the "async" or "defer" attributes for "<script>" tags. "defer" loads the script after the HTML is parsed but before "DOMContentLoaded" and executes them in order. "async" loads scripts asynchronously and executes them when they are available, out of order. * Lazy-load images and other media. * Load fonts asynchronously using "font-display: swap;". * **Don't Do This:** * Load all scripts and resources synchronously, blocking the rendering of the page. **Code Example (Asynchronous Script Loading):** """html <script src="my-script.js" async></script> <script src="my-other-script.js" defer></script> """ """css @font-face { font-family: 'MyFont'; src: url('my-font.woff2') format('woff2'); font-display: swap; /* Tells the browser to use a fallback font immediately and swap to 'MyFont' once it’s downloaded */ } """ **Common Anti-patterns:** * Loading all scripts synchronously. * Not using "font-display: swap;" for custom fonts. ## 3. Bulma-Specific Performance optimizations ### 3.1 Optimizing Responsiveness **Standard**: Correctly utilize Bulma's responsive modifiers and media queries for performance and user experience **Why**: Incorrect responsive breakpoints or overly complex layouts can cause performance issues on different devices, and a poor user experience if not implemented correctly. * **Do this:** * Choose reasonable breakpoints and stick to them. * Use Bulma's built in responsive colums "is-desktop", "is-tablet", "is-mobile" helpers to selectively hide or show content per device. * Test your site extensively on various devices and screen sizes. * **Don't Do This:** * Overuse custom media queries that duplicate functionality already offered in Bulma. * Nest too many Bulma grid systems (columns inside columns inside columns..), instead consider re-organizing, or creating custom CSS where Bulma fails for edge cases. * Ignore device testing. **Code Example (Bulma Responsive Columns):** """html <div class="columns"> <div class="column is-6 is-desktop"> <p>This is visible on desktop and larger screens.</p> </div> <div class="column is-6 is-mobile"> <p>This is visible on mobile screens.</p> </div> </div> """ ### 3.2. Minimize Bulma Component Override Complexity **Standard:** Avoid deeply nested or overly complex overrides of Bulma's default styles. **Why:** Overriding Bulma's styles extensively can lead to increased CSS specificity that harms performance and maintainability. * **Do This:** * Use Bulma's Sass variables to customize the framework's appearance before compiling. * Limit and carefully document any custom CSS rules overriding Bulma's defaults. * Use BEM (Block, Element, Modifier) methodology to style custom components. * **Don't Do This:** * Apply "!important" excessively to override styles; find a more targeted solution. * Use inline styles to override Bulma, as they are hard to manage and have high specificity. **Code Example (Sass Variable Customization):** """scss // _sass/custom.sass $primary: #ff385f; // Customize primary color $body-background-color: #f0f0f0; @import "../node_modules/bulma/bulma.sass"; """ **Common Anti-patterns:** * Overusing "!important". * Creating overly complex CSS selectors to override Bulma's styles. * Avoid customizing with Sass variables. ### 3.3. Optimize JavaScript Interactions with Bulma **Standard:** Optimize JavaScript code that manipulates or interacts with Bulma components. **Why:** Inefficient JavaScript can negate the performance benefits of Bulma's CSS framework. * **Do This:** * Use event delegation for Bulma components that involve multiple elements (e.g., menus, tabs). * Use requestAnimationFrame for animations involving Bulma elements to ensure smooth rendering. * Ensure event handlers are detached when Bulma components are destroyed or no longer needed to prevent memory leaks. * **Don't Do This:** * Directly manipulate Bulma components in computationally intensive loops without debouncing or throttling. * Use jQuery (or similar libraries) when simple vanilla JavaScript can achieve the same result. **Code Example("requestAnimationFrame" Example):** """javascript const element = document.querySelector('.animated-box'); function animate() { // Perform animation-related DOM manipulations or CSS changes element.style.transform = "translateX(${position}px)"; // Increment the animation position position += 2; // Request the next animation frame requestAnimationFrame(animate); } let position = 0; // Start the animation requestAnimationFrame(animate); """ ### 3.4. Accessibility Considerations **Standard:** Maintain accessibility when optimizing Bulma components for performance. **Why:** Performance optimizations should not compromise accessibility. * **Do This:** * Ensure that optimized animations and transitions are still accessible to users with disabilities. * Use ARIA attributes to enhance accessibility. Where appropriate and if it doesn't exist in the Bulma component already. * Test performance optimizations with assistive technologies (e.g., screen readers). * **Don't Do This:** * Remove or disable accessibility features to improve performance. * Use animations excessively, leading to motion sickness or distraction. **Code Example (ARIA Attributes):** """html <button class="button is-primary" aria-label="Submit form"> Submit </button> """ ### 3.5 Use Bulma's Modifiers instead of Writing Custom CSS **Standard:** Prioritize using Bulma's built-in modifiers and helper classes over creating custom CSS for common styling adjustments. **Why:** Bulma's modifiers are optimized and well-tested. Using them reduces the need for custom CSS, decreasing file size and increasing maintainability. * **Do This:** * Explore Bulma's documentation for relevant modifiers before writing custom CSS. Example: Using "is-rounded", "is-shadowed"... * Combine multiple Bulma modifiers to achieve the desired effect. * **Don't Do This:** * Replicate Bulma's existing modifier functionality with custom CSS. * Overlook Bulma's helper classes for spacing, typography, and display. **Code Example (Using Bulma Modifiers):** """html <button class="button is-primary is-rounded is-outlined">Click Me</button> <!-- uses multiple modifiers --> """ Following these comprehensive guidelines will help ensure high-performance Bulma projects while maintaining code quality, readability, and best practices principles.