SweetHome — Full Project Analysis
Project: SweetHome Next.js Real Estate Application
Date: June 16, 2026
Framework: Next.js 16.1.6 (App Router) + React 18.3.1
Language: JavaScript (no TypeScript)
Styling: Tailwind CSS v4 + DaisyUI (unused) + Flowbite (unused)
API: Custom .NET backend at https://45.93.137.91.nip.io/api
1. Project Structure
Directory Tree (Top 3 Levels)
Route Summary (33 pages)
| Type |
Routes |
Count |
| Public |
/, /login, /register/*, /forgot-password, /auth/choose-role, /properties, /property/[id], /terms, /privacy, /faq, /support, /onboarding |
14 |
| Protected (auth only) |
/profile, /settings, /change-password, /account-verification, /favorites, /booked-properties, /reservations, /notifications, /payments, /my-rates, /reports, /blocked |
12 |
| Owner only |
/owner/properties, /owner/properties/add, /owner/reservations, /owner/bookings, /owner/calendar, /owner/profits, /owner/account-book |
7 |
2. Architecture Overview
Layout Hierarchy
- No nested layouts — flat route structure
- No
middleware.js — all route protection is client-side only
- Nav bar hidden on auth pages (
/login, /register/*, /blocked, /forgot-password, /auth/choose-role)
Data Flow Pattern
3. API Layer
File: app/utils/api.js (1198 lines — 370 commented legacy + 828 active)
Ratings API: app/utils/ratings.js (separate file with own apiFetch)
Fetch Helpers
| Function |
Lines |
Method |
Auth |
Error Handling |
Return Type |
apiFetch(endpoint, options) |
421-478 |
Any |
Auto Bearer |
Throws on non-ok (except 206) |
data (auto-unwrapped) |
authFetch(endpoint, body, token) |
483-524 |
POST |
Manual param |
Returns {status,data,ok,message} |
Object |
reportFetch(endpoint, body) |
526-558 |
POST |
None |
Returns {status,data,ok,message} |
Object |
multipartAuthFetch(endpoint, formData) |
772-803 |
POST |
Auto Bearer |
Returns {status,data,ok,message} |
Object |
Exported API Functions (47 total)
| Category |
Functions |
Count |
| Rent Properties |
getRentProperties, getRentProperty, getRentPropertyLocations, filterRentProperties |
4 |
| Sale Properties |
getSaleProperties, getSaleProperty, getSalePropertyById |
3 |
| Generic Property |
getProperty |
1 |
| Recommendations |
getRecommendations, getTopRecommendations |
2 |
| Reservations |
getAvailableDateRanges, getReservations, getReservation, checkAvailability, bookReservation, getUserReservations, getOwnerReservationRequests, getOwnerReservationsByStatuses, ownerConfirmReservation, confirmDepositPayment, adminConfirmDeposit, updateBookingStatus, payDeposit |
13 |
| Owner Management |
getMyRentListings, getMySaleListings, addRentProperty, addSaleProperty, editRentProperty, editSaleProperty, updateRentPropertyStatus, updateSalePropertyStatus, getOwnerContactInformation, getOwnerStatistics |
10 |
| Auth |
loginWithEmail, loginWithPhone, sendEmailOTP, sendPhoneOTP, verifyEmail, verifyPhone, changePassword, requestForgetPasswordOtp, verifyForgetPasswordOtp, resetPassword, deleteMyAccount |
11 |
| Registration |
addOwner, addCustomer, registerRealEstateAgent |
3 |
| Favorites |
getUserFavoriteProperties, addFavoriteProperty, removeFavoriteProperty |
3 |
| Notifications |
getUserNotifications, setFCMToken |
2 |
| Terms |
getARTerms, getENTerms, addOrUpdateTerms |
3 |
| Currencies |
getCurrencies |
1 |
| Files |
uploadPicture |
1 |
| Reports |
sendGeneralReport, submitReport, submitReservationReport, updateReservationReport, submitSaleReport, updateSaleReport |
6 |
| Profile |
getCustomerByUserId, getOwnerByUserId |
2 |
Ratings API (5 functions)
addPropertyRating, addCustomerRating, getPropertyRatings, getCustomerRatings, getPropertyAverageRating
API Endpoint Coverage
| HTTP Method |
Count |
Examples |
| GET |
26 |
/RentProperties/GetRentProperties, /Reservations/GetAvailableDates/available/${id} |
| POST |
17 |
/Auth/LogInWithEmail, /Reservations/PayDeposit/pay-deposit, /Rating/AddPropertyRating |
| PUT |
8 |
/RentProperties/EditRentProperty/${id}, /Reservations/AdminConfirmDeposit/admin-confirm-deposit |
| DELETE |
2 |
/FavoriteProperty/Remove, /User/DeleteMyAccount |
4. State Management
Context Providers
| Context |
File |
State |
Consumers |
Status |
| FavoritesProvider |
app/contexts/FavoritesContext.js |
favorites[], isLoading |
FloatingSidebar, /favorites, /properties, /property/[id] |
✅ Active |
| NotificationsProvider |
app/contexts/NotificationsContext.js |
notifications[], unreadCount, isLoading |
BottomNav, FloatingSidebar |
✅ Active |
| PropertyContext |
app/contexts/PropertyContext.js |
properties[], loading, error |
None |
❌ Orphaned (never mounted) |
| PropertyContext |
app/utils/PropertyContext.js |
Same as above |
None |
❌ Orphaned duplicate |
localStorage Keys (10 actively written, ~5 legacy read-only)
| Key |
Data |
Written By |
Read By |
auth_token |
JWT string |
AuthService.addToken() |
AuthService.getToken(), firebase.js |
cached_user |
User profile JSON |
AuthService.cacheUser() |
AuthService.getCachedUser() |
language |
"en" or "ar" |
ClientLayout.js |
ClientLayout.js |
sweethome_onboarding_completed |
"true" |
/onboarding/page.js |
/onboarding/page.js |
ownerProperties |
Properties array JSON |
/owner/properties/page.js |
/owner/calendar/page.js |
ownerBookings |
Bookings array JSON |
/owner/bookings/page.js |
/owner/bookings/page.js |
ownerProfitsTable |
Profit data JSON |
/owner/profits/page.js |
/owner/profits/page.js |
userProfile |
Profile form data JSON |
/profile/page.js |
/profile/page.js |
userAvatar |
Base64 data URL |
/profile/page.js |
/profile/page.js |
token, accessToken, authToken |
(legacy reads only) |
— |
/settings, /payments, /reservations |
Auth Flow
5. Component Architecture
Component Inventory (14 reusable components)
| Component |
File |
Lines |
Purpose |
State |
| HeroSearch |
components/home/HeroSearch.js |
321 |
Hero search with filters |
filters, login dialog |
| PropertyMap (home) |
components/home/PropertyMap.js |
287 |
Map with markers + popup |
selectedProperty, map ref |
| PropertyMap (property) |
components/property/PropertyMap.js |
166 |
Map at property detail |
Tooltip state |
| BookingCalendar |
components/property/BookingCalendar.js |
124 |
Monthly booking grid |
currentMonth, selectedStart |
| PropertyMapWithMarkers |
components/PropertyMapWithMarkers.js |
100 |
Generic Leaflet map |
Map ref, markers ref |
| StarRating |
components/ratings/StarRating.js |
134 |
5-star input |
hoverRating |
| PropertyRatingList |
components/ratings/PropertyRatingList.js |
286 |
Paginated reviews |
ratings, page, loading |
| PropertyRatingForm |
components/ratings/PropertyRatingForm.js |
317 |
4-field rating form |
Clean/services/owner/experience |
| CustomerRatingForm |
components/ratings/CustomerRatingForm.js |
92 |
3-field rating form |
Furn/terms/behavior |
| BottomNav |
components/BottomNav.js |
58 |
Mobile bottom bar |
Badge from context |
| FloatingSidebar |
components/FloatingSidebar.js |
158 |
Quick-access buttons |
Framer-motion variants |
| NavLinks |
components/NavLinks.js |
42 |
Nav link atoms |
usePathname active |
| NotificationHandler |
components/NotificationHandler.js |
151 |
FCM push handler |
Permission state |
Largest Page Files
| Rank |
File |
Lines |
Complexity |
| 1 |
api.js |
1198 |
60+ functions, 4 fetch helpers, 370 lines commented |
| 2 |
PropertyDetail.js |
1743 |
56 imports, 8+ state vars, booking calendar, image gallery, owner check, ratings, map |
| 3 |
owner/properties/page.js |
2057 |
CRUD + modals + localStorage caching + API calls |
| 4 |
ClientLayout.js |
804 |
Nav (desktop+mobile), user menu, language switcher, context providers |
| 5 |
owner/properties/add/page.js |
700+ |
Multi-step form with map, image upload, pricing |
| 6 |
app/page.js (Home) |
623 |
Property fetching, multi-filter, hero, map, feature cards |
6. Key Patterns
Data Fetching (4 Patterns)
| Pattern |
Usage |
Found In |
useEffect + useState |
~90% of pages |
Most pages |
| Context-level fetch |
2 providers |
FavoritesContext, NotificationsContext |
| localStorage cache |
Owner dashboards |
owner/bookings, owner/calendar, owner/profits |
| Mock data fallback |
3 owner pages |
owner/bookings, owner/calendar, owner/profits |
Styling
- 100% Tailwind CSS v4 (utility classes, no CSS modules)
- Custom
globals.css: Madani Arabic fonts (9 weights), Leaflet overrides, keyframe animations
- Color palette:
amber-500/600 (primary), #ede6e6 (bg), #156874 (accent teal)
- RTL-first with dynamic LTR switching via
currentLanguage state
Animations (Framer Motion v12.29.2)
initial/animate opacity + y/x translations (section reveals)
whileHover/whileTap scale (buttons, interactive elements)
AnimatePresence (property popups, user menus)
whileInView + viewport (scroll-triggered animations on home page)
staggerChildren (hero text)
- Spring transitions
{ type: "spring", damping: 25, stiffness: 300 }
Form Handling
- All forms: Controlled
useState — no React Hook Form, Formik, or useReducer
- Validation: Inline
value === 0 && <p className="text-red-500">مطلوب</p>
- No form libraries — all hand-rolled
Responsive Breakpoints
| Breakpoint |
Layout |
| Default (mobile) |
Single column, BottomNav, hamburger menu |
md: (768px) |
Desktop nav, 2-3 column grids |
lg: (1024px) |
PropertyDetail sidebar, 3-column grids |
7. Owner Pages Analysis (Dashboard Section)
| Route |
File |
Lines |
Status |
Data Source |
/owner/properties |
owner/properties/page.js |
2057 |
✅ Active |
API (getMyRentListings, getMySaleListings) + localStorage cache |
/owner/properties/add |
owner/properties/add/page.js |
700+ |
✅ Active |
API (addRentProperty, addSaleProperty, uploadPicture) |
/owner/reservations |
owner/reservations/page.js |
1400+ |
❌ Commented out |
Mock data (commented) |
/owner/bookings |
owner/bookings/page.js |
560+ |
⚠️ Demo |
localStorage mock data only |
/owner/calendar |
owner/calendar/page.js |
580+ |
⚠️ Demo |
localStorage mock data only |
/owner/profits |
owner/profits/page.js |
600+ |
⚠️ Demo |
localStorage mock data only |
/owner/account-book |
owner/account-book/page.js |
500+ |
✅ Active |
API (getOwnerStatistics) |
8. Admin Functionality
| Component |
Status |
Data Source |
| BookingRequests |
✅ Active |
Real API (getReservations, adminConfirmDeposit) |
| Users |
❌ Not implemented |
— |
| Properties |
❌ Not implemented |
— |
| LedgerBook |
⚠️ Mock only |
3 hardcoded mock transactions |
| Dashboard |
❌ Not implemented |
— |
Designed for internal admin use at /admin — tabs for Bookings/Users/Properties/Ledger/Dashboard.
9. Known Technical Debt
Dead Code
| File |
Dead Lines |
Issue |
api.js |
Lines 1-370 (370 lines) |
Entire legacy version commented out |
StarRating.js |
Lines 1-93 (93 lines) |
Old framer-motion version commented out |
PropertyRatingList.js |
~150 lines |
Old version commented out |
PropertyRatingForm.js |
~220 lines |
Old version commented out |
contexts/PropertyContext.js |
Entire file |
Never mounted |
utils/PropertyContext.js |
Entire file |
Duplicate orphan |
Code Duplication
| Pattern |
Files |
Description |
| Leaflet maps |
3 separate files |
PropertyMapWithMarkers.js, home/PropertyMap.js, property/PropertyMap.js — all setup Leaflet identically |
| Rating forms |
PropertyRatingForm.js (317) + CustomerRatingForm.js (92) |
~75% code overlap; both define identical RatingField inline |
| formatCurrency |
4+ locations |
Scattered across files with slightly different logic |
| Image URL building |
4+ locations |
Different implementations for same task |
| Notifications page |
/notifications/page.js vs NotificationsContext |
Page duplicates all context state/logic |
Architecture Issues
| Issue |
Impact |
| No middleware.js |
All route protection is client-side only |
| JWT in localStorage |
XSS-vulnerable token storage |
| Client-side role checks |
Users can modify JWT to elevate privileges |
| Owner pages use mock data |
/owner/bookings, /owner/calendar, /owner/profits are demo-only |
| 3 unused UI libraries |
DaisyUI, Flowbite, Yandex Maps imported but never used |
| No TypeScript |
112 JS files, no type safety |
| No ESLint |
No linting configured |
| No testing framework |
Zero tests |
| Flat route structure |
No nested layouts; all pages share root layout |
| Active console.log |
~30+ files with console.log statements (security risk) |
10. Dependencies
Production (18)
| Package |
Version |
Purpose |
| next |
16.1.6 |
Framework |
| react / react-dom |
^18.3.1 |
UI |
| firebase |
^12.11.0 |
FCM push notifications |
| leaflet / react-leaflet |
1.9.4 / 4.2.1 |
Maps |
| @pbe/react-yandex-maps |
^1.2.5 |
Yandex Maps (unused) |
| framer-motion |
^12.29.2 |
Animations |
| lucide-react |
^0.563.0 |
Icons |
| flowbite / flowbite-react |
4.0.1 / 0.12.16 |
UI library (unused) |
| react-hot-toast |
^2.6.0 |
Toasts |
| i18next / react-i18next / i18next-browser-languagedetector |
25.8 / 16.5 / 8.2 |
i18n |
| jspdf / html2canvas |
4.2.1 / 1.4.1 |
PDF generation |
| xlsx |
^0.18.5 |
Excel export |
| react-intersection-observer |
^10.0.3 |
Scroll detection |
Dev (7)
| Package |
Version |
Purpose |
| tailwindcss |
^4.1.18 |
CSS framework |
| @tailwindcss/postcss |
^4 |
PostCSS plugin |
| postcss / autoprefixer |
^8.5.6 / ^10.4.23 |
CSS processing |
| daisyui |
^5.5.14 |
UI components (unused) |
| babel-plugin-react-compiler |
1.0.0 |
React compiler optimization |
Missing (notable absences)
- No TypeScript
- No ESLint
- No testing (Jest, Playwright, Cypress)
- No state management library (Redux, Zustand)
- No data fetching library (React Query, SWR)
- No form library (React Hook Form, Formik)
- No security lib (helmet, cors, csurf)
- No HTTP client (axios, ky)
- No JWT lib (jsonwebtoken, jose)
11. Security Summary
(See security-audit-report.md for full details)
| # |
Finding |
Severity |
| 1 |
JWT in localStorage (XSS-theft) |
🔴 Critical |
| 2 |
Stored XSS via Leaflet popup HTML |
🔴 Critical |
| 3 |
OTP code logged to console |
🔴 Critical |
| 4 |
No server-side middleware |
🔴 Critical |
| 5 |
Passwords in URL query params |
🔴 Critical |
| 6 |
IDOR on property edit/status APIs |
🔴 Critical |
| 7 |
Client-only role checks |
🟠 High |
| 8 |
HTTP endpoints leak tokens |
🟠 High |
| 9 |
No CSP/security headers |
🟠 High |
| 10 |
Mass assignment via spread |
🟠 High |
| 11 |
Error messages leak internals |
🟠 High |
| 12 |
Hardcoded IPs (10+ files) |
🟡 Medium |
12. File Size Heatmap
| Size Range |
Files |
Examples |
| 1500-2100 lines |
2 |
PropertyDetail.js (1743), owner/properties/page.js (2057) |
| 600-1200 lines |
6 |
api.js (1198), ClientLayout.js (804), login/page.js (800+), owner/properties/add/page.js (700+), app/page.js (623), owner/bookings/page.js (560+) |
| 200-600 lines |
15 |
Most page files |
| < 200 lines |
~70 |
Enum files, smaller components, error/loading pages |