# User Guide — WorkRoot Company Site

> Complete guide for content management, environment setup, and troubleshooting.

---

## Table of Contents

1. [Environment Setup](#1-environment-setup)
2. [Development Workflow](#2-development-workflow)
3. [Managing Blog Posts](#3-managing-blog-posts)
4. [Updating Portfolio Items](#4-updating-portfolio-items)
5. [Available npm Scripts](#5-available-npm-scripts)
6. [Troubleshooting Common Issues](#6-troubleshooting-common-issues)

---

## 1. Environment Setup

### Prerequisites

| Requirement | Version |
|------------|---------|
| Node.js | 18.x or higher |
| npm | 8.x or higher |

### Step 1: Install Dependencies

```bash
npm install
```

### Step 2: Configure Environment Variables

Copy the example environment file and fill in your values:

```bash
cp .env.example .env
```

Open `.env` and configure the following:

#### Server Settings (Required)

```env
HOST=0.0.0.0
PORT=10000
NODE_ENV=development
```

#### Contact Form Email (Required for contact form to work)

Uncomment and fill in your SMTP credentials. Gmail example:

```env
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your_email@gmail.com
SMTP_PASS=your_app_password_here   # Use App Password, not your regular password
CONTACT_EMAIL=hello@workroot.in    # Where contact form submissions are sent
```

> **Gmail tip:** Go to Google Account → Security → 2-Step Verification → App passwords to generate an App Password.

#### Newsletter Integration (Optional — pick one)

**Option A: Mailchimp**
```env
MAILCHIMP_API_KEY=your_mailchimp_api_key
MAILCHIMP_LIST_ID=your_audience_list_id
MAILCHIMP_DC=us1
```

**Option B: ConvertKit**
```env
CONVERTKIT_API_KEY=your_convertkit_api_key
CONVERTKIT_FORM_ID=your_form_id
```

#### Analytics (Optional — pick one)

**Option A: Google Analytics 4**
```env
GOOGLE_ANALYTICS_ID=G-XXXXXXXXXX
```

**Option B: Plausible (privacy-friendly)**
```env
PLAUSIBLE_DOMAIN=workroot.in
```

#### Error Monitoring (Optional but Recommended for Production)

```env
SENTRY_DSN=https://xxx@oXXXXXX.ingest.sentry.io/XXXXXXX
LOG_LEVEL=info    # Options: debug | info | warn | error
RELEASE_VERSION=1.0.0
```

### Step 3: Start the Development Server

```bash
npm run dev
```

The site will be available at `http://localhost:4321`.

---

## 2. Development Workflow

### Local Development

```bash
npm run dev        # Start dev server with hot reload
npm run build      # Build for production
npm run preview    # Preview the production build locally
```

### Production Server

```bash
npm run start:prod    # Start the production Node.js server
```

The production server uses `server.mjs` which includes gzip/brotli compression and caching headers.

---

## 3. Managing Blog Posts

Blog posts are written in Markdown and stored in `src/content/blog/`. Each file is automatically turned into a page at `/blog/[filename]/`.

### Creating a New Blog Post

1. Create a new `.md` file in `src/content/blog/`:

```
src/content/blog/my-new-post.md
```

The filename becomes the URL slug. Use lowercase with hyphens: `my-new-post.md` → `/blog/my-new-post`.

2. Add the required frontmatter at the top of the file:

```markdown
---
title: "Your Post Title"
description: "A brief description for SEO and social sharing (150-160 characters recommended)."
pubDate: 2026-03-21
heroImage: "/images/blog/your-image.jpg"
category: "Web Development"
tags: ["Tag1", "Tag2", "Tag3"]
author:
  name: "Author Name"
  avatar: "/images/team/author.jpg"
draft: false
---

Your post content goes here...
```

3. Write your content in Markdown below the frontmatter.

### Frontmatter Reference

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `title` | string | Yes | Post title shown on the page |
| `description` | string | Yes | Meta description for SEO |
| `pubDate` | date | Yes | Publication date (`YYYY-MM-DD`) |
| `updatedDate` | date | No | Last updated date |
| `heroImage` | string | No | Path to hero image (e.g., `/images/blog/image.jpg`) |
| `category` | enum | Yes | Must be one of the valid categories (see below) |
| `tags` | string[] | Yes | Array of relevant tags |
| `author.name` | string | Yes | Author's display name |
| `author.avatar` | string | No | Path to author's avatar image |
| `draft` | boolean | No | Set to `true` to hide from listing (default: `false`) |

### Valid Categories

The `category` field must be exactly one of these values:

- `Web Development`
- `Mobile Apps`
- `AI/ML`
- `Cloud`
- `DevOps`
- `Security`

> **Important:** The value must match exactly (case-sensitive). Using an invalid category will cause a build error.

### Working with Draft Posts

To write a post without publishing it:

```yaml
draft: true
```

Draft posts won't appear in the blog listing but will still build. To publish, change `draft: false` or remove the field.

### Adding Images to Blog Posts

1. Place your image in `public/images/blog/`:
   ```
   public/images/blog/my-post-hero.jpg
   ```

2. Reference it in the frontmatter:
   ```yaml
   heroImage: "/images/blog/my-post-hero.jpg"
   ```

3. To embed images in the post body, use standard Markdown:
   ```markdown
   ![Alt text describing the image](/images/blog/diagram.png)
   ```

### Updating an Existing Post

1. Open the post's `.md` file in `src/content/blog/`
2. Update the content and/or frontmatter
3. Add or update `updatedDate` to reflect when it was changed:
   ```yaml
   updatedDate: 2026-03-21
   ```

### Deleting a Blog Post

Simply delete the `.md` file from `src/content/blog/`. The route will no longer exist after the next build.

---

## 4. Updating Portfolio Items

Portfolio items are defined as JavaScript objects inside `src/pages/portfolio.astro`. There is no separate content folder for portfolio items.

### Locating the Portfolio Data

Open `src/pages/portfolio.astro` and look for the array of project objects near the top of the file (inside the frontmatter `---` block).

### Adding a New Portfolio Item

Add a new object to the projects array:

```javascript
{
  id: 'my-new-project',              // Unique ID, used for filtering. Use kebab-case.
  title: 'My New Project',
  category: 'web',                   // Must be: 'web', 'mobile', or 'ai'
  thumbnail: '/images/portfolio/my-project.jpg',
  description: 'Short 1-2 line description shown on the card.',
  techStack: ['React', 'Node.js', 'PostgreSQL'],
  client: 'Client Name',
  duration: '3 months',
  results: [
    '50% reduction in load time',
    '30% increase in user engagement',
  ],
  fullDescription: 'Detailed paragraph describing the project, the challenge, and the solution. This appears in the expanded case study view.',
}
```

### Portfolio Item Fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `id` | string | Yes | Unique identifier. Use kebab-case (e.g., `my-project`). |
| `title` | string | Yes | Project name displayed on the card |
| `category` | string | Yes | Must be `'web'`, `'mobile'`, or `'ai'` |
| `thumbnail` | string | Yes | Image path or URL for the project card |
| `description` | string | Yes | Short summary (1-2 sentences) |
| `techStack` | string[] | Yes | Technologies used (shown as badges) |
| `client` | string | Yes | Client or company name |
| `duration` | string | Yes | How long the project took (e.g., `'6 months'`) |
| `results` | string[] | Yes | Key achievements/metrics (use 2-4 bullet points) |
| `fullDescription` | string | Yes | Detailed description for the case study view |

### Valid Categories for Portfolio

| Category | Shows Up Under |
|----------|---------------|
| `'web'` | "Web Development" filter |
| `'mobile'` | "Mobile Apps" filter |
| `'ai'` | "AI Solutions" filter |

### Editing an Existing Portfolio Item

1. Open `src/pages/portfolio.astro`
2. Find the object with the matching `id`
3. Update any fields you want to change
4. Save the file — changes will appear immediately in dev mode

### Removing a Portfolio Item

Delete the entire object `{ ... }` from the projects array. Make sure to remove any trailing commas to keep valid JavaScript.

### Using External Images (Unsplash, CDN, etc.)

You can use external image URLs directly in the `thumbnail` field:

```javascript
thumbnail: 'https://images.unsplash.com/photo-1556742049-0cfed4f6a45d?w=600&h=400&fit=crop',
```

For local images, place them in `public/images/portfolio/` and reference as `/images/portfolio/filename.jpg`.

---

## 5. Available npm Scripts

### Development

| Command | Description |
|---------|-------------|
| `npm run dev` | Start local development server (hot reload at localhost:4321) |
| `npm run build` | Build the site for production |
| `npm run preview` | Preview production build locally |
| `npm run start` | Start the standalone Node.js server |
| `npm run start:prod` | Start the server in production mode |

### Testing

| Command | Description |
|---------|-------------|
| `npm test` | Run all Playwright tests |
| `npm run test:smoke` | Quick smoke test (critical pages only) |
| `npm run test:critical` | Test critical user paths |
| `npm run test:api` | Test API endpoints |
| `npm run test:forms` | Test contact and newsletter forms |
| `npm run test:chromium` | Run tests in Chrome only |
| `npm run test:firefox` | Run tests in Firefox only |
| `npm run test:mobile` | Run mobile device tests |
| `npm run test:report` | Open the last test report in a browser |
| `npm run test:ci` | Run CI-appropriate subset of tests |

### Backups

| Command | Description |
|---------|-------------|
| `npm run backup:full` | Full site backup |
| `npm run backup:content` | Backup content files only |
| `npm run backup:config` | Backup configuration files |
| `npm run backup:list` | List available backups |
| `npm run backup:restore` | Restore from a backup |
| `npm run backup:verify` | Verify backup integrity |
| `npm run backup:cleanup` | Remove old backups |

### Validation

| Command | Description |
|---------|-------------|
| `npm run validate:schema` | Validate content schemas |
| `npm run validate:structured-data` | Validate JSON-LD structured data |

---

## 6. Troubleshooting Common Issues

### Build fails with "Invalid frontmatter" error

**Symptom:** Running `npm run build` shows an error like `Invalid value for field "category"`.

**Cause:** A blog post has an invalid or misspelled `category` value.

**Fix:** Open the failing `.md` file and ensure `category` is exactly one of:
```
Web Development | Mobile Apps | AI/ML | Cloud | DevOps | Security
```

---

### Blog post not appearing on the site

**Cause 1:** The post has `draft: true` set.
**Fix:** Change to `draft: false` or remove the `draft` line.

**Cause 2:** The `pubDate` is in the future.
**Fix:** Set `pubDate` to today's date or earlier.

**Cause 3:** Missing required frontmatter fields.
**Fix:** Ensure `title`, `description`, `pubDate`, `category`, `tags`, and `author.name` are all present.

---

### Contact form submissions not arriving

**Cause:** SMTP credentials are not configured or are incorrect.

**Checklist:**
1. Confirm `.env` has `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`, and `CONTACT_EMAIL` set
2. If using Gmail, use an **App Password** (not your account password) — see [Google App Passwords](https://support.google.com/accounts/answer/185833)
3. Check `LOG_LEVEL=debug` in `.env` and restart the server to see detailed SMTP logs
4. Test the API directly: `curl -X POST http://localhost:10000/api/contact -H "Content-Type: application/json" -d '{"name":"Test","email":"test@example.com","message":"Hello"}'`

---

### Newsletter subscription not working

**Cause:** Newsletter provider credentials are missing or incorrect.

**Checklist:**
1. Confirm the correct provider variables are set in `.env` (Mailchimp OR ConvertKit, not both)
2. For Mailchimp: verify the `MAILCHIMP_DC` matches your API key's data center (the part after `-` in your API key, e.g., `us1`)
3. For ConvertKit: confirm the `CONVERTKIT_FORM_ID` is the numeric form ID, not the form name
4. Check server logs for error details

---

### Dev server won't start (port conflict)

**Symptom:** Error: `Port 4321 is already in use`.

**Fix:**
```bash
# Find what's using the port
netstat -ano | findstr :4321    # Windows
lsof -i :4321                   # Mac/Linux

# Or change the port in astro.config.mjs:
server: { port: 4322 }
```

---

### Production server not starting

**Symptom:** `npm run start:prod` fails or crashes immediately.

**Checklist:**
1. Run `npm run build` first — the server requires a production build in `dist/`
2. Confirm `NODE_ENV=production` in your `.env`
3. Check that `PORT` is not blocked by a firewall
4. Review error output carefully — missing env variables often cause startup failures

---

### Images not loading in production

**Cause:** Images placed in `src/` instead of `public/`.

**Fix:** All static assets (images, fonts, etc.) must be in the `public/` directory:
```
public/images/blog/my-image.jpg    ✓
src/images/my-image.jpg            ✗ (won't be served)
```

---

### Analytics not tracking

**Cause:** `GOOGLE_ANALYTICS_ID` or `PLAUSIBLE_DOMAIN` not set, or the value uses the old Universal Analytics format.

**Fix for GA4:** The ID must start with `G-`, not `UA-`:
```env
GOOGLE_ANALYTICS_ID=G-XXXXXXXXXX   ✓
GOOGLE_ANALYTICS_ID=UA-XXXXXXXXX   ✗ (old format, won't work)
```

After updating `.env`, rebuild and redeploy for changes to take effect.

---

### Test suite failing locally

**Symptom:** Playwright tests fail with connection errors or timeout.

**Fix:**
1. Ensure the dev/production server is running before tests
2. Install Playwright browsers if first time: `npx playwright install`
3. For API tests, ensure env variables are set
4. Run a focused subset to isolate the issue: `npm run test:smoke`

---

### Validate structured data / schema errors

**Symptom:** `npm run validate:structured-data` shows errors.

**Fix:** Run the validator to see which pages have issues:
```bash
npm run validate:structured-data
```
Check the output for specific JSON-LD errors and fix the structured data in `src/components/SEO.astro` or the relevant page.

---

## Additional Resources

| Resource | Location |
|----------|----------|
| Security audit & headers | `SECURITY-AUDIT.md` |
| SEO implementation details | `SEO-IMPLEMENTATION.md` |
| Performance baseline metrics | `PERFORMANCE-BASELINE.md` |
| Deployment instructions | `DEPLOYMENT.md` |
| Quick deployment reference | `QUICK-DEPLOY.md` |
| Changelog | `CHANGELOG.md` |
| Server setup | `SERVER_README.md` |

---

*Last updated: 2026-03-21*
