<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ehsan Abedi</title>
    <description>The latest articles on DEV Community by Ehsan Abedi (@ehsanabedi_dev).</description>
    <link>https://dev.to/ehsanabedi_dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4174182%2F562fbc4c-d7a1-42cf-bf86-d2be1b9d730d.jpg</url>
      <title>DEV Community: Ehsan Abedi</title>
      <link>https://dev.to/ehsanabedi_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ehsanabedi_dev"/>
    <language>en</language>
    <item>
      <title>Building a Clinic Booking App in Flutter: Slots, Reminders and Privacy</title>
      <dc:creator>Ehsan Abedi</dc:creator>
      <pubDate>Thu, 05 Nov 2026 13:43:29 +0000</pubDate>
      <link>https://dev.to/ehsanabedi_dev/building-a-clinic-booking-app-in-flutter-slots-reminders-and-privacy-1gj2</link>
      <guid>https://dev.to/ehsanabedi_dev/building-a-clinic-booking-app-in-flutter-slots-reminders-and-privacy-1gj2</guid>
      <description>&lt;p&gt;Clinic booking apps look like a calendar with a "Book" button. In practice, the hard parts are elsewhere: how you model free time, how you stop two patients from taking the same slot, how reminders reach people in the right time zone, and how you keep health data out of places it shouldn't be.&lt;/p&gt;

&lt;p&gt;I'm a freelance Flutter and WordPress developer in Famagusta, North Cyprus, where many clinics treat local patients and visitors from abroad in the same week. Here is how I structure these apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model availability, not appointments
&lt;/h2&gt;

&lt;p&gt;Storing only appointments and "calculating" free time on the client gets messy fast. I keep three things on the server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Schedules&lt;/strong&gt;: each practitioner's working hours per weekday, per branch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exceptions&lt;/strong&gt;: holidays, sick days, a surgery that blocks the afternoon.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bookings&lt;/strong&gt;: practitioner, branch, start, end, treatment, status.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Free slots are generated on the server for a requested day: working hours minus exceptions minus existing bookings, cut into pieces of the treatment's duration plus a buffer. The app only displays what the server returns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Never trust the client with the last slot
&lt;/h2&gt;

&lt;p&gt;Two patients tapping the same 10:30 slot at the same moment is not a rare edge case on a Monday morning. The booking must be created in a transaction (or with a unique constraint on practitioner + start time) on the server. With Firestore, that means a transaction that reads the slot document and fails if it already exists. With Supabase / Postgres, an exclusion constraint on a time range does the job elegantly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;bookings&lt;/span&gt;
  &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;no_overlap&lt;/span&gt;
  &lt;span class="n"&gt;EXCLUDE&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;gist&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;practitioner_id&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tstzrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;starts_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ends_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'pending'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'confirmed'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The app then simply handles the error with "This time was just taken, here are the next free times".&lt;/p&gt;

&lt;h2&gt;
  
  
  Time zones: store UTC, show local
&lt;/h2&gt;

&lt;p&gt;Patients book from abroad before they travel. Store &lt;code&gt;starts_at&lt;/code&gt; in UTC, show it in the clinic's time zone with the zone name visible ("10:30, Cyprus time"), and schedule reminders from the server, not with local notifications calculated on the phone. A reminder the day before and a short one two hours before cuts no-shows noticeably.&lt;/p&gt;

&lt;h2&gt;
  
  
  Forms before the visit
&lt;/h2&gt;

&lt;p&gt;Intake forms are where privacy matters most. My rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Collect only what the clinic actually needs.&lt;/li&gt;
&lt;li&gt;Store answers server-side with strict access rules (staff role only), never in local storage or analytics events.&lt;/li&gt;
&lt;li&gt;No health details in push notification text: "You have an appointment tomorrow at 10:30" is fine, the treatment name is not.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  One codebase, two front doors
&lt;/h2&gt;

&lt;p&gt;New patients usually find the clinic through Google and book on the website, while returning patients use the app. Both talk to the same booking API, so the calendar is always the single source of truth. Flutter covers Android and iOS from one codebase, and the website can be WordPress with a small booking front-end calling the same endpoints.&lt;/p&gt;




&lt;p&gt;The business-side version, for clinic owners, is here: &lt;a href="https://ehsanabedi.com/clinic-appointment-app-north-cyprus/" rel="noopener noreferrer"&gt;Clinic Appointment App in North Cyprus: Fewer No-Shows, Happier Patients&lt;/a&gt;. How do you handle slot collisions in your booking apps?&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>firebase</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Taking Over an Unfinished Flutter App: My Audit Checklist (Security First)</title>
      <dc:creator>Ehsan Abedi</dc:creator>
      <pubDate>Tue, 03 Nov 2026 17:18:22 +0000</pubDate>
      <link>https://dev.to/ehsanabedi_dev/taking-over-an-unfinished-flutter-app-my-audit-checklist-security-first-4047</link>
      <guid>https://dev.to/ehsanabedi_dev/taking-over-an-unfinished-flutter-app-my-audit-checklist-security-first-4047</guid>
      <description>&lt;p&gt;"The app is 80% done, the previous developer stopped answering, can you finish it?" If you freelance long enough, you get this message. Sometimes the project is in good shape. Sometimes the last 20% is really 70%. And sometimes the repository itself is a risk to your own machine.&lt;/p&gt;

&lt;p&gt;I'm a freelance Flutter and WordPress developer in Famagusta, North Cyprus. This is the checklist I go through &lt;strong&gt;before&lt;/strong&gt; I quote, in the order I do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Don't run it yet: read it in isolation
&lt;/h2&gt;

&lt;p&gt;The first rule: a repository from a stranger is untrusted code. Fake "fix this bug in our repo" tasks are a known way to steal SSH keys, browser cookies and saved passwords from developers. So the first pass is reading, not running, and anything that executes happens in a throwaway environment (a GitHub Codespace on a separate account, or a VM), never on the laptop that holds my client logins.&lt;/p&gt;

&lt;p&gt;Things I read before any &lt;code&gt;flutter pub get&lt;/code&gt; or &lt;code&gt;gradle&lt;/code&gt; task:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;android/build.gradle&lt;/code&gt;, &lt;code&gt;android/app/build.gradle&lt;/code&gt; and &lt;code&gt;settings.gradle&lt;/code&gt;: anything that calls &lt;code&gt;exec&lt;/code&gt;, &lt;code&gt;commandLine&lt;/code&gt; or downloads scripts at build time.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;android/gradle/wrapper/gradle-wrapper.properties&lt;/code&gt; and the wrapper JAR: does the distribution URL point to &lt;code&gt;services.gradle.org&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ios/Podfile&lt;/code&gt; and any "Run Script" build phases in the Xcode project.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pubspec.yaml&lt;/code&gt;: git dependencies pointing to unknown forks, or path dependencies outside the repo.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.vscode/tasks.json&lt;/code&gt;: a task with &lt;code&gt;"runOn": "folderOpen"&lt;/code&gt; runs the moment you open the folder. Open unknown projects in Restricted Mode.&lt;/li&gt;
&lt;li&gt;Any &lt;code&gt;package.json&lt;/code&gt; (web tooling, Firebase functions): &lt;code&gt;preinstall&lt;/code&gt; / &lt;code&gt;postinstall&lt;/code&gt; scripts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only when that looks clean do I build, and still in the isolated environment. The APK it produces can then be tested on a spare phone or a cloud emulator.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Secure what belongs to the client
&lt;/h2&gt;

&lt;p&gt;Before touching code, I make sure the client actually owns their project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git repo in &lt;strong&gt;their&lt;/strong&gt; organisation, not the previous developer's personal account.&lt;/li&gt;
&lt;li&gt;Google Play Console and Apple Developer accounts in the client's name.&lt;/li&gt;
&lt;li&gt;Owner access to Firebase / Supabase / the backend, plus API keys for maps, payments and push notifications.&lt;/li&gt;
&lt;li&gt;The Figma file and assets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of this is missing, that is the first milestone, because without it nothing else is safe to build on.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Measure the real state
&lt;/h2&gt;

