diff --git a/frontend/app/dashboard-layout.ts b/frontend/app/dashboard-layout.ts
new file mode 100644
index 00000000..28c723ad
--- /dev/null
+++ b/frontend/app/dashboard-layout.ts
@@ -0,0 +1,166 @@
+// frontend/app/(dashboard)/layout.tsx
+import { Sidebar } from '@/components/layout/sidebar';
+import { Topbar } from '@/components/layout/topbar';
+
+export default function DashboardLayout({ children }: { children: React.ReactNode }) {
+return (
+
+);
+}
+
+// frontend/components/layout/topbar.tsx
+'use client';
+
+import { useRouter } from 'next/navigation';
+import { LogOut, User } from 'lucide-react';
+import { useAuthStore } from '@/store/auth.store';
+
+export function Topbar() {
+const router = useRouter();
+const { user, logout } = useAuthStore();
+
+const handleLogout = async () => {
+await logout();
+router.push('/login');
+};
+
+const initials = user
+? `${user.firstName[0]}${user.lastName[0]}`.toUpperCase()
+: '?';
+
+return (
+
+
+
+
+ {/* User info */}
+
+
+ {user ? (
+ {initials}
+ ) : (
+
+ )}
+
+ {user && (
+
+
+ {user.firstName} {user.lastName}
+
+
{user.role}
+
+ )}
+
+
+ {/* Divider */}
+
+
+ {/* Logout */}
+
+
+
+
+);
+}
+
+// frontend/components/layout/sidebar.tsx
+"use client";
+
+import Link from "next/link";
+import { usePathname } from "next/navigation";
+import { clsx } from "clsx";
+import {
+LayoutDashboard,
+Package,
+Users,
+Building2,
+BarChart3,
+Settings,
+} from "lucide-react";
+
+const navItems = [
+{ href: "/dashboard", label: "Dashboard", icon: LayoutDashboard },
+{ href: "/assets", label: "Assets", icon: Package },
+{ href: "/users", label: "Users", icon: Users },
+{ href: "/departments", label: "Organisation", icon: Building2 },
+{ href: "/reports", label: "Reports", icon: BarChart3 },
+];
+
+export function Sidebar() {
+const pathname = usePathname();
+
+return (
+
+
+);
+}
diff --git a/frontend/lib/query/hooks/query.hook.ts b/frontend/lib/query/hooks/query.hook.ts
new file mode 100644
index 00000000..17f766d9
--- /dev/null
+++ b/frontend/lib/query/hooks/query.hook.ts
@@ -0,0 +1,161 @@
+// frontend/lib/query/hooks/useAssets.ts
+import { useQuery, useMutation, useQueryClient, UseQueryOptions } from '@tanstack/react-query';
+import {
+assetApiClient,
+AssetListFilters,
+AssetListResponse,
+CreateAssetInput,
+DepartmentWithCount,
+CategoryWithCount,
+} from '@/lib/api/assets';
+import { queryKeys } from '../keys';
+import { Asset } from '../types/asset';
+import { ApiError } from '../types';
+
+export function useAssets(
+filters?: AssetListFilters,
+options?: Omit, 'queryKey' | 'queryFn'>,
+) {
+return useQuery({
+queryKey: queryKeys.assets.list(filters as Record ?? {}),
+queryFn: () => assetApiClient.getAssets(filters),
+...options,
+});
+}
+
+// ── Departments ──────────────────────────────────────────────
+
+export function useDepartmentsList() {
+return useQuery({
+queryKey: queryKeys.departments.list(),
+queryFn: () => assetApiClient.getDepartments(),
+});
+}
+
+export function useCreateDepartment() {
+const queryClient = useQueryClient();
+return useMutation<{ id: string; name: string }, ApiError, { name: string; description?: string }>({
+mutationFn: (data) => assetApiClient.createDepartment(data),
+onSuccess: () => {
+queryClient.invalidateQueries({ queryKey: queryKeys.departments.all });
+},
+});
+}
+
+export function useDeleteDepartment() {
+const queryClient = useQueryClient();
+return useMutation({
+mutationFn: (id) => assetApiClient.deleteDepartment(id),
+onSuccess: () => {
+queryClient.invalidateQueries({ queryKey: queryKeys.departments.all });
+},
+});
+}
+
+// ── Categories ───────────────────────────────────────────────
+
+export function useCategories() {
+return useQuery({
+queryKey: queryKeys.categories.list(),
+queryFn: () => assetApiClient.getCategories(),
+});
+}
+
+export function useCreateCategory() {
+const queryClient = useQueryClient();
+return useMutation<{ id: string; name: string }, ApiError, { name: string; description?: string }>({
+mutationFn: (data) => assetApiClient.createCategory(data),
+onSuccess: () => {
+queryClient.invalidateQueries({ queryKey: queryKeys.categories.all });
+},
+});
+}
+
+export function useDeleteCategory() {
+const queryClient = useQueryClient();
+return useMutation({
+mutationFn: (id) => assetApiClient.deleteCategory(id),
+onSuccess: () => {
+queryClient.invalidateQueries({ queryKey: queryKeys.categories.all });
+},
+});
+}
+
+// ── Assets ───────────────────────────────────────────────────
+
+export function useCreateAsset() {
+const queryClient = useQueryClient();
+return useMutation({
+mutationFn: (data) => assetApiClient.createAsset(data),
+onSuccess: () => {
+queryClient.invalidateQueries({ queryKey: queryKeys.assets.all });
+},
+});
+}
+
+export function useUpdateAsset(id: string) {
+const queryClient = useQueryClient();
+return useMutation>({
+mutationFn: (data) => assetApiClient.updateAsset(id, data),
+onSuccess: (updated) => {
+queryClient.setQueryData(queryKeys.assets.detail(id), updated);
+queryClient.invalidateQueries({ queryKey: queryKeys.assets.all });
+},
+});
+}
+
+---
+
+// frontend/lib/query/hooks/useReports.ts
+import { useQuery } from '@tanstack/react-query';
+import { reportsApiClient, ReportsSummary } from '@/lib/api/reports';
+
+export function useReportsSummary() {
+return useQuery({
+queryKey: ['reports', 'summary'],
+queryFn: () => reportsApiClient.getSummary(),
+});
+}
+
+---
+
+// frontend/lib/query/hooks/useUser.ts
+import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
+import {
+usersApiClient,
+AppUser,
+UserRole,
+UpdateProfileInput,
+} from "@/lib/api/users";
+
+const usersKeys = {
+all: ["users"] as const,
+list: (search?: string) => [...usersKeys.all, "list", search ?? ""] as const,
+};
+
+export function useUsersList(search?: string) {
+return useQuery({
+queryKey: usersKeys.list(search),
+queryFn: () => usersApiClient.getUsers(search),
+});
+}
+
+export function useUpdateUserRole() {
+const queryClient = useQueryClient();
+return useMutation({
+mutationFn: ({ id, role }) => usersApiClient.updateRole(id, role),
+onSuccess: () => {
+queryClient.invalidateQueries({ queryKey: usersKeys.all });
+},
+});
+}
+
+export function useUpdateProfile() {
+const queryClient = useQueryClient();
+return useMutation({
+mutationFn: (data) => usersApiClient.updateProfile(data),
+onSuccess: () => {
+queryClient.invalidateQueries({ queryKey: usersKeys.all });
+},
+});
+}