@kennethsolomon/shipkit 3.14.0 → 3.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/README.md +1 -0
  2. package/commands/sk/website.md +11 -0
  3. package/package.json +1 -1
  4. package/skills/sk:website/SKILL.md +471 -0
  5. package/skills/sk:website/references/art-direction.md +210 -0
  6. package/skills/sk:website/references/brief-template.md +121 -0
  7. package/skills/sk:website/references/content-seo.md +143 -0
  8. package/skills/sk:website/references/handoff-template.md +261 -0
  9. package/skills/sk:website/references/launch-checklist.md +99 -0
  10. package/skills/sk:website/references/niche/accountant.md +75 -0
  11. package/skills/sk:website/references/niche/agency.md +75 -0
  12. package/skills/sk:website/references/niche/cafe.md +79 -0
  13. package/skills/sk:website/references/niche/dentist.md +78 -0
  14. package/skills/sk:website/references/niche/ecommerce.md +76 -0
  15. package/skills/sk:website/references/niche/gym.md +75 -0
  16. package/skills/sk:website/references/niche/home-services.md +76 -0
  17. package/skills/sk:website/references/niche/law-firm.md +75 -0
  18. package/skills/sk:website/references/niche/local-business.md +78 -0
  19. package/skills/sk:website/references/niche/med-spa.md +78 -0
  20. package/skills/sk:website/references/niche/portfolio.md +77 -0
  21. package/skills/sk:website/references/niche/real-estate.md +72 -0
  22. package/skills/sk:website/references/niche/restaurant.md +80 -0
  23. package/skills/sk:website/references/niche/saas.md +80 -0
  24. package/skills/sk:website/references/niche/wedding.md +80 -0
  25. package/skills/sk:website/references/stacks/laravel.md +425 -0
  26. package/skills/sk:website/references/stacks/nextjs.md +345 -0
  27. package/skills/sk:website/references/stacks/nuxt.md +374 -0
  28. package/skills/sk:website/references/whatsapp-cta.md +160 -0
