[{"data":1,"prerenderedAt":19104},["Reactive",2],{"content-query-GIFUy50xpB":3},[4,886,1795,2989,3829,4896,6479,7346,8574,9742,12162,12914,13912,14232,15187,16338,17228,17924],{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":9,"description":10,"author":11,"date":12,"readingTime":13,"level":14,"image":15,"tags":16,"slugs":21,"relatedArticles":24,"body":28,"_type":881,"_id":882,"_source":883,"_file":884,"_extension":885},"/knowledge/business-blog-is-it-worth-it","knowledge",false,"","Business Blog - Is It Worth It?","How a business blog helps SEO and customer acquisition. Practical tips on content strategy and realistic expectations.","Standa Horvath","2026-03-20",9,"beginner","/featured/business-blog-is-it-worth-it.jpg",[17,18,19,20],"blog","content-marketing","seo","business",{"en":22,"cs":23},"business-blog-is-it-worth-it","blog-na-firemnim-webu-vyplati-se",[25,26,27],"what-should-business-website-contain","how-much-does-website-cost-in-2026","how-to-choose-web-developer",{"type":29,"children":30,"toc":861},"root",[31,38,45,51,56,60,66,71,76,89,92,98,103,108,124,127,133,147,152,218,221,227,232,244,249,270,273,279,284,296,301,306,309,315,320,400,405,408,414,433,438,443,488,505,508,514,519,611,654,657,663,668,734,769,772,778,783,788,793,796,802],{"type":32,"tag":33,"props":34,"children":35},"element","h1",{"id":22},[36],{"type":37,"value":9},"text",{"type":32,"tag":39,"props":40,"children":42},"h2",{"id":41},"introduction",[43],{"type":37,"value":44},"Introduction",{"type":32,"tag":46,"props":47,"children":48},"p",{},[49],{"type":37,"value":50},"A lot of business owners ask me whether it's worth investing time into a company blog. The answer isn't straightforward because it depends on what you expect from a blog and how much you're willing to invest. But if you approach it right, a blog can be one of the most effective marketing tools at your disposal. Even for a small business with a limited budget.",{"type":32,"tag":46,"props":52,"children":53},{},[54],{"type":37,"value":55},"We'll look at what a business blog realistically brings, how to get it rolling, and most importantly - how to avoid the most common mistakes that kill most business blogs after three posts.",{"type":32,"tag":57,"props":58,"children":59},"hr",{},[],{"type":32,"tag":39,"props":61,"children":63},{"id":62},"how-a-business-blog-drives-search-traffic",[64],{"type":37,"value":65},"🔍 How a Business Blog Drives Search Traffic",{"type":32,"tag":46,"props":67,"children":68},{},[69],{"type":37,"value":70},"Every page on your website is an opportunity to show up in search results. When your site has five pages (home, services, about, references, contact), you have five chances of being found. Add a blog with twenty articles and suddenly you have twenty-five. And each article can target different keywords.",{"type":32,"tag":46,"props":72,"children":73},{},[74],{"type":37,"value":75},"Imagine you do accounting for small businesses. Your services page targets \"small business accounting\" or \"accounting services London.\" But what about people searching \"how to file a tax return\" or \"difference between cash and accrual accounting\"? They won't land on your services page. But if you have an article answering those questions, Google can serve it to them. And you've got a visitor who's dealing with exactly the kind of problem you solve.",{"type":32,"tag":46,"props":77,"children":78},{},[79,81,87],{"type":37,"value":80},"This is called ",{"type":32,"tag":82,"props":83,"children":84},"strong",{},[85],{"type":37,"value":86},"long-tail keywords",{"type":37,"value":88}," - longer, more specific phrases people type into search engines. They have lower search volume than generic phrases, but competition is much lower. And crucially - people searching like this are often closer to making a decision.",{"type":32,"tag":57,"props":90,"children":91},{},[],{"type":32,"tag":39,"props":93,"children":95},{"id":94},"blog-as-a-trust-building-tool",[96],{"type":37,"value":97},"🤝 Blog as a Trust-Building Tool",{"type":32,"tag":46,"props":99,"children":100},{},[101],{"type":37,"value":102},"When a potential customer lands on your website, they naturally wonder: \"Do these people actually know what they're doing?\" Your services page says \"we're experts.\" Your blog proves it. When you write a clear article about a problem your customer faces, you show them two things - you understand the subject and you're willing to share your knowledge.",{"type":32,"tag":46,"props":104,"children":105},{},[106],{"type":37,"value":107},"Most people research before buying a service or product. They read reviews, compare options, gather information. If they stumble upon your article during this research and it helps them, they'll remember you. And when they need the service you offer, there's a good chance they'll reach out to you.",{"type":32,"tag":46,"props":109,"children":110},{},[111,113,122],{"type":37,"value":112},"A blog also helps with what Google calls ",{"type":32,"tag":82,"props":114,"children":115},{},[116],{"type":32,"tag":117,"props":118,"children":119},"code-inline",{},[120],{"type":37,"value":121},"E-E-A-T",{"type":37,"value":123}," (Experience, Expertise, Authoritativeness, Trustworthiness). Google wants to show people content from individuals and companies that know what they're talking about. Regular, quality content on your field's topics is one of the signals telling Google \"we really know our stuff.\"",{"type":32,"tag":57,"props":125,"children":126},{},[],{"type":32,"tag":39,"props":128,"children":130},{"id":129},"what-to-write-about",[131],{"type":37,"value":132},"📝 What to Write About",{"type":32,"tag":46,"props":134,"children":135},{},[136,138,145],{"type":37,"value":137},"The best business articles answer questions your customers actually ask you. Literally. When a client asks \"",{"type":32,"tag":139,"props":140,"children":142},"a",{"href":141},"/knowledge/how-much-does-website-cost-in-2026",[143],{"type":37,"value":144},"how much does a website redesign cost",{"type":37,"value":146},"?\" or \"how long does it take to create a logo?\" - you've got an article topic. These questions aren't asked by just that one client - hundreds of others search for them too.",{"type":32,"tag":46,"props":148,"children":149},{},[150],{"type":37,"value":151},"Three main types of content work well:",{"type":32,"tag":153,"props":154,"children":155},"cards",{},[156,180,199],{"type":32,"tag":157,"props":158,"children":159},"card",{},[160,168,175],{"type":32,"tag":161,"props":162,"children":167},"img",{"src":163,"alt":164,"width":165,"style":166},"/article/business-blog-is-it-worth-it/faq-answers.svg","FAQ answers",150,"max-width:100%",[],{"type":32,"tag":169,"props":170,"children":172},"h3",{"id":171},"answers-to-common-questions",[173],{"type":37,"value":174},"❓ Answers to Common Questions",{"type":32,"tag":46,"props":176,"children":177},{},[178],{"type":37,"value":179},"\"How much does X cost?\", \"How long does Y take?\", \"What's the difference between A and B?\". These attract people at the beginning of their decision process. A hair salon can write \"Difference between balayage and ombré,\" a plumber \"Underfloor heating vs radiators.\"",{"type":32,"tag":157,"props":181,"children":182},{},[183,188,194],{"type":32,"tag":161,"props":184,"children":187},{"src":185,"alt":186,"width":165,"style":166},"/article/business-blog-is-it-worth-it/howto-guides.svg","How-to guides",[],{"type":32,"tag":169,"props":189,"children":191},{"id":190},"how-to-guides",[192],{"type":37,"value":193},"📋 How-to Guides",{"type":32,"tag":46,"props":195,"children":196},{},[197],{"type":37,"value":198},"\"How to do X step by step.\" Huge potential because people actively seek solutions. Someone who reads a detailed tax return guide often thinks \"better leave this to a professional.\"",{"type":32,"tag":157,"props":200,"children":201},{},[202,207,213],{"type":32,"tag":161,"props":203,"children":206},{"src":204,"alt":205,"width":165,"style":166},"/article/business-blog-is-it-worth-it/case-studies.svg","Case studies",[],{"type":32,"tag":169,"props":208,"children":210},{"id":209},"case-studies",[211],{"type":37,"value":212},"🏆 Case Studies",{"type":32,"tag":46,"props":214,"children":215},{},[216],{"type":37,"value":217},"\"How we solved problem Y for client X.\" Gold - you combine a demonstration of expertise with real results. Just describe what the client came with, what you did, and how it turned out.",{"type":32,"tag":57,"props":219,"children":220},{},[],{"type":32,"tag":39,"props":222,"children":224},{"id":223},"how-often-to-publish",[225],{"type":37,"value":226},"📅 How Often to Publish",{"type":32,"tag":46,"props":228,"children":229},{},[230],{"type":37,"value":231},"This is where many companies get stuck. They read somewhere that \"ideally you should publish 2-3 times a week\" and either go all in and burn out within a month, or give up immediately because they don't have the capacity.",{"type":32,"tag":46,"props":233,"children":234},{},[235,237,242],{"type":37,"value":236},"A realistic strategy for a small business or freelancer? ",{"type":32,"tag":82,"props":238,"children":239},{},[240],{"type":37,"value":241},"One quality article per month.",{"type":37,"value":243}," That's twelve articles a year. After two years, you have twenty-four articles working for you 24/7.",{"type":32,"tag":46,"props":245,"children":246},{},[247],{"type":37,"value":248},"What matters more than frequency is consistency. Google likes websites that update regularly. But \"regularly\" doesn't mean \"every day.\" It means consistently - if you commit to one article a month, then one article a month. Not three in January, none in February and March, then two in April.",{"type":32,"tag":157,"props":250,"children":251},{},[252,258],{"type":32,"tag":169,"props":253,"children":255},{"id":254},"practical-tip",[256],{"type":37,"value":257},"💡 Practical Tip",{"type":32,"tag":46,"props":259,"children":260},{},[261,263,268],{"type":37,"value":262},"Create a ",{"type":32,"tag":82,"props":264,"children":265},{},[266],{"type":37,"value":267},"content calendar",{"type":37,"value":269}," three months ahead. Nothing fancy - just a table with publication date, topic, and target keyword. When you know what you're writing about next month, it's much easier to find the time.",{"type":32,"tag":57,"props":271,"children":272},{},[],{"type":32,"tag":39,"props":274,"children":276},{"id":275},"️-quality-vs-quantity",[277],{"type":37,"value":278},"⚖️ Quality vs Quantity",{"type":32,"tag":46,"props":280,"children":281},{},[282],{"type":37,"value":283},"The days when 300 words stuffed with keywords would get Google's approval are long gone. Google evaluates content quality - how well it answers the user's question, how thorough it is, how original it is.",{"type":32,"tag":46,"props":285,"children":286},{},[287,289,294],{"type":37,"value":288},"What does \"quality article\" mean in practice? It's an article that ",{"type":32,"tag":82,"props":290,"children":291},{},[292],{"type":37,"value":293},"genuinely helps the reader solve a problem or make a decision",{"type":37,"value":295},". It's 800-2000 words (depending on the topic), well-structured with subheadings, includes practical examples and ideally your own experience. It's not a rewritten Wikipedia article or generic text you had written for pocket change.",{"type":32,"tag":46,"props":297,"children":298},{},[299],{"type":37,"value":300},"One quality article that reaches Google's first page will bring you more visitors than ten average articles on the second page. Because almost nobody looks at Google's second page - over 90% of clicks go to first-page results.",{"type":32,"tag":46,"props":302,"children":303},{},[304],{"type":37,"value":305},"And good articles have a long shelf life. An article like \"How to choose the right dog crate size\" will still be relevant five years from now. This is the fundamental difference from social media, where a post disappears from reach within hours. A blog is an investment, not an expense.",{"type":32,"tag":57,"props":307,"children":308},{},[],{"type":32,"tag":39,"props":310,"children":312},{"id":311},"how-to-measure-if-your-blog-works",[313],{"type":37,"value":314},"📊 How to Measure if Your Blog Works",{"type":32,"tag":46,"props":316,"children":317},{},[318],{"type":37,"value":319},"You've launched a blog, you're writing regularly - but how do you know it's working? You need patience and the right metrics.",{"type":32,"tag":153,"props":321,"children":322},{},[323,362,381],{"type":32,"tag":157,"props":324,"children":325},{},[326,331,337],{"type":32,"tag":161,"props":327,"children":330},{"src":328,"alt":329,"width":165,"style":166},"/article/business-blog-is-it-worth-it/organic-traffic.svg","Organic traffic",[],{"type":32,"tag":169,"props":332,"children":334},{"id":333},"organic-traffic",[335],{"type":37,"value":336},"📈 Organic Traffic",{"type":32,"tag":46,"props":338,"children":339},{},[340,342,351,353,360],{"type":37,"value":341},"How many people find your articles through search. Track this in ",{"type":32,"tag":139,"props":343,"children":348},{"href":344,":target":345,"rel":346,":rel":347},"https://analytics.google.com/","_blank",[347],"nofollow",[349],{"type":37,"value":350},"Google Analytics",{"type":37,"value":352}," (Acquisition > Organic Search) or ",{"type":32,"tag":139,"props":354,"children":357},{"href":355,":target":345,"rel":356,":rel":347},"https://search.google.com/search-console",[347],[358],{"type":37,"value":359},"Google Search Console",{"type":37,"value":361},". Realistically: first results in 3-6 months.",{"type":32,"tag":157,"props":363,"children":364},{},[365,370,376],{"type":32,"tag":161,"props":366,"children":369},{"src":367,"alt":368,"width":165,"style":166},"/article/business-blog-is-it-worth-it/search-rankings.svg","Search rankings",[],{"type":32,"tag":169,"props":371,"children":373},{"id":372},"search-rankings",[374],{"type":37,"value":375},"🎯 Search Rankings",{"type":32,"tag":46,"props":377,"children":378},{},[379],{"type":37,"value":380},"What positions your articles show up for target keywords. Google Search Console shows this for free. Moving from position 50 to 15 is progress, even if it's not driving traffic yet.",{"type":32,"tag":157,"props":382,"children":383},{},[384,389,395],{"type":32,"tag":161,"props":385,"children":388},{"src":386,"alt":387,"width":165,"style":166},"/article/business-blog-is-it-worth-it/conversions.svg","Blog conversions",[],{"type":32,"tag":169,"props":390,"children":392},{"id":391},"blog-conversions",[393],{"type":37,"value":394},"💰 Blog Conversions",{"type":32,"tag":46,"props":396,"children":397},{},[398],{"type":37,"value":399},"How many readers eventually fill out a form, call, or order. The hardest metric to measure, but the most important. Add a call to action at the end of each article and track clicks.",{"type":32,"tag":46,"props":401,"children":402},{},[403],{"type":37,"value":404},"A blog won't generate dozens of inquiries from month one. But after a year of regular writing, you should see steady organic traffic growth and occasional inquiries directly from articles. The effect compounds.",{"type":32,"tag":57,"props":406,"children":407},{},[],{"type":32,"tag":39,"props":409,"children":411},{"id":410},"geo-optimizing-for-ai-search-engines",[412],{"type":37,"value":413},"🤖 GEO - Optimizing for AI Search Engines",{"type":32,"tag":46,"props":415,"children":416},{},[417,419,424,426,431],{"type":37,"value":418},"Alongside traditional ",{"type":32,"tag":117,"props":420,"children":421},{},[422],{"type":37,"value":423},"SEO",{"type":37,"value":425},", a new concept has emerged in recent years - ",{"type":32,"tag":82,"props":427,"children":428},{},[429],{"type":37,"value":430},"GEO (Generative Engine Optimization)",{"type":37,"value":432},". It's about optimizing content so that AI search engines like ChatGPT, Perplexity, Google AI Overviews, or Bing Copilot pick it up and cite it.",{"type":32,"tag":46,"props":434,"children":435},{},[436],{"type":37,"value":437},"Why does this matter for a business blog? More and more people search for answers through AI tools instead of traditional Google. When AI decides which source to cite, it favors content that is clearly structured, contains specific facts, and directly answers the question. That's exactly the kind of content your blog should have.",{"type":32,"tag":46,"props":439,"children":440},{},[441],{"type":37,"value":442},"What helps AI search engines pick up your content:",{"type":32,"tag":444,"props":445,"children":446},"ul",{},[447,458,468,478],{"type":32,"tag":448,"props":449,"children":450},"li",{},[451,456],{"type":32,"tag":82,"props":452,"children":453},{},[454],{"type":37,"value":455},"Direct answers to questions",{"type":37,"value":457}," - the first paragraph under a heading should immediately answer the question the heading poses. AI prefers content where it doesn't have to dig for the answer.",{"type":32,"tag":448,"props":459,"children":460},{},[461,466],{"type":32,"tag":82,"props":462,"children":463},{},[464],{"type":37,"value":465},"Structured data and headings",{"type":37,"value":467}," - a clear H2/H3 heading hierarchy helps AI understand article structure and extract relevant sections.",{"type":32,"tag":448,"props":469,"children":470},{},[471,476],{"type":32,"tag":82,"props":472,"children":473},{},[474],{"type":37,"value":475},"Specific numbers and facts",{"type":37,"value":477}," - \"the average website costs $3,000 - $15,000\" is far more useful to AI than \"website prices vary.\"",{"type":32,"tag":448,"props":479,"children":480},{},[481,486],{"type":32,"tag":82,"props":482,"children":483},{},[484],{"type":37,"value":485},"Authorship and expertise",{"type":37,"value":487}," - AI search engines favor content from identifiable authors with demonstrable expertise in their field.",{"type":32,"tag":46,"props":489,"children":490},{},[491,493,497,499,503],{"type":37,"value":492},"GEO and ",{"type":32,"tag":117,"props":494,"children":495},{},[496],{"type":37,"value":423},{"type":37,"value":498}," don't conflict. Quality content optimized for ",{"type":32,"tag":117,"props":500,"children":501},{},[502],{"type":37,"value":423},{"type":37,"value":504}," will largely work for AI search engines too. But if you want to stay ahead, think about how AI will \"read\" your content when writing.",{"type":32,"tag":57,"props":506,"children":507},{},[],{"type":32,"tag":39,"props":509,"children":511},{"id":510},"most-common-business-blog-mistakes",[512],{"type":37,"value":513},"🚫 Most Common Business Blog Mistakes",{"type":32,"tag":46,"props":515,"children":516},{},[517],{"type":37,"value":518},"Over years of working with websites, I've seen plenty of business blogs. And unfortunately, most of them make the same mistakes.",{"type":32,"tag":153,"props":520,"children":521},{},[522,541,560,585],{"type":32,"tag":157,"props":523,"children":524},{},[525,530,536],{"type":32,"tag":161,"props":526,"children":529},{"src":527,"alt":528,"width":165,"style":166},"/article/business-blog-is-it-worth-it/writing-about-self.svg","Writing about yourself",[],{"type":32,"tag":169,"props":531,"children":533},{"id":532},"writing-about-themselves",[534],{"type":37,"value":535},"🪞 Writing About Themselves",{"type":32,"tag":46,"props":537,"children":538},{},[539],{"type":37,"value":540},"\"We attended a trade show,\" \"We hired a new colleague,\" \"Merry Christmas.\" A blog should answer customer questions, not serve as a company bulletin board.",{"type":32,"tag":157,"props":542,"children":543},{},[544,549,555],{"type":32,"tag":161,"props":545,"children":548},{"src":546,"alt":547,"width":165,"style":166},"/article/business-blog-is-it-worth-it/no-strategy.svg","No strategy",[],{"type":32,"tag":169,"props":550,"children":552},{"id":551},"no-strategy",[553],{"type":37,"value":554},"🎲 No Strategy",{"type":32,"tag":46,"props":556,"children":557},{},[558],{"type":37,"value":559},"Writing an article whenever a topic comes to mind. No keywords, no content calendar. Result - articles nobody searches for.",{"type":32,"tag":157,"props":561,"children":562},{},[563,568,574],{"type":32,"tag":161,"props":564,"children":567},{"src":565,"alt":566,"width":165,"style":166},"/article/business-blog-is-it-worth-it/giving-up.svg","Giving up too soon",[],{"type":32,"tag":169,"props":569,"children":571},{"id":570},"giving-up-too-soon",[572],{"type":37,"value":573},"⏳ Giving Up Too Soon",{"type":32,"tag":46,"props":575,"children":576},{},[577,579,583],{"type":37,"value":578},"Five articles, no miracles after two months, \"blogging doesn't work.\" ",{"type":32,"tag":117,"props":580,"children":581},{},[582],{"type":37,"value":423},{"type":37,"value":584}," needs at least six months. It's like exercise - one month at the gym isn't enough.",{"type":32,"tag":157,"props":586,"children":587},{},[588,593,599],{"type":32,"tag":161,"props":589,"children":592},{"src":590,"alt":591,"width":165,"style":166},"/article/business-blog-is-it-worth-it/copying-content.svg","Copying content",[],{"type":32,"tag":169,"props":594,"children":596},{"id":595},"copying-content",[597],{"type":37,"value":598},"📋 Copying Content",{"type":32,"tag":46,"props":600,"children":601},{},[602,604,609],{"type":37,"value":603},"From competitors or from ",{"type":32,"tag":117,"props":605,"children":606},{},[607],{"type":37,"value":608},"AI",{"type":37,"value":610}," without edits. Google penalizes duplicate content. Your content must be original and include your own experience.",{"type":32,"tag":157,"props":612,"children":613},{},[614,620],{"type":32,"tag":169,"props":615,"children":617},{"id":616},"️-watch-the-technical-basics",[618],{"type":37,"value":619},"⚠️ Watch the Technical Basics",{"type":32,"tag":46,"props":621,"children":622},{},[623,625,631,633,637,639,644,646,652],{"type":37,"value":624},"An article without meta description, without structured headings, without ",{"type":32,"tag":139,"props":626,"children":628},{"href":627},"/knowledge/guide-to-the-world-of-web-image-formats",[629],{"type":37,"value":630},"optimized images",{"type":37,"value":632},". ",{"type":32,"tag":117,"props":634,"children":635},{},[636],{"type":37,"value":423},{"type":37,"value":638}," isn't just about text - the technical side matters too. Fortunately, most modern ",{"type":32,"tag":117,"props":640,"children":641},{},[642],{"type":37,"value":643},"CMS",{"type":37,"value":645}," systems will help with this. If you want to know ",{"type":32,"tag":139,"props":647,"children":649},{"href":648},"/knowledge/what-should-business-website-contain",[650],{"type":37,"value":651},"what a business website should contain",{"type":37,"value":653}," from a technical standpoint, I have a separate article on that.",{"type":32,"tag":57,"props":655,"children":656},{},[],{"type":32,"tag":39,"props":658,"children":660},{"id":659},"️-who-should-write",[661],{"type":37,"value":662},"✍️ Who Should Write",{"type":32,"tag":46,"props":664,"children":665},{},[666],{"type":37,"value":667},"You have three options: write yourself, hire a copywriter, or combine both.",{"type":32,"tag":153,"props":669,"children":670},{},[671,690,709],{"type":32,"tag":157,"props":672,"children":673},{},[674,679,685],{"type":32,"tag":161,"props":675,"children":678},{"src":676,"alt":677,"width":165,"style":166},"/article/business-blog-is-it-worth-it/write-yourself.svg","Write yourself",[],{"type":32,"tag":169,"props":680,"children":682},{"id":681},"write-yourself",[683],{"type":37,"value":684},"🧑‍💼 Write Yourself",{"type":32,"tag":46,"props":686,"children":687},{},[688],{"type":37,"value":689},"Best for authenticity. Nobody knows your field better than you. Downside - it takes time, your first article might take an entire day.",{"type":32,"tag":157,"props":691,"children":692},{},[693,698,704],{"type":32,"tag":161,"props":694,"children":697},{"src":695,"alt":696,"width":165,"style":166},"/article/business-blog-is-it-worth-it/hire-copywriter.svg","Hire a copywriter",[],{"type":32,"tag":169,"props":699,"children":701},{"id":700},"hire-a-copywriter",[702],{"type":37,"value":703},"📝 Hire a Copywriter",{"type":32,"tag":46,"props":705,"children":706},{},[707],{"type":37,"value":708},"Saves time but costs money, and they might not understand the details of your field. Solution - give them notes, answer their questions, send bullet points.",{"type":32,"tag":157,"props":710,"children":711},{},[712,717,723],{"type":32,"tag":161,"props":713,"children":716},{"src":714,"alt":715,"width":165,"style":166},"/article/business-blog-is-it-worth-it/combine-both.svg","Combine both",[],{"type":32,"tag":169,"props":718,"children":720},{"id":719},"combine-both",[721],{"type":37,"value":722},"🤝 Combine Both",{"type":32,"tag":46,"props":724,"children":725},{},[726,728,732],{"type":37,"value":727},"Works best in practice. You provide the expert knowledge, the copywriter shapes it into readable form and handles ",{"type":32,"tag":117,"props":729,"children":730},{},[731],{"type":37,"value":423},{"type":37,"value":733},".",{"type":32,"tag":46,"props":735,"children":736},{},[737,739,756,757,761,763,767],{"type":37,"value":738},"Another option - ",{"type":32,"tag":82,"props":740,"children":741},{},[742,744,754],{"type":37,"value":743},"using ",{"type":32,"tag":139,"props":745,"children":747},{"href":746},"/knowledge/will-ai-replace-web-developers",[748,752],{"type":32,"tag":117,"props":749,"children":750},{},[751],{"type":37,"value":608},{"type":37,"value":753}," as an assistant",{"type":37,"value":755}," in writing",{"type":37,"value":632},{"type":32,"tag":117,"props":758,"children":759},{},[760],{"type":37,"value":608},{"type":37,"value":762}," tools can help with article outlines, wording, or research. But the key is to always review the output, add your own experiences and examples, and edit the text to sound natural. Purely ",{"type":32,"tag":117,"props":764,"children":765},{},[766],{"type":37,"value":608},{"type":37,"value":768},"-generated content without human input is spotted by both readers and Google.",{"type":32,"tag":57,"props":770,"children":771},{},[],{"type":32,"tag":39,"props":773,"children":775},{"id":774},"conclusion",[776],{"type":37,"value":777},"Conclusion",{"type":32,"tag":46,"props":779,"children":780},{},[781],{"type":37,"value":782},"A business blog is worth it, but only if you approach it strategically with realistic expectations. It's not a magic tool that'll bring you customers overnight. It's a long-term investment in your website's visibility and building trust with potential customers.",{"type":32,"tag":46,"props":784,"children":785},{},[786],{"type":37,"value":787},"The key takeaways: Write about your customers' problems, not about yourself. One quality article per month beats ten mediocre ones. Be patient - first results come in 3-6 months. Measure what works and adjust your strategy.",{"type":32,"tag":46,"props":789,"children":790},{},[791],{"type":37,"value":792},"If you're not sure whether and how to launch a blog on your website, feel free to reach out. I'm happy to help with setting up a content strategy and the technical solution so your blog works right from the start.",{"type":32,"tag":57,"props":794,"children":795},{},[],{"type":32,"tag":39,"props":797,"children":799},{"id":798},"useful-links",[800],{"type":37,"value":801},"Useful Links",{"type":32,"tag":444,"props":803,"children":804},{},[805,815,825,837,849],{"type":32,"tag":448,"props":806,"children":807},{},[808,813],{"type":32,"tag":139,"props":809,"children":811},{"href":355,":target":345,"rel":810},[347],[812],{"type":37,"value":359},{"type":37,"value":814}," - free tool for tracking search rankings and your website's performance",{"type":32,"tag":448,"props":816,"children":817},{},[818,823],{"type":32,"tag":139,"props":819,"children":821},{"href":344,":target":345,"rel":820},[347],[822],{"type":37,"value":350},{"type":37,"value":824}," - measuring traffic and user behavior on your website",{"type":32,"tag":448,"props":826,"children":827},{},[828,835],{"type":32,"tag":139,"props":829,"children":832},{"href":830,":target":345,"rel":831},"https://ahrefs.com/webmaster-tools",[347],[833],{"type":37,"value":834},"Ahrefs Webmaster Tools",{"type":37,"value":836}," - free site audit and backlink analysis",{"type":32,"tag":448,"props":838,"children":839},{},[840,847],{"type":32,"tag":139,"props":841,"children":844},{"href":842,":target":345,"rel":843},"https://answerthepublic.com/",[347],[845],{"type":37,"value":846},"AnswerThePublic",{"type":37,"value":848}," - visualize questions people search around any topic",{"type":32,"tag":448,"props":850,"children":851},{},[852,859],{"type":32,"tag":139,"props":853,"children":856},{"href":854,":target":345,"rel":855},"https://hemingwayapp.com/",[347],[857],{"type":37,"value":858},"Hemingway Editor",{"type":37,"value":860}," - tool for simplifying and clarifying your writing",{"title":8,"searchDepth":862,"depth":862,"links":863},2,[864,865,866,867,868,872,873,874,875,878,879,880],{"id":41,"depth":862,"text":44},{"id":62,"depth":862,"text":65},{"id":94,"depth":862,"text":97},{"id":129,"depth":862,"text":132},{"id":223,"depth":862,"text":226,"children":869},[870],{"id":254,"depth":871,"text":257},3,{"id":275,"depth":862,"text":278},{"id":311,"depth":862,"text":314},{"id":410,"depth":862,"text":413},{"id":510,"depth":862,"text":513,"children":876},[877],{"id":616,"depth":871,"text":619},{"id":659,"depth":862,"text":662},{"id":774,"depth":862,"text":777},{"id":798,"depth":862,"text":801},"markdown","content:knowledge:business-blog-is-it-worth-it.md","content","knowledge/business-blog-is-it-worth-it.md","md",{"_path":887,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":888,"description":889,"author":11,"date":890,"readingTime":13,"level":14,"image":891,"tags":892,"slugs":896,"relatedArticles":899,"body":901,"_type":881,"_id":1793,"_source":883,"_file":1794,"_extension":885},"/knowledge/booking-system-for-website","Booking System for Your Website - A Guide for Service Businesses","Online booking for salons, restaurants, doctors and more. Overview of solutions, integrations and what to watch out for.","2026-03-10","/featured/booking-system-for-website.jpg",[893,20,894,895],"web","integrace","tips",{"en":897,"cs":898},"booking-system-for-website","rezervacni-system-na-web",[25,26,900],"gdpr-on-website-what-you-must-comply",{"type":29,"children":902,"toc":1772},[903,908,912,917,922,927,930,936,941,951,961,971,985,988,994,999,1059,1064,1067,1073,1078,1084,1143,1148,1154,1159,1171,1191,1194,1200,1205,1309,1312,1318,1323,1368,1395,1398,1404,1412,1417,1427,1442,1460,1463,1469,1474,1544,1547,1553,1558,1682,1687,1690,1694,1699,1704,1709,1713],{"type":32,"tag":33,"props":904,"children":906},{"id":905},"booking-system-for-your-website-a-guide-for-service-businesses",[907],{"type":37,"value":888},{"type":32,"tag":39,"props":909,"children":910},{"id":41},[911],{"type":37,"value":44},{"type":32,"tag":46,"props":913,"children":914},{},[915],{"type":37,"value":916},"Hair salons, massage therapists, medical offices, gyms, restaurants, car repair shops - all these businesses have one thing in common. Customers call to book an appointment. And they call at the worst possible time - when you're mid-haircut, mid-massage, or elbow-deep in an engine.",{"type":32,"tag":46,"props":918,"children":919},{},[920],{"type":37,"value":921},"An online booking system solves this. Customers pick a time slot themselves, whenever it suits them - even at 3 AM in their pajamas. You open your calendar in the morning and see what's ahead. No missed calls, no scribbling in paper diaries.",{"type":32,"tag":46,"props":923,"children":924},{},[925],{"type":37,"value":926},"We'll go through what options you have, what it costs, and what to watch out for so you pick a solution that actually saves you time and brings in customers.",{"type":32,"tag":57,"props":928,"children":929},{},[],{"type":32,"tag":39,"props":931,"children":933},{"id":932},"why-online-booking-increases-your-customer-count",[934],{"type":37,"value":935},"📈 Why Online Booking Increases Your Customer Count",{"type":32,"tag":46,"props":937,"children":938},{},[939],{"type":37,"value":940},"This isn't just about convenience. Online booking directly affects how many customers you get.",{"type":32,"tag":46,"props":942,"children":943},{},[944,949],{"type":32,"tag":82,"props":945,"children":946},{},[947],{"type":37,"value":948},"24/7 availability.",{"type":37,"value":950}," Your phone works nine to five. A booking system works all the time. A lot of people schedule services in the evening, after work, on weekends. If they can't book at that moment, they go elsewhere - to a competitor that has online booking.",{"type":32,"tag":46,"props":952,"children":953},{},[954,959],{"type":32,"tag":82,"props":955,"children":956},{},[957],{"type":37,"value":958},"Lower barrier.",{"type":37,"value":960}," Calling a stranger is uncomfortable for many people (especially younger generations). Clicking a \"Book Now\" button is painless. Sounds minor, but it genuinely affects how many people reach out.",{"type":32,"tag":46,"props":962,"children":963},{},[964,969],{"type":32,"tag":82,"props":965,"children":966},{},[967],{"type":37,"value":968},"Fewer forgotten appointments.",{"type":37,"value":970}," An automatic reminder the day before cuts no-shows by 30-50%. That's money you'd otherwise throw out the window.",{"type":32,"tag":157,"props":972,"children":973},{},[974,980],{"type":32,"tag":169,"props":975,"children":977},{"id":976},"from-practice",[978],{"type":37,"value":979},"💡 From Practice",{"type":32,"tag":46,"props":981,"children":982},{},[983],{"type":37,"value":984},"Hair salons that switch from phone bookings to an online system typically see a 20-30% increase in bookings within the first three months. The biggest jump is in bookings made outside business hours.",{"type":32,"tag":57,"props":986,"children":987},{},[],{"type":32,"tag":39,"props":989,"children":991},{"id":990},"types-of-booking-systems",[992],{"type":37,"value":993},"🔧 Types of Booking Systems",{"type":32,"tag":46,"props":995,"children":996},{},[997],{"type":37,"value":998},"Before you start picking a specific tool, it helps to know what you actually need. Booking systems fall into three categories by complexity.",{"type":32,"tag":153,"props":1000,"children":1001},{},[1002,1021,1040],{"type":32,"tag":157,"props":1003,"children":1004},{},[1005,1010,1016],{"type":32,"tag":161,"props":1006,"children":1009},{"src":1007,"alt":1008,"width":165,"style":166},"/article/booking-system-for-website/simple-system.svg","Simple booking calendar",[],{"type":32,"tag":169,"props":1011,"children":1013},{"id":1012},"simple-calendar",[1014],{"type":37,"value":1015},"📅 Simple Calendar",{"type":32,"tag":46,"props":1017,"children":1018},{},[1019],{"type":37,"value":1020},"Customers see available slots and pick one. No payments, no complications. Enough for a solo operator or small business with a few services. Typically free or a few dollars a month.",{"type":32,"tag":157,"props":1022,"children":1023},{},[1024,1029,1035],{"type":32,"tag":161,"props":1025,"children":1028},{"src":1026,"alt":1027,"width":165,"style":166},"/article/booking-system-for-website/system-for-team.svg","Booking system for teams",[],{"type":32,"tag":169,"props":1030,"children":1032},{"id":1031},"team-system",[1033],{"type":37,"value":1034},"🏢 Team System",{"type":32,"tag":46,"props":1036,"children":1037},{},[1038],{"type":37,"value":1039},"Multiple employees, each with their own calendar. Service management, pricing, duration. Notifications for customers and staff. For salons, clinics, gyms.",{"type":32,"tag":157,"props":1041,"children":1042},{},[1043,1048,1054],{"type":32,"tag":161,"props":1044,"children":1047},{"src":1045,"alt":1046,"width":165,"style":166},"/article/booking-system-for-website/complex-solution.svg","Complex booking solution",[],{"type":32,"tag":169,"props":1049,"children":1051},{"id":1050},"️-complex-solution",[1052],{"type":37,"value":1053},"⚙️ Complex Solution",{"type":32,"tag":46,"props":1055,"children":1056},{},[1057],{"type":37,"value":1058},"Upfront payments, cancellation policies, loyalty programs, POS integration, reporting. For multi-location restaurants, wellness centers, sports facilities.",{"type":32,"tag":46,"props":1060,"children":1061},{},[1062],{"type":37,"value":1063},"Most small businesses get by with the first two categories. If you don't need online payments and have one to three employees, a simple calendar will do just fine.",{"type":32,"tag":57,"props":1065,"children":1066},{},[],{"type":32,"tag":39,"props":1068,"children":1070},{"id":1069},"️-off-the-shelf-vs-custom-solutions",[1071],{"type":37,"value":1072},"🛠️ Off-the-Shelf vs Custom Solutions",{"type":32,"tag":46,"props":1074,"children":1075},{},[1076],{"type":37,"value":1077},"You have two basic paths - use a ready-made service, or have a custom solution built. Both have their place.",{"type":32,"tag":169,"props":1079,"children":1081},{"id":1080},"third-party-services",[1082],{"type":37,"value":1083},"🌐 Third-Party Services",{"type":32,"tag":153,"props":1085,"children":1086},{},[1087,1101,1115,1129],{"type":32,"tag":157,"props":1088,"children":1089},{},[1090,1096],{"type":32,"tag":169,"props":1091,"children":1093},{"id":1092},"calendly",[1094],{"type":37,"value":1095},"📆 Calendly",{"type":32,"tag":46,"props":1097,"children":1098},{},[1099],{"type":37,"value":1100},"Popular with freelancers and consultants. Simple, elegant, excellent Google Calendar integration. Free plan for basic use, paid plans from $8/month.",{"type":32,"tag":157,"props":1102,"children":1103},{},[1104,1110],{"type":32,"tag":169,"props":1105,"children":1107},{"id":1106},"acuity-scheduling",[1108],{"type":37,"value":1109},"📋 Acuity Scheduling",{"type":32,"tag":46,"props":1111,"children":1112},{},[1113],{"type":37,"value":1114},"Part of the Squarespace ecosystem. Strong customization, intake forms, payment processing. Good for service businesses that need more than a basic calendar.",{"type":32,"tag":157,"props":1116,"children":1117},{},[1118,1124],{"type":32,"tag":169,"props":1119,"children":1121},{"id":1120},"simplybookme",[1122],{"type":37,"value":1123},"🕐 SimplyBook.me",{"type":32,"tag":46,"props":1125,"children":1126},{},[1127],{"type":37,"value":1128},"Feature-rich with a generous free tier. Supports multiple providers, custom booking pages, and various payment integrations. Popular across Europe.",{"type":32,"tag":157,"props":1130,"children":1131},{},[1132,1138],{"type":32,"tag":169,"props":1133,"children":1135},{"id":1134},"️-specialized-systems",[1136],{"type":37,"value":1137},"🍽️ Specialized Systems",{"type":32,"tag":46,"props":1139,"children":1140},{},[1141],{"type":37,"value":1142},"Restaurants, hotels, and medical offices often need industry-specific solutions. General booking tools won't handle table management, room inventory, or patient records.",{"type":32,"tag":46,"props":1144,"children":1145},{},[1146],{"type":37,"value":1147},"The upside of ready-made services is clear - turn it on and go. The downside is platform dependency, monthly fees, and limited control over how the system looks and behaves.",{"type":32,"tag":169,"props":1149,"children":1151},{"id":1150},"custom-solutions",[1152],{"type":37,"value":1153},"🔨 Custom Solutions",{"type":32,"tag":46,"props":1155,"children":1156},{},[1157],{"type":37,"value":1158},"A custom booking system makes sense when you have specific requirements that off-the-shelf solutions can't cover, or when you want bookings fully integrated into your website without redirecting to a third-party page.",{"type":32,"tag":46,"props":1160,"children":1161},{},[1162,1164,1169],{"type":37,"value":1163},"The cost of a custom solution starts around ",{"type":32,"tag":139,"props":1165,"children":1166},{"href":141},[1167],{"type":37,"value":1168},"$1,200",{"type":37,"value":1170}," for a simple calendar and can exceed $8,000 for a complex system with payments and third-party integrations. The advantage is that you pay once and the system is yours.",{"type":32,"tag":46,"props":1172,"children":1173},{},[1174,1176,1180,1182,1189],{"type":37,"value":1175},"If your website runs on a ",{"type":32,"tag":117,"props":1177,"children":1178},{},[1179],{"type":37,"value":643},{"type":37,"value":1181}," with catalog functionality - like ",{"type":32,"tag":139,"props":1183,"children":1186},{"href":1184,":target":345,"rel":1185},"https://www.sqrl.dev",[347],[1187],{"type":37,"value":1188},"Squirrel CMS",{"type":37,"value":1190},", which is built specifically for catalogs and includes a powerful page builder - integrating a booking module is simpler because the foundation (service database, filtering, user roles) is already in place.",{"type":32,"tag":57,"props":1192,"children":1193},{},[],{"type":32,"tag":39,"props":1195,"children":1197},{"id":1196},"integration-with-other-tools",[1198],{"type":37,"value":1199},"🔗 Integration with Other Tools",{"type":32,"tag":46,"props":1201,"children":1202},{},[1203],{"type":37,"value":1204},"The booking system itself is just one piece of the puzzle. To truly save you time, you need to connect it with the tools you already use.",{"type":32,"tag":153,"props":1206,"children":1207},{},[1208,1227,1255,1274],{"type":32,"tag":157,"props":1209,"children":1210},{},[1211,1216,1222],{"type":32,"tag":161,"props":1212,"children":1215},{"src":1213,"alt":1214,"width":165,"style":166},"/article/booking-system-for-website/google-calendar.svg","Google Calendar",[],{"type":32,"tag":169,"props":1217,"children":1219},{"id":1218},"google-calendar",[1220],{"type":37,"value":1221},"📅 Google Calendar",{"type":32,"tag":46,"props":1223,"children":1224},{},[1225],{"type":37,"value":1226},"The baseline. Most booking systems sync with Google Calendar so you see work and personal events in one place. Check that sync works both ways - you want manually added events to block slots too.",{"type":32,"tag":157,"props":1228,"children":1229},{},[1230,1235,1241],{"type":32,"tag":161,"props":1231,"children":1234},{"src":1232,"alt":1233,"width":165,"style":166},"/article/booking-system-for-website/email-marketing.svg","Email marketing",[],{"type":32,"tag":169,"props":1236,"children":1238},{"id":1237},"email-marketing",[1239],{"type":37,"value":1240},"📧 Email Marketing",{"type":32,"tag":46,"props":1242,"children":1243},{},[1244,1246,1253],{"type":37,"value":1245},"With customer emails from bookings, you can send them offers and reminders. Integration with tools like ",{"type":32,"tag":139,"props":1247,"children":1250},{"href":1248,":target":345,"rel":1249,":rel":347},"https://mailchimp.com",[347],[1251],{"type":37,"value":1252},"Mailchimp",{"type":37,"value":1254}," automates this.",{"type":32,"tag":157,"props":1256,"children":1257},{},[1258,1263,1269],{"type":32,"tag":161,"props":1259,"children":1262},{"src":1260,"alt":1261,"width":165,"style":166},"/article/booking-system-for-website/accounting.svg","Accounting systems",[],{"type":32,"tag":169,"props":1264,"children":1266},{"id":1265},"accounting-systems",[1267],{"type":37,"value":1268},"🧾 Accounting Systems",{"type":32,"tag":46,"props":1270,"children":1271},{},[1272],{"type":37,"value":1273},"If you accept upfront payments, you want invoices generated automatically. Connecting to accounting software saves hours every month.",{"type":32,"tag":157,"props":1275,"children":1276},{},[1277,1282,1288],{"type":32,"tag":161,"props":1278,"children":1281},{"src":1279,"alt":1280,"width":165,"style":166},"/article/booking-system-for-website/google-business.svg","Google Business Profile",[],{"type":32,"tag":169,"props":1283,"children":1285},{"id":1284},"google-business",[1286],{"type":37,"value":1287},"📍 Google Business",{"type":32,"tag":46,"props":1289,"children":1290},{},[1291,1293,1300,1302,1307],{"type":37,"value":1292},"Google lets you add a booking button directly to your ",{"type":32,"tag":139,"props":1294,"children":1297},{"href":1295,":target":345,"rel":1296,":rel":347},"https://business.google.com/",[347],[1298],{"type":37,"value":1299},"business profile",{"type":37,"value":1301}," in search results. Customers find you and book right away. If your ",{"type":32,"tag":139,"props":1303,"children":1304},{"href":648},[1305],{"type":37,"value":1306},"business website is missing essentials",{"type":37,"value":1308},", a booking system alone won't be enough.",{"type":32,"tag":57,"props":1310,"children":1311},{},[],{"type":32,"tag":39,"props":1313,"children":1315},{"id":1314},"upfront-payment-how-to-reduce-no-shows",[1316],{"type":37,"value":1317},"💳 Upfront Payment - How to Reduce No-Shows",{"type":32,"tag":46,"props":1319,"children":1320},{},[1321],{"type":37,"value":1322},"A client books an appointment and doesn't show up. Everyone who provides services knows this pain. Upfront payment or deposits cut this down dramatically.",{"type":32,"tag":153,"props":1324,"children":1325},{},[1326,1340,1354],{"type":32,"tag":157,"props":1327,"children":1328},{},[1329,1335],{"type":32,"tag":169,"props":1330,"children":1332},{"id":1331},"full-upfront-payment",[1333],{"type":37,"value":1334},"💰 Full Upfront Payment",{"type":32,"tag":46,"props":1336,"children":1337},{},[1338],{"type":37,"value":1339},"Eliminates no-shows almost completely. Good for pricier services (massages, consultations). Can deter new customers who don't know you yet.",{"type":32,"tag":157,"props":1341,"children":1342},{},[1343,1349],{"type":32,"tag":169,"props":1344,"children":1346},{"id":1345},"deposit",[1347],{"type":37,"value":1348},"🔒 Deposit",{"type":32,"tag":46,"props":1350,"children":1351},{},[1352],{"type":37,"value":1353},"A compromise - the customer pays 20-30% upfront, the rest on site. Motivating enough to show up, but not as off-putting as full payment.",{"type":32,"tag":157,"props":1355,"children":1356},{},[1357,1363],{"type":32,"tag":169,"props":1358,"children":1360},{"id":1359},"card-on-file",[1361],{"type":37,"value":1362},"💳 Card on File",{"type":32,"tag":46,"props":1364,"children":1365},{},[1366],{"type":37,"value":1367},"The customer enters card details when booking, but nothing is charged. If they don't show up without canceling, you charge a fee. Common abroad, less so in some markets.",{"type":32,"tag":157,"props":1369,"children":1370},{},[1371,1382],{"type":32,"tag":169,"props":1372,"children":1374},{"id":1373},"️-watch-out-for-gdpr",[1375,1377],{"type":37,"value":1376},"⚠️ Watch Out for ",{"type":32,"tag":117,"props":1378,"children":1379},{},[1380],{"type":37,"value":1381},"GDPR",{"type":32,"tag":46,"props":1383,"children":1384},{},[1385,1387,1393],{"type":37,"value":1386},"If you accept online payments or store payment details, you need your ",{"type":32,"tag":139,"props":1388,"children":1390},{"href":1389},"/knowledge/gdpr-on-website-what-you-must-comply",[1391],{"type":37,"value":1392},"data processing in order",{"type":37,"value":1394},". Most ready-made solutions handle this for you, but with a custom system it's your responsibility. Also don't forget clear cancellation terms - the customer must know under what conditions they'll get their money back.",{"type":32,"tag":57,"props":1396,"children":1397},{},[],{"type":32,"tag":39,"props":1399,"children":1401},{"id":1400},"automatic-reminders",[1402],{"type":37,"value":1403},"📲 Automatic Reminders",{"type":32,"tag":46,"props":1405,"children":1406},{},[1407],{"type":32,"tag":161,"props":1408,"children":1411},{"alt":1409,"src":1410},"Automatic reminders - email, SMS and WhatsApp","/article/booking-system-for-website/reminders.jpg",[],{"type":32,"tag":46,"props":1413,"children":1414},{},[1415],{"type":37,"value":1416},"Reminders are one of the most valuable features of a booking system. A simple message - \"We're expecting you tomorrow at 2 PM at Salon XY\" - reduces forgotten appointments by tens of percent.",{"type":32,"tag":46,"props":1418,"children":1419},{},[1420,1425],{"type":32,"tag":82,"props":1421,"children":1422},{},[1423],{"type":37,"value":1424},"Email reminders",{"type":37,"value":1426}," are the baseline and usually included even in free plans. Send them 24 hours before - enough time for the customer to reconsider and cancel if needed, but not so early they forget again.",{"type":32,"tag":46,"props":1428,"children":1429},{},[1430,1440],{"type":32,"tag":82,"props":1431,"children":1432},{},[1433,1438],{"type":32,"tag":117,"props":1434,"children":1435},{},[1436],{"type":37,"value":1437},"SMS",{"type":37,"value":1439}," reminders",{"type":37,"value":1441}," have higher effectiveness than email because almost everyone reads their texts. They cost $0.02-0.05 per message, but when one no-show costs you $20+ in lost time, it's an investment that pays for itself many times over.",{"type":32,"tag":46,"props":1443,"children":1444},{},[1445,1447,1452,1454,1458],{"type":37,"value":1446},"Some systems also offer reminders via ",{"type":32,"tag":82,"props":1448,"children":1449},{},[1450],{"type":37,"value":1451},"WhatsApp",{"type":37,"value":1453}," - higher open rates than ",{"type":32,"tag":117,"props":1455,"children":1456},{},[1457],{"type":37,"value":1437},{"type":37,"value":1459},", but setup is more involved and not all customers use WhatsApp.",{"type":32,"tag":57,"props":1461,"children":1462},{},[],{"type":32,"tag":39,"props":1464,"children":1466},{"id":1465},"what-to-watch-out-for",[1467],{"type":37,"value":1468},"🔍 What to Watch Out For",{"type":32,"tag":46,"props":1470,"children":1471},{},[1472],{"type":37,"value":1473},"Picking the wrong booking system can cost you more time than it saves. Here's what to ask before you decide.",{"type":32,"tag":444,"props":1475,"children":1476},{},[1477,1487,1504,1514,1524,1534],{"type":32,"tag":448,"props":1478,"children":1479},{},[1480,1485],{"type":32,"tag":82,"props":1481,"children":1482},{},[1483],{"type":37,"value":1484},"Mobile display",{"type":37,"value":1486}," - more than half of bookings come from mobile. If your booking form doesn't work or is cluttered on a phone, you're losing customers",{"type":32,"tag":448,"props":1488,"children":1489},{},[1490,1495,1497],{"type":32,"tag":82,"props":1491,"children":1492},{},[1493],{"type":37,"value":1494},"Speed",{"type":37,"value":1496}," - every second spent waiting for the calendar to load reduces the chance a customer completes the booking. Test it yourself on a slow connection - try ",{"type":32,"tag":139,"props":1498,"children":1501},{"href":1499,":target":345,"rel":1500,":rel":347},"https://pagespeed.web.dev/",[347],[1502],{"type":37,"value":1503},"PageSpeed Insights",{"type":32,"tag":448,"props":1505,"children":1506},{},[1507,1512],{"type":32,"tag":82,"props":1508,"children":1509},{},[1510],{"type":37,"value":1511},"Language",{"type":37,"value":1513}," - international tools sometimes lack your local language or have awkward translations. For local customers, this matters",{"type":32,"tag":448,"props":1515,"children":1516},{},[1517,1522],{"type":32,"tag":82,"props":1518,"children":1519},{},[1520],{"type":37,"value":1521},"Cancellation and rescheduling",{"type":37,"value":1523}," - customers should be able to reschedule or cancel on their own. Otherwise they'll call you, and you'll be doing what the system was supposed to eliminate",{"type":32,"tag":448,"props":1525,"children":1526},{},[1527,1532],{"type":32,"tag":82,"props":1528,"children":1529},{},[1530],{"type":37,"value":1531},"Integration with your website",{"type":37,"value":1533}," - find out whether the system can be embedded directly into your page (embed/iframe) or redirects customers to a third-party domain. Redirects reduce trust",{"type":32,"tag":448,"props":1535,"children":1536},{},[1537,1542],{"type":32,"tag":82,"props":1538,"children":1539},{},[1540],{"type":37,"value":1541},"Data export",{"type":37,"value":1543}," - if you want to switch systems later, you need to get your data out. Some platforms don't make this easy",{"type":32,"tag":57,"props":1545,"children":1546},{},[],{"type":32,"tag":39,"props":1548,"children":1550},{"id":1549},"what-it-costs",[1551],{"type":37,"value":1552},"💰 What It Costs",{"type":32,"tag":46,"props":1554,"children":1555},{},[1556],{"type":37,"value":1557},"The price range is huge, but it breaks down fairly clearly.",{"type":32,"tag":1559,"props":1560,"children":1561},"table",{},[1562,1587],{"type":32,"tag":1563,"props":1564,"children":1565},"thead",{},[1566],{"type":32,"tag":1567,"props":1568,"children":1569},"tr",{},[1570,1577,1582],{"type":32,"tag":1571,"props":1572,"children":1574},"th",{"align":1573},"left",[1575],{"type":37,"value":1576},"Solution",{"type":32,"tag":1571,"props":1578,"children":1579},{"align":1573},[1580],{"type":37,"value":1581},"Monthly Cost",{"type":32,"tag":1571,"props":1583,"children":1584},{"align":1573},[1585],{"type":37,"value":1586},"Best For",{"type":32,"tag":1588,"props":1589,"children":1590},"tbody",{},[1591,1610,1628,1646,1664],{"type":32,"tag":1567,"props":1592,"children":1593},{},[1594,1600,1605],{"type":32,"tag":1595,"props":1596,"children":1597},"td",{"align":1573},[1598],{"type":37,"value":1599},"Calendly Free / SimplyBook.me Free",{"type":32,"tag":1595,"props":1601,"children":1602},{"align":1573},[1603],{"type":37,"value":1604},"$0",{"type":32,"tag":1595,"props":1606,"children":1607},{"align":1573},[1608],{"type":37,"value":1609},"Solo operator, basic needs",{"type":32,"tag":1567,"props":1611,"children":1612},{},[1613,1618,1623],{"type":32,"tag":1595,"props":1614,"children":1615},{"align":1573},[1616],{"type":37,"value":1617},"Acuity / SimplyBook.me Paid",{"type":32,"tag":1595,"props":1619,"children":1620},{"align":1573},[1621],{"type":37,"value":1622},"$8-30/month",{"type":32,"tag":1595,"props":1624,"children":1625},{"align":1573},[1626],{"type":37,"value":1627},"Small business, team of 2-5",{"type":32,"tag":1567,"props":1629,"children":1630},{},[1631,1636,1641],{"type":32,"tag":1595,"props":1632,"children":1633},{"align":1573},[1634],{"type":37,"value":1635},"Calendly Pro / Full-featured plans",{"type":32,"tag":1595,"props":1637,"children":1638},{"align":1573},[1639],{"type":37,"value":1640},"$15-60/month",{"type":32,"tag":1595,"props":1642,"children":1643},{"align":1573},[1644],{"type":37,"value":1645},"Businesses with payments & integrations",{"type":32,"tag":1567,"props":1647,"children":1648},{},[1649,1654,1659],{"type":32,"tag":1595,"props":1650,"children":1651},{"align":1573},[1652],{"type":37,"value":1653},"Custom solution (simple)",{"type":32,"tag":1595,"props":1655,"children":1656},{"align":1573},[1657],{"type":37,"value":1658},"$1,200-2,500 one-time",{"type":32,"tag":1595,"props":1660,"children":1661},{"align":1573},[1662],{"type":37,"value":1663},"Specific requirements",{"type":32,"tag":1567,"props":1665,"children":1666},{},[1667,1672,1677],{"type":32,"tag":1595,"props":1668,"children":1669},{"align":1573},[1670],{"type":37,"value":1671},"Custom solution (complex)",{"type":32,"tag":1595,"props":1673,"children":1674},{"align":1573},[1675],{"type":37,"value":1676},"$4,000-12,000+ one-time",{"type":32,"tag":1595,"props":1678,"children":1679},{"align":1573},[1680],{"type":37,"value":1681},"Large businesses, multiple locations",{"type":32,"tag":46,"props":1683,"children":1684},{},[1685],{"type":37,"value":1686},"With ready-made services, expect the price to grow with team size and features. What starts as \"free\" can grow to significant monthly costs within a year. With a custom solution, you pay more upfront but then have minimal operating costs - just hosting and occasional maintenance.",{"type":32,"tag":57,"props":1688,"children":1689},{},[],{"type":32,"tag":39,"props":1691,"children":1692},{"id":774},[1693],{"type":37,"value":777},{"type":32,"tag":46,"props":1695,"children":1696},{},[1697],{"type":37,"value":1698},"A booking system isn't a luxury - for a service business, it's a fundamental tool that saves time and brings in customers. If you've been running on phone calls and paper diaries, try starting with a free plan from Calendly or SimplyBook.me. You can set it up in an afternoon and test it in practice.",{"type":32,"tag":46,"props":1700,"children":1701},{},[1702],{"type":37,"value":1703},"If you find a simple system isn't enough, consider a custom solution integrated directly into your website. It costs more upfront but pays off long-term - you have full control, no monthly fees, and bookings feel like a natural part of your website rather than a foreign element.",{"type":32,"tag":46,"props":1705,"children":1706},{},[1707],{"type":37,"value":1708},"Whatever you choose, start now. Every day without online booking is a day customers call, you don't pick up, and they go elsewhere.",{"type":32,"tag":39,"props":1710,"children":1711},{"id":798},[1712],{"type":37,"value":801},{"type":32,"tag":444,"props":1714,"children":1715},{},[1716,1728,1740,1752,1762],{"type":32,"tag":448,"props":1717,"children":1718},{},[1719,1726],{"type":32,"tag":139,"props":1720,"children":1723},{"href":1721,":target":345,"rel":1722},"https://calendly.com/",[347],[1724],{"type":37,"value":1725},"Calendly",{"type":37,"value":1727}," - simple scheduling tool for freelancers and consultants",{"type":32,"tag":448,"props":1729,"children":1730},{},[1731,1738],{"type":32,"tag":139,"props":1732,"children":1735},{"href":1733,":target":345,"rel":1734},"https://simplybook.me/",[347],[1736],{"type":37,"value":1737},"SimplyBook.me",{"type":37,"value":1739}," - feature-rich booking system with a generous free tier",{"type":32,"tag":448,"props":1741,"children":1742},{},[1743,1750],{"type":32,"tag":139,"props":1744,"children":1747},{"href":1745,":target":345,"rel":1746},"https://acuityscheduling.com/",[347],[1748],{"type":37,"value":1749},"Acuity Scheduling",{"type":37,"value":1751}," - part of Squarespace, great for service businesses",{"type":32,"tag":448,"props":1753,"children":1754},{},[1755,1760],{"type":32,"tag":139,"props":1756,"children":1758},{"href":1295,":target":345,"rel":1757},[347],[1759],{"type":37,"value":1280},{"type":37,"value":1761}," - add a booking button to your Google search listing",{"type":32,"tag":448,"props":1763,"children":1764},{},[1765,1770],{"type":32,"tag":139,"props":1766,"children":1768},{"href":1499,":target":345,"rel":1767},[347],[1769],{"type":37,"value":1503},{"type":37,"value":1771}," - test your website speed including the booking system",{"title":8,"searchDepth":862,"depth":862,"links":1773},[1774,1775,1778,1779,1783,1784,1788,1789,1790,1791,1792],{"id":41,"depth":862,"text":44},{"id":932,"depth":862,"text":935,"children":1776},[1777],{"id":976,"depth":871,"text":979},{"id":990,"depth":862,"text":993},{"id":1069,"depth":862,"text":1072,"children":1780},[1781,1782],{"id":1080,"depth":871,"text":1083},{"id":1150,"depth":871,"text":1153},{"id":1196,"depth":862,"text":1199},{"id":1314,"depth":862,"text":1317,"children":1785},[1786],{"id":1373,"depth":871,"text":1787},"⚠️ Watch Out for GDPR",{"id":1400,"depth":862,"text":1403},{"id":1465,"depth":862,"text":1468},{"id":1549,"depth":862,"text":1552},{"id":774,"depth":862,"text":777},{"id":798,"depth":862,"text":801},"content:knowledge:booking-system-for-website.md","knowledge/booking-system-for-website.md",{"_path":1389,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":1796,"description":1797,"author":11,"date":1798,"readingTime":1799,"level":14,"image":1800,"tags":1801,"slugs":1805,"relatedArticles":1807,"body":1811,"_type":881,"_id":2987,"_source":883,"_file":2988,"_extension":885},"GDPR on Your Website - What You Must Comply With in 2026","A practical GDPR checklist for website owners. Cookies, forms, privacy policy, and common mistakes to avoid.","2026-02-26",10,"/featured/gdpr-on-website-what-you-must-comply.jpg",[1802,1803,893,1804],"gdpr","legal","cookies",{"en":900,"cs":1806},"gdpr-na-webu-co-musite-splnit",[1808,1809,1810],"how-to-set-up-a-cookie-bar-correctly","web-accessibility-guide","domains-all-about-it",{"type":29,"children":1812,"toc":2966},[1813,1818,1822,1827,1832,1835,1841,1859,1864,1930,1935,1938,1944,1953,1965,1970,2022,2063,2068,2072,2075,2081,2086,2105,2110,2143,2163,2166,2172,2184,2189,2272,2291,2305,2308,2314,2326,2359,2390,2402,2405,2411,2420,2436,2441,2484,2516,2539,2542,2548,2553,2612,2674,2677,2682,2688,2693,2863,2866,2870,2875,2880,2885,2888,2892],{"type":32,"tag":33,"props":1814,"children":1816},{"id":1815},"gdpr-on-your-website-what-you-must-comply-with-in-2026",[1817],{"type":37,"value":1796},{"type":32,"tag":39,"props":1819,"children":1820},{"id":41},[1821],{"type":37,"value":44},{"type":32,"tag":46,"props":1823,"children":1824},{},[1825],{"type":37,"value":1826},"GDPR has been around since 2018 and plenty of websites still don't have it right. You don't need to be a lawyer to understand what your website needs. This article is a practical guide for website owners - no legal jargon, just concrete steps you need to take.",{"type":32,"tag":46,"props":1828,"children":1829},{},[1830],{"type":37,"value":1831},"If you run a website that collects any data from visitors (and that's nearly every website), this concerns you. Fines for GDPR violations can reach up to 20 million euros or 4% of annual turnover. In practice, fines in the Czech Republic range from tens of thousands to millions of CZK, but inspections from the data protection authority are increasing.",{"type":32,"tag":57,"props":1833,"children":1834},{},[],{"type":32,"tag":39,"props":1836,"children":1838},{"id":1837},"gdpr-in-a-nutshell-what-it-means-for-your-website",[1839],{"type":37,"value":1840},"📋 GDPR in a Nutshell - What It Means for Your Website",{"type":32,"tag":46,"props":1842,"children":1843},{},[1844,1848,1850,1857],{"type":32,"tag":82,"props":1845,"children":1846},{},[1847],{"type":37,"value":1381},{"type":37,"value":1849}," (",{"type":32,"tag":139,"props":1851,"children":1854},{"href":1852,":target":345,"rel":1853,":rel":347},"https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32016R0679",[347],[1855],{"type":37,"value":1856},"General Data Protection Regulation",{"type":37,"value":1858},") is a European regulation on personal data protection. Personal data is anything that can identify a specific person - name, email, IP address, cookies, phone number. If you collect any of these on your website, you must follow GDPR rules.",{"type":32,"tag":46,"props":1860,"children":1861},{},[1862],{"type":37,"value":1863},"For you as a website owner, it boils down to three things in practice:",{"type":32,"tag":153,"props":1865,"children":1866},{},[1867,1888,1909],{"type":32,"tag":157,"props":1868,"children":1869},{},[1870,1876],{"type":32,"tag":169,"props":1871,"children":1873},{"id":1872},"legal-basis",[1874],{"type":37,"value":1875},"📝 Legal Basis",{"type":32,"tag":46,"props":1877,"children":1878},{},[1879,1881,1886],{"type":37,"value":1880},"You must have a ",{"type":32,"tag":82,"props":1882,"children":1883},{},[1884],{"type":37,"value":1885},"legal basis",{"type":37,"value":1887}," for processing each piece of personal data. This can be consent (actively checking a checkbox), contract fulfillment (an e-shop order), legitimate interest (security logs), or legal obligation (accounting records).",{"type":32,"tag":157,"props":1889,"children":1890},{},[1891,1897],{"type":32,"tag":169,"props":1892,"children":1894},{"id":1893},"transparency",[1895],{"type":37,"value":1896},"💬 Transparency",{"type":32,"tag":46,"props":1898,"children":1899},{},[1900,1902,1907],{"type":37,"value":1901},"You must ",{"type":32,"tag":82,"props":1903,"children":1904},{},[1905],{"type":37,"value":1906},"inform",{"type":37,"value":1908}," visitors about what you do with their data. Clearly and accessibly.",{"type":32,"tag":157,"props":1910,"children":1911},{},[1912,1918],{"type":32,"tag":169,"props":1913,"children":1915},{"id":1914},"data-subject-rights",[1916],{"type":37,"value":1917},"🔧 Data Subject Rights",{"type":32,"tag":46,"props":1919,"children":1920},{},[1921,1923,1928],{"type":37,"value":1922},"You must allow visitors to ",{"type":32,"tag":82,"props":1924,"children":1925},{},[1926],{"type":37,"value":1927},"manage",{"type":37,"value":1929}," their data - view, delete, export.",{"type":32,"tag":46,"props":1931,"children":1932},{},[1933],{"type":37,"value":1934},"Most data on a regular website falls under consent or legitimate interest.",{"type":32,"tag":57,"props":1936,"children":1937},{},[],{"type":32,"tag":39,"props":1939,"children":1941},{"id":1940},"cookie-banner-how-to-set-it-up-right-and-how-not-to",[1942],{"type":37,"value":1943},"🍪 Cookie Banner - How to Set It Up Right (and How Not To)",{"type":32,"tag":46,"props":1945,"children":1946},{},[1947],{"type":32,"tag":161,"props":1948,"children":1952},{"alt":1949,"src":1950,"title":1951},"Cookie banner on a website","/article/gdpr-on-website-what-you-must-comply/cookies-banner.png","Cookie Banner",[],{"type":32,"tag":46,"props":1954,"children":1955},{},[1956,1958,1963],{"type":37,"value":1957},"The cookie banner is the first thing a visitor sees on your website. And unfortunately, it's also where most websites make mistakes. The basic rule is: ",{"type":32,"tag":82,"props":1959,"children":1960},{},[1961],{"type":37,"value":1962},"you can only run analytics and marketing cookies after active consent",{"type":37,"value":1964}," from the visitor. Technically necessary cookies (login, shopping cart, language preferences) don't need consent.",{"type":32,"tag":46,"props":1966,"children":1967},{},[1968],{"type":37,"value":1969},"What does this look like in practice? A proper cookie banner must include:",{"type":32,"tag":444,"props":1971,"children":1972},{},[1973,1990,2000,2010],{"type":32,"tag":448,"props":1974,"children":1975},{},[1976,1981,1983,1988],{"type":32,"tag":82,"props":1977,"children":1978},{},[1979],{"type":37,"value":1980},"\"Accept\" button",{"type":37,"value":1982}," and ",{"type":32,"tag":82,"props":1984,"children":1985},{},[1986],{"type":37,"value":1987},"\"Reject\" button",{"type":37,"value":1989}," - both must be equally prominent. No hiding the reject option in gray text.",{"type":32,"tag":448,"props":1991,"children":1992},{},[1993,1998],{"type":32,"tag":82,"props":1994,"children":1995},{},[1996],{"type":37,"value":1997},"Option to select cookie categories",{"type":37,"value":1999}," (necessary, analytics, marketing).",{"type":32,"tag":448,"props":2001,"children":2002},{},[2003,2008],{"type":32,"tag":82,"props":2004,"children":2005},{},[2006],{"type":37,"value":2007},"Link to cookie policy",{"type":37,"value":2009}," with a detailed description of each cookie.",{"type":32,"tag":448,"props":2011,"children":2012},{},[2013,2015,2020],{"type":37,"value":2014},"Consent must be ",{"type":32,"tag":82,"props":2016,"children":2017},{},[2018],{"type":37,"value":2019},"easy to withdraw",{"type":37,"value":2021}," - typically via an icon in the corner of the page.",{"type":32,"tag":157,"props":2023,"children":2024},{},[2025,2031],{"type":32,"tag":169,"props":2026,"children":2028},{"id":2027},"️-what-you-absolutely-must-not-do",[2029],{"type":37,"value":2030},"⚠️ What You Absolutely Must Not Do",{"type":32,"tag":444,"props":2032,"children":2033},{},[2034,2039,2053,2058],{"type":32,"tag":448,"props":2035,"children":2036},{},[2037],{"type":37,"value":2038},"Pre-checked checkboxes for analytics and marketing cookies.",{"type":32,"tag":448,"props":2040,"children":2041},{},[2042,2044,2051],{"type":37,"value":2043},"Running Google Analytics or ",{"type":32,"tag":139,"props":2045,"children":2048},{"href":2046,":target":345,"rel":2047,":rel":347},"https://developers.facebook.com/docs/meta-pixel/",[347],[2049],{"type":37,"value":2050},"Facebook Pixel",{"type":37,"value":2052}," before consent is given.",{"type":32,"tag":448,"props":2054,"children":2055},{},[2056],{"type":37,"value":2057},"Cookie walls - blocking access to content until the person consents.",{"type":32,"tag":448,"props":2059,"children":2060},{},[2061],{"type":37,"value":2062},"Hiding the \"Reject\" button somewhere in settings while \"Accept All\" glows green across the entire screen.",{"type":32,"tag":46,"props":2064,"children":2065},{},[2066],{"type":37,"value":2067},"If you want to dive deeper into cookie banners, I have a dedicated article on that.",{"type":32,"tag":2069,"props":2070,"children":2071},"article-link",{"slug":1808},[],{"type":32,"tag":57,"props":2073,"children":2074},{},[],{"type":32,"tag":39,"props":2076,"children":2078},{"id":2077},"contact-forms-consent-for-data-processing",[2079],{"type":37,"value":2080},"📨 Contact Forms - Consent for Data Processing",{"type":32,"tag":46,"props":2082,"children":2083},{},[2084],{"type":37,"value":2085},"The contact form is one of the most common ways you collect personal data on a website. Name, email, phone, message content - all of these are personal data. And you need a legal basis to process them.",{"type":32,"tag":46,"props":2087,"children":2088},{},[2089,2091,2096,2098,2103],{"type":37,"value":2090},"With a contact form, you have two options. Either use ",{"type":32,"tag":82,"props":2092,"children":2093},{},[2094],{"type":37,"value":2095},"legitimate interest",{"type":37,"value":2097}," (the visitor contacts you voluntarily, expects a response), or request ",{"type":32,"tag":82,"props":2099,"children":2100},{},[2101],{"type":37,"value":2102},"explicit consent",{"type":37,"value":2104}," via a checkbox. In practice, using a consent checkbox is safer because legitimate interest is harder to defend if you use the data for other purposes too.",{"type":32,"tag":46,"props":2106,"children":2107},{},[2108],{"type":37,"value":2109},"A properly set up contact form should include:",{"type":32,"tag":444,"props":2111,"children":2112},{},[2113,2123,2133],{"type":32,"tag":448,"props":2114,"children":2115},{},[2116,2121],{"type":32,"tag":82,"props":2117,"children":2118},{},[2119],{"type":37,"value":2120},"Consent checkbox",{"type":37,"value":2122}," (must not be pre-checked): \"I agree to the processing of personal data for the purpose of handling my inquiry. More information in the Privacy Policy.\"",{"type":32,"tag":448,"props":2124,"children":2125},{},[2126,2131],{"type":32,"tag":82,"props":2127,"children":2128},{},[2129],{"type":37,"value":2130},"Link to the privacy policy",{"type":37,"value":2132}," directly next to the form.",{"type":32,"tag":448,"props":2134,"children":2135},{},[2136,2141],{"type":32,"tag":82,"props":2137,"children":2138},{},[2139],{"type":37,"value":2140},"Information about data retention",{"type":37,"value":2142}," - e.g., \"Your data will be deleted within 6 months of handling your inquiry.\"",{"type":32,"tag":157,"props":2144,"children":2145},{},[2146,2152],{"type":32,"tag":169,"props":2147,"children":2149},{"id":2148},"️-watch-out-for-third-parties",[2150],{"type":37,"value":2151},"⚠️ Watch Out for Third Parties",{"type":32,"tag":46,"props":2153,"children":2154},{},[2155,2157,2162],{"type":37,"value":2156},"If you use services like Formspree, Netlify Forms, or other third parties, you must disclose this in your privacy policy. And if the service is based outside the EU, you also need to address ",{"type":32,"tag":82,"props":2158,"children":2159},{},[2160],{"type":37,"value":2161},"data transfers to third countries",{"type":37,"value":733},{"type":32,"tag":57,"props":2164,"children":2165},{},[],{"type":32,"tag":39,"props":2167,"children":2169},{"id":2168},"privacy-policy-what-it-must-include",[2170],{"type":37,"value":2171},"📄 Privacy Policy - What It Must Include",{"type":32,"tag":46,"props":2173,"children":2174},{},[2175,2177,2182],{"type":37,"value":2176},"Every website that processes personal data must have an accessible ",{"type":32,"tag":82,"props":2178,"children":2179},{},[2180],{"type":37,"value":2181},"privacy policy",{"type":37,"value":2183}," page. You can't just throw in a generated text from the internet - it must reflect what you actually do on your website.",{"type":32,"tag":46,"props":2185,"children":2186},{},[2187],{"type":37,"value":2188},"What must the privacy policy include:",{"type":32,"tag":444,"props":2190,"children":2191},{},[2192,2202,2212,2222,2232,2242,2252,2262],{"type":32,"tag":448,"props":2193,"children":2194},{},[2195,2200],{"type":32,"tag":82,"props":2196,"children":2197},{},[2198],{"type":37,"value":2199},"Who you are",{"type":37,"value":2201}," - identification of the data controller (name, company ID, contact, and optionally a data protection officer contact).",{"type":32,"tag":448,"props":2203,"children":2204},{},[2205,2210],{"type":32,"tag":82,"props":2206,"children":2207},{},[2208],{"type":37,"value":2209},"What data you collect",{"type":37,"value":2211}," - specific list (name, email, IP address, cookies...).",{"type":32,"tag":448,"props":2213,"children":2214},{},[2215,2220],{"type":32,"tag":82,"props":2216,"children":2217},{},[2218],{"type":37,"value":2219},"Why you collect it",{"type":37,"value":2221}," - purpose of processing for each data type (handling inquiries, traffic analysis, marketing...).",{"type":32,"tag":448,"props":2223,"children":2224},{},[2225,2230],{"type":32,"tag":82,"props":2226,"children":2227},{},[2228],{"type":37,"value":2229},"Legal basis",{"type":37,"value":2231}," - consent, legitimate interest, contract fulfillment.",{"type":32,"tag":448,"props":2233,"children":2234},{},[2235,2240],{"type":32,"tag":82,"props":2236,"children":2237},{},[2238],{"type":37,"value":2239},"Who you share data with",{"type":37,"value":2241}," - list of processors (Google, hosting provider, email service...).",{"type":32,"tag":448,"props":2243,"children":2244},{},[2245,2250],{"type":32,"tag":82,"props":2246,"children":2247},{},[2248],{"type":37,"value":2249},"How long you retain data",{"type":37,"value":2251}," - specific time periods, not \"for as long as necessary.\"",{"type":32,"tag":448,"props":2253,"children":2254},{},[2255,2260],{"type":32,"tag":82,"props":2256,"children":2257},{},[2258],{"type":37,"value":2259},"Visitor rights",{"type":37,"value":2261}," - right to access, rectification, erasure, portability, objection.",{"type":32,"tag":448,"props":2263,"children":2264},{},[2265,2270],{"type":32,"tag":82,"props":2266,"children":2267},{},[2268],{"type":37,"value":2269},"How to file a complaint",{"type":37,"value":2271}," - link to the data protection authority.",{"type":32,"tag":46,"props":2273,"children":2274},{},[2275,2277,2283,2285,2290],{"type":37,"value":2276},"The privacy policy must be easily accessible - typically a link in the website footer. I recommend writing it in plain language and paying attention to ",{"type":32,"tag":139,"props":2278,"children":2280},{"href":2279},"/knowledge/web-accessibility-guide",[2281],{"type":37,"value":2282},"web accessibility",{"type":37,"value":2284},". Legal text full of paragraph references helps no one, and GDPR specifically requires that information be presented ",{"type":32,"tag":82,"props":2286,"children":2287},{},[2288],{"type":37,"value":2289},"clearly and comprehensibly",{"type":37,"value":733},{"type":32,"tag":157,"props":2292,"children":2293},{},[2294,2300],{"type":32,"tag":169,"props":2295,"children":2297},{"id":2296},"tip",[2298],{"type":37,"value":2299},"💡 Tip",{"type":32,"tag":46,"props":2301,"children":2302},{},[2303],{"type":37,"value":2304},"Review your privacy policy once a year and update it. Added a new analytics tool to your site? Started using a different emailing service? All of that must be in the policy.",{"type":32,"tag":57,"props":2306,"children":2307},{},[],{"type":32,"tag":39,"props":2309,"children":2311},{"id":2310},"newsletter-and-email-marketing-rules-for-collecting-emails",[2312],{"type":37,"value":2313},"📧 Newsletter and Email Marketing - Rules for Collecting Emails",{"type":32,"tag":46,"props":2315,"children":2316},{},[2317,2319,2324],{"type":37,"value":2318},"Collecting emails for a newsletter is an area where mistakes happen very often. The basic rule: to send marketing emails, you need ",{"type":32,"tag":82,"props":2320,"children":2321},{},[2322],{"type":37,"value":2323},"freely given, specific, informed, and unambiguous consent",{"type":37,"value":2325},". In practice, this means:",{"type":32,"tag":444,"props":2327,"children":2328},{},[2329,2339,2349],{"type":32,"tag":448,"props":2330,"children":2331},{},[2332,2337],{"type":32,"tag":82,"props":2333,"children":2334},{},[2335],{"type":37,"value":2336},"Double opt-in",{"type":37,"value":2338}," - after entering their email, the person receives a confirmation email with a link. Only after clicking it are they subscribed. This isn't strictly required by law, but it's the best way to prove that consent was actually given.",{"type":32,"tag":448,"props":2340,"children":2341},{},[2342,2347],{"type":32,"tag":82,"props":2343,"children":2344},{},[2345],{"type":37,"value":2346},"Separate consent",{"type":37,"value":2348}," - newsletter consent must not be bundled with terms of service consent. It must be a separate checkbox.",{"type":32,"tag":448,"props":2350,"children":2351},{},[2352,2357],{"type":32,"tag":82,"props":2353,"children":2354},{},[2355],{"type":37,"value":2356},"Easy unsubscribe",{"type":37,"value":2358}," - every email must include an unsubscribe link. And unsubscribing must work immediately, not \"within 30 days.\"",{"type":32,"tag":157,"props":2360,"children":2361},{},[2362,2367],{"type":32,"tag":169,"props":2363,"children":2365},{"id":2364},"️-what-you-absolutely-must-not-do-1",[2366],{"type":37,"value":2030},{"type":32,"tag":444,"props":2368,"children":2369},{},[2370,2375,2380,2385],{"type":32,"tag":448,"props":2371,"children":2372},{},[2373],{"type":37,"value":2374},"Add everyone who sends an inquiry through your contact form to the newsletter.",{"type":32,"tag":448,"props":2376,"children":2377},{},[2378],{"type":37,"value":2379},"Buy email databases and send to them.",{"type":32,"tag":448,"props":2381,"children":2382},{},[2383],{"type":37,"value":2384},"Pre-check the \"I want to subscribe to the newsletter\" checkbox in an order form.",{"type":32,"tag":448,"props":2386,"children":2387},{},[2388],{"type":37,"value":2389},"Hide newsletter unsubscribe behind account login or a complicated process.",{"type":32,"tag":46,"props":2391,"children":2392},{},[2393,2395,2400],{"type":37,"value":2394},"Remember that you must be able to ",{"type":32,"tag":82,"props":2396,"children":2397},{},[2398],{"type":37,"value":2399},"prove",{"type":37,"value":2401}," when and how a person gave consent. Save the date, time, IP address, the exact wording of the consent, and how it was given. If the data protection authority comes knocking, they'll want to see evidence.",{"type":32,"tag":57,"props":2403,"children":2404},{},[],{"type":32,"tag":39,"props":2406,"children":2408},{"id":2407},"google-analytics-and-gdpr-how-to-handle-it",[2409],{"type":37,"value":2410},"📊 Google Analytics and GDPR - How to Handle It",{"type":32,"tag":46,"props":2412,"children":2413},{},[2414],{"type":32,"tag":161,"props":2415,"children":2419},{"alt":2416,"src":2417,"title":2418},"Analytics and GDPR","/article/gdpr-on-website-what-you-must-comply/analytics-gdpr.png","Google Analytics and Data Protection",[],{"type":32,"tag":46,"props":2421,"children":2422},{},[2423,2428,2430,2435],{"type":32,"tag":139,"props":2424,"children":2426},{"href":344,":target":345,"rel":2425},[347],[2427],{"type":37,"value":350},{"type":37,"value":2429}," is probably the most widely used analytics tool and also one of the most problematic from a GDPR perspective. While Google Analytics 4 added IP anonymization and shorter data retention options, there's still a fundamental problem - ",{"type":32,"tag":82,"props":2431,"children":2432},{},[2433],{"type":37,"value":2434},"data is transferred to Google's servers in the USA",{"type":37,"value":733},{"type":32,"tag":46,"props":2437,"children":2438},{},[2439],{"type":37,"value":2440},"What this means for you in practice:",{"type":32,"tag":444,"props":2442,"children":2443},{},[2444,2456,2467,2472],{"type":32,"tag":448,"props":2445,"children":2446},{},[2447,2449,2454],{"type":37,"value":2448},"Google Analytics ",{"type":32,"tag":82,"props":2450,"children":2451},{},[2452],{"type":37,"value":2453},"requires consent",{"type":37,"value":2455}," from the visitor. You must not run it before consent is given via the cookie banner.",{"type":32,"tag":448,"props":2457,"children":2458},{},[2459,2460,2465],{"type":37,"value":1880},{"type":32,"tag":82,"props":2461,"children":2462},{},[2463],{"type":37,"value":2464},"Data Processing Agreement",{"type":37,"value":2466}," with Google. You set this up in Google Analytics admin.",{"type":32,"tag":448,"props":2468,"children":2469},{},[2470],{"type":37,"value":2471},"Your privacy policy must state that you use Google Analytics, what data you collect, and that it's transferred to the USA.",{"type":32,"tag":448,"props":2473,"children":2474},{},[2475,2477,2482],{"type":37,"value":2476},"I recommend setting ",{"type":32,"tag":82,"props":2478,"children":2479},{},[2480],{"type":37,"value":2481},"data retention to the minimum",{"type":37,"value":2483}," (2 months) and enabling IP anonymization.",{"type":32,"tag":46,"props":2485,"children":2486},{},[2487,2489,2496,2498,2505,2507,2514],{"type":37,"value":2488},"If you want the path of least resistance, consider GDPR-friendlier alternatives. ",{"type":32,"tag":139,"props":2490,"children":2493},{"href":2491,":target":345,"rel":2492},"https://plausible.io/",[347],[2494],{"type":37,"value":2495},"Plausible",{"type":37,"value":2497},", ",{"type":32,"tag":139,"props":2499,"children":2502},{"href":2500,":target":345,"rel":2501},"https://usefathom.com/",[347],[2503],{"type":37,"value":2504},"Fathom",{"type":37,"value":2506},", or ",{"type":32,"tag":139,"props":2508,"children":2511},{"href":2509,":target":345,"rel":2510},"https://umami.is/",[347],[2512],{"type":37,"value":2513},"Umami",{"type":37,"value":2515}," are analytics tools that don't use cookies, don't collect personal data, and store data in the EU. With these tools, you don't even need cookie consent because they don't fall under cookie regulations.",{"type":32,"tag":46,"props":2517,"children":2518},{},[2519,2521,2528,2530,2537],{"type":37,"value":2520},"Other popular tools - ",{"type":32,"tag":139,"props":2522,"children":2525},{"href":2523,":target":345,"rel":2524},"https://www.hotjar.com/",[347],[2526],{"type":37,"value":2527},"Hotjar",{"type":37,"value":2529}," or ",{"type":32,"tag":139,"props":2531,"children":2534},{"href":2532,":target":345,"rel":2533},"https://clarity.microsoft.com/",[347],[2535],{"type":37,"value":2536},"Microsoft Clarity",{"type":37,"value":2538}," (session recording, heatmaps) - also require consent. Recording visitor behavior is personal data processing and you can't do it without consent.",{"type":32,"tag":57,"props":2540,"children":2541},{},[],{"type":32,"tag":39,"props":2543,"children":2545},{"id":2544},"most-common-mistakes-websites-make",[2546],{"type":37,"value":2547},"🚨 Most Common Mistakes Websites Make",{"type":32,"tag":46,"props":2549,"children":2550},{},[2551],{"type":37,"value":2552},"Over years of working with websites, I've seen plenty of recurring mistakes. Here are the most common ones:",{"type":32,"tag":153,"props":2554,"children":2555},{},[2556,2570,2584,2598],{"type":32,"tag":157,"props":2557,"children":2558},{},[2559,2565],{"type":32,"tag":169,"props":2560,"children":2562},{"id":2561},"cookies-fire-before-consent",[2563],{"type":37,"value":2564},"🔴 Cookies Fire Before Consent",{"type":32,"tag":46,"props":2566,"children":2567},{},[2568],{"type":37,"value":2569},"Open your website in an incognito window and check DevTools (Application tab - Cookies). If you see cookies from Google Analytics or Facebook before clicking \"Accept,\" you have a problem.",{"type":32,"tag":157,"props":2571,"children":2572},{},[2573,2579],{"type":32,"tag":169,"props":2574,"children":2576},{"id":2575},"missing-privacy-policy",[2577],{"type":37,"value":2578},"🔴 Missing Privacy Policy",{"type":32,"tag":46,"props":2580,"children":2581},{},[2582],{"type":37,"value":2583},"Some websites don't have a privacy policy at all, others have an outdated version that doesn't match reality. Check it at least once a year.",{"type":32,"tag":157,"props":2585,"children":2586},{},[2587,2593],{"type":32,"tag":169,"props":2588,"children":2590},{"id":2589},"contact-form-without-consent",[2591],{"type":37,"value":2592},"🔴 Contact Form Without Consent",{"type":32,"tag":46,"props":2594,"children":2595},{},[2596],{"type":37,"value":2597},"A form that submits data without any consent or processing information is a GDPR violation.",{"type":32,"tag":157,"props":2599,"children":2600},{},[2601,2607],{"type":32,"tag":169,"props":2602,"children":2604},{"id":2603},"newsletter-without-double-opt-in",[2605],{"type":37,"value":2606},"🔴 Newsletter Without Double Opt-in",{"type":32,"tag":46,"props":2608,"children":2609},{},[2610],{"type":37,"value":2611},"Technically not mandatory, but without double opt-in you'll struggle to prove consent was actually given. If someone reports spam, you'll be in a tough spot.",{"type":32,"tag":153,"props":2613,"children":2614},{},[2615,2629,2660],{"type":32,"tag":157,"props":2616,"children":2617},{},[2618,2624],{"type":32,"tag":169,"props":2619,"children":2621},{"id":2620},"third-parties-not-listed-in-privacy-policy",[2622],{"type":37,"value":2623},"🔴 Third Parties Not Listed in Privacy Policy",{"type":32,"tag":46,"props":2625,"children":2626},{},[2627],{"type":37,"value":2628},"Using live chat? A CRM system? An email marketing platform? All these services process your visitors' personal data and must be listed in the policy.",{"type":32,"tag":157,"props":2630,"children":2631},{},[2632,2638],{"type":32,"tag":169,"props":2633,"children":2635},{"id":2634},"missing-ssl-certificate",[2636],{"type":37,"value":2637},"🔴 Missing SSL Certificate",{"type":32,"tag":46,"props":2639,"children":2640},{},[2641,2643,2650,2652,2658],{"type":37,"value":2642},"HTTPS isn't a direct GDPR requirement, but the regulation requires \"appropriate technical measures\" to protect data. A website without HTTPS transmits form data unencrypted. You can get a free SSL certificate via ",{"type":32,"tag":139,"props":2644,"children":2647},{"href":2645,":target":345,"rel":2646,":rel":347},"https://letsencrypt.org/",[347],[2648],{"type":37,"value":2649},"Let's Encrypt",{"type":37,"value":2651}," and set it up when ",{"type":32,"tag":139,"props":2653,"children":2655},{"href":2654},"/knowledge/domains-all-about-it",[2656],{"type":37,"value":2657},"configuring your domain",{"type":37,"value":2659}," properly.",{"type":32,"tag":157,"props":2661,"children":2662},{},[2663,2669],{"type":32,"tag":169,"props":2664,"children":2666},{"id":2665},"storing-data-without-time-limits",[2667],{"type":37,"value":2668},"🔴 Storing Data Without Time Limits",{"type":32,"tag":46,"props":2670,"children":2671},{},[2672],{"type":37,"value":2673},"GDPR requires you to retain data only for as long as necessary. \"Forever\" is not a valid answer. Set specific time limits and stick to them.",{"type":32,"tag":57,"props":2675,"children":2676},{},[],{"type":32,"tag":161,"props":2678,"children":2681},{"src":2679,"alt":2680,"width":165,"style":166},"/article/gdpr-on-website-what-you-must-comply/checklist.svg","Checklist",[],{"type":32,"tag":39,"props":2683,"children":2685},{"id":2684},"practical-compliance-checklist",[2686],{"type":37,"value":2687},"✅ Practical Compliance Checklist",{"type":32,"tag":46,"props":2689,"children":2690},{},[2691],{"type":37,"value":2692},"Here's a checklist you can go through to verify your website meets basic GDPR requirements:",{"type":32,"tag":153,"props":2694,"children":2695},{},[2696,2737,2774,2831],{"type":32,"tag":157,"props":2697,"children":2698},{},[2699,2704],{"type":32,"tag":169,"props":2700,"children":2701},{"id":1804},[2702],{"type":37,"value":2703},"🍪 Cookies",{"type":32,"tag":444,"props":2705,"children":2706},{},[2707,2712,2717,2722,2727,2732],{"type":32,"tag":448,"props":2708,"children":2709},{},[2710],{"type":37,"value":2711},"⏹️ Cookie banner appears on first visit",{"type":32,"tag":448,"props":2713,"children":2714},{},[2715],{"type":37,"value":2716},"⏹️ Analytics and marketing cookies don't fire before consent",{"type":32,"tag":448,"props":2718,"children":2719},{},[2720],{"type":37,"value":2721},"⏹️ \"Accept\" and \"Reject\" buttons are equally prominent",{"type":32,"tag":448,"props":2723,"children":2724},{},[2725],{"type":37,"value":2726},"⏹️ Individual cookie categories can be selected",{"type":32,"tag":448,"props":2728,"children":2729},{},[2730],{"type":37,"value":2731},"⏹️ Consent can be easily withdrawn (icon in the corner)",{"type":32,"tag":448,"props":2733,"children":2734},{},[2735],{"type":37,"value":2736},"⏹️ Cookie banner includes a link to detailed cookie information",{"type":32,"tag":157,"props":2738,"children":2739},{},[2740,2746],{"type":32,"tag":169,"props":2741,"children":2743},{"id":2742},"forms",[2744],{"type":37,"value":2745},"📝 Forms",{"type":32,"tag":444,"props":2747,"children":2748},{},[2749,2754,2759,2764,2769],{"type":32,"tag":448,"props":2750,"children":2751},{},[2752],{"type":37,"value":2753},"⏹️ Contact form includes a consent checkbox (not pre-checked)",{"type":32,"tag":448,"props":2755,"children":2756},{},[2757],{"type":37,"value":2758},"⏹️ Link to privacy policy is near the form",{"type":32,"tag":448,"props":2760,"children":2761},{},[2762],{"type":37,"value":2763},"⏹️ Newsletter form uses double opt-in",{"type":32,"tag":448,"props":2765,"children":2766},{},[2767],{"type":37,"value":2768},"⏹️ Newsletter consent is separate from other consents",{"type":32,"tag":448,"props":2770,"children":2771},{},[2772],{"type":37,"value":2773},"⏹️ Every newsletter includes an unsubscribe link",{"type":32,"tag":157,"props":2775,"children":2776},{},[2777,2783],{"type":32,"tag":169,"props":2778,"children":2780},{"id":2779},"privacy-policy",[2781],{"type":37,"value":2782},"📄 Privacy Policy",{"type":32,"tag":444,"props":2784,"children":2785},{},[2786,2791,2796,2801,2806,2811,2816,2821,2826],{"type":32,"tag":448,"props":2787,"children":2788},{},[2789],{"type":37,"value":2790},"⏹️ Privacy policy page exists and is accessible from the footer",{"type":32,"tag":448,"props":2792,"children":2793},{},[2794],{"type":37,"value":2795},"⏹️ Includes data controller identification (name, company ID, contact)",{"type":32,"tag":448,"props":2797,"children":2798},{},[2799],{"type":37,"value":2800},"⏹️ Lists specific types of collected data",{"type":32,"tag":448,"props":2802,"children":2803},{},[2804],{"type":37,"value":2805},"⏹️ States processing purposes and legal bases",{"type":32,"tag":448,"props":2807,"children":2808},{},[2809],{"type":37,"value":2810},"⏹️ Includes a list of processors (third parties)",{"type":32,"tag":448,"props":2812,"children":2813},{},[2814],{"type":37,"value":2815},"⏹️ States specific data retention periods",{"type":32,"tag":448,"props":2817,"children":2818},{},[2819],{"type":37,"value":2820},"⏹️ Informs about visitor rights",{"type":32,"tag":448,"props":2822,"children":2823},{},[2824],{"type":37,"value":2825},"⏹️ Written in plain language",{"type":32,"tag":448,"props":2827,"children":2828},{},[2829],{"type":37,"value":2830},"⏹️ Is up to date (reviewed in the last 12 months)",{"type":32,"tag":157,"props":2832,"children":2833},{},[2834,2840],{"type":32,"tag":169,"props":2835,"children":2837},{"id":2836},"technical-measures",[2838],{"type":37,"value":2839},"🔒 Technical Measures",{"type":32,"tag":444,"props":2841,"children":2842},{},[2843,2848,2853,2858],{"type":32,"tag":448,"props":2844,"children":2845},{},[2846],{"type":37,"value":2847},"⏹️ Website runs on HTTPS",{"type":32,"tag":448,"props":2849,"children":2850},{},[2851],{"type":37,"value":2852},"⏹️ Form data is transmitted encrypted",{"type":32,"tag":448,"props":2854,"children":2855},{},[2856],{"type":37,"value":2857},"⏹️ Access to personal data is restricted to authorized persons",{"type":32,"tag":448,"props":2859,"children":2860},{},[2861],{"type":37,"value":2862},"⏹️ A procedure exists for data breaches",{"type":32,"tag":57,"props":2864,"children":2865},{},[],{"type":32,"tag":39,"props":2867,"children":2868},{"id":774},[2869],{"type":37,"value":777},{"type":32,"tag":46,"props":2871,"children":2872},{},[2873],{"type":37,"value":2874},"GDPR isn't a bogeyman - it's a set of rules that protect people's personal data on the internet. For most regular websites, compliance is a matter of a few hours of work - a properly configured cookie banner, up-to-date privacy policy, secured forms, and order in your analytics tools.",{"type":32,"tag":46,"props":2876,"children":2877},{},[2878],{"type":37,"value":2879},"The data protection authority is checking more and more, and fines are growing. Plus - properly implemented GDPR builds trust with your customers. People notice whether you handle their data responsibly.",{"type":32,"tag":46,"props":2881,"children":2882},{},[2883],{"type":37,"value":2884},"If you're unsure, start with the checklist above. Go through your website point by point and fix what you find. And if you're dealing with more complex cases (e-shop with international customers, processing sensitive data), I recommend consulting a lawyer who specializes in GDPR.",{"type":32,"tag":57,"props":2886,"children":2887},{},[],{"type":32,"tag":39,"props":2889,"children":2890},{"id":798},[2891],{"type":37,"value":801},{"type":32,"tag":444,"props":2893,"children":2894},{},[2895,2907,2919,2930,2942,2954],{"type":32,"tag":448,"props":2896,"children":2897},{},[2898,2905],{"type":32,"tag":139,"props":2899,"children":2902},{"href":2900,":target":345,"rel":2901},"https://www.uoou.cz/",[347],[2903],{"type":37,"value":2904},"Czech Data Protection Authority (ÚOOÚ)",{"type":37,"value":2906}," - Czech supervisory authority with guides and decisions",{"type":32,"tag":448,"props":2908,"children":2909},{},[2910,2917],{"type":32,"tag":139,"props":2911,"children":2914},{"href":2912,":target":345,"rel":2913},"https://www.gdpr.cz/",[347],[2915],{"type":37,"value":2916},"GDPR.cz",{"type":37,"value":2918}," - Czech portal with practical GDPR information",{"type":32,"tag":448,"props":2920,"children":2921},{},[2922,2928],{"type":32,"tag":139,"props":2923,"children":2925},{"href":2491,":target":345,"rel":2924},[347],[2926],{"type":37,"value":2927},"Plausible Analytics",{"type":37,"value":2929}," - GDPR-friendly alternative to Google Analytics",{"type":32,"tag":448,"props":2931,"children":2932},{},[2933,2940],{"type":32,"tag":139,"props":2934,"children":2937},{"href":2935,":target":345,"rel":2936},"https://www.cookiebot.com/",[347],[2938],{"type":37,"value":2939},"Cookiebot",{"type":37,"value":2941}," - cookie consent management tool",{"type":32,"tag":448,"props":2943,"children":2944},{},[2945,2952],{"type":32,"tag":139,"props":2946,"children":2949},{"href":2947,":target":345,"rel":2948},"https://support.google.com/analytics/answer/3379636",[347],[2950],{"type":37,"value":2951},"Google Analytics Data Processing Agreement",{"type":37,"value":2953}," - set up data processing agreement with Google",{"type":32,"tag":448,"props":2955,"children":2956},{},[2957,2964],{"type":32,"tag":139,"props":2958,"children":2961},{"href":2959,":target":345,"rel":2960},"https://www.uoou.cz/vzorove-dokumenty/ds-5765",[347],[2962],{"type":37,"value":2963},"ÚOOÚ Privacy Policy Templates",{"type":37,"value":2965}," - template documents from the Czech DPA",{"title":8,"searchDepth":862,"depth":862,"links":2967},[2968,2969,2970,2973,2976,2979,2982,2983,2984,2985,2986],{"id":41,"depth":862,"text":44},{"id":1837,"depth":862,"text":1840},{"id":1940,"depth":862,"text":1943,"children":2971},[2972],{"id":2027,"depth":871,"text":2030},{"id":2077,"depth":862,"text":2080,"children":2974},[2975],{"id":2148,"depth":871,"text":2151},{"id":2168,"depth":862,"text":2171,"children":2977},[2978],{"id":2296,"depth":871,"text":2299},{"id":2310,"depth":862,"text":2313,"children":2980},[2981],{"id":2364,"depth":871,"text":2030},{"id":2407,"depth":862,"text":2410},{"id":2544,"depth":862,"text":2547},{"id":2684,"depth":862,"text":2687},{"id":774,"depth":862,"text":777},{"id":798,"depth":862,"text":801},"content:knowledge:gdpr-on-website-what-you-must-comply.md","knowledge/gdpr-on-website-what-you-must-comply.md",{"_path":2990,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":2991,"description":2992,"author":11,"date":2993,"readingTime":1799,"level":14,"image":2994,"tags":2995,"slugs":2996,"relatedArticles":2998,"body":3002,"_type":881,"_id":3827,"_source":883,"_file":3828,"_extension":885},"/knowledge/how-to-choose-web-developer","How to Choose a Web Developer - A Practical Guide","What to look for when hiring a developer or agency for your website. Red flags, questions to ask, and how to spot quality work.","2026-02-17","/featured/how-to-choose-web-developer.jpg",[20,895,893],{"en":27,"cs":2997},"jak-vybrat-weboveho-vyvojare",[2999,3000,3001],"will-ai-replace-web-developers","7-most-common-web-developer-mistakes","coder-vs-graphic-designer-how-to-prepare-design-and-deliver-good-quality-results",{"type":29,"children":3003,"toc":3811},[3004,3009,3013,3018,3023,3029,3034,3087,3097,3103,3108,3113,3125,3148,3153,3175,3181,3186,3245,3251,3256,3375,3380,3386,3391,3403,3441,3486,3492,3497,3502,3514,3571,3610,3615,3620,3632,3638,3643,3656,3666,3687,3692,3696,3701,3706,3739,3744,3747,3751],{"type":32,"tag":33,"props":3005,"children":3007},{"id":3006},"how-to-choose-a-web-developer-a-practical-guide",[3008],{"type":37,"value":2991},{"type":32,"tag":39,"props":3010,"children":3011},{"id":41},[3012],{"type":37,"value":44},{"type":32,"tag":46,"props":3014,"children":3015},{},[3016],{"type":37,"value":3017},"You need a new website or a redesign of your current one. You open Google, type \"web development services\" and suddenly face hundreds of offers. Freelancers, agencies, students, a friend of a friend who \"builds websites\". How do you choose? And more importantly - how do you avoid redoing everything from scratch a few months later?",{"type":32,"tag":46,"props":3019,"children":3020},{},[3021],{"type":37,"value":3022},"This article is for you if you're not a developer but need to hire one. We'll cover specific things to look for, questions to ask, and warning signs to watch out for.",{"type":32,"tag":39,"props":3024,"children":3026},{"id":3025},"freelancer-vs-agency-when-to-pick-which",[3027],{"type":37,"value":3028},"👤 Freelancer vs Agency - When to Pick Which",{"type":32,"tag":46,"props":3030,"children":3031},{},[3032],{"type":37,"value":3033},"This is the first decision you'll have to make. Both options have their pros and cons, and the right choice depends mainly on the project scope and your budget.",{"type":32,"tag":153,"props":3035,"children":3036},{},[3037,3065],{"type":32,"tag":157,"props":3038,"children":3039},{},[3040,3046],{"type":32,"tag":169,"props":3041,"children":3043},{"id":3042},"freelancer",[3044],{"type":37,"value":3045},"🧑‍💻 Freelancer",{"type":32,"tag":46,"props":3047,"children":3048},{},[3049,3051,3056,3058,3063],{"type":37,"value":3050},"A good fit when you have a clearly defined small to mid-size project. Typically a business website, an e-shop with a few dozen products, or a simple web app. ",{"type":32,"tag":82,"props":3052,"children":3053},{},[3054],{"type":37,"value":3055},"Pros",{"type":37,"value":3057}," - lower cost, direct communication with no middlemen, often faster response times. ",{"type":32,"tag":82,"props":3059,"children":3060},{},[3061],{"type":37,"value":3062},"Downside",{"type":37,"value":3064}," - one person has limited capacity. If they get sick or go on vacation, your project stops.",{"type":32,"tag":157,"props":3066,"children":3067},{},[3068,3074],{"type":32,"tag":169,"props":3069,"children":3071},{"id":3070},"agency",[3072],{"type":37,"value":3073},"🏢 Agency",{"type":32,"tag":46,"props":3075,"children":3076},{},[3077,3079,3085],{"type":37,"value":3078},"Makes sense for larger projects where you need multiple specializations at once - graphics, ",{"type":32,"tag":139,"props":3080,"children":3082},{"href":3081},"/knowledge/coder-vs-graphic-designer-how-to-prepare-design-and-deliver-good-quality-results",[3083],{"type":37,"value":3084},"UX design",{"type":37,"value":3086},", development, copywriting, SEO. A team means one person's absence won't halt the work. On the other hand, you're also paying for the agency's overhead, and communication often goes through a project manager, which can slow things down.",{"type":32,"tag":46,"props":3088,"children":3089},{},[3090,3095],{"type":32,"tag":82,"props":3091,"children":3092},{},[3093],{"type":37,"value":3094},"Practical tip:",{"type":37,"value":3096}," if your budget is under 100-150 thousand CZK (roughly 4-6k EUR), a quality freelancer will probably give you better value for money. Above that, it starts making sense to consider an agency, especially for capacity and project complexity.",{"type":32,"tag":39,"props":3098,"children":3100},{"id":3099},"how-to-verify-portfolio-and-references",[3101],{"type":37,"value":3102},"🔍 How to Verify Portfolio and References",{"type":32,"tag":46,"props":3104,"children":3105},{},[3106],{"type":37,"value":3107},"The portfolio is the first thing you'll look at. But be careful - pretty pictures in a portfolio don't necessarily mean quality work. You need to dig deeper.",{"type":32,"tag":46,"props":3109,"children":3110},{},[3111],{"type":37,"value":3112},"First, check the portfolio websites directly in your browser. Are they fast? Do they look good on mobile? Try basic scenarios - find the contact page, add a product to cart, submit a form. If the websites in the portfolio don't work well, don't expect yours to be different.",{"type":32,"tag":46,"props":3114,"children":3115},{},[3116,3118,3123],{"type":37,"value":3117},"Next step: ",{"type":32,"tag":82,"props":3119,"children":3120},{},[3121],{"type":37,"value":3122},"references from real clients",{"type":37,"value":3124},". Don't be afraid to ask for contact details of 2-3 previous clients and actually call them. Ask about:",{"type":32,"tag":444,"props":3126,"children":3127},{},[3128,3133,3138,3143],{"type":32,"tag":448,"props":3129,"children":3130},{},[3131],{"type":37,"value":3132},"Did the developer meet deadlines?",{"type":32,"tag":448,"props":3134,"children":3135},{},[3136],{"type":37,"value":3137},"How did they handle feedback?",{"type":32,"tag":448,"props":3139,"children":3140},{},[3141],{"type":37,"value":3142},"Were there hidden costs?",{"type":32,"tag":448,"props":3144,"children":3145},{},[3146],{"type":37,"value":3147},"How does post-launch support work?",{"type":32,"tag":46,"props":3149,"children":3150},{},[3151],{"type":37,"value":3152},"The answers to these questions will tell you way more than any portfolio ever could.",{"type":32,"tag":157,"props":3154,"children":3155},{},[3156,3162],{"type":32,"tag":169,"props":3157,"children":3159},{"id":3158},"️-watch-out-for-portfolio-age",[3160],{"type":37,"value":3161},"⚠️ Watch Out for Portfolio Age",{"type":32,"tag":46,"props":3163,"children":3164},{},[3165,3167,3173],{"type":37,"value":3166},"If all the websites in the portfolio are older than 2-3 years, it might mean the developer isn't keeping up with current technologies. Web development moves fast and what was standard five years ago might not cut it today. If you're curious about ",{"type":32,"tag":139,"props":3168,"children":3170},{"href":3169},"/knowledge/7-most-common-web-developer-mistakes",[3171],{"type":37,"value":3172},"common developer mistakes",{"type":37,"value":3174},", I have a separate article on that.",{"type":32,"tag":39,"props":3176,"children":3178},{"id":3177},"red-flags-what-to-watch-out-for",[3179],{"type":37,"value":3180},"🚩 Red Flags - What to Watch Out For",{"type":32,"tag":46,"props":3182,"children":3183},{},[3184],{"type":37,"value":3185},"Some signals should immediately raise concerns. They don't automatically mean the developer is bad, but they definitely deserve a closer look.",{"type":32,"tag":153,"props":3187,"children":3188},{},[3189,3203,3217,3231],{"type":32,"tag":157,"props":3190,"children":3191},{},[3192,3198],{"type":32,"tag":169,"props":3193,"children":3195},{"id":3194},"we-can-do-anything",[3196],{"type":37,"value":3197},"🌀 \"We Can Do Anything\"",{"type":32,"tag":46,"props":3199,"children":3200},{},[3201],{"type":37,"value":3202},"If a developer or agency claims they can handle absolutely everything, they probably can't do anything really well. Quality professionals know their strengths and have no problem saying something isn't their specialty.",{"type":32,"tag":157,"props":3204,"children":3205},{},[3206,3212],{"type":32,"tag":169,"props":3207,"children":3209},{"id":3208},"no-contract-or-a-vague-one",[3210],{"type":37,"value":3211},"📄 No Contract or a Vague One",{"type":32,"tag":46,"props":3213,"children":3214},{},[3215],{"type":37,"value":3216},"If someone suggests working together without a written contract, run. The contract should clearly define scope of work, timeline, price, and conditions for changes.",{"type":32,"tag":157,"props":3218,"children":3219},{},[3220,3226],{"type":32,"tag":169,"props":3221,"children":3223},{"id":3222},"unrealistically-low-price",[3224],{"type":37,"value":3225},"💸 Unrealistically Low Price",{"type":32,"tag":46,"props":3227,"children":3228},{},[3229],{"type":37,"value":3230},"When you get five quotes and one is three times cheaper than the rest, something's off. Either the developer underestimated the scope, or they're planning to cut corners.",{"type":32,"tag":157,"props":3232,"children":3233},{},[3234,3240],{"type":32,"tag":169,"props":3235,"children":3237},{"id":3236},"slow-responses-from-the-start",[3238],{"type":37,"value":3239},"🐌 Slow Responses From the Start",{"type":32,"tag":46,"props":3241,"children":3242},{},[3243],{"type":37,"value":3244},"If the developer takes three days to reply to emails before you've even signed a contract, imagine what it'll be like mid-project when they already have your money. Communication is everything, and a problematic approach doesn't improve over time.",{"type":32,"tag":39,"props":3246,"children":3248},{"id":3247},"key-questions-before-signing-a-contract",[3249],{"type":37,"value":3250},"❓ Key Questions Before Signing a Contract",{"type":32,"tag":46,"props":3252,"children":3253},{},[3254],{"type":37,"value":3255},"The right questions upfront will protect you from problems later on.",{"type":32,"tag":153,"props":3257,"children":3258},{},[3259,3296,3339],{"type":32,"tag":157,"props":3260,"children":3261},{},[3262,3267,3273],{"type":32,"tag":161,"props":3263,"children":3266},{"src":3264,"width":3265,"style":166},"/article/how-to-choose-web-developer/process.svg",80,[],{"type":32,"tag":169,"props":3268,"children":3270},{"id":3269},"process-and-timelines",[3271],{"type":37,"value":3272},"Process and Timelines",{"type":32,"tag":444,"props":3274,"children":3275},{},[3276,3281,3286,3291],{"type":32,"tag":448,"props":3277,"children":3278},{},[3279],{"type":37,"value":3280},"What does the typical workflow look like from brief to launch?",{"type":32,"tag":448,"props":3282,"children":3283},{},[3284],{"type":37,"value":3285},"What are the project milestones and when can I expect first results?",{"type":32,"tag":448,"props":3287,"children":3288},{},[3289],{"type":37,"value":3290},"What happens if the project gets delayed? Who's responsible?",{"type":32,"tag":448,"props":3292,"children":3293},{},[3294],{"type":37,"value":3295},"How many rounds of revisions are included?",{"type":32,"tag":157,"props":3297,"children":3298},{},[3299,3303,3309],{"type":32,"tag":161,"props":3300,"children":3302},{"src":3301,"width":3265,"style":166},"/article/how-to-choose-web-developer/ownership.svg",[],{"type":32,"tag":169,"props":3304,"children":3306},{"id":3305},"ownership-and-technical-aspects",[3307],{"type":37,"value":3308},"Ownership and Technical Aspects",{"type":32,"tag":444,"props":3310,"children":3311},{},[3312,3317,3329,3334],{"type":32,"tag":448,"props":3313,"children":3314},{},[3315],{"type":37,"value":3316},"Will I own the source code and all website content?",{"type":32,"tag":448,"props":3318,"children":3319},{},[3320,3322,3327],{"type":37,"value":3321},"What ",{"type":32,"tag":139,"props":3323,"children":3324},{"href":2654},[3325],{"type":37,"value":3326},"hosting",{"type":37,"value":3328}," will the site run on?",{"type":32,"tag":448,"props":3330,"children":3331},{},[3332],{"type":37,"value":3333},"Can I switch to a different developer if needed?",{"type":32,"tag":448,"props":3335,"children":3336},{},[3337],{"type":37,"value":3338},"How are backups and security handled?",{"type":32,"tag":157,"props":3340,"children":3341},{},[3342,3346,3352],{"type":32,"tag":161,"props":3343,"children":3345},{"src":3344,"width":3265,"style":166},"/article/how-to-choose-web-developer/price.svg",[],{"type":32,"tag":169,"props":3347,"children":3349},{"id":3348},"pricing-and-payments",[3350],{"type":37,"value":3351},"Pricing and Payments",{"type":32,"tag":444,"props":3353,"children":3354},{},[3355,3360,3365,3370],{"type":32,"tag":448,"props":3356,"children":3357},{},[3358],{"type":37,"value":3359},"Is the price final, or can it change?",{"type":32,"tag":448,"props":3361,"children":3362},{},[3363],{"type":37,"value":3364},"What's the payment schedule? How much upfront?",{"type":32,"tag":448,"props":3366,"children":3367},{},[3368],{"type":37,"value":3369},"What's included in the price and what's billed separately?",{"type":32,"tag":448,"props":3371,"children":3372},{},[3373],{"type":37,"value":3374},"What's the cost for maintenance after launch?",{"type":32,"tag":46,"props":3376,"children":3377},{},[3378],{"type":37,"value":3379},"If the developer can't clearly answer any of these questions, take it as a warning sign. A professional should have ready answers for these - they deal with them on every project.",{"type":32,"tag":39,"props":3381,"children":3383},{"id":3382},"️-technology-stack-what-to-ask-even-if-you-dont-understand-it",[3384],{"type":37,"value":3385},"⚙️ Technology Stack - What to Ask Even If You Don't Understand It",{"type":32,"tag":46,"props":3387,"children":3388},{},[3389],{"type":37,"value":3390},"You don't need to understand code, but you should know what your website will run on. The technology your developer chooses affects site speed, maintenance costs, and how easily you can find a different developer in the future.",{"type":32,"tag":46,"props":3392,"children":3393},{},[3394,3396,3401],{"type":37,"value":3395},"The key question is: ",{"type":32,"tag":82,"props":3397,"children":3398},{},[3399],{"type":37,"value":3400},"why did you choose this specific technology for my project?",{"type":37,"value":3402}," A good developer will explain the reasons clearly, without technical jargon. A bad one will say \"because it's the best\" with no further explanation - or just use whatever they know, regardless of your needs.",{"type":32,"tag":46,"props":3404,"children":3405},{},[3406,3408,3415,3416,3423,3424,3431,3432,3439],{"type":37,"value":3407},"Ask whether the site will be built on a widely-used framework or content management system (CMS). ",{"type":32,"tag":139,"props":3409,"children":3412},{"href":3410,":target":345,"rel":3411,":rel":347},"https://wordpress.org/",[347],[3413],{"type":37,"value":3414},"WordPress",{"type":37,"value":2497},{"type":32,"tag":139,"props":3417,"children":3420},{"href":3418,":target":345,"rel":3419,":rel":347},"https://www.shopify.com/",[347],[3421],{"type":37,"value":3422},"Shopify",{"type":37,"value":2497},{"type":32,"tag":139,"props":3425,"children":3428},{"href":3426,":target":345,"rel":3427,":rel":347},"https://nuxt.com/",[347],[3429],{"type":37,"value":3430},"Nuxt",{"type":37,"value":2497},{"type":32,"tag":139,"props":3433,"children":3436},{"href":3434,":target":345,"rel":3435,":rel":347},"https://nextjs.org/",[347],[3437],{"type":37,"value":3438},"Next.js",{"type":37,"value":3440}," - these are examples of technologies where you'll find plenty of other developers if you ever need to switch. If the developer builds on their own proprietary system that nobody else knows, you're essentially locked in. That's not always bad, but you should know about it upfront.",{"type":32,"tag":153,"props":3442,"children":3443},{},[3444,3466],{"type":32,"tag":157,"props":3445,"children":3446},{},[3447,3453],{"type":32,"tag":169,"props":3448,"children":3450},{"id":3449},"site-speed",[3451],{"type":37,"value":3452},"🚀 Site Speed",{"type":32,"tag":46,"props":3454,"children":3455},{},[3456,3458,3464],{"type":37,"value":3457},"Ask what score they expect in ",{"type":32,"tag":139,"props":3459,"children":3461},{"href":1499,":target":345,"rel":3460,":rel":347},[347],[3462],{"type":37,"value":3463},"Google PageSpeed Insights",{"type":37,"value":3465},". If the developer doesn't know what that is, or says speed \"isn't that important\", look elsewhere. Speed directly affects search rankings and visitor satisfaction.",{"type":32,"tag":157,"props":3467,"children":3468},{},[3469,3475],{"type":32,"tag":169,"props":3470,"children":3472},{"id":3471},"responsive-design",[3473],{"type":37,"value":3474},"📱 Responsive Design",{"type":32,"tag":46,"props":3476,"children":3477},{},[3478,3480,3484],{"type":37,"value":3479},"How will the site look on mobile and tablet? In 2026, most visitors come from mobile devices. A website that doesn't work well on mobile is like a store with locked doors for half your customers. Don't forget about ",{"type":32,"tag":139,"props":3481,"children":3482},{"href":2279},[3483],{"type":37,"value":2282},{"type":37,"value":3485}," either.",{"type":32,"tag":39,"props":3487,"children":3489},{"id":3488},"communication-and-process-what-to-expect-during-collaboration",[3490],{"type":37,"value":3491},"💬 Communication and Process - What to Expect During Collaboration",{"type":32,"tag":46,"props":3493,"children":3494},{},[3495],{"type":37,"value":3496},"Communication quality is often more important than technical skills. A brilliant programmer you can't communicate with won't help you.",{"type":32,"tag":46,"props":3498,"children":3499},{},[3500],{"type":37,"value":3501},"At the start of the collaboration, agree on a few basics - how often you'll get project updates, which channel you'll use (email, Slack, phone), and who your point of contact is. This seems obvious, but it's surprisingly often overlooked.",{"type":32,"tag":46,"props":3503,"children":3504},{},[3505,3507,3512],{"type":37,"value":3506},"The ",{"type":32,"tag":82,"props":3508,"children":3509},{},[3510],{"type":37,"value":3511},"approval process",{"type":37,"value":3513}," should be clearly defined:",{"type":32,"tag":153,"props":3515,"children":3516},{},[3517,3535,3553],{"type":32,"tag":157,"props":3518,"children":3519},{},[3520,3524,3530],{"type":32,"tag":161,"props":3521,"children":3523},{"src":3522,"width":3265,"style":166},"/article/how-to-choose-web-developer/wireframe.svg",[],{"type":32,"tag":169,"props":3525,"children":3527},{"id":3526},"wireframe",[3528],{"type":37,"value":3529},"Wireframe",{"type":32,"tag":46,"props":3531,"children":3532},{},[3533],{"type":37,"value":3534},"Basic page layouts and navigation. This is about structure, not colors.",{"type":32,"tag":157,"props":3536,"children":3537},{},[3538,3542,3548],{"type":32,"tag":161,"props":3539,"children":3541},{"src":3540,"width":3265,"style":166},"/article/how-to-choose-web-developer/design.svg",[],{"type":32,"tag":169,"props":3543,"children":3545},{"id":3544},"visual-design",[3546],{"type":37,"value":3547},"Visual Design",{"type":32,"tag":46,"props":3549,"children":3550},{},[3551],{"type":37,"value":3552},"The visual look of the website. Design should be finalized at this stage before coding begins.",{"type":32,"tag":157,"props":3554,"children":3555},{},[3556,3560,3566],{"type":32,"tag":161,"props":3557,"children":3559},{"src":3558,"width":3265,"style":166},"/article/how-to-choose-web-developer/code.svg",[],{"type":32,"tag":169,"props":3561,"children":3563},{"id":3562},"development",[3564],{"type":37,"value":3565},"Development",{"type":32,"tag":46,"props":3567,"children":3568},{},[3569],{"type":37,"value":3570},"The developer turns designs into a working website. Regular previews are standard.",{"type":32,"tag":153,"props":3572,"children":3573},{},[3574,3592],{"type":32,"tag":157,"props":3575,"children":3576},{},[3577,3581,3587],{"type":32,"tag":161,"props":3578,"children":3580},{"src":3579,"width":3265,"style":166},"/article/how-to-choose-web-developer/testing.svg",[],{"type":32,"tag":169,"props":3582,"children":3584},{"id":3583},"testing",[3585],{"type":37,"value":3586},"Testing",{"type":32,"tag":46,"props":3588,"children":3589},{},[3590],{"type":37,"value":3591},"Checking across different devices and browsers, fixing bugs.",{"type":32,"tag":157,"props":3593,"children":3594},{},[3595,3599,3605],{"type":32,"tag":161,"props":3596,"children":3598},{"src":3597,"width":3265,"style":166},"/article/how-to-choose-web-developer/launch.svg",[],{"type":32,"tag":169,"props":3600,"children":3602},{"id":3601},"launch",[3603],{"type":37,"value":3604},"Launch",{"type":32,"tag":46,"props":3606,"children":3607},{},[3608],{"type":37,"value":3609},"The site goes live. This should be followed by a support and maintenance phase.",{"type":32,"tag":46,"props":3611,"children":3612},{},[3613],{"type":37,"value":3614},"At each stage, you should be able to see the project and provide feedback. If the developer says \"you'll see it when it's done\", that's a problem. The later in the process a requirement error is discovered, the more expensive it is to fix.",{"type":32,"tag":46,"props":3616,"children":3617},{},[3618],{"type":37,"value":3619},"A good developer will ask you questions. Lots of them. They'll want to know who your customers are, what they should do on the site, what problems you're solving. If a developer accepts the brief without a single question and promises it'll \"be great\", be cautious.",{"type":32,"tag":46,"props":3621,"children":3622},{},[3623,3625,3630],{"type":37,"value":3624},"Also agree on how you'll handle ",{"type":32,"tag":82,"props":3626,"children":3627},{},[3628],{"type":37,"value":3629},"changes during the project",{"type":37,"value":3631},". They will happen - that's perfectly normal. What matters is having a clear process: what counts as a minor tweak within the project scope and what's a change that requires additional payment and a timeline extension.",{"type":32,"tag":39,"props":3633,"children":3635},{"id":3634},"price-vs-value-why-the-cheapest-option-isnt-the-best",[3636],{"type":37,"value":3637},"💶 Price vs Value - Why the Cheapest Option Isn't the Best",{"type":32,"tag":46,"props":3639,"children":3640},{},[3641],{"type":37,"value":3642},"Price obviously matters. But it's just one number among many you should consider.",{"type":32,"tag":46,"props":3644,"children":3645},{},[3646,3648,3654],{"type":37,"value":3647},"Imagine two offers. One for 30 thousand CZK, another for 80 thousand. At first glance, the choice is obvious. But what if the cheaper one doesn't include responsive design, ",{"type":32,"tag":139,"props":3649,"children":3652},{"href":3650,":target":345,"rel":3651,":rel":347},"https://developers.google.com/search/docs/fundamentals/seo-starter-guide",[347],[3653],{"type":37,"value":423},{"type":37,"value":3655}," optimization, analytics integration, or any post-launch support? And what if the 30k website is so slow that visitors leave before they can do anything?",{"type":32,"tag":46,"props":3657,"children":3658},{},[3659,3664],{"type":32,"tag":82,"props":3660,"children":3661},{},[3662],{"type":37,"value":3663},"Ask what exactly is included in the price.",{"type":37,"value":3665}," A quality offer should contain a detailed breakdown - how many hours are planned for design, for development, for testing. If you just get one lump sum with no breakdown, you have no way to judge whether the price is fair.",{"type":32,"tag":157,"props":3667,"children":3668},{},[3669,3675],{"type":32,"tag":169,"props":3670,"children":3672},{"id":3671},"tip-compare-offers",[3673],{"type":37,"value":3674},"💡 Tip: Compare Offers",{"type":32,"tag":46,"props":3676,"children":3677},{},[3678,3680,3685],{"type":37,"value":3679},"A good benchmark is to compare at least ",{"type":32,"tag":82,"props":3681,"children":3682},{},[3683],{"type":37,"value":3684},"3-4 offers",{"type":37,"value":3686}," from different developers. Not to pick the cheapest one, but to understand the realistic price for what you need. If three offers are around 70-90 thousand and one is 25 thousand, the cheap one is probably skipping something.",{"type":32,"tag":46,"props":3688,"children":3689},{},[3690],{"type":37,"value":3691},"Think of your website as an investment, not an expense. How many new customers will a quality website bring you per year? How much money will you save by not having to redo the site in two years? A cheap website that doesn't work is ultimately more expensive than a quality one that generates revenue.",{"type":32,"tag":39,"props":3693,"children":3694},{"id":774},[3695],{"type":37,"value":777},{"type":32,"tag":46,"props":3697,"children":3698},{},[3699],{"type":37,"value":3700},"Choosing a web developer is a decision that will affect your business for years to come. Don't rely solely on a nice portfolio or a low price.",{"type":32,"tag":46,"props":3702,"children":3703},{},[3704],{"type":37,"value":3705},"Key takeaways:",{"type":32,"tag":444,"props":3707,"children":3708},{},[3709,3714,3719,3724,3729,3734],{"type":32,"tag":448,"props":3710,"children":3711},{},[3712],{"type":37,"value":3713},"Start by deciding whether you need a freelancer or an agency",{"type":32,"tag":448,"props":3715,"children":3716},{},[3717],{"type":37,"value":3718},"Verify the portfolio and check references with actual clients",{"type":32,"tag":448,"props":3720,"children":3721},{},[3722],{"type":37,"value":3723},"Watch out for prices that are too low and promises that are too big",{"type":32,"tag":448,"props":3725,"children":3726},{},[3727],{"type":37,"value":3728},"Insist on a contract with specific milestones and deadlines",{"type":32,"tag":448,"props":3730,"children":3731},{},[3732],{"type":37,"value":3733},"Ask about technology, speed, and mobile responsiveness",{"type":32,"tag":448,"props":3735,"children":3736},{},[3737],{"type":37,"value":3738},"Set up communication rules and an approval process",{"type":32,"tag":46,"props":3740,"children":3741},{},[3742],{"type":37,"value":3743},"One last thing - trust your gut. If something feels off before the collaboration even starts, it'll probably get worse when things get tough. Better to invest time finding the right developer now than paying for a rebuild in a year.",{"type":32,"tag":57,"props":3745,"children":3746},{},[],{"type":32,"tag":39,"props":3748,"children":3749},{"id":798},[3750],{"type":37,"value":801},{"type":32,"tag":444,"props":3752,"children":3753},{},[3754,3764,3776,3788,3799],{"type":32,"tag":448,"props":3755,"children":3756},{},[3757,3762],{"type":32,"tag":139,"props":3758,"children":3760},{"href":1499,":target":345,"rel":3759},[347],[3761],{"type":37,"value":3463},{"type":37,"value":3763}," - free tool for measuring website speed",{"type":32,"tag":448,"props":3765,"children":3766},{},[3767,3774],{"type":32,"tag":139,"props":3768,"children":3771},{"href":3769,":target":345,"rel":3770},"https://clutch.co/",[347],[3772],{"type":37,"value":3773},"Clutch.co",{"type":37,"value":3775}," - reviews and ratings of agencies and freelancers worldwide",{"type":32,"tag":448,"props":3777,"children":3778},{},[3779,3786],{"type":32,"tag":139,"props":3780,"children":3783},{"href":3781,":target":345,"rel":3782},"https://webaim.org/resources/contrastchecker/",[347],[3784],{"type":37,"value":3785},"WebAIM Contrast Checker",{"type":37,"value":3787}," - check color contrast for web accessibility",{"type":32,"tag":448,"props":3789,"children":3790},{},[3791,3797],{"type":32,"tag":139,"props":3792,"children":3795},{"href":3793,":target":345,"rel":3794},"https://search.google.com/search-console/about",[347],[3796],{"type":37,"value":359},{"type":37,"value":3798}," - monitor your website's visibility in search",{"type":32,"tag":448,"props":3800,"children":3801},{},[3802,3809],{"type":32,"tag":139,"props":3803,"children":3806},{"href":3804,":target":345,"rel":3805},"https://w3techs.com/",[347],[3807],{"type":37,"value":3808},"W3Techs",{"type":37,"value":3810}," - statistics on web technologies and CMS market share",{"title":8,"searchDepth":862,"depth":862,"links":3812},[3813,3814,3815,3818,3819,3820,3821,3822,3825,3826],{"id":41,"depth":862,"text":44},{"id":3025,"depth":862,"text":3028},{"id":3099,"depth":862,"text":3102,"children":3816},[3817],{"id":3158,"depth":871,"text":3161},{"id":3177,"depth":862,"text":3180},{"id":3247,"depth":862,"text":3250},{"id":3382,"depth":862,"text":3385},{"id":3488,"depth":862,"text":3491},{"id":3634,"depth":862,"text":3637,"children":3823},[3824],{"id":3671,"depth":871,"text":3674},{"id":774,"depth":862,"text":777},{"id":798,"depth":862,"text":801},"content:knowledge:how-to-choose-web-developer.md","knowledge/how-to-choose-web-developer.md",{"_path":648,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":3830,"description":3831,"author":11,"date":3832,"readingTime":3833,"level":14,"image":3834,"tags":3835,"slugs":3836,"relatedArticles":3838,"body":3839,"_type":881,"_id":4894,"_source":883,"_file":4895,"_extension":885},"What Should a Business Website Contain in 2026","Complete checklist of elements every business website needs. From contact details to SEO and legal requirements.","2026-02-05",8,"/featured/what-should-business-website-contain.jpg",[893,20,895],{"en":25,"cs":3837},"co-ma-obsahovat-firemni-web",[26,27,900],{"type":29,"children":3840,"toc":4872},[3841,3846,3850,3855,3860,3863,3869,3874,3893,3910,3926,3974,3977,3980,3986,3991,4001,4022,4034,4081,4084,4090,4102,4107,4126,4138,4195,4198,4204,4216,4228,4246,4258,4295,4298,4304,4309,4327,4337,4349,4352,4365,4382,4393,4417,4433,4498,4501,4507,4512,4599,4689,4692,4698,4703,4778,4781,4785,4790,4801,4806,4809,4813],{"type":32,"tag":33,"props":3842,"children":3844},{"id":3843},"what-should-a-business-website-contain-in-2026",[3845],{"type":37,"value":3830},{"type":32,"tag":39,"props":3847,"children":3848},{"id":41},[3849],{"type":37,"value":44},{"type":32,"tag":46,"props":3851,"children":3852},{},[3853],{"type":37,"value":3854},"Your business website is often the first place a potential customer encounters your company. And you only get one shot at a first impression. Yet I still come across websites where basic contact details are missing, pages take forever to load, or it's simply unclear what the company actually does.",{"type":32,"tag":46,"props":3856,"children":3857},{},[3858],{"type":37,"value":3859},"This is a practical checklist for anyone who runs a business website or is having one built. We'll cover everything from legal requirements through content to the technical minimum. No rocket science - just common sense backed by experience.",{"type":32,"tag":57,"props":3861,"children":3862},{},[],{"type":32,"tag":39,"props":3864,"children":3866},{"id":3865},"️-mandatory-legal-requirements",[3867],{"type":37,"value":3868},"⚖️ Mandatory Legal Requirements",{"type":32,"tag":46,"props":3870,"children":3871},{},[3872],{"type":37,"value":3873},"Let's start with the least exciting topic that can save you a lot of headaches. Laws vary by country, but most jurisdictions require certain information to be displayed on business websites. And fines for non-compliance aren't trivial.",{"type":32,"tag":46,"props":3875,"children":3876},{},[3877,3879,3884,3886,3891],{"type":37,"value":3878},"At minimum, your website should display your ",{"type":32,"tag":82,"props":3880,"children":3881},{},[3882],{"type":37,"value":3883},"business name, registration number, and registered address",{"type":37,"value":3885},". For limited companies, you'll also need your ",{"type":32,"tag":82,"props":3887,"children":3888},{},[3889],{"type":37,"value":3890},"company registration details",{"type":37,"value":3892},". These typically go in the footer or on a dedicated \"Legal Information\" page. Either works, just make sure they're there.",{"type":32,"tag":46,"props":3894,"children":3895},{},[3896,3898,3908],{"type":37,"value":3897},"Then there's ",{"type":32,"tag":82,"props":3899,"children":3900},{},[3901],{"type":32,"tag":139,"props":3902,"children":3903},{"href":1389},[3904],{"type":32,"tag":117,"props":3905,"children":3906},{},[3907],{"type":37,"value":1381},{"type":37,"value":3909}," (or equivalent privacy laws) - if you collect any personal data (and you do, even with just a contact form), you need a privacy policy on your website. Don't just copy a generic text from a competitor. The document should describe what data you collect, why, how long you keep it, and what rights visitors have.",{"type":32,"tag":46,"props":3911,"children":3912},{},[3913,3915,3924],{"type":37,"value":3914},"And finally, the ",{"type":32,"tag":82,"props":3916,"children":3917},{},[3918],{"type":32,"tag":139,"props":3919,"children":3921},{"href":3920},"/knowledge/how-to-set-up-a-cookie-bar-correctly",[3922],{"type":37,"value":3923},"cookie consent banner",{"type":37,"value":3925},". You need active consent from visitors before firing analytical and marketing cookies. Technical cookies (those necessary for the website to function) don't require consent.",{"type":32,"tag":157,"props":3927,"children":3928},{},[3929,3935],{"type":32,"tag":169,"props":3930,"children":3932},{"id":3931},"legal-requirements-checklist",[3933],{"type":37,"value":3934},"✅ Legal Requirements Checklist",{"type":32,"tag":444,"props":3936,"children":3937},{},[3938,3943,3948,3953,3964,3969],{"type":32,"tag":448,"props":3939,"children":3940},{},[3941],{"type":37,"value":3942},"⏹️ Business name and registration number in the footer",{"type":32,"tag":448,"props":3944,"children":3945},{},[3946],{"type":37,"value":3947},"⏹️ Registered address",{"type":32,"tag":448,"props":3949,"children":3950},{},[3951],{"type":37,"value":3952},"⏹️ Company registration details (for corporations)",{"type":32,"tag":448,"props":3954,"children":3955},{},[3956,3958,3962],{"type":37,"value":3957},"⏹️ Privacy policy (",{"type":32,"tag":117,"props":3959,"children":3960},{},[3961],{"type":37,"value":1381},{"type":37,"value":3963}," compliance)",{"type":32,"tag":448,"props":3965,"children":3966},{},[3967],{"type":37,"value":3968},"⏹️ Functional cookie consent banner with opt-out",{"type":32,"tag":448,"props":3970,"children":3971},{},[3972],{"type":37,"value":3973},"⏹️ Terms and conditions (if selling online)",{"type":32,"tag":2069,"props":3975,"children":3976},{"slug":900},[],{"type":32,"tag":57,"props":3978,"children":3979},{},[],{"type":32,"tag":39,"props":3981,"children":3983},{"id":3982},"contact-information-and-map",[3984],{"type":37,"value":3985},"📞 Contact Information and Map",{"type":32,"tag":46,"props":3987,"children":3988},{},[3989],{"type":37,"value":3990},"Sounds obvious, but the number of business websites where it's hard to find a phone number or address is alarming. Contact details are among the most sought-after information on any business website. If visitors can't find them within seconds, they'll go to your competitor.",{"type":32,"tag":46,"props":3992,"children":3993},{},[3994,3999],{"type":32,"tag":82,"props":3995,"children":3996},{},[3997],{"type":37,"value":3998},"Phone and email",{"type":37,"value":4000}," should be visible immediately - ideally in the header or at least in the footer on every page. Especially the phone number. A lot of people (particularly older generations) just want to call and don't want to fill out a form. Don't forget that on mobile, the phone number should be tappable to initiate a call.",{"type":32,"tag":46,"props":4002,"children":4003},{},[4004,4006,4011,4013,4020],{"type":37,"value":4005},"A dedicated ",{"type":32,"tag":82,"props":4007,"children":4008},{},[4009],{"type":37,"value":4010},"contact page",{"type":37,"value":4012}," should include all ways to reach you - phone, email, contact form, address, and a map. If you have a physical location, a map is essential. A ",{"type":32,"tag":139,"props":4014,"children":4017},{"href":4015,":target":345,"rel":4016,":rel":347},"https://www.google.com/maps",[347],[4018],{"type":37,"value":4019},"Google Maps",{"type":37,"value":4021}," embed is free and takes minutes to implement.",{"type":32,"tag":46,"props":4023,"children":4024},{},[4025,4027,4032],{"type":37,"value":4026},"If your business has ",{"type":32,"tag":82,"props":4028,"children":4029},{},[4030],{"type":37,"value":4031},"opening hours",{"type":37,"value":4033},", display them on the contact page and in the footer. And keep them up to date. Few things are more frustrating than arriving at a closed shop because the website had wrong hours.",{"type":32,"tag":157,"props":4035,"children":4036},{},[4037,4043],{"type":32,"tag":169,"props":4038,"children":4040},{"id":4039},"contact-information-checklist",[4041],{"type":37,"value":4042},"✅ Contact Information Checklist",{"type":32,"tag":444,"props":4044,"children":4045},{},[4046,4051,4056,4061,4066,4071,4076],{"type":32,"tag":448,"props":4047,"children":4048},{},[4049],{"type":37,"value":4050},"⏹️ Phone number in header or footer (tappable on mobile)",{"type":32,"tag":448,"props":4052,"children":4053},{},[4054],{"type":37,"value":4055},"⏹️ Email address",{"type":32,"tag":448,"props":4057,"children":4058},{},[4059],{"type":37,"value":4060},"⏹️ Contact form",{"type":32,"tag":448,"props":4062,"children":4063},{},[4064],{"type":37,"value":4065},"⏹️ Office/business address",{"type":32,"tag":448,"props":4067,"children":4068},{},[4069],{"type":37,"value":4070},"⏹️ Map (Google Maps or equivalent)",{"type":32,"tag":448,"props":4072,"children":4073},{},[4074],{"type":37,"value":4075},"⏹️ Opening hours (if applicable)",{"type":32,"tag":448,"props":4077,"children":4078},{},[4079],{"type":37,"value":4080},"⏹️ Social media links",{"type":32,"tag":57,"props":4082,"children":4083},{},[],{"type":32,"tag":39,"props":4085,"children":4087},{"id":4086},"services-and-products",[4088],{"type":37,"value":4089},"🎯 Services and Products",{"type":32,"tag":46,"props":4091,"children":4092},{},[4093,4095,4100],{"type":37,"value":4094},"This is the core of your entire website. Visitors need to understand within seconds ",{"type":32,"tag":82,"props":4096,"children":4097},{},[4098],{"type":37,"value":4099},"what you do and who you do it for",{"type":37,"value":4101},". You know that feeling when you land on a website and after a minute of scrolling you still have no idea what the company does? That's exactly what you want to avoid.",{"type":32,"tag":46,"props":4103,"children":4104},{},[4105],{"type":37,"value":4106},"Each service or product should have its own page (or at least its own section). That page should clearly state what the service includes, who it's for, and what problem it solves. Avoid corporate jargon and marketing fluff. Write like you'd explain it to a friend over a beer.",{"type":32,"tag":46,"props":4108,"children":4109},{},[4110,4112,4117,4119,4124],{"type":37,"value":4111},"Don't be afraid to list ",{"type":32,"tag":82,"props":4113,"children":4114},{},[4115],{"type":37,"value":4116},"approximate prices",{"type":37,"value":4118},". Many companies hide their pricing because \"it depends on the project.\" If you're curious about ",{"type":32,"tag":139,"props":4120,"children":4121},{"href":141},[4122],{"type":37,"value":4123},"how much a website actually costs",{"type":37,"value":4125},", I have a dedicated article on that. I get it, but customers want at least a ballpark. Write \"from $X\" or \"typical projects range between X and Y.\" You'll save time for both sides - if your price range is out of their budget, you won't waste each other's time on a call.",{"type":32,"tag":46,"props":4127,"children":4128},{},[4129,4131,4136],{"type":37,"value":4130},"If you offer multiple services, put an ",{"type":32,"tag":82,"props":4132,"children":4133},{},[4134],{"type":37,"value":4135},"overview with short descriptions",{"type":37,"value":4137}," and links to details on the main page. Visitors should know within 10 seconds of scrolling what you're good at.",{"type":32,"tag":153,"props":4139,"children":4140},{},[4141,4159,4177],{"type":32,"tag":157,"props":4142,"children":4143},{},[4144,4148,4154],{"type":32,"tag":161,"props":4145,"children":4147},{"src":4146,"width":165,"style":166},"/article/what-should-business-website-contain/clear-description.svg",[],{"type":32,"tag":169,"props":4149,"children":4151},{"id":4150},"clear-description",[4152],{"type":37,"value":4153},"📝 Clear Description",{"type":32,"tag":46,"props":4155,"children":4156},{},[4157],{"type":37,"value":4158},"What the service includes, who it's for, and what problem it solves. No jargon.",{"type":32,"tag":157,"props":4160,"children":4161},{},[4162,4166,4172],{"type":32,"tag":161,"props":4163,"children":4165},{"src":4164,"width":165,"style":166},"/article/what-should-business-website-contain/pricing.svg",[],{"type":32,"tag":169,"props":4167,"children":4169},{"id":4168},"approximate-pricing",[4170],{"type":37,"value":4171},"💰 Approximate Pricing",{"type":32,"tag":46,"props":4173,"children":4174},{},[4175],{"type":37,"value":4176},"At least \"from $X\" or a range. Saves time for everyone.",{"type":32,"tag":157,"props":4178,"children":4179},{},[4180,4184,4190],{"type":32,"tag":161,"props":4181,"children":4183},{"src":4182,"width":165,"style":166},"/article/what-should-business-website-contain/visual-overview.svg",[],{"type":32,"tag":169,"props":4185,"children":4187},{"id":4186},"️-visual-overview",[4188],{"type":37,"value":4189},"🖼️ Visual Overview",{"type":32,"tag":46,"props":4191,"children":4192},{},[4193],{"type":37,"value":4194},"Icons, short headings, 1-2 sentences. Details on subpages.",{"type":32,"tag":57,"props":4196,"children":4197},{},[],{"type":32,"tag":39,"props":4199,"children":4201},{"id":4200},"testimonials-and-case-studies",[4202],{"type":37,"value":4203},"⭐ Testimonials and Case Studies",{"type":32,"tag":46,"props":4205,"children":4206},{},[4207,4209,4214],{"type":37,"value":4208},"You can write about how great you are all day, but it's far more convincing when someone else says it. ",{"type":32,"tag":82,"props":4210,"children":4211},{},[4212],{"type":37,"value":4213},"Testimonials and case studies",{"type":37,"value":4215}," are among the strongest trust-building tools on a business website.",{"type":32,"tag":46,"props":4217,"children":4218},{},[4219,4221,4226],{"type":37,"value":4220},"The simplest format is ",{"type":32,"tag":82,"props":4222,"children":4223},{},[4224],{"type":37,"value":4225},"customer quotes",{"type":37,"value":4227}," - a short text, name, company, ideally a photo. The more specific the quote, the better. \"Great collaboration\" convinces nobody. \"Our inquiries went up 40% in the first quarter after the new website\" - that's a different league.",{"type":32,"tag":46,"props":4229,"children":4230},{},[4231,4233,4238,4240,4244],{"type":37,"value":4232},"If you have the capacity, invest time in ",{"type":32,"tag":82,"props":4234,"children":4235},{},[4236],{"type":37,"value":4237},"case studies",{"type":37,"value":4239},". Describe the client's problem, your solution, and the results. It doesn't have to be a novel - a few paragraphs will do. Case studies also work great for ",{"type":32,"tag":117,"props":4241,"children":4242},{},[4243],{"type":37,"value":423},{"type":37,"value":4245}," because they're unique content full of relevant keywords.",{"type":32,"tag":46,"props":4247,"children":4248},{},[4249,4251,4256],{"type":37,"value":4250},"Another option is ",{"type":32,"tag":82,"props":4252,"children":4253},{},[4254],{"type":37,"value":4255},"client logos",{"type":37,"value":4257},". If you've worked with well-known brands, show it. A row of recognizable logos immediately builds credibility. Just make sure you have the client's permission first.",{"type":32,"tag":157,"props":4259,"children":4260},{},[4261,4267],{"type":32,"tag":169,"props":4262,"children":4264},{"id":4263},"testimonials-checklist",[4265],{"type":37,"value":4266},"✅ Testimonials Checklist",{"type":32,"tag":444,"props":4268,"children":4269},{},[4270,4275,4280,4285,4290],{"type":32,"tag":448,"props":4271,"children":4272},{},[4273],{"type":37,"value":4274},"⏹️ At least 3-5 client quotes",{"type":32,"tag":448,"props":4276,"children":4277},{},[4278],{"type":37,"value":4279},"⏹️ Specific results (numbers, percentages)",{"type":32,"tag":448,"props":4281,"children":4282},{},[4283],{"type":37,"value":4284},"⏹️ Name and company for each reference",{"type":32,"tag":448,"props":4286,"children":4287},{},[4288],{"type":37,"value":4289},"⏹️ Case studies (at least 2-3)",{"type":32,"tag":448,"props":4291,"children":4292},{},[4293],{"type":37,"value":4294},"⏹️ Client logos (with permission)",{"type":32,"tag":57,"props":4296,"children":4297},{},[],{"type":32,"tag":39,"props":4299,"children":4301},{"id":4300},"about-us",[4302],{"type":37,"value":4303},"👤 About Us",{"type":32,"tag":46,"props":4305,"children":4306},{},[4307],{"type":37,"value":4308},"The \"About Us\" page is surprisingly one of the most visited pages on business websites. People want to know who they'll be working with. Especially for smaller companies and freelancers, this is often the deciding factor.",{"type":32,"tag":46,"props":4310,"children":4311},{},[4312,4314,4319,4321,4325],{"type":37,"value":4313},"Write about ",{"type":32,"tag":82,"props":4315,"children":4316},{},[4317],{"type":37,"value":4318},"who you are, what drives you, and why you do what you do",{"type":37,"value":4320},". You don't need a biography from kindergarten, but a short story of how you got into the field works brilliantly. People buy from people, not companies. If you're a small business or ",{"type":32,"tag":139,"props":4322,"children":4323},{"href":2990},[4324],{"type":37,"value":3042},{"type":37,"value":4326},", this is your advantage over corporations - use it.",{"type":32,"tag":46,"props":4328,"children":4329},{},[4330,4335],{"type":32,"tag":82,"props":4331,"children":4332},{},[4333],{"type":37,"value":4334},"Team photos",{"type":37,"value":4336}," (or your own, if you're a one-person business) significantly boost credibility. A quality photo doesn't have to come from a professional shoot - a decent portrait with good lighting will do. But definitely not a vacation selfie.",{"type":32,"tag":46,"props":4338,"children":4339},{},[4340,4342,4347],{"type":37,"value":4341},"If you have any ",{"type":32,"tag":82,"props":4343,"children":4344},{},[4345],{"type":37,"value":4346},"certifications, awards, or professional memberships",{"type":37,"value":4348},", list them here. Same goes for years in business, number of completed projects, or other numbers that support your credibility.",{"type":32,"tag":57,"props":4350,"children":4351},{},[],{"type":32,"tag":39,"props":4353,"children":4355},{"id":4354},"calls-to-action-cta",[4356,4358,4363],{"type":37,"value":4357},"🔘 Calls to Action (",{"type":32,"tag":117,"props":4359,"children":4360},{},[4361],{"type":37,"value":4362},"CTA",{"type":37,"value":4364},")",{"type":32,"tag":46,"props":4366,"children":4367},{},[4368,4370,4375,4376,4380],{"type":37,"value":4369},"A website without clear ",{"type":32,"tag":82,"props":4371,"children":4372},{},[4373],{"type":37,"value":4374},"calls to action",{"type":37,"value":1849},{"type":32,"tag":117,"props":4377,"children":4378},{},[4379],{"type":37,"value":4362},{"type":37,"value":4381},") is like a shop without a checkout. Visitors browse what you offer, and then... what? You need to tell them what to do next.",{"type":32,"tag":46,"props":4383,"children":4384},{},[4385,4387,4391],{"type":37,"value":4386},"Every page should have at least one ",{"type":32,"tag":117,"props":4388,"children":4389},{},[4390],{"type":37,"value":4362},{"type":37,"value":4392},". On a services page, it could be \"Get a Free Quote\" or \"Book a Consultation.\" On a blog, \"Read Another Article.\" On the homepage, your most important action - typically contact or inquiry.",{"type":32,"tag":46,"props":4394,"children":4395},{},[4396,4398,4402,4404,4409,4411,4415],{"type":37,"value":4397},"A ",{"type":32,"tag":117,"props":4399,"children":4400},{},[4401],{"type":37,"value":4362},{"type":37,"value":4403}," should be ",{"type":32,"tag":82,"props":4405,"children":4406},{},[4407],{"type":37,"value":4408},"visually prominent",{"type":37,"value":4410}," - a button in a contrasting color, large enough, with clear text. \"Submit\" is a bad ",{"type":32,"tag":117,"props":4412,"children":4413},{},[4414],{"type":37,"value":4362},{"type":37,"value":4416},". \"Get a Free Quote\" is much better - it tells the visitor exactly what happens after clicking.",{"type":32,"tag":46,"props":4418,"children":4419},{},[4420,4422,4431],{"type":37,"value":4421},"Don't overdo it. When there are ten different buttons on a page, visitors won't know where to click and won't click anywhere. Choose ",{"type":32,"tag":82,"props":4423,"children":4424},{},[4425,4427],{"type":37,"value":4426},"one primary ",{"type":32,"tag":117,"props":4428,"children":4429},{},[4430],{"type":37,"value":4362},{"type":37,"value":4432}," per page and optionally one secondary.",{"type":32,"tag":153,"props":4434,"children":4435},{},[4436,4467],{"type":32,"tag":157,"props":4437,"children":4438},{},[4439,4443,4449],{"type":32,"tag":161,"props":4440,"children":4442},{"src":4441,"width":165,"style":166},"/article/what-should-business-website-contain/good-cta.svg",[],{"type":32,"tag":169,"props":4444,"children":4446},{"id":4445},"good-ctas",[4447],{"type":37,"value":4448},"✅ Good CTAs",{"type":32,"tag":444,"props":4450,"children":4451},{},[4452,4457,4462],{"type":32,"tag":448,"props":4453,"children":4454},{},[4455],{"type":37,"value":4456},"\"Get a Free Quote\"",{"type":32,"tag":448,"props":4458,"children":4459},{},[4460],{"type":37,"value":4461},"\"Book a Free Consultation\"",{"type":32,"tag":448,"props":4463,"children":4464},{},[4465],{"type":37,"value":4466},"\"Download Price List\"",{"type":32,"tag":157,"props":4468,"children":4469},{},[4470,4474,4480],{"type":32,"tag":161,"props":4471,"children":4473},{"src":4472,"width":165,"style":166},"/article/what-should-business-website-contain/bad-cta.svg",[],{"type":32,"tag":169,"props":4475,"children":4477},{"id":4476},"bad-ctas",[4478],{"type":37,"value":4479},"❌ Bad CTAs",{"type":32,"tag":444,"props":4481,"children":4482},{},[4483,4488,4493],{"type":32,"tag":448,"props":4484,"children":4485},{},[4486],{"type":37,"value":4487},"\"Submit\"",{"type":32,"tag":448,"props":4489,"children":4490},{},[4491],{"type":37,"value":4492},"\"Click Here\"",{"type":32,"tag":448,"props":4494,"children":4495},{},[4496],{"type":37,"value":4497},"\"More Information\"",{"type":32,"tag":57,"props":4499,"children":4500},{},[],{"type":32,"tag":39,"props":4502,"children":4504},{"id":4503},"️-technical-minimum",[4505],{"type":37,"value":4506},"⚙️ Technical Minimum",{"type":32,"tag":46,"props":4508,"children":4509},{},[4510],{"type":37,"value":4511},"Content is king, but if your website displays poorly on mobile or takes 8 seconds to load, even the best copy won't help.",{"type":32,"tag":153,"props":4513,"children":4514},{},[4515,4531,4556],{"type":32,"tag":157,"props":4516,"children":4517},{},[4518,4522,4526],{"type":32,"tag":161,"props":4519,"children":4521},{"src":4520,"width":165,"style":166},"/article/what-should-business-website-contain/responsive.svg",[],{"type":32,"tag":169,"props":4523,"children":4524},{"id":3471},[4525],{"type":37,"value":3474},{"type":32,"tag":46,"props":4527,"children":4528},{},[4529],{"type":37,"value":4530},"In 2026, over 70% of visitors come from mobile devices. Open your website on your phone and try to find contact info, pricing, and submit an inquiry. Takes more than a minute? You have a problem.",{"type":32,"tag":157,"props":4532,"children":4533},{},[4534,4538,4544],{"type":32,"tag":161,"props":4535,"children":4537},{"src":4536,"width":165,"style":166},"/article/what-should-business-website-contain/speed.svg",[],{"type":32,"tag":169,"props":4539,"children":4541},{"id":4540},"loading-speed",[4542],{"type":37,"value":4543},"⚡ Loading Speed",{"type":32,"tag":46,"props":4545,"children":4546},{},[4547,4549,4554],{"type":37,"value":4548},"Google recommends under 2.5 seconds. Biggest killers - ",{"type":32,"tag":139,"props":4550,"children":4551},{"href":627},[4552],{"type":37,"value":4553},"unoptimized images",{"type":37,"value":4555},", unnecessary plugins, and cheap hosting.",{"type":32,"tag":157,"props":4557,"children":4558},{},[4559,4563,4573],{"type":32,"tag":161,"props":4560,"children":4562},{"src":4561,"width":165,"style":166},"/article/what-should-business-website-contain/seo.svg",[],{"type":32,"tag":169,"props":4564,"children":4566},{"id":4565},"basic-seo",[4567,4569],{"type":37,"value":4568},"🔍 Basic ",{"type":32,"tag":117,"props":4570,"children":4571},{},[4572],{"type":37,"value":423},{"type":32,"tag":46,"props":4574,"children":4575},{},[4576,4578,4583,4585,4590,4592,4597],{"type":37,"value":4577},"Unique title tag and meta description on every page. Alt texts on images. Readable ",{"type":32,"tag":117,"props":4579,"children":4580},{},[4581],{"type":37,"value":4582},"URL",{"type":37,"value":4584}," addresses. ",{"type":32,"tag":117,"props":4586,"children":4587},{},[4588],{"type":37,"value":4589},"SSL",{"type":37,"value":4591}," certificate (",{"type":32,"tag":117,"props":4593,"children":4594},{},[4595],{"type":37,"value":4596},"HTTPS",{"type":37,"value":4598},").",{"type":32,"tag":157,"props":4600,"children":4601},{},[4602,4608],{"type":32,"tag":169,"props":4603,"children":4605},{"id":4604},"technical-minimum-checklist",[4606],{"type":37,"value":4607},"✅ Technical Minimum Checklist",{"type":32,"tag":444,"props":4609,"children":4610},{},[4611,4616,4621,4636,4641,4646,4657,4662,4667,4678],{"type":32,"tag":448,"props":4612,"children":4613},{},[4614],{"type":37,"value":4615},"⏹️ Responsive design (works on mobile)",{"type":32,"tag":448,"props":4617,"children":4618},{},[4619],{"type":37,"value":4620},"⏹️ Loading speed under 3 seconds",{"type":32,"tag":448,"props":4622,"children":4623},{},[4624,4626,4630,4631,4635],{"type":37,"value":4625},"⏹️ ",{"type":32,"tag":117,"props":4627,"children":4628},{},[4629],{"type":37,"value":4589},{"type":37,"value":4591},{"type":32,"tag":117,"props":4632,"children":4633},{},[4634],{"type":37,"value":4596},{"type":37,"value":4364},{"type":32,"tag":448,"props":4637,"children":4638},{},[4639],{"type":37,"value":4640},"⏹️ Unique title tags and meta descriptions",{"type":32,"tag":448,"props":4642,"children":4643},{},[4644],{"type":37,"value":4645},"⏹️ Alt texts on images",{"type":32,"tag":448,"props":4647,"children":4648},{},[4649,4651,4655],{"type":37,"value":4650},"⏹️ Readable ",{"type":32,"tag":117,"props":4652,"children":4653},{},[4654],{"type":37,"value":4582},{"type":37,"value":4656}," addresses",{"type":32,"tag":448,"props":4658,"children":4659},{},[4660],{"type":37,"value":4661},"⏹️ Working forms (tested!)",{"type":32,"tag":448,"props":4663,"children":4664},{},[4665],{"type":37,"value":4666},"⏹️ Website backups",{"type":32,"tag":448,"props":4668,"children":4669},{},[4670,4671,4676],{"type":37,"value":4625},{"type":32,"tag":139,"props":4672,"children":4674},{"href":355,":target":345,"rel":4673,":rel":347},[347],[4675],{"type":37,"value":359},{"type":37,"value":4677}," connected",{"type":32,"tag":448,"props":4679,"children":4680},{},[4681,4682,4687],{"type":37,"value":4625},{"type":32,"tag":139,"props":4683,"children":4685},{"href":1295,":target":345,"rel":4684,":rel":347},[347],[4686],{"type":37,"value":1280},{"type":37,"value":4688}," (for local businesses)",{"type":32,"tag":57,"props":4690,"children":4691},{},[],{"type":32,"tag":39,"props":4693,"children":4695},{"id":4694},"what-your-business-website-doesnt-need",[4696],{"type":37,"value":4697},"🚫 What Your Business Website Doesn't Need",{"type":32,"tag":46,"props":4699,"children":4700},{},[4701],{"type":37,"value":4702},"Knowing what to put on your website is just as important as knowing what to leave out. Many business websites suffer from trying to be everything at once.",{"type":32,"tag":153,"props":4704,"children":4705},{},[4706,4724,4742,4760],{"type":32,"tag":157,"props":4707,"children":4708},{},[4709,4713,4719],{"type":32,"tag":161,"props":4710,"children":4712},{"src":4711,"width":165,"style":166},"/article/what-should-business-website-contain/auto-media.svg",[],{"type":32,"tag":169,"props":4714,"children":4716},{"id":4715},"auto-playing-media",[4717],{"type":37,"value":4718},"🔇 Auto-Playing Media",{"type":32,"tag":46,"props":4720,"children":4721},{},[4722],{"type":37,"value":4723},"Video on a website is fine, but let visitors decide whether to play it. Sound without warning = closed tab.",{"type":32,"tag":157,"props":4725,"children":4726},{},[4727,4731,4737],{"type":32,"tag":161,"props":4728,"children":4730},{"src":4729,"width":165,"style":166},"/article/what-should-business-website-contain/dead-blog.svg",[],{"type":32,"tag":169,"props":4732,"children":4734},{"id":4733},"dead-blog",[4735],{"type":37,"value":4736},"📝 Dead Blog",{"type":32,"tag":46,"props":4738,"children":4739},{},[4740],{"type":37,"value":4741},"A blog with the last post from 2023 looks worse than no blog at all. Can't write at least once a month? Better not to start one.",{"type":32,"tag":157,"props":4743,"children":4744},{},[4745,4749,4755],{"type":32,"tag":161,"props":4746,"children":4748},{"src":4747,"width":165,"style":166},"/article/what-should-business-website-contain/widgets.svg",[],{"type":32,"tag":169,"props":4750,"children":4752},{"id":4751},"unnecessary-widgets",[4753],{"type":37,"value":4754},"🔢 Unnecessary Widgets",{"type":32,"tag":46,"props":4756,"children":4757},{},[4758],{"type":37,"value":4759},"Visitor counters, weather widgets, ticking clocks. Every element on your website should have a purpose.",{"type":32,"tag":157,"props":4761,"children":4762},{},[4763,4767,4773],{"type":32,"tag":161,"props":4764,"children":4766},{"src":4765,"width":165,"style":166},"/article/what-should-business-website-contain/stock-photos.svg",[],{"type":32,"tag":169,"props":4768,"children":4770},{"id":4769},"generic-stock-photos",[4771],{"type":37,"value":4772},"📸 Generic Stock Photos",{"type":32,"tag":46,"props":4774,"children":4775},{},[4776],{"type":37,"value":4777},"You know exactly which ones I mean. Four people in suits smiling over a laptop. Better to use quality illustrations or your own photos.",{"type":32,"tag":57,"props":4779,"children":4780},{},[],{"type":32,"tag":39,"props":4782,"children":4783},{"id":774},[4784],{"type":37,"value":777},{"type":32,"tag":46,"props":4786,"children":4787},{},[4788],{"type":37,"value":4789},"A business website doesn't have to be complex or expensive. But it must contain the basic elements that let visitors quickly figure out what you do, why they should trust you, and how to reach you. Go through the checklists in this article and compare them with your current website. I bet you'll find at least a few things you can improve.",{"type":32,"tag":46,"props":4791,"children":4792},{},[4793,4795,4799],{"type":37,"value":4794},"Start with the most important stuff - contact details, service descriptions, legal requirements. Then gradually add testimonials, fine-tune your ",{"type":32,"tag":117,"props":4796,"children":4797},{},[4798],{"type":37,"value":4362},{"type":37,"value":4800},"s, and take care of the technical basics. You don't have to do everything at once, but have a clear plan for where the website is heading.",{"type":32,"tag":46,"props":4802,"children":4803},{},[4804],{"type":37,"value":4805},"And if you're not sure whether your website works well, try a simple test - send the link to someone who doesn't know your company and ask them to figure out within 30 seconds what you do and how to contact you. If they can't, it's time for a change.",{"type":32,"tag":57,"props":4807,"children":4808},{},[],{"type":32,"tag":39,"props":4810,"children":4811},{"id":798},[4812],{"type":37,"value":801},{"type":32,"tag":444,"props":4814,"children":4815},{},[4816,4826,4836,4848,4860],{"type":32,"tag":448,"props":4817,"children":4818},{},[4819,4824],{"type":32,"tag":139,"props":4820,"children":4822},{"href":355,":target":345,"rel":4821},[347],[4823],{"type":37,"value":359},{"type":37,"value":4825}," - free tool for monitoring your website's search visibility",{"type":32,"tag":448,"props":4827,"children":4828},{},[4829,4834],{"type":32,"tag":139,"props":4830,"children":4832},{"href":1499,":target":345,"rel":4831},[347],[4833],{"type":37,"value":1503},{"type":37,"value":4835}," - Google's website speed and performance testing tool",{"type":32,"tag":448,"props":4837,"children":4838},{},[4839,4846],{"type":32,"tag":139,"props":4840,"children":4843},{"href":4841,":target":345,"rel":4842},"https://schema.org/",[347],[4844],{"type":37,"value":4845},"Schema.org",{"type":37,"value":4847}," - structured data markup reference for better SEO",{"type":32,"tag":448,"props":4849,"children":4850},{},[4851,4858],{"type":32,"tag":139,"props":4852,"children":4855},{"href":4853,":target":345,"rel":4854},"https://imagecompressor.com/",[347],[4856],{"type":37,"value":4857},"Image Compressor",{"type":37,"value":4859}," - online image compression for faster page loading",{"type":32,"tag":448,"props":4861,"children":4862},{},[4863,4870],{"type":32,"tag":139,"props":4864,"children":4867},{"href":4865,":target":345,"rel":4866},"https://www.osano.com/cookieconsent",[347],[4868],{"type":37,"value":4869},"Cookie Consent by Osano",{"type":37,"value":4871}," - open-source cookie consent solution",{"title":8,"searchDepth":862,"depth":862,"links":4873},[4874,4875,4878,4881,4882,4885,4886,4888,4891,4892,4893],{"id":41,"depth":862,"text":44},{"id":3865,"depth":862,"text":3868,"children":4876},[4877],{"id":3931,"depth":871,"text":3934},{"id":3982,"depth":862,"text":3985,"children":4879},[4880],{"id":4039,"depth":871,"text":4042},{"id":4086,"depth":862,"text":4089},{"id":4200,"depth":862,"text":4203,"children":4883},[4884],{"id":4263,"depth":871,"text":4266},{"id":4300,"depth":862,"text":4303},{"id":4354,"depth":862,"text":4887},"🔘 Calls to Action (CTA)",{"id":4503,"depth":862,"text":4506,"children":4889},[4890],{"id":4604,"depth":871,"text":4607},{"id":4694,"depth":862,"text":4697},{"id":774,"depth":862,"text":777},{"id":798,"depth":862,"text":801},"content:knowledge:what-should-business-website-contain.md","knowledge/what-should-business-website-contain.md",{"_path":141,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":4897,"description":4898,"author":11,"date":4899,"readingTime":4900,"level":14,"image":4901,"tags":4902,"slugs":4903,"relatedArticles":4905,"body":4906,"_type":881,"_id":6477,"_source":883,"_file":6478,"_extension":885},"How much does a website cost in 2026 - complete pricing guide","Real prices for websites, e-shops and web applications in 2026. What affects the price, hidden costs and how to compare quotes.","2026-01-27",12,"/featured/kolik-stoji-web-v-roce-2026.jpg",[20,893,895],{"en":26,"cs":4904},"kolik-stoji-web-v-roce-2026",[27,900,2999],{"type":29,"children":4907,"toc":6451},[4908,4913,4917,4922,4927,4933,4938,4943,5093,5098,5120,5126,5131,5263,5269,5282,5287,5291,5455,5461,5466,5472,5485,5491,5496,5501,5612,5618,5637,5655,5667,5690,5696,5701,5854,5870,5978,5984,5989,6057,6062,6067,6073,6078,6084,6094,6121,6131,6141,6147,6157,6173,6199,6209,6215,6220,6285,6302,6378,6382,6387,6392,6397,6402],{"type":32,"tag":33,"props":4909,"children":4911},{"id":4910},"how-much-does-a-website-cost-in-2026-complete-pricing-guide",[4912],{"type":37,"value":4897},{"type":32,"tag":39,"props":4914,"children":4915},{"id":41},[4916],{"type":37,"value":44},{"type":32,"tag":46,"props":4918,"children":4919},{},[4920],{"type":37,"value":4921},"\"How much does a website cost?\" is probably the most common question I get from potential clients. And the answer is always the same - it depends. But that's not very helpful, so I decided to put together real prices you'll encounter on the Czech market in 2026. No fluff, no marketing speak.",{"type":32,"tag":46,"props":4923,"children":4924},{},[4925],{"type":37,"value":4926},"The prices in this article come from my experience and what I see from colleagues in the industry. These aren't numbers pulled from thin air - they're amounts you'll actually pay when you get a website made professionally in Czechia.",{"type":32,"tag":39,"props":4928,"children":4930},{"id":4929},"website-pricing-categories-from-business-card-to-complex-app",[4931],{"type":37,"value":4932},"💰 Website pricing categories - from business card to complex app",{"type":32,"tag":46,"props":4934,"children":4935},{},[4936],{"type":37,"value":4937},"\"Website\" can mean absolutely anything. A simple five-page site with a contact form is fundamentally different from an e-shop with thousands of products or a custom web application.",{"type":32,"tag":46,"props":4939,"children":4940},{},[4941],{"type":37,"value":4942},"Generally, websites fall into four basic categories by complexity and price:",{"type":32,"tag":153,"props":4944,"children":4945},{},[4946,4983,5024,5061],{"type":32,"tag":157,"props":4947,"children":4948},{},[4949,4954,4960],{"type":32,"tag":161,"props":4950,"children":4953},{"src":4951,"alt":4952,"width":165,"style":166},"/article/how-much-does-website-cost-in-2026/business-card.svg","Business card website",[],{"type":32,"tag":169,"props":4955,"children":4957},{"id":4956},"business-card-website",[4958],{"type":37,"value":4959},"📄 Business card website",{"type":32,"tag":444,"props":4961,"children":4962},{},[4963,4968,4973],{"type":32,"tag":448,"props":4964,"children":4965},{},[4966],{"type":37,"value":4967},"1-5 pages",{"type":32,"tag":448,"props":4969,"children":4970},{},[4971],{"type":37,"value":4972},"basic presentation",{"type":32,"tag":448,"props":4974,"children":4975},{},[4976,4981],{"type":32,"tag":82,"props":4977,"children":4978},{},[4979],{"type":37,"value":4980},"CZK 15,000 - 50,000",{"type":37,"value":4982}," (~EUR 600 - 2,000)",{"type":32,"tag":157,"props":4984,"children":4985},{},[4986,4991,4997],{"type":32,"tag":161,"props":4987,"children":4990},{"src":4988,"alt":4989,"width":165,"style":166},"/article/how-much-does-website-cost-in-2026/company-website.svg","Company website",[],{"type":32,"tag":169,"props":4992,"children":4994},{"id":4993},"company-website",[4995],{"type":37,"value":4996},"🏢 Company website",{"type":32,"tag":444,"props":4998,"children":4999},{},[5000,5005,5014],{"type":32,"tag":448,"props":5001,"children":5002},{},[5003],{"type":37,"value":5004},"5-20 pages",{"type":32,"tag":448,"props":5006,"children":5007},{},[5008,5010],{"type":37,"value":5009},"blog, ",{"type":32,"tag":117,"props":5011,"children":5012},{},[5013],{"type":37,"value":423},{"type":32,"tag":448,"props":5015,"children":5016},{},[5017,5022],{"type":32,"tag":82,"props":5018,"children":5019},{},[5020],{"type":37,"value":5021},"CZK 50,000 - 200,000",{"type":37,"value":5023}," (~EUR 2,000 - 8,000)",{"type":32,"tag":157,"props":5025,"children":5026},{},[5027,5032,5038],{"type":32,"tag":161,"props":5028,"children":5031},{"src":5029,"alt":5030,"width":165,"style":166},"/article/how-much-does-website-cost-in-2026/eshop.svg","E-shop",[],{"type":32,"tag":169,"props":5033,"children":5035},{"id":5034},"e-shop",[5036],{"type":37,"value":5037},"🛒 E-shop",{"type":32,"tag":444,"props":5039,"children":5040},{},[5041,5046,5051],{"type":32,"tag":448,"props":5042,"children":5043},{},[5044],{"type":37,"value":5045},"catalog, cart, payments",{"type":32,"tag":448,"props":5047,"children":5048},{},[5049],{"type":37,"value":5050},"custom even over a million",{"type":32,"tag":448,"props":5052,"children":5053},{},[5054,5059],{"type":32,"tag":82,"props":5055,"children":5056},{},[5057],{"type":37,"value":5058},"CZK 80,000 - 500,000",{"type":37,"value":5060}," (~EUR 3,200 - 20,000)",{"type":32,"tag":157,"props":5062,"children":5063},{},[5064,5069,5075],{"type":32,"tag":161,"props":5065,"children":5068},{"src":5066,"alt":5067,"width":165,"style":166},"/article/how-much-does-website-cost-in-2026/web-application.svg","Custom web application",[],{"type":32,"tag":169,"props":5070,"children":5072},{"id":5071},"️-custom-web-application",[5073],{"type":37,"value":5074},"⚙️ Custom web application",{"type":32,"tag":444,"props":5076,"children":5077},{},[5078,5083],{"type":32,"tag":448,"props":5079,"children":5080},{},[5081],{"type":37,"value":5082},"software in the browser",{"type":32,"tag":448,"props":5084,"children":5085},{},[5086,5091],{"type":32,"tag":82,"props":5087,"children":5088},{},[5089],{"type":37,"value":5090},"CZK 200,000 - 2,000,000+",{"type":37,"value":5092}," (~EUR 8,000 - 80,000+)",{"type":32,"tag":46,"props":5094,"children":5095},{},[5096],{"type":37,"value":5097},"These ranges are quite wide because every project is different. We'll break down what exactly affects the price in the following sections.",{"type":32,"tag":46,"props":5099,"children":5100},{},[5101,5103,5110,5111,5118],{"type":37,"value":5102},"There are cheaper options too - ",{"type":32,"tag":139,"props":5104,"children":5107},{"href":5105,":target":345,"rel":5106,":rel":347},"https://www.wix.com",[347],[5108],{"type":37,"value":5109},"Wix",{"type":37,"value":2497},{"type":32,"tag":139,"props":5112,"children":5115},{"href":5113,":target":345,"rel":5114,":rel":347},"https://www.squarespace.com",[347],[5116],{"type":37,"value":5117},"Squarespace",{"type":37,"value":5119}," or WordPress with a ready-made template can be done for a few hundred euros. But that's a different category. Here we're talking about professionally built custom websites.",{"type":32,"tag":39,"props":5121,"children":5123},{"id":5122},"️-company-website-what-affects-the-price",[5124],{"type":37,"value":5125},"🏗️ Company website - what affects the price",{"type":32,"tag":46,"props":5127,"children":5128},{},[5129],{"type":37,"value":5130},"A company website is the most common type of project. Typically it's a business presentation with service info, references, a blog and a contact form. The price depends on several factors.",{"type":32,"tag":153,"props":5132,"children":5133},{},[5134,5176,5231],{"type":32,"tag":157,"props":5135,"children":5136},{},[5137,5142,5148],{"type":32,"tag":161,"props":5138,"children":5141},{"src":5139,"alt":5140,"width":165,"style":166},"/article/how-much-does-website-cost-in-2026/design.svg","Design",[],{"type":32,"tag":169,"props":5143,"children":5145},{"id":5144},"design",[5146],{"type":37,"value":5147},"🎨 Design",{"type":32,"tag":444,"props":5149,"children":5150},{},[5151,5161,5166],{"type":32,"tag":448,"props":5152,"children":5153},{},[5154,5156],{"type":37,"value":5155},"template or ",{"type":32,"tag":139,"props":5157,"children":5158},{"href":3081},[5159],{"type":37,"value":5160},"custom design",{"type":32,"tag":448,"props":5162,"children":5163},{},[5164],{"type":37,"value":5165},"original design starts at CZK 25,000, easily over CZK 80,000",{"type":32,"tag":448,"props":5167,"children":5168},{},[5169,5174],{"type":32,"tag":117,"props":5170,"children":5171},{},[5172],{"type":37,"value":5173},"UX",{"type":37,"value":5175}," design adds CZK 10,000 - 30,000 but pays off for most websites",{"type":32,"tag":157,"props":5177,"children":5178},{},[5179,5184,5190],{"type":32,"tag":161,"props":5180,"children":5183},{"src":5181,"alt":5182,"width":165,"style":166},"/article/how-much-does-website-cost-in-2026/technical.svg","Technical implementation",[],{"type":32,"tag":169,"props":5185,"children":5187},{"id":5186},"technical-implementation",[5188],{"type":37,"value":5189},"💻 Technical implementation",{"type":32,"tag":444,"props":5191,"children":5192},{},[5193,5198,5220],{"type":32,"tag":448,"props":5194,"children":5195},{},[5196],{"type":37,"value":5197},"WordPress with customizations CZK 20,000 - 60,000",{"type":32,"tag":448,"props":5199,"children":5200},{},[5201,5203,5209,5211,5218],{"type":37,"value":5202},"modern framework (",{"type":32,"tag":139,"props":5204,"children":5207},{"href":5205,":target":345,"rel":5206,":rel":347},"https://nextjs.org",[347],[5208],{"type":37,"value":3438},{"type":37,"value":5210},", Nuxt, ",{"type":32,"tag":139,"props":5212,"children":5215},{"href":5213,":target":345,"rel":5214,":rel":347},"https://astro.build",[347],[5216],{"type":37,"value":5217},"Astro",{"type":37,"value":5219},") CZK 40,000 - 120,000",{"type":32,"tag":448,"props":5221,"children":5222},{},[5223,5225,5229],{"type":37,"value":5224},"headless ",{"type":32,"tag":117,"props":5226,"children":5227},{},[5228],{"type":37,"value":643},{"type":37,"value":5230}," another CZK 15,000 - 40,000",{"type":32,"tag":157,"props":5232,"children":5233},{},[5234,5239,5245],{"type":32,"tag":161,"props":5235,"children":5238},{"src":5236,"alt":5237,"width":165,"style":166},"/article/how-much-does-website-cost-in-2026/copywriting.svg","Content",[],{"type":32,"tag":169,"props":5240,"children":5242},{"id":5241},"️-content",[5243],{"type":37,"value":5244},"✍️ Content",{"type":32,"tag":444,"props":5246,"children":5247},{},[5248,5253,5258],{"type":32,"tag":448,"props":5249,"children":5250},{},[5251],{"type":37,"value":5252},"copywriting CZK 1,500 - 4,000 per page",{"type":32,"tag":448,"props":5254,"children":5255},{},[5256],{"type":37,"value":5257},"product or team photography CZK 5,000 - 20,000",{"type":32,"tag":448,"props":5259,"children":5260},{},[5261],{"type":37,"value":5262},"translations for multilingual sites CZK 2,000 - 5,000 per page",{"type":32,"tag":169,"props":5264,"children":5266},{"id":5265},"how-ai-affects-website-pricing",[5267],{"type":37,"value":5268},"🤖 How AI affects website pricing",{"type":32,"tag":46,"props":5270,"children":5271},{},[5272,5274,5280],{"type":37,"value":5273},"In 2026, ",{"type":32,"tag":139,"props":5275,"children":5277},{"href":5276},"/knowledge/ai-assisted-web-application-development",[5278],{"type":37,"value":5279},"AI-assisted development",{"type":37,"value":5281}," is increasingly reflected in website prices. Developers working with AI tools can deliver projects faster - and that shows in the final price. For simpler websites, AI-assisted development can reduce costs by 15-30%. For more complex projects the savings are smaller, since AI helps mostly with routine work, not architecture design or business logic.",{"type":32,"tag":46,"props":5283,"children":5284},{},[5285],{"type":37,"value":5286},"What to watch out for - a lower price doesn't mean lower quality, but it depends on how the developer uses AI. An experienced programmer with AI tools delivers a site faster at the same quality. A beginner who relies mainly on AI might deliver a site with technical debt that only shows up later.",{"type":32,"tag":2069,"props":5288,"children":5290},{"slug":5289},"ai-assisted-web-application-development",[],{"type":32,"tag":153,"props":5292,"children":5293},{},[5294],{"type":32,"tag":157,"props":5295,"children":5296},{},[5297,5303],{"type":32,"tag":169,"props":5298,"children":5300},{"id":5299},"real-example-mid-sized-company-website",[5301],{"type":37,"value":5302},"📊 Real example - mid-sized company website",{"type":32,"tag":1559,"props":5304,"children":5305},{},[5306,5327],{"type":32,"tag":1563,"props":5307,"children":5308},{},[5309],{"type":32,"tag":1567,"props":5310,"children":5311},{},[5312,5317,5322],{"type":32,"tag":1571,"props":5313,"children":5314},{"align":1573},[5315],{"type":37,"value":5316},"Item",{"type":32,"tag":1571,"props":5318,"children":5319},{"align":1573},[5320],{"type":37,"value":5321},"Without AI",{"type":32,"tag":1571,"props":5323,"children":5324},{"align":1573},[5325],{"type":37,"value":5326},"With AI assistance",{"type":32,"tag":1588,"props":5328,"children":5329},{},[5330,5348,5365,5387,5408,5424],{"type":32,"tag":1567,"props":5331,"children":5332},{},[5333,5338,5343],{"type":32,"tag":1595,"props":5334,"children":5335},{"align":1573},[5336],{"type":37,"value":5337},"Custom design (8 unique pages)",{"type":32,"tag":1595,"props":5339,"children":5340},{"align":1573},[5341],{"type":37,"value":5342},"CZK 45,000",{"type":32,"tag":1595,"props":5344,"children":5345},{"align":1573},[5346],{"type":37,"value":5347},"CZK 40,000",{"type":32,"tag":1567,"props":5349,"children":5350},{},[5351,5356,5361],{"type":32,"tag":1595,"props":5352,"children":5353},{"align":1573},[5354],{"type":37,"value":5355},"Development on modern framework",{"type":32,"tag":1595,"props":5357,"children":5358},{"align":1573},[5359],{"type":37,"value":5360},"CZK 65,000",{"type":32,"tag":1595,"props":5362,"children":5363},{"align":1573},[5364],{"type":37,"value":5342},{"type":32,"tag":1567,"props":5366,"children":5367},{},[5368,5377,5382],{"type":32,"tag":1595,"props":5369,"children":5370},{"align":1573},[5371,5375],{"type":32,"tag":117,"props":5372,"children":5373},{},[5374],{"type":37,"value":643},{"type":37,"value":5376}," for content management",{"type":32,"tag":1595,"props":5378,"children":5379},{"align":1573},[5380],{"type":37,"value":5381},"CZK 20,000",{"type":32,"tag":1595,"props":5383,"children":5384},{"align":1573},[5385],{"type":37,"value":5386},"CZK 15,000",{"type":32,"tag":1567,"props":5388,"children":5389},{},[5390,5399,5403],{"type":32,"tag":1595,"props":5391,"children":5392},{"align":1573},[5393,5397],{"type":32,"tag":117,"props":5394,"children":5395},{},[5396],{"type":37,"value":423},{"type":37,"value":5398}," basics + analytics setup",{"type":32,"tag":1595,"props":5400,"children":5401},{"align":1573},[5402],{"type":37,"value":5386},{"type":32,"tag":1595,"props":5404,"children":5405},{"align":1573},[5406],{"type":37,"value":5407},"CZK 12,000",{"type":32,"tag":1567,"props":5409,"children":5410},{},[5411,5416,5420],{"type":32,"tag":1595,"props":5412,"children":5413},{"align":1573},[5414],{"type":37,"value":5415},"Copywriting (8 pages)",{"type":32,"tag":1595,"props":5417,"children":5418},{"align":1573},[5419],{"type":37,"value":5381},{"type":32,"tag":1595,"props":5421,"children":5422},{"align":1573},[5423],{"type":37,"value":5381},{"type":32,"tag":1567,"props":5425,"children":5426},{},[5427,5435,5445],{"type":32,"tag":1595,"props":5428,"children":5429},{"align":1573},[5430],{"type":32,"tag":82,"props":5431,"children":5432},{},[5433],{"type":37,"value":5434},"Total",{"type":32,"tag":1595,"props":5436,"children":5437},{"align":1573},[5438,5443],{"type":32,"tag":82,"props":5439,"children":5440},{},[5441],{"type":37,"value":5442},"approx. CZK 165,000",{"type":37,"value":5444}," (~EUR 6,600)",{"type":32,"tag":1595,"props":5446,"children":5447},{"align":1573},[5448,5453],{"type":32,"tag":82,"props":5449,"children":5450},{},[5451],{"type":37,"value":5452},"approx. CZK 132,000",{"type":37,"value":5454}," (~EUR 5,300)",{"type":32,"tag":39,"props":5456,"children":5458},{"id":5457},"️-custom-e-shop-vs-off-the-shelf-solution",[5459],{"type":37,"value":5460},"🛍️ Custom e-shop vs off-the-shelf solution",{"type":32,"tag":46,"props":5462,"children":5463},{},[5464],{"type":37,"value":5465},"For e-shops, the decision between an off-the-shelf solution and custom development is even more significant than for company websites. The price difference can be tenfold.",{"type":32,"tag":169,"props":5467,"children":5469},{"id":5468},"off-the-shelf-solutions",[5470],{"type":37,"value":5471},"📦 Off-the-shelf solutions",{"type":32,"tag":46,"props":5473,"children":5474},{},[5475,5477,5483],{"type":37,"value":5476},"Shoptet, ",{"type":32,"tag":139,"props":5478,"children":5481},{"href":5479,":target":345,"rel":5480,":rel":347},"https://www.shopify.com",[347],[5482],{"type":37,"value":3422},{"type":37,"value":5484}," or WooCommerce have a huge advantage in upfront cost. Shoptet can be set up from CZK 15,000 (basic setup and template customization) to CZK 80,000 (major visual changes, integration with accounting, carriers and payment gateways). Monthly fees for Shoptet range from CZK 500 to 5,000 depending on the plan. WooCommerce on WordPress costs CZK 30,000 - 120,000 for setup and customization, with no monthly platform fees (but you need hosting).",{"type":32,"tag":169,"props":5486,"children":5488},{"id":5487},"custom-e-shop",[5489],{"type":37,"value":5490},"🔧 Custom e-shop",{"type":32,"tag":46,"props":5492,"children":5493},{},[5494],{"type":37,"value":5495},"Starts at around CZK 200,000 and there's practically no upper limit. A typical custom e-shop for a mid-sized company costs CZK 300,000 - 800,000. Why such a big difference? Because everything is built from scratch - product catalog, cart, order process, admin panel, warehouse and accounting integrations.",{"type":32,"tag":46,"props":5497,"children":5498},{},[5499],{"type":37,"value":5500},"When does a custom e-shop make sense? When you have a specific business model that off-the-shelf solutions can't cover. Like a product configurator, non-standard pricing logic, or you need to process thousands of orders daily and off-the-shelf performance isn't enough. If you're selling 50 products with no special requirements, go with an off-the-shelf solution - you'll save hundreds of thousands.",{"type":32,"tag":153,"props":5502,"children":5503},{},[5504],{"type":32,"tag":157,"props":5505,"children":5506},{},[5507,5513],{"type":32,"tag":169,"props":5508,"children":5510},{"id":5509},"e-shop-cost-comparison-first-year",[5511],{"type":37,"value":5512},"📊 E-shop cost comparison (first year)",{"type":32,"tag":1559,"props":5514,"children":5515},{},[5516,5540],{"type":32,"tag":1563,"props":5517,"children":5518},{},[5519],{"type":32,"tag":1567,"props":5520,"children":5521},{},[5522,5525,5530,5535],{"type":32,"tag":1571,"props":5523,"children":5524},{"align":1573},[],{"type":32,"tag":1571,"props":5526,"children":5527},{"align":1573},[5528],{"type":37,"value":5529},"Shoptet",{"type":32,"tag":1571,"props":5531,"children":5532},{"align":1573},[5533],{"type":37,"value":5534},"WooCommerce",{"type":32,"tag":1571,"props":5536,"children":5537},{"align":1573},[5538],{"type":37,"value":5539},"Custom",{"type":32,"tag":1588,"props":5541,"children":5542},{},[5543,5566,5589],{"type":32,"tag":1567,"props":5544,"children":5545},{},[5546,5551,5556,5561],{"type":32,"tag":1595,"props":5547,"children":5548},{"align":1573},[5549],{"type":37,"value":5550},"Upfront investment",{"type":32,"tag":1595,"props":5552,"children":5553},{"align":1573},[5554],{"type":37,"value":5555},"CZK 25,000 - 80,000",{"type":32,"tag":1595,"props":5557,"children":5558},{"align":1573},[5559],{"type":37,"value":5560},"CZK 40,000 - 120,000",{"type":32,"tag":1595,"props":5562,"children":5563},{"align":1573},[5564],{"type":37,"value":5565},"CZK 300,000 - 800,000",{"type":32,"tag":1567,"props":5567,"children":5568},{},[5569,5574,5579,5584],{"type":32,"tag":1595,"props":5570,"children":5571},{"align":1573},[5572],{"type":37,"value":5573},"Monthly operation",{"type":32,"tag":1595,"props":5575,"children":5576},{"align":1573},[5577],{"type":37,"value":5578},"CZK 1,500 - 5,000",{"type":32,"tag":1595,"props":5580,"children":5581},{"align":1573},[5582],{"type":37,"value":5583},"CZK 500 - 2,000 (hosting)",{"type":32,"tag":1595,"props":5585,"children":5586},{"align":1573},[5587],{"type":37,"value":5588},"CZK 2,000 - 8,000",{"type":32,"tag":1567,"props":5590,"children":5591},{},[5592,5597,5602,5607],{"type":32,"tag":1595,"props":5593,"children":5594},{"align":1573},[5595],{"type":37,"value":5596},"Annual total",{"type":32,"tag":1595,"props":5598,"children":5599},{"align":1573},[5600],{"type":37,"value":5601},"CZK 43,000 - 140,000",{"type":32,"tag":1595,"props":5603,"children":5604},{"align":1573},[5605],{"type":37,"value":5606},"CZK 46,000 - 144,000",{"type":32,"tag":1595,"props":5608,"children":5609},{"align":1573},[5610],{"type":37,"value":5611},"CZK 324,000 - 896,000",{"type":32,"tag":39,"props":5613,"children":5615},{"id":5614},"web-application-a-different-price-league",[5616],{"type":37,"value":5617},"🚀 Web application - a different price league",{"type":32,"tag":46,"props":5619,"children":5620},{},[5621,5623,5628,5630,5635],{"type":37,"value":5622},"A web application is a fundamentally different type of project compared to a presentation website or e-shop. We're talking about software running in the browser - ",{"type":32,"tag":117,"props":5624,"children":5625},{},[5626],{"type":37,"value":5627},"CRM",{"type":37,"value":5629}," systems, internal tools, customer portals, booking systems or ",{"type":32,"tag":117,"props":5631,"children":5632},{},[5633],{"type":37,"value":5634},"SaaS",{"type":37,"value":5636}," products.",{"type":32,"tag":46,"props":5638,"children":5639},{},[5640,5642,5647,5649,5653],{"type":37,"value":5641},"The price depends mainly on ",{"type":32,"tag":82,"props":5643,"children":5644},{},[5645],{"type":37,"value":5646},"business logic complexity",{"type":37,"value":5648},". A simple booking system for a hair salon might cost CZK 100,000 - 200,000. An internal order management system for a manufacturing company CZK 500,000 - 1,500,000. And a full-blown ",{"type":32,"tag":117,"props":5650,"children":5651},{},[5652],{"type":37,"value":5634},{"type":37,"value":5654}," product easily over CZK 2,000,000 before it hits the market.",{"type":32,"tag":46,"props":5656,"children":5657},{},[5658,5660,5665],{"type":37,"value":5659},"Applications also differ significantly in development approach. While a website is usually delivered as a one-off, applications are typically developed iteratively - you start with an ",{"type":32,"tag":117,"props":5661,"children":5662},{},[5663],{"type":37,"value":5664},"MVP",{"type":37,"value":5666}," (minimum viable product) for CZK 200,000 - 500,000 and then gradually add features. This is the smarter approach because you find out what users actually need before spending the entire budget.",{"type":32,"tag":46,"props":5668,"children":5669},{},[5670,5672,5677,5679,5688],{"type":37,"value":5671},"Another factor is ",{"type":32,"tag":82,"props":5673,"children":5674},{},[5675],{"type":37,"value":5676},"infrastructure and security",{"type":37,"value":5678},". Applications work with user data, so you need to handle security, backups, ",{"type":32,"tag":139,"props":5680,"children":5681},{"href":1389},[5682,5686],{"type":32,"tag":117,"props":5683,"children":5684},{},[5685],{"type":37,"value":1381},{"type":37,"value":5687}," compliance",{"type":37,"value":5689}," and often scalability. These are costs you don't deal with for a regular company website.",{"type":32,"tag":39,"props":5691,"children":5693},{"id":5692},"hidden-costs-hosting-domain-maintenance-content",[5694],{"type":37,"value":5695},"🔍 Hidden costs - hosting, domain, maintenance, content",{"type":32,"tag":46,"props":5697,"children":5698},{},[5699],{"type":37,"value":5700},"The price for creating a website is just the beginning. A lot of clients are surprised how much it costs to run and maintain a website. And these are costs that never end.",{"type":32,"tag":153,"props":5702,"children":5703},{},[5704,5748,5792,5824],{"type":32,"tag":157,"props":5705,"children":5706},{},[5707,5712,5718],{"type":32,"tag":161,"props":5708,"children":5711},{"src":5709,"alt":5710,"width":165,"style":166},"/article/how-much-does-website-cost-in-2026/domain.svg","Domain",[],{"type":32,"tag":169,"props":5713,"children":5715},{"id":5714},"domain",[5716],{"type":37,"value":5717},"🌐 Domain",{"type":32,"tag":444,"props":5719,"children":5720},{},[5721,5743],{"type":32,"tag":448,"props":5722,"children":5723},{},[5724,5734,5736,5741],{"type":32,"tag":139,"props":5725,"children":5726},{"href":2654},[5727,5732],{"type":32,"tag":117,"props":5728,"children":5729},{},[5730],{"type":37,"value":5731},".cz",{"type":37,"value":5733}," domain",{"type":37,"value":5735}," costs around CZK 200 - 300 per year, ",{"type":32,"tag":117,"props":5737,"children":5738},{},[5739],{"type":37,"value":5740},".com",{"type":37,"value":5742}," around CZK 300 - 400",{"type":32,"tag":448,"props":5744,"children":5745},{},[5746],{"type":37,"value":5747},"if you want multiple domains, costs multiply, but it's still small change",{"type":32,"tag":157,"props":5749,"children":5750},{},[5751,5756,5762],{"type":32,"tag":161,"props":5752,"children":5755},{"src":5753,"alt":5754,"width":165,"style":166},"/article/how-much-does-website-cost-in-2026/hosting.svg","Hosting",[],{"type":32,"tag":169,"props":5757,"children":5759},{"id":5758},"️-hosting",[5760],{"type":37,"value":5761},"🖥️ Hosting",{"type":32,"tag":444,"props":5763,"children":5764},{},[5765,5770,5782,5787],{"type":32,"tag":448,"props":5766,"children":5767},{},[5768],{"type":37,"value":5769},"from CZK 50/month for shared hosting (fine for small sites)",{"type":32,"tag":448,"props":5771,"children":5772},{},[5773,5775,5780],{"type":37,"value":5774},"CZK 300 - 1,500 for a ",{"type":32,"tag":117,"props":5776,"children":5777},{},[5778],{"type":37,"value":5779},"VPS",{"type":37,"value":5781}," server",{"type":32,"tag":448,"props":5783,"children":5784},{},[5785],{"type":37,"value":5786},"CZK 2,000 - 10,000 for managed cloud",{"type":32,"tag":448,"props":5788,"children":5789},{},[5790],{"type":37,"value":5791},"hosting quality directly affects site speed and search rankings",{"type":32,"tag":157,"props":5793,"children":5794},{},[5795,5800,5806],{"type":32,"tag":161,"props":5796,"children":5799},{"src":5797,"alt":5798,"width":165,"style":166},"/article/how-much-does-website-cost-in-2026/maintenance.svg","Maintenance and updates",[],{"type":32,"tag":169,"props":5801,"children":5803},{"id":5802},"maintenance-and-updates",[5804],{"type":37,"value":5805},"🔄 Maintenance and updates",{"type":32,"tag":444,"props":5807,"children":5808},{},[5809,5814,5819],{"type":32,"tag":448,"props":5810,"children":5811},{},[5812],{"type":37,"value":5813},"WordPress needs regular updates - otherwise it becomes a security risk",{"type":32,"tag":448,"props":5815,"children":5816},{},[5817],{"type":37,"value":5818},"monthly WordPress maintenance CZK 1,000 - 3,000",{"type":32,"tag":448,"props":5820,"children":5821},{},[5822],{"type":37,"value":5823},"sites on modern frameworks CZK 500 - 2,000 monthly",{"type":32,"tag":157,"props":5825,"children":5826},{},[5827,5831,5836],{"type":32,"tag":161,"props":5828,"children":5830},{"src":5829,"alt":5237,"width":165,"style":166},"/article/how-much-does-website-cost-in-2026/content.svg",[],{"type":32,"tag":169,"props":5832,"children":5834},{"id":5833},"️-content-1",[5835],{"type":37,"value":5244},{"type":32,"tag":444,"props":5837,"children":5838},{},[5839,5844,5849],{"type":32,"tag":448,"props":5840,"children":5841},{},[5842],{"type":37,"value":5843},"the biggest hidden cost long-term",{"type":32,"tag":448,"props":5845,"children":5846},{},[5847],{"type":37,"value":5848},"a blog post from a copywriter costs CZK 2,000 - 8,000",{"type":32,"tag":448,"props":5850,"children":5851},{},[5852],{"type":37,"value":5853},"two articles per month = CZK 4,000 - 16,000 monthly just for texts",{"type":32,"tag":46,"props":5855,"children":5856},{},[5857,5861,5863,5868],{"type":32,"tag":117,"props":5858,"children":5859},{},[5860],{"type":37,"value":4589},{"type":37,"value":5862}," certificates are free these days through Let's Encrypt, so that's no longer a cost. If you need an extended certificate (",{"type":32,"tag":117,"props":5864,"children":5865},{},[5866],{"type":37,"value":5867},"EV SSL",{"type":37,"value":5869},") for an e-shop, count on CZK 2,000 - 8,000 annually.",{"type":32,"tag":153,"props":5871,"children":5872},{},[5873],{"type":32,"tag":157,"props":5874,"children":5875},{},[5876,5882],{"type":32,"tag":169,"props":5877,"children":5879},{"id":5878},"typical-annual-operating-costs-for-a-company-website",[5880],{"type":37,"value":5881},"📊 Typical annual operating costs for a company website",{"type":32,"tag":1559,"props":5883,"children":5884},{},[5885,5900],{"type":32,"tag":1563,"props":5886,"children":5887},{},[5888],{"type":32,"tag":1567,"props":5889,"children":5890},{},[5891,5895],{"type":32,"tag":1571,"props":5892,"children":5893},{"align":1573},[5894],{"type":37,"value":5316},{"type":32,"tag":1571,"props":5896,"children":5897},{"align":1573},[5898],{"type":37,"value":5899},"Price",{"type":32,"tag":1588,"props":5901,"children":5902},{},[5903,5915,5933,5945,5958],{"type":32,"tag":1567,"props":5904,"children":5905},{},[5906,5910],{"type":32,"tag":1595,"props":5907,"children":5908},{"align":1573},[5909],{"type":37,"value":5710},{"type":32,"tag":1595,"props":5911,"children":5912},{"align":1573},[5913],{"type":37,"value":5914},"CZK 250",{"type":32,"tag":1567,"props":5916,"children":5917},{},[5918,5928],{"type":32,"tag":1595,"props":5919,"children":5920},{"align":1573},[5921,5923,5927],{"type":37,"value":5922},"Hosting (",{"type":32,"tag":117,"props":5924,"children":5925},{},[5926],{"type":37,"value":5779},{"type":37,"value":4364},{"type":32,"tag":1595,"props":5929,"children":5930},{"align":1573},[5931],{"type":37,"value":5932},"CZK 6,000 - 12,000",{"type":32,"tag":1567,"props":5934,"children":5935},{},[5936,5940],{"type":32,"tag":1595,"props":5937,"children":5938},{"align":1573},[5939],{"type":37,"value":5798},{"type":32,"tag":1595,"props":5941,"children":5942},{"align":1573},[5943],{"type":37,"value":5944},"CZK 12,000 - 36,000",{"type":32,"tag":1567,"props":5946,"children":5947},{},[5948,5953],{"type":32,"tag":1595,"props":5949,"children":5950},{"align":1573},[5951],{"type":37,"value":5952},"Content (blog, 2 articles/month)",{"type":32,"tag":1595,"props":5954,"children":5955},{"align":1573},[5956],{"type":37,"value":5957},"CZK 48,000 - 96,000",{"type":32,"tag":1567,"props":5959,"children":5960},{},[5961,5968],{"type":32,"tag":1595,"props":5962,"children":5963},{"align":1573},[5964],{"type":32,"tag":82,"props":5965,"children":5966},{},[5967],{"type":37,"value":5596},{"type":32,"tag":1595,"props":5969,"children":5970},{"align":1573},[5971,5976],{"type":32,"tag":82,"props":5972,"children":5973},{},[5974],{"type":37,"value":5975},"CZK 66,000 - 144,000",{"type":37,"value":5977}," (~EUR 2,600 - 5,800)",{"type":32,"tag":39,"props":5979,"children":5981},{"id":5980},"️-hourly-rate-vs-fixed-price",[5982],{"type":37,"value":5983},"⚖️ Hourly rate vs fixed price",{"type":32,"tag":46,"props":5985,"children":5986},{},[5987],{"type":37,"value":5988},"When you get a quote for a website, it'll be either a fixed price for the whole project or an hourly rate. Both have their pros and cons.",{"type":32,"tag":153,"props":5990,"children":5991},{},[5992,6017],{"type":32,"tag":157,"props":5993,"children":5994},{},[5995,6000,6006],{"type":32,"tag":161,"props":5996,"children":5999},{"src":5997,"alt":5998,"width":165,"style":166},"/article/how-much-does-website-cost-in-2026/fixed-price.svg","Fixed price",[],{"type":32,"tag":169,"props":6001,"children":6003},{"id":6002},"fixed-price",[6004],{"type":37,"value":6005},"📋 Fixed price",{"type":32,"tag":46,"props":6007,"children":6008},{},[6009,6011,6015],{"type":37,"value":6010},"Gives you certainty about what you'll pay. You know upfront and can approve it in your budget. ",{"type":32,"tag":82,"props":6012,"children":6013},{},[6014],{"type":37,"value":3062},{"type":37,"value":6016}," - the vendor builds in a risk premium (typically 15-30% extra). Changes during the project are billed separately and usually expensively.",{"type":32,"tag":157,"props":6018,"children":6019},{},[6020,6025,6031],{"type":32,"tag":161,"props":6021,"children":6024},{"src":6022,"alt":6023,"width":165,"style":166},"/article/how-much-does-website-cost-in-2026/hourly-rate.svg","Hourly rate",[],{"type":32,"tag":169,"props":6026,"children":6028},{"id":6027},"️-hourly-rate",[6029],{"type":37,"value":6030},"⏱️ Hourly rate",{"type":32,"tag":46,"props":6032,"children":6033},{},[6034,6036,6041,6043,6048,6050,6055],{"type":37,"value":6035},"On the Czech market in 2026: ",{"type":32,"tag":82,"props":6037,"children":6038},{},[6039],{"type":37,"value":6040},"CZK 800/h",{"type":37,"value":6042}," for juniors, ",{"type":32,"tag":82,"props":6044,"children":6045},{},[6046],{"type":37,"value":6047},"CZK 1,200 - 2,000/h",{"type":37,"value":6049}," for experienced freelancers and mid-sized agencies, ",{"type":32,"tag":82,"props":6051,"children":6052},{},[6053],{"type":37,"value":6054},"CZK 2,000 - 3,500/h",{"type":37,"value":6056}," for large agencies. More transparent - you pay for actual work done. The risk is a higher final price.",{"type":32,"tag":46,"props":6058,"children":6059},{},[6060],{"type":37,"value":6061},"An interesting AI effect - hourly rates haven't changed, but developers with AI tools get more done in the same time. A project that would take 80 hours without AI, an experienced developer with AI finishes in 50-60 hours. The project price ends up lower even though the hourly rate stays the same.",{"type":32,"tag":46,"props":6063,"children":6064},{},[6065],{"type":37,"value":6066},"My recommendation? For well-defined projects (company website with a precise brief), a fixed price is fine. For projects where requirements will change (applications, complex e-shops), hourly rates are fairer for both sides. The ideal is a combination - fixed price for the defined scope with an hourly rate for any changes and extensions.",{"type":32,"tag":39,"props":6068,"children":6070},{"id":6069},"where-to-save-and-where-definitely-not",[6071],{"type":37,"value":6072},"✅ Where to save and where definitely not",{"type":32,"tag":46,"props":6074,"children":6075},{},[6076],{"type":37,"value":6077},"The website budget isn't unlimited, so it makes sense to look for savings. But there are places where cuts hurt more than they save.",{"type":32,"tag":169,"props":6079,"children":6081},{"id":6080},"where-it-pays-to-save",[6082],{"type":37,"value":6083},"💡 Where it pays to save",{"type":32,"tag":46,"props":6085,"children":6086},{},[6087,6092],{"type":32,"tag":82,"props":6088,"children":6089},{},[6090],{"type":37,"value":6091},"Unnecessary features at launch.",{"type":37,"value":6093}," Don't build a website with everything you can think of. Start with what you actually need and expand gradually. A chatbot nobody will use or a complicated calculator that a simple form could handle - that's money thrown out the window.",{"type":32,"tag":46,"props":6095,"children":6096},{},[6097,6102,6104,6111,6112,6119],{"type":32,"tag":82,"props":6098,"children":6099},{},[6100],{"type":37,"value":6101},"Stock photos instead of photography.",{"type":37,"value":6103}," Quality stock photos (",{"type":32,"tag":139,"props":6105,"children":6108},{"href":6106,":target":345,"rel":6107,":rel":347},"https://unsplash.com",[347],[6109],{"type":37,"value":6110},"Unsplash",{"type":37,"value":2497},{"type":32,"tag":139,"props":6113,"children":6116},{"href":6114,":target":345,"rel":6115,":rel":347},"https://www.pexels.com",[347],[6117],{"type":37,"value":6118},"Pexels",{"type":37,"value":6120}," - free, or Shutterstock - approx. CZK 200-600 per photo) are perfectly fine to start with. Professional photography makes sense but doesn't have to be day one.",{"type":32,"tag":46,"props":6122,"children":6123},{},[6124,6129],{"type":32,"tag":82,"props":6125,"children":6126},{},[6127],{"type":37,"value":6128},"Animations and effects.",{"type":37,"value":6130}," Subtle animations bring a website to life, but overdone effects cost a lot of development time and often slow down loading. Less is more.",{"type":32,"tag":46,"props":6132,"children":6133},{},[6134,6139],{"type":32,"tag":82,"props":6135,"children":6136},{},[6137],{"type":37,"value":6138},"A developer with AI instead of a cheap amateur.",{"type":37,"value":6140}," For an MVP or simpler website, a better choice is an experienced developer who uses AI tools rather than a cheap beginner. A pro with AI delivers a website faster, with better quality and at a comparable price - because AI saves them hours of routine work, while experience ensures proper architecture and maintainability.",{"type":32,"tag":169,"props":6142,"children":6144},{"id":6143},"where-you-definitely-shouldnt-save",[6145],{"type":37,"value":6146},"🚫 Where you definitely shouldn't save",{"type":32,"tag":46,"props":6148,"children":6149},{},[6150,6155],{"type":32,"tag":82,"props":6151,"children":6152},{},[6153],{"type":37,"value":6154},"Mobile responsiveness",{"type":37,"value":6156}," - over 70% of visitors come from mobile. A website that doesn't work properly on phones is useless in 2026.",{"type":32,"tag":46,"props":6158,"children":6159},{},[6160,6165,6167,6171],{"type":32,"tag":82,"props":6161,"children":6162},{},[6163],{"type":37,"value":6164},"Loading speed",{"type":37,"value":6166}," - every extra second reduces conversions by 7-10%. Cheap hosting and ",{"type":32,"tag":139,"props":6168,"children":6169},{"href":627},[6170],{"type":37,"value":4553},{"type":37,"value":6172}," will cost you more in lost business than what you save.",{"type":32,"tag":46,"props":6174,"children":6175},{},[6176,6185,6187,6191,6193,6197],{"type":32,"tag":82,"props":6177,"children":6178},{},[6179,6183],{"type":32,"tag":117,"props":6180,"children":6181},{},[6182],{"type":37,"value":423},{"type":37,"value":6184}," fundamentals",{"type":37,"value":6186}," - proper page structure, meta tags, technical ",{"type":32,"tag":117,"props":6188,"children":6189},{},[6190],{"type":37,"value":423},{"type":37,"value":6192},". Without it, Google won't find you. Retrofitting ",{"type":32,"tag":117,"props":6194,"children":6195},{},[6196],{"type":37,"value":423},{"type":37,"value":6198}," on a poorly built website is more expensive than doing it right from the start.",{"type":32,"tag":46,"props":6200,"children":6201},{},[6202,6207],{"type":32,"tag":82,"props":6203,"children":6204},{},[6205],{"type":37,"value":6206},"Security",{"type":37,"value":6208}," - especially for e-shops. A customer data breach can cost you fines in the hundreds of thousands and loss of trust that's hard to buy back.",{"type":32,"tag":39,"props":6210,"children":6212},{"id":6211},"how-to-compare-quotes",[6213],{"type":37,"value":6214},"🔎 How to compare quotes",{"type":32,"tag":46,"props":6216,"children":6217},{},[6218],{"type":37,"value":6219},"You have three quotes for a website and the prices differ threefold. How do you tell which one is fair?",{"type":32,"tag":6221,"props":6222,"children":6223},"steps",{},[6224,6230,6252,6258,6263,6269,6274,6280],{"type":32,"tag":169,"props":6225,"children":6227},{"id":6226},"compare-scope-not-price",[6228],{"type":37,"value":6229},"Compare scope, not price",{"type":32,"tag":46,"props":6231,"children":6232},{},[6233,6235,6239,6240,6244,6246,6250],{"type":37,"value":6234},"A quote for CZK 40,000 and a quote for CZK 120,000 probably don't cover the same thing. Look at what's exactly included - number of pages, type of design (template vs custom), ",{"type":32,"tag":117,"props":6236,"children":6237},{},[6238],{"type":37,"value":643},{"type":37,"value":2497},{"type":32,"tag":117,"props":6241,"children":6242},{},[6243],{"type":37,"value":423},{"type":37,"value":6245},", training, how many revision rounds. Many cheap quotes don't include copywriting, ",{"type":32,"tag":117,"props":6247,"children":6248},{},[6249],{"type":37,"value":423},{"type":37,"value":6251}," or analytics integration.",{"type":32,"tag":169,"props":6253,"children":6255},{"id":6254},"ask-about-technologies",[6256],{"type":37,"value":6257},"Ask about technologies",{"type":32,"tag":46,"props":6259,"children":6260},{},[6261],{"type":37,"value":6262},"This isn't just a technical detail. Technology affects how easy it will be to expand the website in the future, how fast it'll run and how much maintenance will cost. Ask why the vendor chose this particular technology and what its advantages are for your specific case.",{"type":32,"tag":169,"props":6264,"children":6266},{"id":6265},"find-out-what-happens-after-launch",[6267],{"type":37,"value":6268},"Find out what happens after launch",{"type":32,"tag":46,"props":6270,"children":6271},{},[6272],{"type":37,"value":6273},"Does the vendor offer support? For how much? What if you find a bug - is warranty repair included? How much does adding a new page or feature cost? A lot of \"cheap\" websites get expensive the moment you need to change anything.",{"type":32,"tag":169,"props":6275,"children":6277},{"id":6276},"check-portfolio-and-references",[6278],{"type":37,"value":6279},"Check portfolio and references",{"type":32,"tag":46,"props":6281,"children":6282},{},[6283],{"type":37,"value":6284},"Look at websites the vendor actually built. Try opening them on mobile. Check how fast they load (e.g. via Google's PageSpeed Insights). Call one or two former clients.",{"type":32,"tag":153,"props":6286,"children":6287},{},[6288],{"type":32,"tag":157,"props":6289,"children":6290},{},[6291,6297],{"type":32,"tag":169,"props":6292,"children":6294},{"id":6293},"red-flags-in-quotes",[6295],{"type":37,"value":6296},"🚩 Red flags in quotes",{"type":32,"tag":46,"props":6298,"children":6299},{},[6300],{"type":37,"value":6301},"A suspiciously low price without explanation, unclear scope of work, no mention of responsive design, absence of deadlines and milestones, missing information about who will own the code and data. If you see any of these, ask questions. If you don't get a clear answer, look elsewhere.",{"type":32,"tag":153,"props":6303,"children":6304},{},[6305],{"type":32,"tag":157,"props":6306,"children":6307},{},[6308,6312,6318],{"type":32,"tag":161,"props":6309,"children":6311},{"src":6310,"alt":2680,"width":165,"style":166},"/article/web-accessiblity/checklist.svg",[],{"type":32,"tag":169,"props":6313,"children":6315},{"id":6314},"checklist-for-comparing-quotes",[6316],{"type":37,"value":6317},"✅ Checklist for comparing quotes",{"type":32,"tag":444,"props":6319,"children":6320},{},[6321,6326,6331,6342,6353,6358,6363,6368,6373],{"type":32,"tag":448,"props":6322,"children":6323},{},[6324],{"type":37,"value":6325},"⏹️ Is the scope clearly defined (number of pages, features)?",{"type":32,"tag":448,"props":6327,"children":6328},{},[6329],{"type":37,"value":6330},"⏹️ Does the price include custom design, or is it a template?",{"type":32,"tag":448,"props":6332,"children":6333},{},[6334,6336,6340],{"type":37,"value":6335},"⏹️ Is a ",{"type":32,"tag":117,"props":6337,"children":6338},{},[6339],{"type":37,"value":643},{"type":37,"value":6341}," for content management included?",{"type":32,"tag":448,"props":6343,"children":6344},{},[6345,6347,6351],{"type":37,"value":6346},"⏹️ Does the quote include basic ",{"type":32,"tag":117,"props":6348,"children":6349},{},[6350],{"type":37,"value":423},{"type":37,"value":6352},"?",{"type":32,"tag":448,"props":6354,"children":6355},{},[6356],{"type":37,"value":6357},"⏹️ Is a responsive mobile version mentioned?",{"type":32,"tag":448,"props":6359,"children":6360},{},[6361],{"type":37,"value":6362},"⏹️ What's the delivery timeline and how many revision rounds?",{"type":32,"tag":448,"props":6364,"children":6365},{},[6366],{"type":37,"value":6367},"⏹️ What does operation and maintenance cost after launch?",{"type":32,"tag":448,"props":6369,"children":6370},{},[6371],{"type":37,"value":6372},"⏹️ Who owns the code and data after delivery?",{"type":32,"tag":448,"props":6374,"children":6375},{},[6376],{"type":37,"value":6377},"⏹️ Is there a warranty on functionality?",{"type":32,"tag":39,"props":6379,"children":6380},{"id":774},[6381],{"type":37,"value":777},{"type":32,"tag":46,"props":6383,"children":6384},{},[6385],{"type":37,"value":6386},"Website pricing in 2026 ranges from tens of thousands for a simple business card site to millions for a complex application. The most important thing isn't finding the cheapest quote, but understanding what you're paying for and what value it brings.",{"type":32,"tag":46,"props":6388,"children":6389},{},[6390],{"type":37,"value":6391},"A company website for CZK 80,000 - 150,000 that brings you customers and represents you well is a better investment than a CZK 30,000 website that looks cheap and impresses nobody. At the same time, a CZK 300,000 website with features you don't need is unnecessary luxury.",{"type":32,"tag":46,"props":6393,"children":6394},{},[6395],{"type":37,"value":6396},"My advice - define what you actually need from the website, get at least three quotes, compare them by scope (not just price), and choose a vendor you trust and get along with. A website is a long-term project and you'll be working with your vendor for months, maybe years.",{"type":32,"tag":39,"props":6398,"children":6399},{"id":798},[6400],{"type":37,"value":6401},"Useful links",{"type":32,"tag":444,"props":6403,"children":6404},{},[6405,6414,6424,6433,6442],{"type":32,"tag":448,"props":6406,"children":6407},{},[6408],{"type":32,"tag":139,"props":6409,"children":6411},{"href":1499,":target":345,"rel":6410},[347],[6412],{"type":37,"value":6413},"PageSpeed Insights - test your website speed",{"type":32,"tag":448,"props":6415,"children":6416},{},[6417],{"type":32,"tag":139,"props":6418,"children":6421},{"href":6419,":target":345,"rel":6420},"https://www.shoptet.cz/",[347],[6422],{"type":37,"value":6423},"Shoptet - most popular Czech e-shop platform",{"type":32,"tag":448,"props":6425,"children":6426},{},[6427],{"type":32,"tag":139,"props":6428,"children":6430},{"href":3410,":target":345,"rel":6429},[347],[6431],{"type":37,"value":6432},"WordPress.org - open-source CMS",{"type":32,"tag":448,"props":6434,"children":6435},{},[6436],{"type":32,"tag":139,"props":6437,"children":6439},{"href":3426,":target":345,"rel":6438},[347],[6440],{"type":37,"value":6441},"Nuxt.js - modern Vue framework",{"type":32,"tag":448,"props":6443,"children":6444},{},[6445],{"type":32,"tag":139,"props":6446,"children":6448},{"href":2645,":target":345,"rel":6447},[347],[6449],{"type":37,"value":6450},"Let's Encrypt - free SSL certificates",{"title":8,"searchDepth":862,"depth":862,"links":6452},[6453,6454,6455,6458,6462,6463,6464,6465,6469,6475,6476],{"id":41,"depth":862,"text":44},{"id":4929,"depth":862,"text":4932},{"id":5122,"depth":862,"text":5125,"children":6456},[6457],{"id":5265,"depth":871,"text":5268},{"id":5457,"depth":862,"text":5460,"children":6459},[6460,6461],{"id":5468,"depth":871,"text":5471},{"id":5487,"depth":871,"text":5490},{"id":5614,"depth":862,"text":5617},{"id":5692,"depth":862,"text":5695},{"id":5980,"depth":862,"text":5983},{"id":6069,"depth":862,"text":6072,"children":6466},[6467,6468],{"id":6080,"depth":871,"text":6083},{"id":6143,"depth":871,"text":6146},{"id":6211,"depth":862,"text":6214,"children":6470},[6471,6472,6473,6474],{"id":6226,"depth":871,"text":6229},{"id":6254,"depth":871,"text":6257},{"id":6265,"depth":871,"text":6268},{"id":6276,"depth":871,"text":6279},{"id":774,"depth":862,"text":777},{"id":798,"depth":862,"text":6401},"content:knowledge:how-much-does-website-cost-in-2026.md","knowledge/how-much-does-website-cost-in-2026.md",{"_path":746,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":6480,"description":6481,"author":11,"date":6482,"readingTime":4900,"level":14,"image":6483,"tags":6484,"slugs":6487,"relatedArticles":6489,"body":6491,"_type":881,"_id":7344,"_source":883,"_file":7345,"_extension":885},"Will AI Replace Web Developers?","Can AI build your website? A practical look at what AI can and cannot do in web development in 2026, and when you still need a professional developer.","2026-01-16","/featured/will-ai-replace-web-developers.jpg",[6485,6486,20,895],"ai","web development",{"en":2999,"cs":6488},"nahradi-ai-webove-vyvojare",[5289,6490,3000],"what-are-spa-ssr-pwa-and-what-are-the-benefits-and-disadvantages",{"type":29,"children":6492,"toc":7317},[6493,6497,6501,6506,6516,6521,6527,6532,6609,6623,6629,6637,6642,6648,6669,6674,6704,6714,6720,6732,6766,6771,6777,6789,6824,6829,6843,6849,6861,6891,6896,6901,6906,6934,6939,6945,6950,6992,6997,7003,7011,7016,7108,7114,7122,7139,7151,7196,7208,7222,7228,7233,7291,7295,7300,7312],{"type":32,"tag":33,"props":6494,"children":6495},{"id":2999},[6496],{"type":37,"value":6480},{"type":32,"tag":39,"props":6498,"children":6499},{"id":41},[6500],{"type":37,"value":44},{"type":32,"tag":46,"props":6502,"children":6503},{},[6504],{"type":37,"value":6505},"You've seen the headlines. \"AI builds a website in 60 seconds.\" \"No-code tools make developers obsolete.\" Maybe you've tried describing your business to ChatGPT and had it generate a website for you - and the result looked pretty decent.",{"type":32,"tag":46,"props":6507,"children":6508},{},[6509,6511],{"type":37,"value":6510},"So the question makes sense: ",{"type":32,"tag":82,"props":6512,"children":6513},{},[6514],{"type":37,"value":6515},"is it still worth paying a developer when AI can do it for free?",{"type":32,"tag":46,"props":6517,"children":6518},{},[6519],{"type":37,"value":6520},"I build websites professionally and use AI tools every day. So I have a pretty clear picture of where AI helps and where it gets you into trouble.",{"type":32,"tag":39,"props":6522,"children":6524},{"id":6523},"what-ai-can-actually-do-today",[6525],{"type":37,"value":6526},"What AI Can Actually Do Today",{"type":32,"tag":46,"props":6528,"children":6529},{},[6530],{"type":37,"value":6531},"No point pretending otherwise - AI has come a long way in some areas.",{"type":32,"tag":153,"props":6533,"children":6534},{},[6535,6558,6572,6595],{"type":32,"tag":157,"props":6536,"children":6537},{},[6538,6544],{"type":32,"tag":169,"props":6539,"children":6541},{"id":6540},"️-simple-landing-page",[6542],{"type":37,"value":6543},"🖥️ Simple Landing Page",{"type":32,"tag":46,"props":6545,"children":6546},{},[6547,6549,6556],{"type":37,"value":6548},"Describe your business to ",{"type":32,"tag":139,"props":6550,"children":6553},{"href":6551,":rel":347,":target":345,"rel":6552},"https://chatgpt.com",[347],[6554],{"type":37,"value":6555},"ChatGPT",{"type":37,"value":6557}," or Claude and within minutes you'll have a working HTML page with styles. For a personal project, quick prototype or hackathon - genuinely useful.",{"type":32,"tag":157,"props":6559,"children":6560},{},[6561,6567],{"type":32,"tag":169,"props":6562,"children":6564},{"id":6563},"️-text-content",[6565],{"type":37,"value":6566},"✏️ Text Content",{"type":32,"tag":46,"props":6568,"children":6569},{},[6570],{"type":37,"value":6571},"AI can draft your \"About us\" page, product descriptions or blog posts. It's not perfect, but as a starting point it saves a lot of time.",{"type":32,"tag":157,"props":6573,"children":6574},{},[6575,6581],{"type":32,"tag":169,"props":6576,"children":6578},{"id":6577},"basic-designs",[6579],{"type":37,"value":6580},"🎨 Basic Designs",{"type":32,"tag":46,"props":6582,"children":6583},{},[6584,6586,6593],{"type":37,"value":6585},"Midjourney, DALL-E, ",{"type":32,"tag":139,"props":6587,"children":6590},{"href":6588,":rel":347,":target":345,"rel":6589},"https://v0.dev",[347],[6591],{"type":37,"value":6592},"v0 by Vercel",{"type":37,"value":6594}," - these tools can generate images and UI components from a description. For a first draft, the results often look surprisingly good.",{"type":32,"tag":157,"props":6596,"children":6597},{},[6598,6604],{"type":32,"tag":169,"props":6599,"children":6601},{"id":6600},"️-simple-applications",[6602],{"type":37,"value":6603},"⚙️ Simple Applications",{"type":32,"tag":46,"props":6605,"children":6606},{},[6607],{"type":37,"value":6608},"Contact form, basic CRUD app, simple e-commerce prototype. If your needs are standard, AI can get you to 80% of the goal.",{"type":32,"tag":157,"props":6610,"children":6611},{},[6612,6618],{"type":32,"tag":169,"props":6613,"children":6615},{"id":6614},"️-the-80-trap",[6616],{"type":37,"value":6617},"⚠️ The 80% Trap",{"type":32,"tag":46,"props":6619,"children":6620},{},[6621],{"type":37,"value":6622},"AI gets you to 80% fast. But the remaining 20% - the part that actually adapts your site to your business - is where things get complicated. And that's exactly where most AI-generated projects stall.",{"type":32,"tag":39,"props":6624,"children":6626},{"id":6625},"where-ai-falls-short",[6627],{"type":37,"value":6628},"Where AI Falls Short",{"type":32,"tag":46,"props":6630,"children":6631},{},[6632],{"type":32,"tag":161,"props":6633,"children":6636},{"alt":6634,"src":6635},"AI limitations in web development: broken SEO, security holes, poor performance","/article/will-ai-replace-web-developers/ai-falls-short.png",[],{"type":32,"tag":46,"props":6638,"children":6639},{},[6640],{"type":37,"value":6641},"This is what those \"AI builds a website in 60 seconds\" videos don't show you.",{"type":32,"tag":169,"props":6643,"children":6645},{"id":6644},"seo-that-actually-ranks",[6646],{"type":37,"value":6647},"🔍 SEO That Actually Ranks",{"type":32,"tag":46,"props":6649,"children":6650},{},[6651,6653,6658,6660,6667],{"type":37,"value":6652},"AI can generate meta tags and write content. But ",{"type":32,"tag":82,"props":6654,"children":6655},{},[6656],{"type":37,"value":6657},"SEO is not just keywords",{"type":37,"value":6659},". It's site architecture, internal linking strategy, ",{"type":32,"tag":139,"props":6661,"children":6664},{"href":6662,":rel":347,":target":345,"rel":6663},"https://web.dev/articles/vitals",[347],[6665],{"type":37,"value":6666},"Core Web Vitals",{"type":37,"value":6668},", structured data, crawlability and dozens of technical details that compound over time.",{"type":32,"tag":46,"props":6670,"children":6671},{},[6672],{"type":37,"value":6673},"An AI-generated site might look great but tank in Google because:",{"type":32,"tag":444,"props":6675,"children":6676},{},[6677,6682,6694,6699],{"type":32,"tag":448,"props":6678,"children":6679},{},[6680],{"type":37,"value":6681},"The HTML structure is semantically wrong",{"type":32,"tag":448,"props":6683,"children":6684},{},[6685,6687,6692],{"type":37,"value":6686},"Images aren't optimized (",{"type":32,"tag":139,"props":6688,"children":6689},{"href":627},[6690],{"type":37,"value":6691},"wrong formats",{"type":37,"value":6693},", no lazy loading, missing alt texts)",{"type":32,"tag":448,"props":6695,"children":6696},{},[6697],{"type":37,"value":6698},"There's no sitemap, no proper canonical URLs, no redirect strategy",{"type":32,"tag":448,"props":6700,"children":6701},{},[6702],{"type":37,"value":6703},"The page takes 5+ seconds to load because nobody optimized the bundle",{"type":32,"tag":46,"props":6705,"children":6706},{},[6707,6712],{"type":32,"tag":82,"props":6708,"children":6709},{},[6710],{"type":37,"value":6711},"Real impact:",{"type":37,"value":6713}," You save on development and then spend 10x more on ads because organic traffic never comes.",{"type":32,"tag":169,"props":6715,"children":6717},{"id":6716},"performance-and-speed",[6718],{"type":37,"value":6719},"🚀 Performance and Speed",{"type":32,"tag":46,"props":6721,"children":6722},{},[6723,6725,6730],{"type":37,"value":6724},"AI generates code that works. It rarely generates code that's ",{"type":32,"tag":82,"props":6726,"children":6727},{},[6728],{"type":37,"value":6729},"fast",{"type":37,"value":6731},". In a real project, performance depends on:",{"type":32,"tag":444,"props":6733,"children":6734},{},[6735,6746,6751,6756,6761],{"type":32,"tag":448,"props":6736,"children":6737},{},[6738,6740],{"type":37,"value":6739},"Choosing the ",{"type":32,"tag":139,"props":6741,"children":6743},{"href":6742},"/knowledge/what-are-spa-ssr-pwa-and-what-are-the-benefits-and-disadvantages",[6744],{"type":37,"value":6745},"right rendering strategy (SSR, SSG, ISR)",{"type":32,"tag":448,"props":6747,"children":6748},{},[6749],{"type":37,"value":6750},"Optimizing images, fonts and third-party scripts",{"type":32,"tag":448,"props":6752,"children":6753},{},[6754],{"type":37,"value":6755},"Code splitting, tree shaking, lazy loading",{"type":32,"tag":448,"props":6757,"children":6758},{},[6759],{"type":37,"value":6760},"Caching strategies, CDN configuration",{"type":32,"tag":448,"props":6762,"children":6763},{},[6764],{"type":37,"value":6765},"Database query optimization",{"type":32,"tag":46,"props":6767,"children":6768},{},[6769],{"type":37,"value":6770},"A better prompt won't fix this. It requires understanding how browsers, servers and networks actually work.",{"type":32,"tag":169,"props":6772,"children":6774},{"id":6773},"security",[6775],{"type":37,"value":6776},"🔒 Security",{"type":32,"tag":46,"props":6778,"children":6779},{},[6780,6782,6787],{"type":37,"value":6781},"This is where it gets ugly. AI-generated code often contains ",{"type":32,"tag":82,"props":6783,"children":6784},{},[6785],{"type":37,"value":6786},"security holes that look perfectly innocent",{"type":37,"value":6788},":",{"type":32,"tag":444,"props":6790,"children":6791},{},[6792,6804,6809,6814,6819],{"type":32,"tag":448,"props":6793,"children":6794},{},[6795,6802],{"type":32,"tag":139,"props":6796,"children":6799},{"href":6797,":rel":347,":target":345,"rel":6798},"https://owasp.org/www-community/attacks/SQL_Injection",[347],[6800],{"type":37,"value":6801},"SQL injection",{"type":37,"value":6803}," in database queries",{"type":32,"tag":448,"props":6805,"children":6806},{},[6807],{"type":37,"value":6808},"Cross-site scripting (XSS) in input fields",{"type":32,"tag":448,"props":6810,"children":6811},{},[6812],{"type":37,"value":6813},"Exposed API keys and credentials",{"type":32,"tag":448,"props":6815,"children":6816},{},[6817],{"type":37,"value":6818},"Missing authentication on API endpoints",{"type":32,"tag":448,"props":6820,"children":6821},{},[6822],{"type":37,"value":6823},"Insecure cookie handling",{"type":32,"tag":46,"props":6825,"children":6826},{},[6827],{"type":37,"value":6828},"Until someone exploits them, you don't even know the holes are there. And if customer data or payments flow through your site, that can become a very expensive problem.",{"type":32,"tag":157,"props":6830,"children":6831},{},[6832,6838],{"type":32,"tag":169,"props":6833,"children":6835},{"id":6834},"️-real-example",[6836],{"type":37,"value":6837},"⚠️ Real Example",{"type":32,"tag":46,"props":6839,"children":6840},{},[6841],{"type":37,"value":6842},"I've reviewed a few websites that clients had \"built by AI\". One had the database password hardcoded in client-side JavaScript. Another had no CSRF protection on its payment form. The owners had no idea because the sites looked and worked fine.",{"type":32,"tag":169,"props":6844,"children":6846},{"id":6845},"responsive-design-that-actually-works",[6847],{"type":37,"value":6848},"📱 Responsive Design That Actually Works",{"type":32,"tag":46,"props":6850,"children":6851},{},[6852,6854,6859],{"type":37,"value":6853},"AI can make a site look responsive in a demo. But ",{"type":32,"tag":82,"props":6855,"children":6856},{},[6857],{"type":37,"value":6858},"real responsive design",{"type":37,"value":6860}," means:",{"type":32,"tag":444,"props":6862,"children":6863},{},[6864,6869,6874,6886],{"type":32,"tag":448,"props":6865,"children":6866},{},[6867],{"type":37,"value":6868},"Testing across dozens of real devices and browsers",{"type":32,"tag":448,"props":6870,"children":6871},{},[6872],{"type":37,"value":6873},"Handling edge cases (long text, missing images, slow connections)",{"type":32,"tag":448,"props":6875,"children":6876},{},[6877,6879,6884],{"type":37,"value":6878},"Touch interactions, ",{"type":32,"tag":139,"props":6880,"children":6881},{"href":2279},[6882],{"type":37,"value":6883},"accessibility",{"type":37,"value":6885},", keyboard navigation",{"type":32,"tag":448,"props":6887,"children":6888},{},[6889],{"type":37,"value":6890},"Print stylesheets, dark mode, reduced motion preferences",{"type":32,"tag":46,"props":6892,"children":6893},{},[6894],{"type":37,"value":6895},"\"It looks good on my phone\" is not the same as \"it works for all users.\"",{"type":32,"tag":169,"props":6897,"children":6898},{"id":5802},[6899],{"type":37,"value":6900},"🔧 Maintenance and Updates",{"type":32,"tag":46,"props":6902,"children":6903},{},[6904],{"type":37,"value":6905},"A website is not a one-time project. It needs:",{"type":32,"tag":444,"props":6907,"children":6908},{},[6909,6914,6919,6924,6929],{"type":32,"tag":448,"props":6910,"children":6911},{},[6912],{"type":37,"value":6913},"Security updates for dependencies",{"type":32,"tag":448,"props":6915,"children":6916},{},[6917],{"type":37,"value":6918},"Bug fixes when browsers update",{"type":32,"tag":448,"props":6920,"children":6921},{},[6922],{"type":37,"value":6923},"Content updates that don't break the layout",{"type":32,"tag":448,"props":6925,"children":6926},{},[6927],{"type":37,"value":6928},"New features as your business grows",{"type":32,"tag":448,"props":6930,"children":6931},{},[6932],{"type":37,"value":6933},"Monitoring and error tracking",{"type":32,"tag":46,"props":6935,"children":6936},{},[6937],{"type":37,"value":6938},"AI will build you a site, but who maintains it six months later? AI-generated code tends to be hard to maintain - it lacks consistent architecture, sensible error handling and documentation.",{"type":32,"tag":169,"props":6940,"children":6942},{"id":6941},"integration-with-real-systems",[6943],{"type":37,"value":6944},"🔗 Integration with Real Systems",{"type":32,"tag":46,"props":6946,"children":6947},{},[6948],{"type":37,"value":6949},"Your business probably needs the website to connect with:",{"type":32,"tag":444,"props":6951,"children":6952},{},[6953,6967,6972,6977,6987],{"type":32,"tag":448,"props":6954,"children":6955},{},[6956,6958,6965],{"type":37,"value":6957},"Payment gateways (",{"type":32,"tag":139,"props":6959,"children":6962},{"href":6960,":rel":347,":target":345,"rel":6961},"https://stripe.com",[347],[6963],{"type":37,"value":6964},"Stripe",{"type":37,"value":6966},", PayPal, local providers)",{"type":32,"tag":448,"props":6968,"children":6969},{},[6970],{"type":37,"value":6971},"CRM systems",{"type":32,"tag":448,"props":6973,"children":6974},{},[6975],{"type":37,"value":6976},"Email marketing tools",{"type":32,"tag":448,"props":6978,"children":6979},{},[6980,6982,6986],{"type":37,"value":6981},"Analytics and tracking (properly, with ",{"type":32,"tag":139,"props":6983,"children":6984},{"href":3920},[6985],{"type":37,"value":1381},{"type":37,"value":3963},{"type":32,"tag":448,"props":6988,"children":6989},{},[6990],{"type":37,"value":6991},"Inventory management, booking systems, APIs",{"type":32,"tag":46,"props":6993,"children":6994},{},[6995],{"type":37,"value":6996},"Each integration has tons of edge cases, webhooks and security requirements. AI either skips them or solves them naively.",{"type":32,"tag":39,"props":6998,"children":7000},{"id":6999},"decision-checklist",[7001],{"type":37,"value":7002},"Decision Checklist",{"type":32,"tag":46,"props":7004,"children":7005},{},[7006],{"type":32,"tag":161,"props":7007,"children":7010},{"alt":7008,"src":7009},"AI alone vs. hiring a developer - decision comparison","/article/will-ai-replace-web-developers/decision-checklist.png",[],{"type":32,"tag":46,"props":7012,"children":7013},{},[7014],{"type":37,"value":7015},"To help you decide, I've put together a simple overview.",{"type":32,"tag":153,"props":7017,"children":7018},{},[7019,7061],{"type":32,"tag":157,"props":7020,"children":7021},{},[7022,7028],{"type":32,"tag":169,"props":7023,"children":7025},{"id":7024},"ai-alone-might-be-enough-if",[7026],{"type":37,"value":7027},"✅ AI Alone Might Be Enough If:",{"type":32,"tag":444,"props":7029,"children":7030},{},[7031,7036,7041,7046,7051,7056],{"type":32,"tag":448,"props":7032,"children":7033},{},[7034],{"type":37,"value":7035},"You need a simple personal page or portfolio",{"type":32,"tag":448,"props":7037,"children":7038},{},[7039],{"type":37,"value":7040},"It's a prototype or proof of concept",{"type":32,"tag":448,"props":7042,"children":7043},{},[7044],{"type":37,"value":7045},"You're technical enough to review and fix the code",{"type":32,"tag":448,"props":7047,"children":7048},{},[7049],{"type":37,"value":7050},"You don't depend on organic traffic",{"type":32,"tag":448,"props":7052,"children":7053},{},[7054],{"type":37,"value":7055},"You don't handle sensitive user data",{"type":32,"tag":448,"props":7057,"children":7058},{},[7059],{"type":37,"value":7060},"\"Good enough\" is good enough for you",{"type":32,"tag":157,"props":7062,"children":7063},{},[7064,7070],{"type":32,"tag":169,"props":7065,"children":7067},{"id":7066},"you-need-a-developer-when",[7068],{"type":37,"value":7069},"👨‍💻 You Need a Developer When:",{"type":32,"tag":444,"props":7071,"children":7072},{},[7073,7078,7083,7088,7093,7098,7103],{"type":32,"tag":448,"props":7074,"children":7075},{},[7076],{"type":37,"value":7077},"Your website should generate revenue",{"type":32,"tag":448,"props":7079,"children":7080},{},[7081],{"type":37,"value":7082},"You need to rank in Google for competitive keywords",{"type":32,"tag":448,"props":7084,"children":7085},{},[7086],{"type":37,"value":7087},"You handle customer data or payments",{"type":32,"tag":448,"props":7089,"children":7090},{},[7091],{"type":37,"value":7092},"You need custom functionality or integrations",{"type":32,"tag":448,"props":7094,"children":7095},{},[7096],{"type":37,"value":7097},"Your brand and reputation depend on the site quality",{"type":32,"tag":448,"props":7099,"children":7100},{},[7101],{"type":37,"value":7102},"You need long-term maintenance and evolution",{"type":32,"tag":448,"props":7104,"children":7105},{},[7106],{"type":37,"value":7107},"You need guaranteed uptime and performance",{"type":32,"tag":39,"props":7109,"children":7111},{"id":7110},"the-real-answer-developer-ai",[7112],{"type":37,"value":7113},"The Real Answer: Developer + AI",{"type":32,"tag":46,"props":7115,"children":7116},{},[7117],{"type":32,"tag":161,"props":7118,"children":7121},{"alt":7119,"src":7120},"Developer collaborating with AI for faster, cheaper, better results","/article/will-ai-replace-web-developers/developer-plus-ai.png",[],{"type":32,"tag":46,"props":7123,"children":7124},{},[7125,7127,7132,7134],{"type":37,"value":7126},"Most people ask this question wrong. It's not ",{"type":32,"tag":82,"props":7128,"children":7129},{},[7130],{"type":37,"value":7131},"\"AI or developer?\"",{"type":37,"value":7133}," but ",{"type":32,"tag":82,"props":7135,"children":7136},{},[7137],{"type":37,"value":7138},"\"developer without AI or developer with AI?\"",{"type":32,"tag":46,"props":7140,"children":7141},{},[7142,7144,7149],{"type":37,"value":7143},"A developer who ",{"type":32,"tag":139,"props":7145,"children":7146},{"href":5276},[7147],{"type":37,"value":7148},"uses AI effectively",{"type":37,"value":7150}," delivers:",{"type":32,"tag":153,"props":7152,"children":7153},{},[7154,7168,7182],{"type":32,"tag":157,"props":7155,"children":7156},{},[7157,7163],{"type":32,"tag":169,"props":7158,"children":7160},{"id":7159},"️-faster",[7161],{"type":37,"value":7162},"🏎️ Faster",{"type":32,"tag":46,"props":7164,"children":7165},{},[7166],{"type":37,"value":7167},"AI handles boilerplate, the developer focuses on what matters.",{"type":32,"tag":157,"props":7169,"children":7170},{},[7171,7177],{"type":32,"tag":169,"props":7172,"children":7174},{"id":7173},"cheaper",[7175],{"type":37,"value":7176},"💰 Cheaper",{"type":32,"tag":46,"props":7178,"children":7179},{},[7180],{"type":37,"value":7181},"Less time on repetitive tasks means lower cost for you.",{"type":32,"tag":157,"props":7183,"children":7184},{},[7185,7191],{"type":32,"tag":169,"props":7186,"children":7188},{"id":7187},"better-quality",[7189],{"type":37,"value":7190},"🎯 Better Quality",{"type":32,"tag":46,"props":7192,"children":7193},{},[7194],{"type":37,"value":7195},"AI catches bugs, suggests improvements, writes tests.",{"type":32,"tag":46,"props":7197,"children":7198},{},[7199,7201,7206],{"type":37,"value":7200},"When you hire a developer who knows how to use AI, you're not paying for typing code. You're paying for someone who ",{"type":32,"tag":82,"props":7202,"children":7203},{},[7204],{"type":37,"value":7205},"knows what to build and why",{"type":37,"value":7207}," - and uses everything at their disposal to get it done.",{"type":32,"tag":157,"props":7209,"children":7210},{},[7211,7217],{"type":32,"tag":169,"props":7212,"children":7214},{"id":7213},"building-analogy",[7215],{"type":37,"value":7216},"🏠 Building Analogy",{"type":32,"tag":46,"props":7218,"children":7219},{},[7220],{"type":37,"value":7221},"You don't buy a drill and build a house. But a carpenter with a drill is faster than one without. Same goes for AI.",{"type":32,"tag":39,"props":7223,"children":7225},{"id":7224},"what-to-look-for-in-a-developer-in-2026",[7226],{"type":37,"value":7227},"What to Look For in a Developer in 2026",{"type":32,"tag":46,"props":7229,"children":7230},{},[7231],{"type":37,"value":7232},"If you're looking for a developer for a serious project, here's what matters today:",{"type":32,"tag":6221,"props":7234,"children":7235},{},[7236,7242,7247,7253,7258,7264,7269,7275,7280,7286],{"type":32,"tag":169,"props":7237,"children":7239},{"id":7238},"uses-ai-tools",[7240],{"type":37,"value":7241},"Uses AI tools",{"type":32,"tag":46,"props":7243,"children":7244},{},[7245],{"type":37,"value":7246},"If a developer doesn't use AI in 2026, they'll likely be slower and more expensive than one who does.",{"type":32,"tag":169,"props":7248,"children":7250},{"id":7249},"asks-about-your-business",[7251],{"type":37,"value":7252},"Asks about your business",{"type":32,"tag":46,"props":7254,"children":7255},{},[7256],{"type":37,"value":7257},"Before they start coding, they want to know what problem you're solving, who your customers are and what you measure.",{"type":32,"tag":169,"props":7259,"children":7261},{"id":7260},"thinks-ahead",[7262],{"type":37,"value":7263},"Thinks ahead",{"type":32,"tag":46,"props":7265,"children":7266},{},[7267],{"type":37,"value":7268},"Not just whether it works now, but whether it can be maintained and extended.",{"type":32,"tag":169,"props":7270,"children":7272},{"id":7271},"communicates-clearly",[7273],{"type":37,"value":7274},"Communicates clearly",{"type":32,"tag":46,"props":7276,"children":7277},{},[7278],{"type":37,"value":7279},"You should understand what's being built and why, even if you don't understand the code.",{"type":32,"tag":169,"props":7281,"children":7283},{"id":7282},"shows-results",[7284],{"type":37,"value":7285},"Shows results",{"type":32,"tag":46,"props":7287,"children":7288},{},[7289],{"type":37,"value":7290},"Site speed, Google rankings, conversions. That's how their work should be measured.",{"type":32,"tag":39,"props":7292,"children":7293},{"id":774},[7294],{"type":37,"value":777},{"type":32,"tag":46,"props":7296,"children":7297},{},[7298],{"type":37,"value":7299},"AI has changed how websites are built. That's a fact.",{"type":32,"tag":46,"props":7301,"children":7302},{},[7303,7305,7310],{"type":37,"value":7304},"For a prototype or personal page, AI might be enough on its own. But if your website is supposed to ",{"type":32,"tag":82,"props":7306,"children":7307},{},[7308],{"type":37,"value":7309},"make money and represent your company",{"type":37,"value":7311},", you need someone who knows what they're doing - with AI helping them along the way.",{"type":32,"tag":46,"props":7313,"children":7314},{},[7315],{"type":37,"value":7316},"Look for developers who use AI as a tool, not as a replacement for experience.",{"title":8,"searchDepth":862,"depth":862,"links":7318},[7319,7320,7323,7332,7333,7336,7343],{"id":41,"depth":862,"text":44},{"id":6523,"depth":862,"text":6526,"children":7321},[7322],{"id":6614,"depth":871,"text":6617},{"id":6625,"depth":862,"text":6628,"children":7324},[7325,7326,7327,7328,7329,7330,7331],{"id":6644,"depth":871,"text":6647},{"id":6716,"depth":871,"text":6719},{"id":6773,"depth":871,"text":6776},{"id":6834,"depth":871,"text":6837},{"id":6845,"depth":871,"text":6848},{"id":5802,"depth":871,"text":6900},{"id":6941,"depth":871,"text":6944},{"id":6999,"depth":862,"text":7002},{"id":7110,"depth":862,"text":7113,"children":7334},[7335],{"id":7213,"depth":871,"text":7216},{"id":7224,"depth":862,"text":7227,"children":7337},[7338,7339,7340,7341,7342],{"id":7238,"depth":871,"text":7241},{"id":7249,"depth":871,"text":7252},{"id":7260,"depth":871,"text":7263},{"id":7271,"depth":871,"text":7274},{"id":7282,"depth":871,"text":7285},{"id":774,"depth":862,"text":777},"content:knowledge:will-ai-replace-web-developers.md","knowledge/will-ai-replace-web-developers.md",{"_path":5276,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":7347,"description":7348,"author":11,"date":7349,"readingTime":7350,"level":14,"image":7351,"tags":7352,"slugs":7355,"relatedArticles":7357,"body":7359,"_type":881,"_id":8572,"_source":883,"_file":8573,"_extension":885},"AI-Assisted Web Application Development","How to use AI tools in web development? Practical tips, real workflows, and personal experience with AI assistants in everyday coding.","2026-01-08",15,"/featured/ai-asisted-development.jpg",[6485,7353,7354,895],"tools","effectivity",{"en":5289,"cs":7356},"ai-asistovany-vyvoj-webovych-aplikaci",[2999,7358,6490],"vs-code-10-most-useful-tips-you-may-not-know",{"type":29,"children":7360,"toc":8547},[7361,7365,7369,7381,7393,7399,7411,7417,7480,7486,7528,7549,7555,7563,7568,7574,7593,7601,7653,7663,7678,7683,7689,7701,7709,7752,7757,7763,7782,7790,7813,7821,7839,7844,7850,8037,8043,8051,8063,8069,8081,8086,8092,8104,8109,8115,8134,8145,8156,8189,8201,8207,8219,8242,8254,8260,8272,8291,8303,8309,8314,8394,8400,8405,8448,8460,8464,8476,8481,8492,8496],{"type":32,"tag":33,"props":7362,"children":7363},{"id":5289},[7364],{"type":37,"value":7347},{"type":32,"tag":39,"props":7366,"children":7367},{"id":41},[7368],{"type":37,"value":44},{"type":32,"tag":46,"props":7370,"children":7371},{},[7372,7374,7379],{"type":37,"value":7373},"A few years ago, if someone told you that you'd have a colleague in your editor who never sleeps, doesn't need coffee, and can write regex for you - you wouldn't believe them. Yet here we are in 2026. ",{"type":32,"tag":82,"props":7375,"children":7376},{},[7377],{"type":37,"value":7378},"AI tools have become part of the developer workflow",{"type":37,"value":7380}," and it's no longer just hype, but a real tool that can save you hours of work.",{"type":32,"tag":46,"props":7382,"children":7383},{},[7384,7386,7391],{"type":37,"value":7385},"In this article, we'll look at how to actually use AI assistants in web application development - not just for generating hello world examples, but in a ",{"type":32,"tag":82,"props":7387,"children":7388},{},[7389],{"type":37,"value":7390},"real everyday workflow",{"type":37,"value":7392},". I'll share my experience, show concrete examples, and also tell you where AI fails and what to watch out for.",{"type":32,"tag":39,"props":7394,"children":7396},{"id":7395},"what-ai-assistants-can-and-cant-do",[7397],{"type":37,"value":7398},"What AI Assistants Can (and Can't) Do",{"type":32,"tag":46,"props":7400,"children":7401},{},[7402,7404,7409],{"type":37,"value":7403},"Before we dive into specific tools, let's clarify ",{"type":32,"tag":82,"props":7405,"children":7406},{},[7407],{"type":37,"value":7408},"what you can realistically expect from AI",{"type":37,"value":7410}," and where you should remain vigilant.",{"type":32,"tag":169,"props":7412,"children":7414},{"id":7413},"where-ai-excels",[7415],{"type":37,"value":7416},"Where AI Excels",{"type":32,"tag":444,"props":7418,"children":7419},{},[7420,7430,7440,7450,7460,7470],{"type":32,"tag":448,"props":7421,"children":7422},{},[7423,7428],{"type":32,"tag":82,"props":7424,"children":7425},{},[7426],{"type":37,"value":7427},"Generating boilerplate code",{"type":37,"value":7429}," - components, CRUD operations, configuration",{"type":32,"tag":448,"props":7431,"children":7432},{},[7433,7438],{"type":32,"tag":82,"props":7434,"children":7435},{},[7436],{"type":37,"value":7437},"Refactoring",{"type":37,"value":7439}," - rewriting code into cleaner form, renaming variables in context",{"type":32,"tag":448,"props":7441,"children":7442},{},[7443,7448],{"type":32,"tag":82,"props":7444,"children":7445},{},[7446],{"type":37,"value":7447},"Writing tests",{"type":37,"value":7449}," - unit tests, edge cases you wouldn't think of",{"type":32,"tag":448,"props":7451,"children":7452},{},[7453,7458],{"type":32,"tag":82,"props":7454,"children":7455},{},[7456],{"type":37,"value":7457},"Debugging",{"type":37,"value":7459}," - analyzing error messages, suggesting fixes",{"type":32,"tag":448,"props":7461,"children":7462},{},[7463,7468],{"type":32,"tag":82,"props":7464,"children":7465},{},[7466],{"type":37,"value":7467},"Documentation",{"type":37,"value":7469}," - JSDoc comments, README files, API documentation",{"type":32,"tag":448,"props":7471,"children":7472},{},[7473,7478],{"type":32,"tag":82,"props":7474,"children":7475},{},[7476],{"type":37,"value":7477},"Learning",{"type":37,"value":7479}," - explaining unfamiliar code, technologies, concepts",{"type":32,"tag":169,"props":7481,"children":7483},{"id":7482},"where-ai-still-struggles",[7484],{"type":37,"value":7485},"Where AI Still Struggles",{"type":32,"tag":444,"props":7487,"children":7488},{},[7489,7499,7508,7518],{"type":32,"tag":448,"props":7490,"children":7491},{},[7492,7497],{"type":32,"tag":82,"props":7493,"children":7494},{},[7495],{"type":37,"value":7496},"Complex architectural decisions",{"type":37,"value":7498}," - AI doesn't have the context of your business",{"type":32,"tag":448,"props":7500,"children":7501},{},[7502,7506],{"type":32,"tag":82,"props":7503,"children":7504},{},[7505],{"type":37,"value":6206},{"type":37,"value":7507}," - blindly trusting AI-generated code for authentication or validation is risky",{"type":32,"tag":448,"props":7509,"children":7510},{},[7511,7516],{"type":32,"tag":82,"props":7512,"children":7513},{},[7514],{"type":37,"value":7515},"Currency",{"type":37,"value":7517}," - models have a knowledge cutoff and may suggest outdated approaches",{"type":32,"tag":448,"props":7519,"children":7520},{},[7521,7526],{"type":32,"tag":82,"props":7522,"children":7523},{},[7524],{"type":37,"value":7525},"Specific domain context",{"type":37,"value":7527}," - your unique tech stack and conventions are unknown to AI",{"type":32,"tag":157,"props":7529,"children":7530},{},[7531,7537],{"type":32,"tag":169,"props":7532,"children":7534},{"id":7533},"️-important-rule",[7535],{"type":37,"value":7536},"⚠️ Important Rule",{"type":32,"tag":46,"props":7538,"children":7539},{},[7540,7542,7547],{"type":37,"value":7541},"AI is an ",{"type":32,"tag":82,"props":7543,"children":7544},{},[7545],{"type":37,"value":7546},"assistant, not an author",{"type":37,"value":7548},". Always review generated code, understand it, and don't blindly rely on the output. You are the one responsible for code quality.",{"type":32,"tag":39,"props":7550,"children":7552},{"id":7551},"tools-worth-your-attention",[7553],{"type":37,"value":7554},"Tools Worth Your Attention",{"type":32,"tag":46,"props":7556,"children":7557},{},[7558],{"type":32,"tag":161,"props":7559,"children":7562},{"alt":7560,"src":7561},"AI development tools","/article/ai-assisted-web-application-development/ai-tools.png",[],{"type":32,"tag":46,"props":7564,"children":7565},{},[7566],{"type":37,"value":7567},"Let's look at specific tools you can start using today.",{"type":32,"tag":169,"props":7569,"children":7571},{"id":7570},"claude-code-anthropic",[7572],{"type":37,"value":7573},"🧠 Claude Code (Anthropic)",{"type":32,"tag":46,"props":7575,"children":7576},{},[7577,7579,7584,7586,7591],{"type":37,"value":7578},"Claude Code is a ",{"type":32,"tag":82,"props":7580,"children":7581},{},[7582],{"type":37,"value":7583},"CLI tool from Anthropic",{"type":37,"value":7585}," that lets you work with AI directly in the terminal and across your entire project. This isn't a chatbot where you copy-paste code snippets - Claude Code sees ",{"type":32,"tag":82,"props":7587,"children":7588},{},[7589],{"type":37,"value":7590},"your entire repository",{"type":37,"value":7592},", reads files, searches code, and suggests changes in context.",{"type":32,"tag":46,"props":7594,"children":7595},{},[7596],{"type":32,"tag":82,"props":7597,"children":7598},{},[7599],{"type":37,"value":7600},"Why I use it as my main tool:",{"type":32,"tag":444,"props":7602,"children":7603},{},[7604,7614,7624,7633,7643],{"type":32,"tag":448,"props":7605,"children":7606},{},[7607,7612],{"type":32,"tag":82,"props":7608,"children":7609},{},[7610],{"type":37,"value":7611},"Understands the entire project",{"type":37,"value":7613}," - you don't need to send individual files, it finds what it needs on its own",{"type":32,"tag":448,"props":7615,"children":7616},{},[7617,7622],{"type":32,"tag":82,"props":7618,"children":7619},{},[7620],{"type":37,"value":7621},"Cross-file refactoring",{"type":37,"value":7623}," - \"rename this composable and update all imports\"",{"type":32,"tag":448,"props":7625,"children":7626},{},[7627,7631],{"type":32,"tag":82,"props":7628,"children":7629},{},[7630],{"type":37,"value":7457},{"type":37,"value":7632}," - I paste an error message and Claude Code looks into relevant files on its own",{"type":32,"tag":448,"props":7634,"children":7635},{},[7636,7641],{"type":32,"tag":82,"props":7637,"children":7638},{},[7639],{"type":37,"value":7640},"Architecture planning",{"type":37,"value":7642}," - \"how would you solve XY in Nuxt 3?\" with full project context",{"type":32,"tag":448,"props":7644,"children":7645},{},[7646,7651],{"type":32,"tag":82,"props":7647,"children":7648},{},[7649],{"type":37,"value":7650},"Code review",{"type":37,"value":7652}," - it reviews code and points out weak spots",{"type":32,"tag":46,"props":7654,"children":7655},{},[7656,7661],{"type":32,"tag":82,"props":7657,"children":7658},{},[7659],{"type":37,"value":7660},"Practical example",{"type":37,"value":7662}," - I tell Claude Code what I want and it suggests implementation directly in the project:",{"type":32,"tag":7664,"props":7665,"children":7669},"code",{"code":7666,"language":7667,"meta":7668},"# Claude Code works directly with your files\r\nclaude \"Create a Vue component for form validation with email and debounce\"\r\n\r\n# Or debugging - just describe the problem\r\nclaude \"I have a hydration mismatch on the /knowledge page, find the cause\"\n","bash",null,[7670],{"type":32,"tag":7671,"props":7672,"children":7673},"pre",{},[7674],{"type":32,"tag":7664,"props":7675,"children":7676},{"__ignoreMap":8},[7677],{"type":37,"value":7666},{"type":32,"tag":46,"props":7679,"children":7680},{},[7681],{"type":37,"value":7682},"Claude Code is also available as a VS Code extension and within the Cursor editor, so you can integrate it into your favorite environment.",{"type":32,"tag":169,"props":7684,"children":7686},{"id":7685},"cursor",[7687],{"type":37,"value":7688},"⚡ Cursor",{"type":32,"tag":46,"props":7690,"children":7691},{},[7692,7694,7699],{"type":37,"value":7693},"Cursor is a ",{"type":32,"tag":82,"props":7695,"children":7696},{},[7697],{"type":37,"value":7698},"fork of VS Code",{"type":37,"value":7700}," with deeply integrated AI. Imagine VS Code where AI is a first-class citizen - not just an extension, but part of the entire editor.",{"type":32,"tag":46,"props":7702,"children":7703},{},[7704],{"type":32,"tag":82,"props":7705,"children":7706},{},[7707],{"type":37,"value":7708},"Interesting features:",{"type":32,"tag":444,"props":7710,"children":7711},{},[7712,7722,7732,7742],{"type":32,"tag":448,"props":7713,"children":7714},{},[7715,7720],{"type":32,"tag":82,"props":7716,"children":7717},{},[7718],{"type":37,"value":7719},"Composer",{"type":37,"value":7721}," - describe a change in natural language and Cursor modifies multiple files at once",{"type":32,"tag":448,"props":7723,"children":7724},{},[7725,7730],{"type":32,"tag":82,"props":7726,"children":7727},{},[7728],{"type":37,"value":7729},"Chat with context",{"type":37,"value":7731}," - automatically indexes the entire project",{"type":32,"tag":448,"props":7733,"children":7734},{},[7735,7740],{"type":32,"tag":82,"props":7736,"children":7737},{},[7738],{"type":37,"value":7739},"Apply",{"type":37,"value":7741}," - apply suggested changes with a single click",{"type":32,"tag":448,"props":7743,"children":7744},{},[7745,7750],{"type":32,"tag":82,"props":7746,"children":7747},{},[7748],{"type":37,"value":7749},"Tab completion",{"type":37,"value":7751}," - inline autocomplete that understands the surrounding code context",{"type":32,"tag":46,"props":7753,"children":7754},{},[7755],{"type":37,"value":7756},"Under the hood, Cursor uses various models (including Claude) and combines them with its own project indexing. It's a great choice if you want AI integrated directly into your editor without switching between tools.",{"type":32,"tag":169,"props":7758,"children":7760},{"id":7759},"openai-codex",[7761],{"type":37,"value":7762},"🔮 OpenAI Codex",{"type":32,"tag":46,"props":7764,"children":7765},{},[7766,7768,7773,7775,7780],{"type":37,"value":7767},"Codex is a ",{"type":32,"tag":82,"props":7769,"children":7770},{},[7771],{"type":37,"value":7772},"cloud-based AI agent from OpenAI",{"type":37,"value":7774}," that works in a sandboxed environment. Unlike local tools, Codex receives a task, creates its own environment, clones the repository, and ",{"type":32,"tag":82,"props":7776,"children":7777},{},[7778],{"type":37,"value":7779},"works autonomously",{"type":37,"value":7781}," - writing code, running tests, and preparing a pull request.",{"type":32,"tag":46,"props":7783,"children":7784},{},[7785],{"type":32,"tag":82,"props":7786,"children":7787},{},[7788],{"type":37,"value":7789},"How it works:",{"type":32,"tag":444,"props":7791,"children":7792},{},[7793,7798,7803,7808],{"type":32,"tag":448,"props":7794,"children":7795},{},[7796],{"type":37,"value":7797},"You assign a task in natural language directly from ChatGPT or via API",{"type":32,"tag":448,"props":7799,"children":7800},{},[7801],{"type":37,"value":7802},"Codex creates an isolated environment and works in the background",{"type":32,"tag":448,"props":7804,"children":7805},{},[7806],{"type":37,"value":7807},"Upon completion, you get a diff with proposed changes",{"type":32,"tag":448,"props":7809,"children":7810},{},[7811],{"type":37,"value":7812},"Suitable for parallel processing of multiple tasks at once",{"type":32,"tag":46,"props":7814,"children":7815},{},[7816],{"type":32,"tag":82,"props":7817,"children":7818},{},[7819],{"type":37,"value":7820},"Where it makes sense:",{"type":32,"tag":444,"props":7822,"children":7823},{},[7824,7829,7834],{"type":32,"tag":448,"props":7825,"children":7826},{},[7827],{"type":37,"value":7828},"Simpler feature requests and bug fixes",{"type":32,"tag":448,"props":7830,"children":7831},{},[7832],{"type":37,"value":7833},"Automatic fixes from the issue tracker",{"type":32,"tag":448,"props":7835,"children":7836},{},[7837],{"type":37,"value":7838},"Tasks where you don't need real-time interaction",{"type":32,"tag":46,"props":7840,"children":7841},{},[7842],{"type":37,"value":7843},"It's a slightly different approach than Claude Code or Cursor - instead of real-time collaboration, you assign a task and come back to the result. It works well as a complement to interactive tools.",{"type":32,"tag":169,"props":7845,"children":7847},{"id":7846},"tool-comparison",[7848],{"type":37,"value":7849},"Tool Comparison",{"type":32,"tag":1559,"props":7851,"children":7852},{},[7853,7879],{"type":32,"tag":1563,"props":7854,"children":7855},{},[7856],{"type":32,"tag":1567,"props":7857,"children":7858},{},[7859,7864,7869,7874],{"type":32,"tag":1571,"props":7860,"children":7861},{"align":7668},[7862],{"type":37,"value":7863},"Feature",{"type":32,"tag":1571,"props":7865,"children":7866},{"align":7668},[7867],{"type":37,"value":7868},"Claude Code",{"type":32,"tag":1571,"props":7870,"children":7871},{"align":7668},[7872],{"type":37,"value":7873},"Cursor",{"type":32,"tag":1571,"props":7875,"children":7876},{"align":7668},[7877],{"type":37,"value":7878},"Codex",{"type":32,"tag":1588,"props":7880,"children":7881},{},[7882,7905,7926,7948,7969,7991,8014],{"type":32,"tag":1567,"props":7883,"children":7884},{},[7885,7890,7895,7900],{"type":32,"tag":1595,"props":7886,"children":7887},{"align":7668},[7888],{"type":37,"value":7889},"Inline autocomplete",{"type":32,"tag":1595,"props":7891,"children":7892},{"align":7668},[7893],{"type":37,"value":7894},"❌ No (but yes in Cursor)",{"type":32,"tag":1595,"props":7896,"children":7897},{"align":7668},[7898],{"type":37,"value":7899},"✅ Excellent",{"type":32,"tag":1595,"props":7901,"children":7902},{"align":7668},[7903],{"type":37,"value":7904},"❌ No",{"type":32,"tag":1567,"props":7906,"children":7907},{},[7908,7913,7917,7921],{"type":32,"tag":1595,"props":7909,"children":7910},{"align":7668},[7911],{"type":37,"value":7912},"Chat / Dialog",{"type":32,"tag":1595,"props":7914,"children":7915},{"align":7668},[7916],{"type":37,"value":7899},{"type":32,"tag":1595,"props":7918,"children":7919},{"align":7668},[7920],{"type":37,"value":7899},{"type":32,"tag":1595,"props":7922,"children":7923},{"align":7668},[7924],{"type":37,"value":7925},"⚠️ Asynchronous",{"type":32,"tag":1567,"props":7927,"children":7928},{},[7929,7934,7939,7943],{"type":32,"tag":1595,"props":7930,"children":7931},{"align":7668},[7932],{"type":37,"value":7933},"Full project context",{"type":32,"tag":1595,"props":7935,"children":7936},{"align":7668},[7937],{"type":37,"value":7938},"✅ Yes",{"type":32,"tag":1595,"props":7940,"children":7941},{"align":7668},[7942],{"type":37,"value":7938},{"type":32,"tag":1595,"props":7944,"children":7945},{"align":7668},[7946],{"type":37,"value":7947},"✅ Yes (clones repo)",{"type":32,"tag":1567,"props":7949,"children":7950},{},[7951,7956,7960,7965],{"type":32,"tag":1595,"props":7952,"children":7953},{"align":7668},[7954],{"type":37,"value":7955},"Multifile edits",{"type":32,"tag":1595,"props":7957,"children":7958},{"align":7668},[7959],{"type":37,"value":7938},{"type":32,"tag":1595,"props":7961,"children":7962},{"align":7668},[7963],{"type":37,"value":7964},"✅ Composer",{"type":32,"tag":1595,"props":7966,"children":7967},{"align":7668},[7968],{"type":37,"value":7938},{"type":32,"tag":1567,"props":7970,"children":7971},{},[7972,7977,7982,7986],{"type":32,"tag":1595,"props":7973,"children":7974},{"align":7668},[7975],{"type":37,"value":7976},"Autonomous work",{"type":32,"tag":1595,"props":7978,"children":7979},{"align":7668},[7980],{"type":37,"value":7981},"⚠️ With confirmation",{"type":32,"tag":1595,"props":7983,"children":7984},{"align":7668},[7985],{"type":37,"value":7981},{"type":32,"tag":1595,"props":7987,"children":7988},{"align":7668},[7989],{"type":37,"value":7990},"✅ Fully autonomous",{"type":32,"tag":1567,"props":7992,"children":7993},{},[7994,7999,8004,8009],{"type":32,"tag":1595,"props":7995,"children":7996},{"align":7668},[7997],{"type":37,"value":7998},"Environment",{"type":32,"tag":1595,"props":8000,"children":8001},{"align":7668},[8002],{"type":37,"value":8003},"CLI, VS Code, Cursor",{"type":32,"tag":1595,"props":8005,"children":8006},{"align":7668},[8007],{"type":37,"value":8008},"Custom editor",{"type":32,"tag":1595,"props":8010,"children":8011},{"align":7668},[8012],{"type":37,"value":8013},"Cloud sandbox",{"type":32,"tag":1567,"props":8015,"children":8016},{},[8017,8022,8027,8032],{"type":32,"tag":1595,"props":8018,"children":8019},{"align":7668},[8020],{"type":37,"value":8021},"Price (monthly)",{"type":32,"tag":1595,"props":8023,"children":8024},{"align":7668},[8025],{"type":37,"value":8026},"Various plans",{"type":32,"tag":1595,"props":8028,"children":8029},{"align":7668},[8030],{"type":37,"value":8031},"~20 USD",{"type":32,"tag":1595,"props":8033,"children":8034},{"align":7668},[8035],{"type":37,"value":8036},"Part of ChatGPT Pro/Team",{"type":32,"tag":39,"props":8038,"children":8040},{"id":8039},"my-workflow-with-ai",[8041],{"type":37,"value":8042},"My Workflow with AI",{"type":32,"tag":46,"props":8044,"children":8045},{},[8046],{"type":32,"tag":161,"props":8047,"children":8050},{"alt":8048,"src":8049},"AI workflow","/article/ai-assisted-web-application-development/ai-workflow.png",[],{"type":32,"tag":46,"props":8052,"children":8053},{},[8054,8056,8061],{"type":37,"value":8055},"Many people use AI in a \"just write this for me\" fashion and call it done. Over time, I've developed a ",{"type":32,"tag":82,"props":8057,"children":8058},{},[8059],{"type":37,"value":8060},"structured workflow",{"type":37,"value":8062}," that gives me much better results. Let's walk through it step by step.",{"type":32,"tag":169,"props":8064,"children":8066},{"id":8065},"_1️⃣-the-plan",[8067],{"type":37,"value":8068},"1️⃣ The Plan",{"type":32,"tag":46,"props":8070,"children":8071},{},[8072,8074,8079],{"type":37,"value":8073},"Everything starts with a plan. I don't jump straight into code - first I ",{"type":32,"tag":82,"props":8075,"children":8076},{},[8077],{"type":37,"value":8078},"write down what I want to do",{"type":37,"value":8080},", what the requirements are, what components will be needed, and how it all fits together. I then pass this plan to AI as context.",{"type":32,"tag":46,"props":8082,"children":8083},{},[8084],{"type":37,"value":8085},"For example: \"I need to create article filtering by tags. It will be a Vue composable that takes an array of articles and returns a reactive filtered list. The filter is saved to URL query parameters.\"",{"type":32,"tag":169,"props":8087,"children":8089},{"id":8088},"_2️⃣-plan-verification",[8090],{"type":37,"value":8091},"2️⃣ Plan Verification",{"type":32,"tag":46,"props":8093,"children":8094},{},[8095,8097,8102],{"type":37,"value":8096},"This is the step many people skip - and that's a shame. I let AI ",{"type":32,"tag":82,"props":8098,"children":8099},{},[8100],{"type":37,"value":8101},"review my plan and find the gaps",{"type":37,"value":8103},". What did I overlook? What edge cases might occur? Does the architecture make sense?",{"type":32,"tag":46,"props":8105,"children":8106},{},[8107],{"type":37,"value":8108},"AI sees things from a different angle and often reveals problems that would only occur to me during implementation. For instance: \"What happens when a user enters a tag that doesn't exist? How will this work with SSR? Shouldn't you add debounce to the URL update?\"",{"type":32,"tag":169,"props":8110,"children":8112},{"id":8111},"_3️⃣-implementation-with-tests",[8113],{"type":37,"value":8114},"3️⃣ Implementation with Tests",{"type":32,"tag":46,"props":8116,"children":8117},{},[8118,8120,8125,8127,8132],{"type":37,"value":8119},"Only now comes the actual coding. For this I have a ",{"type":32,"tag":82,"props":8121,"children":8122},{},[8123],{"type":37,"value":8124},"custom slash command",{"type":37,"value":8126}," in Claude Code - I just call ",{"type":32,"tag":117,"props":8128,"children":8129},{},[8130],{"type":37,"value":8131},"/implement",{"type":37,"value":8133}," with a reference to the plan file and Claude Code takes care of the rest:",{"type":32,"tag":7664,"props":8135,"children":8137},{"code":8136,"language":7667,"meta":7668},"/implement plan-name.md\n",[8138],{"type":32,"tag":7671,"props":8139,"children":8140},{},[8141],{"type":32,"tag":7664,"props":8142,"children":8143},{"__ignoreMap":8},[8144],{"type":37,"value":8136},{"type":32,"tag":46,"props":8146,"children":8147},{},[8148,8150,8155],{"type":37,"value":8149},"This command ensures that ",{"type":32,"tag":82,"props":8151,"children":8152},{},[8153],{"type":37,"value":8154},"AI doesn't just implement the feature, but also the tests right away",{"type":37,"value":6788},{"type":32,"tag":444,"props":8157,"children":8158},{},[8159,8169,8179],{"type":32,"tag":448,"props":8160,"children":8161},{},[8162,8167],{"type":32,"tag":82,"props":8163,"children":8164},{},[8165],{"type":37,"value":8166},"Unit tests",{"type":37,"value":8168}," - testing individual functions and composables",{"type":32,"tag":448,"props":8170,"children":8171},{},[8172,8177],{"type":32,"tag":82,"props":8173,"children":8174},{},[8175],{"type":37,"value":8176},"E2E tests",{"type":37,"value":8178}," - the entire user flow from A to Z",{"type":32,"tag":448,"props":8180,"children":8181},{},[8182,8187],{"type":32,"tag":82,"props":8183,"children":8184},{},[8185],{"type":37,"value":8186},"Playwright tests",{"type":37,"value":8188}," - visual and interaction testing via MCP server",{"type":32,"tag":46,"props":8190,"children":8191},{},[8192,8194,8199],{"type":37,"value":8193},"No need to manually type or copy context - the slash command loads the plan and knows what to do. Tests are an integral part of implementation, not something to \"add later.\" This gives me ",{"type":32,"tag":82,"props":8195,"children":8196},{},[8197],{"type":37,"value":8198},"confidence that the code works",{"type":37,"value":8200}," before I even look at it.",{"type":32,"tag":169,"props":8202,"children":8204},{"id":8203},"_4️⃣-manual-testing-and-code-review",[8205],{"type":37,"value":8206},"4️⃣ Manual Testing and Code Review",{"type":32,"tag":46,"props":8208,"children":8209},{},[8210,8212,8217],{"type":37,"value":8211},"This is the step I ",{"type":32,"tag":82,"props":8213,"children":8214},{},[8215],{"type":37,"value":8216},"never skip",{"type":37,"value":8218},". I go through the generated code line by line, run the application, and manually test it. I ask myself:",{"type":32,"tag":444,"props":8220,"children":8221},{},[8222,8227,8232,8237],{"type":32,"tag":448,"props":8223,"children":8224},{},[8225],{"type":37,"value":8226},"Does this code make sense?",{"type":32,"tag":448,"props":8228,"children":8229},{},[8230],{"type":37,"value":8231},"Is it readable and maintainable?",{"type":32,"tag":448,"props":8233,"children":8234},{},[8235],{"type":37,"value":8236},"Are the tests actually meaningful, or just there \"to exist\"?",{"type":32,"tag":448,"props":8238,"children":8239},{},[8240],{"type":37,"value":8241},"Does it work correctly in the browser?",{"type":32,"tag":46,"props":8243,"children":8244},{},[8245,8247,8252],{"type":37,"value":8246},"AI can write code that passes tests, but it ",{"type":32,"tag":82,"props":8248,"children":8249},{},[8250],{"type":37,"value":8251},"isn't necessarily good code",{"type":37,"value":8253},". Code review is where you bring your expertise into the equation.",{"type":32,"tag":169,"props":8255,"children":8257},{"id":8256},"_5️⃣-feedback-loop",[8258],{"type":37,"value":8259},"5️⃣ Feedback Loop",{"type":32,"tag":46,"props":8261,"children":8262},{},[8263,8265,8270],{"type":37,"value":8264},"The final step is feedback. When I find something I don't like - poor naming, unnecessary complexity, a missing edge case - ",{"type":32,"tag":82,"props":8266,"children":8267},{},[8268],{"type":37,"value":8269},"I tell AI and have it fix it",{"type":37,"value":8271},". We iterate until I'm satisfied.",{"type":32,"tag":46,"props":8273,"children":8274},{},[8275,8277,8282,8284,8289],{"type":37,"value":8276},"\"Rename the composable from ",{"type":32,"tag":117,"props":8278,"children":8279},{},[8280],{"type":37,"value":8281},"useFilter",{"type":37,"value":8283}," to ",{"type":32,"tag":117,"props":8285,"children":8286},{},[8287],{"type":37,"value":8288},"useArticleTagFilter",{"type":37,"value":8290},", it's more specific. And add handling for when the tags array is empty.\"",{"type":32,"tag":46,"props":8292,"children":8293},{},[8294,8296,8301],{"type":37,"value":8295},"The entire cycle repeats until the result is what I want. The key takeaway is that ",{"type":32,"tag":82,"props":8297,"children":8298},{},[8299],{"type":37,"value":8300},"I drive the process",{"type":37,"value":8302}," - AI is the executor, not the decision-maker.",{"type":32,"tag":39,"props":8304,"children":8306},{"id":8305},"tips-for-effective-work-with-ai",[8307],{"type":37,"value":8308},"Tips for Effective Work with AI",{"type":32,"tag":46,"props":8310,"children":8311},{},[8312],{"type":37,"value":8313},"From my experience, a few rules emerge that will help you get more out of AI.",{"type":32,"tag":153,"props":8315,"children":8316},{},[8317,8331,8345,8359,8380],{"type":32,"tag":157,"props":8318,"children":8319},{},[8320,8326],{"type":32,"tag":169,"props":8321,"children":8323},{"id":8322},"_1️⃣-be-specific",[8324],{"type":37,"value":8325},"1️⃣ Be Specific",{"type":32,"tag":46,"props":8327,"children":8328},{},[8329],{"type":37,"value":8330},"Instead of \"write me a component,\" say \"write me a Vue 3 component with Composition API that displays a list of users with sorting by name and registration date, use TypeScript.\"",{"type":32,"tag":157,"props":8332,"children":8333},{},[8334,8340],{"type":32,"tag":169,"props":8335,"children":8337},{"id":8336},"_2️⃣-provide-context",[8338],{"type":37,"value":8339},"2️⃣ Provide Context",{"type":32,"tag":46,"props":8341,"children":8342},{},[8343],{"type":37,"value":8344},"Tell AI what framework you're using, what conventions you follow, what the goal is. The more context, the better the output.",{"type":32,"tag":157,"props":8346,"children":8347},{},[8348,8354],{"type":32,"tag":169,"props":8349,"children":8351},{"id":8350},"_3️⃣-iterate",[8352],{"type":37,"value":8353},"3️⃣ Iterate",{"type":32,"tag":46,"props":8355,"children":8356},{},[8357],{"type":37,"value":8358},"The first output doesn't have to be perfect. Say what you want differently - \"add error handling\", \"use a composable instead of a mixin\", \"simplify it\".",{"type":32,"tag":157,"props":8360,"children":8361},{},[8362,8368],{"type":32,"tag":169,"props":8363,"children":8365},{"id":8364},"_4️⃣-always-review-output",[8366],{"type":37,"value":8367},"4️⃣ Always Review Output",{"type":32,"tag":46,"props":8369,"children":8370},{},[8371,8373,8378],{"type":37,"value":8372},"AI can generate code that looks correct but contains subtle bugs. ",{"type":32,"tag":82,"props":8374,"children":8375},{},[8376],{"type":37,"value":8377},"Understand every line",{"type":37,"value":8379}," you commit.",{"type":32,"tag":157,"props":8381,"children":8382},{},[8383,8389],{"type":32,"tag":169,"props":8384,"children":8386},{"id":8385},"_5️⃣-dont-be-afraid-to-experiment",[8387],{"type":37,"value":8388},"5️⃣ Don't Be Afraid to Experiment",{"type":32,"tag":46,"props":8390,"children":8391},{},[8392],{"type":37,"value":8393},"Try different tools, different approaches. What works for one person might not work for another. Find your sweet spot.",{"type":32,"tag":39,"props":8395,"children":8397},{"id":8396},"the-future-of-ai-in-development",[8398],{"type":37,"value":8399},"The Future of AI in Development",{"type":32,"tag":46,"props":8401,"children":8402},{},[8403],{"type":37,"value":8404},"AI tools are improving at an incredible pace. What's ahead?",{"type":32,"tag":444,"props":8406,"children":8407},{},[8408,8418,8428,8438],{"type":32,"tag":448,"props":8409,"children":8410},{},[8411,8416],{"type":32,"tag":82,"props":8412,"children":8413},{},[8414],{"type":37,"value":8415},"Deeper CI/CD integration",{"type":37,"value":8417}," - automatic code review, bug detection in PRs",{"type":32,"tag":448,"props":8419,"children":8420},{},[8421,8426],{"type":32,"tag":82,"props":8422,"children":8423},{},[8424],{"type":37,"value":8425},"Autonomous agents",{"type":37,"value":8427}," - AI that not only suggests solutions but implements and tests them",{"type":32,"tag":448,"props":8429,"children":8430},{},[8431,8436],{"type":32,"tag":82,"props":8432,"children":8433},{},[8434],{"type":37,"value":8435},"Better context understanding",{"type":37,"value":8437}," - AI that understands the entire project, its history, and business logic",{"type":32,"tag":448,"props":8439,"children":8440},{},[8441,8446],{"type":32,"tag":82,"props":8442,"children":8443},{},[8444],{"type":37,"value":8445},"Personalization",{"type":37,"value":8447}," - tools that learn your coding style and conventions",{"type":32,"tag":46,"props":8449,"children":8450},{},[8451,8453,8458],{"type":37,"value":8452},"I personally believe that AI ",{"type":32,"tag":82,"props":8454,"children":8455},{},[8456],{"type":37,"value":8457},"won't replace developers",{"type":37,"value":8459},", but developers who use AI will replace those who don't. It's like any other tool - a hammer won't build a house on its own, but try building without one.",{"type":32,"tag":39,"props":8461,"children":8462},{"id":774},[8463],{"type":37,"value":777},{"type":32,"tag":46,"props":8465,"children":8466},{},[8467,8469,8474],{"type":37,"value":8468},"AI-assisted development isn't magic or a threat - it's a ",{"type":32,"tag":82,"props":8470,"children":8471},{},[8472],{"type":37,"value":8473},"tool that can significantly boost your productivity",{"type":37,"value":8475}," if you use it correctly. The key is to approach AI as a junior colleague - you give it a task, review the output, and bear responsibility for the result.",{"type":32,"tag":46,"props":8477,"children":8478},{},[8479],{"type":37,"value":8480},"Start with one tool, learn to use it effectively, and gradually expand your workflow. You don't have to change your entire approach right away - just start with autocomplete or a chatbot for debugging and build from there.",{"type":32,"tag":46,"props":8482,"children":8483},{},[8484,8486,8491],{"type":37,"value":8485},"And if you've been avoiding AI so far - now is the right time to start. Not because it's trendy, but because it will ",{"type":32,"tag":82,"props":8487,"children":8488},{},[8489],{"type":37,"value":8490},"genuinely save you time and frustration",{"type":37,"value":733},{"type":32,"tag":39,"props":8493,"children":8494},{"id":798},[8495],{"type":37,"value":801},{"type":32,"tag":444,"props":8497,"children":8498},{},[8499,8508,8518,8527,8537],{"type":32,"tag":448,"props":8500,"children":8501},{},[8502],{"type":32,"tag":139,"props":8503,"children":8506},{":target":345,"href":8504,"rel":8505},"https://docs.anthropic.com/en/docs/claude-code",[347],[8507],{"type":37,"value":7868},{"type":32,"tag":448,"props":8509,"children":8510},{},[8511],{"type":32,"tag":139,"props":8512,"children":8515},{":target":345,"href":8513,"rel":8514},"https://claude.ai",[347],[8516],{"type":37,"value":8517},"Claude",{"type":32,"tag":448,"props":8519,"children":8520},{},[8521],{"type":32,"tag":139,"props":8522,"children":8525},{":target":345,"href":8523,"rel":8524},"https://cursor.com",[347],[8526],{"type":37,"value":7873},{"type":32,"tag":448,"props":8528,"children":8529},{},[8530],{"type":32,"tag":139,"props":8531,"children":8534},{":target":345,"href":8532,"rel":8533},"https://openai.com/index/introducing-codex/",[347],[8535],{"type":37,"value":8536},"OpenAI Codex",{"type":32,"tag":448,"props":8538,"children":8539},{},[8540],{"type":32,"tag":139,"props":8541,"children":8544},{":target":345,"href":8542,"rel":8543,":rel":347},"https://www.promptingguide.ai/",[347],[8545],{"type":37,"value":8546},"Prompt Engineering Guide",{"title":8,"searchDepth":862,"depth":862,"links":8548},[8549,8550,8555,8561,8568,8569,8570,8571],{"id":41,"depth":862,"text":44},{"id":7395,"depth":862,"text":7398,"children":8551},[8552,8553,8554],{"id":7413,"depth":871,"text":7416},{"id":7482,"depth":871,"text":7485},{"id":7533,"depth":871,"text":7536},{"id":7551,"depth":862,"text":7554,"children":8556},[8557,8558,8559,8560],{"id":7570,"depth":871,"text":7573},{"id":7685,"depth":871,"text":7688},{"id":7759,"depth":871,"text":7762},{"id":7846,"depth":871,"text":7849},{"id":8039,"depth":862,"text":8042,"children":8562},[8563,8564,8565,8566,8567],{"id":8065,"depth":871,"text":8068},{"id":8088,"depth":871,"text":8091},{"id":8111,"depth":871,"text":8114},{"id":8203,"depth":871,"text":8206},{"id":8256,"depth":871,"text":8259},{"id":8305,"depth":862,"text":8308},{"id":8396,"depth":862,"text":8399},{"id":774,"depth":862,"text":777},{"id":798,"depth":862,"text":801},"content:knowledge:ai-assisted-web-application-development.md","knowledge/ai-assisted-web-application-development.md",{"_path":3920,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":8575,"description":8576,"author":11,"date":8577,"readingTime":7350,"level":14,"image":8578,"tags":8579,"slugs":8582,"relatedArticles":8584,"body":8585,"_type":881,"_id":9740,"_source":883,"_file":9741,"_extension":885},"How to set up a cookie bar correctly?","We will look at the basic mistakes when implementing the cookie bar and how to address them correctly. We will show you two open-source solutions that will make your job much easier.","2025-01-02","/featured/how-to-set-up-a-cookie-bar-correctly.jpg",[8580,8581,1804,1802],"html","javascript",{"en":1808,"cs":8583},"jak-spravne-na-cookies-listu",[1809,1810,3000],{"type":29,"children":8586,"toc":9720},[8587,8593,8597,8615,8628,8634,8658,8756,8762,8776,8782,8803,8808,8814,8819,8844,8850,8855,8953,8959,9125,9224,9230,9269,9275,9280,9293,9302,9307,9319,9330,9341,9352,9370,9381,9392,9414,9420,9438,9449,9457,9468,9479,9485,9490,9495,9670,9674,9679,9683],{"type":32,"tag":33,"props":8588,"children":8590},{"id":8589},"cookies-bar-and-web-implementation",[8591],{"type":37,"value":8592},"Cookies bar and web implementation",{"type":32,"tag":39,"props":8594,"children":8595},{"id":41},[8596],{"type":37,"value":44},{"type":32,"tag":46,"props":8598,"children":8599},{},[8600,8602,8607,8609,8614],{"type":37,"value":8601},"In recent years, cookie bars have become a ",{"type":32,"tag":82,"props":8603,"children":8604},{},[8605],{"type":37,"value":8606},"standard feature of websites",{"type":37,"value":8608}," around the world. Not only do they inform users about the use of cookies on the site, but they also ensure compliance with ",{"type":32,"tag":82,"props":8610,"children":8611},{},[8612],{"type":37,"value":8613},"data protection legislation",{"type":37,"value":733},{"type":32,"tag":46,"props":8616,"children":8617},{},[8618,8620,8627],{"type":37,"value":8619},"In this article, we'll look at what cookies actually are, who needs to have a cookie bar and why, what categories of cookies exist, and how you can implement a cookie bar using ",{"type":32,"tag":139,"props":8621,"children":8624},{"href":8622,"rel":8623,":target":345},"https://cs.wikipedia.org/wiki/Otev%C5%99en%C3%BD_software",[347],[8625],{"type":37,"value":8626},"open source solution",{"type":37,"value":733},{"type":32,"tag":39,"props":8629,"children":8631},{"id":8630},"what-are-cookies",[8632],{"type":37,"value":8633},"What are cookies 🍪",{"type":32,"tag":46,"props":8635,"children":8636},{},[8637,8639,8649,8651,8656],{"type":37,"value":8638},"Cookies are ",{"type":32,"tag":139,"props":8640,"children":8643},{"href":8641,"rel":8642,":target":345},"https://en.wikipedia.org/wiki/HTTP_cookie",[347],[8644],{"type":32,"tag":82,"props":8645,"children":8646},{},[8647],{"type":37,"value":8648},"small text files",{"type":37,"value":8650}," that websites store in your browser when you visit them. These files contain information that can then be used for a variety of purposes, such as ",{"type":32,"tag":82,"props":8652,"children":8653},{},[8654],{"type":37,"value":8655},"tracking user activity, storing preferences or authenticating the user",{"type":37,"value":8657},". Cookies can be temporary (session cookies), which are deleted when you close your browser, or persistent (persistent cookies), which remain stored for a longer period of time.",{"type":32,"tag":157,"props":8659,"children":8660},{},[8661,8667,8672,8747],{"type":32,"tag":169,"props":8662,"children":8664},{"id":8663},"technical-window",[8665],{"type":37,"value":8666},"Technical window",{"type":32,"tag":46,"props":8668,"children":8669},{},[8670],{"type":37,"value":8671},"Let's take a look at the basic communication between the browser and the server when cookies are used.",{"type":32,"tag":444,"props":8673,"children":8674},{},[8675,8692,8720,8737],{"type":32,"tag":448,"props":8676,"children":8677},{},[8678,8683,8685,8690],{"type":32,"tag":82,"props":8679,"children":8680},{},[8681],{"type":37,"value":8682},"HTTP GET request:",{"type":37,"value":8684}," The browser visits a website (e.g. the ",{"type":32,"tag":117,"props":8686,"children":8687},{},[8688],{"type":37,"value":8689},"/home.php",{"type":37,"value":8691}," page).",{"type":32,"tag":448,"props":8693,"children":8694},{},[8695,8706,8708,8712,8714,8719],{"type":32,"tag":82,"props":8696,"children":8697},{},[8698,8700,8705],{"type":37,"value":8699},"HTTP response + ",{"type":32,"tag":117,"props":8701,"children":8702},{},[8703],{"type":37,"value":8704},"Set-Cookies",{"type":37,"value":6788},{"type":37,"value":8707}," The server returns a response along with a ",{"type":32,"tag":117,"props":8709,"children":8710},{},[8711],{"type":37,"value":8704},{"type":37,"value":8713}," header that contains information about the cookies to be stored in the browser. For example, ",{"type":32,"tag":117,"props":8715,"children":8716},{},[8717],{"type":37,"value":8718},"SessionID",{"type":37,"value":733},{"type":32,"tag":448,"props":8721,"children":8722},{},[8723,8728,8730,8735],{"type":32,"tag":82,"props":8724,"children":8725},{},[8726],{"type":37,"value":8727},"Next HTTP GET request with Cookie:",{"type":37,"value":8729}," The next time you browse the web (e.g. ",{"type":32,"tag":117,"props":8731,"children":8732},{},[8733],{"type":37,"value":8734},"/cart.php",{"type":37,"value":8736},"), the browser will automatically add the stored cookies to the request header so the server can associate the browser with its actions on the web.",{"type":32,"tag":448,"props":8738,"children":8739},{},[8740,8745],{"type":32,"tag":82,"props":8741,"children":8742},{},[8743],{"type":37,"value":8744},"HTTP response:",{"type":37,"value":8746}," The server uses the received cookies (e.g. for personalization or user tracking) and returns a response.",{"type":32,"tag":46,"props":8748,"children":8749},{},[8750],{"type":32,"tag":161,"props":8751,"children":8755},{"alt":8752,"src":8753,"title":8754},"Necessary cookies","/article/how-implement-cookies/cookie_http_server.svg","Client-server communication",[],{"type":32,"tag":39,"props":8757,"children":8759},{"id":8758},"web-extension",[8760],{"type":37,"value":8761},"Web extension",{"type":32,"tag":46,"props":8763,"children":8764},{},[8765,8767,8774],{"type":37,"value":8766},"To read cookies in the browser, I recommend the ",{"type":32,"tag":139,"props":8768,"children":8771},{"href":8769,"rel":8770,":target":345},"https://chromewebstore.google.com/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm",[347],[8772],{"type":37,"value":8773},"Cookie editor",{"type":37,"value":8775}," browser add-on.",{"type":32,"tag":39,"props":8777,"children":8779},{"id":8778},"who-needs-to-have-a-cookie-bar-on-the-web-and-why",[8780],{"type":37,"value":8781},"Who needs to have a cookie bar on the web and why",{"type":32,"tag":46,"props":8783,"children":8784},{},[8785,8787,8794,8796,8801],{"type":37,"value":8786},"The European Union, through the ",{"type":32,"tag":139,"props":8788,"children":8791},{"href":8789,"rel":8790},"https://eur-lex.europa.eu/legal-content/CS/ALL/?uri=CELEX%3A32002L0058",[347],[8792],{"type":37,"value":8793},"ePrivacy Directive",{"type":37,"value":8795}," and the General Data Protection Regulation (GDPR), has set strict requirements for the use of cookies. These regulations require websites to inform users about the use of cookies and obtain their consent before cookies are stored on their device. This measure applies to ",{"type":32,"tag":82,"props":8797,"children":8798},{},[8799],{"type":37,"value":8800},"all websites that target users in the EU",{"type":37,"value":8802},", regardless of where the website itself is located.",{"type":32,"tag":46,"props":8804,"children":8805},{},[8806],{"type":37,"value":8807},"A cookie bar is therefore necessary to comply with this legislation. Not only does it protect users' privacy, but it also ensures that websites are compliant with the legislation, avoiding potential fines.",{"type":32,"tag":39,"props":8809,"children":8811},{"id":8810},"do-i-need-to-have-a-cookie-bar-even-if-i-am-not-tracking-the-user",[8812],{"type":37,"value":8813},"Do I need to have a cookie bar even if I am not tracking the user?",{"type":32,"tag":46,"props":8815,"children":8816},{},[8817],{"type":37,"value":8818},"No, and I will use a quote from the Data Protection Authority website to answer:",{"type":32,"tag":8820,"props":8821,"children":8822},"blockquote",{},[8823,8828],{"type":32,"tag":46,"props":8824,"children":8825},{},[8826],{"type":37,"value":8827},"If you only use technical cookies, you may not have a cookie bar. However, if personal data is processed in the context of technical cookies, the information obligation must be fulfilled in another appropriate way, accessible on the website where such processing takes place.",{"type":32,"tag":46,"props":8829,"children":8830},{},[8831,8833],{"type":37,"value":8832},"-- ",{"type":32,"tag":8834,"props":8835,"children":8836},"cite",{},[8837],{"type":32,"tag":139,"props":8838,"children":8841},{"href":8839,"rel":8840,"target":345},"https://uoou.gov.cz/verejnost/qa-otazky-a-odpovedi/cookies",[347],[8842],{"type":37,"value":8843},"Website of the Data Protection Authority (CZ)",{"type":32,"tag":39,"props":8845,"children":8847},{"id":8846},"what-are-the-cookie-categories",[8848],{"type":37,"value":8849},"What are the cookie categories",{"type":32,"tag":46,"props":8851,"children":8852},{},[8853],{"type":37,"value":8854},"Cookies can be divided into several categories, each of which serves a different purpose:",{"type":32,"tag":153,"props":8856,"children":8857},{},[8858,8881,8905,8929],{"type":32,"tag":157,"props":8859,"children":8860},{},[8861,8869,8874],{"type":32,"tag":169,"props":8862,"children":8864},{"id":8863},"necessary-cookies",[8865],{"type":32,"tag":82,"props":8866,"children":8867},{},[8868],{"type":37,"value":8752},{"type":32,"tag":46,"props":8870,"children":8871},{},[8872],{"type":37,"value":8873},"These cookies are essential for basic site functions such as user login or shopping cart. Without these cookies, the website would not function properly. We do not need user consent for this category.",{"type":32,"tag":46,"props":8875,"children":8876},{},[8877],{"type":32,"tag":161,"props":8878,"children":8880},{"alt":8752,"src":8879,"title":8752},"/article/how-implement-cookies/necessary_cookies.svg",[],{"type":32,"tag":157,"props":8882,"children":8883},{},[8884,8893,8898],{"type":32,"tag":169,"props":8885,"children":8887},{"id":8886},"preference-cookies",[8888],{"type":32,"tag":82,"props":8889,"children":8890},{},[8891],{"type":37,"value":8892},"Preference cookies",{"type":32,"tag":46,"props":8894,"children":8895},{},[8896],{"type":37,"value":8897},"Allow a site to remember information that changes the look or behavior of the site, such as preferred language or region.",{"type":32,"tag":46,"props":8899,"children":8900},{},[8901],{"type":32,"tag":161,"props":8902,"children":8904},{"alt":8892,"src":8903,"title":8892},"/article/how-implement-cookies/preferenced_cookies.svg",[],{"type":32,"tag":157,"props":8906,"children":8907},{},[8908,8917,8922],{"type":32,"tag":169,"props":8909,"children":8911},{"id":8910},"statistical-cookies",[8912],{"type":32,"tag":82,"props":8913,"children":8914},{},[8915],{"type":37,"value":8916},"Statistical cookies",{"type":32,"tag":46,"props":8918,"children":8919},{},[8920],{"type":37,"value":8921},"Help site owners understand how visitors interact with the site by collecting and reporting information anonymously.",{"type":32,"tag":46,"props":8923,"children":8924},{},[8925],{"type":32,"tag":161,"props":8926,"children":8928},{"alt":8916,"src":8927,"title":8916},"/article/how-implement-cookies/analytics_cookies.svg",[],{"type":32,"tag":157,"props":8930,"children":8931},{},[8932,8941,8946],{"type":32,"tag":169,"props":8933,"children":8935},{"id":8934},"marketing-cookies",[8936],{"type":32,"tag":82,"props":8937,"children":8938},{},[8939],{"type":37,"value":8940},"Marketing cookies",{"type":32,"tag":46,"props":8942,"children":8943},{},[8944],{"type":37,"value":8945},"These are used to track visitors to the website. Their aim is to serve ads that are relevant and interesting to the individual user, and thus more valuable to publishers and third-party advertisers.",{"type":32,"tag":46,"props":8947,"children":8948},{},[8949],{"type":32,"tag":161,"props":8950,"children":8952},{"alt":8940,"src":8951,"title":8940},"/article/how-implement-cookies/marketing_cookies.svg",[],{"type":32,"tag":39,"props":8954,"children":8956},{"id":8955},"the-most-common-mistakes-when-implementing-cookies",[8957],{"type":37,"value":8958},"The most common mistakes when implementing cookies",{"type":32,"tag":153,"props":8960,"children":8961},{},[8962,9023,9080],{"type":32,"tag":157,"props":8963,"children":8964},{},[8965,8971,9004,9012],{"type":32,"tag":169,"props":8966,"children":8968},{"id":8967},"_1️⃣-making-it-harder-to-reject-cookies-than-to-accept-them",[8969],{"type":37,"value":8970},"1️⃣ Making it harder to reject cookies than to accept them",{"type":32,"tag":46,"props":8972,"children":8973},{},[8974,8976,8981,8983,8988,8990,8995,8997,9002],{"type":37,"value":8975},"Another common mistake is making it harder to reject cookies versus accepting them. Often banners only offer the option ",{"type":32,"tag":82,"props":8977,"children":8978},{},[8979],{"type":37,"value":8980},"\"accept all cookies \"",{"type":37,"value":8982}," or a hidden option ",{"type":32,"tag":82,"props":8984,"children":8985},{},[8986],{"type":37,"value":8987},"\"set more detailed \"",{"type":37,"value":8989},", which forces users to put more effort into rejecting cookies. Under GDPR, it should be as easy to reject cookies as it is to accept them. This means that if there is an ",{"type":32,"tag":82,"props":8991,"children":8992},{},[8993],{"type":37,"value":8994},"\"accept all \"",{"type":37,"value":8996}," button on the banner, there should also be a ",{"type":32,"tag":82,"props":8998,"children":8999},{},[9000],{"type":37,"value":9001},"\"reject all \"",{"type":37,"value":9003}," button next to it, both easily accessible and visible, so that users can quickly and easily express their choice.",{"type":32,"tag":46,"props":9005,"children":9006},{},[9007],{"type":32,"tag":82,"props":9008,"children":9009},{},[9010],{"type":37,"value":9011},"Example of a flawed cookie bar implementation:",{"type":32,"tag":46,"props":9013,"children":9014},{},[9015],{"type":32,"tag":139,"props":9016,"children":9018},{"href":9017,":target":345},"/article/how-implement-cookies/reject_fail.png",[9019],{"type":32,"tag":161,"props":9020,"children":9022},{"alt":9021,"src":9017,"title":9021},"Make it harder to decline",[],{"type":32,"tag":157,"props":9024,"children":9025},{},[9026,9032,9051,9069],{"type":32,"tag":169,"props":9027,"children":9029},{"id":9028},"_2️⃣-insufficient-consent",[9030],{"type":37,"value":9031},"2️⃣ Insufficient consent",{"type":32,"tag":46,"props":9033,"children":9034},{},[9035,9037,9042,9044,9049],{"type":37,"value":9036},"Some sites resort to practices such as ",{"type":32,"tag":82,"props":9038,"children":9039},{},[9040],{"type":37,"value":9041},"pre-ticking a box",{"type":37,"value":9043}," or informing the user that ",{"type":32,"tag":82,"props":9045,"children":9046},{},[9047],{"type":37,"value":9048},"by continuing to use the site they automatically consent to cookies",{"type":37,"value":9050},". However, these methods are in breach of the GDPR, which requires active, specific and informed consent from the user.",{"type":32,"tag":46,"props":9052,"children":9053},{},[9054,9056,9061,9063,9068],{"type":37,"value":9055},"Consent must be given after clear information has been provided about the purposes of the cookies and must be ",{"type":32,"tag":82,"props":9057,"children":9058},{},[9059],{"type":37,"value":9060},"the user's free choice",{"type":37,"value":9062},". Passive or unconscious consent is not acceptable and website operators should ensure that the process of obtaining consent is ",{"type":32,"tag":82,"props":9064,"children":9065},{},[9066],{"type":37,"value":9067},"transparent and user-friendly",{"type":37,"value":733},{"type":32,"tag":46,"props":9070,"children":9071},{},[9072],{"type":32,"tag":139,"props":9073,"children":9075},{"href":9074,":target":345},"/article/how-implement-cookies/no_reject.png",[9076],{"type":32,"tag":161,"props":9077,"children":9079},{"alt":9078,"src":9074,"title":9078},"Cannot reject cookies",[],{"type":32,"tag":157,"props":9081,"children":9082},{},[9083,9089,9114],{"type":32,"tag":169,"props":9084,"children":9086},{"id":9085},"_3️⃣-processing-cookies-without-consent",[9087],{"type":37,"value":9088},"3️⃣ Processing cookies without consent",{"type":32,"tag":46,"props":9090,"children":9091},{},[9092,9094,9099,9101,9106,9108,9113],{"type":37,"value":9093},"Many websites automatically store cookies on a user's device without their informed consent, which is in breach of the GDPR and ePrivacy Directive. This approach, known as ",{"type":32,"tag":82,"props":9095,"children":9096},{},[9097],{"type":37,"value":9098},"\"opt-out\", has been illegal since 1 January 2022",{"type":37,"value":9100}," when the ",{"type":32,"tag":82,"props":9102,"children":9103},{},[9104],{"type":37,"value":9105},"\"opt-in \"",{"type":37,"value":9107}," regime was introduced. This means that website operators must first identify non-technical cookies and obtain the user's prior consent to use them. Ignoring the user's choice, where cookies are stored despite not having permission, is a serious breach of the law and ",{"type":32,"tag":82,"props":9109,"children":9110},{},[9111],{"type":37,"value":9112},"can lead to hefty fines",{"type":37,"value":733},{"type":32,"tag":46,"props":9115,"children":9116},{},[9117],{"type":32,"tag":139,"props":9118,"children":9120},{"href":9119,":target":345},"/article/how-implement-cookies/no_agree.png",[9121],{"type":32,"tag":161,"props":9122,"children":9124},{"alt":9123,"src":9119,"title":9123},"Processing cookies without consent",[],{"type":32,"tag":153,"props":9126,"children":9127},{},[9128,9155,9190],{"type":32,"tag":157,"props":9129,"children":9130},{},[9131,9137],{"type":32,"tag":169,"props":9132,"children":9134},{"id":9133},"_4️⃣-bad-categorization-of-cookies",[9135],{"type":37,"value":9136},"4️⃣ Bad categorization of cookies",{"type":32,"tag":46,"props":9138,"children":9139},{},[9140,9142,9147,9149,9153],{"type":37,"value":9141},"One of the common mistakes is ",{"type":32,"tag":82,"props":9143,"children":9144},{},[9145],{"type":37,"value":9146},"not categorising",{"type":37,"value":9148}," cookies according to their purpose. Some sites still only offer the option to ",{"type":32,"tag":82,"props":9150,"children":9151},{},[9152],{"type":37,"value":8980},{"type":37,"value":9154}," or \"reject all cookies\", which does not take into account the different consent needs for different types of cookies. The ideal solution involves dividing cookies into categories such as strictly necessary, analytical and advertising cookies, allowing the user to choose which purposes they consent to. This ensures that users' rights are respected while complying with legal requirements.",{"type":32,"tag":157,"props":9156,"children":9157},{},[9158,9164],{"type":32,"tag":169,"props":9159,"children":9161},{"id":9160},"_5️⃣-inability-to-withdraw-consent-once-given",[9162],{"type":37,"value":9163},"5️⃣ Inability to withdraw consent once given",{"type":32,"tag":46,"props":9165,"children":9166},{},[9167,9169,9174,9176,9181,9183,9188],{"type":37,"value":9168},"Another common error is ",{"type":32,"tag":82,"props":9170,"children":9171},{},[9172],{"type":37,"value":9173},"not allowing users to withdraw consent once given",{"type":37,"value":9175},". Consent must be revocable at any time to be considered free. Website operators often forget to offer an easy way for the user to ",{"type":32,"tag":82,"props":9177,"children":9178},{},[9179],{"type":37,"value":9180},"change their preferences",{"type":37,"value":9182}," regarding cookies. The optimal solution is to place a link to change cookie settings in the ",{"type":32,"tag":82,"props":9184,"children":9185},{},[9186],{"type":37,"value":9187},"footer of the site or use a graphical icon",{"type":37,"value":9189}," that is always visible and allows users quick access to modify their preferences. This ensures that consent is fully GDPR compliant and users are in control of their personal data.",{"type":32,"tag":157,"props":9191,"children":9192},{},[9193,9199],{"type":32,"tag":169,"props":9194,"children":9196},{"id":9195},"_6️⃣-lack-of-user-awareness",[9197],{"type":37,"value":9198},"6️⃣ Lack of user awareness",{"type":32,"tag":46,"props":9200,"children":9201},{},[9202,9204,9209,9211,9216,9218,9223],{"type":37,"value":9203},"The last common mistake when implementing a cookie bar is ",{"type":32,"tag":82,"props":9205,"children":9206},{},[9207],{"type":37,"value":9208},"not informing users enough about what cookies are used and for what purpose",{"type":37,"value":9210},". Many websites only provide basic information that is not detailed enough for users to make an informed decision. Under the GDPR, users must be clearly and understandably ",{"type":32,"tag":82,"props":9212,"children":9213},{},[9214],{"type":37,"value":9215},"informed about the types of cookies",{"type":37,"value":9217}," a site uses, the purpose of their processing, and who will have access to that data. In addition, users should be given the opportunity to obtain more information by following links to a detailed ",{"type":32,"tag":82,"props":9219,"children":9220},{},[9221],{"type":37,"value":9222},"cookie policy or privacy policy",{"type":37,"value":733},{"type":32,"tag":39,"props":9225,"children":9227},{"id":9226},"easy-to-implement-cookie-bar-on-the-web",[9228],{"type":37,"value":9229},"Easy to implement cookie bar on the web",{"type":32,"tag":46,"props":9231,"children":9232},{},[9233,9235,9241,9243,9248,9249,9254,9256,9261,9263,9268],{"type":37,"value":9234},"I've prepared two ",{"type":32,"tag":139,"props":9236,"children":9238},{"href":8622,"rel":9237,"target":345},[347],[9239],{"type":37,"value":9240},"open-source",{"type":37,"value":9242}," solutions that will make working with the cookie bar much easier. Both tools are ",{"type":32,"tag":82,"props":9244,"children":9245},{},[9246],{"type":37,"value":9247},"free",{"type":37,"value":2497},{"type":32,"tag":82,"props":9250,"children":9251},{},[9252],{"type":37,"value":9253},"easily configurable",{"type":37,"value":9255},", and ",{"type":32,"tag":82,"props":9257,"children":9258},{},[9259],{"type":37,"value":9260},"compliant with GDPR",{"type":37,"value":9262}," (if you properly contextualize and link them to your ",{"type":32,"tag":82,"props":9264,"children":9265},{},[9266],{"type":37,"value":9267},"cookies policy",{"type":37,"value":4598},{"type":32,"tag":169,"props":9270,"children":9272},{"id":9271},"solution-1-orestbidacookieconsent",[9273],{"type":37,"value":9274},"📦 Solution #1 - OrestBida/cookieconsent",{"type":32,"tag":46,"props":9276,"children":9277},{},[9278],{"type":37,"value":9279},"A proven, functional and visually great cookie bar that also meets legal requirements. Before you start implementing it, you can see a sample from the author.",{"type":32,"tag":46,"props":9281,"children":9282},{},[9283],{"type":32,"tag":139,"props":9284,"children":9287},{"href":9285,"rel":9286,":target":345},"https://playground.cookieconsent.orestbida.com",[347],[9288],{"type":32,"tag":161,"props":9289,"children":9292},{"alt":9290,"src":9291,"title":9290},"Open Source Orest Bida Cookies","/article/how-implement-cookies/orestbida.png",[],{"type":32,"tag":46,"props":9294,"children":9295},{},[9296],{"type":32,"tag":139,"props":9297,"children":9299},{"href":9285,"rel":9298,":target":345},[347],[9300],{"type":37,"value":9301},"Link to sample",{"type":32,"tag":46,"props":9303,"children":9304},{},[9305],{"type":37,"value":9306},"Where you can try to easily modify and customize it, at the same time you can generate a configuration json on this page which you can use later during installation.",{"type":32,"tag":46,"props":9308,"children":9309},{},[9310,9312,9317],{"type":37,"value":9311},"Step ",{"type":32,"tag":117,"props":9313,"children":9314},{},[9315],{"type":37,"value":9316},"1",{"type":37,"value":9318}," Embed CSS and Javascript into the site.",{"type":32,"tag":7664,"props":9320,"children":9322},{"code":9321,"language":8580,"meta":7668},"\u003Cscript type=\"module\" src=\"cookieconsent-config.js\">\u003C/script>\r\n\u003Clink rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@3.0.1/dist/cookieconsent.css\">\n",[9323],{"type":32,"tag":7671,"props":9324,"children":9325},{},[9326],{"type":32,"tag":7664,"props":9327,"children":9328},{"__ignoreMap":8},[9329],{"type":37,"value":9321},{"type":32,"tag":46,"props":9331,"children":9332},{},[9333,9334,9339],{"type":37,"value":9311},{"type":32,"tag":117,"props":9335,"children":9336},{},[9337],{"type":37,"value":9338},"2",{"type":37,"value":9340},"   Mark javascript blocks on the page with categories and switch their type to text/plain",{"type":32,"tag":7664,"props":9342,"children":9344},{"code":9343,"language":8580,"meta":7668},"\u003Cscript\r\n    type=\"text/plain\"\r\n    data-category=\"analytics\"\r\n    data-service=\"Google Analytics\"\r\n>\r\n\u003C!-- Google analytics code -->\r\n\u003C!-- ... -->\r\n\u003C/script>\n",[9345],{"type":32,"tag":7671,"props":9346,"children":9347},{},[9348],{"type":32,"tag":7664,"props":9349,"children":9350},{"__ignoreMap":8},[9351],{"type":37,"value":9343},{"type":32,"tag":46,"props":9353,"children":9354},{},[9355,9356,9361,9363,9368],{"type":37,"value":9311},{"type":32,"tag":117,"props":9357,"children":9358},{},[9359],{"type":37,"value":9360},"3",{"type":37,"value":9362}," Download and insert ",{"type":32,"tag":117,"props":9364,"children":9365},{},[9366],{"type":37,"value":9367},"cookieconsent-config.js",{"type":37,"value":9369}," from playground and edit the text",{"type":32,"tag":46,"props":9371,"children":9372},{},[9373,9374,9379],{"type":37,"value":9311},{"type":32,"tag":117,"props":9375,"children":9376},{},[9377],{"type":37,"value":9378},"4",{"type":37,"value":9380}," Paste the change cookie settings link into the footer",{"type":32,"tag":7664,"props":9382,"children":9384},{"code":9383,"language":8580,"meta":7668},"\u003Cbutton type=\"button\" data-cc=\"show-preferencesModal\">View Preferences Modal\u003C/button>\n",[9385],{"type":32,"tag":7671,"props":9386,"children":9387},{},[9388],{"type":32,"tag":7664,"props":9389,"children":9390},{"__ignoreMap":8},[9391],{"type":37,"value":9383},{"type":32,"tag":157,"props":9393,"children":9394},{},[9395],{"type":32,"tag":46,"props":9396,"children":9397},{},[9398,9403,9405,9412],{"type":32,"tag":82,"props":9399,"children":9400},{},[9401],{"type":37,"value":9402},"Pro Tip:",{"type":37,"value":9404}," More experienced developers will use ",{"type":32,"tag":139,"props":9406,"children":9409},{"href":9407,"rel":9408,":target":345},"https://www.npmjs.com/package/vanilla-cookieconsent",[347],[9410],{"type":37,"value":9411},"install using NPM",{"type":37,"value":9413},", or the ability to integrate with many frameworks like vue js, react, angular and so on.",{"type":32,"tag":169,"props":9415,"children":9417},{"id":9416},"solution-2-osanocookieconsent",[9418],{"type":37,"value":9419},"📦 Solution #2 - Osano/cookieconsent",{"type":32,"tag":9421,"props":9422,"children":9423},"ol",{},[9424],{"type":32,"tag":448,"props":9425,"children":9426},{},[9427,9429,9436],{"type":37,"value":9428},"First, embed the CookieConsent library into your site. You can find it on ",{"type":32,"tag":139,"props":9430,"children":9433},{"href":9431,"rel":9432,":target":345},"https://github.com/osano/cookieconsent",[347],[9434],{"type":37,"value":9435},"GitHubu",{"type":37,"value":9437}," or use the CDN.",{"type":32,"tag":7664,"props":9439,"children":9441},{"code":9440,"language":8580,"meta":7668},"\u003Cscript src=\"\r\nhttps://cdn.jsdelivr.net/npm/cookieconsent@3.1.1/build/cookieconsent.min.js\r\n\">\u003C/script>\r\n\u003Clink href=\"\r\nhttps://cdn.jsdelivr.net/npm/cookieconsent@3.1.1/build/cookieconsent.min.css\r\n\" rel=\"stylesheet\">\n",[9442],{"type":32,"tag":7671,"props":9443,"children":9444},{},[9445],{"type":32,"tag":7664,"props":9446,"children":9447},{"__ignoreMap":8},[9448],{"type":37,"value":9440},{"type":32,"tag":9421,"props":9450,"children":9451},{"start":862},[9452],{"type":32,"tag":448,"props":9453,"children":9454},{},[9455],{"type":37,"value":9456},"Customize the look and feel",{"type":32,"tag":7664,"props":9458,"children":9460},{"code":9459,"language":8581,"meta":7668},"window.addEventListener(\"load\", function() {\r\n  window.cookieconsent.initialise({\r\n    palette: {\r\n      popup: { background: \"#000\" },\r\n      button: { background: \"#f1d600\" }\r\n    },\r\n    theme: \"classic\",\r\n    content: {\r\n      message: \"This website uses cookies to ensure you get the best experience.\",\r\n      dismiss: \"I understand!\",\r\n      link: \"Find out more\",\r\n      href: \"/privacy-policy\"\r\n    }\r\n  });\r\n});\n",[9461],{"type":32,"tag":7671,"props":9462,"children":9463},{},[9464],{"type":32,"tag":7664,"props":9465,"children":9466},{"__ignoreMap":8},[9467],{"type":37,"value":9459},{"type":32,"tag":7664,"props":9469,"children":9471},{"code":9470,"language":8581,"meta":7668},"window.addEventListener(\"load\", function() {\r\n  window.cookieconsent.initialise({\r\n    palette: {\r\n      popup: {\r\n        background: \"#edeff5\",\r\n        text: \"#838391\"\r\n      },\r\n      button: {\r\n        background: \"#4b81e8\"\r\n      }\r\n    },\r\n    theme: \"edgeless\",\r\n    type: \"opt-in\",\r\n    content: {\r\n      message: 'This website uses cookies to give you the best experience',\r\n      allow: \"Allow cookies\",\r\n      deny: \"Disable\",\r\n      link: \"Learn more\",\r\n      href: \"/privacy-policy\"\r\n    },\r\n    onInitialise: function (status) {\r\n      var type = this.options.type;\r\n      var didConsent = this.hasConsented();\r\n      if (type == 'opt-in' && didConsent) {\r\n        // enable cookies\r\n      }\r\n      if (type == 'opt-out' && !didConsent) {\r\n        // disable cookies\r\n      }\r\n    },\r\n    onStatusChange: function(status, chosenBefore) {\r\n      var type = this.options.type;\r\n      var didConsent = this.hasConsented();\r\n      if (type == 'opt-in' && didConsent) {\r\n        // enable cookies\r\n      }\r\n      if (type == 'opt-out' && !didConsent) {\r\n        // disable cookies\r\n      }\r\n    },\r\n    onRevokeChoice: function() {\r\n      var type = this.options.type;\r\n      if (type == 'opt-in') {\r\n        // disable cookies\r\n      }\r\n      if (type == 'opt-out') {\r\n        // enable cookies\r\n      }\r\n    }\r\n  });\r\n});\n",[9472],{"type":32,"tag":7671,"props":9473,"children":9474},{},[9475],{"type":32,"tag":7664,"props":9476,"children":9477},{"__ignoreMap":8},[9478],{"type":37,"value":9470},{"type":32,"tag":39,"props":9480,"children":9482},{"id":9481},"checklist-for-cookie-bar-implementation",[9483],{"type":37,"value":9484},"Checklist for cookie bar implementation",{"type":32,"tag":46,"props":9486,"children":9487},{},[9488],{"type":37,"value":9489},"I've put together a simple checklist to help you ensure that your cookie bar complies with legal requirements:",{"type":32,"tag":169,"props":9491,"children":9493},{"id":9492},"checklist",[9494],{"type":37,"value":2680},{"type":32,"tag":444,"props":9496,"children":9497},{},[9498,9510,9522,9546,9558,9570,9588,9600,9612,9624,9635,9647,9659],{"type":32,"tag":448,"props":9499,"children":9500},{},[9501,9503,9508],{"type":37,"value":9502},"⏹️ User consent is obtained ",{"type":32,"tag":82,"props":9504,"children":9505},{},[9506],{"type":37,"value":9507},"before",{"type":37,"value":9509}," non-technical cookies are stored.",{"type":32,"tag":448,"props":9511,"children":9512},{},[9513,9515,9520],{"type":37,"value":9514},"⏹️ The cookie bar allows ",{"type":32,"tag":82,"props":9516,"children":9517},{},[9518],{"type":37,"value":9519},"easy access",{"type":37,"value":9521}," to the cookie policy or privacy policy.",{"type":32,"tag":448,"props":9523,"children":9524},{},[9525,9527,9532,9533,9538,9540,9545],{"type":37,"value":9526},"⏹️ The ",{"type":32,"tag":82,"props":9528,"children":9529},{},[9530],{"type":37,"value":9531},"\"Accept All \"",{"type":37,"value":1982},{"type":32,"tag":82,"props":9534,"children":9535},{},[9536],{"type":37,"value":9537},"\"Reject All \"",{"type":37,"value":9539}," buttons are equally ",{"type":32,"tag":82,"props":9541,"children":9542},{},[9543],{"type":37,"value":9544},"easily accessible",{"type":37,"value":733},{"type":32,"tag":448,"props":9547,"children":9548},{},[9549,9551,9556],{"type":37,"value":9550},"⏹️ Users have the possibility to ",{"type":32,"tag":82,"props":9552,"children":9553},{},[9554],{"type":37,"value":9555},"set their cookie preferences",{"type":37,"value":9557}," in detail (e.g. by category).",{"type":32,"tag":448,"props":9559,"children":9560},{},[9561,9563,9568],{"type":37,"value":9562},"⏹️ The cookie bar ",{"type":32,"tag":82,"props":9564,"children":9565},{},[9566],{"type":37,"value":9567},"does not interfere with site navigation",{"type":37,"value":9569},", but is also easily visible.",{"type":32,"tag":448,"props":9571,"children":9572},{},[9573,9574,9579,9581,9586],{"type":37,"value":4625},{"type":32,"tag":82,"props":9575,"children":9576},{},[9577],{"type":37,"value":9578},"An icon or link",{"type":37,"value":9580}," for changing the cookie settings is ",{"type":32,"tag":82,"props":9582,"children":9583},{},[9584],{"type":37,"value":9585},"always accessible",{"type":37,"value":9587}," (e.g. in the footer of the website).",{"type":32,"tag":448,"props":9589,"children":9590},{},[9591,9593,9598],{"type":37,"value":9592},"⏹️ The cookie bar is ",{"type":32,"tag":82,"props":9594,"children":9595},{},[9596],{"type":37,"value":9597},"fully functional on mobile devices",{"type":37,"value":9599}," and different browsers.",{"type":32,"tag":448,"props":9601,"children":9602},{},[9603,9605,9610],{"type":37,"value":9604},"⏹️ Categories of cookies are ",{"type":32,"tag":82,"props":9606,"children":9607},{},[9608],{"type":37,"value":9609},"rightly marked and separated according to purpose",{"type":37,"value":9611}," (necessary, preferential, statistical, marketing).",{"type":32,"tag":448,"props":9613,"children":9614},{},[9615,9617,9622],{"type":37,"value":9616},"⏹️ Users are able to ",{"type":32,"tag":82,"props":9618,"children":9619},{},[9620],{"type":37,"value":9621},"revoke their consent or change their preferences",{"type":37,"value":9623}," at any time.",{"type":32,"tag":448,"props":9625,"children":9626},{},[9627,9629,9634],{"type":37,"value":9628},"⏹️ When withdrawing consent, cookies are ",{"type":32,"tag":82,"props":9630,"children":9631},{},[9632],{"type":37,"value":9633},"rightfully removed or deactivated",{"type":37,"value":733},{"type":32,"tag":448,"props":9636,"children":9637},{},[9638,9640,9645],{"type":37,"value":9639},"⏹️ Users are ",{"type":32,"tag":82,"props":9641,"children":9642},{},[9643],{"type":37,"value":9644},"not manipulated",{"type":37,"value":9646}," by preset options (e.g. pre-ticked boxes).",{"type":32,"tag":448,"props":9648,"children":9649},{},[9650,9652,9657],{"type":37,"value":9651},"⏹️ Users ",{"type":32,"tag":82,"props":9653,"children":9654},{},[9655],{"type":37,"value":9656},"are not forced to accept",{"type":37,"value":9658}," cookies to access basic site features.",{"type":32,"tag":448,"props":9660,"children":9661},{},[9662,9664,9669],{"type":37,"value":9663},"⏹️ A detailed description of all cookies used is ",{"type":32,"tag":82,"props":9665,"children":9666},{},[9667],{"type":37,"value":9668},"part of the cookie policy",{"type":37,"value":733},{"type":32,"tag":39,"props":9671,"children":9672},{"id":774},[9673],{"type":37,"value":777},{"type":32,"tag":46,"props":9675,"children":9676},{},[9677],{"type":37,"value":9678},"The cookie bar is an important element of a website that ensures compliance with data protection legislation. Implementing a cookie bar requires careful planning and adherence to the principles of transparency, information and respect for user privacy. Thanks to open source solutions, you can easily and efficiently implement a cookie bar on your website to ensure that you are compliant with the legislation and protect yourself from potential fines and legal issues.",{"type":32,"tag":39,"props":9680,"children":9681},{"id":798},[9682],{"type":37,"value":6401},{"type":32,"tag":444,"props":9684,"children":9685},{},[9686,9695,9703,9711],{"type":32,"tag":448,"props":9687,"children":9688},{},[9689],{"type":32,"tag":139,"props":9690,"children":9692},{"href":8839,"rel":9691,":rel":347},[347],[9693],{"type":37,"value":9694},"Data Protection Authority",{"type":32,"tag":448,"props":9696,"children":9697},{},[9698],{"type":32,"tag":139,"props":9699,"children":9701},{"href":8789,"rel":9700,":rel":347},[347],[9702],{"type":37,"value":8793},{"type":32,"tag":448,"props":9704,"children":9705},{},[9706],{"type":32,"tag":139,"props":9707,"children":9709},{"href":9285,"rel":9708,":rel":347},[347],[9710],{"type":37,"value":9290},{"type":32,"tag":448,"props":9712,"children":9713},{},[9714],{"type":32,"tag":139,"props":9715,"children":9717},{"href":8769,"rel":9716,":rel":347},[347],[9718],{"type":37,"value":9719},"Chrome Extension Cookies",{"title":8,"searchDepth":862,"depth":862,"links":9721},[9722,9723,9726,9727,9728,9729,9730,9731,9735,9738,9739],{"id":41,"depth":862,"text":44},{"id":8630,"depth":862,"text":8633,"children":9724},[9725],{"id":8663,"depth":871,"text":8666},{"id":8758,"depth":862,"text":8761},{"id":8778,"depth":862,"text":8781},{"id":8810,"depth":862,"text":8813},{"id":8846,"depth":862,"text":8849},{"id":8955,"depth":862,"text":8958},{"id":9226,"depth":862,"text":9229,"children":9732},[9733,9734],{"id":9271,"depth":871,"text":9274},{"id":9416,"depth":871,"text":9419},{"id":9481,"depth":862,"text":9484,"children":9736},[9737],{"id":9492,"depth":871,"text":2680},{"id":774,"depth":862,"text":777},{"id":798,"depth":862,"text":6401},"content:knowledge:how-to-set-up-a-cookie-bar-correctly.md","knowledge/how-to-set-up-a-cookie-bar-correctly.md",{"_path":2279,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":9743,"description":9744,"author":11,"date":9745,"readingTime":9746,"level":9747,"image":9748,"tags":9749,"slugs":9753,"relatedArticles":9755,"body":9757,"_type":881,"_id":12160,"_source":883,"_file":12161,"_extension":885},"Web Accessibility Guide","Come and explore the world of accessible web development. We will show you the WCAG or WAI-ARIA standards along with sample applications and much more...","2024-02-28",20,"intermediate","/featured/web-accessiblity.jpg",[9750,9751,9752],"WCAG","WAIARIA","webaccessibility",{"en":1809,"cs":9754},"pruvodce-webove-pristupnosti",[1808,9756,3001],"guide-to-the-world-of-web-image-formats",{"type":29,"children":9758,"toc":12128},[9759,9763,9769,9786,9795,9813,9824,9930,9936,9948,9954,9968,9978,10115,10128,10137,10145,10196,10202,10236,10245,10251,10256,10262,10293,10301,10312,10320,10331,10334,10340,10359,10374,10382,10393,10401,10412,10424,10435,10438,10444,10456,10461,10469,10480,10483,10489,10494,10500,10512,10521,10529,10591,10599,10654,10657,10663,10682,10694,10716,10724,10750,10759,10771,10876,10879,10885,10903,10910,10918,10928,10940,10951,10958,10967,10978,10989,10996,11005,11017,11024,11032,11044,11055,11081,11088,11097,11107,11118,11125,11134,11151,11162,11169,11178,11190,11201,11208,11217,11227,11238,11245,11254,11266,11277,11280,11286,11298,11310,11322,11325,11331,11357,11370,11379,11382,11387,11393,11412,11421,11429,11452,11459,11530,11536,11574,11588,11594,11599,11607,11651,11656,11662,11687,11693,11719,11728,11740,11746,11781,11789,11856,11863,11869,11875,11894,11902,11908,11920,11927,11931,12014,12020],{"type":32,"tag":33,"props":9760,"children":9761},{"id":1809},[9762],{"type":37,"value":9743},{"type":32,"tag":39,"props":9764,"children":9766},{"id":9765},"what-is-web-accessibility-and-who-does-it-serve",[9767],{"type":37,"value":9768},"What is web accessibility and who does it serve",{"type":32,"tag":46,"props":9770,"children":9771},{},[9772,9777,9779,9784],{"type":32,"tag":82,"props":9773,"children":9774},{},[9775],{"type":37,"value":9776},"Web accessibility",{"type":37,"value":9778}," is about creating and maintaining websites and applications that are accessible and usable ",{"type":32,"tag":82,"props":9780,"children":9781},{},[9782],{"type":37,"value":9783},"for as many users as possible",{"type":37,"value":9785},", including those with different types of disabilities.",{"type":32,"tag":46,"props":9787,"children":9788},{},[9789],{"type":32,"tag":161,"props":9790,"children":9794},{"alt":9791,"src":9792,"title":9791,"width":9793},"Web Accessibility","/article/web-accessiblity/web-accesibility.svg","420",[],{"type":32,"tag":46,"props":9796,"children":9797},{},[9798,9800,9805,9807,9812],{"type":37,"value":9799},"Involves the implementation of ",{"type":32,"tag":82,"props":9801,"children":9802},{},[9803],{"type":37,"value":9804},"technical, design and content features",{"type":37,"value":9806}," that enable people with visual, hearing, motor or cognitive disabilities to navigate, ",{"type":32,"tag":82,"props":9808,"children":9809},{},[9810],{"type":37,"value":9811},"understand and interact with web content",{"type":37,"value":733},{"type":32,"tag":46,"props":9814,"children":9815},{},[9816,9818,9822],{"type":37,"value":9817},"We could also describe ",{"type":32,"tag":82,"props":9819,"children":9820},{},[9821],{"type":37,"value":2282},{"type":37,"value":9823}," as a set of guidelines, rules and procedures that, when followed, have a significant impact on the user experience and accessibility of a website for a wide range of users.",{"type":32,"tag":157,"props":9825,"children":9826},{},[9827,9833,9844],{"type":32,"tag":39,"props":9828,"children":9830},{"id":9829},"benefits-of-the-accessible-web",[9831],{"type":37,"value":9832},"Benefits of the accessible web",{"type":32,"tag":46,"props":9834,"children":9835},{},[9836,9837,9842],{"type":37,"value":3506},{"type":32,"tag":82,"props":9838,"children":9839},{},[9840],{"type":37,"value":9841},"Accessible Web",{"type":37,"value":9843}," offers a number of benefits not only for users with disabilities, but for all Internet users. The following are some of the biggest benefits:",{"type":32,"tag":444,"props":9845,"children":9846},{},[9847,9863,9880,9897,9914],{"type":32,"tag":448,"props":9848,"children":9849},{},[9850,9855,9857,9862],{"type":32,"tag":82,"props":9851,"children":9852},{},[9853],{"type":37,"value":9854},"Expanding the reach of the target audience",{"type":37,"value":9856}," - The accessible web increases the accessibility of content for users with visual, hearing, motor and cognitive impairments, meaning that the web can reach a ",{"type":32,"tag":82,"props":9858,"children":9859},{},[9860],{"type":37,"value":9861},"wider range of users",{"type":37,"value":733},{"type":32,"tag":448,"props":9864,"children":9865},{},[9866,9871,9873,9878],{"type":32,"tag":82,"props":9867,"children":9868},{},[9869],{"type":37,"value":9870},"Improved SEO",{"type":37,"value":9872}," - Websites with accessible and structured content are ",{"type":32,"tag":82,"props":9874,"children":9875},{},[9876],{"type":37,"value":9877},"ranked higher by search engines",{"type":37,"value":9879},", increasing their visibility and reach online and in search.",{"type":32,"tag":448,"props":9881,"children":9882},{},[9883,9888,9890,9895],{"type":32,"tag":82,"props":9884,"children":9885},{},[9886],{"type":37,"value":9887},"Improved usability and user satisfaction",{"type":37,"value":9889}," - An accessible website provides a better usability and user experience, which can lead to ",{"type":32,"tag":82,"props":9891,"children":9892},{},[9893],{"type":37,"value":9894},"higher conversion",{"type":37,"value":9896},", lower abandonment rates and greater user loyalty.",{"type":32,"tag":448,"props":9898,"children":9899},{},[9900,9905,9907,9912],{"type":32,"tag":82,"props":9901,"children":9902},{},[9903],{"type":37,"value":9904},"Compliance with legal and regulatory requirements",{"type":37,"value":9906}," - Web accessibility is a ",{"type":32,"tag":82,"props":9908,"children":9909},{},[9910],{"type":37,"value":9911},"legislative obligation",{"type":37,"value":9913}," for any website belonging to a government entity.",{"type":32,"tag":448,"props":9915,"children":9916},{},[9917,9922,9924,9929],{"type":32,"tag":82,"props":9918,"children":9919},{},[9920],{"type":37,"value":9921},"Clearer, easier-to-understand information",{"type":37,"value":9923}," - An accessible website emphasizes structured and well-described information (learn more later in the design and development process) which contributes to ",{"type":32,"tag":82,"props":9925,"children":9926},{},[9927],{"type":37,"value":9928},"easier navigation and use of the website",{"type":37,"value":733},{"type":32,"tag":39,"props":9931,"children":9933},{"id":9932},"what-are-wai-aria-and-wcag",[9934],{"type":37,"value":9935},"What are WAI-ARIA and WCAG",{"type":32,"tag":46,"props":9937,"children":9938},{},[9939,9941,9946],{"type":37,"value":9940},"Both are key standards in the field of web accessibility. They specify ",{"type":32,"tag":82,"props":9942,"children":9943},{},[9944],{"type":37,"value":9945},"best-practices in developing and maintaining websites",{"type":37,"value":9947}," with the utmost regard for usability and clarity.",{"type":32,"tag":39,"props":9949,"children":9951},{"id":9950},"wcag-22",[9952],{"type":37,"value":9953},"WCAG 2.2",{"type":32,"tag":46,"props":9955,"children":9956},{},[9957,9959,9966],{"type":37,"value":9958},"This is ",{"type":32,"tag":139,"props":9960,"children":9963},{"href":9961,"rel":9962,"target":345},"https://www.w3.org/WAI/standards-guidelines/wcag/",[347],[9964],{"type":37,"value":9965},"a set of recommendations, guidelines for creating",{"type":37,"value":9967}," accessible web pages.",{"type":32,"tag":46,"props":9969,"children":9970},{},[9971,9973],{"type":37,"value":9972},"It ",{"type":32,"tag":82,"props":9974,"children":9975},{},[9976],{"type":37,"value":9977},"generally puts into practice the following four principles:",{"type":32,"tag":153,"props":9979,"children":9980},{},[9981,10016,10045,10080],{"type":32,"tag":157,"props":9982,"children":9983},{},[9984,9992,9998],{"type":32,"tag":46,"props":9985,"children":9986},{},[9987],{"type":32,"tag":161,"props":9988,"children":9991},{"alt":9989,"src":9990,"title":9989},"Visibility","/article/web-accessiblity/visibility.svg",[],{"type":32,"tag":169,"props":9993,"children":9995},{"id":9994},"_1-perceptibility-️",[9996],{"type":37,"value":9997},"1. Perceptibility 👁️",{"type":32,"tag":46,"props":9999,"children":10000},{},[10001,10003,10008,10010,10015],{"type":37,"value":10002},"Information and user interface components must be ",{"type":32,"tag":82,"props":10004,"children":10005},{},[10006],{"type":37,"value":10007},"presentable to users in a way they can perceive",{"type":37,"value":10009},". This means that users must be able to perceive the presented information ",{"type":32,"tag":82,"props":10011,"children":10012},{},[10013],{"type":37,"value":10014},"(it cannot be invisible to all their senses)",{"type":37,"value":733},{"type":32,"tag":157,"props":10017,"children":10018},{},[10019,10027,10033],{"type":32,"tag":46,"props":10020,"children":10021},{},[10022],{"type":32,"tag":161,"props":10023,"children":10026},{"alt":10024,"src":10025,"title":10024},"Controllability","/article/web-accessiblity/control.svg",[],{"type":32,"tag":169,"props":10028,"children":10030},{"id":10029},"_2-controllability-️",[10031],{"type":37,"value":10032},"2. Controllability 🕹️",{"type":32,"tag":46,"props":10034,"children":10035},{},[10036,10038,10043],{"type":37,"value":10037},"UI and navigation components must be controllable. This means that users ",{"type":32,"tag":82,"props":10039,"children":10040},{},[10041],{"type":37,"value":10042},"must be able to control",{"type":37,"value":10044}," the interface\r\n(the interface must not require interaction that the user cannot perform).",{"type":32,"tag":157,"props":10046,"children":10047},{},[10048,10056,10062],{"type":32,"tag":46,"props":10049,"children":10050},{},[10051],{"type":32,"tag":161,"props":10052,"children":10055},{"alt":10053,"src":10054,"title":10053},"Readability","/article/web-accessiblity/readable.svg",[],{"type":32,"tag":169,"props":10057,"children":10059},{"id":10058},"_3-intelligibility",[10060],{"type":37,"value":10061},"3. Intelligibility 😎",{"type":32,"tag":46,"props":10063,"children":10064},{},[10065,10067,10072,10074,10079],{"type":37,"value":10066},"Information and user interface controls ",{"type":32,"tag":82,"props":10068,"children":10069},{},[10070],{"type":37,"value":10071},"must be understandable",{"type":37,"value":10073},". This means that users must be able to understand the information and UI controls ",{"type":32,"tag":82,"props":10075,"children":10076},{},[10077],{"type":37,"value":10078},"(the content or controls must not be beyond their comprehension)",{"type":37,"value":733},{"type":32,"tag":157,"props":10081,"children":10082},{},[10083,10091,10097],{"type":32,"tag":46,"props":10084,"children":10085},{},[10086],{"type":32,"tag":161,"props":10087,"children":10090},{"alt":10088,"src":10089,"title":10088},"Robustness","/article/web-accessiblity/robust.svg",[],{"type":32,"tag":169,"props":10092,"children":10094},{"id":10093},"_4-robustness",[10095],{"type":37,"value":10096},"4. Robustness 🧱",{"type":32,"tag":46,"props":10098,"children":10099},{},[10100,10102,10107,10109,10114],{"type":37,"value":10101},"Content must be ",{"type":32,"tag":82,"props":10103,"children":10104},{},[10105],{"type":37,"value":10106},"sufficiently robust",{"type":37,"value":10108}," to be reliably interpreted by a wide range of user clients/devices, including assistive technologies. This means that users must be ",{"type":32,"tag":82,"props":10110,"children":10111},{},[10112],{"type":37,"value":10113},"able to access content as technology evolves",{"type":37,"value":733},{"type":32,"tag":46,"props":10116,"children":10117},{},[10118,10120,10127],{"type":37,"value":10119},"(",{"type":32,"tag":139,"props":10121,"children":10124},{"href":10122,"rel":10123},"https://www.w3.org/WAI/WCAG22/Understanding/intro#understanding-the-four-principles-of-accessibility",[347],[10125],{"type":37,"value":10126},"Source W3",{"type":37,"value":4364},{"type":32,"tag":46,"props":10129,"children":10130},{},[10131],{"type":32,"tag":139,"props":10132,"children":10134},{"href":10133},"#design-and-development-of-accessible-web",[10135],{"type":37,"value":10136},"We'll demonstrate these principles in practice below",{"type":32,"tag":46,"props":10138,"children":10139},{},[10140],{"type":32,"tag":82,"props":10141,"children":10142},{},[10143],{"type":37,"value":10144},"WCAG escalates to three levels of optimization:",{"type":32,"tag":444,"props":10146,"children":10147},{},[10148,10164,10180],{"type":32,"tag":448,"props":10149,"children":10150},{},[10151,10156,10158,10163],{"type":32,"tag":82,"props":10152,"children":10153},{},[10154],{"type":37,"value":10155},"Level A",{"type":37,"value":10157}," 🥉 is the minimum level of optimization. It aims to ensure that web content is ",{"type":32,"tag":82,"props":10159,"children":10160},{},[10161],{"type":37,"value":10162},"accessible to most users with disabilities",{"type":37,"value":733},{"type":32,"tag":448,"props":10165,"children":10166},{},[10167,10172,10174,10179],{"type":32,"tag":82,"props":10168,"children":10169},{},[10170],{"type":37,"value":10171},"Level AA",{"type":37,"value":10173}," 🥈 is a higher level of optimization than Level A. It is designed to ensure that web content is accessible to ",{"type":32,"tag":82,"props":10175,"children":10176},{},[10177],{"type":37,"value":10178},"a wider range of users with disabilities, including users with more severe disabilities",{"type":37,"value":733},{"type":32,"tag":448,"props":10181,"children":10182},{},[10183,10188,10190,10195],{"type":32,"tag":82,"props":10184,"children":10185},{},[10186],{"type":37,"value":10187},"Level AAA",{"type":37,"value":10189}," 🥇 is the highest level of optimization. It aims to ensure that the content of the site is accessible to ",{"type":32,"tag":82,"props":10191,"children":10192},{},[10193],{"type":37,"value":10194},"all users regardless of disability",{"type":37,"value":733},{"type":32,"tag":39,"props":10197,"children":10199},{"id":10198},"wai-aria",[10200],{"type":37,"value":10201},"WAI-ARIA",{"type":32,"tag":46,"props":10203,"children":10204},{},[10205,10206,10211,10213,10220,10222,10227,10229,10234],{"type":37,"value":3506},{"type":32,"tag":82,"props":10207,"children":10208},{},[10209],{"type":37,"value":10210},"Web Accessibility Initiative - Accessible Rich Internet Applications",{"type":37,"value":10212}," (WAI-ARIA) is a technical specification developed by the ",{"type":32,"tag":139,"props":10214,"children":10217},{"href":10215,"rel":10216},"https://www.w3.org",[347],[10218],{"type":37,"value":10219},"W3C",{"type":37,"value":10221},", it is a set of attributes and properties that allow developers to ",{"type":32,"tag":82,"props":10223,"children":10224},{},[10225],{"type":37,"value":10226},"tag significant user interface elements",{"type":37,"value":10228}," and provide sufficient information about their function, roles and relationships. This can help assistive technologies such as screen readers to ",{"type":32,"tag":82,"props":10230,"children":10231},{},[10232],{"type":37,"value":10233},"better interpret and display content",{"type":37,"value":10235}," at the cost of relatively little effort.",{"type":32,"tag":46,"props":10237,"children":10238},{},[10239],{"type":32,"tag":161,"props":10240,"children":10244},{"alt":10241,"src":10242,"title":10241,"width":10243},"ARIA accessibility meme","/article/web-accessiblity/aria-meme.png","250",[],{"type":32,"tag":39,"props":10246,"children":10248},{"id":10247},"accessible-web-design-and-development",[10249],{"type":37,"value":10250},"Accessible web design and development",{"type":32,"tag":46,"props":10252,"children":10253},{},[10254],{"type":37,"value":10255},"In the following sections, we will discuss the most important rules for developing an accessible website, with an example of implementation and use for each.",{"type":32,"tag":169,"props":10257,"children":10259},{"id":10258},"headings-h1-h6",[10260],{"type":37,"value":10261},"Headings H1-H6",{"type":32,"tag":46,"props":10263,"children":10264},{},[10265,10267,10272,10273,10278,10280,10285,10287,10292],{"type":37,"value":10266},"Proper use of a hierarchy of headings from ",{"type":32,"tag":117,"props":10268,"children":10269},{},[10270],{"type":37,"value":10271},"\u003CH1>",{"type":37,"value":8283},{"type":32,"tag":117,"props":10274,"children":10275},{},[10276],{"type":37,"value":10277},"\u003CH6>",{"type":37,"value":10279}," helps users and ",{"type":32,"tag":82,"props":10281,"children":10282},{},[10283],{"type":37,"value":10284},"reduces confusion when navigating the site",{"type":37,"value":10286},". This helps to better define the content structure and importance of each section of the page.\r\nThis rule also helps indexing by search bots (e.g. google bot) and ",{"type":32,"tag":82,"props":10288,"children":10289},{},[10290],{"type":37,"value":10291},"helps to improve SEO",{"type":37,"value":733},{"type":32,"tag":46,"props":10294,"children":10295},{},[10296],{"type":32,"tag":82,"props":10297,"children":10298},{},[10299],{"type":37,"value":10300},"Correct heading hierarchy:",{"type":32,"tag":7664,"props":10302,"children":10304},{"code":10303,"language":8580,"meta":7668},"\u003Ch1>Page name\u003C/h1>\r\n\u003Ch2>Section title\u003C/h2>\r\n\u003Ch2>Next section title\u003C/h2>\r\n\u003Ch3>Subsection title\u003Ch3>\r\n\u003Ch4>Fourth level heading\u003C/h4>\r\n\u003Ch3>Subsection heading\u003C/h3>\r\n\u003Ch2>Section heading\u003C/h2>\n",[10305],{"type":32,"tag":7671,"props":10306,"children":10307},{},[10308],{"type":32,"tag":7664,"props":10309,"children":10310},{"__ignoreMap":8},[10311],{"type":37,"value":10303},{"type":32,"tag":46,"props":10313,"children":10314},{},[10315],{"type":32,"tag":82,"props":10316,"children":10317},{},[10318],{"type":37,"value":10319},"Current heading hierarchy:",{"type":32,"tag":7664,"props":10321,"children":10323},{"code":10322,"language":8580,"meta":7668},"\u003Ch1>Page title\u003C/h1>\r\n\u003Ch5>Level 5 heading\u003C/h5> \u003C!-- Incorrect use of heading -->\r\n\u003Ch2>Next section heading\u003C/h2>\r\n\u003Ch1>Next page title\u003Ch1> \u003C!-- Should be only one H1 per page -->\r\n\u003Ch4>Fourth level heading\u003C/h4> \u003C!-- Incorrect use of heading -->\r\n\u003Ch3>Subsection heading\u003C/h3>\r\n\u003Ch2>Section heading\u003C/h2>\n",[10324],{"type":32,"tag":7671,"props":10325,"children":10326},{},[10327],{"type":32,"tag":7664,"props":10328,"children":10329},{"__ignoreMap":8},[10330],{"type":37,"value":10322},{"type":32,"tag":57,"props":10332,"children":10333},{},[],{"type":32,"tag":169,"props":10335,"children":10337},{"id":10336},"alternative-texts-for-media",[10338],{"type":37,"value":10339},"Alternative texts for media",{"type":32,"tag":46,"props":10341,"children":10342},{},[10343,10345,10351,10353,10358],{"type":37,"value":10344},"Every image on the web should have ",{"type":32,"tag":139,"props":10346,"children":10348},{"href":10347},"/knowledge/7-most-common-web-developer-mistakes#missing-image-alt-attribute",[10349],{"type":37,"value":10350},"alternative text",{"type":37,"value":10352}," that describes its content or purpose, which ",{"type":32,"tag":82,"props":10354,"children":10355},{},[10356],{"type":37,"value":10357},"allows users with visual impairments to understand the content",{"type":37,"value":733},{"type":32,"tag":46,"props":10360,"children":10361},{},[10362],{"type":32,"tag":10363,"props":10364,"children":10365},"em",{},[10366,10368,10373],{"type":37,"value":10367},"This rule also helps indexing by search bots (e.g. google bot) and ",{"type":32,"tag":82,"props":10369,"children":10370},{},[10371],{"type":37,"value":10372},"helps improve SEO",{"type":37,"value":733},{"type":32,"tag":46,"props":10375,"children":10376},{},[10377],{"type":32,"tag":82,"props":10378,"children":10379},{},[10380],{"type":37,"value":10381},"Properly described image:",{"type":32,"tag":7664,"props":10383,"children":10385},{"code":10384,"language":8580,"meta":7668},"\u003Cimg src=\"...\" alt=\"Implementation process diagram\">\n",[10386],{"type":32,"tag":7671,"props":10387,"children":10388},{},[10389],{"type":32,"tag":7664,"props":10390,"children":10391},{"__ignoreMap":8},[10392],{"type":37,"value":10384},{"type":32,"tag":46,"props":10394,"children":10395},{},[10396],{"type":32,"tag":82,"props":10397,"children":10398},{},[10399],{"type":37,"value":10400},"Described and misdescribed picture",{"type":32,"tag":7664,"props":10402,"children":10404},{"code":10403,"language":8580,"meta":7668},"\u003Cimg src=\"...\">\r\n\u003Cimg src=\"...\" alt=\"IMG_20240101\">\n",[10405],{"type":32,"tag":7671,"props":10406,"children":10407},{},[10408],{"type":32,"tag":7664,"props":10409,"children":10410},{"__ignoreMap":8},[10411],{"type":37,"value":10403},{"type":32,"tag":46,"props":10413,"children":10414},{},[10415,10417,10422],{"type":37,"value":10416},"If this is an image that ",{"type":32,"tag":82,"props":10418,"children":10419},{},[10420],{"type":37,"value":10421},"contains only web graphics",{"type":37,"value":10423}," then we should insert an empty alt and a role attribute with the value presentation:",{"type":32,"tag":7664,"props":10425,"children":10427},{"code":10426,"language":8580,"meta":7668},"\u003Cimg src=\"...\" alt=\"\" role=\"presentation\">\n",[10428],{"type":32,"tag":7671,"props":10429,"children":10430},{},[10431],{"type":32,"tag":7664,"props":10432,"children":10433},{"__ignoreMap":8},[10434],{"type":37,"value":10426},{"type":32,"tag":57,"props":10436,"children":10437},{},[],{"type":32,"tag":169,"props":10439,"children":10441},{"id":10440},"meta-labels",[10442],{"type":37,"value":10443},"Meta labels",{"type":32,"tag":46,"props":10445,"children":10446},{},[10447,10449,10454],{"type":37,"value":10448},"The \"description\" meta tag contains a brief summary of the page content that search engines and other tools can use to preview or snippet a page. This tag can also be useful for users who may use assistive technologies when browsing search results.\r\nThe ideal number of characters in the meta description is between ",{"type":32,"tag":82,"props":10450,"children":10451},{},[10452],{"type":37,"value":10453},"140-160 characters",{"type":37,"value":10455},", and we should briefly describe the content and meaning and the page in this text.",{"type":32,"tag":46,"props":10457,"children":10458},{},[10459],{"type":37,"value":10460},"This rule also helps indexing by search bots (e.g. google bot) and thus aids in better SEO.",{"type":32,"tag":46,"props":10462,"children":10463},{},[10464],{"type":32,"tag":82,"props":10465,"children":10466},{},[10467],{"type":37,"value":10468},"Example of how meta description of this article can look like:",{"type":32,"tag":7664,"props":10470,"children":10472},{"code":10471,"language":8580,"meta":7668},"\u003Chead>\r\n\u003Cmeta name=\"description\" content=\"Come explore the world of accessible web development. We\\'ll show you the WCAG or WAI-ARIA standards along with sample applications and much more...\">\r\n\u003C/head>\n",[10473],{"type":32,"tag":7671,"props":10474,"children":10475},{},[10476],{"type":32,"tag":7664,"props":10477,"children":10478},{"__ignoreMap":8},[10479],{"type":37,"value":10471},{"type":32,"tag":57,"props":10481,"children":10482},{},[],{"type":32,"tag":169,"props":10484,"children":10486},{"id":10485},"controlling-the-web-using-the-keyboard",[10487],{"type":37,"value":10488},"Controlling the web using the keyboard",{"type":32,"tag":46,"props":10490,"children":10491},{},[10492],{"type":37,"value":10493},"Websites should be fully keyboard navigable, which is crucial for users with limited mobility.",{"type":32,"tag":169,"props":10495,"children":10497},{"id":10496},"how-to-achieve-this",[10498],{"type":37,"value":10499},"How to achieve this?",{"type":32,"tag":46,"props":10501,"children":10502},{},[10503,10505,10510],{"type":37,"value":10504},"The very basics are to ",{"type":32,"tag":82,"props":10506,"children":10507},{},[10508],{"type":37,"value":10509},"allow the user to navigate the site and interact with the site using tab, escape, arrow keys and enter",{"type":37,"value":10511},". This means that all interaction elements on the page should be able to get focus, or be able to interact with them further.",{"type":32,"tag":46,"props":10513,"children":10514},{},[10515],{"type":32,"tag":161,"props":10516,"children":10520},{"alt":10517,"src":10518,"title":10517,"width":10519},"Keyboard Interaction","/article/web-accessiblity/keyboard.svg","450",[],{"type":32,"tag":46,"props":10522,"children":10523},{},[10524],{"type":32,"tag":82,"props":10525,"children":10526},{},[10527],{"type":37,"value":10528},"What are the elements that get focus by default?",{"type":32,"tag":444,"props":10530,"children":10531},{},[10532,10540,10548,10556,10564,10572,10580],{"type":32,"tag":448,"props":10533,"children":10534},{},[10535],{"type":32,"tag":117,"props":10536,"children":10537},{},[10538],{"type":37,"value":10539},"\u003Cselect>",{"type":32,"tag":448,"props":10541,"children":10542},{},[10543],{"type":32,"tag":117,"props":10544,"children":10545},{},[10546],{"type":37,"value":10547},"\u003Cinput>",{"type":32,"tag":448,"props":10549,"children":10550},{},[10551],{"type":32,"tag":117,"props":10552,"children":10553},{},[10554],{"type":37,"value":10555},"\u003Ctextarea>",{"type":32,"tag":448,"props":10557,"children":10558},{},[10559],{"type":32,"tag":117,"props":10560,"children":10561},{},[10562],{"type":37,"value":10563},"\u003Ciframe>",{"type":32,"tag":448,"props":10565,"children":10566},{},[10567],{"type":32,"tag":117,"props":10568,"children":10569},{},[10570],{"type":37,"value":10571},"\u003Cbutton>",{"type":32,"tag":448,"props":10573,"children":10574},{},[10575],{"type":32,"tag":117,"props":10576,"children":10577},{},[10578],{"type":37,"value":10579},"\u003Ca href=\"...\">",{"type":32,"tag":448,"props":10581,"children":10582},{},[10583,10585,10590],{"type":37,"value":10584},"Any element for which we declare ",{"type":32,"tag":117,"props":10586,"children":10587},{},[10588],{"type":37,"value":10589},"tabindex",{"type":37,"value":733},{"type":32,"tag":46,"props":10592,"children":10593},{},[10594],{"type":32,"tag":82,"props":10595,"children":10596},{},[10597],{"type":37,"value":10598},"The user on your website should be able to use tab, enter, escape and arrow keys:",{"type":32,"tag":444,"props":10600,"children":10601},{},[10602,10612,10624,10634,10644],{"type":32,"tag":448,"props":10603,"children":10604},{},[10605,10607],{"type":37,"value":10606},"1️⃣ ",{"type":32,"tag":82,"props":10608,"children":10609},{},[10610],{"type":37,"value":10611},"Expand all menu items",{"type":32,"tag":448,"props":10613,"children":10614},{},[10615,10617,10622],{"type":37,"value":10616},"2️⃣ ",{"type":32,"tag":82,"props":10618,"children":10619},{},[10620],{"type":37,"value":10621},"Submit forms",{"type":37,"value":10623}," (including search)",{"type":32,"tag":448,"props":10625,"children":10626},{},[10627,10629],{"type":37,"value":10628},"3️⃣ ",{"type":32,"tag":82,"props":10630,"children":10631},{},[10632],{"type":37,"value":10633},"Close or confirm modal windows and cookie bar",{"type":32,"tag":448,"props":10635,"children":10636},{},[10637,10639],{"type":37,"value":10638},"4️⃣ ",{"type":32,"tag":82,"props":10640,"children":10641},{},[10642],{"type":37,"value":10643},"Move around the site using linking",{"type":32,"tag":448,"props":10645,"children":10646},{},[10647,10649],{"type":37,"value":10648},"5️⃣ ",{"type":32,"tag":82,"props":10650,"children":10651},{},[10652],{"type":37,"value":10653},"To be able to have other interactions such as sliders, add to cart, find additional information that normally only shows on hover, etc",{"type":32,"tag":57,"props":10655,"children":10656},{},[],{"type":32,"tag":169,"props":10658,"children":10660},{"id":10659},"contrast-ratio-and-text-legibility",[10661],{"type":37,"value":10662},"Contrast ratio and text legibility",{"type":32,"tag":46,"props":10664,"children":10665},{},[10666,10668,10673,10675,10680],{"type":37,"value":10667},"The right contrast ratio between text and background ",{"type":32,"tag":82,"props":10669,"children":10670},{},[10671],{"type":37,"value":10672},"increases readability and improves accessibility for users",{"type":37,"value":10674}," with visual impairments, but also for those using devices with smaller screens ",{"type":32,"tag":82,"props":10676,"children":10677},{},[10678],{"type":37,"value":10679},"or in poor lighting conditions",{"type":37,"value":10681}," (you'll know when the summer sun is beating down and you're trying to find a contact number on the web to call a business).",{"type":32,"tag":46,"props":10683,"children":10684},{},[10685,10687,10692],{"type":37,"value":10686},"It's good to say that contrast ratio ",{"type":32,"tag":82,"props":10688,"children":10689},{},[10690],{"type":37,"value":10691},"should be addressed in the design of a website",{"type":37,"value":10693},", not during its implementation",{"type":32,"tag":157,"props":10695,"children":10696},{},[10697,10707],{"type":32,"tag":46,"props":10698,"children":10699},{},[10700,10705],{"type":32,"tag":82,"props":10701,"children":10702},{},[10703],{"type":37,"value":10704},"Tip:",{"type":37,"value":10706},"\r\nThe ratio can be calculated by entering the text color and background color into an online calculator, the higher the better.",{"type":32,"tag":46,"props":10708,"children":10709},{},[10710],{"type":32,"tag":139,"props":10711,"children":10713},{"href":3781,"rel":10712},[347],[10714],{"type":37,"value":10715},"Link to online calculator ➡️",{"type":32,"tag":46,"props":10717,"children":10718},{},[10719],{"type":32,"tag":82,"props":10720,"children":10721},{},[10722],{"type":37,"value":10723}," ",{"type":32,"tag":46,"props":10725,"children":10726},{},[10727,10729,10734,10736,10741,10743,10748],{"type":37,"value":10728},"WCAG states that the contrast ratio for normal text should ",{"type":32,"tag":82,"props":10730,"children":10731},{},[10732],{"type":37,"value":10733},"be at least 4.5:1",{"type":37,"value":10735},", while for ",{"type":32,"tag":82,"props":10737,"children":10738},{},[10739],{"type":37,"value":10740},"large text it should be at least 3:1",{"type":37,"value":10742}," to meet the AA level 🥈. An even higher contrast is then required for Level AAA 🥇, with ",{"type":32,"tag":82,"props":10744,"children":10745},{},[10746],{"type":37,"value":10747},"minimum 7:1 for normal text and 4.5:1 for large text",{"type":37,"value":10749},". Large text is defined as that which is at least 18px in size.",{"type":32,"tag":46,"props":10751,"children":10752},{},[10753],{"type":32,"tag":161,"props":10754,"children":10758},{"alt":10755,"src":10756,"title":10755,"width":10757},"Contrast ratio","/article/web-accessiblity/contrast.svg","320",[],{"type":32,"tag":46,"props":10760,"children":10761},{},[10762,10764,10770],{"type":37,"value":10763},"To check and simplify, you can follow the calculators to calculate the contrast ratio and the met criteria, for example in ",{"type":32,"tag":139,"props":10765,"children":10767},{"href":3781,"rel":10766},[347],[10768],{"type":37,"value":10769},"link to calculator",{"type":37,"value":733},{"type":32,"tag":157,"props":10772,"children":10773},{},[10774,10782],{"type":32,"tag":46,"props":10775,"children":10776},{},[10777],{"type":32,"tag":82,"props":10778,"children":10779},{},[10780],{"type":37,"value":10781},"For clarity, the table of values below:",{"type":32,"tag":1559,"props":10783,"children":10784},{},[10785,10805],{"type":32,"tag":1563,"props":10786,"children":10787},{},[10788],{"type":32,"tag":1567,"props":10789,"children":10790},{},[10791,10796,10800],{"type":32,"tag":1571,"props":10792,"children":10793},{"align":1573},[10794],{"type":37,"value":10795},"Text type",{"type":32,"tag":1571,"props":10797,"children":10798},{"align":1573},[10799],{"type":37,"value":10755},{"type":32,"tag":1571,"props":10801,"children":10802},{"align":1573},[10803],{"type":37,"value":10804},"WCAG compliance level",{"type":32,"tag":1588,"props":10806,"children":10807},{},[10808,10826,10843,10861],{"type":32,"tag":1567,"props":10809,"children":10810},{},[10811,10816,10821],{"type":32,"tag":1595,"props":10812,"children":10813},{"align":1573},[10814],{"type":37,"value":10815},"Normal text",{"type":32,"tag":1595,"props":10817,"children":10818},{"align":1573},[10819],{"type":37,"value":10820},"4.5:1 and above",{"type":32,"tag":1595,"props":10822,"children":10823},{"align":1573},[10824],{"type":37,"value":10825},"AA",{"type":32,"tag":1567,"props":10827,"children":10828},{},[10829,10834,10839],{"type":32,"tag":1595,"props":10830,"children":10831},{"align":1573},[10832],{"type":37,"value":10833},"Large Text",{"type":32,"tag":1595,"props":10835,"children":10836},{"align":1573},[10837],{"type":37,"value":10838},"3:1 and above",{"type":32,"tag":1595,"props":10840,"children":10841},{"align":1573},[10842],{"type":37,"value":10825},{"type":32,"tag":1567,"props":10844,"children":10845},{},[10846,10851,10856],{"type":32,"tag":1595,"props":10847,"children":10848},{"align":1573},[10849],{"type":37,"value":10850},"Normal Text",{"type":32,"tag":1595,"props":10852,"children":10853},{"align":1573},[10854],{"type":37,"value":10855},"7:1 and above",{"type":32,"tag":1595,"props":10857,"children":10858},{"align":1573},[10859],{"type":37,"value":10860},"AAA",{"type":32,"tag":1567,"props":10862,"children":10863},{},[10864,10868,10872],{"type":32,"tag":1595,"props":10865,"children":10866},{"align":1573},[10867],{"type":37,"value":10833},{"type":32,"tag":1595,"props":10869,"children":10870},{"align":1573},[10871],{"type":37,"value":10820},{"type":32,"tag":1595,"props":10873,"children":10874},{"align":1573},[10875],{"type":37,"value":10860},{"type":32,"tag":57,"props":10877,"children":10878},{},[],{"type":32,"tag":169,"props":10880,"children":10882},{"id":10881},"wai-aria-attributes-for-assistive-devices",[10883],{"type":37,"value":10884},"WAI-ARIA attributes for assistive devices",{"type":32,"tag":46,"props":10886,"children":10887},{},[10888,10894,10896,10901],{"type":32,"tag":139,"props":10889,"children":10891},{"href":10890},"#wai-aria",[10892],{"type":37,"value":10893},"We talked about WAI-AIRA in the introduction",{"type":37,"value":10895},", so it is a set of added ",{"type":32,"tag":82,"props":10897,"children":10898},{},[10899],{"type":37,"value":10900},"attributes and properties",{"type":37,"value":10902}," that we can use to enrich our HTML to make it easier for people using web readers to navigate and work with the web.",{"type":32,"tag":46,"props":10904,"children":10905},{},[10906],{"type":32,"tag":82,"props":10907,"children":10908},{},[10909],{"type":37,"value":10723},{"type":32,"tag":46,"props":10911,"children":10912},{},[10913],{"type":32,"tag":82,"props":10914,"children":10915},{},[10916],{"type":37,"value":10917},"Let's practically list the most important attributes directly with examples:",{"type":32,"tag":10919,"props":10920,"children":10922},"h4",{"id":10921},"rolebutton",[10923],{"type":32,"tag":117,"props":10924,"children":10925},{},[10926],{"type":37,"value":10927},"role=\"button\"",{"type":32,"tag":46,"props":10929,"children":10930},{},[10931,10933,10938],{"type":37,"value":10932},"identifies the element as a button, allowing assistive technologies to identify that it is an ",{"type":32,"tag":82,"props":10934,"children":10935},{},[10936],{"type":37,"value":10937},"interactive element",{"type":37,"value":10939}," that can be activated by pressing or clicking.",{"type":32,"tag":7664,"props":10941,"children":10943},{"code":10942,"language":8580,"meta":7668},"\u003Cbutton role=\"button\">Button\u003C/button>\n",[10944],{"type":32,"tag":7671,"props":10945,"children":10946},{},[10947],{"type":32,"tag":7664,"props":10948,"children":10949},{"__ignoreMap":8},[10950],{"type":37,"value":10942},{"type":32,"tag":46,"props":10952,"children":10953},{},[10954],{"type":32,"tag":82,"props":10955,"children":10956},{},[10957],{"type":37,"value":10723},{"type":32,"tag":10919,"props":10959,"children":10961},{"id":10960},"rolenavigation",[10962],{"type":32,"tag":117,"props":10963,"children":10964},{},[10965],{"type":37,"value":10966},"role=\"navigation\"",{"type":32,"tag":46,"props":10968,"children":10969},{},[10970,10972,10977],{"type":37,"value":10971},"marks part of the page as a navigation menu, which helps screen readers easily ",{"type":32,"tag":82,"props":10973,"children":10974},{},[10975],{"type":37,"value":10976},"identify navigation elements",{"type":37,"value":733},{"type":32,"tag":7664,"props":10979,"children":10981},{"code":10980,"language":8580,"meta":7668},"\u003Cnav role=\"navigation\">\r\n  \u003Cul>\r\n    \u003Cli>\u003Ca href=\"#\">Home\u003C/a>\u003C/li>\r\n    \u003Cli>\u003Ca href=\"#\">About\u003C/a>\u003C/li> \r\n    \u003Cli>\u003Ca href=\"#\">Contact\u003C/a>\u003C/li>\r\n  \u003C/ul>\r\n\u003C/nav>\n",[10982],{"type":32,"tag":7671,"props":10983,"children":10984},{},[10985],{"type":32,"tag":7664,"props":10986,"children":10987},{"__ignoreMap":8},[10988],{"type":37,"value":10980},{"type":32,"tag":46,"props":10990,"children":10991},{},[10992],{"type":32,"tag":82,"props":10993,"children":10994},{},[10995],{"type":37,"value":10723},{"type":32,"tag":10919,"props":10997,"children":10999},{"id":10998},"roletextbox",[11000],{"type":32,"tag":117,"props":11001,"children":11002},{},[11003],{"type":37,"value":11004},"role=\"textbox\"",{"type":32,"tag":46,"props":11006,"children":11007},{},[11008,11010,11015],{"type":37,"value":11009},"marks the element as a textbox, allowing assistive technologies to interpret the element as an ",{"type":32,"tag":82,"props":11011,"children":11012},{},[11013],{"type":37,"value":11014},"input box",{"type":37,"value":11016}," into which the user can enter text.",{"type":32,"tag":46,"props":11018,"children":11019},{},[11020],{"type":32,"tag":82,"props":11021,"children":11022},{},[11023],{"type":37,"value":10723},{"type":32,"tag":10919,"props":11025,"children":11027},{"id":11026},"aria-label",[11028],{"type":32,"tag":117,"props":11029,"children":11030},{},[11031],{"type":37,"value":11026},{"type":32,"tag":46,"props":11033,"children":11034},{},[11035,11037,11042],{"type":37,"value":11036},"provides an ",{"type":32,"tag":82,"props":11038,"children":11039},{},[11040],{"type":37,"value":11041},"alternative label for the element",{"type":37,"value":11043},", which helps users with limited vision to understand the function of the element",{"type":32,"tag":7664,"props":11045,"children":11047},{"code":11046,"language":8580,"meta":7668},"\u003Clabel for=\"username\">Username:\u003C/label>\r\n\u003Cinput type=\"text\" id=\"username\" name=\"username\" aria-label=\"Username\">\n",[11048],{"type":32,"tag":7671,"props":11049,"children":11050},{},[11051],{"type":32,"tag":7664,"props":11052,"children":11053},{"__ignoreMap":8},[11054],{"type":37,"value":11046},{"type":32,"tag":46,"props":11056,"children":11057},{},[11058,11060,11065,11067,11072,11074,11079],{"type":37,"value":11059},"Note the use of the ",{"type":32,"tag":117,"props":11061,"children":11062},{},[11063],{"type":37,"value":11064},"for",{"type":37,"value":11066}," + ",{"type":32,"tag":117,"props":11068,"children":11069},{},[11070],{"type":37,"value":11071},"id",{"type":37,"value":11073}," attribute, which is one of the other important accessibility points on the site, which allows readers to ",{"type":32,"tag":82,"props":11075,"children":11076},{},[11077],{"type":37,"value":11078},"link the label to the input field",{"type":37,"value":11080}," for better orientation and description.",{"type":32,"tag":46,"props":11082,"children":11083},{},[11084],{"type":32,"tag":82,"props":11085,"children":11086},{},[11087],{"type":37,"value":10723},{"type":32,"tag":10919,"props":11089,"children":11091},{"id":11090},"rolebanner",[11092],{"type":32,"tag":117,"props":11093,"children":11094},{},[11095],{"type":37,"value":11096},"role=\"banner\"",{"type":32,"tag":46,"props":11098,"children":11099},{},[11100,11102],{"type":37,"value":11101},"Indicates the part of the page that contains the ",{"type":32,"tag":82,"props":11103,"children":11104},{},[11105],{"type":37,"value":11106},"website name, logo or other identifying elements",{"type":32,"tag":7664,"props":11108,"children":11110},{"code":11109,"language":8580,"meta":7668},"\u003Cheader role=\"banner\">\r\n  \u003Cimg src=\"...\" alt=\"Logo\">\r\n  \u003Cnav role=\"navigation\">\r\n    \u003C!-- Navigation links -->\r\n  \u003C/nav>\r\n\u003C/header>\n",[11111],{"type":32,"tag":7671,"props":11112,"children":11113},{},[11114],{"type":32,"tag":7664,"props":11115,"children":11116},{"__ignoreMap":8},[11117],{"type":37,"value":11109},{"type":32,"tag":46,"props":11119,"children":11120},{},[11121],{"type":32,"tag":82,"props":11122,"children":11123},{},[11124],{"type":37,"value":10723},{"type":32,"tag":10919,"props":11126,"children":11128},{"id":11127},"rolemain",[11129],{"type":32,"tag":117,"props":11130,"children":11131},{},[11132],{"type":37,"value":11133},"role=\"main\"",{"type":32,"tag":46,"props":11135,"children":11136},{},[11137,11139,11144,11146],{"type":37,"value":11138},"indicates the main content part of the page that carries the ",{"type":32,"tag":82,"props":11140,"children":11141},{},[11142],{"type":37,"value":11143},"most important information",{"type":37,"value":11145},", for example on this particular page it would be the ",{"type":32,"tag":82,"props":11147,"children":11148},{},[11149],{"type":37,"value":11150},"content of the article itself",{"type":32,"tag":7664,"props":11152,"children":11154},{"code":11153,"language":8580,"meta":7668},"\u003Cdiv role=\"main\">\r\n  \u003C!-- Main content of page -->\r\n\u003C/div>\n",[11155],{"type":32,"tag":7671,"props":11156,"children":11157},{},[11158],{"type":32,"tag":7664,"props":11159,"children":11160},{"__ignoreMap":8},[11161],{"type":37,"value":11153},{"type":32,"tag":46,"props":11163,"children":11164},{},[11165],{"type":32,"tag":82,"props":11166,"children":11167},{},[11168],{"type":37,"value":10723},{"type":32,"tag":10919,"props":11170,"children":11172},{"id":11171},"rolesearch",[11173],{"type":32,"tag":117,"props":11174,"children":11175},{},[11176],{"type":37,"value":11177},"role=\"search\"",{"type":32,"tag":46,"props":11179,"children":11180},{},[11181,11183,11188],{"type":37,"value":11182},"indicates the part of the page containing the ",{"type":32,"tag":82,"props":11184,"children":11185},{},[11186],{"type":37,"value":11187},"search form",{"type":37,"value":11189},", can be applied directly to the form itself",{"type":32,"tag":7664,"props":11191,"children":11193},{"code":11192,"language":8580,"meta":7668},"\u003Cform action=\"/search\" method=\"get\" role=\"search\">\r\n    \u003Clabel for=\"search-input\">Search this site\u003C/label>\r\n    \u003Cinput type=\"search\" name=\"q\" id=\"search-input\" placeholder=\"Search...\" aria-label=\"Search field\">\r\n    \u003Cbutton type=\"submit\" role=\"button\">Search\u003C/button>\r\n\u003C/form>\n",[11194],{"type":32,"tag":7671,"props":11195,"children":11196},{},[11197],{"type":32,"tag":7664,"props":11198,"children":11199},{"__ignoreMap":8},[11200],{"type":37,"value":11192},{"type":32,"tag":46,"props":11202,"children":11203},{},[11204],{"type":32,"tag":82,"props":11205,"children":11206},{},[11207],{"type":37,"value":10723},{"type":32,"tag":10919,"props":11209,"children":11211},{"id":11210},"rolecomplementary",[11212],{"type":32,"tag":117,"props":11213,"children":11214},{},[11215],{"type":37,"value":11216},"role=\"complementary\"",{"type":32,"tag":46,"props":11218,"children":11219},{},[11220,11222],{"type":37,"value":11221},"Indicates supplementary content that is not necessary to understand the main content of the page, such as ",{"type":32,"tag":82,"props":11223,"children":11224},{},[11225],{"type":37,"value":11226},"sidebar links or widgets",{"type":32,"tag":7664,"props":11228,"children":11230},{"code":11229,"language":8580,"meta":7668},"\u003Caside role=\"complementary\">\r\n  \u003C!-- Complementary content, such as a sidebar -->\r\n\u003C/aside>\n",[11231],{"type":32,"tag":7671,"props":11232,"children":11233},{},[11234],{"type":32,"tag":7664,"props":11235,"children":11236},{"__ignoreMap":8},[11237],{"type":37,"value":11229},{"type":32,"tag":46,"props":11239,"children":11240},{},[11241],{"type":32,"tag":82,"props":11242,"children":11243},{},[11244],{"type":37,"value":10723},{"type":32,"tag":10919,"props":11246,"children":11248},{"id":11247},"rolecontentinfo",[11249],{"type":32,"tag":117,"props":11250,"children":11251},{},[11252],{"type":37,"value":11253},"role=\"contentinfo\"",{"type":32,"tag":46,"props":11255,"children":11256},{},[11257,11259,11264],{"type":37,"value":11258},"This attribute indicates ",{"type":32,"tag":82,"props":11260,"children":11261},{},[11262],{"type":37,"value":11263},"information about the content of the page",{"type":37,"value":11265},", usually located in the footer, such as copyright, contact information, or links to terms of use.",{"type":32,"tag":7664,"props":11267,"children":11269},{"code":11268,"language":8580,"meta":7668},"\u003Cfooter role=\"contentinfo\">\r\n  \u003C!-- Content information, such as the footer -->\r\n\u003C/footer>\n",[11270],{"type":32,"tag":7671,"props":11271,"children":11272},{},[11273],{"type":32,"tag":7664,"props":11274,"children":11275},{"__ignoreMap":8},[11276],{"type":37,"value":11268},{"type":32,"tag":57,"props":11278,"children":11279},{},[],{"type":32,"tag":169,"props":11281,"children":11283},{"id":11282},"alternative-web-version",[11284],{"type":37,"value":11285},"Alternative web version",{"type":32,"tag":46,"props":11287,"children":11288},{},[11289,11291,11296],{"type":37,"value":11290},"There may be cases where ",{"type":32,"tag":82,"props":11292,"children":11293},{},[11294],{"type":37,"value":11295},"web design does not allow for effective deployment of web accessibility",{"type":37,"value":11297},", either for design or technical reasons (for example, advanced UI work that would be difficult to optimize).",{"type":32,"tag":46,"props":11299,"children":11300},{},[11301,11303,11308],{"type":37,"value":11302},"For these and other cases, an ",{"type":32,"tag":82,"props":11304,"children":11305},{},[11306],{"type":37,"value":11307},"alternative version of the site",{"type":37,"value":11309}," can be built that differs from the classic one and is tailored primarily for web accessibility.",{"type":32,"tag":46,"props":11311,"children":11312},{},[11313,11315,11320],{"type":37,"value":11314},"The alternative version can be ",{"type":32,"tag":82,"props":11316,"children":11317},{},[11318],{"type":37,"value":11319},"differentiated by the CSS styles used",{"type":37,"value":11321}," (stronger focus, higher color contrast, larger fonts, etc...), but it can also differ in the layout of sections on the site or, for example, a simplified conversion path.",{"type":32,"tag":57,"props":11323,"children":11324},{},[],{"type":32,"tag":169,"props":11326,"children":11328},{"id":11327},"page-speed",[11329],{"type":37,"value":11330},"Page speed",{"type":32,"tag":46,"props":11332,"children":11333},{},[11334,11336,11341,11343,11348,11350,11355],{"type":37,"value":11335},"The responsiveness of web applications and pages ",{"type":32,"tag":82,"props":11337,"children":11338},{},[11339],{"type":37,"value":11340},"has a big impact on their usability",{"type":37,"value":11342},", this is also related to web accessibility, because the faster a website is, the faster and easier it is for the user to navigate and interact with it.\r\nIn addition to easier and faster web interactions, ",{"type":32,"tag":82,"props":11344,"children":11345},{},[11346],{"type":37,"value":11347},"we also gain an SEO advantage",{"type":37,"value":11349},", where search engines like Google ",{"type":32,"tag":82,"props":11351,"children":11352},{},[11353],{"type":37,"value":11354},"prioritize sites that provide better performance",{"type":37,"value":11356}," in the search listing.",{"type":32,"tag":46,"props":11358,"children":11359},{},[11360,11362,11369],{"type":37,"value":11361},"You can get a rough idea of page speed using ",{"type":32,"tag":139,"props":11363,"children":11366},{"href":11364,"rel":11365,"target":345},"https://pagespeed.web.dev",[347],[11367],{"type":37,"value":11368},"Google PageSpeed insights",{"type":37,"value":733},{"type":32,"tag":46,"props":11371,"children":11372},{},[11373],{"type":32,"tag":161,"props":11374,"children":11378},{"alt":11375,"src":11376,"title":11375,"width":11377},"Web Vitals","/article/web-accessiblity/webvitals.png","480",[],{"type":32,"tag":57,"props":11380,"children":11381},{},[],{"type":32,"tag":39,"props":11383,"children":11384},{"id":1465},[11385],{"type":37,"value":11386},"What to watch out for",{"type":32,"tag":169,"props":11388,"children":11390},{"id":11389},"google-re-captcha",[11391],{"type":37,"value":11392},"Google Re-Captcha",{"type":32,"tag":46,"props":11394,"children":11395},{},[11396,11398,11403,11405,11410],{"type":37,"value":11397},"A frequently used tool to ",{"type":32,"tag":82,"props":11399,"children":11400},{},[11401],{"type":37,"value":11402},"distinguish people from bots online",{"type":37,"value":11404},", to prevent misuse of forms or services by ",{"type":32,"tag":82,"props":11406,"children":11407},{},[11408],{"type":37,"value":11409},"deciphering objects in a picture or listening to spoken words",{"type":37,"value":11411}," and transcribing them into a text box. But is this method appropriate with respect to web accessibility?",{"type":32,"tag":46,"props":11413,"children":11414},{},[11415],{"type":32,"tag":161,"props":11416,"children":11420},{"alt":11417,"src":11418,"title":11417,"width":11419},"reCaptcha","/article/web-accessiblity/recaptcha.png","300",[],{"type":32,"tag":46,"props":11422,"children":11423},{},[11424],{"type":32,"tag":82,"props":11425,"children":11426},{},[11427],{"type":37,"value":11428},"I think this may not be a suitable solution for the following reasons:",{"type":32,"tag":444,"props":11430,"children":11431},{},[11432,11437,11442,11447],{"type":32,"tag":448,"props":11433,"children":11434},{},[11435],{"type":37,"value":11436},"Heavy testing leads to leaving the website.",{"type":32,"tag":448,"props":11438,"children":11439},{},[11440],{"type":37,"value":11441},"It can be difficult for people with motor difficulties to hit the images",{"type":32,"tag":448,"props":11443,"children":11444},{},[11445],{"type":37,"value":11446},"Persons with visual difficulties may have difficulty deciphering the image",{"type":32,"tag":448,"props":11448,"children":11449},{},[11450],{"type":37,"value":11451},"However, when switching to audio form, only the English transcript is offered, which can be a big problem for non-English speakers",{"type":32,"tag":46,"props":11453,"children":11454},{},[11455],{"type":32,"tag":82,"props":11456,"children":11457},{},[11458],{"type":37,"value":10723},{"type":32,"tag":157,"props":11460,"children":11461},{},[11462,11478],{"type":32,"tag":46,"props":11463,"children":11464},{},[11465],{"type":32,"tag":82,"props":11466,"children":11467},{"target":345},[11468,11470,11477],{"type":37,"value":11469},"The solution may be to secure forms ",{"type":32,"tag":139,"props":11471,"children":11474},{"href":11472,"rel":11473},"https://stackoverflow.com/questions/26452716/how-to-create-a-nuclear-honeypot-to-catch-form-spammers",[347],[11475],{"type":37,"value":11476},"by other methods",{"type":37,"value":6788},{"type":32,"tag":444,"props":11479,"children":11480},{},[11481,11496,11510,11520],{"type":32,"tag":448,"props":11482,"children":11483},{},[11484,11494],{"type":32,"tag":139,"props":11485,"children":11488},{"href":11486,"rel":11487,"target":345},"https://cs.wikipedia.org/wiki/Honeypot",[347],[11489],{"type":32,"tag":82,"props":11490,"children":11491},{},[11492],{"type":37,"value":11493},"Honeypot",{"type":37,"value":11495}," 🍯 - This method involves adding a hidden field to the form that will only be visible to the bot, but not to the normal user. If the field is filled in, the form is automatically marked as invalid and rejected.",{"type":32,"tag":448,"props":11497,"children":11498},{},[11499,11508],{"type":32,"tag":82,"props":11500,"children":11501},{"target":345},[11502],{"type":32,"tag":139,"props":11503,"children":11505},{"href":11472,"rel":11504},[347],[11506],{"type":37,"value":11507},"Time Trap",{"type":37,"value":11509}," ⌛ - Bots often fill out forms very quickly, while humans usually need some time to fill them out. The Time Trap method can detect if a form is filled out too quickly and mark it as suspicious.",{"type":32,"tag":448,"props":11511,"children":11512},{},[11513,11518],{"type":32,"tag":82,"props":11514,"children":11515},{},[11516],{"type":37,"value":11517},"Simple Question",{"type":37,"value":11519}," ❓- You can protect the form against spam by using a checkbox and a simple question, for example: What color are tree leaves most often?",{"type":32,"tag":448,"props":11521,"children":11522},{},[11523,11528],{"type":32,"tag":82,"props":11524,"children":11525},{},[11526],{"type":37,"value":11527},"Geographic restrictions",{"type":37,"value":11529}," 🌍 - If circumstances allow it, you can allow the form to be submitted only from a certain range of IP addresses, thus allowing the form to be submitted only from the Czech Republic, for example.",{"type":32,"tag":169,"props":11531,"children":11533},{"id":11532},"keyboard-traps",[11534],{"type":37,"value":11535},"Keyboard traps",{"type":32,"tag":46,"props":11537,"children":11538},{},[11539,11544,11546,11551,11553,11558,11560,11565,11567,11572],{"type":32,"tag":82,"props":11540,"children":11541},{},[11542],{"type":37,"value":11543},"Imagine the following situation:",{"type":37,"value":11545}," As a person with motor difficulties, you ",{"type":32,"tag":82,"props":11547,"children":11548},{},[11549],{"type":37,"value":11550},"navigate the web using only your keyboard",{"type":37,"value":11552},". You are on the detail page of an e-shop for a product and come across the \"View more product information\" button, ",{"type":32,"tag":82,"props":11554,"children":11555},{},[11556],{"type":37,"value":11557},"press enter and a modal window",{"type":37,"value":11559}," appears with more information about the product. However, ",{"type":32,"tag":82,"props":11561,"children":11562},{},[11563],{"type":37,"value":11564},"when you want to close the modal, nothing helps",{"type":37,"value":11566},", you press the esc key, you try to focus on the cross to close the modal window, but unfortunately it is not made as a link and does not have a tab index. You ",{"type":32,"tag":82,"props":11568,"children":11569},{},[11570],{"type":37,"value":11571},"have fallen into a keyboard trap",{"type":37,"value":11573}," and only a refresh of the page will help.",{"type":32,"tag":157,"props":11575,"children":11576},{},[11577],{"type":32,"tag":46,"props":11578,"children":11579},{},[11580,11581,11586],{"type":37,"value":3506},{"type":32,"tag":82,"props":11582,"children":11583},{},[11584],{"type":37,"value":11585},"solution to these situations is to test",{"type":37,"value":11587},", go through the whole site and make sure that such traps are not present.",{"type":32,"tag":39,"props":11589,"children":11591},{"id":11590},"how-to-test",[11592],{"type":37,"value":11593},"How to test?",{"type":32,"tag":46,"props":11595,"children":11596},{},[11597],{"type":37,"value":11598},"We definitely need to test, why would we need theoretical knowledge and implementation without proper verification in practice.",{"type":32,"tag":46,"props":11600,"children":11601},{},[11602],{"type":32,"tag":82,"props":11603,"children":11604},{},[11605],{"type":37,"value":11606},"Testing could be divided into two groups:",{"type":32,"tag":444,"props":11608,"children":11609},{},[11610,11627],{"type":32,"tag":448,"props":11611,"children":11612},{},[11613,11618,11620,11625],{"type":32,"tag":82,"props":11614,"children":11615},{},[11616],{"type":37,"value":11617},"Automatic tests",{"type":37,"value":11619},", these are tests where we use software that ",{"type":32,"tag":82,"props":11621,"children":11622},{},[11623],{"type":37,"value":11624},"crawls the web and checks it for accessibility",{"type":37,"value":11626},". Such tests are good for initially determining the state of optimizing a site for accessibility and identifying critical bugs.",{"type":32,"tag":448,"props":11628,"children":11629},{},[11630,11635,11637,11642,11644,11649],{"type":32,"tag":82,"props":11631,"children":11632},{},[11633],{"type":37,"value":11634},"Manual testing",{"type":37,"value":11636},", is ",{"type":32,"tag":82,"props":11638,"children":11639},{},[11640],{"type":37,"value":11641},"human testing",{"type":37,"value":11643}," ideally by our target audience for whom we are optimizing the site. ",{"type":32,"tag":82,"props":11645,"children":11646},{},[11647],{"type":37,"value":11648},"Manual testing will be more thorough",{"type":37,"value":11650}," compared to automated testing and can give us not only technical feedback but also user feedback which is equally valuable.",{"type":32,"tag":46,"props":11652,"children":11653},{},[11654],{"type":37,"value":11655},"When testing, we should have a preconceived strategy for how we test the site. It's also a good idea to set web accessibility acceptance criteria in advance (a simple example is the checklist below) and check them off as you go along.",{"type":32,"tag":169,"props":11657,"children":11659},{"id":11658},"keyboard",[11660],{"type":37,"value":11661},"Keyboard",{"type":32,"tag":46,"props":11663,"children":11664},{},[11665,11666,11671,11673,11678,11680,11685],{"type":37,"value":3506},{"type":32,"tag":82,"props":11667,"children":11668},{},[11669],{"type":37,"value":11670},"Tester will only go through the page using the keyboard",{"type":37,"value":11672},", examining whether it is easy to navigate between links, buttons and other interactive elements, and whether they can be activated using keyboard shortcuts. The emphasis is on ",{"type":32,"tag":82,"props":11674,"children":11675},{},[11676],{"type":37,"value":11677},"making navigation logical and predictable",{"type":37,"value":11679},", meaning that the user should be able to easily determine which element on the page is currently active and how to navigate to other parts of the content.\r\nKeyboard ",{"type":32,"tag":82,"props":11681,"children":11682},{},[11683],{"type":37,"value":11684},"testing is key",{"type":37,"value":11686}," to ensure that the website is usable for users with limited fine motor skills or those who cannot use a mouse for other reasons.",{"type":32,"tag":169,"props":11688,"children":11690},{"id":11689},"nvda-firefox",[11691],{"type":37,"value":11692},"NVDA + Firefox",{"type":32,"tag":46,"props":11694,"children":11695},{},[11696,11703,11705,11710,11712,11717],{"type":32,"tag":139,"props":11697,"children":11700},{"href":11698,"rel":11699,"target":345},"https://www.nvaccess.org",[347],[11701],{"type":37,"value":11702},"Nonvisual Desktop Access (acronym NVDA)",{"type":37,"value":11704}," is a great tool for blind and low vision users, allowing them ",{"type":32,"tag":82,"props":11706,"children":11707},{},[11708],{"type":37,"value":11709},"full access to web content",{"type":37,"value":11711},". The NVDA project was founded in 2006 by Michael Curran to provide an effective image reader for Microsoft Windows users. Since then, it has become ",{"type":32,"tag":82,"props":11713,"children":11714},{},[11715],{"type":37,"value":11716},"one of the most widely used tools",{"type":37,"value":11718}," for computer use for those who rely on voice output feedback.",{"type":32,"tag":46,"props":11720,"children":11721},{},[11722],{"type":32,"tag":161,"props":11723,"children":11727},{"alt":11724,"src":11725,"title":11724,"width":11726},"NVDA","/article/web-accessiblity/nvaccess.png","280",[],{"type":32,"tag":46,"props":11729,"children":11730},{},[11731,11733,11738],{"type":37,"value":11732},"The combination of NVDA with the Mozilla Firefox web browser creates an ",{"type":32,"tag":82,"props":11734,"children":11735},{},[11736],{"type":37,"value":11737},"excellent testing environment",{"type":37,"value":11739}," for web accessibility verification. This combination allows testers to simulate the experience of users with visual impairments and identify areas where websites can be improved for accessibility.",{"type":32,"tag":169,"props":11741,"children":11743},{"id":11742},"voiceover-mac",[11744],{"type":37,"value":11745},"VoiceOver Mac",{"type":32,"tag":46,"props":11747,"children":11748},{},[11749,11751,11756,11758,11765,11767,11772,11774,11779],{"type":37,"value":11750},"You may also be familiar with it, the ",{"type":32,"tag":82,"props":11752,"children":11753},{},[11754],{"type":37,"value":11755},"image reader provided by the macOS (Apple)",{"type":37,"value":11757}," operating system. ",{"type":32,"tag":139,"props":11759,"children":11762},{"href":11760,"rel":11761,"target":345},"https://support.apple.com/cs-cz/guide/voiceover/vo2682/mac",[347],[11763],{"type":37,"value":11764},"This tool",{"type":37,"value":11766}," is designed to provide voice feedback and ",{"type":32,"tag":82,"props":11768,"children":11769},{},[11770],{"type":37,"value":11771},"allow users with visual impairments to navigate within the system and use applications",{"type":37,"value":11773},". VoiceOver Mac is a powerful accessibility tool that allows users to not only browse content on screen, but also interact with it using a variety of gestures and keyboard shortcuts. This integrated tool provides a ",{"type":32,"tag":82,"props":11775,"children":11776},{},[11777],{"type":37,"value":11778},"wide range of functions",{"type":37,"value":11780}," including reading text, describing graphics, and navigating web pages.",{"type":32,"tag":46,"props":11782,"children":11783},{},[11784],{"type":32,"tag":161,"props":11785,"children":11788},{"alt":11745,"src":11786,"title":11745,"width":11787},"/article/web-accessiblity/voiceover.png","180",[],{"type":32,"tag":157,"props":11790,"children":11791},{},[11792,11800],{"type":32,"tag":46,"props":11793,"children":11794},{},[11795],{"type":32,"tag":82,"props":11796,"children":11797},{},[11798],{"type":37,"value":11799},"A few observations for testing with the web reader:",{"type":32,"tag":444,"props":11801,"children":11802},{},[11803,11814,11826,11844],{"type":32,"tag":448,"props":11804,"children":11805},{},[11806,11808,11813],{"type":37,"value":11807},"All text, links, forms and other interactive elements ",{"type":32,"tag":82,"props":11809,"children":11810},{},[11811],{"type":37,"value":11812},"should be presented in a clear manner",{"type":37,"value":733},{"type":32,"tag":448,"props":11815,"children":11816},{},[11817,11819,11824],{"type":37,"value":11818},"It is important to check that all images on the page have ",{"type":32,"tag":82,"props":11820,"children":11821},{},[11822],{"type":37,"value":11823},"appropriate alternative text",{"type":37,"value":11825}," to describe their content to users with disabilities.",{"type":32,"tag":448,"props":11827,"children":11828},{},[11829,11831,11836,11838,11843],{"type":37,"value":11830},"It is also important to check that any interactive elements, such as buttons and links, are ",{"type":32,"tag":82,"props":11832,"children":11833},{},[11834],{"type":37,"value":11835},"easily accessible using keyboard shortcuts",{"type":37,"value":11837}," and that the navigation is sufficiently clear ",{"type":32,"tag":82,"props":11839,"children":11840},{},[11841],{"type":37,"value":11842},"defines the reading order for image reader users",{"type":37,"value":733},{"type":32,"tag":448,"props":11845,"children":11846},{},[11847,11849,11854],{"type":37,"value":11848},"It is also advisable to ",{"type":32,"tag":82,"props":11850,"children":11851},{},[11852],{"type":37,"value":11853},"test dynamic content and interactive page features",{"type":37,"value":11855}," such as dialog boxes and form fields to ensure that these elements are correctly interpreted and navigable.",{"type":32,"tag":46,"props":11857,"children":11858},{},[11859],{"type":32,"tag":82,"props":11860,"children":11861},{},[11862],{"type":37,"value":10723},{"type":32,"tag":169,"props":11864,"children":11866},{"id":11865},"automated-testing-tools",[11867],{"type":37,"value":11868},"Automated testing tools",{"type":32,"tag":10919,"props":11870,"children":11872},{"id":11871},"pa11y-opensource",[11873],{"type":37,"value":11874},"pa11y (opensource)",{"type":32,"tag":46,"props":11876,"children":11877},{},[11878,11880,11885,11887,11892],{"type":37,"value":11879},"This is a ",{"type":32,"tag":82,"props":11881,"children":11882},{},[11883],{"type":37,"value":11884},"tool developed in Node.js",{"type":37,"value":11886}," that allows processing of web URLs and then provides a list of semantic errors and accessibility recommendations. Its flexibility allows integration directly into the development process or use as ",{"type":32,"tag":82,"props":11888,"children":11889},{},[11890],{"type":37,"value":11891},"part of continuous integration and deployment (CI/CD)",{"type":37,"value":11893},". This ensures that accessibility standards are met with every change to the site.",{"type":32,"tag":46,"props":11895,"children":11896},{},[11897],{"type":32,"tag":161,"props":11898,"children":11901},{"alt":11899,"src":11900,"title":11899},"Pa11y","/article/web-accessiblity/pa11y.png",[],{"type":32,"tag":39,"props":11903,"children":11905},{"id":11904},"web-accessibility-checklist",[11906],{"type":37,"value":11907},"Web Accessibility Checklist",{"type":32,"tag":46,"props":11909,"children":11910},{},[11911,11913,11918],{"type":37,"value":11912},"I have compiled a checklist of points ",{"type":32,"tag":82,"props":11914,"children":11915},{},[11916],{"type":37,"value":11917},"that I consider important when implementing accessibility on the web",{"type":37,"value":11919},". I tried to prioritize the list (the higher the priority) but it may depend on the type of project.",{"type":32,"tag":46,"props":11921,"children":11922},{},[11923],{"type":32,"tag":161,"props":11924,"children":11926},{"alt":2680,"src":6310,"title":2680,"width":11925},"120",[],{"type":32,"tag":169,"props":11928,"children":11929},{"id":9492},[11930],{"type":37,"value":2680},{"type":32,"tag":444,"props":11932,"children":11933},{},[11934,11944,11949,11954,11959,11964,11969,11974,11979,11984,11989,11994,11999,12004,12009],{"type":32,"tag":448,"props":11935,"children":11936},{},[11937,11939],{"type":37,"value":11938},"⏹️ Highlighted element with active ",{"type":32,"tag":117,"props":11940,"children":11941},{},[11942],{"type":37,"value":11943},":focus",{"type":32,"tag":448,"props":11945,"children":11946},{},[11947],{"type":37,"value":11948},"⏹️ Semantic HTML code structure (headings, navigation, tables, forms, etc.)",{"type":32,"tag":448,"props":11950,"children":11951},{},[11952],{"type":37,"value":11953},"⏹️ Ability to browse and interact with the entire site using the keyboard",{"type":32,"tag":448,"props":11955,"children":11956},{},[11957],{"type":37,"value":11958},"⏹️ Accessibility of forms using the keyboard",{"type":32,"tag":448,"props":11960,"children":11961},{},[11962],{"type":37,"value":11963},"⏹️ Alternative text for all images",{"type":32,"tag":448,"props":11965,"children":11966},{},[11967],{"type":37,"value":11968},"⏹️ Sufficient contrast and text size",{"type":32,"tag":448,"props":11970,"children":11971},{},[11972],{"type":37,"value":11973},"⏹️ Form labels",{"type":32,"tag":448,"props":11975,"children":11976},{},[11977],{"type":37,"value":11978},"⏹️ Basic WAI-ARIA attributes",{"type":32,"tag":448,"props":11980,"children":11981},{},[11982],{"type":37,"value":11983},"⏹️ Responsive design",{"type":32,"tag":448,"props":11985,"children":11986},{},[11987],{"type":37,"value":11988},"⏹️ The site should not break when the base text size is increased (System Settings)",{"type":32,"tag":448,"props":11990,"children":11991},{},[11992],{"type":37,"value":11993},"⏹️ Web is tested using manual testing",{"type":32,"tag":448,"props":11995,"children":11996},{},[11997],{"type":37,"value":11998},"⏹️ Web speed optimization",{"type":32,"tag":448,"props":12000,"children":12001},{},[12002],{"type":37,"value":12003},"⏹️ Clear link labeling",{"type":32,"tag":448,"props":12005,"children":12006},{},[12007],{"type":37,"value":12008},"⏹️ Large enough controls",{"type":32,"tag":448,"props":12010,"children":12011},{},[12012],{"type":37,"value":12013},"⏹️ Accessibility of multimedia content",{"type":32,"tag":39,"props":12015,"children":12017},{"id":12016},"užitečné-odkazy",[12018],{"type":37,"value":12019},"Užitečné odkazy",{"type":32,"tag":444,"props":12021,"children":12022},{},[12023,12033,12041,12050,12059,12068,12076,12086,12094,12103,12111,12119],{"type":32,"tag":448,"props":12024,"children":12025},{},[12026],{"type":32,"tag":139,"props":12027,"children":12030},{"href":12028,"rel":12029,":target":345},"http://blindfriendly.cz",[347],[12031],{"type":37,"value":12032},"Blind Friendly (CZ)",{"type":32,"tag":448,"props":12034,"children":12035},{},[12036],{"type":32,"tag":139,"props":12037,"children":12039},{"href":11698,"rel":12038,":target":345},[347],[12040],{"type":37,"value":11724},{"type":32,"tag":448,"props":12042,"children":12043},{},[12044],{"type":32,"tag":139,"props":12045,"children":12048},{"href":12046,"rel":12047,":target":345},"https://support.apple.com/en-gb/guide/voiceover/vo2682/mac",[347],[12049],{"type":37,"value":11745},{"type":32,"tag":448,"props":12051,"children":12052},{},[12053],{"type":32,"tag":139,"props":12054,"children":12057},{"href":12055,"rel":12056,":target":345},"https://pa11y.org",[347],[12058],{"type":37,"value":11899},{"type":32,"tag":448,"props":12060,"children":12061},{},[12062],{"type":32,"tag":139,"props":12063,"children":12066},{"href":12064,"rel":12065,":target":345},"https://www.w3.org/WAI/standards-guidelines/aria/",[347],[12067],{"type":37,"value":10201},{"type":32,"tag":448,"props":12069,"children":12070},{},[12071],{"type":32,"tag":139,"props":12072,"children":12074},{"href":9961,"rel":12073,":target":345},[347],[12075],{"type":37,"value":9750},{"type":32,"tag":448,"props":12077,"children":12078},{},[12079],{"type":32,"tag":139,"props":12080,"children":12083},{"href":12081,"rel":12082,":target":345},"https://webaim.org/",[347],[12084],{"type":37,"value":12085},"WebAIM",{"type":32,"tag":448,"props":12087,"children":12088},{},[12089],{"type":32,"tag":139,"props":12090,"children":12092},{"href":11364,"rel":12091,":target":345},[347],[12093],{"type":37,"value":11368},{"type":32,"tag":448,"props":12095,"children":12096},{},[12097],{"type":32,"tag":139,"props":12098,"children":12101},{"href":12099,"rel":12100,":target":345},"https://web.dev/vitals/",[347],[12102],{"type":37,"value":11375},{"type":32,"tag":448,"props":12104,"children":12105},{},[12106],{"type":32,"tag":139,"props":12107,"children":12109},{"href":3781,"rel":12108,":target":345},[347],[12110],{"type":37,"value":3785},{"type":32,"tag":448,"props":12112,"children":12113},{},[12114],{"type":32,"tag":139,"props":12115,"children":12117},{"href":11486,"rel":12116,":target":345},[347],[12118],{"type":37,"value":11493},{"type":32,"tag":448,"props":12120,"children":12121},{},[12122],{"type":32,"tag":139,"props":12123,"children":12125},{"href":11472,"rel":12124,":target":345},[347],[12126],{"type":37,"value":12127},"Antispam",{"title":8,"searchDepth":862,"depth":862,"links":12129},[12130,12131,12132,12133,12134,12135,12146,12150,12156,12159],{"id":9765,"depth":862,"text":9768},{"id":9829,"depth":862,"text":9832},{"id":9932,"depth":862,"text":9935},{"id":9950,"depth":862,"text":9953},{"id":10198,"depth":862,"text":10201},{"id":10247,"depth":862,"text":10250,"children":12136},[12137,12138,12139,12140,12141,12142,12143,12144,12145],{"id":10258,"depth":871,"text":10261},{"id":10336,"depth":871,"text":10339},{"id":10440,"depth":871,"text":10443},{"id":10485,"depth":871,"text":10488},{"id":10496,"depth":871,"text":10499},{"id":10659,"depth":871,"text":10662},{"id":10881,"depth":871,"text":10884},{"id":11282,"depth":871,"text":11285},{"id":11327,"depth":871,"text":11330},{"id":1465,"depth":862,"text":11386,"children":12147},[12148,12149],{"id":11389,"depth":871,"text":11392},{"id":11532,"depth":871,"text":11535},{"id":11590,"depth":862,"text":11593,"children":12151},[12152,12153,12154,12155],{"id":11658,"depth":871,"text":11661},{"id":11689,"depth":871,"text":11692},{"id":11742,"depth":871,"text":11745},{"id":11865,"depth":871,"text":11868},{"id":11904,"depth":862,"text":11907,"children":12157},[12158],{"id":9492,"depth":871,"text":2680},{"id":12016,"depth":862,"text":12019},"content:knowledge:web-accessibility-guide.md","knowledge/web-accessibility-guide.md",{"_path":12163,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":12164,"description":12165,"author":11,"date":12166,"readingTime":1799,"level":14,"image":12167,"tags":12168,"slugs":12172,"relatedArticles":12174,"body":12177,"_type":881,"_id":12912,"_source":883,"_file":12913,"_extension":885},"/knowledge/vs-code-10-most-useful-tips-you-may-not-know","VS Code - 10 most useful tips you may not know","Lets take a look at how to make working with VS Code more enjoyable and efficient with these 10 tips.","2024-01-21","/featured/vs-code-10-useful-tips.jpg",[12169,895,12170,12171],"vscode","tricks","extensions",{"en":7358,"cs":12173},"vs-code-10-uzitecnych-tipu-ktere-mozna-neznate",[5289,12175,12176],"tailwind-introduction","local-wordpress-development-harness-the-power-of-docker-containers",{"type":29,"children":12178,"toc":12897},[12179,12183,12195,12201,12213,12225,12242,12248,12267,12275,12314,12322,12328,12367,12375,12381,12406,12411,12417,12428,12479,12487,12493,12498,12525,12533,12545,12551,12556,12577,12583,12632,12640,12646,12672,12679,12684,12692,12698,12717,12725,12730,12738,12744,12774,12782,12788,12815,12823,12827],{"type":32,"tag":33,"props":12180,"children":12181},{"id":7358},[12182],{"type":37,"value":12164},{"type":32,"tag":46,"props":12184,"children":12185},{},[12186,12188,12193],{"type":37,"value":12187},"VS Code is a ",{"type":32,"tag":82,"props":12189,"children":12190},{},[12191],{"type":37,"value":12192},"multiplatform code editor",{"type":37,"value":12194},", very popular among programmers and that's why I decided to write some tips on this excellent working hammer of most web developers.",{"type":32,"tag":39,"props":12196,"children":12198},{"id":12197},"open-a-project-from-the-command-line",[12199],{"type":37,"value":12200},"Open a project from the command line",{"type":32,"tag":46,"props":12202,"children":12203},{},[12204,12206,12211],{"type":37,"value":12205},"It is very useful that you can ",{"type":32,"tag":82,"props":12207,"children":12208},{},[12209],{"type":37,"value":12210},"open a folder or file",{"type":37,"value":12212}," in VS code directly from the command line. A simple command is all it takes:",{"type":32,"tag":7664,"props":12214,"children":12217},{"code":12215,"language":12216,"meta":7668},"code \u003Cpath>\n","cmd",[12218],{"type":32,"tag":7671,"props":12219,"children":12220},{},[12221],{"type":32,"tag":7664,"props":12222,"children":12223},{"__ignoreMap":8},[12224],{"type":37,"value":12215},{"type":32,"tag":46,"props":12226,"children":12227},{},[12228,12230,12235,12237],{"type":37,"value":12229},"So when I'm in a folder I want to open I just type ",{"type":32,"tag":117,"props":12231,"children":12232},{},[12233],{"type":37,"value":12234},"code .",{"type":37,"value":12236}," And when I want to open or create a file I just type ",{"type":32,"tag":117,"props":12238,"children":12239},{},[12240],{"type":37,"value":12241},"code readme.md",{"type":32,"tag":39,"props":12243,"children":12245},{"id":12244},"multi-line-editing",[12246],{"type":37,"value":12247},"Multi-line editing",{"type":32,"tag":46,"props":12249,"children":12250},{},[12251,12253,12258,12260,12265],{"type":37,"value":12252},"If we mark a piece of code that is repeated in multiple places in the file and we want to ",{"type":32,"tag":82,"props":12254,"children":12255},{},[12256],{"type":37,"value":12257},"edit it in multiple places at once",{"type":37,"value":12259},", we just press ",{"type":32,"tag":117,"props":12261,"children":12262},{},[12263],{"type":37,"value":12264},"CTRL+D",{"type":37,"value":12266}," as many times as we want to edit the occurrences and then just type to edit the occurrences.",{"type":32,"tag":46,"props":12268,"children":12269},{},[12270],{"type":32,"tag":161,"props":12271,"children":12274},{"alt":12272,"src":12273,"title":12272},"Multiline editing","/article/vs-code-10-usefull-tips/multiline-edit.gif",[],{"type":32,"tag":46,"props":12276,"children":12277},{},[12278,12280,12285,12286,12291,12293,12298,12300,12305,12307,12312],{"type":37,"value":12279},"If you hold ",{"type":32,"tag":117,"props":12281,"children":12282},{},[12283],{"type":37,"value":12284},"CTRL+ALT",{"type":37,"value":2529},{"type":32,"tag":117,"props":12287,"children":12288},{},[12289],{"type":37,"value":12290},"CMD+ALT",{"type":37,"value":12292}," and move the arrow keys around, you'll copy the cursor to multiple lines below you and ",{"type":32,"tag":82,"props":12294,"children":12295},{},[12296],{"type":37,"value":12297},"can write multi-line",{"type":37,"value":12299},".\r\nOr you can click the mouse instead of the arrow while holding ",{"type":32,"tag":117,"props":12301,"children":12302},{},[12303],{"type":37,"value":12304},"ALT",{"type":37,"value":12306},", this allows you to ",{"type":32,"tag":82,"props":12308,"children":12309},{},[12310],{"type":37,"value":12311},"move the cursor around the document",{"type":37,"value":12313}," for multi-line editing as well.",{"type":32,"tag":46,"props":12315,"children":12316},{},[12317],{"type":32,"tag":161,"props":12318,"children":12321},{"alt":12319,"src":12320,"title":12319},"Multi-line editing with the arrow","/article/vs-code-10-usefull-tips/multiline-edit-arrow.gif",[],{"type":32,"tag":39,"props":12323,"children":12325},{"id":12324},"hands-on-the-keyboard",[12326],{"type":37,"value":12327},"Hands on the keyboard",{"type":32,"tag":46,"props":12329,"children":12330},{},[12331,12333,12338,12340,12345,12346,12351,12353,12358,12360,12365],{"type":37,"value":12332},"If you're writing code and you have to reach for the mouse, ",{"type":32,"tag":82,"props":12334,"children":12335},{},[12336],{"type":37,"value":12337},"you would have clicked to the sidepanel",{"type":37,"value":12339}," where you have your project's file tree, so you don't have to. Just hit ",{"type":32,"tag":117,"props":12341,"children":12342},{},[12343],{"type":37,"value":12344},"ctrl+0",{"type":37,"value":2529},{"type":32,"tag":117,"props":12347,"children":12348},{},[12349],{"type":37,"value":12350},"cmd+0",{"type":37,"value":12352}," and the sidebar will load. You can continue to move around with the arrow keys or start typing the file name, it will be highlighted in the tree, you can open folders with ",{"type":32,"tag":117,"props":12354,"children":12355},{},[12356],{"type":37,"value":12357},"space",{"type":37,"value":12359}," and enter the file with the ",{"type":32,"tag":117,"props":12361,"children":12362},{},[12363],{"type":37,"value":12364},"enter",{"type":37,"value":12366}," button.",{"type":32,"tag":46,"props":12368,"children":12369},{},[12370],{"type":32,"tag":161,"props":12371,"children":12374},{"alt":12372,"src":12373,"title":12372},"Using a keyboard shortcut to move around in the side navigator","/article/vs-code-10-usefull-tips/sidebar.gif",[],{"type":32,"tag":39,"props":12376,"children":12378},{"id":12377},"move-a-line",[12379],{"type":37,"value":12380},"Move a line",{"type":32,"tag":46,"props":12382,"children":12383},{},[12384,12386,12391,12393,12397,12399,12404],{"type":37,"value":12385},"In VS Code we can very easily ",{"type":32,"tag":82,"props":12387,"children":12388},{},[12389],{"type":37,"value":12390},"move a line higher or lower",{"type":37,"value":12392},". Simply place the cursor in the line you want to move, hold left ",{"type":32,"tag":117,"props":12394,"children":12395},{},[12396],{"type":37,"value":12304},{"type":37,"value":12398}," and use the up and down arrow keys to move the line.\r\nVery handy for determining the ",{"type":32,"tag":82,"props":12400,"children":12401},{},[12402],{"type":37,"value":12403},"order of function execution",{"type":37,"value":12405},", initializing objects, and so on.",{"type":32,"tag":46,"props":12407,"children":12408},{},[12409],{"type":37,"value":12410},"!Move lines using the ALT button](/article/vs-code-10-usefull-tips/alt-move.gif \"Move lines using the ALT button\")",{"type":32,"tag":39,"props":12412,"children":12414},{"id":12413},"comments",[12415],{"type":37,"value":12416},"Comments",{"type":32,"tag":46,"props":12418,"children":12419},{},[12420,12422,12427],{"type":37,"value":12421},"Comments will be much easier to work with if we learn ",{"type":32,"tag":82,"props":12423,"children":12424},{},[12425],{"type":37,"value":12426},"the following abbreviations",{"type":37,"value":6788},{"type":32,"tag":444,"props":12429,"children":12430},{},[12431,12447,12463],{"type":32,"tag":448,"props":12432,"children":12433},{},[12434,12439,12440,12445],{"type":32,"tag":117,"props":12435,"children":12436},{},[12437],{"type":37,"value":12438},"CTRL+/",{"type":37,"value":2529},{"type":32,"tag":117,"props":12441,"children":12442},{},[12443],{"type":37,"value":12444},"CMD+/",{"type":37,"value":12446}," - Adding a line comment",{"type":32,"tag":448,"props":12448,"children":12449},{},[12450,12455,12456,12461],{"type":32,"tag":117,"props":12451,"children":12452},{},[12453],{"type":37,"value":12454},"CTRL+K+C",{"type":37,"value":2529},{"type":32,"tag":117,"props":12457,"children":12458},{},[12459],{"type":37,"value":12460},"CMD+K+C",{"type":37,"value":12462}," - Add a block comment",{"type":32,"tag":448,"props":12464,"children":12465},{},[12466,12471,12472,12477],{"type":32,"tag":117,"props":12467,"children":12468},{},[12469],{"type":37,"value":12470},"CTRL+K+U",{"type":37,"value":2529},{"type":32,"tag":117,"props":12473,"children":12474},{},[12475],{"type":37,"value":12476},"CMD+K+U",{"type":37,"value":12478}," - Uncomment a block or line",{"type":32,"tag":46,"props":12480,"children":12481},{},[12482],{"type":32,"tag":161,"props":12483,"children":12486},{"alt":12484,"src":12485,"title":12484},"Working with comments","/article/vs-code-10-usefull-tips/comments.gif",[],{"type":32,"tag":39,"props":12488,"children":12490},{"id":12489},"pimp-my-terminal",[12491],{"type":37,"value":12492},"Pimp my terminal",{"type":32,"tag":46,"props":12494,"children":12495},{},[12496],{"type":37,"value":12497},"You can beautify and make the terminal you run in VS Code. After clicking on the terminal line, you can do the following:",{"type":32,"tag":444,"props":12499,"children":12500},{},[12501,12509,12517],{"type":32,"tag":448,"props":12502,"children":12503},{},[12504],{"type":32,"tag":82,"props":12505,"children":12506},{},[12507],{"type":37,"value":12508},"Change terminal color",{"type":32,"tag":448,"props":12510,"children":12511},{},[12512],{"type":32,"tag":82,"props":12513,"children":12514},{},[12515],{"type":37,"value":12516},"Change the name",{"type":32,"tag":448,"props":12518,"children":12519},{},[12520],{"type":32,"tag":82,"props":12521,"children":12522},{},[12523],{"type":37,"value":12524},"Change icon",{"type":32,"tag":46,"props":12526,"children":12527},{},[12528],{"type":32,"tag":161,"props":12529,"children":12532},{"alt":12530,"src":12531,"title":12530},"Edit terminal","/article/vs-code-10-usefull-tips/cmd.gif",[],{"type":32,"tag":46,"props":12534,"children":12535},{},[12536,12538,12543],{"type":37,"value":12537},"You can also take the terminal and move it to the open files level and ",{"type":32,"tag":82,"props":12539,"children":12540},{},[12541],{"type":37,"value":12542},"have it as a tab",{"type":37,"value":12544},", or put it halfway down the screen, allowing you to program and watch the console output.",{"type":32,"tag":39,"props":12546,"children":12548},{"id":12547},"cheatsheet",[12549],{"type":37,"value":12550},"Cheatsheet",{"type":32,"tag":46,"props":12552,"children":12553},{},[12554],{"type":37,"value":12555},"For most shortcuts there is a cheatsheet, a list of shortcuts that you can use in the editor in a clear list. A link to it is below:",{"type":32,"tag":444,"props":12557,"children":12558},{},[12559,12568],{"type":32,"tag":448,"props":12560,"children":12561},{},[12562],{"type":32,"tag":139,"props":12563,"children":12565},{"href":12564,":target":345},"/downloads/keyboard-shortcuts-windows.pdf",[12566],{"type":37,"value":12567},"Windows",{"type":32,"tag":448,"props":12569,"children":12570},{},[12571],{"type":32,"tag":139,"props":12572,"children":12574},{"href":12573,":target":345},"/downloads/keyboard-shortcuts-macos.pdf",[12575],{"type":37,"value":12576},"Mac OS",{"type":32,"tag":39,"props":12578,"children":12580},{"id":12579},"zen-mode",[12581],{"type":37,"value":12582},"Zen Mode",{"type":32,"tag":46,"props":12584,"children":12585},{},[12586,12588,12593,12595,12599,12601,12606,12608,12613,12614,12619,12621,12626,12627,12631],{"type":37,"value":12587},"Want to focus only on the code? ",{"type":32,"tag":82,"props":12589,"children":12590},{},[12591],{"type":37,"value":12592},"Don't want to see anything in the editor other than your code",{"type":37,"value":12594}," Then that's what ",{"type":32,"tag":82,"props":12596,"children":12597},{},[12598],{"type":37,"value":12582},{"type":37,"value":12600}," is all about, activated by using ",{"type":32,"tag":117,"props":12602,"children":12603},{},[12604],{"type":37,"value":12605},"Ctrl+K",{"type":37,"value":12607}," ",{"type":32,"tag":117,"props":12609,"children":12610},{},[12611],{"type":37,"value":12612},"Z",{"type":37,"value":2529},{"type":32,"tag":117,"props":12615,"children":12616},{},[12617],{"type":37,"value":12618},"View",{"type":37,"value":12620}," -> ",{"type":32,"tag":117,"props":12622,"children":12623},{},[12624],{"type":37,"value":12625},"Appearance",{"type":37,"value":12620},{"type":32,"tag":117,"props":12628,"children":12629},{},[12630],{"type":37,"value":12582},{"type":37,"value":733},{"type":32,"tag":46,"props":12633,"children":12634},{},[12635],{"type":32,"tag":161,"props":12636,"children":12639},{"alt":12637,"src":12638,"title":12637},"Zen mode","/article/vs-code-10-usefull-tips/zen-mode.gif",[],{"type":32,"tag":39,"props":12641,"children":12643},{"id":12642},"extensions-gitlens",[12644],{"type":37,"value":12645},"Extensions - GitLens",{"type":32,"tag":46,"props":12647,"children":12648},{},[12649,12651,12656,12658,12663,12665,12670],{"type":37,"value":12650},"One of the most useful extensions I know, at least for working with Git, is the ",{"type":32,"tag":82,"props":12652,"children":12653},{},[12654],{"type":37,"value":12655},"GitLens",{"type":37,"value":12657}," extension. The extension allows you to ",{"type":32,"tag":82,"props":12659,"children":12660},{},[12661],{"type":37,"value":12662},"see changes to a file directly in the editor",{"type":37,"value":12664},", you can browse the history of a file directly in the editor. You can see which git user changed which line, when they changed it, and what commit they sent it in. GitLens goes even further, showing you the ",{"type":32,"tag":82,"props":12666,"children":12667},{},[12668],{"type":37,"value":12669},"current state of the git",{"type":37,"value":12671},", each branch in a clear tree, and also allowing you to compare different versions against each other.\r\nI definitely recommend exploring GitLens.",{"type":32,"tag":46,"props":12673,"children":12674},{},[12675],{"type":32,"tag":161,"props":12676,"children":12678},{"alt":12655,"src":12677,"title":12655},"/article/vs-code-10-usefull-tips/gitlens.png",[],{"type":32,"tag":46,"props":12680,"children":12681},{},[12682],{"type":37,"value":12683},"A sample of what the branch graph view looks like in GitLens.",{"type":32,"tag":46,"props":12685,"children":12686},{},[12687],{"type":32,"tag":161,"props":12688,"children":12691},{"alt":12689,"src":12690,"title":12689},"GitLens Tree","/article/vs-code-10-usefull-tips/gitlens-tree.png",[],{"type":32,"tag":39,"props":12693,"children":12695},{"id":12694},"extensions-figma",[12696],{"type":37,"value":12697},"Extensions - Figma",{"type":32,"tag":46,"props":12699,"children":12700},{},[12701,12703,12708,12710,12715],{"type":37,"value":12702},"When I found out that there is an extension for Figma directly into VS Code two thoughts stood out in my mind. ",{"type":32,"tag":82,"props":12704,"children":12705},{},[12706],{"type":37,"value":12707},"What does it all do? And haven't extensions gone too far already?",{"type":37,"value":12709},"\r\nUpon closer inspection, you'll find that it may actually make sense. In your favorite editor, you can see ",{"type":32,"tag":82,"props":12711,"children":12712},{},[12713],{"type":37,"value":12714},"all shared figma designs",{"type":37,"value":12716},", open them and even extract CSS styles**, color values, sizes and more from the components. It really is a useful tool and I highly recommend giving it a try.",{"type":32,"tag":46,"props":12718,"children":12719},{},[12720],{"type":32,"tag":161,"props":12721,"children":12724},{"alt":12722,"src":12723,"title":12722},"Figma","/article/vs-code-10-usefull-tips/figma.png",[],{"type":32,"tag":46,"props":12726,"children":12727},{},[12728],{"type":37,"value":12729},"A sample of what the Figma design view looks like in the editor.",{"type":32,"tag":46,"props":12731,"children":12732},{},[12733],{"type":32,"tag":161,"props":12734,"children":12737},{"alt":12735,"src":12736,"title":12735},"Figma view extension","/article/vs-code-10-usefull-tips/figma-view.png",[],{"type":32,"tag":39,"props":12739,"children":12741},{"id":12740},"extension-spotify",[12742],{"type":37,"value":12743},"Extension - Spotify",{"type":32,"tag":46,"props":12745,"children":12746},{},[12747,12752,12754,12759,12761,12766,12768,12772],{"type":32,"tag":82,"props":12748,"children":12749},{},[12750],{"type":37,"value":12751},"Do you like to listen to music while you program?",{"type":37,"value":12753}," Well, I have good news for you, in the extension installation options you will find an extension called vscode-spotify that uses an API to communicate with your Spotify application and send commands to it directly from the editor. So you don't have to switch windows and you can control everything from the IDE.\r\nAfter installation you need to sign in, you do this by pressing ",{"type":32,"tag":117,"props":12755,"children":12756},{},[12757],{"type":37,"value":12758},"CTRL+P",{"type":37,"value":12760}," and in the command palette line type ",{"type":32,"tag":117,"props":12762,"children":12763},{},[12764],{"type":37,"value":12765},"> Spotify Sign In",{"type":37,"value":12767}," and press ",{"type":32,"tag":117,"props":12769,"children":12770},{},[12771],{"type":37,"value":12364},{"type":37,"value":12773},". You'll be redirected to a web site where you log in and generate authentication for the extension. You can then play.",{"type":32,"tag":46,"props":12775,"children":12776},{},[12777],{"type":32,"tag":161,"props":12778,"children":12781},{"alt":12779,"src":12780,"title":12779},"Spotify","/article/vs-code-10-usefull-tips/spotify.png",[],{"type":32,"tag":39,"props":12783,"children":12785},{"id":12784},"bonus",[12786],{"type":37,"value":12787},"Bonus",{"type":32,"tag":46,"props":12789,"children":12790},{},[12791,12793,12798,12800,12807,12809,12813],{"type":37,"value":12792},"Did you know that there is a ",{"type":32,"tag":82,"props":12794,"children":12795},{},[12796],{"type":37,"value":12797},"web version of VS Code",{"type":37,"value":12799},"? Try opening ",{"type":32,"tag":139,"props":12801,"children":12804},{"href":12802,"rel":12803},"https://github.com/standahorvath/Wordpress-Docker",[347],[12805],{"type":37,"value":12806},"any repository",{"type":37,"value":12808}," on GitHub (you have to be a logged in user) and pressing the ",{"type":32,"tag":117,"props":12810,"children":12811},{},[12812],{"type":37,"value":733},{"type":37,"value":12814}," key, i.e. the period.\r\nWeb VS Code can be used in GitHub to develop your own projects and collaborate over shared repositories. Enjoy!",{"type":32,"tag":46,"props":12816,"children":12817},{},[12818],{"type":32,"tag":161,"props":12819,"children":12822},{"alt":12820,"src":12821,"title":12820},"Web Editor","/article/vs-code-10-usefull-tips/web-editor.png",[],{"type":32,"tag":39,"props":12824,"children":12825},{"id":798},[12826],{"type":37,"value":6401},{"type":32,"tag":444,"props":12828,"children":12829},{},[12830,12840,12850,12860,12869,12878,12887],{"type":32,"tag":448,"props":12831,"children":12832},{},[12833],{"type":32,"tag":139,"props":12834,"children":12837},{"href":12835,":target":345,"rel":12836},"https://code.visualstudio.com/",[347],[12838],{"type":37,"value":12839},"VS Code",{"type":32,"tag":448,"props":12841,"children":12842},{},[12843],{"type":32,"tag":139,"props":12844,"children":12847},{"href":12845,":target":345,"rel":12846},"https://code.visualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf",[347],[12848],{"type":37,"value":12849},"VS Code - Cheatsheet Windows",{"type":32,"tag":448,"props":12851,"children":12852},{},[12853],{"type":32,"tag":139,"props":12854,"children":12857},{"href":12855,":target":345,"rel":12856},"https://code.visualstudio.com/shortcuts/keyboard-shortcuts-macos.pdf",[347],[12858],{"type":37,"value":12859},"VS Code - Cheatsheet Mac OS",{"type":32,"tag":448,"props":12861,"children":12862},{},[12863],{"type":32,"tag":139,"props":12864,"children":12867},{"href":12865,":target":345,"rel":12866},"https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens",[347],[12868],{"type":37,"value":12655},{"type":32,"tag":448,"props":12870,"children":12871},{},[12872],{"type":32,"tag":139,"props":12873,"children":12876},{"href":12874,":target":345,"rel":12875},"https://help.figma.com/hc/en-us/articles/15023121296151-Figma-for-VS-Code",[347],[12877],{"type":37,"value":12722},{"type":32,"tag":448,"props":12879,"children":12880},{},[12881],{"type":32,"tag":139,"props":12882,"children":12885},{"href":12883,":target":345,"rel":12884},"https://marketplace.visualstudio.com/items?itemName=shyykoserhiy.vscode-spotify",[347],[12886],{"type":37,"value":12779},{"type":32,"tag":448,"props":12888,"children":12889},{},[12890],{"type":32,"tag":139,"props":12891,"children":12894},{"href":12892,":target":345,"rel":12893},"https://github.dev/",[347],[12895],{"type":37,"value":12896},"VS Code Web",{"title":8,"searchDepth":862,"depth":862,"links":12898},[12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,12910,12911],{"id":12197,"depth":862,"text":12200},{"id":12244,"depth":862,"text":12247},{"id":12324,"depth":862,"text":12327},{"id":12377,"depth":862,"text":12380},{"id":12413,"depth":862,"text":12416},{"id":12489,"depth":862,"text":12492},{"id":12547,"depth":862,"text":12550},{"id":12579,"depth":862,"text":12582},{"id":12642,"depth":862,"text":12645},{"id":12694,"depth":862,"text":12697},{"id":12740,"depth":862,"text":12743},{"id":12784,"depth":862,"text":12787},{"id":798,"depth":862,"text":6401},"content:knowledge:vs-code-10-most-useful-tips-you-may-not-know.md","knowledge/vs-code-10-most-useful-tips-you-may-not-know.md",{"_path":627,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":12915,"description":12916,"author":11,"date":12917,"readingTime":1799,"level":14,"image":12918,"tags":12919,"slugs":12921,"relatedArticles":12923,"body":12924,"_type":881,"_id":13910,"_source":883,"_file":13911,"_extension":885},"Guide to the World of Web Image Formats","Learn the differences between the different formats and their advantages and disadvantages. We will show examples of how to use them and when to use which format.","2023-11-14","/featured/image-formats.jpg",[8580,12920,893],"basics",{"en":9756,"cs":12922},"pruvodce-svetem-formatu-webovych-obrazku",[3001,1809,12175],{"type":29,"children":12925,"toc":13897},[12926,12932,12936,12948,12967,12979,12987,12993,13062,13068,13073,13079,13111,13119,13130,13138,13149,13157,13169,13172,13178,13197,13205,13212,13230,13237,13249,13252,13258,13269,13277,13285,13297,13329,13336,13348,13351,13357,13382,13389,13400,13407,13425,13433,13446,13454,13457,13463,13468,13803,13807,13826,13844,13849,13853],{"type":32,"tag":33,"props":12927,"children":12929},{"id":12928},"a-guide-to-the-world-of-web-image-formats",[12930],{"type":37,"value":12931},"A guide to the world of web image formats",{"type":32,"tag":33,"props":12933,"children":12934},{"id":41},[12935],{"type":37,"value":44},{"type":32,"tag":46,"props":12937,"children":12938},{},[12939,12941,12946],{"type":37,"value":12940},"We encounter images on the web on almost every page. Some of them load at lightning speed, while others can take a while to load with a mobile connection. Yet getting a handle on web images is ",{"type":32,"tag":82,"props":12942,"children":12943},{},[12944],{"type":37,"value":12945},"one of the most important things",{"type":37,"value":12947}," when creating a new website or modifying an existing one.",{"type":32,"tag":46,"props":12949,"children":12950},{},[12951,12953,12959,12961,12966],{"type":37,"value":12952},"The speed of images can also show up in what we call ",{"type":32,"tag":139,"props":12954,"children":12956},{"href":6662,"rel":12955,"target":345},[347],[12957],{"type":37,"value":12958},"web vitals",{"type":37,"value":12960},", which are basic web speed metrics, and it's also one of the criteria Google uses to determine ",{"type":32,"tag":82,"props":12962,"children":12963},{},[12964],{"type":37,"value":12965},"the ranking of pages in a search listing",{"type":37,"value":733},{"type":32,"tag":46,"props":12968,"children":12969},{},[12970,12972,12977],{"type":37,"value":12971},"This article aims to introduce you to the ",{"type":32,"tag":82,"props":12973,"children":12974},{},[12975],{"type":37,"value":12976},"basic image formats",{"type":37,"value":12978}," and put you into practice using them, listing some best-practices and explaining their differences.",{"type":32,"tag":46,"props":12980,"children":12981},{},[12982],{"type":32,"tag":161,"props":12983,"children":12986},{"alt":12984,"src":12985,"title":12984,"width":10243},"JPG or PNG meme","/article/image-formats/jpg-or-png.jpg",[],{"type":32,"tag":39,"props":12988,"children":12990},{"id":12989},"basis",[12991],{"type":37,"value":12992},"Basis",{"type":32,"tag":153,"props":12994,"children":12995},{},[12996,13022],{"type":32,"tag":157,"props":12997,"children":12998},{},[12999,13005],{"type":32,"tag":169,"props":13000,"children":13002},{"id":13001},"bitmap",[13003],{"type":37,"value":13004},"Bitmap",{"type":32,"tag":46,"props":13006,"children":13007},{},[13008,13010,13015,13017],{"type":37,"value":13009},"Image formats can be divided into two groups, the first group is ",{"type":32,"tag":82,"props":13011,"children":13012},{},[13013],{"type":37,"value":13014},"bitmap images",{"type":37,"value":13016}," (photos, product renders, etc.) which are created from points (pixels). These formats are limited by their quality, you have to pay attention to their size (resolution), we will talk more about image sizes below.\r\n",{"type":32,"tag":161,"props":13018,"children":13021},{"alt":13019,"src":13020,"title":13019},"Sample bitmap image","/article/image-formats/bitmap_en.png",[],{"type":32,"tag":157,"props":13023,"children":13024},{},[13025,13031],{"type":32,"tag":169,"props":13026,"children":13028},{"id":13027},"vector",[13029],{"type":37,"value":13030},"Vector",{"type":32,"tag":46,"props":13032,"children":13033},{},[13034,13036,13041,13043,13048,13050,13055,13057],{"type":37,"value":13035},"The second group are ",{"type":32,"tag":82,"props":13037,"children":13038},{},[13039],{"type":37,"value":13040},"vector images",{"type":37,"value":13042},", these are images that are written using ",{"type":32,"tag":82,"props":13044,"children":13045},{},[13046],{"type":37,"value":13047},"curves and shapes",{"type":37,"value":13049},". Thanks to this notation, they can be enlarged indefinitely, as their shape is mathematically written. So you don't have to worry about the quality of the image, it stays the same. However, what we need to be careful of is that the vector is not ",{"type":32,"tag":82,"props":13051,"children":13052},{},[13053],{"type":37,"value":13054},"too complex",{"type":37,"value":13056},", if we have too many shapes in the image, it could slow down the site as all the shapes have to be calculated to render it.\r\n",{"type":32,"tag":161,"props":13058,"children":13061},{"alt":13059,"src":13060,"title":13059},"Sample vector image","/article/image-formats/vector_en.svg",[],{"type":32,"tag":39,"props":13063,"children":13065},{"id":13064},"image-formats",[13066],{"type":37,"value":13067},"Image formats",{"type":32,"tag":46,"props":13069,"children":13070},{},[13071],{"type":37,"value":13072},"Images can be stored in many ways, depending on their use and content we choose the right ones. Image formats can also be messed up, so let's take a look at the differences between them.",{"type":32,"tag":169,"props":13074,"children":13076},{"id":13075},"jpgjpeg",[13077],{"type":37,"value":13078},"JPG/JPEG",{"type":32,"tag":46,"props":13080,"children":13081},{},[13082,13084,13089,13091,13096,13098,13103,13105,13110],{"type":37,"value":13083},"A format you've probably already met, it is the ",{"type":32,"tag":82,"props":13085,"children":13086},{},[13087],{"type":37,"value":13088},"JPG or JPEG",{"type":37,"value":13090}," format and is used to store photos, pictures of cats, products and so on... This format is a ",{"type":32,"tag":82,"props":13092,"children":13093},{},[13094],{"type":37,"value":13095},"bitmap format",{"type":37,"value":13097}," and allows compression, so you can tell the image how much to save its volume. If you compress too much you get a ",{"type":32,"tag":82,"props":13099,"children":13100},{},[13101],{"type":37,"value":13102},"poor quality image",{"type":37,"value":13104},", but if the compression is too small the image can be ",{"type":32,"tag":82,"props":13106,"children":13107},{},[13108],{"type":37,"value":13109},"large in kb",{"type":37,"value":733},{"type":32,"tag":46,"props":13112,"children":13113},{},[13114],{"type":32,"tag":161,"props":13115,"children":13118},{"alt":13116,"src":13117,"title":13116},"Example of using image compression","/article/image-formats/compression_en.png",[],{"type":32,"tag":46,"props":13120,"children":13121},{},[13122,13124,13129],{"type":37,"value":13123},"In general, it is a good idea to choose an image quality with compression ",{"type":32,"tag":82,"props":13125,"children":13126},{},[13127],{"type":37,"value":13128},"between 70-90%",{"type":37,"value":733},{"type":32,"tag":46,"props":13131,"children":13132},{},[13133],{"type":32,"tag":82,"props":13134,"children":13135},{},[13136],{"type":37,"value":13137},"Benefits",{"type":32,"tag":46,"props":13139,"children":13140},{},[13141,13143,13148],{"type":37,"value":13142},"This format is suitable for storing bitmaps where we don't mind compression (photos) so much, its advantage is its ",{"type":32,"tag":82,"props":13144,"children":13145},{},[13146],{"type":37,"value":13147},"relatively small size",{"type":37,"value":733},{"type":32,"tag":46,"props":13150,"children":13151},{},[13152],{"type":32,"tag":82,"props":13153,"children":13154},{},[13155],{"type":37,"value":13156},"Disadvantages",{"type":32,"tag":46,"props":13158,"children":13159},{},[13160,13162,13167],{"type":37,"value":13161},"JPG is not a format where we can expect sharp edges between transitions of two surfaces, ",{"type":32,"tag":82,"props":13163,"children":13164},{},[13165],{"type":37,"value":13166},"not suitable for storing logos, gradients and the like",{"type":37,"value":13168},".\r\nIt does not support transparency of images.",{"type":32,"tag":57,"props":13170,"children":13171},{},[],{"type":32,"tag":39,"props":13173,"children":13175},{"id":13174},"png",[13176],{"type":37,"value":13177},"PNG",{"type":32,"tag":46,"props":13179,"children":13180},{},[13181,13183,13188,13190,13195],{"type":37,"value":13182},"Is a format that uses ",{"type":32,"tag":82,"props":13184,"children":13185},{},[13186],{"type":37,"value":13187},"error-free compression with no data loss",{"type":37,"value":13189},", which means that no information is lost during compression. PNG images retain more detail and are generally of high quality. PNG images ",{"type":32,"tag":82,"props":13191,"children":13192},{},[13193],{"type":37,"value":13194},"allow transparency",{"type":37,"value":13196},". However, it is still a bitmap and the image is therefore composed of individual pixels.",{"type":32,"tag":46,"props":13198,"children":13199},{},[13200],{"type":32,"tag":161,"props":13201,"children":13204},{"alt":13202,"src":13203,"title":13202},"PNG image example","/article/image-formats/png_example.png",[],{"type":32,"tag":46,"props":13206,"children":13207},{},[13208],{"type":32,"tag":82,"props":13209,"children":13210},{},[13211],{"type":37,"value":13137},{"type":32,"tag":46,"props":13213,"children":13214},{},[13215,13217,13222,13224,13229],{"type":37,"value":13216},"We can use PNGs ",{"type":32,"tag":82,"props":13218,"children":13219},{},[13220],{"type":37,"value":13221},"for logos, icons and various graphics",{"type":37,"value":13223}," where we take advantage of the transparency and quality of the image, but keep in mind that we are limited by quality due to the pixels in the image. Where it makes sense, let's use SVG format rather than PNG for logos and icons or simple graphics. The advantage of PNG is that it ",{"type":32,"tag":82,"props":13225,"children":13226},{},[13227],{"type":37,"value":13228},"doesn't mind transitions and sharp edged areas",{"type":37,"value":733},{"type":32,"tag":46,"props":13231,"children":13232},{},[13233],{"type":32,"tag":82,"props":13234,"children":13235},{},[13236],{"type":37,"value":13156},{"type":32,"tag":46,"props":13238,"children":13239},{},[13240,13242,13247],{"type":37,"value":13241},"PNG tends to be ",{"type":32,"tag":82,"props":13243,"children":13244},{},[13245],{"type":37,"value":13246},"bulky and data intensive",{"type":37,"value":13248}," compared to other formats.",{"type":32,"tag":57,"props":13250,"children":13251},{},[],{"type":32,"tag":169,"props":13253,"children":13255},{"id":13254},"svg",[13256],{"type":37,"value":13257},"SVG",{"type":32,"tag":46,"props":13259,"children":13260},{},[13261,13262,13267],{"type":37,"value":11879},{"type":32,"tag":82,"props":13263,"children":13264},{},[13265],{"type":37,"value":13266},"vector format",{"type":37,"value":13268},", which means that images in this format are created using mathematical paths and shapes instead of pixels, as we discussed above in the differences between Bitmap and Vector.",{"type":32,"tag":46,"props":13270,"children":13271},{},[13272],{"type":32,"tag":161,"props":13273,"children":13276},{"alt":13274,"src":13275,"title":13274},"SVG image example","/article/image-formats/svg_example.png",[],{"type":32,"tag":46,"props":13278,"children":13279},{},[13280],{"type":32,"tag":82,"props":13281,"children":13282},{},[13283],{"type":37,"value":13284},"Advantages",{"type":32,"tag":46,"props":13286,"children":13287},{},[13288,13290,13295],{"type":37,"value":13289},"SVG images are fully ",{"type":32,"tag":82,"props":13291,"children":13292},{},[13293],{"type":37,"value":13294},"scalable without loss of quality",{"type":37,"value":13296},". This means you can enlarge or reduce an SVG image to any size without blurring or distortion.",{"type":32,"tag":46,"props":13298,"children":13299},{},[13300,13302,13307,13309,13314,13316,13321,13323,13328],{"type":37,"value":13301},"The files are usually ",{"type":32,"tag":82,"props":13303,"children":13304},{},[13305],{"type":37,"value":13306},"very small",{"type":37,"value":13308},", which means faster loading web pages.\r\nSVG ",{"type":32,"tag":82,"props":13310,"children":13311},{},[13312],{"type":37,"value":13313},"supports transparency",{"type":37,"value":13315}," and allows you to create images with transparent backgrounds, which is useful for a variety of design applications.\r\nThey are ",{"type":32,"tag":82,"props":13317,"children":13318},{},[13319],{"type":37,"value":13320},"text files",{"type":37,"value":13322}," and can also be embedded directly into code.\r\n",{"type":32,"tag":82,"props":13324,"children":13325},{},[13326],{"type":37,"value":13327},"Very suitable for logos and icons",{"type":37,"value":733},{"type":32,"tag":46,"props":13330,"children":13331},{},[13332],{"type":32,"tag":82,"props":13333,"children":13334},{},[13335],{"type":37,"value":13156},{"type":32,"tag":46,"props":13337,"children":13338},{},[13339,13341,13346],{"type":37,"value":13340},"Creating complex SVG images can be tricky, especially for beginners.\r\nSVG is ",{"type":32,"tag":82,"props":13342,"children":13343},{},[13344],{"type":37,"value":13345},"not suitable for storing photos",{"type":37,"value":13347}," or images with many color gradients, as it is based on shapes and paths, which is not effective for photographic details.",{"type":32,"tag":57,"props":13349,"children":13350},{},[],{"type":32,"tag":169,"props":13352,"children":13354},{"id":13353},"webp",[13355],{"type":37,"value":13356},"WebP",{"type":32,"tag":46,"props":13358,"children":13359},{},[13360,13362,13367,13369,13374,13376,13381],{"type":37,"value":13361},"WebP is a modern format designed ",{"type":32,"tag":82,"props":13363,"children":13364},{},[13365],{"type":37,"value":13366},"for image compression",{"type":37,"value":13368},", developed by Google. Its main goal is to provide high quality images while keeping the data volume as low as possible. WebP ",{"type":32,"tag":82,"props":13370,"children":13371},{},[13372],{"type":37,"value":13373},"supports both lossy compression",{"type":37,"value":13375}," and lossless compression. It is actually a kind of universal format that combines ",{"type":32,"tag":82,"props":13377,"children":13378},{},[13379],{"type":37,"value":13380},"the best features of JPEG, PNG and GIF",{"type":37,"value":733},{"type":32,"tag":46,"props":13383,"children":13384},{},[13385],{"type":32,"tag":82,"props":13386,"children":13387},{},[13388],{"type":37,"value":13137},{"type":32,"tag":46,"props":13390,"children":13391},{},[13392,13394,13398],{"type":37,"value":13393},"This format usually provides better compression than formats like JPEG and PNG, resulting in reduced file sizes. Like PNG, WebP ",{"type":32,"tag":82,"props":13395,"children":13396},{},[13397],{"type":37,"value":13313},{"type":37,"value":13399},", which means it can be used for images with transparent backgrounds, and it also supports animations like the GIF format.",{"type":32,"tag":46,"props":13401,"children":13402},{},[13403],{"type":32,"tag":82,"props":13404,"children":13405},{},[13406],{"type":37,"value":13156},{"type":32,"tag":46,"props":13408,"children":13409},{},[13410,13412,13417,13419,13424],{"type":37,"value":13411},"Although WebP is becoming more widely used, some older browsers and platforms ",{"type":32,"tag":82,"props":13413,"children":13414},{},[13415],{"type":37,"value":13416},"may not have full support",{"type":37,"value":13418}," for the format. WebP is ideal for web images, but may not be optimal for all purposes, especially if you need to preserve ",{"type":32,"tag":82,"props":13420,"children":13421},{},[13422],{"type":37,"value":13423},"high quality detail",{"type":37,"value":733},{"type":32,"tag":46,"props":13426,"children":13427},{},[13428],{"type":32,"tag":161,"props":13429,"children":13432},{"alt":13430,"src":13431,"title":13430},"Comparison of JPG and WEBP formats","/article/image-formats/jpg_vs_webp.png",[],{"type":32,"tag":46,"props":13434,"children":13435},{},[13436,13438,13445],{"type":37,"value":13437},"Below is a table of WEBP format support by each browser version. You can learn more at ",{"type":32,"tag":139,"props":13439,"children":13442},{"href":13440,"rel":13441,"target":345},"https://caniuse.com/?search=webp",[347],[13443],{"type":37,"value":13444},"caniuse.com",{"type":37,"value":733},{"type":32,"tag":46,"props":13447,"children":13448},{},[13449],{"type":32,"tag":161,"props":13450,"children":13453},{"alt":13451,"src":13452,"title":13451},"WEBP format support table by browser","/article/image-formats/caniuse.jpg",[],{"type":32,"tag":57,"props":13455,"children":13456},{},[],{"type":32,"tag":39,"props":13458,"children":13460},{"id":13459},"comparison",[13461],{"type":37,"value":13462},"Comparison",{"type":32,"tag":46,"props":13464,"children":13465},{},[13466],{"type":37,"value":13467},"Below is a table comparing different image formats and their usage.",{"type":32,"tag":1559,"props":13469,"children":13470},{},[13471,13512],{"type":32,"tag":1563,"props":13472,"children":13473},{},[13474],{"type":32,"tag":1567,"props":13475,"children":13476},{},[13477,13482,13487,13492,13497,13502,13507],{"type":32,"tag":1571,"props":13478,"children":13479},{"align":1573},[13480],{"type":37,"value":13481},"Formats",{"type":32,"tag":1571,"props":13483,"children":13484},{"align":1573},[13485],{"type":37,"value":13486},"Photos",{"type":32,"tag":1571,"props":13488,"children":13489},{"align":1573},[13490],{"type":37,"value":13491},"Logos",{"type":32,"tag":1571,"props":13493,"children":13494},{"align":1573},[13495],{"type":37,"value":13496},"Icons",{"type":32,"tag":1571,"props":13498,"children":13499},{"align":1573},[13500],{"type":37,"value":13501},"Infographics",{"type":32,"tag":1571,"props":13503,"children":13504},{"align":1573},[13505],{"type":37,"value":13506},"Illustrations",{"type":32,"tag":1571,"props":13508,"children":13509},{"align":1573},[13510],{"type":37,"value":13511},"Animations",{"type":32,"tag":1588,"props":13513,"children":13514},{},[13515,13549,13581,13613,13644,13676,13708,13739,13771],{"type":32,"tag":1567,"props":13516,"children":13517},{},[13518,13522,13527,13532,13536,13541,13545],{"type":32,"tag":1595,"props":13519,"children":13520},{"align":1573},[13521],{"type":37,"value":13078},{"type":32,"tag":1595,"props":13523,"children":13524},{"align":1573},[13525],{"type":37,"value":13526},"YES",{"type":32,"tag":1595,"props":13528,"children":13529},{"align":1573},[13530],{"type":37,"value":13531},"NO",{"type":32,"tag":1595,"props":13533,"children":13534},{"align":1573},[13535],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13537,"children":13538},{"align":1573},[13539],{"type":37,"value":13540},"Rather not",{"type":32,"tag":1595,"props":13542,"children":13543},{"align":1573},[13544],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13546,"children":13547},{"align":1573},[13548],{"type":37,"value":13531},{"type":32,"tag":1567,"props":13550,"children":13551},{},[13552,13556,13560,13565,13569,13573,13577],{"type":32,"tag":1595,"props":13553,"children":13554},{"align":1573},[13555],{"type":37,"value":13177},{"type":32,"tag":1595,"props":13557,"children":13558},{"align":1573},[13559],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13561,"children":13562},{"align":1573},[13563],{"type":37,"value":13564},"May be",{"type":32,"tag":1595,"props":13566,"children":13567},{"align":1573},[13568],{"type":37,"value":13564},{"type":32,"tag":1595,"props":13570,"children":13571},{"align":1573},[13572],{"type":37,"value":13540},{"type":32,"tag":1595,"props":13574,"children":13575},{"align":1573},[13576],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13578,"children":13579},{"align":1573},[13580],{"type":37,"value":13531},{"type":32,"tag":1567,"props":13582,"children":13583},{},[13584,13589,13593,13597,13601,13605,13609],{"type":32,"tag":1595,"props":13585,"children":13586},{"align":1573},[13587],{"type":37,"value":13588},"GIF",{"type":32,"tag":1595,"props":13590,"children":13591},{"align":1573},[13592],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13594,"children":13595},{"align":1573},[13596],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13598,"children":13599},{"align":1573},[13600],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13602,"children":13603},{"align":1573},[13604],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13606,"children":13607},{"align":1573},[13608],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13610,"children":13611},{"align":1573},[13612],{"type":37,"value":13564},{"type":32,"tag":1567,"props":13614,"children":13615},{},[13616,13620,13624,13628,13632,13636,13640],{"type":32,"tag":1595,"props":13617,"children":13618},{"align":1573},[13619],{"type":37,"value":13257},{"type":32,"tag":1595,"props":13621,"children":13622},{"align":1573},[13623],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13625,"children":13626},{"align":1573},[13627],{"type":37,"value":13526},{"type":32,"tag":1595,"props":13629,"children":13630},{"align":1573},[13631],{"type":37,"value":13526},{"type":32,"tag":1595,"props":13633,"children":13634},{"align":1573},[13635],{"type":37,"value":13526},{"type":32,"tag":1595,"props":13637,"children":13638},{"align":1573},[13639],{"type":37,"value":13526},{"type":32,"tag":1595,"props":13641,"children":13642},{"align":1573},[13643],{"type":37,"value":13564},{"type":32,"tag":1567,"props":13645,"children":13646},{},[13647,13652,13656,13660,13664,13668,13672],{"type":32,"tag":1595,"props":13648,"children":13649},{"align":1573},[13650],{"type":37,"value":13651},"BMP",{"type":32,"tag":1595,"props":13653,"children":13654},{"align":1573},[13655],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13657,"children":13658},{"align":1573},[13659],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13661,"children":13662},{"align":1573},[13663],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13665,"children":13666},{"align":1573},[13667],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13669,"children":13670},{"align":1573},[13671],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13673,"children":13674},{"align":1573},[13675],{"type":37,"value":13531},{"type":32,"tag":1567,"props":13677,"children":13678},{},[13679,13684,13688,13692,13696,13700,13704],{"type":32,"tag":1595,"props":13680,"children":13681},{"align":1573},[13682],{"type":37,"value":13683},"TIFF",{"type":32,"tag":1595,"props":13685,"children":13686},{"align":1573},[13687],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13689,"children":13690},{"align":1573},[13691],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13693,"children":13694},{"align":1573},[13695],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13697,"children":13698},{"align":1573},[13699],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13701,"children":13702},{"align":1573},[13703],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13705,"children":13706},{"align":1573},[13707],{"type":37,"value":13531},{"type":32,"tag":1567,"props":13709,"children":13710},{},[13711,13715,13719,13723,13727,13731,13735],{"type":32,"tag":1595,"props":13712,"children":13713},{"align":1573},[13714],{"type":37,"value":13356},{"type":32,"tag":1595,"props":13716,"children":13717},{"align":1573},[13718],{"type":37,"value":13526},{"type":32,"tag":1595,"props":13720,"children":13721},{"align":1573},[13722],{"type":37,"value":13564},{"type":32,"tag":1595,"props":13724,"children":13725},{"align":1573},[13726],{"type":37,"value":13564},{"type":32,"tag":1595,"props":13728,"children":13729},{"align":1573},[13730],{"type":37,"value":13526},{"type":32,"tag":1595,"props":13732,"children":13733},{"align":1573},[13734],{"type":37,"value":13564},{"type":32,"tag":1595,"props":13736,"children":13737},{"align":1573},[13738],{"type":37,"value":13564},{"type":32,"tag":1567,"props":13740,"children":13741},{},[13742,13747,13751,13755,13759,13763,13767],{"type":32,"tag":1595,"props":13743,"children":13744},{"align":1573},[13745],{"type":37,"value":13746},"ICO",{"type":32,"tag":1595,"props":13748,"children":13749},{"align":1573},[13750],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13752,"children":13753},{"align":1573},[13754],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13756,"children":13757},{"align":1573},[13758],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13760,"children":13761},{"align":1573},[13762],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13764,"children":13765},{"align":1573},[13766],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13768,"children":13769},{"align":1573},[13770],{"type":37,"value":13531},{"type":32,"tag":1567,"props":13772,"children":13773},{},[13774,13779,13783,13787,13791,13795,13799],{"type":32,"tag":1595,"props":13775,"children":13776},{"align":1573},[13777],{"type":37,"value":13778},"EPS",{"type":32,"tag":1595,"props":13780,"children":13781},{"align":1573},[13782],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13784,"children":13785},{"align":1573},[13786],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13788,"children":13789},{"align":1573},[13790],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13792,"children":13793},{"align":1573},[13794],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13796,"children":13797},{"align":1573},[13798],{"type":37,"value":13531},{"type":32,"tag":1595,"props":13800,"children":13801},{"align":1573},[13802],{"type":37,"value":13531},{"type":32,"tag":39,"props":13804,"children":13805},{"id":774},[13806],{"type":37,"value":777},{"type":32,"tag":46,"props":13808,"children":13809},{},[13810,13812,13817,13819,13824],{"type":37,"value":13811},"To conclude this article, proper image manipulation on web pages is a ",{"type":32,"tag":82,"props":13813,"children":13814},{},[13815],{"type":37,"value":13816},"key element for optimizing loading speed",{"type":37,"value":13818}," and overall user experience. Choosing the right image format plays an ",{"type":32,"tag":82,"props":13820,"children":13821},{},[13822],{"type":37,"value":13823},"important role in striking a balance",{"type":37,"value":13825}," between quality and file size.",{"type":32,"tag":46,"props":13827,"children":13828},{},[13829,13831,13836,13838,13843],{"type":37,"value":13830},"Experiment with image formats, always check the resulting quality after exporting the image and the file size. Try to have ",{"type":32,"tag":82,"props":13832,"children":13833},{},[13834],{"type":37,"value":13835},"logos in curves in vector, photos with ideal compression like JPEG or WEBP",{"type":37,"value":13837},". On the other hand, graphics that can't handle compression and can't be in curves should probably be in PNG. Finally, ",{"type":32,"tag":82,"props":13839,"children":13840},{},[13841],{"type":37,"value":13842},"animate the vector in SVG or GIF / WEBP bitmap",{"type":37,"value":733},{"type":32,"tag":46,"props":13845,"children":13846},{},[13847],{"type":37,"value":13848},"I hope you enjoyed this article and found it useful. You can give me any feedback in messages or on social media, below I summarize some links where you can continue your study.",{"type":32,"tag":39,"props":13850,"children":13851},{"id":798},[13852],{"type":37,"value":6401},{"type":32,"tag":444,"props":13854,"children":13855},{},[13856,13866,13876,13887],{"type":32,"tag":448,"props":13857,"children":13858},{},[13859],{"type":32,"tag":139,"props":13860,"children":13863},{"href":13861,"rel":13862,":rel":347},"https://www.svgator.com",[347],[13864],{"type":37,"value":13865},"Svgator for SVG animation",{"type":32,"tag":448,"props":13867,"children":13868},{},[13869],{"type":32,"tag":139,"props":13870,"children":13873},{"href":13871,"rel":13872,":rel":347},"https://www.vzhurudolu.cz/prirucka/webp",[347],[13874],{"type":37,"value":13875},"About webp on Vzhurudol.cz",{"type":32,"tag":448,"props":13877,"children":13878},{},[13879],{"type":32,"tag":139,"props":13880,"children":13884},{"href":13881,"rel":13882,":rel":13883},"https://www.photopea.com",[347],"follow",[13885],{"type":37,"value":13886},"Online image editor",{"type":32,"tag":448,"props":13888,"children":13889},{},[13890],{"type":32,"tag":139,"props":13891,"children":13894},{"href":13892,"rel":13893,":rel":13883},"https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types",[347],[13895],{"type":37,"value":13896},"Description of image formats on mozila.org",{"title":8,"searchDepth":862,"depth":862,"links":13898},[13899,13900,13903,13907,13908,13909],{"id":12989,"depth":862,"text":12992},{"id":13064,"depth":862,"text":13067,"children":13901},[13902],{"id":13075,"depth":871,"text":13078},{"id":13174,"depth":862,"text":13177,"children":13904},[13905,13906],{"id":13254,"depth":871,"text":13257},{"id":13353,"depth":871,"text":13356},{"id":13459,"depth":862,"text":13462},{"id":774,"depth":862,"text":777},{"id":798,"depth":862,"text":6401},"content:knowledge:guide-to-the-world-of-web-image-formats.md","knowledge/guide-to-the-world-of-web-image-formats.md",{"_path":13913,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":13914,"description":13915,"author":11,"date":13916,"readingTime":13917,"level":14,"image":13918,"tags":13919,"slugs":13922,"relatedArticles":13925,"body":13926,"_type":881,"_id":14230,"_source":883,"_file":14231,"_extension":885},"/knowledge/meditation-as-a-tool-for-greater-effectiveness","Meditation as a tool for greater effectiveness","Discover the benefits of meditation for efficiency and mental health. Improves concentration, reduces stress and anxiety. Science confirms positive effects on the body and mind.","2023-08-25",7,"/featured/meditation-to-effectivity.jpg",[7354,13920,13921],"meditation","mindfulness",{"en":13923,"cs":13924},"meditation-as-a-tool-for-greater-effectiveness","meditace-jako-nastroj-k-vyssi-efektivite",[5289,7358,3000],{"type":29,"children":13927,"toc":14221},[13928,13932,13936,13941,13947,13973,13981,13987,14013,14032,14038,14078,14084,14089,14101,14109,14173,14184,14188],{"type":32,"tag":33,"props":13929,"children":13930},{"id":13923},[13931],{"type":37,"value":13914},{"type":32,"tag":39,"props":13933,"children":13934},{"id":41},[13935],{"type":37,"value":44},{"type":32,"tag":46,"props":13937,"children":13938},{},[13939],{"type":37,"value":13940},"The word meditation has different effects on different types of people. Some people have it stored in their ezo dictionary and for others it is a tool for relaxation. In this article I would like to look at what science thinks about meditation and also share some of my experiences of how I use meditation to do my work.",{"type":32,"tag":39,"props":13942,"children":13944},{"id":13943},"what-is-meditation",[13945],{"type":37,"value":13946},"What is meditation",{"type":32,"tag":46,"props":13948,"children":13949},{},[13950,13952,13957,13959,13964,13966,13971],{"type":37,"value":13951},"Meditation is a ",{"type":32,"tag":82,"props":13953,"children":13954},{},[13955],{"type":37,"value":13956},"state of relaxation",{"type":37,"value":13958}," in which we try to relax both physically and mentally. We should be in a calm environment and focus on our breath or on a particular point or thought. The goal of meditation is to ",{"type":32,"tag":82,"props":13960,"children":13961},{},[13962],{"type":37,"value":13963},"achieve inner peace and harmony",{"type":37,"value":13965},", improve your concentration and reduce stress and anxiety. There are many different meditation techniques that come from different cultures and traditions, such as ",{"type":32,"tag":82,"props":13967,"children":13968},{},[13969],{"type":37,"value":13970},"mindfulness meditation",{"type":37,"value":13972},", Zen meditation, transcendental meditation and many others.",{"type":32,"tag":46,"props":13974,"children":13975},{},[13976],{"type":32,"tag":161,"props":13977,"children":13980},{"alt":13978,"src":13979,"title":13978},"Meditation principle","/article/meditation-to-effectivity/meditation_effect.png",[],{"type":32,"tag":39,"props":13982,"children":13984},{"id":13983},"how-i-use-meditation-to-effectiveness",[13985],{"type":37,"value":13986},"How I use meditation to effectiveness",{"type":32,"tag":46,"props":13988,"children":13989},{},[13990,13992,13997,13999,14004,14006,14011],{"type":37,"value":13991},"If you're a freelancer it may be that you simply ",{"type":32,"tag":82,"props":13993,"children":13994},{},[13995],{"type":37,"value":13996},"work all the time",{"type":37,"value":13998},". When you're constantly immersed in your work, there's a danger of ",{"type":32,"tag":82,"props":14000,"children":14001},{},[14002],{"type":37,"value":14003},"burnout and fatigue",{"type":37,"value":14005},". Meditation helps me clear my head, reboot my thought processes and sort out my thoughts. If you have a head full of deadlines, obligations to meet so a simple exercise for ",{"type":32,"tag":82,"props":14007,"children":14008},{},[14009],{"type":37,"value":14010},"20 minutes a day will calm you down",{"type":37,"value":14012}," and throw you into a state of wellbeing so that you are ready to tackle a busy day.",{"type":32,"tag":46,"props":14014,"children":14015},{},[14016,14018,14023,14025,14030],{"type":37,"value":14017},"Finally, meditation allows me to ",{"type":32,"tag":82,"props":14019,"children":14020},{},[14021],{"type":37,"value":14022},"better balance my work and personal life",{"type":37,"value":14024},". A regular meditation practice reminds me of the importance of taking care of myself and my mental health. By taking time to meditate each day, I create a ",{"type":32,"tag":82,"props":14026,"children":14027},{},[14028],{"type":37,"value":14029},"structure and ritual",{"type":37,"value":14031}," that helps me maintain stability and avoid burnout.",{"type":32,"tag":39,"props":14033,"children":14035},{"id":14034},"what-science-says",[14036],{"type":37,"value":14037},"What science says",{"type":32,"tag":46,"props":14039,"children":14040},{},[14041,14043,14048,14050,14055,14057,14062,14064,14069,14071,14076],{"type":37,"value":14042},"Scientific research shows that meditation offers a wide range of beneficial effects for mental and physical health. It ",{"type":32,"tag":82,"props":14044,"children":14045},{},[14046],{"type":37,"value":14047},"reduces stress by lowering cortisol levels and suppressing inflammatory responses.",{"type":37,"value":14049}," It becomes an effective tool for managing ",{"type":32,"tag":82,"props":14051,"children":14052},{},[14053],{"type":37,"value":14054},"anxiety and anxiety disorders",{"type":37,"value":14056}," with long-term positive effects. Promotes ",{"type":32,"tag":82,"props":14058,"children":14059},{},[14060],{"type":37,"value":14061},"emotional stability",{"type":37,"value":14063}," by increasing optimism and ",{"type":32,"tag":82,"props":14065,"children":14066},{},[14067],{"type":37,"value":14068},"reducing depression",{"type":37,"value":14070},". It improves our ability for self-knowledge and concentration, bringing greater focus on tasks and peace of mind. Meditation even contributes to ",{"type":32,"tag":82,"props":14072,"children":14073},{},[14074],{"type":37,"value":14075},"better quality sleep, reduces pain and affects blood pressure",{"type":37,"value":14077},". Overall, meditation provides comprehensive health benefits for the body and mind.",{"type":32,"tag":39,"props":14079,"children":14081},{"id":14080},"how-to-get-started",[14082],{"type":37,"value":14083},"How to get started?",{"type":32,"tag":46,"props":14085,"children":14086},{},[14087],{"type":37,"value":14088},"I recommend starting with one of the guided meditations, which takes the form of spoken word and background music, where the meditation author should relax you and guide you through the entire meditation from beginning to end. There are plenty of meditations like this on youtube or maybe spotify or apple music.",{"type":32,"tag":46,"props":14090,"children":14091},{},[14092,14094,14099],{"type":37,"value":14093},"I recommend doing the meditation ",{"type":32,"tag":82,"props":14095,"children":14096},{},[14097],{"type":37,"value":14098},"regularly",{"type":37,"value":14100},", I personally notice a difference after a week of meditating for 15-20 minutes every day.",{"type":32,"tag":46,"props":14102,"children":14103},{},[14104],{"type":32,"tag":161,"props":14105,"children":14108},{"alt":14106,"src":14107,"title":14106},"Mindfulness","/article/meditation-to-effectivity/mindfulness.png",[],{"type":32,"tag":157,"props":14110,"children":14111},{},[14112,14118],{"type":32,"tag":39,"props":14113,"children":14115},{"id":14114},"some-tips",[14116],{"type":37,"value":14117},"Some tips",{"type":32,"tag":444,"props":14119,"children":14120},{},[14121,14131,14142,14152,14163],{"type":32,"tag":448,"props":14122,"children":14123},{},[14124,14129],{"type":32,"tag":82,"props":14125,"children":14126},{},[14127],{"type":37,"value":14128},"Find a quiet and peaceful place.",{"type":37,"value":14130}," Set aside a few minutes in the hustle and bustle of the day and create your own oasis of calm where you can focus on meditation.",{"type":32,"tag":448,"props":14132,"children":14133},{},[14134,14135,14140],{"type":37,"value":3506},{"type":32,"tag":82,"props":14136,"children":14137},{},[14138],{"type":37,"value":14139},"ideal time is in the morning, after stretching.",{"type":37,"value":14141}," Take a moment to stretch your body upon waking up, then settle into a quiet meditation to give your day a positive start.",{"type":32,"tag":448,"props":14143,"children":14144},{},[14145,14150],{"type":32,"tag":82,"props":14146,"children":14147},{},[14148],{"type":37,"value":14149},"Meditation techniques vary.",{"type":37,"value":14151}," Meditation is not just about one way. You can choose to watch your breath, observe the thoughts that pass through your mind, or create harmonious visualizations in your mind.",{"type":32,"tag":448,"props":14153,"children":14154},{},[14155,14156,14161],{"type":37,"value":3506},{"type":32,"tag":82,"props":14157,"children":14158},{},[14159],{"type":37,"value":14160},"key is in the regularity.",{"type":37,"value":14162}," As with any other skill, regular practice is the foundation of success. Set a firm time frame and try to meditate every day so that meditation becomes a permanent part of your life.",{"type":32,"tag":448,"props":14164,"children":14165},{},[14166,14171],{"type":32,"tag":82,"props":14167,"children":14168},{},[14169],{"type":37,"value":14170},"Nothing is wrong.",{"type":37,"value":14172}," Every meditation, even the seemingly unsuccessful ones, is a step towards a better self. Just as a flower needs time to grow, your meditation skills will develop over time. Each attempt is a valuable step towards deeper peace and inner balance.",{"type":32,"tag":157,"props":14174,"children":14175},{},[14176],{"type":32,"tag":46,"props":14177,"children":14178},{},[14179],{"type":32,"tag":161,"props":14180,"children":14183},{"alt":14181,"src":14182,"title":14181},"Meditation meme","/article/meditation-to-effectivity/meditation_meme.jpg",[],{"type":32,"tag":39,"props":14185,"children":14186},{"id":798},[14187],{"type":37,"value":6401},{"type":32,"tag":444,"props":14189,"children":14190},{},[14191,14201,14211],{"type":32,"tag":448,"props":14192,"children":14193},{},[14194],{"type":32,"tag":139,"props":14195,"children":14198},{":rel":347,"href":14196,"rel":14197},"https://www.nccih.nih.gov/health/meditation-and-mindfulness-what-you-need-to-know",[347],[14199],{"type":37,"value":14200},"Meditation at NCCIH",{"type":32,"tag":448,"props":14202,"children":14203},{},[14204],{"type":32,"tag":139,"props":14205,"children":14208},{":rel":347,"href":14206,"rel":14207},"https://en.wikipedia.org/wiki/Effects_of_meditation",[347],[14209],{"type":37,"value":14210},"Meditation Effect on Wiki",{"type":32,"tag":448,"props":14212,"children":14213},{},[14214],{"type":32,"tag":139,"props":14215,"children":14218},{":rel":13883,"href":14216,"rel":14217},"https://www.youtube.com/watch?v=SOf6EXR3qlQ",[347],[14219],{"type":37,"value":14220},"Meditation on youtube",{"title":8,"searchDepth":862,"depth":862,"links":14222},[14223,14224,14225,14226,14227,14228,14229],{"id":41,"depth":862,"text":44},{"id":13943,"depth":862,"text":13946},{"id":13983,"depth":862,"text":13986},{"id":14034,"depth":862,"text":14037},{"id":14080,"depth":862,"text":14083},{"id":14114,"depth":862,"text":14117},{"id":798,"depth":862,"text":6401},"content:knowledge:meditation-as-a-tool-for-greater-effectiveness.md","knowledge/meditation-as-a-tool-for-greater-effectiveness.md",{"_path":14233,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":14234,"description":14235,"author":11,"date":14236,"readingTime":1799,"level":9747,"image":14237,"tags":14238,"slugs":14243,"relatedArticles":14245,"body":14246,"_type":881,"_id":15185,"_source":883,"_file":15186,"_extension":885},"/knowledge/local-wordpress-development-harness-the-power-of-docker-containers","Local WordPress development: harness the power of Docker containers","Are you developing WordPress sites on localhost? Then try harnessing the power of Docker containers and see how convenient it can be.","2023-07-27","/featured/docker-and-wordpress.jpg",[14239,14240,14241,14242],"docker","wordpress","php","mysql",{"en":12176,"cs":14244},"lokalni-vyvoj-wordpressu-vyuzijte-silu-docker-kontejneru",[1810,7358,6490],{"type":29,"children":14247,"toc":15169},[14248,14252,14256,14281,14290,14295,14314,14320,14363,14374,14378,14404,14410,14451,14472,14491,14497,14502,14533,14545,14553,14559,14578,14604,14627,14639,14650,14656,14702,14713,14725,14730,14830,14849,14860,14872,14883,14888,14896,14908,14916,14930,14941,14949,14954,14962,14967,14973,14984,14995,15006,15018,15023,15068,15073,15100,15104,15135,15143,15147],{"type":32,"tag":33,"props":14249,"children":14250},{"id":12176},[14251],{"type":37,"value":14234},{"type":32,"tag":39,"props":14253,"children":14254},{"id":41},[14255],{"type":37,"value":44},{"type":32,"tag":46,"props":14257,"children":14258},{},[14259,14261,14266,14268,14273,14275,14280],{"type":37,"value":14260},"Do you develop ",{"type":32,"tag":82,"props":14262,"children":14263},{},[14264],{"type":37,"value":14265},"Wordpress",{"type":37,"value":14267}," sites locally? Then you may know annoying tasks like - create virtual host, solve PHP version, solve virtual host routing to folder, errors related to starting local PHP server like xamp, apache and so on. If you switch to docker then ",{"type":32,"tag":82,"props":14269,"children":14270},{},[14271],{"type":37,"value":14272},"part of these worries will disappear",{"type":37,"value":14274}," and you can change PHP version by rewriting one number, ",{"type":32,"tag":82,"props":14276,"children":14277},{},[14278],{"type":37,"value":14279},"read on to learn more",{"type":37,"value":733},{"type":32,"tag":46,"props":14282,"children":14283},{},[14284],{"type":32,"tag":161,"props":14285,"children":14289},{"alt":14286,"src":14287,"title":14286,"width":14288},"Docker logo","/article/docker-and-wordpress/Docker-Logo.png","240",[],{"type":32,"tag":39,"props":14291,"children":14292},{"id":14239},[14293],{"type":37,"value":14294},"Docker 🐋",{"type":32,"tag":46,"props":14296,"children":14297},{},[14298,14300,14305,14307,14312],{"type":37,"value":14299},"Allows you to ",{"type":32,"tag":82,"props":14301,"children":14302},{},[14303],{"type":37,"value":14304},"encapsulate WordPress and its development environment",{"type":37,"value":14306},", including the web server, database, and other dependencies, into so-called containers. These containers are ",{"type":32,"tag":82,"props":14308,"children":14309},{},[14310],{"type":37,"value":14311},"isolated and run on any device",{"type":37,"value":14313}," that supports Docker, regardless of operating system. This minimizes the risk of version conflicts and makes the development environment easily portable and shareable between team members.",{"type":32,"tag":169,"props":14315,"children":14317},{"id":14316},"i-would-divide-the-use-of-the-docker-into-two-basic-ones",[14318],{"type":37,"value":14319},"I would divide the use of the docker into two basic ones.",{"type":32,"tag":153,"props":14321,"children":14322},{},[14323,14343],{"type":32,"tag":157,"props":14324,"children":14325},{},[14326],{"type":32,"tag":46,"props":14327,"children":14328},{},[14329,14334,14336,14341],{"type":32,"tag":82,"props":14330,"children":14331},{},[14332],{"type":37,"value":14333},"Docker for local development",{"type":37,"value":14335}," - in this case we use docker as a development environment to which we ",{"type":32,"tag":82,"props":14337,"children":14338},{},[14339],{"type":37,"value":14340},"attach a shared folder",{"type":37,"value":14342}," with the project and the container has the ability to work with our project files. We have the ability to easily add the containers and technologies we need for development.",{"type":32,"tag":157,"props":14344,"children":14345},{},[14346],{"type":32,"tag":46,"props":14347,"children":14348},{},[14349,14354,14356,14361],{"type":32,"tag":82,"props":14350,"children":14351},{},[14352],{"type":37,"value":14353},"Docker for deploy",{"type":37,"value":14355}," - this is ",{"type":32,"tag":82,"props":14357,"children":14358},{},[14359],{"type":37,"value":14360},"deploying our application using the container, to production servers",{"type":37,"value":14362},". Usually we use the same or slightly modified containers from development, so we have a very good chance that our application will behave identically to how it did during development.",{"type":32,"tag":46,"props":14364,"children":14365},{},[14366,14368,14373],{"type":37,"value":14367},"In this article, we will discuss the use of docker for local development of ",{"type":32,"tag":82,"props":14369,"children":14370},{},[14371],{"type":37,"value":14372},"Wordpress CMS",{"type":37,"value":733},{"type":32,"tag":39,"props":14375,"children":14376},{"id":14240},[14377],{"type":37,"value":14265},{"type":32,"tag":46,"props":14379,"children":14380},{},[14381,14383,14388,14390,14395,14397,14402],{"type":37,"value":14382},"To make the introduction complete, it is necessary to explain what Wordpress is, although I assume that the reader of this article who decides to dockerize Wordpress has already met it. WordPress is an ",{"type":32,"tag":82,"props":14384,"children":14385},{},[14386],{"type":37,"value":14387},"open-source content management system (CMS)",{"type":37,"value":14389},". It is a web platform that allows users to easily create and manage websites and blogs without the need for extensive programming knowledge. WordPress offers an ",{"type":32,"tag":82,"props":14391,"children":14392},{},[14393],{"type":37,"value":14394},"intuitive user interface",{"type":37,"value":14396},", a rich menu of templates and plugins, allowing for quick and easy customization and extension of site features. It's ",{"type":32,"tag":82,"props":14398,"children":14399},{},[14400],{"type":37,"value":14401},"widely adopted",{"type":37,"value":14403}," for its simplicity and modularity thanks to the aforementioned plugins, wide variety of templates and so on.",{"type":32,"tag":39,"props":14405,"children":14407},{"id":14406},"pre-requisites",[14408],{"type":37,"value":14409},"Pre-requisites",{"type":32,"tag":46,"props":14411,"children":14412},{},[14413,14415,14420,14422,14429,14431,14436,14438,14443,14444,14449],{"type":37,"value":14414},"In order to run anything on docker we need a ",{"type":32,"tag":82,"props":14416,"children":14417},{},[14418],{"type":37,"value":14419},"docker client",{"type":37,"value":14421},". For local development, I recommend ",{"type":32,"tag":139,"props":14423,"children":14426},{"href":14424,"rel":14425},"https://www.docker.com/products/docker-desktop/",[347],[14427],{"type":37,"value":14428},"Docker Desktop application",{"type":37,"value":14430},", which uses a nice UI to show the ",{"type":32,"tag":82,"props":14432,"children":14433},{},[14434],{"type":37,"value":14435},"current state of our containers",{"type":37,"value":14437},", allows us to ",{"type":32,"tag":82,"props":14439,"children":14440},{},[14441],{"type":37,"value":14442},"delete images",{"type":37,"value":2497},{"type":32,"tag":82,"props":14445,"children":14446},{},[14447],{"type":37,"value":14448},"volumes",{"type":37,"value":14450}," and much more.",{"type":32,"tag":46,"props":14452,"children":14453},{},[14454,14456,14461,14463,14470],{"type":37,"value":14455},"Next, we'll need a ",{"type":32,"tag":82,"props":14457,"children":14458},{},[14459],{"type":37,"value":14460},"text editor",{"type":37,"value":14462}," (I recommend ",{"type":32,"tag":139,"props":14464,"children":14467},{"href":14465,"rel":14466},"https://code.visualstudio.com",[347],[14468],{"type":37,"value":14469},"Visual Studio Code",{"type":37,"value":14471},") and a folder where we'll create the project.",{"type":32,"tag":157,"props":14473,"children":14474},{},[14475],{"type":32,"tag":46,"props":14476,"children":14477},{},[14478,14483,14485],{"type":32,"tag":82,"props":14479,"children":14480},{},[14481],{"type":37,"value":14482},"TIP:",{"type":37,"value":14484}," If you want to skip the manual file creation and download the project directly, you can do so in this repository: ",{"type":32,"tag":139,"props":14486,"children":14488},{"href":12802,"rel":14487},[347],[14489],{"type":37,"value":14490},"github.com/standahorvath/Wordpress-Docker",{"type":32,"tag":39,"props":14492,"children":14494},{"id":14493},"lets-get-started",[14495],{"type":37,"value":14496},"Let's get started",{"type":32,"tag":46,"props":14498,"children":14499},{},[14500],{"type":37,"value":14501},"To develop comfortably on wordpress we need the following:",{"type":32,"tag":444,"props":14503,"children":14504},{},[14505,14515,14523],{"type":32,"tag":448,"props":14506,"children":14507},{},[14508,14513],{"type":32,"tag":82,"props":14509,"children":14510},{},[14511],{"type":37,"value":14512},"PHP server",{"type":37,"value":14514}," (in our case apache)",{"type":32,"tag":448,"props":14516,"children":14517},{},[14518],{"type":32,"tag":82,"props":14519,"children":14520},{},[14521],{"type":37,"value":14522},"MySQL database",{"type":32,"tag":448,"props":14524,"children":14525},{},[14526,14531],{"type":32,"tag":82,"props":14527,"children":14528},{},[14529],{"type":37,"value":14530},"PhpMyAdmin",{"type":37,"value":14532}," (for database management)",{"type":32,"tag":46,"props":14534,"children":14535},{},[14536,14538,14543],{"type":37,"value":14537},"Our task will be to ",{"type":32,"tag":82,"props":14539,"children":14540},{},[14541],{"type":37,"value":14542},"make containers out of these three services and run Wordpress",{"type":37,"value":14544}," on them.",{"type":32,"tag":46,"props":14546,"children":14547},{},[14548],{"type":32,"tag":161,"props":14549,"children":14552},{"alt":14550,"src":14551,"title":14550},"Docker compose project overview","/article/docker-and-wordpress/docker-compose-project.png",[],{"type":32,"tag":39,"props":14554,"children":14556},{"id":14555},"dockerfile",[14557],{"type":37,"value":14558},"Dockerfile",{"type":32,"tag":46,"props":14560,"children":14561},{},[14562,14564,14569,14571,14576],{"type":37,"value":14563},"A Dockerfile is a ",{"type":32,"tag":82,"props":14565,"children":14566},{},[14567],{"type":37,"value":14568},"text file containing instructions and commands",{"type":37,"value":14570}," for creating a custom Docker container. This file defines ",{"type":32,"tag":82,"props":14572,"children":14573},{},[14574],{"type":37,"value":14575},"how the container should be built",{"type":37,"value":14577},", which includes the base image, installing the necessary software packages, copying files into the container, setting up the environment, and other configurations.",{"type":32,"tag":46,"props":14579,"children":14580},{},[14581,14583,14588,14590,14595,14597,14602],{"type":37,"value":14582},"Our Dockerfile will be based on the ",{"type":32,"tag":117,"props":14584,"children":14585},{},[14586],{"type":37,"value":14587},"php:8.2-apache",{"type":37,"value":14589}," image, which is a Linux image running apache with ",{"type":32,"tag":82,"props":14591,"children":14592},{},[14593],{"type":37,"value":14594},"PHP version 8.2",{"type":37,"value":14596},". At the same time, we know that we want to mount the web application (in our case Wordpress) to the ",{"type":32,"tag":117,"props":14598,"children":14599},{},[14600],{"type":37,"value":14601},"/var/www/html",{"type":37,"value":14603}," folder inside the container.",{"type":32,"tag":153,"props":14605,"children":14606},{},[14607],{"type":32,"tag":157,"props":14608,"children":14609},{},[14610],{"type":32,"tag":46,"props":14611,"children":14612},{},[14613,14618,14620],{"type":32,"tag":82,"props":14614,"children":14615},{},[14616],{"type":37,"value":14617},"Note:",{"type":37,"value":14619}," If we wanted to replace the PHP version with another one, we just need to change the image tag that the Dockerfile is based on. List all the tags for php here: ",{"type":32,"tag":139,"props":14621,"children":14624},{"href":14622,"rel":14623},"https://hub.docker.com/_/php/tags",[347],[14625],{"type":37,"value":14626},"hub.docker.com/_/php/tags",{"type":32,"tag":46,"props":14628,"children":14629},{},[14630,14632,14637],{"type":37,"value":14631},"We will place the Dockerfile in the ",{"type":32,"tag":117,"props":14633,"children":14634},{},[14635],{"type":37,"value":14636},"docker/dev/Dockerfile",{"type":37,"value":14638}," folder in our project and it will look like this:",{"type":32,"tag":7664,"props":14640,"children":14642},{"code":14641,"language":14555,"meta":7668},"## The base image we are starting from\r\nFROM php:8.2-apache\r\n\r\n# Setting up the working directory\r\nWORKDIR /var/www/html\r\n\r\n# Installing dependencies\r\nRUN apt-get update && apt-get install -y \\\r\n    curl \\\r\n    git \\\r\n    zlib1g-dev \\\r\n    libicu-dev \\\r\n    g++ \\\r\n    libpng-dev \\\r\n    libwebp-dev \\\r\n    libfreetype6-dev \\\r\n    libjpeg62-turbo-dev \\\r\n    libmcrypt-dev \\\r\n    libzip-dev\r\n\r\n# Installing PHP extensions\r\nRUN docker-php-ext-configure gd --with-webp --with-freetype --with-jpeg \\\r\n    && docker-php-ext-configure zip \\\r\n    && docker-php-ext-install gd intl zip mysqli pdo pdo_mysql\r\n\r\n# Set rights for the project folder\r\nRUN chown -R www-data:www-data /var/www/html\r\n\r\n# Install composer if we would like to use it\r\nRUN curl -sSL https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer\r\n\r\n# Enable mod_rewrite for apache\r\nRUN a2enmod rewrite\r\n\r\n# Exposing port 80\r\nEXPOSE 80\r\n\r\n# Start apache server\r\nCMD [\"apache2-foreground\"]\n",[14643],{"type":32,"tag":7671,"props":14644,"children":14645},{},[14646],{"type":32,"tag":7664,"props":14647,"children":14648},{"__ignoreMap":8},[14649],{"type":37,"value":14641},{"type":32,"tag":39,"props":14651,"children":14653},{"id":14652},"docker-composeyml",[14654],{"type":37,"value":14655},"docker-compose.yml",{"type":32,"tag":46,"props":14657,"children":14658},{},[14659,14660,14665,14667,14672,14674,14679,14681,14686,14688,14693,14695,14700],{"type":37,"value":11879},{"type":32,"tag":82,"props":14661,"children":14662},{},[14663],{"type":37,"value":14664},"text file",{"type":37,"value":14666}," in ",{"type":32,"tag":117,"props":14668,"children":14669},{},[14670],{"type":37,"value":14671},"YAML",{"type":37,"value":14673}," format that tells **how to start ",{"type":32,"tag":82,"props":14675,"children":14676},{},[14677],{"type":37,"value":14678},"which containers",{"type":37,"value":14680},", on ",{"type":32,"tag":82,"props":14682,"children":14683},{},[14684],{"type":37,"value":14685},"which port",{"type":37,"value":14687}," to run, where to get ",{"type":32,"tag":117,"props":14689,"children":14690},{},[14691],{"type":37,"value":14692},"Images",{"type":37,"value":14694}," for them, which folders to ",{"type":32,"tag":82,"props":14696,"children":14697},{},[14698],{"type":37,"value":14699},"mount",{"type":37,"value":14701},", and so on.",{"type":32,"tag":46,"props":14703,"children":14704},{},[14705,14707,14711],{"type":37,"value":14706},"Our ",{"type":32,"tag":117,"props":14708,"children":14709},{},[14710],{"type":37,"value":14655},{"type":37,"value":14712}," will look like this:",{"type":32,"tag":7664,"props":14714,"children":14717},{"code":14715,"language":14716,"meta":7668},"version: '3'\r\nservices:\r\n  # PHP server\r\n  php:\r\n    # container name (WP-App)\r\n    container_name: WP-App\r\n    build:\r\n      # Path to Dockerfile in our project\r\n      dockerfile: docker/dev/Dockerfile\r\n    volumes:\r\n      # Mount the project folder to /var/www/html/ inside the container\r\n      - ./:/var/www/html/\r\n    ports:\r\n      # Exposing port 80 to port 80 on our system\r\n      - 80:80\r\n    depends_on:\r\n      # Depend on the database container, wait for it to start\r\n      - database\r\n    links:\r\n      # Link database container to php container\r\n      - database\r\n\r\n  database:\r\n    # Container name (WP-Database)\r\n    container_name: WP-Database\r\n    # Image used\r\n    platform: linux/x86_64\r\n    image: mysql:5.7\r\n    ports:\r\n      - 3306:3306\r\n    # User, password and database settings from .env file\r\n    env_file:\r\n      - docker/dev/.env\r\n\r\n  phpmyadmin:\r\n    # Container name (WP-PhpMyAdmin)\r\n    container_name: WP-PhpMyAdmin\r\n    # Again, dependency on the database container\r\n    depends_on:\r\n      - database\r\n    # The image used\r\n    image: phpmyadmin/phpmyadmin\r\n    # Exposing port 80 to port 8282 of our system i.e. localhost:8282\r\n    ports:\r\n      - '8282:80'\r\n    # Setting up the user, password and database from the .env file\r\n    env_file:\r\n      - docker/dev/.env\r\n    # Set the upload limit to 300M if we would like to import .sql\r\n    environment:\r\n      UPLOAD_LIMIT: 300M\n","yaml",[14718],{"type":32,"tag":7671,"props":14719,"children":14720},{},[14721],{"type":32,"tag":7664,"props":14722,"children":14723},{"__ignoreMap":8},[14724],{"type":37,"value":14715},{"type":32,"tag":46,"props":14726,"children":14727},{},[14728],{"type":37,"value":14729},"The configuration consists of a total of three containers.",{"type":32,"tag":444,"props":14731,"children":14732},{},[14733,14758,14782,14807],{"type":32,"tag":448,"props":14734,"children":14735},{},[14736,14738,14743,14745,14750,14752,14756],{"type":37,"value":14737},"Note that we attach our ",{"type":32,"tag":82,"props":14739,"children":14740},{},[14741],{"type":37,"value":14742},"project folder",{"type":37,"value":14744}," to the ",{"type":32,"tag":117,"props":14746,"children":14747},{},[14748],{"type":37,"value":14749},"/var/www/html/",{"type":37,"value":14751}," folder inside the php container, which is the ",{"type":32,"tag":82,"props":14753,"children":14754},{},[14755],{"type":37,"value":14512},{"type":37,"value":14757}," container.",{"type":32,"tag":448,"props":14759,"children":14760},{},[14761,14763,14768,14770,14775,14777],{"type":37,"value":14762},"Our PHP server will be running on port ",{"type":32,"tag":117,"props":14764,"children":14765},{},[14766],{"type":37,"value":14767},"80",{"type":37,"value":14769},", which means we will see ",{"type":32,"tag":82,"props":14771,"children":14772},{},[14773],{"type":37,"value":14774},"server output",{"type":37,"value":14776}," at ",{"type":32,"tag":117,"props":14778,"children":14779},{},[14780],{"type":37,"value":14781},"http://localhost",{"type":32,"tag":448,"props":14783,"children":14784},{},[14785,14786,14798,14800,14805],{"type":37,"value":3506},{"type":32,"tag":82,"props":14787,"children":14788},{},[14789,14791,14796],{"type":37,"value":14790},"database and phpmyadmin containers share the same ",{"type":32,"tag":117,"props":14792,"children":14793},{},[14794],{"type":37,"value":14795},"env",{"type":37,"value":14797}," file",{"type":37,"value":14799},", which guarantees that they will have ",{"type":32,"tag":82,"props":14801,"children":14802},{},[14803],{"type":37,"value":14804},"the same user configuration, passwords",{"type":37,"value":14806},", etc.",{"type":32,"tag":448,"props":14808,"children":14809},{},[14810,14811,14816,14818,14823,14825],{"type":37,"value":3506},{"type":32,"tag":82,"props":14812,"children":14813},{},[14814],{"type":37,"value":14815},"PHPMyAdmin",{"type":37,"value":14817}," container runs on port ",{"type":32,"tag":117,"props":14819,"children":14820},{},[14821],{"type":37,"value":14822},"8282",{"type":37,"value":14824}," and therefore we will be able to visit it at ",{"type":32,"tag":117,"props":14826,"children":14827},{},[14828],{"type":37,"value":14829},"http://localhost:8282",{"type":32,"tag":46,"props":14831,"children":14832},{},[14833,14835,14840,14842,14847],{"type":37,"value":14834},"At this point we are missing the ",{"type":32,"tag":117,"props":14836,"children":14837},{},[14838],{"type":37,"value":14839},".env",{"type":37,"value":14841}," (dot env) file to complete the docker configuration, we will create it in the ",{"type":32,"tag":117,"props":14843,"children":14844},{},[14845],{"type":37,"value":14846},"docker/dev/.env",{"type":37,"value":14848}," folder with the following contents:",{"type":32,"tag":7664,"props":14850,"children":14852},{"code":14851,"language":14795,"meta":7668},"PHP_ENABLE_XDEBUG=0\r\nMYSQL_HOST=database\r\nMYSQL_PORT=3306\r\nMYSQL_DATABASE=wordpress\r\nMYSQL_USER=wp\r\nMYSQL_PASSWORD=wp\r\nMYSQL_ROOT_PASSWORD=wp\r\nPMA_HOST=database\n",[14853],{"type":32,"tag":7671,"props":14854,"children":14855},{},[14856],{"type":32,"tag":7664,"props":14857,"children":14858},{"__ignoreMap":8},[14859],{"type":37,"value":14851},{"type":32,"tag":46,"props":14861,"children":14862},{},[14863,14865,14870],{"type":37,"value":14864},"If we have done everything correctly and we have ",{"type":32,"tag":82,"props":14866,"children":14867},{},[14868],{"type":37,"value":14869},"enabled the Docker client (Docker Desktop)",{"type":37,"value":14871}," then we can run the whole project using the command inside the project folder:",{"type":32,"tag":7664,"props":14873,"children":14875},{"code":14874,"language":7667,"meta":7668},"docker-compose up -d\n",[14876],{"type":32,"tag":7671,"props":14877,"children":14878},{},[14879],{"type":32,"tag":7664,"props":14880,"children":14881},{"__ignoreMap":8},[14882],{"type":37,"value":14874},{"type":32,"tag":46,"props":14884,"children":14885},{},[14886],{"type":37,"value":14887},"This should get our docker containers start up.",{"type":32,"tag":46,"props":14889,"children":14890},{},[14891],{"type":32,"tag":161,"props":14892,"children":14895},{"alt":14893,"src":14894,"title":14893},"Docker containers","/article/docker-and-wordpress/containers.png",[],{"type":32,"tag":46,"props":14897,"children":14898},{},[14899,14901,14906],{"type":37,"value":14900},"However the PHP server does not have ",{"type":32,"tag":117,"props":14902,"children":14903},{},[14904],{"type":37,"value":14905},"index.php",{"type":37,"value":14907},", we do not have Wordpress downloaded in the project.",{"type":32,"tag":46,"props":14909,"children":14910},{},[14911],{"type":32,"tag":161,"props":14912,"children":14915},{"alt":14913,"src":14914,"title":14913},"Forbidden","/article/docker-and-wordpress/forbidden.png",[],{"type":32,"tag":46,"props":14917,"children":14918},{},[14919,14921,14928],{"type":37,"value":14920},"In this case, just ",{"type":32,"tag":139,"props":14922,"children":14925},{"href":14923,"rel":14924},"https://wordpress.org/download/",[347],[14926],{"type":37,"value":14927},"download Wordpress from the official site",{"type":37,"value":14929}," and copy it to the root folder of our project.",{"type":32,"tag":46,"props":14931,"children":14932},{},[14933,14935,14939],{"type":37,"value":14934},"After visiting ",{"type":32,"tag":117,"props":14936,"children":14937},{},[14938],{"type":37,"value":14781},{"type":37,"value":14940}," we should see the Wordpress installation.",{"type":32,"tag":46,"props":14942,"children":14943},{},[14944],{"type":32,"tag":161,"props":14945,"children":14948},{"alt":14946,"src":14947,"title":14946},"Wordpress intro","/article/docker-and-wordpress/wordpress-intro.png",[],{"type":32,"tag":46,"props":14950,"children":14951},{},[14952],{"type":37,"value":14953},"Where in the next step we should fill in the database data as follows:",{"type":32,"tag":46,"props":14955,"children":14956},{},[14957],{"type":32,"tag":161,"props":14958,"children":14961},{"alt":14959,"src":14960,"title":14959},"Wordpress config","/article/docker-and-wordpress/wordpress-config.png",[],{"type":32,"tag":46,"props":14963,"children":14964},{},[14965],{"type":37,"value":14966},"Then we continue with the installation as we are used to.",{"type":32,"tag":39,"props":14968,"children":14970},{"id":14969},"a-couple-of-commands-that-will-come-in-handy",[14971],{"type":37,"value":14972},"A couple of commands that will come in handy",{"type":32,"tag":7664,"props":14974,"children":14976},{"code":14975,"language":7667,"meta":7668},"# Starting the project\r\ndocker-compose up -d\n",[14977],{"type":32,"tag":7671,"props":14978,"children":14979},{},[14980],{"type":32,"tag":7664,"props":14981,"children":14982},{"__ignoreMap":8},[14983],{"type":37,"value":14975},{"type":32,"tag":7664,"props":14985,"children":14987},{"code":14986,"language":7667,"meta":7668},"# Stop containers and delete all data\r\n# Containers, Images, Volumes, Networks\r\ndocker-compose down\n",[14988],{"type":32,"tag":7671,"props":14989,"children":14990},{},[14991],{"type":32,"tag":7664,"props":14992,"children":14993},{"__ignoreMap":8},[14994],{"type":37,"value":14986},{"type":32,"tag":7664,"props":14996,"children":14998},{"code":14997,"language":7667,"meta":7668},"# Recompile dockerfile\r\ndocker-compose build\n",[14999],{"type":32,"tag":7671,"props":15000,"children":15001},{},[15002],{"type":32,"tag":7664,"props":15003,"children":15004},{"__ignoreMap":8},[15005],{"type":37,"value":14997},{"type":32,"tag":46,"props":15007,"children":15008},{},[15009,15011],{"type":37,"value":15010},"For a full description of the docker-compose command, see ",{"type":32,"tag":139,"props":15012,"children":15015},{"href":15013,"rel":15014},"https://docs.docker.com/engine/reference/commandline/compose/",[347],[15016],{"type":37,"value":15017},"docs.docker.com/engine/reference/commandline/compose/",{"type":32,"tag":39,"props":15019,"children":15021},{"id":15020},"benefits",[15022],{"type":37,"value":13137},{"type":32,"tag":444,"props":15024,"children":15025},{},[15026,15036,15048,15058],{"type":32,"tag":448,"props":15027,"children":15028},{},[15029,15034],{"type":32,"tag":82,"props":15030,"children":15031},{},[15032],{"type":37,"value":15033},"Easy to change",{"type":37,"value":15035}," PHP version",{"type":32,"tag":448,"props":15037,"children":15038},{},[15039,15041,15046],{"type":37,"value":15040},"If you are working in a team, your ",{"type":32,"tag":82,"props":15042,"children":15043},{},[15044],{"type":37,"value":15045},"collaborator will install the development environment with a single command",{"type":37,"value":15047}," (assuming they have docker installed)",{"type":32,"tag":448,"props":15049,"children":15050},{},[15051,15053],{"type":37,"value":15052},"If you should deploy also via docker so ",{"type":32,"tag":82,"props":15054,"children":15055},{},[15056],{"type":37,"value":15057},"you have consistent development with the distribution",{"type":32,"tag":448,"props":15059,"children":15060},{},[15061,15063],{"type":37,"value":15062},"If you are developing more than one project, you will appreciate the ",{"type":32,"tag":82,"props":15064,"children":15065},{},[15066],{"type":37,"value":15067},"isolated environment and the ability to quickly start another project",{"type":32,"tag":39,"props":15069,"children":15071},{"id":15070},"disadvantages",[15072],{"type":37,"value":13156},{"type":32,"tag":444,"props":15074,"children":15075},{},[15076,15088],{"type":32,"tag":448,"props":15077,"children":15078},{},[15079,15081,15086],{"type":37,"value":15080},"Docker is ",{"type":32,"tag":82,"props":15082,"children":15083},{},[15084],{"type":37,"value":15085},"demanding on your HW resources",{"type":37,"value":15087}," machines, especially if you don't have linux",{"type":32,"tag":448,"props":15089,"children":15090},{},[15091,15093,15098],{"type":37,"value":15092},"There can be ",{"type":32,"tag":82,"props":15094,"children":15095},{},[15096],{"type":37,"value":15097},"other problems associated with docker",{"type":37,"value":15099}," (bad ports, bad paths, etc.)",{"type":32,"tag":39,"props":15101,"children":15102},{"id":774},[15103],{"type":37,"value":777},{"type":32,"tag":46,"props":15105,"children":15106},{},[15107,15109,15114,15116,15121,15123,15127,15129,15134],{"type":37,"value":15108},"We have explained the ",{"type":32,"tag":82,"props":15110,"children":15111},{},[15112],{"type":37,"value":15113},"advantages of a development environment using docker containers",{"type":37,"value":15115},". We have shown the ",{"type":32,"tag":82,"props":15117,"children":15118},{},[15119],{"type":37,"value":15120},"basic building blocks",{"type":37,"value":15122}," of docker configuration and how to prepare it for Wordpress. We told how to install ",{"type":32,"tag":82,"props":15124,"children":15125},{},[15126],{"type":37,"value":14265},{"type":37,"value":15128}," and what advantages and disadvantages this solution comes with. I hope you found this article helpful and will try containerizing your ",{"type":32,"tag":82,"props":15130,"children":15131},{},[15132],{"type":37,"value":15133},"Wordpress development environment",{"type":37,"value":733},{"type":32,"tag":46,"props":15136,"children":15137},{},[15138],{"type":32,"tag":161,"props":15139,"children":15142},{"alt":15140,"src":15141,"title":15140},"Docker meme","/article/docker-and-wordpress/docker-everywhere.jpg",[],{"type":32,"tag":39,"props":15144,"children":15145},{"id":798},[15146],{"type":37,"value":6401},{"type":32,"tag":444,"props":15148,"children":15149},{},[15150,15159],{"type":32,"tag":448,"props":15151,"children":15152},{},[15153],{"type":32,"tag":139,"props":15154,"children":15156},{"href":12802,"rel":15155,":rel":347},[347],[15157],{"type":37,"value":15158},"Finished project on github",{"type":32,"tag":448,"props":15160,"children":15161},{},[15162],{"type":32,"tag":139,"props":15163,"children":15166},{"href":15164,"rel":15165,":rel":347},"https://github.com/standahorvath/Wordpress-Docker/tree/wordpress-6-2-2",[347],[15167],{"type":37,"value":15168},"Finished project with wordpress 6.2.2",{"title":8,"searchDepth":862,"depth":862,"links":15170},[15171,15172,15175,15176,15177,15178,15179,15180,15181,15182,15183,15184],{"id":41,"depth":862,"text":44},{"id":14239,"depth":862,"text":14294,"children":15173},[15174],{"id":14316,"depth":871,"text":14319},{"id":14240,"depth":862,"text":14265},{"id":14406,"depth":862,"text":14409},{"id":14493,"depth":862,"text":14496},{"id":14555,"depth":862,"text":14558},{"id":14652,"depth":862,"text":14655},{"id":14969,"depth":862,"text":14972},{"id":15020,"depth":862,"text":13137},{"id":15070,"depth":862,"text":13156},{"id":774,"depth":862,"text":777},{"id":798,"depth":862,"text":6401},"content:knowledge:local-wordpress-development-harness-the-power-of-docker-containers.md","knowledge/local-wordpress-development-harness-the-power-of-docker-containers.md",{"_path":3169,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":15188,"description":15189,"author":11,"date":15190,"readingTime":7350,"level":14,"image":15191,"tags":15192,"slugs":15195,"relatedArticles":15197,"body":15198,"_type":881,"_id":16336,"_source":883,"_file":16337,"_extension":885},"7 most common web developer mistakes, don't you make them too?","Let's take a look at what beginners struggle with most often and what could help them move forward. I've focused on 7 issues that I see as essential in my practice.","2023-07-11","/featured/7-most-common-web-developer-mistakes.jpg",[8580,15193,8581,15194],"css","bugfixing",{"en":3000,"cs":15196},"7-nejcastejsich-chyb-kodera",[3001,12175,1809],{"type":29,"children":15199,"toc":16321},[15200,15205,15209,15228,15234,15302,15328,15331,15337,15367,15375,15410,15413,15419,15458,15466,15517,15520,15526,15579,15589,15608,15616,15622,15671,15694,15697,15703,15715,15726,15741,15752,15771,15787,15798,15831,15850,15861,15864,15870,15902,15910,15915,15926,15944,15963,15974,15986,15997,16036,16047,16058,16077,16088,16091,16097,16132,16140,16145,16156,16167,16210,16229,16235,16247,16258,16270,16274,16286,16290],{"type":32,"tag":33,"props":15201,"children":15203},{"id":15202},"_7-most-common-web-developer-mistakes-dont-you-make-them-too",[15204],{"type":37,"value":15188},{"type":32,"tag":33,"props":15206,"children":15207},{"id":41},[15208],{"type":37,"value":44},{"type":32,"tag":46,"props":15210,"children":15211},{},[15212,15214,15219,15221,15226],{"type":37,"value":15213},"I am very happy to help beginners and advanced web developers. I've been thinking about what beginners struggle with most often and what might help them move forward. I certainly don't aim to cover all the problems in this article, but I have focused on ",{"type":32,"tag":82,"props":15215,"children":15216},{},[15217],{"type":37,"value":15218},"the following 7 issues",{"type":37,"value":15220}," that I see as ",{"type":32,"tag":82,"props":15222,"children":15223},{},[15224],{"type":37,"value":15225},"essential",{"type":37,"value":15227}," in my experience and also occur a lot.",{"type":32,"tag":39,"props":15229,"children":15231},{"id":15230},"inserting-an-entire-library-into-a-project-just-for-one-function",[15232],{"type":37,"value":15233},"Inserting an entire library into a project just for one function",{"type":32,"tag":46,"props":15235,"children":15236},{},[15237,15239,15246,15247,15254,15256,15261,15263,15270,15272,15279,15281,15285,15287,15294,15296,15301],{"type":37,"value":15238},"Many beginners like a variety of libraries, some of the most well-known being ",{"type":32,"tag":139,"props":15240,"children":15243},{"href":15241,"rel":15242,"target":345},"https://getbootstrap.com",[347],[15244],{"type":37,"value":15245},"Bootstrap",{"type":37,"value":2529},{"type":32,"tag":139,"props":15248,"children":15251},{"href":15249,"rel":15250,"target":345},"https://bulma.io",[347],[15252],{"type":37,"value":15253},"Bluma",{"type":37,"value":15255},". These popular libraries are used ",{"type":32,"tag":82,"props":15257,"children":15258},{},[15259],{"type":37,"value":15260},"everywhere",{"type":37,"value":15262},", with no hesitation about whether they fit the project. One such example would be using the entire Bootstrap library just for the sake of ",{"type":32,"tag":139,"props":15264,"children":15267},{"href":15265,"rel":15266,"target":345},"https://getbootstrap.com/docs/4.0/layout/grid/",[347],[15268],{"type":37,"value":15269},"Grid System",{"type":37,"value":15271}," (rows and columns).\r\nAnother example would be using the ",{"type":32,"tag":139,"props":15273,"children":15276},{"href":15274,"rel":15275,"target":345},"https://jquery.com",[347],[15277],{"type":37,"value":15278},"jQuery",{"type":37,"value":15280}," library just for  selecting elements in ",{"type":32,"tag":117,"props":15282,"children":15283},{},[15284],{"type":37,"value":8580},{"type":37,"value":15286},", when this ",{"type":32,"tag":139,"props":15288,"children":15291},{"href":15289,"rel":15290,"target":345},"https://youmightnotneedjquery.com/",[347],[15292],{"type":37,"value":15293},"can be done easily",{"type":37,"value":15295}," in pure ",{"type":32,"tag":117,"props":15297,"children":15298},{},[15299],{"type":37,"value":15300},"JS",{"type":37,"value":733},{"type":32,"tag":157,"props":15303,"children":15304},{},[15305],{"type":32,"tag":46,"props":15306,"children":15307},{},[15308,15313,15315,15320,15322,15327],{"type":32,"tag":82,"props":15309,"children":15310},{},[15311],{"type":37,"value":15312},"Solution:",{"type":37,"value":15314}," It is necessary to think at the beginning of the project what libraries I want to use and whether I will use all of them, or import only parts of them. For example, Bootstrap is already written in ",{"type":32,"tag":117,"props":15316,"children":15317},{},[15318],{"type":37,"value":15319},"Sass",{"type":37,"value":15321}," since version 4 and allows you to import ",{"type":32,"tag":82,"props":15323,"children":15324},{},[15325],{"type":37,"value":15326},"only those components that you use",{"type":37,"value":733},{"type":32,"tag":57,"props":15329,"children":15330},{},[],{"type":32,"tag":39,"props":15332,"children":15334},{"id":15333},"too-small-clickable-area",[15335],{"type":37,"value":15336},"Too small clickable area",{"type":32,"tag":46,"props":15338,"children":15339},{},[15340,15342,15347,15349,15353,15354,15358,15360,15365],{"type":37,"value":15341},"It happens to newcomers that when they create a new interactive element they forget to have ",{"type":32,"tag":82,"props":15343,"children":15344},{},[15345],{"type":37,"value":15346},"enough area for interaction",{"type":37,"value":15348},", whether clicking or tapping with a finger. A prime example is the production of \"a chevron\", which is made of two lines turned opposite each other by a few degrees. This arrow can be made using only ",{"type":32,"tag":117,"props":15350,"children":15351},{},[15352],{"type":37,"value":8580},{"type":37,"value":1982},{"type":32,"tag":117,"props":15355,"children":15356},{},[15357],{"type":37,"value":15193},{"type":37,"value":15359},". When interaction is then added directly to the arrow itself, the ",{"type":32,"tag":82,"props":15361,"children":15362},{},[15363],{"type":37,"value":15364},"click area is very small",{"type":37,"value":15366}," and the visitor may have trouble hitting the element.",{"type":32,"tag":46,"props":15368,"children":15369},{},[15370],{"type":32,"tag":161,"props":15371,"children":15374},{"alt":15372,"src":15373,"title":15372,"width":11419},"Clickable area problem","/article/coder-mistakes/clickable_en.svg",[],{"type":32,"tag":157,"props":15376,"children":15377},{},[15378,15401],{"type":32,"tag":46,"props":15379,"children":15380},{},[15381,15385,15387,15392,15394,15399],{"type":32,"tag":82,"props":15382,"children":15383},{},[15384],{"type":37,"value":15312},{"type":37,"value":15386}," It is necessary to think about how the user will work with the site, in case of small clickable areas it is good to ",{"type":32,"tag":82,"props":15388,"children":15389},{},[15390],{"type":37,"value":15391},"wrap these areas in a wrapper element",{"type":37,"value":15393}," (for example a button), which is set some internal indentation ",{"type":32,"tag":117,"props":15395,"children":15396},{},[15397],{"type":37,"value":15398},"padding",{"type":37,"value":15400}," and set the interaction to this element.",{"type":32,"tag":46,"props":15402,"children":15403},{},[15404],{"type":32,"tag":161,"props":15405,"children":15409},{"alt":15406,"src":15407,"title":15406,"width":15408},"Fixed clickable area problem","/article/coder-mistakes/fix_clickable_en.svg","380",[],{"type":32,"tag":57,"props":15411,"children":15412},{},[],{"type":32,"tag":39,"props":15414,"children":15416},{"id":15415},"inconsistent-hover",[15417],{"type":37,"value":15418},"Inconsistent hover",{"type":32,"tag":46,"props":15420,"children":15421},{},[15422,15424,15429,15431,15436,15438,15443,15445,15450,15452,15457],{"type":37,"value":15423},"This problem happens when web developer ",{"type":32,"tag":82,"props":15425,"children":15426},{},[15427],{"type":37,"value":15428},"doesn't have the hover",{"type":37,"value":15430}," (hover is the state of the element after mouseover) designed by the graphic designer and has to improvise. The developer creates element by element, each of the elements can be created for different lengths of time, and so sometimes a newbie can lose the ",{"type":32,"tag":82,"props":15432,"children":15433},{},[15434],{"type":37,"value":15435},"whole picture",{"type":37,"value":15437}," of the result of the work, or some feeling of the user using the web page. It often happens that developer assigns elements a hover that he likes, but in the overall picture it can be ",{"type":32,"tag":82,"props":15439,"children":15440},{},[15441],{"type":37,"value":15442},"very disjointed and inconsistent",{"type":37,"value":15444},". A prime example might be two buttons, while one of them ",{"type":32,"tag":82,"props":15446,"children":15447},{},[15448],{"type":37,"value":15449},"changes the background color",{"type":37,"value":15451},", the other responds with ",{"type":32,"tag":82,"props":15453,"children":15454},{},[15455],{"type":37,"value":15456},"scale",{"type":37,"value":733},{"type":32,"tag":46,"props":15459,"children":15460},{},[15461],{"type":32,"tag":161,"props":15462,"children":15465},{"alt":15418,"src":15463,"title":15418,"width":15464},"/article/coder-mistakes/non-consistent-hover.gif","430",[],{"type":32,"tag":157,"props":15467,"children":15468},{},[15469],{"type":32,"tag":46,"props":15470,"children":15471},{},[15472,15476,15478,15483,15485,15490,15492,15496,15497,15502,15504,15509,15511,15516],{"type":32,"tag":82,"props":15473,"children":15474},{},[15475],{"type":37,"value":15312},{"type":37,"value":15477}," First of all, it's good if the developer doesn't have to improvise so much and has everything ",{"type":32,"tag":82,"props":15479,"children":15480},{},[15481],{"type":37,"value":15482},"prepared by the graphic designer",{"type":37,"value":15484}," and not only ",{"type":32,"tag":117,"props":15486,"children":15487},{},[15488],{"type":37,"value":15489},":hover",{"type":37,"value":15491}," states but also for example ",{"type":32,"tag":117,"props":15493,"children":15494},{},[15495],{"type":37,"value":11943},{"type":37,"value":2529},{"type":32,"tag":117,"props":15498,"children":15499},{},[15500],{"type":37,"value":15501},":active",{"type":37,"value":15503}," states of buttons/inputs if they are important for the web application. But if the frontend developer has freedom in this direction, it is good to test the result a few times during the work to see how it works together and whether ",{"type":32,"tag":82,"props":15505,"children":15506},{},[15507],{"type":37,"value":15508},"everything reacts consistently",{"type":37,"value":15510},", then prepare a preview of the project and ",{"type":32,"tag":82,"props":15512,"children":15513},{},[15514],{"type":37,"value":15515},"consult interactions with team members",{"type":37,"value":733},{"type":32,"tag":57,"props":15518,"children":15519},{},[],{"type":32,"tag":39,"props":15521,"children":15523},{"id":15522},"missing-image-alt-attribute",[15524],{"type":37,"value":15525},"Missing image alt attribute",{"type":32,"tag":46,"props":15527,"children":15528},{},[15529,15530,15535,15537,15542,15544,15549,15551,15556,15558,15563,15565,15570,15572,15577],{"type":37,"value":3506},{"type":32,"tag":117,"props":15531,"children":15532},{},[15533],{"type":37,"value":15534},"\u003Cimg>",{"type":37,"value":15536}," image tag is one of the first things one encounters if one decides to learn ",{"type":32,"tag":117,"props":15538,"children":15539},{},[15540],{"type":37,"value":15541},"HTML",{"type":37,"value":15543},". The image tag contains attributes such as the path to the image ",{"type":32,"tag":117,"props":15545,"children":15546},{},[15547],{"type":37,"value":15548},"src=\"\"",{"type":37,"value":15550},", a description of the image when hovered over ",{"type":32,"tag":117,"props":15552,"children":15553},{},[15554],{"type":37,"value":15555},"title=\"\"",{"type":37,"value":15557},", an alternate description if the image cannot be displayed ",{"type":32,"tag":117,"props":15559,"children":15560},{},[15561],{"type":37,"value":15562},"alt=\"\"",{"type":37,"value":15564},", width ",{"type":32,"tag":117,"props":15566,"children":15567},{},[15568],{"type":37,"value":15569},"width=\"\"",{"type":37,"value":15571},", height ",{"type":32,"tag":117,"props":15573,"children":15574},{},[15575],{"type":37,"value":15576},"height=\"\"",{"type":37,"value":15578}," and a few others...",{"type":32,"tag":46,"props":15580,"children":15581},{},[15582,15587],{"type":32,"tag":82,"props":15583,"children":15584},{},[15585],{"type":37,"value":15586},"But only one of the image attributes is required by the specification",{"type":37,"value":15588},", would you know which one?",{"type":32,"tag":46,"props":15590,"children":15591},{},[15592,15594,15599,15601,15606],{"type":37,"value":15593},"It is an ",{"type":32,"tag":117,"props":15595,"children":15596},{},[15597],{"type":37,"value":15598},"alt",{"type":37,"value":15600}," attribute, an ",{"type":32,"tag":82,"props":15602,"children":15603},{},[15604],{"type":37,"value":15605},"alternative description",{"type":37,"value":15607},", a piece of text that is displayed as an alternative if the image cannot be displayed in the browser (e.g. wrong path, unsupported format, etc...).",{"type":32,"tag":46,"props":15609,"children":15610},{},[15611],{"type":32,"tag":161,"props":15612,"children":15615},{"alt":15613,"src":15614,"title":15613},"Alt attribute sample","/article/coder-mistakes/wrong-image-en.png",[],{"type":32,"tag":169,"props":15617,"children":15619},{"id":15618},"to-justify-why-the-alt-attribute-is-so-important",[15620],{"type":37,"value":15621},"To justify why the alt attribute is so important:",{"type":32,"tag":444,"props":15623,"children":15624},{},[15625,15636,15648,15659],{"type":32,"tag":448,"props":15626,"children":15627},{},[15628,15630,15634],{"type":37,"value":15629},"It provides ",{"type":32,"tag":82,"props":15631,"children":15632},{},[15633],{"type":37,"value":10350},{"type":37,"value":15635}," for users with visual impairments.",{"type":32,"tag":448,"props":15637,"children":15638},{},[15639,15641,15646],{"type":37,"value":15640},"It helps search engines better ",{"type":32,"tag":82,"props":15642,"children":15643},{},[15644],{"type":37,"value":15645},"understand the content",{"type":37,"value":15647}," of an image.",{"type":32,"tag":448,"props":15649,"children":15650},{},[15651,15653,15658],{"type":37,"value":15652},"It is displayed if the image ",{"type":32,"tag":82,"props":15654,"children":15655},{},[15656],{"type":37,"value":15657},"cannot be loaded",{"type":37,"value":733},{"type":32,"tag":448,"props":15660,"children":15661},{},[15662,15664,15669],{"type":37,"value":15663},"Serves as a ",{"type":32,"tag":82,"props":15665,"children":15666},{},[15667],{"type":37,"value":15668},"replacement for slow loading",{"type":37,"value":15670}," on mobile devices.",{"type":32,"tag":157,"props":15672,"children":15673},{},[15674],{"type":32,"tag":46,"props":15675,"children":15676},{},[15677,15681,15683,15687,15689,15693],{"type":32,"tag":82,"props":15678,"children":15679},{},[15680],{"type":37,"value":15312},{"type":37,"value":15682}," Describe images in ",{"type":32,"tag":117,"props":15684,"children":15685},{},[15686],{"type":37,"value":15598},{"type":37,"value":15688}," attributes. If the image is only decorative, for example to complete the web design, I recommend to use alt anyway and leave it empty ",{"type":32,"tag":117,"props":15690,"children":15691},{},[15692],{"type":37,"value":15562},{"type":37,"value":733},{"type":32,"tag":57,"props":15695,"children":15696},{},[],{"type":32,"tag":39,"props":15698,"children":15700},{"id":15699},"relative-vs-absolute-links",[15701],{"type":37,"value":15702},"Relative vs Absolute links",{"type":32,"tag":46,"props":15704,"children":15705},{},[15706,15708,15713],{"type":37,"value":15707},"Although this may seem trivial from a more experienced developer's perspective, novice developers may have trouble ",{"type":32,"tag":82,"props":15709,"children":15710},{},[15711],{"type":37,"value":15712},"perceiving context",{"type":37,"value":15714}," by referencing the directory structure. First, let's see what an absolute reference looks like and what a relative reference looks like:",{"type":32,"tag":7664,"props":15716,"children":15718},{"code":15717,"language":8580,"meta":7668},"\u003Ca href=\"/index.html\">Absolute link starts with a slash\u003C/a>\r\n\u003Ca href=\"index.html\">A relative reference does not begin with a slash\u003C/a>\n",[15719],{"type":32,"tag":7671,"props":15720,"children":15721},{},[15722],{"type":32,"tag":7664,"props":15723,"children":15724},{"__ignoreMap":8},[15725],{"type":37,"value":15717},{"type":32,"tag":46,"props":15727,"children":15728},{},[15729,15734,15736],{"type":32,"tag":82,"props":15730,"children":15731},{},[15732],{"type":37,"value":15733},"Absolute link",{"type":37,"value":15735}," - links directly from the root of the domain, wherever it is used on the site, it will link to the same place. For example, if I use the link on ",{"type":32,"tag":82,"props":15737,"children":15738},{},[15739],{"type":37,"value":15740},"example.com/contact/",{"type":32,"tag":7664,"props":15742,"children":15744},{"code":15743,"language":8580,"meta":7668},"\u003Ca href=\"/products.html\">Products\u003C/a>\n",[15745],{"type":32,"tag":7671,"props":15746,"children":15747},{},[15748],{"type":32,"tag":7664,"props":15749,"children":15750},{"__ignoreMap":8},[15751],{"type":37,"value":15743},{"type":32,"tag":46,"props":15753,"children":15754},{},[15755,15757,15763,15765,15770],{"type":37,"value":15756},"It will link to ",{"type":32,"tag":139,"props":15758,"children":15761},{"href":15759,"rel":15760},"https://example.com/products.html",[347],[15762],{"type":37,"value":15759},{"type":37,"value":15764},", it simply replaces everything after the domain with my link (",{"type":32,"tag":82,"props":15766,"children":15767},{},[15768],{"type":37,"value":15769},"/products.html",{"type":37,"value":4364},{"type":32,"tag":46,"props":15772,"children":15773},{},[15774,15779,15781,15785],{"type":32,"tag":82,"props":15775,"children":15776},{},[15777],{"type":37,"value":15778},"Relative link",{"type":37,"value":15780}," - refers relatively to the place where I am. So if I modify the previous example slightly and use a link on ",{"type":32,"tag":82,"props":15782,"children":15783},{},[15784],{"type":37,"value":15740},{"type":37,"value":15786}," */",{"type":32,"tag":7664,"props":15788,"children":15790},{"code":15789,"language":8580,"meta":7668},"\u003Ca href=\"products.html\">Products (bad link)\u003C/a>\n",[15791],{"type":32,"tag":7671,"props":15792,"children":15793},{},[15794],{"type":32,"tag":7664,"props":15795,"children":15796},{"__ignoreMap":8},[15797],{"type":37,"value":15789},{"type":32,"tag":46,"props":15799,"children":15800},{},[15801,15802,15808,15810,15815,15817,15822,15824,15829],{"type":37,"value":15756},{"type":32,"tag":139,"props":15803,"children":15806},{"href":15804,"rel":15805},"https://example.com/contact/products.html",[347],[15807],{"type":37,"value":15804},{"type":37,"value":15809}," which I didn't want, the products are located at ",{"type":32,"tag":139,"props":15811,"children":15813},{"href":15759,"rel":15812},[347],[15814],{"type":37,"value":15759},{"type":37,"value":15816},". So relative links work by taking the path (folder) where I'm located - in our case ",{"type":32,"tag":82,"props":15818,"children":15819},{},[15820],{"type":37,"value":15821},"/contact/",{"type":37,"value":15823}," */ and putting our relative path at the end of the path, that is ",{"type":32,"tag":82,"props":15825,"children":15826},{},[15827],{"type":37,"value":15828},"products.html",{"type":37,"value":15830}," and I saw the result above.",{"type":32,"tag":46,"props":15832,"children":15833},{},[15834,15836,15841,15843,15848],{"type":37,"value":15835},"We need to be aware of this behavior and write the links correctly. A bitter discovery often occurs when we ",{"type":32,"tag":82,"props":15837,"children":15838},{},[15839],{"type":37,"value":15840},"write links relatively",{"type":37,"value":15842}," and then put the content in some sub-folder where the relative links ",{"type":32,"tag":82,"props":15844,"children":15845},{},[15846],{"type":37,"value":15847},"stop working",{"type":37,"value":15849}," because the context has changed, all the resources have a folder above.",{"type":32,"tag":157,"props":15851,"children":15852},{},[15853],{"type":32,"tag":46,"props":15854,"children":15855},{},[15856],{"type":32,"tag":82,"props":15857,"children":15858},{},[15859],{"type":37,"value":15860},"The solution may be to write links absolutely.",{"type":32,"tag":57,"props":15862,"children":15863},{},[],{"type":32,"tag":39,"props":15865,"children":15867},{"id":15866},"unnamed-constants-magic-numbers",[15868],{"type":37,"value":15869},"Unnamed constants (Magic numbers)",{"type":32,"tag":46,"props":15871,"children":15872},{},[15873,15875,15880,15882,15887,15889,15894,15896,15901],{"type":37,"value":15874},"The problem of unnamed constants, can be found in almost every programming language, even in CSS.\r\nWe can recognize it by encountering a number that ",{"type":32,"tag":82,"props":15876,"children":15877},{},[15878],{"type":37,"value":15879},"has no obvious reason",{"type":37,"value":15881}," why it is the way it is. They degrade our ",{"type":32,"tag":82,"props":15883,"children":15884},{},[15885],{"type":37,"value":15886},"code readability",{"type":37,"value":15888},", are ",{"type":32,"tag":82,"props":15890,"children":15891},{},[15892],{"type":37,"value":15893},"hard to maintain",{"type":37,"value":15895},", and can lead to future ",{"type":32,"tag":82,"props":15897,"children":15898},{},[15899],{"type":37,"value":15900},"application errors",{"type":37,"value":733},{"type":32,"tag":46,"props":15903,"children":15904},{},[15905],{"type":32,"tag":161,"props":15906,"children":15909},{"alt":15907,"src":15908,"title":15907},"Magic numbers","/article/coder-mistakes/magic-hat.png",[],{"type":32,"tag":46,"props":15911,"children":15912},{},[15913],{"type":37,"value":15914},"An example of such code can be the following condition in javascript:",{"type":32,"tag":7664,"props":15916,"children":15918},{"code":15917,"language":8581,"meta":7668},"function isSmallScreen() {\r\n  if (window.innerWidth > 640) {\r\n  // What does the number 640 mean? Where did it come from?\r\n    return true\r\n  } else {\r\n    return false\r\n  }\r\n}\n",[15919],{"type":32,"tag":7671,"props":15920,"children":15921},{},[15922],{"type":32,"tag":7664,"props":15923,"children":15924},{"__ignoreMap":8},[15925],{"type":37,"value":15917},{"type":32,"tag":46,"props":15927,"children":15928},{},[15929,15931,15936,15938,15943],{"type":37,"value":15930},"In the example we see the number ",{"type":32,"tag":82,"props":15932,"children":15933},{},[15934],{"type":37,"value":15935},"640",{"type":37,"value":15937}," used, which is written hard, it is not based on any constant or configuration. Code written this way is usually a sign of ",{"type":32,"tag":82,"props":15939,"children":15940},{},[15941],{"type":37,"value":15942},"small time saving at the expense of very poor clarity",{"type":37,"value":733},{"type":32,"tag":157,"props":15945,"children":15946},{},[15947],{"type":32,"tag":46,"props":15948,"children":15949},{},[15950,15954,15956,15961],{"type":32,"tag":82,"props":15951,"children":15952},{},[15953],{"type":37,"value":15312},{"type":37,"value":15955}," How should it be done? We should use ",{"type":32,"tag":82,"props":15957,"children":15958},{},[15959],{"type":37,"value":15960},"constants",{"type":37,"value":15962},", ideally defined in some configuration file or otherwise reasonably defined.",{"type":32,"tag":7664,"props":15964,"children":15966},{"code":15965,"language":8581,"meta":7668},"// File config.js\r\nexport {\r\n    Screen: {\r\n\r\n    // …\r\n    sm: 640,\r\n    // …\r\n\r\n}\r\n\r\n// File script.js\r\nfunction isSmallScreen() {\r\n  if (window.innerWidth > Screen.sm) {\r\n    return true\r\n  } else {\r\n    return false\r\n  }\r\n}\n",[15967],{"type":32,"tag":7671,"props":15968,"children":15969},{},[15970],{"type":32,"tag":7664,"props":15971,"children":15972},{"__ignoreMap":8},[15973],{"type":37,"value":15965},{"type":32,"tag":46,"props":15975,"children":15976},{},[15977,15979,15984],{"type":37,"value":15978},"Similarly, we ",{"type":32,"tag":82,"props":15980,"children":15981},{},[15982],{"type":37,"value":15983},"shouldn't",{"type":37,"value":15985}," use magic numbers in CSS**. Let's demonstrate this with the following example:",{"type":32,"tag":7664,"props":15987,"children":15989},{"code":15988,"language":15193,"meta":7668},".cta-box {\r\n    width: 100%;\r\n    background: #424242;\r\n    margin-top: 273px;\r\n    margin-bottom: 266px;\r\n    padding: 12px;\r\n}\n",[15990],{"type":32,"tag":7671,"props":15991,"children":15992},{},[15993],{"type":32,"tag":7664,"props":15994,"children":15995},{"__ignoreMap":8},[15996],{"type":37,"value":15988},{"type":32,"tag":46,"props":15998,"children":15999},{},[16000,16002,16007,16009,16014,16015,16020,16022,16027,16029,16034],{"type":37,"value":16001},"Colors should ideally be defined when we start coding the project and then ",{"type":32,"tag":82,"props":16003,"children":16004},{},[16005],{"type":37,"value":16006},"use colors from the palette",{"type":37,"value":16008},", so the color must go into a variable. The ",{"type":32,"tag":117,"props":16010,"children":16011},{},[16012],{"type":37,"value":16013},"margin-top",{"type":37,"value":1982},{"type":32,"tag":117,"props":16016,"children":16017},{},[16018],{"type":37,"value":16019},"margin-bottom",{"type":37,"value":16021}," are problematic, because they are probably ",{"type":32,"tag":82,"props":16023,"children":16024},{},[16025],{"type":37,"value":16026},"somehow generalized numbers",{"type":37,"value":16028}," and it would be good to at least round them off, ideally to define some ",{"type":32,"tag":82,"props":16030,"children":16031},{},[16032],{"type":37,"value":16033},"spacing variables",{"type":37,"value":16035}," for each block of the project.",{"type":32,"tag":46,"props":16037,"children":16038},{},[16039,16041,16046],{"type":37,"value":16040},"Let's see what the corrected code could look like to make it more ",{"type":32,"tag":82,"props":16042,"children":16043},{},[16044],{"type":37,"value":16045},"readable and systematic",{"type":37,"value":6788},{"type":32,"tag":7664,"props":16048,"children":16050},{"code":16049,"language":15193,"meta":7668},":root {\r\n    /* Colour definition */\r\n    --bg-secondary: #424242;\r\n    /* ... */\r\n    /* Section indentation */\r\n    --section-spacing-lg: 17rem; /* 272 pixels */\r\n    /* Global indentation */\r\n    --gutter: 12px;\r\n}\r\n\r\n/* ... */\r\n\r\n.cta-box {\r\n    width: 100%;\r\n    background:var(--bg-secondary);\r\n    margin-top: var(--section-spacing-lg);\r\n    margin-bottom: var(--section-spacing-lg);\r\n    padding:var(--gutter);\r\n}\n",[16051],{"type":32,"tag":7671,"props":16052,"children":16053},{},[16054],{"type":32,"tag":7664,"props":16055,"children":16056},{"__ignoreMap":8},[16057],{"type":37,"value":16049},{"type":32,"tag":46,"props":16059,"children":16060},{},[16061,16063,16068,16070,16075],{"type":37,"value":16062},"As you can notice, we have defined variables for color, section indentation and global indentation. All of these values are now ",{"type":32,"tag":82,"props":16064,"children":16065},{},[16066],{"type":37,"value":16067},"defined in one place",{"type":37,"value":16069}," and we can ",{"type":32,"tag":82,"props":16071,"children":16072},{},[16073],{"type":37,"value":16074},"easily change",{"type":37,"value":16076}," them.",{"type":32,"tag":46,"props":16078,"children":16079},{},[16080,16082,16087],{"type":37,"value":16081},"The code written this way is ",{"type":32,"tag":82,"props":16083,"children":16084},{},[16085],{"type":37,"value":16086},"descriptive, easy to understand and maintain",{"type":37,"value":733},{"type":32,"tag":57,"props":16089,"children":16090},{},[],{"type":32,"tag":39,"props":16092,"children":16094},{"id":16093},"important",[16095],{"type":37,"value":16096},"!important",{"type":32,"tag":46,"props":16098,"children":16099},{},[16100,16102,16106,16108,16112,16114,16118,16120,16124,16126,16130],{"type":37,"value":16101},"There is a ",{"type":32,"tag":117,"props":16103,"children":16104},{},[16105],{"type":37,"value":16096},{"type":37,"value":16107}," rule in css that gives more priority to the css styles to which it is applied. However, beginners tend to solve some of their problems this way. Overusing the ",{"type":32,"tag":117,"props":16109,"children":16110},{},[16111],{"type":37,"value":16096},{"type":37,"value":16113}," rule then results in very poor orientation, and furthermore the ",{"type":32,"tag":117,"props":16115,"children":16116},{},[16117],{"type":37,"value":16096},{"type":37,"value":16119}," rule can only be overridden by the ",{"type":32,"tag":117,"props":16121,"children":16122},{},[16123],{"type":37,"value":16096},{"type":37,"value":16125}," rule, so when we need to overload/override such rules the ",{"type":32,"tag":117,"props":16127,"children":16128},{},[16129],{"type":37,"value":16096},{"type":37,"value":16131}," rules keep replicating.",{"type":32,"tag":46,"props":16133,"children":16134},{},[16135],{"type":32,"tag":161,"props":16136,"children":16139},{"alt":16137,"src":16138,"title":16137,"width":10757},"CSS !Important meme","/article/coder-mistakes/use-important.jpg",[],{"type":32,"tag":46,"props":16141,"children":16142},{},[16143],{"type":37,"value":16144},"Let's illustrate this with an example:",{"type":32,"tag":7664,"props":16146,"children":16148},{"code":16147,"language":8580,"meta":7668},"\u003Csection>\r\n  \u003Ca href=\"#\" class=\"button\">Button\u003C/a>\r\n\u003C/section>\n",[16149],{"type":32,"tag":7671,"props":16150,"children":16151},{},[16152],{"type":32,"tag":7664,"props":16153,"children":16154},{"__ignoreMap":8},[16155],{"type":37,"value":16147},{"type":32,"tag":7664,"props":16157,"children":16159},{"code":16158,"language":15193,"meta":7668},"/* We have defined the background colour of the button */\r\nsection .button {\r\n    background: red;\r\n}\r\n\r\n/* ... */\r\n\r\n/* Somewhere down the line we want to change the color of the button */\r\n/* But we can't because the rule above is more specific */\r\n/* So we use !important */\r\n.button {\r\n    background: blue !important;\r\n}\n",[16160],{"type":32,"tag":7671,"props":16161,"children":16162},{},[16163],{"type":32,"tag":7664,"props":16164,"children":16165},{"__ignoreMap":8},[16166],{"type":37,"value":16158},{"type":32,"tag":46,"props":16168,"children":16169},{},[16170,16175,16177,16182,16184,16189,16191,16195,16197,16202,16204,16209],{"type":32,"tag":82,"props":16171,"children":16172},{},[16173],{"type":37,"value":16174},"Let's consider the situation",{"type":37,"value":16176}," - the developer first defined the button and then in CSS ",{"type":32,"tag":82,"props":16178,"children":16179},{},[16180],{"type":37,"value":16181},"wanted to change the button in the section",{"type":37,"value":16183},". However, the top entry has ",{"type":32,"tag":82,"props":16185,"children":16186},{},[16187],{"type":37,"value":16188},"higher element specificity",{"type":37,"value":16190}," and thus has higher priority, so the developer decided to solve the problem with ",{"type":32,"tag":117,"props":16192,"children":16193},{},[16194],{"type":37,"value":16096},{"type":37,"value":16196},", to say that the bottom rule has higher priority. This way, however, he ",{"type":32,"tag":82,"props":16198,"children":16199},{},[16200],{"type":37,"value":16201},"set himself up for a future problem",{"type":37,"value":16203},", because now the background color of the button will not change ",{"type":32,"tag":82,"props":16205,"children":16206},{},[16207],{"type":37,"value":16208},"without using another !important",{"type":37,"value":733},{"type":32,"tag":157,"props":16211,"children":16212},{},[16213],{"type":32,"tag":46,"props":16214,"children":16215},{},[16216,16220,16222,16227],{"type":32,"tag":82,"props":16217,"children":16218},{},[16219],{"type":37,"value":14617},{"type":37,"value":16221}," This is a model situation, in reality you will want to change the color of the button in its initial definition and ideally ",{"type":32,"tag":82,"props":16223,"children":16224},{},[16225],{"type":37,"value":16226},"through a configured variable",{"type":37,"value":16228},", the example serves as a representative of the issue.",{"type":32,"tag":169,"props":16230,"children":16232},{"id":16231},"so-how-to-override-css-styles-correctly",[16233],{"type":37,"value":16234},"So how to override CSS styles correctly?",{"type":32,"tag":46,"props":16236,"children":16237},{},[16238,16240,16245],{"type":37,"value":16239},"We need to either ",{"type":32,"tag":82,"props":16241,"children":16242},{},[16243],{"type":37,"value":16244},"reduce the specificity of the rewritten rule or increase the specificity of the newly created rule",{"type":37,"value":16246},", for example like this:",{"type":32,"tag":7664,"props":16248,"children":16250},{"code":16249,"language":15193,"meta":7668},"/* We have defined the background colour of the button */\r\n/* in the same way as in the first example */\r\nsection .button {\r\n    background: red;\r\n}\r\n\r\n/* ... */\r\n\r\n/* But here we increase the specificity */\r\n/* so we don't have to use !important */\r\nsection .button {\r\n    background: blue;\r\n}\n",[16251],{"type":32,"tag":7671,"props":16252,"children":16253},{},[16254],{"type":32,"tag":7664,"props":16255,"children":16256},{"__ignoreMap":8},[16257],{"type":37,"value":16249},{"type":32,"tag":46,"props":16259,"children":16260},{},[16261,16263,16268],{"type":37,"value":16262},"The advice for this issue is ",{"type":32,"tag":82,"props":16264,"children":16265},{},[16266],{"type":37,"value":16267},"avoid the `!important' rule",{"type":37,"value":16269},", but there are rare cases where this is unavoidable.\r\n(For example, in some cases when working with third-party libraries that we can't touch)",{"type":32,"tag":39,"props":16271,"children":16272},{"id":774},[16273],{"type":37,"value":777},{"type":32,"tag":46,"props":16275,"children":16276},{},[16277,16279,16284],{"type":37,"value":16278},"I'm sure there are many other things to watch out for, the ones I mentioned in the article I consider basic and every frontend user should know them. It's great that you've read this far and I'll be very happy if you ",{"type":32,"tag":82,"props":16280,"children":16281},{},[16282],{"type":37,"value":16283},"share this article",{"type":37,"value":16285}," among your frontmen** either in your company or friends, maybe some of the above will be interesting for them too :)",{"type":32,"tag":39,"props":16287,"children":16288},{"id":798},[16289],{"type":37,"value":6401},{"type":32,"tag":444,"props":16291,"children":16292},{},[16293,16303,16313],{"type":32,"tag":448,"props":16294,"children":16295},{},[16296],{"type":32,"tag":139,"props":16297,"children":16300},{"href":16298,"rel":16299,":rel":347},"https://specificity.keegan.st",[347],[16301],{"type":37,"value":16302},"CSS Specificity Calculator",{"type":32,"tag":448,"props":16304,"children":16305},{},[16306],{"type":32,"tag":139,"props":16307,"children":16310},{"href":16308,"rel":16309,":rel":347},"https://en.wikipedia.org/wiki/Magic_number_(programming)",[347],[16311],{"type":37,"value":16312},"Magic Number Problem on Wiki",{"type":32,"tag":448,"props":16314,"children":16315},{},[16316],{"type":32,"tag":139,"props":16317,"children":16318},{"href":3081,":rel":13883},[16319],{"type":37,"value":16320},"Article on collaborating with a graphic designer",{"title":8,"searchDepth":862,"depth":862,"links":16322},[16323,16324,16325,16326,16329,16330,16331,16334,16335],{"id":15230,"depth":862,"text":15233},{"id":15333,"depth":862,"text":15336},{"id":15415,"depth":862,"text":15418},{"id":15522,"depth":862,"text":15525,"children":16327},[16328],{"id":15618,"depth":871,"text":15621},{"id":15699,"depth":862,"text":15702},{"id":15866,"depth":862,"text":15869},{"id":16093,"depth":862,"text":16096,"children":16332},[16333],{"id":16231,"depth":871,"text":16234},{"id":774,"depth":862,"text":777},{"id":798,"depth":862,"text":6401},"content:knowledge:7-most-common-web-developer-mistakes.md","knowledge/7-most-common-web-developer-mistakes.md",{"_path":6742,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":16339,"description":16340,"author":11,"date":16341,"readingTime":16342,"level":14,"image":16343,"tags":16344,"slugs":16349,"relatedArticles":16351,"body":16352,"_type":881,"_id":17226,"_source":883,"_file":17227,"_extension":885},"What are SPA, SSR, PWA and what are the advantages or disadvantages?","A little bit of historical development of websites to today. Explanation of the terms Single Page Application, Server Side Rendering, Progressive web appgres, differences between them and advantages/disadvantages.","2023-07-05",16,"/featured/SPA-SSR-PWA.jpg",[16345,16346,16347,8580,16348],"spa","ssr","pwa","history",{"en":6490,"cs":16350},"co-jsou-spa-ssr-pwa-a-jake-jsou-vyhody-ci-nevyhody",[12175,12176,5289],{"type":29,"children":16353,"toc":17212},[16354,16359,16363,16382,16388,16430,16442,16512,16521,16527,16566,16619,16628,16633,16699,16707,16715,16777,16795,16801,16852,16871,16879,16884,16910,16918,16923,16949,16954,16993,17005,17010,17027,17039,17072,17078,17104,17112,17117,17121,17145,17149],{"type":32,"tag":33,"props":16355,"children":16357},{"id":16356},"what-are-spa-ssr-pwa-and-what-are-the-advantages-or-disadvantages",[16358],{"type":37,"value":16339},{"type":32,"tag":39,"props":16360,"children":16361},{"id":41},[16362],{"type":37,"value":44},{"type":32,"tag":46,"props":16364,"children":16365},{},[16366,16368,16373,16375,16380],{"type":37,"value":16367},"The aim of this article is to ",{"type":32,"tag":82,"props":16369,"children":16370},{},[16371],{"type":37,"value":16372},"outline the terms SPA, SSR, PWA",{"type":37,"value":16374},", their advantages, disadvantages and differences. First, we will look at the history of the web, discuss how the internet came to be and how it has evolved to understand why technology is moving in this direction. We'll take a bite of modern frameworks and use examples to introduce the aforementioned acronyms. This article is intended for anyone interested in modern web technologies, and is intended to introduce the topic and ",{"type":32,"tag":82,"props":16376,"children":16377},{},[16378],{"type":37,"value":16379},"motivate the reader to continue further study",{"type":37,"value":16381}," of this exciting subject.",{"type":32,"tag":39,"props":16383,"children":16385},{"id":16384},"first-websites",[16386],{"type":37,"value":16387},"First websites",{"type":32,"tag":46,"props":16389,"children":16390},{},[16391,16393,16398,16400,16405,16407,16412,16414,16421,16423,16428],{"type":37,"value":16392},"To get to the explanation of the terms in the title of this article, we must first get to the roots of the origins of the ",{"type":32,"tag":82,"props":16394,"children":16395},{},[16396],{"type":37,"value":16397},"Internet itself (WorldWideWeb)",{"type":37,"value":16399},". It began when British scientist ",{"type":32,"tag":82,"props":16401,"children":16402},{},[16403],{"type":37,"value":16404},"Sir Tim Berners-Lee",{"type":37,"value":16406}," solved the problem of how to share information in a structured form between scientists at ",{"type":32,"tag":82,"props":16408,"children":16409},{},[16410],{"type":37,"value":16411},"CERN",{"type":37,"value":16413},". In 1989, he came up with a proposal which he called \"",{"type":32,"tag":139,"props":16415,"children":16418},{"href":16416,"rel":16417,":target":345},"https://cds.cern.ch/record/369245/files/dd-89-001.pdf",[347],[16419],{"type":37,"value":16420},"Information Management: A Proposal",{"type":37,"value":16422},"\"\r\nThis idea did not meet with much success, Tim's boss (Mike Sendall) called the proposal ",{"type":32,"tag":82,"props":16424,"children":16425},{},[16426],{"type":37,"value":16427},"vague",{"type":37,"value":16429}," and the project was never an official CERN project.",{"type":32,"tag":46,"props":16431,"children":16432},{},[16433,16435,16440],{"type":37,"value":16434},"In 1990 Tim wrote the basic ",{"type":32,"tag":82,"props":16436,"children":16437},{},[16438],{"type":37,"value":16439},"three building blocks of the web",{"type":37,"value":16441},", which still survive in some form today:",{"type":32,"tag":444,"props":16443,"children":16444},{},[16445,16461,16483],{"type":32,"tag":448,"props":16446,"children":16447},{},[16448,16452,16454,16459],{"type":32,"tag":117,"props":16449,"children":16450},{},[16451],{"type":37,"value":15541},{"type":37,"value":16453}," - ",{"type":32,"tag":82,"props":16455,"children":16456},{},[16457],{"type":37,"value":16458},"Hypertext Markup Language",{"type":37,"value":16460},", the markup language of web pages.",{"type":32,"tag":448,"props":16462,"children":16463},{},[16464,16469,16470,16475,16477,16481],{"type":32,"tag":117,"props":16465,"children":16466},{},[16467],{"type":37,"value":16468},"URI",{"type":37,"value":16453},{"type":32,"tag":82,"props":16471,"children":16472},{},[16473],{"type":37,"value":16474},"Uniform Resource Identifier",{"type":37,"value":16476},", now known as ",{"type":32,"tag":117,"props":16478,"children":16479},{},[16480],{"type":37,"value":4582},{"type":37,"value":16482},", the link you see in your browser's address bar",{"type":32,"tag":448,"props":16484,"children":16485},{},[16486,16491,16492,16497,16499,16503,16505],{"type":32,"tag":117,"props":16487,"children":16488},{},[16489],{"type":37,"value":16490},"HTTP",{"type":37,"value":16453},{"type":32,"tag":82,"props":16493,"children":16494},{},[16495],{"type":37,"value":16496},"Hypertext Transfer Protocol",{"type":37,"value":16498},", the basic protocol for communicating with a server and transferring data\r\nIn 1993, Tim gave this technology completely free to use and since then the popularity of the web has grown enormously. The first ever ",{"type":32,"tag":117,"props":16500,"children":16501},{},[16502],{"type":37,"value":15541},{"type":37,"value":16504}," page has even survived and can be found here: ",{"type":32,"tag":139,"props":16506,"children":16509},{"href":16507,"rel":16508,":target":345},"http://info.cern.ch/hypertext/WWW/TheProject.html",[347],[16510],{"type":37,"value":16511},"TheProject.html",{"type":32,"tag":46,"props":16513,"children":16514},{},[16515],{"type":32,"tag":161,"props":16516,"children":16520},{"alt":16517,"src":16518,"title":16517,"width":16519},"URI format","/article/SPA-SSR-PWA/URI_en.svg","760",[],{"type":32,"tag":39,"props":16522,"children":16524},{"id":16523},"dynamic-websites",[16525],{"type":37,"value":16526},"Dynamic websites",{"type":32,"tag":46,"props":16528,"children":16529},{},[16530,16532,16537,16539,16544,16546,16551,16553,16558,16560,16565],{"type":37,"value":16531},"The first websites were called ",{"type":32,"tag":82,"props":16533,"children":16534},{},[16535],{"type":37,"value":16536},"static",{"type":37,"value":16538}," - their content did not change as the author put it on the web, so they ",{"type":32,"tag":82,"props":16540,"children":16541},{},[16542],{"type":37,"value":16543},"remained in that form",{"type":37,"value":16545},". Which was great for sharing information, but very soon it started to lack any automation, independent of humans. For example, showing data from the system without having to manually update it on the web. So we get to ",{"type":32,"tag":82,"props":16547,"children":16548},{},[16549],{"type":37,"value":16550},"dynamic sites",{"type":37,"value":16552}," - these are sites where content is more or less generated on the server using some rule and data. For example, if you want to ",{"type":32,"tag":82,"props":16554,"children":16555},{},[16556],{"type":37,"value":16557},"display the results of a football match",{"type":37,"value":16559}," or your latest blog post on the site, you'll probably need to ",{"type":32,"tag":82,"props":16561,"children":16562},{},[16563],{"type":37,"value":16564},"get the data and then dynamically render it into the site",{"type":37,"value":733},{"type":32,"tag":46,"props":16567,"children":16568},{},[16569,16571,16576,16578,16583,16585,16590,16592,16597,16599,16604,16606,16611,16613,16618],{"type":37,"value":16570},"Dynamic content started to emerge back in 1993 with ",{"type":32,"tag":82,"props":16572,"children":16573},{},[16574],{"type":37,"value":16575},"CGI (Common Gateway Interface)",{"type":37,"value":16577},", but by 1994, for example, ",{"type":32,"tag":117,"props":16579,"children":16580},{},[16581],{"type":37,"value":16582},"PHP",{"type":37,"value":16584}," version 2 and ",{"type":32,"tag":117,"props":16586,"children":16587},{},[16588],{"type":37,"value":16589},"Ruby",{"type":37,"value":16591}," had already emerged. This was followed in the next years by ",{"type":32,"tag":117,"props":16593,"children":16594},{},[16595],{"type":37,"value":16596},"ASP",{"type":37,"value":16598}," (1996), ",{"type":32,"tag":117,"props":16600,"children":16601},{},[16602],{"type":37,"value":16603},"Python 1.4",{"type":37,"value":16605}," (1996) and also for example ",{"type":32,"tag":117,"props":16607,"children":16608},{},[16609],{"type":37,"value":16610},"Java Servrlet",{"type":37,"value":16612}," (1997). So content began to be created on servers and sent to browsers where it was rendered. The html structure was very simple and the web carried ",{"type":32,"tag":82,"props":16614,"children":16615},{},[16616],{"type":37,"value":16617},"primary informational value",{"type":37,"value":733},{"type":32,"tag":46,"props":16620,"children":16621},{},[16622],{"type":32,"tag":161,"props":16623,"children":16627},{"alt":16624,"src":16625,"title":16624,"width":16626},"Dynamic Web","/article/SPA-SSR-PWA/dynamic_web_en.svg","500",[],{"type":32,"tag":39,"props":16629,"children":16630},{"id":8581},[16631],{"type":37,"value":16632},"Javascript",{"type":32,"tag":46,"props":16634,"children":16635},{},[16636,16638,16643,16645,16649,16651,16656,16658,16663,16665,16670,16672,16677,16679,16684,16686,16691,16693,16698],{"type":37,"value":16637},"Finally, we come to JavaScript, the ",{"type":32,"tag":82,"props":16639,"children":16640},{},[16641],{"type":37,"value":16642},"programming language for the frontend",{"type":37,"value":16644}," (nowadays also the backend). ",{"type":32,"tag":117,"props":16646,"children":16647},{},[16648],{"type":37,"value":16632},{"type":37,"value":16650}," was invented by a man named ",{"type":32,"tag":82,"props":16652,"children":16653},{},[16654],{"type":37,"value":16655},"Brendan Eich",{"type":37,"value":16657}," in 1995. It was developed at ",{"type":32,"tag":82,"props":16659,"children":16660},{},[16661],{"type":37,"value":16662},"Netscape",{"type":37,"value":16664}," for the company's then flagship browser, ",{"type":32,"tag":82,"props":16666,"children":16667},{},[16668],{"type":37,"value":16669},"Netscape Navigator",{"type":37,"value":16671},". The language was originally to be called ",{"type":32,"tag":117,"props":16673,"children":16674},{},[16675],{"type":37,"value":16676},"LiveScript",{"type":37,"value":16678},", but was renamed ",{"type":32,"tag":117,"props":16680,"children":16681},{},[16682],{"type":37,"value":16683},"JavaScript",{"type":37,"value":16685}," so that it could be promoted alongside ",{"type":32,"tag":117,"props":16687,"children":16688},{},[16689],{"type":37,"value":16690},"Java",{"type":37,"value":16692},", a product of their partner ",{"type":32,"tag":82,"props":16694,"children":16695},{},[16696],{"type":37,"value":16697},"Sun Micro Systems",{"type":37,"value":733},{"type":32,"tag":46,"props":16700,"children":16701},{},[16702],{"type":32,"tag":161,"props":16703,"children":16706},{"alt":16704,"src":16705,"title":16704},"Java is not Javascript","/article/SPA-SSR-PWA/java-is-not-javascript.png",[],{"type":32,"tag":46,"props":16708,"children":16709},{},[16710],{"type":32,"tag":82,"props":16711,"children":16712},{},[16713],{"type":37,"value":16714},"JavaScript has almost nothing to do with Java.",{"type":32,"tag":46,"props":16716,"children":16717},{},[16718,16720,16725,16727,16732,16733,16738,16739,16744,16746,16751,16752,16757,16759,16763,16765,16769,16771,16776],{"type":37,"value":16719},"In 1997, the ",{"type":32,"tag":117,"props":16721,"children":16722},{},[16723],{"type":37,"value":16724},"ECMAScript 1",{"type":37,"value":16726}," standard was released, and this increased the popularity of developers using this language. Technology companies come up with ",{"type":32,"tag":82,"props":16728,"children":16729},{},[16730],{"type":37,"value":16731},"their own implementation of JavaScript",{"type":37,"value":16453},{"type":32,"tag":117,"props":16734,"children":16735},{},[16736],{"type":37,"value":16737},"JScript",{"type":37,"value":1849},{"type":32,"tag":82,"props":16740,"children":16741},{},[16742],{"type":37,"value":16743},"Microsoft",{"type":37,"value":16745},"), ",{"type":32,"tag":117,"props":16747,"children":16748},{},[16749],{"type":37,"value":16750},"ActionScript",{"type":37,"value":1849},{"type":32,"tag":82,"props":16753,"children":16754},{},[16755],{"type":37,"value":16756},"Adobe",{"type":37,"value":16758},"). There is a flurry of development, with each of the browsers of the time (NetScape, InternetExplorer, Opera, Mozilla) interpreting ",{"type":32,"tag":117,"props":16760,"children":16761},{},[16762],{"type":37,"value":16632},{"type":37,"value":16764}," a little differently. To the rescue comes ",{"type":32,"tag":117,"props":16766,"children":16767},{},[16768],{"type":37,"value":15278},{"type":37,"value":16770}," in 2005, which is a library that ",{"type":32,"tag":82,"props":16772,"children":16773},{},[16774],{"type":37,"value":16775},"creates an intermediate layer and unifies browser compatibilities",{"type":37,"value":733},{"type":32,"tag":46,"props":16778,"children":16779},{},[16780,16782,16787,16789,16793],{"type":37,"value":16781},"We find ourselves in a state where the ",{"type":32,"tag":82,"props":16783,"children":16784},{},[16785],{"type":37,"value":16786},"backend generates dynamic HTML",{"type":37,"value":16788}," and we enhance it with ",{"type":32,"tag":117,"props":16790,"children":16791},{},[16792],{"type":37,"value":16632},{"type":37,"value":16794}," - Animate, Interact with the user.",{"type":32,"tag":39,"props":16796,"children":16798},{"id":16797},"js-frameworks",[16799],{"type":37,"value":16800},"JS frameworks",{"type":32,"tag":46,"props":16802,"children":16803},{},[16804,16806,16811,16813,16818,16820,16824,16826,16831,16832,16837,16838,16843,16845,16850],{"type":37,"value":16805},"As the javascript language and needs grow, it becomes confusing to use it in its basic form. This ",{"type":32,"tag":82,"props":16807,"children":16808},{},[16809],{"type":37,"value":16810},"creates a lot of libraries with predefined functions",{"type":37,"value":16812}," so we don't have to invent them, and more importantly, ",{"type":32,"tag":82,"props":16814,"children":16815},{},[16816],{"type":37,"value":16817},"frameworks",{"type":37,"value":16819}," are created to build on top of ",{"type":32,"tag":117,"props":16821,"children":16822},{},[16823],{"type":37,"value":16632},{"type":37,"value":16825}," itself.\r\nI'm thinking of the famous trio of ",{"type":32,"tag":117,"props":16827,"children":16828},{},[16829],{"type":37,"value":16830},"React",{"type":37,"value":2497},{"type":32,"tag":117,"props":16833,"children":16834},{},[16835],{"type":37,"value":16836},"Angular",{"type":37,"value":2497},{"type":32,"tag":117,"props":16839,"children":16840},{},[16841],{"type":37,"value":16842},"Vue.js",{"type":37,"value":16844},", which ",{"type":32,"tag":82,"props":16846,"children":16847},{},[16848],{"type":37,"value":16849},"twisted the world of frontend",{"type":37,"value":16851}," development and brought a new way of looking at web application development into play.",{"type":32,"tag":46,"props":16853,"children":16854},{},[16855,16857,16862,16864,16869],{"type":37,"value":16856},"They ",{"type":32,"tag":82,"props":16858,"children":16859},{},[16860],{"type":37,"value":16861},"create an abstract layer",{"type":37,"value":16863}," that allows us to program where to display what data or entire components, but no longer deal with the complex logic behind when and how to update them. They allow us to ",{"type":32,"tag":82,"props":16865,"children":16866},{},[16867],{"type":37,"value":16868},"encapsulate pieces of code into components",{"type":37,"value":16870},", classes and objects. It brings code organization, best-practices and much more...",{"type":32,"tag":46,"props":16872,"children":16873},{},[16874],{"type":32,"tag":161,"props":16875,"children":16878},{"alt":16876,"src":16877,"title":16876},"Výhody SPA frameworků","/article/SPA-SSR-PWA/SPA_features_en.svg",[],{"type":32,"tag":39,"props":16880,"children":16881},{"id":16345},[16882],{"type":37,"value":16883},"SPA",{"type":32,"tag":46,"props":16885,"children":16886},{},[16887,16889,16894,16896,16901,16903,16908],{"type":37,"value":16888},"Single page application is a term that refers to a web application that is loaded into a browser and ",{"type":32,"tag":82,"props":16890,"children":16891},{},[16892],{"type":37,"value":16893},"only redraws the parts of the HTML that dynamically change",{"type":37,"value":16895},". The server provides the javascript code to the browser, but the page is ",{"type":32,"tag":82,"props":16897,"children":16898},{},[16899],{"type":37,"value":16900},"generated in the browser",{"type":37,"value":16902},". For example - if you click on a link in the menu on this page you are currently on, the content will be redrawn, but the header and footer will remain unchanged, you won't even see a page reload, the dynamic redraw will take place ",{"type":32,"tag":82,"props":16904,"children":16905},{},[16906],{"type":37,"value":16907},"instantly and without waiting for a server response",{"type":37,"value":16909}," - because there is no need for one.",{"type":32,"tag":46,"props":16911,"children":16912},{},[16913],{"type":32,"tag":161,"props":16914,"children":16917},{"alt":16915,"src":16916,"title":16915},"SPA reload","/article/SPA-SSR-PWA/SPA_reload_en.svg",[],{"type":32,"tag":46,"props":16919,"children":16920},{},[16921],{"type":37,"value":16922},"So SPA has only one page, the web application javascript page. This has the following implications:",{"type":32,"tag":444,"props":16924,"children":16925},{},[16926,16931],{"type":32,"tag":448,"props":16927,"children":16928},{},[16929],{"type":37,"value":16930},"SPA will be faster than \"client-server\" web crawling with a request for each page handled",{"type":32,"tag":448,"props":16932,"children":16933},{},[16934,16936,16940,16942,16947],{"type":37,"value":16935},"SPA itself suffers from bad ",{"type":32,"tag":82,"props":16937,"children":16938},{},[16939],{"type":37,"value":423},{"type":37,"value":16941},", due to the fact that HTML is rendered only by running JS and ",{"type":32,"tag":82,"props":16943,"children":16944},{},[16945],{"type":37,"value":16946},"web crawlers usually can't do that",{"type":37,"value":16948}," (even google doesn't do well with indexing SPA)",{"type":32,"tag":39,"props":16950,"children":16951},{"id":16346},[16952],{"type":37,"value":16953},"SSR",{"type":32,"tag":46,"props":16955,"children":16956},{},[16957,16959,16964,16966,16971,16973,16977,16979,16984,16986,16991],{"type":37,"value":16958},"In response to poor search engine optimization (SEO) comes a technology called ",{"type":32,"tag":82,"props":16960,"children":16961},{},[16962],{"type":37,"value":16963},"Server Site Rendering (SSR)",{"type":37,"value":16965},". This solves the SEO problem by ",{"type":32,"tag":82,"props":16967,"children":16968},{},[16969],{"type":37,"value":16970},"rendering the HTML on the server",{"type":37,"value":16972},", sending the HTML to the browser, which runs ",{"type":32,"tag":117,"props":16974,"children":16975},{},[16976],{"type":37,"value":8581},{"type":37,"value":16978},", which in turn hydrates and builds a virtual DOM page. It's defacto similar to SPA, except that we ",{"type":32,"tag":82,"props":16980,"children":16981},{},[16982],{"type":37,"value":16983},"have full-fledged HTML generated on the server",{"type":37,"value":16985}," with all the text, html elements and so on... This enhancement is useful where we want to have a web application ",{"type":32,"tag":82,"props":16987,"children":16988},{},[16989],{"type":37,"value":16990},"ready to be indexed by web search engines",{"type":37,"value":16992}," like Google bot.",{"type":32,"tag":46,"props":16994,"children":16995},{},[16996,16998,17003],{"type":37,"value":16997},"Also note here that compared to pure SPA, where the page was generated by the browser, ",{"type":32,"tag":82,"props":16999,"children":17000},{},[17001],{"type":37,"value":17002},"with SSR we put the burden of generating the page back on the server",{"type":37,"value":17004},", as it has been since the beginning of web development.",{"type":32,"tag":39,"props":17006,"children":17007},{"id":16347},[17008],{"type":37,"value":17009},"PWA",{"type":32,"tag":46,"props":17011,"children":17012},{},[17013,17018,17020,17025],{"type":32,"tag":82,"props":17014,"children":17015},{},[17016],{"type":37,"value":17017},"Progressive Web Apps",{"type":37,"value":17019}," aim to be more than a web app. By being able to work in a web application (SPA) and hardly needing a server (or not needing one at all), the idea of ",{"type":32,"tag":82,"props":17021,"children":17022},{},[17023],{"type":37,"value":17024},"being able to run the application outside of a web browser",{"type":37,"value":17026}," with the ability to go offline, just like a native application, is what PWAs are all about, getting more like native applications.",{"type":32,"tag":46,"props":17028,"children":17029},{},[17030,17032,17037],{"type":37,"value":17031},"This type of applications allow to use so called ",{"type":32,"tag":117,"props":17033,"children":17034},{},[17035],{"type":37,"value":17036},"Service Workers",{"type":37,"value":17038},", which are used just to get closer to the native application, thanks to this we get for example the following possibilities:",{"type":32,"tag":444,"props":17040,"children":17041},{},[17042,17047,17052,17057,17062,17067],{"type":32,"tag":448,"props":17043,"children":17044},{},[17045],{"type":37,"value":17046},"Work with the application offline",{"type":32,"tag":448,"props":17048,"children":17049},{},[17050],{"type":37,"value":17051},"Update the application in the background",{"type":32,"tag":448,"props":17053,"children":17054},{},[17055],{"type":37,"value":17056},"Sending notifications and push notifications",{"type":32,"tag":448,"props":17058,"children":17059},{},[17060],{"type":37,"value":17061},"The ability to access hardware features of the device (e.g. camera, geolocation)",{"type":32,"tag":448,"props":17063,"children":17064},{},[17065],{"type":37,"value":17066},"Loading and caching data",{"type":32,"tag":448,"props":17068,"children":17069},{},[17070],{"type":37,"value":17071},"Create a security layer",{"type":32,"tag":169,"props":17073,"children":17075},{"id":17074},"what-does-it-look-like-in-practice",[17076],{"type":37,"value":17077},"What does it look like in practice?",{"type":32,"tag":46,"props":17079,"children":17080},{},[17081,17083,17088,17090,17095,17097,17102],{"type":37,"value":17082},"I'm sure you've seen this on some web applications, in the browser you can ",{"type":32,"tag":82,"props":17084,"children":17085},{},[17086],{"type":37,"value":17087},"click on the icon next to the address bar",{"type":37,"value":17089}," which creates a new window from the web page that is slightly different from the search engine window and creates a ",{"type":32,"tag":82,"props":17091,"children":17092},{},[17093],{"type":37,"value":17094},"desktop icon",{"type":37,"value":17096}," that you can use to launch the PWA.\r\nYou can try it right away, this page enables PWA and ",{"type":32,"tag":82,"props":17098,"children":17099},{},[17100],{"type":37,"value":17101},"just install the app",{"type":37,"value":17103},", see image below (Chrome browser).",{"type":32,"tag":46,"props":17105,"children":17106},{},[17107],{"type":32,"tag":161,"props":17108,"children":17111},{"alt":17109,"src":17110,"title":17109},"PWA in practice","/article/SPA-SSR-PWA/PWA_en.png",[],{"type":32,"tag":46,"props":17113,"children":17114},{},[17115],{"type":37,"value":17116},"Other examples you may be familiar with are Figma, Facebook or Freelo.",{"type":32,"tag":39,"props":17118,"children":17119},{"id":774},[17120],{"type":37,"value":777},{"type":32,"tag":46,"props":17122,"children":17123},{},[17124,17126,17131,17133,17138,17140],{"type":37,"value":17125},"If you've read this far in the article you should have a basic ",{"type":32,"tag":82,"props":17127,"children":17128},{},[17129],{"type":37,"value":17130},"understanding of what SPA, SSR, PWA are",{"type":37,"value":17132}," and why these technologies have come into existence. Below the article I will add some resources that I think are ",{"type":32,"tag":82,"props":17134,"children":17135},{},[17136],{"type":37,"value":17137},"worth studying",{"type":37,"value":17139}," if you are interested in this topic. If you come across any questions or inconsistencies while reading, ",{"type":32,"tag":82,"props":17141,"children":17142},{},[17143],{"type":37,"value":17144},"feel free to email me :)",{"type":32,"tag":39,"props":17146,"children":17147},{"id":798},[17148],{"type":37,"value":6401},{"type":32,"tag":444,"props":17150,"children":17151},{},[17152,17162,17172,17182,17192,17202],{"type":32,"tag":448,"props":17153,"children":17154},{},[17155],{"type":32,"tag":139,"props":17156,"children":17159},{"href":17157,"rel":17158,":rel":347},"https://home.cern/science/computing/birth-web/short-history-web",[347],[17160],{"type":37,"value":17161},"Web History (CERN)",{"type":32,"tag":448,"props":17163,"children":17164},{},[17165],{"type":32,"tag":139,"props":17166,"children":17169},{"href":17167,"rel":17168,":rel":347},"https://en.wikipedia.org/wiki/Single-page_application",[347],[17170],{"type":37,"value":17171},"SPA Wikipedia",{"type":32,"tag":448,"props":17173,"children":17174},{},[17175],{"type":32,"tag":139,"props":17176,"children":17179},{"href":17177,"rel":17178,":rel":347},"https://web.dev/rendering-on-the-web/",[347],[17180],{"type":37,"value":17181},"About SSR on web.dev",{"type":32,"tag":448,"props":17183,"children":17184},{},[17185],{"type":32,"tag":139,"props":17186,"children":17189},{"href":17187,"rel":17188,":rel":347},"https://vuejs.org/guide/scaling-up/ssr.html#what-is-ssr",[347],[17190],{"type":37,"value":17191},"SSR in Vue.js",{"type":32,"tag":448,"props":17193,"children":17194},{},[17195],{"type":32,"tag":139,"props":17196,"children":17199},{"href":17197,"rel":17198,":rel":347},"https://web.dev/progressive-web-apps/",[347],[17200],{"type":37,"value":17201},"About PWA on web.dev",{"type":32,"tag":448,"props":17203,"children":17204},{},[17205],{"type":32,"tag":139,"props":17206,"children":17209},{"href":17207,"rel":17208,":rel":347},"https://www.youtube.com/watch?v=sFsRylCQblw",[347],[17210],{"type":37,"value":17211},"Short video about PWA on Fireship",{"title":8,"searchDepth":862,"depth":862,"links":17213},[17214,17215,17216,17217,17218,17219,17220,17221,17224,17225],{"id":41,"depth":862,"text":44},{"id":16384,"depth":862,"text":16387},{"id":16523,"depth":862,"text":16526},{"id":8581,"depth":862,"text":16632},{"id":16797,"depth":862,"text":16800},{"id":16345,"depth":862,"text":16883},{"id":16346,"depth":862,"text":16953},{"id":16347,"depth":862,"text":17009,"children":17222},[17223],{"id":17074,"depth":871,"text":17077},{"id":774,"depth":862,"text":777},{"id":798,"depth":862,"text":6401},"content:knowledge:what-are-SPA-SSR-PWA-and-what-are-the-benefits-and-disadvantages.md","knowledge/what-are-SPA-SSR-PWA-and-what-are-the-benefits-and-disadvantages.md",{"_path":3081,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":17229,"description":17230,"author":11,"date":17231,"readingTime":4900,"level":14,"image":17232,"tags":17233,"slugs":17237,"relatedArticles":17239,"body":17240,"_type":881,"_id":17922,"_source":883,"_file":17923,"_extension":885},"Coder VS Graphic Designer - How to properly prepare design and deliver a good quality result","A few tips on how to prepare documents for a coder to deliver the best possible result. I explain the perspectives of both sides and try to outline best-practices for preparing the documents.","2023-06-26","/featured/graphics-vs-coder.jpg",[17234,17235,17236,8580,15193],"figma","adobexd","bestpractice",{"en":3001,"cs":17238},"koder-vs-grafik-jak-spravne-pripravit-podklady-a-dorucit-kvalitni-vysledek",[3000,12175,9756],{"type":29,"children":17241,"toc":17906},[17242,17248,17252,17271,17351,17357,17368,17386,17412,17420,17425,17431,17462,17471,17483,17489,17555,17561,17580,17599,17604,17615,17623,17629,17641,17647,17659,17667,17673,17678,17684,17696,17702,17742,17748,17855,17859,17871,17876,17879,17883],{"type":32,"tag":33,"props":17243,"children":17245},{"id":17244},"coder-vs-graphic-designer-how-to-properly-prepare-documents-and-deliver-a-quality-result",[17246],{"type":37,"value":17247},"Coder VS Graphic Designer - How to properly prepare documents and deliver a quality result",{"type":32,"tag":39,"props":17249,"children":17250},{"id":41},[17251],{"type":37,"value":44},{"type":32,"tag":46,"props":17253,"children":17254},{},[17255,17257,17262,17264,17269],{"type":37,"value":17256},"This article is about two worlds - the world of ",{"type":32,"tag":82,"props":17258,"children":17259},{},[17260],{"type":37,"value":17261},"web design",{"type":37,"value":17263}," and the world of ",{"type":32,"tag":82,"props":17265,"children":17266},{},[17267],{"type":37,"value":17268},"coding",{"type":37,"value":17270},". It is meant to describe the issues that happen in practice. At the same time, it will also show some best-practices that I think are good to know, using concrete examples.",{"type":32,"tag":153,"props":17272,"children":17273},{},[17274,17309],{"type":32,"tag":157,"props":17275,"children":17276},{},[17277,17283],{"type":32,"tag":39,"props":17278,"children":17280},{"id":17279},"graphic-designers-view",[17281],{"type":37,"value":17282},"Graphic designer's view",{"type":32,"tag":46,"props":17284,"children":17285},{},[17286,17288,17293,17295,17300,17302,17307],{"type":37,"value":17287},"The incentive of a graphic designer is to ",{"type":32,"tag":82,"props":17289,"children":17290},{},[17291],{"type":37,"value":17292},"deliver a good graphical result",{"type":37,"value":17294},". A design that will have a wow effect, that will be modern and maybe even novel. Something that puts a piece of themselves into it, dazzles the client and fits the brief at the same time. A good graphic designer follows trends, tries to combine new elements and push themselves in creativity.\nHowever, in my experience, a graphic designer often doesn't want to get bogged down in technicalities. He doesn't start learning the differences between ",{"type":32,"tag":117,"props":17296,"children":17297},{},[17298],{"type":37,"value":17299},"background-size:cover;",{"type":37,"value":17301}," vs ",{"type":32,"tag":117,"props":17303,"children":17304},{},[17305],{"type":37,"value":17306},"background-size:contain;",{"type":37,"value":17308}," or studying the grid of, for example, Bootstrap.",{"type":32,"tag":157,"props":17310,"children":17311},{},[17312,17318],{"type":32,"tag":39,"props":17313,"children":17315},{"id":17314},"coders-view",[17316],{"type":37,"value":17317},"Coder's view",{"type":32,"tag":46,"props":17319,"children":17320},{},[17321,17323,17328,17330,17335,17337,17342,17344,17349],{"type":37,"value":17322},"While from the coder's side, it's often about converting ",{"type":32,"tag":82,"props":17324,"children":17325},{},[17326],{"type":37,"value":17327},"design into a consistent form",{"type":37,"value":17329}," that has order and rules if possible. Defining a reasonable number of colors and fonts. Splitting the page into reusable components or spacing in nice numbers - who wants to have ",{"type":32,"tag":117,"props":17331,"children":17332},{},[17333],{"type":37,"value":17334},"padding-left: 17px;",{"type":37,"value":17336}," ? or even worse ",{"type":32,"tag":117,"props":17338,"children":17339},{},[17340],{"type":37,"value":17341},"padding-left: 1.0625rem",{"type":37,"value":17343},".\nOn the other hand, coders often lack ",{"type":32,"tag":82,"props":17345,"children":17346},{},[17347],{"type":37,"value":17348},"understanding of the graphic designer's intent",{"type":37,"value":17350},". Yes the ratio of logo size to font size in menus is important to keep, as is symmetrical indentation of products in category listings and so on...",{"type":32,"tag":39,"props":17352,"children":17354},{"id":17353},"what-about-it",[17355],{"type":37,"value":17356},"What about it?",{"type":32,"tag":46,"props":17358,"children":17359},{},[17360,17362,17367],{"type":37,"value":17361},"Exactly the same as in any human-to-human relationship, i.e. ",{"type":32,"tag":82,"props":17363,"children":17364},{},[17365],{"type":37,"value":17366},"communicate",{"type":37,"value":733},{"type":32,"tag":46,"props":17369,"children":17370},{},[17371,17373,17378,17380,17385],{"type":37,"value":17372},"Graphic designers don't be afraid to ",{"type":32,"tag":82,"props":17374,"children":17375},{},[17376],{"type":37,"value":17377},"ask coders what's important to them",{"type":37,"value":17379},", let yourself be drawn into their world a bit and take away what will be pivotal to delivering maximum final quality. Ask what you can do to make the coded result more like the design, if they use any CSS frameworks and what their patterns are, what JS libraries they prefer to work with, and if they have any specifics that would be good to know about before designing something that will subsequently be a terrible ",{"type":32,"tag":82,"props":17381,"children":17382},{},[17383],{"type":37,"value":17384},"bottle-neck",{"type":37,"value":733},{"type":32,"tag":46,"props":17387,"children":17388},{},[17389,17391,17396,17398,17403,17405,17410],{"type":37,"value":17390},"Coders ",{"type":32,"tag":82,"props":17392,"children":17393},{},[17394],{"type":37,"value":17395},"don't be afraid to go",{"type":37,"value":17397}," back ",{"type":32,"tag":82,"props":17399,"children":17400},{},[17401],{"type":37,"value":17402},"to the graphic designer",{"type":37,"value":17404}," with the delivered design and tell him what you're struggling with, or what you need to dodge in the design, so that the result is the best possible and maybe also that the time spent is efficient. If you don't have a responsive design delivered then at least ask for a ",{"type":32,"tag":82,"props":17406,"children":17407},{},[17408],{"type":37,"value":17409},"key part",{"type":37,"value":17411}," in the responsive design, it won't cost the graphic designer so much time and you won't worry about figuring it out on mobile.",{"type":32,"tag":46,"props":17413,"children":17414},{},[17415],{"type":32,"tag":161,"props":17416,"children":17419},{"alt":17417,"src":17418,"title":17417},"Graphic designer and coder form a team","/article/coder-vs-designer/dream-team-en.svg",[],{"type":32,"tag":46,"props":17421,"children":17422},{},[17423],{"type":37,"value":17424},"In the following sections, I will discuss specific examples that I would recommend from a coder's perspective for a design development workflow.",{"type":32,"tag":39,"props":17426,"children":17428},{"id":17427},"colour-definition",[17429],{"type":37,"value":17430},"Colour definition",{"type":32,"tag":46,"props":17432,"children":17433},{},[17434,17436,17441,17442,17447,17448,17453,17455,17460],{"type":37,"value":17435},"Every modern web design software can define key colors that can be used in a project. For the coder it is a great help if the graphic designer defines and ideally describes them (in the style of ",{"type":32,"tag":117,"props":17437,"children":17438},{},[17439],{"type":37,"value":17440},"primary-100",{"type":37,"value":2497},{"type":32,"tag":117,"props":17443,"children":17444},{},[17445],{"type":37,"value":17446},"primary-200",{"type":37,"value":2497},{"type":32,"tag":117,"props":17449,"children":17450},{},[17451],{"type":37,"value":17452},"primary-300",{"type":37,"value":17454},"). He then uses only the colors he has defined, this allows the coder to create ",{"type":32,"tag":82,"props":17456,"children":17457},{},[17458],{"type":37,"value":17459},"identically named variables",{"type":37,"value":17461}," and when coding he doesn't even worry about the hex number of the color, he just looks at the name and uses the identically named variable.",{"type":32,"tag":46,"props":17463,"children":17464},{},[17465],{"type":32,"tag":161,"props":17466,"children":17470},{"alt":17467,"src":17468,"title":17467,"width":17469},"Using colors from Figma in CSS code","/article/coder-vs-designer/figma-css-and-tailwind.png","620",[],{"type":32,"tag":46,"props":17472,"children":17473},{},[17474,17476,17481],{"type":37,"value":17475},"Additionally, variables named this way (ideally mirrored ",{"type":32,"tag":82,"props":17477,"children":17478},{},[17479],{"type":37,"value":17480},"design \u003C-> code",{"type":37,"value":17482},") make it very easy to re-brand the page. That is, by changing one variable, you can overwrite the color of the entire site.",{"type":32,"tag":39,"props":17484,"children":17486},{"id":17485},"spacing-padding-margin",[17487],{"type":37,"value":17488},"Spacing, padding, margin",{"type":32,"tag":46,"props":17490,"children":17491},{},[17492,17494,17498,17500,17505,17507,17512,17514,17519,17521,17526,17528,17533,17535,17540,17541,17546,17548,17553],{"type":37,"value":17493},"Another minor difficulty is the values chosen for indentation, either internal ",{"type":32,"tag":117,"props":17495,"children":17496},{},[17497],{"type":37,"value":15398},{"type":37,"value":17499}," or external ",{"type":32,"tag":117,"props":17501,"children":17502},{},[17503],{"type":37,"value":17504},"margin",{"type":37,"value":17506},". The problem occurs when the graphic designer chooses values by eye and ",{"type":32,"tag":82,"props":17508,"children":17509},{},[17510],{"type":37,"value":17511},"doesn't have insight",{"type":37,"value":17513}," into the coder's techstack. Whether we're talking about bootstrap grid values or perhaps tailwind values, no coder is going to be too happy specifying ",{"type":32,"tag":82,"props":17515,"children":17516},{},[17517],{"type":37,"value":17518},"\"magic numbers \"",{"type":37,"value":17520}," like ",{"type":32,"tag":117,"props":17522,"children":17523},{},[17524],{"type":37,"value":17525},"padding: 11px 23px;",{"type":37,"value":17527}," but instead choose the near eye-pleasing values of ",{"type":32,"tag":117,"props":17529,"children":17530},{},[17531],{"type":37,"value":17532},"padding: 12px 25px;",{"type":37,"value":17534}," or if we're talking about Tailwind, the utility classes ",{"type":32,"tag":117,"props":17536,"children":17537},{},[17538],{"type":37,"value":17539},"py-3",{"type":37,"value":12607},{"type":32,"tag":117,"props":17542,"children":17543},{},[17544],{"type":37,"value":17545},"px-6",{"type":37,"value":17547},".\nNeither option is a happy ending, the ideal would be to sit down with a graphic designer and see how spacing works together in ",{"type":32,"tag":82,"props":17549,"children":17550},{},[17551],{"type":37,"value":17552},"what you like to do",{"type":37,"value":17554},". After all, even the graphic designer will be happier if it fits better.",{"type":32,"tag":39,"props":17556,"children":17558},{"id":17557},"components",[17559],{"type":37,"value":17560},"Components",{"type":32,"tag":46,"props":17562,"children":17563},{},[17564,17566,17571,17573,17578],{"type":37,"value":17565},"A great thing in modern web design is the ability to wrap a part of the GUI, or one particular element, into a ",{"type":32,"tag":82,"props":17567,"children":17568},{},[17569],{"type":37,"value":17570},"component",{"type":37,"value":17572}," and then ",{"type":32,"tag":82,"props":17574,"children":17575},{},[17576],{"type":37,"value":17577},"reuse",{"type":37,"value":17579}," it. The satisfying part is that this is exactly what we can do in development, we can wrap a component and reuse it with different inputs and therefore content.",{"type":32,"tag":46,"props":17581,"children":17582},{},[17583,17585,17590,17592,17597],{"type":37,"value":17584},"This means a lot, for example you can define ",{"type":32,"tag":82,"props":17586,"children":17587},{},[17588],{"type":37,"value":17589},"component states",{"type":37,"value":17591}," in the design and design how the active input field will look like for example. It is possible to reuse a component to create a binding to a so-called master component and by changing the design in the ",{"type":32,"tag":82,"props":17593,"children":17594},{},[17595],{"type":37,"value":17596},"master component",{"type":37,"value":17598}," to reflect the changes in all places where it is used.",{"type":32,"tag":46,"props":17600,"children":17601},{},[17602],{"type":37,"value":17603},"Theoretically, this can help the programmer lay out the distribution into components, because if they know you'll be using a piece of UI in multiple places, they'll create a component right away.",{"type":32,"tag":46,"props":17605,"children":17606},{},[17607,17609,17614],{"type":37,"value":17608},"By starting to create the components as a graphic designer, you are subtly forcing yourself to use them on the site, thus ",{"type":32,"tag":82,"props":17610,"children":17611},{},[17612],{"type":37,"value":17613},"saving the programmer development time",{"type":37,"value":733},{"type":32,"tag":46,"props":17616,"children":17617},{},[17618],{"type":32,"tag":161,"props":17619,"children":17622},{"alt":17620,"src":17621,"title":17620,"width":17469},"Using components in Figma","/article/coder-vs-designer/components.png",[],{"type":32,"tag":39,"props":17624,"children":17626},{"id":17625},"export-icons",[17627],{"type":37,"value":17628},"Export icons",{"type":32,"tag":46,"props":17630,"children":17631},{},[17632,17634,17639],{"type":37,"value":17633},"Saving vector icons for use on the web is a discipline in itself for me. It depends a lot on ",{"type":32,"tag":82,"props":17635,"children":17636},{},[17637],{"type":37,"value":17638},"how you work with icons on the web",{"type":37,"value":17640},", and the requirements for saving them properly depend on that. However, I will allow myself to pick out a few general pointers.",{"type":32,"tag":169,"props":17642,"children":17644},{"id":17643},"size-ratio",[17645],{"type":37,"value":17646},"Size, ratio",{"type":32,"tag":46,"props":17648,"children":17649},{},[17650,17652,17657],{"type":37,"value":17651},"Icons that are to be next to/above each other or are required to be aligned in some way, it is very important to export them with ",{"type":32,"tag":82,"props":17653,"children":17654},{},[17655],{"type":37,"value":17656},"exactly the same canvas/artboard",{"type":37,"value":17658}," (drawing area). Personally, I recommend putting X identical artboards side by side and placing the icons one at a time so that they visually match and at the same time the icons don't have too much empty space around them. This will give us the best chance of having them display great on the site.",{"type":32,"tag":46,"props":17660,"children":17661},{},[17662],{"type":32,"tag":161,"props":17663,"children":17666},{"alt":17664,"src":17665,"title":17664,"width":10519},"Export icons for font","/article/coder-vs-designer/icons.png",[],{"type":32,"tag":169,"props":17668,"children":17670},{"id":17669},"style",[17671],{"type":37,"value":17672},"Style",{"type":32,"tag":46,"props":17674,"children":17675},{},[17676],{"type":37,"value":17677},"If we want the icons to look the same style we need to give them the same stroke thickness, again it's a good idea to line them up in artboards and check them all at once.",{"type":32,"tag":169,"props":17679,"children":17681},{"id":17680},"icons-with-stroke",[17682],{"type":37,"value":17683},"Icons with stroke",{"type":32,"tag":46,"props":17685,"children":17686},{},[17687,17689,17694],{"type":37,"value":17688},"We always export icons (unless otherwise required) by converting ",{"type":32,"tag":82,"props":17690,"children":17691},{},[17692],{"type":37,"value":17693},"stroke to shape",{"type":37,"value":17695},", called the outline stroke function. This way the icon loses the ability to change the stroke thickness, which is what we want on the site, because it will behave consistently when zoomed in/out.",{"type":32,"tag":169,"props":17697,"children":17699},{"id":17698},"icons-in-font",[17700],{"type":37,"value":17701},"Icons in font",{"type":32,"tag":46,"props":17703,"children":17704},{},[17705,17707,17712,17714,17719,17721,17726,17727,17732,17734,17741],{"type":37,"value":17706},"If icons need to be exported with the intention of generating a font from them, then it is important to pay attention to other criteria. If we consider generating a font from Fontella, for example, then we need to have the icon ",{"type":32,"tag":82,"props":17708,"children":17709},{},[17710],{"type":37,"value":17711},"unified into one shape",{"type":37,"value":17713}," (union).\nFurthermore, we need to have the icon only in ",{"type":32,"tag":82,"props":17715,"children":17716},{},[17717],{"type":37,"value":17718},"one color",{"type":37,"value":17720},", without any background, because once the icon is converted to a font, it will be completely colored to the text color (CSS color value).\nIf you are generating a font using Figma, make sure that the resulting SVG does not contain the ",{"type":32,"tag":117,"props":17722,"children":17723},{},[17724],{"type":37,"value":17725},"fill-rule:evenodd;",{"type":37,"value":2529},{"type":32,"tag":117,"props":17728,"children":17729},{},[17730],{"type":37,"value":17731},"clip-rule:evenodd;",{"type":37,"value":17733}," attributes, because Fontello can't handle those. If you'd like to know more about the combination of fontello and figma, then I recommend ",{"type":32,"tag":139,"props":17735,"children":17738},{"href":17736,"rel":17737,":target":345},"https://medium.com/mabiloft/we-designed-an-icon-font-with-figma-and-fontello-and-it-has-not-been-a-piece-of-cake-b2948973738e",[347],[17739],{"type":37,"value":17740},"this article",{"type":37,"value":733},{"type":32,"tag":39,"props":17743,"children":17745},{"id":17744},"a-few-tips-for-the-end",[17746],{"type":37,"value":17747},"A few tips for the end",{"type":32,"tag":153,"props":17749,"children":17750},{},[17751,17812],{"type":32,"tag":157,"props":17752,"children":17753},{},[17754,17760,17791,17800],{"type":32,"tag":169,"props":17755,"children":17757},{"id":17756},"kits-for-graphics",[17758],{"type":37,"value":17759},"Kits for graphics",{"type":32,"tag":46,"props":17761,"children":17762},{},[17763,17765,17772,17774,17780,17782,17789],{"type":37,"value":17764},"Help yourself with the technical stuff by using pre-made templates, for example for Bootstrap grid there is ",{"type":32,"tag":139,"props":17766,"children":17769},{"href":17767,"rel":17768,":target":345},"https://www.figma.com/community/file/1021683007799895845/Bootstrap-Grid-V4-V5",[347],[17770],{"type":37,"value":17771},"this",{"type":37,"value":17773}," template. If you want a whole kit of components for Booststrap, then I recommend ",{"type":32,"tag":139,"props":17775,"children":17778},{"href":17776,"rel":17777,":target":345},"https://www.figma.com/community/file/1044316192441037087/Bootstrap-5-Design-System---UI-Kit",[347],[17779],{"type":37,"value":17771},{"type":37,"value":17781}," template.\nThen for the tailwind template, ",{"type":32,"tag":139,"props":17783,"children":17786},{"href":17784,"rel":17785,":target":345},"https://www.figma.com/community/file/768809027799962739/Tailwind-CSS-UI",[347],[17787],{"type":37,"value":17788},"this kit",{"type":37,"value":17790}," is useful, showing the basic principles of the framework.",{"type":32,"tag":46,"props":17792,"children":17793},{},[17794],{"type":32,"tag":161,"props":17795,"children":17799},{"alt":17796,"src":17797,"title":17796,"width":17798},"UI Kit for figma","/article/coder-vs-designer/ui-kit.png","370",[],{"type":32,"tag":46,"props":17801,"children":17802},{},[17803,17805,17810],{"type":37,"value":17804},"The point I'm trying to make is ",{"type":32,"tag":82,"props":17806,"children":17807},{},[17808],{"type":37,"value":17809},"make your job easier",{"type":37,"value":17811},", there are a great many shared libraries/plugins that will make your job easier. Just check with your dev team and pick the right workflow.",{"type":32,"tag":157,"props":17813,"children":17814},{},[17815,17821,17842,17847],{"type":32,"tag":39,"props":17816,"children":17818},{"id":17817},"extensions-for-coders",[17819],{"type":37,"value":17820},"Extensions for coders",{"type":32,"tag":46,"props":17822,"children":17823},{},[17824,17826,17831,17833,17840],{"type":37,"value":17825},"It's been my experience that us coders can sometimes lack an eye for detail and simply may not notice some small difference in design. That's why it's always a good idea to ",{"type":32,"tag":82,"props":17827,"children":17828},{},[17829],{"type":37,"value":17830},"compare the design with the final site",{"type":37,"value":17832}," and check if everything is displaying correctly. For this purpose, I personally use the browser extension ",{"type":32,"tag":139,"props":17834,"children":17837},{"href":17835,"rel":17836,":target":345},"https://chrome.google.com/webstore/detail/perfectpixel-by-welldonec/dkaagdgjmgdmbnecmcefdhjekcoceebi",[347],[17838],{"type":37,"value":17839},"Pixel Perfect",{"type":37,"value":17841},", which allows you to overlay the design over the site and see the differences in the result compared to the original design.",{"type":32,"tag":46,"props":17843,"children":17844},{},[17845],{"type":37,"value":17846},"Note: I don't think we should create pixel-perfect code because the web is a fluid medium, but I think it's necessary to do at least a cursory check to make sure everything fits as it should.",{"type":32,"tag":46,"props":17848,"children":17849},{},[17850],{"type":32,"tag":161,"props":17851,"children":17854},{"alt":17852,"src":17853,"title":17852,"width":17798},"Pixel perfect - sample","/article/coder-vs-designer/perfect-design-en.png",[],{"type":32,"tag":39,"props":17856,"children":17857},{"id":774},[17858],{"type":37,"value":777},{"type":32,"tag":46,"props":17860,"children":17861},{},[17862,17864,17869],{"type":37,"value":17863},"The creative world of a graphic designer and the exact world of a coder are very different, but both should have the same goal - ",{"type":32,"tag":82,"props":17865,"children":17866},{},[17867],{"type":37,"value":17868},"deliver great final quality",{"type":37,"value":17870},". The only way to achieve this is by fine-tuning our workflows together and educating and learning about each other's worlds.",{"type":32,"tag":46,"props":17872,"children":17873},{},[17874],{"type":37,"value":17875},"Did you miss any information in the article? Do you have any questions? Feel free to contact me :)",{"type":32,"tag":57,"props":17877,"children":17878},{},[],{"type":32,"tag":39,"props":17880,"children":17881},{"id":798},[17882],{"type":37,"value":6401},{"type":32,"tag":444,"props":17884,"children":17885},{},[17886,17896],{"type":32,"tag":448,"props":17887,"children":17888},{},[17889],{"type":32,"tag":139,"props":17890,"children":17893},{"href":17891,"rel":17892,":rel":347},"https://www.figma.com/best-practices/",[347],[17894],{"type":37,"value":17895},"Best Practice in Figma",{"type":32,"tag":448,"props":17897,"children":17898},{},[17899],{"type":32,"tag":139,"props":17900,"children":17903},{"href":17901,"rel":17902,":rel":347},"https://www.adobe.com/products/xd/learn/design/layout/web-design-best-practices.html",[347],[17904],{"type":37,"value":17905},"Best Practice in Adobe XD",{"title":8,"searchDepth":862,"depth":862,"links":17907},[17908,17909,17910,17911,17912,17913,17919,17920,17921],{"id":41,"depth":862,"text":44},{"id":17353,"depth":862,"text":17356},{"id":17427,"depth":862,"text":17430},{"id":17485,"depth":862,"text":17488},{"id":17557,"depth":862,"text":17560},{"id":17625,"depth":862,"text":17628,"children":17914},[17915,17916,17917,17918],{"id":17643,"depth":871,"text":17646},{"id":17669,"depth":871,"text":17672},{"id":17680,"depth":871,"text":17683},{"id":17698,"depth":871,"text":17701},{"id":17744,"depth":862,"text":17747},{"id":774,"depth":862,"text":777},{"id":798,"depth":862,"text":6401},"content:knowledge:coder-vs-graphic-designer-how-to-prepare-design-and-deliver-good-quality-results.md","knowledge/coder-vs-graphic-designer-how-to-prepare-design-and-deliver-good-quality-results.md",{"_path":17925,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"_empty":7,"title":17926,"description":17927,"author":11,"date":17928,"readingTime":9746,"level":14,"image":17929,"tags":17930,"slugs":17932,"relatedArticles":17934,"body":17935,"_type":881,"_id":19102,"_source":883,"_file":19103,"_extension":885},"/knowledge/tailwind-introduction","Introduction to the framework, should I implement it in my Tech Stack?","Find out how Tailwind CSS makes web development easier. Utility-first framework with predefined classes for faster development.","2023-06-19","/featured/tailwind-introduction.jpg",[8580,15193,17931],"framework",{"en":12175,"cs":17933},"tailwind-uvod-do-frameworku",[3000,3001,6490],{"type":29,"children":17936,"toc":19088},[17937,17943,17947,17952,17958,17972,17978,17983,17994,18006,18017,18034,18042,18048,18059,18064,18070,18101,18130,18135,18266,18313,18319,18363,18395,18400,18501,18601,18629,18634,18640,18650,18661,18666,18677,18682,18693,18698,18709,18714,18720,18744,18768,18779,18784,18789,18888,18893,18904,18908,18922,18927,18938,18943,18949,18970,18975,18987,18992,19003,19008,19019,19023,19037,19042,19046],{"type":32,"tag":33,"props":17938,"children":17940},{"id":17939},"tailwind-introduction-to-the-framework-should-i-implement-it-in-my-tech-stack",[17941],{"type":37,"value":17942},"Tailwind: Introduction to the Framework, Should I Implement It in My Tech Stack?",{"type":32,"tag":39,"props":17944,"children":17945},{"id":41},[17946],{"type":37,"value":44},{"type":32,"tag":46,"props":17948,"children":17949},{},[17950],{"type":37,"value":17951},"Tailwind CSS is one of the most popular CSS frameworks recently. Its aim is to simplify and speed up the development of websites and applications using predefined utility classes. This article will introduce you to this framework and explain some of the principles it applies.",{"type":32,"tag":39,"props":17953,"children":17955},{"id":17954},"utility-first",[17956],{"type":37,"value":17957},"Utility-first",{"type":32,"tag":46,"props":17959,"children":17960},{},[17961,17963,17970],{"type":37,"value":17962},"Tailwind CSS is considered a ",{"type":32,"tag":139,"props":17964,"children":17967},{":target":345,"href":17965,"rel":17966},"https://tailwindcss.com/docs/utility-first",[347],[17968],{"type":37,"value":17969},"utility-first framework",{"type":37,"value":17971},", which means it focuses on providing simple and straightforward utility classes for quick and efficient styling. Instead of constructing custom classes for each element on a page, with Tailwind, you can easily combine existing classes to achieve the desired appearance. This approach allows developers to work faster and reduces the likelihood of duplicate code.",{"type":32,"tag":39,"props":17973,"children":17975},{"id":17974},"examples",[17976],{"type":37,"value":17977},"Examples",{"type":32,"tag":46,"props":17979,"children":17980},{},[17981],{"type":37,"value":17982},"Let's say we want to style a button with rounded corners, white text, and a green background. In traditional CSS, we would create a class like .button and assign CSS styles to it, for example:",{"type":32,"tag":7664,"props":17984,"children":17986},{"code":17985,"language":8580,"meta":7668},"\u003Cbutton class=\"button\">Order\u003C/button>\n\u003Cstyle>\n.button {\n  background:green;\n  color:white;\n  border-radius : 0.25rem;\n}\n\u003C/style>\n",[17987],{"type":32,"tag":7671,"props":17988,"children":17989},{},[17990],{"type":32,"tag":7664,"props":17991,"children":17992},{"__ignoreMap":8},[17993],{"type":37,"value":17985},{"type":32,"tag":46,"props":17995,"children":17996},{},[17997,17999,18004],{"type":37,"value":17998},"And how would the same example look rewritten in ",{"type":32,"tag":82,"props":18000,"children":18001},{},[18002],{"type":37,"value":18003},"TailwindCSS",{"type":37,"value":18005},"?\nLet's take a look.",{"type":32,"tag":7664,"props":18007,"children":18009},{"code":18008,"language":8580,"meta":7668},"\u003Cbutton class=\"bg-green text-white rounded\">Order\u003C/button>\n",[18010],{"type":32,"tag":7671,"props":18011,"children":18012},{},[18013],{"type":32,"tag":7664,"props":18014,"children":18015},{"__ignoreMap":8},[18016],{"type":37,"value":18008},{"type":32,"tag":46,"props":18018,"children":18019},{},[18020,18022,18026,18027,18032],{"type":37,"value":18021},"As you can see, we use CSS classes similar to writing inline styles. This means we don't have to switch context between ",{"type":32,"tag":117,"props":18023,"children":18024},{},[18025],{"type":37,"value":15541},{"type":37,"value":1982},{"type":32,"tag":117,"props":18028,"children":18029},{},[18030],{"type":37,"value":18031},"CSS",{"type":37,"value":18033},", in our minds; instead, we stay within HTML",{"type":32,"tag":46,"props":18035,"children":18036},{},[18037],{"type":32,"tag":161,"props":18038,"children":18041},{"alt":18039,"src":18040,"title":18039},"Tailwind Overview","/article/tailwind-introduction/tailwind-overview.svg",[],{"type":32,"tag":39,"props":18043,"children":18045},{"id":18044},"configuration",[18046],{"type":37,"value":18047},"Configuration",{"type":32,"tag":46,"props":18049,"children":18050},{},[18051,18052,18057],{"type":37,"value":3506},{"type":32,"tag":117,"props":18053,"children":18054},{},[18055],{"type":37,"value":18056},"tailwind.config.js",{"type":37,"value":18058}," file is used for configuration. In it, you can specify the colors you want to use, define breakpoints for your media queries, create animations, gradients, shadows, and much more. The definitions in the configuration file prepare the classes for use in your project.",{"type":32,"tag":46,"props":18060,"children":18061},{},[18062],{"type":37,"value":18063},"A great advantage of this framework is that the resulting minified CSS contains only the classes that are actually used in the project. Before the project is built, it goes through a simple regex search for classes, and the found values are used as the set of names for which CSS will be generated.",{"type":32,"tag":39,"props":18065,"children":18067},{"id":18066},"units",[18068],{"type":37,"value":18069},"Units",{"type":32,"tag":46,"props":18071,"children":18072},{},[18073,18075,18080,18082,18092,18094,18099],{"type":37,"value":18074},"In Tailwind, units are based on ",{"type":32,"tag":117,"props":18076,"children":18077},{},[18078],{"type":37,"value":18079},"rem",{"type":37,"value":18081},", with  ",{"type":32,"tag":82,"props":18083,"children":18084},{},[18085,18087],{"type":37,"value":18086},"1 tawilwind jednotka je ",{"type":32,"tag":117,"props":18088,"children":18089},{},[18090],{"type":37,"value":18091},"1/4 rem",{"type":37,"value":18093}," which is ",{"type":32,"tag":117,"props":18095,"children":18096},{},[18097],{"type":37,"value":18098},"4px",{"type":37,"value":18100}," by default.",{"type":32,"tag":46,"props":18102,"children":18103},{},[18104,18129],{"type":32,"tag":82,"props":18105,"children":18106},{},[18107,18112,18114,18119,18120,18124,18125],{"type":32,"tag":117,"props":18108,"children":18109},{},[18110],{"type":37,"value":18111},"1 rem",{"type":37,"value":18113}," = ",{"type":32,"tag":117,"props":18115,"children":18116},{},[18117],{"type":37,"value":18118},"16px",{"type":37,"value":2497},{"type":32,"tag":117,"props":18121,"children":18122},{},[18123],{"type":37,"value":18091},{"type":37,"value":18113},{"type":32,"tag":117,"props":18126,"children":18127},{},[18128],{"type":37,"value":18098},{"type":37,"value":733},{"type":32,"tag":46,"props":18131,"children":18132},{},[18133],{"type":37,"value":18134},"See the table below:",{"type":32,"tag":1559,"props":18136,"children":18137},{},[18138,18159],{"type":32,"tag":1563,"props":18139,"children":18140},{},[18141],{"type":32,"tag":1567,"props":18142,"children":18143},{},[18144,18150,18154],{"type":32,"tag":1571,"props":18145,"children":18147},{"align":18146},"right",[18148],{"type":37,"value":18149},"Tailwind",{"type":32,"tag":1571,"props":18151,"children":18152},{"align":18146},[18153],{"type":37,"value":18079},{"type":32,"tag":1571,"props":18155,"children":18156},{"align":18146},[18157],{"type":37,"value":18158},"px",{"type":32,"tag":1588,"props":18160,"children":18161},{},[18162,18180,18196,18214,18231,18249],{"type":32,"tag":1567,"props":18163,"children":18164},{},[18165,18170,18175],{"type":32,"tag":1595,"props":18166,"children":18167},{"align":18146},[18168],{"type":37,"value":18169},"0.5",{"type":32,"tag":1595,"props":18171,"children":18172},{"align":18146},[18173],{"type":37,"value":18174},"0.125rem",{"type":32,"tag":1595,"props":18176,"children":18177},{"align":18146},[18178],{"type":37,"value":18179},"2px",{"type":32,"tag":1567,"props":18181,"children":18182},{},[18183,18187,18192],{"type":32,"tag":1595,"props":18184,"children":18185},{"align":18146},[18186],{"type":37,"value":9316},{"type":32,"tag":1595,"props":18188,"children":18189},{"align":18146},[18190],{"type":37,"value":18191},"0.25rem",{"type":32,"tag":1595,"props":18193,"children":18194},{"align":18146},[18195],{"type":37,"value":18098},{"type":32,"tag":1567,"props":18197,"children":18198},{},[18199,18204,18209],{"type":32,"tag":1595,"props":18200,"children":18201},{"align":18146},[18202],{"type":37,"value":18203},"1.5",{"type":32,"tag":1595,"props":18205,"children":18206},{"align":18146},[18207],{"type":37,"value":18208},"0.375rem",{"type":32,"tag":1595,"props":18210,"children":18211},{"align":18146},[18212],{"type":37,"value":18213},"6px",{"type":32,"tag":1567,"props":18215,"children":18216},{},[18217,18221,18226],{"type":32,"tag":1595,"props":18218,"children":18219},{"align":18146},[18220],{"type":37,"value":9338},{"type":32,"tag":1595,"props":18222,"children":18223},{"align":18146},[18224],{"type":37,"value":18225},"0.5rem",{"type":32,"tag":1595,"props":18227,"children":18228},{"align":18146},[18229],{"type":37,"value":18230},"8px",{"type":32,"tag":1567,"props":18232,"children":18233},{},[18234,18239,18244],{"type":32,"tag":1595,"props":18235,"children":18236},{"align":18146},[18237],{"type":37,"value":18238},"2.5",{"type":32,"tag":1595,"props":18240,"children":18241},{"align":18146},[18242],{"type":37,"value":18243},"0.625rem",{"type":32,"tag":1595,"props":18245,"children":18246},{"align":18146},[18247],{"type":37,"value":18248},"10px",{"type":32,"tag":1567,"props":18250,"children":18251},{},[18252,18256,18261],{"type":32,"tag":1595,"props":18253,"children":18254},{"align":18146},[18255],{"type":37,"value":9360},{"type":32,"tag":1595,"props":18257,"children":18258},{"align":18146},[18259],{"type":37,"value":18260},"0.75rem",{"type":32,"tag":1595,"props":18262,"children":18263},{"align":18146},[18264],{"type":37,"value":18265},"12px",{"type":32,"tag":153,"props":18267,"children":18268},{},[18269],{"type":32,"tag":157,"props":18270,"children":18271},{},[18272],{"type":32,"tag":46,"props":18273,"children":18274},{},[18275,18277,18281,18283,18287,18288,18292,18294,18299,18301,18305,18307,18311],{"type":37,"value":18276},"Why so complicated? Because it's actually easier. The fundamental dimension of modern coding is ",{"type":32,"tag":117,"props":18278,"children":18279},{},[18280],{"type":37,"value":18079},{"type":37,"value":18282}," units, as ",{"type":32,"tag":117,"props":18284,"children":18285},{},[18286],{"type":37,"value":18079},{"type":37,"value":18113},{"type":32,"tag":117,"props":18289,"children":18290},{},[18291],{"type":37,"value":18118},{"type":37,"value":18293}," by default, fractional rem values are often used in code (e.g., ",{"type":32,"tag":117,"props":18295,"children":18296},{},[18297],{"type":37,"value":18298},"padding: 0.5rem 0.75rem;",{"type":37,"value":18300},"). To eliminate decimal places in CSS class names, it was necessary to adjust the ratio and divide the ",{"type":32,"tag":117,"props":18302,"children":18303},{},[18304],{"type":37,"value":18079},{"type":37,"value":18306}," unit by four. Therefore, 1 unit in Tailwind is equal to ",{"type":32,"tag":117,"props":18308,"children":18309},{},[18310],{"type":37,"value":18098},{"type":37,"value":18312}," (16 / 4 = 4).",{"type":32,"tag":39,"props":18314,"children":18316},{"id":18315},"width-height-spacing",[18317],{"type":37,"value":18318},"Width, Height, Spacing",{"type":32,"tag":46,"props":18320,"children":18321},{},[18322,18324,18329,18331,18336,18338,18343,18345,18349,18351,18356,18357,18362],{"type":37,"value":18323},"Now that we know the units, let's demonstrate their simple usage. Width has the prefix ",{"type":32,"tag":117,"props":18325,"children":18326},{},[18327],{"type":37,"value":18328},"w-*",{"type":37,"value":18330},", and height has the prefix ",{"type":32,"tag":117,"props":18332,"children":18333},{},[18334],{"type":37,"value":18335},"h-*",{"type":37,"value":18337},". So, if we want a square with a width of ",{"type":32,"tag":117,"props":18339,"children":18340},{},[18341],{"type":37,"value":18342},"40px",{"type":37,"value":18344}," and height of ",{"type":32,"tag":117,"props":18346,"children":18347},{},[18348],{"type":37,"value":18342},{"type":37,"value":18350},", we write it like this: ",{"type":32,"tag":117,"props":18352,"children":18353},{},[18354],{"type":37,"value":18355},"w-10",{"type":37,"value":12607},{"type":32,"tag":117,"props":18358,"children":18359},{},[18360],{"type":37,"value":18361},"h-10",{"type":37,"value":733},{"type":32,"tag":46,"props":18364,"children":18365},{},[18366,18368,18373,18375,18380,18382,18387,18389,18394],{"type":37,"value":18367},"Margin and padding are very similar, but while padding has the prefix ",{"type":32,"tag":117,"props":18369,"children":18370},{},[18371],{"type":37,"value":18372},"p-*",{"type":37,"value":18374},", margin has the prefix ",{"type":32,"tag":117,"props":18376,"children":18377},{},[18378],{"type":37,"value":18379},"m-*",{"type":37,"value":18381},". We can also specify which specific margin/padding we want. For example, padding top is written with the prefix ",{"type":32,"tag":117,"props":18383,"children":18384},{},[18385],{"type":37,"value":18386},"pt-*",{"type":37,"value":18388},", padding left and right with the prefix ",{"type":32,"tag":117,"props":18390,"children":18391},{},[18392],{"type":37,"value":18393},"px-*",{"type":37,"value":733},{"type":32,"tag":46,"props":18396,"children":18397},{},[18398],{"type":37,"value":18399},"The table below provides a better explanation:",{"type":32,"tag":1559,"props":18401,"children":18402},{},[18403,18418],{"type":32,"tag":1563,"props":18404,"children":18405},{},[18406],{"type":32,"tag":1567,"props":18407,"children":18408},{},[18409,18414],{"type":32,"tag":1571,"props":18410,"children":18411},{"align":18146},[18412],{"type":37,"value":18413},"Class",{"type":32,"tag":1571,"props":18415,"children":18416},{"align":1573},[18417],{"type":37,"value":18031},{"type":32,"tag":1588,"props":18419,"children":18420},{},[18421,18437,18453,18469,18485],{"type":32,"tag":1567,"props":18422,"children":18423},{},[18424,18432],{"type":32,"tag":1595,"props":18425,"children":18426},{"align":18146},[18427],{"type":32,"tag":117,"props":18428,"children":18429},{},[18430],{"type":37,"value":18431},"p-2",{"type":32,"tag":1595,"props":18433,"children":18434},{"align":1573},[18435],{"type":37,"value":18436},"padding: 8px;",{"type":32,"tag":1567,"props":18438,"children":18439},{},[18440,18448],{"type":32,"tag":1595,"props":18441,"children":18442},{"align":18146},[18443],{"type":32,"tag":117,"props":18444,"children":18445},{},[18446],{"type":37,"value":18447},"pt-2",{"type":32,"tag":1595,"props":18449,"children":18450},{"align":1573},[18451],{"type":37,"value":18452},"padding-top: 8px",{"type":32,"tag":1567,"props":18454,"children":18455},{},[18456,18464],{"type":32,"tag":1595,"props":18457,"children":18458},{"align":18146},[18459],{"type":32,"tag":117,"props":18460,"children":18461},{},[18462],{"type":37,"value":18463},"pb-2",{"type":32,"tag":1595,"props":18465,"children":18466},{"align":1573},[18467],{"type":37,"value":18468},"padding-bottom: 8px",{"type":32,"tag":1567,"props":18470,"children":18471},{},[18472,18480],{"type":32,"tag":1595,"props":18473,"children":18474},{"align":18146},[18475],{"type":32,"tag":117,"props":18476,"children":18477},{},[18478],{"type":37,"value":18479},"px-2",{"type":32,"tag":1595,"props":18481,"children":18482},{"align":1573},[18483],{"type":37,"value":18484},"padding-left: 8px; padding-right: 8px;",{"type":32,"tag":1567,"props":18486,"children":18487},{},[18488,18496],{"type":32,"tag":1595,"props":18489,"children":18490},{"align":18146},[18491],{"type":32,"tag":117,"props":18492,"children":18493},{},[18494],{"type":37,"value":18495},"py-2",{"type":32,"tag":1595,"props":18497,"children":18498},{"align":1573},[18499],{"type":37,"value":18500},"padding-top: 8px; padding-bottom: 8px;",{"type":32,"tag":1559,"props":18502,"children":18503},{},[18504,18518],{"type":32,"tag":1563,"props":18505,"children":18506},{},[18507],{"type":32,"tag":1567,"props":18508,"children":18509},{},[18510,18514],{"type":32,"tag":1571,"props":18511,"children":18512},{"align":18146},[18513],{"type":37,"value":18413},{"type":32,"tag":1571,"props":18515,"children":18516},{"align":1573},[18517],{"type":37,"value":18031},{"type":32,"tag":1588,"props":18519,"children":18520},{},[18521,18537,18553,18569,18585],{"type":32,"tag":1567,"props":18522,"children":18523},{},[18524,18532],{"type":32,"tag":1595,"props":18525,"children":18526},{"align":18146},[18527],{"type":32,"tag":117,"props":18528,"children":18529},{},[18530],{"type":37,"value":18531},"m-2",{"type":32,"tag":1595,"props":18533,"children":18534},{"align":1573},[18535],{"type":37,"value":18536},"margin: 8px;",{"type":32,"tag":1567,"props":18538,"children":18539},{},[18540,18548],{"type":32,"tag":1595,"props":18541,"children":18542},{"align":18146},[18543],{"type":32,"tag":117,"props":18544,"children":18545},{},[18546],{"type":37,"value":18547},"mt-2",{"type":32,"tag":1595,"props":18549,"children":18550},{"align":1573},[18551],{"type":37,"value":18552},"margin-top: 8px",{"type":32,"tag":1567,"props":18554,"children":18555},{},[18556,18564],{"type":32,"tag":1595,"props":18557,"children":18558},{"align":18146},[18559],{"type":32,"tag":117,"props":18560,"children":18561},{},[18562],{"type":37,"value":18563},"mb-2",{"type":32,"tag":1595,"props":18565,"children":18566},{"align":1573},[18567],{"type":37,"value":18568},"margin-bottom: 8px",{"type":32,"tag":1567,"props":18570,"children":18571},{},[18572,18580],{"type":32,"tag":1595,"props":18573,"children":18574},{"align":18146},[18575],{"type":32,"tag":117,"props":18576,"children":18577},{},[18578],{"type":37,"value":18579},"mx-2",{"type":32,"tag":1595,"props":18581,"children":18582},{"align":1573},[18583],{"type":37,"value":18584},"margin-left: 8px; margin-right: 8px;",{"type":32,"tag":1567,"props":18586,"children":18587},{},[18588,18596],{"type":32,"tag":1595,"props":18589,"children":18590},{"align":18146},[18591],{"type":32,"tag":117,"props":18592,"children":18593},{},[18594],{"type":37,"value":18595},"my-2",{"type":32,"tag":1595,"props":18597,"children":18598},{"align":1573},[18599],{"type":37,"value":18600},"margin-top: 8px; margin-bottom: 8px;",{"type":32,"tag":153,"props":18602,"children":18603},{},[18604],{"type":32,"tag":157,"props":18605,"children":18606},{},[18607,18621],{"type":32,"tag":46,"props":18608,"children":18609},{},[18610,18612,18619],{"type":37,"value":18611},"How is one supposed to remember all this?\nDon't worry, modern editors like ",{"type":32,"tag":139,"props":18613,"children":18616},{":target":345,"href":18614,"rel":18615},"https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss",[347],[18617],{"type":37,"value":18618},"VS code have a plugin",{"type":37,"value":18620}," for tailwind that tells and explains what class contains what.",{"type":32,"tag":46,"props":18622,"children":18623},{},[18624],{"type":32,"tag":161,"props":18625,"children":18628},{"alt":18626,"src":18627,"title":18626},"VS Code Tailwind","/article/tailwind-introduction/vs-code-view.png",[],{"type":32,"tag":46,"props":18630,"children":18631},{},[18632],{"type":37,"value":18633},"In addition, the authors of Tailwind have written really good documentation, where you can find everything you need.",{"type":32,"tag":39,"props":18635,"children":18637},{"id":18636},"colors",[18638],{"type":37,"value":18639},"Colors",{"type":32,"tag":46,"props":18641,"children":18642},{},[18643,18645,18649],{"type":37,"value":18644},"Colors can be used in text, backgrounds, gradients, borders, etc. Colors are configuration driven, then all colors are available in all classes that are related to the color. For example, if we define a primary color in ",{"type":32,"tag":117,"props":18646,"children":18647},{},[18648],{"type":37,"value":18056},{"type":37,"value":6788},{"type":32,"tag":7664,"props":18651,"children":18653},{"code":18652,"language":8581,"meta":7668},"colors: {\n    primary: {\n        DEFAULT: '#AA1BBD',\n    },\n}\n",[18654],{"type":32,"tag":7671,"props":18655,"children":18656},{},[18657],{"type":32,"tag":7664,"props":18658,"children":18659},{"__ignoreMap":8},[18660],{"type":37,"value":18652},{"type":32,"tag":46,"props":18662,"children":18663},{},[18664],{"type":37,"value":18665},"We can then use it, for example, in text colouring",{"type":32,"tag":7664,"props":18667,"children":18669},{"code":18668,"language":8580,"meta":7668},"\u003Ch1 class=\"text-primary\">Heading\u003C/h1>\n",[18670],{"type":32,"tag":7671,"props":18671,"children":18672},{},[18673],{"type":32,"tag":7664,"props":18674,"children":18675},{"__ignoreMap":8},[18676],{"type":37,"value":18668},{"type":32,"tag":46,"props":18678,"children":18679},{},[18680],{"type":37,"value":18681},"or in the background colour of the div",{"type":32,"tag":7664,"props":18683,"children":18685},{"code":18684,"language":8580,"meta":7668},"\u003Cdiv class=\"bg-primary\">\u003C/div>\n",[18686],{"type":32,"tag":7671,"props":18687,"children":18688},{},[18689],{"type":32,"tag":7664,"props":18690,"children":18691},{"__ignoreMap":8},[18692],{"type":37,"value":18684},{"type":32,"tag":46,"props":18694,"children":18695},{},[18696],{"type":37,"value":18697},"Or maybe as a border color",{"type":32,"tag":7664,"props":18699,"children":18701},{"code":18700,"language":8580,"meta":7668},"\u003Cdiv class=\"border border-primary\">\u003C/div>\n",[18702],{"type":32,"tag":7671,"props":18703,"children":18704},{},[18705],{"type":32,"tag":7664,"props":18706,"children":18707},{"__ignoreMap":8},[18708],{"type":37,"value":18700},{"type":32,"tag":46,"props":18710,"children":18711},{},[18712],{"type":37,"value":18713},"And so on.",{"type":32,"tag":39,"props":18715,"children":18717},{"id":18716},"responsiveness",[18718],{"type":37,"value":18719},"Responsiveness",{"type":32,"tag":46,"props":18721,"children":18722},{},[18723,18725,18730,18731,18736,18737,18742],{"type":37,"value":18724},"Now you're wondering how to write responsive styles in such a utility-first framework and maybe the idea of bootstrap and its classes ",{"type":32,"tag":117,"props":18726,"children":18727},{},[18728],{"type":37,"value":18729},"col-sm-*",{"type":37,"value":2497},{"type":32,"tag":117,"props":18732,"children":18733},{},[18734],{"type":37,"value":18735},"col-md-*",{"type":37,"value":2497},{"type":32,"tag":117,"props":18738,"children":18739},{},[18740],{"type":37,"value":18741},"col-lg-*",{"type":37,"value":18743}," etc... comes to mind.",{"type":32,"tag":46,"props":18745,"children":18746},{},[18747,18749,18754,18755,18760,18761,18766],{"type":37,"value":18748},"TailwindCSS went much further in this and handles responsiveness by prefixing with a colon (",{"type":32,"tag":117,"props":18750,"children":18751},{},[18752],{"type":37,"value":18753},"sm:",{"type":37,"value":2497},{"type":32,"tag":117,"props":18756,"children":18757},{},[18758],{"type":37,"value":18759},"md:",{"type":37,"value":2497},{"type":32,"tag":117,"props":18762,"children":18763},{},[18764],{"type":37,"value":18765},"lg:",{"type":37,"value":18767},"), if we want to hide the button on mobile and leave it on desktop the notation would look like this:",{"type":32,"tag":7664,"props":18769,"children":18771},{"code":18770,"language":8580,"meta":7668},"\u003Cbutton class=\"hidden lg:inline-block\">Button\u003C/button>\n",[18772],{"type":32,"tag":7671,"props":18773,"children":18774},{},[18775],{"type":32,"tag":7664,"props":18776,"children":18777},{"__ignoreMap":8},[18778],{"type":37,"value":18770},{"type":32,"tag":46,"props":18780,"children":18781},{},[18782],{"type":37,"value":18783},"The more astute of you will notice that this is a mobile-first solution, where the non-prefix values are applied from the bottom and we use the prefix to change the properties for a higher view.",{"type":32,"tag":46,"props":18785,"children":18786},{},[18787],{"type":37,"value":18788},"For reference, the breakpoint table for the default tailwind settings:",{"type":32,"tag":1559,"props":18790,"children":18791},{},[18792,18808],{"type":32,"tag":1563,"props":18793,"children":18794},{},[18795],{"type":32,"tag":1567,"props":18796,"children":18797},{},[18798,18803],{"type":32,"tag":1571,"props":18799,"children":18800},{"align":18146},[18801],{"type":37,"value":18802},"Prefix",{"type":32,"tag":1571,"props":18804,"children":18805},{"align":1573},[18806],{"type":37,"value":18807},"Breakpoint",{"type":32,"tag":1588,"props":18809,"children":18810},{},[18811,18826,18841,18856,18872],{"type":32,"tag":1567,"props":18812,"children":18813},{},[18814,18821],{"type":32,"tag":1595,"props":18815,"children":18816},{"align":18146},[18817],{"type":32,"tag":117,"props":18818,"children":18819},{},[18820],{"type":37,"value":18753},{"type":32,"tag":1595,"props":18822,"children":18823},{"align":1573},[18824],{"type":37,"value":18825},">= 640px",{"type":32,"tag":1567,"props":18827,"children":18828},{},[18829,18836],{"type":32,"tag":1595,"props":18830,"children":18831},{"align":18146},[18832],{"type":32,"tag":117,"props":18833,"children":18834},{},[18835],{"type":37,"value":18759},{"type":32,"tag":1595,"props":18837,"children":18838},{"align":1573},[18839],{"type":37,"value":18840},">= 768px",{"type":32,"tag":1567,"props":18842,"children":18843},{},[18844,18851],{"type":32,"tag":1595,"props":18845,"children":18846},{"align":18146},[18847],{"type":32,"tag":117,"props":18848,"children":18849},{},[18850],{"type":37,"value":18765},{"type":32,"tag":1595,"props":18852,"children":18853},{"align":1573},[18854],{"type":37,"value":18855},">= 1024px",{"type":32,"tag":1567,"props":18857,"children":18858},{},[18859,18867],{"type":32,"tag":1595,"props":18860,"children":18861},{"align":18146},[18862],{"type":32,"tag":117,"props":18863,"children":18864},{},[18865],{"type":37,"value":18866},"xl:",{"type":32,"tag":1595,"props":18868,"children":18869},{"align":1573},[18870],{"type":37,"value":18871},">= 1280px",{"type":32,"tag":1567,"props":18873,"children":18874},{},[18875,18883],{"type":32,"tag":1595,"props":18876,"children":18877},{"align":18146},[18878],{"type":32,"tag":117,"props":18879,"children":18880},{},[18881],{"type":37,"value":18882},"2xl:",{"type":32,"tag":1595,"props":18884,"children":18885},{"align":1573},[18886],{"type":37,"value":18887},">= 1536px",{"type":32,"tag":46,"props":18889,"children":18890},{},[18891],{"type":37,"value":18892},"If you need, it is not a problem to add new media queries simply in the configuration, for example as follows:",{"type":32,"tag":7664,"props":18894,"children":18896},{"code":18895,"language":8581,"meta":7668},"module.exports = {\n  theme: {\n    extend: {\n      screens: {\n        '3xl': '1600px',\n      },\n    },\n  },\n}\n",[18897],{"type":32,"tag":7671,"props":18898,"children":18899},{},[18900],{"type":32,"tag":7664,"props":18901,"children":18902},{"__ignoreMap":8},[18903],{"type":37,"value":18895},{"type":32,"tag":39,"props":18905,"children":18906},{"id":17557},[18907],{"type":37,"value":17560},{"type":32,"tag":46,"props":18909,"children":18910},{},[18911,18913,18920],{"type":37,"value":18912},"It often happens that we repeat certain styles - for example buttons, headings, lists, inputs. To avoid repeating ourselves (",{"type":32,"tag":139,"props":18914,"children":18917},{":target":345,"href":18915,"rel":18916},"https://en.wikipedia.org/wiki/Don%27t_repeat_yourself",[347],[18918],{"type":37,"value":18919},"DRY",{"type":37,"value":18921},") we use components, which is nothing more than defining a new class as a combination of Tailwind classes.",{"type":32,"tag":46,"props":18923,"children":18924},{},[18925],{"type":37,"value":18926},"To give you an example, here's how:",{"type":32,"tag":7664,"props":18928,"children":18930},{"code":18929,"language":15193,"meta":7668},"@layer components {\n  .btn-primary {\n    @apply py-4 lg:py-5 px-4 px-6 lg:px-10 2xl:px-16 text-lg md:text-xl border border-primary text-primary bg-transparent;\n  }\n}\n",[18931],{"type":32,"tag":7671,"props":18932,"children":18933},{},[18934],{"type":32,"tag":7664,"props":18935,"children":18936},{"__ignoreMap":8},[18937],{"type":37,"value":18929},{"type":32,"tag":46,"props":18939,"children":18940},{},[18941],{"type":37,"value":18942},"This is how we have created the look for the button, but we are using Tailwind classes so we will be overwriting the defined colors, sizes, etc. The authors of the framework recommend to create components with discretion, because it should not go into writing classic CSS. Components should only be there to simplify repetitive properties.",{"type":32,"tag":39,"props":18944,"children":18946},{"id":18945},"reactions-to-new-frameworks",[18947],{"type":37,"value":18948},"Reactions to new frameworks",{"type":32,"tag":46,"props":18950,"children":18951},{},[18952,18954,18959,18961,18968],{"type":37,"value":18953},"Tailwind is a great tool, especially where we are encapsulating HTML code in components. I'm thinking of modern JS frameworks like ",{"type":32,"tag":82,"props":18955,"children":18956},{},[18957],{"type":37,"value":18958},"React, Vue, Angular, Svelte",{"type":37,"value":18960},". When writing such components we can use stylesheets straight away (faster creation, saves our head) and we don't have to worry so much that the list of classes is long and less fancy than, for example, the classic ",{"type":32,"tag":139,"props":18962,"children":18965},{":target":345,"href":18963,"rel":18964},"https://getbem.com/introduction/",[347],[18966],{"type":37,"value":18967},"BEM method",{"type":37,"value":18969},", because we then use the component as a single tag with no classes hiding inside.",{"type":32,"tag":46,"props":18971,"children":18972},{},[18973],{"type":37,"value":18974},"I'm thinking of the following Vue component button:",{"type":32,"tag":7664,"props":18976,"children":18979},{"code":18977,"language":18978,"meta":7668},"\u003Ctemplate>\n  \u003Cbutton \n    class=\"py-4 lg:py-5 px-6 lg:px-10 2xl:px-16 text-lg md:text-xl border border-primary text-primary bg-transparent\"\n    >\n    \u003Cslot />\n  \u003C/button>\n\u003C/template>\n","vue",[18980],{"type":32,"tag":7671,"props":18981,"children":18982},{},[18983],{"type":32,"tag":7664,"props":18984,"children":18985},{"__ignoreMap":8},[18986],{"type":37,"value":18977},{"type":32,"tag":46,"props":18988,"children":18989},{},[18990],{"type":37,"value":18991},"Use in the project:",{"type":32,"tag":7664,"props":18993,"children":18995},{"code":18994,"language":8580,"meta":7668},"\u003CButton>Button\u003C/Button>\n",[18996],{"type":32,"tag":7671,"props":18997,"children":18998},{},[18999],{"type":32,"tag":7664,"props":19000,"children":19001},{"__ignoreMap":8},[19002],{"type":37,"value":18994},{"type":32,"tag":46,"props":19004,"children":19005},{},[19006],{"type":37,"value":19007},"At the same time, the classes can be inserted as a computed variable and you can easily style the button according to the input props.",{"type":32,"tag":7664,"props":19009,"children":19011},{"code":19010,"language":18978,"meta":7668},"\u003Ctemplate>\n  \u003Cbutton class=\"py-4 lg:py-5 px-4 lg:px-10 2xl:px-16 text-lg md:text-xl\" :class=\"buttonClasses\">\n    \u003Cslot />\n  \u003C/button>\n\u003C/template>\n\u003Cscript>\nexport default {\n  props:['variant'],\n  computed: {\n    buttonClasses(){\n      switch(this.variant){\n        /* Main colour styles/variants */\n        case 'primary':\n        return 'border border-primary text-primary bg-transparent'\n\n        /* Secondary colour styles/variants */\n        case 'secondary':\n        return 'border border-secondary text-secondary bg-transparent'\n      }\n    }\n  }\n}\n\u003C/script>\n",[19012],{"type":32,"tag":7671,"props":19013,"children":19014},{},[19015],{"type":32,"tag":7664,"props":19016,"children":19017},{"__ignoreMap":8},[19018],{"type":37,"value":19010},{"type":32,"tag":39,"props":19020,"children":19021},{"id":774},[19022],{"type":37,"value":777},{"type":32,"tag":46,"props":19024,"children":19025},{},[19026,19028,19035],{"type":37,"value":19027},"Do you like this style of writing code? If so, you should study the ",{"type":32,"tag":139,"props":19029,"children":19032},{":target":345,"href":19030,"rel":19031},"https://tailwindcss.com/docs/installation",[347],[19033],{"type":37,"value":19034},"tailwind documentation",{"type":37,"value":19036}," and possibly incorporate it into your technology arsenal. I think it's definitely a revolutionary tool and worth getting familiar with.",{"type":32,"tag":46,"props":19038,"children":19039},{},[19040],{"type":37,"value":19041},"Interested in the article and have a question? Feel free to get in touch, I'd be happy to clarify or advise anything on this topic.",{"type":32,"tag":39,"props":19043,"children":19044},{"id":798},[19045],{"type":37,"value":6401},{"type":32,"tag":444,"props":19047,"children":19048},{},[19049,19059,19069,19079],{"type":32,"tag":448,"props":19050,"children":19051},{},[19052],{"type":32,"tag":139,"props":19053,"children":19056},{":target":345,"href":19054,"rel":19055},"https://tailwindcss.com/docs/customizing-spacing",[347],[19057],{"type":37,"value":19058},"Spacing in TailwindCSS",{"type":32,"tag":448,"props":19060,"children":19061},{},[19062],{"type":32,"tag":139,"props":19063,"children":19066},{":target":345,"href":19064,"rel":19065},"https://tailwindcss.com/docs/configuration",[347],[19067],{"type":37,"value":19068},"Explanation of tailwind.config.js",{"type":32,"tag":448,"props":19070,"children":19071},{},[19072],{"type":32,"tag":139,"props":19073,"children":19076},{":target":345,"href":19074,"rel":19075},"https://trends.builtwith.com/framework/Tailwind-CSS",[347],[19077],{"type":37,"value":19078},"Trend in TailwindCSS usage",{"type":32,"tag":448,"props":19080,"children":19081},{},[19082],{"type":32,"tag":139,"props":19083,"children":19085},{":target":345,"href":18614,"rel":19084},[347],[19086],{"type":37,"value":19087},"Plugin for VS Code",{"title":8,"searchDepth":862,"depth":862,"links":19089},[19090,19091,19092,19093,19094,19095,19096,19097,19098,19099,19100,19101],{"id":41,"depth":862,"text":44},{"id":17954,"depth":862,"text":17957},{"id":17974,"depth":862,"text":17977},{"id":18044,"depth":862,"text":18047},{"id":18066,"depth":862,"text":18069},{"id":18315,"depth":862,"text":18318},{"id":18636,"depth":862,"text":18639},{"id":18716,"depth":862,"text":18719},{"id":17557,"depth":862,"text":17560},{"id":18945,"depth":862,"text":18948},{"id":774,"depth":862,"text":777},{"id":798,"depth":862,"text":6401},"content:knowledge:tailwind-introduction.md","knowledge/tailwind-introduction.md",1775463423537]