&lt;p&gt;Then the honest part. I run through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;flutter analyze&lt;/code&gt; and the number of warnings (and whether &lt;code&gt;analysis_options.yaml&lt;/code&gt; silences everything).&lt;/li&gt;
&lt;li&gt;Flutter / Dart SDK constraints vs. current stable, and &lt;code&gt;flutter pub outdated&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;State management: one consistent approach, or three mixed together?&lt;/li&gt;
&lt;li&gt;Secrets in source: API keys or passwords committed in Dart files or &lt;code&gt;google-services.json&lt;/code&gt; for the wrong project.&lt;/li&gt;
&lt;li&gt;Tests: any at all? Do they pass?&lt;/li&gt;
&lt;li&gt;Every screen on a real device: which features &lt;em&gt;work&lt;/em&gt;, and which only &lt;em&gt;look&lt;/em&gt; finished.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output is a short written report for the client in plain language: what works, what needs fixing, what is missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Finish, refactor or rebuild
&lt;/h2&gt;

&lt;p&gt;Most rescues end up in one of three buckets:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Clean structure, missing features&lt;/td&gt;
&lt;td&gt;Finish as is&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works, but features break each other&lt;/td&gt;
&lt;td&gt;Refactor key modules first, then finish&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weak foundation or very old SDK&lt;/td&gt;
&lt;td&gt;Rebuild, keeping designs, backend and data&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Rebuilding sounds expensive, but it is often cheaper than fighting a codebase where every change breaks two other screens.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Make the next handover painless
&lt;/h2&gt;

&lt;p&gt;Whatever happens, I set the project up so the client is never stuck again: weekly pushes to their repo, regular test builds they can install, store accounts and keys in their name, and a short README that explains how to build and release.&lt;/p&gt;




&lt;p&gt;I wrote a non-technical version of this for business owners here: &lt;a href="https://ehsanabedi.com/unfinished-app-rescue/" rel="noopener noreferrer"&gt;Unfinished App? How to Rescue a Half-Built App and Launch It&lt;/a&gt;. If you've taken over a project that turned out to be a trap, I'd love to hear what you check first.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>security</category>
      <category>dart</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Building a Car Rental Booking Site: Availability Is the Hard Part</title>
      <dc:creator>Ehsan Abedi</dc:creator>
      <pubDate>Wed, 28 Oct 2026 17:47:16 +0000</pubDate>
      <link>https://dev.to/ehsanabedi_dev/building-a-car-rental-booking-site-availability-is-the-hard-part-1fng</link>
      <guid>https://dev.to/ehsanabedi_dev/building-a-car-rental-booking-site-availability-is-the-hard-part-1fng</guid>
      <description>&lt;p&gt;A car rental website looks simple from the outside: pick dates, pick a car, pay. Under the hood, almost every problem comes back to one question: &lt;strong&gt;is this car actually free for these dates?&lt;/strong&gt; Get that wrong and you get double bookings, angry customers at the airport and a team that stops trusting the website.&lt;/p&gt;

&lt;p&gt;I'm a freelance WordPress and Flutter developer in Famagusta, North Cyprus, where a lot of small rental companies still take bookings over WhatsApp. Here is how I approach a booking site for them, from a developer's point of view.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model the fleet, not just "products"
&lt;/h2&gt;

&lt;p&gt;The tempting shortcut is to treat each car as a WooCommerce product with stock. It breaks quickly, because rental stock is about &lt;strong&gt;time&lt;/strong&gt;, not quantity. I usually model it like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Car group&lt;/strong&gt; (e.g. "Economy automatic"): what the customer books, with photos, seats, luggage and transmission.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vehicle&lt;/strong&gt;: the physical car with its plate, linked to a group, which can be blocked for service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Booking&lt;/strong&gt;: vehicle, pick-up datetime, return datetime, locations, extras, status.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Customers book a group and the system assigns a free vehicle. That way one car in the workshop doesn't make the whole group "sold out" on the website.&lt;/p&gt;

&lt;h2&gt;
  
  
  The overlap query
&lt;/h2&gt;

&lt;p&gt;Two bookings clash when one starts before the other ends and ends after the other starts. In SQL that is the classic interval check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;wp_rental_bookings&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;vehicle_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'confirmed'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'pending'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;pickup_at&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;   &lt;span class="c1"&gt;-- requested return&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;return_at&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;-- requested pick-up&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Small details that matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store datetimes in UTC and convert for display. Rental days cross midnight, and daylight saving changes will bite you otherwise.&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;buffer&lt;/strong&gt; after each return (cleaning, fuel, delivery time) before the car is free again.&lt;/li&gt;
&lt;li&gt;Count &lt;code&gt;pending&lt;/code&gt; bookings too, so two people paying at the same time can't both get the last car.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prevent the race condition
&lt;/h2&gt;

&lt;p&gt;Checking availability and inserting the booking are two steps. If two requests run between them, both pass the check. Wrap the check and the insert in a transaction and lock the vehicle row (&lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt; on InnoDB), or hold a short reservation that expires if payment isn't completed in, say, 15 minutes. It's boring code, and it's the code that saves the business.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prices are rules, not numbers
&lt;/h2&gt;

&lt;p&gt;Rental pricing is rarely "price × days". There are seasonal rates, discounts for longer rentals, a minimum number of days, one-way fees and extras like a child seat or full insurance. I keep these as small, testable rules and calculate the total on the server, never only in JavaScript. The customer sees the full breakdown before confirming, which also reduces the "why is it more at the desk?" conversations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Airport delivery and the booking form
&lt;/h2&gt;

&lt;p&gt;Many visitors here land at Ercan Airport or arrive at the port in Kyrenia. Delivery locations, a delivery fee and a flight number field belong in the booking form itself. A booking that arrives with all the details means one message for the staff instead of five.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speed and languages
&lt;/h2&gt;

&lt;p&gt;Most people book on a phone, often on roaming data, so the search results page has to be light: real image sizes, WebP, lazy-loading below the fold, and no heavy slider. On a four-language WordPress site I improved homepage PageSpeed from 51 to 75 on mobile and 81 to 97 on desktop without touching the design, mostly through this kind of asset discipline. For languages I use WPML with real URLs per language and &lt;code&gt;hreflang&lt;/code&gt;, so the German page can rank for German searches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where a Flutter app fits
&lt;/h2&gt;

&lt;p&gt;The website is for customers. The part rental companies love is a small &lt;strong&gt;staff app&lt;/strong&gt;: at pick-up and return the employee takes photos of the car, records fuel and mileage, and the customer signs on the screen. Built in Flutter, it runs on Android and iPhone and talks to the same WordPress database through the REST API, so bookings and check-ins stay in one place.&lt;/p&gt;

&lt;p&gt;I wrote a client-facing version of this, for rental company owners rather than developers, here: &lt;a href="https://ehsanabedi.com/car-rental-website-north-cyprus/" rel="noopener noreferrer"&gt;Car Rental Website Design in North Cyprus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;How do you handle availability in booking systems: database locks, short reservations, or something else?&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>webdev</category>
      <category>php</category>
      <category>flutter</category>
    </item>
    <item>
      <title>Building a Restaurant Website? Please Don't Ship the Menu as a PDF</title>
      <dc:creator>Ehsan Abedi</dc:creator>
      <pubDate>Tue, 27 Oct 2026 19:07:30 +0000</pubDate>
      <link>https://dev.to/ehsanabedi_dev/building-a-restaurant-website-please-dont-ship-the-menu-as-a-pdf-4dfa</link>
      <guid>https://dev.to/ehsanabedi_dev/building-a-restaurant-website-please-dont-ship-the-menu-as-a-pdf-4dfa</guid>
      <description>&lt;p&gt;Ask anyone how they choose a new restaurant or café and the answer is almost always the same three steps on a phone: look at the food, check the menu, find out how to get there. A restaurant website has one job, and that's making those three steps fast.&lt;/p&gt;

