Bunny-Agency-Italy/README.md
BigMarc 67ea5d48be Initial commit: Bunny Agency Italia (it-IT) marketing site
Italian-market site for the Bunny Agency network, built on the shared
Next.js App Router template with content driven from site-content.json.

- 50 routes: home, 5 services, pricing, FAQ, about/apply/contact,
  32 blog answers and guides, 5 legal pages
- Research-driven Italian copy citing ISTAT, INPS and Agenzia delle Entrate
  (forfettario 15%/5%, ATECO 73.11.03, INPS 26,07%, tassa etica, DAC7)
- 6 long-form guides targeting high-volume Italian creator searches
- "Milanese Editoriale" design system with stats band, editorial article
  layout, creator gallery and footer language switcher to 18 sibling sites
- Full SEO/AEO/GEO: JSON-LD entity graph, hreflang cluster, llms.txt,
  IndexNow, sitemap, AI-crawler-friendly robots
- validate-seo.mjs passes with 0 errors

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 09:00:28 +02:00

85 lines
3.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Bunny Agency Italia — bunny-agency.it
Italian-market creator-management site (`it-IT`), part of the Bunny Agency network.
Next.js App Router, statically generated, content-driven from a single JSON registry.
## Stack
- Next.js 16 (App Router) + React 19, fully static (SSG)
- No CSS framework — one hand-written stylesheet (`src/app/globals.css`, "Milanese Editoriale")
- All page content lives in `src/content/site-content.json`; components are presentational
## Local development
```bash
npm install
npm run dev # http://localhost:3000
npm run build # runs prebuild (llms.txt) + next build
npm run validate:seo # SEO invariants — must pass before deploy
```
Node 22 is required (see `engines` in `package.json`).
## Content model
`src/content/site-content.json` holds:
| Key | Purpose |
|---|---|
| `site` | locale, URLs, hreflang cluster, legal entity, ratings, IndexNow key |
| `labels` / `core` | all UI strings and page H1/summaries (Italian) |
| `pages[]` | every route: path, title, description, H1, sections, FAQ, citations, image, author |
| `people`, `videos`, `creatorGallery` | E-E-A-T entities, Vimeo case studies, creator photos |
| `network` | footer language switcher — all sibling language sites |
Routing is a single catch-all (`src/app/[[...slug]]/page.tsx`) that resolves a path
against `pages[]`, so **adding a page = adding an object to `pages[]`** (plus an image).
### Page invariants enforced by `scripts/validate-seo.mjs`
- title ≤ 60 chars, description ≤ 155 chars, unique across the site
- ≥ 2 citations per page; a quotable number in the summary and in **every** FAQ answer
- blog keyword present in the H1 or a section heading; service keyword in the H1
- money pages (`/`, `/pricing`, `/services/account-management`, and 3 blog pages)
need 5–7 sections, ≥ 5 FAQs, and 580–1000 words
- the referenced image file must exist in `public/`
Pages that exist only on this site carry `"italyOnly": true`, which suppresses the
network hreflang alternates (siblings have no equivalent URL).
## Images
Per-page WebP assets are generated deterministically by the network tool:
```bash
cd ../_seo-tools && ONLY_REPO=Bunny-Agency-Italy node generate-images.mjs
```
Creator photos in `public/images/creators/` are the shared network pool.
## SEO / AEO / GEO
- `sitemap.xml` and `robots.txt` are generated from `pages[]` (AI crawlers allowed)
- `llms.txt` / `llms-full.txt` regenerate on `prebuild` (`scripts/generate-llms.mjs`)
- JSON-LD: Organization, WebSite, WebPage/Article/Service, FAQPage, BreadcrumbList,
Review, AggregateRating, VideoObject, Person
- IndexNow: key file in `public/`, submitted by `scripts/submit-indexnow.mjs`
(`npm run postdeploy`) and by `.github/workflows/indexnow-production.yml`
## Deployment (Vercel)
Framework preset `nextjs`; config in `vercel.json` (security headers, immutable
image caching, `fra1` region). Set in Vercel project settings:
| Env var | Value |
|---|---|
| `NEXT_PUBLIC_SITE_URL` | `https://www.bunny-agency.it` |
Domain `bunny-agency.it` must be registered and pointed at Vercel (`.it` requires an
EU/EEA registrant). Until then the production build serves on the `*.vercel.app` URL;
canonicals and hreflang already point at the final domain.
After the domain is live: verify in Google Search Console and Bing Webmaster Tools,
submit the sitemap, and add `https://www.bunny-agency.it` to the sibling sites'
`schemaSameAs` + `it-IT` hreflang (already done in this repo's network config).