{"id":37956,"date":"2026-03-18T20:16:27","date_gmt":"2026-03-18T13:16:27","guid":{"rendered":"https:\/\/dps.media\/?p=37956"},"modified":"2026-03-18T20:25:33","modified_gmt":"2026-03-18T13:25:33","slug":"wordpress-plugin-dev-guide","status":"publish","type":"post","link":"http:\/\/dps.media\/en\/wordpress-plugin-dev-guide\/","title":{"rendered":"WordPress Plugin Dev Guide"},"content":{"rendered":"<?xml encoding=\"utf-8\" ?><style>\n@import url('https:\/\/fonts.googleapis.com\/css2?family=Syne:wght@600;700;800&family=JetBrains+Mono:wght@300;400;500&family=DM+Sans:wght@300;400;500&display=swap');\n\n#dps-guide {\n  --bg:      #09090e;\n  --bg2:     #0e0e18;\n  --faint:   #1a1a2c;\n  --border:  rgba(255,255,255,0.07);\n  --border2: rgba(255,255,255,0.13);\n  --text:    #ddddf0;\n  --muted:   #6060a0;\n  --blue:    #5b9cf6;\n  --green:   #34d399;\n  --purple:  #a78bfa;\n  --amber:   #fbbf24;\n  --slate:   #94a3b8;\n  --coral:   #fb7185;\n  --blue-bg:   rgba(91,156,246,0.08);\n  --green-bg:  rgba(52,211,153,0.08);\n  --purple-bg: rgba(167,139,250,0.08);\n  --amber-bg:  rgba(251,191,36,0.08);\n  --slate-bg:  rgba(148,163,184,0.08);\n  --coral-bg:  rgba(251,113,133,0.08);\n  background: var(--bg);\n  color: var(--text);\n  font-family: 'DM Sans', sans-serif;\n  line-height: 1.6;\n  border-radius: 16px;\n  overflow: hidden;\n  position: relative;\n}\n\n#dps-guide *,#dps-guide *::before,#dps-guide *::after{box-sizing:border-box;margin:0;padding:0;}\n\n\/* TOP BAR *\/\n#dps-guide .dps-topbar{background:rgba(9,9,14,0.92);backdrop-filter:blur(20px);border-bottom:1px solid var(--border);padding:0 40px;height:52px;display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:50;}\n#dps-guide .dps-brand{display:flex;align-items:center;gap:10px;text-decoration:none;}\n#dps-guide .dps-logo{width:28px;height:28px;border-radius:7px;background:linear-gradient(135deg,rgba(91,156,246,.35),rgba(167,139,250,.35));border:1px solid rgba(167,139,250,.25);display:flex;align-items:center;justify-content:center;font-family:'Syne',sans-serif;font-size:13px;font-weight:800;color:#c4b5f4;flex-shrink:0;}\n#dps-guide .dps-brand-name{font-family:'Syne',sans-serif;font-size:14px;font-weight:700;color:#fff;letter-spacing:-.01em;}\n#dps-guide .dps-topbar-right{display:flex;align-items:center;gap:14px;}\n#dps-guide .dps-nav-tag{font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--muted);letter-spacing:.04em;}\n#dps-guide #dps-copy-btn{display:flex;align-items:center;gap:7px;background:var(--faint);border:1px solid var(--border2);border-radius:8px;padding:6px 14px;cursor:pointer;font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--text);transition:all .18s;white-space:nowrap;}\n#dps-guide #dps-copy-btn:hover{background:rgba(255,255,255,0.06);border-color:rgba(255,255,255,0.2);}\n#dps-guide #dps-copy-btn.copied{background:rgba(52,211,153,0.08);border-color:rgba(52,211,153,.35);color:var(--green);}\n\n\/* PAGE *\/\n#dps-guide .dps-page{padding:48px 40px 64px;max-width:1080px;margin:0 auto;}\n\n\/* HEADER *\/\n#dps-guide .author-pill{display:inline-flex;align-items:center;gap:10px;background:var(--faint);border:1px solid var(--border2);border-radius:99px;padding:6px 14px 6px 8px;margin-bottom:28px;}\n#dps-guide .author-av{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,rgba(91,156,246,.4),rgba(167,139,250,.4));display:flex;align-items:center;justify-content:center;font-family:'Syne',sans-serif;font-size:12px;font-weight:800;color:#fff;}\n#dps-guide .author-pill span{font-size:13px;color:var(--text);font-weight:500;}\n#dps-guide .author-pill em{font-style:normal;color:var(--muted);font-size:12px;}\n#dps-guide h1{font-family:'Syne',sans-serif;font-size:clamp(34px,5vw,58px);font-weight:800;line-height:.95;letter-spacing:-.03em;color:#fff;margin-bottom:16px;}\n#dps-guide h1 span{background:linear-gradient(120deg,var(--blue) 0%,var(--purple) 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;}\n#dps-guide .header-sub{font-size:15px;font-weight:300;color:var(--muted);max-width:500px;margin-bottom:56px;}\n\n\/* SECTION LABEL *\/\n#dps-guide .slabel{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);display:flex;align-items:center;gap:10px;margin-bottom:20px;}\n#dps-guide .slabel::after{content:'';flex:1;height:1px;background:var(--border);}\n\n\/* TAGS *\/\n#dps-guide .tag{font-family:'JetBrains Mono',monospace;font-size:10px;font-weight:500;padding:3px 10px;border-radius:4px;border:1px solid;display:inline-flex;align-items:center;gap:6px;white-space:nowrap;}\n#dps-guide .tag .dot{width:5px;height:5px;border-radius:50%;background:currentColor;}\n#dps-guide .t-blue  {color:var(--blue);  background:var(--blue-bg);  border-color:rgba(91,156,246,.25);}\n#dps-guide .t-green {color:var(--green); background:var(--green-bg); border-color:rgba(52,211,153,.25);}\n#dps-guide .t-purple{color:var(--purple);background:var(--purple-bg);border-color:rgba(167,139,250,.25);}\n#dps-guide .t-amber {color:var(--amber); background:var(--amber-bg); border-color:rgba(251,191,36,.25);}\n#dps-guide .t-slate {color:var(--slate); background:var(--slate-bg); border-color:rgba(148,163,184,.25);}\n#dps-guide .t-coral {color:var(--coral); background:var(--coral-bg); border-color:rgba(251,113,133,.25);}\n\n\/* CARD *\/\n#dps-guide .card{background:var(--bg2);border:1px solid var(--border);border-radius:16px;overflow:hidden;}\n#dps-guide .card-pad{padding:28px;}\n\n\/* FILE TREE *\/\n#dps-guide .tree-section{margin-bottom:56px;}\n#dps-guide .tree-wrap{background:var(--bg2);border:1px solid var(--border);border-radius:16px;overflow:hidden;}\n#dps-guide .tree-topbar-inner{background:var(--faint);border-bottom:1px solid var(--border);padding:10px 20px;display:flex;align-items:center;gap:8px;}\n#dps-guide .tree-topbar-inner span{width:10px;height:10px;border-radius:50%;}\n#dps-guide .tree-topbar-inner small{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--muted);margin-left:8px;}\n#dps-guide .tree-body{display:grid;grid-template-columns:1fr 1fr;gap:0;}\n#dps-guide .tree-col{padding:24px 28px;}\n#dps-guide .tree-col+.tree-col{border-left:1px solid var(--border);}\n#dps-guide .tree-label{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin-bottom:14px;}\n#dps-guide .tree{font-family:'JetBrains Mono',monospace;font-size:12px;line-height:2.1;}\n#dps-guide .tree .d{color:var(--blue);font-weight:500;}\n#dps-guide .tree .f{color:var(--text);}\n#dps-guide .tree .x{color:var(--green);font-weight:500;}\n#dps-guide .tree .c{color:var(--muted);font-size:11px;}\n#dps-guide .tree .i{color:var(--coral);}\n#dps-guide .tree .indent{padding-left:20px;}\n#dps-guide .tree .indent2{padding-left:40px;}\n#dps-guide .tree .indent3{padding-left:60px;}\n\n\/* FLOW *\/\n#dps-guide .flow-section{margin-bottom:56px;}\n#dps-guide .flow-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;}\n#dps-guide .fcard{background:var(--bg2);border:1px solid var(--border);border-radius:16px;overflow:hidden;}\n#dps-guide .fcard-head{padding:20px 24px 0;}\n#dps-guide .fcard h3{font-family:'Syne',sans-serif;font-size:18px;font-weight:700;color:#fff;letter-spacing:-.01em;margin-bottom:4px;margin-top:10px;}\n#dps-guide .fcard-sub{font-size:12.5px;color:var(--muted);font-weight:300;margin-bottom:20px;}\n#dps-guide .fcard-body{padding:0 24px 24px;}\n#dps-guide .steps{display:flex;flex-direction:column;}\n#dps-guide .step{display:flex;gap:14px;align-items:flex-start;}\n#dps-guide .step-l{display:flex;flex-direction:column;align-items:center;flex-shrink:0;}\n#dps-guide .step-dot{width:28px;height:28px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-family:'JetBrains Mono',monospace;font-size:11px;font-weight:500;border:1px solid;flex-shrink:0;}\n#dps-guide .step-line{width:1px;flex:1;min-height:14px;background:var(--border);margin:3px 0;}\n#dps-guide .step-r{padding-top:4px;padding-bottom:18px;}\n#dps-guide .step-title{font-size:13px;font-weight:500;color:var(--text);margin-bottom:2px;}\n#dps-guide .step-desc{font-size:12px;color:var(--muted);font-weight:300;line-height:1.55;}\n#dps-guide .code{margin-top:6px;background:var(--faint);border-radius:6px;padding:7px 12px;font-family:'JetBrains Mono',monospace;font-size:11px;line-height:1.9;}\n#dps-guide .code .cmd{color:var(--green);}\n#dps-guide .code .cmt{color:var(--muted);}\n#dps-guide .code .val{color:var(--amber);}\n#dps-guide .code .key{color:var(--blue);}\n\n\/* SCRIPTS *\/\n#dps-guide .scripts-section{margin-bottom:56px;}\n#dps-guide .scripts-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;}\n#dps-guide .scmd{background:var(--bg2);border:1px solid var(--border);border-radius:12px;padding:18px 20px;transition:border-color .2s;}\n#dps-guide .scmd:hover{border-color:var(--border2);}\n#dps-guide .scmd-cmd{font-family:'JetBrains Mono',monospace;font-size:13px;font-weight:500;color:var(--green);margin-bottom:6px;}\n#dps-guide .scmd-what{font-size:12.5px;color:var(--muted);font-weight:300;line-height:1.5;margin-bottom:8px;}\n#dps-guide .scmd-detail{font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--muted);border-top:1px solid var(--border);padding-top:8px;line-height:1.7;}\n\n\/* DO\/DONT *\/\n#dps-guide .dodonts{display:grid;grid-template-columns:1fr 1fr;gap:2px;border-radius:12px;overflow:hidden;border:1px solid var(--border);}\n#dps-guide .do-col{background:rgba(52,211,153,.04);padding:20px 22px;}\n#dps-guide .dont-col{background:rgba(251,113,133,.04);padding:20px 22px;}\n#dps-guide .do-head{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--green);margin-bottom:12px;display:flex;align-items:center;gap:8px;}\n#dps-guide .dont-head{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--coral);margin-bottom:12px;display:flex;align-items:center;gap:8px;}\n#dps-guide .do-head::before{content:'\u2713';font-size:12px;}\n#dps-guide .dont-head::before{content:'\u2717';font-size:12px;}\n#dps-guide .do-item,#dps-guide .dont-item{font-family:'JetBrains Mono',monospace;font-size:11.5px;padding:6px 10px;border-radius:6px;margin-bottom:4px;line-height:1.5;}\n#dps-guide .do-item{color:var(--green);background:rgba(52,211,153,.06);}\n#dps-guide .dont-item{color:var(--coral);background:rgba(251,113,133,.06);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);}\n\n\/* ZIP *\/\n#dps-guide .zip-section{margin-bottom:56px;}\n#dps-guide .zip-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;}\n#dps-guide .zip-card{background:var(--bg2);border:1px solid var(--border);border-radius:14px;overflow:hidden;}\n#dps-guide .zip-head{padding:14px 18px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:10px;}\n#dps-guide .zip-body{padding:14px 18px;}\n#dps-guide .zip-row{display:flex;align-items:center;justify-content:space-between;padding:7px 0;border-bottom:1px solid var(--border);}\n#dps-guide .zip-row:last-child{border-bottom:none;}\n#dps-guide .zip-path{font-family:'JetBrains Mono',monospace;font-size:11.5px;}\n#dps-guide .zip-note{font-size:11px;color:var(--muted);font-weight:300;}\n\n\/* ACCEPTANCE *\/\n#dps-guide .ac-section{margin-bottom:56px;}\n#dps-guide .ac-list{display:flex;flex-direction:column;gap:6px;}\n#dps-guide .ac-item{display:flex;align-items:center;gap:14px;background:var(--bg2);border:1px solid var(--border);border-radius:10px;padding:12px 18px;transition:border-color .2s;}\n#dps-guide .ac-item:hover{border-color:var(--border2);}\n#dps-guide .ac-check{width:20px;height:20px;border-radius:6px;border:1px solid rgba(52,211,153,.3);background:rgba(52,211,153,.06);display:flex;align-items:center;justify-content:center;font-size:11px;color:var(--green);flex-shrink:0;}\n#dps-guide .ac-text{font-size:13px;color:var(--text);font-weight:400;}\n\n\/* BOTTOM BAR *\/\n#dps-guide .dps-footer{border-top:1px solid var(--border);padding:22px 40px;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:12px;}\n#dps-guide .dps-footer-l{display:flex;align-items:center;gap:10px;}\n#dps-guide .dps-footer p{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--muted);}\n#dps-guide .dps-footer-links{display:flex;gap:20px;}\n#dps-guide .dps-footer-links a{font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--muted);text-decoration:none;}\n#dps-guide .dps-footer-links a:hover{color:var(--text);}\n\n\/* FADE *\/\n#dps-guide .fi{opacity:0;transform:translateY(18px);transition:opacity .5s ease,transform .5s ease;}\n#dps-guide .fi.in{opacity:1;transform:none;}\n\n@media(max-width:720px){\n  #dps-guide .dps-topbar{padding:0 20px;}\n  #dps-guide .dps-nav-tag{display:none;}\n  #dps-guide .dps-page{padding:32px 20px 48px;}\n  #dps-guide .tree-body,#dps-guide .flow-grid,#dps-guide .scripts-grid,#dps-guide .zip-grid,#dps-guide .dodonts{grid-template-columns:1fr;}\n  #dps-guide .tree-col+.tree-col{border-left:none;border-top:1px solid var(--border);}\n  #dps-guide .dps-footer{padding:20px;}\n}\n<\/style><div id=\"dps-guide\">\n\n  <!-- TOP BAR -->\n  <div class=\"dps-topbar\">\n    <div class=\"dps-brand\">\n      <div class=\"dps-logo\">D<\/div>\n      <span class=\"dps-brand-name\">DPS.MEDIA<\/span>\n    <\/div>\n    <div class=\"dps-topbar-right\">\n      <span class=\"dps-nav-tag\">WP Plugin Dev Guide \u2014 Internal<\/span>\n      <button id=\"dps-copy-btn\">\n        <svg width=\"13\" height=\"13\" viewbox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"5\" y=\"5\" width=\"9\" height=\"9\" rx=\"2\"><\/rect><path d=\"M11 5V3a2 2 0 0 0-2-2H3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2\"><\/path><\/svg>\n        <span id=\"dps-copy-label\">Copy agent prompt<\/span>\n      <\/button>\n    <\/div>\n  <\/div>\n\n  <div class=\"dps-page\">\n\n    <!-- HEADER -->\n    <div class=\"fi\">\n      <div class=\"author-pill\">\n        <div class=\"author-av\">H<\/div>\n        <span>Hien<\/span>\n        <em>CEO \u00b7 DPS.MEDIA<\/em>\n      <\/div>\n      <h1>WordPress<br><span>Plugin Dev<\/span><br>Guide<\/h1>\n      <p class=\"header-sub\">Source \u2192 build \u2192 release flow for teams. Sufficient for local dev, ZIP packaging, and WordPress production installation.<\/p>\n    <\/div>\n\n    <!-- STACK PILLS -->\n    <div class=\"fi\" style=\"display:flex;gap:8px;flex-wrap:wrap;margin-bottom:56px;\">\n      <span class=\"tag t-blue\"><span class=\"dot\"><\/span>PHP 8.x<\/span>\n      <span class=\"tag t-blue\"><span class=\"dot\"><\/span>WordPress hooks API<\/span>\n      <span class=\"tag t-green\"><span class=\"dot\"><\/span>@wordpress\/scripts<\/span>\n      <span class=\"tag t-green\"><span class=\"dot\"><\/span>React (Admin UI)<\/span>\n      <span class=\"tag t-green\"><span class=\"dot\"><\/span>Webpack 5<\/span>\n      <span class=\"tag t-amber\"><span class=\"dot\"><\/span>npm scripts<\/span>\n      <span class=\"tag t-slate\"><span class=\"dot\"><\/span>Node.js \u2265 18<\/span>\n      <span class=\"tag t-slate\"><span class=\"dot\"><\/span>ZIP release<\/span>\n    <\/div>\n\n    <!-- FILE TREE -->\n    <div class=\"tree-section fi\">\n      <div class=\"slabel\">Directory structure<\/div>\n      <div class=\"tree-wrap\">\n        <div class=\"tree-topbar-inner\">\n          <span style=\"background:#ff5f57;\"><\/span>\n          <span style=\"background:#febc2e;\"><\/span>\n          <span style=\"background:#28c840;\"><\/span>\n          <small>my-plugin\/ \u2014 project root<\/small>\n        <\/div>\n        <div class=\"tree-body\">\n          <div class=\"tree-col\">\n            <div class=\"tree-label\">Source (dev)<\/div>\n            <div class=\"tree\">\n              <div><span class=\"d\">my-plugin.php<\/span> <span class=\"c\">\u2190 main plugin file<\/span><\/div>\n              <div class=\"indent\"><span class=\"d\">includes\/<\/span> <span class=\"c\">\u2190 PHP runtime<\/span><\/div>\n              <div class=\"indent2\"><span class=\"f\">class-core.php<\/span><\/div>\n              <div class=\"indent2\"><span class=\"f\">class-admin.php<\/span><\/div>\n              <div class=\"indent\"><span class=\"d\">admin\/<\/span><\/div>\n              <div class=\"indent2\"><span class=\"d\" style=\"color:var(--amber);\">src\/<\/span> <span class=\"c\">\u2190 write code here<\/span><\/div>\n              <div class=\"indent3\"><span class=\"x\">index.js<\/span> <span class=\"c\">\u2190 entry point<\/span><\/div>\n              <div class=\"indent3\"><span class=\"f\">components\/<\/span><\/div>\n              <div class=\"indent2\"><span class=\"d\" style=\"color:var(--green);\">dist\/<\/span> <span class=\"c\">\u2190 build output<\/span><\/div>\n              <div class=\"indent3\"><span class=\"x\">index.js<\/span><\/div>\n              <div class=\"indent3\"><span class=\"x\">index.asset.php<\/span><\/div>\n              <div class=\"indent3\"><span class=\"f\">index.css<\/span><\/div>\n              <div class=\"indent\"><span class=\"f\">languages\/<\/span> <span class=\"c\">\u2190 i18n<\/span><\/div>\n              <div class=\"indent\"><span class=\"i\">node_modules\/<\/span> <span class=\"c\">\u2190 .gitignore<\/span><\/div>\n              <div class=\"indent\"><span class=\"i\">releases\/<\/span> <span class=\"c\">\u2190 .gitignore<\/span><\/div>\n            <\/div>\n          <\/div>\n          <div class=\"tree-col\">\n            <div class=\"tree-label\">Config files<\/div>\n            <div class=\"tree\">\n              <div><span class=\"x\">package.json<\/span><\/div>\n              <div><span class=\"f\">webpack.config.js<\/span> <span class=\"c\">\u2190 if custom is needed<\/span><\/div>\n              <div><span class=\"x\">.gitignore<\/span><\/div>\n              <div><span class=\"x\">BUILD.md<\/span><\/div>\n              <div><span class=\"f\">readme.txt<\/span><\/div>\n              <div><span class=\"f\">uninstall.php<\/span><\/div>\n              <div style=\"margin-top:16px;background:var(--faint);border-radius:8px;padding:12px 14px;border:1px solid var(--border);\">\n                <div style=\"color:var(--muted);\">\/\/ \u2713 Correct \u2014 enqueue from dist<\/div>\n                <div style=\"color:var(--green);\">plugins_url(<span style=\"color:var(--amber);\">\u2018admin\/dist\/index.js\u2019<\/span>)<\/div>\n                <div style=\"color:var(--muted);margin-top:8px;\">\/\/ \u2717 Incorrect \u2014 do not enqueue src<\/div>\n                <div style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.5);\">plugins_url(<span style=\"color:var(--amber);\">\u2018admin\/src\/index.js\u2019<\/span>)<\/div>\n              <\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- WORKFLOWS -->\n    <div class=\"flow-section fi\">\n      <div class=\"slabel\">Workflows<\/div>\n      <div class=\"flow-grid\">\n        <div class=\"fcard\">\n          <div class=\"fcard-head\">\n            <div class=\"tag t-green\"><span class=\"dot\"><\/span>Local Development<\/div>\n            <h3>Local dev<\/h3>\n            <p class=\"fcard-sub\">Ch\u1ea1y watch mode, s\u1eeda JS\/React \u2192 build t\u1ef1 \u0111\u1ed9ng, F5 WP l\u00e0 th\u1ea5y ngay.<\/p>\n          <\/div>\n          <div class=\"fcard-body\">\n            <div class=\"steps\">\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-green\">01<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">C\u00e0i dependencies<\/div><div class=\"step-desc\">Only needed the first time. Requires Node.js \u2265 18.<\/div><div class=\"code\"><span class=\"cmd\">npm install<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-green\">02<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">B\u1eadt watch mode<\/div><div class=\"step-desc\">Webpack watch: save file in <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--amber);\">admin\/src\/<\/code> \u2192 t\u1ef1 build ra <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--green);\">admin\/dist\/<\/code>. Need manual F5 in WP.<\/div><div class=\"code\"><span class=\"cmd\">npm run start<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-green\">03<\/div><\/div><div class=\"step-r\"><div class=\"step-title\">Test on local WP<\/div><div class=\"step-desc\">Symlink into <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--slate);\">wp-content\/plugins\/<\/code> or use Local by Flywheel.<\/div><\/div><\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n        <div class=\"fcard\">\n          <div class=\"fcard-head\">\n            <div class=\"tag t-amber\"><span class=\"dot\"><\/span>Build &amp; Release<\/div>\n            <h3>Zip, install WP<\/h3>\n            <p class=\"fcard-sub\">Production build, package clean ZIP \u2014 no npm needed on server.<\/p>\n          <\/div>\n          <div class=\"fcard-body\">\n            <div class=\"steps\">\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-amber\">01<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">Build production<\/div><div class=\"step-desc\">Webpack build with minify + tree-shaking.<\/div><div class=\"code\"><span class=\"cmd\">npm run build<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-amber\">02<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">Package ZIP<\/div><div class=\"step-desc\">Script copies correct files, excludes <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--coral);\">node_modules<\/code> and <code style=\"font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--coral);\">admin\/src<\/code>.<\/div><div class=\"code\"><span class=\"cmd\">npm run package<\/span><br><span class=\"cmt\"># \u2192 releases\/plugin-v1.0.0.zip<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot t-amber\">03<\/div><div class=\"step-line\"><\/div><\/div><div class=\"step-r\"><div class=\"step-title\">Verify SHA256<\/div><div class=\"code\"><span class=\"cmd\">sha256sum<\/span> <span class=\"val\">releases\/plugin-v1.0.0.zip<\/span><\/div><\/div><\/div>\n              <div class=\"step\"><div class=\"step-l\"><div class=\"step-dot\" style=\"color:var(--green);background:var(--green-bg);border-color:rgba(52,211,153,.25);\">\u2713<\/div><\/div><div class=\"step-r\"><div class=\"step-title\" style=\"color:var(--green);\">Upload to WordPress<\/div><div class=\"step-desc\">Admin \u2192 Plugins \u2192 Add New \u2192 Upload. Activate. No npm needed on server.<\/div><\/div><\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- NPM SCRIPTS -->\n    <div class=\"scripts-section fi\">\n      <div class=\"slabel\">npm scripts \u2014 cheat sheet<\/div>\n      <div class=\"scripts-grid\">\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run start<\/div><div class=\"scmd-what\">Watch mode \u2014 daily dev<\/div><div class=\"scmd-detail\">webpack \u2013watch \u2013mode development<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run build<\/div><div class=\"scmd-what\">Production build \u2014 before release<\/div><div class=\"scmd-detail\">webpack \u2013mode production + minify<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run package<\/div><div class=\"scmd-what\">Zip clean into releases\/<\/div><div class=\"scmd-detail\">exclude src\/ node_modules\/ .git\/<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run lint:js<\/div><div class=\"scmd-what\">Lint JS according to WP standards<\/div><div class=\"scmd-detail\">wp-scripts lint-js<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run format<\/div><div class=\"scmd-what\">Auto code formatting<\/div><div class=\"scmd-detail\">wp-scripts format (prettier)<\/div><\/div>\n        <div class=\"scmd\"><div class=\"scmd-cmd\">npm run release<\/div><div class=\"scmd-what\">Lint \u2192 build \u2192 package<\/div><div class=\"scmd-detail\">check + build + package in 1 cmd<\/div><\/div>\n      <\/div>\n    <\/div>\n\n    <!-- ZIP CONTENTS -->\n    <div class=\"zip-section fi\">\n      <div class=\"slabel\">ZIP release \u2014 inside and out<\/div>\n      <div class=\"zip-grid\">\n        <div class=\"zip-card\">\n          <div class=\"zip-head\"><span class=\"tag t-green\"><span class=\"dot\"><\/span>\u2713 Included in ZIP<\/span><\/div>\n          <div class=\"zip-body\">\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">my-plugin.php<\/span><span class=\"zip-note\">main plugin file<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">includes\/<\/span><span class=\"zip-note\">Full PHP runtime<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">admin\/dist\/<\/span><span class=\"zip-note\">Pre-built JS\/CSS<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">languages\/<\/span><span class=\"zip-note\">i18n if applicable<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">readme.txt<\/span><span class=\"zip-note\">WP.org format<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--green);\">uninstall.php<\/span><span class=\"zip-note\">cleanup on plugin deletion<\/span><\/div>\n          <\/div>\n        <\/div>\n        <div class=\"zip-card\">\n          <div class=\"zip-head\"><span class=\"tag t-coral\"><span class=\"dot\"><\/span>\u2717 Not included in ZIP<\/span><\/div>\n          <div class=\"zip-body\">\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">node_modules\/<\/span><span class=\"zip-note\">deps dev only<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">admin\/src\/<\/span><span class=\"zip-note\">source, not executed<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">.git\/<\/span><span class=\"zip-note\">repo metadata<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">package.json \/ webpack.config.js<\/span><span class=\"zip-note\">build config<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">.test.js \/ debug-.php<\/span><span class=\"zip-note\">internal test files<\/span><\/div>\n            <div class=\"zip-row\"><span class=\"zip-path\" style=\"color:var(--coral);text-decoration:line-through;text-decoration-color:rgba(251,113,133,.4);\">.env \/ .DS_Store<\/span><span class=\"zip-note\">local machine files<\/span><\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- DO \/ DON'T -->\n    <div class=\"fi\" style=\"margin-bottom:56px;\">\n      <div class=\"slabel\">Important rules<\/div>\n      <div class=\"dodonts\">\n        <div class=\"do-col\">\n          <div class=\"do-head\">Do it right<\/div>\n          <div class=\"do-item\">Enqueue from <code style=\"font-family:'JetBrains Mono',monospace;\">admin\/dist\/<\/code><\/div>\n          <div class=\"do-item\">Read <code style=\"font-family:'JetBrains Mono',monospace;\">index.asset.php<\/code> get deps + version<\/div>\n          <div class=\"do-item\">Use <code style=\"font-family:'JetBrains Mono',monospace;\">wp_localize_script()<\/code> pass data PHP \u2192 JS<\/div>\n          <div class=\"do-item\">Run <code style=\"font-family:'JetBrains Mono',monospace;\">npm run build<\/code> before <code style=\"font-family:'JetBrains Mono',monospace;\">npm run package<\/code><\/div>\n          <div class=\"do-item\">Conditional load \u2014 only enqueue needed page<\/div>\n          <div class=\"do-item\">Prefix everything: <code style=\"font-family:'JetBrains Mono',monospace;\">dps_<\/code>, <code style=\"font-family:'JetBrains Mono',monospace;\">DPS_<\/code><\/div>\n        <\/div>\n        <div class=\"dont-col\">\n          <div class=\"dont-head\">Don't do<\/div>\n          <div class=\"dont-item\">Enqueue from <code style=\"font-family:'JetBrains Mono',monospace;\">admin\/src\/<\/code><\/div>\n          <div class=\"dont-item\">Hardcode version hash in PHP<\/div>\n          <div class=\"dont-item\">To <code style=\"font-family:'JetBrains Mono',monospace;\">node_modules\/<\/code> inside ZIP<\/div>\n          <div class=\"dont-item\">npm install on production server<\/div>\n          <div class=\"dont-item\">Run heavy DB queries at <code style=\"font-family:'JetBrains Mono',monospace;\">init<\/code> hook<\/div>\n          <div class=\"dont-item\"><code style=\"font-family:'JetBrains Mono',monospace;\">echo $_POST['x']<\/code> not sanitized\/escaped<\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- CHECKLIST -->\n    <div class=\"ac-section fi\">\n      <div class=\"slabel\">Checklist production-ready<\/div>\n      <div style=\"display:grid;grid-template-columns:1fr 1fr;gap:6px;\">\n        <div style=\"display:flex;flex-direction:column;gap:6px;\">\n          <div style=\"font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--blue);padding:4px 0 8px;\">Build &amp; Release<\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\"><code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\">npm run build<\/code> no errors \u2192 <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\">admin\/dist\/<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">ZIP installs, Activate without errors \u2014 no npm server needed<\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">ZIP does not contain <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--coral);\">node_modules\/<\/code> or <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--coral);\">src\/<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">Report back: file list + ZIP path + SHA256<\/div><\/div>\n          <div style=\"font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--purple);padding:12px 0 8px;\">Security<\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">All PHP files have <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--purple);\">if (!defined('ABSPATH')) exit;<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">All AJAX\/forms: nonce verify + <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--purple);\">current_user_can()<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">Input sanitized, output escaped<\/div><\/div>\n        <\/div>\n        <div style=\"display:flex;flex-direction:column;gap:6px;\">\n          <div style=\"font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--amber);padding:4px 0 8px;\">Performance<\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">Asset load conditional \u2014 not loaded site-wide<\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">Script: <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--amber);\">in_footer: true<\/code> + <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--amber);\">strategy: defer<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">Do not run heavy DB queries at <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--amber);\">init<\/code> hook<\/div><\/div>\n          <div style=\"font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--green);padding:12px 0 8px;\">Standards<\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">All functions\/classes\/options have prefix <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\">dps_<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">Plugin header: <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\">Requires at least<\/code>, <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\">Requires PHP<\/code><\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\">All strings use i18n, <code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\">uninstall.php<\/code> clean cleanup<\/div><\/div>\n          <div class=\"ac-item\"><div class=\"ac-check\">\u2713<\/div><div class=\"ac-text\"><code style=\"font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green);\">BUILD.md<\/code> complete: install, build, package, test<\/div><\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n  <\/div><!-- \/dps-page -->\n\n  <!-- BOTTOM BAR -->\n  <div class=\"dps-footer\">\n    <div class=\"dps-footer-l\">\n      <div class=\"dps-logo\">D<\/div>\n      <p>DPS.MEDIA JOINT STOCK COMPANY \u00b7 TIN 0318700500<\/p>\n    <\/div>\n    <div class=\"dps-footer-links\">\n      <a href=\"mailto:marketing@dps.media\">marketing@dps.media<\/a>\n      <a href=\"tel:0961545445\">0961 545 445<\/a>\n      <a href=\"https:\/\/dps.media\/en\/\">dps.media<\/a>\n    <\/div>\n  <\/div>\n\n<\/div><!-- \/#dps-guide --><script>\n(function(){\n  var guide = document.getElementById('dps-guide');\n  if(!guide) return;\n\n  \/\/ Fade-in on scroll\n  var io = new IntersectionObserver(function(es){\n    es.forEach(function(e){ if(e.isIntersecting){ e.target.classList.add('in'); io.unobserve(e.target); } });\n  },{threshold:0.05});\n  guide.querySelectorAll('.fi').forEach(function(el,i){\n    el.style.transitionDelay=(i*0.06)+'s';\n    io.observe(el);\n  });\n\n  \/\/ Copy button\n  var btn = document.getElementById('dps-copy-btn');\n  var lbl = document.getElementById('dps-copy-label');\n  if(!btn) return;\n\n  btn.addEventListener('click', function(){\n    var md = \"# WP Plugin Dev \\u2014 Agent Prompt (DPS.MEDIA)\\n\\n## M\\u1ee5c ti\\u00eau\\nRefactor plugin sang flow **source \\u2192 build \\u2192 release**. Plugin ph\\u1ea3i: load nhanh, kh\\u00f4ng conflict, \\u0111\\u00fang WP coding standards, b\\u1ea3o m\\u1eadt, d\\u1ec5 b\\u1ea3o tr\\u00ec.\\n\\n---\\n\\n## 0. \\u0110\\u00e1nh gi\\u00e1 tr\\u01b0\\u1edbc khi b\\u1eaft \\u0111\\u1ea7u (YAGNI check)\\n\\nTr\\u01b0\\u1edbc khi refactor b\\u1ea5t k\\u1ef3 th\\u1ee9 g\\u00ec, ki\\u1ec3m tra t\\u1eebng th\\u01b0 m\\u1ee5c asset v\\u00e0 t\\u1ef1 \\u0111\\u00e1nh gi\\u00e1:\\n\\n- `admin\/` \\u2014 c\\u00f3 React\/JSX\/TS, import ES module, Sass? \\u2192 \\u0111\\u01b0a v\\u00e0o pipeline\\n- `public\/` \\u2014 ch\\u1ec9 vanilla JS\/jQuery\/CSS thu\\u1ea7n? \\u2192 gi\\u1eef static, kh\\u00f4ng build\\n\\n\\u00c1p d\\u1ee5ng **YAGNI** \\u2014 ch\\u1ec9 build nh\\u1eefng g\\u00ec th\\u1ef1c s\\u1ef1 c\\u1ea7n transpile. B\\u00e1o l\\u1ea1i quy\\u1ebft \\u0111\\u1ecbnh tr\\u01b0\\u1edbc khi vi\\u1ebft code.\\n\\n---\\n\\n## 1. C\\u1ea5u tr\\u00fac th\\u01b0 m\\u1ee5c\\n```\\nmy-plugin\/\\n\\u251c\\u2500\\u2500 my-plugin.php\\n\\u251c\\u2500\\u2500 includes\/\\n\\u251c\\u2500\\u2500 admin\/\\n\\u2502   \\u251c\\u2500\\u2500 src\/     \\u2190 vi\\u1ebft code \\u1edf \\u0111\\u00e2y\\n\\u2502   \\u2514\\u2500\\u2500 dist\/    \\u2190 PHP enqueue t\\u1eeb \\u0111\\u00e2y\\n\\u251c\\u2500\\u2500 languages\/\\n\\u251c\\u2500\\u2500 releases\/  (.gitignore)\\n\\u251c\\u2500\\u2500 package.json\\n\\u251c\\u2500\\u2500 .gitignore\\n\\u2514\\u2500\\u2500 BUILD.md\\n```\\n\\n## 2. Plugin file header\\n```php\\n\/**\\n * Plugin Name: My Plugin\\n * Requires at least: 6.0\\n * Requires PHP: 8.0\\n * Tested up to: 6.7\\n * Text Domain: my-plugin\\n *\/\\nif (!defined('ABSPATH')) exit;\\n```\\n\\n## 3. npm scripts\\n```json\\n{\\n  \\\"start\\\":   \\\"wp-scripts start\\\",\\n  \\\"build\\\":   \\\"wp-scripts build\\\",\\n  \\\"package\\\": \\\"node scripts\/package.js\\\",\\n  \\\"lint:js\\\": \\\"wp-scripts lint-js admin\/src\\\",\\n  \\\"check\\\":   \\\"npm run lint:js && npm run lint:css\\\",\\n  \\\"release\\\": \\\"npm run check && npm run build && npm run package\\\"\\n}\\n```\\n\\n## 4. PHP enqueue \\u2014 chu\\u1ea9n\\n```php\\nadd_action('admin_enqueue_scripts', function($hook) {\\n  if ($hook !== 'toplevel_page_my-plugin') return; \/\/ conditional\\n  $asset = include plugin_dir_path(__FILE__) . 'admin\/dist\/index.asset.php';\\n  wp_enqueue_script('my-plugin', plugins_url('admin\/dist\/index.js', __FILE__),\\n    $asset['dependencies'], $asset['version'],\\n    ['in_footer' => true, 'strategy' => 'defer']);\\n  wp_localize_script('my-plugin', 'dpsData', [\\n    'nonce' => wp_create_nonce('dps_nonce')\\n  ]);\\n});\\n```\\n\\n## 5. Security\\n```php\\n\/\/ \\u0110\\u1ea7u m\\u1ecdi file PHP\\nif (!defined('ABSPATH')) exit;\\n\\n\/\/ Prefix t\\u1ea5t c\\u1ea3\\nfunction dps_get_settings() {}\\nclass DPS_Plugin_Core {}\\n\\n\/\/ AJAX handler\\nfunction dps_handle_ajax() {\\n  check_ajax_referer('dps_nonce', 'nonce');\\n  if (!current_user_can('manage_options')) wp_die('Unauthorized', 403);\\n  $name = sanitize_text_field($_POST['name']);\\n  echo esc_html($name);\\n  wp_die();\\n}\\n```\\n\\n## 6. ZIP release\\nCo trong ZIP: my-plugin.php, includes\/, admin\/dist\/, languages\/, readme.txt, uninstall.php\\nKHONG co: node_modules\/, admin\/src\/, .git\/, package.json, *.test.js\\n\\n## 7. Acceptance criteria\\n- [ ] npm run build khong loi, output ra admin\/dist\/\\n- [ ] ZIP cai duoc, Activate khong loi, khong can npm tren server\\n- [ ] ZIP khong chua node_modules\/ hay admin\/src\/\\n- [ ] Bao lai: danh sach file + ZIP path + SHA256\\n- [ ] Moi file PHP co: if (!defined('ABSPATH')) exit;\\n- [ ] Moi AJAX\/form: nonce verify + current_user_can()\\n- [ ] Input sanitized, output escaped\\n- [ ] Asset load conditional, script defer\\n- [ ] Prefix dps_ cho moi function\/class\/option\\n- [ ] Plugin header day du fields\\n- [ ] uninstall.php cleanup sach\\n- [ ] BUILD.md day du\\n\";\n\n    try {\n      var ta = document.createElement('textarea');\n      ta.value = md;\n      ta.style.cssText = 'position:fixed;top:-9999px;left:-9999px;opacity:0;';\n      document.body.appendChild(ta);\n      ta.focus(); ta.select();\n      document.execCommand('copy');\n      document.body.removeChild(ta);\n      btn.classList.add('copied');\n      lbl.textContent = 'Copied!';\n      setTimeout(function(){ btn.classList.remove('copied'); lbl.textContent = 'Copy agent prompt'; }, 2200);\n    } catch(e) {\n      lbl.textContent = 'Failed';\n      setTimeout(function(){ lbl.textContent = 'Copy agent prompt'; }, 2000);\n    }\n  });\n})();\n<\/script>\n<style>\r\n.lwrp.link-whisper-related-posts{\r\n            \r\n            margin-top: 40px;\nmargin-bottom: 30px;\r\n        }\r\n        .lwrp .lwrp-title{\r\n            \r\n            \r\n        }.lwrp .lwrp-description{\r\n            \r\n            \r\n\r\n        }\r\n        .lwrp .lwrp-list-container{\r\n        }\r\n        .lwrp .lwrp-list-multi-container{\r\n            display: flex;\r\n        }\r\n        .lwrp .lwrp-list-double{\r\n            width: 48%;\r\n        }\r\n        .lwrp .lwrp-list-triple{\r\n            width: 32%;\r\n        }\r\n        .lwrp .lwrp-list-row-container{\r\n            display: flex;\r\n            justify-content: space-between;\r\n        }\r\n        .lwrp .lwrp-list-row-container .lwrp-list-item{\r\n            width: calc(33% - 20px);\r\n        }\r\n        .lwrp .lwrp-list-item:not(.lwrp-no-posts-message-item){\r\n            \r\n            max-width: 150px;\r\n        }\r\n        .lwrp .lwrp-list-item img{\r\n            max-width: 100%;\r\n            height: auto;\r\n            object-fit: cover;\r\n            aspect-ratio: 1 \/ 1;\r\n        }\r\n        .lwrp .lwrp-list-item.lwrp-empty-list-item{\r\n            background: initial !important;\r\n        }\r\n        .lwrp .lwrp-list-item .lwrp-list-link .lwrp-list-link-title-text,\r\n        .lwrp .lwrp-list-item .lwrp-list-no-posts-message{\r\n            \r\n            \r\n            \r\n            \r\n        }@media screen and (max-width: 480px) {\r\n            .lwrp.link-whisper-related-posts{\r\n                \r\n                \r\n            }\r\n            .lwrp .lwrp-title{\r\n                \r\n                \r\n            }.lwrp .lwrp-description{\r\n                \r\n                \r\n            }\r\n            .lwrp .lwrp-list-multi-container{\r\n                flex-direction: column;\r\n            }\r\n            .lwrp .lwrp-list-multi-container ul.lwrp-list{\r\n                margin-top: 0px;\r\n                margin-bottom: 0px;\r\n                padding-top: 0px;\r\n                padding-bottom: 0px;\r\n            }\r\n            .lwrp .lwrp-list-double,\r\n            .lwrp .lwrp-list-triple{\r\n                width: 100%;\r\n            }\r\n            .lwrp .lwrp-list-row-container{\r\n                justify-content: initial;\r\n                flex-direction: column;\r\n            }\r\n            .lwrp .lwrp-list-row-container .lwrp-list-item{\r\n                width: 100%;\r\n            }\r\n            .lwrp .lwrp-list-item:not(.lwrp-no-posts-message-item){\r\n                \r\n                max-width: initial;\r\n            }\r\n            .lwrp .lwrp-list-item .lwrp-list-link .lwrp-list-link-title-text,\r\n            .lwrp .lwrp-list-item .lwrp-list-no-posts-message{\r\n                \r\n                \r\n                \r\n                \r\n            };\r\n        }<\/style>\r\n<div id=\"link-whisper-related-posts-widget\" class=\"link-whisper-related-posts lwrp\">\r\n            <div class=\"lwrp-title\">Related Posts<\/div>    \r\n        <div class=\"lwrp-list-container\">\r\n                                <div class=\"lwrp-list lwrp-list-row-container lwrp-list-double-row\">\r\n                <div class=\"lwrp-list-item\"><a href=\"https:\/\/dps.media\/en\/wp-mcp-connect-all-in-one-solution-connecting-ai-agents-with-wordpress\/\" class=\"lwrp-list-link\"><span class=\"lwrp-list-link-title-text\">WP-MCP-Connect:-All-in-One-Solution-Connecting-AI-Agents-with-WordPress<\/span><\/a><\/div><div class=\"lwrp-list-item\"><a href=\"https:\/\/dps.media\/en\/reliable-and-100-safe-tiktok-channel-buying-and-selling-service\/\" class=\"lwrp-list-link\"><span class=\"lwrp-list-link-title-text\">Reputable and safe TikTok channel buying and selling service 100% guaranteed<\/span><\/a><\/div><div class=\"lwrp-list-item\"><a href=\"https:\/\/dps.media\/en\/cheap-facebook-seeding-service-package-to-increase-likes-and-comments\/\" class=\"lwrp-list-link\"><span class=\"lwrp-list-link-title-text\">Cheap Facebook Seeding Service, Package \u2013 Increase Likes, Comments<\/span><\/a><\/div>                <\/div>\r\n                            <div class=\"lwrp-list lwrp-list-row-container lwrp-list-double-row\">\r\n                <div class=\"lwrp-list-item\"><a href=\"https:\/\/dps.media\/en\/top-10-trusted-business-website-design-companies\/\" class=\"lwrp-list-link\"><span class=\"lwrp-list-link-title-text\">Top 10 Corporate Website Design Companies Trusted by Businesses<\/span><\/a><\/div><div class=\"lwrp-list-item\"><a href=\"https:\/\/dps.media\/en\/how-to-build-a-tiktok-community-to-retain-customers\/\" class=\"lwrp-list-link\"><span class=\"lwrp-list-link-title-text\">How to build a TikTok community to retain customers<\/span><\/a><\/div><div class=\"lwrp-list-item\"><a href=\"https:\/\/dps.media\/en\/capability-profile-of-advertising-design-company-building-sustainable-brands\/\" class=\"lwrp-list-link\"><span class=\"lwrp-list-link-title-text\">Company profile specializing in advertising design \u2013 Building sustainable brands<\/span><\/a><\/div>                <\/div>\r\n                <\/div>\r\n<\/div>","protected":false},"excerpt":{"rendered":"<p>D DPS.MEDIA WP Plugin Dev Guide \u2014 Internal Copy agent prompt H Hi\u1ec3n CEO \u00b7 DPS.MEDIA WordPressPlugin DevGuide Flow source \u2192 build \u2192 release cho team. \u0110\u1ee7 \u0111\u1ec3 dev local, \u0111\u00f3ng ZIP, c\u00e0i l\u00ean WordPress production. PHP 8.x WordPress hooks API @wordpress\/scripts React (Admin UI) Webpack 5 npm scripts Node.js \u2265 18 ZIP release C\u1ea5u [&hellip;]<\/p>","protected":false},"author":1,"featured_media":37957,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,1204],"tags":[],"class_list":["post-37956","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","category-wordpress-marketing"],"acf":[],"rankmath_keywords":{"primary":"","secondary":[""]},"yoast_keywords":{"primary":"","secondary":[]},"yoast_focuskw":"","rankmath_focuskw":"","seo_keywords":{"primary":"","secondary":[""]},"_links":{"self":[{"href":"http:\/\/dps.media\/en\/wp-json\/wp\/v2\/posts\/37956","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/dps.media\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/dps.media\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/dps.media\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/dps.media\/en\/wp-json\/wp\/v2\/comments?post=37956"}],"version-history":[{"count":4,"href":"http:\/\/dps.media\/en\/wp-json\/wp\/v2\/posts\/37956\/revisions"}],"predecessor-version":[{"id":37961,"href":"http:\/\/dps.media\/en\/wp-json\/wp\/v2\/posts\/37956\/revisions\/37961"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/dps.media\/en\/wp-json\/wp\/v2\/media\/37957"}],"wp:attachment":[{"href":"http:\/\/dps.media\/en\/wp-json\/wp\/v2\/media?parent=37956"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/dps.media\/en\/wp-json\/wp\/v2\/categories?post=37956"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/dps.media\/en\/wp-json\/wp\/v2\/tags?post=37956"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}