&lt;p&gt;I'm a freelance WordPress and Flutter developer in Famagusta, North Cyprus. Small local businesses are a big part of what I think about, and restaurant sites are where the same few technical decisions matter most. Here is how I'd build one, from a developer's point of view.&lt;/p&gt;

&lt;h2&gt;
  
  
  The menu is a web page, not a file
&lt;/h2&gt;

&lt;p&gt;The most common mistake is uploading the menu as a PDF or a photo of the printed card. On a phone, a PDF has to be downloaded, pinch-zoomed and scrolled sideways. Search engines also get very little from it, so a search like "breakfast in Famagusta" has nothing to match.&lt;/p&gt;

&lt;p&gt;In WordPress I build the menu as real content: a custom post type or a simple repeater with sections, dish names, short descriptions and dietary tags (vegan, gluten-free, spicy). Then:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The owner edits a dish from the dashboard in a minute, without asking a developer.&lt;/li&gt;
&lt;li&gt;The page is plain HTML, readable on any screen and fully indexable.&lt;/li&gt;
&lt;li&gt;If they still want a printable version, a "Download PDF" link sits &lt;strong&gt;under&lt;/strong&gt; the web menu, not instead of it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tell search engines it's a restaurant
&lt;/h2&gt;

&lt;p&gt;Local search is where restaurants live: "restaurant near me", "best coffee in Famagusta". Structured data helps Google connect the website with the place. A minimal &lt;code&gt;Restaurant&lt;/code&gt; block looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Restaurant"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Example Café"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"servesCuisine"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Mediterranean"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Breakfast"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PostalAddress"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"addressLocality"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Famagusta"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"addressCountry"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CY"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"telephone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+90 000 000 0000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"openingHours"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Mo-Sa 08:00-22:00"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hasMenu"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/menu/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"acceptsReservations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"True"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the part developers often skip: the name, address, phone number and opening hours must be &lt;strong&gt;exactly the same&lt;/strong&gt; on the website, the Google Business Profile and the social pages. Mismatched data makes Google trust all of it less, and it sends guests to a closed door.&lt;/p&gt;

&lt;h2&gt;
  
  
  Photos sell, and photos make it slow
&lt;/h2&gt;

&lt;p&gt;Food photos do more selling than any copy, and they're also the number one reason restaurant sites are slow. My routine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resize to the size actually displayed, compress, serve WebP with &lt;code&gt;srcset&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;loading="lazy"&lt;/code&gt; on everything below the fold, but &lt;strong&gt;not&lt;/strong&gt; on the hero image, because lazy-loading the largest image hurts LCP.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; so the layout doesn't jump while photos load.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On a four-language real estate site I work on, a colleague and I raised the median mobile PageSpeed score from 51 to 75 and desktop from 81 to 97 without changing the design. Most of that came from exactly this kind of image and asset discipline.&lt;/p&gt;

&lt;h2&gt;
  
  
  One obvious next step
&lt;/h2&gt;

&lt;p&gt;Every page should make the next action a single tap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tel:&lt;/code&gt; link for calling,&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;https://wa.me/&lt;/code&gt; link with a pre-filled message, which in North Cyprus is often how people actually book,&lt;/li&gt;
&lt;li&gt;a short reservation form, or a link to the delivery platform the place already uses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Online ordering with WooCommerce is possible, but I usually start with the simple version and add ordering only when the owner really needs it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Languages: real pages, not a translate button
&lt;/h2&gt;

&lt;p&gt;A restaurant in North Cyprus serves locals, visitors from Turkey, tourists from Europe and the UK, and a lot of international students. With WPML, each language gets its own URLs and &lt;code&gt;hreflang&lt;/code&gt; tags, so Google can show the Turkish menu to Turkish searches. An automatic "translate" widget doesn't do that.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I leave out
&lt;/h2&gt;

&lt;p&gt;Autoplay music, a long intro video, a newsletter pop-up in the first second, a slider with eight slides. Each one makes the site slower and pushes the menu further down. A small, fast site with a clear menu wins.&lt;/p&gt;

&lt;h2&gt;
  
  
  When an app makes sense
&lt;/h2&gt;

&lt;p&gt;Once a place has regular customers, a Flutter app can do what a website can't: a loyalty card on the phone, push notifications for a weekend event, fast reordering. The nice part is that the app can read the menu from the same WordPress site through the REST API, so the owner updates one place and both stay in sync. For most restaurants, though, the website and the Google profile come first.&lt;/p&gt;

&lt;p&gt;I wrote a longer, client-facing version of this for restaurant and café owners here: &lt;a href="https://ehsanabedi.com/restaurant-website-north-cyprus/" rel="noopener noreferrer"&gt;Restaurant &amp;amp; Café Website Design in North Cyprus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What's the worst restaurant-website pattern you keep running into?&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>webdev</category>
      <category>seo</category>
      <category>freelancing</category>
    </item>
    <item>
      <title>The Monthly WordPress Maintenance Checklist I Use for Small Business Sites</title>
      <dc:creator>Ehsan Abedi</dc:creator>
      <pubDate>Fri, 23 Oct 2026 14:13:28 +0000</pubDate>
      <link>https://dev.to/ehsanabedi_dev/the-monthly-wordpress-maintenance-checklist-i-use-for-small-business-sites-53cp</link>
      <guid>https://dev.to/ehsanabedi_dev/the-monthly-wordpress-maintenance-checklist-i-use-for-small-business-sites-53cp</guid>
      <description>&lt;p&gt;Most WordPress sites don't break in one dramatic moment. They decay quietly: a plugin stops getting updates, the cache stops working after an update, someone uploads a 6 MB photo, the contact form silently stops sending email. Nobody notices until a customer says "I sent you a message last week".&lt;/p&gt;

&lt;p&gt;I'm a freelance WordPress and Flutter developer in Famagusta, North Cyprus, and besides building sites I look after existing ones. This is the routine I actually use. It's boring on purpose: boring maintenance is what keeps sites from becoming emergencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before touching anything: a backup you can restore
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Full backup of &lt;strong&gt;files and database&lt;/strong&gt;, stored &lt;strong&gt;outside&lt;/strong&gt; the site's public folder.&lt;/li&gt;
&lt;li&gt;On some shared hosts &lt;code&gt;wp db export&lt;/code&gt; fails because &lt;code&gt;proc_open&lt;/code&gt; is disabled. &lt;code&gt;mysqldump&lt;/code&gt; with the credentials from &lt;code&gt;wp config get&lt;/code&gt; works instead.&lt;/li&gt;
&lt;li&gt;Once in a while, actually restore a backup to a staging copy. A backup you've never restored is a hope, not a backup.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Updates, one group at a time
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Core, theme and plugins, but not all blindly at once on a site that matters. Update, then check, then continue.&lt;/li&gt;
&lt;li&gt;After updating, check the pages that make money: home, the main service page, the contact form, checkout if there is one.&lt;/li&gt;
&lt;li&gt;Watch for side effects of cache plugins. On one site, a plugin action triggered a full cache purge, and the optimised CSS files briefly returned 404s, so the site loaded unstyled until the cache was rebuilt. Now I check that every CSS and JS file on key pages returns 200 after any update.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Security basics that catch most problems
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hidden login URL, two-factor authentication for every admin, limited login attempts.&lt;/li&gt;
&lt;li&gt;No public &lt;code&gt;readme.html&lt;/code&gt;, no &lt;code&gt;xmlrpc.php&lt;/code&gt; if nothing uses it, no user enumeration through &lt;code&gt;?author=1&lt;/code&gt; or &lt;code&gt;/wp-json/wp/v2/users&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Remove the WordPress version from the page source, including the &lt;code&gt;?ver=&lt;/code&gt; on core assets. It doesn't make the site invisible, but it stops making it easy for bots to match the site to a known vulnerable version.&lt;/li&gt;
&lt;li&gt;Review admin users and installed plugins. Every plugin is code you're trusting.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Speed that doesn't slide back
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Run PageSpeed on the home page and one inner page, and take the &lt;strong&gt;median of several runs&lt;/strong&gt;, because single runs vary a lot.&lt;/li&gt;
&lt;li&gt;Look for new full-size images, new third-party scripts and cache misses.&lt;/li&gt;
&lt;li&gt;On a four-language real estate site I work on, a colleague and I raised the median mobile PageSpeed score from 51 to 75 and desktop from 81 to 97 without changing the design. Monthly checks are what keep those numbers from drifting down.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Forms, links and search visibility
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Send a real test message through every form and confirm it arrives. Email deliverability breaks more often than people think.&lt;/li&gt;
&lt;li&gt;Check Google Search Console for new indexing problems, 404s and manual actions.&lt;/li&gt;
&lt;li&gt;Make sure the sitemap still lists the right pages and nothing important is accidentally &lt;code&gt;noindex&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Content: the part clients forget
&lt;/h2&gt;

