[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"categories-en":3,"post:\u002Fpost\u002Ffirebase-with-nextjs-typescript-ultimate-baas-guide":37},[4,11,17,24,30],{"id":5,"slug":6,"name":7,"colorHex":8,"iconName":9,"postCount":10},"0e2c1225-f78a-4c20-8c93-998ab9dc93b9","frontend","Frontend","#40484f",null,25,{"id":12,"slug":13,"name":14,"colorHex":15,"iconName":9,"postCount":16},"bc8df70e-b7fb-4d89-a80c-fd458d36d58c","code-development","Code & Development","#8b5cf6",23,{"id":18,"slug":19,"name":20,"colorHex":21,"iconName":22,"postCount":23},"550e8400-e29b-41d4-a716-446655440001","inteligencia-artificial","Artificial Intelligence","#6366f1","brain",14,{"id":25,"slug":26,"name":27,"colorHex":28,"iconName":9,"postCount":29},"ea63b69c-2eb4-4100-81f3-70ce52d33743","tech-news","Tech News","#e50606",4,{"id":31,"slug":32,"name":33,"colorHex":34,"iconName":35,"postCount":36},"550e8400-e29b-41d4-a716-446655440017","how-to-guides","How-To & Guides","#be123c","book-open",2,{"post":38,"related":2210,"translations":2276,"resolved":9},{"id":39,"slug":40,"title":41,"excerpt":42,"image":43,"featured":44,"groupId":45,"publishedAt":46,"readingTime":23,"views":47,"author":48,"category":50,"tags":51,"contentJson":61,"metaTitle":41,"metaDescription":2208,"updatedAt":2209},"c0dc6d09-7c9d-479a-a3cf-4387fa5e7d7c","firebase-with-nextjs-typescript-ultimate-baas-guide","Firebase with Next.js & TypeScript: Ultimate BaaS Guide","Modern web development demands full-stack solutions. Firebase transforms into an indispensable ally for Next.js developers, removing infrastructure complexity. This guide covers robust integration with TypeScript, leveraging Firestore, Auth, Cloud Functions, and new AI features like Data Connect and Genkit to accelerate project delivery.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1766806352787-featured-sflfuf.png",false,"5f43c57d-5bc9-488c-97ac-cc995eb25164","2025-12-24T14:36:23.616797+00:00",90,{"name":49,"avatar":9},"Genildo Souza",{"slug":6,"name":7,"color":8},[52,55,58],{"slug":53,"name":54},"react","React",{"slug":56,"name":57},"javascript","JavaScript",{"slug":59,"name":60},"nextjs","Next.js",{"type":62,"content":63},"doc",[64,72,78,84,91,97,103,114,124,134,144,154,164,174,184,190,196,202,212,235,241,250,265,271,280,289,295,301,307,313,323,419,429,437,491,500,534,543,587,596,640,649,683,692,736,745,799,805,811,820,894,904,958,968,974,980,986,995,1065,1074,1082,1088,1094,1148,1154,1160,1204,1214,1220,1226,1235,1365,1374,1383,1390,1396,1402,1408,1414,1420,1427,1433,1439,1446,1452,1458,1465,1471,1477,1484,1490,1496,1503,1509,1515,1522,1528,1536,1542,1602,1608,1616,1649,1655,1662,1671,1678,1684,1691,1697,1703,1709,1718,1725,1734,1741,1747,1759,1765,1772,1778,1787,1837,1846,1890,1899,1943,1949,1955,1961,2031,2037,2043,2103,2109,2115,2121,2127,2133,2135,2141,2147,2205],{"type":65,"attrs":66,"content":68},"paragraph",{"id":67},"p_oxph3el7",[69],{"text":70,"type":71},"In modern web development, especially with frameworks like Next.js, the line between frontend and backend is increasingly blurred. Developers need to think about user interfaces, business logic, databases, authentication, scalability, and security. It's an enormous challenge. Often, we only realize the magnitude of this challenge when we move beyond tutorials and start building real applications.","text",{"type":65,"attrs":73,"content":75},{"id":74},"p_3g4eua1e",[76],{"text":77,"type":71},"This is exactly where Google Firebase transforms from an interesting tool into an indispensable ally. It's not just a database; it's a Backend-as-a-Service (BaaS) platform designed to remove much of the infrastructure complexity, allowing you to build and launch projects in a fraction of the time.",{"type":65,"attrs":79,"content":81},{"id":80},"p_turzqmxu",[82],{"text":83,"type":71},"This article is a comprehensive guide for Next.js developers who want to understand and implement Firebase robustly, leveraging the full power of TypeScript.",{"type":85,"attrs":86,"content":88},"heading",{"id":87},"h_k9po60im",[89],{"text":90,"type":71},"What is Firebase and Why Does It Accelerate Projects?",{"type":65,"attrs":92,"content":94},{"id":93},"p_t17es5d4",[95],{"text":96,"type":71},"Think of Firebase as a \"ready-to-use backend.\" Instead of building, configuring, and maintaining servers, databases, authentication systems, and file storage yourself, Firebase offers all of this as ready-made, scalable services managed by Google.",{"type":65,"attrs":98,"content":100},{"id":99},"p_sbiwgwqe",[101],{"text":102,"type":71},"The main services that accelerate development are:",{"type":65,"attrs":104,"content":106},{"id":105},"p_0hg6tfj9",[107,112],{"text":108,"type":71,"marks":109},"Firestore",[110],{"type":111},"bold",{"text":113,"type":71},": A NoSQL, document-oriented database with real-time query capabilities. Database updates propagate to connected clients in milliseconds.",{"type":65,"attrs":115,"content":117},{"id":116},"p_2fxm721z",[118,122],{"text":119,"type":71,"marks":120},"Firebase Authentication",[121],{"type":111},{"text":123,"type":71},": A complete authentication service supporting email\u002Fpassword, phone, and OAuth providers (Google, Facebook, GitHub, etc.) with just a few lines of code.",{"type":65,"attrs":125,"content":127},{"id":126},"p_sfhn7jk6",[128,132],{"text":129,"type":71,"marks":130},"Cloud Storage for Firebase",[131],{"type":111},{"text":133,"type":71},": For storing and managing user-generated files like images, videos, and documents simply and securely.",{"type":65,"attrs":135,"content":137},{"id":136},"p_5630wlvv",[138,142],{"text":139,"type":71,"marks":140},"Firebase Hosting",[141],{"type":111},{"text":143,"type":71},": High-performance hosting for your static assets and web applications, with global CDN and SSL enabled by default.",{"type":65,"attrs":145,"content":147},{"id":146},"p_s1x1mzk1",[148,152],{"text":149,"type":71,"marks":150},"Cloud Functions for Firebase",[151],{"type":111},{"text":153,"type":71},": Allows you to run backend code (serverless) in response to Firebase ecosystem events (e.g., a new user signing up, a file upload) or HTTP requests.",{"type":65,"attrs":155,"content":157},{"id":156},"p_ich06ow2",[158,162],{"text":159,"type":71,"marks":160},"Firebase App Hosting",[161],{"type":111},{"text":163,"type":71}," (GA in 2025): The next generation of serverless hosting optimized for Next.js and Angular applications with SSR (Server-Side Rendering). Unlike traditional Hosting, App Hosting manages the entire cycle: build, deploy, CDN, and server-side rendering automatically from your GitHub repository.",{"type":65,"attrs":165,"content":167},{"id":166},"p_zksnpgof",[168,172],{"text":169,"type":71,"marks":170},"Data Connect",[171],{"type":111},{"text":173,"type":71}," (GA in 2025): A backend-as-a-service powered by Cloud SQL PostgreSQL. You define your data model through a GraphQL schema, and Data Connect automatically generates secure endpoints and typed SDKs. Includes native support for relational queries, complex joins, and even semantic vector search.",{"type":65,"attrs":175,"content":177},{"id":176},"p_sz7svnux",[178,182],{"text":179,"type":71,"marks":180},"Firebase Studio",[181],{"type":111},{"text":183,"type":71}," (Preview 2025): A cloud-based agentic development environment that allows you to create, prototype, and manage full-stack applications with AI assistance (Gemini). You can generate functional prototypes from natural language or images and publish directly to App Hosting.",{"type":85,"attrs":185,"content":187},{"id":186},"h_io52gbk9",[188],{"text":189,"type":71},"Where Firebase Shines: Abstractions that Free Developers",{"type":65,"attrs":191,"content":193},{"id":192},"p_xkab3lno",[194],{"text":195,"type":71},"Firebase's real power lies in what it prevents you from having to do. It abstracts entire layers of complexity:",{"type":85,"attrs":197,"content":199},{"id":198},"h_3csm3ul4",[200],{"text":201,"type":71},"1. Authentication Abstraction",{"type":65,"attrs":203,"content":205},{"id":204},"p_vk0hk7rc",[206,210],{"text":207,"type":71,"marks":208},"Without Firebase",[209],{"type":111},{"text":211,"type":71},": You'd need to create user tables, implement password hashing and salting, manage session tokens (JWTs), build \"forgot password\" flows, and manually integrate each OAuth provider. It's enormous work, and a security failure can be catastrophic.",{"type":65,"attrs":213,"content":215},{"id":214},"p_m3i4sxqi",[216,220,222,227,229,233],{"text":217,"type":71,"marks":218},"With Firebase",[219],{"type":111},{"text":221,"type":71},": You use ",{"text":223,"type":71,"marks":224},"createUserWithEmailAndPassword()",[225],{"type":226},"code",{"text":228,"type":71}," or ",{"text":230,"type":71,"marks":231},"signInWithPopup()",[232],{"type":226},{"text":234,"type":71},". Firebase manages all the security, tokens, sessions, and complexity behind the scenes, delivering a ready-to-use user object.",{"type":85,"attrs":236,"content":238},{"id":237},"h_dwwfgh41",[239],{"text":240,"type":71},"2. Real-Time Scalable Database Abstraction",{"type":65,"attrs":242,"content":244},{"id":243},"p_45dn2r24",[245,248],{"text":207,"type":71,"marks":246},[247],{"type":111},{"text":249,"type":71},": You'd need to configure a database server (PostgreSQL, MongoDB), manage connections, optimize queries, create a REST or GraphQL API to expose data to the frontend, and for real-time, implement WebSockets. Scaling all of this is a challenge in itself.",{"type":65,"attrs":251,"content":253},{"id":252},"p_8mvf6bb9",[254,257,259,263],{"text":217,"type":71,"marks":255},[256],{"type":111},{"text":258,"type":71},": You define your data structure, set security rules, and use ",{"text":260,"type":71,"marks":261},"onSnapshot()",[262],{"type":226},{"text":264,"type":71}," to \"listen\" to real-time changes. The Firebase SDK handles all communication, optimization, and scalability.",{"type":85,"attrs":266,"content":268},{"id":267},"h_djhiyspr",[269],{"text":270,"type":71},"3. Serverless Infrastructure Abstraction",{"type":65,"attrs":272,"content":274},{"id":273},"p_7ob5cn5a",[275,278],{"text":207,"type":71,"marks":276},[277],{"type":111},{"text":279,"type":71},": You need to manage servers, apply security patches, configure load balancers, and worry about scaling your application.",{"type":65,"attrs":281,"content":283},{"id":282},"p_505qjqbv",[284,287],{"text":217,"type":71,"marks":285},[286],{"type":111},{"text":288,"type":71},": With Hosting, App Hosting, and Cloud Functions, your application and backend run in a serverless environment. You never think about servers. If your application goes viral, Google automatically scales the infrastructure for you.",{"type":85,"attrs":290,"content":292},{"id":291},"h_qc8qd2fb",[293],{"text":294,"type":71},"Firebase Plans: Spark vs Blaze",{"type":65,"attrs":296,"content":298},{"id":297},"p_06lw4p0x",[299],{"text":300,"type":71},"Firebase offers two main plans:",{"type":85,"attrs":302,"content":304},{"id":303},"h_k7ei3uvf",[305],{"text":306,"type":71},"Spark Plan (Free)",{"type":65,"attrs":308,"content":310},{"id":309},"p_dug70vx6",[311],{"text":312,"type":71},"The free plan is incredibly generous and sufficient for most early-stage projects:",{"type":65,"attrs":314,"content":316},{"id":315},"p_dyn4r3xb",[317,321],{"text":318,"type":71,"marks":319},"Fully Free Products",[320],{"type":111},{"text":322,"type":71}," (no limitations beyond fair use):",{"type":324,"attrs":325,"content":327},"bulletList",{"id":326},"ul_3gb17klj",[328,339,349,359,369,379,389,399,409],{"type":329,"attrs":330,"content":332},"listItem",{"id":331},"li_0vqbuez7",[333],{"type":65,"attrs":334,"content":336},{"id":335},"p_nl0wptva",[337],{"text":338,"type":71},"Firebase Analytics (always free, unlimited)",{"type":329,"attrs":340,"content":342},{"id":341},"li_ofelly84",[343],{"type":65,"attrs":344,"content":346},{"id":345},"p_guoohxdw",[347],{"text":348,"type":71},"Cloud Messaging (FCM) - unlimited push notifications",{"type":329,"attrs":350,"content":352},{"id":351},"li_nub9mahp",[353],{"type":65,"attrs":354,"content":356},{"id":355},"p_p2cnbkeh",[357],{"text":358,"type":71},"Remote Config",{"type":329,"attrs":360,"content":362},{"id":361},"li_wy516gix",[363],{"type":65,"attrs":364,"content":366},{"id":365},"p_uqjbk8k8",[367],{"text":368,"type":71},"A\u002FB Testing",{"type":329,"attrs":370,"content":372},{"id":371},"li_x03h1q1y",[373],{"type":65,"attrs":374,"content":376},{"id":375},"p_eij28z35",[377],{"text":378,"type":71},"Crashlytics",{"type":329,"attrs":380,"content":382},{"id":381},"li_p1lf8c5s",[383],{"type":65,"attrs":384,"content":386},{"id":385},"p_r06ivbsy",[387],{"text":388,"type":71},"Performance Monitoring",{"type":329,"attrs":390,"content":392},{"id":391},"li_xlbvv4wu",[393],{"type":65,"attrs":394,"content":396},{"id":395},"p_81ix8mrj",[397],{"text":398,"type":71},"In-App Messaging",{"type":329,"attrs":400,"content":402},{"id":401},"li_erbd7st2",[403],{"type":65,"attrs":404,"content":406},{"id":405},"p_iokl6k91",[407],{"text":408,"type":71},"Dynamic Links",{"type":329,"attrs":410,"content":412},{"id":411},"li_0adqzq82",[413],{"type":65,"attrs":414,"content":416},{"id":415},"p_hyrx5k3q",[417],{"text":418,"type":71},"App Distribution",{"type":65,"attrs":420,"content":422},{"id":421},"p_wjqrogni",[423,427],{"text":424,"type":71,"marks":425},"Products with Daily Free Quota",[426],{"type":111},{"text":428,"type":71},":",{"type":65,"attrs":430,"content":432},{"id":431},"p_ke65m6hh",[433,436],{"text":108,"type":71,"marks":434},[435],{"type":111},{"text":428,"type":71},{"type":324,"attrs":438,"content":440},{"id":439},"ul_y9d88u65",[441,451,461,471,481],{"type":329,"attrs":442,"content":444},{"id":443},"li_4w9oemch",[445],{"type":65,"attrs":446,"content":448},{"id":447},"p_6ho6tk4y",[449],{"text":450,"type":71},"50,000 reads\u002Fday (~1.5M\u002Fmonth)",{"type":329,"attrs":452,"content":454},{"id":453},"li_1hjbb1im",[455],{"type":65,"attrs":456,"content":458},{"id":457},"p_f194fyvj",[459],{"text":460,"type":71},"20,000 writes\u002Fday (~600K\u002Fmonth)",{"type":329,"attrs":462,"content":464},{"id":463},"li_uyhnihxz",[465],{"type":65,"attrs":466,"content":468},{"id":467},"p_blxi0dz2",[469],{"text":470,"type":71},"20,000 deletes\u002Fday (~600K\u002Fmonth)",{"type":329,"attrs":472,"content":474},{"id":473},"li_lhc9leoc",[475],{"type":65,"attrs":476,"content":478},{"id":477},"p_9rk8rmr4",[479],{"text":480,"type":71},"1 GiB total storage",{"type":329,"attrs":482,"content":484},{"id":483},"li_2alkdldq",[485],{"type":65,"attrs":486,"content":488},{"id":487},"p_dz4qf82x",[489],{"text":490,"type":71},"10 GiB network transfer\u002Fmonth",{"type":65,"attrs":492,"content":494},{"id":493},"p_52spkwlv",[495,499],{"text":496,"type":71,"marks":497},"Authentication",[498],{"type":111},{"text":428,"type":71},{"type":324,"attrs":501,"content":503},{"id":502},"ul_x8c8fnam",[504,514,524],{"type":329,"attrs":505,"content":507},{"id":506},"li_euhdyjqb",[508],{"type":65,"attrs":509,"content":511},{"id":510},"p_8n42m0wi",[512],{"text":513,"type":71},"50,000 MAUs (Monthly Active Users) for basic authentication",{"type":329,"attrs":515,"content":517},{"id":516},"li_4q5mx4mn",[518],{"type":65,"attrs":519,"content":521},{"id":520},"p_x9byxg2k",[522],{"text":523,"type":71},"10,000 verifications\u002Fmonth for Phone Authentication (SMS)",{"type":329,"attrs":525,"content":527},{"id":526},"li_jspcr7i6",[528],{"type":65,"attrs":529,"content":531},{"id":530},"p_lg7tzjtu",[532],{"text":533,"type":71},"Unlimited social authentication (Google, Facebook, GitHub, etc.)",{"type":65,"attrs":535,"content":537},{"id":536},"p_38gyh966",[538,542],{"text":539,"type":71,"marks":540},"Cloud Storage",[541],{"type":111},{"text":428,"type":71},{"type":324,"attrs":544,"content":546},{"id":545},"ul_9ptnl3z5",[547,557,567,577],{"type":329,"attrs":548,"content":550},{"id":549},"li_rt9c5h5b",[551],{"type":65,"attrs":552,"content":554},{"id":553},"p_svdbv7oe",[555],{"text":556,"type":71},"5 GB storage",{"type":329,"attrs":558,"content":560},{"id":559},"li_yf5ln1f7",[561],{"type":65,"attrs":562,"content":564},{"id":563},"p_q17892xe",[565],{"text":566,"type":71},"1 GB\u002Fday transfer (download)",{"type":329,"attrs":568,"content":570},{"id":569},"li_m2pwwm3l",[571],{"type":65,"attrs":572,"content":574},{"id":573},"p_2v7mdijk",[575],{"text":576,"type":71},"20,000 get operations\u002Fday",{"type":329,"attrs":578,"content":580},{"id":579},"li_ofnshoxo",[581],{"type":65,"attrs":582,"content":584},{"id":583},"p_cx364a6w",[585],{"text":586,"type":71},"20,000 upload operations\u002Fday",{"type":65,"attrs":588,"content":590},{"id":589},"p_v7s8iijl",[591,595],{"text":592,"type":71,"marks":593},"Hosting",[594],{"type":111},{"text":428,"type":71},{"type":324,"attrs":597,"content":599},{"id":598},"ul_xmts8h80",[600,610,620,630],{"type":329,"attrs":601,"content":603},{"id":602},"li_edu4ne63",[604],{"type":65,"attrs":605,"content":607},{"id":606},"p_lqtegdve",[608],{"text":609,"type":71},"10 GB storage",{"type":329,"attrs":611,"content":613},{"id":612},"li_yjzpgqa3",[614],{"type":65,"attrs":615,"content":617},{"id":616},"p_xaj7jr9u",[618],{"text":619,"type":71},"360 MB\u002Fday transfer (~10 GB\u002Fmonth)",{"type":329,"attrs":621,"content":623},{"id":622},"li_e8n5dsie",[624],{"type":65,"attrs":625,"content":627},{"id":626},"p_yngmqobu",[628],{"text":629,"type":71},"Free SSL certificate",{"type":329,"attrs":631,"content":633},{"id":632},"li_2xmtnzcj",[634],{"type":65,"attrs":635,"content":637},{"id":636},"p_3jicfth0",[638],{"text":639,"type":71},"Global CDN included",{"type":65,"attrs":641,"content":643},{"id":642},"p_y424c4ji",[644,648],{"text":645,"type":71,"marks":646},"Realtime Database",[647],{"type":111},{"text":428,"type":71},{"type":324,"attrs":650,"content":652},{"id":651},"ul_867dnhmc",[653,663,673],{"type":329,"attrs":654,"content":656},{"id":655},"li_lwkbqhfh",[657],{"type":65,"attrs":658,"content":660},{"id":659},"p_1m68tzdf",[661],{"text":662,"type":71},"1 GB storage",{"type":329,"attrs":664,"content":666},{"id":665},"li_k0w7o2jc",[667],{"type":65,"attrs":668,"content":670},{"id":669},"p_ytc7h1le",[671],{"text":672,"type":71},"10 GB\u002Fmonth transfer",{"type":329,"attrs":674,"content":676},{"id":675},"li_lbdwlb8y",[677],{"type":65,"attrs":678,"content":680},{"id":679},"p_pomwkhd3",[681],{"text":682,"type":71},"100 simultaneous connections",{"type":65,"attrs":684,"content":686},{"id":685},"p_53xn7din",[687,691],{"text":688,"type":71,"marks":689},"Cloud Functions",[690],{"type":111},{"text":428,"type":71},{"type":324,"attrs":693,"content":695},{"id":694},"ul_l79rqlrs",[696,706,716,726],{"type":329,"attrs":697,"content":699},{"id":698},"li_gtivbbzo",[700],{"type":65,"attrs":701,"content":703},{"id":702},"p_lmn5ra2d",[704],{"text":705,"type":71},"125,000 invocations\u002Fmonth",{"type":329,"attrs":707,"content":709},{"id":708},"li_3mr1urrn",[710],{"type":65,"attrs":711,"content":713},{"id":712},"p_fh7z6sdu",[714],{"text":715,"type":71},"40,000 GB-seconds compute resources",{"type":329,"attrs":717,"content":719},{"id":718},"li_4lsh4g5e",[720],{"type":65,"attrs":721,"content":723},{"id":722},"p_wqpxt6bv",[724],{"text":725,"type":71},"40,000 CPU-seconds",{"type":329,"attrs":727,"content":729},{"id":728},"li_jfwxtevj",[730],{"type":65,"attrs":731,"content":733},{"id":732},"p_yn1f8qx0",[734],{"text":735,"type":71},"5 GB outbound traffic\u002Fmonth",{"type":65,"attrs":737,"content":739},{"id":738},"p_20zwfy0p",[740,744],{"text":741,"type":71,"marks":742},"Spark Plan Limitations",[743],{"type":111},{"text":428,"type":71},{"type":324,"attrs":746,"content":748},{"id":747},"ul_ygvpiv7x",[749,759,769,779,789],{"type":329,"attrs":750,"content":752},{"id":751},"li_ytog3d89",[753],{"type":65,"attrs":754,"content":756},{"id":755},"p_6mnnx5in",[757],{"text":758,"type":71},"Only one Firestore database per project qualifies for free quota",{"type":329,"attrs":760,"content":762},{"id":761},"li_vc7o3xgh",[763],{"type":65,"attrs":764,"content":766},{"id":765},"p_ln30rvcn",[767],{"text":768,"type":71},"Cannot use Firebase Extensions (requires Blaze)",{"type":329,"attrs":770,"content":772},{"id":771},"li_cehf1ba7",[773],{"type":65,"attrs":774,"content":776},{"id":775},"p_ezz4gsfe",[777],{"text":778,"type":71},"Cannot use App Hosting (requires Blaze)",{"type":329,"attrs":780,"content":782},{"id":781},"li_mzta7ifq",[783],{"type":65,"attrs":784,"content":786},{"id":785},"p_dil46yu6",[787],{"text":788,"type":71},"No access to paid Google Cloud products (BigQuery, Pub\u002FSub, etc.)",{"type":329,"attrs":790,"content":792},{"id":791},"li_zy41bt4q",[793],{"type":65,"attrs":794,"content":796},{"id":795},"p_35s6wcvi",[797],{"text":798,"type":71},"Cloud Functions limited to Firebase triggers only",{"type":85,"attrs":800,"content":802},{"id":801},"h_glju20f4",[803],{"text":804,"type":71},"Blaze Plan (Pay-as-you-go)",{"type":65,"attrs":806,"content":808},{"id":807},"p_50xdp7c6",[809],{"text":810,"type":71},"The Blaze plan maintains all Spark free quotas and adds:",{"type":65,"attrs":812,"content":814},{"id":813},"p_zu4okqtb",[815,819],{"text":816,"type":71,"marks":817},"Advantages",[818],{"type":111},{"text":428,"type":71},{"type":324,"attrs":821,"content":823},{"id":822},"ul_j9xpb2v5",[824,834,844,854,864,874,884],{"type":329,"attrs":825,"content":827},{"id":826},"li_aijw32nm",[828],{"type":65,"attrs":829,"content":831},{"id":830},"p_hnqb2bm4",[832],{"text":833,"type":71},"Billing only for usage above free quotas",{"type":329,"attrs":835,"content":837},{"id":836},"li_hjyu9v6h",[838],{"type":65,"attrs":839,"content":841},{"id":840},"p_na0rtqip",[842],{"text":843,"type":71},"Access to Firebase Extensions",{"type":329,"attrs":845,"content":847},{"id":846},"li_nsx4wv75",[848],{"type":65,"attrs":849,"content":851},{"id":850},"p_hkki0z4i",[852],{"text":853,"type":71},"Access to App Hosting",{"type":329,"attrs":855,"content":857},{"id":856},"li_ft3p0550",[858],{"type":65,"attrs":859,"content":861},{"id":860},"p_yrzi6udz",[862],{"text":863,"type":71},"Full access to Google Cloud products",{"type":329,"attrs":865,"content":867},{"id":866},"li_gruaizzi",[868],{"type":65,"attrs":869,"content":871},{"id":870},"p_7f3cet21",[872],{"text":873,"type":71},"Cloud Functions can respond to HTTP events and other triggers",{"type":329,"attrs":875,"content":877},{"id":876},"li_bp4daxho",[878],{"type":65,"attrs":879,"content":881},{"id":880},"p_8oxan4qd",[882],{"text":883,"type":71},"Ability to create multiple databases (only the first has free quota)",{"type":329,"attrs":885,"content":887},{"id":886},"li_ri7v5hjj",[888],{"type":65,"attrs":889,"content":891},{"id":890},"p_mads0c0c",[892],{"text":893,"type":71},"$300 credits available for eligible new users",{"type":65,"attrs":895,"content":897},{"id":896},"p_8jvq7p6u",[898,902],{"text":899,"type":71,"marks":900},"Costs After Free Quota",[901],{"type":111},{"text":903,"type":71}," (may vary by region):",{"type":324,"attrs":905,"content":907},{"id":906},"ul_ru5rmlas",[908,918,928,938,948],{"type":329,"attrs":909,"content":911},{"id":910},"li_csxmgrl8",[912],{"type":65,"attrs":913,"content":915},{"id":914},"p_d0qkf25s",[916],{"text":917,"type":71},"Firestore: ~$0.06 per 100K reads, ~$0.18 per 100K writes",{"type":329,"attrs":919,"content":921},{"id":920},"li_f2p9g6kx",[922],{"type":65,"attrs":923,"content":925},{"id":924},"p_863xr84n",[926],{"text":927,"type":71},"Cloud Storage: ~$0.026\u002FGB storage, ~$0.12\u002FGB transfer",{"type":329,"attrs":929,"content":931},{"id":930},"li_jx13zte3",[932],{"type":65,"attrs":933,"content":935},{"id":934},"p_0tw0ipzn",[936],{"text":937,"type":71},"Authentication: Free up to 50K MAUs, then $0.0055\u002FMAU (Tier 1)",{"type":329,"attrs":939,"content":941},{"id":940},"li_4vyodc7a",[942],{"type":65,"attrs":943,"content":945},{"id":944},"p_ghx10r3t",[946],{"text":947,"type":71},"Cloud Functions: ~$0.40 per million invocations",{"type":329,"attrs":949,"content":951},{"id":950},"li_eb2vrf3z",[952],{"type":65,"attrs":953,"content":955},{"id":954},"p_ero6687l",[956],{"text":957,"type":71},"Hosting: ~$0.15\u002FGB after free quota",{"type":65,"attrs":959,"content":961},{"id":960},"p_scahses2",[962,966],{"text":963,"type":71,"marks":964},"Important",[965],{"type":111},{"text":967,"type":71},": Set up budget alerts in Google Cloud Console to avoid surprises. Firebase doesn't automatically block usage when limits are reached - you need to actively monitor.",{"type":85,"attrs":969,"content":971},{"id":970},"h_v38zwkqs",[972],{"text":973,"type":71},"Modern AI Features in Firebase",{"type":85,"attrs":975,"content":977},{"id":976},"h_5sbao6hx",[978],{"text":979,"type":71},"Genkit: Open Source Framework for AI",{"type":65,"attrs":981,"content":983},{"id":982},"p_b9gp9mlm",[984],{"text":985,"type":71},"Genkit is an open-source framework created by Google to build AI features in applications. It supports JavaScript\u002FTypeScript, Python (Alpha), and Go (Beta).",{"type":65,"attrs":987,"content":989},{"id":988},"p_u7ecr8d1",[990,994],{"text":991,"type":71,"marks":992},"Key Features",[993],{"type":111},{"text":428,"type":71},{"type":324,"attrs":996,"content":998},{"id":997},"ul_y9m5ky8v",[999,1009,1019,1029,1045,1055],{"type":329,"attrs":1000,"content":1002},{"id":1001},"li_08lhbfcr",[1003],{"type":65,"attrs":1004,"content":1006},{"id":1005},"p_a2abeudx",[1007],{"text":1008,"type":71},"Unified API for multiple model providers (Gemini, OpenAI, Anthropic, Ollama)",{"type":329,"attrs":1010,"content":1012},{"id":1011},"li_xw5oqvp3",[1013],{"type":65,"attrs":1014,"content":1016},{"id":1015},"p_mla8wwb4",[1017],{"text":1018,"type":71},"Native support for RAG (Retrieval-Augmented Generation)",{"type":329,"attrs":1020,"content":1022},{"id":1021},"li_fmjferii",[1023],{"type":65,"attrs":1024,"content":1026},{"id":1025},"p_gancpcw6",[1027],{"text":1028,"type":71},"Local Developer UI for testing and debugging",{"type":329,"attrs":1030,"content":1032},{"id":1031},"li_z7h51e1i",[1033],{"type":65,"attrs":1034,"content":1036},{"id":1035},"p_z19xarer",[1037,1039,1043],{"text":1038,"type":71},"Direct integration with Cloud Functions via ",{"text":1040,"type":71,"marks":1041},"onCallGenkit",[1042],{"type":226},{"text":1044,"type":71}," trigger",{"type":329,"attrs":1046,"content":1048},{"id":1047},"li_15za1hnl",[1049],{"type":65,"attrs":1050,"content":1052},{"id":1051},"p_nu5cbfq2",[1053],{"text":1054,"type":71},"Response streaming for real-time experiences",{"type":329,"attrs":1056,"content":1058},{"id":1057},"li_i34blzkd",[1059],{"type":65,"attrs":1060,"content":1062},{"id":1061},"p_ycpt2a9c",[1063],{"text":1064,"type":71},"Integrated monitoring in Firebase Console",{"type":65,"attrs":1066,"content":1068},{"id":1067},"p_noupv2bi",[1069,1073],{"text":1070,"type":71,"marks":1071},"Basic Example with Genkit",[1072],{"type":111},{"text":428,"type":71},{"type":1075,"attrs":1076,"content":1079},"codeBlock",{"id":1077,"highlighted":1078},"code_3v34dj0v","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { genkit } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'genkit'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { googleAI } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> '@genkit-ai\u002Fgoogleai'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> ai\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> genkit\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  plugins: [\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">googleAI\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">()],\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  model: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'gemini-1.5-flash'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> chatFlow\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> ai.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">defineFlow\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'chat'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">async\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#E36209;--shiki-dark:#FFAB70\">input\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> string\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=>\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> response\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> ai.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">generate\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    prompt: input,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    model: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'gemini-1.5-flash'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  });\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> response.text;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">});\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[1080],{"text":1081,"type":71},"import { genkit } from 'genkit';\nimport { googleAI } from '@genkit-ai\u002Fgoogleai';\n\nconst ai = genkit({\n  plugins: [googleAI()],\n  model: 'gemini-1.5-flash',\n});\n\nconst chatFlow = ai.defineFlow('chat', async (input: string) => {\n  const response = await ai.generate({\n    prompt: input,\n    model: 'gemini-1.5-flash',\n  });\n  return response.text;\n});",{"type":85,"attrs":1083,"content":1085},{"id":1084},"h_ews7wgal",[1086],{"text":1087,"type":71},"Vertex AI in Firebase",{"type":65,"attrs":1089,"content":1091},{"id":1090},"p_hagng382",[1092],{"text":1093,"type":71},"Allows integrating Gemini and Imagen models directly into mobile and web applications:",{"type":324,"attrs":1095,"content":1097},{"id":1096},"ul_s0cv78su",[1098,1108,1118,1128,1138],{"type":329,"attrs":1099,"content":1101},{"id":1100},"li_4txwl7jt",[1102],{"type":65,"attrs":1103,"content":1105},{"id":1104},"p_9qiiabxi",[1106],{"text":1107,"type":71},"Gemini API for text generation and chat",{"type":329,"attrs":1109,"content":1111},{"id":1110},"li_18lnz0an",[1112],{"type":65,"attrs":1113,"content":1115},{"id":1114},"p_m3j6uczw",[1116],{"text":1117,"type":71},"Imagen 3 for image generation from text",{"type":329,"attrs":1119,"content":1121},{"id":1120},"li_rpyeq296",[1122],{"type":65,"attrs":1123,"content":1125},{"id":1124},"p_eawxaax2",[1126],{"text":1127,"type":71},"Live API for real-time voice interactions",{"type":329,"attrs":1129,"content":1131},{"id":1130},"li_rteykyox",[1132],{"type":65,"attrs":1133,"content":1135},{"id":1134},"p_tb2kgsao",[1136],{"text":1137,"type":71},"Simplified serverless SDK",{"type":329,"attrs":1139,"content":1141},{"id":1140},"li_mghhcxvq",[1142],{"type":65,"attrs":1143,"content":1145},{"id":1144},"p_mccfoyhh",[1146],{"text":1147,"type":71},"No infrastructure management needed",{"type":85,"attrs":1149,"content":1151},{"id":1150},"h_gb6twm23",[1152],{"text":1153,"type":71},"Gemini in Firebase",{"type":65,"attrs":1155,"content":1157},{"id":1156},"p_eb2nvx1d",[1158],{"text":1159,"type":71},"AI assistant integrated into Firebase Console that helps with:",{"type":324,"attrs":1161,"content":1163},{"id":1162},"ul_jzmh6unv",[1164,1174,1184,1194],{"type":329,"attrs":1165,"content":1167},{"id":1166},"li_gup8kgth",[1168],{"type":65,"attrs":1169,"content":1171},{"id":1170},"p_k1oacrj7",[1172],{"text":1173,"type":71},"Schema creation in Data Connect",{"type":329,"attrs":1175,"content":1177},{"id":1176},"li_2qntlys0",[1178],{"type":65,"attrs":1179,"content":1181},{"id":1180},"p_9pgvuh2x",[1182],{"text":1183,"type":71},"GraphQL query and mutation generation",{"type":329,"attrs":1185,"content":1187},{"id":1186},"li_zy3e1d0m",[1188],{"type":65,"attrs":1189,"content":1191},{"id":1190},"p_ihpxju4l",[1192],{"text":1193,"type":71},"Security rule suggestions",{"type":329,"attrs":1195,"content":1197},{"id":1196},"li_eju3mzwh",[1198],{"type":65,"attrs":1199,"content":1201},{"id":1200},"p_v94oljq6",[1202],{"text":1203,"type":71},"Code optimization",{"type":65,"attrs":1205,"content":1207},{"id":1206},"p_2cgkpvf7",[1208,1212],{"text":1209,"type":71,"marks":1210},"Cost",[1211],{"type":111},{"text":1213,"type":71},": Free for individual developers. Google Workspace users need Gemini Code Assist subscription.",{"type":85,"attrs":1215,"content":1217},{"id":1216},"h_kbtvtqsg",[1218],{"text":1219,"type":71},"Firebase Extensions: Ready Functionality in Minutes",{"type":65,"attrs":1221,"content":1223},{"id":1222},"p_dbxq6ozx",[1224],{"text":1225,"type":71},"Firebase Extensions are pre-packaged solutions that add complex functionality to your application without needing to code from scratch.",{"type":65,"attrs":1227,"content":1229},{"id":1228},"p_2gcf6uiy",[1230,1234],{"text":1231,"type":71,"marks":1232},"Popular Extensions",[1233],{"type":111},{"text":428,"type":71},{"type":324,"attrs":1236,"content":1238},{"id":1237},"ul_glygg21z",[1239,1253,1267,1281,1295,1309,1323,1337,1351],{"type":329,"attrs":1240,"content":1242},{"id":1241},"li_0ol63zvu",[1243],{"type":65,"attrs":1244,"content":1246},{"id":1245},"p_7hh8lif5",[1247,1251],{"text":1248,"type":71,"marks":1249},"Resize Images",[1250],{"type":111},{"text":1252,"type":71},": Automatically resizes images on upload",{"type":329,"attrs":1254,"content":1256},{"id":1255},"li_enzck7ew",[1257],{"type":65,"attrs":1258,"content":1260},{"id":1259},"p_72u09u8p",[1261,1265],{"text":1262,"type":71,"marks":1263},"Translate Text",[1264],{"type":111},{"text":1266,"type":71},": Translates Firestore strings to multiple languages",{"type":329,"attrs":1268,"content":1270},{"id":1269},"li_bdheevrd",[1271],{"type":65,"attrs":1272,"content":1274},{"id":1273},"p_9mos3tzl",[1275,1279],{"text":1276,"type":71,"marks":1277},"Trigger Email",[1278],{"type":111},{"text":1280,"type":71},": Automatically sends emails based on Firestore events",{"type":329,"attrs":1282,"content":1284},{"id":1283},"li_hml6aaw4",[1285],{"type":65,"attrs":1286,"content":1288},{"id":1287},"p_0q2dh0uc",[1289,1293],{"text":1290,"type":71,"marks":1291},"Stripe Payments",[1292],{"type":111},{"text":1294,"type":71},": Complete Stripe integration for payments",{"type":329,"attrs":1296,"content":1298},{"id":1297},"li_pcs1am4r",[1299],{"type":65,"attrs":1300,"content":1302},{"id":1301},"p_62ryeg7s",[1303,1307],{"text":1304,"type":71,"marks":1305},"Export to BigQuery",[1306],{"type":111},{"text":1308,"type":71},": Automatically exports Firestore data to BigQuery",{"type":329,"attrs":1310,"content":1312},{"id":1311},"li_wdd68hhg",[1313],{"type":65,"attrs":1314,"content":1316},{"id":1315},"p_8iwstnyo",[1317,1321],{"text":1318,"type":71,"marks":1319},"Delete User Data",[1320],{"type":111},{"text":1322,"type":71},": Removes all user data when account is deleted",{"type":329,"attrs":1324,"content":1326},{"id":1325},"li_1qcbh4zv",[1327],{"type":65,"attrs":1328,"content":1330},{"id":1329},"p_u5ju5ra4",[1331,1335],{"text":1332,"type":71,"marks":1333},"Chatbot with Gemini",[1334],{"type":111},{"text":1336,"type":71},": Creates customizable chatbots using Gemini models",{"type":329,"attrs":1338,"content":1340},{"id":1339},"li_liqvst0j",[1341],{"type":65,"attrs":1342,"content":1344},{"id":1343},"p_41x23tif",[1345,1349],{"text":1346,"type":71,"marks":1347},"Algolia Search",[1348],{"type":111},{"text":1350,"type":71},": Adds full-text search to your Firestore data",{"type":329,"attrs":1352,"content":1354},{"id":1353},"li_jqvmyc5g",[1355],{"type":65,"attrs":1356,"content":1358},{"id":1357},"p_p0o0h9rc",[1359,1363],{"text":1360,"type":71,"marks":1361},"Mailchimp Sync",[1362],{"type":111},{"text":1364,"type":71},": Syncs users with Mailchimp audiences",{"type":65,"attrs":1366,"content":1368},{"id":1367},"p_24s6tbig",[1369,1372],{"text":963,"type":71,"marks":1370},[1371],{"type":111},{"text":1373,"type":71},": Extensions require the Blaze plan, but you only pay for resources the extension consumes (e.g., invoked Cloud Functions).",{"type":65,"attrs":1375,"content":1377},{"id":1376},"p_7llajvhd",[1378,1382],{"text":1379,"type":71,"marks":1380},"How to Install",[1381],{"type":111},{"text":428,"type":71},{"type":1075,"attrs":1384,"content":1387},{"id":1385,"highlighted":1386},"code_ojces4hu","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">firebase \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">ext\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:install firebase\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">firestore\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">-\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">bigquery\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">-export\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[1388],{"text":1389,"type":71},"firebase ext:install firebase\u002Ffirestore-bigquery-export",{"type":65,"attrs":1391,"content":1393},{"id":1392},"p_2anlk2lq",[1394],{"text":1395,"type":71},"Or through Firebase Console in Extensions → Browse Extensions.",{"type":85,"attrs":1397,"content":1399},{"id":1398},"h_1897pggk",[1400],{"text":1401,"type":71},"Robust Setup: Firebase with Next.js and TypeScript",{"type":65,"attrs":1403,"content":1405},{"id":1404},"p_p0t79tmq",[1406],{"text":1407,"type":71},"Let's get practical. The key to robust integration with Next.js (App Router) is separating Firebase initialization for client-side (Client Components) and server-side (Server Components, Route Handlers).",{"type":85,"attrs":1409,"content":1411},{"id":1410},"h_b5uj7lh4",[1412],{"text":1413,"type":71},"1. Project Structure",{"type":65,"attrs":1415,"content":1417},{"id":1416},"p_465g9cn6",[1418],{"text":1419,"type":71},"Create a folder at your project root to organize configuration:",{"type":1075,"attrs":1421,"content":1424},{"id":1422,"highlighted":1423},"code_nlvjsobj","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">├── app\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">├── lib\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">│   └── firebase\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">│       ├── admin.ts       \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F Admin SDK configuration (server-side)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">│       └── client.ts      \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F Client SDK configuration (client-side)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">└── \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">...\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[1425],{"text":1426,"type":71},"\u002F\n├── app\u002F\n├── lib\u002F\n│   └── firebase\u002F\n│       ├── admin.ts       \u002F\u002F Admin SDK configuration (server-side)\n│       └── client.ts      \u002F\u002F Client SDK configuration (client-side)\n└── ...",{"type":85,"attrs":1428,"content":1430},{"id":1429},"h_yq3bpswf",[1431],{"text":1432,"type":71},"2. Environment Variables (.env.local)",{"type":65,"attrs":1434,"content":1436},{"id":1435},"p_et3t135v",[1437],{"text":1438,"type":71},"Add your Firebase credentials to the .env.local file. Client variables must start with NEXT_PUBLIC_.",{"type":1075,"attrs":1440,"content":1443},{"id":1441,"highlighted":1442},"code_qnmkd9u7","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"># Client\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">-\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">side \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">Config\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (safe to expose \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">in\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> browser)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NEXT_PUBLIC_FIREBASE_API_KEY\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"AIza...\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"your-project.firebaseapp.com\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NEXT_PUBLIC_FIREBASE_PROJECT_ID\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"your-project\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"your-project.appspot.com\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"...\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NEXT_PUBLIC_FIREBASE_APP_ID\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"1:...\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"># Server\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">-\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">side \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">Config\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">SECRET\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> -\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> NEVER\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> expose to client)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">FIREBASE_PRIVATE_KEY\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"-----BEGIN PRIVATE KEY-----\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">\\n\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">...\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">FIREBASE_CLIENT_EMAIL\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"firebase-adminsdk-...@your-project.iam.gserviceaccount.com\"\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[1444],{"text":1445,"type":71},"# Client-side Config (safe to expose in browser)\nNEXT_PUBLIC_FIREBASE_API_KEY=\"AIza...\"\nNEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=\"your-project.firebaseapp.com\"\nNEXT_PUBLIC_FIREBASE_PROJECT_ID=\"your-project\"\nNEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=\"your-project.appspot.com\"\nNEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=\"...\"\nNEXT_PUBLIC_FIREBASE_APP_ID=\"1:...\"\n\n# Server-side Config (SECRET - NEVER expose to client)\nFIREBASE_PRIVATE_KEY=\"-----BEGIN PRIVATE KEY-----\\n...\"\nFIREBASE_CLIENT_EMAIL=\"firebase-adminsdk-...@your-project.iam.gserviceaccount.com\"",{"type":85,"attrs":1447,"content":1449},{"id":1448},"h_sv7w1ccd",[1450],{"text":1451,"type":71},"3. Client SDK Configuration (lib\u002Ffirebase\u002Fclient.ts)",{"type":65,"attrs":1453,"content":1455},{"id":1454},"p_r94atzd3",[1456],{"text":1457,"type":71},"This file initializes Firebase for use in Client Components.",{"type":1075,"attrs":1459,"content":1462},{"id":1460,"highlighted":1461},"code_8aaqy0zo","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { initializeApp, getApps, getApp } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> \"firebase\u002Fapp\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { getAuth } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> \"firebase\u002Fauth\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { getFirestore } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> \"firebase\u002Ffirestore\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { getStorage } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> \"firebase\u002Fstorage\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> firebaseConfig\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  apiKey: process.env.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NEXT_PUBLIC_FIREBASE_API_KEY\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  authDomain: process.env.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  projectId: process.env.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NEXT_PUBLIC_FIREBASE_PROJECT_ID\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  storageBucket: process.env.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  messagingSenderId: process.env.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  appId: process.env.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NEXT_PUBLIC_FIREBASE_APP_ID\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">};\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F Initialize Firebase for client-side\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F The getApps().length check prevents reinitialization on HMR (Hot Module Replacement)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> app\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> !\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">getApps\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">().\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">length\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> ?\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> initializeApp\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(firebaseConfig) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> getApp\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> auth\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> getAuth\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(app);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> db\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> getFirestore\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(app);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> storage\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> getStorage\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(app);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">export\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { app, auth, db, storage };\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[1463],{"text":1464,"type":71},"import { initializeApp, getApps, getApp } from \"firebase\u002Fapp\";\nimport { getAuth } from \"firebase\u002Fauth\";\nimport { getFirestore } from \"firebase\u002Ffirestore\";\nimport { getStorage } from \"firebase\u002Fstorage\";\n\nconst firebaseConfig = {\n  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,\n  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,\n  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,\n  storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,\n  messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,\n  appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,\n};\n\n\u002F\u002F Initialize Firebase for client-side\n\u002F\u002F The getApps().length check prevents reinitialization on HMR (Hot Module Replacement)\nconst app = !getApps().length ? initializeApp(firebaseConfig) : getApp();\n\nconst auth = getAuth(app);\nconst db = getFirestore(app);\nconst storage = getStorage(app);\n\nexport { app, auth, db, storage };",{"type":85,"attrs":1466,"content":1468},{"id":1467},"h_knzm7lja",[1469],{"text":1470,"type":71},"4. Admin SDK Configuration (lib\u002Ffirebase\u002Fadmin.ts)",{"type":65,"attrs":1472,"content":1474},{"id":1473},"p_mz46lhkr",[1475],{"text":1476,"type":71},"This file initializes Firebase for secure backend use (Route Handlers, Server Components). It uses admin credentials that should never be exposed to the client.",{"type":1075,"attrs":1478,"content":1481},{"id":1479,"highlighted":1480},"code_tjy3z6hv","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> admin \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> \"firebase-admin\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F Decode the private key that's on a single line in .env\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> privateKey\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> process.env.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">FIREBASE_PRIVATE_KEY\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">?.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">replace\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#22863A;--shiki-light-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold\">\\\\\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#DBEDFF\">n\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">g\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">\\n\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">!\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">admin.apps.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">length\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  admin.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">initializeApp\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    credential: admin.credential.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">cert\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      projectId: process.env.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NEXT_PUBLIC_FIREBASE_PROJECT_ID\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      clientEmail: process.env.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">FIREBASE_CLIENT_EMAIL\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      privateKey: privateKey,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    }),\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  });\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> adminAuth\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> admin.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">auth\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> adminDb\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> admin.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">firestore\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">export\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { adminAuth, adminDb };\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[1482],{"text":1483,"type":71},"import admin from \"firebase-admin\";\n\n\u002F\u002F Decode the private key that's on a single line in .env\nconst privateKey = process.env.FIREBASE_PRIVATE_KEY?.replace(\u002F\\\\n\u002Fg, '\\n');\n\nif (!admin.apps.length) {\n  admin.initializeApp({\n    credential: admin.credential.cert({\n      projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,\n      clientEmail: process.env.FIREBASE_CLIENT_EMAIL,\n      privateKey: privateKey,\n    }),\n  });\n}\n\nconst adminAuth = admin.auth();\nconst adminDb = admin.firestore();\n\nexport { adminAuth, adminDb };",{"type":85,"attrs":1485,"content":1487},{"id":1486},"h_78jupv94",[1488],{"text":1489,"type":71},"5. Gold Standard: Authentication Hook (Client-side)",{"type":65,"attrs":1491,"content":1493},{"id":1492},"p_phsomdzr",[1494],{"text":1495,"type":71},"To manage user state reactively and with typing, create a custom hook.",{"type":1075,"attrs":1497,"content":1500},{"id":1498,"highlighted":1499},"code_qrmznkee","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F hooks\u002FuseAuth.ts\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'use client'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { useState, useEffect } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'react'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { onAuthStateChanged, User } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'firebase\u002Fauth'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { auth } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> '@\u002Flib\u002Ffirebase\u002Fclient'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">export\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> function\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> useAuth\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">() {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> [\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">user\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">setUser\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">] \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> useState\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">&#x3C;\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">User\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> |\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> null\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">>(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">null\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> [\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">loading\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">setLoading\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">] \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> useState\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">true\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">  useEffect\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(() \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=>\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">    const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> unsubscribe\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> onAuthStateChanged\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(auth, (\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#E36209;--shiki-dark:#FFAB70\">user\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=>\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">      setUser\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(user);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">      setLoading\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">false\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    });\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">    \u002F\u002F Clean up listener when component unmounts\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">    return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> () \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=>\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> unsubscribe\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  }, []);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { user, loading };\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[1501],{"text":1502,"type":71},"\u002F\u002F hooks\u002FuseAuth.ts\n'use client';\n\nimport { useState, useEffect } from 'react';\nimport { onAuthStateChanged, User } from 'firebase\u002Fauth';\nimport { auth } from '@\u002Flib\u002Ffirebase\u002Fclient';\n\nexport function useAuth() {\n  const [user, setUser] = useState\u003CUser | null>(null);\n  const [loading, setLoading] = useState(true);\n\n  useEffect(() => {\n    const unsubscribe = onAuthStateChanged(auth, (user) => {\n      setUser(user);\n      setLoading(false);\n    });\n\n    \u002F\u002F Clean up listener when component unmounts\n    return () => unsubscribe();\n  }, []);\n\n  return { user, loading };\n}",{"type":85,"attrs":1504,"content":1506},{"id":1505},"h_n7kfui43",[1507],{"text":1508,"type":71},"6. Server Usage (Example: Route Handler)",{"type":65,"attrs":1510,"content":1512},{"id":1511},"p_jj6qng01",[1513],{"text":1514,"type":71},"For operations requiring admin privileges (e.g., creating a custom user, accessing data while bypassing security rules), use the Admin SDK in a Route Handler.",{"type":1075,"attrs":1516,"content":1519},{"id":1517,"highlighted":1518},"code_f5jywalh","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F app\u002Fapi\u002Fpromote-user\u002Froute.ts\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { NextResponse } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'next\u002Fserver'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { adminAuth } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> '@\u002Flib\u002Ffirebase\u002Fadmin'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">export\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> async\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> function\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> POST\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#E36209;--shiki-dark:#FFAB70\">request\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> Request\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">userId\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> request.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">json\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">!\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">userId) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">    return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> NextResponse.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">json\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">({ error: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'User ID is required'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> }, { status: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">400\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> });\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  try\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">    \u002F\u002F Example: Add a custom claim to make user an 'admin'\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">    await\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> adminAuth.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">setCustomUserClaims\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(userId, { admin: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">true\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> });\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">    return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> NextResponse.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">json\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">({ message: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">`User ${\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">userId\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">} has been promoted to admin.`\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> });\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">catch\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (error) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">    return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> NextResponse.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">json\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">({ error: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'Failed to promote user'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> }, { status: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">500\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> });\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[1520],{"text":1521,"type":71},"\u002F\u002F app\u002Fapi\u002Fpromote-user\u002Froute.ts\nimport { NextResponse } from 'next\u002Fserver';\nimport { adminAuth } from '@\u002Flib\u002Ffirebase\u002Fadmin';\n\nexport async function POST(request: Request) {\n  const { userId } = await request.json();\n\n  if (!userId) {\n    return NextResponse.json({ error: 'User ID is required' }, { status: 400 });\n  }\n\n  try {\n    \u002F\u002F Example: Add a custom claim to make user an 'admin'\n    await adminAuth.setCustomUserClaims(userId, { admin: true });\n    return NextResponse.json({ message: `User ${userId} has been promoted to admin.` });\n  } catch (error) {\n    return NextResponse.json({ error: 'Failed to promote user' }, { status: 500 });\n  }\n}",{"type":85,"attrs":1523,"content":1525},{"id":1524},"h_i12ositj",[1526],{"text":1527,"type":71},"Integrating Data Connect with Next.js",{"type":65,"attrs":1529,"content":1531},{"id":1530},"p_gytypila",[1532],{"text":1533,"type":71,"marks":1534},"What is Data Connect?",[1535],{"type":111},{"type":65,"attrs":1537,"content":1539},{"id":1538},"p_t9jfnud9",[1540],{"text":1541,"type":71},"Data Connect is a backend-as-a-service that combines the power of a managed PostgreSQL database (Cloud SQL) with the simplicity of automatically generated typed SDKs. Unlike Firestore (NoSQL), Data Connect is ideal when you need:",{"type":324,"attrs":1543,"content":1545},{"id":1544},"ul_8oeuacef",[1546,1560,1574,1588],{"type":329,"attrs":1547,"content":1549},{"id":1548},"li_0r0x0ho1",[1550],{"type":65,"attrs":1551,"content":1553},{"id":1552},"p_jn9vo4ot",[1554,1558],{"text":1555,"type":71,"marks":1556},"Complex relationships",[1557],{"type":111},{"text":1559,"type":71},": Joins, foreign keys, and referential integrity",{"type":329,"attrs":1561,"content":1563},{"id":1562},"li_hli09bdb",[1564],{"type":65,"attrs":1565,"content":1567},{"id":1566},"p_4hbsa0b8",[1568,1572],{"text":1569,"type":71,"marks":1570},"Advanced SQL queries",[1571],{"type":111},{"text":1573,"type":71},": Aggregations, subqueries, and multi-step transactions",{"type":329,"attrs":1575,"content":1577},{"id":1576},"li_20yn3p1c",[1578],{"type":65,"attrs":1579,"content":1581},{"id":1580},"p_mpxlqb1l",[1582,1586],{"text":1583,"type":71,"marks":1584},"Strong end-to-end typing",[1585],{"type":111},{"text":1587,"type":71},": From database to client, with TypeScript",{"type":329,"attrs":1589,"content":1591},{"id":1590},"li_iu8il5hc",[1592],{"type":65,"attrs":1593,"content":1595},{"id":1594},"p_4k98j7af",[1596,1600],{"text":1597,"type":71,"marks":1598},"GraphQL without complexity",[1599],{"type":111},{"text":1601,"type":71},": You write the schema, Data Connect generates the resolvers",{"type":65,"attrs":1603,"content":1605},{"id":1604},"p_l8fbmq8y",[1606],{"text":1607,"type":71},"Instead of manually writing APIs, you define your data model in GraphQL and Data Connect automatically creates secure endpoints and typed SDKs for React, Angular, Next.js, and mobile (iOS\u002FAndroid).",{"type":65,"attrs":1609,"content":1611},{"id":1610},"p_5p0n5xot",[1612],{"text":1613,"type":71,"marks":1614},"When to use Data Connect vs Firestore?",[1615],{"type":111},{"type":324,"attrs":1617,"content":1619},{"id":1618},"ul_91jgarz6",[1620,1635],{"type":329,"attrs":1621,"content":1623},{"id":1622},"li_vb9k0y9t",[1624],{"type":65,"attrs":1625,"content":1627},{"id":1626},"p_lu7qltfw",[1628,1630,1633],{"text":1629,"type":71},"Use ",{"text":169,"type":71,"marks":1631},[1632],{"type":111},{"text":1634,"type":71}," for: e-commerce, ERPs, systems with complex relational data",{"type":329,"attrs":1636,"content":1638},{"id":1637},"li_asmq1w5d",[1639],{"type":65,"attrs":1640,"content":1642},{"id":1641},"p_d4ffnwi2",[1643,1644,1647],{"text":1629,"type":71},{"text":108,"type":71,"marks":1645},[1646],{"type":111},{"text":1648,"type":71}," for: real-time chat, social feeds, hierarchical data and documents",{"type":65,"attrs":1650,"content":1652},{"id":1651},"p_8av39ooh",[1653],{"text":1654,"type":71},"Data Connect is ideal for applications needing a relational database with strong typing:",{"type":1075,"attrs":1656,"content":1659},{"id":1657,"highlighted":1658},"code_lmxwg5bn","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F lib\u002Ffirebase\u002Fdataconnect.ts\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { getDataConnect, connectDataConnectEmulator } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'firebase\u002Fdata-connect'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { app } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> '.\u002Fclient'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> dataConnect\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> getDataConnect\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(app, {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  connector: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'your-connector'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  location: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'us-central1'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F For local development\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (process.env.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NODE_ENV\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> ===\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'development'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">  connectDataConnectEmulator\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(dataConnect, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'localhost'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">9399\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">export\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { dataConnect };\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[1660],{"text":1661,"type":71},"\u002F\u002F lib\u002Ffirebase\u002Fdataconnect.ts\nimport { getDataConnect, connectDataConnectEmulator } from 'firebase\u002Fdata-connect';\nimport { app } from '.\u002Fclient';\n\nconst dataConnect = getDataConnect(app, {\n  connector: 'your-connector',\n  location: 'us-central1',\n});\n\n\u002F\u002F For local development\nif (process.env.NODE_ENV === 'development') {\n  connectDataConnectEmulator(dataConnect, 'localhost', 9399);\n}\n\nexport { dataConnect };",{"type":65,"attrs":1663,"content":1665},{"id":1664},"p_9e5cy4f9",[1666,1670],{"text":1667,"type":71,"marks":1668},"Example GraphQL Schema",[1669],{"type":111},{"text":428,"type":71},{"type":1075,"attrs":1672,"content":1675},{"id":1673,"highlighted":1674},"code_3zy5n8r2","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">type\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> User\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> @table {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  id: String! @col\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  email: String! @col\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  displayName: String @col\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  posts: [Post] @relation\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">type\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> Post\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> @table {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  id: String! @col\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  title: String! @col\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  content: String! @col\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  authorId: String! @col\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  author: User @relation(fields: [\"authorId\"])\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[1676],{"text":1677,"type":71},"type User @table {\n  id: String! @col\n  email: String! @col\n  displayName: String @col\n  posts: [Post] @relation\n}\n\ntype Post @table {\n  id: String! @col\n  title: String! @col\n  content: String! @col\n  authorId: String! @col\n  author: User @relation(fields: [\"authorId\"])\n}",{"type":65,"attrs":1679,"content":1681},{"id":1680},"p_sac8986y",[1682],{"text":1683,"type":71},"Data Connect automatically generates typed SDKs for you to use:",{"type":1075,"attrs":1685,"content":1688},{"id":1686,"highlighted":1687},"code_1vfirikw","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F Auto-generated example\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { createUser, listPosts } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> '@\u002Flib\u002Fdataconnect-sdk'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F Create user\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> result\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> createUser\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  email: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'user@example.com'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  displayName: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'John Doe'\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F List posts with author\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> posts\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> listPosts\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">();\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[1689],{"text":1690,"type":71},"\u002F\u002F Auto-generated example\nimport { createUser, listPosts } from '@\u002Flib\u002Fdataconnect-sdk';\n\n\u002F\u002F Create user\nconst result = await createUser({\n  email: 'user@example.com',\n  displayName: 'John Doe'\n});\n\n\u002F\u002F List posts with author\nconst posts = await listPosts();",{"type":85,"attrs":1692,"content":1694},{"id":1693},"h_1cahdssf",[1695],{"text":1696,"type":71},"Advanced Topics for Professional Applications",{"type":85,"attrs":1698,"content":1700},{"id":1699},"h_nx387g8h",[1701],{"text":1702,"type":71},"Firebase Emulator Suite",{"type":65,"attrs":1704,"content":1706},{"id":1705},"p_lbypz5tx",[1707],{"text":1708,"type":71},"For local development, don't use your production project. The Emulator Suite simulates Firebase services (Auth, Firestore, Functions, Data Connect) on your machine. It's faster, free, and avoids the risk of polluting your production database.",{"type":65,"attrs":1710,"content":1712},{"id":1711},"p_2u7uamxh",[1713,1717],{"text":1714,"type":71,"marks":1715},"Installation",[1716],{"type":111},{"text":428,"type":71},{"type":1075,"attrs":1719,"content":1722},{"id":1720,"highlighted":1721},"code_xvbuod64","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">firebase init emulators\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">firebase \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">emulators\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:start\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[1723],{"text":1724,"type":71},"firebase init emulators\nfirebase emulators:start",{"type":65,"attrs":1726,"content":1728},{"id":1727},"p_pydh9sns",[1729,1733],{"text":1730,"type":71,"marks":1731},"Code Configuration",[1732],{"type":111},{"text":428,"type":71},{"type":1075,"attrs":1735,"content":1738},{"id":1736,"highlighted":1737},"code_i1b86l94","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F lib\u002Ffirebase\u002Fclient.ts\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { connectAuthEmulator } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> \"firebase\u002Fauth\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { connectFirestoreEmulator } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> \"firebase\u002Ffirestore\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (process.env.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">NODE_ENV\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> ===\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'development'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">  connectAuthEmulator\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(auth, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"http:\u002F\u002Flocalhost:9099\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">  connectFirestoreEmulator\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(db, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"localhost\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">8080\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[1739],{"text":1740,"type":71},"\u002F\u002F lib\u002Ffirebase\u002Fclient.ts\nimport { connectAuthEmulator } from \"firebase\u002Fauth\";\nimport { connectFirestoreEmulator } from \"firebase\u002Ffirestore\";\n\nif (process.env.NODE_ENV === 'development') {\n  connectAuthEmulator(auth, \"http:\u002F\u002Flocalhost:9099\");\n  connectFirestoreEmulator(db, \"localhost\", 8080);\n}",{"type":85,"attrs":1742,"content":1744},{"id":1743},"h_il6z6pmm",[1745],{"text":1746,"type":71},"Security with Firestore Rules",{"type":65,"attrs":1748,"content":1750},{"id":1749},"p_tcxf8zn0",[1751,1753,1757],{"text":1752,"type":71},"This is the most critical point of a robust application. Firestore rules are your security backend. They define on the server who can read, write, update, or delete each document. ",{"text":1754,"type":71,"marks":1755},"DO NOT TRUST CLIENT-SIDE LOGIC FOR SECURITY",[1756],{"type":111},{"text":1758,"type":71},".",{"type":65,"attrs":1760,"content":1762},{"id":1761},"p_gx69w39x",[1763],{"text":1764,"type":71},"A simple yet powerful example:",{"type":1075,"attrs":1766,"content":1769},{"id":1767,"highlighted":1768},"code_p7lbs9ab","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F firestore.rules\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">rules_version \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> '2'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">service cloud.firestore {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  match \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">databases\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">{database}\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">documents {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">    \u002F\u002F Helper function to verify authentication\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">    function\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> isAuthenticated\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">() {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">      return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> request.auth \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">!=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> null\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    \u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">    \u002F\u002F Function to verify document ownership\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">    function\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> isOwner\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#E36209;--shiki-dark:#FFAB70\">userId\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">      return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> isAuthenticated\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">() \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">&#x26;&#x26;\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> request.auth.uid \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">==\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> userId;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    \u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">    \u002F\u002F Allow any authenticated user to read post list\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    match \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">posts\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">{postId} {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      allow \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">read\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> isAuthenticated\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      \u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">      \u002F\u002F Allow post creation if userId is the authenticated user\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      allow \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">create\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> isAuthenticated\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">() \u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">                    &#x26;&#x26;\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> request.resource.data.userId \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">==\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> request.auth.uid;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      \u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">      \u002F\u002F Allow update\u002Fdelete only if author\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      allow update, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">delete\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> isOwner\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(resource.data.userId);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    \u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">    \u002F\u002F Private user data\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    match \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">users\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">{userId} {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">      \u002F\u002F User can only read their own data\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      allow \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">read\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> isOwner\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(userId);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      \u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">      \u002F\u002F User can only create\u002Fupdate their own data\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      allow create, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">update\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> isOwner\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(userId);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      \u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">      \u002F\u002F Never allow direct delete (use Cloud Function)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      allow \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">delete\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> false\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[1770],{"text":1771,"type":71},"\u002F\u002F firestore.rules\nrules_version = '2';\nservice cloud.firestore {\n  match \u002Fdatabases\u002F{database}\u002Fdocuments {\n    \u002F\u002F Helper function to verify authentication\n    function isAuthenticated() {\n      return request.auth != null;\n    }\n    \n    \u002F\u002F Function to verify document ownership\n    function isOwner(userId) {\n      return isAuthenticated() && request.auth.uid == userId;\n    }\n    \n    \u002F\u002F Allow any authenticated user to read post list\n    match \u002Fposts\u002F{postId} {\n      allow read: if isAuthenticated();\n      \n      \u002F\u002F Allow post creation if userId is the authenticated user\n      allow create: if isAuthenticated() \n                    && request.resource.data.userId == request.auth.uid;\n      \n      \u002F\u002F Allow update\u002Fdelete only if author\n      allow update, delete: if isOwner(resource.data.userId);\n    }\n    \n    \u002F\u002F Private user data\n    match \u002Fusers\u002F{userId} {\n      \u002F\u002F User can only read their own data\n      allow read: if isOwner(userId);\n      \n      \u002F\u002F User can only create\u002Fupdate their own data\n      allow create, update: if isOwner(userId);\n      \n      \u002F\u002F Never allow direct delete (use Cloud Function)\n      allow delete: if false;\n    }\n  }\n}",{"type":85,"attrs":1773,"content":1775},{"id":1774},"h_s11ou44i",[1776],{"text":1777,"type":71},"Cost Optimizations",{"type":65,"attrs":1779,"content":1781},{"id":1780},"p_9xfzlp4m",[1782,1786],{"text":1783,"type":71,"marks":1784},"1. Minimize Firestore Reads",[1785],{"type":111},{"text":428,"type":71},{"type":324,"attrs":1788,"content":1790},{"id":1789},"ul_u7lsgrcq",[1791,1801,1817,1827],{"type":329,"attrs":1792,"content":1794},{"id":1793},"li_9u2bcnef",[1795],{"type":65,"attrs":1796,"content":1798},{"id":1797},"p_8zlizart",[1799],{"text":1800,"type":71},"Use client-side caching when possible",{"type":329,"attrs":1802,"content":1804},{"id":1803},"li_p7by5gii",[1805],{"type":65,"attrs":1806,"content":1808},{"id":1807},"p_90bsyyg8",[1809,1811,1815],{"text":1810,"type":71},"Avoid queries with ",{"text":1812,"type":71,"marks":1813},"offset",[1814],{"type":226},{"text":1816,"type":71}," (each skipped document counts as a read)",{"type":329,"attrs":1818,"content":1820},{"id":1819},"li_rjmm0glt",[1821],{"type":65,"attrs":1822,"content":1824},{"id":1823},"p_owx21jrs",[1825],{"text":1826,"type":71},"Use cursors\u002Fpagination instead of loading everything at once",{"type":329,"attrs":1828,"content":1830},{"id":1829},"li_xrt8aahs",[1831],{"type":65,"attrs":1832,"content":1834},{"id":1833},"p_kcku6hhv",[1835],{"text":1836,"type":71},"Configure composite indexes for complex queries",{"type":65,"attrs":1838,"content":1840},{"id":1839},"p_8nh7d4i9",[1841,1845],{"text":1842,"type":71,"marks":1843},"2. Optimize Cloud Storage",[1844],{"type":111},{"text":428,"type":71},{"type":324,"attrs":1847,"content":1849},{"id":1848},"ul_mowtp0bi",[1850,1860,1870,1880],{"type":329,"attrs":1851,"content":1853},{"id":1852},"li_9zf96jks",[1854],{"type":65,"attrs":1855,"content":1857},{"id":1856},"p_avo73lpa",[1858],{"text":1859,"type":71},"Resize images before client-side upload",{"type":329,"attrs":1861,"content":1863},{"id":1862},"li_ckv28006",[1864],{"type":65,"attrs":1865,"content":1867},{"id":1866},"p_t2akjuyt",[1868],{"text":1869,"type":71},"Use Firebase Extensions (Resize Images) to automatically create thumbnails",{"type":329,"attrs":1871,"content":1873},{"id":1872},"li_4ur2t88x",[1874],{"type":65,"attrs":1875,"content":1877},{"id":1876},"p_wmgo3x25",[1878],{"text":1879,"type":71},"Configure CORS properly",{"type":329,"attrs":1881,"content":1883},{"id":1882},"li_kjwypapw",[1884],{"type":65,"attrs":1885,"content":1887},{"id":1886},"p_16qxxxz2",[1888],{"text":1889,"type":71},"Use cache headers for static files",{"type":65,"attrs":1891,"content":1893},{"id":1892},"p_a88f6dk6",[1894,1898],{"text":1895,"type":71,"marks":1896},"3. Active Monitoring",[1897],{"type":111},{"text":428,"type":71},{"type":324,"attrs":1900,"content":1902},{"id":1901},"ul_y52cbv8r",[1903,1913,1923,1933],{"type":329,"attrs":1904,"content":1906},{"id":1905},"li_t0ekxc88",[1907],{"type":65,"attrs":1908,"content":1910},{"id":1909},"p_z6bdn6um",[1911],{"text":1912,"type":71},"Set up budget alerts in Google Cloud Console",{"type":329,"attrs":1914,"content":1916},{"id":1915},"li_l2a7yue0",[1917],{"type":65,"attrs":1918,"content":1920},{"id":1919},"p_oecpx7ze",[1921],{"text":1922,"type":71},"Use Firebase Usage Dashboard daily during development",{"type":329,"attrs":1924,"content":1926},{"id":1925},"li_l8o2ujwr",[1927],{"type":65,"attrs":1928,"content":1930},{"id":1929},"p_uhs0msly",[1931],{"text":1932,"type":71},"Implement rate limiting in public Cloud Functions",{"type":329,"attrs":1934,"content":1936},{"id":1935},"li_fvxbsmo9",[1937],{"type":65,"attrs":1938,"content":1940},{"id":1939},"p_vkk8ajkb",[1941],{"text":1942,"type":71},"Use Firebase App Check to prevent abuse",{"type":85,"attrs":1944,"content":1946},{"id":1945},"h_pf7elkyj",[1947],{"text":1948,"type":71},"Monitoring and Observability",{"type":85,"attrs":1950,"content":1952},{"id":1951},"h_je90ko9f",[1953],{"text":1954,"type":71},"Firebase Console Dashboard",{"type":65,"attrs":1956,"content":1958},{"id":1957},"p_kmpcz2z3",[1959],{"text":1960,"type":71},"Firebase Console provides dedicated dashboards for:",{"type":324,"attrs":1962,"content":1964},{"id":1963},"ul_wzw9zh7g",[1965,1979,1992,2005,2018],{"type":329,"attrs":1966,"content":1968},{"id":1967},"li_xigih6i1",[1969],{"type":65,"attrs":1970,"content":1972},{"id":1971},"p_n8re56xz",[1973,1977],{"text":1974,"type":71,"marks":1975},"Usage & Billing",[1976],{"type":111},{"text":1978,"type":71},": Real-time usage and cost monitoring",{"type":329,"attrs":1980,"content":1982},{"id":1981},"li_uyj15zxc",[1983],{"type":65,"attrs":1984,"content":1986},{"id":1985},"p_glhd8bd9",[1987,1990],{"text":496,"type":71,"marks":1988},[1989],{"type":111},{"text":1991,"type":71},": Sign-in metrics, most used providers",{"type":329,"attrs":1993,"content":1995},{"id":1994},"li_pbjof24k",[1996],{"type":65,"attrs":1997,"content":1999},{"id":1998},"p_3cnp2j9u",[2000,2003],{"text":108,"type":71,"marks":2001},[2002],{"type":111},{"text":2004,"type":71},": Reads, writes, storage used",{"type":329,"attrs":2006,"content":2008},{"id":2007},"li_ihi0t0xr",[2009],{"type":65,"attrs":2010,"content":2012},{"id":2011},"p_ithb4rhh",[2013,2016],{"text":388,"type":71,"marks":2014},[2015],{"type":111},{"text":2017,"type":71},": Core Web Vitals, response times",{"type":329,"attrs":2019,"content":2021},{"id":2020},"li_uq3u44vq",[2022],{"type":65,"attrs":2023,"content":2025},{"id":2024},"p_fq0rvd0z",[2026,2029],{"text":378,"type":71,"marks":2027},[2028],{"type":111},{"text":2030,"type":71},": Real-time crashes with stack traces",{"type":85,"attrs":2032,"content":2034},{"id":2033},"h_tv7fvvie",[2035],{"text":2036,"type":71},"Google Cloud Integration",{"type":65,"attrs":2038,"content":2040},{"id":2039},"p_mwfbwp9r",[2041],{"text":2042,"type":71},"For production applications, integrate with:",{"type":324,"attrs":2044,"content":2046},{"id":2045},"ul_2sqkytgp",[2047,2061,2075,2089],{"type":329,"attrs":2048,"content":2050},{"id":2049},"li_tlklezzn",[2051],{"type":65,"attrs":2052,"content":2054},{"id":2053},"p_h3dmto2e",[2055,2059],{"text":2056,"type":71,"marks":2057},"Cloud Logging",[2058],{"type":111},{"text":2060,"type":71},": Centralized logs from all Cloud Functions",{"type":329,"attrs":2062,"content":2064},{"id":2063},"li_7lff7abw",[2065],{"type":65,"attrs":2066,"content":2068},{"id":2067},"p_ogv1fkyz",[2069,2073],{"text":2070,"type":71,"marks":2071},"Cloud Trace",[2072],{"type":111},{"text":2074,"type":71},": Distributed tracing to understand latency",{"type":329,"attrs":2076,"content":2078},{"id":2077},"li_x16acq1s",[2079],{"type":65,"attrs":2080,"content":2082},{"id":2081},"p_80utkh1s",[2083,2087],{"text":2084,"type":71,"marks":2085},"Cloud Monitoring",[2086],{"type":111},{"text":2088,"type":71},": Custom alerts and advanced dashboards",{"type":329,"attrs":2090,"content":2092},{"id":2091},"li_3qcusgwl",[2093],{"type":65,"attrs":2094,"content":2096},{"id":2095},"p_pak6u6pq",[2097,2101],{"text":2098,"type":71,"marks":2099},"Error Reporting",[2100],{"type":111},{"text":2102,"type":71},": Intelligent error aggregation",{"type":85,"attrs":2104,"content":2106},{"id":2105},"h_0ayglrxq",[2107],{"text":2108,"type":71},"Conclusion",{"type":65,"attrs":2110,"content":2112},{"id":2111},"p_fb6py5zz",[2113],{"text":2114,"type":71},"Integrating Firebase with Next.js isn't just a convenience; it's a paradigm shift. It allows teams and individual developers to build complex, scalable full-stack applications, focusing on user experience and business logic rather than getting lost in infrastructure complexity.",{"type":65,"attrs":2116,"content":2118},{"id":2117},"p_07v4ip8w",[2119],{"text":2120,"type":71},"The Spark plan offers an extremely generous free quota - sufficient to validate ideas, create MVPs, and even support small production applications. When you need to scale, the Blaze plan offers competitive pricing with a pay-as-you-go model.",{"type":65,"attrs":2122,"content":2124},{"id":2123},"p_h7bz282k",[2125],{"text":2126,"type":71},"New services like App Hosting, Data Connect, and Firebase Studio (2025) make Firebase even more powerful, offering modern solutions for developers working with frameworks like Next.js and Angular. Native AI integration through Genkit and Vertex AI in Firebase positions the platform at the forefront of intelligent application development.",{"type":65,"attrs":2128,"content":2130},{"id":2129},"p_vgd39rac",[2131],{"text":2132,"type":71},"By following an organized structure, separating client and server configurations, and treating security rules as a priority, you create a solid and professional foundation. Firebase handles the heavy lifting so you can focus on building what truly matters.",{"type":2134},"horizontalRule",{"type":85,"attrs":2136,"content":2138},{"id":2137},"h_2xk9qdgx",[2139],{"text":2140,"type":71},"Sources",{"type":65,"attrs":2142,"content":2144},{"id":2143},"p_d3ys4qpp",[2145],{"text":2146,"type":71},"This article was supplemented with information from the following official sources:",{"type":2148,"attrs":2149,"content":2151},"orderedList",{"id":2150},"ol_0lb1s920",[2152,2171,2188],{"type":329,"attrs":2153,"content":2155},{"id":2154},"li_byytp2nt",[2156],{"type":65,"attrs":2157,"content":2159},{"id":2158},"p_2yh4a16g",[2160,2164,2166],{"text":2161,"type":71,"marks":2162},"Firebase Pricing",[2163],{"type":111},{"text":2165,"type":71}," - ",{"text":2167,"type":71,"marks":2168},"https:\u002F\u002Ffirebase.google.com\u002Fpricing",[2169],{"type":2170},"link",{"type":329,"attrs":2172,"content":2174},{"id":2173},"li_2n3fstj4",[2175],{"type":65,"attrs":2176,"content":2178},{"id":2177},"p_ze1yj36u",[2179,2183,2184],{"text":2180,"type":71,"marks":2181},"Firebase at Google I\u002FO 2025",[2182],{"type":111},{"text":2165,"type":71},{"text":2185,"type":71,"marks":2186},"https:\u002F\u002Ffirebase.blog\u002Fposts\u002F2025\u002F05\u002Fwhats-new-at-google-io",[2187],{"type":2170},{"type":329,"attrs":2189,"content":2191},{"id":2190},"li_7kz7lqcn",[2192],{"type":65,"attrs":2193,"content":2195},{"id":2194},"p_izhl8u6m",[2196,2200,2201],{"text":2197,"type":71,"marks":2198},"Firebase Documentation - Pricing Plans",[2199],{"type":111},{"text":2165,"type":71},{"text":2202,"type":71,"marks":2203},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fprojects\u002Fbilling\u002Ffirebase-pricing-plans",[2204],{"type":2170},{"type":65,"attrs":2206},{"id":2207},"p_42mjseoz","Accelerate Next.js development with Firebase BaaS. Learn robust integration, Firestore, Auth, Storage, Cloud Functions, and AI features using TypeScript.","2026-08-24T14:53:53.315534+00:00",[2211,2230,2243,2257],{"id":2212,"slug":2213,"title":2214,"excerpt":2215,"image":2216,"featured":44,"groupId":2217,"publishedAt":2218,"readingTime":2219,"views":2220,"author":2221,"category":2222,"tags":2223},"841890b2-1a8c-43d4-b434-b94714705605","debugging-css-the-forgotten-margin-and-frontend-lessons","Debugging CSS: The Forgotten Margin and Frontend Lessons","A forgotten CSS property turned a minor layout glitch into a two-week ordeal. Learn how to avoid emotional debugging and fix complex UI issues faster.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1767745741814-featured-i6p1gc.jpeg","bcaf503a-15c1-4d28-8795-6ae3c2a3e06f","2026-08-02T16:09:35.153874+00:00",8,0,{"name":49,"avatar":9},{"slug":6,"name":7,"color":8},[2224,2227],{"slug":2225,"name":2226},"css","CSS",{"slug":2228,"name":2229},"performance","Performance",{"id":2231,"slug":2232,"title":2233,"excerpt":2234,"image":2235,"featured":44,"groupId":2236,"publishedAt":2237,"readingTime":23,"views":2220,"author":2238,"category":2239,"tags":2240},"d5167910-cc5b-4fae-a2e8-d09adcf354b2","stop-using-usememo-wrong-a-practical-guide-to-react-performance","Stop Using useMemo Wrong: A Practical Guide to React Performance","Master React useMemo with this guide. Learn when to memoize, how to fix dependency array bugs, and why over-optimization can hurt your performance.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1769657096789-featured-r2q2sb.jpeg","a1c571c1-aa37-404d-ac67-f265c8a9985b","2026-07-08T23:34:34.563653+00:00",{"name":49,"avatar":9},{"slug":6,"name":7,"color":8},[2241,2242],{"slug":56,"name":57},{"slug":53,"name":54},{"id":2244,"slug":2245,"title":2246,"excerpt":2247,"image":2248,"featured":44,"groupId":2249,"publishedAt":2250,"readingTime":2251,"views":2220,"author":2252,"category":2253,"tags":2254},"f1b5af43-20da-4150-a7c7-ef17675d1fee","css-animations-how-to-build-performant-professional-interfaces-without-messy-code","CSS Animations: How to Build Performant, Professional Interfaces Without Messy Code","Bring your web interfaces to life. Learn when to use CSS transitions versus keyframes and how to optimize your animations for peak performance.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1770952624247-featured-in9pir.jpeg","de5a7726-1227-4080-b572-9d91a37b207b","2026-07-04T03:00:53.174696+00:00",17,{"name":49,"avatar":9},{"slug":6,"name":7,"color":8},[2255,2256],{"slug":2225,"name":2226},{"slug":2228,"name":2229},{"id":2258,"slug":2259,"title":2260,"excerpt":2261,"image":2262,"featured":44,"groupId":2263,"publishedAt":2264,"readingTime":2265,"views":2220,"author":2266,"category":2267,"tags":2268},"86e804a8-71f4-4985-a013-d6c033e28967","angular-micro-frontends-how-to-scale-large-applications-and-eliminate-monolithic-build-times-with-module-federation","Angular Micro-frontends: How to Scale Large Applications and Eliminate Monolithic Build Times with Module Federation","Discover how to break down large Angular monoliths using Module Federation to enable independent deployments and seamless team scaling.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1774499855857-featured-x9ugz1.jpg","a029aa9b-573b-4e5b-921b-eaecea6e989f","2026-06-21T06:41:59.230237+00:00",10,{"name":49,"avatar":9},{"slug":6,"name":7,"color":8},[2269,2272,2273],{"slug":2270,"name":2271},"angular","Angular",{"slug":56,"name":57},{"slug":2274,"name":2275},"typescript","TypeScript",{"es":2277,"pt":2278,"en":40},"nextjs-firebase-backend-escalable-con-typescript","firebase-e-next-js-dupla-dinamica-acelerar-seus-projetos-full-stack-typescript"]