Compare commits

26 Commits

Author SHA1 Message Date
Kunthawat Greethong
689a8924e6 fix: Business Knowledge card visibility, spread neural cards, adjust layout
- Add position:absolute to neural-node.liquid-glass override to fix
  3D positioning (liquid-glass was overriding to position:relative)
- Spread outer cards further apart for better visual separation
- Increase container size to 600x520px to accommodate spread
- Enlarge neural cards (220px width, 130px min-height)
- Update float animations to match new positions
2026-06-24 14:20:57 +07:00
Kunthawat Greethong
2a3062357f fix: hero neural UX improvements
1. Mouse move listener now on document (not just hero section)
2. Removed hover effect on outer cards, kept only for center กำไร card
3. Bigger text: card-tag 20px, card-desc 16px
4. Hero overflow visible on desktop (cards can extend left)
5. Hero overflow clip on mobile (normal containment)
2026-06-24 09:14:55 +07:00
Kunthawat Greethong
1d893e1bcb fix: remove duplicate CSS causing style conflicts
- Removed old translateZ() CSS that was overriding new translate3d() styles
- This was causing nodes to not display in correct 3D positions
2026-06-24 09:02:19 +07:00
Kunthawat Greethong
61c2bd6924 feat: neural network hero with true 3D and dynamic lines
- True 3D positioning with translate3d(x, y, z) for each node
- Larger cards (200px width) with proper spacing
- Canvas-based dynamic connection lines
- Lines connect at card borders (edge-to-edge)
- Straight solid lines (3px, yellow, 50% opacity)
- Mouse parallax with smooth easing
- 3D perspective changes card sizes dynamically
- Mobile responsive: flat column layout
- Device orientation support for touch devices
2026-06-24 08:58:32 +07:00
Kunthawat Greethong
fdb03f6117 feat: neural network hero with 3D parallax
- Replace profit cluster with neural network visualization
- 4 liquid-glass nodes: กำไร (center), Marketing, AI, Business Knowledge
- 3D perspective with CSS preserve-3d
- Mouse parallax: scene rotates ±15deg following cursor
- Unequal distances: nodes at z: -100, -150, -200
- Floating animations for each outer node
- SVG dashed connector lines with pulse animation
- Device orientation support for mobile
- Responsive: flat column layout on mobile (≤620px)
- Smooth easing with requestAnimationFrame
2026-06-24 08:45:49 +07:00
Kunthawat Greethong
0f244424c0 feat: hero profit cluster, dark text fix, footer, privacy/terms pages
- Replace hero right panel with liquid-glass profit cluster (กำไร + Marketing/AI/Business Knowledge)
- Fix dark-on-dark text visibility in all inverted sections (scene-dark, page-section)
- Add Footer component with liquid-glass design, contact info, legal links
- Add privacy and terms placeholder pages
- Update PageShell to include Footer on all pages
2026-06-24 08:24:49 +07:00
Kunthawat Greethong
f827afb33f feat: liquid glass UI, blob background, redesign home/portfolio/about pages
- Liquid glass effect on navbar/cards with backdrop-filter invert
- Animated blob gradient background (SVG-based)
- Portfolio section: scene-dark invert, show 5 items on home
- How Work section: step flow with numbers + connecting lines
- Hero: Decision snapshot replacing problem selector
- About page: inverted background with contrast fixes
- Fix parallax JS bundling via Astro
- Fix navbar fixed positioning after liquid glass CSS
- Submenu hover fix
- Clean up removed legacy files/assets
2026-06-23 11:40:37 +07:00
Kunthawat Greethong
e279119f97 fix(dark): resolve dark-on-dark text in marquee, log, footer
Dark mode bug: hardcoded rgba(10,10,10,0.3) used as text color
on dark backgrounds — unreadable.

Fix: html.dark overrides for:
- .marquee-track .ts
- .fx-marquee-track .ts
- .fx-log .ts
- .fx-footer-bottom
All now use rgba(250,238,200,0.4) (warm cream, legible on dark)
2026-06-14 21:34:08 +07:00
Kunthawat Greethong
ceffb2a3f3 refactor(legacy): apply v6 design to all inner pages (delete bento components)
Per user: 'เราไม่ต้องการ legacy design น่ะ เพราะมีดีไชน์ใหม่แล้วไง'
- New v6 design must apply to EVERY page, not just index

PHASE A — Add CSS compatibility aliases (~600 lines)
==================================================
fx-system.css grew from 0.05MB → 0.12MB with 3 new alias blocks
for legacy class names that pages still use:

1. LEGACY → v6 ALIASES
   .section, .section-bento, .section-soft, .section-yellow
   .section-header, .section-badge, .section-title, .section-desc
   .reveal, .hero-content, .hero-badge, .hero-grid
   .service-stack + .service-stack-{item,num,icon,body,title,bullets}
   .portfolio-card-{grid,top,badge,arrow,name,industry,highlight}
   .contact-form, .form-{group,label,input,row,success}, .btn, .btn-{primary,outline-dark}
   .filter-section, .filter-bar, .filter-btn
   .info-icon, .checklist
   All styled with v6 design tokens (--ink, --paper, --coral,
   --brand-yellow, --line-2, --paper-2, etc.)

2. BENTO COMPONENT ALIASES
   .bento-grid, .bento-tile, .span-{3,4,5,6,7,8,12}, .rows-{2,3}
   .surface-{white,soft,yellow,purple,purple-soft,teal,teal-soft,mint,dark,coral}
   .tile-{eyebrow,title,body,link}, .mega-cta
   All render via CSS Grid 12-col + v6 surface treatments
   Children (.tile-eyebrow, .tile-title, .tile-body) get v6
   typography (Kanit 800 for titles, JetBrains Mono 700 for
   eyebrows, Itim for em accents).

3. DARK MODE OVERRIDES
   html.dark .section-soft/.filter-section: var(--paper-2)
   html.dark .section-badge/.filter-btn.active: yellow
   html.dark .contact-form .form-input: dark inputs
   html.dark .bento-tile.surface-{soft,purple-soft,yellow}: dark variants

PHASE B — Replace legacy components with inline divs
==================================================
Deleted components (no longer imported by anyone):
- src/components/BentoGrid.astro
- src/components/BentoTile.astro
- src/components/DecoOrb.astro
- src/components/PageHero.astro

Replaced in 7 pages (mechanical regex sweep):
- services/[slug].astro
- contact.astro
- faq.astro
- blog/index.astro
- blog/[slug].astro
- privacy.astro
- terms.astro

JSX transforms:
- <BentoGrid>...</BentoGrid> → <div class='bento-grid'>...</div>
- <BentoTile span={6} surface='yellow' /> → <div class='bento-tile span-6 surface-yellow' />
- <DecoOrb .../> → (deleted, was decorative empty)
- Removed unused BentoGrid/BentoTile/DecoOrb imports

Cleaned orphan comments referencing deleted components:
- // use data-parallax-speed from DecoOrb
- <!-- mail, line, hours as separate BentoTiles -->
- /* FAQ inside BentoTile */

FINAL AUDIT
===========
- 0 legacy component refs in src/
- Build: 22 pages, 1.98s, 0 errors
- All 11 pages have v6 styling (via direct fx-* or via aliases)

Result: every page now uses the v6 design system consistently.
No more yellow DecorativeOrbs, no more BentoTile grid overlap,
no more PageHero/KineticHero mixing. Visual continuity across
all 11 pages.
2026-06-14 21:22:58 +07:00
Kunthawat Greethong
73d820412a fix(nav): remove extra border-bottom under each nav item (desktop)
User reported: 'header menu มีบรรทัดเกิน แปลกๆ' — the 'หน้าแรก'
active link had 2 horizontal lines under it (coral ::after + gray border-bottom).

ROOT CAUSE: v7-5 .fx-nav-menu>li had border-bottom: 1px solid meant
for MOBILE menu (separating stacked items) but the rule escaped
the @media block during Phase 6.2 refactor and now applied to
ALL viewports.

FIX: Add .fx-nav-menu>li { border-bottom: none; } in base CSS
(placed AFTER the original v7-5 rule so cascade applies it).
Mobile @media block below still re-enables border-bottom:1px
for stacked menu.

Verified in built CSS: 12 .fx-nav-menu rules, override present
and last. Build: 22 pages, 2.06s.
2026-06-14 15:05:06 +07:00
Kunthawat Greethong
40382bbf55 refactor(content): reposition from 'app developer' to 'AI + Marketing consultant'
User feedback: design + content was too app-dev focused
(terminal commands, figma labels, code jargon). Business is
'ที่ปรึกษา AI + การตลาด' focused on 3 outcomes:
- เพิ่มยอดขาย (more sales)
- ลดต้นทุน (lower costs)
- ประหยัดเวลา (save time)

Changes:

VISIBLE TEXT replaced:
- Hero title: 'เราจะช่วยคุณเพิ่มกำไร ไม่ใช่แค่เพิ่มงบ'
  → 'เพิ่มยอดขาย ลดต้นทุน ประหยัดเวลา'
- Hero eyebrow: 'MOREMINIMORE / EST. 2024'
  → 'MOREMINIMORE / AI + MARKETING CONSULTANT'
- Hero lede rewrote: 'วางระบบ AI + Online Marketing + Automation...'
  → 'ที่ปรึกษา AI + การตลาดออนไลน์ สำหรับ SME ไทย'
- Hero CTA primary: 'ปรึกษาฟรี →' → 'ปรึกษาฟรี 30 นาที →'
- Process section: '$ npx req/analyze/design/build' (4 steps)
  → '→ ขั้นตอนที่ 1/2/3/4' with business Thai labels
- Case study logs: '[2024-01-15] INFO/SUCCESS' (dates + log tags)
  → 'ขั้นที่ 1/2/3 INFO/SUCCESS' (milestone language)
- Marquee ticker: '[2026-06-13] $ build/deploy' + '[log]'
  → 'อัปเดต/ผลงาน' (Thai status labels)
- Contact prompt placeholder: 'name / phone / line' + 'ENTER' button
  → 'ชื่อ / เบอร์โทร / LINE' + 'ส่งข้อความ' button
- Contact hint: 'กด ENTER เพื่อส่ง' → 'กดส่งเพื่อเริ่มคุยกับเรา'

NEW SECTION: 3 results cards under hero
- Each card: icon + label + example
- เพิ่มยอดขาย / ลดต้นทุน / ประหยัดเวลา
- Examples tied to Dataroot case
- Yellow icon box + black border + lift hover

CSS PSEUDO-ELEMENTS hidden (display:none !important):
- .fx-hero::before '> section: hero · frame: 00.0'
- .fx-case::before '> section: case-study · frame: 01.0'
- .fx-case-image::before 'fig.01 / 4×3'
- .fx-case-content::before 'case.log'
- .fx-services::before '> section: services · 4 cards'
- .fx-callout::before '> callout / 02.0'
- .fx-portfolio::before '> section: portfolio · 4 items'
- .fx-process::before '> $ npx workflow run · 4 steps'
- .fx-pricing::before '> $ cat /pricing/packages.json'
- .fx-faq::before '> $ cat /faq.txt'
- .fx-contact::before '> $ contact@start.sh'
- .fx-portfolio-card::before '◉ ◉ ◉ moreminimore.com/[path]'
- .fx-pricing-card::before 'tier / X'
- .fx-service-card::before 'card / 02.A' + ::after '600×360'
- .fx-hero-side::before 'STATS.LOG'

CSS ::before content hidden:
- .fx-hero-content::before '$' (terminal prompt)
- .fx-contact-form::before '$' (terminal prompt)
- .fx-hero-content::after 'moreminimore --init'
  → 'AI · MARKETING · RESULTS' (business tagline)

CSS-Internal markers (data-coord '00.1', 'P.1' etc) KEPT
as per user choice A+C — they're invisible to user (HTML data
attributes), Vite would also strip if removed, and they help
with future debugging.

