Deploy to Production / Build & Verify (push) Failing after 5m56s
Ping Search Engines / Notify Search Engines (push) Successful in 2s
Deploy to Production / Pre-Deploy Tests (push) Has been skipped
Deploy to Production / Deploy to Railway (push) Has been skipped
Deploy to Production / Deploy to Render (push) Has been skipped
Deploy to Production / Deploy to VPS (PM2) (push) Has been skipped
Deploy to Production / Deploy to Fly.io (push) Has been skipped
Deploy to Production / Post-Deploy Verification (push) Has been skipped
Deploy to Production / Notify on Failure (push) Successful in 2s
E2E Test Suite / Critical User Journeys (push) Has been skipped
E2E Test Suite / API Integration Tests (push) Has been skipped
E2E Test Suite / Smoke Tests (P0) (push) Failing after 11m26s
E2E Test Suite / Form Interaction Tests (push) Failing after 11m42s
E2E Test Suite / Destructive & Chaos Tests (push) Failing after 12m2s
E2E Test Suite / Cross-Browser Regression (chromium) (push) Failing after 16m14s
E2E Test Suite / Cross-Browser Regression (webkit) (push) Failing after 17m45s
E2E Test Suite / Cross-Browser Regression (firefox) (push) Failing after 25m23s
E2E Test Suite / Security Header Tests (push) Failing after 7m55s
E2E Test Suite / Test Report Summary (push) Failing after 20s
E2E Test Suite / Mobile Device Tests (push) Failing after 2h49m9s
Uptime Monitor / Health & Response Time (push) Failing after 2s
Uptime Monitor / SSL Certificate (push) Successful in 2s
Uptime Monitor / Send Alerts (push) Failing after 3s
Uptime Monitor / Record Uptime Success (push) Has been skipped
504 lines
14 KiB
Markdown
504 lines
14 KiB
Markdown
# 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
|
|

|
|
```
|
|
|
|
### 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*
|