[{"data":1,"prerenderedAt":711},["ShallowReactive",2],{"blog-index-posts":3},[4,194,326,512,589,645],{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"date":11,"tags":12,"readingTime":17,"draft":7,"body":18,"_type":188,"_id":189,"_source":190,"_file":191,"_stem":192,"_extension":193},"/blog/clean-architecture-for-enterprise-apps","blog",false,"","Clean architecture for enterprise apps","Module boundaries, domain services, and persistence isolation so enterprise applications stay evolvable—especially in fintech and regulated workflows.","2026-04-26",[13,14,15,16],"Architecture","Enterprise","Backend","Fintech","6 min",{"type":19,"children":20,"toc":179},"root",[21,44,51,56,62,67,73,92,98,112,118,143,149],{"type":22,"tag":23,"props":24,"children":25},"element","p",{},[26,29,35,37,42],{"type":27,"value":28},"text","Enterprise applications accumulate requirements faster than any team can rewrite. ",{"type":22,"tag":30,"props":31,"children":32},"strong",{},[33],{"type":27,"value":34},"Clean architecture",{"type":27,"value":36}," here does not mean a diagram from a book—it means ",{"type":22,"tag":30,"props":38,"children":39},{},[40],{"type":27,"value":41},"dependencies point inward",{"type":27,"value":43},", and domain rules stay testable when the database or UI framework changes.",{"type":22,"tag":45,"props":46,"children":48},"h2",{"id":47},"separate-domain-services-from-delivery-mechanisms",[49],{"type":27,"value":50},"Separate domain services from delivery mechanisms",{"type":22,"tag":23,"props":52,"children":53},{},[54],{"type":27,"value":55},"HTTP controllers, CLI jobs, and message consumers should be thin. They parse input, call application services, and map results to responses. The “what should happen when a loan is approved?” question belongs in a service that does not know about Express, Nuxt, or Nest decorators.",{"type":22,"tag":45,"props":57,"children":59},{"id":58},"persistence-should-not-own-your-behavior",[60],{"type":27,"value":61},"Persistence should not own your behavior",{"type":22,"tag":23,"props":63,"children":64},{},[65],{"type":27,"value":66},"ORM models are convenient but dangerous as the home for business rules. Keep persistence mapping predictable: load aggregates, apply domain operations, persist changes. If SQL becomes the source of truth for policy, you will eventually lose the ability to reason about the system in code review.",{"type":22,"tag":45,"props":68,"children":70},{"id":69},"boundaries-that-match-how-teams-work",[71],{"type":27,"value":72},"Boundaries that match how teams work",{"type":22,"tag":23,"props":74,"children":75},{},[76,78,83,85,90],{"type":27,"value":77},"Modules should reflect ",{"type":22,"tag":30,"props":79,"children":80},{},[81],{"type":27,"value":82},"team boundaries",{"type":27,"value":84}," or ",{"type":22,"tag":30,"props":86,"children":87},{},[88],{"type":27,"value":89},"bounded contexts",{"type":27,"value":91}," where possible. Two teams fighting over one “god” package is a scaling problem for people, not machines. Clear interfaces between modules make refactors feasible.",{"type":22,"tag":45,"props":93,"children":95},{"id":94},"connect-architecture-to-outcomes",[96],{"type":27,"value":97},"Connect architecture to outcomes",{"type":22,"tag":23,"props":99,"children":100},{},[101,103,110],{"type":27,"value":102},"Readable structure shows up in hiring conversations and delivery speed. On this site, the ",{"type":22,"tag":104,"props":105,"children":107},"a",{"href":106},"/projects/loan-management-platform",[108],{"type":27,"value":109},"loan management platform case study",{"type":27,"value":111}," ties architecture language to a concrete product story—use the same pattern in your portfolio.",{"type":22,"tag":45,"props":113,"children":115},{"id":114},"practical-checklist",[116],{"type":27,"value":117},"Practical checklist",{"type":22,"tag":119,"props":120,"children":121},"ul",{},[122,128,133,138],{"type":22,"tag":123,"props":124,"children":125},"li",{},[126],{"type":27,"value":127},"Domain rules live in services, not controllers.",{"type":22,"tag":123,"props":129,"children":130},{},[131],{"type":27,"value":132},"DTOs validate shape; services validate meaning.",{"type":22,"tag":123,"props":134,"children":135},{},[136],{"type":27,"value":137},"Side effects (email, webhooks) are explicit and retry-safe.",{"type":22,"tag":123,"props":139,"children":140},{},[141],{"type":27,"value":142},"Migrations are reviewed like application code.",{"type":22,"tag":45,"props":144,"children":146},{"id":145},"summary",[147],{"type":27,"value":148},"Summary",{"type":22,"tag":23,"props":150,"children":151},{},[152,156,158,163,165,170,172,177],{"type":22,"tag":30,"props":153,"children":154},{},[155],{"type":27,"value":9},{"type":27,"value":157}," is about ",{"type":22,"tag":30,"props":159,"children":160},{},[161],{"type":27,"value":162},"testable domain logic",{"type":27,"value":164},", ",{"type":22,"tag":30,"props":166,"children":167},{},[168],{"type":27,"value":169},"honest persistence",{"type":27,"value":171},", and ",{"type":22,"tag":30,"props":173,"children":174},{},[175],{"type":27,"value":176},"module boundaries",{"type":27,"value":178}," that match how the product actually evolves—especially when financial logic is involved.",{"title":8,"searchDepth":180,"depth":180,"links":181},2,[182,183,184,185,186,187],{"id":47,"depth":180,"text":50},{"id":58,"depth":180,"text":61},{"id":69,"depth":180,"text":72},{"id":94,"depth":180,"text":97},{"id":114,"depth":180,"text":117},{"id":145,"depth":180,"text":148},"markdown","content:blog:clean-architecture-for-enterprise-apps.md","content","blog/clean-architecture-for-enterprise-apps.md","blog/clean-architecture-for-enterprise-apps","md",{"_path":195,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":196,"description":197,"date":198,"tags":199,"readingTime":17,"draft":7,"body":201,"_type":188,"_id":323,"_source":190,"_file":324,"_stem":325,"_extension":193},"/blog/handling-financial-logic-in-backend-systems","Handling financial logic in backend systems","Money math, idempotency, and transactional boundaries for backend engineers building fintech and enterprise financial workflows.","2026-04-22",[16,15,200,14],"Financial Logic",{"type":19,"children":202,"toc":315},[203,215,221,226,232,237,243,255,261,272,278,283,287],{"type":22,"tag":23,"props":204,"children":205},{},[206,208,213],{"type":27,"value":207},"Financial logic is where “it works on my machine” stops being funny. A fintech software engineer treats money movement as ",{"type":22,"tag":30,"props":209,"children":210},{},[211],{"type":27,"value":212},"data with invariants",{"type":27,"value":214},", not as floating-point convenience.",{"type":22,"tag":45,"props":216,"children":218},{"id":217},"prefer-integers-and-explicit-currency-rules",[219],{"type":27,"value":220},"Prefer integers and explicit currency rules",{"type":22,"tag":23,"props":222,"children":223},{},[224],{"type":27,"value":225},"Store amounts in minor units (cents) or use a decimal type your database and runtime agree on. Never let presentation formatting leak into core calculations. Round only at well-defined boundaries—usually when displaying or when a contract says so.",{"type":22,"tag":45,"props":227,"children":229},{"id":228},"idempotency-is-non-negotiable",[230],{"type":27,"value":231},"Idempotency is non-negotiable",{"type":22,"tag":23,"props":233,"children":234},{},[235],{"type":27,"value":236},"Network retries will happen. Use idempotency keys on write endpoints that create charges, transfers, or ledger entries. The second request with the same key should return the same outcome as the first, without duplicating side effects.",{"type":22,"tag":45,"props":238,"children":240},{"id":239},"transactional-boundaries-should-match-the-business-story",[241],{"type":27,"value":242},"Transactional boundaries should match the business story",{"type":22,"tag":23,"props":244,"children":245},{},[246,248,253],{"type":27,"value":247},"A single “repayment applied” operation might touch balance, ledger row, and schedule row. Those updates belong in one ",{"type":22,"tag":30,"props":249,"children":250},{},[251],{"type":27,"value":252},"transactional boundary",{"type":27,"value":254}," so partial failures do not leave half-truths in the database. If the workflow spans services, design compensating actions or outbox patterns—avoid “best effort” distributed commits unless you truly need them.",{"type":22,"tag":45,"props":256,"children":258},{"id":257},"see-it-in-a-shipped-surface",[259],{"type":27,"value":260},"See it in a shipped surface",{"type":22,"tag":23,"props":262,"children":263},{},[264,266,270],{"type":27,"value":265},"When UI and API disagree, users lose confidence. A full-stack view of the same rules—like the ",{"type":22,"tag":104,"props":267,"children":268},{"href":106},[269],{"type":27,"value":109},{"type":27,"value":271},"—shows how explicit backend contracts keep dashboards honest.",{"type":22,"tag":45,"props":273,"children":275},{"id":274},"testing-the-scary-paths",[276],{"type":27,"value":277},"Testing the scary paths",{"type":22,"tag":23,"props":279,"children":280},{},[281],{"type":27,"value":282},"Focus tests on: reversals, partial payments, duplicate webhooks, clock skew around cutoffs, and currency edge cases. Property-based tests can help for schedule generators when inputs have wide variance.",{"type":22,"tag":45,"props":284,"children":285},{"id":145},[286],{"type":27,"value":148},{"type":22,"tag":23,"props":288,"children":289},{},[290,295,296,301,302,307,308,313],{"type":22,"tag":30,"props":291,"children":292},{},[293],{"type":27,"value":294},"Integers or decimals with discipline",{"type":27,"value":164},{"type":22,"tag":30,"props":297,"children":298},{},[299],{"type":27,"value":300},"idempotent writes",{"type":27,"value":164},{"type":22,"tag":30,"props":303,"children":304},{},[305],{"type":27,"value":306},"clear transactions",{"type":27,"value":171},{"type":22,"tag":30,"props":309,"children":310},{},[311],{"type":27,"value":312},"tests on failure paths",{"type":27,"value":314}," are the backbone of maintainable financial backends—whether you call yourself a loan system developer or a general backend engineer.",{"title":8,"searchDepth":180,"depth":180,"links":316},[317,318,319,320,321,322],{"id":217,"depth":180,"text":220},{"id":228,"depth":180,"text":231},{"id":239,"depth":180,"text":242},{"id":257,"depth":180,"text":260},{"id":274,"depth":180,"text":277},{"id":145,"depth":180,"text":148},"content:blog:handling-financial-logic-in-backend-systems.md","blog/handling-financial-logic-in-backend-systems.md","blog/handling-financial-logic-in-backend-systems",{"_path":327,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":328,"description":329,"date":330,"tags":331,"readingTime":17,"draft":7,"body":333,"_type":188,"_id":509,"_source":190,"_file":510,"_stem":511,"_extension":193},"/blog/designing-scalable-loan-systems","Designing scalable loan systems","Practical patterns for repayment schedules, disbursement scenarios, and audit-friendly loan workflows—written by a fintech software engineer.","2026-04-18",[16,332,15,13],"Loan Systems",{"type":19,"children":334,"toc":501},[335,347,353,365,376,382,409,415,436,442,454,460,473,477],{"type":22,"tag":23,"props":336,"children":337},{},[338,340,345],{"type":27,"value":339},"Loan systems fail quietly. A small rounding mistake or an ambiguous partial disbursement rule becomes a month of reconciliation. Scalable loan software is less about raw traffic and more about ",{"type":22,"tag":30,"props":341,"children":342},{},[343],{"type":27,"value":344},"clear boundaries",{"type":27,"value":346}," between product rules, money movement, and user-facing status.",{"type":22,"tag":45,"props":348,"children":350},{"id":349},"start-from-the-lifecycle-not-the-screen",[351],{"type":27,"value":352},"Start from the lifecycle, not the screen",{"type":22,"tag":23,"props":354,"children":355},{},[356,358,363],{"type":27,"value":357},"Before choosing frameworks, map the lifecycle: application, approval, disbursement, servicing, repayment, closure, and exceptions. Each transition should have a single authority in code—usually a ",{"type":22,"tag":30,"props":359,"children":360},{},[361],{"type":27,"value":362},"domain service",{"type":27,"value":364},"—so policy changes do not scatter across controllers and SQL snippets.",{"type":22,"tag":23,"props":366,"children":367},{},[368,370,374],{"type":27,"value":369},"For a concrete example of how this shows up in shipping software, see the ",{"type":22,"tag":104,"props":371,"children":372},{"href":106},[373],{"type":27,"value":109},{"type":27,"value":375},".",{"type":22,"tag":45,"props":377,"children":379},{"id":378},"repayment-logic-has-to-be-boring",[380],{"type":27,"value":381},"Repayment logic has to be boring",{"type":22,"tag":23,"props":383,"children":384},{},[385,387,392,394,399,401,407],{"type":27,"value":386},"Repayment schedules should be ",{"type":22,"tag":30,"props":388,"children":389},{},[390],{"type":27,"value":391},"deterministic",{"type":27,"value":393}," and ",{"type":22,"tag":30,"props":395,"children":396},{},[397],{"type":27,"value":398},"idempotent",{"type":27,"value":400},". Given the same inputs (principal, rate, term, calendar conventions), recalculating twice should yield the same schedule. When terms change mid-flight, the system should record ",{"type":22,"tag":402,"props":403,"children":404},"em",{},[405],{"type":27,"value":406},"why",{"type":27,"value":408}," the schedule changed and keep enough history to answer audit questions later.",{"type":22,"tag":45,"props":410,"children":412},{"id":411},"model-disbursement-scenarios-explicitly",[413],{"type":27,"value":414},"Model disbursement scenarios explicitly",{"type":22,"tag":23,"props":416,"children":417},{},[418,420,427,429,434],{"type":27,"value":419},"Multiple draws, partial funding, and fee handling are where spreadsheets die. Encode scenarios as explicit cases or strategies—not nested ",{"type":22,"tag":421,"props":422,"children":424},"code",{"className":423},[],[425],{"type":27,"value":426},"if",{"type":27,"value":428}," trees that only the author understands. Your future self (or a regulator-style question) will ask: ",{"type":22,"tag":402,"props":430,"children":431},{},[432],{"type":27,"value":433},"what happened to this balance on this date?",{"type":27,"value":435}," The database and service layer should tell the same story.",{"type":22,"tag":45,"props":437,"children":439},{"id":438},"audit-trails-are-a-product-feature",[440],{"type":27,"value":441},"Audit trails are a product feature",{"type":22,"tag":23,"props":443,"children":444},{},[445,447,452],{"type":27,"value":446},"Treat approvals, manual overrides, and state transitions as first-class events. Structured logs and immutable rows for money movement are not “nice to have”; they are how you keep ",{"type":22,"tag":30,"props":448,"children":449},{},[450],{"type":27,"value":451},"trust",{"type":27,"value":453}," when complexity grows.",{"type":22,"tag":45,"props":455,"children":457},{"id":456},"internal-links-and-authority",[458],{"type":27,"value":459},"Internal links and authority",{"type":22,"tag":23,"props":461,"children":462},{},[463,465,471],{"type":27,"value":464},"If you are building in public, connect writing to proof: link from articles to ",{"type":22,"tag":104,"props":466,"children":468},{"href":467},"/projects",[469],{"type":27,"value":470},"case studies",{"type":27,"value":472}," and back. It helps readers—and search systems—understand what you actually ship.",{"type":22,"tag":45,"props":474,"children":475},{"id":145},[476],{"type":27,"value":148},{"type":22,"tag":23,"props":478,"children":479},{},[480,482,487,488,493,494,499],{"type":27,"value":481},"Scalable loan systems prioritize ",{"type":22,"tag":30,"props":483,"children":484},{},[485],{"type":27,"value":486},"correctness",{"type":27,"value":164},{"type":22,"tag":30,"props":489,"children":490},{},[491],{"type":27,"value":492},"traceability",{"type":27,"value":171},{"type":22,"tag":30,"props":495,"children":496},{},[497],{"type":27,"value":498},"modular rules",{"type":27,"value":500},". Keep financial logic in focused services, make repayment boring, and design for audits from day one.",{"title":8,"searchDepth":180,"depth":180,"links":502},[503,504,505,506,507,508],{"id":349,"depth":180,"text":352},{"id":378,"depth":180,"text":381},{"id":411,"depth":180,"text":414},{"id":438,"depth":180,"text":441},{"id":456,"depth":180,"text":459},{"id":145,"depth":180,"text":148},"content:blog:designing-scalable-loan-systems.md","blog/designing-scalable-loan-systems.md","blog/designing-scalable-loan-systems",{"_path":513,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":514,"description":515,"date":516,"tags":517,"readingTime":519,"draft":7,"body":520,"_type":188,"_id":586,"_source":190,"_file":587,"_stem":588,"_extension":193},"/blog/scalable-business-systems","How I Think About Scalable Business Systems","A practical note on separating domain logic, persistence, and interface concerns when business workflows become complex.","2026-04-01",[13,15,518],"Systems","4 min",{"type":19,"children":521,"toc":582},[522,527,532,538,543,548,554,577],{"type":22,"tag":23,"props":523,"children":524},{},[525],{"type":27,"value":526},"Scalable business systems are not only about traffic. They are about clarity.",{"type":22,"tag":23,"props":528,"children":529},{},[530],{"type":27,"value":531},"When a product contains approvals, financial calculations, permissions, reporting, and operational workflows, the system needs boundaries that make change safe. The most important decision is often where domain logic lives.",{"type":22,"tag":45,"props":533,"children":535},{"id":534},"what-matters-most",[536],{"type":27,"value":537},"What matters most",{"type":22,"tag":23,"props":539,"children":540},{},[541],{"type":27,"value":542},"A reliable system should keep business rules explicit, testable, and separate from presentation details. Database design should support the workflow instead of becoming a hidden source of behavior.",{"type":22,"tag":23,"props":544,"children":545},{},[546],{"type":27,"value":547},"For Tahmid Islam, scalable software means code that can handle real-world complexity while staying readable for the next engineer.",{"type":22,"tag":45,"props":549,"children":551},{"id":550},"a-useful-structure",[552],{"type":27,"value":553},"A useful structure",{"type":22,"tag":119,"props":555,"children":556},{},[557,562,567,572],{"type":22,"tag":123,"props":558,"children":559},{},[560],{"type":27,"value":561},"Keep domain rules in focused service layers.",{"type":22,"tag":123,"props":563,"children":564},{},[565],{"type":27,"value":566},"Keep persistence logic predictable and observable.",{"type":22,"tag":123,"props":568,"children":569},{},[570],{"type":27,"value":571},"Keep user interfaces clear about status, errors, and next actions.",{"type":22,"tag":123,"props":573,"children":574},{},[575],{"type":27,"value":576},"Use TypeScript to make important data shapes visible.",{"type":22,"tag":23,"props":578,"children":579},{},[580],{"type":27,"value":581},"This approach helps teams move faster without losing confidence in the system.",{"title":8,"searchDepth":180,"depth":180,"links":583},[584,585],{"id":534,"depth":180,"text":537},{"id":550,"depth":180,"text":553},"content:blog:scalable-business-systems.md","blog/scalable-business-systems.md","blog/scalable-business-systems",{"_path":590,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":591,"description":592,"date":593,"tags":594,"readingTime":598,"draft":7,"body":599,"_type":188,"_id":642,"_source":190,"_file":643,"_stem":644,"_extension":193},"/blog/clean-logic-modern-ui","Clean Logic and Modern UI Belong Together","Why maintainable backend decisions and calm interface design should be treated as one product quality standard.","2026-03-12",[595,596,597],"Frontend","UX","TypeScript","3 min",{"type":19,"children":600,"toc":638},[601,606,611,617,622,627,633],{"type":22,"tag":23,"props":602,"children":603},{},[604],{"type":27,"value":605},"Users rarely care which part of a system failed. They experience the whole product at once.",{"type":22,"tag":23,"props":607,"children":608},{},[609],{"type":27,"value":610},"That is why clean backend logic and modern UI design belong together. A clear interface can still feel unreliable if the system underneath is hard to reason about. A strong backend can still feel frustrating if the UI hides status, errors, or intent.",{"type":22,"tag":45,"props":612,"children":614},{"id":613},"the-engineering-goal",[615],{"type":27,"value":616},"The engineering goal",{"type":22,"tag":23,"props":618,"children":619},{},[620],{"type":27,"value":621},"The goal is to make complexity understandable.",{"type":22,"tag":23,"props":623,"children":624},{},[625],{"type":27,"value":626},"For product interfaces, this means strong hierarchy, helpful labels, fast feedback, and responsive layouts. For backend systems, it means clear contracts, explicit rules, and predictable data flow.",{"type":22,"tag":45,"props":628,"children":630},{"id":629},"practical-result",[631],{"type":27,"value":632},"Practical result",{"type":22,"tag":23,"props":634,"children":635},{},[636],{"type":27,"value":637},"When both sides are designed together, software feels calmer. Teams debug faster. Users make fewer mistakes. Features become easier to extend.",{"title":8,"searchDepth":180,"depth":180,"links":639},[640,641],{"id":613,"depth":180,"text":616},{"id":629,"depth":180,"text":632},"content:blog:clean-logic-modern-ui.md","blog/clean-logic-modern-ui.md","blog/clean-logic-modern-ui",{"_path":646,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":647,"description":648,"date":649,"tags":650,"readingTime":598,"draft":7,"body":654,"_type":188,"_id":708,"_source":190,"_file":709,"_stem":710,"_extension":193},"/blog/performance-minded-nuxt","Performance-Minded Nuxt Interfaces","A short checklist for building Nuxt interfaces that feel polished without shipping unnecessary client-side weight.","2026-02-20",[651,652,653],"Nuxt","Performance","Tailwind",{"type":19,"children":655,"toc":705},[656,661,666,672,700],{"type":22,"tag":23,"props":657,"children":658},{},[659],{"type":27,"value":660},"Premium interfaces do not need heavy animation or large dependencies.",{"type":22,"tag":23,"props":662,"children":663},{},[664],{"type":27,"value":665},"Nuxt makes it possible to create polished websites with server rendering, simple routing, optimized assets, and component-level structure. The key is to keep the first experience light.",{"type":22,"tag":45,"props":667,"children":669},{"id":668},"useful-defaults",[670],{"type":27,"value":671},"Useful defaults",{"type":22,"tag":119,"props":673,"children":674},{},[675,680,685,690,695],{"type":22,"tag":123,"props":676,"children":677},{},[678],{"type":27,"value":679},"Use semantic HTML before adding decorative layers.",{"type":22,"tag":123,"props":681,"children":682},{},[683],{"type":27,"value":684},"Prefer CSS transitions for subtle motion.",{"type":22,"tag":123,"props":686,"children":687},{},[688],{"type":27,"value":689},"Keep mock visuals CSS-based when possible.",{"type":22,"tag":123,"props":691,"children":692},{},[693],{"type":27,"value":694},"Use readable typography and spacing instead of excessive effects.",{"type":22,"tag":123,"props":696,"children":697},{},[698],{"type":27,"value":699},"Lazy-load non-critical media.",{"type":22,"tag":23,"props":701,"children":702},{},[703],{"type":27,"value":704},"The result is a site that feels high-end because it is fast, calm, and easy to read.",{"title":8,"searchDepth":180,"depth":180,"links":706},[707],{"id":668,"depth":180,"text":671},"content:blog:performance-minded-nuxt.md","blog/performance-minded-nuxt.md","blog/performance-minded-nuxt",1780404801347]