• Field Notes

The work behind the public grid

The public screenshots are not the whole record. Most of the work lived on real products: shops, apps, internal tools, trade portals, servers, and WordPress. These notes are written as problems, not as a technology list.

01

Commerce and payments

Plenty of shops look finished until money moves. Installments, the gateway, and the order each live in a different place. That is the part I work on: a mistake there becomes a support call, not a ticket on paper.

  • WooCommerce
  • Installments
  • Crypto

Installments on a live shop

For everyoneThe client needed installments without leaving WooCommerce. The plan had to live inside the same cart and order, not a side form someone checks by hand later.

For specialistsA custom installment plugin on WooCommerce, wired into the order lifecycle and status, instead of an isolated form.

A gateway outside the usual path

For everyoneWhen a rial gateway was not enough, crypto checkout sat beside the normal path so the order was recorded there, not later in a spreadsheet.

For specialistsA crypto payment flow in parallel with checkout, with a stored order and an explicit payment status.

Sample code

php
add_action('woocommerce_checkout_order_processed', function ($order_id) {
    $order = wc_get_order($order_id);
    $plan = sanitize_text_field($_POST['installment_plan'] ?? '');

    if (!$order || $plan === '') {
        return;
    }

    $order->update_meta_data('_installment_plan', $plan);
    $order->update_status('on-hold', 'Waiting for installment confirmation');
    $order->save();
});
02

Apps and mobile experience

Some products end on a desktop browser. Others have to live in a pocket: a shop, a portal, or something opened every day. I have built native apps, controlled webviews, and interfaces that feel like an app on a phone.

  • React Native
  • WebView
  • PWA

A shop app on React Native

For everyoneFor a shop whose customers arrived on phones, a responsive site was not the whole answer. The catalog and cart moved into an app under the thumb.

For specialistsReact Native for the shop UI, talking to the existing API, without rewriting the whole backend.

A site inside an app, with a clear border

For everyoneSome products need the live site, but inside an app. The webview was boxed so the user stays on a trusted path and it still feels like an app.

For specialistsA WebView with URL allowlisting, an explicit loading state, and no uncontrolled new windows.

Sample code

tsx
function ShopWebView({ uri }: { uri: string }) {
  return (
    <WebView
      source={{ uri }}
      startInLoadingState
      setSupportMultipleWindows={false}
      onShouldStartLoadWithRequest={(request) =>
        request.url.startsWith("https://")
      }
    />
  );
}
03

Internal company tools

The client site is the storefront. Behind it are tools that stop a team if they break: work reports, remote access, status dashboards. They usually stay private, and they are a large part of the real work.

  • Dashboard
  • RMM
  • Internal tools

A daily report instead of scattered messages

For everyoneInstead of letting the day’s work vanish in chat, the report path collects what was done and what was blocked, in one place you can follow later.

For specialistsA clear report model, a submit API, and an internal UI that does not depend on a messenger.

Dashboard and remote tools for the technical team

For everyoneFor work that has to be seen and handled remotely, the dashboard and remote tools put system status in one view, not ten separate sessions.

For specialistsAn internal panel, RMM, and status monitoring, kept apart from the public client site.

Sample code

ts
type DailyReport = {
  userId: string;
  date: string;
  done: string[];
  blocked: string[];
};

export async function submitReport(report: DailyReport) {
  const response = await fetch("/api/reports", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(report),
  });

  if (!response.ok) {
    throw new Error("Report was not saved");
  }

  return response.json();
}
04

Import, export, and customs

Raw customs and trade data on a page does not get used. The work is to show maps, foreign companies, consulting, and portals in a language a trader can follow, not only a developer.

  • React
  • Maps
  • ixport

A map of Iranian customs

For everyoneInstead of a long table, customs offices sat on a map so location and details could be found at a glance.

For specialistsReact and a map layer, with markers and popups over geospatial customs data.

An export portal for a real user

For everyoneAn export portal has to be multilingual, with a path a non-developer can register and follow. That is the work behind ixport and its related surfaces.

For specialistsA multilingual portal, child theme, and a data layer for companies and export paths.

Sample code

tsx
const customs = [
  { id: "bandar-abbas", lat: 27.1832, lng: 56.2666, name: "Bandar Abbas" },
  { id: "bushehr", lat: 28.9234, lng: 50.8203, name: "Bushehr" },
];

export function CustomsMap() {
  return customs.map((item) => (
    <Marker key={item.id} position={[item.lat, item.lng]}>
      <Popup>{item.name}</Popup>
    </Marker>
  ));
}
05

Infrastructure and security

Deploy means the site opens. The real work after that is security headers, static cache, nginx, and a panel that shows status. I keep that layer apart from the public look of the site.

  • Nginx
  • Linux
  • Security

Server config for a live site

For everyoneFor a site that has to stay fast and stable, static files were cached and headers were set to block common iframe and sniffing mistakes.

For specialistsnginx with try_files, static caching, SSL/HTTP2, and security headers.

A layer you can see, not only a server that is up

For everyoneAn uptime ping is not enough. The security platform and dashboard were set up so status is visible before an end user hits an error.

For specialistsA monitoring and security platform apart from the public frontend, with logs and status in an internal panel.

Sample code

nginx
server {
    listen 443 ssl http2;
    server_name example.com;

    location / {
        try_files $uri $uri/ /index.php?$args;
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Content-Type-Options "nosniff" always;
    }

    location ~* \.(js|css|webp|png)$ {
        expires 30d;
        access_log off;
    }
}
06

WordPress and plugins

Most of the live sites end here: a child theme on Woodmart or Hello with Elementor, installment plugins, stories, sliders, SMS login, cart widgets. WordPress is not a ready-made CMS for me. It is a base that has to behave like a product.

  • WordPress
  • Plugin
  • Elementor

A child theme instead of editing the parent

For everyoneLook and behavior stayed in a child theme so a parent update would not wipe the custom work.

For specialistsChild themes on Woodmart, Hello, and Elementor: template and style overrides without forking the parent.

A plugin for work a theme should not do

For everyoneStories, sliders, SMS login, and a custom cart moved into plugins so a visual change would not delete the logic.

For specialistsCustom post types, shortcodes, REST, and WordPress hooks for features that have to outlive the theme.

Sample code

php
add_action('init', function () {
    register_post_type('story', [
        'label' => 'Stories',
        'public' => true,
        'show_in_rest' => true,
        'supports' => ['title', 'editor', 'thumbnail'],
    ]);
});

add_shortcode('story_flow', function () {
    $query = new WP_Query([
        'post_type' => 'story',
        'posts_per_page' => 6,
    ]);

    ob_start();
    while ($query->have_posts()) {
        $query->the_post();
        echo '<article>' . esc_html(get_the_title()) . '</article>';
    }
    wp_reset_postdata();
    return ob_get_clean();
});