[{"data":1,"prerenderedAt":10900},["ShallowReactive",2],{"navigation":3,"/static-assets-and-frontend-integration/using-react-or-vue-with-django":1016,"/static-assets-and-frontend-integration/using-react-or-vue-with-django-surround":10895},[4,54,89,123,165,211,253,331,389,439,462,488,514,540,578,624,650,672,702,736,774,800,850,856,862,868,874,928],{"title":5,"path":6,"stem":7,"children":8},"Introduction and Foundations","/introduction-and-foundations","01.introduction-and-foundations/01.index",[9,10,14,18,22,26,30,34,38,42,46,50],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13},"What is Django","/introduction-and-foundations/what-is-django","01.introduction-and-foundations/02.what-is-django",{"title":15,"path":16,"stem":17},"Key Concepts and Philosophy","/introduction-and-foundations/key-concepts-and-philosophy","01.introduction-and-foundations/03.key-concepts-and-philosophy",{"title":19,"path":20,"stem":21},"MVC vs MVT: Understanding Django's Architecture","/introduction-and-foundations/mvc-vs-mvt","01.introduction-and-foundations/04.mvc-vs-mvt",{"title":23,"path":24,"stem":25},"Project Structure Overview","/introduction-and-foundations/project-structure-overview","01.introduction-and-foundations/05.project-structure-overview",{"title":27,"path":28,"stem":29},"Installing Django","/introduction-and-foundations/installing-django","01.introduction-and-foundations/06.installing-django",{"title":31,"path":32,"stem":33},"Creating Your First Django Project","/introduction-and-foundations/creating-first-project","01.introduction-and-foundations/07.creating-first-project",{"title":35,"path":36,"stem":37},"Creating Your First Django App","/introduction-and-foundations/creating-first-app","01.introduction-and-foundations/08.creating-first-app",{"title":39,"path":40,"stem":41},"Your First Django \"Hello World\"","/introduction-and-foundations/hello-world","01.introduction-and-foundations/09.hello-world",{"title":43,"path":44,"stem":45},"Django Quick Start Guide","/introduction-and-foundations/quick-start-guide","01.introduction-and-foundations/10.quick-start-guide",{"title":47,"path":48,"stem":49},"How Django Handles Requests","/introduction-and-foundations/how-django-handles-requests","01.introduction-and-foundations/11.how-django-handles-requests",{"title":51,"path":52,"stem":53},"Django Settings","/introduction-and-foundations/django-settings","01.introduction-and-foundations/12.django-settings",{"title":55,"path":56,"stem":57,"children":58},"The Development Environment","/development-environment","02.development-environment/1.index",[59,61,65,69,73,77,81,85],{"title":60,"path":56,"stem":57},"Development Environment",{"title":62,"path":63,"stem":64},"Recommended Tooling for Django Development","/development-environment/recommended-tooling","02.development-environment/2.recommended-tooling",{"title":66,"path":67,"stem":68},"Virtual Environments","/development-environment/virtual-environments","02.development-environment/3.virtual-environments",{"title":70,"path":71,"stem":72},"Django Admin and Management Commands","/development-environment/admin-and-management-commands","02.development-environment/4.admin-and-management-commands",{"title":74,"path":75,"stem":76},"Django Project Settings","/development-environment/project-settings","02.development-environment/5.project-settings",{"title":78,"path":79,"stem":80},"Managing Django Environments: Local, Staging, and Production","/development-environment/environments-local-staging-production","02.development-environment/6.environments-local-staging-production",{"title":82,"path":83,"stem":84},"Running Django Development Server","/development-environment/running-development-server","02.development-environment/7.running-development-server",{"title":86,"path":87,"stem":88},"Working with Django Shell","/development-environment/working-with-shell","02.development-environment/8.working-with-shell",{"title":90,"path":91,"stem":92,"children":93},"Templates and Presentation Layer","/templates-and-presentation","03.templates-and-presentation/1.index",[94,95,99,103,107,111,115,119],{"title":90,"path":91,"stem":92},{"title":96,"path":97,"stem":98},"Introduction to Django Templates","/templates-and-presentation/introduction-to-templates","03.templates-and-presentation/2.introduction-to-templates",{"title":100,"path":101,"stem":102},"The Django Template Language","/templates-and-presentation/django-template-language","03.templates-and-presentation/3.django-template-language",{"title":104,"path":105,"stem":106},"Template Inheritance","/templates-and-presentation/template-inheritance","03.templates-and-presentation/4.template-inheritance",{"title":108,"path":109,"stem":110},"Built-in Template Tags and Filters","/templates-and-presentation/built-in-template-tags-and-filters","03.templates-and-presentation/5.built-in-template-tags-and-filters",{"title":112,"path":113,"stem":114},"Including Static Files","/templates-and-presentation/including-static-files","03.templates-and-presentation/6.including-static-files",{"title":116,"path":117,"stem":118},"Working with Media Files","/templates-and-presentation/working-with-media-files","03.templates-and-presentation/7.working-with-media-files",{"title":120,"path":121,"stem":122},"Using Alternative Template Engines","/templates-and-presentation/using-alternative-template-engines","03.templates-and-presentation/8.using-alternative-template-engines",{"title":124,"path":125,"stem":126,"children":127},"URLs and Views","/urls-and-views","04.urls-and-views/01.index",[128,129,133,137,141,145,149,153,157,161],{"title":124,"path":125,"stem":126},{"title":130,"path":131,"stem":132},"The URL Dispatcher","/urls-and-views/the-url-dispatcher","04.urls-and-views/02.the-url-dispatcher",{"title":134,"path":135,"stem":136},"Writing Function-Based Views","/urls-and-views/writing-function-based-views","04.urls-and-views/03.writing-function-based-views",{"title":138,"path":139,"stem":140},"View Decorators","/urls-and-views/view-decorators","04.urls-and-views/04.view-decorators",{"title":142,"path":143,"stem":144},"Rendering Responses","/urls-and-views/rendering-responses","04.urls-and-views/05.rendering-responses",{"title":146,"path":147,"stem":148},"Redirects","/urls-and-views/redirects","04.urls-and-views/06.redirects",{"title":150,"path":151,"stem":152},"Handling HTTP Methods","/urls-and-views/handling-http-methods","04.urls-and-views/07.handling-http-methods",{"title":154,"path":155,"stem":156},"Conditional View Processing","/urls-and-views/conditional-view-processing","04.urls-and-views/08.conditional-view-processing",{"title":158,"path":159,"stem":160},"File Uploads","/urls-and-views/file-uploads","04.urls-and-views/09.file-uploads",{"title":162,"path":163,"stem":164},"Using Django Shortcut Functions","/urls-and-views/using-django-shortcut-functions","04.urls-and-views/10.using-django-shortcut-functions",{"title":166,"path":167,"stem":168,"children":169},"Class Based Views","/class-based-views","05.class-based-views/01.index",[170,171,175,179,183,187,191,195,199,203,207],{"title":166,"path":167,"stem":168},{"title":172,"path":173,"stem":174},"Introduction to Class-Based Views","/class-based-views/introduction-to-class-based-views","05.class-based-views/02.introduction-to-class-based-views",{"title":176,"path":177,"stem":178},"Common Base Classes","/class-based-views/common-base-classes","05.class-based-views/03.common-base-classes",{"title":180,"path":181,"stem":182},"Built-in Generic Views","/class-based-views/built-in-generic-views","05.class-based-views/04.built-in-generic-views",{"title":184,"path":185,"stem":186},"Views for CRUD Operations","/class-based-views/views-for-crud-operations","05.class-based-views/05.views-for-crud-operations",{"title":188,"path":189,"stem":190},"Handling Forms with Class-Based Views","/class-based-views/handling-forms-with-class-based-views","05.class-based-views/06.handling-forms-with-class-based-views",{"title":192,"path":193,"stem":194},"Using Mixins","/class-based-views/using-mixins","05.class-based-views/07.using-mixins",{"title":196,"path":197,"stem":198},"URL Configuration with Class-Based Views","/class-based-views/url-configuration-with-class-based-views","05.class-based-views/08.url-configuration-with-class-based-views",{"title":200,"path":201,"stem":202},"Subclassing Generic Views","/class-based-views/subclassing-generic-views","05.class-based-views/09.subclassing-generic-views",{"title":204,"path":205,"stem":206},"Asynchronous Class-Based Views","/class-based-views/asynchronous-class-based-views","05.class-based-views/10.asynchronous-class-based-views",{"title":208,"path":209,"stem":210},"Pagination","/class-based-views/pagination","05.class-based-views/11.pagination",{"title":212,"path":213,"stem":214,"children":215},"Forms and User Input","/forms-and-user-input","06.forms-and-user-input/01.index",[216,217,221,225,229,233,237,241,245,249],{"title":212,"path":213,"stem":214},{"title":218,"path":219,"stem":220},"Understanding HTML Forms","/forms-and-user-input/understanding-html-forms","06.forms-and-user-input/02.understanding-html-forms",{"title":222,"path":223,"stem":224},"Django's Role in Form Handling","/forms-and-user-input/djangos-role-in-form-handling","06.forms-and-user-input/03.djangos-role-in-form-handling",{"title":226,"path":227,"stem":228},"Creating Forms with Forms API","/forms-and-user-input/creating-forms-with-forms-api","06.forms-and-user-input/04.creating-forms-with-forms-api",{"title":230,"path":231,"stem":232},"Form Validation","/forms-and-user-input/form-validation","06.forms-and-user-input/05.form-validation",{"title":234,"path":235,"stem":236},"Built-in Fields and Widgets","/forms-and-user-input/built-in-fields-and-widgets","06.forms-and-user-input/06.built-in-fields-and-widgets",{"title":238,"path":239,"stem":240},"Form Rendering in Templates","/forms-and-user-input/form-rendering-in-templates","06.forms-and-user-input/07.form-rendering-in-templates",{"title":242,"path":243,"stem":244},"Model Forms","/forms-and-user-input/model-forms","06.forms-and-user-input/08.model-forms",{"title":246,"path":247,"stem":248},"Advanced Form Techniques","/forms-and-user-input/advanced-form-techniques","06.forms-and-user-input/09.advanced-form-techniques",{"title":250,"path":251,"stem":252},"Security Considerations for Forms","/forms-and-user-input/security-considerations-for-forms","06.forms-and-user-input/10.security-considerations-for-forms",{"title":254,"path":255,"stem":256,"children":257},"Models and Databases","/models-and-databases","07.models-and-databases/01.index",[258,259,263,267,271,275,279,283,287,291,295,299,303,307,311,315,319,323,327],{"title":254,"path":255,"stem":256},{"title":260,"path":261,"stem":262},"Understanding Django Models","/models-and-databases/understanding-django-models","07.models-and-databases/02.understanding-django-models",{"title":264,"path":265,"stem":266},"Defining Fields","/models-and-databases/defining-fields","07.models-and-databases/03.defining-fields",{"title":268,"path":269,"stem":270},"Relationships and Foreign Keys","/models-and-databases/relationships-and-foreign-keys","07.models-and-databases/04.relationships-and-foreign-keys",{"title":272,"path":273,"stem":274},"Examples of Relationship Patterns","/models-and-databases/examples-of-relationship-patterns","07.models-and-databases/05.examples-of-relationship-patterns",{"title":276,"path":277,"stem":278},"Making Queries","/models-and-databases/making-queries","07.models-and-databases/06.making-queries",{"title":280,"path":281,"stem":282},"Filtering, Ordering, and Slicing","/models-and-databases/filtering-ordering-slicing","07.models-and-databases/07.filtering-ordering-slicing",{"title":284,"path":285,"stem":286},"Managers and QuerySets","/models-and-databases/managers-and-querysets","07.models-and-databases/08.managers-and-querysets",{"title":288,"path":289,"stem":290},"Aggregation","/models-and-databases/aggregation","07.models-and-databases/09.aggregation",{"title":292,"path":293,"stem":294},"Search","/models-and-databases/search","07.models-and-databases/10.search",{"title":296,"path":297,"stem":298},"Raw SQL Queries","/models-and-databases/raw-sql-queries","07.models-and-databases/11.raw-sql-queries",{"title":300,"path":301,"stem":302},"Transactions","/models-and-databases/transactions","07.models-and-databases/12.transactions",{"title":304,"path":305,"stem":306},"Multiple Databases","/models-and-databases/multiple-databases","07.models-and-databases/13.multiple-databases",{"title":308,"path":309,"stem":310},"Tablespaces","/models-and-databases/tablespaces","07.models-and-databases/14.tablespaces",{"title":312,"path":313,"stem":314},"Composite Primary Keys","/models-and-databases/composite-primary-keys","07.models-and-databases/15.composite-primary-keys",{"title":316,"path":317,"stem":318},"Database Instrumentation","/models-and-databases/database-instrumentation","07.models-and-databases/16.database-instrumentation",{"title":320,"path":321,"stem":322},"Database Optimization","/models-and-databases/database-optimization","07.models-and-databases/17.database-optimization",{"title":324,"path":325,"stem":326},"Fixtures","/models-and-databases/fixtures","07.models-and-databases/18.fixtures",{"title":328,"path":329,"stem":330},"Signals","/models-and-databases/signals","07.models-and-databases/19.signals",{"title":332,"path":333,"stem":334,"children":335},"Migrations","/migrations","08.migrations/01.index",[336,337,341,345,349,353,357,361,365,369,373,377,381,385],{"title":332,"path":333,"stem":334},{"title":338,"path":339,"stem":340},"How Migrations Work","/migrations/how-migrations-work","08.migrations/02.how-migrations-work",{"title":342,"path":343,"stem":344},"Management Commands","/migrations/management-commands","08.migrations/03.management-commands",{"title":346,"path":347,"stem":348},"Dependencies and Workflow","/migrations/dependencies-and-workflow","08.migrations/04.dependencies-and-workflow",{"title":350,"path":351,"stem":352},"Transaction Handling","/migrations/transaction-handling","08.migrations/05.transaction-handling",{"title":354,"path":355,"stem":356},"Adding Migrations to Apps","/migrations/adding-migrations-to-apps","08.migrations/06.adding-migrations-to-apps",{"title":358,"path":359,"stem":360},"Reversing Migrations","/migrations/reversing-migrations","08.migrations/07.reversing-migrations",{"title":362,"path":363,"stem":364},"Historical Models","/migrations/historical-models","08.migrations/08.historical-models",{"title":366,"path":367,"stem":368},"Considerations When Removing Fields","/migrations/considerations-when-removing-fields","08.migrations/09.considerations-when-removing-fields",{"title":370,"path":371,"stem":372},"Data Migrations","/migrations/data-migrations","08.migrations/10.data-migrations",{"title":374,"path":375,"stem":376},"Squashing Migrations","/migrations/squashing-migrations","08.migrations/11.squashing-migrations",{"title":378,"path":379,"stem":380},"Serializing Values","/migrations/serializing-values","08.migrations/12.serializing-values",{"title":382,"path":383,"stem":384},"Supporting Multiple Django Versions","/migrations/supporting-multiple-django-versions","08.migrations/13.supporting-multiple-django-versions",{"title":386,"path":387,"stem":388},"Django Serialization Framework","/migrations/django-serialization-framework","08.migrations/14.django-serialization-framework",{"title":390,"path":391,"stem":392,"children":393},"Authentication and Authorization","/authentication-and-authorization","09.authentication-and-authorization/01.index",[394,395,399,403,407,411,415,419,423,427,431,435],{"title":390,"path":391,"stem":392},{"title":396,"path":397,"stem":398},"Overview of Django's Authentication System","/authentication-and-authorization/overview-of-django-authentication-system","09.authentication-and-authorization/02.overview-of-django-authentication-system",{"title":400,"path":401,"stem":402},"Users and Groups","/authentication-and-authorization/users-and-groups","09.authentication-and-authorization/03.users-and-groups",{"title":404,"path":405,"stem":406},"Permissions","/authentication-and-authorization/permissions","09.authentication-and-authorization/04.permissions",{"title":408,"path":409,"stem":410},"Password Management","/authentication-and-authorization/password-management","09.authentication-and-authorization/05.password-management",{"title":412,"path":413,"stem":414},"Authentication Views","/authentication-and-authorization/authentication-views","09.authentication-and-authorization/06.authentication-views",{"title":416,"path":417,"stem":418},"Login and Logout","/authentication-and-authorization/login-and-logout","09.authentication-and-authorization/07.login-and-logout",{"title":420,"path":421,"stem":422},"Custom User Models","/authentication-and-authorization/custom-user-models","09.authentication-and-authorization/08.custom-user-models",{"title":424,"path":425,"stem":426},"Middleware for Authentication","/authentication-and-authorization/middleware-for-authentication","09.authentication-and-authorization/09.middleware-for-authentication",{"title":428,"path":429,"stem":430},"Authorization in Views and Templates","/authentication-and-authorization/authorization-in-views-and-templates","09.authentication-and-authorization/10.authorization-in-views-and-templates",{"title":432,"path":433,"stem":434},"Integrating Social Authentication","/authentication-and-authorization/integrating-social-authentication","09.authentication-and-authorization/11.integrating-social-authentication",{"title":436,"path":437,"stem":438},"Security Best Practices","/authentication-and-authorization/security-best-practices","09.authentication-and-authorization/12.security-best-practices",{"title":440,"path":441,"stem":442,"children":443},"Sessions, Cookies, and State","/sessions-cookies-state","10.sessions-cookies-state/01.index",[444,446,450,454,458],{"title":445,"path":441,"stem":442},"Sessions, Cookies, and State Management",{"title":447,"path":448,"stem":449},"Introduction to Sessions","/sessions-cookies-state/introduction-to-sessions","10.sessions-cookies-state/02.introduction-to-sessions",{"title":451,"path":452,"stem":453},"Working with Cookies","/sessions-cookies-state/working-with-cookies","10.sessions-cookies-state/03.working-with-cookies",{"title":455,"path":456,"stem":457},"Server-Side Session Storage Options","/sessions-cookies-state/server-side-session-storage-options","10.sessions-cookies-state/04.server-side-session-storage-options",{"title":459,"path":460,"stem":461},"Session Security","/sessions-cookies-state/session-security","10.sessions-cookies-state/05.session-security",{"title":463,"path":464,"stem":465,"children":466},"Working with Files","/working-with-files","11.working-with-files/01.index",[467,468,472,476,480,484],{"title":463,"path":464,"stem":465},{"title":469,"path":470,"stem":471},"Files in Models","/working-with-files/files-in-models","11.working-with-files/02.files-in-models",{"title":473,"path":474,"stem":475},"The File Object","/working-with-files/the-file-object","11.working-with-files/03.the-file-object",{"title":477,"path":478,"stem":479},"Storage Backends","/working-with-files/storage-backends","11.working-with-files/04.storage-backends",{"title":481,"path":482,"stem":483},"Using Cloud Storage Providers","/working-with-files/using-cloud-storage-providers","11.working-with-files/05.using-cloud-storage-providers",{"title":485,"path":486,"stem":487},"Managing Media in Production","/working-with-files/managing-media-in-production","11.working-with-files/06.managing-media-in-production",{"title":489,"path":490,"stem":491,"children":492},"Admin Site","/admin-site","12.admin-site/01.index",[493,494,498,502,506,510],{"title":489,"path":490,"stem":491},{"title":495,"path":496,"stem":497},"Enabling the Admin","/admin-site/enabling-the-admin","12.admin-site/02.enabling-the-admin",{"title":499,"path":500,"stem":501},"Registering Models","/admin-site/registering-models","12.admin-site/03.registering-models",{"title":503,"path":504,"stem":505},"Customizing Admin Display","/admin-site/customizing-admin-display","12.admin-site/04.customizing-admin-display",{"title":507,"path":508,"stem":509},"Admin Actions","/admin-site/admin-actions","12.admin-site/05.admin-actions",{"title":511,"path":512,"stem":513},"Admin Security Best Practices","/admin-site/admin-security-best-practices","12.admin-site/06.admin-security-best-practices",{"title":515,"path":516,"stem":517,"children":518},"Middleware","/middleware","13.middleware/01.index",[519,520,524,528,532,536],{"title":515,"path":516,"stem":517},{"title":521,"path":522,"stem":523},"Middleware Overview","/middleware/middleware-overview","13.middleware/02.middleware-overview",{"title":525,"path":526,"stem":527},"Built-in Middleware","/middleware/built-in-middleware","13.middleware/03.built-in-middleware",{"title":529,"path":530,"stem":531},"Creating Custom Middleware","/middleware/creating-custom-middleware","13.middleware/04.creating-custom-middleware",{"title":533,"path":534,"stem":535},"Middleware Ordering","/middleware/middleware-ordering","13.middleware/05.middleware-ordering",{"title":537,"path":538,"stem":539},"Performance and Debugging","/middleware/performance-and-debugging","13.middleware/06.performance-and-debugging",{"title":541,"path":542,"stem":543,"children":544},"Security","/security","14.security/01.index",[545,546,550,554,558,562,566,570,574],{"title":541,"path":542,"stem":543},{"title":547,"path":548,"stem":549},"Django Security Philosophy","/security/django-security-philosophy","14.security/02.django-security-philosophy",{"title":551,"path":552,"stem":553},"Cross Site Request Forgery","/security/cross-site-request-forgery","14.security/03.cross-site-request-forgery",{"title":555,"path":556,"stem":557},"Cross Site Scripting","/security/cross-site-scripting","14.security/04.cross-site-scripting",{"title":559,"path":560,"stem":561},"SQL Injection Protection","/security/sql-injection-protection","14.security/05.sql-injection-protection",{"title":563,"path":564,"stem":565},"Clickjacking Protection","/security/clickjacking-protection","14.security/06.clickjacking-protection",{"title":567,"path":568,"stem":569},"HTTPS Setup and HSTS","/security/https-setup-and-hsts","14.security/07.https-setup-and-hsts",{"title":571,"path":572,"stem":573},"Password Storage and Cryptography","/security/password-storage-and-cryptography","14.security/08.password-storage-and-cryptography",{"title":575,"path":576,"stem":577},"Secure Deployment Checklist","/security/secure-deployment-checklist","14.security/09.secure-deployment-checklist",{"title":579,"path":580,"stem":581,"children":582},"Testing","/testing","15.testing/01.index",[583,584,588,592,596,600,604,608,612,616,620],{"title":579,"path":580,"stem":581},{"title":585,"path":586,"stem":587},"Introduction to Django Testing","/testing/introduction-to-django-testing","15.testing/02.introduction-to-django-testing",{"title":589,"path":590,"stem":591},"Writing and Running Tests","/testing/writing-and-running-tests","15.testing/03.writing-and-running-tests",{"title":593,"path":594,"stem":595},"Test Tools","/testing/test-tools","15.testing/04.test-tools",{"title":597,"path":598,"stem":599},"Testing Models","/testing/testing-models","15.testing/05.testing-models",{"title":601,"path":602,"stem":603},"Testing Views","/testing/testing-views","15.testing/06.testing-views",{"title":605,"path":606,"stem":607},"Testing Forms","/testing/testing-forms","15.testing/07.testing-forms",{"title":609,"path":610,"stem":611},"Testing Templates","/testing/testing-templates","15.testing/08.testing-templates",{"title":613,"path":614,"stem":615},"Testing Authentication","/testing/testing-authentication","15.testing/09.testing-authentication",{"title":617,"path":618,"stem":619},"Advanced Testing Topics","/testing/advanced-testing-topics","15.testing/10.advanced-testing-topics",{"title":621,"path":622,"stem":623},"Performance Testing","/testing/performance-testing","15.testing/11.performance-testing",{"title":625,"path":626,"stem":627,"children":628},"Static Assets and Frontend Integration","/static-assets-and-frontend-integration","16.static-assets-and-frontend-integration/01.index",[629,630,634,638,642,646],{"title":625,"path":626,"stem":627},{"title":631,"path":632,"stem":633},"Working with Static Files","/static-assets-and-frontend-integration/working-with-static-files","16.static-assets-and-frontend-integration/02.working-with-static-files",{"title":635,"path":636,"stem":637},"Integrating CSS and JavaScript","/static-assets-and-frontend-integration/integrating-css-and-javascript","16.static-assets-and-frontend-integration/03.integrating-css-and-javascript",{"title":639,"path":640,"stem":641},"Using Build Tools like Vite or Webpack","/static-assets-and-frontend-integration/using-build-tools-like-vite-or-webpack","16.static-assets-and-frontend-integration/04.using-build-tools-like-vite-or-webpack",{"title":643,"path":644,"stem":645},"Using React or Vue with Django","/static-assets-and-frontend-integration/using-react-or-vue-with-django","16.static-assets-and-frontend-integration/05.using-react-or-vue-with-django",{"title":647,"path":648,"stem":649},"Managing CORS","/static-assets-and-frontend-integration/managing-cors","16.static-assets-and-frontend-integration/06.managing-cors",{"title":651,"path":652,"stem":653,"children":654},"Internationalization and Localization","/internationalization-and-localization","17.internationalization-and-localization/01.index",[655,656,660,664,668],{"title":651,"path":652,"stem":653},{"title":657,"path":658,"stem":659},"Enabling Translation","/internationalization-and-localization/enabling-translation","17.internationalization-and-localization/02.enabling-translation",{"title":661,"path":662,"stem":663},"Translating Text in Code and Templates","/internationalization-and-localization/translating-text-in-code-and-templates","17.internationalization-and-localization/03.translating-text-in-code-and-templates",{"title":665,"path":666,"stem":667},"Timezone Support","/internationalization-and-localization/timezone-support","17.internationalization-and-localization/04.timezone-support",{"title":669,"path":670,"stem":671},"Locale Middleware","/internationalization-and-localization/locale-middleware","17.internationalization-and-localization/05.locale-middleware",{"title":673,"path":674,"stem":675,"children":676},"Caching","/caching","18.caching/01.index",[677,678,682,686,690,694,698],{"title":673,"path":674,"stem":675},{"title":679,"path":680,"stem":681},"Introduction to Caching","/caching/introduction-to-caching","18.caching/02.introduction-to-caching",{"title":683,"path":684,"stem":685},"Cache Backends","/caching/cache-backends","18.caching/03.cache-backends",{"title":687,"path":688,"stem":689},"Per View Caching","/caching/per-view-caching","18.caching/04.per-view-caching",{"title":691,"path":692,"stem":693},"Low Level Cache API","/caching/low-level-cache-api","18.caching/05.low-level-cache-api",{"title":695,"path":696,"stem":697},"Template Fragment Caching","/caching/template-fragment-caching","18.caching/06.template-fragment-caching",{"title":699,"path":700,"stem":701},"Deployment Level Caching Patterns","/caching/deployment-level-caching-patterns","18.caching/07.deployment-level-caching-patterns",{"title":703,"path":704,"stem":705,"children":706},"Asynchronous Django","/asynchronous-django","19.asynchronous-django/01.index",[707,708,712,716,720,724,728,732],{"title":703,"path":704,"stem":705},{"title":709,"path":710,"stem":711},"Introduction to ASGI","/asynchronous-django/introduction-to-asgi","19.asynchronous-django/02.introduction-to-asgi",{"title":713,"path":714,"stem":715},"Async Views","/asynchronous-django/async-views","19.asynchronous-django/03.async-views",{"title":717,"path":718,"stem":719},"Async ORM Status","/asynchronous-django/async-orm-status","19.asynchronous-django/04.async-orm-status",{"title":721,"path":722,"stem":723},"WebSockets with Channels","/asynchronous-django/websockets-with-channels","19.asynchronous-django/05.websockets-with-channels",{"title":725,"path":726,"stem":727},"Background Tasks with Celery or RQ","/asynchronous-django/background-tasks-with-celery-or-rq","19.asynchronous-django/06.background-tasks-with-celery-or-rq",{"title":729,"path":730,"stem":731},"Asynchronous Support","/asynchronous-django/asynchronous-support","19.asynchronous-django/07.asynchronous-support",{"title":733,"path":734,"stem":735},"Django's Tasks Framework","/asynchronous-django/django-tasks-framework","19.asynchronous-django/08.django-tasks-framework",{"title":737,"path":738,"stem":739,"children":740},"Deployment","/deployment","20.deployment/01.index",[741,742,746,750,754,758,762,766,770],{"title":737,"path":738,"stem":739},{"title":743,"path":744,"stem":745},"Preparing for Production","/deployment/preparing-for-production","20.deployment/02.preparing-for-production",{"title":747,"path":748,"stem":749},"Using WSGI and ASGI Servers","/deployment/using-wsgi-and-asgi-servers","20.deployment/03.using-wsgi-and-asgi-servers",{"title":751,"path":752,"stem":753},"Deploying on Linux Servers","/deployment/deploying-on-linux-servers","20.deployment/04.deploying-on-linux-servers",{"title":755,"path":756,"stem":757},"Using Docker","/deployment/using-docker","20.deployment/05.using-docker",{"title":759,"path":760,"stem":761},"Cloud Deployment Guides","/deployment/cloud-deployment-guides","20.deployment/06.cloud-deployment-guides",{"title":763,"path":764,"stem":765},"Scaling and Load Balancing","/deployment/scaling-and-load-balancing","20.deployment/07.scaling-and-load-balancing",{"title":767,"path":768,"stem":769},"Monitoring and Logging","/deployment/monitoring-and-logging","20.deployment/08.monitoring-and-logging",{"title":771,"path":772,"stem":773},"Backup Strategies","/deployment/backup-strategies","20.deployment/09.backup-strategies",{"title":775,"path":776,"stem":777,"children":778},"Performance and Optimization","/performance-and-optimization","21.performance-and-optimization/01.index",[779,780,784,788,792,796],{"title":775,"path":776,"stem":777},{"title":781,"path":782,"stem":783},"Query Optimization","/performance-and-optimization/query-optimization","21.performance-and-optimization/02.query-optimization",{"title":785,"path":786,"stem":787},"Template Rendering Optimization","/performance-and-optimization/template-rendering-optimization","21.performance-and-optimization/03.template-rendering-optimization",{"title":789,"path":790,"stem":791},"Using Select Related and Prefetch Related","/performance-and-optimization/using-select-related-and-prefetch-related","21.performance-and-optimization/04.using-select-related-and-prefetch-related",{"title":793,"path":794,"stem":795},"Caching Strategies","/performance-and-optimization/caching-strategies","21.performance-and-optimization/05.caching-strategies",{"title":797,"path":798,"stem":799},"Profiling Django Apps","/performance-and-optimization/profiling-django-apps","21.performance-and-optimization/06.profiling-django-apps",{"title":801,"path":802,"stem":803,"children":804},"Advanced and Expert Topics","/advanced-and-expert-topics","22.advanced-and-expert-topics/01.index",[805,806,810,814,818,822,826,830,834,838,842,846],{"title":801,"path":802,"stem":803},{"title":807,"path":808,"stem":809},"System Architecture Patterns","/advanced-and-expert-topics/system-architecture-patterns","22.advanced-and-expert-topics/02.system-architecture-patterns",{"title":811,"path":812,"stem":813},"Domain Driven Design with Django","/advanced-and-expert-topics/domain-driven-design-with-django","22.advanced-and-expert-topics/03.domain-driven-design-with-django",{"title":815,"path":816,"stem":817},"Building Large Scale Django Projects","/advanced-and-expert-topics/building-large-scale-django-projects","22.advanced-and-expert-topics/04.building-large-scale-django-projects",{"title":819,"path":820,"stem":821},"Plugin Architectures for Django Apps","/advanced-and-expert-topics/plugin-architectures-for-django-apps","22.advanced-and-expert-topics/05.plugin-architectures-for-django-apps",{"title":823,"path":824,"stem":825},"Extending Django's Core","/advanced-and-expert-topics/extending-djangos-core","22.advanced-and-expert-topics/06.extending-djangos-core",{"title":827,"path":828,"stem":829},"Custom ORM Expressions","/advanced-and-expert-topics/custom-orm-expressions","22.advanced-and-expert-topics/07.custom-orm-expressions",{"title":831,"path":832,"stem":833},"Custom Management Commands","/advanced-and-expert-topics/custom-management-commands","22.advanced-and-expert-topics/08.custom-management-commands",{"title":835,"path":836,"stem":837},"Working with Signals","/advanced-and-expert-topics/working-with-signals","22.advanced-and-expert-topics/09.working-with-signals",{"title":839,"path":840,"stem":841},"Building Reusable Django Packages","/advanced-and-expert-topics/building-reusable-django-packages","22.advanced-and-expert-topics/10.building-reusable-django-packages",{"title":843,"path":844,"stem":845},"Integrating Microservices","/advanced-and-expert-topics/integrating-microservices","22.advanced-and-expert-topics/11.integrating-microservices",{"title":847,"path":848,"stem":849},"Advanced Security Hardening","/advanced-and-expert-topics/advanced-security-hardening","22.advanced-and-expert-topics/12.advanced-security-hardening",{"title":851,"path":852,"stem":853,"children":854},"Logging in Django","/logging-in-django","23.logging-in-django/01.index",[855],{"title":851,"path":852,"stem":853},{"title":857,"path":858,"stem":859,"children":860},"FAQ and Troubleshooting","/faq-and-troubleshooting","24.faq-and-troubleshooting/01.index",[861],{"title":857,"path":858,"stem":859},{"title":863,"path":864,"stem":865,"children":866},"External Packages and Ecosystem","/external-packages-and-ecosystem","25.external-packages-and-ecosystem/01.index",[867],{"title":863,"path":864,"stem":865},{"title":869,"path":870,"stem":871,"children":872},"Django Internals and Contributing","/django-internals-and-contributing","26.django-internals-and-contributing/01.index",[873],{"title":869,"path":870,"stem":871},{"title":875,"path":876,"stem":877,"children":878},"Microservices with Django","/microservices-with-django","27.microservices-with-django/01.index",[879,880,884,888,892,896,900,904,908,912,916,920,924],{"title":875,"path":876,"stem":877},{"title":881,"path":882,"stem":883},"What Is a Microservice?","/microservices-with-django/what-is-a-microservice","27.microservices-with-django/02.what-is-a-microservice",{"title":885,"path":886,"stem":887},"Introducing the Django Microservices Architecture","/microservices-with-django/django-microservices-architecture","27.microservices-with-django/03.django-microservices-architecture",{"title":889,"path":890,"stem":891},"Setting Up the Development and Runtime Environment","/microservices-with-django/development-environment","27.microservices-with-django/04.development-environment",{"title":893,"path":894,"stem":895},"Cloud-native Data Processing with MongoDB","/microservices-with-django/cloud-native-data-processing","27.microservices-with-django/05.cloud-native-data-processing",{"title":897,"path":898,"stem":899},"Creating RESTful APIs for Microservices","/microservices-with-django/restful-apis","27.microservices-with-django/06.restful-apis",{"title":901,"path":902,"stem":903},"Orchestrating Microservices with Celery and RabbitMQ","/microservices-with-django/orchestrating-celery-rabbitmq","27.microservices-with-django/07.orchestrating-celery-rabbitmq",{"title":905,"path":906,"stem":907},"Testing Microservices","/microservices-with-django/testing-microservices","27.microservices-with-django/08.testing-microservices",{"title":909,"path":910,"stem":911},"Deploying Microservices","/microservices-with-django/deploying-microservices","27.microservices-with-django/09.deploying-microservices",{"title":913,"path":914,"stem":915},"Securing Microservices","/microservices-with-django/securing-microservices","27.microservices-with-django/10.securing-microservices",{"title":917,"path":918,"stem":919},"Improving Microservices Performance with Caching","/microservices-with-django/performance-caching","27.microservices-with-django/11.performance-caching",{"title":921,"path":922,"stem":923},"Best Practices","/microservices-with-django/best-practices","27.microservices-with-django/12.best-practices",{"title":925,"path":926,"stem":927},"Transforming a Monolithic Web App into a Microservice version","/microservices-with-django/monolith-to-microservices","27.microservices-with-django/13.monolith-to-microservices",{"title":929,"path":930,"stem":931,"children":932},"Releases","/releases","releases",[933,936,940,944,948,952,956,960,964,968,972,976,980,984,988,992,996,1000,1004,1008,1012],{"title":934,"path":930,"stem":935},"Django Releases","releases/index",{"title":937,"path":938,"stem":939},"Django 5.1.10 release notes","/releases/5.1.10","releases/5.1.10",{"title":941,"path":942,"stem":943},"Django 5.1.11 release notes","/releases/5.1.11","releases/5.1.11",{"title":945,"path":946,"stem":947},"Django 5.1.12 release notes","/releases/5.1.12","releases/5.1.12",{"title":949,"path":950,"stem":951},"Django 5.1.13 release notes","/releases/5.1.13","releases/5.1.13",{"title":953,"path":954,"stem":955},"Django 5.1.14 release notes","/releases/5.1.14","releases/5.1.14",{"title":957,"path":958,"stem":959},"Django 5.1.15 release notes","/releases/5.1.15","releases/5.1.15",{"title":961,"path":962,"stem":963},"Django 5.2 release notes","/releases/5.2","releases/5.2",{"title":965,"path":966,"stem":967},"Django 5.2.1 release notes","/releases/5.2.1","releases/5.2.1",{"title":969,"path":970,"stem":971},"Django 5.2.10 release notes","/releases/5.2.10","releases/5.2.10",{"title":973,"path":974,"stem":975},"Django 5.2.2 release notes","/releases/5.2.2","releases/5.2.2",{"title":977,"path":978,"stem":979},"Django 5.2.3 release notes","/releases/5.2.3","releases/5.2.3",{"title":981,"path":982,"stem":983},"Django 5.2.4 release notes","/releases/5.2.4","releases/5.2.4",{"title":985,"path":986,"stem":987},"Django 5.2.5 release notes","/releases/5.2.5","releases/5.2.5",{"title":989,"path":990,"stem":991},"Django 5.2.6 release notes","/releases/5.2.6","releases/5.2.6",{"title":993,"path":994,"stem":995},"Django 5.2.7 release notes","/releases/5.2.7","releases/5.2.7",{"title":997,"path":998,"stem":999},"Django 5.2.8 release notes","/releases/5.2.8","releases/5.2.8",{"title":1001,"path":1002,"stem":1003},"Django 5.2.9 release notes","/releases/5.2.9","releases/5.2.9",{"title":1005,"path":1006,"stem":1007},"Django 6.0 release notes","/releases/6.0","releases/6.0",{"title":1009,"path":1010,"stem":1011},"Django 6.0.1 release notes","/releases/6.0.1","releases/6.0.1",{"title":1013,"path":1014,"stem":1015},"Django 6.1 release notes - UNDER DEVELOPMENT","/releases/6.1","releases/6.1",{"id":1017,"title":643,"body":1018,"description":1028,"extension":10890,"links":10891,"meta":10892,"navigation":1641,"path":644,"seo":10893,"stem":645,"__hash__":10894},"docs/16.static-assets-and-frontend-integration/05.using-react-or-vue-with-django.md",{"type":1019,"value":1020,"toc":10859},"minimark",[1021,1025,1029,1034,1039,1042,1046,1049,1053,1056,1060,1064,1556,2087,2091,2253,2477,2481,3520,3906,3910,4323,5064,5068,5072,5413,5825,5829,6167,6514,6518,7444,7448,8588,8592,8596,9550,9554,9797,9801,9932,10162,10166,10170,10335,10518,10522,10526,10693,10697,10852,10855],[1022,1023,643],"h1",{"id":1024},"using-react-or-vue-with-django",[1026,1027,1028],"p",{},"Modern frontend frameworks like React and Vue enable building sophisticated single-page applications (SPAs) that communicate with Django backends through APIs. This chapter covers various integration patterns, from simple component embedding to full SPA architectures, including authentication, state management, and deployment strategies.",[1030,1031,1033],"h2",{"id":1032},"integration-patterns","Integration Patterns",[1035,1036,1038],"h3",{"id":1037},"pattern-1-component-islands","Pattern 1: Component Islands",[1026,1040,1041],{},"Embed React/Vue components within Django templates for specific interactive features.",[1035,1043,1045],{"id":1044},"pattern-2-hybrid-architecture","Pattern 2: Hybrid Architecture",[1026,1047,1048],{},"Use Django templates for some pages and SPA for others, sharing authentication and data.",[1035,1050,1052],{"id":1051},"pattern-3-full-spa-with-api-backend","Pattern 3: Full SPA with API Backend",[1026,1054,1055],{},"Complete separation where Django serves only APIs and React/Vue handles all frontend rendering.",[1030,1057,1059],{"id":1058},"react-integration-with-django","React Integration with Django",[1035,1061,1063],{"id":1062},"setting-up-react-with-vite","Setting Up React with Vite",[1065,1066,1071],"pre",{"className":1067,"code":1068,"language":1069,"meta":1070,"style":1070},"language-json shiki shiki-themes material-theme-lighter vitesse-light vitesse-dark","// package.json\n{\n  \"name\": \"django-react-app\",\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"react\": \"^18.2.0\",\n    \"react-dom\": \"^18.2.0\",\n    \"react-router-dom\": \"^6.8.0\",\n    \"axios\": \"^1.6.0\",\n    \"@tanstack/react-query\": \"^5.0.0\",\n    \"zustand\": \"^4.4.0\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^18.2.0\",\n    \"@types/react-dom\": \"^18.2.0\",\n    \"@vitejs/plugin-react\": \"^4.2.0\",\n    \"vite\": \"^5.0.0\",\n    \"eslint\": \"^8.55.0\",\n    \"eslint-plugin-react\": \"^7.33.0\",\n    \"eslint-plugin-react-hooks\": \"^4.6.0\"\n  }\n}\n","json","",[1072,1073,1074,1083,1090,1120,1141,1162,1177,1200,1221,1241,1247,1261,1282,1302,1323,1344,1365,1384,1389,1403,1423,1443,1464,1483,1504,1525,1544,1550],"code",{"__ignoreMap":1070},[1075,1076,1079],"span",{"class":1077,"line":1078},"line",1,[1075,1080,1082],{"class":1081},"s9Tkl","// package.json\n",[1075,1084,1086],{"class":1077,"line":1085},2,[1075,1087,1089],{"class":1088},"soVBu","{\n",[1075,1091,1093,1097,1101,1104,1107,1111,1115,1117],{"class":1077,"line":1092},3,[1075,1094,1096],{"class":1095},"s4Jsk","  \"",[1075,1098,1100],{"class":1099},"sLorS","name",[1075,1102,1103],{"class":1095},"\"",[1075,1105,1106],{"class":1088},":",[1075,1108,1110],{"class":1109},"sbYkP"," \"",[1075,1112,1114],{"class":1113},"sTbE_","django-react-app",[1075,1116,1103],{"class":1109},[1075,1118,1119],{"class":1088},",\n",[1075,1121,1123,1125,1128,1130,1132,1134,1137,1139],{"class":1077,"line":1122},4,[1075,1124,1096],{"class":1095},[1075,1126,1127],{"class":1099},"version",[1075,1129,1103],{"class":1095},[1075,1131,1106],{"class":1088},[1075,1133,1110],{"class":1109},[1075,1135,1136],{"class":1113},"1.0.0",[1075,1138,1103],{"class":1109},[1075,1140,1119],{"class":1088},[1075,1142,1144,1146,1149,1151,1153,1155,1158,1160],{"class":1077,"line":1143},5,[1075,1145,1096],{"class":1095},[1075,1147,1148],{"class":1099},"type",[1075,1150,1103],{"class":1095},[1075,1152,1106],{"class":1088},[1075,1154,1110],{"class":1109},[1075,1156,1157],{"class":1113},"module",[1075,1159,1103],{"class":1109},[1075,1161,1119],{"class":1088},[1075,1163,1165,1167,1170,1172,1174],{"class":1077,"line":1164},6,[1075,1166,1096],{"class":1095},[1075,1168,1169],{"class":1099},"scripts",[1075,1171,1103],{"class":1095},[1075,1173,1106],{"class":1088},[1075,1175,1176],{"class":1088}," {\n",[1075,1178,1180,1183,1187,1189,1191,1193,1196,1198],{"class":1077,"line":1179},7,[1075,1181,1182],{"class":1095},"    \"",[1075,1184,1186],{"class":1185},"sa2tF","dev",[1075,1188,1103],{"class":1095},[1075,1190,1106],{"class":1088},[1075,1192,1110],{"class":1109},[1075,1194,1195],{"class":1113},"vite",[1075,1197,1103],{"class":1109},[1075,1199,1119],{"class":1088},[1075,1201,1203,1205,1208,1210,1212,1214,1217,1219],{"class":1077,"line":1202},8,[1075,1204,1182],{"class":1095},[1075,1206,1207],{"class":1185},"build",[1075,1209,1103],{"class":1095},[1075,1211,1106],{"class":1088},[1075,1213,1110],{"class":1109},[1075,1215,1216],{"class":1113},"vite build",[1075,1218,1103],{"class":1109},[1075,1220,1119],{"class":1088},[1075,1222,1224,1226,1229,1231,1233,1235,1238],{"class":1077,"line":1223},9,[1075,1225,1182],{"class":1095},[1075,1227,1228],{"class":1185},"preview",[1075,1230,1103],{"class":1095},[1075,1232,1106],{"class":1088},[1075,1234,1110],{"class":1109},[1075,1236,1237],{"class":1113},"vite preview",[1075,1239,1240],{"class":1109},"\"\n",[1075,1242,1244],{"class":1077,"line":1243},10,[1075,1245,1246],{"class":1088},"  },\n",[1075,1248,1250,1252,1255,1257,1259],{"class":1077,"line":1249},11,[1075,1251,1096],{"class":1095},[1075,1253,1254],{"class":1099},"dependencies",[1075,1256,1103],{"class":1095},[1075,1258,1106],{"class":1088},[1075,1260,1176],{"class":1088},[1075,1262,1264,1266,1269,1271,1273,1275,1278,1280],{"class":1077,"line":1263},12,[1075,1265,1182],{"class":1095},[1075,1267,1268],{"class":1185},"react",[1075,1270,1103],{"class":1095},[1075,1272,1106],{"class":1088},[1075,1274,1110],{"class":1109},[1075,1276,1277],{"class":1113},"^18.2.0",[1075,1279,1103],{"class":1109},[1075,1281,1119],{"class":1088},[1075,1283,1285,1287,1290,1292,1294,1296,1298,1300],{"class":1077,"line":1284},13,[1075,1286,1182],{"class":1095},[1075,1288,1289],{"class":1185},"react-dom",[1075,1291,1103],{"class":1095},[1075,1293,1106],{"class":1088},[1075,1295,1110],{"class":1109},[1075,1297,1277],{"class":1113},[1075,1299,1103],{"class":1109},[1075,1301,1119],{"class":1088},[1075,1303,1305,1307,1310,1312,1314,1316,1319,1321],{"class":1077,"line":1304},14,[1075,1306,1182],{"class":1095},[1075,1308,1309],{"class":1185},"react-router-dom",[1075,1311,1103],{"class":1095},[1075,1313,1106],{"class":1088},[1075,1315,1110],{"class":1109},[1075,1317,1318],{"class":1113},"^6.8.0",[1075,1320,1103],{"class":1109},[1075,1322,1119],{"class":1088},[1075,1324,1326,1328,1331,1333,1335,1337,1340,1342],{"class":1077,"line":1325},15,[1075,1327,1182],{"class":1095},[1075,1329,1330],{"class":1185},"axios",[1075,1332,1103],{"class":1095},[1075,1334,1106],{"class":1088},[1075,1336,1110],{"class":1109},[1075,1338,1339],{"class":1113},"^1.6.0",[1075,1341,1103],{"class":1109},[1075,1343,1119],{"class":1088},[1075,1345,1347,1349,1352,1354,1356,1358,1361,1363],{"class":1077,"line":1346},16,[1075,1348,1182],{"class":1095},[1075,1350,1351],{"class":1185},"@tanstack/react-query",[1075,1353,1103],{"class":1095},[1075,1355,1106],{"class":1088},[1075,1357,1110],{"class":1109},[1075,1359,1360],{"class":1113},"^5.0.0",[1075,1362,1103],{"class":1109},[1075,1364,1119],{"class":1088},[1075,1366,1368,1370,1373,1375,1377,1379,1382],{"class":1077,"line":1367},17,[1075,1369,1182],{"class":1095},[1075,1371,1372],{"class":1185},"zustand",[1075,1374,1103],{"class":1095},[1075,1376,1106],{"class":1088},[1075,1378,1110],{"class":1109},[1075,1380,1381],{"class":1113},"^4.4.0",[1075,1383,1240],{"class":1109},[1075,1385,1387],{"class":1077,"line":1386},18,[1075,1388,1246],{"class":1088},[1075,1390,1392,1394,1397,1399,1401],{"class":1077,"line":1391},19,[1075,1393,1096],{"class":1095},[1075,1395,1396],{"class":1099},"devDependencies",[1075,1398,1103],{"class":1095},[1075,1400,1106],{"class":1088},[1075,1402,1176],{"class":1088},[1075,1404,1406,1408,1411,1413,1415,1417,1419,1421],{"class":1077,"line":1405},20,[1075,1407,1182],{"class":1095},[1075,1409,1410],{"class":1185},"@types/react",[1075,1412,1103],{"class":1095},[1075,1414,1106],{"class":1088},[1075,1416,1110],{"class":1109},[1075,1418,1277],{"class":1113},[1075,1420,1103],{"class":1109},[1075,1422,1119],{"class":1088},[1075,1424,1426,1428,1431,1433,1435,1437,1439,1441],{"class":1077,"line":1425},21,[1075,1427,1182],{"class":1095},[1075,1429,1430],{"class":1185},"@types/react-dom",[1075,1432,1103],{"class":1095},[1075,1434,1106],{"class":1088},[1075,1436,1110],{"class":1109},[1075,1438,1277],{"class":1113},[1075,1440,1103],{"class":1109},[1075,1442,1119],{"class":1088},[1075,1444,1446,1448,1451,1453,1455,1457,1460,1462],{"class":1077,"line":1445},22,[1075,1447,1182],{"class":1095},[1075,1449,1450],{"class":1185},"@vitejs/plugin-react",[1075,1452,1103],{"class":1095},[1075,1454,1106],{"class":1088},[1075,1456,1110],{"class":1109},[1075,1458,1459],{"class":1113},"^4.2.0",[1075,1461,1103],{"class":1109},[1075,1463,1119],{"class":1088},[1075,1465,1467,1469,1471,1473,1475,1477,1479,1481],{"class":1077,"line":1466},23,[1075,1468,1182],{"class":1095},[1075,1470,1195],{"class":1185},[1075,1472,1103],{"class":1095},[1075,1474,1106],{"class":1088},[1075,1476,1110],{"class":1109},[1075,1478,1360],{"class":1113},[1075,1480,1103],{"class":1109},[1075,1482,1119],{"class":1088},[1075,1484,1486,1488,1491,1493,1495,1497,1500,1502],{"class":1077,"line":1485},24,[1075,1487,1182],{"class":1095},[1075,1489,1490],{"class":1185},"eslint",[1075,1492,1103],{"class":1095},[1075,1494,1106],{"class":1088},[1075,1496,1110],{"class":1109},[1075,1498,1499],{"class":1113},"^8.55.0",[1075,1501,1103],{"class":1109},[1075,1503,1119],{"class":1088},[1075,1505,1507,1509,1512,1514,1516,1518,1521,1523],{"class":1077,"line":1506},25,[1075,1508,1182],{"class":1095},[1075,1510,1511],{"class":1185},"eslint-plugin-react",[1075,1513,1103],{"class":1095},[1075,1515,1106],{"class":1088},[1075,1517,1110],{"class":1109},[1075,1519,1520],{"class":1113},"^7.33.0",[1075,1522,1103],{"class":1109},[1075,1524,1119],{"class":1088},[1075,1526,1528,1530,1533,1535,1537,1539,1542],{"class":1077,"line":1527},26,[1075,1529,1182],{"class":1095},[1075,1531,1532],{"class":1185},"eslint-plugin-react-hooks",[1075,1534,1103],{"class":1095},[1075,1536,1106],{"class":1088},[1075,1538,1110],{"class":1109},[1075,1540,1541],{"class":1113},"^4.6.0",[1075,1543,1240],{"class":1109},[1075,1545,1547],{"class":1077,"line":1546},27,[1075,1548,1549],{"class":1088},"  }\n",[1075,1551,1553],{"class":1077,"line":1552},28,[1075,1554,1555],{"class":1088},"}\n",[1065,1557,1561],{"className":1558,"code":1559,"language":1560,"meta":1070,"style":1070},"language-javascript shiki shiki-themes material-theme-lighter vitesse-light vitesse-dark","// vite.config.js\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\nimport { resolve } from 'path';\n\nexport default defineConfig({\n  plugins: [react()],\n  \n  build: {\n    outDir: 'staticfiles/dist',\n    manifest: true,\n    rollupOptions: {\n      input: {\n        main: resolve(__dirname, 'frontend/js/main.jsx'),\n        components: resolve(__dirname, 'frontend/js/components.jsx')\n      }\n    }\n  },\n  \n  server: {\n    port: 3000,\n    proxy: {\n      '/api': 'http://localhost:8000',\n      '/admin': 'http://localhost:8000'\n    }\n  },\n  \n  resolve: {\n    alias: {\n      '@': resolve(__dirname, 'frontend'),\n      '@components': resolve(__dirname, 'frontend/js/components'),\n      '@hooks': resolve(__dirname, 'frontend/js/hooks'),\n      '@utils': resolve(__dirname, 'frontend/js/utils'),\n      '@store': resolve(__dirname, 'frontend/js/store')\n    }\n  }\n});\n","javascript",[1072,1562,1563,1568,1598,1615,1637,1643,1660,1678,1684,1693,1709,1722,1731,1740,1769,1794,1799,1804,1808,1812,1821,1834,1843,1865,1883,1887,1891,1895,1904,1914,1945,1976,2007,2038,2067,2072,2077],{"__ignoreMap":1070},[1075,1564,1565],{"class":1077,"line":1078},[1075,1566,1567],{"class":1081},"// vite.config.js\n",[1075,1569,1570,1574,1577,1581,1584,1587,1590,1592,1595],{"class":1077,"line":1085},[1075,1571,1573],{"class":1572},"siDh9","import",[1075,1575,1576],{"class":1088}," {",[1075,1578,1580],{"class":1579},"sSC40"," defineConfig",[1075,1582,1583],{"class":1088}," }",[1075,1585,1586],{"class":1572}," from",[1075,1588,1589],{"class":1109}," '",[1075,1591,1195],{"class":1113},[1075,1593,1594],{"class":1109},"'",[1075,1596,1597],{"class":1088},";\n",[1075,1599,1600,1602,1605,1607,1609,1611,1613],{"class":1077,"line":1092},[1075,1601,1573],{"class":1572},[1075,1603,1604],{"class":1579}," react",[1075,1606,1586],{"class":1572},[1075,1608,1589],{"class":1109},[1075,1610,1450],{"class":1113},[1075,1612,1594],{"class":1109},[1075,1614,1597],{"class":1088},[1075,1616,1617,1619,1621,1624,1626,1628,1630,1633,1635],{"class":1077,"line":1122},[1075,1618,1573],{"class":1572},[1075,1620,1576],{"class":1088},[1075,1622,1623],{"class":1579}," resolve",[1075,1625,1583],{"class":1088},[1075,1627,1586],{"class":1572},[1075,1629,1589],{"class":1109},[1075,1631,1632],{"class":1113},"path",[1075,1634,1594],{"class":1109},[1075,1636,1597],{"class":1088},[1075,1638,1639],{"class":1077,"line":1143},[1075,1640,1642],{"emptyLinePlaceholder":1641},true,"\n",[1075,1644,1645,1648,1651,1654,1658],{"class":1077,"line":1164},[1075,1646,1647],{"class":1572},"export",[1075,1649,1650],{"class":1572}," default",[1075,1652,1580],{"class":1653},"sljsM",[1075,1655,1657],{"class":1656},"snCua","(",[1075,1659,1089],{"class":1088},[1075,1661,1662,1666,1668,1671,1673,1676],{"class":1077,"line":1179},[1075,1663,1665],{"class":1664},"suXOh","  plugins",[1075,1667,1106],{"class":1088},[1075,1669,1670],{"class":1656}," [",[1075,1672,1268],{"class":1653},[1075,1674,1675],{"class":1656},"()]",[1075,1677,1119],{"class":1088},[1075,1679,1680],{"class":1077,"line":1202},[1075,1681,1683],{"class":1682},"sftqT","  \n",[1075,1685,1686,1689,1691],{"class":1077,"line":1223},[1075,1687,1688],{"class":1664},"  build",[1075,1690,1106],{"class":1088},[1075,1692,1176],{"class":1088},[1075,1694,1695,1698,1700,1702,1705,1707],{"class":1077,"line":1243},[1075,1696,1697],{"class":1664},"    outDir",[1075,1699,1106],{"class":1088},[1075,1701,1589],{"class":1109},[1075,1703,1704],{"class":1113},"staticfiles/dist",[1075,1706,1594],{"class":1109},[1075,1708,1119],{"class":1088},[1075,1710,1711,1714,1716,1720],{"class":1077,"line":1249},[1075,1712,1713],{"class":1664},"    manifest",[1075,1715,1106],{"class":1088},[1075,1717,1719],{"class":1718},"sq3J1"," true",[1075,1721,1119],{"class":1088},[1075,1723,1724,1727,1729],{"class":1077,"line":1263},[1075,1725,1726],{"class":1664},"    rollupOptions",[1075,1728,1106],{"class":1088},[1075,1730,1176],{"class":1088},[1075,1732,1733,1736,1738],{"class":1077,"line":1284},[1075,1734,1735],{"class":1664},"      input",[1075,1737,1106],{"class":1088},[1075,1739,1176],{"class":1088},[1075,1741,1742,1745,1747,1749,1751,1754,1757,1759,1762,1764,1767],{"class":1077,"line":1304},[1075,1743,1744],{"class":1664},"        main",[1075,1746,1106],{"class":1088},[1075,1748,1623],{"class":1653},[1075,1750,1657],{"class":1656},[1075,1752,1753],{"class":1579},"__dirname",[1075,1755,1756],{"class":1088},",",[1075,1758,1589],{"class":1109},[1075,1760,1761],{"class":1113},"frontend/js/main.jsx",[1075,1763,1594],{"class":1109},[1075,1765,1766],{"class":1656},")",[1075,1768,1119],{"class":1088},[1075,1770,1771,1774,1776,1778,1780,1782,1784,1786,1789,1791],{"class":1077,"line":1325},[1075,1772,1773],{"class":1664},"        components",[1075,1775,1106],{"class":1088},[1075,1777,1623],{"class":1653},[1075,1779,1657],{"class":1656},[1075,1781,1753],{"class":1579},[1075,1783,1756],{"class":1088},[1075,1785,1589],{"class":1109},[1075,1787,1788],{"class":1113},"frontend/js/components.jsx",[1075,1790,1594],{"class":1109},[1075,1792,1793],{"class":1656},")\n",[1075,1795,1796],{"class":1077,"line":1346},[1075,1797,1798],{"class":1088},"      }\n",[1075,1800,1801],{"class":1077,"line":1367},[1075,1802,1803],{"class":1088},"    }\n",[1075,1805,1806],{"class":1077,"line":1386},[1075,1807,1246],{"class":1088},[1075,1809,1810],{"class":1077,"line":1391},[1075,1811,1683],{"class":1682},[1075,1813,1814,1817,1819],{"class":1077,"line":1405},[1075,1815,1816],{"class":1664},"  server",[1075,1818,1106],{"class":1088},[1075,1820,1176],{"class":1088},[1075,1822,1823,1826,1828,1832],{"class":1077,"line":1425},[1075,1824,1825],{"class":1664},"    port",[1075,1827,1106],{"class":1088},[1075,1829,1831],{"class":1830},"s7CZa"," 3000",[1075,1833,1119],{"class":1088},[1075,1835,1836,1839,1841],{"class":1077,"line":1445},[1075,1837,1838],{"class":1664},"    proxy",[1075,1840,1106],{"class":1088},[1075,1842,1176],{"class":1088},[1075,1844,1845,1848,1852,1854,1856,1858,1861,1863],{"class":1077,"line":1466},[1075,1846,1847],{"class":1109},"      '",[1075,1849,1851],{"class":1850},"sQtxO","/api",[1075,1853,1594],{"class":1109},[1075,1855,1106],{"class":1088},[1075,1857,1589],{"class":1109},[1075,1859,1860],{"class":1113},"http://localhost:8000",[1075,1862,1594],{"class":1109},[1075,1864,1119],{"class":1088},[1075,1866,1867,1869,1872,1874,1876,1878,1880],{"class":1077,"line":1485},[1075,1868,1847],{"class":1109},[1075,1870,1871],{"class":1850},"/admin",[1075,1873,1594],{"class":1109},[1075,1875,1106],{"class":1088},[1075,1877,1589],{"class":1109},[1075,1879,1860],{"class":1113},[1075,1881,1882],{"class":1109},"'\n",[1075,1884,1885],{"class":1077,"line":1506},[1075,1886,1803],{"class":1088},[1075,1888,1889],{"class":1077,"line":1527},[1075,1890,1246],{"class":1088},[1075,1892,1893],{"class":1077,"line":1546},[1075,1894,1683],{"class":1682},[1075,1896,1897,1900,1902],{"class":1077,"line":1552},[1075,1898,1899],{"class":1664},"  resolve",[1075,1901,1106],{"class":1088},[1075,1903,1176],{"class":1088},[1075,1905,1907,1910,1912],{"class":1077,"line":1906},29,[1075,1908,1909],{"class":1664},"    alias",[1075,1911,1106],{"class":1088},[1075,1913,1176],{"class":1088},[1075,1915,1917,1919,1922,1924,1926,1928,1930,1932,1934,1936,1939,1941,1943],{"class":1077,"line":1916},30,[1075,1918,1847],{"class":1109},[1075,1920,1921],{"class":1850},"@",[1075,1923,1594],{"class":1109},[1075,1925,1106],{"class":1088},[1075,1927,1623],{"class":1653},[1075,1929,1657],{"class":1656},[1075,1931,1753],{"class":1579},[1075,1933,1756],{"class":1088},[1075,1935,1589],{"class":1109},[1075,1937,1938],{"class":1113},"frontend",[1075,1940,1594],{"class":1109},[1075,1942,1766],{"class":1656},[1075,1944,1119],{"class":1088},[1075,1946,1948,1950,1953,1955,1957,1959,1961,1963,1965,1967,1970,1972,1974],{"class":1077,"line":1947},31,[1075,1949,1847],{"class":1109},[1075,1951,1952],{"class":1850},"@components",[1075,1954,1594],{"class":1109},[1075,1956,1106],{"class":1088},[1075,1958,1623],{"class":1653},[1075,1960,1657],{"class":1656},[1075,1962,1753],{"class":1579},[1075,1964,1756],{"class":1088},[1075,1966,1589],{"class":1109},[1075,1968,1969],{"class":1113},"frontend/js/components",[1075,1971,1594],{"class":1109},[1075,1973,1766],{"class":1656},[1075,1975,1119],{"class":1088},[1075,1977,1979,1981,1984,1986,1988,1990,1992,1994,1996,1998,2001,2003,2005],{"class":1077,"line":1978},32,[1075,1980,1847],{"class":1109},[1075,1982,1983],{"class":1850},"@hooks",[1075,1985,1594],{"class":1109},[1075,1987,1106],{"class":1088},[1075,1989,1623],{"class":1653},[1075,1991,1657],{"class":1656},[1075,1993,1753],{"class":1579},[1075,1995,1756],{"class":1088},[1075,1997,1589],{"class":1109},[1075,1999,2000],{"class":1113},"frontend/js/hooks",[1075,2002,1594],{"class":1109},[1075,2004,1766],{"class":1656},[1075,2006,1119],{"class":1088},[1075,2008,2010,2012,2015,2017,2019,2021,2023,2025,2027,2029,2032,2034,2036],{"class":1077,"line":2009},33,[1075,2011,1847],{"class":1109},[1075,2013,2014],{"class":1850},"@utils",[1075,2016,1594],{"class":1109},[1075,2018,1106],{"class":1088},[1075,2020,1623],{"class":1653},[1075,2022,1657],{"class":1656},[1075,2024,1753],{"class":1579},[1075,2026,1756],{"class":1088},[1075,2028,1589],{"class":1109},[1075,2030,2031],{"class":1113},"frontend/js/utils",[1075,2033,1594],{"class":1109},[1075,2035,1766],{"class":1656},[1075,2037,1119],{"class":1088},[1075,2039,2041,2043,2046,2048,2050,2052,2054,2056,2058,2060,2063,2065],{"class":1077,"line":2040},34,[1075,2042,1847],{"class":1109},[1075,2044,2045],{"class":1850},"@store",[1075,2047,1594],{"class":1109},[1075,2049,1106],{"class":1088},[1075,2051,1623],{"class":1653},[1075,2053,1657],{"class":1656},[1075,2055,1753],{"class":1579},[1075,2057,1756],{"class":1088},[1075,2059,1589],{"class":1109},[1075,2061,2062],{"class":1113},"frontend/js/store",[1075,2064,1594],{"class":1109},[1075,2066,1793],{"class":1656},[1075,2068,2070],{"class":1077,"line":2069},35,[1075,2071,1803],{"class":1088},[1075,2073,2075],{"class":1077,"line":2074},36,[1075,2076,1549],{"class":1088},[1075,2078,2080,2083,2085],{"class":1077,"line":2079},37,[1075,2081,2082],{"class":1088},"}",[1075,2084,1766],{"class":1656},[1075,2086,1597],{"class":1088},[1035,2088,2090],{"id":2089},"react-component-structure","React Component Structure",[1065,2092,2096],{"className":2093,"code":2094,"language":2095,"meta":1070,"style":1070},"language-jsx shiki shiki-themes material-theme-lighter vitesse-light vitesse-dark","// frontend/js/main.jsx\nimport React from 'react';\nimport { createRoot } from 'react-dom/client';\nimport { BrowserRouter } from 'react-router-dom';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport App from './App';\nimport './styles/main.css';\n\n// Create React Query client\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      staleTime: 5 * 60 * 1000, // 5 minutes\n      retry: 1\n    }\n  }\n});\n\n// Mount React app\nconst container = document.getElementById('react-app');\nif (container) {\n  const root = createRoot(container);\n  root.render(\n    \u003CReact.StrictMode>\n      \u003CQueryClientProvider client={queryClient}>\n        \u003CBrowserRouter>\n          \u003CApp />\n        \u003C/BrowserRouter>\n      \u003C/QueryClientProvider>\n    \u003C/React.StrictMode>\n  );\n}\n","jsx",[1072,2097,2098,2103,2108,2113,2118,2123,2128,2133,2137,2142,2147,2152,2157,2162,2167,2171,2175,2180,2184,2189,2194,2199,2204,2209,2214,2219,2224,2229,2234,2239,2244,2249],{"__ignoreMap":1070},[1075,2099,2100],{"class":1077,"line":1078},[1075,2101,2102],{},"// frontend/js/main.jsx\n",[1075,2104,2105],{"class":1077,"line":1085},[1075,2106,2107],{},"import React from 'react';\n",[1075,2109,2110],{"class":1077,"line":1092},[1075,2111,2112],{},"import { createRoot } from 'react-dom/client';\n",[1075,2114,2115],{"class":1077,"line":1122},[1075,2116,2117],{},"import { BrowserRouter } from 'react-router-dom';\n",[1075,2119,2120],{"class":1077,"line":1143},[1075,2121,2122],{},"import { QueryClient, QueryClientProvider } from '@tanstack/react-query';\n",[1075,2124,2125],{"class":1077,"line":1164},[1075,2126,2127],{},"import App from './App';\n",[1075,2129,2130],{"class":1077,"line":1179},[1075,2131,2132],{},"import './styles/main.css';\n",[1075,2134,2135],{"class":1077,"line":1202},[1075,2136,1642],{"emptyLinePlaceholder":1641},[1075,2138,2139],{"class":1077,"line":1223},[1075,2140,2141],{},"// Create React Query client\n",[1075,2143,2144],{"class":1077,"line":1243},[1075,2145,2146],{},"const queryClient = new QueryClient({\n",[1075,2148,2149],{"class":1077,"line":1249},[1075,2150,2151],{},"  defaultOptions: {\n",[1075,2153,2154],{"class":1077,"line":1263},[1075,2155,2156],{},"    queries: {\n",[1075,2158,2159],{"class":1077,"line":1284},[1075,2160,2161],{},"      staleTime: 5 * 60 * 1000, // 5 minutes\n",[1075,2163,2164],{"class":1077,"line":1304},[1075,2165,2166],{},"      retry: 1\n",[1075,2168,2169],{"class":1077,"line":1325},[1075,2170,1803],{},[1075,2172,2173],{"class":1077,"line":1346},[1075,2174,1549],{},[1075,2176,2177],{"class":1077,"line":1367},[1075,2178,2179],{},"});\n",[1075,2181,2182],{"class":1077,"line":1386},[1075,2183,1642],{"emptyLinePlaceholder":1641},[1075,2185,2186],{"class":1077,"line":1391},[1075,2187,2188],{},"// Mount React app\n",[1075,2190,2191],{"class":1077,"line":1405},[1075,2192,2193],{},"const container = document.getElementById('react-app');\n",[1075,2195,2196],{"class":1077,"line":1425},[1075,2197,2198],{},"if (container) {\n",[1075,2200,2201],{"class":1077,"line":1445},[1075,2202,2203],{},"  const root = createRoot(container);\n",[1075,2205,2206],{"class":1077,"line":1466},[1075,2207,2208],{},"  root.render(\n",[1075,2210,2211],{"class":1077,"line":1485},[1075,2212,2213],{},"    \u003CReact.StrictMode>\n",[1075,2215,2216],{"class":1077,"line":1506},[1075,2217,2218],{},"      \u003CQueryClientProvider client={queryClient}>\n",[1075,2220,2221],{"class":1077,"line":1527},[1075,2222,2223],{},"        \u003CBrowserRouter>\n",[1075,2225,2226],{"class":1077,"line":1546},[1075,2227,2228],{},"          \u003CApp />\n",[1075,2230,2231],{"class":1077,"line":1552},[1075,2232,2233],{},"        \u003C/BrowserRouter>\n",[1075,2235,2236],{"class":1077,"line":1906},[1075,2237,2238],{},"      \u003C/QueryClientProvider>\n",[1075,2240,2241],{"class":1077,"line":1916},[1075,2242,2243],{},"    \u003C/React.StrictMode>\n",[1075,2245,2246],{"class":1077,"line":1947},[1075,2247,2248],{},"  );\n",[1075,2250,2251],{"class":1077,"line":1978},[1075,2252,1555],{},[1065,2254,2256],{"className":2093,"code":2255,"language":2095,"meta":1070,"style":1070},"// frontend/js/App.jsx\nimport React from 'react';\nimport { Routes, Route } from 'react-router-dom';\nimport { useAuthStore } from '@store/authStore';\nimport Navigation from '@components/Navigation';\nimport Home from '@components/pages/Home';\nimport Blog from '@components/pages/Blog';\nimport BlogPost from '@components/pages/BlogPost';\nimport Dashboard from '@components/pages/Dashboard';\nimport Login from '@components/auth/Login';\nimport ProtectedRoute from '@components/auth/ProtectedRoute';\n\nfunction App() {\n  const { user, loading } = useAuthStore();\n\n  if (loading) {\n    return \u003Cdiv className=\"loading\">Loading...\u003C/div>;\n  }\n\n  return (\n    \u003Cdiv className=\"app\">\n      \u003CNavigation user={user} />\n      \n      \u003Cmain className=\"main-content\">\n        \u003CRoutes>\n          \u003CRoute path=\"/\" element={\u003CHome />} />\n          \u003CRoute path=\"/blog\" element={\u003CBlog />} />\n          \u003CRoute path=\"/blog/:slug\" element={\u003CBlogPost />} />\n          \u003CRoute path=\"/login\" element={\u003CLogin />} />\n          \u003CRoute \n            path=\"/dashboard\" \n            element={\n              \u003CProtectedRoute>\n                \u003CDashboard />\n              \u003C/ProtectedRoute>\n            } \n          />\n        \u003C/Routes>\n      \u003C/main>\n    \u003C/div>\n  );\n}\n\nexport default App;\n",[1072,2257,2258,2263,2267,2272,2277,2282,2287,2292,2297,2302,2307,2312,2316,2321,2326,2330,2335,2340,2344,2348,2353,2358,2363,2368,2373,2378,2383,2388,2393,2398,2403,2408,2413,2418,2423,2428,2433,2438,2444,2450,2456,2461,2466,2471],{"__ignoreMap":1070},[1075,2259,2260],{"class":1077,"line":1078},[1075,2261,2262],{},"// frontend/js/App.jsx\n",[1075,2264,2265],{"class":1077,"line":1085},[1075,2266,2107],{},[1075,2268,2269],{"class":1077,"line":1092},[1075,2270,2271],{},"import { Routes, Route } from 'react-router-dom';\n",[1075,2273,2274],{"class":1077,"line":1122},[1075,2275,2276],{},"import { useAuthStore } from '@store/authStore';\n",[1075,2278,2279],{"class":1077,"line":1143},[1075,2280,2281],{},"import Navigation from '@components/Navigation';\n",[1075,2283,2284],{"class":1077,"line":1164},[1075,2285,2286],{},"import Home from '@components/pages/Home';\n",[1075,2288,2289],{"class":1077,"line":1179},[1075,2290,2291],{},"import Blog from '@components/pages/Blog';\n",[1075,2293,2294],{"class":1077,"line":1202},[1075,2295,2296],{},"import BlogPost from '@components/pages/BlogPost';\n",[1075,2298,2299],{"class":1077,"line":1223},[1075,2300,2301],{},"import Dashboard from '@components/pages/Dashboard';\n",[1075,2303,2304],{"class":1077,"line":1243},[1075,2305,2306],{},"import Login from '@components/auth/Login';\n",[1075,2308,2309],{"class":1077,"line":1249},[1075,2310,2311],{},"import ProtectedRoute from '@components/auth/ProtectedRoute';\n",[1075,2313,2314],{"class":1077,"line":1263},[1075,2315,1642],{"emptyLinePlaceholder":1641},[1075,2317,2318],{"class":1077,"line":1284},[1075,2319,2320],{},"function App() {\n",[1075,2322,2323],{"class":1077,"line":1304},[1075,2324,2325],{},"  const { user, loading } = useAuthStore();\n",[1075,2327,2328],{"class":1077,"line":1325},[1075,2329,1642],{"emptyLinePlaceholder":1641},[1075,2331,2332],{"class":1077,"line":1346},[1075,2333,2334],{},"  if (loading) {\n",[1075,2336,2337],{"class":1077,"line":1367},[1075,2338,2339],{},"    return \u003Cdiv className=\"loading\">Loading...\u003C/div>;\n",[1075,2341,2342],{"class":1077,"line":1386},[1075,2343,1549],{},[1075,2345,2346],{"class":1077,"line":1391},[1075,2347,1642],{"emptyLinePlaceholder":1641},[1075,2349,2350],{"class":1077,"line":1405},[1075,2351,2352],{},"  return (\n",[1075,2354,2355],{"class":1077,"line":1425},[1075,2356,2357],{},"    \u003Cdiv className=\"app\">\n",[1075,2359,2360],{"class":1077,"line":1445},[1075,2361,2362],{},"      \u003CNavigation user={user} />\n",[1075,2364,2365],{"class":1077,"line":1466},[1075,2366,2367],{},"      \n",[1075,2369,2370],{"class":1077,"line":1485},[1075,2371,2372],{},"      \u003Cmain className=\"main-content\">\n",[1075,2374,2375],{"class":1077,"line":1506},[1075,2376,2377],{},"        \u003CRoutes>\n",[1075,2379,2380],{"class":1077,"line":1527},[1075,2381,2382],{},"          \u003CRoute path=\"/\" element={\u003CHome />} />\n",[1075,2384,2385],{"class":1077,"line":1546},[1075,2386,2387],{},"          \u003CRoute path=\"/blog\" element={\u003CBlog />} />\n",[1075,2389,2390],{"class":1077,"line":1552},[1075,2391,2392],{},"          \u003CRoute path=\"/blog/:slug\" element={\u003CBlogPost />} />\n",[1075,2394,2395],{"class":1077,"line":1906},[1075,2396,2397],{},"          \u003CRoute path=\"/login\" element={\u003CLogin />} />\n",[1075,2399,2400],{"class":1077,"line":1916},[1075,2401,2402],{},"          \u003CRoute \n",[1075,2404,2405],{"class":1077,"line":1947},[1075,2406,2407],{},"            path=\"/dashboard\" \n",[1075,2409,2410],{"class":1077,"line":1978},[1075,2411,2412],{},"            element={\n",[1075,2414,2415],{"class":1077,"line":2009},[1075,2416,2417],{},"              \u003CProtectedRoute>\n",[1075,2419,2420],{"class":1077,"line":2040},[1075,2421,2422],{},"                \u003CDashboard />\n",[1075,2424,2425],{"class":1077,"line":2069},[1075,2426,2427],{},"              \u003C/ProtectedRoute>\n",[1075,2429,2430],{"class":1077,"line":2074},[1075,2431,2432],{},"            } \n",[1075,2434,2435],{"class":1077,"line":2079},[1075,2436,2437],{},"          />\n",[1075,2439,2441],{"class":1077,"line":2440},38,[1075,2442,2443],{},"        \u003C/Routes>\n",[1075,2445,2447],{"class":1077,"line":2446},39,[1075,2448,2449],{},"      \u003C/main>\n",[1075,2451,2453],{"class":1077,"line":2452},40,[1075,2454,2455],{},"    \u003C/div>\n",[1075,2457,2459],{"class":1077,"line":2458},41,[1075,2460,2248],{},[1075,2462,2464],{"class":1077,"line":2463},42,[1075,2465,1555],{},[1075,2467,2469],{"class":1077,"line":2468},43,[1075,2470,1642],{"emptyLinePlaceholder":1641},[1075,2472,2474],{"class":1077,"line":2473},44,[1075,2475,2476],{},"export default App;\n",[1035,2478,2480],{"id":2479},"authentication-integration","Authentication Integration",[1065,2482,2484],{"className":1558,"code":2483,"language":1560,"meta":1070,"style":1070},"// frontend/js/store/authStore.js\nimport { create } from 'zustand';\nimport { persist } from 'zustand/middleware';\nimport api from '@utils/api';\n\nexport const useAuthStore = create(\n  persist(\n    (set, get) => ({\n      user: null,\n      token: null,\n      loading: true,\n      \n      // Initialize auth state\n      initialize: async () => {\n        const token = get().token;\n        if (token) {\n          try {\n            const user = await api.get('/auth/user/');\n            set({ user: user.data, loading: false });\n          } catch (error) {\n            set({ user: null, token: null, loading: false });\n          }\n        } else {\n          set({ loading: false });\n        }\n      },\n      \n      // Login\n      login: async (credentials) => {\n        try {\n          const response = await api.post('/auth/login/', credentials);\n          const { user, token } = response.data;\n          \n          set({ user, token });\n          api.defaults.headers.common['Authorization'] = `Bearer ${token}`;\n          \n          return { success: true };\n        } catch (error) {\n          return { \n            success: false, \n            error: error.response?.data?.message || 'Login failed' \n          };\n        }\n      },\n      \n      // Logout\n      logout: async () => {\n        try {\n          await api.post('/auth/logout/');\n        } catch (error) {\n          // Continue with logout even if API call fails\n        }\n        \n        set({ user: null, token: null });\n        delete api.defaults.headers.common['Authorization'];\n      },\n      \n      // Update user\n      updateUser: (userData) => {\n        set({ user: { ...get().user, ...userData } });\n      }\n    }),\n    {\n      name: 'auth-storage',\n      partialize: (state) => ({ token: state.token })\n    }\n  )\n);\n\n// Initialize auth on app start\nuseAuthStore.getState().initialize();\n",[1072,2485,2486,2491,2512,2534,2552,2556,2575,2582,2607,2620,2631,2642,2646,2651,2668,2692,2705,2712,2745,2782,2799,2835,2840,2850,2871,2876,2881,2885,2890,2910,2917,2954,2978,2984,3004,3059,3063,3080,3094,3103,3116,3153,3158,3162,3166,3171,3177,3193,3200,3225,3240,3246,3251,3257,3287,3319,3324,3329,3335,3354,3395,3400,3410,3416,3433,3469,3474,3480,3487,3492,3498],{"__ignoreMap":1070},[1075,2487,2488],{"class":1077,"line":1078},[1075,2489,2490],{"class":1081},"// frontend/js/store/authStore.js\n",[1075,2492,2493,2495,2497,2500,2502,2504,2506,2508,2510],{"class":1077,"line":1085},[1075,2494,1573],{"class":1572},[1075,2496,1576],{"class":1088},[1075,2498,2499],{"class":1579}," create",[1075,2501,1583],{"class":1088},[1075,2503,1586],{"class":1572},[1075,2505,1589],{"class":1109},[1075,2507,1372],{"class":1113},[1075,2509,1594],{"class":1109},[1075,2511,1597],{"class":1088},[1075,2513,2514,2516,2518,2521,2523,2525,2527,2530,2532],{"class":1077,"line":1092},[1075,2515,1573],{"class":1572},[1075,2517,1576],{"class":1088},[1075,2519,2520],{"class":1579}," persist",[1075,2522,1583],{"class":1088},[1075,2524,1586],{"class":1572},[1075,2526,1589],{"class":1109},[1075,2528,2529],{"class":1113},"zustand/middleware",[1075,2531,1594],{"class":1109},[1075,2533,1597],{"class":1088},[1075,2535,2536,2538,2541,2543,2545,2548,2550],{"class":1077,"line":1122},[1075,2537,1573],{"class":1572},[1075,2539,2540],{"class":1579}," api",[1075,2542,1586],{"class":1572},[1075,2544,1589],{"class":1109},[1075,2546,2547],{"class":1113},"@utils/api",[1075,2549,1594],{"class":1109},[1075,2551,1597],{"class":1088},[1075,2553,2554],{"class":1077,"line":1143},[1075,2555,1642],{"emptyLinePlaceholder":1641},[1075,2557,2558,2560,2564,2567,2570,2572],{"class":1077,"line":1164},[1075,2559,1647],{"class":1572},[1075,2561,2563],{"class":2562},"s5Kfy"," const",[1075,2565,2566],{"class":1579}," useAuthStore",[1075,2568,2569],{"class":1088}," =",[1075,2571,2499],{"class":1653},[1075,2573,2574],{"class":1656},"(\n",[1075,2576,2577,2580],{"class":1077,"line":1179},[1075,2578,2579],{"class":1653},"  persist",[1075,2581,2574],{"class":1656},[1075,2583,2584,2587,2591,2593,2596,2598,2602,2605],{"class":1077,"line":1202},[1075,2585,2586],{"class":1088},"    (",[1075,2588,2590],{"class":2589},"sqOPj","set",[1075,2592,1756],{"class":1088},[1075,2594,2595],{"class":2589}," get",[1075,2597,1766],{"class":1088},[1075,2599,2601],{"class":2600},"sIOqK"," =>",[1075,2603,2604],{"class":1656}," (",[1075,2606,1089],{"class":1088},[1075,2608,2609,2612,2614,2618],{"class":1077,"line":1223},[1075,2610,2611],{"class":1664},"      user",[1075,2613,1106],{"class":1088},[1075,2615,2617],{"class":2616},"sVsLi"," null",[1075,2619,1119],{"class":1088},[1075,2621,2622,2625,2627,2629],{"class":1077,"line":1243},[1075,2623,2624],{"class":1664},"      token",[1075,2626,1106],{"class":1088},[1075,2628,2617],{"class":2616},[1075,2630,1119],{"class":1088},[1075,2632,2633,2636,2638,2640],{"class":1077,"line":1249},[1075,2634,2635],{"class":1664},"      loading",[1075,2637,1106],{"class":1088},[1075,2639,1719],{"class":1718},[1075,2641,1119],{"class":1088},[1075,2643,2644],{"class":1077,"line":1263},[1075,2645,2367],{"class":1682},[1075,2647,2648],{"class":1077,"line":1284},[1075,2649,2650],{"class":1081},"      // Initialize auth state\n",[1075,2652,2653,2656,2658,2661,2664,2666],{"class":1077,"line":1304},[1075,2654,2655],{"class":1653},"      initialize",[1075,2657,1106],{"class":1088},[1075,2659,2660],{"class":2562}," async",[1075,2662,2663],{"class":1088}," ()",[1075,2665,2601],{"class":2600},[1075,2667,1176],{"class":1088},[1075,2669,2670,2673,2676,2678,2680,2684,2687,2690],{"class":1077,"line":1325},[1075,2671,2672],{"class":2562},"        const",[1075,2674,2675],{"class":1579}," token",[1075,2677,2569],{"class":1088},[1075,2679,2595],{"class":1653},[1075,2681,2683],{"class":2682},"sLdnO","()",[1075,2685,2686],{"class":1088},".",[1075,2688,2689],{"class":1579},"token",[1075,2691,1597],{"class":1088},[1075,2693,2694,2697,2699,2701,2703],{"class":1077,"line":1346},[1075,2695,2696],{"class":1572},"        if",[1075,2698,2604],{"class":2682},[1075,2700,2689],{"class":1579},[1075,2702,1766],{"class":2682},[1075,2704,1176],{"class":1088},[1075,2706,2707,2710],{"class":1077,"line":1367},[1075,2708,2709],{"class":1572},"          try",[1075,2711,1176],{"class":1088},[1075,2713,2714,2717,2720,2722,2725,2727,2729,2732,2734,2736,2739,2741,2743],{"class":1077,"line":1386},[1075,2715,2716],{"class":2562},"            const",[1075,2718,2719],{"class":1579}," user",[1075,2721,2569],{"class":1088},[1075,2723,2724],{"class":1572}," await",[1075,2726,2540],{"class":1579},[1075,2728,2686],{"class":1088},[1075,2730,2731],{"class":1653},"get",[1075,2733,1657],{"class":2682},[1075,2735,1594],{"class":1109},[1075,2737,2738],{"class":1113},"/auth/user/",[1075,2740,1594],{"class":1109},[1075,2742,1766],{"class":2682},[1075,2744,1597],{"class":1088},[1075,2746,2747,2750,2752,2755,2757,2759,2761,2763,2766,2768,2771,2773,2776,2778,2780],{"class":1077,"line":1391},[1075,2748,2749],{"class":1653},"            set",[1075,2751,1657],{"class":2682},[1075,2753,2754],{"class":1088},"{",[1075,2756,2719],{"class":1664},[1075,2758,1106],{"class":1088},[1075,2760,2719],{"class":1579},[1075,2762,2686],{"class":1088},[1075,2764,2765],{"class":1579},"data",[1075,2767,1756],{"class":1088},[1075,2769,2770],{"class":1664}," loading",[1075,2772,1106],{"class":1088},[1075,2774,2775],{"class":1718}," false",[1075,2777,1583],{"class":1088},[1075,2779,1766],{"class":2682},[1075,2781,1597],{"class":1088},[1075,2783,2784,2787,2790,2792,2795,2797],{"class":1077,"line":1405},[1075,2785,2786],{"class":1088},"          }",[1075,2788,2789],{"class":1572}," catch",[1075,2791,2604],{"class":2682},[1075,2793,2794],{"class":1579},"error",[1075,2796,1766],{"class":2682},[1075,2798,1176],{"class":1088},[1075,2800,2801,2803,2805,2807,2809,2811,2813,2815,2817,2819,2821,2823,2825,2827,2829,2831,2833],{"class":1077,"line":1425},[1075,2802,2749],{"class":1653},[1075,2804,1657],{"class":2682},[1075,2806,2754],{"class":1088},[1075,2808,2719],{"class":1664},[1075,2810,1106],{"class":1088},[1075,2812,2617],{"class":2616},[1075,2814,1756],{"class":1088},[1075,2816,2675],{"class":1664},[1075,2818,1106],{"class":1088},[1075,2820,2617],{"class":2616},[1075,2822,1756],{"class":1088},[1075,2824,2770],{"class":1664},[1075,2826,1106],{"class":1088},[1075,2828,2775],{"class":1718},[1075,2830,1583],{"class":1088},[1075,2832,1766],{"class":2682},[1075,2834,1597],{"class":1088},[1075,2836,2837],{"class":1077,"line":1445},[1075,2838,2839],{"class":1088},"          }\n",[1075,2841,2842,2845,2848],{"class":1077,"line":1466},[1075,2843,2844],{"class":1088},"        }",[1075,2846,2847],{"class":1572}," else",[1075,2849,1176],{"class":1088},[1075,2851,2852,2855,2857,2859,2861,2863,2865,2867,2869],{"class":1077,"line":1485},[1075,2853,2854],{"class":1653},"          set",[1075,2856,1657],{"class":2682},[1075,2858,2754],{"class":1088},[1075,2860,2770],{"class":1664},[1075,2862,1106],{"class":1088},[1075,2864,2775],{"class":1718},[1075,2866,1583],{"class":1088},[1075,2868,1766],{"class":2682},[1075,2870,1597],{"class":1088},[1075,2872,2873],{"class":1077,"line":1506},[1075,2874,2875],{"class":1088},"        }\n",[1075,2877,2878],{"class":1077,"line":1527},[1075,2879,2880],{"class":1088},"      },\n",[1075,2882,2883],{"class":1077,"line":1546},[1075,2884,2367],{"class":1682},[1075,2886,2887],{"class":1077,"line":1552},[1075,2888,2889],{"class":1081},"      // Login\n",[1075,2891,2892,2895,2897,2899,2901,2904,2906,2908],{"class":1077,"line":1906},[1075,2893,2894],{"class":1653},"      login",[1075,2896,1106],{"class":1088},[1075,2898,2660],{"class":2562},[1075,2900,2604],{"class":1088},[1075,2902,2903],{"class":2589},"credentials",[1075,2905,1766],{"class":1088},[1075,2907,2601],{"class":2600},[1075,2909,1176],{"class":1088},[1075,2911,2912,2915],{"class":1077,"line":1916},[1075,2913,2914],{"class":1572},"        try",[1075,2916,1176],{"class":1088},[1075,2918,2919,2922,2925,2927,2929,2931,2933,2936,2938,2940,2943,2945,2947,2950,2952],{"class":1077,"line":1947},[1075,2920,2921],{"class":2562},"          const",[1075,2923,2924],{"class":1579}," response",[1075,2926,2569],{"class":1088},[1075,2928,2724],{"class":1572},[1075,2930,2540],{"class":1579},[1075,2932,2686],{"class":1088},[1075,2934,2935],{"class":1653},"post",[1075,2937,1657],{"class":2682},[1075,2939,1594],{"class":1109},[1075,2941,2942],{"class":1113},"/auth/login/",[1075,2944,1594],{"class":1109},[1075,2946,1756],{"class":1088},[1075,2948,2949],{"class":1579}," credentials",[1075,2951,1766],{"class":2682},[1075,2953,1597],{"class":1088},[1075,2955,2956,2958,2960,2962,2964,2966,2968,2970,2972,2974,2976],{"class":1077,"line":1978},[1075,2957,2921],{"class":2562},[1075,2959,1576],{"class":1088},[1075,2961,2719],{"class":1579},[1075,2963,1756],{"class":1088},[1075,2965,2675],{"class":1579},[1075,2967,1583],{"class":1088},[1075,2969,2569],{"class":1088},[1075,2971,2924],{"class":1579},[1075,2973,2686],{"class":1088},[1075,2975,2765],{"class":1579},[1075,2977,1597],{"class":1088},[1075,2979,2980],{"class":1077,"line":2009},[1075,2981,2983],{"class":2982},"sBPpx","          \n",[1075,2985,2986,2988,2990,2992,2994,2996,2998,3000,3002],{"class":1077,"line":2040},[1075,2987,2854],{"class":1653},[1075,2989,1657],{"class":2682},[1075,2991,2754],{"class":1088},[1075,2993,2719],{"class":1579},[1075,2995,1756],{"class":1088},[1075,2997,2675],{"class":1579},[1075,2999,1583],{"class":1088},[1075,3001,1766],{"class":2682},[1075,3003,1597],{"class":1088},[1075,3005,3006,3009,3011,3014,3016,3019,3021,3024,3027,3029,3032,3034,3037,3039,3042,3045,3049,3052,3054,3057],{"class":1077,"line":2069},[1075,3007,3008],{"class":1579},"          api",[1075,3010,2686],{"class":1088},[1075,3012,3013],{"class":1579},"defaults",[1075,3015,2686],{"class":1088},[1075,3017,3018],{"class":1579},"headers",[1075,3020,2686],{"class":1088},[1075,3022,3023],{"class":1579},"common",[1075,3025,3026],{"class":2682},"[",[1075,3028,1594],{"class":1109},[1075,3030,3031],{"class":1113},"Authorization",[1075,3033,1594],{"class":1109},[1075,3035,3036],{"class":2682},"]",[1075,3038,2569],{"class":1088},[1075,3040,3041],{"class":1109}," `",[1075,3043,3044],{"class":1113},"Bearer ",[1075,3046,3048],{"class":3047},"s8XtY","${",[1075,3050,2689],{"class":3051},"su_V2",[1075,3053,2082],{"class":3047},[1075,3055,3056],{"class":1109},"`",[1075,3058,1597],{"class":1088},[1075,3060,3061],{"class":1077,"line":2074},[1075,3062,2983],{"class":2982},[1075,3064,3065,3068,3070,3073,3075,3077],{"class":1077,"line":2079},[1075,3066,3067],{"class":1572},"          return",[1075,3069,1576],{"class":1088},[1075,3071,3072],{"class":1664}," success",[1075,3074,1106],{"class":1088},[1075,3076,1719],{"class":1718},[1075,3078,3079],{"class":1088}," };\n",[1075,3081,3082,3084,3086,3088,3090,3092],{"class":1077,"line":2440},[1075,3083,2844],{"class":1088},[1075,3085,2789],{"class":1572},[1075,3087,2604],{"class":2682},[1075,3089,2794],{"class":1579},[1075,3091,1766],{"class":2682},[1075,3093,1176],{"class":1088},[1075,3095,3096,3098,3100],{"class":1077,"line":2446},[1075,3097,3067],{"class":1572},[1075,3099,1576],{"class":1088},[1075,3101,3102],{"class":2982}," \n",[1075,3104,3105,3108,3110,3112,3114],{"class":1077,"line":2452},[1075,3106,3107],{"class":1664},"            success",[1075,3109,1106],{"class":1088},[1075,3111,2775],{"class":1718},[1075,3113,1756],{"class":1088},[1075,3115,3102],{"class":2982},[1075,3117,3118,3121,3123,3126,3128,3131,3134,3136,3138,3141,3144,3146,3149,3151],{"class":1077,"line":2458},[1075,3119,3120],{"class":1664},"            error",[1075,3122,1106],{"class":1088},[1075,3124,3125],{"class":1579}," error",[1075,3127,2686],{"class":1088},[1075,3129,3130],{"class":1579},"response",[1075,3132,3133],{"class":1088},"?.",[1075,3135,2765],{"class":1579},[1075,3137,3133],{"class":1088},[1075,3139,3140],{"class":1579},"message",[1075,3142,3143],{"class":2616}," ||",[1075,3145,1589],{"class":1109},[1075,3147,3148],{"class":1113},"Login failed",[1075,3150,1594],{"class":1109},[1075,3152,3102],{"class":2982},[1075,3154,3155],{"class":1077,"line":2463},[1075,3156,3157],{"class":1088},"          };\n",[1075,3159,3160],{"class":1077,"line":2468},[1075,3161,2875],{"class":1088},[1075,3163,3164],{"class":1077,"line":2473},[1075,3165,2880],{"class":1088},[1075,3167,3169],{"class":1077,"line":3168},45,[1075,3170,2367],{"class":1682},[1075,3172,3174],{"class":1077,"line":3173},46,[1075,3175,3176],{"class":1081},"      // Logout\n",[1075,3178,3180,3183,3185,3187,3189,3191],{"class":1077,"line":3179},47,[1075,3181,3182],{"class":1653},"      logout",[1075,3184,1106],{"class":1088},[1075,3186,2660],{"class":2562},[1075,3188,2663],{"class":1088},[1075,3190,2601],{"class":2600},[1075,3192,1176],{"class":1088},[1075,3194,3196,3198],{"class":1077,"line":3195},48,[1075,3197,2914],{"class":1572},[1075,3199,1176],{"class":1088},[1075,3201,3203,3206,3208,3210,3212,3214,3216,3219,3221,3223],{"class":1077,"line":3202},49,[1075,3204,3205],{"class":1572},"          await",[1075,3207,2540],{"class":1579},[1075,3209,2686],{"class":1088},[1075,3211,2935],{"class":1653},[1075,3213,1657],{"class":2682},[1075,3215,1594],{"class":1109},[1075,3217,3218],{"class":1113},"/auth/logout/",[1075,3220,1594],{"class":1109},[1075,3222,1766],{"class":2682},[1075,3224,1597],{"class":1088},[1075,3226,3228,3230,3232,3234,3236,3238],{"class":1077,"line":3227},50,[1075,3229,2844],{"class":1088},[1075,3231,2789],{"class":1572},[1075,3233,2604],{"class":2682},[1075,3235,2794],{"class":1579},[1075,3237,1766],{"class":2682},[1075,3239,1176],{"class":1088},[1075,3241,3243],{"class":1077,"line":3242},51,[1075,3244,3245],{"class":1081},"          // Continue with logout even if API call fails\n",[1075,3247,3249],{"class":1077,"line":3248},52,[1075,3250,2875],{"class":1088},[1075,3252,3254],{"class":1077,"line":3253},53,[1075,3255,3256],{"class":2982},"        \n",[1075,3258,3260,3263,3265,3267,3269,3271,3273,3275,3277,3279,3281,3283,3285],{"class":1077,"line":3259},54,[1075,3261,3262],{"class":1653},"        set",[1075,3264,1657],{"class":2682},[1075,3266,2754],{"class":1088},[1075,3268,2719],{"class":1664},[1075,3270,1106],{"class":1088},[1075,3272,2617],{"class":2616},[1075,3274,1756],{"class":1088},[1075,3276,2675],{"class":1664},[1075,3278,1106],{"class":1088},[1075,3280,2617],{"class":2616},[1075,3282,1583],{"class":1088},[1075,3284,1766],{"class":2682},[1075,3286,1597],{"class":1088},[1075,3288,3290,3293,3295,3297,3299,3301,3303,3305,3307,3309,3311,3313,3315,3317],{"class":1077,"line":3289},55,[1075,3291,3292],{"class":2616},"        delete",[1075,3294,2540],{"class":1579},[1075,3296,2686],{"class":1088},[1075,3298,3013],{"class":1579},[1075,3300,2686],{"class":1088},[1075,3302,3018],{"class":1579},[1075,3304,2686],{"class":1088},[1075,3306,3023],{"class":1579},[1075,3308,3026],{"class":2682},[1075,3310,1594],{"class":1109},[1075,3312,3031],{"class":1113},[1075,3314,1594],{"class":1109},[1075,3316,3036],{"class":2682},[1075,3318,1597],{"class":1088},[1075,3320,3322],{"class":1077,"line":3321},56,[1075,3323,2880],{"class":1088},[1075,3325,3327],{"class":1077,"line":3326},57,[1075,3328,2367],{"class":1682},[1075,3330,3332],{"class":1077,"line":3331},58,[1075,3333,3334],{"class":1081},"      // Update user\n",[1075,3336,3338,3341,3343,3345,3348,3350,3352],{"class":1077,"line":3337},59,[1075,3339,3340],{"class":1653},"      updateUser",[1075,3342,1106],{"class":1088},[1075,3344,2604],{"class":1088},[1075,3346,3347],{"class":2589},"userData",[1075,3349,1766],{"class":1088},[1075,3351,2601],{"class":2600},[1075,3353,1176],{"class":1088},[1075,3355,3357,3359,3361,3363,3365,3367,3369,3372,3374,3376,3378,3381,3383,3385,3387,3389,3391,3393],{"class":1077,"line":3356},60,[1075,3358,3262],{"class":1653},[1075,3360,1657],{"class":2682},[1075,3362,2754],{"class":1088},[1075,3364,2719],{"class":1664},[1075,3366,1106],{"class":1088},[1075,3368,1576],{"class":1088},[1075,3370,3371],{"class":1088}," ...",[1075,3373,2731],{"class":1653},[1075,3375,2683],{"class":2682},[1075,3377,2686],{"class":1088},[1075,3379,3380],{"class":1579},"user",[1075,3382,1756],{"class":1088},[1075,3384,3371],{"class":1088},[1075,3386,3347],{"class":1579},[1075,3388,1583],{"class":1088},[1075,3390,1583],{"class":1088},[1075,3392,1766],{"class":2682},[1075,3394,1597],{"class":1088},[1075,3396,3398],{"class":1077,"line":3397},61,[1075,3399,1798],{"class":1088},[1075,3401,3403,3406,3408],{"class":1077,"line":3402},62,[1075,3404,3405],{"class":1088},"    }",[1075,3407,1766],{"class":1656},[1075,3409,1119],{"class":1088},[1075,3411,3413],{"class":1077,"line":3412},63,[1075,3414,3415],{"class":1088},"    {\n",[1075,3417,3419,3422,3424,3426,3429,3431],{"class":1077,"line":3418},64,[1075,3420,3421],{"class":1664},"      name",[1075,3423,1106],{"class":1088},[1075,3425,1589],{"class":1109},[1075,3427,3428],{"class":1113},"auth-storage",[1075,3430,1594],{"class":1109},[1075,3432,1119],{"class":1088},[1075,3434,3436,3439,3441,3443,3446,3448,3450,3452,3454,3456,3458,3461,3463,3465,3467],{"class":1077,"line":3435},65,[1075,3437,3438],{"class":1653},"      partialize",[1075,3440,1106],{"class":1088},[1075,3442,2604],{"class":1088},[1075,3444,3445],{"class":2589},"state",[1075,3447,1766],{"class":1088},[1075,3449,2601],{"class":2600},[1075,3451,2604],{"class":1656},[1075,3453,2754],{"class":1088},[1075,3455,2675],{"class":1664},[1075,3457,1106],{"class":1088},[1075,3459,3460],{"class":1579}," state",[1075,3462,2686],{"class":1088},[1075,3464,2689],{"class":1579},[1075,3466,1583],{"class":1088},[1075,3468,1793],{"class":1656},[1075,3470,3472],{"class":1077,"line":3471},66,[1075,3473,1803],{"class":1088},[1075,3475,3477],{"class":1077,"line":3476},67,[1075,3478,3479],{"class":1656},"  )\n",[1075,3481,3483,3485],{"class":1077,"line":3482},68,[1075,3484,1766],{"class":1656},[1075,3486,1597],{"class":1088},[1075,3488,3490],{"class":1077,"line":3489},69,[1075,3491,1642],{"emptyLinePlaceholder":1641},[1075,3493,3495],{"class":1077,"line":3494},70,[1075,3496,3497],{"class":1081},"// Initialize auth on app start\n",[1075,3499,3501,3504,3506,3509,3511,3513,3516,3518],{"class":1077,"line":3500},71,[1075,3502,3503],{"class":1579},"useAuthStore",[1075,3505,2686],{"class":1088},[1075,3507,3508],{"class":1653},"getState",[1075,3510,2683],{"class":1656},[1075,3512,2686],{"class":1088},[1075,3514,3515],{"class":1653},"initialize",[1075,3517,2683],{"class":1656},[1075,3519,1597],{"class":1088},[1065,3521,3523],{"className":2093,"code":3522,"language":2095,"meta":1070,"style":1070},"// frontend/js/components/auth/Login.jsx\nimport React, { useState } from 'react';\nimport { Navigate, useLocation } from 'react-router-dom';\nimport { useAuthStore } from '@store/authStore';\n\nfunction Login() {\n  const [credentials, setCredentials] = useState({ username: '', password: '' });\n  const [error, setError] = useState('');\n  const [loading, setLoading] = useState(false);\n  \n  const { user, login } = useAuthStore();\n  const location = useLocation();\n  \n  // Redirect if already logged in\n  if (user) {\n    const from = location.state?.from?.pathname || '/dashboard';\n    return \u003CNavigate to={from} replace />;\n  }\n  \n  const handleSubmit = async (e) => {\n    e.preventDefault();\n    setLoading(true);\n    setError('');\n    \n    const result = await login(credentials);\n    \n    if (result.success) {\n      const from = location.state?.from?.pathname || '/dashboard';\n      window.location.href = from; // Full page redirect\n    } else {\n      setError(result.error);\n    }\n    \n    setLoading(false);\n  };\n  \n  return (\n    \u003Cdiv className=\"login-container\">\n      \u003Cform onSubmit={handleSubmit} className=\"login-form\">\n        \u003Ch2>Login\u003C/h2>\n        \n        {error && \u003Cdiv className=\"error-message\">{error}\u003C/div>}\n        \n        \u003Cdiv className=\"form-group\">\n          \u003Clabel htmlFor=\"username\">Username:\u003C/label>\n          \u003Cinput\n            type=\"text\"\n            id=\"username\"\n            value={credentials.username}\n            onChange={(e) => setCredentials(prev => ({\n              ...prev,\n              username: e.target.value\n            }))}\n            required\n          />\n        \u003C/div>\n        \n        \u003Cdiv className=\"form-group\">\n          \u003Clabel htmlFor=\"password\">Password:\u003C/label>\n          \u003Cinput\n            type=\"password\"\n            id=\"password\"\n            value={credentials.password}\n            onChange={(e) => setCredentials(prev => ({\n              ...prev,\n              password: e.target.value\n            }))}\n            required\n          />\n        \u003C/div>\n        \n        \u003Cbutton type=\"submit\" disabled={loading}>\n          {loading ? 'Logging in...' : 'Login'}\n        \u003C/button>\n      \u003C/form>\n    \u003C/div>\n  );\n}\n\nexport default Login;\n",[1072,3524,3525,3530,3535,3540,3544,3548,3553,3558,3563,3568,3572,3577,3582,3586,3591,3596,3601,3606,3610,3614,3619,3624,3629,3634,3639,3644,3648,3653,3658,3663,3668,3673,3677,3681,3686,3691,3695,3699,3704,3709,3714,3718,3723,3727,3732,3737,3742,3747,3752,3757,3762,3767,3772,3777,3782,3786,3791,3795,3799,3804,3808,3813,3818,3823,3827,3831,3836,3840,3844,3848,3852,3856,3862,3868,3874,3880,3885,3890,3895,3900],{"__ignoreMap":1070},[1075,3526,3527],{"class":1077,"line":1078},[1075,3528,3529],{},"// frontend/js/components/auth/Login.jsx\n",[1075,3531,3532],{"class":1077,"line":1085},[1075,3533,3534],{},"import React, { useState } from 'react';\n",[1075,3536,3537],{"class":1077,"line":1092},[1075,3538,3539],{},"import { Navigate, useLocation } from 'react-router-dom';\n",[1075,3541,3542],{"class":1077,"line":1122},[1075,3543,2276],{},[1075,3545,3546],{"class":1077,"line":1143},[1075,3547,1642],{"emptyLinePlaceholder":1641},[1075,3549,3550],{"class":1077,"line":1164},[1075,3551,3552],{},"function Login() {\n",[1075,3554,3555],{"class":1077,"line":1179},[1075,3556,3557],{},"  const [credentials, setCredentials] = useState({ username: '', password: '' });\n",[1075,3559,3560],{"class":1077,"line":1202},[1075,3561,3562],{},"  const [error, setError] = useState('');\n",[1075,3564,3565],{"class":1077,"line":1223},[1075,3566,3567],{},"  const [loading, setLoading] = useState(false);\n",[1075,3569,3570],{"class":1077,"line":1243},[1075,3571,1683],{},[1075,3573,3574],{"class":1077,"line":1249},[1075,3575,3576],{},"  const { user, login } = useAuthStore();\n",[1075,3578,3579],{"class":1077,"line":1263},[1075,3580,3581],{},"  const location = useLocation();\n",[1075,3583,3584],{"class":1077,"line":1284},[1075,3585,1683],{},[1075,3587,3588],{"class":1077,"line":1304},[1075,3589,3590],{},"  // Redirect if already logged in\n",[1075,3592,3593],{"class":1077,"line":1325},[1075,3594,3595],{},"  if (user) {\n",[1075,3597,3598],{"class":1077,"line":1346},[1075,3599,3600],{},"    const from = location.state?.from?.pathname || '/dashboard';\n",[1075,3602,3603],{"class":1077,"line":1367},[1075,3604,3605],{},"    return \u003CNavigate to={from} replace />;\n",[1075,3607,3608],{"class":1077,"line":1386},[1075,3609,1549],{},[1075,3611,3612],{"class":1077,"line":1391},[1075,3613,1683],{},[1075,3615,3616],{"class":1077,"line":1405},[1075,3617,3618],{},"  const handleSubmit = async (e) => {\n",[1075,3620,3621],{"class":1077,"line":1425},[1075,3622,3623],{},"    e.preventDefault();\n",[1075,3625,3626],{"class":1077,"line":1445},[1075,3627,3628],{},"    setLoading(true);\n",[1075,3630,3631],{"class":1077,"line":1466},[1075,3632,3633],{},"    setError('');\n",[1075,3635,3636],{"class":1077,"line":1485},[1075,3637,3638],{},"    \n",[1075,3640,3641],{"class":1077,"line":1506},[1075,3642,3643],{},"    const result = await login(credentials);\n",[1075,3645,3646],{"class":1077,"line":1527},[1075,3647,3638],{},[1075,3649,3650],{"class":1077,"line":1546},[1075,3651,3652],{},"    if (result.success) {\n",[1075,3654,3655],{"class":1077,"line":1552},[1075,3656,3657],{},"      const from = location.state?.from?.pathname || '/dashboard';\n",[1075,3659,3660],{"class":1077,"line":1906},[1075,3661,3662],{},"      window.location.href = from; // Full page redirect\n",[1075,3664,3665],{"class":1077,"line":1916},[1075,3666,3667],{},"    } else {\n",[1075,3669,3670],{"class":1077,"line":1947},[1075,3671,3672],{},"      setError(result.error);\n",[1075,3674,3675],{"class":1077,"line":1978},[1075,3676,1803],{},[1075,3678,3679],{"class":1077,"line":2009},[1075,3680,3638],{},[1075,3682,3683],{"class":1077,"line":2040},[1075,3684,3685],{},"    setLoading(false);\n",[1075,3687,3688],{"class":1077,"line":2069},[1075,3689,3690],{},"  };\n",[1075,3692,3693],{"class":1077,"line":2074},[1075,3694,1683],{},[1075,3696,3697],{"class":1077,"line":2079},[1075,3698,2352],{},[1075,3700,3701],{"class":1077,"line":2440},[1075,3702,3703],{},"    \u003Cdiv className=\"login-container\">\n",[1075,3705,3706],{"class":1077,"line":2446},[1075,3707,3708],{},"      \u003Cform onSubmit={handleSubmit} className=\"login-form\">\n",[1075,3710,3711],{"class":1077,"line":2452},[1075,3712,3713],{},"        \u003Ch2>Login\u003C/h2>\n",[1075,3715,3716],{"class":1077,"line":2458},[1075,3717,3256],{},[1075,3719,3720],{"class":1077,"line":2463},[1075,3721,3722],{},"        {error && \u003Cdiv className=\"error-message\">{error}\u003C/div>}\n",[1075,3724,3725],{"class":1077,"line":2468},[1075,3726,3256],{},[1075,3728,3729],{"class":1077,"line":2473},[1075,3730,3731],{},"        \u003Cdiv className=\"form-group\">\n",[1075,3733,3734],{"class":1077,"line":3168},[1075,3735,3736],{},"          \u003Clabel htmlFor=\"username\">Username:\u003C/label>\n",[1075,3738,3739],{"class":1077,"line":3173},[1075,3740,3741],{},"          \u003Cinput\n",[1075,3743,3744],{"class":1077,"line":3179},[1075,3745,3746],{},"            type=\"text\"\n",[1075,3748,3749],{"class":1077,"line":3195},[1075,3750,3751],{},"            id=\"username\"\n",[1075,3753,3754],{"class":1077,"line":3202},[1075,3755,3756],{},"            value={credentials.username}\n",[1075,3758,3759],{"class":1077,"line":3227},[1075,3760,3761],{},"            onChange={(e) => setCredentials(prev => ({\n",[1075,3763,3764],{"class":1077,"line":3242},[1075,3765,3766],{},"              ...prev,\n",[1075,3768,3769],{"class":1077,"line":3248},[1075,3770,3771],{},"              username: e.target.value\n",[1075,3773,3774],{"class":1077,"line":3253},[1075,3775,3776],{},"            }))}\n",[1075,3778,3779],{"class":1077,"line":3259},[1075,3780,3781],{},"            required\n",[1075,3783,3784],{"class":1077,"line":3289},[1075,3785,2437],{},[1075,3787,3788],{"class":1077,"line":3321},[1075,3789,3790],{},"        \u003C/div>\n",[1075,3792,3793],{"class":1077,"line":3326},[1075,3794,3256],{},[1075,3796,3797],{"class":1077,"line":3331},[1075,3798,3731],{},[1075,3800,3801],{"class":1077,"line":3337},[1075,3802,3803],{},"          \u003Clabel htmlFor=\"password\">Password:\u003C/label>\n",[1075,3805,3806],{"class":1077,"line":3356},[1075,3807,3741],{},[1075,3809,3810],{"class":1077,"line":3397},[1075,3811,3812],{},"            type=\"password\"\n",[1075,3814,3815],{"class":1077,"line":3402},[1075,3816,3817],{},"            id=\"password\"\n",[1075,3819,3820],{"class":1077,"line":3412},[1075,3821,3822],{},"            value={credentials.password}\n",[1075,3824,3825],{"class":1077,"line":3418},[1075,3826,3761],{},[1075,3828,3829],{"class":1077,"line":3435},[1075,3830,3766],{},[1075,3832,3833],{"class":1077,"line":3471},[1075,3834,3835],{},"              password: e.target.value\n",[1075,3837,3838],{"class":1077,"line":3476},[1075,3839,3776],{},[1075,3841,3842],{"class":1077,"line":3482},[1075,3843,3781],{},[1075,3845,3846],{"class":1077,"line":3489},[1075,3847,2437],{},[1075,3849,3850],{"class":1077,"line":3494},[1075,3851,3790],{},[1075,3853,3854],{"class":1077,"line":3500},[1075,3855,3256],{},[1075,3857,3859],{"class":1077,"line":3858},72,[1075,3860,3861],{},"        \u003Cbutton type=\"submit\" disabled={loading}>\n",[1075,3863,3865],{"class":1077,"line":3864},73,[1075,3866,3867],{},"          {loading ? 'Logging in...' : 'Login'}\n",[1075,3869,3871],{"class":1077,"line":3870},74,[1075,3872,3873],{},"        \u003C/button>\n",[1075,3875,3877],{"class":1077,"line":3876},75,[1075,3878,3879],{},"      \u003C/form>\n",[1075,3881,3883],{"class":1077,"line":3882},76,[1075,3884,2455],{},[1075,3886,3888],{"class":1077,"line":3887},77,[1075,3889,2248],{},[1075,3891,3893],{"class":1077,"line":3892},78,[1075,3894,1555],{},[1075,3896,3898],{"class":1077,"line":3897},79,[1075,3899,1642],{"emptyLinePlaceholder":1641},[1075,3901,3903],{"class":1077,"line":3902},80,[1075,3904,3905],{},"export default Login;\n",[1035,3907,3909],{"id":3908},"api-integration-with-react-query","API Integration with React Query",[1065,3911,3913],{"className":1558,"code":3912,"language":1560,"meta":1070,"style":1070},"// frontend/js/utils/api.js\nimport axios from 'axios';\n\n// Create axios instance\nconst api = axios.create({\n  baseURL: '/api',\n  headers: {\n    'Content-Type': 'application/json'\n  }\n});\n\n// Request interceptor for CSRF token\napi.interceptors.request.use((config) => {\n  const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]')?.value;\n  if (csrfToken) {\n    config.headers['X-CSRFToken'] = csrfToken;\n  }\n  return config;\n});\n\n// Response interceptor for error handling\napi.interceptors.response.use(\n  (response) => response,\n  (error) => {\n    if (error.response?.status === 401) {\n      // Handle unauthorized access\n      window.location.href = '/login';\n    }\n    return Promise.reject(error);\n  }\n);\n\nexport default api;\n",[1072,3914,3915,3920,3937,3941,3946,3966,3981,3990,4009,4013,4021,4025,4030,4063,4099,4113,4139,4143,4153,4161,4165,4170,4188,4203,4215,4243,4248,4274,4278,4299,4303,4309,4313],{"__ignoreMap":1070},[1075,3916,3917],{"class":1077,"line":1078},[1075,3918,3919],{"class":1081},"// frontend/js/utils/api.js\n",[1075,3921,3922,3924,3927,3929,3931,3933,3935],{"class":1077,"line":1085},[1075,3923,1573],{"class":1572},[1075,3925,3926],{"class":1579}," axios",[1075,3928,1586],{"class":1572},[1075,3930,1589],{"class":1109},[1075,3932,1330],{"class":1113},[1075,3934,1594],{"class":1109},[1075,3936,1597],{"class":1088},[1075,3938,3939],{"class":1077,"line":1092},[1075,3940,1642],{"emptyLinePlaceholder":1641},[1075,3942,3943],{"class":1077,"line":1122},[1075,3944,3945],{"class":1081},"// Create axios instance\n",[1075,3947,3948,3951,3953,3955,3957,3959,3962,3964],{"class":1077,"line":1143},[1075,3949,3950],{"class":2562},"const",[1075,3952,2540],{"class":1579},[1075,3954,2569],{"class":1088},[1075,3956,3926],{"class":1579},[1075,3958,2686],{"class":1088},[1075,3960,3961],{"class":1653},"create",[1075,3963,1657],{"class":1656},[1075,3965,1089],{"class":1088},[1075,3967,3968,3971,3973,3975,3977,3979],{"class":1077,"line":1164},[1075,3969,3970],{"class":1664},"  baseURL",[1075,3972,1106],{"class":1088},[1075,3974,1589],{"class":1109},[1075,3976,1851],{"class":1113},[1075,3978,1594],{"class":1109},[1075,3980,1119],{"class":1088},[1075,3982,3983,3986,3988],{"class":1077,"line":1179},[1075,3984,3985],{"class":1664},"  headers",[1075,3987,1106],{"class":1088},[1075,3989,1176],{"class":1088},[1075,3991,3992,3995,3998,4000,4002,4004,4007],{"class":1077,"line":1202},[1075,3993,3994],{"class":1109},"    '",[1075,3996,3997],{"class":1850},"Content-Type",[1075,3999,1594],{"class":1109},[1075,4001,1106],{"class":1088},[1075,4003,1589],{"class":1109},[1075,4005,4006],{"class":1113},"application/json",[1075,4008,1882],{"class":1109},[1075,4010,4011],{"class":1077,"line":1223},[1075,4012,1549],{"class":1088},[1075,4014,4015,4017,4019],{"class":1077,"line":1243},[1075,4016,2082],{"class":1088},[1075,4018,1766],{"class":1656},[1075,4020,1597],{"class":1088},[1075,4022,4023],{"class":1077,"line":1249},[1075,4024,1642],{"emptyLinePlaceholder":1641},[1075,4026,4027],{"class":1077,"line":1263},[1075,4028,4029],{"class":1081},"// Request interceptor for CSRF token\n",[1075,4031,4032,4035,4037,4040,4042,4045,4047,4050,4052,4054,4057,4059,4061],{"class":1077,"line":1284},[1075,4033,4034],{"class":1579},"api",[1075,4036,2686],{"class":1088},[1075,4038,4039],{"class":1579},"interceptors",[1075,4041,2686],{"class":1088},[1075,4043,4044],{"class":1579},"request",[1075,4046,2686],{"class":1088},[1075,4048,4049],{"class":1653},"use",[1075,4051,1657],{"class":1656},[1075,4053,1657],{"class":1088},[1075,4055,4056],{"class":2589},"config",[1075,4058,1766],{"class":1088},[1075,4060,2601],{"class":2600},[1075,4062,1176],{"class":1088},[1075,4064,4065,4068,4071,4073,4076,4078,4081,4083,4085,4088,4090,4092,4094,4097],{"class":1077,"line":1304},[1075,4066,4067],{"class":2562},"  const",[1075,4069,4070],{"class":1579}," csrfToken",[1075,4072,2569],{"class":1088},[1075,4074,4075],{"class":1579}," document",[1075,4077,2686],{"class":1088},[1075,4079,4080],{"class":1653},"querySelector",[1075,4082,1657],{"class":2682},[1075,4084,1594],{"class":1109},[1075,4086,4087],{"class":1113},"[name=csrfmiddlewaretoken]",[1075,4089,1594],{"class":1109},[1075,4091,1766],{"class":2682},[1075,4093,3133],{"class":1088},[1075,4095,4096],{"class":1579},"value",[1075,4098,1597],{"class":1088},[1075,4100,4101,4104,4106,4109,4111],{"class":1077,"line":1325},[1075,4102,4103],{"class":1572},"  if",[1075,4105,2604],{"class":2682},[1075,4107,4108],{"class":1579},"csrfToken",[1075,4110,1766],{"class":2682},[1075,4112,1176],{"class":1088},[1075,4114,4115,4118,4120,4122,4124,4126,4129,4131,4133,4135,4137],{"class":1077,"line":1346},[1075,4116,4117],{"class":1579},"    config",[1075,4119,2686],{"class":1088},[1075,4121,3018],{"class":1579},[1075,4123,3026],{"class":2682},[1075,4125,1594],{"class":1109},[1075,4127,4128],{"class":1113},"X-CSRFToken",[1075,4130,1594],{"class":1109},[1075,4132,3036],{"class":2682},[1075,4134,2569],{"class":1088},[1075,4136,4070],{"class":1579},[1075,4138,1597],{"class":1088},[1075,4140,4141],{"class":1077,"line":1367},[1075,4142,1549],{"class":1088},[1075,4144,4145,4148,4151],{"class":1077,"line":1386},[1075,4146,4147],{"class":1572},"  return",[1075,4149,4150],{"class":1579}," config",[1075,4152,1597],{"class":1088},[1075,4154,4155,4157,4159],{"class":1077,"line":1391},[1075,4156,2082],{"class":1088},[1075,4158,1766],{"class":1656},[1075,4160,1597],{"class":1088},[1075,4162,4163],{"class":1077,"line":1405},[1075,4164,1642],{"emptyLinePlaceholder":1641},[1075,4166,4167],{"class":1077,"line":1425},[1075,4168,4169],{"class":1081},"// Response interceptor for error handling\n",[1075,4171,4172,4174,4176,4178,4180,4182,4184,4186],{"class":1077,"line":1445},[1075,4173,4034],{"class":1579},[1075,4175,2686],{"class":1088},[1075,4177,4039],{"class":1579},[1075,4179,2686],{"class":1088},[1075,4181,3130],{"class":1579},[1075,4183,2686],{"class":1088},[1075,4185,4049],{"class":1653},[1075,4187,2574],{"class":1656},[1075,4189,4190,4193,4195,4197,4199,4201],{"class":1077,"line":1466},[1075,4191,4192],{"class":1088},"  (",[1075,4194,3130],{"class":2589},[1075,4196,1766],{"class":1088},[1075,4198,2601],{"class":2600},[1075,4200,2924],{"class":1579},[1075,4202,1119],{"class":1088},[1075,4204,4205,4207,4209,4211,4213],{"class":1077,"line":1485},[1075,4206,4192],{"class":1088},[1075,4208,2794],{"class":2589},[1075,4210,1766],{"class":1088},[1075,4212,2601],{"class":2600},[1075,4214,1176],{"class":1088},[1075,4216,4217,4220,4222,4224,4226,4228,4230,4233,4236,4239,4241],{"class":1077,"line":1506},[1075,4218,4219],{"class":1572},"    if",[1075,4221,2604],{"class":2682},[1075,4223,2794],{"class":1579},[1075,4225,2686],{"class":1088},[1075,4227,3130],{"class":1579},[1075,4229,3133],{"class":1088},[1075,4231,4232],{"class":1579},"status",[1075,4234,4235],{"class":2616}," ===",[1075,4237,4238],{"class":1830}," 401",[1075,4240,1766],{"class":2682},[1075,4242,1176],{"class":1088},[1075,4244,4245],{"class":1077,"line":1527},[1075,4246,4247],{"class":1081},"      // Handle unauthorized access\n",[1075,4249,4250,4253,4255,4258,4260,4263,4265,4267,4270,4272],{"class":1077,"line":1546},[1075,4251,4252],{"class":1579},"      window",[1075,4254,2686],{"class":1088},[1075,4256,4257],{"class":1579},"location",[1075,4259,2686],{"class":1088},[1075,4261,4262],{"class":1579},"href",[1075,4264,2569],{"class":1088},[1075,4266,1589],{"class":1109},[1075,4268,4269],{"class":1113},"/login",[1075,4271,1594],{"class":1109},[1075,4273,1597],{"class":1088},[1075,4275,4276],{"class":1077,"line":1552},[1075,4277,1803],{"class":1088},[1075,4279,4280,4283,4286,4288,4291,4293,4295,4297],{"class":1077,"line":1906},[1075,4281,4282],{"class":1572},"    return",[1075,4284,4285],{"class":1185}," Promise",[1075,4287,2686],{"class":1088},[1075,4289,4290],{"class":1653},"reject",[1075,4292,1657],{"class":2682},[1075,4294,2794],{"class":1579},[1075,4296,1766],{"class":2682},[1075,4298,1597],{"class":1088},[1075,4300,4301],{"class":1077,"line":1916},[1075,4302,1549],{"class":1088},[1075,4304,4305,4307],{"class":1077,"line":1947},[1075,4306,1766],{"class":1656},[1075,4308,1597],{"class":1088},[1075,4310,4311],{"class":1077,"line":1978},[1075,4312,1642],{"emptyLinePlaceholder":1641},[1075,4314,4315,4317,4319,4321],{"class":1077,"line":2009},[1075,4316,1647],{"class":1572},[1075,4318,1650],{"class":1572},[1075,4320,2540],{"class":1579},[1075,4322,1597],{"class":1088},[1065,4324,4326],{"className":1558,"code":4325,"language":1560,"meta":1070,"style":1070},"// frontend/js/hooks/useBlog.js\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\nimport api from '@utils/api';\n\nexport function useBlogPosts() {\n  return useQuery({\n    queryKey: ['blogPosts'],\n    queryFn: async () => {\n      const response = await api.get('/blog/posts/');\n      return response.data;\n    }\n  });\n}\n\nexport function useBlogPost(slug) {\n  return useQuery({\n    queryKey: ['blogPost', slug],\n    queryFn: async () => {\n      const response = await api.get(`/blog/posts/${slug}/`);\n      return response.data;\n    },\n    enabled: !!slug\n  });\n}\n\nexport function useCreateBlogPost() {\n  const queryClient = useQueryClient();\n  \n  return useMutation({\n    mutationFn: async (postData) => {\n      const response = await api.post('/blog/posts/', postData);\n      return response.data;\n    },\n    onSuccess: () => {\n      queryClient.invalidateQueries({ queryKey: ['blogPosts'] });\n    }\n  });\n}\n\nexport function useUpdateBlogPost() {\n  const queryClient = useQueryClient();\n  \n  return useMutation({\n    mutationFn: async ({ id, data }) => {\n      const response = await api.put(`/blog/posts/${id}/`, data);\n      return response.data;\n    },\n    onSuccess: (data) => {\n      queryClient.invalidateQueries({ queryKey: ['blogPosts'] });\n      queryClient.invalidateQueries({ queryKey: ['blogPost', data.slug] });\n    }\n  });\n}\n",[1072,4327,4328,4333,4364,4380,4384,4398,4408,4428,4443,4473,4486,4490,4499,4503,4507,4525,4535,4559,4573,4610,4622,4627,4640,4648,4652,4656,4669,4684,4688,4698,4718,4751,4763,4767,4780,4815,4819,4827,4831,4835,4848,4862,4866,4876,4902,4944,4956,4960,4976,5008,5048,5052,5060],{"__ignoreMap":1070},[1075,4329,4330],{"class":1077,"line":1078},[1075,4331,4332],{"class":1081},"// frontend/js/hooks/useBlog.js\n",[1075,4334,4335,4337,4339,4342,4344,4347,4349,4352,4354,4356,4358,4360,4362],{"class":1077,"line":1085},[1075,4336,1573],{"class":1572},[1075,4338,1576],{"class":1088},[1075,4340,4341],{"class":1579}," useQuery",[1075,4343,1756],{"class":1088},[1075,4345,4346],{"class":1579}," useMutation",[1075,4348,1756],{"class":1088},[1075,4350,4351],{"class":1579}," useQueryClient",[1075,4353,1583],{"class":1088},[1075,4355,1586],{"class":1572},[1075,4357,1589],{"class":1109},[1075,4359,1351],{"class":1113},[1075,4361,1594],{"class":1109},[1075,4363,1597],{"class":1088},[1075,4365,4366,4368,4370,4372,4374,4376,4378],{"class":1077,"line":1092},[1075,4367,1573],{"class":1572},[1075,4369,2540],{"class":1579},[1075,4371,1586],{"class":1572},[1075,4373,1589],{"class":1109},[1075,4375,2547],{"class":1113},[1075,4377,1594],{"class":1109},[1075,4379,1597],{"class":1088},[1075,4381,4382],{"class":1077,"line":1122},[1075,4383,1642],{"emptyLinePlaceholder":1641},[1075,4385,4386,4388,4391,4394,4396],{"class":1077,"line":1143},[1075,4387,1647],{"class":1572},[1075,4389,4390],{"class":2562}," function",[1075,4392,4393],{"class":1653}," useBlogPosts",[1075,4395,2683],{"class":1088},[1075,4397,1176],{"class":1088},[1075,4399,4400,4402,4404,4406],{"class":1077,"line":1164},[1075,4401,4147],{"class":1572},[1075,4403,4341],{"class":1653},[1075,4405,1657],{"class":2682},[1075,4407,1089],{"class":1088},[1075,4409,4410,4413,4415,4417,4419,4422,4424,4426],{"class":1077,"line":1179},[1075,4411,4412],{"class":1664},"    queryKey",[1075,4414,1106],{"class":1088},[1075,4416,1670],{"class":2682},[1075,4418,1594],{"class":1109},[1075,4420,4421],{"class":1113},"blogPosts",[1075,4423,1594],{"class":1109},[1075,4425,3036],{"class":2682},[1075,4427,1119],{"class":1088},[1075,4429,4430,4433,4435,4437,4439,4441],{"class":1077,"line":1202},[1075,4431,4432],{"class":1653},"    queryFn",[1075,4434,1106],{"class":1088},[1075,4436,2660],{"class":2562},[1075,4438,2663],{"class":1088},[1075,4440,2601],{"class":2600},[1075,4442,1176],{"class":1088},[1075,4444,4445,4448,4450,4452,4454,4456,4458,4460,4462,4464,4467,4469,4471],{"class":1077,"line":1223},[1075,4446,4447],{"class":2562},"      const",[1075,4449,2924],{"class":1579},[1075,4451,2569],{"class":1088},[1075,4453,2724],{"class":1572},[1075,4455,2540],{"class":1579},[1075,4457,2686],{"class":1088},[1075,4459,2731],{"class":1653},[1075,4461,1657],{"class":2682},[1075,4463,1594],{"class":1109},[1075,4465,4466],{"class":1113},"/blog/posts/",[1075,4468,1594],{"class":1109},[1075,4470,1766],{"class":2682},[1075,4472,1597],{"class":1088},[1075,4474,4475,4478,4480,4482,4484],{"class":1077,"line":1243},[1075,4476,4477],{"class":1572},"      return",[1075,4479,2924],{"class":1579},[1075,4481,2686],{"class":1088},[1075,4483,2765],{"class":1579},[1075,4485,1597],{"class":1088},[1075,4487,4488],{"class":1077,"line":1249},[1075,4489,1803],{"class":1088},[1075,4491,4492,4495,4497],{"class":1077,"line":1263},[1075,4493,4494],{"class":1088},"  }",[1075,4496,1766],{"class":2682},[1075,4498,1597],{"class":1088},[1075,4500,4501],{"class":1077,"line":1284},[1075,4502,1555],{"class":1088},[1075,4504,4505],{"class":1077,"line":1304},[1075,4506,1642],{"emptyLinePlaceholder":1641},[1075,4508,4509,4511,4513,4516,4518,4521,4523],{"class":1077,"line":1325},[1075,4510,1647],{"class":1572},[1075,4512,4390],{"class":2562},[1075,4514,4515],{"class":1653}," useBlogPost",[1075,4517,1657],{"class":1088},[1075,4519,4520],{"class":2589},"slug",[1075,4522,1766],{"class":1088},[1075,4524,1176],{"class":1088},[1075,4526,4527,4529,4531,4533],{"class":1077,"line":1346},[1075,4528,4147],{"class":1572},[1075,4530,4341],{"class":1653},[1075,4532,1657],{"class":2682},[1075,4534,1089],{"class":1088},[1075,4536,4537,4539,4541,4543,4545,4548,4550,4552,4555,4557],{"class":1077,"line":1367},[1075,4538,4412],{"class":1664},[1075,4540,1106],{"class":1088},[1075,4542,1670],{"class":2682},[1075,4544,1594],{"class":1109},[1075,4546,4547],{"class":1113},"blogPost",[1075,4549,1594],{"class":1109},[1075,4551,1756],{"class":1088},[1075,4553,4554],{"class":1579}," slug",[1075,4556,3036],{"class":2682},[1075,4558,1119],{"class":1088},[1075,4560,4561,4563,4565,4567,4569,4571],{"class":1077,"line":1386},[1075,4562,4432],{"class":1653},[1075,4564,1106],{"class":1088},[1075,4566,2660],{"class":2562},[1075,4568,2663],{"class":1088},[1075,4570,2601],{"class":2600},[1075,4572,1176],{"class":1088},[1075,4574,4575,4577,4579,4581,4583,4585,4587,4589,4591,4593,4595,4597,4599,4601,4604,4606,4608],{"class":1077,"line":1391},[1075,4576,4447],{"class":2562},[1075,4578,2924],{"class":1579},[1075,4580,2569],{"class":1088},[1075,4582,2724],{"class":1572},[1075,4584,2540],{"class":1579},[1075,4586,2686],{"class":1088},[1075,4588,2731],{"class":1653},[1075,4590,1657],{"class":2682},[1075,4592,3056],{"class":1109},[1075,4594,4466],{"class":1113},[1075,4596,3048],{"class":3047},[1075,4598,4520],{"class":3051},[1075,4600,2082],{"class":3047},[1075,4602,4603],{"class":1113},"/",[1075,4605,3056],{"class":1109},[1075,4607,1766],{"class":2682},[1075,4609,1597],{"class":1088},[1075,4611,4612,4614,4616,4618,4620],{"class":1077,"line":1405},[1075,4613,4477],{"class":1572},[1075,4615,2924],{"class":1579},[1075,4617,2686],{"class":1088},[1075,4619,2765],{"class":1579},[1075,4621,1597],{"class":1088},[1075,4623,4624],{"class":1077,"line":1425},[1075,4625,4626],{"class":1088},"    },\n",[1075,4628,4629,4632,4634,4637],{"class":1077,"line":1445},[1075,4630,4631],{"class":1664},"    enabled",[1075,4633,1106],{"class":1088},[1075,4635,4636],{"class":2616}," !!",[1075,4638,4639],{"class":1579},"slug\n",[1075,4641,4642,4644,4646],{"class":1077,"line":1466},[1075,4643,4494],{"class":1088},[1075,4645,1766],{"class":2682},[1075,4647,1597],{"class":1088},[1075,4649,4650],{"class":1077,"line":1485},[1075,4651,1555],{"class":1088},[1075,4653,4654],{"class":1077,"line":1506},[1075,4655,1642],{"emptyLinePlaceholder":1641},[1075,4657,4658,4660,4662,4665,4667],{"class":1077,"line":1527},[1075,4659,1647],{"class":1572},[1075,4661,4390],{"class":2562},[1075,4663,4664],{"class":1653}," useCreateBlogPost",[1075,4666,2683],{"class":1088},[1075,4668,1176],{"class":1088},[1075,4670,4671,4673,4676,4678,4680,4682],{"class":1077,"line":1546},[1075,4672,4067],{"class":2562},[1075,4674,4675],{"class":1579}," queryClient",[1075,4677,2569],{"class":1088},[1075,4679,4351],{"class":1653},[1075,4681,2683],{"class":2682},[1075,4683,1597],{"class":1088},[1075,4685,4686],{"class":1077,"line":1552},[1075,4687,1683],{"class":2982},[1075,4689,4690,4692,4694,4696],{"class":1077,"line":1906},[1075,4691,4147],{"class":1572},[1075,4693,4346],{"class":1653},[1075,4695,1657],{"class":2682},[1075,4697,1089],{"class":1088},[1075,4699,4700,4703,4705,4707,4709,4712,4714,4716],{"class":1077,"line":1916},[1075,4701,4702],{"class":1653},"    mutationFn",[1075,4704,1106],{"class":1088},[1075,4706,2660],{"class":2562},[1075,4708,2604],{"class":1088},[1075,4710,4711],{"class":2589},"postData",[1075,4713,1766],{"class":1088},[1075,4715,2601],{"class":2600},[1075,4717,1176],{"class":1088},[1075,4719,4720,4722,4724,4726,4728,4730,4732,4734,4736,4738,4740,4742,4744,4747,4749],{"class":1077,"line":1947},[1075,4721,4447],{"class":2562},[1075,4723,2924],{"class":1579},[1075,4725,2569],{"class":1088},[1075,4727,2724],{"class":1572},[1075,4729,2540],{"class":1579},[1075,4731,2686],{"class":1088},[1075,4733,2935],{"class":1653},[1075,4735,1657],{"class":2682},[1075,4737,1594],{"class":1109},[1075,4739,4466],{"class":1113},[1075,4741,1594],{"class":1109},[1075,4743,1756],{"class":1088},[1075,4745,4746],{"class":1579}," postData",[1075,4748,1766],{"class":2682},[1075,4750,1597],{"class":1088},[1075,4752,4753,4755,4757,4759,4761],{"class":1077,"line":1978},[1075,4754,4477],{"class":1572},[1075,4756,2924],{"class":1579},[1075,4758,2686],{"class":1088},[1075,4760,2765],{"class":1579},[1075,4762,1597],{"class":1088},[1075,4764,4765],{"class":1077,"line":2009},[1075,4766,4626],{"class":1088},[1075,4768,4769,4772,4774,4776,4778],{"class":1077,"line":2040},[1075,4770,4771],{"class":1653},"    onSuccess",[1075,4773,1106],{"class":1088},[1075,4775,2663],{"class":1088},[1075,4777,2601],{"class":2600},[1075,4779,1176],{"class":1088},[1075,4781,4782,4785,4787,4790,4792,4794,4797,4799,4801,4803,4805,4807,4809,4811,4813],{"class":1077,"line":2069},[1075,4783,4784],{"class":1579},"      queryClient",[1075,4786,2686],{"class":1088},[1075,4788,4789],{"class":1653},"invalidateQueries",[1075,4791,1657],{"class":2682},[1075,4793,2754],{"class":1088},[1075,4795,4796],{"class":1664}," queryKey",[1075,4798,1106],{"class":1088},[1075,4800,1670],{"class":2682},[1075,4802,1594],{"class":1109},[1075,4804,4421],{"class":1113},[1075,4806,1594],{"class":1109},[1075,4808,3036],{"class":2682},[1075,4810,1583],{"class":1088},[1075,4812,1766],{"class":2682},[1075,4814,1597],{"class":1088},[1075,4816,4817],{"class":1077,"line":2074},[1075,4818,1803],{"class":1088},[1075,4820,4821,4823,4825],{"class":1077,"line":2079},[1075,4822,4494],{"class":1088},[1075,4824,1766],{"class":2682},[1075,4826,1597],{"class":1088},[1075,4828,4829],{"class":1077,"line":2440},[1075,4830,1555],{"class":1088},[1075,4832,4833],{"class":1077,"line":2446},[1075,4834,1642],{"emptyLinePlaceholder":1641},[1075,4836,4837,4839,4841,4844,4846],{"class":1077,"line":2452},[1075,4838,1647],{"class":1572},[1075,4840,4390],{"class":2562},[1075,4842,4843],{"class":1653}," useUpdateBlogPost",[1075,4845,2683],{"class":1088},[1075,4847,1176],{"class":1088},[1075,4849,4850,4852,4854,4856,4858,4860],{"class":1077,"line":2458},[1075,4851,4067],{"class":2562},[1075,4853,4675],{"class":1579},[1075,4855,2569],{"class":1088},[1075,4857,4351],{"class":1653},[1075,4859,2683],{"class":2682},[1075,4861,1597],{"class":1088},[1075,4863,4864],{"class":1077,"line":2463},[1075,4865,1683],{"class":2982},[1075,4867,4868,4870,4872,4874],{"class":1077,"line":2468},[1075,4869,4147],{"class":1572},[1075,4871,4346],{"class":1653},[1075,4873,1657],{"class":2682},[1075,4875,1089],{"class":1088},[1075,4877,4878,4880,4882,4884,4887,4890,4892,4895,4898,4900],{"class":1077,"line":2473},[1075,4879,4702],{"class":1653},[1075,4881,1106],{"class":1088},[1075,4883,2660],{"class":2562},[1075,4885,4886],{"class":1088}," ({",[1075,4888,4889],{"class":2589}," id",[1075,4891,1756],{"class":1088},[1075,4893,4894],{"class":2589}," data",[1075,4896,4897],{"class":1088}," })",[1075,4899,2601],{"class":2600},[1075,4901,1176],{"class":1088},[1075,4903,4904,4906,4908,4910,4912,4914,4916,4919,4921,4923,4925,4927,4930,4932,4934,4936,4938,4940,4942],{"class":1077,"line":3168},[1075,4905,4447],{"class":2562},[1075,4907,2924],{"class":1579},[1075,4909,2569],{"class":1088},[1075,4911,2724],{"class":1572},[1075,4913,2540],{"class":1579},[1075,4915,2686],{"class":1088},[1075,4917,4918],{"class":1653},"put",[1075,4920,1657],{"class":2682},[1075,4922,3056],{"class":1109},[1075,4924,4466],{"class":1113},[1075,4926,3048],{"class":3047},[1075,4928,4929],{"class":3051},"id",[1075,4931,2082],{"class":3047},[1075,4933,4603],{"class":1113},[1075,4935,3056],{"class":1109},[1075,4937,1756],{"class":1088},[1075,4939,4894],{"class":1579},[1075,4941,1766],{"class":2682},[1075,4943,1597],{"class":1088},[1075,4945,4946,4948,4950,4952,4954],{"class":1077,"line":3173},[1075,4947,4477],{"class":1572},[1075,4949,2924],{"class":1579},[1075,4951,2686],{"class":1088},[1075,4953,2765],{"class":1579},[1075,4955,1597],{"class":1088},[1075,4957,4958],{"class":1077,"line":3179},[1075,4959,4626],{"class":1088},[1075,4961,4962,4964,4966,4968,4970,4972,4974],{"class":1077,"line":3195},[1075,4963,4771],{"class":1653},[1075,4965,1106],{"class":1088},[1075,4967,2604],{"class":1088},[1075,4969,2765],{"class":2589},[1075,4971,1766],{"class":1088},[1075,4973,2601],{"class":2600},[1075,4975,1176],{"class":1088},[1075,4977,4978,4980,4982,4984,4986,4988,4990,4992,4994,4996,4998,5000,5002,5004,5006],{"class":1077,"line":3202},[1075,4979,4784],{"class":1579},[1075,4981,2686],{"class":1088},[1075,4983,4789],{"class":1653},[1075,4985,1657],{"class":2682},[1075,4987,2754],{"class":1088},[1075,4989,4796],{"class":1664},[1075,4991,1106],{"class":1088},[1075,4993,1670],{"class":2682},[1075,4995,1594],{"class":1109},[1075,4997,4421],{"class":1113},[1075,4999,1594],{"class":1109},[1075,5001,3036],{"class":2682},[1075,5003,1583],{"class":1088},[1075,5005,1766],{"class":2682},[1075,5007,1597],{"class":1088},[1075,5009,5010,5012,5014,5016,5018,5020,5022,5024,5026,5028,5030,5032,5034,5036,5038,5040,5042,5044,5046],{"class":1077,"line":3227},[1075,5011,4784],{"class":1579},[1075,5013,2686],{"class":1088},[1075,5015,4789],{"class":1653},[1075,5017,1657],{"class":2682},[1075,5019,2754],{"class":1088},[1075,5021,4796],{"class":1664},[1075,5023,1106],{"class":1088},[1075,5025,1670],{"class":2682},[1075,5027,1594],{"class":1109},[1075,5029,4547],{"class":1113},[1075,5031,1594],{"class":1109},[1075,5033,1756],{"class":1088},[1075,5035,4894],{"class":1579},[1075,5037,2686],{"class":1088},[1075,5039,4520],{"class":1579},[1075,5041,3036],{"class":2682},[1075,5043,1583],{"class":1088},[1075,5045,1766],{"class":2682},[1075,5047,1597],{"class":1088},[1075,5049,5050],{"class":1077,"line":3242},[1075,5051,1803],{"class":1088},[1075,5053,5054,5056,5058],{"class":1077,"line":3248},[1075,5055,4494],{"class":1088},[1075,5057,1766],{"class":2682},[1075,5059,1597],{"class":1088},[1075,5061,5062],{"class":1077,"line":3253},[1075,5063,1555],{"class":1088},[1030,5065,5067],{"id":5066},"vue-integration-with-django","Vue Integration with Django",[1035,5069,5071],{"id":5070},"setting-up-vue-with-vite","Setting Up Vue with Vite",[1065,5073,5075],{"className":1067,"code":5074,"language":1069,"meta":1070,"style":1070},"// package.json\n{\n  \"name\": \"django-vue-app\",\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"vue\": \"^3.3.0\",\n    \"vue-router\": \"^4.2.0\",\n    \"pinia\": \"^2.1.0\",\n    \"axios\": \"^1.6.0\",\n    \"@vueuse/core\": \"^10.7.0\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-vue\": \"^4.5.0\",\n    \"vite\": \"^5.0.0\",\n    \"eslint\": \"^8.55.0\",\n    \"eslint-plugin-vue\": \"^9.19.0\"\n  }\n}\n",[1072,5076,5077,5081,5085,5104,5122,5140,5152,5170,5188,5204,5208,5220,5240,5259,5279,5297,5315,5319,5331,5351,5369,5387,5405,5409],{"__ignoreMap":1070},[1075,5078,5079],{"class":1077,"line":1078},[1075,5080,1082],{"class":1081},[1075,5082,5083],{"class":1077,"line":1085},[1075,5084,1089],{"class":1088},[1075,5086,5087,5089,5091,5093,5095,5097,5100,5102],{"class":1077,"line":1092},[1075,5088,1096],{"class":1095},[1075,5090,1100],{"class":1099},[1075,5092,1103],{"class":1095},[1075,5094,1106],{"class":1088},[1075,5096,1110],{"class":1109},[1075,5098,5099],{"class":1113},"django-vue-app",[1075,5101,1103],{"class":1109},[1075,5103,1119],{"class":1088},[1075,5105,5106,5108,5110,5112,5114,5116,5118,5120],{"class":1077,"line":1122},[1075,5107,1096],{"class":1095},[1075,5109,1127],{"class":1099},[1075,5111,1103],{"class":1095},[1075,5113,1106],{"class":1088},[1075,5115,1110],{"class":1109},[1075,5117,1136],{"class":1113},[1075,5119,1103],{"class":1109},[1075,5121,1119],{"class":1088},[1075,5123,5124,5126,5128,5130,5132,5134,5136,5138],{"class":1077,"line":1143},[1075,5125,1096],{"class":1095},[1075,5127,1148],{"class":1099},[1075,5129,1103],{"class":1095},[1075,5131,1106],{"class":1088},[1075,5133,1110],{"class":1109},[1075,5135,1157],{"class":1113},[1075,5137,1103],{"class":1109},[1075,5139,1119],{"class":1088},[1075,5141,5142,5144,5146,5148,5150],{"class":1077,"line":1164},[1075,5143,1096],{"class":1095},[1075,5145,1169],{"class":1099},[1075,5147,1103],{"class":1095},[1075,5149,1106],{"class":1088},[1075,5151,1176],{"class":1088},[1075,5153,5154,5156,5158,5160,5162,5164,5166,5168],{"class":1077,"line":1179},[1075,5155,1182],{"class":1095},[1075,5157,1186],{"class":1185},[1075,5159,1103],{"class":1095},[1075,5161,1106],{"class":1088},[1075,5163,1110],{"class":1109},[1075,5165,1195],{"class":1113},[1075,5167,1103],{"class":1109},[1075,5169,1119],{"class":1088},[1075,5171,5172,5174,5176,5178,5180,5182,5184,5186],{"class":1077,"line":1202},[1075,5173,1182],{"class":1095},[1075,5175,1207],{"class":1185},[1075,5177,1103],{"class":1095},[1075,5179,1106],{"class":1088},[1075,5181,1110],{"class":1109},[1075,5183,1216],{"class":1113},[1075,5185,1103],{"class":1109},[1075,5187,1119],{"class":1088},[1075,5189,5190,5192,5194,5196,5198,5200,5202],{"class":1077,"line":1223},[1075,5191,1182],{"class":1095},[1075,5193,1228],{"class":1185},[1075,5195,1103],{"class":1095},[1075,5197,1106],{"class":1088},[1075,5199,1110],{"class":1109},[1075,5201,1237],{"class":1113},[1075,5203,1240],{"class":1109},[1075,5205,5206],{"class":1077,"line":1243},[1075,5207,1246],{"class":1088},[1075,5209,5210,5212,5214,5216,5218],{"class":1077,"line":1249},[1075,5211,1096],{"class":1095},[1075,5213,1254],{"class":1099},[1075,5215,1103],{"class":1095},[1075,5217,1106],{"class":1088},[1075,5219,1176],{"class":1088},[1075,5221,5222,5224,5227,5229,5231,5233,5236,5238],{"class":1077,"line":1263},[1075,5223,1182],{"class":1095},[1075,5225,5226],{"class":1185},"vue",[1075,5228,1103],{"class":1095},[1075,5230,1106],{"class":1088},[1075,5232,1110],{"class":1109},[1075,5234,5235],{"class":1113},"^3.3.0",[1075,5237,1103],{"class":1109},[1075,5239,1119],{"class":1088},[1075,5241,5242,5244,5247,5249,5251,5253,5255,5257],{"class":1077,"line":1284},[1075,5243,1182],{"class":1095},[1075,5245,5246],{"class":1185},"vue-router",[1075,5248,1103],{"class":1095},[1075,5250,1106],{"class":1088},[1075,5252,1110],{"class":1109},[1075,5254,1459],{"class":1113},[1075,5256,1103],{"class":1109},[1075,5258,1119],{"class":1088},[1075,5260,5261,5263,5266,5268,5270,5272,5275,5277],{"class":1077,"line":1304},[1075,5262,1182],{"class":1095},[1075,5264,5265],{"class":1185},"pinia",[1075,5267,1103],{"class":1095},[1075,5269,1106],{"class":1088},[1075,5271,1110],{"class":1109},[1075,5273,5274],{"class":1113},"^2.1.0",[1075,5276,1103],{"class":1109},[1075,5278,1119],{"class":1088},[1075,5280,5281,5283,5285,5287,5289,5291,5293,5295],{"class":1077,"line":1325},[1075,5282,1182],{"class":1095},[1075,5284,1330],{"class":1185},[1075,5286,1103],{"class":1095},[1075,5288,1106],{"class":1088},[1075,5290,1110],{"class":1109},[1075,5292,1339],{"class":1113},[1075,5294,1103],{"class":1109},[1075,5296,1119],{"class":1088},[1075,5298,5299,5301,5304,5306,5308,5310,5313],{"class":1077,"line":1346},[1075,5300,1182],{"class":1095},[1075,5302,5303],{"class":1185},"@vueuse/core",[1075,5305,1103],{"class":1095},[1075,5307,1106],{"class":1088},[1075,5309,1110],{"class":1109},[1075,5311,5312],{"class":1113},"^10.7.0",[1075,5314,1240],{"class":1109},[1075,5316,5317],{"class":1077,"line":1367},[1075,5318,1246],{"class":1088},[1075,5320,5321,5323,5325,5327,5329],{"class":1077,"line":1386},[1075,5322,1096],{"class":1095},[1075,5324,1396],{"class":1099},[1075,5326,1103],{"class":1095},[1075,5328,1106],{"class":1088},[1075,5330,1176],{"class":1088},[1075,5332,5333,5335,5338,5340,5342,5344,5347,5349],{"class":1077,"line":1391},[1075,5334,1182],{"class":1095},[1075,5336,5337],{"class":1185},"@vitejs/plugin-vue",[1075,5339,1103],{"class":1095},[1075,5341,1106],{"class":1088},[1075,5343,1110],{"class":1109},[1075,5345,5346],{"class":1113},"^4.5.0",[1075,5348,1103],{"class":1109},[1075,5350,1119],{"class":1088},[1075,5352,5353,5355,5357,5359,5361,5363,5365,5367],{"class":1077,"line":1405},[1075,5354,1182],{"class":1095},[1075,5356,1195],{"class":1185},[1075,5358,1103],{"class":1095},[1075,5360,1106],{"class":1088},[1075,5362,1110],{"class":1109},[1075,5364,1360],{"class":1113},[1075,5366,1103],{"class":1109},[1075,5368,1119],{"class":1088},[1075,5370,5371,5373,5375,5377,5379,5381,5383,5385],{"class":1077,"line":1425},[1075,5372,1182],{"class":1095},[1075,5374,1490],{"class":1185},[1075,5376,1103],{"class":1095},[1075,5378,1106],{"class":1088},[1075,5380,1110],{"class":1109},[1075,5382,1499],{"class":1113},[1075,5384,1103],{"class":1109},[1075,5386,1119],{"class":1088},[1075,5388,5389,5391,5394,5396,5398,5400,5403],{"class":1077,"line":1445},[1075,5390,1182],{"class":1095},[1075,5392,5393],{"class":1185},"eslint-plugin-vue",[1075,5395,1103],{"class":1095},[1075,5397,1106],{"class":1088},[1075,5399,1110],{"class":1109},[1075,5401,5402],{"class":1113},"^9.19.0",[1075,5404,1240],{"class":1109},[1075,5406,5407],{"class":1077,"line":1466},[1075,5408,1549],{"class":1088},[1075,5410,5411],{"class":1077,"line":1485},[1075,5412,1555],{"class":1088},[1065,5414,5416],{"className":1558,"code":5415,"language":1560,"meta":1070,"style":1070},"// vite.config.js\nimport { defineConfig } from 'vite';\nimport vue from '@vitejs/plugin-vue';\nimport { resolve } from 'path';\n\nexport default defineConfig({\n  plugins: [vue()],\n  \n  build: {\n    outDir: 'staticfiles/dist',\n    manifest: true,\n    rollupOptions: {\n      input: {\n        main: resolve(__dirname, 'frontend/js/main.js'),\n        components: resolve(__dirname, 'frontend/js/components.js')\n      }\n    }\n  },\n  \n  server: {\n    port: 3000,\n    proxy: {\n      '/api': 'http://localhost:8000'\n    }\n  },\n  \n  resolve: {\n    alias: {\n      '@': resolve(__dirname, 'frontend'),\n      '@components': resolve(__dirname, 'frontend/js/components'),\n      '@composables': resolve(__dirname, 'frontend/js/composables'),\n      '@stores': resolve(__dirname, 'frontend/js/stores')\n    }\n  }\n});\n",[1072,5417,5418,5422,5442,5459,5479,5483,5495,5509,5513,5521,5535,5545,5553,5561,5586,5609,5613,5617,5621,5625,5633,5643,5651,5667,5671,5675,5679,5687,5695,5723,5751,5781,5809,5813,5817],{"__ignoreMap":1070},[1075,5419,5420],{"class":1077,"line":1078},[1075,5421,1567],{"class":1081},[1075,5423,5424,5426,5428,5430,5432,5434,5436,5438,5440],{"class":1077,"line":1085},[1075,5425,1573],{"class":1572},[1075,5427,1576],{"class":1088},[1075,5429,1580],{"class":1579},[1075,5431,1583],{"class":1088},[1075,5433,1586],{"class":1572},[1075,5435,1589],{"class":1109},[1075,5437,1195],{"class":1113},[1075,5439,1594],{"class":1109},[1075,5441,1597],{"class":1088},[1075,5443,5444,5446,5449,5451,5453,5455,5457],{"class":1077,"line":1092},[1075,5445,1573],{"class":1572},[1075,5447,5448],{"class":1579}," vue",[1075,5450,1586],{"class":1572},[1075,5452,1589],{"class":1109},[1075,5454,5337],{"class":1113},[1075,5456,1594],{"class":1109},[1075,5458,1597],{"class":1088},[1075,5460,5461,5463,5465,5467,5469,5471,5473,5475,5477],{"class":1077,"line":1122},[1075,5462,1573],{"class":1572},[1075,5464,1576],{"class":1088},[1075,5466,1623],{"class":1579},[1075,5468,1583],{"class":1088},[1075,5470,1586],{"class":1572},[1075,5472,1589],{"class":1109},[1075,5474,1632],{"class":1113},[1075,5476,1594],{"class":1109},[1075,5478,1597],{"class":1088},[1075,5480,5481],{"class":1077,"line":1143},[1075,5482,1642],{"emptyLinePlaceholder":1641},[1075,5484,5485,5487,5489,5491,5493],{"class":1077,"line":1164},[1075,5486,1647],{"class":1572},[1075,5488,1650],{"class":1572},[1075,5490,1580],{"class":1653},[1075,5492,1657],{"class":1656},[1075,5494,1089],{"class":1088},[1075,5496,5497,5499,5501,5503,5505,5507],{"class":1077,"line":1179},[1075,5498,1665],{"class":1664},[1075,5500,1106],{"class":1088},[1075,5502,1670],{"class":1656},[1075,5504,5226],{"class":1653},[1075,5506,1675],{"class":1656},[1075,5508,1119],{"class":1088},[1075,5510,5511],{"class":1077,"line":1202},[1075,5512,1683],{"class":1682},[1075,5514,5515,5517,5519],{"class":1077,"line":1223},[1075,5516,1688],{"class":1664},[1075,5518,1106],{"class":1088},[1075,5520,1176],{"class":1088},[1075,5522,5523,5525,5527,5529,5531,5533],{"class":1077,"line":1243},[1075,5524,1697],{"class":1664},[1075,5526,1106],{"class":1088},[1075,5528,1589],{"class":1109},[1075,5530,1704],{"class":1113},[1075,5532,1594],{"class":1109},[1075,5534,1119],{"class":1088},[1075,5536,5537,5539,5541,5543],{"class":1077,"line":1249},[1075,5538,1713],{"class":1664},[1075,5540,1106],{"class":1088},[1075,5542,1719],{"class":1718},[1075,5544,1119],{"class":1088},[1075,5546,5547,5549,5551],{"class":1077,"line":1263},[1075,5548,1726],{"class":1664},[1075,5550,1106],{"class":1088},[1075,5552,1176],{"class":1088},[1075,5554,5555,5557,5559],{"class":1077,"line":1284},[1075,5556,1735],{"class":1664},[1075,5558,1106],{"class":1088},[1075,5560,1176],{"class":1088},[1075,5562,5563,5565,5567,5569,5571,5573,5575,5577,5580,5582,5584],{"class":1077,"line":1304},[1075,5564,1744],{"class":1664},[1075,5566,1106],{"class":1088},[1075,5568,1623],{"class":1653},[1075,5570,1657],{"class":1656},[1075,5572,1753],{"class":1579},[1075,5574,1756],{"class":1088},[1075,5576,1589],{"class":1109},[1075,5578,5579],{"class":1113},"frontend/js/main.js",[1075,5581,1594],{"class":1109},[1075,5583,1766],{"class":1656},[1075,5585,1119],{"class":1088},[1075,5587,5588,5590,5592,5594,5596,5598,5600,5602,5605,5607],{"class":1077,"line":1325},[1075,5589,1773],{"class":1664},[1075,5591,1106],{"class":1088},[1075,5593,1623],{"class":1653},[1075,5595,1657],{"class":1656},[1075,5597,1753],{"class":1579},[1075,5599,1756],{"class":1088},[1075,5601,1589],{"class":1109},[1075,5603,5604],{"class":1113},"frontend/js/components.js",[1075,5606,1594],{"class":1109},[1075,5608,1793],{"class":1656},[1075,5610,5611],{"class":1077,"line":1346},[1075,5612,1798],{"class":1088},[1075,5614,5615],{"class":1077,"line":1367},[1075,5616,1803],{"class":1088},[1075,5618,5619],{"class":1077,"line":1386},[1075,5620,1246],{"class":1088},[1075,5622,5623],{"class":1077,"line":1391},[1075,5624,1683],{"class":1682},[1075,5626,5627,5629,5631],{"class":1077,"line":1405},[1075,5628,1816],{"class":1664},[1075,5630,1106],{"class":1088},[1075,5632,1176],{"class":1088},[1075,5634,5635,5637,5639,5641],{"class":1077,"line":1425},[1075,5636,1825],{"class":1664},[1075,5638,1106],{"class":1088},[1075,5640,1831],{"class":1830},[1075,5642,1119],{"class":1088},[1075,5644,5645,5647,5649],{"class":1077,"line":1445},[1075,5646,1838],{"class":1664},[1075,5648,1106],{"class":1088},[1075,5650,1176],{"class":1088},[1075,5652,5653,5655,5657,5659,5661,5663,5665],{"class":1077,"line":1466},[1075,5654,1847],{"class":1109},[1075,5656,1851],{"class":1850},[1075,5658,1594],{"class":1109},[1075,5660,1106],{"class":1088},[1075,5662,1589],{"class":1109},[1075,5664,1860],{"class":1113},[1075,5666,1882],{"class":1109},[1075,5668,5669],{"class":1077,"line":1485},[1075,5670,1803],{"class":1088},[1075,5672,5673],{"class":1077,"line":1506},[1075,5674,1246],{"class":1088},[1075,5676,5677],{"class":1077,"line":1527},[1075,5678,1683],{"class":1682},[1075,5680,5681,5683,5685],{"class":1077,"line":1546},[1075,5682,1899],{"class":1664},[1075,5684,1106],{"class":1088},[1075,5686,1176],{"class":1088},[1075,5688,5689,5691,5693],{"class":1077,"line":1552},[1075,5690,1909],{"class":1664},[1075,5692,1106],{"class":1088},[1075,5694,1176],{"class":1088},[1075,5696,5697,5699,5701,5703,5705,5707,5709,5711,5713,5715,5717,5719,5721],{"class":1077,"line":1906},[1075,5698,1847],{"class":1109},[1075,5700,1921],{"class":1850},[1075,5702,1594],{"class":1109},[1075,5704,1106],{"class":1088},[1075,5706,1623],{"class":1653},[1075,5708,1657],{"class":1656},[1075,5710,1753],{"class":1579},[1075,5712,1756],{"class":1088},[1075,5714,1589],{"class":1109},[1075,5716,1938],{"class":1113},[1075,5718,1594],{"class":1109},[1075,5720,1766],{"class":1656},[1075,5722,1119],{"class":1088},[1075,5724,5725,5727,5729,5731,5733,5735,5737,5739,5741,5743,5745,5747,5749],{"class":1077,"line":1916},[1075,5726,1847],{"class":1109},[1075,5728,1952],{"class":1850},[1075,5730,1594],{"class":1109},[1075,5732,1106],{"class":1088},[1075,5734,1623],{"class":1653},[1075,5736,1657],{"class":1656},[1075,5738,1753],{"class":1579},[1075,5740,1756],{"class":1088},[1075,5742,1589],{"class":1109},[1075,5744,1969],{"class":1113},[1075,5746,1594],{"class":1109},[1075,5748,1766],{"class":1656},[1075,5750,1119],{"class":1088},[1075,5752,5753,5755,5758,5760,5762,5764,5766,5768,5770,5772,5775,5777,5779],{"class":1077,"line":1947},[1075,5754,1847],{"class":1109},[1075,5756,5757],{"class":1850},"@composables",[1075,5759,1594],{"class":1109},[1075,5761,1106],{"class":1088},[1075,5763,1623],{"class":1653},[1075,5765,1657],{"class":1656},[1075,5767,1753],{"class":1579},[1075,5769,1756],{"class":1088},[1075,5771,1589],{"class":1109},[1075,5773,5774],{"class":1113},"frontend/js/composables",[1075,5776,1594],{"class":1109},[1075,5778,1766],{"class":1656},[1075,5780,1119],{"class":1088},[1075,5782,5783,5785,5788,5790,5792,5794,5796,5798,5800,5802,5805,5807],{"class":1077,"line":1978},[1075,5784,1847],{"class":1109},[1075,5786,5787],{"class":1850},"@stores",[1075,5789,1594],{"class":1109},[1075,5791,1106],{"class":1088},[1075,5793,1623],{"class":1653},[1075,5795,1657],{"class":1656},[1075,5797,1753],{"class":1579},[1075,5799,1756],{"class":1088},[1075,5801,1589],{"class":1109},[1075,5803,5804],{"class":1113},"frontend/js/stores",[1075,5806,1594],{"class":1109},[1075,5808,1793],{"class":1656},[1075,5810,5811],{"class":1077,"line":2009},[1075,5812,1803],{"class":1088},[1075,5814,5815],{"class":1077,"line":2040},[1075,5816,1549],{"class":1088},[1075,5818,5819,5821,5823],{"class":1077,"line":2069},[1075,5820,2082],{"class":1088},[1075,5822,1766],{"class":1656},[1075,5824,1597],{"class":1088},[1035,5826,5828],{"id":5827},"vue-application-structure","Vue Application Structure",[1065,5830,5832],{"className":1558,"code":5831,"language":1560,"meta":1070,"style":1070},"// frontend/js/main.js\nimport { createApp } from 'vue';\nimport { createRouter, createWebHistory } from 'vue-router';\nimport { createPinia } from 'pinia';\nimport App from './App.vue';\nimport routes from './routes';\nimport './styles/main.css';\n\n// Create router\nconst router = createRouter({\n  history: createWebHistory(),\n  routes\n});\n\n// Create Pinia store\nconst pinia = createPinia();\n\n// Create and mount app\nconst app = createApp(App);\napp.use(router);\napp.use(pinia);\n\n// Mount to DOM\nconst container = document.getElementById('vue-app');\nif (container) {\n  app.mount(container);\n}\n",[1072,5833,5834,5839,5860,5886,5907,5925,5943,5956,5960,5965,5980,5993,5998,6006,6010,6015,6030,6034,6039,6059,6077,6093,6097,6102,6131,6145,6163],{"__ignoreMap":1070},[1075,5835,5836],{"class":1077,"line":1078},[1075,5837,5838],{"class":1081},"// frontend/js/main.js\n",[1075,5840,5841,5843,5845,5848,5850,5852,5854,5856,5858],{"class":1077,"line":1085},[1075,5842,1573],{"class":1572},[1075,5844,1576],{"class":1088},[1075,5846,5847],{"class":1579}," createApp",[1075,5849,1583],{"class":1088},[1075,5851,1586],{"class":1572},[1075,5853,1589],{"class":1109},[1075,5855,5226],{"class":1113},[1075,5857,1594],{"class":1109},[1075,5859,1597],{"class":1088},[1075,5861,5862,5864,5866,5869,5871,5874,5876,5878,5880,5882,5884],{"class":1077,"line":1092},[1075,5863,1573],{"class":1572},[1075,5865,1576],{"class":1088},[1075,5867,5868],{"class":1579}," createRouter",[1075,5870,1756],{"class":1088},[1075,5872,5873],{"class":1579}," createWebHistory",[1075,5875,1583],{"class":1088},[1075,5877,1586],{"class":1572},[1075,5879,1589],{"class":1109},[1075,5881,5246],{"class":1113},[1075,5883,1594],{"class":1109},[1075,5885,1597],{"class":1088},[1075,5887,5888,5890,5892,5895,5897,5899,5901,5903,5905],{"class":1077,"line":1122},[1075,5889,1573],{"class":1572},[1075,5891,1576],{"class":1088},[1075,5893,5894],{"class":1579}," createPinia",[1075,5896,1583],{"class":1088},[1075,5898,1586],{"class":1572},[1075,5900,1589],{"class":1109},[1075,5902,5265],{"class":1113},[1075,5904,1594],{"class":1109},[1075,5906,1597],{"class":1088},[1075,5908,5909,5911,5914,5916,5918,5921,5923],{"class":1077,"line":1143},[1075,5910,1573],{"class":1572},[1075,5912,5913],{"class":1579}," App",[1075,5915,1586],{"class":1572},[1075,5917,1589],{"class":1109},[1075,5919,5920],{"class":1113},"./App.vue",[1075,5922,1594],{"class":1109},[1075,5924,1597],{"class":1088},[1075,5926,5927,5929,5932,5934,5936,5939,5941],{"class":1077,"line":1164},[1075,5928,1573],{"class":1572},[1075,5930,5931],{"class":1579}," routes",[1075,5933,1586],{"class":1572},[1075,5935,1589],{"class":1109},[1075,5937,5938],{"class":1113},"./routes",[1075,5940,1594],{"class":1109},[1075,5942,1597],{"class":1088},[1075,5944,5945,5947,5949,5952,5954],{"class":1077,"line":1179},[1075,5946,1573],{"class":1572},[1075,5948,1589],{"class":1109},[1075,5950,5951],{"class":1113},"./styles/main.css",[1075,5953,1594],{"class":1109},[1075,5955,1597],{"class":1088},[1075,5957,5958],{"class":1077,"line":1202},[1075,5959,1642],{"emptyLinePlaceholder":1641},[1075,5961,5962],{"class":1077,"line":1223},[1075,5963,5964],{"class":1081},"// Create router\n",[1075,5966,5967,5969,5972,5974,5976,5978],{"class":1077,"line":1243},[1075,5968,3950],{"class":2562},[1075,5970,5971],{"class":1579}," router",[1075,5973,2569],{"class":1088},[1075,5975,5868],{"class":1653},[1075,5977,1657],{"class":1656},[1075,5979,1089],{"class":1088},[1075,5981,5982,5985,5987,5989,5991],{"class":1077,"line":1249},[1075,5983,5984],{"class":1664},"  history",[1075,5986,1106],{"class":1088},[1075,5988,5873],{"class":1653},[1075,5990,2683],{"class":1656},[1075,5992,1119],{"class":1088},[1075,5994,5995],{"class":1077,"line":1263},[1075,5996,5997],{"class":1579},"  routes\n",[1075,5999,6000,6002,6004],{"class":1077,"line":1284},[1075,6001,2082],{"class":1088},[1075,6003,1766],{"class":1656},[1075,6005,1597],{"class":1088},[1075,6007,6008],{"class":1077,"line":1304},[1075,6009,1642],{"emptyLinePlaceholder":1641},[1075,6011,6012],{"class":1077,"line":1325},[1075,6013,6014],{"class":1081},"// Create Pinia store\n",[1075,6016,6017,6019,6022,6024,6026,6028],{"class":1077,"line":1346},[1075,6018,3950],{"class":2562},[1075,6020,6021],{"class":1579}," pinia",[1075,6023,2569],{"class":1088},[1075,6025,5894],{"class":1653},[1075,6027,2683],{"class":1656},[1075,6029,1597],{"class":1088},[1075,6031,6032],{"class":1077,"line":1367},[1075,6033,1642],{"emptyLinePlaceholder":1641},[1075,6035,6036],{"class":1077,"line":1386},[1075,6037,6038],{"class":1081},"// Create and mount app\n",[1075,6040,6041,6043,6046,6048,6050,6052,6055,6057],{"class":1077,"line":1391},[1075,6042,3950],{"class":2562},[1075,6044,6045],{"class":1579}," app",[1075,6047,2569],{"class":1088},[1075,6049,5847],{"class":1653},[1075,6051,1657],{"class":1656},[1075,6053,6054],{"class":1579},"App",[1075,6056,1766],{"class":1656},[1075,6058,1597],{"class":1088},[1075,6060,6061,6064,6066,6068,6070,6073,6075],{"class":1077,"line":1405},[1075,6062,6063],{"class":1579},"app",[1075,6065,2686],{"class":1088},[1075,6067,4049],{"class":1653},[1075,6069,1657],{"class":1656},[1075,6071,6072],{"class":1579},"router",[1075,6074,1766],{"class":1656},[1075,6076,1597],{"class":1088},[1075,6078,6079,6081,6083,6085,6087,6089,6091],{"class":1077,"line":1425},[1075,6080,6063],{"class":1579},[1075,6082,2686],{"class":1088},[1075,6084,4049],{"class":1653},[1075,6086,1657],{"class":1656},[1075,6088,5265],{"class":1579},[1075,6090,1766],{"class":1656},[1075,6092,1597],{"class":1088},[1075,6094,6095],{"class":1077,"line":1445},[1075,6096,1642],{"emptyLinePlaceholder":1641},[1075,6098,6099],{"class":1077,"line":1466},[1075,6100,6101],{"class":1081},"// Mount to DOM\n",[1075,6103,6104,6106,6109,6111,6113,6115,6118,6120,6122,6125,6127,6129],{"class":1077,"line":1485},[1075,6105,3950],{"class":2562},[1075,6107,6108],{"class":1579}," container",[1075,6110,2569],{"class":1088},[1075,6112,4075],{"class":1579},[1075,6114,2686],{"class":1088},[1075,6116,6117],{"class":1653},"getElementById",[1075,6119,1657],{"class":1656},[1075,6121,1594],{"class":1109},[1075,6123,6124],{"class":1113},"vue-app",[1075,6126,1594],{"class":1109},[1075,6128,1766],{"class":1656},[1075,6130,1597],{"class":1088},[1075,6132,6133,6136,6138,6141,6143],{"class":1077,"line":1506},[1075,6134,6135],{"class":1572},"if",[1075,6137,2604],{"class":1656},[1075,6139,6140],{"class":1579},"container",[1075,6142,1766],{"class":1656},[1075,6144,1176],{"class":1088},[1075,6146,6147,6150,6152,6155,6157,6159,6161],{"class":1077,"line":1527},[1075,6148,6149],{"class":1579},"  app",[1075,6151,2686],{"class":1088},[1075,6153,6154],{"class":1653},"mount",[1075,6156,1657],{"class":2682},[1075,6158,6140],{"class":1579},[1075,6160,1766],{"class":2682},[1075,6162,1597],{"class":1088},[1075,6164,6165],{"class":1077,"line":1546},[1075,6166,1555],{"class":1088},[1065,6168,6171],{"className":6169,"code":6170,"language":5226,"meta":1070,"style":1070},"language-vue shiki shiki-themes material-theme-lighter vitesse-light vitesse-dark","\u003C!-- frontend/js/App.vue -->\n\u003Ctemplate>\n  \u003Cdiv class=\"app\">\n    \u003CNavigation :user=\"user\" @logout=\"handleLogout\" />\n    \n    \u003Cmain class=\"main-content\">\n      \u003Crouter-view />\n    \u003C/main>\n  \u003C/div>\n\u003C/template>\n\n\u003Cscript setup>\nimport { onMounted } from 'vue';\nimport { useAuthStore } from '@stores/auth';\nimport Navigation from '@components/Navigation.vue';\n\nconst authStore = useAuthStore();\nconst { user, initialize } = authStore;\n\nconst handleLogout = async () => {\n  await authStore.logout();\n};\n\nonMounted(() => {\n  initialize();\n});\n\u003C/script>\n",[1072,6172,6173,6178,6190,6213,6253,6257,6277,6287,6296,6305,6314,6318,6330,6351,6372,6390,6394,6409,6430,6434,6452,6467,6472,6476,6489,6498,6506],{"__ignoreMap":1070},[1075,6174,6175],{"class":1077,"line":1078},[1075,6176,6177],{"class":1081},"\u003C!-- frontend/js/App.vue -->\n",[1075,6179,6180,6183,6187],{"class":1077,"line":1085},[1075,6181,6182],{"class":1088},"\u003C",[1075,6184,6186],{"class":6185},"sJFLg","template",[1075,6188,6189],{"class":1088},">\n",[1075,6191,6192,6195,6198,6202,6205,6207,6209,6211],{"class":1077,"line":1092},[1075,6193,6194],{"class":1088},"  \u003C",[1075,6196,6197],{"class":6185},"div",[1075,6199,6201],{"class":6200},"s5q8q"," class",[1075,6203,6204],{"class":1088},"=",[1075,6206,1103],{"class":1109},[1075,6208,6063],{"class":1113},[1075,6210,1103],{"class":1109},[1075,6212,6189],{"class":1088},[1075,6214,6215,6218,6221,6224,6227,6229,6231,6233,6235,6238,6241,6243,6245,6248,6250],{"class":1077,"line":1122},[1075,6216,6217],{"class":1088},"    \u003C",[1075,6219,6220],{"class":6185},"Navigation",[1075,6222,6223],{"class":1088}," :",[1075,6225,3380],{"class":6226},"s1Bar",[1075,6228,6204],{"class":1088},[1075,6230,1103],{"class":1088},[1075,6232,3380],{"class":1579},[1075,6234,1103],{"class":1088},[1075,6236,6237],{"class":1088}," @",[1075,6239,6240],{"class":6226},"logout",[1075,6242,6204],{"class":1088},[1075,6244,1103],{"class":1088},[1075,6246,6247],{"class":1579},"handleLogout",[1075,6249,1103],{"class":1088},[1075,6251,6252],{"class":1088}," />\n",[1075,6254,6255],{"class":1077,"line":1143},[1075,6256,3638],{"class":1682},[1075,6258,6259,6261,6264,6266,6268,6270,6273,6275],{"class":1077,"line":1164},[1075,6260,6217],{"class":1088},[1075,6262,6263],{"class":6185},"main",[1075,6265,6201],{"class":6200},[1075,6267,6204],{"class":1088},[1075,6269,1103],{"class":1109},[1075,6271,6272],{"class":1113},"main-content",[1075,6274,1103],{"class":1109},[1075,6276,6189],{"class":1088},[1075,6278,6279,6282,6285],{"class":1077,"line":1179},[1075,6280,6281],{"class":1088},"      \u003C",[1075,6283,6284],{"class":6185},"router-view",[1075,6286,6252],{"class":1088},[1075,6288,6289,6292,6294],{"class":1077,"line":1202},[1075,6290,6291],{"class":1088},"    \u003C/",[1075,6293,6263],{"class":6185},[1075,6295,6189],{"class":1088},[1075,6297,6298,6301,6303],{"class":1077,"line":1223},[1075,6299,6300],{"class":1088},"  \u003C/",[1075,6302,6197],{"class":6185},[1075,6304,6189],{"class":1088},[1075,6306,6307,6310,6312],{"class":1077,"line":1243},[1075,6308,6309],{"class":1088},"\u003C/",[1075,6311,6186],{"class":6185},[1075,6313,6189],{"class":1088},[1075,6315,6316],{"class":1077,"line":1249},[1075,6317,1642],{"emptyLinePlaceholder":1641},[1075,6319,6320,6322,6325,6328],{"class":1077,"line":1263},[1075,6321,6182],{"class":1088},[1075,6323,6324],{"class":6185},"script",[1075,6326,6327],{"class":6200}," setup",[1075,6329,6189],{"class":1088},[1075,6331,6332,6334,6336,6339,6341,6343,6345,6347,6349],{"class":1077,"line":1284},[1075,6333,1573],{"class":1572},[1075,6335,1576],{"class":1088},[1075,6337,6338],{"class":1579}," onMounted",[1075,6340,1583],{"class":1088},[1075,6342,1586],{"class":1572},[1075,6344,1589],{"class":1109},[1075,6346,5226],{"class":1113},[1075,6348,1594],{"class":1109},[1075,6350,1597],{"class":1088},[1075,6352,6353,6355,6357,6359,6361,6363,6365,6368,6370],{"class":1077,"line":1304},[1075,6354,1573],{"class":1572},[1075,6356,1576],{"class":1088},[1075,6358,2566],{"class":1579},[1075,6360,1583],{"class":1088},[1075,6362,1586],{"class":1572},[1075,6364,1589],{"class":1109},[1075,6366,6367],{"class":1113},"@stores/auth",[1075,6369,1594],{"class":1109},[1075,6371,1597],{"class":1088},[1075,6373,6374,6376,6379,6381,6383,6386,6388],{"class":1077,"line":1325},[1075,6375,1573],{"class":1572},[1075,6377,6378],{"class":1579}," Navigation",[1075,6380,1586],{"class":1572},[1075,6382,1589],{"class":1109},[1075,6384,6385],{"class":1113},"@components/Navigation.vue",[1075,6387,1594],{"class":1109},[1075,6389,1597],{"class":1088},[1075,6391,6392],{"class":1077,"line":1346},[1075,6393,1642],{"emptyLinePlaceholder":1641},[1075,6395,6396,6398,6401,6403,6405,6407],{"class":1077,"line":1367},[1075,6397,3950],{"class":2562},[1075,6399,6400],{"class":1579}," authStore",[1075,6402,2569],{"class":1088},[1075,6404,2566],{"class":1653},[1075,6406,2683],{"class":1656},[1075,6408,1597],{"class":1088},[1075,6410,6411,6413,6415,6417,6419,6422,6424,6426,6428],{"class":1077,"line":1386},[1075,6412,3950],{"class":2562},[1075,6414,1576],{"class":1088},[1075,6416,2719],{"class":1579},[1075,6418,1756],{"class":1088},[1075,6420,6421],{"class":1579}," initialize",[1075,6423,1583],{"class":1088},[1075,6425,2569],{"class":1088},[1075,6427,6400],{"class":1579},[1075,6429,1597],{"class":1088},[1075,6431,6432],{"class":1077,"line":1391},[1075,6433,1642],{"emptyLinePlaceholder":1641},[1075,6435,6436,6438,6442,6444,6446,6448,6450],{"class":1077,"line":1405},[1075,6437,3950],{"class":2562},[1075,6439,6441],{"class":6440},"sAbu7"," handleLogout",[1075,6443,2569],{"class":1088},[1075,6445,2660],{"class":2562},[1075,6447,2663],{"class":1088},[1075,6449,2601],{"class":2600},[1075,6451,1176],{"class":1088},[1075,6453,6454,6457,6459,6461,6463,6465],{"class":1077,"line":1425},[1075,6455,6456],{"class":1572},"  await",[1075,6458,6400],{"class":1579},[1075,6460,2686],{"class":1088},[1075,6462,6240],{"class":1653},[1075,6464,2683],{"class":2682},[1075,6466,1597],{"class":1088},[1075,6468,6469],{"class":1077,"line":1445},[1075,6470,6471],{"class":1088},"};\n",[1075,6473,6474],{"class":1077,"line":1466},[1075,6475,1642],{"emptyLinePlaceholder":1641},[1075,6477,6478,6481,6483,6485,6487],{"class":1077,"line":1485},[1075,6479,6480],{"class":1653},"onMounted",[1075,6482,1657],{"class":1656},[1075,6484,2683],{"class":1088},[1075,6486,2601],{"class":2600},[1075,6488,1176],{"class":1088},[1075,6490,6491,6494,6496],{"class":1077,"line":1506},[1075,6492,6493],{"class":1653},"  initialize",[1075,6495,2683],{"class":2682},[1075,6497,1597],{"class":1088},[1075,6499,6500,6502,6504],{"class":1077,"line":1527},[1075,6501,2082],{"class":1088},[1075,6503,1766],{"class":1656},[1075,6505,1597],{"class":1088},[1075,6507,6508,6510,6512],{"class":1077,"line":1546},[1075,6509,6309],{"class":1088},[1075,6511,6324],{"class":6185},[1075,6513,6189],{"class":1088},[1035,6515,6517],{"id":6516},"vue-state-management-with-pinia","Vue State Management with Pinia",[1065,6519,6521],{"className":1558,"code":6520,"language":1560,"meta":1070,"style":1070},"// frontend/js/stores/auth.js\nimport { defineStore } from 'pinia';\nimport { ref, computed } from 'vue';\nimport api from '@/utils/api';\n\nexport const useAuthStore = defineStore('auth', () => {\n  // State\n  const user = ref(null);\n  const token = ref(localStorage.getItem('auth-token'));\n  const loading = ref(true);\n  \n  // Getters\n  const isAuthenticated = computed(() => !!user.value);\n  \n  // Actions\n  const initialize = async () => {\n    if (token.value) {\n      try {\n        const response = await api.get('/auth/user/');\n        user.value = response.data;\n      } catch (error) {\n        token.value = null;\n        localStorage.removeItem('auth-token');\n      }\n    }\n    loading.value = false;\n  };\n  \n  const login = async (credentials) => {\n    try {\n      const response = await api.post('/auth/login/', credentials);\n      const { user: userData, token: authToken } = response.data;\n      \n      user.value = userData;\n      token.value = authToken;\n      localStorage.setItem('auth-token', authToken);\n      \n      // Set default authorization header\n      api.defaults.headers.common['Authorization'] = `Bearer ${authToken}`;\n      \n      return { success: true };\n    } catch (error) {\n      return {\n        success: false,\n        error: error.response?.data?.message || 'Login failed'\n      };\n    }\n  };\n  \n  const logout = async () => {\n    try {\n      await api.post('/auth/logout/');\n    } catch (error) {\n      // Continue with logout\n    }\n    \n    user.value = null;\n    token.value = null;\n    localStorage.removeItem('auth-token');\n    delete api.defaults.headers.common['Authorization'];\n  };\n  \n  return {\n    user,\n    token,\n    loading,\n    isAuthenticated,\n    initialize,\n    login,\n    logout\n  };\n});\n",[1072,6522,6523,6528,6549,6575,6592,6596,6625,6630,6649,6683,6702,6706,6711,6740,6744,6749,6765,6781,6788,6816,6835,6850,6865,6887,6891,6895,6910,6914,6918,6939,6946,6978,7013,7017,7031,7045,7071,7075,7080,7124,7128,7142,7156,7162,7173,7202,7207,7211,7215,7219,7236,7242,7265,7279,7284,7288,7292,7307,7322,7343,7374,7378,7382,7388,7394,7400,7406,7413,7420,7427,7432,7436],{"__ignoreMap":1070},[1075,6524,6525],{"class":1077,"line":1078},[1075,6526,6527],{"class":1081},"// frontend/js/stores/auth.js\n",[1075,6529,6530,6532,6534,6537,6539,6541,6543,6545,6547],{"class":1077,"line":1085},[1075,6531,1573],{"class":1572},[1075,6533,1576],{"class":1088},[1075,6535,6536],{"class":1579}," defineStore",[1075,6538,1583],{"class":1088},[1075,6540,1586],{"class":1572},[1075,6542,1589],{"class":1109},[1075,6544,5265],{"class":1113},[1075,6546,1594],{"class":1109},[1075,6548,1597],{"class":1088},[1075,6550,6551,6553,6555,6558,6560,6563,6565,6567,6569,6571,6573],{"class":1077,"line":1092},[1075,6552,1573],{"class":1572},[1075,6554,1576],{"class":1088},[1075,6556,6557],{"class":1579}," ref",[1075,6559,1756],{"class":1088},[1075,6561,6562],{"class":1579}," computed",[1075,6564,1583],{"class":1088},[1075,6566,1586],{"class":1572},[1075,6568,1589],{"class":1109},[1075,6570,5226],{"class":1113},[1075,6572,1594],{"class":1109},[1075,6574,1597],{"class":1088},[1075,6576,6577,6579,6581,6583,6585,6588,6590],{"class":1077,"line":1122},[1075,6578,1573],{"class":1572},[1075,6580,2540],{"class":1579},[1075,6582,1586],{"class":1572},[1075,6584,1589],{"class":1109},[1075,6586,6587],{"class":1113},"@/utils/api",[1075,6589,1594],{"class":1109},[1075,6591,1597],{"class":1088},[1075,6593,6594],{"class":1077,"line":1143},[1075,6595,1642],{"emptyLinePlaceholder":1641},[1075,6597,6598,6600,6602,6604,6606,6608,6610,6612,6615,6617,6619,6621,6623],{"class":1077,"line":1164},[1075,6599,1647],{"class":1572},[1075,6601,2563],{"class":2562},[1075,6603,2566],{"class":1579},[1075,6605,2569],{"class":1088},[1075,6607,6536],{"class":1653},[1075,6609,1657],{"class":1656},[1075,6611,1594],{"class":1109},[1075,6613,6614],{"class":1113},"auth",[1075,6616,1594],{"class":1109},[1075,6618,1756],{"class":1088},[1075,6620,2663],{"class":1088},[1075,6622,2601],{"class":2600},[1075,6624,1176],{"class":1088},[1075,6626,6627],{"class":1077,"line":1179},[1075,6628,6629],{"class":1081},"  // State\n",[1075,6631,6632,6634,6636,6638,6640,6642,6645,6647],{"class":1077,"line":1202},[1075,6633,4067],{"class":2562},[1075,6635,2719],{"class":1579},[1075,6637,2569],{"class":1088},[1075,6639,6557],{"class":1653},[1075,6641,1657],{"class":2682},[1075,6643,6644],{"class":2616},"null",[1075,6646,1766],{"class":2682},[1075,6648,1597],{"class":1088},[1075,6650,6651,6653,6655,6657,6659,6661,6664,6666,6669,6671,6673,6676,6678,6681],{"class":1077,"line":1223},[1075,6652,4067],{"class":2562},[1075,6654,2675],{"class":1579},[1075,6656,2569],{"class":1088},[1075,6658,6557],{"class":1653},[1075,6660,1657],{"class":2682},[1075,6662,6663],{"class":1579},"localStorage",[1075,6665,2686],{"class":1088},[1075,6667,6668],{"class":1653},"getItem",[1075,6670,1657],{"class":2682},[1075,6672,1594],{"class":1109},[1075,6674,6675],{"class":1113},"auth-token",[1075,6677,1594],{"class":1109},[1075,6679,6680],{"class":2682},"))",[1075,6682,1597],{"class":1088},[1075,6684,6685,6687,6689,6691,6693,6695,6698,6700],{"class":1077,"line":1243},[1075,6686,4067],{"class":2562},[1075,6688,2770],{"class":1579},[1075,6690,2569],{"class":1088},[1075,6692,6557],{"class":1653},[1075,6694,1657],{"class":2682},[1075,6696,6697],{"class":1718},"true",[1075,6699,1766],{"class":2682},[1075,6701,1597],{"class":1088},[1075,6703,6704],{"class":1077,"line":1249},[1075,6705,1683],{"class":2982},[1075,6707,6708],{"class":1077,"line":1263},[1075,6709,6710],{"class":1081},"  // Getters\n",[1075,6712,6713,6715,6718,6720,6722,6724,6726,6728,6730,6732,6734,6736,6738],{"class":1077,"line":1284},[1075,6714,4067],{"class":2562},[1075,6716,6717],{"class":1579}," isAuthenticated",[1075,6719,2569],{"class":1088},[1075,6721,6562],{"class":1653},[1075,6723,1657],{"class":2682},[1075,6725,2683],{"class":1088},[1075,6727,2601],{"class":2600},[1075,6729,4636],{"class":2616},[1075,6731,3380],{"class":1579},[1075,6733,2686],{"class":1088},[1075,6735,4096],{"class":1579},[1075,6737,1766],{"class":2682},[1075,6739,1597],{"class":1088},[1075,6741,6742],{"class":1077,"line":1304},[1075,6743,1683],{"class":2982},[1075,6745,6746],{"class":1077,"line":1325},[1075,6747,6748],{"class":1081},"  // Actions\n",[1075,6750,6751,6753,6755,6757,6759,6761,6763],{"class":1077,"line":1346},[1075,6752,4067],{"class":2562},[1075,6754,6421],{"class":6440},[1075,6756,2569],{"class":1088},[1075,6758,2660],{"class":2562},[1075,6760,2663],{"class":1088},[1075,6762,2601],{"class":2600},[1075,6764,1176],{"class":1088},[1075,6766,6767,6769,6771,6773,6775,6777,6779],{"class":1077,"line":1367},[1075,6768,4219],{"class":1572},[1075,6770,2604],{"class":2682},[1075,6772,2689],{"class":1579},[1075,6774,2686],{"class":1088},[1075,6776,4096],{"class":1579},[1075,6778,1766],{"class":2682},[1075,6780,1176],{"class":1088},[1075,6782,6783,6786],{"class":1077,"line":1386},[1075,6784,6785],{"class":1572},"      try",[1075,6787,1176],{"class":1088},[1075,6789,6790,6792,6794,6796,6798,6800,6802,6804,6806,6808,6810,6812,6814],{"class":1077,"line":1391},[1075,6791,2672],{"class":2562},[1075,6793,2924],{"class":1579},[1075,6795,2569],{"class":1088},[1075,6797,2724],{"class":1572},[1075,6799,2540],{"class":1579},[1075,6801,2686],{"class":1088},[1075,6803,2731],{"class":1653},[1075,6805,1657],{"class":2682},[1075,6807,1594],{"class":1109},[1075,6809,2738],{"class":1113},[1075,6811,1594],{"class":1109},[1075,6813,1766],{"class":2682},[1075,6815,1597],{"class":1088},[1075,6817,6818,6821,6823,6825,6827,6829,6831,6833],{"class":1077,"line":1405},[1075,6819,6820],{"class":1579},"        user",[1075,6822,2686],{"class":1088},[1075,6824,4096],{"class":1579},[1075,6826,2569],{"class":1088},[1075,6828,2924],{"class":1579},[1075,6830,2686],{"class":1088},[1075,6832,2765],{"class":1579},[1075,6834,1597],{"class":1088},[1075,6836,6837,6840,6842,6844,6846,6848],{"class":1077,"line":1425},[1075,6838,6839],{"class":1088},"      }",[1075,6841,2789],{"class":1572},[1075,6843,2604],{"class":2682},[1075,6845,2794],{"class":1579},[1075,6847,1766],{"class":2682},[1075,6849,1176],{"class":1088},[1075,6851,6852,6855,6857,6859,6861,6863],{"class":1077,"line":1445},[1075,6853,6854],{"class":1579},"        token",[1075,6856,2686],{"class":1088},[1075,6858,4096],{"class":1579},[1075,6860,2569],{"class":1088},[1075,6862,2617],{"class":2616},[1075,6864,1597],{"class":1088},[1075,6866,6867,6870,6872,6875,6877,6879,6881,6883,6885],{"class":1077,"line":1466},[1075,6868,6869],{"class":1579},"        localStorage",[1075,6871,2686],{"class":1088},[1075,6873,6874],{"class":1653},"removeItem",[1075,6876,1657],{"class":2682},[1075,6878,1594],{"class":1109},[1075,6880,6675],{"class":1113},[1075,6882,1594],{"class":1109},[1075,6884,1766],{"class":2682},[1075,6886,1597],{"class":1088},[1075,6888,6889],{"class":1077,"line":1485},[1075,6890,1798],{"class":1088},[1075,6892,6893],{"class":1077,"line":1506},[1075,6894,1803],{"class":1088},[1075,6896,6897,6900,6902,6904,6906,6908],{"class":1077,"line":1527},[1075,6898,6899],{"class":1579},"    loading",[1075,6901,2686],{"class":1088},[1075,6903,4096],{"class":1579},[1075,6905,2569],{"class":1088},[1075,6907,2775],{"class":1718},[1075,6909,1597],{"class":1088},[1075,6911,6912],{"class":1077,"line":1546},[1075,6913,3690],{"class":1088},[1075,6915,6916],{"class":1077,"line":1552},[1075,6917,1683],{"class":2982},[1075,6919,6920,6922,6925,6927,6929,6931,6933,6935,6937],{"class":1077,"line":1906},[1075,6921,4067],{"class":2562},[1075,6923,6924],{"class":6440}," login",[1075,6926,2569],{"class":1088},[1075,6928,2660],{"class":2562},[1075,6930,2604],{"class":1088},[1075,6932,2903],{"class":2589},[1075,6934,1766],{"class":1088},[1075,6936,2601],{"class":2600},[1075,6938,1176],{"class":1088},[1075,6940,6941,6944],{"class":1077,"line":1916},[1075,6942,6943],{"class":1572},"    try",[1075,6945,1176],{"class":1088},[1075,6947,6948,6950,6952,6954,6956,6958,6960,6962,6964,6966,6968,6970,6972,6974,6976],{"class":1077,"line":1947},[1075,6949,4447],{"class":2562},[1075,6951,2924],{"class":1579},[1075,6953,2569],{"class":1088},[1075,6955,2724],{"class":1572},[1075,6957,2540],{"class":1579},[1075,6959,2686],{"class":1088},[1075,6961,2935],{"class":1653},[1075,6963,1657],{"class":2682},[1075,6965,1594],{"class":1109},[1075,6967,2942],{"class":1113},[1075,6969,1594],{"class":1109},[1075,6971,1756],{"class":1088},[1075,6973,2949],{"class":1579},[1075,6975,1766],{"class":2682},[1075,6977,1597],{"class":1088},[1075,6979,6980,6982,6984,6987,6989,6992,6994,6996,6998,7001,7003,7005,7007,7009,7011],{"class":1077,"line":1978},[1075,6981,4447],{"class":2562},[1075,6983,1576],{"class":1088},[1075,6985,2719],{"class":6986},"skjlz",[1075,6988,1106],{"class":1088},[1075,6990,6991],{"class":1579}," userData",[1075,6993,1756],{"class":1088},[1075,6995,2675],{"class":6986},[1075,6997,1106],{"class":1088},[1075,6999,7000],{"class":1579}," authToken",[1075,7002,1583],{"class":1088},[1075,7004,2569],{"class":1088},[1075,7006,2924],{"class":1579},[1075,7008,2686],{"class":1088},[1075,7010,2765],{"class":1579},[1075,7012,1597],{"class":1088},[1075,7014,7015],{"class":1077,"line":2009},[1075,7016,2367],{"class":2982},[1075,7018,7019,7021,7023,7025,7027,7029],{"class":1077,"line":2040},[1075,7020,2611],{"class":1579},[1075,7022,2686],{"class":1088},[1075,7024,4096],{"class":1579},[1075,7026,2569],{"class":1088},[1075,7028,6991],{"class":1579},[1075,7030,1597],{"class":1088},[1075,7032,7033,7035,7037,7039,7041,7043],{"class":1077,"line":2069},[1075,7034,2624],{"class":1579},[1075,7036,2686],{"class":1088},[1075,7038,4096],{"class":1579},[1075,7040,2569],{"class":1088},[1075,7042,7000],{"class":1579},[1075,7044,1597],{"class":1088},[1075,7046,7047,7050,7052,7055,7057,7059,7061,7063,7065,7067,7069],{"class":1077,"line":2074},[1075,7048,7049],{"class":1579},"      localStorage",[1075,7051,2686],{"class":1088},[1075,7053,7054],{"class":1653},"setItem",[1075,7056,1657],{"class":2682},[1075,7058,1594],{"class":1109},[1075,7060,6675],{"class":1113},[1075,7062,1594],{"class":1109},[1075,7064,1756],{"class":1088},[1075,7066,7000],{"class":1579},[1075,7068,1766],{"class":2682},[1075,7070,1597],{"class":1088},[1075,7072,7073],{"class":1077,"line":2079},[1075,7074,2367],{"class":2982},[1075,7076,7077],{"class":1077,"line":2440},[1075,7078,7079],{"class":1081},"      // Set default authorization header\n",[1075,7081,7082,7085,7087,7089,7091,7093,7095,7097,7099,7101,7103,7105,7107,7109,7111,7113,7115,7118,7120,7122],{"class":1077,"line":2446},[1075,7083,7084],{"class":1579},"      api",[1075,7086,2686],{"class":1088},[1075,7088,3013],{"class":1579},[1075,7090,2686],{"class":1088},[1075,7092,3018],{"class":1579},[1075,7094,2686],{"class":1088},[1075,7096,3023],{"class":1579},[1075,7098,3026],{"class":2682},[1075,7100,1594],{"class":1109},[1075,7102,3031],{"class":1113},[1075,7104,1594],{"class":1109},[1075,7106,3036],{"class":2682},[1075,7108,2569],{"class":1088},[1075,7110,3041],{"class":1109},[1075,7112,3044],{"class":1113},[1075,7114,3048],{"class":3047},[1075,7116,7117],{"class":3051},"authToken",[1075,7119,2082],{"class":3047},[1075,7121,3056],{"class":1109},[1075,7123,1597],{"class":1088},[1075,7125,7126],{"class":1077,"line":2452},[1075,7127,2367],{"class":2982},[1075,7129,7130,7132,7134,7136,7138,7140],{"class":1077,"line":2458},[1075,7131,4477],{"class":1572},[1075,7133,1576],{"class":1088},[1075,7135,3072],{"class":1664},[1075,7137,1106],{"class":1088},[1075,7139,1719],{"class":1718},[1075,7141,3079],{"class":1088},[1075,7143,7144,7146,7148,7150,7152,7154],{"class":1077,"line":2463},[1075,7145,3405],{"class":1088},[1075,7147,2789],{"class":1572},[1075,7149,2604],{"class":2682},[1075,7151,2794],{"class":1579},[1075,7153,1766],{"class":2682},[1075,7155,1176],{"class":1088},[1075,7157,7158,7160],{"class":1077,"line":2468},[1075,7159,4477],{"class":1572},[1075,7161,1176],{"class":1088},[1075,7163,7164,7167,7169,7171],{"class":1077,"line":2473},[1075,7165,7166],{"class":1664},"        success",[1075,7168,1106],{"class":1088},[1075,7170,2775],{"class":1718},[1075,7172,1119],{"class":1088},[1075,7174,7175,7178,7180,7182,7184,7186,7188,7190,7192,7194,7196,7198,7200],{"class":1077,"line":3168},[1075,7176,7177],{"class":1664},"        error",[1075,7179,1106],{"class":1088},[1075,7181,3125],{"class":1579},[1075,7183,2686],{"class":1088},[1075,7185,3130],{"class":1579},[1075,7187,3133],{"class":1088},[1075,7189,2765],{"class":1579},[1075,7191,3133],{"class":1088},[1075,7193,3140],{"class":1579},[1075,7195,3143],{"class":2616},[1075,7197,1589],{"class":1109},[1075,7199,3148],{"class":1113},[1075,7201,1882],{"class":1109},[1075,7203,7204],{"class":1077,"line":3173},[1075,7205,7206],{"class":1088},"      };\n",[1075,7208,7209],{"class":1077,"line":3179},[1075,7210,1803],{"class":1088},[1075,7212,7213],{"class":1077,"line":3195},[1075,7214,3690],{"class":1088},[1075,7216,7217],{"class":1077,"line":3202},[1075,7218,1683],{"class":2982},[1075,7220,7221,7223,7226,7228,7230,7232,7234],{"class":1077,"line":3227},[1075,7222,4067],{"class":2562},[1075,7224,7225],{"class":6440}," logout",[1075,7227,2569],{"class":1088},[1075,7229,2660],{"class":2562},[1075,7231,2663],{"class":1088},[1075,7233,2601],{"class":2600},[1075,7235,1176],{"class":1088},[1075,7237,7238,7240],{"class":1077,"line":3242},[1075,7239,6943],{"class":1572},[1075,7241,1176],{"class":1088},[1075,7243,7244,7247,7249,7251,7253,7255,7257,7259,7261,7263],{"class":1077,"line":3248},[1075,7245,7246],{"class":1572},"      await",[1075,7248,2540],{"class":1579},[1075,7250,2686],{"class":1088},[1075,7252,2935],{"class":1653},[1075,7254,1657],{"class":2682},[1075,7256,1594],{"class":1109},[1075,7258,3218],{"class":1113},[1075,7260,1594],{"class":1109},[1075,7262,1766],{"class":2682},[1075,7264,1597],{"class":1088},[1075,7266,7267,7269,7271,7273,7275,7277],{"class":1077,"line":3253},[1075,7268,3405],{"class":1088},[1075,7270,2789],{"class":1572},[1075,7272,2604],{"class":2682},[1075,7274,2794],{"class":1579},[1075,7276,1766],{"class":2682},[1075,7278,1176],{"class":1088},[1075,7280,7281],{"class":1077,"line":3259},[1075,7282,7283],{"class":1081},"      // Continue with logout\n",[1075,7285,7286],{"class":1077,"line":3289},[1075,7287,1803],{"class":1088},[1075,7289,7290],{"class":1077,"line":3321},[1075,7291,3638],{"class":2982},[1075,7293,7294,7297,7299,7301,7303,7305],{"class":1077,"line":3326},[1075,7295,7296],{"class":1579},"    user",[1075,7298,2686],{"class":1088},[1075,7300,4096],{"class":1579},[1075,7302,2569],{"class":1088},[1075,7304,2617],{"class":2616},[1075,7306,1597],{"class":1088},[1075,7308,7309,7312,7314,7316,7318,7320],{"class":1077,"line":3331},[1075,7310,7311],{"class":1579},"    token",[1075,7313,2686],{"class":1088},[1075,7315,4096],{"class":1579},[1075,7317,2569],{"class":1088},[1075,7319,2617],{"class":2616},[1075,7321,1597],{"class":1088},[1075,7323,7324,7327,7329,7331,7333,7335,7337,7339,7341],{"class":1077,"line":3337},[1075,7325,7326],{"class":1579},"    localStorage",[1075,7328,2686],{"class":1088},[1075,7330,6874],{"class":1653},[1075,7332,1657],{"class":2682},[1075,7334,1594],{"class":1109},[1075,7336,6675],{"class":1113},[1075,7338,1594],{"class":1109},[1075,7340,1766],{"class":2682},[1075,7342,1597],{"class":1088},[1075,7344,7345,7348,7350,7352,7354,7356,7358,7360,7362,7364,7366,7368,7370,7372],{"class":1077,"line":3356},[1075,7346,7347],{"class":2616},"    delete",[1075,7349,2540],{"class":1579},[1075,7351,2686],{"class":1088},[1075,7353,3013],{"class":1579},[1075,7355,2686],{"class":1088},[1075,7357,3018],{"class":1579},[1075,7359,2686],{"class":1088},[1075,7361,3023],{"class":1579},[1075,7363,3026],{"class":2682},[1075,7365,1594],{"class":1109},[1075,7367,3031],{"class":1113},[1075,7369,1594],{"class":1109},[1075,7371,3036],{"class":2682},[1075,7373,1597],{"class":1088},[1075,7375,7376],{"class":1077,"line":3397},[1075,7377,3690],{"class":1088},[1075,7379,7380],{"class":1077,"line":3402},[1075,7381,1683],{"class":2982},[1075,7383,7384,7386],{"class":1077,"line":3412},[1075,7385,4147],{"class":1572},[1075,7387,1176],{"class":1088},[1075,7389,7390,7392],{"class":1077,"line":3418},[1075,7391,7296],{"class":1579},[1075,7393,1119],{"class":1088},[1075,7395,7396,7398],{"class":1077,"line":3435},[1075,7397,7311],{"class":1579},[1075,7399,1119],{"class":1088},[1075,7401,7402,7404],{"class":1077,"line":3471},[1075,7403,6899],{"class":1579},[1075,7405,1119],{"class":1088},[1075,7407,7408,7411],{"class":1077,"line":3476},[1075,7409,7410],{"class":1579},"    isAuthenticated",[1075,7412,1119],{"class":1088},[1075,7414,7415,7418],{"class":1077,"line":3482},[1075,7416,7417],{"class":1579},"    initialize",[1075,7419,1119],{"class":1088},[1075,7421,7422,7425],{"class":1077,"line":3489},[1075,7423,7424],{"class":1579},"    login",[1075,7426,1119],{"class":1088},[1075,7428,7429],{"class":1077,"line":3494},[1075,7430,7431],{"class":1579},"    logout\n",[1075,7433,7434],{"class":1077,"line":3500},[1075,7435,3690],{"class":1088},[1075,7437,7438,7440,7442],{"class":1077,"line":3858},[1075,7439,2082],{"class":1088},[1075,7441,1766],{"class":1656},[1075,7443,1597],{"class":1088},[1035,7445,7447],{"id":7446},"vue-composables-for-api-integration","Vue Composables for API Integration",[1065,7449,7451],{"className":1558,"code":7450,"language":1560,"meta":1070,"style":1070},"// frontend/js/composables/useBlog.js\nimport { ref, computed } from 'vue';\nimport { useAsyncState } from '@vueuse/core';\nimport api from '@/utils/api';\n\nexport function useBlogPosts() {\n  const { state: posts, isLoading, error, execute } = useAsyncState(\n    () => api.get('/blog/posts/').then(res => res.data),\n    [],\n    { immediate: true }\n  );\n  \n  const refresh = () => execute();\n  \n  return {\n    posts,\n    loading: isLoading,\n    error,\n    refresh\n  };\n}\n\nexport function useBlogPost(slug) {\n  const { state: post, isLoading, error, execute } = useAsyncState(\n    () => api.get(`/blog/posts/${slug}/`).then(res => res.data),\n    null,\n    { immediate: false }\n  );\n  \n  const load = () => execute();\n  \n  return {\n    post,\n    loading: isLoading,\n    error,\n    load\n  };\n}\n\nexport function useBlogMutations() {\n  const creating = ref(false);\n  const updating = ref(false);\n  const deleting = ref(false);\n  \n  const createPost = async (postData) => {\n    creating.value = true;\n    try {\n      const response = await api.post('/blog/posts/', postData);\n      return { success: true, data: response.data };\n    } catch (error) {\n      return { success: false, error: error.response?.data };\n    } finally {\n      creating.value = false;\n    }\n  };\n  \n  const updatePost = async (id, postData) => {\n    updating.value = true;\n    try {\n      const response = await api.put(`/blog/posts/${id}/`, postData);\n      return { success: true, data: response.data };\n    } catch (error) {\n      return { success: false, error: error.response?.data };\n    } finally {\n      updating.value = false;\n    }\n  };\n  \n  const deletePost = async (id) => {\n    deleting.value = true;\n    try {\n      await api.delete(`/blog/posts/${id}/`);\n      return { success: true };\n    } catch (error) {\n      return { success: false, error: error.response?.data };\n    } finally {\n      deleting.value = false;\n    }\n  };\n  \n  return {\n    creating,\n    updating,\n    deleting,\n    createPost,\n    updatePost,\n    deletePost\n  };\n}\n",[1072,7452,7453,7458,7482,7503,7519,7523,7535,7570,7616,7623,7638,7645,7649,7668,7672,7678,7685,7695,7702,7707,7711,7715,7719,7735,7768,7818,7825,7837,7843,7847,7866,7870,7876,7883,7893,7899,7904,7908,7912,7916,7929,7949,7968,7987,7991,8012,8027,8033,8065,8091,8105,8135,8144,8159,8163,8167,8171,8196,8211,8217,8257,8283,8297,8327,8335,8350,8354,8358,8362,8383,8398,8404,8435,8449,8463,8493,8501,8516,8520,8524,8528,8535,8542,8549,8556,8564,8572,8578,8583],{"__ignoreMap":1070},[1075,7454,7455],{"class":1077,"line":1078},[1075,7456,7457],{"class":1081},"// frontend/js/composables/useBlog.js\n",[1075,7459,7460,7462,7464,7466,7468,7470,7472,7474,7476,7478,7480],{"class":1077,"line":1085},[1075,7461,1573],{"class":1572},[1075,7463,1576],{"class":1088},[1075,7465,6557],{"class":1579},[1075,7467,1756],{"class":1088},[1075,7469,6562],{"class":1579},[1075,7471,1583],{"class":1088},[1075,7473,1586],{"class":1572},[1075,7475,1589],{"class":1109},[1075,7477,5226],{"class":1113},[1075,7479,1594],{"class":1109},[1075,7481,1597],{"class":1088},[1075,7483,7484,7486,7488,7491,7493,7495,7497,7499,7501],{"class":1077,"line":1092},[1075,7485,1573],{"class":1572},[1075,7487,1576],{"class":1088},[1075,7489,7490],{"class":1579}," useAsyncState",[1075,7492,1583],{"class":1088},[1075,7494,1586],{"class":1572},[1075,7496,1589],{"class":1109},[1075,7498,5303],{"class":1113},[1075,7500,1594],{"class":1109},[1075,7502,1597],{"class":1088},[1075,7504,7505,7507,7509,7511,7513,7515,7517],{"class":1077,"line":1122},[1075,7506,1573],{"class":1572},[1075,7508,2540],{"class":1579},[1075,7510,1586],{"class":1572},[1075,7512,1589],{"class":1109},[1075,7514,6587],{"class":1113},[1075,7516,1594],{"class":1109},[1075,7518,1597],{"class":1088},[1075,7520,7521],{"class":1077,"line":1143},[1075,7522,1642],{"emptyLinePlaceholder":1641},[1075,7524,7525,7527,7529,7531,7533],{"class":1077,"line":1164},[1075,7526,1647],{"class":1572},[1075,7528,4390],{"class":2562},[1075,7530,4393],{"class":1653},[1075,7532,2683],{"class":1088},[1075,7534,1176],{"class":1088},[1075,7536,7537,7539,7541,7543,7545,7548,7550,7553,7555,7557,7559,7562,7564,7566,7568],{"class":1077,"line":1179},[1075,7538,4067],{"class":2562},[1075,7540,1576],{"class":1088},[1075,7542,3460],{"class":6986},[1075,7544,1106],{"class":1088},[1075,7546,7547],{"class":1579}," posts",[1075,7549,1756],{"class":1088},[1075,7551,7552],{"class":1579}," isLoading",[1075,7554,1756],{"class":1088},[1075,7556,3125],{"class":1579},[1075,7558,1756],{"class":1088},[1075,7560,7561],{"class":1579}," execute",[1075,7563,1583],{"class":1088},[1075,7565,2569],{"class":1088},[1075,7567,7490],{"class":1653},[1075,7569,2574],{"class":2682},[1075,7571,7572,7575,7577,7579,7581,7583,7585,7587,7589,7591,7593,7595,7598,7600,7603,7605,7608,7610,7612,7614],{"class":1077,"line":1202},[1075,7573,7574],{"class":1088},"    ()",[1075,7576,2601],{"class":2600},[1075,7578,2540],{"class":1579},[1075,7580,2686],{"class":1088},[1075,7582,2731],{"class":1653},[1075,7584,1657],{"class":2682},[1075,7586,1594],{"class":1109},[1075,7588,4466],{"class":1113},[1075,7590,1594],{"class":1109},[1075,7592,1766],{"class":2682},[1075,7594,2686],{"class":1088},[1075,7596,7597],{"class":1653},"then",[1075,7599,1657],{"class":2682},[1075,7601,7602],{"class":2589},"res",[1075,7604,2601],{"class":2600},[1075,7606,7607],{"class":1579}," res",[1075,7609,2686],{"class":1088},[1075,7611,2765],{"class":1579},[1075,7613,1766],{"class":2682},[1075,7615,1119],{"class":1088},[1075,7617,7618,7621],{"class":1077,"line":1223},[1075,7619,7620],{"class":2682},"    []",[1075,7622,1119],{"class":1088},[1075,7624,7625,7628,7631,7633,7635],{"class":1077,"line":1243},[1075,7626,7627],{"class":1088},"    {",[1075,7629,7630],{"class":1664}," immediate",[1075,7632,1106],{"class":1088},[1075,7634,1719],{"class":1718},[1075,7636,7637],{"class":1088}," }\n",[1075,7639,7640,7643],{"class":1077,"line":1249},[1075,7641,7642],{"class":2682},"  )",[1075,7644,1597],{"class":1088},[1075,7646,7647],{"class":1077,"line":1263},[1075,7648,1683],{"class":2982},[1075,7650,7651,7653,7656,7658,7660,7662,7664,7666],{"class":1077,"line":1284},[1075,7652,4067],{"class":2562},[1075,7654,7655],{"class":6440}," refresh",[1075,7657,2569],{"class":1088},[1075,7659,2663],{"class":1088},[1075,7661,2601],{"class":2600},[1075,7663,7561],{"class":1653},[1075,7665,2683],{"class":2682},[1075,7667,1597],{"class":1088},[1075,7669,7670],{"class":1077,"line":1304},[1075,7671,1683],{"class":2982},[1075,7673,7674,7676],{"class":1077,"line":1325},[1075,7675,4147],{"class":1572},[1075,7677,1176],{"class":1088},[1075,7679,7680,7683],{"class":1077,"line":1346},[1075,7681,7682],{"class":1579},"    posts",[1075,7684,1119],{"class":1088},[1075,7686,7687,7689,7691,7693],{"class":1077,"line":1367},[1075,7688,6899],{"class":1664},[1075,7690,1106],{"class":1088},[1075,7692,7552],{"class":1579},[1075,7694,1119],{"class":1088},[1075,7696,7697,7700],{"class":1077,"line":1386},[1075,7698,7699],{"class":1579},"    error",[1075,7701,1119],{"class":1088},[1075,7703,7704],{"class":1077,"line":1391},[1075,7705,7706],{"class":1579},"    refresh\n",[1075,7708,7709],{"class":1077,"line":1405},[1075,7710,3690],{"class":1088},[1075,7712,7713],{"class":1077,"line":1425},[1075,7714,1555],{"class":1088},[1075,7716,7717],{"class":1077,"line":1445},[1075,7718,1642],{"emptyLinePlaceholder":1641},[1075,7720,7721,7723,7725,7727,7729,7731,7733],{"class":1077,"line":1466},[1075,7722,1647],{"class":1572},[1075,7724,4390],{"class":2562},[1075,7726,4515],{"class":1653},[1075,7728,1657],{"class":1088},[1075,7730,4520],{"class":2589},[1075,7732,1766],{"class":1088},[1075,7734,1176],{"class":1088},[1075,7736,7737,7739,7741,7743,7745,7748,7750,7752,7754,7756,7758,7760,7762,7764,7766],{"class":1077,"line":1485},[1075,7738,4067],{"class":2562},[1075,7740,1576],{"class":1088},[1075,7742,3460],{"class":6986},[1075,7744,1106],{"class":1088},[1075,7746,7747],{"class":1579}," post",[1075,7749,1756],{"class":1088},[1075,7751,7552],{"class":1579},[1075,7753,1756],{"class":1088},[1075,7755,3125],{"class":1579},[1075,7757,1756],{"class":1088},[1075,7759,7561],{"class":1579},[1075,7761,1583],{"class":1088},[1075,7763,2569],{"class":1088},[1075,7765,7490],{"class":1653},[1075,7767,2574],{"class":2682},[1075,7769,7770,7772,7774,7776,7778,7780,7782,7784,7786,7788,7790,7792,7794,7796,7798,7800,7802,7804,7806,7808,7810,7812,7814,7816],{"class":1077,"line":1506},[1075,7771,7574],{"class":1088},[1075,7773,2601],{"class":2600},[1075,7775,2540],{"class":1579},[1075,7777,2686],{"class":1088},[1075,7779,2731],{"class":1653},[1075,7781,1657],{"class":2682},[1075,7783,3056],{"class":1109},[1075,7785,4466],{"class":1113},[1075,7787,3048],{"class":3047},[1075,7789,4520],{"class":3051},[1075,7791,2082],{"class":3047},[1075,7793,4603],{"class":1113},[1075,7795,3056],{"class":1109},[1075,7797,1766],{"class":2682},[1075,7799,2686],{"class":1088},[1075,7801,7597],{"class":1653},[1075,7803,1657],{"class":2682},[1075,7805,7602],{"class":2589},[1075,7807,2601],{"class":2600},[1075,7809,7607],{"class":1579},[1075,7811,2686],{"class":1088},[1075,7813,2765],{"class":1579},[1075,7815,1766],{"class":2682},[1075,7817,1119],{"class":1088},[1075,7819,7820,7823],{"class":1077,"line":1527},[1075,7821,7822],{"class":2616},"    null",[1075,7824,1119],{"class":1088},[1075,7826,7827,7829,7831,7833,7835],{"class":1077,"line":1546},[1075,7828,7627],{"class":1088},[1075,7830,7630],{"class":1664},[1075,7832,1106],{"class":1088},[1075,7834,2775],{"class":1718},[1075,7836,7637],{"class":1088},[1075,7838,7839,7841],{"class":1077,"line":1552},[1075,7840,7642],{"class":2682},[1075,7842,1597],{"class":1088},[1075,7844,7845],{"class":1077,"line":1906},[1075,7846,1683],{"class":2982},[1075,7848,7849,7851,7854,7856,7858,7860,7862,7864],{"class":1077,"line":1916},[1075,7850,4067],{"class":2562},[1075,7852,7853],{"class":6440}," load",[1075,7855,2569],{"class":1088},[1075,7857,2663],{"class":1088},[1075,7859,2601],{"class":2600},[1075,7861,7561],{"class":1653},[1075,7863,2683],{"class":2682},[1075,7865,1597],{"class":1088},[1075,7867,7868],{"class":1077,"line":1947},[1075,7869,1683],{"class":2982},[1075,7871,7872,7874],{"class":1077,"line":1978},[1075,7873,4147],{"class":1572},[1075,7875,1176],{"class":1088},[1075,7877,7878,7881],{"class":1077,"line":2009},[1075,7879,7880],{"class":1579},"    post",[1075,7882,1119],{"class":1088},[1075,7884,7885,7887,7889,7891],{"class":1077,"line":2040},[1075,7886,6899],{"class":1664},[1075,7888,1106],{"class":1088},[1075,7890,7552],{"class":1579},[1075,7892,1119],{"class":1088},[1075,7894,7895,7897],{"class":1077,"line":2069},[1075,7896,7699],{"class":1579},[1075,7898,1119],{"class":1088},[1075,7900,7901],{"class":1077,"line":2074},[1075,7902,7903],{"class":1579},"    load\n",[1075,7905,7906],{"class":1077,"line":2079},[1075,7907,3690],{"class":1088},[1075,7909,7910],{"class":1077,"line":2440},[1075,7911,1555],{"class":1088},[1075,7913,7914],{"class":1077,"line":2446},[1075,7915,1642],{"emptyLinePlaceholder":1641},[1075,7917,7918,7920,7922,7925,7927],{"class":1077,"line":2452},[1075,7919,1647],{"class":1572},[1075,7921,4390],{"class":2562},[1075,7923,7924],{"class":1653}," useBlogMutations",[1075,7926,2683],{"class":1088},[1075,7928,1176],{"class":1088},[1075,7930,7931,7933,7936,7938,7940,7942,7945,7947],{"class":1077,"line":2458},[1075,7932,4067],{"class":2562},[1075,7934,7935],{"class":1579}," creating",[1075,7937,2569],{"class":1088},[1075,7939,6557],{"class":1653},[1075,7941,1657],{"class":2682},[1075,7943,7944],{"class":1718},"false",[1075,7946,1766],{"class":2682},[1075,7948,1597],{"class":1088},[1075,7950,7951,7953,7956,7958,7960,7962,7964,7966],{"class":1077,"line":2463},[1075,7952,4067],{"class":2562},[1075,7954,7955],{"class":1579}," updating",[1075,7957,2569],{"class":1088},[1075,7959,6557],{"class":1653},[1075,7961,1657],{"class":2682},[1075,7963,7944],{"class":1718},[1075,7965,1766],{"class":2682},[1075,7967,1597],{"class":1088},[1075,7969,7970,7972,7975,7977,7979,7981,7983,7985],{"class":1077,"line":2468},[1075,7971,4067],{"class":2562},[1075,7973,7974],{"class":1579}," deleting",[1075,7976,2569],{"class":1088},[1075,7978,6557],{"class":1653},[1075,7980,1657],{"class":2682},[1075,7982,7944],{"class":1718},[1075,7984,1766],{"class":2682},[1075,7986,1597],{"class":1088},[1075,7988,7989],{"class":1077,"line":2473},[1075,7990,1683],{"class":2982},[1075,7992,7993,7995,7998,8000,8002,8004,8006,8008,8010],{"class":1077,"line":3168},[1075,7994,4067],{"class":2562},[1075,7996,7997],{"class":6440}," createPost",[1075,7999,2569],{"class":1088},[1075,8001,2660],{"class":2562},[1075,8003,2604],{"class":1088},[1075,8005,4711],{"class":2589},[1075,8007,1766],{"class":1088},[1075,8009,2601],{"class":2600},[1075,8011,1176],{"class":1088},[1075,8013,8014,8017,8019,8021,8023,8025],{"class":1077,"line":3173},[1075,8015,8016],{"class":1579},"    creating",[1075,8018,2686],{"class":1088},[1075,8020,4096],{"class":1579},[1075,8022,2569],{"class":1088},[1075,8024,1719],{"class":1718},[1075,8026,1597],{"class":1088},[1075,8028,8029,8031],{"class":1077,"line":3179},[1075,8030,6943],{"class":1572},[1075,8032,1176],{"class":1088},[1075,8034,8035,8037,8039,8041,8043,8045,8047,8049,8051,8053,8055,8057,8059,8061,8063],{"class":1077,"line":3195},[1075,8036,4447],{"class":2562},[1075,8038,2924],{"class":1579},[1075,8040,2569],{"class":1088},[1075,8042,2724],{"class":1572},[1075,8044,2540],{"class":1579},[1075,8046,2686],{"class":1088},[1075,8048,2935],{"class":1653},[1075,8050,1657],{"class":2682},[1075,8052,1594],{"class":1109},[1075,8054,4466],{"class":1113},[1075,8056,1594],{"class":1109},[1075,8058,1756],{"class":1088},[1075,8060,4746],{"class":1579},[1075,8062,1766],{"class":2682},[1075,8064,1597],{"class":1088},[1075,8066,8067,8069,8071,8073,8075,8077,8079,8081,8083,8085,8087,8089],{"class":1077,"line":3202},[1075,8068,4477],{"class":1572},[1075,8070,1576],{"class":1088},[1075,8072,3072],{"class":1664},[1075,8074,1106],{"class":1088},[1075,8076,1719],{"class":1718},[1075,8078,1756],{"class":1088},[1075,8080,4894],{"class":1664},[1075,8082,1106],{"class":1088},[1075,8084,2924],{"class":1579},[1075,8086,2686],{"class":1088},[1075,8088,2765],{"class":1579},[1075,8090,3079],{"class":1088},[1075,8092,8093,8095,8097,8099,8101,8103],{"class":1077,"line":3227},[1075,8094,3405],{"class":1088},[1075,8096,2789],{"class":1572},[1075,8098,2604],{"class":2682},[1075,8100,2794],{"class":1579},[1075,8102,1766],{"class":2682},[1075,8104,1176],{"class":1088},[1075,8106,8107,8109,8111,8113,8115,8117,8119,8121,8123,8125,8127,8129,8131,8133],{"class":1077,"line":3242},[1075,8108,4477],{"class":1572},[1075,8110,1576],{"class":1088},[1075,8112,3072],{"class":1664},[1075,8114,1106],{"class":1088},[1075,8116,2775],{"class":1718},[1075,8118,1756],{"class":1088},[1075,8120,3125],{"class":1664},[1075,8122,1106],{"class":1088},[1075,8124,3125],{"class":1579},[1075,8126,2686],{"class":1088},[1075,8128,3130],{"class":1579},[1075,8130,3133],{"class":1088},[1075,8132,2765],{"class":1579},[1075,8134,3079],{"class":1088},[1075,8136,8137,8139,8142],{"class":1077,"line":3248},[1075,8138,3405],{"class":1088},[1075,8140,8141],{"class":1572}," finally",[1075,8143,1176],{"class":1088},[1075,8145,8146,8149,8151,8153,8155,8157],{"class":1077,"line":3253},[1075,8147,8148],{"class":1579},"      creating",[1075,8150,2686],{"class":1088},[1075,8152,4096],{"class":1579},[1075,8154,2569],{"class":1088},[1075,8156,2775],{"class":1718},[1075,8158,1597],{"class":1088},[1075,8160,8161],{"class":1077,"line":3259},[1075,8162,1803],{"class":1088},[1075,8164,8165],{"class":1077,"line":3289},[1075,8166,3690],{"class":1088},[1075,8168,8169],{"class":1077,"line":3321},[1075,8170,1683],{"class":2982},[1075,8172,8173,8175,8178,8180,8182,8184,8186,8188,8190,8192,8194],{"class":1077,"line":3326},[1075,8174,4067],{"class":2562},[1075,8176,8177],{"class":6440}," updatePost",[1075,8179,2569],{"class":1088},[1075,8181,2660],{"class":2562},[1075,8183,2604],{"class":1088},[1075,8185,4929],{"class":2589},[1075,8187,1756],{"class":1088},[1075,8189,4746],{"class":2589},[1075,8191,1766],{"class":1088},[1075,8193,2601],{"class":2600},[1075,8195,1176],{"class":1088},[1075,8197,8198,8201,8203,8205,8207,8209],{"class":1077,"line":3331},[1075,8199,8200],{"class":1579},"    updating",[1075,8202,2686],{"class":1088},[1075,8204,4096],{"class":1579},[1075,8206,2569],{"class":1088},[1075,8208,1719],{"class":1718},[1075,8210,1597],{"class":1088},[1075,8212,8213,8215],{"class":1077,"line":3337},[1075,8214,6943],{"class":1572},[1075,8216,1176],{"class":1088},[1075,8218,8219,8221,8223,8225,8227,8229,8231,8233,8235,8237,8239,8241,8243,8245,8247,8249,8251,8253,8255],{"class":1077,"line":3356},[1075,8220,4447],{"class":2562},[1075,8222,2924],{"class":1579},[1075,8224,2569],{"class":1088},[1075,8226,2724],{"class":1572},[1075,8228,2540],{"class":1579},[1075,8230,2686],{"class":1088},[1075,8232,4918],{"class":1653},[1075,8234,1657],{"class":2682},[1075,8236,3056],{"class":1109},[1075,8238,4466],{"class":1113},[1075,8240,3048],{"class":3047},[1075,8242,4929],{"class":3051},[1075,8244,2082],{"class":3047},[1075,8246,4603],{"class":1113},[1075,8248,3056],{"class":1109},[1075,8250,1756],{"class":1088},[1075,8252,4746],{"class":1579},[1075,8254,1766],{"class":2682},[1075,8256,1597],{"class":1088},[1075,8258,8259,8261,8263,8265,8267,8269,8271,8273,8275,8277,8279,8281],{"class":1077,"line":3397},[1075,8260,4477],{"class":1572},[1075,8262,1576],{"class":1088},[1075,8264,3072],{"class":1664},[1075,8266,1106],{"class":1088},[1075,8268,1719],{"class":1718},[1075,8270,1756],{"class":1088},[1075,8272,4894],{"class":1664},[1075,8274,1106],{"class":1088},[1075,8276,2924],{"class":1579},[1075,8278,2686],{"class":1088},[1075,8280,2765],{"class":1579},[1075,8282,3079],{"class":1088},[1075,8284,8285,8287,8289,8291,8293,8295],{"class":1077,"line":3402},[1075,8286,3405],{"class":1088},[1075,8288,2789],{"class":1572},[1075,8290,2604],{"class":2682},[1075,8292,2794],{"class":1579},[1075,8294,1766],{"class":2682},[1075,8296,1176],{"class":1088},[1075,8298,8299,8301,8303,8305,8307,8309,8311,8313,8315,8317,8319,8321,8323,8325],{"class":1077,"line":3412},[1075,8300,4477],{"class":1572},[1075,8302,1576],{"class":1088},[1075,8304,3072],{"class":1664},[1075,8306,1106],{"class":1088},[1075,8308,2775],{"class":1718},[1075,8310,1756],{"class":1088},[1075,8312,3125],{"class":1664},[1075,8314,1106],{"class":1088},[1075,8316,3125],{"class":1579},[1075,8318,2686],{"class":1088},[1075,8320,3130],{"class":1579},[1075,8322,3133],{"class":1088},[1075,8324,2765],{"class":1579},[1075,8326,3079],{"class":1088},[1075,8328,8329,8331,8333],{"class":1077,"line":3418},[1075,8330,3405],{"class":1088},[1075,8332,8141],{"class":1572},[1075,8334,1176],{"class":1088},[1075,8336,8337,8340,8342,8344,8346,8348],{"class":1077,"line":3435},[1075,8338,8339],{"class":1579},"      updating",[1075,8341,2686],{"class":1088},[1075,8343,4096],{"class":1579},[1075,8345,2569],{"class":1088},[1075,8347,2775],{"class":1718},[1075,8349,1597],{"class":1088},[1075,8351,8352],{"class":1077,"line":3471},[1075,8353,1803],{"class":1088},[1075,8355,8356],{"class":1077,"line":3476},[1075,8357,3690],{"class":1088},[1075,8359,8360],{"class":1077,"line":3482},[1075,8361,1683],{"class":2982},[1075,8363,8364,8366,8369,8371,8373,8375,8377,8379,8381],{"class":1077,"line":3489},[1075,8365,4067],{"class":2562},[1075,8367,8368],{"class":6440}," deletePost",[1075,8370,2569],{"class":1088},[1075,8372,2660],{"class":2562},[1075,8374,2604],{"class":1088},[1075,8376,4929],{"class":2589},[1075,8378,1766],{"class":1088},[1075,8380,2601],{"class":2600},[1075,8382,1176],{"class":1088},[1075,8384,8385,8388,8390,8392,8394,8396],{"class":1077,"line":3494},[1075,8386,8387],{"class":1579},"    deleting",[1075,8389,2686],{"class":1088},[1075,8391,4096],{"class":1579},[1075,8393,2569],{"class":1088},[1075,8395,1719],{"class":1718},[1075,8397,1597],{"class":1088},[1075,8399,8400,8402],{"class":1077,"line":3500},[1075,8401,6943],{"class":1572},[1075,8403,1176],{"class":1088},[1075,8405,8406,8408,8410,8412,8415,8417,8419,8421,8423,8425,8427,8429,8431,8433],{"class":1077,"line":3858},[1075,8407,7246],{"class":1572},[1075,8409,2540],{"class":1579},[1075,8411,2686],{"class":1088},[1075,8413,8414],{"class":1653},"delete",[1075,8416,1657],{"class":2682},[1075,8418,3056],{"class":1109},[1075,8420,4466],{"class":1113},[1075,8422,3048],{"class":3047},[1075,8424,4929],{"class":3051},[1075,8426,2082],{"class":3047},[1075,8428,4603],{"class":1113},[1075,8430,3056],{"class":1109},[1075,8432,1766],{"class":2682},[1075,8434,1597],{"class":1088},[1075,8436,8437,8439,8441,8443,8445,8447],{"class":1077,"line":3864},[1075,8438,4477],{"class":1572},[1075,8440,1576],{"class":1088},[1075,8442,3072],{"class":1664},[1075,8444,1106],{"class":1088},[1075,8446,1719],{"class":1718},[1075,8448,3079],{"class":1088},[1075,8450,8451,8453,8455,8457,8459,8461],{"class":1077,"line":3870},[1075,8452,3405],{"class":1088},[1075,8454,2789],{"class":1572},[1075,8456,2604],{"class":2682},[1075,8458,2794],{"class":1579},[1075,8460,1766],{"class":2682},[1075,8462,1176],{"class":1088},[1075,8464,8465,8467,8469,8471,8473,8475,8477,8479,8481,8483,8485,8487,8489,8491],{"class":1077,"line":3876},[1075,8466,4477],{"class":1572},[1075,8468,1576],{"class":1088},[1075,8470,3072],{"class":1664},[1075,8472,1106],{"class":1088},[1075,8474,2775],{"class":1718},[1075,8476,1756],{"class":1088},[1075,8478,3125],{"class":1664},[1075,8480,1106],{"class":1088},[1075,8482,3125],{"class":1579},[1075,8484,2686],{"class":1088},[1075,8486,3130],{"class":1579},[1075,8488,3133],{"class":1088},[1075,8490,2765],{"class":1579},[1075,8492,3079],{"class":1088},[1075,8494,8495,8497,8499],{"class":1077,"line":3882},[1075,8496,3405],{"class":1088},[1075,8498,8141],{"class":1572},[1075,8500,1176],{"class":1088},[1075,8502,8503,8506,8508,8510,8512,8514],{"class":1077,"line":3887},[1075,8504,8505],{"class":1579},"      deleting",[1075,8507,2686],{"class":1088},[1075,8509,4096],{"class":1579},[1075,8511,2569],{"class":1088},[1075,8513,2775],{"class":1718},[1075,8515,1597],{"class":1088},[1075,8517,8518],{"class":1077,"line":3892},[1075,8519,1803],{"class":1088},[1075,8521,8522],{"class":1077,"line":3897},[1075,8523,3690],{"class":1088},[1075,8525,8526],{"class":1077,"line":3902},[1075,8527,1683],{"class":2982},[1075,8529,8531,8533],{"class":1077,"line":8530},81,[1075,8532,4147],{"class":1572},[1075,8534,1176],{"class":1088},[1075,8536,8538,8540],{"class":1077,"line":8537},82,[1075,8539,8016],{"class":1579},[1075,8541,1119],{"class":1088},[1075,8543,8545,8547],{"class":1077,"line":8544},83,[1075,8546,8200],{"class":1579},[1075,8548,1119],{"class":1088},[1075,8550,8552,8554],{"class":1077,"line":8551},84,[1075,8553,8387],{"class":1579},[1075,8555,1119],{"class":1088},[1075,8557,8559,8562],{"class":1077,"line":8558},85,[1075,8560,8561],{"class":1579},"    createPost",[1075,8563,1119],{"class":1088},[1075,8565,8567,8570],{"class":1077,"line":8566},86,[1075,8568,8569],{"class":1579},"    updatePost",[1075,8571,1119],{"class":1088},[1075,8573,8575],{"class":1077,"line":8574},87,[1075,8576,8577],{"class":1579},"    deletePost\n",[1075,8579,8581],{"class":1077,"line":8580},88,[1075,8582,3690],{"class":1088},[1075,8584,8586],{"class":1077,"line":8585},89,[1075,8587,1555],{"class":1088},[1030,8589,8591],{"id":8590},"django-backend-configuration","Django Backend Configuration",[1035,8593,8595],{"id":8594},"api-views-for-frontend-integration","API Views for Frontend Integration",[1065,8597,8601],{"className":8598,"code":8599,"language":8600,"meta":1070,"style":1070},"language-python shiki shiki-themes material-theme-lighter vitesse-light vitesse-dark","# views/api.py\nfrom rest_framework import viewsets, status\nfrom rest_framework.decorators import action\nfrom rest_framework.response import Response\nfrom rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly\nfrom django.contrib.auth import authenticate, login, logout\nfrom django.contrib.auth.models import User\nfrom .models import BlogPost\nfrom .serializers import BlogPostSerializer, UserSerializer\n\nclass AuthViewSet(viewsets.ViewSet):\n    \"\"\"Authentication endpoints for frontend.\"\"\"\n    \n    def create(self, request):\n        \"\"\"Login endpoint.\"\"\"\n        username = request.data.get('username')\n        password = request.data.get('password')\n        \n        if not username or not password:\n            return Response(\n                {'message': 'Username and password required'},\n                status=status.HTTP_400_BAD_REQUEST\n            )\n        \n        user = authenticate(username=username, password=password)\n        if user:\n            login(request, user)\n            \n            # Generate or get token (if using token auth)\n            from rest_framework.authtoken.models import Token\n            token, created = Token.objects.get_or_create(user=user)\n            \n            return Response({\n                'user': UserSerializer(user).data,\n                'token': token.key\n            })\n        \n        return Response(\n            {'message': 'Invalid credentials'},\n            status=status.HTTP_401_UNAUTHORIZED\n        )\n    \n    @action(detail=False, methods=['post'])\n    def logout(self, request):\n        \"\"\"Logout endpoint.\"\"\"\n        logout(request)\n        return Response({'message': 'Logged out successfully'})\n    \n    @action(detail=False, methods=['get'], permission_classes=[IsAuthenticated])\n    def user(self, request):\n        \"\"\"Get current user info.\"\"\"\n        return Response(UserSerializer(request.user).data)\n\nclass BlogPostViewSet(viewsets.ModelViewSet):\n    \"\"\"Blog post CRUD operations.\"\"\"\n    queryset = BlogPost.objects.all()\n    serializer_class = BlogPostSerializer\n    permission_classes = [IsAuthenticatedOrReadOnly]\n    lookup_field = 'slug'\n    \n    def perform_create(self, serializer):\n        serializer.save(author=self.request.user)\n","python",[1072,8602,8603,8608,8626,8643,8659,8680,8711,8735,8749,8768,8772,8795,8808,8812,8833,8843,8872,8900,8904,8925,8935,8958,8973,8978,8982,9009,9017,9032,9037,9042,9063,9098,9102,9111,9136,9153,9158,9162,9171,9193,9207,9212,9216,9251,9267,9276,9287,9314,9318,9357,9373,9382,9407,9411,9429,9438,9460,9470,9485,9498,9502,9520],{"__ignoreMap":1070},[1075,8604,8605],{"class":1077,"line":1078},[1075,8606,8607],{"class":1081},"# views/api.py\n",[1075,8609,8610,8613,8616,8618,8621,8623],{"class":1077,"line":1085},[1075,8611,8612],{"class":1572},"from",[1075,8614,8615],{"class":1682}," rest_framework ",[1075,8617,1573],{"class":1572},[1075,8619,8620],{"class":1682}," viewsets",[1075,8622,1756],{"class":1088},[1075,8624,8625],{"class":1682}," status\n",[1075,8627,8628,8630,8633,8635,8638,8640],{"class":1077,"line":1092},[1075,8629,8612],{"class":1572},[1075,8631,8632],{"class":1682}," rest_framework",[1075,8634,2686],{"class":1088},[1075,8636,8637],{"class":1682},"decorators ",[1075,8639,1573],{"class":1572},[1075,8641,8642],{"class":1682}," action\n",[1075,8644,8645,8647,8649,8651,8654,8656],{"class":1077,"line":1122},[1075,8646,8612],{"class":1572},[1075,8648,8632],{"class":1682},[1075,8650,2686],{"class":1088},[1075,8652,8653],{"class":1682},"response ",[1075,8655,1573],{"class":1572},[1075,8657,8658],{"class":1682}," Response\n",[1075,8660,8661,8663,8665,8667,8670,8672,8675,8677],{"class":1077,"line":1143},[1075,8662,8612],{"class":1572},[1075,8664,8632],{"class":1682},[1075,8666,2686],{"class":1088},[1075,8668,8669],{"class":1682},"permissions ",[1075,8671,1573],{"class":1572},[1075,8673,8674],{"class":1682}," IsAuthenticated",[1075,8676,1756],{"class":1088},[1075,8678,8679],{"class":1682}," IsAuthenticatedOrReadOnly\n",[1075,8681,8682,8684,8687,8689,8692,8694,8697,8699,8702,8704,8706,8708],{"class":1077,"line":1164},[1075,8683,8612],{"class":1572},[1075,8685,8686],{"class":1682}," django",[1075,8688,2686],{"class":1088},[1075,8690,8691],{"class":1682},"contrib",[1075,8693,2686],{"class":1088},[1075,8695,8696],{"class":1682},"auth ",[1075,8698,1573],{"class":1572},[1075,8700,8701],{"class":1682}," authenticate",[1075,8703,1756],{"class":1088},[1075,8705,6924],{"class":1682},[1075,8707,1756],{"class":1088},[1075,8709,8710],{"class":1682}," logout\n",[1075,8712,8713,8715,8717,8719,8721,8723,8725,8727,8730,8732],{"class":1077,"line":1179},[1075,8714,8612],{"class":1572},[1075,8716,8686],{"class":1682},[1075,8718,2686],{"class":1088},[1075,8720,8691],{"class":1682},[1075,8722,2686],{"class":1088},[1075,8724,6614],{"class":1682},[1075,8726,2686],{"class":1088},[1075,8728,8729],{"class":1682},"models ",[1075,8731,1573],{"class":1572},[1075,8733,8734],{"class":1682}," User\n",[1075,8736,8737,8739,8742,8744,8746],{"class":1077,"line":1202},[1075,8738,8612],{"class":1572},[1075,8740,8741],{"class":1088}," .",[1075,8743,8729],{"class":1682},[1075,8745,1573],{"class":1572},[1075,8747,8748],{"class":1682}," BlogPost\n",[1075,8750,8751,8753,8755,8758,8760,8763,8765],{"class":1077,"line":1223},[1075,8752,8612],{"class":1572},[1075,8754,8741],{"class":1088},[1075,8756,8757],{"class":1682},"serializers ",[1075,8759,1573],{"class":1572},[1075,8761,8762],{"class":1682}," BlogPostSerializer",[1075,8764,1756],{"class":1088},[1075,8766,8767],{"class":1682}," UserSerializer\n",[1075,8769,8770],{"class":1077,"line":1243},[1075,8771,1642],{"emptyLinePlaceholder":1641},[1075,8773,8774,8777,8781,8783,8787,8789,8792],{"class":1077,"line":1249},[1075,8775,8776],{"class":2562},"class",[1075,8778,8780],{"class":8779},"sD-vU"," AuthViewSet",[1075,8782,1657],{"class":1088},[1075,8784,8786],{"class":8785},"sYn-s","viewsets",[1075,8788,2686],{"class":1088},[1075,8790,8791],{"class":8785},"ViewSet",[1075,8793,8794],{"class":1088},"):\n",[1075,8796,8797,8801,8805],{"class":1077,"line":1263},[1075,8798,8800],{"class":8799},"sm7ve","    \"\"\"",[1075,8802,8804],{"class":8803},"sVyVU","Authentication endpoints for frontend.",[1075,8806,8807],{"class":8799},"\"\"\"\n",[1075,8809,8810],{"class":1077,"line":1284},[1075,8811,3638],{"class":1682},[1075,8813,8814,8817,8819,8821,8825,8827,8831],{"class":1077,"line":1304},[1075,8815,8816],{"class":2562},"    def",[1075,8818,2499],{"class":1653},[1075,8820,1657],{"class":1088},[1075,8822,8824],{"class":8823},"sRjD_","self",[1075,8826,1756],{"class":1088},[1075,8828,8830],{"class":8829},"sCyAa"," request",[1075,8832,8794],{"class":1088},[1075,8834,8835,8838,8841],{"class":1077,"line":1325},[1075,8836,8837],{"class":8799},"        \"\"\"",[1075,8839,8840],{"class":8803},"Login endpoint.",[1075,8842,8807],{"class":8799},[1075,8844,8845,8848,8850,8852,8854,8856,8858,8861,8863,8865,8868,8870],{"class":1077,"line":1346},[1075,8846,8847],{"class":1682},"        username ",[1075,8849,6204],{"class":1088},[1075,8851,8830],{"class":1682},[1075,8853,2686],{"class":1088},[1075,8855,2765],{"class":2982},[1075,8857,2686],{"class":1088},[1075,8859,2731],{"class":8860},"siWMO",[1075,8862,1657],{"class":1088},[1075,8864,1594],{"class":1109},[1075,8866,8867],{"class":1113},"username",[1075,8869,1594],{"class":1109},[1075,8871,1793],{"class":1088},[1075,8873,8874,8877,8879,8881,8883,8885,8887,8889,8891,8893,8896,8898],{"class":1077,"line":1367},[1075,8875,8876],{"class":1682},"        password ",[1075,8878,6204],{"class":1088},[1075,8880,8830],{"class":1682},[1075,8882,2686],{"class":1088},[1075,8884,2765],{"class":2982},[1075,8886,2686],{"class":1088},[1075,8888,2731],{"class":8860},[1075,8890,1657],{"class":1088},[1075,8892,1594],{"class":1109},[1075,8894,8895],{"class":1113},"password",[1075,8897,1594],{"class":1109},[1075,8899,1793],{"class":1088},[1075,8901,8902],{"class":1077,"line":1386},[1075,8903,3256],{"class":1682},[1075,8905,8906,8908,8911,8914,8917,8919,8922],{"class":1077,"line":1391},[1075,8907,2696],{"class":1572},[1075,8909,8910],{"class":2616}," not",[1075,8912,8913],{"class":1682}," username ",[1075,8915,8916],{"class":2616},"or",[1075,8918,8910],{"class":2616},[1075,8920,8921],{"class":1682}," password",[1075,8923,8924],{"class":1088},":\n",[1075,8926,8927,8930,8933],{"class":1077,"line":1405},[1075,8928,8929],{"class":1572},"            return",[1075,8931,8932],{"class":8860}," Response",[1075,8934,2574],{"class":1088},[1075,8936,8937,8940,8942,8944,8946,8948,8950,8953,8955],{"class":1077,"line":1425},[1075,8938,8939],{"class":1088},"                {",[1075,8941,1594],{"class":1109},[1075,8943,3140],{"class":1113},[1075,8945,1594],{"class":1109},[1075,8947,1106],{"class":1088},[1075,8949,1589],{"class":1109},[1075,8951,8952],{"class":1113},"Username and password required",[1075,8954,1594],{"class":1109},[1075,8956,8957],{"class":1088},"},\n",[1075,8959,8960,8963,8965,8967,8969],{"class":1077,"line":1445},[1075,8961,8962],{"class":2589},"                status",[1075,8964,6204],{"class":1088},[1075,8966,4232],{"class":8860},[1075,8968,2686],{"class":1088},[1075,8970,8972],{"class":8971},"sFGJz","HTTP_400_BAD_REQUEST\n",[1075,8974,8975],{"class":1077,"line":1466},[1075,8976,8977],{"class":1088},"            )\n",[1075,8979,8980],{"class":1077,"line":1485},[1075,8981,3256],{"class":1682},[1075,8983,8984,8987,8989,8991,8993,8995,8997,8999,9001,9003,9005,9007],{"class":1077,"line":1506},[1075,8985,8986],{"class":1682},"        user ",[1075,8988,6204],{"class":1088},[1075,8990,8701],{"class":8860},[1075,8992,1657],{"class":1088},[1075,8994,8867],{"class":2589},[1075,8996,6204],{"class":1088},[1075,8998,8867],{"class":8860},[1075,9000,1756],{"class":1088},[1075,9002,8921],{"class":2589},[1075,9004,6204],{"class":1088},[1075,9006,8895],{"class":8860},[1075,9008,1793],{"class":1088},[1075,9010,9011,9013,9015],{"class":1077,"line":1527},[1075,9012,2696],{"class":1572},[1075,9014,2719],{"class":1682},[1075,9016,8924],{"class":1088},[1075,9018,9019,9022,9024,9026,9028,9030],{"class":1077,"line":1546},[1075,9020,9021],{"class":8860},"            login",[1075,9023,1657],{"class":1088},[1075,9025,4044],{"class":8860},[1075,9027,1756],{"class":1088},[1075,9029,2719],{"class":8860},[1075,9031,1793],{"class":1088},[1075,9033,9034],{"class":1077,"line":1552},[1075,9035,9036],{"class":1682},"            \n",[1075,9038,9039],{"class":1077,"line":1906},[1075,9040,9041],{"class":1081},"            # Generate or get token (if using token auth)\n",[1075,9043,9044,9047,9049,9051,9054,9056,9058,9060],{"class":1077,"line":1916},[1075,9045,9046],{"class":1572},"            from",[1075,9048,8632],{"class":1682},[1075,9050,2686],{"class":1088},[1075,9052,9053],{"class":1682},"authtoken",[1075,9055,2686],{"class":1088},[1075,9057,8729],{"class":1682},[1075,9059,1573],{"class":1572},[1075,9061,9062],{"class":1682}," Token\n",[1075,9064,9065,9068,9070,9073,9075,9078,9080,9083,9085,9088,9090,9092,9094,9096],{"class":1077,"line":1947},[1075,9066,9067],{"class":1682},"            token",[1075,9069,1756],{"class":1088},[1075,9071,9072],{"class":1682}," created ",[1075,9074,6204],{"class":1088},[1075,9076,9077],{"class":1682}," Token",[1075,9079,2686],{"class":1088},[1075,9081,9082],{"class":2982},"objects",[1075,9084,2686],{"class":1088},[1075,9086,9087],{"class":8860},"get_or_create",[1075,9089,1657],{"class":1088},[1075,9091,3380],{"class":2589},[1075,9093,6204],{"class":1088},[1075,9095,3380],{"class":8860},[1075,9097,1793],{"class":1088},[1075,9099,9100],{"class":1077,"line":1978},[1075,9101,9036],{"class":1682},[1075,9103,9104,9106,9108],{"class":1077,"line":2009},[1075,9105,8929],{"class":1572},[1075,9107,8932],{"class":8860},[1075,9109,9110],{"class":1088},"({\n",[1075,9112,9113,9116,9118,9120,9122,9125,9127,9129,9132,9134],{"class":1077,"line":2040},[1075,9114,9115],{"class":1109},"                '",[1075,9117,3380],{"class":1113},[1075,9119,1594],{"class":1109},[1075,9121,1106],{"class":1088},[1075,9123,9124],{"class":8860}," UserSerializer",[1075,9126,1657],{"class":1088},[1075,9128,3380],{"class":8860},[1075,9130,9131],{"class":1088},").",[1075,9133,2765],{"class":2982},[1075,9135,1119],{"class":1088},[1075,9137,9138,9140,9142,9144,9146,9148,9150],{"class":1077,"line":2069},[1075,9139,9115],{"class":1109},[1075,9141,2689],{"class":1113},[1075,9143,1594],{"class":1109},[1075,9145,1106],{"class":1088},[1075,9147,2675],{"class":8860},[1075,9149,2686],{"class":1088},[1075,9151,9152],{"class":2982},"key\n",[1075,9154,9155],{"class":1077,"line":2074},[1075,9156,9157],{"class":1088},"            })\n",[1075,9159,9160],{"class":1077,"line":2079},[1075,9161,3256],{"class":1682},[1075,9163,9164,9167,9169],{"class":1077,"line":2440},[1075,9165,9166],{"class":1572},"        return",[1075,9168,8932],{"class":8860},[1075,9170,2574],{"class":1088},[1075,9172,9173,9176,9178,9180,9182,9184,9186,9189,9191],{"class":1077,"line":2446},[1075,9174,9175],{"class":1088},"            {",[1075,9177,1594],{"class":1109},[1075,9179,3140],{"class":1113},[1075,9181,1594],{"class":1109},[1075,9183,1106],{"class":1088},[1075,9185,1589],{"class":1109},[1075,9187,9188],{"class":1113},"Invalid credentials",[1075,9190,1594],{"class":1109},[1075,9192,8957],{"class":1088},[1075,9194,9195,9198,9200,9202,9204],{"class":1077,"line":2452},[1075,9196,9197],{"class":2589},"            status",[1075,9199,6204],{"class":1088},[1075,9201,4232],{"class":8860},[1075,9203,2686],{"class":1088},[1075,9205,9206],{"class":8971},"HTTP_401_UNAUTHORIZED\n",[1075,9208,9209],{"class":1077,"line":2458},[1075,9210,9211],{"class":1088},"        )\n",[1075,9213,9214],{"class":1077,"line":2463},[1075,9215,3638],{"class":1682},[1075,9217,9218,9221,9224,9226,9229,9231,9234,9236,9239,9242,9244,9246,9248],{"class":1077,"line":2468},[1075,9219,9220],{"class":1088},"    @",[1075,9222,9223],{"class":1653},"action",[1075,9225,1657],{"class":1088},[1075,9227,9228],{"class":2589},"detail",[1075,9230,6204],{"class":1088},[1075,9232,9233],{"class":3047},"False",[1075,9235,1756],{"class":1088},[1075,9237,9238],{"class":2589}," methods",[1075,9240,9241],{"class":1088},"=[",[1075,9243,1594],{"class":1109},[1075,9245,2935],{"class":1113},[1075,9247,1594],{"class":1109},[1075,9249,9250],{"class":1088},"])\n",[1075,9252,9253,9255,9257,9259,9261,9263,9265],{"class":1077,"line":2473},[1075,9254,8816],{"class":2562},[1075,9256,7225],{"class":1653},[1075,9258,1657],{"class":1088},[1075,9260,8824],{"class":8823},[1075,9262,1756],{"class":1088},[1075,9264,8830],{"class":8829},[1075,9266,8794],{"class":1088},[1075,9268,9269,9271,9274],{"class":1077,"line":3168},[1075,9270,8837],{"class":8799},[1075,9272,9273],{"class":8803},"Logout endpoint.",[1075,9275,8807],{"class":8799},[1075,9277,9278,9281,9283,9285],{"class":1077,"line":3173},[1075,9279,9280],{"class":8860},"        logout",[1075,9282,1657],{"class":1088},[1075,9284,4044],{"class":8860},[1075,9286,1793],{"class":1088},[1075,9288,9289,9291,9293,9296,9298,9300,9302,9304,9306,9309,9311],{"class":1077,"line":3179},[1075,9290,9166],{"class":1572},[1075,9292,8932],{"class":8860},[1075,9294,9295],{"class":1088},"({",[1075,9297,1594],{"class":1109},[1075,9299,3140],{"class":1113},[1075,9301,1594],{"class":1109},[1075,9303,1106],{"class":1088},[1075,9305,1589],{"class":1109},[1075,9307,9308],{"class":1113},"Logged out successfully",[1075,9310,1594],{"class":1109},[1075,9312,9313],{"class":1088},"})\n",[1075,9315,9316],{"class":1077,"line":3195},[1075,9317,3638],{"class":1682},[1075,9319,9320,9322,9324,9326,9328,9330,9332,9334,9336,9338,9340,9342,9344,9347,9350,9352,9355],{"class":1077,"line":3202},[1075,9321,9220],{"class":1088},[1075,9323,9223],{"class":1653},[1075,9325,1657],{"class":1088},[1075,9327,9228],{"class":2589},[1075,9329,6204],{"class":1088},[1075,9331,9233],{"class":3047},[1075,9333,1756],{"class":1088},[1075,9335,9238],{"class":2589},[1075,9337,9241],{"class":1088},[1075,9339,1594],{"class":1109},[1075,9341,2731],{"class":1113},[1075,9343,1594],{"class":1109},[1075,9345,9346],{"class":1088},"],",[1075,9348,9349],{"class":2589}," permission_classes",[1075,9351,9241],{"class":1088},[1075,9353,9354],{"class":8860},"IsAuthenticated",[1075,9356,9250],{"class":1088},[1075,9358,9359,9361,9363,9365,9367,9369,9371],{"class":1077,"line":3227},[1075,9360,8816],{"class":2562},[1075,9362,2719],{"class":1653},[1075,9364,1657],{"class":1088},[1075,9366,8824],{"class":8823},[1075,9368,1756],{"class":1088},[1075,9370,8830],{"class":8829},[1075,9372,8794],{"class":1088},[1075,9374,9375,9377,9380],{"class":1077,"line":3242},[1075,9376,8837],{"class":8799},[1075,9378,9379],{"class":8803},"Get current user info.",[1075,9381,8807],{"class":8799},[1075,9383,9384,9386,9388,9390,9393,9395,9397,9399,9401,9403,9405],{"class":1077,"line":3248},[1075,9385,9166],{"class":1572},[1075,9387,8932],{"class":8860},[1075,9389,1657],{"class":1088},[1075,9391,9392],{"class":8860},"UserSerializer",[1075,9394,1657],{"class":1088},[1075,9396,4044],{"class":8860},[1075,9398,2686],{"class":1088},[1075,9400,3380],{"class":2982},[1075,9402,9131],{"class":1088},[1075,9404,2765],{"class":2982},[1075,9406,1793],{"class":1088},[1075,9408,9409],{"class":1077,"line":3253},[1075,9410,1642],{"emptyLinePlaceholder":1641},[1075,9412,9413,9415,9418,9420,9422,9424,9427],{"class":1077,"line":3259},[1075,9414,8776],{"class":2562},[1075,9416,9417],{"class":8779}," BlogPostViewSet",[1075,9419,1657],{"class":1088},[1075,9421,8786],{"class":8785},[1075,9423,2686],{"class":1088},[1075,9425,9426],{"class":8785},"ModelViewSet",[1075,9428,8794],{"class":1088},[1075,9430,9431,9433,9436],{"class":1077,"line":3289},[1075,9432,8800],{"class":8799},[1075,9434,9435],{"class":8803},"Blog post CRUD operations.",[1075,9437,8807],{"class":8799},[1075,9439,9440,9443,9445,9448,9450,9452,9454,9457],{"class":1077,"line":3321},[1075,9441,9442],{"class":1682},"    queryset ",[1075,9444,6204],{"class":1088},[1075,9446,9447],{"class":1682}," BlogPost",[1075,9449,2686],{"class":1088},[1075,9451,9082],{"class":2982},[1075,9453,2686],{"class":1088},[1075,9455,9456],{"class":8860},"all",[1075,9458,9459],{"class":1088},"()\n",[1075,9461,9462,9465,9467],{"class":1077,"line":3326},[1075,9463,9464],{"class":1682},"    serializer_class ",[1075,9466,6204],{"class":1088},[1075,9468,9469],{"class":1682}," BlogPostSerializer\n",[1075,9471,9472,9475,9477,9479,9482],{"class":1077,"line":3331},[1075,9473,9474],{"class":1682},"    permission_classes ",[1075,9476,6204],{"class":1088},[1075,9478,1670],{"class":1088},[1075,9480,9481],{"class":1682},"IsAuthenticatedOrReadOnly",[1075,9483,9484],{"class":1088},"]\n",[1075,9486,9487,9490,9492,9494,9496],{"class":1077,"line":3337},[1075,9488,9489],{"class":1682},"    lookup_field ",[1075,9491,6204],{"class":1088},[1075,9493,1589],{"class":1109},[1075,9495,4520],{"class":1113},[1075,9497,1882],{"class":1109},[1075,9499,9500],{"class":1077,"line":3356},[1075,9501,3638],{"class":1682},[1075,9503,9504,9506,9509,9511,9513,9515,9518],{"class":1077,"line":3397},[1075,9505,8816],{"class":2562},[1075,9507,9508],{"class":1653}," perform_create",[1075,9510,1657],{"class":1088},[1075,9512,8824],{"class":8823},[1075,9514,1756],{"class":1088},[1075,9516,9517],{"class":8829}," serializer",[1075,9519,8794],{"class":1088},[1075,9521,9522,9525,9527,9530,9532,9535,9537,9540,9542,9544,9546,9548],{"class":1077,"line":3402},[1075,9523,9524],{"class":1682},"        serializer",[1075,9526,2686],{"class":1088},[1075,9528,9529],{"class":8860},"save",[1075,9531,1657],{"class":1088},[1075,9533,9534],{"class":2589},"author",[1075,9536,6204],{"class":1088},[1075,9538,8824],{"class":9539},"se3Ec",[1075,9541,2686],{"class":1088},[1075,9543,4044],{"class":2982},[1075,9545,2686],{"class":1088},[1075,9547,3380],{"class":2982},[1075,9549,1793],{"class":1088},[1035,9551,9553],{"id":9552},"url-configuration","URL Configuration",[1065,9555,9557],{"className":8598,"code":9556,"language":8600,"meta":1070,"style":1070},"# urls.py\nfrom django.urls import path, include\nfrom rest_framework.routers import DefaultRouter\nfrom .views.api import AuthViewSet, BlogPostViewSet\n\n# API router\nrouter = DefaultRouter()\nrouter.register(r'auth', AuthViewSet, basename='auth')\nrouter.register(r'blog/posts', BlogPostViewSet)\n\nurlpatterns = [\n    # API endpoints\n    path('api/', include(router.urls)),\n    \n    # Frontend routes (catch-all for SPA)\n    path('', include('frontend.urls')),\n]\n",[1072,9558,9559,9564,9585,9601,9624,9628,9633,9645,9685,9710,9714,9724,9729,9760,9764,9769,9793],{"__ignoreMap":1070},[1075,9560,9561],{"class":1077,"line":1078},[1075,9562,9563],{"class":1081},"# urls.py\n",[1075,9565,9566,9568,9570,9572,9575,9577,9580,9582],{"class":1077,"line":1085},[1075,9567,8612],{"class":1572},[1075,9569,8686],{"class":1682},[1075,9571,2686],{"class":1088},[1075,9573,9574],{"class":1682},"urls ",[1075,9576,1573],{"class":1572},[1075,9578,9579],{"class":1682}," path",[1075,9581,1756],{"class":1088},[1075,9583,9584],{"class":1682}," include\n",[1075,9586,9587,9589,9591,9593,9596,9598],{"class":1077,"line":1092},[1075,9588,8612],{"class":1572},[1075,9590,8632],{"class":1682},[1075,9592,2686],{"class":1088},[1075,9594,9595],{"class":1682},"routers ",[1075,9597,1573],{"class":1572},[1075,9599,9600],{"class":1682}," DefaultRouter\n",[1075,9602,9603,9605,9607,9610,9612,9615,9617,9619,9621],{"class":1077,"line":1122},[1075,9604,8612],{"class":1572},[1075,9606,8741],{"class":1088},[1075,9608,9609],{"class":1682},"views",[1075,9611,2686],{"class":1088},[1075,9613,9614],{"class":1682},"api ",[1075,9616,1573],{"class":1572},[1075,9618,8780],{"class":1682},[1075,9620,1756],{"class":1088},[1075,9622,9623],{"class":1682}," BlogPostViewSet\n",[1075,9625,9626],{"class":1077,"line":1143},[1075,9627,1642],{"emptyLinePlaceholder":1641},[1075,9629,9630],{"class":1077,"line":1164},[1075,9631,9632],{"class":1081},"# API router\n",[1075,9634,9635,9638,9640,9643],{"class":1077,"line":1179},[1075,9636,9637],{"class":1682},"router ",[1075,9639,6204],{"class":1088},[1075,9641,9642],{"class":8860}," DefaultRouter",[1075,9644,9459],{"class":1088},[1075,9646,9647,9649,9651,9654,9656,9659,9661,9664,9666,9668,9670,9672,9675,9677,9679,9681,9683],{"class":1077,"line":1202},[1075,9648,6072],{"class":1682},[1075,9650,2686],{"class":1088},[1075,9652,9653],{"class":8860},"register",[1075,9655,1657],{"class":1088},[1075,9657,9658],{"class":2562},"r",[1075,9660,1594],{"class":1109},[1075,9662,6614],{"class":9663},"s27EL",[1075,9665,1594],{"class":1109},[1075,9667,1756],{"class":1088},[1075,9669,8780],{"class":8860},[1075,9671,1756],{"class":1088},[1075,9673,9674],{"class":2589}," basename",[1075,9676,6204],{"class":1088},[1075,9678,1594],{"class":1109},[1075,9680,6614],{"class":1113},[1075,9682,1594],{"class":1109},[1075,9684,1793],{"class":1088},[1075,9686,9687,9689,9691,9693,9695,9697,9699,9702,9704,9706,9708],{"class":1077,"line":1223},[1075,9688,6072],{"class":1682},[1075,9690,2686],{"class":1088},[1075,9692,9653],{"class":8860},[1075,9694,1657],{"class":1088},[1075,9696,9658],{"class":2562},[1075,9698,1594],{"class":1109},[1075,9700,9701],{"class":9663},"blog/posts",[1075,9703,1594],{"class":1109},[1075,9705,1756],{"class":1088},[1075,9707,9417],{"class":8860},[1075,9709,1793],{"class":1088},[1075,9711,9712],{"class":1077,"line":1243},[1075,9713,1642],{"emptyLinePlaceholder":1641},[1075,9715,9716,9719,9721],{"class":1077,"line":1249},[1075,9717,9718],{"class":1682},"urlpatterns ",[1075,9720,6204],{"class":1088},[1075,9722,9723],{"class":1088}," [\n",[1075,9725,9726],{"class":1077,"line":1263},[1075,9727,9728],{"class":1081},"    # API endpoints\n",[1075,9730,9731,9734,9736,9738,9741,9743,9745,9748,9750,9752,9754,9757],{"class":1077,"line":1284},[1075,9732,9733],{"class":8860},"    path",[1075,9735,1657],{"class":1088},[1075,9737,1594],{"class":1109},[1075,9739,9740],{"class":1113},"api/",[1075,9742,1594],{"class":1109},[1075,9744,1756],{"class":1088},[1075,9746,9747],{"class":8860}," include",[1075,9749,1657],{"class":1088},[1075,9751,6072],{"class":8860},[1075,9753,2686],{"class":1088},[1075,9755,9756],{"class":2982},"urls",[1075,9758,9759],{"class":1088},")),\n",[1075,9761,9762],{"class":1077,"line":1304},[1075,9763,3638],{"class":1682},[1075,9765,9766],{"class":1077,"line":1325},[1075,9767,9768],{"class":1081},"    # Frontend routes (catch-all for SPA)\n",[1075,9770,9771,9773,9775,9778,9780,9782,9784,9786,9789,9791],{"class":1077,"line":1346},[1075,9772,9733],{"class":8860},[1075,9774,1657],{"class":1088},[1075,9776,9777],{"class":1109},"''",[1075,9779,1756],{"class":1088},[1075,9781,9747],{"class":8860},[1075,9783,1657],{"class":1088},[1075,9785,1594],{"class":1109},[1075,9787,9788],{"class":1113},"frontend.urls",[1075,9790,1594],{"class":1109},[1075,9792,9759],{"class":1088},[1075,9794,9795],{"class":1077,"line":1367},[1075,9796,9484],{"class":1088},[1035,9798,9800],{"id":9799},"frontend-url-handling","Frontend URL Handling",[1065,9802,9804],{"className":8598,"code":9803,"language":8600,"meta":1070,"style":1070},"# frontend/urls.py\nfrom django.urls import path, re_path\nfrom django.views.generic import TemplateView\n\nurlpatterns = [\n    # Serve React/Vue app for all frontend routes\n    re_path(r'^(?!api/).*$', TemplateView.as_view(template_name='index.html')),\n]\n",[1072,9805,9806,9811,9830,9850,9854,9862,9867,9928],{"__ignoreMap":1070},[1075,9807,9808],{"class":1077,"line":1078},[1075,9809,9810],{"class":1081},"# frontend/urls.py\n",[1075,9812,9813,9815,9817,9819,9821,9823,9825,9827],{"class":1077,"line":1085},[1075,9814,8612],{"class":1572},[1075,9816,8686],{"class":1682},[1075,9818,2686],{"class":1088},[1075,9820,9574],{"class":1682},[1075,9822,1573],{"class":1572},[1075,9824,9579],{"class":1682},[1075,9826,1756],{"class":1088},[1075,9828,9829],{"class":1682}," re_path\n",[1075,9831,9832,9834,9836,9838,9840,9842,9845,9847],{"class":1077,"line":1092},[1075,9833,8612],{"class":1572},[1075,9835,8686],{"class":1682},[1075,9837,2686],{"class":1088},[1075,9839,9609],{"class":1682},[1075,9841,2686],{"class":1088},[1075,9843,9844],{"class":1682},"generic ",[1075,9846,1573],{"class":1572},[1075,9848,9849],{"class":1682}," TemplateView\n",[1075,9851,9852],{"class":1077,"line":1122},[1075,9853,1642],{"emptyLinePlaceholder":1641},[1075,9855,9856,9858,9860],{"class":1077,"line":1143},[1075,9857,9718],{"class":1682},[1075,9859,6204],{"class":1088},[1075,9861,9723],{"class":1088},[1075,9863,9864],{"class":1077,"line":1164},[1075,9865,9866],{"class":1081},"    # Serve React/Vue app for all frontend routes\n",[1075,9868,9869,9872,9874,9876,9878,9882,9884,9887,9889,9891,9893,9897,9900,9902,9904,9907,9909,9912,9914,9917,9919,9921,9924,9926],{"class":1077,"line":1179},[1075,9870,9871],{"class":8860},"    re_path",[1075,9873,1657],{"class":1088},[1075,9875,9658],{"class":2562},[1075,9877,1594],{"class":1109},[1075,9879,9881],{"class":9880},"sRJPX","^",[1075,9883,1657],{"class":1088},[1075,9885,9886],{"class":2616},"?!",[1075,9888,9740],{"class":9663},[1075,9890,1766],{"class":1088},[1075,9892,2686],{"class":9880},[1075,9894,9896],{"class":9895},"sGuSu","*",[1075,9898,9899],{"class":9880},"$",[1075,9901,1594],{"class":1109},[1075,9903,1756],{"class":1088},[1075,9905,9906],{"class":8860}," TemplateView",[1075,9908,2686],{"class":1088},[1075,9910,9911],{"class":8860},"as_view",[1075,9913,1657],{"class":1088},[1075,9915,9916],{"class":2589},"template_name",[1075,9918,6204],{"class":1088},[1075,9920,1594],{"class":1109},[1075,9922,9923],{"class":1113},"index.html",[1075,9925,1594],{"class":1109},[1075,9927,9759],{"class":1088},[1075,9929,9930],{"class":1077,"line":1202},[1075,9931,9484],{"class":1088},[1065,9933,9937],{"className":9934,"code":9935,"language":9936,"meta":1070,"style":1070},"language-html shiki shiki-themes material-theme-lighter vitesse-light vitesse-dark","\u003C!-- templates/index.html -->\n{% load vite_tags %}\n\u003C!DOCTYPE html>\n\u003Chtml lang=\"en\">\n\u003Chead>\n    \u003Cmeta charset=\"UTF-8\">\n    \u003Cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    \u003Ctitle>Django + React/Vue App\u003C/title>\n    {% csrf_token %}\n    {% vite_hmr %}\n    {% vite_asset 'frontend/js/main.js' %}\n\u003C/head>\n\u003Cbody>\n    \u003Cdiv id=\"react-app\">\u003C/div>\n    \u003C!-- or -->\n    \u003Cdiv id=\"vue-app\">\u003C/div>\n\u003C/body>\n\u003C/html>\n","html",[1072,9938,9939,9944,9949,9962,9982,9991,10012,10044,10063,10068,10073,10078,10086,10095,10119,10124,10146,10154],{"__ignoreMap":1070},[1075,9940,9941],{"class":1077,"line":1078},[1075,9942,9943],{"class":1081},"\u003C!-- templates/index.html -->\n",[1075,9945,9946],{"class":1077,"line":1085},[1075,9947,9948],{"class":1682},"{% load vite_tags %}\n",[1075,9950,9951,9954,9957,9960],{"class":1077,"line":1092},[1075,9952,9953],{"class":1088},"\u003C!",[1075,9955,9956],{"class":6185},"DOCTYPE",[1075,9958,9959],{"class":6200}," html",[1075,9961,6189],{"class":1088},[1075,9963,9964,9966,9968,9971,9973,9975,9978,9980],{"class":1077,"line":1122},[1075,9965,6182],{"class":1088},[1075,9967,9936],{"class":6185},[1075,9969,9970],{"class":6200}," lang",[1075,9972,6204],{"class":1088},[1075,9974,1103],{"class":1109},[1075,9976,9977],{"class":1113},"en",[1075,9979,1103],{"class":1109},[1075,9981,6189],{"class":1088},[1075,9983,9984,9986,9989],{"class":1077,"line":1143},[1075,9985,6182],{"class":1088},[1075,9987,9988],{"class":6185},"head",[1075,9990,6189],{"class":1088},[1075,9992,9993,9995,9998,10001,10003,10005,10008,10010],{"class":1077,"line":1164},[1075,9994,6217],{"class":1088},[1075,9996,9997],{"class":6185},"meta",[1075,9999,10000],{"class":6200}," charset",[1075,10002,6204],{"class":1088},[1075,10004,1103],{"class":1109},[1075,10006,10007],{"class":1113},"UTF-8",[1075,10009,1103],{"class":1109},[1075,10011,6189],{"class":1088},[1075,10013,10014,10016,10018,10021,10023,10025,10028,10030,10033,10035,10037,10040,10042],{"class":1077,"line":1179},[1075,10015,6217],{"class":1088},[1075,10017,9997],{"class":6185},[1075,10019,10020],{"class":6200}," name",[1075,10022,6204],{"class":1088},[1075,10024,1103],{"class":1109},[1075,10026,10027],{"class":1113},"viewport",[1075,10029,1103],{"class":1109},[1075,10031,10032],{"class":6200}," content",[1075,10034,6204],{"class":1088},[1075,10036,1103],{"class":1109},[1075,10038,10039],{"class":1113},"width=device-width, initial-scale=1.0",[1075,10041,1103],{"class":1109},[1075,10043,6189],{"class":1088},[1075,10045,10046,10048,10051,10054,10057,10059,10061],{"class":1077,"line":1202},[1075,10047,6217],{"class":1088},[1075,10049,10050],{"class":6185},"title",[1075,10052,10053],{"class":1088},">",[1075,10055,10056],{"class":1682},"Django + React/Vue App",[1075,10058,6309],{"class":1088},[1075,10060,10050],{"class":6185},[1075,10062,6189],{"class":1088},[1075,10064,10065],{"class":1077,"line":1223},[1075,10066,10067],{"class":1682},"    {% csrf_token %}\n",[1075,10069,10070],{"class":1077,"line":1243},[1075,10071,10072],{"class":1682},"    {% vite_hmr %}\n",[1075,10074,10075],{"class":1077,"line":1249},[1075,10076,10077],{"class":1682},"    {% vite_asset 'frontend/js/main.js' %}\n",[1075,10079,10080,10082,10084],{"class":1077,"line":1263},[1075,10081,6309],{"class":1088},[1075,10083,9988],{"class":6185},[1075,10085,6189],{"class":1088},[1075,10087,10088,10090,10093],{"class":1077,"line":1284},[1075,10089,6182],{"class":1088},[1075,10091,10092],{"class":6185},"body",[1075,10094,6189],{"class":1088},[1075,10096,10097,10099,10101,10103,10105,10107,10110,10112,10115,10117],{"class":1077,"line":1304},[1075,10098,6217],{"class":1088},[1075,10100,6197],{"class":6185},[1075,10102,4889],{"class":6200},[1075,10104,6204],{"class":1088},[1075,10106,1103],{"class":1109},[1075,10108,10109],{"class":1113},"react-app",[1075,10111,1103],{"class":1109},[1075,10113,10114],{"class":1088},">\u003C/",[1075,10116,6197],{"class":6185},[1075,10118,6189],{"class":1088},[1075,10120,10121],{"class":1077,"line":1325},[1075,10122,10123],{"class":1081},"    \u003C!-- or -->\n",[1075,10125,10126,10128,10130,10132,10134,10136,10138,10140,10142,10144],{"class":1077,"line":1346},[1075,10127,6217],{"class":1088},[1075,10129,6197],{"class":6185},[1075,10131,4889],{"class":6200},[1075,10133,6204],{"class":1088},[1075,10135,1103],{"class":1109},[1075,10137,6124],{"class":1113},[1075,10139,1103],{"class":1109},[1075,10141,10114],{"class":1088},[1075,10143,6197],{"class":6185},[1075,10145,6189],{"class":1088},[1075,10147,10148,10150,10152],{"class":1077,"line":1367},[1075,10149,6309],{"class":1088},[1075,10151,10092],{"class":6185},[1075,10153,6189],{"class":1088},[1075,10155,10156,10158,10160],{"class":1077,"line":1386},[1075,10157,6309],{"class":1088},[1075,10159,9936],{"class":6185},[1075,10161,6189],{"class":1088},[1030,10163,10165],{"id":10164},"component-islands-pattern","Component Islands Pattern",[1035,10167,10169],{"id":10168},"embedding-react-components-in-django-templates","Embedding React Components in Django Templates",[1065,10171,10173],{"className":2093,"code":10172,"language":2095,"meta":1070,"style":1070},"// frontend/js/components.jsx\nimport React from 'react';\nimport { createRoot } from 'react-dom/client';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport CommentSection from '@components/CommentSection';\nimport BlogPostForm from '@components/BlogPostForm';\nimport UserProfile from '@components/UserProfile';\n\nconst queryClient = new QueryClient();\n\n// Component registry\nconst components = {\n  CommentSection,\n  BlogPostForm,\n  UserProfile\n};\n\n// Mount components based on data attributes\ndocument.addEventListener('DOMContentLoaded', () => {\n  document.querySelectorAll('[data-react-component]').forEach(element => {\n    const componentName = element.dataset.reactComponent;\n    const props = JSON.parse(element.dataset.reactProps || '{}');\n    \n    const Component = components[componentName];\n    if (Component) {\n      const root = createRoot(element);\n      root.render(\n        \u003CQueryClientProvider client={queryClient}>\n          \u003CComponent {...props} />\n        \u003C/QueryClientProvider>\n      );\n    }\n  });\n});\n",[1072,10174,10175,10180,10184,10188,10192,10197,10202,10207,10211,10216,10220,10225,10230,10235,10240,10245,10249,10253,10258,10263,10268,10273,10278,10282,10287,10292,10297,10302,10307,10312,10317,10322,10326,10331],{"__ignoreMap":1070},[1075,10176,10177],{"class":1077,"line":1078},[1075,10178,10179],{},"// frontend/js/components.jsx\n",[1075,10181,10182],{"class":1077,"line":1085},[1075,10183,2107],{},[1075,10185,10186],{"class":1077,"line":1092},[1075,10187,2112],{},[1075,10189,10190],{"class":1077,"line":1122},[1075,10191,2122],{},[1075,10193,10194],{"class":1077,"line":1143},[1075,10195,10196],{},"import CommentSection from '@components/CommentSection';\n",[1075,10198,10199],{"class":1077,"line":1164},[1075,10200,10201],{},"import BlogPostForm from '@components/BlogPostForm';\n",[1075,10203,10204],{"class":1077,"line":1179},[1075,10205,10206],{},"import UserProfile from '@components/UserProfile';\n",[1075,10208,10209],{"class":1077,"line":1202},[1075,10210,1642],{"emptyLinePlaceholder":1641},[1075,10212,10213],{"class":1077,"line":1223},[1075,10214,10215],{},"const queryClient = new QueryClient();\n",[1075,10217,10218],{"class":1077,"line":1243},[1075,10219,1642],{"emptyLinePlaceholder":1641},[1075,10221,10222],{"class":1077,"line":1249},[1075,10223,10224],{},"// Component registry\n",[1075,10226,10227],{"class":1077,"line":1263},[1075,10228,10229],{},"const components = {\n",[1075,10231,10232],{"class":1077,"line":1284},[1075,10233,10234],{},"  CommentSection,\n",[1075,10236,10237],{"class":1077,"line":1304},[1075,10238,10239],{},"  BlogPostForm,\n",[1075,10241,10242],{"class":1077,"line":1325},[1075,10243,10244],{},"  UserProfile\n",[1075,10246,10247],{"class":1077,"line":1346},[1075,10248,6471],{},[1075,10250,10251],{"class":1077,"line":1367},[1075,10252,1642],{"emptyLinePlaceholder":1641},[1075,10254,10255],{"class":1077,"line":1386},[1075,10256,10257],{},"// Mount components based on data attributes\n",[1075,10259,10260],{"class":1077,"line":1391},[1075,10261,10262],{},"document.addEventListener('DOMContentLoaded', () => {\n",[1075,10264,10265],{"class":1077,"line":1405},[1075,10266,10267],{},"  document.querySelectorAll('[data-react-component]').forEach(element => {\n",[1075,10269,10270],{"class":1077,"line":1425},[1075,10271,10272],{},"    const componentName = element.dataset.reactComponent;\n",[1075,10274,10275],{"class":1077,"line":1445},[1075,10276,10277],{},"    const props = JSON.parse(element.dataset.reactProps || '{}');\n",[1075,10279,10280],{"class":1077,"line":1466},[1075,10281,3638],{},[1075,10283,10284],{"class":1077,"line":1485},[1075,10285,10286],{},"    const Component = components[componentName];\n",[1075,10288,10289],{"class":1077,"line":1506},[1075,10290,10291],{},"    if (Component) {\n",[1075,10293,10294],{"class":1077,"line":1527},[1075,10295,10296],{},"      const root = createRoot(element);\n",[1075,10298,10299],{"class":1077,"line":1546},[1075,10300,10301],{},"      root.render(\n",[1075,10303,10304],{"class":1077,"line":1552},[1075,10305,10306],{},"        \u003CQueryClientProvider client={queryClient}>\n",[1075,10308,10309],{"class":1077,"line":1906},[1075,10310,10311],{},"          \u003CComponent {...props} />\n",[1075,10313,10314],{"class":1077,"line":1916},[1075,10315,10316],{},"        \u003C/QueryClientProvider>\n",[1075,10318,10319],{"class":1077,"line":1947},[1075,10320,10321],{},"      );\n",[1075,10323,10324],{"class":1077,"line":1978},[1075,10325,1803],{},[1075,10327,10328],{"class":1077,"line":2009},[1075,10329,10330],{},"  });\n",[1075,10332,10333],{"class":1077,"line":2040},[1075,10334,2179],{},[1065,10336,10338],{"className":9934,"code":10337,"language":9936,"meta":1070,"style":1070},"\u003C!-- templates/blog/post_detail.html -->\n{% extends 'base.html' %}\n{% load vite_tags %}\n\n{% block content %}\n\u003Carticle class=\"blog-post\">\n    \u003Ch1>{{ post.title }}\u003C/h1>\n    \u003Cdiv class=\"post-content\">\n        {{ post.content|safe }}\n    \u003C/div>\n    \n    \u003C!-- Embed React component -->\n    \u003Cdiv \n        data-react-component=\"CommentSection\"\n        data-react-props='{\"postId\": {{ post.id }}, \"postSlug\": \"{{ post.slug }}\"}'\n    >\u003C/div>\n\u003C/article>\n{% endblock %}\n\n{% block extra_js %}\n    {% vite_asset 'frontend/js/components.js' %}\n{% endblock %}\n",[1072,10339,10340,10345,10350,10354,10358,10363,10383,10400,10419,10424,10432,10436,10441,10450,10464,10478,10487,10495,10500,10504,10509,10514],{"__ignoreMap":1070},[1075,10341,10342],{"class":1077,"line":1078},[1075,10343,10344],{"class":1081},"\u003C!-- templates/blog/post_detail.html -->\n",[1075,10346,10347],{"class":1077,"line":1085},[1075,10348,10349],{"class":1682},"{% extends 'base.html' %}\n",[1075,10351,10352],{"class":1077,"line":1092},[1075,10353,9948],{"class":1682},[1075,10355,10356],{"class":1077,"line":1122},[1075,10357,1642],{"emptyLinePlaceholder":1641},[1075,10359,10360],{"class":1077,"line":1143},[1075,10361,10362],{"class":1682},"{% block content %}\n",[1075,10364,10365,10367,10370,10372,10374,10376,10379,10381],{"class":1077,"line":1164},[1075,10366,6182],{"class":1088},[1075,10368,10369],{"class":6185},"article",[1075,10371,6201],{"class":6200},[1075,10373,6204],{"class":1088},[1075,10375,1103],{"class":1109},[1075,10377,10378],{"class":1113},"blog-post",[1075,10380,1103],{"class":1109},[1075,10382,6189],{"class":1088},[1075,10384,10385,10387,10389,10391,10394,10396,10398],{"class":1077,"line":1179},[1075,10386,6217],{"class":1088},[1075,10388,1022],{"class":6185},[1075,10390,10053],{"class":1088},[1075,10392,10393],{"class":1682},"{{ post.title }}",[1075,10395,6309],{"class":1088},[1075,10397,1022],{"class":6185},[1075,10399,6189],{"class":1088},[1075,10401,10402,10404,10406,10408,10410,10412,10415,10417],{"class":1077,"line":1202},[1075,10403,6217],{"class":1088},[1075,10405,6197],{"class":6185},[1075,10407,6201],{"class":6200},[1075,10409,6204],{"class":1088},[1075,10411,1103],{"class":1109},[1075,10413,10414],{"class":1113},"post-content",[1075,10416,1103],{"class":1109},[1075,10418,6189],{"class":1088},[1075,10420,10421],{"class":1077,"line":1223},[1075,10422,10423],{"class":1682},"        {{ post.content|safe }}\n",[1075,10425,10426,10428,10430],{"class":1077,"line":1243},[1075,10427,6291],{"class":1088},[1075,10429,6197],{"class":6185},[1075,10431,6189],{"class":1088},[1075,10433,10434],{"class":1077,"line":1249},[1075,10435,3638],{"class":1682},[1075,10437,10438],{"class":1077,"line":1263},[1075,10439,10440],{"class":1081},"    \u003C!-- Embed React component -->\n",[1075,10442,10443,10445,10447],{"class":1077,"line":1284},[1075,10444,6217],{"class":1088},[1075,10446,6197],{"class":6185},[1075,10448,3102],{"class":10449},"sHnae",[1075,10451,10452,10455,10457,10459,10462],{"class":1077,"line":1304},[1075,10453,10454],{"class":6200},"        data-react-component",[1075,10456,6204],{"class":1088},[1075,10458,1103],{"class":1109},[1075,10460,10461],{"class":1113},"CommentSection",[1075,10463,1240],{"class":1109},[1075,10465,10466,10469,10471,10473,10476],{"class":1077,"line":1325},[1075,10467,10468],{"class":6200},"        data-react-props",[1075,10470,6204],{"class":1088},[1075,10472,1594],{"class":1109},[1075,10474,10475],{"class":1113},"{\"postId\": {{ post.id }}, \"postSlug\": \"{{ post.slug }}\"}",[1075,10477,1882],{"class":1109},[1075,10479,10480,10483,10485],{"class":1077,"line":1346},[1075,10481,10482],{"class":1088},"    >\u003C/",[1075,10484,6197],{"class":6185},[1075,10486,6189],{"class":1088},[1075,10488,10489,10491,10493],{"class":1077,"line":1367},[1075,10490,6309],{"class":1088},[1075,10492,10369],{"class":6185},[1075,10494,6189],{"class":1088},[1075,10496,10497],{"class":1077,"line":1386},[1075,10498,10499],{"class":1682},"{% endblock %}\n",[1075,10501,10502],{"class":1077,"line":1391},[1075,10503,1642],{"emptyLinePlaceholder":1641},[1075,10505,10506],{"class":1077,"line":1405},[1075,10507,10508],{"class":1682},"{% block extra_js %}\n",[1075,10510,10511],{"class":1077,"line":1425},[1075,10512,10513],{"class":1682},"    {% vite_asset 'frontend/js/components.js' %}\n",[1075,10515,10516],{"class":1077,"line":1445},[1075,10517,10499],{"class":1682},[1030,10519,10521],{"id":10520},"production-deployment","Production Deployment",[1035,10523,10525],{"id":10524},"build-configuration","Build Configuration",[1065,10527,10531],{"className":10528,"code":10529,"language":10530,"meta":1070,"style":1070},"language-yaml shiki shiki-themes material-theme-lighter vitesse-light vitesse-dark","# docker-compose.yml\nversion: '3.8'\n\nservices:\n  frontend-builder:\n    image: node:18-alpine\n    working_dir: /app\n    volumes:\n      - .:/app\n    command: >\n      sh -c \"npm ci && npm run build\"\n  \n  web:\n    build: .\n    ports:\n      - \"8000:8000\"\n    depends_on:\n      - frontend-builder\n    environment:\n      - DEBUG=False\n      - VITE_DEV_MODE=False\n","yaml",[1072,10532,10533,10538,10551,10555,10562,10569,10579,10589,10596,10604,10614,10619,10623,10630,10640,10647,10658,10665,10672,10679,10686],{"__ignoreMap":1070},[1075,10534,10535],{"class":1077,"line":1078},[1075,10536,10537],{"class":1081},"# docker-compose.yml\n",[1075,10539,10540,10542,10544,10546,10549],{"class":1077,"line":1085},[1075,10541,1127],{"class":1664},[1075,10543,1106],{"class":1088},[1075,10545,1589],{"class":1109},[1075,10547,10548],{"class":1113},"3.8",[1075,10550,1882],{"class":1109},[1075,10552,10553],{"class":1077,"line":1092},[1075,10554,1642],{"emptyLinePlaceholder":1641},[1075,10556,10557,10560],{"class":1077,"line":1122},[1075,10558,10559],{"class":1664},"services",[1075,10561,8924],{"class":1088},[1075,10563,10564,10567],{"class":1077,"line":1143},[1075,10565,10566],{"class":1664},"  frontend-builder",[1075,10568,8924],{"class":1088},[1075,10570,10571,10574,10576],{"class":1077,"line":1164},[1075,10572,10573],{"class":1664},"    image",[1075,10575,1106],{"class":1088},[1075,10577,10578],{"class":1113}," node:18-alpine\n",[1075,10580,10581,10584,10586],{"class":1077,"line":1179},[1075,10582,10583],{"class":1664},"    working_dir",[1075,10585,1106],{"class":1088},[1075,10587,10588],{"class":1113}," /app\n",[1075,10590,10591,10594],{"class":1077,"line":1202},[1075,10592,10593],{"class":1664},"    volumes",[1075,10595,8924],{"class":1088},[1075,10597,10598,10601],{"class":1077,"line":1223},[1075,10599,10600],{"class":1088},"      -",[1075,10602,10603],{"class":1113}," .:/app\n",[1075,10605,10606,10609,10611],{"class":1077,"line":1243},[1075,10607,10608],{"class":1664},"    command",[1075,10610,1106],{"class":1088},[1075,10612,10613],{"class":1572}," >\n",[1075,10615,10616],{"class":1077,"line":1249},[1075,10617,10618],{"class":1113},"      sh -c \"npm ci && npm run build\"\n",[1075,10620,10621],{"class":1077,"line":1263},[1075,10622,1683],{"class":1113},[1075,10624,10625,10628],{"class":1077,"line":1284},[1075,10626,10627],{"class":1664},"  web",[1075,10629,8924],{"class":1088},[1075,10631,10632,10635,10637],{"class":1077,"line":1304},[1075,10633,10634],{"class":1664},"    build",[1075,10636,1106],{"class":1088},[1075,10638,10639],{"class":1830}," .\n",[1075,10641,10642,10645],{"class":1077,"line":1325},[1075,10643,10644],{"class":1664},"    ports",[1075,10646,8924],{"class":1088},[1075,10648,10649,10651,10653,10656],{"class":1077,"line":1346},[1075,10650,10600],{"class":1088},[1075,10652,1110],{"class":1109},[1075,10654,10655],{"class":1113},"8000:8000",[1075,10657,1240],{"class":1109},[1075,10659,10660,10663],{"class":1077,"line":1367},[1075,10661,10662],{"class":1664},"    depends_on",[1075,10664,8924],{"class":1088},[1075,10666,10667,10669],{"class":1077,"line":1386},[1075,10668,10600],{"class":1088},[1075,10670,10671],{"class":1113}," frontend-builder\n",[1075,10673,10674,10677],{"class":1077,"line":1391},[1075,10675,10676],{"class":1664},"    environment",[1075,10678,8924],{"class":1088},[1075,10680,10681,10683],{"class":1077,"line":1405},[1075,10682,10600],{"class":1088},[1075,10684,10685],{"class":1113}," DEBUG=False\n",[1075,10687,10688,10690],{"class":1077,"line":1425},[1075,10689,10600],{"class":1088},[1075,10691,10692],{"class":1113}," VITE_DEV_MODE=False\n",[1035,10694,10696],{"id":10695},"nginx-configuration","Nginx Configuration",[1065,10698,10702],{"className":10699,"code":10700,"language":10701,"meta":1070,"style":1070},"language-nginx shiki shiki-themes material-theme-lighter vitesse-light vitesse-dark","# nginx.conf\nserver {\n    listen 80;\n    server_name example.com;\n    \n    # Serve static files\n    location /static/ {\n        alias /app/staticfiles/;\n        expires 1y;\n        add_header Cache-Control \"public, immutable\";\n    }\n    \n    # API requests to Django\n    location /api/ {\n        proxy_pass http://django:8000;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n    }\n    \n    # Admin requests to Django\n    location /admin/ {\n        proxy_pass http://django:8000;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n    }\n    \n    # SPA fallback - serve index.html for all other routes\n    location / {\n        try_files $uri $uri/ /index.html;\n        root /app/staticfiles/dist;\n    }\n}\n","nginx",[1072,10703,10704,10709,10714,10719,10724,10728,10733,10738,10743,10748,10753,10757,10761,10766,10771,10776,10781,10786,10790,10794,10799,10804,10808,10812,10816,10820,10824,10829,10834,10839,10844,10848],{"__ignoreMap":1070},[1075,10705,10706],{"class":1077,"line":1078},[1075,10707,10708],{},"# nginx.conf\n",[1075,10710,10711],{"class":1077,"line":1085},[1075,10712,10713],{},"server {\n",[1075,10715,10716],{"class":1077,"line":1092},[1075,10717,10718],{},"    listen 80;\n",[1075,10720,10721],{"class":1077,"line":1122},[1075,10722,10723],{},"    server_name example.com;\n",[1075,10725,10726],{"class":1077,"line":1143},[1075,10727,3638],{},[1075,10729,10730],{"class":1077,"line":1164},[1075,10731,10732],{},"    # Serve static files\n",[1075,10734,10735],{"class":1077,"line":1179},[1075,10736,10737],{},"    location /static/ {\n",[1075,10739,10740],{"class":1077,"line":1202},[1075,10741,10742],{},"        alias /app/staticfiles/;\n",[1075,10744,10745],{"class":1077,"line":1223},[1075,10746,10747],{},"        expires 1y;\n",[1075,10749,10750],{"class":1077,"line":1243},[1075,10751,10752],{},"        add_header Cache-Control \"public, immutable\";\n",[1075,10754,10755],{"class":1077,"line":1249},[1075,10756,1803],{},[1075,10758,10759],{"class":1077,"line":1263},[1075,10760,3638],{},[1075,10762,10763],{"class":1077,"line":1284},[1075,10764,10765],{},"    # API requests to Django\n",[1075,10767,10768],{"class":1077,"line":1304},[1075,10769,10770],{},"    location /api/ {\n",[1075,10772,10773],{"class":1077,"line":1325},[1075,10774,10775],{},"        proxy_pass http://django:8000;\n",[1075,10777,10778],{"class":1077,"line":1346},[1075,10779,10780],{},"        proxy_set_header Host $host;\n",[1075,10782,10783],{"class":1077,"line":1367},[1075,10784,10785],{},"        proxy_set_header X-Real-IP $remote_addr;\n",[1075,10787,10788],{"class":1077,"line":1386},[1075,10789,1803],{},[1075,10791,10792],{"class":1077,"line":1391},[1075,10793,3638],{},[1075,10795,10796],{"class":1077,"line":1405},[1075,10797,10798],{},"    # Admin requests to Django\n",[1075,10800,10801],{"class":1077,"line":1425},[1075,10802,10803],{},"    location /admin/ {\n",[1075,10805,10806],{"class":1077,"line":1445},[1075,10807,10775],{},[1075,10809,10810],{"class":1077,"line":1466},[1075,10811,10780],{},[1075,10813,10814],{"class":1077,"line":1485},[1075,10815,10785],{},[1075,10817,10818],{"class":1077,"line":1506},[1075,10819,1803],{},[1075,10821,10822],{"class":1077,"line":1527},[1075,10823,3638],{},[1075,10825,10826],{"class":1077,"line":1546},[1075,10827,10828],{},"    # SPA fallback - serve index.html for all other routes\n",[1075,10830,10831],{"class":1077,"line":1552},[1075,10832,10833],{},"    location / {\n",[1075,10835,10836],{"class":1077,"line":1906},[1075,10837,10838],{},"        try_files $uri $uri/ /index.html;\n",[1075,10840,10841],{"class":1077,"line":1916},[1075,10842,10843],{},"        root /app/staticfiles/dist;\n",[1075,10845,10846],{"class":1077,"line":1947},[1075,10847,1803],{},[1075,10849,10850],{"class":1077,"line":1978},[1075,10851,1555],{},[1026,10853,10854],{},"Integrating React or Vue with Django enables building modern, interactive web applications that leverage Django's robust backend capabilities with cutting-edge frontend technologies. Choose the integration pattern that best fits your project requirements: component islands for progressive enhancement, hybrid architecture for mixed rendering needs, or full SPA for maximum interactivity. Proper authentication handling, state management, and build configuration ensure a seamless development experience and production-ready deployment.",[10856,10857,10858],"style",{},"html pre.shiki code .s9Tkl, html code.shiki .s9Tkl{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#A0ADA0;--shiki-default-font-style:inherit;--shiki-dark:#758575DD;--shiki-dark-font-style:inherit}html pre.shiki code .soVBu, html code.shiki .soVBu{--shiki-light:#39ADB5;--shiki-default:#999999;--shiki-dark:#666666}html pre.shiki code .s4Jsk, html code.shiki .s4Jsk{--shiki-light:#39ADB5;--shiki-default:#99841877;--shiki-dark:#B8A96577}html pre.shiki code .sLorS, html code.shiki .sLorS{--shiki-light:#9C3EDA;--shiki-default:#998418;--shiki-dark:#B8A965}html pre.shiki code .sbYkP, html code.shiki .sbYkP{--shiki-light:#39ADB5;--shiki-default:#B5695977;--shiki-dark:#C98A7D77}html pre.shiki code .sTbE_, html code.shiki .sTbE_{--shiki-light:#91B859;--shiki-default:#B56959;--shiki-dark:#C98A7D}html pre.shiki code .sa2tF, html code.shiki .sa2tF{--shiki-light:#E2931D;--shiki-default:#998418;--shiki-dark:#B8A965}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .siDh9, html code.shiki .siDh9{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#1E754F;--shiki-default-font-style:inherit;--shiki-dark:#4D9375;--shiki-dark-font-style:inherit}html pre.shiki code .sSC40, html code.shiki .sSC40{--shiki-light:#90A4AE;--shiki-default:#B07D48;--shiki-dark:#BD976A}html pre.shiki code .sljsM, html code.shiki .sljsM{--shiki-light:#6182B8;--shiki-default:#59873A;--shiki-dark:#80A665}html pre.shiki code .snCua, html code.shiki .snCua{--shiki-light:#90A4AE;--shiki-default:#999999;--shiki-dark:#666666}html pre.shiki code .suXOh, html code.shiki .suXOh{--shiki-light:#E53935;--shiki-default:#998418;--shiki-dark:#B8A965}html pre.shiki code .sftqT, html code.shiki .sftqT{--shiki-light:#90A4AE;--shiki-default:#393A34;--shiki-dark:#DBD7CAEE}html pre.shiki code .sq3J1, html code.shiki .sq3J1{--shiki-light:#FF5370;--shiki-default:#1E754F;--shiki-dark:#4D9375}html pre.shiki code .s7CZa, html code.shiki .s7CZa{--shiki-light:#F76D47;--shiki-default:#2F798A;--shiki-dark:#4C9A91}html pre.shiki code .sQtxO, html code.shiki .sQtxO{--shiki-light:#E53935;--shiki-default:#B56959;--shiki-dark:#C98A7D}html pre.shiki code .s5Kfy, html code.shiki .s5Kfy{--shiki-light:#9C3EDA;--shiki-default:#AB5959;--shiki-dark:#CB7676}html pre.shiki code .sqOPj, html code.shiki .sqOPj{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#B07D48;--shiki-default-font-style:inherit;--shiki-dark:#BD976A;--shiki-dark-font-style:inherit}html pre.shiki code .sIOqK, html code.shiki .sIOqK{--shiki-light:#9C3EDA;--shiki-default:#999999;--shiki-dark:#666666}html pre.shiki code .sVsLi, html code.shiki .sVsLi{--shiki-light:#39ADB5;--shiki-default:#AB5959;--shiki-dark:#CB7676}html pre.shiki code .sLdnO, html code.shiki .sLdnO{--shiki-light:#E53935;--shiki-default:#999999;--shiki-dark:#666666}html pre.shiki code .sBPpx, html code.shiki .sBPpx{--shiki-light:#E53935;--shiki-default:#393A34;--shiki-dark:#DBD7CAEE}html pre.shiki code .s8XtY, html code.shiki .s8XtY{--shiki-light:#39ADB5;--shiki-default:#1E754F;--shiki-dark:#4D9375}html pre.shiki code .su_V2, html code.shiki .su_V2{--shiki-light:#90A4AE;--shiki-default:#B56959;--shiki-dark:#C98A7D}html pre.shiki code .sAbu7, html code.shiki .sAbu7{--shiki-light:#90A4AE;--shiki-default:#59873A;--shiki-dark:#80A665}html pre.shiki code .skjlz, html code.shiki .skjlz{--shiki-light:#E53935;--shiki-default:#B07D48;--shiki-dark:#BD976A}html pre.shiki code .sD-vU, html code.shiki .sD-vU{--shiki-light:#E2931D;--shiki-default:#2E8F82;--shiki-dark:#5DA994}html pre.shiki code .sYn-s, html code.shiki .sYn-s{--shiki-light:#E2931D;--shiki-default:#59873A;--shiki-dark:#80A665}html pre.shiki code .sm7ve, html code.shiki .sm7ve{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#B5695977;--shiki-default-font-style:inherit;--shiki-dark:#C98A7D77;--shiki-dark-font-style:inherit}html pre.shiki code .sVyVU, html code.shiki .sVyVU{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#B56959;--shiki-default-font-style:inherit;--shiki-dark:#C98A7D;--shiki-dark-font-style:inherit}html pre.shiki code .sRjD_, html code.shiki .sRjD_{--shiki-light:#E53935;--shiki-light-font-style:italic;--shiki-default:#393A34;--shiki-default-font-style:inherit;--shiki-dark:#DBD7CAEE;--shiki-dark-font-style:inherit}html pre.shiki code .sCyAa, html code.shiki .sCyAa{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#393A34;--shiki-default-font-style:inherit;--shiki-dark:#DBD7CAEE;--shiki-dark-font-style:inherit}html pre.shiki code .siWMO, html code.shiki .siWMO{--shiki-light:#6182B8;--shiki-default:#393A34;--shiki-dark:#DBD7CAEE}html pre.shiki code .sFGJz, html code.shiki .sFGJz{--shiki-light:#E53935;--shiki-default:#A65E2B;--shiki-dark:#C99076}html pre.shiki code .se3Ec, html code.shiki .se3Ec{--shiki-light:#90A4AE;--shiki-default:#A65E2B;--shiki-dark:#C99076}html pre.shiki code .s27EL, html code.shiki .s27EL{--shiki-light:#91B859;--shiki-default:#AB5E3F;--shiki-dark:#C4704F}html pre.shiki code .sRJPX, html code.shiki .sRJPX{--shiki-light:#91B859;--shiki-default:#998418;--shiki-dark:#B8A965}html pre.shiki code .sGuSu, html code.shiki .sGuSu{--shiki-light:#39ADB5;--shiki-default:#2F798A;--shiki-dark:#4C9A91}html pre.shiki code .sJFLg, html code.shiki .sJFLg{--shiki-light:#E53935;--shiki-default:#1E754F;--shiki-dark:#4D9375}html pre.shiki code .s5q8q, html code.shiki .s5q8q{--shiki-light:#9C3EDA;--shiki-default:#B07D48;--shiki-dark:#BD976A}html pre.shiki code .sHnae, html code.shiki .sHnae{--shiki-light:#39ADB5;--shiki-default:#393A34;--shiki-dark:#DBD7CAEE}html pre.shiki code .s1Bar, html code.shiki .s1Bar{--shiki-light:#9C3EDA;--shiki-default:#59873A;--shiki-dark:#80A665}",{"title":1070,"searchDepth":1078,"depth":1085,"links":10860},[10861,10866,10872,10878,10883,10886],{"id":1032,"depth":1085,"text":1033,"children":10862},[10863,10864,10865],{"id":1037,"depth":1092,"text":1038},{"id":1044,"depth":1092,"text":1045},{"id":1051,"depth":1092,"text":1052},{"id":1058,"depth":1085,"text":1059,"children":10867},[10868,10869,10870,10871],{"id":1062,"depth":1092,"text":1063},{"id":2089,"depth":1092,"text":2090},{"id":2479,"depth":1092,"text":2480},{"id":3908,"depth":1092,"text":3909},{"id":5066,"depth":1085,"text":5067,"children":10873},[10874,10875,10876,10877],{"id":5070,"depth":1092,"text":5071},{"id":5827,"depth":1092,"text":5828},{"id":6516,"depth":1092,"text":6517},{"id":7446,"depth":1092,"text":7447},{"id":8590,"depth":1085,"text":8591,"children":10879},[10880,10881,10882],{"id":8594,"depth":1092,"text":8595},{"id":9552,"depth":1092,"text":9553},{"id":9799,"depth":1092,"text":9800},{"id":10164,"depth":1085,"text":10165,"children":10884},[10885],{"id":10168,"depth":1092,"text":10169},{"id":10520,"depth":1085,"text":10521,"children":10887},[10888,10889],{"id":10524,"depth":1092,"text":10525},{"id":10695,"depth":1092,"text":10696},"md",null,{},{"title":643,"description":1028},"Fgt73SMNXQRc6dkHcRF7jDNknCIpVAUF4t6NoCuk0uA",[10896,10898],{"title":639,"path":640,"stem":641,"description":10897,"children":-1},"Modern build tools transform the frontend development experience by providing features like hot module replacement, code splitting, automatic optimization, and seamless integration with CSS preprocessors and JavaScript transpilers. This chapter covers integrating Vite and Webpack with Django to create efficient development workflows and optimized production builds.",{"title":647,"path":648,"stem":649,"description":10899,"children":-1},"Cross-Origin Resource Sharing (CORS) is essential when building modern web applications where frontend and backend are served from different origins. This chapter covers CORS configuration in Django, security best practices, and troubleshooting common issues when integrating with frontend frameworks.",1772474944744]