&lt;p&gt;Maintenance isn't only technical. Old prices, last year's opening hours and a "new" offer from two seasons ago hurt trust as much as a slow page. A short monthly content check with the client is often the most valuable part of the routine.&lt;/p&gt;

&lt;h2&gt;
  
  
  When the client also has an app
&lt;/h2&gt;

&lt;p&gt;When a Flutter app reads its content from the same WordPress site through the REST API, one routine covers both: if a WordPress update changes an endpoint or a field, it gets caught before users of the app notice.&lt;/p&gt;

&lt;p&gt;I wrote the client-facing version of this, explaining what maintenance includes and when a business needs a monthly plan, here: &lt;a href="https://ehsanabedi.com/wordpress-maintenance-north-cyprus/" rel="noopener noreferrer"&gt;WordPress Maintenance in North Cyprus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What's on your maintenance checklist that isn't on mine?&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>webdev</category>
      <category>security</category>
      <category>freelancing</category>
    </item>
    <item>
      <title>Why I Still Recommend WordPress to Small Business Clients in 2026 (and When I Don't)</title>
      <dc:creator>Ehsan Abedi</dc:creator>
      <pubDate>Fri, 23 Oct 2026 11:38:22 +0000</pubDate>
      <link>https://dev.to/ehsanabedi_dev/why-i-still-recommend-wordpress-to-small-business-clients-in-2026-and-when-i-dont-18na</link>
      <guid>https://dev.to/ehsanabedi_dev/why-i-still-recommend-wordpress-to-small-business-clients-in-2026-and-when-i-dont-18na</guid>
      <description>&lt;p&gt;Every few months someone tells me WordPress is dead. Then a hotel, a clinic or a property agency asks me for a website, and I recommend WordPress again.&lt;/p&gt;

&lt;p&gt;I'm a freelance WordPress and Flutter developer in Famagusta, North Cyprus. My clients are mostly small businesses: they want a site that looks professional, loads fast, shows up on Google, and that they can update themselves without calling me for every price change. Here's my honest reasoning, including the cases where I suggest something else.&lt;/p&gt;

&lt;h2&gt;
  
  
  The client needs to own the content, not me
&lt;/h2&gt;

&lt;p&gt;The most important question I ask is: who will update this site after launch?&lt;/p&gt;

&lt;p&gt;For most small businesses the answer is "us". WordPress gives them a dashboard they understand in an afternoon. They change a price, add a photo or publish a news post, and the design stays consistent. That alone removes most of the "my developer disappeared" stories I hear from new clients.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design freedom without hand-coding every page
&lt;/h2&gt;

&lt;p&gt;With a page builder like Elementor, I can deliver a custom design and still hand over pages the client can edit. Everything is responsive by default, which matters when nearly all visitors arrive on a phone.&lt;/p&gt;

&lt;p&gt;I don't treat the page builder as an excuse to skip structure, though. Clean headings, sensible templates and reusable sections make the site easier to maintain and better for SEO.&lt;/p&gt;

&lt;h2&gt;
  
  
  SEO is solid out of the box
&lt;/h2&gt;

&lt;p&gt;WordPress outputs clean, crawlable HTML. Add an SEO plugin such as Rank Math and you control titles, descriptions, sitemaps and structured data per page. The platform won't rank a site on its own, but it never gets in the way of good content and internal linking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multilingual sites are where it really shines
&lt;/h2&gt;

&lt;p&gt;Many of my clients serve customers in several languages. WordPress with &lt;strong&gt;WPML&lt;/strong&gt; gives every language its own URLs, menus, forms and SEO settings, including right-to-left languages like Persian and Arabic.&lt;/p&gt;

&lt;p&gt;I work on a four-language real estate site (English, German, Turkish and Persian) built exactly this way. Doing that with a hosted site builder would be painful; with WPML it's a normal day's work.&lt;/p&gt;

&lt;h2&gt;
  
  
  "But WordPress is slow"
&lt;/h2&gt;

&lt;p&gt;It's slow when it's set up carelessly. With decent hosting, page caching, a CDN, properly sized images and some discipline about plugins, WordPress can score very well on PageSpeed.&lt;/p&gt;

&lt;p&gt;On that real estate site, a colleague and I raised the median mobile PageSpeed score from 51 to 75 and desktop from 81 to 97 without changing the design. The work was mostly boring: caching rules, image sizes, removing what wasn't needed and testing every change.&lt;/p&gt;

&lt;h2&gt;
  
  
  It grows with the business
&lt;/h2&gt;

&lt;p&gt;Forms, bookings, an online shop with WooCommerce, property listings with maps and search: there's a mature plugin for almost everything a small business asks for in year two. And because WordPress is open source, the client owns the site and can move hosts or developers whenever they want.&lt;/p&gt;

&lt;h2&gt;
  
  
  When I don't recommend WordPress
&lt;/h2&gt;

&lt;p&gt;Being honest about this is part of the job:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A one-page site that will never change.&lt;/strong&gt; A static site or a simple builder is cheaper to run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A web application, not a website.&lt;/strong&gt; Dashboards, complex user accounts and real-time features belong in a proper app framework.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A client who won't keep it updated.&lt;/strong&gt; WordPress needs updates and backups. If nobody will do that, I either include maintenance or suggest a hosted platform.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  WordPress and apps together
&lt;/h2&gt;

&lt;p&gt;The part I enjoy most: when a client also wants a mobile app, I build it in Flutter and let it read pages, products or listings from WordPress through the REST API. The client updates content once in a dashboard they already know, and it appears on the website and in the app.&lt;/p&gt;

&lt;p&gt;I wrote the client-facing version of this, with a short FAQ, here: &lt;a href="https://ehsanabedi.com/why-wordpress-for-business-websites/" rel="noopener noreferrer"&gt;Why WordPress Is Still the Best Choice for Business Websites&lt;/a&gt;. If you're a business looking for a site, you can see my &lt;a href="https://ehsanabedi.com/web-design/" rel="noopener noreferrer"&gt;web design services in North Cyprus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Fellow developers: what's your rule for when &lt;em&gt;not&lt;/em&gt; to use WordPress?&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>webdev</category>
      <category>freelancing</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How I Explain Cross-Platform vs Native to Clients (and Why I Usually Recommend Flutter)</title>
      <dc:creator>Ehsan Abedi</dc:creator>
      <pubDate>Wed, 21 Oct 2026 08:41:51 +0000</pubDate>
      <link>https://dev.to/ehsanabedi_dev/how-i-explain-cross-platform-vs-native-to-clients-and-why-i-usually-recommend-flutter-4ega</link>
      <guid>https://dev.to/ehsanabedi_dev/how-i-explain-cross-platform-vs-native-to-clients-and-why-i-usually-recommend-flutter-4ega</guid>
      <description>&lt;p&gt;Almost every first call about a new app reaches the same question within ten minutes: "Should we build two native apps, or one app for both phones?"&lt;/p&gt;

&lt;p&gt;I'm a freelance Flutter and WordPress developer in Famagusta, North Cyprus, and most of my clients are small and medium businesses, not tech companies. They don't need a lecture on rendering engines. They need a clear answer they can take back to their partner or their accountant. This is the explanation I've settled on, and the cases where I still say "go native".&lt;/p&gt;

&lt;h2&gt;
  
  
  The one-sentence version
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;native&lt;/strong&gt; app is built twice: once for Android (usually Kotlin) and once for iPhone (Swift). A &lt;strong&gt;cross-platform&lt;/strong&gt; app is built once, with a framework like &lt;strong&gt;Flutter&lt;/strong&gt; or React Native, and runs on both. Often on the web and desktop too.&lt;/p&gt;

&lt;p&gt;Everything else follows from "built once" versus "built twice".&lt;/p&gt;

&lt;h2&gt;
  
  
  What "built once" means for a business
&lt;/h2&gt;

&lt;p&gt;When I put it in business terms, the list is short:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Budget:&lt;/strong&gt; one codebase, one development process, one round of testing. Not two.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Launch day:&lt;/strong&gt; Android and iPhone users get the app on the same day, instead of one platform waiting for a second team.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency:&lt;/strong&gt; the brand, screens and features are identical whatever phone the customer has.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance:&lt;/strong&gt; a bug is fixed once, a feature is built once, then released everywhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Growth:&lt;/strong&gt; the same code can later become a web or desktop version.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Maintenance is the point that lands best. Clients think about the launch; I ask them to think about year two, when every change in a native setup has to be made, tested and released twice.&lt;/p&gt;

&lt;h2&gt;
  
  
  "But won't it feel slow?"
&lt;/h2&gt;

&lt;p&gt;This is the worry clients bring from older hybrid apps that were basically websites in a wrapper. I explain that Flutter is different: it compiles to native ARM code and draws its own UI with its own rendering engine, so scrolling, animations and transitions are smooth. For the kind of apps most businesses need (bookings, ordering, listings, internal tools, content), users simply can't tell.&lt;/p&gt;

&lt;p&gt;Then I show them something running on my own phone. A demo beats any argument.&lt;/p&gt;

&lt;h2&gt;
  
  
  When I still recommend native
&lt;/h2&gt;

&lt;p&gt;Being honest about the limits is what makes the recommendation believable. I suggest a fully native approach when:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The app depends on &lt;strong&gt;brand-new platform features on the day they're released&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;It's a &lt;strong&gt;demanding 3D game&lt;/strong&gt; or something close to the metal.&lt;/li&gt;
&lt;li&gt;The client &lt;strong&gt;already has strong native teams&lt;/strong&gt; and an existing native codebase.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For most other cases, Flutter can still call native code through platform channels when one specific feature needs it, so you keep one main codebase and still have an escape hatch.&lt;/p&gt;

&lt;h2&gt;
  
  
  The comparison table I send after the call
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Two native apps&lt;/th&gt;
&lt;th&gt;One cross-platform app&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Codebases&lt;/td&gt;
&lt;td&gt;Two&lt;/td&gt;
&lt;td&gt;One&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Budget&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;td&gt;Lower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Launch on Android &amp;amp; iOS&lt;/td&gt;
&lt;td&gt;Often at different times&lt;/td&gt;
&lt;td&gt;Same day&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Design consistency&lt;/td&gt;
&lt;td&gt;Harder to keep identical&lt;/td&gt;
&lt;td&gt;Identical by default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance&lt;/td&gt;
&lt;td&gt;Every change done twice&lt;/td&gt;
&lt;td&gt;Every change done once&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It's deliberately simple. The client will forward it to someone, and it has to make sense without me in the room.&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions clients ask next
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"Is it harder to publish?"&lt;/strong&gt; No. It goes to Google Play and the App Store as two normal apps, built from the same project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Can we add native parts later?"&lt;/strong&gt; Yes, small native pieces can be added for very specific features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Will users notice?"&lt;/strong&gt; With a well-built Flutter app, usually not.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bonus: the website and the app together
&lt;/h2&gt;

&lt;p&gt;Most of my clients also need a website, because customers find them on Google before they ever install an app. When the same developer builds the WordPress site and the Flutter app, the app can read listings, products or bookings from the site's REST API. Content is updated once and appears in both places.&lt;/p&gt;

&lt;p&gt;I wrote the client-facing version of this guide, with a short FAQ, here: &lt;a href="https://ehsanabedi.com/cross-platform-vs-native-apps/" rel="noopener noreferrer"&gt;Cross-Platform vs Native Apps: Why Build Once for Android and iOS&lt;/a&gt;. If you're a business planning an app, you can see my &lt;a href="https://ehsanabedi.com/app-developer/" rel="noopener noreferrer"&gt;Flutter app development services in North Cyprus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Fellow developers: how do you explain this trade-off to non-technical clients? I'd love to steal a better analogy.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>crossplatform</category>
      <category>beginners</category>
    </item>
    <item>
      <title>When I Tell a Client to Hire an Agency Instead of Me (a Freelance Flutter Developer's Honest Checklist)</title>
      <dc:creator>Ehsan Abedi</dc:creator>
      <pubDate>Tue, 20 Oct 2026 09:41:29 +0000</pubDate>
      <link>https://dev.to/ehsanabedi_dev/when-i-tell-a-client-to-hire-an-agency-instead-of-me-a-freelance-flutter-developers-honest-3583</link>
      <guid>https://dev.to/ehsanabedi_dev/when-i-tell-a-client-to-hire-an-agency-instead-of-me-a-freelance-flutter-developers-honest-3583</guid>
      <description>&lt;p&gt;Almost every business owner who wants an app asks the same question early on: should I hire a freelance developer or an agency? Most articles on this are written by one side trying to win the deal.&lt;/p&gt;

&lt;p&gt;I'm a freelance Flutter and WordPress developer in Famagusta, North Cyprus. I'd rather lose a project at the first call than win one I shouldn't be doing alone. So here's the checklist I actually use, from the developer's side of the table. If you freelance too, I think being this open is one of the best ways to earn trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Projects where one developer is the right fit
&lt;/h2&gt;

&lt;p&gt;With Flutter, a single codebase becomes a native app for Android and iPhone, which changes the maths for small and medium projects. These are well within reach of one experienced developer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Booking apps&lt;/strong&gt; for clinics, salons and gyms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ordering apps&lt;/strong&gt; for restaurants and cafés&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Property apps&lt;/strong&gt; for real estate agencies, reading listings from the company website&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internal tools&lt;/strong&gt; for a team: schedules, checklists, simple dashboards&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content apps&lt;/strong&gt; that mirror a WordPress site through the REST API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What the client gets: direct contact with the person writing the code, quick decisions, lower overheads and one person who knows the app inside out after launch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Projects where I recommend an agency
&lt;/h2&gt;

&lt;p&gt;I say this openly when one of these applies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Several apps that must ship at the same time&lt;/strong&gt;, for example a marketplace with separate apps for customers, drivers and partners, all on a tight deadline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Many parallel workstreams&lt;/strong&gt;: heavy custom backend, admin panel, three platforms and a web app, all at once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The company needs a formal supplier&lt;/strong&gt; with many staff, insurance and procurement paperwork.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;24/7 operational support&lt;/strong&gt; with guaranteed response times from day one.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of this means a freelancer can't contribute. Often the honest answer is "start with an agency for version one, or let me build a focused first version and grow from there".&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions I encourage clients to ask me (and any developer)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Can I see apps or app concepts you designed and built?&lt;/li&gt;
&lt;li&gt;How will the app run on both Android and iPhone?&lt;/li&gt;
&lt;li&gt;Which backend stores the data: Firebase, my website or something else?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Will I own the code repository and the App Store and Google Play accounts?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;How do we test before release?&lt;/li&gt;
&lt;li&gt;What happens after launch, when Android and iOS update?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The ownership question is the one that removes most of the "bus factor" risk of hiring one person. If the client owns the repo and the store accounts, and the code is clean and documented, any qualified Flutter developer can continue the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost: features matter more than who builds it
&lt;/h2&gt;

&lt;p&gt;The price of an app depends far more on what it has to do than on who writes it: number of screens, logins, payments, languages, integrations. A freelancer usually has lower overheads; an agency includes the cost of a bigger team and more process. Both can be fair.&lt;/p&gt;

&lt;h2&gt;
  
  
  The website and the app from one person
&lt;/h2&gt;

&lt;p&gt;This is the part I enjoy most. When the same developer builds the WordPress site and the Flutter app, the app can read listings, products or bookings straight from the site. The client updates content once and it appears everywhere. Two projects become one system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters if you freelance
&lt;/h2&gt;

&lt;p&gt;Telling a client "this one is too big for me alone" feels like losing work. In my experience it does the opposite: clients remember who was honest, and they come back for the projects that do fit.&lt;/p&gt;

&lt;p&gt;I wrote a client-facing version of this guide, with a short FAQ, here: &lt;a href="https://ehsanabedi.com/app-developer-or-agency/" rel="noopener noreferrer"&gt;Freelance App Developer or Agency: Which Is Right for Your Business?&lt;/a&gt;. If you're a business looking for help, you can see my &lt;a href="https://ehsanabedi.com/app-developer/" rel="noopener noreferrer"&gt;app development services in North Cyprus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Freelancers: where do you draw the line between "I can do this" and "you need a team"?&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>freelancing</category>
      <category>mobile</category>
      <category>career</category>
    </item>
    <item>
      <title>The 10 Questions Clients Should Ask Before Hiring a Web Designer (and How I Answer Them as a WordPress Developer)</title>
      <dc:creator>Ehsan Abedi</dc:creator>
      <pubDate>Mon, 19 Oct 2026 19:00:17 +0000</pubDate>
      <link>https://dev.to/ehsanabedi_dev/the-10-questions-clients-should-ask-before-hiring-a-web-designer-and-how-i-answer-them-as-a-512j</link>
      <guid>https://dev.to/ehsanabedi_dev/the-10-questions-clients-should-ask-before-hiring-a-web-designer-and-how-i-answer-them-as-a-512j</guid>
      <description>&lt;p&gt;Most small business owners hire a web designer once every few years. They don't know which questions matter, so they compare quotes by price and by how nice the homepage mockup looks. Then, six months later, they find out the site is slow, they can't edit it, and nobody set up Search Console.&lt;/p&gt;

&lt;p&gt;I'm a WordPress and Flutter developer in Famagusta, North Cyprus. When I talk to a new client, I try to answer the questions they &lt;em&gt;should&lt;/em&gt; be asking, even if they don't ask them. Here are the ten I think matter most, written from the developer's side of the table. If you freelance or run a small studio, having a clear answer to each one is also a good way to stand out from cheaper quotes.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. "Can I see live sites you built and still maintain?"
&lt;/h2&gt;

&lt;p&gt;Screenshots in a portfolio prove very little. A live site proves you can ship, and a site you still maintain proves it held up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I answer:&lt;/strong&gt; I send live links and suggest the client opens them on their own phone, on mobile data. If a site is slow or the contact button is hard to find, they'll notice in ten seconds, and that's fair.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. "How will you learn about my business?"
&lt;/h2&gt;

&lt;p&gt;If the first meeting is about colours and fonts, something is wrong. The first meeting should be about customers: who they are, what language they search in, and what you want them to do on the site (call, send a WhatsApp message, book, buy).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I answer:&lt;/strong&gt; I start with a short list of questions about customers and goals, and I only talk about design after that.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. "Which platform will you use, and will I own everything?"
&lt;/h2&gt;

&lt;p&gt;This is the question that protects the client most. Who owns the domain? Who has the hosting login? Can they move the site to another provider without you?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I answer:&lt;/strong&gt; I build on WordPress, the domain and hosting are registered in the client's name, and they get admin access from day one. If we ever stop working together, they can take the site anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. "Will it be designed for phones first?"
&lt;/h2&gt;

&lt;p&gt;Most visitors arrive on a phone, so the mobile layout should be planned first, not patched at the end.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I answer:&lt;/strong&gt; I show the mobile version during the design phase and ask the client to test it on their own device before launch, not only in a desktop browser with DevTools.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. "How fast will it load?"
&lt;/h2&gt;

&lt;p&gt;Speed affects both visitors and rankings, but it's rarely in the brief. A good developer brings it up without being asked: image sizes and formats, caching, render-blocking scripts, and Core Web Vitals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I answer:&lt;/strong&gt; I explain what we'll measure and use real numbers from my own work. On a four-language real estate site I work on, a colleague and I raised the median mobile PageSpeed score from 51 to 75 and the desktop score from 81 to 97. I always say that the score is a median of several runs, because a single run varies a lot.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. "What do you do for SEO?"
&lt;/h2&gt;

&lt;p&gt;"SEO" in a quote can mean anything. Clients should ask what exactly is included on launch day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I answer:&lt;/strong&gt; titles and meta descriptions per page, one H1 per page, clean headings, structured data (Person or Organization, Breadcrumbs, FAQ where it fits), an XML sitemap, robots.txt, and the site verified in Google Search Console with the sitemap submitted. That's the foundation. Rankings still depend on content, links and time, and I say that too.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. "Can the site speak my customers' languages?"
&lt;/h2&gt;

&lt;p&gt;In a place like North Cyprus, one small business can get messages in English, Turkish, German, Russian and Persian in the same week. Multilingual is normal here, not a luxury.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I answer:&lt;/strong&gt; each language gets its own URL and its own SEO, with proper hreflang tags. If the client needs Persian or Arabic, I make sure the right-to-left layout is designed and tested, not just mirrored. I use WPML for this on WordPress.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. "Can I update it myself?"
&lt;/h2&gt;

&lt;p&gt;If the client has to email you to change a price, both sides lose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I answer:&lt;/strong&gt; at handover I run a short training session and leave a simple written guide for the most common edits: text, photos, prices, new blog posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. "How does the project run, step by step?"
&lt;/h2&gt;

&lt;p&gt;A clear process protects both the client and the developer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I answer:&lt;/strong&gt; a written proposal with pages and features, a design the client approves before building starts, preview links during development, a launch checklist, and payments split into stages that follow those steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. "What happens after launch?"
&lt;/h2&gt;

&lt;p&gt;Websites need updates, backups and security fixes. Somebody has to own that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I answer:&lt;/strong&gt; I say clearly who handles updates and backups, how fast I respond, and what ongoing care costs, before the project starts, not after the first plugin conflict.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: "Can you also build the app later?"
&lt;/h2&gt;

&lt;p&gt;Many businesses start with a website and add a mobile app later for repeat customers. If the same developer can plan both, the app can read its content straight from the WordPress REST API, so there's one place to manage listings, menus or prices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I answer:&lt;/strong&gt; that's exactly why I work with both WordPress and Flutter. The website and the app share content and design instead of becoming two separate projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters for developers
&lt;/h2&gt;

&lt;p&gt;If you're competing with cheaper quotes, these answers are your advantage. Clients rarely know to ask about ownership, speed or Search Console, but once you explain them in plain language, the conversation stops being about price.&lt;/p&gt;

&lt;p&gt;I wrote a client-facing version of this checklist, with a short FAQ, here: &lt;a href="https://ehsanabedi.com/how-to-choose-a-web-designer/" rel="noopener noreferrer"&gt;How to Choose a Web Designer: 10 Questions to Ask Before You Hire&lt;/a&gt;. If you're a business looking for help, you can see my &lt;a href="https://ehsanabedi.com/web-design/" rel="noopener noreferrer"&gt;web design services in North Cyprus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What would you add to this list? I'm curious which question your clients ask most often.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>webdev</category>
      <category>freelancing</category>
      <category>career</category>
    </item>
    <item>
      <title>One Set of Listings, Two Front Ends: Planning a Real Estate App with Flutter and the WordPress REST API</title>
      <dc:creator>Ehsan Abedi</dc:creator>
      <pubDate>Sun, 18 Oct 2026 14:42:10 +0000</pubDate>
      <link>https://dev.to/ehsanabedi_dev/one-set-of-listings-two-front-ends-planning-a-real-estate-app-with-flutter-and-the-wordpress-rest-39m</link>
      <guid>https://dev.to/ehsanabedi_dev/one-set-of-listings-two-front-ends-planning-a-real-estate-app-with-flutter-and-the-wordpress-rest-39m</guid>
      <description>&lt;p&gt;Most real estate agencies already have a WordPress website full of listings. When they ask for an app, the expensive mistake is building a second backend with its own database, its own admin panel and its own copy of every property. Six months later, the website and the app show different prices.&lt;/p&gt;

&lt;p&gt;I'm a WordPress and Flutter developer in Famagusta, North Cyprus, and I work on a multilingual real estate website (English, German, Turkish, Persian). These are the notes I use when planning how an app should sit next to a site like that. The short version: &lt;strong&gt;keep WordPress as the single source of truth and let Flutter read from it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Expose the listings through the REST API
&lt;/h2&gt;

&lt;p&gt;If properties are a custom post type, make sure it's available in the REST API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;register_post_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'property'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'public'&lt;/span&gt;       &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'show_in_rest'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;// exposes /wp-json/wp/v2/property&lt;/span&gt;
    &lt;span class="s1"&gt;'rest_base'&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'property'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'supports'&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'editor'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'thumbnail'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'custom-fields'&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fields like price, bedrooms and area usually live in post meta or ACF. Register only the fields the app actually needs (&lt;code&gt;register_rest_field&lt;/code&gt; or &lt;code&gt;register_post_meta&lt;/code&gt; with &lt;code&gt;show_in_rest&lt;/code&gt;), so you don't leak internal data and responses stay small.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Keep the Flutter side boring and testable
&lt;/h2&gt;

&lt;p&gt;A clean split makes the app easy to change later:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data layer:&lt;/strong&gt; a repository that calls &lt;code&gt;/wp-json/wp/v2/property&lt;/code&gt; and maps JSON to a &lt;code&gt;Property&lt;/code&gt; model&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain layer:&lt;/strong&gt; plain Dart entities and use cases (search, favourite, request a viewing)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Presentation:&lt;/strong&gt; BLoC per screen (list, details, favourites)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PropertyRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;PropertyRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;_client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;_baseUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;_baseUrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'en'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Uri&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;$_baseUrl&lt;/span&gt;&lt;span class="s"&gt;/wp-json/wp/v2/property?page=&lt;/span&gt;&lt;span class="si"&gt;$page&lt;/span&gt;&lt;span class="s"&gt;&amp;amp;per_page=20&amp;amp;lang=&lt;/span&gt;&lt;span class="si"&gt;$lang&lt;/span&gt;&lt;span class="s"&gt;&amp;amp;_embed'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Failed to load properties (&lt;/span&gt;&lt;span class="si"&gt;${res.statusCode}&lt;/span&gt;&lt;span class="s"&gt;)'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jsonDecode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Property&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;_embed&lt;/code&gt; pulls in the featured image in the same request. Use pagination from day one: real agencies have hundreds of listings.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Multilingual and right-to-left from the start
&lt;/h2&gt;

&lt;p&gt;International buyers expect their own language. Two things save a lot of pain later:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Content language&lt;/strong&gt; comes from WordPress. With WPML, each translation is its own post, so the app requests the right language (the &lt;code&gt;lang&lt;/code&gt; parameter above, or a language-specific endpoint depending on your setup).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI language&lt;/strong&gt; lives in Flutter's localisation files. For Persian and Arabic, Flutter flips the layout to right-to-left automatically when the locale changes. Still test every screen in RTL: icons with a direction, price formats and mixed English/Persian text are where bugs hide.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Features buyers actually use
&lt;/h2&gt;

&lt;p&gt;For a first version, these are the features I would prioritise:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search with filters (area, type, bedrooms, price, sea view, pool)&lt;/li&gt;
&lt;li&gt;Map view with pins along the coast&lt;/li&gt;
&lt;li&gt;Property pages with a gallery, key facts and a floor plan&lt;/li&gt;
&lt;li&gt;Favourites and sharing a listing on WhatsApp&lt;/li&gt;
&lt;li&gt;A one-tap viewing request and phone/WhatsApp buttons&lt;/li&gt;
&lt;li&gt;Alerts when a new listing matches a saved search&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Video tours, side-by-side comparison, buyer accounts and an agent area can come later, once people are using the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Notifications without a second database
&lt;/h2&gt;

&lt;p&gt;Saved-search alerts sound like they need a big backend. A simple approach: store each saved search (filters plus the device token) in a small table or service, and run a scheduled job when a new property is published that checks for matches and sends a push notification. The listings themselves still live only in WordPress.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Performance on both sides
&lt;/h2&gt;

&lt;p&gt;The app is only as fast as the API behind it. Cache REST responses on the server, return only the fields you need, and serve images as WebP in sensible sizes. On the website I work on, a colleague and I raised the median mobile PageSpeed score from 51 to 75, and most of that came from the same basics: caching, lighter images and fewer heavy scripts.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Can the app use listings from an existing WordPress site?&lt;/strong&gt;&lt;br&gt;
In most cases, yes. Once the post type and fields are exposed in the REST API, the app reads the same data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I still need the website if I have an app?&lt;/strong&gt;&lt;br&gt;
Yes. The website brings new buyers in from Google. The app keeps returning buyers close.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Android and iPhone?&lt;/strong&gt;&lt;br&gt;
One Flutter codebase covers both, which keeps development and maintenance lower than building two separate apps.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://ehsanabedi.com/real-estate-app-north-cyprus/" rel="noopener noreferrer"&gt;ehsanabedi.com&lt;/a&gt;. You can see a &lt;a href="https://ehsanabedi.com/portfolio-archive/real-estate-app-concept/" rel="noopener noreferrer"&gt;real estate app concept&lt;/a&gt; in my portfolio.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>wordpress</category>
      <category>mobile</category>
      <category>api</category>
    </item>
    <item>
      <title>8 Things a Hotel or Villa Website Needs Before Guests Will Book (A Developer's Checklist)</title>
      <dc:creator>Ehsan Abedi</dc:creator>
      <pubDate>Sun, 18 Oct 2026 11:15:35 +0000</pubDate>
      <link>https://dev.to/ehsanabedi_dev/8-things-a-hotel-or-villa-website-needs-before-guests-will-book-a-developers-checklist-3ide</link>
      <guid>https://dev.to/ehsanabedi_dev/8-things-a-hotel-or-villa-website-needs-before-guests-will-book-a-developers-checklist-3ide</guid>
      <description>&lt;p&gt;Most guests book their stay from a phone. They often scroll on mobile data, sometimes from an airport gate, and they make up their mind in a few seconds. A hospitality website gets judged by different rules than a portfolio or a company page: it either answers "what will I get, and how do I book it?" right away, or the visitor goes back to a booking platform.&lt;/p&gt;

&lt;p&gt;I am a WordPress and Flutter developer in Famagusta, North Cyprus. Many of the small hotels, villas and holiday rentals around me depend on summer visitors from Turkey, the UK, Germany and Russia. Here is the checklist I use when I build or review a hospitality site. If you build sites for clients in tourism, most of it applies wherever you are.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Photos that sell the stay, without killing speed
&lt;/h2&gt;

&lt;p&gt;People decide to book by looking. Large, bright photos of the rooms, the pool and the view do more than any paragraph. The technical part is keeping them fast:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;serve WebP at the size each breakpoint actually needs&lt;/li&gt;
&lt;li&gt;lazy-load everything below the first screen&lt;/li&gt;
&lt;li&gt;use a gallery that swipes properly on touch screens&lt;/li&gt;
&lt;li&gt;put the most convincing photo first, not the reception desk&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. One page per room or villa
&lt;/h2&gt;

&lt;p&gt;Each unit needs its own URL with the essentials visible at a glance: number of guests, beds, bathrooms, distance to the beach, what is included and the price per night or per season. If you can, add an availability calendar. If you can't, a clear "Check availability" button still saves a lot of back-and-forth over email.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. A direct booking path on every screen
&lt;/h2&gt;

&lt;p&gt;Booking platforms bring visibility, but they take a commission on every booking, and the guest relationship belongs to them. The website's job is to turn returning guests and Google visitors into direct bookings. That means either a booking request form or a connected booking engine, plus one-tap WhatsApp, phone and email buttons. On mobile, a sticky contact bar works well.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Every language in its own URL
&lt;/h2&gt;

&lt;p&gt;A Turkish family, a British couple and a German group all trust a booking page more in their own language. For SEO, give each language its own address (&lt;code&gt;/de/&lt;/code&gt;, &lt;code&gt;/tr/&lt;/code&gt; and so on), use proper &lt;code&gt;hreflang&lt;/code&gt;, and translate menus, forms and confirmation emails as well as the page text. A plugin like WPML handles this in WordPress. Remember that right-to-left languages need their own layout checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Location and local context
&lt;/h2&gt;

&lt;p&gt;Guests want to know where they'll actually be: how far the beach is, how to get there from the airport, and what's within walking distance. An embedded map, simple directions and a short area guide keep visitors on your site while they plan. They also give Google more local signals to work with.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Trust details
&lt;/h2&gt;

&lt;p&gt;Show reviews from past guests and link to your profiles on review platforms. Publish check-in times, cancellation rules and house rules, and show a licence number, a real address and the people behind the business. For a small hotel, this is what makes booking directly feel safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Speed on mobile data
&lt;/h2&gt;

&lt;p&gt;A heavy theme loses guests before the first photo loads. Page caching, optimised images, fewer third-party scripts and lean CSS let a site look luxurious and still feel fast. On a multilingual WordPress site I helped optimise, the median mobile PageSpeed score went from 51 to 75 on the same page. That shows how much room for improvement most sites have.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Local SEO for every season
&lt;/h2&gt;

&lt;p&gt;Write pages for the searches guests actually type, like "villa with private pool in Kyrenia" or "beach hotel near Famagusta". Add &lt;code&gt;Hotel&lt;/code&gt; / &lt;code&gt;LodgingBusiness&lt;/code&gt; structured data and keep publishing seasonal content, so you show up before travellers settle on a platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  When an app is worth it
&lt;/h2&gt;

&lt;p&gt;For a larger hotel or a group of villas, a companion app can add digital check-in, room-service requests, local recommendations and return-visit offers. With Flutter, one codebase can share content and APIs with the website, which keeps both in sync.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can the website take bookings directly?
&lt;/h3&gt;

&lt;p&gt;Yes. It can send booking requests to the owner, show live availability or connect to a booking engine. It depends on how many units there are and how many bookings come in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I still need booking platforms?
&lt;/h3&gt;

&lt;p&gt;Usually, yes, because they bring visibility. Your own site works alongside them and turns returning guests into direct bookings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can the owner update prices and photos?
&lt;/h3&gt;

&lt;p&gt;With WordPress and Elementor, yes. Seasonal prices, photos and offers can be edited in every language without calling a developer.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://ehsanabedi.com/hotel-villa-website-design-north-cyprus/" rel="noopener noreferrer"&gt;ehsanabedi.com&lt;/a&gt;. Running a hotel or villa in North Cyprus? See my &lt;a href="https://ehsanabedi.com/web-design/" rel="noopener noreferrer"&gt;web design services&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>webdev</category>
      <category>ux</category>
      <category>seo</category>
    </item>
    <item>
      <title>What Really Decides the Cost of a WordPress Website (8 Factors I Explain to Every Client)</title>
      <dc:creator>Ehsan Abedi</dc:creator>
      <pubDate>Sat, 17 Oct 2026 09:29:05 +0000</pubDate>
      <link>https://dev.to/ehsanabedi_dev/what-really-decides-the-cost-of-a-wordpress-website-8-factors-i-explain-to-every-client-47hh</link>
      <guid>https://dev.to/ehsanabedi_dev/what-really-decides-the-cost-of-a-wordpress-website-8-factors-i-explain-to-every-client-47hh</guid>
      <description>&lt;p&gt;"How much does a website cost?" is the first question almost every client asks me. It is a fair question, but there is no honest one-number answer. A one-page site for a new café and a multilingual property portal with hundreds of listings are both "websites", yet they are completely different projects.&lt;/p&gt;

&lt;p&gt;I am a web designer and WordPress developer based in Famagusta, North Cyprus. Here is the breakdown I walk clients through, so they understand what they are paying for and can compare quotes fairly. If you are a developer, it may also help you explain your own pricing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a website has no fixed price
&lt;/h2&gt;

&lt;p&gt;A website is closer to a tailored suit than a product on a shelf. One business wants phone calls, another wants online bookings, a third needs four languages for international buyers. The price follows the work, so the clearer the goals, the clearer the quote.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 8 factors that shape the cost
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Pages and sections.&lt;/strong&gt; A focused business site usually needs a home page, an about page, one page per main service and a contact page. Every extra page adds design, content and testing time. Start with what customers really need; add the rest later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Theme or custom design.&lt;/strong&gt; A good WordPress theme adapted to the brand is the fastest route to a professional look. A fully custom design takes longer, but pays off in crowded markets like real estate or hospitality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Languages.&lt;/strong&gt; In North Cyprus, many businesses serve customers in English, Turkish, German, Russian or Persian. Every language means translated pages, menus and forms, and right-to-left languages need their own layout checks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Features and integrations.&lt;/strong&gt; A contact form or WhatsApp button is simple. Booking, property search filters, an online shop, payments or a CRM connection need more planning and testing. Split the list into "day one" and "later".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Content.&lt;/strong&gt; Ready text and photos make a project move faster. If they need writing, translating or photographing, that belongs in the plan, because content is what turns visitors into enquiries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Speed and SEO setup.&lt;/strong&gt; Titles, structured data, a sitemap, Search Console and performance work decide whether anyone finds the site and whether it opens quickly on a phone. I treat this as part of the build, not an extra.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Hosting, domain and email.&lt;/strong&gt; Small yearly costs, but quality matters. Cheap, slow hosting can undo all the work that went into the design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Care after launch.&lt;/strong&gt; WordPress core, plugins and content need regular updates and backups. A simple care plan keeps the site secure and makes small changes easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  One-off costs vs yearly costs
&lt;/h2&gt;

&lt;p&gt;I always split the budget in two:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One-off:&lt;/strong&gt; planning, design, build, content and launch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yearly:&lt;/strong&gt; domain, hosting, email and care&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Knowing both from the start means no surprises, and it makes quotes from different people easy to compare.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to get an accurate quote
&lt;/h2&gt;

&lt;p&gt;Before the first call, prepare:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What the site should achieve: calls, messages, bookings, sales or trust&lt;/li&gt;
&lt;li&gt;A rough list of pages and languages&lt;/li&gt;
&lt;li&gt;Two or three websites you like, and why&lt;/li&gt;
&lt;li&gt;Features needed now vs later&lt;/li&gt;
&lt;li&gt;Your ideal launch date&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Keeping the budget under control
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Launch the core first&lt;/strong&gt;, then add pages in a second phase&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose a platform you can edit yourself&lt;/strong&gt; (WordPress + Elementor), so small text and price changes cost nothing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reuse what works&lt;/strong&gt;: good photos, texts and logos can often be refreshed instead of recreated&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redesign instead of rebuilding&lt;/strong&gt; when the current structure is sound&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is a cheap website a bad idea?
&lt;/h3&gt;

&lt;p&gt;Not necessarily. A simple site is a great start if it is fast, works on phones and is set up for Google. The expensive mistake is a site that looks fine but never brings in enquiries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I pay every year?
&lt;/h3&gt;

&lt;p&gt;The design and build are paid once. Domain, hosting, email and care are the yearly costs that keep the site online, fast and secure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I add languages or features later?
&lt;/h3&gt;

&lt;p&gt;Yes. A WordPress site on a clean structure can grow with the business, so languages, booking or a shop can come when you are ready.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://ehsanabedi.com/website-cost-north-cyprus/" rel="noopener noreferrer"&gt;ehsanabedi.com&lt;/a&gt;. Planning a website or a Flutter app in North Cyprus? See my &lt;a href="https://ehsanabedi.com/web-design/" rel="noopener noreferrer"&gt;web design services&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>webdev</category>
      <category>freelance</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