Build: 22 pages, 2.20s. Verified jargon gone, business content
present, hero results section rendering.
2026-06-14 10:26:21 +07:00
Kunthawat Greethong
8b04c739e1 fix(utility): remove mode indicator (button label is enough)
Per user: the mode indicator text 'light/dark/auto' next to the
toggle button is redundant — the button itself shows the current
mode in its label ('◐ auto' / '☀ light' / '☾ dark').

Removed:
- <span id='fx-mode-indicator'> from UtilityBar.astro
- getElementById('fx-mode-indicator') in applyTheme() JS
- (CSS for .fx-mode-indicator stays — minimal cost, no harm)

Build: 22 pages, 2.27s.
2026-06-14 10:17:20 +07:00
Kunthawat Greethong
caab40d9a4 fix(theme): switch to .dark class (Astro/Vite strips [data-theme] selectors)
ROOT CAUSE found via build artifact analysis:
- Built CSS files (dist/_astro/Base.*.css) had ZERO [data-theme='dark']
  selectors even though source had 17. Astro/Vite CSS optimizer
  strips attribute selectors that don't match any static HTML attribute
  (we set data-theme dynamically via JS, not in JSX/HTML).
- Also stripped: all html { } and body { } rules from source.
- Result: dark mode visually did nothing. Body stayed white.

FIX:
- Replace [data-theme='dark'] with html.dark (17 occurrences in
  fx-system.css). Vite keeps .dark class selectors because the
  anti-flash script (in Base.astro <head>) sets a class, not an
  attribute, which Vite sees as 'used'.
- Update anti-flash script in Base.astro: classList.add/remove
  instead of setAttribute('data-theme', ...).
- Update UtilityBar.astro applyTheme() to use classList too.
- Restore body { background: var(--body-bg) } override (was stripped
  by Vite as 'unused' — but now html.dark applies to it correctly).

ALSO FIXED theme toggle button visibility (from previous turn):
- Removed v7-5 base .fx-theme-toggle rule (rgba(0.1) opacity made
  button invisible — only visible on hover).
- Consolidated into single rule with proper contrast for both modes.

Verified by:
- Build complete: 22 pages, 1.97s
- Built CSS: 17 html.dark selectors present (was 0)
- Body background override present in built CSS
- HTTP server on :4322 serving correct artifacts
2026-06-14 09:41:32 +07:00
Kunthawat Greethong
96caca4af6 fix(theme+marquee): restore marquee scroll + add light/dark mode toggle
User reported 2 issues after Phase 6.2:
1. 'marquee ควรต้องเลื่อนด้วย' — ROOT CAUSE: v7-5 source CSS included
   override at end of <style> block:
     .fx-marquee-track{animation:none}
     .fx-faq-a::after{display:none}
     .fx-hero::after{display:none}
   These were 'no-op' overrides from the mockup library (which doesn't
   actually animate things in showcase mode). Copied verbatim when I
   extracted fx-system.css in Phase 1.1, killing marquee + 2 other
   animations.
   FIX: replaced with the real animations (marquee 40s, blink-cursor,
   hero noise overlay). All 3 now actually run.

2. 'เราต้องการ light and dark mode ด้วย โดยมีปุ่มเปลี่ยน mode ได้' —
   Implemented full light/dark theme system:
   - Added [data-theme='dark'] block in fx-system.css overriding 11
     CSS tokens (--ink, --paper, --line, --text-dim, + 5 new
     --utility-bg/--nav-bg/--hero-content-bg/etc.)
   - Refactored .fx-utility-bar to use --utility-bg/--fg vars instead
     of hardcoded #0A0A0A (so it inverts correctly in dark mode)
   - Refactored .fx-nav, .fx-hero-content, .fx-hero-side, .fx-faq-item
     to use theme-aware vars
   - Added 13 [data-theme='dark'] overrides for elements needing
     extra contrast tweaks (pricing featured, callout, portfolio name,
     process/service numbers, prose)
   - Added smooth 0.3s transition on theme change (no jarring swap)

3. Theme toggle button (UtilityBar.astro):
   - Replaced text-only indicator with <button id='fx-theme-toggle'>
   - 3 modes cycle: auto (follow OS) → light → dark → auto
   - Persists to localStorage 'moreminimore-theme'
   - Default = 'auto' (follows system preference)
   - Button label changes: '◐ auto' / '☀ light' / '☾ dark'
   - Mode indicator shows user's chosen mode
   - Listens to OS preference change live (when in 'auto' mode)
   - ARIA label + title for accessibility

4. Anti-flash inline script in Base.astro <head>:
   - Runs synchronously before first paint
   - Reads localStorage → applies data-theme
   - If 'auto' or unset, follows prefers-color-scheme
   - Prevents white→dark flash on first load

Build: 22 pages, 0 errors, 2.11s.
CSS: 545/545 braces, 9 keyframes, 13 dark-mode selectors.
2026-06-13 19:41:54 +07:00
Kunthawat Greethong
5393cf611c fix(animations): 8 keyframes + reveal/stagger initial state + button hovers
User reported 2 issues after Phase 6:
1. 'เว็บไม่มี animation เลย' — v7-5 CSS referenced 6+ animations
   (sparkle-float, pulse-glow, float, tag-pulse, type-up,
   blink-cursor, gradient-vertical) but the @keyframes for
   5 of them were NEVER included in the copy. marquee was the
   only one that worked. All other animations silently failed.
2. 'ปุ่มกดไม่ได้' — buttons were styled (cursor:pointer, colors)
   but had no :hover state for visual feedback. User couldn't tell
   they were interactive. .fx-btn:hover, .fx-nav-cta:hover,
   .fx-pricing-cta:hover, .fx-nav-menu a:hover all missing.

Also: .fx-reveal had no initial hidden state (started at opacity:1
with no .revealed class to transition TO) — observer fired but
nothing moved. Same for .fx-stagger.

Fixes (verified by re-parsing CSS):
- Added 7 missing @keyframes: sparkle-float, pulse-glow, float,
  tag-pulse, type-up, blink-cursor, gradient-vertical
- .fx-reveal:not(.revealed) = opacity:0, translateY(40px)
- .fx-stagger:not(.staggered) > * = opacity:0, translateY(20px)
- .fx-stagger.staggered > * = fade in with staggered delays (6 children)
- .fx-btn:hover = lift + coral bg + 4px shadow
- .fx-btn.ghost:hover = lift + yellow bg
- .fx-nav-cta:hover = invert colors + 4px shadow
- .fx-pricing-cta:hover = coral bg + yellow shadow
- .fx-nav-menu a:hover = yellow bg + coral text
- .fx-theme-toggle:hover = yellow bg
- .fx-service-card / .fx-portfolio-card / .fx-pricing-card hover
  = lift + 6px shadow
- .fx-faq-item:hover = slide right + paper bg
- .fx-stat:hover = yellow highlight + lift
- .fx-process-step:hover = lift + coral border

CSS now: 518 braces balanced, 8 keyframes, 0 broken animation refs.

Build: 22 pages, 0 errors, 2.12s.
2026-06-13 19:25:41 +07:00
Kunthawat Greethong
b8ac07996e feat(fx-system): Itim Thai side-bearing fix + prefers-reduced-motion
Phase 6.1: Itim fix — apply letter-spacing: -0.5px + margin-right: -2px
to all <em> in v7-5 sections. Per user memory, Thai display fonts ship
with wide side bearings causing visual gaps after Latin punctuation.
Scope: 20 selectors covering every .fx-* section + .fx-prose (about body).

Phase 6.2: prefers-reduced-motion — kill animations when user prefers.
Disables .fx-marquee-track, .fx-sparkle, .fx-reveal, .fx-stagger animations.
Also hides .fx-hero::after and .fx-faq-a::after decorations.

Phase 6.3: production build verified (22 pages, 0 errors, 1.96s)

Refs: .hermes/plans/2026-06-13_124000-moreminimore-v7-5-migration.md Task 6.1-6.3
2026-06-13 18:02:07 +07:00
Kunthawat Greethong
caa412dbe2 feat(pages): wire v6 sections to all 9 pages
- index.astro: full 9-section home (Hero → Case → Services → Callout →
  Portfolio → Process → Pricing → Faq → Contact prompt form)
- about.astro: v6 Hero + body content from <Content /> wrapped in .fx-prose
- services/index.astro: v6 Hero + v6 Services (4 from collection) + Contact prompt
- portfolio.astro: v6 Hero + v6 Portfolio (pinned 3) + grid of remaining 6 + Contact
- blog/index.astro: PageHero → Hero (badge→eyebrow, subtitle→lede, showStats=false)
- blog/[slug].astro: same PageHero → Hero swap
- faq.astro: same swap (existing bento FAQ body preserved)
- contact.astro: same swap + WIRED form to submitContact() (real backend).
  Was setTimeout 800ms placeholder — now uses contact-submit.ts which
  POSTs to PUBLIC_CONTACT_ENDPOINT (Apps Script) or dev-mocks if empty.
- privacy.astro + terms.astro: same PageHero → Hero swap

Build: 22 pages, 0 errors. Phase 4.9d complete (contact form wired).

Refs: .hermes/plans/2026-06-13_124000-moreminimore-v7-5-migration.md Task 5.1-5.9
2026-06-13 18:01:17 +07:00
Kunthawat Greethong
8c2bf3d303 feat(contact): real working form with Apps Script backend (3 sub-tasks)
4.9a: Contact.astro (v6-contact enhanced)
- 2 variants: 'prompt' (1 input + ENTER, for home) + 'full' (5 fields, for /contact)
- Smart-parses prompt input (phone vs name detection)
- Toast feedback on submit (success/error, 5s auto-hide)
- Dev-mode aware (no endpoint = console.log + 'dev mode' toast)

4.9b: apps-script/contact-form/ (USER DEPLOYS)
- Code.gs: doPost() handler → 3 actions:
  1. Append to Google Sheet (SHEET_ID from Script Properties)
  2. Send email via MailApp to RECIPIENT_EMAIL
  3. Send LINE Notify via UrlFetchApp
- Returns {ok, id} or {ok:false, error} as JSON
- Includes testDoPost() for testing in Apps Script editor
- README.md: 6-step deploy guide (Script Properties + Sheet + LINE token)
  with security notes + cost breakdown

4.9c: src/lib/contact-submit.ts
- Reads PUBLIC_CONTACT_ENDPOINT from .env
- Empty/missing = dev mode (console.log + 300ms mock latency)
- Set = POST JSON to endpoint
- Exports submitContact() + isDevMode() for Contact.astro to use

Refs: .hermes/plans/2026-06-13_124000-moreminimore-v7-5-migration.md Task 4.9a-c
2026-06-13 17:55:59 +07:00
Kunthawat Greethong
154e3f2d91 feat(sections): v6-hero, case, services, callout, portfolio, process, pricing, faq (8 components)
- Hero.astro: REPLACED 714-line legacy. v6-hero terminal+stats — 2-col grid
  with $ command + eyebrow + sparkles + 2x2 stats sidebar. All via props.
