Built an *Offline-first Todo App* that keeps working even when the backend or internet goes down ⚡ Try it: https://lnkd.in/guCR4Gua This started as a basic full-stack project, but I pushed it further to handle real-world issues like unreliable networks. --- ## ⚙️ How it works - Data is stored locally using IndexedDB (Dexie) - You can create/update/delete todos fully offline - Changes are stored locally and marked as unsynced A background sync process runs only when: - 🌐 internet is available - 🔐 user is authenticated - 🖥️ server is reachable - Polling (~5s) keeps data in sync across devices - UI shows connection state (internet + server) ### 🧩 Manual controls - Force sync → push local changes immediately - Refetch → pull latest state from backend Even if the backend is down, the app still works using the local database. --- ## 🧠 Design choices I chose polling over WebSockets: - simpler, stateless backend - easier to deploy and scale - real-time updates weren’t critical **Tradeoff:** updates are delayed by a few seconds.(5 sec ) --- ## 📚 What I learned - Offline-first architecture ≠ API-first thinking - Syncing data is harder than CRUD - Handling failure cases changes how you design apps --- ## 🚀 Next step Batching updates and improving retry logic. --- #webdevelopment #fullstack #reactjs #javascript
Offline Todo App with Local Storage and Syncing
More Relevant Posts
-
Most performance issues in web apps aren’t because of “bad code.” They’re because of how data is fetched and handled. I ran into this while working on a full-stack application where APIs started slowing down as usage increased. Here’s what was happening 👇 ⚠️ Symptoms: • APIs taking longer to respond under load • Repeated database calls for similar data • Frontend waiting too long → poor user experience 👉 What we changed: • Optimized API design (reduced unnecessary data transfer) • Introduced efficient query handling in the backend • Reduced redundant calls by restructuring how data was fetched • Improved client-side handling to avoid blocking UI rendering 🚀 Results: • ~25–30% improvement in response time • Noticeably smoother user experience • Better scalability under concurrent usage 💡 Key takeaway: Good performance isn’t just about writing efficient functions. It’s about: • Designing APIs thoughtfully • Minimizing unnecessary data flow • Thinking end-to-end (frontend + backend + database) Curious, how do you usually approach performance issues in your applications? #SoftwareEngineering #FullStackDeveloper #NodeJS #ReactJS #SystemDesign
To view or add a comment, sign in
-
Most Next.js apps become unmaintainable after 6 months. Here's what we did differently in DutyDuke. Side effect we didn't plan for: Claude Code and Cursor ship better PRs here, because the pattern is so rigid there's only one reasonable way to add a feature. The problem isn't Next.js. It's that business logic ends up everywhere - in components, in API routes, in queries. Everything coupled to everything. Nobody plans it that way. It just happens. When we built DutyDuke, we made one rule early: business logic lives in exactly one place, and it knows nothing about Next.js, Prisma, or anything else. Every domain - employees, absences, documents, benefits - follows the same three layers: Model - pure TypeScript. No framework, no database. Just business rules. The only layer we'd carry unchanged into any other stack. Infrastructure - implements the interfaces the model defines. Prisma lives here. Controllers live here. The model never knows they exist. Next.js - Server Actions for mutations, Server Components for data fetching, Client Components only where truly needed. 11 domains in DutyDuke. All the same shape. After 18 months, adding something new still feels boring - and boring means predictable, predictable means fast. The full architecture is documented in the repo if you want to dig in.
To view or add a comment, sign in
-
AI can handle 100% of software development, so we don’t need to worry about code quality. I still come across statements like this from time to time. From my experience working heavily with AI agents (where they generate 80 to 90% of my code), we’re not there yet. That remaining 10% might seem small, but it’s vital for AI-driven development. It’s the foundation everything else depends on. Those 10% are: - Setting up the right AI environment - creating sub-agents and skills tailored to the project requirements - Choosing the right structure and architecture - clear boundaries and a predictable flow for implementing features When logic is scattered across 10 different server components, every change becomes a search problem. Agents have to explore, infer, and guess, or you must actually remember where these things are and pin-point for AI where they are. Oftentimes it means more tokens, more tool calls, and a higher chance of subtle bugs. With proper architecture, everything changes: - Business logic lives in one logical place - Context is easier to reason about - AI can deliver features end-to-end - You get better results with less overhead We actually see it in action in DutyDuke. Before writing any code, we spent a lot of time thinking through the system and choosing the right architecture. At first, it felt like overkill. More boilerplate, complexity and upfront effort. Decision to stick with it paid off quickly. Instead of fighting the codebase, AI could actually build on top of it. And since it's open source you can see it for yourself as well. Good engineering practices are more important now than ever.
Most Next.js apps become unmaintainable after 6 months. Here's what we did differently in DutyDuke. Side effect we didn't plan for: Claude Code and Cursor ship better PRs here, because the pattern is so rigid there's only one reasonable way to add a feature. The problem isn't Next.js. It's that business logic ends up everywhere - in components, in API routes, in queries. Everything coupled to everything. Nobody plans it that way. It just happens. When we built DutyDuke, we made one rule early: business logic lives in exactly one place, and it knows nothing about Next.js, Prisma, or anything else. Every domain - employees, absences, documents, benefits - follows the same three layers: Model - pure TypeScript. No framework, no database. Just business rules. The only layer we'd carry unchanged into any other stack. Infrastructure - implements the interfaces the model defines. Prisma lives here. Controllers live here. The model never knows they exist. Next.js - Server Actions for mutations, Server Components for data fetching, Client Components only where truly needed. 11 domains in DutyDuke. All the same shape. After 18 months, adding something new still feels boring - and boring means predictable, predictable means fast. The full architecture is documented in the repo if you want to dig in.
To view or add a comment, sign in
-
Things I stopped doing in Next.js (after working on production systems at scale): ❌ Treating App Router like traditional CSR/SSR ❌ Defaulting to client-side state for server data ❌ Ignoring cache invalidation strategy ❌ Coupling data fetching tightly with UI structure At a small scale, this works. At scale? 👉 Inconsistent data 👉 Over-fetching and hidden latency 👉 Cache behaving unpredictably 👉 Systems that are hard to reason about --- Next.js is not just a framework— it’s an opinionated runtime around data flow and caching. Once I started thinking in those terms: ✔️ Designed data boundaries first, UI second → What runs on server vs client is a system decision, not convenience ✔️ Treated caching as a first-class concern → "force-cache", "no-store", "revalidate" are not options—they define system behavior ✔️ Avoided implicit data dependencies → Made data flow explicit instead of relying on component tree structure ✔️ Used client components intentionally → Only where interactivity is required, not as a default escape hatch ✔️ Optimized around consistency vs freshness trade-offs → Not every request needs real-time data Because most issues in Next.js apps don’t come from React or syntax… They come from misunderstanding how data flows through the system. Once you get that right: → Performance becomes predictable → Scaling becomes manageable → Debugging becomes easier Development on Next.js is not about knowing APIs. #NextJS #ReactJS #WebDevelopment #SoftwareEngineering #SystemDesign #FullStackDeveloper #TechLeadership #ScalableSystems It’s about making the right architectural decisions early. What’s one design decision in Next.js that came back to bite you later? #NextJS #AppRouter #SoftwareArchitecture #FullStackDevelopment #WebPerformance #SystemDesign #ReactJS
To view or add a comment, sign in
-
-
Your Next.js app does not have a performance problem. It has a data fetching problem. I have seen this pattern on almost every project we take over from another team: → Some pages use Server Components. → Some use useEffect with fetch(). → Some use React Query. → Some call the API directly inside components. → None of them share a caching layer. The result is a dashboard that feels slow, a page that flashes empty content, and an API getting hit with requests for data that has not changed in six hours. Nobody made bad decisions. Nobody made any decisions. Each developer just did what made sense for their component in isolation. Here is what one hour of planning at the start of a project locks in: → Server vs client fetching: defined per data type, not per developer. → One tool for client-side fetching. React Query. Used everywhere. → Staleness profiles set per data type. Not all data needs to be fresh. → Waterfall dependencies mapped before components are built. → Error states defined for critical data vs secondary data. Five decisions. One hour. Zero performance debugging later. The conversation that saves the most time is the one you have before writing the first line. What does your team's data fetching strategy look like at project start? #NextJS #FrontendArchitecture #ReactDevelopment #WebPerformance #FrontendBestPractices
To view or add a comment, sign in
-
-
“How do you handle API calls efficiently in a frontend application?” This is something I’ve learned more from real projects than theory. In the beginning, I used to call APIs directly wherever needed. It worked… until the app grew. - Same API getting called multiple times. - Unnecessary loading states. - Slower UI on repeated navigation. Now my approach is more structured. First, I avoid duplicate calls. - If the same data is needed in multiple places, I cache it (in memory or using tools like React Query). Second, I control when APIs are called. - Not everything needs to load on page load. - Lazy fetching and conditional calls help a lot. Third, I handle loading and error states properly. - Because a fast app isn’t just about speed, it’s about how it behaves during delays. Fourth, I think about caching strategy: - Can this data be reused? - How long should it stay fresh? Sometimes even a simple cache can reduce a lot of unnecessary requests. One thing I’ve realized: Frontend performance is often about reducing API calls, not just optimizing rendering.
To view or add a comment, sign in
-
🚀 Day 26/30 – useReducer (Advanced State Management) When state gets messy… "useState" starts struggling 👀 Today I learned how React handles complex state updates cleanly ⚡ 👉 useReducer --- 💻 The Problem: Managing multiple related states with "useState" ❌ 👉 Too many setters 👉 Scattered logic 👉 Hard to maintain --- 💻 The Solution: Use "useReducer" ✅ 👉 Centralize state logic in one place 👉 Predictable updates 👉 Easier to scale --- 💻 Example: import { useReducer } from "react"; const initialState = { count: 0 }; function reducer(state, action) { switch (action.type) { case "INCREMENT": return { count: state.count + 1 }; case "DECREMENT": return { count: state.count - 1 }; default: return state; } } function App() { const [state, dispatch] = useReducer(reducer, initialState); return ( <> <h2>{state.count}</h2> <button onClick={() => dispatch({ type: "INCREMENT" })}> + </button> <button onClick={() => dispatch({ type: "DECREMENT" })}> - </button> </> ); } --- 🔥 What actually happens: 1️⃣ User clicks button 2️⃣ dispatch(action) runs 3️⃣ reducer receives state + action 4️⃣ New state returned 5️⃣ UI updates --- 💡 Why this matters: ✅ Better for complex forms ✅ Multiple related states ✅ Cleaner update logic --- ⚡ Real Use Cases: - Shopping cart - Auth flow - Form wizard - Dashboard filters --- ⚡ Advanced Insight: "useReducer" is the same mental model used in Redux 👀 --- 🔥 Key Takeaway: Simple state → useState Complex state → useReducer --- Be honest 👇 Are you still forcing everything into useState? 🚀 #React #useReducer #FrontendDevelopment #JavaScript #StateManagement
To view or add a comment, sign in
-
-
For the longest time, my pattern looked like this: • useEffect → call API • useState → store data • loading + error states manually handled It worked… until the app grew. Then came the problems: • duplicate API calls • inconsistent loading states • manual caching (or no caching at all) • refetching logic scattered everywhere That’s when I switched to React Query. — What changed? Server state ≠ UI state React Query made this distinction clear. Caching became automatic Data stays fresh without unnecessary refetching. Background updates UI stays responsive while data syncs silently. Built-in loading & error handling No more boilerplate in every component. Refetching is declarative Not tied to lifecycle hacks anymore. — The biggest mindset shift: Stop thinking: “Where should I fetch this data?” Start thinking: “How should this data behave over time?” — Final takeaway: React Query is not just a library. It’s a different way of thinking about data in frontend. And once you get it, going back to useEffect feels… painful 😅 #reactjs #frontend #javascript #webdevelopment #reactquery #softwareengineering
To view or add a comment, sign in
-
Built a Next.js App Router project today — a fully typed Users Directory. What I built: A dynamic Next.js application that fetches real API data, renders a list of users, and navigates to individual user pages — all with TypeScript throughout. What I learned: Dynamic routing in Next.js is elegant. One file with [id] handles infinite URL variations — no configuration, no react-router setup. Just a folder and a file. The fetch happens directly in an async Server Component — no useEffect, no useState, no loading boilerplate. The data is ready before the page renders. Business value: Server Components keep sensitive logic on the server and send only the rendered HTML to the client. Faster page loads, better SEO, and a cleaner separation between data fetching and UI — all out of the box. The challenge: Shifting my mental model from React's client-side data fetching patterns to Next.js server-first architecture. In React everything fetches in the browser. In Next.js the server does the heavy lifting. How I overcame it: Followed the data. Asked: where should this run — server or client? Once that decision was clear, the right pattern followed naturally.
To view or add a comment, sign in
-
-
Frontend State Management is evolving fast. But the real question is: When should you use what? Let’s break it with a real-world example 👇 Imagine you’re building an E-commerce app using React You’ll deal with different types of state: 🟢 1. UI State (Local) Example: • Open/close cart modal • Toggle dark mode 👉 Best choice: useState Because it’s simple and component-specific --- 🔵 2. Global State (Shared across app) Example: • Logged-in user • Cart items • Theme 👉 Best choice: Context API / Redux Because multiple components need access --- 🟣 3. Server State (Data from backend) Example: • Product list • Order history • User profile 👉 Best choice: React Query Why? • Caching • Auto refetch • Sync with server --- 🔴 The mistake many developers make: Using useEffect for everything ❌ Result: • Repeated API calls • No caching • Messy code --- ✅ The better approach: • useState → UI behavior • Context/Redux → App-wide data • React Query → Server data --- 💡 Key insight: Not all state is the same. Choosing the right tool: 👉 Improves performance 👉 Reduces bugs 👉 Makes your app scalable --- Frontend is no longer just about UI. It’s about **managing data efficiently** #ReactJS #Frontend #WebDevelopment #JavaScript #TechTrends
To view or add a comment, sign in
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development