@@ -0,0 +1,80 @@
1
+ # Restaurant
2
+
3
+ Use for full-service restaurants, casual dining, bistros, brasseries, and food-first hospitality brands where reservations, menus, and atmosphere all drive decisions.
4
+
5
+ ## Priorities
6
+
7
+ 1. Menu and reservation path must be the top two accessible things on the site.
8
+ 2. Atmosphere through photography — people decide before they taste.
9
+ 3. Location, hours, and parking are always important.
10
+ 4. Reduce friction to booking — no multi-step flows for a table inquiry.
11
+
12
+ ## Default page set
13
+
14
+ - Home (hero + ambiance + signature dishes + reservation CTA)
15
+ - Menu (full menu by category — starters, mains, desserts, drinks)
16
+ - About (story, chef, kitchen philosophy)
17
+ - Reservations (booking form or third-party reservation link)
18
+ - Find Us (address, hours, parking, map embed)
19
+
20
+ Optional: Events / Private Dining, Gallery, Takeout / Delivery, Press
21
+
22
+ ## Section guidance
23
+
24
+ **Hero:**
25
+ - Strong food or interior photography above the fold
26
+ - Headline should set the dining experience: cuisine type + atmosphere + location
27
+ - Two CTAs: "Make a Reservation" (primary) + "View Menu" (secondary)
28
+
29
+ **Signature dishes:**
30
+ - 3–6 featured dishes with short descriptions — texture, flavor, ingredient-forward
31
+ - Real names from the actual menu only
32
+
33
+ **About / story:**
34
+ - Chef background if notable, kitchen philosophy, sourcing if meaningful
35
+ - Warm and specific — not generic "passion for food" copy
36
+
37
+ **Reservation section:**
38
+ - Keep it simple: Name, Date, Time, Number of guests, Phone/Email
39
+ - Link to OpenTable / Resy / Quandoo if integrated
40
+ - WhatsApp for direct reservation inquiries
41
+
42
+ **Location + hours:**
43
+ - Prominently placed — in nav, on homepage, and on dedicated page
44
+ - Include parking, valet, or transit notes
45
+ - Map embed (Google Maps iframe)
46
+
47
+ **Reviews:**
48
+ - Real rating + review count from Google, Zomato, or TripAdvisor if available
49
+ - Specific quotes if real reviews exist — never invent
50
+
51
+ ## Design guidance
52
+
53
+ - **Art direction:** Warm Hospitality almost always. Bold Brand-Forward for trendy concept restaurants.
54
+ - Photography is the design system's backbone — image quality matters more than any other element.
55
+ - Typography: editorial serif for headlines (Playfair Display, Cormorant, Fraunces) + clean sans for menus.
56
+ - Palette: warm, food-first colors — deep red, terracotta, cream, charcoal, dark green.
57
+ - Menu page: well-structured table/list layout — legible at a glance, not overly designed.
58
+ - Motion: minimal — slow hero crossfade, gentle parallax on food photography.
59
+
60
+ ## SEO guidance
61
+
62
+ - Homepage title: "[Restaurant Name] — [Cuisine] Restaurant in [Neighborhood], [City]"
63
+ - H1: "[Cuisine type] in [Location]" e.g., "Modern Filipino Restaurant in Poblacion, Makati"
64
+ - Target: "restaurant in [city]", "[cuisine] restaurant near me", "best [cuisine] [city]"
65
+ - Include structured data: `Restaurant` schema with address, hours, telephone, menu URL, accepts reservations
66
+ - Separate menu page helps SEO — ensure it's crawlable HTML, not just a PDF
67
+
68
+ ## WhatsApp / contact
69
+
70
+ - WhatsApp for reservation inquiries — high conversion for SEA restaurants
71
+ - Pre-filled message: "Hi! I'd like to make a reservation. I found you on your website."
72
+ - Combine with a simple form for advance/large-group bookings
73
+
74
+ ## Avoid
75
+
76
+ - Menu as a PDF (not crawlable, terrible UX on mobile)
77
+ - Reservations buried below the fold
78
+ - Using SaaS/tech visual aesthetics for a warm dining brand
79
+ - Generic stock photography of food
80
+ - Hiding the address — locals google restaurants on the go
@@ -0,0 +1,80 @@
1
+ # SaaS / Software Product
2
+
3
+ Use for SaaS products, B2B tools, AI products, developer platforms, and software-first brands.
4
+
5
+ ## Priorities
6
+
7
+ 1. Clarify what the product does in the first 5 seconds — no mystery.
8
+ 2. Show who it's for — visitors self-qualify before trialing.
9
+ 3. Reduce perceived complexity — demos, how-it-works, and proof over feature lists.
10
+ 4. Move visitors toward signup, trial, or demo request.
11
+
12
+ ## Default page set
13
+
14
+ - Home (outcome-driven hero + proof + social proof + pricing CTA)
15
+ - Features (or use cases, if that's the better frame)
16
+ - Pricing (3-tier with clear feature comparison)
17
+ - About (team + mission + why this product)
18
+ - Contact / Demo (simple lead capture or Calendly)
19
+
20
+ Optional: Docs, Blog, Changelog, Integrations, Customers/Case Studies
21
+
22
+ ## Section guidance
23
+
24
+ **Hero:**
25
+ - One clear benefit statement — what the user can do with this product
26
+ - Sub-headline: who it's for + how it works in one line
27
+ - CTA: "Start Free Trial", "Request a Demo", or "Get Started Free"
28
+ - Supporting visual: screenshot, short video loop, or product mockup (real only)
29
+
30
+ **Social proof bar:**
31
+ - Company logos or "X+ teams" or "Y+ users" — real numbers only
32
+ - Even if small: "Trusted by 50+ early teams" is credible; invented logos are not
33
+
34
+ **Features / value pillars:**
35
+ - 3–6 cards: one benefit per card, not feature specs
36
+ - Frame around outcomes: "Deploy in minutes, not days" not "One-click deployment button"
37
+
38
+ **How it works:**
39
+ - 3-step visual flow — numbered, no jargon
40
+ - If there's a product tour or demo video, this is where it goes
41
+
42
+ **Pricing:**
43
+ - 3 tiers standard (Free/Starter/Pro or Starter/Growth/Enterprise)
44
+ - Highlight the recommended tier
45
+ - Annual toggle if applicable
46
+ - Use real pricing if known; if not, use "Contact for pricing" not invented numbers
47
+
48
+ **Testimonials:**
49
+ - Real quotes from real customers, name + role + company
50
+ - If none available, use social proof bar instead — never invent
51
+
52
+ ## Design guidance
53
+
54
+ - **Art direction:** Premium Product-Led or Sharp Technical — depending on whether the product is design-forward or developer-facing.
55
+ - Avoid generic SaaS visual tropes: purple gradients, glowing UI previews, "scale" metaphors.
56
+ - Typography: clean, modern sans — DM Sans, Inter, Plus Jakarta Sans.
57
+ - Palette: controlled — neutral background, one primary brand color, strategic accent.
58
+ - Dark mode optional — great for developer tools, not necessary for all SaaS.
59
+ - Screenshots of real product UI carry more weight than illustrations.
60
+
61
+ ## SEO guidance
62
+
63
+ - Homepage title: "[Product Name] — [Primary Benefit] for [Audience]"
64
+ - H1: specific value statement, not just a tagline
65
+ - Target: "[problem the product solves]", "[product category] software", "[use case] tool"
66
+ - Structured data: `SoftwareApplication` or `WebApplication`
67
+ - Blog/docs pages help long-tail SEO significantly
68
+
69
+ ## WhatsApp / contact
70
+
71
+ - Not applicable for SaaS — use demo form, trial signup, or Calendly
72
+ - If B2B sales motion: contact form with company size, use case fields
73
+
74
+ ## Avoid
75
+
76
+ - Fake product dashboards when no real screenshots exist
77
+ - Purple-to-blue gradients as the primary design element
78
+ - Feature lists without benefit framing
79
+ - "Innovative" and "cutting-edge" — show, don't claim
80
+ - Pricing page with no real tiers
@@ -0,0 +1,80 @@
1
+ # Wedding / Event / Bridal
2
+
3
+ Use for wedding planners, bridal brands, venues, photographers, florists, and wedding-focused event businesses.
4
+
5
+ ## Priorities
6
+
7
+ 1. Create emotional atmosphere immediately — couples are making an emotional, high-stakes purchase.
8
+ 2. Make inquiry or booking paths obvious — couples often browse multiple vendors before contacting.
9
+ 3. Show taste, portfolio, and experience.
10
+ 4. Balance romance with practical planning information.
11
+
12
+ ## Default page set
13
+
14
+ - Home (emotional positioning + portfolio preview + inquiry CTA)
15
+ - Services / Packages (what you offer, how it works, pricing approach)
16
+ - Portfolio / Gallery (real work — weddings photographed, events planned, flowers arranged)
17
+ - About (your story, why you do this, your team)
18
+ - Contact / Inquire (inquiry form with date, venue, guest count)
19
+
20
+ Optional: FAQ, Testimonials (real), Blog, Availability Calendar
21
+
22
+ ## Section guidance
23
+
24
+ **Hero:**
25
+ - Set the emotional tone before the practical details
26
+ - Example: "Wedding Photographer in Manila — Candid, Intimate, Timeless"
27
+ - CTA: "Check Availability" or "Inquire Now"
28
+ - Strong hero photography (real work only)
29
+
30
+ **Portfolio / gallery:**
31
+ - Real weddings/events only — no stock wedding imagery
32
+ - If portfolio is limited (new business), use 3–5 strong examples or focus on mood/process
33
+ - Quality over quantity — 6 great photos beat 30 mediocre ones
34
+
35
+ **Services / packages:**
36
+ - Clear list of offerings: what's included, duration, deliverables
37
+ - Pricing approach: "Packages starting from [X]" or "Contact for custom quote" — avoid total opacity
38
+ - Separate wedding day vs. engagement vs. elopement if applicable
39
+
40
+ **About / story:**
41
+ - Personal and specific — why you do this work, your approach
42
+ - Team photos if working with a crew
43
+
44
+ **Testimonials:**
45
+ - Real couple quotes, real names, optional wedding date/venue
46
+ - Google Review count if available
47
+
48
+ **Contact / inquiry:**
49
+ - Form: Name, Email, Phone, Date, Venue (or location), Type of event, Guest count, Message
50
+ - Response time expectation — couples often contact multiple vendors simultaneously
51
+
52
+ ## Design guidance
53
+
54
+ - **Art direction:** Quiet Luxury or Restrained Editorial for premium brands; Warm Hospitality for approachable/bohemian styles.
55
+ - Visual pacing and typography carry more weight than heavy ornament.
56
+ - Typography: romantic but readable — fine serif (Cormorant, Playfair Display) + clean sans
57
+ - Palette: soft and curated — blush, ivory, sage, champagne, dusty rose, eucalyptus green
58
+ - Photography is the entire design system — never use stock wedding imagery
59
+ - Motion: slow and graceful — crossfades, gentle scroll reveals
60
+
61
+ ## SEO guidance
62
+
63
+ - Title: "[Business Name] — Wedding [Photographer/Planner/Florist] in [City]"
64
+ - H1: "Wedding [Service Type] in [City]" — e.g., "Wedding Photographer in Manila"
65
+ - Target: "wedding photographer [city]", "wedding planner [city]", "wedding florist near me"
66
+ - Portfolio pages optimized per wedding style/venue help for style-specific searches
67
+ - Structured data: `LocalBusiness` or `EventPlanner`
68
+
69
+ ## WhatsApp / contact
70
+
71
+ - WhatsApp for initial availability inquiries in PH/SEA
72
+ - Pre-filled: "Hi! I'm inquiring about availability for my wedding. I found you on your website."
73
+ - Full inquiry form for packages/quotes
74
+
75
+ ## Avoid
76
+
77
+ - Stock wedding photography — real work or no work
78
+ - Generic "Love, Laughter, and Happily Ever After" copy
79
+ - Hiding pricing entirely (couples will bounce if they have no price signal)
80
+ - Burying the inquiry form below excessive intro copy
@@ -0,0 +1,425 @@
1
+ # Laravel 11 + Blade + Tailwind — Client Website Stack Reference
2
+
3
+ Stack for building multi-page client marketing sites with PHP/Laravel. NOT a prototype — real copy, real SEO, no fake data.
4
+
5
+ ## Scaffold
6
+
7
+ ```bash
8
+ composer create-project laravel/laravel {project-name}
9
+ cd {project-name}
10
+ npm install
11
+ ```
12
+
13
+ Laravel 11 ships with Tailwind CSS configured via Vite out of the box.
14
+
15
+ ## Directory Structure
16
+
17
+ ```
18
+ {project-name}/
19
+ ├── resources/
20
+ │ ├── views/
21
+ │ │ ├── layouts/
22
+ │ │ │ └── site.blade.php ← site layout (head, nav, footer, WhatsApp)
23
+ │ │ ├── components/
24
+ │ │ │ ├── layout/
25
+ │ │ │ │ ├── navbar.blade.php
26
+ │ │ │ │ └── footer.blade.php
27
+ │ │ │ ├── home/
28
+ │ │ │ │ ├── hero.blade.php
29
+ │ │ │ │ ├── services.blade.php
30
+ │ │ │ │ └── testimonials.blade.php
31
+ │ │ │ ├── contact/
32
+ │ │ │ │ └── form.blade.php
33
+ │ │ │ └── whatsapp-button.blade.php ← floating CTA partial
34
+ │ │ ├── home.blade.php ← Home page
35
+ │ │ ├── about.blade.php ← About page
36
+ │ │ ├── services.blade.php ← Services / Menu page
37
+ │ │ └── contact.blade.php ← Contact page
38
+ │ ├── css/
39
+ │ │ └── app.css ← Tailwind directives + CSS custom properties
40
+ │ └── js/
41
+ │ └── app.js ← Vite entry + Alpine.js for interactivity
42
+ ├── routes/
43
+ │ └── web.php ← page routes + contact POST route
44
+ ├── app/
45
+ │ ├── Http/
46
+ │ │ └── Controllers/
47
+ │ │ └── ContactController.php ← contact form handler
48
+ │ └── Data/
49
+ │ └── SiteData.php ← typed site config: copy, pages, metadata
50
+ ├── config/
51
+ │ └── site.php ← site-wide config values
52
+ ├── public/
53
+ │ ├── images/
54
+ │ └── favicon.ico
55
+ ├── tailwind.config.js
56
+ └── vite.config.js
57
+ ```
58
+
59
+ ## Site Config
60
+
61
+ `config/site.php` — single source of truth for all copy and metadata:
62
+
63
+ ```php
64
+ <?php
65
+
66
+ return [
67
+ 'name' => '{Business Name}',
68
+ 'tagline' => '{Tagline}',
69
+ 'description' => '{Meta description — used for SEO}',
70
+ 'url' => env('APP_URL', 'https://{domain}'),
71
+ 'phone' => '{639171234567}', // E.164 without +
72
+ 'email' => '{contact@example.com}',
73
+ 'address' => '{Full address}',
74
+ 'hours' => '{Mon–Fri 9am–6pm}',
75
+ 'social' => [
76
+ 'facebook' => '{https://facebook.com/page}',
77
+ 'instagram' => '{https://instagram.com/handle}',
78
+ ],
79
+ 'pages' => [
80
+ 'home' => [
81
+ 'title' => '{Business Name} — {Primary benefit}',
82
+ 'description' => '{Page-specific meta description}',
83
+ 'hero' => [
84
+ 'headline' => '{Real headline — no Lorem ipsum}',
85
+ 'subheadline' => '{Supporting line}',
86
+ 'cta' => '{Primary CTA text}',
87
+ 'cta_href' => '/contact',
88
+ ],
89
+ ],
90
+ 'about' => [
91
+ 'title' => 'About — {Business Name}',
92
+ 'description' => '{About page meta description}',
93
+ ],
94
+ 'services' => [
95
+ 'title' => 'Services — {Business Name}',
96
+ 'description' => '{Services page meta description}',
97
+ 'items' => [
98
+ ['name' => '{Service 1}', 'description' => '{Real description}', 'price' => '{optional}'],
99
+ ],
100
+ ],
101
+ 'contact' => [
102
+ 'title' => 'Contact — {Business Name}',
103
+ 'description' => '{Contact page meta description}',
104
+ ],
105
+ ],
106
+ ];
107
+ ```
108
+
109
+ ## Site Layout
110
+
111
+ `resources/views/layouts/site.blade.php`:
112
+
113
+ ```blade
114
+ <!DOCTYPE html>
115
+ <html lang="en">
116
+ <head>
117
+ <meta charset="UTF-8">
118
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
119
+ <title>{{ $title ?? config('site.name') }}</title>
120
+ <meta name="description" content="{{ $description ?? config('site.description') }}">
121
+
122
+ {{-- Open Graph --}}
123
+ <meta property="og:title" content="{{ $title ?? config('site.name') }}">
124
+ <meta property="og:description" content="{{ $description ?? config('site.description') }}">
125
+ <meta property="og:url" content="{{ $canonical ?? url()->current() }}">
126
+ <meta property="og:site_name" content="{{ config('site.name') }}">
127
+ <meta property="og:type" content="website">
128
+
129
+ {{-- Canonical --}}
130
+ <link rel="canonical" href="{{ $canonical ?? url()->current() }}">
131
+ <link rel="icon" href="/favicon.ico">
132
+
133
+ {{-- Fonts: replace with art-direction spec fonts --}}
134
+ <link rel="preconnect" href="https://fonts.googleapis.com">
135
+ <link href="https://fonts.googleapis.com/css2?family={DisplayFont}:wght@400;600;700;800&family={BodyFont}:wght@400;500;600&display=swap" rel="stylesheet">
136
+
137
+ @vite(['resources/css/app.css', 'resources/js/app.js'])
138
+ </head>
139
+ <body class="bg-bg text-fg font-body antialiased">
140
+ <x-layout.navbar />
141
+ <main>
142
+ {{ $slot }}
143
+ </main>
144
+ <x-layout.footer />
145
+
146
+ {{-- Remove if not a local PH/SEA business --}}
147
+ <x-whatsapp-button :phone="config('site.phone')" message="Hi! I found you on your website." />
148
+
149
+ {{-- LocalBusiness structured data --}}
150
+ <script type="application/ld+json">
151
+ {
152
+ "@context": "https://schema.org",
153
+ "@type": "LocalBusiness",
154
+ "name": "{{ config('site.name') }}",
155
+ "description": "{{ config('site.description') }}",
156
+ "url": "{{ config('site.url') }}",
157
+ "telephone": "+{{ config('site.phone') }}",
158
+ "address": {
159
+ "@type": "PostalAddress",
160
+ "streetAddress": "{{ config('site.address') }}"
161
+ }
162
+ }
163
+ </script>
164
+ </body>
165
+ </html>
166
+ ```
167
+
168
+ ## Page Views
169
+
170
+ `resources/views/home.blade.php`:
171
+
172
+ ```blade
173
+ <x-layouts.site
174
+ title="{{ config('site.pages.home.title') }}"
175
+ description="{{ config('site.pages.home.description') }}"
176
+ >
177
+ <x-home.hero />
178
+ <x-home.services />
179
+ <x-home.testimonials />
180
+ </x-layouts.site>
181
+ ```
182
+
183
+ `resources/views/contact.blade.php`:
184
+
185
+ ```blade
186
+ <x-layouts.site
187
+ title="{{ config('site.pages.contact.title') }}"
188
+ description="{{ config('site.pages.contact.description') }}"
189
+ >
190
+ <section class="py-24 px-4 max-w-2xl mx-auto">
191
+ <h1 class="font-display text-4xl font-bold mb-8">Contact Us</h1>
192
+ <x-contact.form />
193
+ </section>
194
+ </x-layouts.site>
195
+ ```
196
+
197
+ ## Routes
198
+
199
+ `routes/web.php`:
200
+
201
+ ```php
202
+ <?php
203
+
204
+ use App\Http\Controllers\ContactController;
205
+
206
+ Route::view('/', 'home')->name('home');
207
+ Route::view('/about', 'about')->name('about');
208
+ Route::view('/services', 'services')->name('services');
209
+ Route::view('/contact', 'contact')->name('contact');
210
+
211
+ Route::post('/contact', [ContactController::class, 'store'])->name('contact.store');
212
+
213
+ // Sitemap
214
+ Route::get('/sitemap.xml', function () {
215
+ $sitemap = simplexml_load_string('<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></urlset>');
216
+ foreach (['/', '/about', '/services', '/contact'] as $path) {
217
+ $url = $sitemap->addChild('url');
218
+ $url->addChild('loc', config('site.url') . $path);
219
+ $url->addChild('changefreq', 'monthly');
220
+ $url->addChild('priority', $path === '/' ? '1.0' : '0.8');
221
+ }
222
+ return response($sitemap->asXML(), 200)->header('Content-Type', 'application/xml');
223
+ })->name('sitemap');
224
+
225
+ // Robots.txt
226
+ Route::get('/robots.txt', function () {
227
+ return response("User-agent: *\nAllow: /\nSitemap: " . config('site.url') . "/sitemap.xml", 200)
228
+ ->header('Content-Type', 'text/plain');
229
+ });
230
+ ```
231
+
232
+ ## Contact Controller
233
+
234
+ `app/Http/Controllers/ContactController.php`:
235
+
236
+ ```php
237
+ <?php
238
+
239
+ namespace App\Http\Controllers;
240
+
241
+ use Illuminate\Http\Request;
242
+
243
+ class ContactController extends Controller
244
+ {
245
+ public function store(Request $request)
246
+ {
247
+ $validated = $request->validate([
248
+ 'name' => 'required|string|max:255',
249
+ 'email' => 'required|email',
250
+ 'phone' => 'nullable|string|max:50',
251
+ 'message' => 'required|string|max:5000',
252
+ ]);
253
+
254
+ // Honeypot check (add a hidden "website" field to the form)
255
+ if ($request->filled('website')) {
256
+ return back()->with('success', "Message received. We'll be in touch soon.");
257
+ }
258
+
259
+ // TODO: wire to mail (Mail::to(...)->send(new ContactMail($validated)))
260
+ // For now: log submission
261
+ logger()->info('Contact form submission', $validated);
262
+
263
+ return back()->with('success', "Message received. We'll be in touch soon.");
264
+ }
265
+ }
266
+ ```
267
+
268
+ ## Contact Form Component
269
+
270
+ `resources/views/components/contact/form.blade.php`:
271
+
272
+ ```blade
273
+ <form
274
+ action="{{ route('contact.store') }}"
275
+ method="POST"
276
+ x-data="{ loading: false }"
277
+ @submit="loading = true"
278
+ class="space-y-4"
279
+ >
280
+ @csrf
281
+
282
+ {{-- Honeypot --}}
283
+ <input type="text" name="website" class="hidden" autocomplete="off" tabindex="-1">
284
+
285
+ @if (session('success'))
286
+ <p class="text-green-600 font-medium">{{ session('success') }}</p>
287
+ @endif
288
+
289
+ <input type="text" name="name" value="{{ old('name') }}" placeholder="Your name" required
290
+ class="w-full px-4 py-3 border rounded-lg @error('name') border-red-500 @enderror">
291
+ @error('name') <p class="text-red-500 text-sm">{{ $message }}</p> @enderror
292
+
293
+ <input type="email" name="email" value="{{ old('email') }}" placeholder="Email address" required
294
+ class="w-full px-4 py-3 border rounded-lg @error('email') border-red-500 @enderror">
295
+ @error('email') <p class="text-red-500 text-sm">{{ $message }}</p> @enderror
296
+
297
+ <input type="tel" name="phone" value="{{ old('phone') }}" placeholder="Phone (optional)"
298
+ class="w-full px-4 py-3 border rounded-lg">
299
+
300
+ <textarea name="message" placeholder="Your message" required rows="4"
301
+ class="w-full px-4 py-3 border rounded-lg resize-none @error('message') border-red-500 @enderror">{{ old('message') }}</textarea>
302
+ @error('message') <p class="text-red-500 text-sm">{{ $message }}</p> @enderror
303
+
304
+ <button type="submit" :disabled="loading"
305
+ class="w-full px-6 py-3 bg-accent text-white rounded-lg font-medium transition hover:opacity-90 disabled:opacity-60">
306
+ <span x-show="!loading">Send Message</span>
307
+ <span x-show="loading">Sending...</span>
308
+ </button>
309
+ </form>
310
+ ```
311
+
312
+ ## WhatsApp Blade Component
313
+
314
+ `resources/views/components/whatsapp-button.blade.php`:
315
+
316
+ ```blade
317
+ @props([
318
+ 'phone', // E.164 without +: e.g., "639171234567"
319
+ 'message' => null,
320
+ ])
321
+
322
+ @php
323
+ $url = $message
324
+ ? 'https://wa.me/' . $phone . '?text=' . urlencode($message)
325
+ : 'https://wa.me/' . $phone;
326
+ @endphp
327
+
328
+ <a
329
+ href="{{ $url }}"
330
+ target="_blank"
331
+ rel="noopener noreferrer"
332
+ aria-label="Chat on WhatsApp"
333
+ class="fixed bottom-6 right-6 z-50 flex h-14 w-14 items-center justify-center rounded-full bg-[#25D366] shadow-lg transition-transform hover:scale-110 focus:outline-none focus:ring-2 focus:ring-[#25D366] focus:ring-offset-2"
334
+ >
335
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" class="h-7 w-7" aria-hidden="true">
336
+ <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/>
337
+ </svg>
338
+ </a>
339
+ ```
340
+
341
+ ## Tailwind Config
342
+
343
+ `tailwind.config.js`:
344
+
345
+ ```js
346
+ export default {
347
+ content: [
348
+ './resources/**/*.blade.php',
349
+ './resources/**/*.js',
350
+ ],
351
+ theme: {
352
+ extend: {
353
+ colors: {
354
+ bg: 'var(--color-bg)',
355
+ fg: 'var(--color-fg)',
356
+ accent: 'var(--color-accent)',
357
+ muted: 'var(--color-muted)',
358
+ surface: 'var(--color-surface)',
359
+ },
360
+ fontFamily: {
361
+ display: ['{DisplayFont}', 'serif'],
362
+ body: ['{BodyFont}', 'sans-serif'],
363
+ },
364
+ },
365
+ },
366
+ }
367
+ ```
368
+
369
+ `resources/css/app.css`:
370
+
371
+ ```css
372
+ @tailwind base;
373
+ @tailwind components;
374
+ @tailwind utilities;
375
+
376
+ :root {
377
+ --color-bg: #xxxxxx; /* from art direction spec */
378
+ --color-fg: #xxxxxx;
379
+ --color-accent: #xxxxxx;
380
+ --color-muted: #xxxxxx;
381
+ --color-surface: #xxxxxx;
382
+ }
383
+ ```
384
+
385
+ ## Alpine.js for Interactivity
386
+
387
+ `resources/js/app.js`:
388
+
389
+ ```js
390
+ import Alpine from 'alpinejs'
391
+ window.Alpine = Alpine
392
+ Alpine.start()
393
+ ```
394
+
395
+ Install:
396
+
397
+ ```bash
398
+ npm install alpinejs
399
+ ```
400
+
401
+ ## Dev + Build Commands
402
+
403
+ ```bash
404
+ # Run both in separate terminals
405
+ php artisan serve # http://localhost:8000
406
+ npm run dev # Vite HMR for assets
407
+
408
+ # Or use Laravel Herd (auto-serves at {project-name}.test)
409
+
410
+ npm run build # compile assets for production
411
+ php artisan optimize # cache config, routes, views for production
412
+ ```
413
+
414
+ ## Vercel / Netlify Deploy
415
+
416
+ Laravel requires a PHP host — Vercel and Netlify do not support PHP natively. Options:
417
+
418
+ | Host | Notes |
419
+ |---|---|
420
+ | **Laravel Cloud** | First-party — simplest, scalable |
421
+ | **Forge + DigitalOcean** | Full control, $6–12/mo droplet |
422
+ | **Railway** | Docker-based, easy setup |
423
+ | **Render** | Free tier available for small sites |
424
+
425
+ Add deploy steps to `DEPLOY.md` based on chosen host. The default guide should recommend Laravel Cloud or Forge.