- CaseStudy.astro: v6-case — image + 3 stats + log + CTAs. Defaults to Dataroot.
- Services.astro: v6-services 2x2 grid. Loads from src/content/services/*-new.mdx
  (4 services). Features hardcoded per title (v7-5 style).
- Callout.astro: v6-callout yellow pullquote.
- Portfolio.astro: v6-portfolio 2-1-1 modal grid. PINNED 3 per plan round 2
  (Dataroot flagship, Luadjob, Jet). First is 'featured' (large).
- Process.astro: v6-process 4-col flow. Hardcoded 4 steps per plan round 2.
- Pricing.astro: v6-pricing. New pricing collection (2 webdev tiers only
  per plan round 2): Astro ฿5,000 featured + WordPress ฿30,000.
  Grid uses auto-fit to gracefully accept 2-3 tiers.
- Faq.astro: v6-faq Q+A list. Loads from src/content/faq/*.md (20 items),
  default limit=4 to match v7-5 demo. Highlights keywords via hardcoded map.

+ src/content/pricing/astro.md + wordpress.md (new)
+ src/content.config.ts: +pricing collection (z.object with features array)

Refs: .hermes/plans/2026-06-13_124000-moreminimore-v7-5-migration.md Task 4.1-4.8
2026-06-13 17:54:10 +07:00
Kunthawat Greethong
b586464b5c feat(footer+layout): v6-footer + mount UtilityBar/Marquee/Nav/Footer in Base.astro
- Footer.astro (v6-footer): REPLACED legacy 439-line version. 4-col sitemap
  bound to site settings (phone, email, line, facebook, linkedin) +
  servicesDropdown + company links. Logo uses /images/logo-long-black.png
  (local, was hardcoded to dataroot CDN in v7-5).
- Base.astro: mount <UtilityBar /> + <Marquee /> + <Navigation /> + <Footer />
  around <slot />. Nav receives currentPath for active link highlight.
  Animation init now runs BOTH initAnimations (legacy bento) and fxInit (v7-5).
- SWEEP: removed duplicate <Navigation /> / <Footer /> + their imports
  from 11 page files. Idempotent script via execute_code.

Verified: all 9 pages return 200, header/footer render exactly once each.

Refs: .hermes/plans/2026-06-13_124000-moreminimore-v7-5-migration.md Task 3.1-3.2
2026-06-13 17:50:10 +07:00
Kunthawat Greethong
1f859921cb feat(header): add UtilityBar + Marquee + Navigation from v6-nav
- UtilityBar.astro (v6-utility): phone, clock, date, email from site settings
  Clock updated by fxClock() in src/lib/fx-animations.ts
- Marquee.astro (v6-marquee): log ticker with 4 entries (animated horizontally)
  Content duplicated for seamless loop
- Navigation.astro (v6-nav): REPLACED legacy. Adds 'บริการ' dropdown
  (4 services) + 'บทความ' link per plan round 2. Click-to-toggle on mobile.
- src/data/nav.ts: single source of truth for mainLinks + servicesDropdown
- fx-system.css: +27 lines for dropdown styles + active link underline
  (v6-nav originally had no dropdown — we added per spec)

Refs: .hermes/plans/2026-06-13_124000-moreminimore-v7-5-migration.md Task 2.1-2.4
2026-06-13 17:47:40 +07:00
Kunthawat Greethong
582998a340 feat(fx): extract clock + reveal + stagger from v7-5 (line 1567-1624)
3 SSR-safe utilities in one module:
- fxClock() — live Thai Buddhist calendar (id=fx-time, id=fx-date)
- fxReveal() — add .revealed to .fx-reveal on scroll (with 2 failsafes)
- fxStagger() — add .staggered to .fx-stagger on scroll (with 2 failsafes)
- fxInit() — convenience to run all 3

Typed with HTMLElement generics. Uses standard IntersectionObserver.
Namespaced .fx-* classes — no collision with legacy src/lib/animations.ts
(which uses .reveal / counterUp for bento components).

Refs: .hermes/plans/2026-06-13_124000-moreminimore-v7-5-migration.md Task 1.3
2026-06-13 17:45:58 +07:00
Kunthawat Greethong
9eea9cbe6d feat(layout): import fx-system alongside global.css
fx-system.css is v7-5's .fx-* design system. global.css continues to
serve the legacy bento components (still used by /about, /services,
/contact, /faq, /blog). No collision because all v7-5 classes are
prefixed .fx-*. No visual change yet — components not wired yet.

Refs: .hermes/plans/2026-06-13_124000-moreminimore-v7-5-migration.md Task 1.2
2026-06-13 17:45:01 +07:00
Kunthawat Greethong
ed03060ff7 feat(fx-system): copy v7-5 design system CSS (485 lines, 12 categories)
Extracted verbatim from Desktop/moreminomore-mockup-v7-5.html lines 10-484.
All .fx-* classes namespaced to avoid collision with global.css.

- Tokens: --brand-yellow #FFD60A, --coral #FF5A3C, --ink #0A0A0A
- Fonts: Kanit + Itim + JetBrains Mono (matches global.css)
- Animations: @keyframes marquee + reveal/stagger JS in src/lib/fx-animations.ts

Refs: .hermes/plans/2026-06-13_124000-moreminimore-v7-5-migration.md Task 1.1
2026-06-13 17:44:10 +07:00
Kunthawat Greethong
45f548421d chore: gitignore .hermes (local plans/notes, not for remote) 2026-06-13 17:43:41 +07:00
Kunthawat Greethong
b54657f58a chore(services): sync existing [slug].astro updates from staging 2026-06-13 17:43:35 +07:00
177 changed files with 5107 additions and 15468 deletions

4
.gitignore vendored
View File

@@ -22,3 +22,7 @@ pnpm-debug.log*
# jetbrains setting folder
.idea/
.hermes/
# archive (large local files)
_archive/

View File

@@ -1,111 +0,0 @@
# Blog Topics — 5 เรื่องที่ควรเขียน
> เรียงตามลำดับที่ควรเขียน เริ่มจากเรื่องที่ "อยู่ในใจลูกค้ามากที่สุด" ก่อน
> แต่ละเรื่องมี: ที่มา (จากคำตอบข้อไหน) + โครงสร้าง outline + เหตุผลที่ควรเขียน
---
## 1. "SME ไทยเสียเงินหลายแสนกับโฆษณาที่ไม่มีใครซื้อ — เรื่องจริงจากคนทำ"
**ที่มา:** A6 (SME ไทยทำพลาดเรื่องเดิมซ้ำ ๆ) + เคส Dataroot + เคสเกือบพังเรื่องกลุ่มเป้าหมาย
**ทำไมต้องเขียน:** คือเคส flagship ของเรา เขียนครั้งเดียวใช้ได้หลายที่ — เว็บ, LinkedIn, ใบเสนอราคา
**Outline:**
- เริ่มจากเคส Dataroot: คลิกเยอะ ยอดไม่ขยับ งบหลายแสน/เดือน
- ดูสถิติย้อนหลัง → เจอว่าคลิกมาจากกลุ่มที่ไม่ซื้อ
- ปรับ 3 อย่าง: ตัดกลุ่ม, ปรับ Creative, ขยายช่องทาง
- ผลลัพธ์ (Impression ↑373%, Click ↑114%, Ad spend ↓28%)
- เคสเกือบพัง: ยิงไปกลุ่ม "คนสนใจเรื่องเงิน" → มีแต่คนมาขอกู้
- บทเรียน: ดู "คนที่จะซื้อ" ไม่ใช่ "คนที่คลิกง่าย"
**Length:** 1,500-2,000 คำ
---
## 2. "AI ไม่ได้แพงเสมอไป — งาน 80% ใช้ Model ถูกก็พอ ประหยัดได้ครึ่ง"
**ที่มา:** D15 (เรื่องที่ไม่เห็นด้วย) + A6 (SME ใช้ AI ผิดแบบ) + คำตอบ B7 (AI Consult)
**ทำไมต้องเขียน:** ลูกค้า SME ส่วนใหญ่กลัว "AI แพง" — ถ้าเขียนเรื่องนี้ได้ดี คือ lead magnet เลย
**Outline:**
- เปิดด้วย: "ถ้าคุณจ่าย GPT-4 ทุกครั้ง คุณกำลังเปลืองเงินเปล่า ๆ"
- งานแบ่งเป็น 3 ระดับ: งานทั่วไป, งานวิเคราะห์, งานเฉพาะทาง
- ตารางเปรียบเทียบ: งาน X ใช้ Model Y คุณภาพ Z ราคาเท่าไหร่
- ตัวอย่างจริง: ลูกค้าเคยใช้ GPT-4 ทุกงาน → ลดเหลือ GPT-4o-mini + Sonnet + Local LLM → ประหยัด 60%
- Local LLM คืออะไร + เหมาะกับงานแบบไหน (PDPA, ความลับ)
- วิธีเลือก Model: ถ้างานเป็น "ตอบคำถาม" → ใช้ของถูก / ถ้าเป็น "วิเคราะห์ข้อมูล" → ใช้ของกลาง
**Length:** 1,500-2,000 คำ
---
## 3. "เว็บสวย vs เว็บขายได้ — ทำไมหลายเว็บที่ดูรก ๆ ถึงขายดีกว่า"
**ที่มา:** D15 (เว็บสวยไม่ได้แปลว่าขายได้)
**ทำไมต้องเขียน:** ลูกค้า SME ส่วนใหญ่ตัดสิน agency ด้วย "ผลงานสวยไหม" — ถ้าเขียนเรื่องนี้ได้ ลูกค้าจะเริ่มคิดใหม่
**Outline:**
- ตัวอย่าง: เว็บ A ดูหรูหรา แต่ Conversion 0.5% / เว็บ B ดูเก่า แต่ Conversion 3.2%
- ทำไม: เว็บสวยเน้น "ภาพลักษณ์" / เว็บขายได้เน้น "ลูกค้าทำอะไรได้"
- หลักการเว็บที่ขายได้: Clear CTA, Trust signals, Friction ต่ำ, Mobile-first
- เคสของเรา: เว็บที่ดูไม่หรูแต่ขายได้ (Baofuling, Tuanthong, Jet Industries)
- "เว็บสวย vs เว็บขายได้ ไม่ได้แยกกันเสมอ — แต่ถ้าต้องเลือก เราเลือกขายได้"
**Length:** 1,200-1,500 คำ
---
## 4. "5 ค่าใช้จ่ายแฝงที่ทำให้ร้านออนไลน์ขาดทุน — แม้ยอดขายจะเติบโต"
**ที่มา:** เคสเกือบพังเรื่อง Platform fees + A6 (SME ทดลองตลาดใหม่โดยไม่คำนวณค่าใช้จ่ายแฝง)
**ทำไมต้องเขียน:** ลูกค้า E-commerce เจอปัญหานี้เยอะมาก แต่ไม่ค่อยมีใครเขียนเรื่องนี้
**Outline:**
- ค่าใช้จ่ายแฝง 5 อย่าง: ค่าธรรมเนียม Platform / ค่าจัดส่งที่แท้จริง / ค่าคืนสินค้า / ส่วนลดที่ไม่ได้คิด / ค่าโฆษณาต่อ Lead
- เคสจริง: ร้านค้าออนไลน์ขายดี ยอดเดือนละ 500,000 แต่เหลือกำไร 15,000
- วิธีคำนวณ: ทำ Spreadsheet ต้นทุนแท้จริง (เอา Template ไปด้วย)
- วิธีแก้: ปรับราคา + เพิ่มช่องทางขายตรง
- ผลลัพธ์: ลูกค้าเราเพิ่มกำไรต่อชิ้น 35% ใน 2 เดือน
**Length:** 1,500 คำ
---
## 5. "GEO คืออะไร และทำไม SEO แบบเดิมอาจไม่พอในยุค ChatGPT"
**ที่มา:** A6 (รูปแบบการตลาดใหม่ ๆ ที่จะเปลี่ยนไปในยุค AI) + C13 (กำลังเรียนรู้ SEO กับ GEO)
**ทำไมต้องเขียน:** ยังเป็นเรื่องใหม่สำหรับ SME ส่วนใหญ่ ถ้าเขียนก่อน คุณจะเป็น authority ในเรื่องนี้
**Outline:**
- เปิดด้วย: "ปี 2024 คนเริ่มถาม ChatGPT แทน Google — เว็บคุณอยู่ในคำตอบไหม?"
- SEO vs GEO: ต่างกันยังไง
- ตัวอย่าง: ถาม ChatGPT "ที่ปรึกษา AI ในไทย" — ได้คำตอบแบบไหน เว็บไหนถูกอ้างอิง
- 3 สิ่งที่ต้องทำเพื่อให้ AI อ้างอิงเว็บคุณ: โครงสร้างข้อมูล, Authority, Mention ในแหล่งอื่น
- เคสของเรา: ทำให้ลูกค้าโผล่ใน ChatGPT/Perplexity
- 2026 คือปีที่ GEO สำคัญกว่า SEO — เตรียมตัวยังไง
**Length:** 1,500-2,000 คำ
---
## เขียนยังไงให้ได้ผล
**Tone:** ตรง ๆ มีตัวเลข เล่าเคสจริง ไม่ขายของ — เหมือนคุยกับเพื่อนที่เป็น SME
**โครงสร้าง:** ปัญหา → ตัวอย่างจริง → วิธีแก้ → ผลลัพธ์ (ถ้ามี) → บทเรียน/ข้อคิด
**สิ่งที่ไม่ควรทำ:**
- ไม่ขายบริการตรง ๆ ใน blog — ให้คนอ่านแล้วเกิดความเชื่อถือ แล้วเขาจะกลับมาเอง
- ไม่ใช้ "ครบวงจร ทันสมัย" — ใช้ตัวเลขแทน
- ไม่อ้างอิง source ที่ไม่มีจริง
**SEO:** แต่ละ blog ควรมี:
- Title ที่มีคีย์เวิร์ด (เช่น "AI ไม่ได้แพงเสมอไป")
- Meta description ที่ดึงดูด
- Internal link ไปหน้า services/portfolio
- CTA ท้ายบทความ: "อยากให้ช่วยดูเคสของคุณ? นัดคุย 30 นาทีฟรี"

22
PLAN-REVIEW-LOG.md Normal file
View File

@@ -0,0 +1,22 @@
# Plan Review Log: Footer Component + Remove Yellow Lines from Process Section
Act 1 (grill) complete — plan locked with the user. MAX_ROUNDS=5.
## Round 1 — Codex
พบ 10 issues (3 critical, 3 significant, 4 minor):
1. 🔴 PageShell layout ignored — ควรแก้ผ่าน PageShell
2. 🔴 Privacy/Terms pages ไม่มี — dead links
3. 🔴 Liquid glass markup pattern ไม่ระบุ
4. 🟡 service-proof-grid yellow accent missed
5. 🟡 Mobile layout spec ambiguous
6. 🟡 Step-flow visual cue removed without alternative
7. 🟡 Missing semantic `<footer>` element
8. 🟠 LINE URL unspecified
9. 🟠 Logo dimensions omitted
10. 🟠 z-index risk unresolved
### Claude's response
แก้ทั้ง 10 ข้อใน PLAN.md revision
## Round 2 — Codex
All 10 findings addressed. Minor note: footer ควรวางระหว่าง `</main>` กับ floating-cta (ไม่ใช่ inside `<main>`).
VERDICT: APPROVED (2 rounds)

71
PLAN.md Normal file
View File

@@ -0,0 +1,71 @@
# Plan: Footer Component + Remove Yellow Lines from Process Section
_Locked via grill — by Claude + Kunthawat — Revised Round 1_
## Goal
สร้าง Footer component ใหม่ด้วย liquid glass style และลบเส้นสีเหลืองออกจาก How we work section
## Approach
### 1. ลบเส้นสีเหลืองจาก Process Section (`src/styles/global.css`)
- ลบ `.process-grid::before` (เส้นแนวนอนสีเหลือง) → `display: none`
- ลบ `.process-grid article::after` (วงกลม ">" สีเหลืองระหว่าง step) → `display: none`
- `.process-grid .step-number`: เปลี่ยน `background: var(--yellow)``background: rgb(255 255 255 / .5)` + ลบ yellow box-shadow
- `.service-proof-grid .process-grid .step-number`: override สีเหลืองเหมือนกัน (scope เพิ่ม)
- **หมายเหตุ:** step numbers (01, 02, 03, 04) ยังคงแสดง sequential flow อยู่แล้ว ไม่ต้องเพิ่ม connector แทน
### 2. สร้าง Footer Component (`src/components/Footer.astro`)
- ใช้ `<footer>` semantic element
- ใช้ liquid glass style (ต้องมี 3 child divs):
```html
<footer class="site-footer liquid-glass liquidGlass-wrapper">
<div class="liquidGlass-effect" aria-hidden="true"></div>
<div class="liquidGlass-tint" aria-hidden="true"></div>
<div class="liquidGlass-shine" aria-hidden="true"></div>
<!-- content -->
</footer>
```
- `position: relative; z-index: auto` (ไม่ทับ lead-panel z-index: 110)
### 3. เนื้อหา Footer
**ซ้าย:**
- โลโก้: `/images/logos/logo-long-black.png` (width="205" height="36")
- คำอธิบาย: "ที่ปรึกษาเว็บไซต์ การตลาด และ AI สำหรับ SME"
**กลาง:**
- ลิงก์: หน้าแรก / บริการ / ผลงาน / บล็อก / ติดต่อ / นโยบายความเป็นส่วนตัว / เงื่อนไขการใช้งาน
**ขวา:**
- LINE: @moreminimore (link: https://line.me/ti/p/@moreminimore)
- Email: contact@moreminimore.com
**ล่าง:**
- Copyright: © {new Date().getFullYear()} MoreminiMore
### 4. Responsive
- Desktop (>768px): 3 columns (grid-template-columns: 1fr 1fr 1fr)
- Mobile (≤768px): vertical stack (flex-direction: column) — เรียง: โลโก้ → ลิงก์ → ติดต่อ → copyright
### 5. Integration Strategy
- **PageShell pages** (about, services, blog, blog/[slug], contact, faq, portfolio, services/[slug]):
เพิ่ม `<Footer />` import + render ใน `src/components/PageShell.astro` ก่อน `</main>` หรือก่อน `</body>`
- **index.astro** (standalone, ไม่ใช้ PageShell):
เพิ่ม `<Footer />` import + render ก่อน `</body>` โดยตรง
### 6. สร้าง Placeholder Pages
- สร้าง `src/pages/privacy.astro` (placeholder — "นโยบายความเป็นส่วนตัว กำลังอัพเดท")
- สร้าง `src/pages/terms.astro` (placeholder — "เงื่อนไขการใช้งาน กำลังอัพเดท")
- ใช้ PageShell layout เหมือนหน้าอื่น
## Key decisions & tradeoffs
- ใช้ liquid glass style เดียวกับ navbar เพื่อความ cohesive
- ลบเส้นเหลืองทั้งหมด — step numbers ยังบ่งบอกลำดับอยู่
- ใช้ dynamic year (`new Date().getFullYear()`) ใน copyright (Astro SSG → build-time inlined)
- Footer ใน PageShell = แก้จุดเดียว ครอบคลุม 8 หน้า
- z-index: auto (ไม่ทับ lead-panel)
## Risks / open questions
- Privacy/Terms pages เป็น placeholder — ต้องเพิ่ม content ทีหลัง
- Logo อาจต้องเปลี่ยนเป็นสีขาวเมื่ออยู่บนพื้นเข้ม (invert)
## Out of scope
- ไม่แก้ไขหน้า Privacy/Terms content จริง
- ไม่เพิ่ม social media icons (Facebook/X/LinkedIn)

View File

@@ -1,43 +0,0 @@
# Astro Starter Kit: Minimal
```sh
npm create astro@latest -- --template minimal
```
> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun!
## 🚀 Project Structure
Inside of your Astro project, you'll see the following folders and files:
```text
/
├── public/
├── src/
│ └── pages/
│ └── index.astro
└── package.json
```
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
Any static assets, like images, can be placed in the `public/` directory.
## 🧞 Commands
All commands are run from the root of the project, from a terminal:
| Command | Action |
| :------------------------ | :----------------------------------------------- |
| `npm install` | Installs dependencies |
| `npm run dev` | Starts local dev server at `localhost:4321` |
| `npm run build` | Build your production site to `./dist/` |
| `npm run preview` | Preview your build locally, before deploying |
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
| `npm run astro -- --help` | Get help using the Astro CLI |
## 👀 Want to learn more?
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).

View File

@@ -1,15 +1,8 @@
// @ts-check
import { defineConfig } from 'astro/config';
import react from "@astrojs/react";
import mdx from "@astrojs/mdx";
// All content is markdown → static output. No server runtime needed.
export default defineConfig({
output: "static",
integrations: [
react(),
mdx(),
],
image: { layout: "constrained", responsiveStyles: true },
devToolbar: { enabled: true },
output: 'static',
image: { layout: 'constrained', responsiveStyles: true },
devToolbar: { enabled: false },
});

153
google-apps-script/SETUP.md Normal file
View File

@@ -0,0 +1,153 @@
# Google Apps Script Lead Form Setup
ใช้ไฟล์นี้เพื่อตั้งระบบรับ lead จากฟอร์ม MoreminiMore แบบง่ายก่อน โดยให้ Google Apps Script บันทึกข้อมูลลง Google Sheet และส่งอีเมลแจ้งเตือนเข้า Gmail/Google Workspace
อ้างอิง official docs:
- Apps Script Web App deployment: https://developers.google.com/apps-script/guides/web
- Apps Script MailApp: https://developers.google.com/apps-script/reference/mail/mail-app
## สิ่งที่ต้องมี
- Google account หรือ Google Workspace account ที่จะใช้รับ lead
- แนะนำให้ใช้บัญชีของโดเมนบริษัท เช่น `contact@moreminimore.com`
- Google Sheet ใหม่ 1 ไฟล์ สำหรับเก็บ lead
## ขั้นตอนติดตั้ง
### 1. สร้าง Google Sheet
1. เข้า Google Drive
2. สร้าง Google Sheet ใหม่
3. ตั้งชื่อเช่น `MoreminiMore Website Leads`
4. ไม่ต้องสร้าง column เอง script จะสร้าง header ให้ตอนมี lead แรก
### 2. เปิด Apps Script จาก Sheet
1. ใน Google Sheet ไปที่ `Extensions`
2. เลือก `Apps Script`
3. จะเปิดหน้า Apps Script editor
4. ลบโค้ดเดิมใน `Code.gs`
5. Copy โค้ดทั้งหมดจาก `google-apps-script/lead-form.gs`
6. Paste ลงใน `Code.gs`
### 3. แก้อีเมลผู้รับ
ในไฟล์ `Code.gs` หา:
```js
const CONFIG = {
RECIPIENT_EMAIL: 'contact@moreminimore.com',
```
เปลี่ยน `RECIPIENT_EMAIL` เป็นอีเมลที่จะรับแจ้งเตือน lead
ถ้าใช้ `contact@moreminimore.com` อยู่แล้ว ไม่ต้องแก้
### 4. Save project
1. กด Save
2. ตั้งชื่อ project เช่น `MoreminiMore Lead Form`
### 5. Deploy เป็น Web App
ตาม official docs ของ Google ให้ deploy web app โดย:
1. มุมขวาบน กด `Deploy`
2. เลือก `New deployment`
3. ตรง `Select type` กด icon ตั้งค่า แล้วเลือก `Web app`
4. ตั้งค่า:
- Description: `MoreminiMore lead form endpoint`
- Execute as: `Me`
- Who has access: `Anyone`
5. กด `Deploy`
6. Google จะขอ authorize permissions
7. เลือก account ของคุณ
8. อนุญาตสิทธิ์ที่เกี่ยวกับ Google Sheets และส่งอีเมล
9. Copy `Web app URL` เก็บไว้
URL จะหน้าตาประมาณ:
```text
https://script.google.com/macros/s/xxxxxxxxxxxxxxxx/exec
```
### 6. ทดสอบ endpoint
เปิด URL ที่ copy มาใน browser ถ้าระบบทำงาน จะเห็น JSON ประมาณ:
```json
{"ok":true,"service":"MoreminiMore lead form"}
```
### 7. เอา URL ไปใส่ในเว็บ
ตอน implement หน้าเว็บ ให้ตั้งค่า URL นี้เป็น endpoint ของฟอร์ม
ข้อควรระวัง: Apps Script web app มักไม่เหมาะกับ fetch ที่ต้องอ่าน JSON response ข้ามโดเมนแบบเต็ม ๆ เพราะอาจติด CORS ได้ วิธีที่เหมาะกับ static site คือส่งข้อมูลแบบ simple POST หรือ `fetch(..., { mode: "no-cors" })` แล้วให้หน้าเว็บแสดง success state หลัง request ถูกส่งออกไป
ตัวอย่าง payload ที่เว็บควรส่ง:
```json
{
"name": "คุณเอ",
"phone": "0800000000",
"email": "owner@example.com",
"problems": ["ads_not_worth_it", "wrong_leads"],
"message": "ยิงแอดอยู่ แต่ยอดขายไม่คุ้ม อยากรู้ว่าควรแก้อะไรก่อน",
"pageUrl": "https://moreminimore.com/",
"userAgent": "browser user agent"
}
```
## Problem Keys ที่ script รองรับ
| Key | ข้อความ |
| --- | --- |
| `website_no_leads` | เว็บมีอยู่แล้ว แต่ไม่ค่อยมีลูกค้าทัก |
| `ads_not_worth_it` | ยิงแอดอยู่ แต่ยอดขายไม่คุ้ม |
| `wrong_leads` | มีคนทักมา แต่ไม่ใช่ลูกค้าที่ใช่ |
| `slow_or_error_work` | ทีมงานทำงานเดิม ๆ แต่ทำงานช้า หรือผิดพลาดบ่อย |
| `ai_not_sure` | อยากใช้ AI แต่ไม่รู้เริ่มตรงไหน |
| `not_sure` | ยังไม่แน่ใจว่าควรแก้อะไรก่อน |
## วิธีลดโอกาสเมลเข้าขยะ
Apps Script จะส่งเมลจากบัญชี Google ที่ deploy script ดังนั้นควร:
- ใช้บัญชี Google Workspace ของบริษัท ถ้ามี
- ตั้งค่า SPF/DKIM/DMARC ของโดเมนให้ถูกต้อง
- ใช้ subject ปกติ ไม่ spammy เช่น `มีโจทย์ธุรกิจใหม่จากเว็บไซต์ MoreminiMore`
- อย่าใช้ email ลูกค้าเป็น `From`
- ให้ script ใช้ email ลูกค้าเป็น `Reply-To` แทน
- เนื้อหาอีเมลควรเป็นข้อความสะอาด ไม่ใส่คำขายหรือ link เยอะ
## เวลาแก้ script หลัง deploy
ถ้าแก้โค้ดหลังจาก deploy แล้ว:
1. กด `Deploy`
2. เลือก `Manage deployments`
3. เลือก deployment เดิม
4. กด edit
5. เลือก version ใหม่ หรือ new version
6. กด deploy/update
ถ้าสร้าง deployment ใหม่ URL อาจเปลี่ยน ต้องเอา URL ใหม่ไปใส่ในเว็บอีกครั้ง
## Debug เบื้องต้น
ถ้า submit แล้วไม่เข้า Sheet:
1. เปิด Apps Script
2. ดูเมนู `Executions`
3. เปิด execution ล่าสุดเพื่อดู error
4. ตรวจว่า deploy เป็น `Who has access: Anyone`
5. ตรวจว่าใช้ URL ที่ลงท้าย `/exec` ไม่ใช่ `/dev`
ถ้าเข้า Sheet แต่ไม่ส่งเมล:
1. ตรวจสิทธิ์ MailApp ตอน authorize
2. ตรวจ `RECIPIENT_EMAIL`
3. ตรวจ quota ของ Google account
4. ดู error ใน `Executions`

View File

@@ -0,0 +1,290 @@
/**
* MoreminiMore lead form endpoint.
*
* Recommended setup:
* 1. Create a Google Sheet for leads.
* 2. Open Extensions > Apps Script.
* 3. Paste this entire file into Code.gs.
* 4. Update CONFIG.RECIPIENT_EMAIL.
* 5. Deploy as Web app.
*/
const CONFIG = {
RECIPIENT_EMAIL: 'contact@moreminimore.com',
SHEET_NAME: 'Leads',
TIMEZONE: 'Asia/Bangkok',
EMAIL_SUBJECT: 'มีโจทย์ธุรกิจใหม่จากเว็บไซต์ MoreminiMore',
};
const PROBLEM_LABELS = {
website_no_leads: 'เว็บมีอยู่แล้ว แต่ไม่ค่อยมีลูกค้าทัก',
ads_not_worth_it: 'ยิงแอดอยู่ แต่ยอดขายไม่คุ้ม',
wrong_leads: 'มีคนทักมา แต่ไม่ใช่ลูกค้าที่ใช่',
slow_or_error_work: 'ทีมงานทำงานเดิม ๆ แต่ทำงานช้า หรือผิดพลาดบ่อย',
ai_not_sure: 'อยากใช้ AI แต่ไม่รู้เริ่มตรงไหน',
not_sure: 'ยังไม่แน่ใจว่าควรแก้อะไรก่อน',
};
function doGet() {
return jsonResponse({
ok: true,
service: 'MoreminiMore lead form',
});
}
function doPost(e) {
try {
const data = parseRequest(e);
if (isSpam(data)) {
return jsonResponse({ ok: true, skipped: true });
}
const lead = normalizeLead(data);
const validation = validateLead(lead);
if (!validation.ok) {
return jsonResponse({
ok: false,
error: validation.error,
});
}
const lock = LockService.getScriptLock();
lock.waitLock(10000);
try {
appendLead(lead);
} finally {
lock.releaseLock();
}
sendLeadEmail(lead);
return jsonResponse({
ok: true,
message: 'Lead received',
diagnosis: buildLightDiagnosis(lead.problems),
});
} catch (error) {
console.error(error);
return jsonResponse({
ok: false,
error: 'ระบบรับข้อมูลมีปัญหา กรุณาลองใหม่อีกครั้ง',
});
}
}
function parseRequest(e) {
if (!e) return {};
const contentType = String(e.postData && e.postData.type || '').toLowerCase();
const raw = e.postData && e.postData.contents;
if (raw && contentType.indexOf('application/json') !== -1) {
return JSON.parse(raw);
}
if (raw && contentType.indexOf('text/plain') !== -1) {
try {
return JSON.parse(raw);
} catch (error) {
return e.parameter || {};
}
}
return e.parameter || {};
}
function normalizeLead(data) {
const problems = normalizeProblems(data.problems || data.problem || data.problemKeys);
return {
createdAt: Utilities.formatDate(new Date(), CONFIG.TIMEZONE, 'yyyy-MM-dd HH:mm:ss'),
name: cleanText(data.name),
phone: cleanText(data.phone),
email: cleanText(data.email).toLowerCase(),
message: cleanText(data.message || data.details || data.note),
problems,
pageUrl: cleanText(data.pageUrl || data.url),
userAgent: cleanText(data.userAgent),
};
}
function normalizeProblems(value) {
if (!value) return [];
if (Array.isArray(value)) {
return value.map(String).map(cleanText).filter(Boolean);
}
return String(value)
.split(',')
.map(cleanText)
.filter(Boolean);
}
function validateLead(lead) {
if (!lead.name) {
return { ok: false, error: 'กรุณาใส่ชื่อ' };
}
if (!lead.phone && !lead.email) {
return { ok: false, error: 'ใส่เบอร์โทรหรืออีเมลอย่างใดอย่างหนึ่งก็ได้' };
}
if (lead.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(lead.email)) {
return { ok: false, error: 'รูปแบบอีเมลไม่ถูกต้อง' };
}
if (lead.message.length > 2000) {
return { ok: false, error: 'รายละเอียดโจทย์ยาวเกินไป' };
}
return { ok: true };
}
function appendLead(lead) {
const sheet = getLeadSheet();
sheet.appendRow([
lead.createdAt,
lead.name,
lead.phone,
lead.email,
problemLabels(lead.problems).join(', '),
lead.message,
buildLightDiagnosis(lead.problems),
lead.pageUrl,
lead.userAgent,
]);
}
function getLeadSheet() {
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
let sheet = spreadsheet.getSheetByName(CONFIG.SHEET_NAME);
if (!sheet) {
sheet = spreadsheet.insertSheet(CONFIG.SHEET_NAME);
}
if (sheet.getLastRow() === 0) {
sheet.appendRow([
'วันที่ส่ง',
'ชื่อ',
'เบอร์โทร',
'อีเมล',
'ปัญหาที่เลือก',
'รายละเอียด',
'แนวทางเริ่มต้น',
'Page URL',
'User Agent',
]);
sheet.setFrozenRows(1);
}
return sheet;
}
function sendLeadEmail(lead) {
const labels = problemLabels(lead.problems);
const diagnosis = buildLightDiagnosis(lead.problems);
const plainBody = [
'มีโจทย์ธุรกิจใหม่จากเว็บไซต์ MoreminiMore',
'',
`ชื่อ: ${lead.name}`,
`เบอร์โทร: ${lead.phone || '-'}`,
`อีเมล: ${lead.email || '-'}`,
`ปัญหาที่เลือก: ${labels.length ? labels.join(', ') : '-'}`,
'',
'รายละเอียด:',
lead.message || '-',
'',
`แนวทางเริ่มต้น: ${diagnosis}`,
'',
`Page URL: ${lead.pageUrl || '-'}`,
`เวลาที่ส่ง: ${lead.createdAt}`,
].join('\n');
const htmlBody = `
<div style="font-family:Arial,sans-serif;line-height:1.6;color:#17120a">
<h2 style="margin:0 0 12px">มีโจทย์ธุรกิจใหม่จากเว็บไซต์ MoreminiMore</h2>
<p><strong>ชื่อ:</strong> ${escapeHtml(lead.name)}</p>
<p><strong>เบอร์โทร:</strong> ${escapeHtml(lead.phone || '-')}</p>
<p><strong>อีเมล:</strong> ${escapeHtml(lead.email || '-')}</p>
<p><strong>ปัญหาที่เลือก:</strong> ${escapeHtml(labels.length ? labels.join(', ') : '-')}</p>
<p><strong>รายละเอียด:</strong><br>${escapeHtml(lead.message || '-').replace(/\n/g, '<br>')}</p>
<p><strong>แนวทางเริ่มต้น:</strong> ${escapeHtml(diagnosis)}</p>
<hr>
<p style="color:#666;font-size:13px">
Page URL: ${escapeHtml(lead.pageUrl || '-')}<br>
เวลาที่ส่ง: ${escapeHtml(lead.createdAt)}
</p>
</div>
`;
const options = {
name: 'MoreminiMore Website',
htmlBody,
};
if (lead.email) {
options.replyTo = lead.email;
}
MailApp.sendEmail(CONFIG.RECIPIENT_EMAIL, CONFIG.EMAIL_SUBJECT, plainBody, options);
}
function buildLightDiagnosis(problemKeys) {
const keys = problemKeys || [];
if (keys.indexOf('ads_not_worth_it') !== -1 || keys.indexOf('wrong_leads') !== -1) {
return 'น่าจะเริ่มจากการดูข้อมูลแอด กลุ่มเป้าหมาย และคุณภาพลูกค้าที่ทักเข้ามาก่อน';
}
if (keys.indexOf('website_no_leads') !== -1) {
return 'น่าจะเริ่มจากการดูเว็บ เส้นทางลูกค้า และจุดที่ควรชวนให้ติดต่อก่อน';
}
if (keys.indexOf('slow_or_error_work') !== -1) {
return 'น่าจะเริ่มจากการดูขั้นตอนทำงานซ้ำ จุดที่ช้า และจุดที่ผิดพลาดบ่อยก่อน';
}
if (keys.indexOf('ai_not_sure') !== -1) {
return 'น่าจะเริ่มจากการดูงานจริงของทีมก่อน แล้วค่อยเลือกจุดที่ AI ช่วยได้อย่างเหมาะสม';
}
return 'เราจะเริ่มจากการทำความเข้าใจธุรกิจและข้อมูลที่มีอยู่ก่อน แล้วค่อยแนะนำทางที่คุ้มที่สุด';
}
function problemLabels(problemKeys) {
return (problemKeys || []).map(function (key) {
return PROBLEM_LABELS[key] || key;
});
}
function isSpam(data) {
return Boolean(data.website || data.company_url || data.url2);
}
function cleanText(value) {
return String(value || '')
.replace(/\r/g, '')
.trim()
.slice(0, 2000);
}
function escapeHtml(value) {
return String(value || '')
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;');
}
function jsonResponse(data) {
return ContentService
.createTextOutput(JSON.stringify(data))
.setMimeType(ContentService.MimeType.JSON);
}

