@@ -98,312 +98,6 @@ NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX
9898NEXT_PUBLIC_PLAUSIBLE_DOMAIN=your-site.com
9999```
100100
101- ### 3. Run Development Server
102-
103- ``` bash
104- pnpm dev
105- ```
106-
107- Visit [ http://localhost:3000 ] ( http://localhost:3000 )
108-
109- ### 4. Build for Production
110-
111- ``` bash
112- pnpm build
113- pnpm start
114- ```
115-
116- ## On-Demand Revalidation Setup
117-
118- Rush CMS can automatically invalidate Next.js cache when content is updated.
119-
120- ### Step 1: Generate Revalidation Secret
121-
122- ``` bash
123- # Generate a secure random key
124- openssl rand -hex 32
125- ```
126-
127- Add to your ` .env ` :
128-
129- ``` env
130- REVALIDATE_SECRET=your-generated-secret-here
131- ```
132-
133- ### Step 2: Configure Webhook in Rush CMS
134-
135- In your Rush CMS installation, configure the webhook:
136-
137- ** URL Format:**
138- ```
139- https://your-nextjs-site.com/api/revalidate
140- ```
141-
142- ** Method:** ` POST `
143-
144- ** Headers:**
145- ```
146- Content-Type: application/json
147- ```
148-
149- ** Payload Example (Path Revalidation):**
150- ``` json
151- {
152- "secret" : " your-revalidation-secret" ,
153- "path" : " /blog/my-post-slug"
154- }
155- ```
156-
157- ** Payload Example (Tag Revalidation):**
158- ``` json
159- {
160- "secret" : " your-revalidation-secret" ,
161- "tag" : " blog-posts"
162- }
163- ```
164-
165- ### Step 3: Test Revalidation
166-
167- Test manually with curl:
168-
169- ``` bash
170- curl -X POST https://your-site.com/api/revalidate \
171- -H " Content-Type: application/json" \
172- -d ' {
173- "secret": "your-secret",
174- "path": "/"
175- }'
176- ```
177-
178- ** Expected Response:**
179- ``` json
180- {
181- "success" : true ,
182- "message" : " Revalidation triggered successfully" ,
183- "revalidated" : {
184- "path" : " /" ,
185- "tag" : null
186- },
187- "timestamp" : " 2025-11-12T10:30:00.000Z"
188- }
189- ```
190-
191- ### Rush CMS Observer Implementation
192-
193- Add this observer to your Rush CMS Laravel application:
194-
195- ``` php
196- <?php
197-
198- namespace App\Observers;
199-
200- use App\Models\Entry;
201- use Illuminate\Support\Facades\Http;
202-
203- class EntryObserver
204- {
205- public function updated(Entry $entry): void
206- {
207- $this->revalidateNextjs($entry);
208- }
209-
210- public function deleted(Entry $entry): void
211- {
212- $this->revalidateNextjs($entry);
213- }
214-
215- protected function revalidateNextjs(Entry $entry): void
216- {
217- $nextjsUrl = config('services.nextjs.url');
218- $secret = config('services.nextjs.revalidate_secret');
219-
220- if (!$nextjsUrl || !$secret) {
221- return;
222- }
223-
224- // Determine path based on collection
225- $path = match($entry->collection->slug) {
226- 'blog' => "/blog/{$entry->slug}",
227- 'pages' => "/{$entry->slug}",
228- default => null,
229- };
230-
231- if ($path) {
232- Http::post("{$nextjsUrl}/api/revalidate", [
233- 'secret' => $secret,
234- 'path' => $path,
235- ]);
236-
237- // Also revalidate listing pages
238- if ($entry->collection->slug === 'blog') {
239- Http::post("{$nextjsUrl}/api/revalidate", [
240- 'secret' => $secret,
241- 'path' => '/blog',
242- ]);
243- }
244- }
245- }
246- }
247- ```
248-
249- Register the observer in ` AppServiceProvider ` :
250-
251- ``` php
252- use App\Models\Entry;
253- use App\Observers\EntryObserver;
254-
255- public function boot(): void
256- {
257- Entry::observe(EntryObserver::class);
258- }
259- ```
260-
261- Add to ` config/services.php ` :
262-
263- ``` php
264- 'nextjs' => [
265- 'url' => env('NEXTJS_URL', 'https://your-nextjs-site.com'),
266- 'revalidate_secret' => env('NEXTJS_REVALIDATE_SECRET'),
267- ],
268- ```
269-
270- ## Analytics Setup
271-
272- ### Google Analytics 4
273-
274- 1 . Create a GA4 property in Google Analytics
275- 2 . Get your Measurement ID (format: ` G-XXXXXXXXXX ` )
276- 3 . Add to ` .env ` :
277-
278- ``` env
279- NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX
280- ```
281-
282- ### Plausible Analytics
283-
284- 1 . Sign up at [ plausible.io] ( https://plausible.io )
285- 2 . Add your domain
286- 3 . Add to ` .env ` :
287-
288- ``` env
289- NEXT_PUBLIC_PLAUSIBLE_DOMAIN=your-site.com
290- ```
291-
292- ### Custom Event Tracking
293-
294- Use the analytics helpers in your code:
295-
296- ``` typescript
297- import { trackEvent , trackFormSubmit , trackSearch } from ' @/lib/analytics'
298-
299- // Track custom events
300- trackEvent (' button_click' , { button_name: ' subscribe' })
301-
302- // Track form submissions
303- trackFormSubmit (' contact_form' , true )
304-
305- // Track search queries
306- trackSearch (' next.js tutorial' , 42 )
307- ```
308-
309- ## Project Structure
310-
311- ```
312- src/
313- ├── app/
314- │ ├── api/
315- │ │ └── revalidate/
316- │ │ └── route.ts # Revalidation webhook endpoint
317- │ ├── blog/
318- │ │ ├── [slug]/
319- │ │ │ ├── page.tsx # Blog post detail
320- │ │ │ └── error.tsx # Blog post error boundary
321- │ │ ├── page.tsx # Blog listing with search
322- │ │ └── error.tsx # Blog error boundary
323- │ ├── [slug]/
324- │ │ └── page.tsx # Dynamic pages
325- │ ├── contact/
326- │ │ └── page.tsx # Contact form
327- │ ├── error.tsx # Global error boundary
328- │ ├── loading.tsx # Global loading state
329- │ ├── not-found.tsx # 404 page
330- │ ├── page.tsx # Homepage
331- │ ├── layout.tsx # Root layout
332- │ ├── globals.css # Global styles
333- │ ├── sitemap.ts # Dynamic sitemap
334- │ └── robots.ts # Robots.txt
335- ├── components/
336- │ ├── analytics/
337- │ │ └── analytics-script.tsx # Analytics integration
338- │ ├── blog/
339- │ │ └── blog-listing.tsx # Blog listing with search & pagination
340- │ ├── breadcrumbs/
341- │ │ └── breadcrumbs.tsx # Breadcrumb navigation
342- │ ├── loading/
343- │ │ ├── skeleton.tsx # Base skeleton loader
344- │ │ ├── blog-post-skeleton.tsx # Blog post skeleton
345- │ │ ├── card-skeleton.tsx # Card skeleton
346- │ │ └── form-skeleton.tsx # Form skeleton
347- │ ├── pagination/
348- │ │ └── pagination.tsx # Pagination component
349- │ ├── rush/
350- │ │ ├── article.tsx # Blog post renderer
351- │ │ ├── article-content.tsx # Article content with TOC
352- │ │ ├── block-editor-renderer.tsx # Block editor
353- │ │ ├── entry-renderer.tsx # Generic entry renderer
354- │ │ └── form-builder.tsx # Dynamic forms
355- │ ├── search/
356- │ │ ├── blog-search.tsx # Generic search wrapper
357- │ │ ├── search-input.tsx # Search input with debounce
358- │ │ └── search-results.tsx # Search results display
359- │ ├── share/
360- │ │ └── share-buttons.tsx # Social media share buttons
361- │ ├── structured-data/
362- │ │ └── entry-schema.tsx # JSON-LD structured data
363- │ ├── toc/
364- │ │ └── table-of-contents.tsx # Table of contents
365- │ ├── ui/
366- │ │ ├── alert.tsx # Alert component
367- │ │ ├── badge.tsx # Badge component
368- │ │ ├── button.tsx # Button component
369- │ │ ├── card.tsx # Card component
370- │ │ ├── input.tsx # Input component
371- │ │ ├── label.tsx # Label component
372- │ │ ├── optimized-image.tsx # Optimized image wrapper
373- │ │ ├── select.tsx # Select component
374- │ │ └── textarea.tsx # Textarea component
375- │ ├── blog-card.tsx # Blog card component
376- │ └── navigation.tsx # Main navigation
377- ├── lib/
378- │ ├── analytics.ts # Analytics helpers
379- │ ├── config.ts # Centralized config
380- │ ├── date.ts # Date formatting
381- │ ├── logger.ts # Structured logging
382- │ ├── metadata.ts # SEO metadata helpers
383- │ ├── rush-cms.ts # API client
384- │ ├── sanitize.ts # HTML sanitization
385- │ └── utils.ts # Utility functions
386- └── types/
387- ├── analytics.d.ts # Analytics types
388- └── rush-cms.ts # TypeScript types
389- ```
390-
391- ## Available Scripts
392-
393- ``` bash
394- # Development
395- pnpm dev # Start dev server (localhost:3000)
396- pnpm type-check # Run TypeScript compiler check
397- pnpm lint # Run ESLint
398-
399- # Production
400- pnpm build # Build for production
401- pnpm start # Start production server
402-
403- # Deployment
404- pnpm deploy # Deploy to configured platform
405- ```
406-
407101## Type Safety
408102
409103This starter uses strict TypeScript with no ` any ` types:
@@ -428,8 +122,6 @@ See [DEPLOYMENT.md](./DEPLOYMENT.md) for comprehensive deployment guides for:
428122- ** Webhooks** - On-demand revalidation setup
429123- ** Troubleshooting** - Common deployment issues
430124
431- ### Quick Deploy
432-
433125#### Vercel (Recommended)
434126
435127[ ![ Deploy with Vercel] ( https://vercel.com/button )] ( https://vercel.com/new/clone )
@@ -452,71 +144,4 @@ pnpm i -g netlify-cli
452144
453145# Deploy
454146netlify deploy --prod
455- ```
456-
457- ## Troubleshooting
458-
459- ### Issue: API requests failing
460-
461- ** Check:**
462- - ` NEXT_PUBLIC_API_URL ` is correct (no trailing slash)
463- - ` API_TOKEN ` is valid (regenerate in Rush CMS if needed)
464- - Rush CMS CORS settings allow your Next.js domain
465-
466- ### Issue: Images not loading
467-
468- ** Check:**
469- - ` NEXT_PUBLIC_S3_URL ` matches your media storage URL
470- - Add S3 domain to ` next.config.js ` :
471-
472- ``` js
473- images: {
474- domains: [' your-bucket.s3.amazonaws.com' ]
475- }
476- ```
477-
478- ### Issue: Revalidation not working
479-
480- ** Check:**
481- - ` REVALIDATE_SECRET ` matches in both ` .env ` and Rush CMS webhook
482- - Webhook URL is correct (https://your-site.com/api/revalidate )
483- - Check Next.js logs for revalidation messages
484-
485- ### Issue: Analytics not tracking
486-
487- ** Check:**
488- - Analytics only loads in production (` NODE_ENV=production ` )
489- - Environment variables use ` NEXT_PUBLIC_ ` prefix
490- - Check browser console for errors (ad blockers may interfere)
491-
492- ## Contributing
493-
494- 1 . Fork the repository
495- 2 . Create a feature branch (` git checkout -b feature/amazing-feature ` )
496- 3 . Commit using conventional commits (` feat: ` , ` fix: ` , ` docs: ` , etc.)
497- 4 . Push to the branch (` git push origin feature/amazing-feature ` )
498- 5 . Open a Pull Request
499-
500- ## Code Style
501-
502- This project follows strict code guidelines (see ` CLAUDE.md ` ):
503-
504- - Single quotes (` ' ` ) not double quotes
505- - Tabs (size 4) for indentation
506- - No semicolons
507- - Kebab-case file names (` blog-card.tsx ` )
508- - Mobile-first approach
509-
510- ## License
511-
512- MIT
513-
514- ## Support
515-
516- - ** Rush CMS Documentation** : [ https://docs.rushcms.com ] ( https://docs.rushcms.com )
517- - ** Issues** : [ GitHub Issues] ( https://github.com/your-org/rush-cms-nextjs-starter/issues )
518- - ** Discussions** : [ GitHub Discussions] ( https://github.com/your-org/rush-cms-nextjs-starter/discussions )
519-
520- ---
521-
522- Built with ❤️ using [ Rush CMS] ( https://rushcms.com ) and [ Next.js] ( https://nextjs.org )
147+ ```
0 commit comments