| Abdulrhman Al-Qassas

Front-End Best Practices I Use in Real Projects

Front-end project preview

Introduction

Front-end development is not only about making a page look good. A good interface should be clear, responsive, fast, accessible, and simple enough for another developer to understand later.

In my work with React, Vite, Tailwind CSS, React Query, Redux, and OpenLayers, I have learned that best practices are not abstract rules. They are small habits that prevent real problems: slow pages, duplicated logic, confusing state, broken mobile layouts, and code that becomes hard to change.

Start with the User Flow

Before building components, I like to understand what the user is trying to do.

For a book review project, the important flow might be searching, browsing, and reading book details. For a geospatial project, the important flow might be finding a location, understanding map data, and taking an action. For a verification system, the important flow might be trust, clarity, and safe handling of information.

When the user flow is clear, the interface becomes easier to design and the code becomes easier to organize.

Keep Components Focused

A component should have one clear responsibility. If one component handles layout, data fetching, form state, map setup, filtering, and styling, it becomes difficult to reuse or debug.

I prefer this structure:

components/
  ProjectCard.tsx
  SearchInput.tsx
  EmptyState.tsx
  map/
    OpenLayersMap.tsx
    markerLayer.ts
    mapStyles.ts

Small components make the project easier to scan. They also make it easier to improve the UI without touching business logic.

Use the Right State Tool

Not every piece of data belongs in Redux. Not every API response belongs in local state.

My general rule is:

  • Use local state for UI details like opened menus, form inputs, and active tabs.
  • Use React Query for server data, loading states, caching, and refetching.
  • Use Redux only for state that many parts of the app truly need to share.
  • Use refs for non-React objects like an OpenLayers map instance.

This keeps state predictable. It also avoids unnecessary re-renders and duplicated API logic.

Build Responsive Layouts from the Beginning

Responsive design should not be a final step. It should be part of the first implementation.

With Tailwind CSS, I usually start with the mobile layout, then add larger breakpoints only when the design needs them.

<section className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
  {projects.map((project) => (
    <ProjectCard key={project.title} project={project} />
  ))}
</section>

A simple grid like this is easier to maintain than many custom media queries.

Make Loading and Empty States Real

A polished project handles more than the happy path. Users should know what is happening when data is loading, when a search returns nothing, or when an API request fails.

For example, a book library should show:

  • A loading state while books are being fetched.
  • An empty state when no books match the search.
  • A clear error state if the request fails.

These details make the application feel reliable.

Write Clear Data Boundaries

Frontend code becomes cleaner when data is transformed before it reaches the UI.

Instead of formatting dates, fixing missing fields, and building labels inside every component, I prefer small helper functions:

export function formatProjectDate(date: string) {
  return new Intl.DateTimeFormat('en', {
    month: 'short',
    year: 'numeric'
  }).format(new Date(date));
}

This keeps components focused on rendering.

Treat Accessibility as Part of Quality

Good UI should work with a keyboard, readable contrast, clear labels, and semantic HTML.

Some simple checks I use:

  • Buttons are buttons, not clickable divs.
  • Form inputs have labels, even when the visual label is hidden.
  • Images have meaningful alt text when they communicate content.
  • Focus states are visible.
  • Text remains readable on mobile screens.

Accessibility is not separate from design. It is part of building a professional interface.

Keep Map Interfaces Organized

Geospatial interfaces can become complex quickly. A map may include tile layers, markers, popups, search, filters, selected features, and drawing tools.

The best practice is to separate map concerns:

  • Base layer setup.
  • Marker or vector layer setup.
  • Map interactions.
  • UI controls outside the map.
  • Data fetching outside the map rendering code.

This makes OpenLayers easier to use inside React and prevents the map component from becoming too large.

Test the Build, Not Only the Browser

A page can look fine during development and still fail during production build. Static generation, TypeScript checks, imports, path handling, and content parsing can expose issues late.

That is why I like to run:

pnpm run build

before considering a change complete. A successful build gives confidence that the project can be deployed.

Conclusion

Best practices are not about making code look complicated. They are about making the next change easier.

For me, good front-end work means building interfaces that feel smooth to users and stay understandable for developers. Whether the project is a React portfolio, a book review app, a blockchain verification system, or an OpenLayers map, the same principles apply: clear structure, focused components, thoughtful state, responsive design, and careful attention to real user workflows.

Stay up-to-date with my words