6122
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,8 @@
{
"name": "moreminimore-site",
"type": "module",
"version": "0.0.1",
"version": "1.0.0",
"private": true,
"engines": {
"node": ">=22.12.0"
},
@@ -12,10 +13,6 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/mdx": "^5.0.6",
"@astrojs/react": "^5.0.5",
"astro": "^6.2.2",
"react": "^19.2.5",
"react-dom": "^19.2.5"
"astro": "^6.2.2"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1 +0,0 @@
<svg fill="#0866FF" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Facebook</title><path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z"/></svg>

Before

Width:  |  Height:  |  Size: 558 B

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 36 36" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-6,-6)">
<path d="M12.5,42L35.5,42C39.09,42 42,39.09 42,35.5L42,12.5C42,8.91 39.09,6 35.5,6L12.5,6C8.91,6 6,8.91 6,12.5L6,35.5C6,39.09 8.91,42 12.5,42Z" style="fill:rgb(0,195,0);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,-6,-6)">
<path d="M37.113,22.417C37.113,16.552 31.233,11.78 24.006,11.78C16.779,11.78 10.898,16.552 10.898,22.417C10.898,27.675 15.561,32.079 21.86,32.912C22.287,33.004 22.868,33.194 23.015,33.558C23.147,33.889 23.101,34.408 23.057,34.743C23.057,34.743 22.904,35.668 22.87,35.865C22.813,36.196 22.607,37.161 24.005,36.572C25.404,35.983 31.553,32.127 34.303,28.961L34.302,28.961C36.203,26.879 37.113,24.764 37.113,22.417ZM18.875,25.907L16.271,25.907C15.892,25.907 15.584,25.599 15.584,25.219L15.584,20.01C15.584,19.631 15.892,19.323 16.271,19.323C16.65,19.323 16.958,19.631 16.958,20.01L16.958,24.531L18.875,24.531C19.254,24.531 19.562,24.839 19.562,25.218C19.562,25.598 19.254,25.907 18.875,25.907ZM21.568,25.219C21.568,25.598 21.26,25.907 20.881,25.907C20.502,25.907 20.194,25.599 20.194,25.219L20.194,20.01C20.194,19.631 20.502,19.323 20.881,19.323C21.26,19.323 21.568,19.631 21.568,20.01L21.568,25.219ZM27.838,25.219C27.838,25.516 27.65,25.778 27.368,25.871C27.297,25.895 27.223,25.907 27.15,25.907C26.935,25.907 26.73,25.804 26.601,25.632L23.932,21.997L23.932,25.219C23.932,25.598 23.624,25.907 23.244,25.907C22.865,25.907 22.556,25.599 22.556,25.219L22.556,20.01C22.556,19.714 22.745,19.452 23.026,19.358C23.097,19.334 23.17,19.323 23.244,19.323C23.458,19.323 23.664,19.426 23.793,19.598L26.463,23.233L26.463,20.01C26.463,19.631 26.772,19.323 27.151,19.323C27.53,19.323 27.838,19.631 27.838,20.01L27.838,25.219ZM32.052,21.927C32.431,21.927 32.74,22.235 32.74,22.615C32.74,22.994 32.432,23.302 32.052,23.302L30.135,23.302L30.135,24.532L32.052,24.532C32.431,24.532 32.74,24.84 32.74,25.219C32.74,25.598 32.431,25.907 32.052,25.907L29.448,25.907C29.07,25.907 28.761,25.599 28.761,25.219L28.761,20.011C28.761,19.632 29.069,19.324 29.448,19.324L32.052,19.324C32.431,19.324 32.74,19.632 32.74,20.011C32.74,20.39 32.432,20.698 32.052,20.698L30.135,20.698L30.135,21.928L32.052,21.928L32.052,21.927Z" style="fill:white;fill-rule:nonzero;"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -1 +0,0 @@
<svg role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><path fill="#00c300" d="M12.5,42h23c3.59,0,6.5-2.91,6.5-6.5v-23C42,8.91,39.09,6,35.5,6h-23C8.91,6,6,8.91,6,12.5v23C6,39.09,8.91,42,12.5,42z"/><path fill="#fff" d="M37.113,22.417c0-5.865-5.88-10.637-13.107-10.637s-13.108,4.772-13.108,10.637c0,5.258,4.663,9.662,10.962,10.495c0.427,0.092,1.008,0.282,1.155,0.646c0.132,0.331,0.086,0.85,0.042,1.185c0,0-0.153,0.925-0.187,1.122c-0.057,0.331-0.263,1.296,1.135,0.707c1.399-0.589,7.548-4.445,10.298-7.611h-0.001C36.203,26.879,37.113,24.764,37.113,22.417z M18.875,25.907h-2.604c-0.379,0-0.687-0.308-0.687-0.688V20.01c0-0.379,0.308-0.687,0.687-0.687c0.379,0,0.687,0.308,0.687,0.687v4.521h1.917c0.379,0,0.687,0.308,0.687,0.687C19.562,25.598,19.254,25.907,18.875,25.907z M21.568,25.219c0,0.379-0.308,0.688-0.687,0.688s-0.687-0.308-0.687-0.688V20.01c0-0.379,0.308-0.687,0.687-0.687s0.687,0.308,0.687,0.687V25.219z M27.838,25.219c0,0.297-0.188,0.559-0.47,0.652c-0.071,0.024-0.145,0.036-0.218,0.036c-0.215,0-0.42-0.103-0.549-0.275l-2.669-3.635v3.222c0,0.379-0.308,0.688-0.688,0.688c-0.379,0-0.688-0.308-0.688-0.688V20.01c0-0.296,0.189-0.558,0.47-0.652c0.071-0.024,0.144-0.035,0.218-0.035c0.214,0,0.42,0.103,0.549,0.275l2.67,3.635V20.01c0-0.379,0.309-0.687,0.688-0.687c0.379,0,0.687,0.308,0.687,0.687V25.219z M32.052,21.927c0.379,0,0.688,0.308,0.688,0.688c0,0.379-0.308,0.687-0.688,0.687h-1.917v1.23h1.917c0.379,0,0.688,0.308,0.688,0.687c0,0.379-0.309,0.688-0.688,0.688h-2.604c-0.378,0-0.687-0.308-0.687-0.688v-2.603c0-0.001,0-0.001,0-0.001c0,0,0-0.001,0-0.001v-2.601c0-0.001,0-0.001,0-0.002c0-0.379,0.308-0.687,0.687-0.687h2.604c0.379,0,0.688,0.308,0.688,0.687s-0.308,0.687-0.688,0.687h-1.917v1.23H32.052z"/></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1 +0,0 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="#0A66C2"><title>LinkedIn</title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>

Before

Width:  |  Height:  |  Size: 626 B

View File

@@ -1 +0,0 @@
<svg fill="#000000" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>X</title><path d="M14.234 10.162 22.977 0h-2.072l-7.591 8.824L7.251 0H.258l9.168 13.343L.258 24H2.33l8.016-9.318L16.749 24h6.993zm-2.837 3.299-.929-1.329L3.076 1.56h3.182l5.965 8.532.929 1.329 7.754 11.09h-3.182z"/></svg>

Before

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 270 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 477 B

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -1,22 +0,0 @@
{
"name": "MoreminiMore",
"short_name": "MoreminiMore",
"description": "ที่ปรึกษาที่วางกลยุทธ์จากข้อมูล ไม่ใช่จากประสบการณ์ล้วน ๆ — รับทำเว็บ ที่ปรึกษาการตลาด และวางระบบ AI ในองค์กร",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#fed400",
"background_color": "#ffffff",
"display": "standalone",
"start_url": "/",
"lang": "th"
}

Binary file not shown.

View File

@@ -1,277 +0,0 @@
# คำถามสำหรับปรับปรุงเนื้อหาเว็บ moreminimore
> ตอบข้อไหนได้ก็ตอบ ข้อไหนไม่รู้หรือไม่อยากตอบก็เว้นว่างไว้
> พิมพ์สั้น ๆ ก็ได้ เช่น `A1: คนที่ทำเว็บแล้วดูแลต่อ ไม่ทิ้ง` — พอแล้ว เอาไปขยายต่อได้
>
> เมื่อเติมคำตอบเสร็จ ให้บอก path ของไฟล์นี้กลับมา เช่น `~/Desktop/questions-for-content.md` หรือ `moreminimore-astroreal/questions-for-content.md` หลัง `git push`
---
## 🔴 กลุ่ม A — ตัวตน & ตลาด (ตอบก่อนแตะปากกา)
เรื่องพื้นฐานที่ต้องชัดก่อนเขียนอะไร — ถ้าตอบไม่ได้สักข้อ ก็เป็นสัญญาณว่าเว็บยังเขียนไม่ได้
### A1 — คุณเป็นใครในมุมของลูกค้า
ถ้าเพื่อนที่เป็น SME ถามว่า "ทำไมต้องจ้างมอร์มินิมอร์ ทั้ง ๆ ที่มีตัวเลือกเยอะ" คุณตอบยังไงใน 1 ประโยค? (ไม่ใช่ประวัติ — เป็นสิ่งที่ทำให้คุณต่าง)
```
คำตอบ:
```
### A2 — ลูกค้าที่คุณชอบทำงานด้วยที่สุด
เป็นแบบไหน? (ขนาด, อุตสาหกรรม, ลักษณะนิสัย, งบประมาณคร่าว ๆ)
```
คำตอบ:
```
### A3 — ลูกค้าที่คุณไม่อยากรับ
เป็นแบบไหน? (จะเอาไปเขียนเป็นส่วน "ไม่เหมาะกับ" ในเว็บ — ทำให้คนที่ใช่อยากคุยมากขึ้น และลดเคสที่เสียเวลา)
```
คำตอบ:
```
### A4 — งานชิ้นที่ภูมิใจที่สุด
ชิ้นไหน และทำไม? (จะกลายเป็น portfolio flagship — อาจเล่าแบบเจาะลึก 1 หน้าเต็ม)
```
คำตอบ:
```
### A5 — งานชิ้นที่พังหรือเกือบพัง
เกิดอะไรขึ้น แก้ยังไง? (เอาไปเล่าเป็นบทเรียน — แบบนี้ลูกค้าจะเชื่อถือมากกว่า "ผลงานสวยหมด" เพราะดูจริงใจ)
```
คำตอบ:
```
### A6 — SME ไทยทำพลาดเรื่องเดิมซ้ำ ๆ เรื่องอะไร
ช่วง 5 ปีที่ผ่านมา คุณเห็นอะไรซ้ำ ๆ? (คำตอบจะกลายเป็นเสียงของคุณในเว็บ + ไอเดียเขียน blog ได้อีกหลายเรื่อง)
```
คำตอบ:
```
---
## 🟠 กลุ่ม B — เสนอคุณค่า (ตอบก่อนเขียน service page)
เพื่อให้ service page แต่ละหน้าไม่ซ้ำกัน และลูกค้าเห็นว่าต้องเลือกคุณยังไง
### B7 — บริการแต่ละตัวต่างกันตรงไหน
Web / Marketing / Automation / AI Consult — กระบวนการทำงานต่างกันยังไง? ไม่ใช่ "ส่งมอบอะไร" แต่ "ทำงานยังไง"
- **Web (Astro/WordPress)** — workflow เป็นยังไง กี่รอบ feedback ใช้ stack อะไร
```
คำตอบ:
```
- **Marketing** — ใช้ GA4 / Meta Pixel / SEO tools อะไร วัดผลยังไง
```
คำตอบ:
```
- **Automation** — ใช้ n8n / Make / Zapier / custom code เลือกยังไง
```
คำตอบ:
```
- **AI Consult** — ใช้ RAG / fine-tune / agent อะไร เหมาะกับ case ไหน
```
คำตอบ:
```
### B8 — ถ้าทำได้อย่างเดียว ควรเริ่มจากอะไร
ลูกค้ามีงบจำกัด ทำได้อย่างเดียว — อันไหนคุ้มสุด? (ตอบตรง ๆ ตามจริง ไม่ใช่คำตอบที่ขายดีที่สุด — ความจริงใจตรงนี้จะกลายเป็นเครื่องมือปิดการขาย)
```
คำตอบ:
```
### B9 — คิดค่าบริการยังไง
เหมาจ่าย / รายเดือน / เก็บตาม sprint / value-based? ช่วงราคาคร่าว ๆ ของแต่ละบริการ:
- **Web Development** — โปรเจกต์ทั่วไปอยู่ที่ ____ บาท
```
คำตอบ:
```
- **Marketing** — ค่า setup + รายเดือน
```
คำตอบ:
```
- **Automation** — ค่าพัฒนา + ค่าดูแล
```
คำตอบ:
```
- **AI Consult** — ค่า consult / ชั่วโมง / โปรเจกต์
```
คำตอบ:
```
### B10 — คำถาม 5 ข้อที่ถามลูกค้าในการคุยครั้งแรก
ตอนคุยกันครั้งแรก คุณถามอะไรบ้าง? (จะเอาไปใส่หน้า Contact เป็น "ก่อนคุย เตรียมคำตอบพวกนี้มา" — คนที่อ่านแล้วตอบได้ = lead ที่มีคุณภาพ)
```
คำตอบ:
```
---
## 🟡 กลุ่ม C — ความน่าเชื่อถือ (ตอบก่อนเขียน About / Portfolio)
ทำให้ soloprenuer กลายเป็นข้อได้เปรียบ ไม่ใช่จุดอ่อน
### C11 — เบื้องหลังการทำงานจริง
นั่งทำที่ไหน ใช้เครื่องอะไร stack/workflow แบบไหน — เล่าแบบที่คนอ่านแล้วเห็นภาพ "คนคนนี้จริงจัง"
```
คำตอบ:
```
### C12 — คำพูดลูกค้าที่จำไม่ลืม
เคยมีลูกค้าพูดอะไรที่ทำให้คุณจำได้? (quote แบบนี้แพ้ portfolio 10 หน้า — ถ้ามีหลาย quote บอกมาหลาย ๆ อันได้)
```
คำตอบ:
```
### C13 — กำลังเรียนรู้ / ทดลองอะไรอยู่
เช่น RAG, GEO, AI agent workflow, automation platform ใหม่ ๆ — ทำให้เห็นว่าคุณยังเดินหน้า ไม่หยุดนิ่ง
```
คำตอบ:
```
### C14 — ตัวเลขจริง ๆ ตอนนี้
ไม่ต้องสวย แค่ให้ calibrate เสียงและระดับความกล้าในการ claim:
- ทำมากี่ปี
- ส่งมอบกี่โปรเจกต์
- ลูกค้าซ้ำกี่คน
- ราคาเฉลี่ยต่อโปรเจกต์
- (ไม่ต้องเอาลงเว็บ แค่บอกผม)
```
คำตอบ:
```
---
## 🟢 กลุ่ม D — มุมมอง & เสียง (ตอบก่อนเขียนทุกหน้า)
เสียงที่จดจำได้ = มุมมองที่ชัด ไม่ใช่ถ้อยคำที่สวย
### D15 — เรื่องที่ไม่เห็นด้วยในวงการ
AI/Web agency ทำอะไรที่คุณคิดว่าผิด / เกินจำเป็น / หลอกลูกค้า? (ความเห็นต่าง = เสียงที่จดจำได้ เช่น "เราไม่เชื่อว่า SME ต้องมี chatbot ทุกเว็บ")
```
คำตอบ:
```
### D16 — 1 ประโยคที่อยากให้คนจำ
ถ้าเขียนเว็บได้แค่ 1 ประโยค อยากให้คนจำว่ามอร์มินิมอร์เป็นแบบไหน — ประโยคนั้นคืออะไร?
```
คำตอบ:
```
### D17 — โทนเสียงที่อยากให้เว็บเป็น
เลือก 1-2 ข้อ (หรือผสม):
- [ ] ตรง ๆ ดุ ๆ (เหมือนคุยกับเพื่อน)
- [ ] สุภาพ มืออาชีพ (เหมือนที่ปรึกษา)
- [ ] ขำ ๆ มีอารมณ์ขัน
- [ ] เน้นข้อมูล ไม่มีน้ำ
- [ ] เล่าเรื่อง เป็นกันเอง
- [ ] อื่น ๆ (บอกมา)
```
คำตอบ:
```
### D18 — เว็บที่ชอบ / vibe ที่อยากได้
เว็บคู่แข่ง หรือเว็บต่างประเทศที่ชอบ vibe คล้าย ๆ — ส่งลิงก์มากี่อันก็ได้ พร้อมเหตุผลสั้น ๆ ว่าชอบอะไร
```
คำตอบ:
```
---
## หลังได้คำตอบแล้ว จะทำอะไรต่อ
1. สรุป "เสียงของแบรนด์" ใน 1 หน้า (ไม่เกิน 10 ข้อ)
2. เขียน portfolio แต่ละชิ้นใหม่ — format: `[ชื่อ]. [อุตสาหกรรม]. [ปัญหา]. [สิ่งที่ทำ]. [ตัวเลข]. [เวลา]`
3. เขียน Home page copy ใหม่ — ลด 12 problem cards เหลือ 3-4 ที่เจ็บที่สุด พร้อมเฉลย
4. เขียน Service pages ใหม่ แยกตามเสียงและกระบวนการจริง
5. เขียน About page ใหม่ ให้ soloprenuer กลายเป็นข้อได้เปรียบ
6. เขียน FAQ จากคำถามที่ลูกค้าถามบ่อยจริง ๆ
7. วางแผน Blog topics 5 เรื่อง จากคำตอบ A6 + D15

Binary file not shown.

19
redesign-input/README.md Normal file
View File

@@ -0,0 +1,19 @@
# MoreminiMore Redesign Input
ชุดนี้คือข้อมูลที่ extract ออกจากเว็บเดิมก่อนรื้อใหม่ ใช้เป็นฐานสำหรับวางแผน redesign รอบถัดไป
## Files
- `WEBSITE-CONTENT-EXTRACT.md` - สรุปเนื้อหาเว็บที่ควรพกต่อไป
- `assets/logos/` - logo files ที่ใช้ได้ต่อ
- `assets/portfolio/` - ภาพผลงาน portfolio
- `raw/src-content/` - content collection เดิมแบบ raw
- `raw/src-data/` - data files เดิมแบบ raw
- `raw/BRAND-VOICE.md` - brand voice เดิม
- `raw/moreminimore-content.md` - planning/content draft เดิม
## Important Note
โค้ด implementation เก่า, build output, mockup, และไฟล์ทดลอง ถูกย้ายไปไว้ที่:
`_archive/pre-redesign-2026-06-21/`

View File

@@ -0,0 +1,177 @@
# MoreminiMore Website Content Extract
Extract date: 2026-06-21
เอกสารนี้ดึงเฉพาะเนื้อหาและ asset สำคัญจากเว็บเดิม เพื่อใช้วางแผนใหม่ ไม่ถือว่าเป็น design direction ใหม่
## Brand
- Brand name: MoreminiMore
- Business: ที่ปรึกษาด้านเว็บไซต์ การตลาดออนไลน์ AI และระบบอัตโนมัติสำหรับ SME ไทย
- Core promise: เพิ่มยอดขาย ลดต้นทุน ประหยัดเวลา
- Positioning: เริ่มจากดูข้อมูลจริงก่อน แล้วค่อยเลือกสิ่งที่ควรทำ
- Memorable line from brand voice: เป้าหมายของเราคือการเพิ่มกำไรให้ลูกค้า
- Tone: ตรง สุภาพ เน้นข้อมูล ไม่ขายฝัน ไม่ทำให้เทคโนโลยีดูยากเกินจำเป็น
- Primary CTA: ปรึกษาฟรี 30 นาที
- Secondary CTA: ดูผลงานจริง
## Contact
- Email: contact@moreminimore.com
- Phone: 080-995-5945
- Address: 53 หมู่ 1 ต.บ้านแพ้ว อ.บ้านแพ้ว สมุทรสาคร 74120
- Facebook: https://www.facebook.com/moreminimore
- LINE: https://line.me/ti/p/~539hdlul
- LINE ID: @moreminimore
- LinkedIn: https://www.linkedin.com/company/moreminimore
## Navigation Candidates
- หน้าแรก
- บริการ
- ผลงาน
- บทความ
- FAQ
- เกี่ยวกับ
- ติดต่อ
## Homepage Content To Preserve
### Hero
- Headline option currently used: เพิ่มยอดขาย ลดต้นทุน ประหยัดเวลา
- Supporting copy: ที่ปรึกษาด้านเว็บไซต์ การตลาดออนไลน์ AI และระบบอัตโนมัติสำหรับ SME ไทย เริ่มจากดูข้อมูลจริงก่อน แล้วค่อยเลือกสิ่งที่ควรทำ
### Data First Section
- Heading: เราใช้ข้อมูลจริง เพื่อวางแผนให้คุ้มกว่าเดิม
- Copy: ก่อนเสนอเว็บไซต์ แคมเปญ หรือระบบอัตโนมัติ เราดูข้อมูลจริงก่อนเสมอ ทั้งเว็บเดิม ช่องทางการตลาด พฤติกรรมลูกค้า ผู้สนใจที่ติดต่อเข้ามา และขั้นตอนทำงานของทีม
- Metrics:
- +373% impression จากเคส Dataroot
- +114.2% click หลังปรับกลุ่มเป้าหมาย
- -28.3% ad spend จากข้อมูลที่ยืนยันแล้ว
### Process
- ดูข้อมูล: เข้าใจตัวเลข เว็บไซต์ ช่องทางขาย และขั้นตอนทำงานเดิม
- เลือกทางที่คุ้ม: เลือกสิ่งที่ควรทำก่อนจากโจทย์จริง
- ลงมือทำ: สร้างเว็บ แคมเปญ ระบบอัตโนมัติ หรือวิธีใช้ AI ที่ใช้งานได้จริง
- วัดผลและปรับต่อ: ดูผลหลังใช้งาน แล้วปรับให้คุ้มขึ้น
### Final CTA
- Heading: ไม่แน่ใจว่าควรเริ่มตรงไหน คุยกับเราก่อน
- Copy: เล่าโจทย์ของธุรกิจคุณให้เราฟัง เราจะช่วยดูว่าควรเริ่มจากเว็บไซต์ การตลาด ระบบอัตโนมัติ หรือ AI
## Services
### Website Development
- Short: สร้างเว็บไซต์ที่โหลดไว แก้ไขง่าย วัดผลได้ และเป็นฐานหลักของการขายออนไลน์
- Hero title: เว็บไซต์ที่แก้เองได้ โหลดไว และพร้อมวัดผล
- Hero subtitle: สร้างเว็บไซต์ธุรกิจที่เป็นฐานหลักของการขายออนไลน์ พร้อม SEO โครงสร้างหน้า และช่องทางรับลูกค้าใหม่
- Problems:
- เว็บเดิมโหลดช้า
- แก้ไขเนื้อหาเองไม่ได้
- ไม่มีระบบวัดผล
- SEO และโครงสร้างหน้ายังไม่พร้อม
- ลูกค้าเข้าเว็บแล้วไม่รู้ว่าต้องทำอะไรต่อ
### Marketing Consult
- Short: ดูข้อมูลการตลาดเดิม แล้วปรับกลุ่มเป้าหมาย ช่องทาง และข้อความขายให้ใช้งบคุ้มขึ้น
- Hero title: การตลาดที่เริ่มจากข้อมูล ไม่ใช่ความรู้สึก
- Hero subtitle: เราช่วยดูข้อมูลการตลาดเดิม วิเคราะห์ช่องทาง กลุ่มเป้าหมาย และข้อความขาย เพื่อเลือกสิ่งที่ควรปรับให้ใช้งบคุ้มขึ้น
- Problems:
- ยิงแอดแล้วไม่คุ้ม
- ยอดขายไม่เพิ่มแม้ใช้งบมากขึ้น
- มีคนทักเข้ามา แต่ไม่ใช่ลูกค้าที่มีคุณภาพ
- ไม่รู้ว่าควรทำช่องทางไหนต่อ
- คอนเทนต์ไม่เชื่อมกับการขาย
### Automation Workflow
- Short: วางระบบทำงานอัตโนมัติสำหรับงานที่มีขั้นตอนแน่นอน ช่วยให้ทีมไม่ต้องเสียเวลากับงานซ้ำ
- Hero title: ลดงานซ้ำ ด้วยระบบการทำงานอัตโนมัติ
- Hero subtitle: เราช่วยวางระบบอัตโนมัติด้วยการเขียนแอปหรือเชื่อมต่อเครื่องมือที่มีอยู่ เพื่อให้งานที่มีขั้นตอนชัดเจนทำงานได้เร็วขึ้น และลดเวลาที่พนักงานต้องทำซ้ำ
- Problems:
- พนักงานต้อง copy/paste ข้อมูลซ้ำ
- งานมีขั้นตอนชัดเจน แต่ยังต้องทำมือ
- ข้อมูลกระจายหลายที่
- ผู้สนใจหรืองานเอกสารหลุดระหว่างทาง
- ผู้จัดการต้องตามงานเดิมซ้ำ ๆ
### AI Consult
- Short: ออกแบบวิธีใช้ AI ให้ทำงานร่วมกับพนักงาน และช่วยเก็บความรู้สำคัญไว้ในองค์กร
- Hero title: ให้ AI ทำงานร่วมกับพนักงาน และเก็บความรู้ไว้กับองค์กร
- Hero subtitle: เราช่วยออกแบบวิธีใช้ AI ให้เข้ากับงานจริงของทีม และค่อย ๆ เก็บความรู้จากพนักงาน เพื่อให้ความรู้สำคัญยังอยู่กับองค์กรแม้มีการเปลี่ยนคน
- Problems:
- ความรู้สำคัญอยู่กับพนักงานบางคน
- พนักงานใหม่ต้องใช้เวลานานในการเรียนรู้งาน
- คำถามซ้ำ ๆ ไม่มีแหล่งคำตอบกลาง
- เอกสารกระจัดกระจาย
- ใช้ AI แบบทดลอง แต่ยังไม่เชื่อมกับงานจริง
## Portfolio
| Name | URL | Category | Image |
| --- | --- | --- | --- |
| Dataroot | https://erp.dataroot.asia | ที่ปรึกษาการตลาด | `assets/portfolio/dataroot.png` |
| ทวนทอง 99 | https://tuanthong99.com | อีคอมเมิร์ซ | `assets/portfolio/tuanthong.png` |
| Underdog Marketing | https://underdog.run | Website Development | `assets/portfolio/underdog.png` |
| เทรนเนอร์ซันนี่ | https://trainersunny.com | Website Development | `assets/portfolio/trainersunny.png` |
| Lungfinler | https://lungfinler.com | Website Development | `assets/portfolio/lungfinler.png` |
| Jet Industries | https://jetindustries.co.th | Website Development | `assets/portfolio/jetindustries.png` |
| สำนักงานกฎหมาย ตถาตา | https://lawyernoom.com | Website Development | `assets/portfolio/lawyernoom.png` |
| Baofuling Shop | https://baofulingshop.com | อีคอมเมิร์ซ | `assets/portfolio/baofuling.png` |
| เลือดจระเข้วานิไทย | https://เลือดจระเข้วานิไทย.com | อีคอมเมิร์ซ | `assets/portfolio/luadjob.png` |
## Blog Content
Raw blog posts are preserved in `raw/src-content/blog/`.
- 5 วิธีใช้ AI เพิ่มยอดขายให้ธุรกิจของคุณ
- วิธีสร้าง Content ด้วย AI ที่ Google รัก
- AI สำหรับ SME ไทย: คู่มือฉบับสมบูรณ์
- Digital Transformation Guide
- Marketing Automation Guide
## FAQ Content
Raw FAQ entries are preserved in `raw/src-content/faq/`.
Categories found:
- บริการ
- ราคา
- เวลา
- AI
- Support
## Assets
### Logos
- `assets/logos/logo-long-black.png`
- `assets/logos/logo-long.png`
- `assets/logos/logo.svg`
### Portfolio Images
- `assets/portfolio/baofuling.png`
- `assets/portfolio/dataroot.png`
- `assets/portfolio/jetindustries.png`
- `assets/portfolio/lawyernoom.png`
- `assets/portfolio/luadjob.png`
- `assets/portfolio/lungfinler.png`
- `assets/portfolio/trainersunny.png`
- `assets/portfolio/tuanthong.png`
- `assets/portfolio/underdog.png`
## Raw Sources Preserved
- `raw/src-content/`
- `raw/src-data/`
- `raw/BRAND-VOICE.md`
- `raw/moreminimore-content.md`

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 40" fill="none">
<rect width="40" height="40" rx="8" fill="#fed400"/>
<text x="8" y="28" font-family="Kanit, sans-serif" font-weight="800" font-size="20" fill="#000">M</text>
<text x="52" y="26" font-family="Kanit, sans-serif" font-weight="600" font-size="18" fill="#000">M</text>
<text x="72" y="26" font-family="Noto Sans Thai, sans-serif" font-weight="500" font-size="14" fill="#000">oreMiniMore</text>
</svg>

After

Width:  |  Height:  |  Size: 477 B

View File

@@ -0,0 +1,15 @@
# Dealplustech Portfolio Asset
Dealplustech is included in the rebuilt website portfolio.
- URL: https://www.dealplustech.co.th
- Homepage screenshot captured: `dealplustech.png`
- Screenshot status: clean homepage capture with header/menu visible and cookie banner removed.
- Target style: same portfolio-image treatment as existing clients
- Output filename: `dealplustech.png`
Notes:
- Dealplustech is a new client.
- It should appear as website portfolio work.
- It can also support consulting-adjacent credibility, but should not replace Dataroot main diagnosis story.

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 KiB

View File

@@ -0,0 +1,103 @@
# MoreminiMore — เนื้อหาเว็บไซต์
## ข้อมูลบริษัท
- **ชื่อ**: MoreminiMore
- **ประเภทธุรกิจ**: ที่ปรึกษา AI + การตลาดออนไลน์ สำหรับ SME ไทย
- **จุดเด่น**: เริ่มจากดูสถิติจริง ไม่ใช่เดาว่าควรทำอะไร
- **สัญลักษณ์**: more**mini**more (mini = สีแดง #d4553a)
---
## Hero Section
- **Headline**: พาธุรกิจคุณ **บินสูง** ด้วยข้อมูล
- **Subheadline**: ที่ปรึกษา AI + การตลาดออนไลน์ สำหรับ SME ไทย — เริ่มจากดูสถิติของคุณก่อน
- **CTA 1**: ปรึกษาฟรี 30 นาที →
- **CTA 2**: ดูผลงานจริง
- **Trust badges**: ✓ ปรึกษาฟรี 30 นาที · ✓ ไม่มีผูกมัด · ✓ เห็นผลภายใน 30 วัน
---
## Section 1: ผลลัพธ์จริง
**หัวข้อ**: เราช่วย SME ไทย บินสูงขึ้น
**คำอธิบาย**: ไม่ใช่แค่ทำเว็บ — แต่ช่วยให้ธุรกิจเติบโตจริง ด้วยข้อมูลจริง
| ตัวเลข | หัวข้อ | รายละเอียด |
|--------|--------|-----------|
| +373% | เพิ่มยอดขาย | Dataroot +373% impression ใน 1 เดือน |
| 28% | ลดต้นทุน | ลดงบโฆษณา 28% โดยยอดขายไม่ลด |
| 5 ชม. | ประหยัดเวลา | AI + Automation ทำงานแทน 5 ชม./วัน |
---
## Section 2: Case Study / Dataroot
**หัวข้อ**: จากยิงโฆษณาแบบกว้าง สู่ผลลัพธ์ที่แม่นยำ
**Quote**: "เราไม่ได้ยิงโฆษณาเก่ง เราแค่ดูสถิติ"
### ขั้นตอน:
1. **วิเคราะห์ข้อมูล 3 เดือนย้อนหลัง** — ดูสถิติจริง ไม่ใช่เดา
2. **แยกกลุ่มเป้าหมาย: 4 segments** — ยิงให้แม่น ไม่ใช่ยิงให้กว้าง
3. **ได้ผลลัพธ์ +373% impression** — วัดผลได้จริง
### ตัวเลข:
- +373% IMPRESSION
- +114% CLICK
- 28% AD_SPEND
**CTA**: อ่านเคสเต็ม →
---
## Section 3: บริการ
**หัวข้อ**: เราทำอะไรได้บ้าง
| ไอคอน | บริการ | คำอธิบาย |
|--------|--------|----------|
| 🌐 | รับทำเว็บไซต์ | เว็บที่ Google รัก + โหลดเร็ว ไม่ใช่แค่สวย |
| 🤖 | ที่ปรึกษา AI | AI ที่ใช้ได้จริงกับธุรกิจ ไม่ใช่แค่ buzzword |
| 📈 | การตลาดออนไลน์ | SEO + Ads + Content ที่วัดผลได้ |
| ⚡ | Automation | ทำงานแทน 5 ชม./วัน ด้วย AI |
---
## Section 4: ขั้นตอนทำงาน
**หัวข้อ**: เราทำงานยังไง
| ขั้น | หัวข้อ | รายละเอียด |
|------|--------|-----------|
| 01 | ดูสถิติ | วิเคราะห์ข้อมูลปัจจุบัน — ไม่ใช่เดา |
| 02 | วางแผน | กลยุทธ์ที่เหมาะกับธุรกิจคุณ |
| 03 | ลงมือทำ | ทีมเราทำงานเอง — ไม่ outsource |
| 04 | วัดผล | รายงานผลลัพธ์จริง — ไม่ใช่ vanity metrics |
---
## Section 5: บล็อก
**หัวข้อ**: บทความล่าสุด
| ไอคอน | หัวข้อ | คำอธิบาย |
|--------|--------|----------|
| 📊 | 5 วิธีใช้ AI เพิ่มยอดขาย | เริ่มได้เลยวันนี้ |
| 🎯 | Content แบบไหน Google รัก | อัปเดต SEO 2026 |
| 🔧 | Automation 101 | เริ่มยังไงให้ได้ผล |
---
## Section 6: Contact
**หัวข้อ**: พร้อมที่จะบินสูงขึ้นหรือยัง?
**คำอธิบาย**: ปรึกษาฟรี 30 นาที — ไม่มีผูกมัด
**CTA 1**: ปรึกษาฟรี →
**CTA 2**: ดูผลงานจริง
---
## Navigation
- เกี่ยวกับ
- บริการ
- ผลงาน
- ปรึกษาฟรี → (CTA button)
---
## ภาษา
- **ภาษาไทย** ทั้งหมด
- **Font**: Kanit (หัวข้อ), Itim (เนื้อหา), JetBrains Mono (labels/eyebrow)

Some files were not shown because too many files have changed in this diff Show More